Я разрабатываю динамическую модель, описывающую динамику растений и микробов. Рост растений может быть ограничен углеродом (светом), азотом или фосфором, и модель имеет различную динамику в зависимости от того, какой из этих трех элементов является лимитирующим. Растения могут получать азот либо из почвы, либо из атмосферы, и я хочу определить количество питательных веществ, получаемых каждым путем. Итак, на каждом временном шаге я хочу рассчитать, какое питательное вещество ограничивает, а затем рассчитать соответствующие потоки и изменения в пулах. Моя конечная цель — иметь таблицу с данными для всех пулов, потоков и ограничений.
До сих пор для решения этого вопроса я использовал ode45
в MATLAB. Моя функция имеет как события, так и ряд дополнительных значений, которые вычисляются в моем ODE (т. е. я хочу извлечь различные потоки с течением времени, а не только значения dY
). Есть ли способ экспортировать все потоки/переменные и использовать функцию событий?
Код, который я использую для передачи дополнительных переменных (xvt
, yvt
, limvt
), имеет форму ниже
(на основе этой публикации MATLAB Central):
function [dydx xvt yvt limvt] = myode(t,input,ps)
persistent xv yv limv
condition=input*ps;
if condition>1: lim=1; x=x*1; y=y/1;
elseif condition==1: lim=2; x=x*2; y=y/2;
elseif condition<1: lim=3; x=x*3; y=y/3;
end
limv = [limv; lim];
yv = [yv; y];
xv = [xv; x];
dydx = x + y;
if nargout>1
xvt = xv; yvt = yv; limvt = limv;
end
Решение ОДУ можно решить с помощью команд:
[X Y] = ode45(@myode, [0 5], 1);
Затем xv
, yv
и limv
можно получить с помощью:
[dY, xv, yv, limv]=myode([], input,ps);
Чтобы использовать функцию событий, где изменения в limv
являются событиями, я установил параметры следующим образом (events_functions
выполняет математические операции, чтобы события выдавали правильные значения в нужное время):
options = odeset('Events',@(t0,y,ps)events_function(t0,input,ps,limv,years));
Итак, я могу запустить функцию с событиями (в цикле while, чтобы запускать и останавливать всякий раз, когда происходят события):
[t,xx] = ode23(@myode,[t0:years],input,options,ps);
Однако приведенное выше позволяет мне выполнять либо события на основе limv
, либо вычислять limv
, но не то и другое одновременно. Я считаю, что этот плакат пытался сделать то же самое. Вы знаете, возможно ли это?
xv
иyv
не являются параметрами. Это просто значения времени (независимой переменной) и вектора состояния на каждом временном шаге. Ваши функции событий имеют доступ к этим двум входам. Я не вижу никаких параметров в вашем примере кода, который, кажется, взят из вопроса Matlab Central. Пожалуйста, отредактируйте свой вопрос, чтобы предоставить код того, что вы на самом деле пытаетесь выполнить (или более четкий пример). - person horchler   schedule 10.11.2015limv
— это просто зависит от переменной состоянияinput
и параметраps
, к которым у вашей функции событий уже есть доступ. Также нет необходимости сохранятьxv
иyv
, так как это простоX
иY output from
ode23/
ode45` (плюс некоторые дополнительные значения из-за неудачных шагов, которые вам не нужны). Кроме того, обычно плохая идея помещать разрывы в функцию ОДУ (например, в ваш операторif
/elseif
) — это делает уравнение очень жестким и может привести к неточности и даже к совершенно неверным решениям. Используйте события для решения этих переходов. - person horchler   schedule 10.11.2015x
?), и, как указал @horchler, вычислениеlimv
не нужно, и его лучше выполнять внутри функция событий. Более того, постоянные переменные внутри функции ОДУ, используемой в решателе с переменным шагом, не дадут ожидаемого результата; многие шаги интеграции будут отклонены, промежуточные значения, которые не отображаются в решении и т. д., по-прежнему будут собираться постоянными переменными. - person Rody Oldenhuis   schedule 12.11.2015