2013-07-08 130 views
2

當ODE45發散(不要緊,爲何以及如何)的解決方案,將顯示以下警告,並求解器無法繼續:如何在不查看顯示警告的情況下發現ode45的故障?

警告:如果在t = 8.190397e + 01。在時間t時,不能將步長減小到低於允許的最小值 (2.273737e-13),而無法滿足集成 公差。

我在矩陣(大量的投入)運行ODE45,所以我想找出自動爲其輸入上述條件(失敗)發生。我的意思是,是否有任何其他跡象表明ode45 可以自動將其寫入陣列?東西,可以在if statment作爲:

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

你可以反過來說,warningerror,並錯誤可以通過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); 

可以憑藉lastwarn命令得到任何警告的warnId。有關錯誤,請參見lasterr

0

另一種方法是檢查ode45能夠運行多少時間。例如,如果您運行

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

然後在執行此行後,只需檢查t(結束)的值。如果t(end)== tf,那麼ode45做了它的工作,否則就出現了失敗

相關問題