цикл for для значений параметров, зависящих от времени, в решателе ode работает только для некоторых значений t

Я использую простой цикл if для изменения значений параметров в моем сценарии ode. Вот пример сценария, который я написал, который демонстрирует ту же проблему. Итак, первая версия, которая работает:

function aah = al(t,x)

if (t>10000 && t<10300)
    ab = [0; 150];
else
    ab = [150; 0];
end

aah = [ab];

это можно запустить с помощью

t = [0:1:10400];
x0 = [0,0];
[t,x] = ode23tb(@al, t,x0);

и визуализировать с

plot(t,x(:,1))
plot(t,x(:,2))

Хорошо, это хорошая версия. Теперь, если все, что вы делаете, это меняете t на

t = [0:1:12000];

все взрывается. Вы можете подумать, что Matlab просто усредняет график, но это не так, потому что, если вы посмотрите на

x(10300,2) 

ответ должен быть одинаковым в обоих случаях, потому что код не изменился. но эта вторая версия выводит 0, что неверно!

Что, черт возьми, происходит? У кого-нибудь есть идея?

Большое спасибо за любую помощь


person user1792403    schedule 21.11.2012    source источник


Ответы (1)


Ваша функция постоянна (кроме 10000 ‹ t ‹ 10300), поэтому внутренний решатель начинает решать систему с очень большим временным шагом, по умолчанию 10% от общего времени. (В адаптивном решателе ОДУ, если система постоянна, решения более высокого и более низкого порядка дадут одно и то же решение, а (оценочная) ошибка будет равна нулю. Таким образом, решатель предполагает, что текущий временной шаг достаточно хорош.) Вы можете посмотрите, дадите ли вы tspan только с двумя элементами, временем начала и окончания.

t = [0 12000];

Обычно tspan не влияет на внутренний временной шаг решателя. Решатели решают систему со своим внутренним временным шагом, а затем просто интерполируют на tspan, заданном пользователем. Таким образом, если внутренний временной шаг, к сожалению, «перепрыгнет» через интервал [10000, 10300], решатель не узнает об этом интервале.

Поэтому вам лучше установить максимальный размер шага, относительно меньше 300.

options = odeset('MaxStep', 10);
[t, x] = ode23tb(@al, t, x0, options);

Если вы не хотите все время решать с малым шагом (и если вы «знаете», когда функция непостоянна), вам следует решать отдельно.

t1 = [0 9990];
t2 = [9990 10310];
t3 = [10310 12000];

[T1, x1] = ode23tb(@al, t1, x0);
[T2, x2] = ode23tb(@al, t2, x1(end,:));
[T3, x3] = ode23tb(@al, t3, x2(end,:));

T = [T1; T2(2:end); T3(2:end)];
x = [x1; x2(2:end,:); x3(2:end,:)];
person dlimpid    schedule 22.11.2012
comment
на самом деле вы можете сделать размер шага равным 300. Большинство алгоритмов оды возвращаются во времени, чтобы скорректировать быстрые изменения, которые они могли пропустить. Пока шаг попадает в чувствительную зону, все будет в порядке. - person Rasman; 22.11.2012
comment
Абсолютно замечательный. Имеет так много смысла, большое спасибо. - person user1792403; 22.11.2012