2013-07-08 2 views
2

Когда раствор ode45 расходится (не имеет значения, почему и как), будет отображаться следующее предупреждение, и решатель не может продолжаться:Как узнать о неисправности ode45, не глядя на отображаемое предупреждение?

Предупреждение: Сбой при Т = 8.190397e + 01. Не удалось выполнить интеграцию допусков без уменьшения размера шага ниже наименьшего значения разрешено (2.273737e-13) в момент времени t.

Я бегу ode45 на матрице (много входов), поэтому я хочу, чтобы выяснить, автоматически, для которых вводит вышеуказанное условие (неисправность) происходит. Я имею в виду, есть ли другие признаки этого условия, возвращаемые ode45 , которые могут быть записаны в массив автоматически? То, что может быть использовано в if даного как:

if {some variable is returned/is equal to ...} then {the solver has failed}

идентифицировать те неисправные входы автоматически без поиска отображаемого предупреждения.

+0

Простой пример, демонстрирующий проблему: '[t, y] = ode45 (@ (t, y) [y (1)^2; y (2)], [0 1], [1; 1]). Два уравнения независимы. Первый имеет темп роста, который заставляет размер шага становиться очень маленьким. В свою очередь это приводит к тому, что «ode45» в конечном итоге прекратится. Я думаю, вопрос заключается в том, как можно написать свою функцию ODE, чтобы определить, что это произойдет, но избежать этого, обнуляя уравнение до того, как размер шага станет слишком малым? Очевидно, что решение обнуленного уравнения не будет найдено, но «ode45» может продолжить свой весомый путь и получить полные решения для остальных элементов. – horchler

+0

@horchler я добавил больше информация. Теперь я должен проверить каждый отдельный вход и посмотреть, не сработает ли ode45 или нет (путем поиска отображаемого предупреждения). Я хочу еще один признак, с которым можно обращаться автоматически; скажем, путем написания оператора 'if' и проверки сбоя при каждом запуске. –

ответ

3

Вы можете превратить это warning в error и ошибки могут быть пойманы try/catch блоков.

Пример:

% Change this particular warning into an error 
warnId = 'MATLAB:ode45:IntegrationTolNotMet'; 
warnstate = warning('error', warnId);  

% That can be caught with try/catch 
try  
    % Quick-failing integration, suggested by horchler 
    [t,y] = ode45(@(t,y)[y(1)^2;y(2)],[0 1],[1;1]); 

catch ME 
    % Check if we indeed failed on meeting the tolerances 
    if strcmp(ME.identifier, warnId) 

     % DO YOUR STUFF HERE 

    else 
     % Something else has gone wrong: just re-throw the error 
     throw(ME); 
    end 

end 

% Don't forget to reset the warning status 
warning(warnstate); 

Вы можете получить warnId любого предупреждения в силу команды lastwarn. Для ошибок см. lasterr.

0

Другим методом было бы просто проверить, сколько времени было выполнено ode45. например, если вы запустили

[x,t] = ode45(@some_ode,[t0,tf],x0); 

, то после выполнения этой строки просто проверьте значение t (конец). Если t (end) == tf, то ode45 выполнил свою работу, в противном случае произошел сбой

Смежные вопросы