Как узнать об отказе ode45, не глядя на отображаемое предупреждение?

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

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

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

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

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


person Mostafa    schedule 08.07.2013    source источник
comment
Простой пример, демонстрирующий проблему: [t,y]=ode45(@(t,y)[y(1)^2;y(2)],[0 1],[1;1]);. Два уравнения независимы. Первый имеет скорость роста, из-за которой размер шага становится очень маленьким. В свою очередь, это приводит к тому, что ode45 в конце концов прерывается. Я предполагаю, что вопрос в том, как можно написать свою функцию ОДУ, чтобы определить, что это произойдет, но избежать этого, обнулив уравнение до того, как размер шага станет слишком маленьким? Очевидно, что у обнуленного уравнения не было бы решения, но ode45 мог бы продолжить свой веселый путь и получить полные решения для оставшихся элементов.   -  person horchler    schedule 09.07.2013
comment
@horchler Я добавил больше объяснений. Теперь я должен проверить каждый отдельный вход и посмотреть, не работает ли ode45 (просматривая отображаемое предупреждение). Я хочу еще один знак, с которым можно было бы иметь дело автоматически; скажем, написав оператор if и проверяя наличие ошибок при каждом запуске.   -  person Mostafa    schedule 09.07.2013


Ответы (2)


Вы можете превратить этот 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.

person Rody Oldenhuis    schedule 09.07.2013

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

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

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

person T. Manzoor    schedule 25.07.2016