在Matlab中指定的时间长度后停止集成 [英] Stop integration after designated length of time in Matlab
问题描述
如果要花费超过指定的时间,我想在Matlab中停止求解微分方程.我尝试了以下操作,但不起作用...
I want to stop solving a differential equation in Matlab if it takes more than a designated amount of time. I tried the following,but it doesn't work...
options = odeset('AbsTol',1e-8,'RelTol',1e-5);
RUNTIME=5;
timerID = tic;
while (toc(timerID) < RUNTIME)
[t_pae,x_th_pae] = ode15s(@prosomoiwsh,[0 t_end],[80*pi/180;0;130*pi/180;0;th_initial(1);th_initial(2);th_initial(3);th_initial(4)],options);
end
我该如何解决?
更新: 我尝试了horchler的建议,现在我的代码如下:
UPDATE : I tried what horchler suggested and now my code looks like this :
interupt_time = 20;
outputFun= @(t,y,flag)interuptFun(t,y,flag,interupt_time);
options = odeset('AbsTol',1e-5,'RelTol',1e-5,'OutputFcn',outputFun);
try
[t_pae,x_b_th_pae] = ode15s(@prosomoiwsh,[0 t_end],[0;0;0;th_initial(1);th_initial(2);th_initial(3);th_initial(4);th_initial(5);th_initial(6);th_initial(7);th_initial(8);th_initial(9);th_initial(10);th_initial(11);th_initial(12)],options);
u_pae=compute_input(epsilon,ke,kv,dD,IwF,IwG,IwD,IbF,IbG,IbD,p,m,t_pae,x_b_th_pae);
catch ME
if strcmp(ME.identifier,'interuptFun:Interupt')
disp(ME.message);
input('got caught')
else
rethrow(ME); % It's possible the error was due to something else
end
end
function dx_b_th = prosomoiwsh(t,x_b_th)
...
end
outputFun与建议的一位完全相同.但是现在它每次都超时,而以前这只是偶尔发生.我在做什么错了?
The outputFun is exactly the same as the one horchler suggested. But now it times out every single time,while previously this only happened occasionally. What am I doing wrong?
推荐答案
首先,您无法做任何尝试的事情.将会发生的一切是ode15s
将在需要的时间内运行,并像往常一样返回结果.您需要一种在超过指定的特定时间量时在执行过程中中断ODE求解器的方法.不幸的是,您没有提供可运行的代码,因此我将不得不提供一些通用建议,以适应您的问题.
First, you can't do anything like what you're trying. All that will happen is that ode15s
will run for as long as it needs and return it's result as usual. You need a way of interrupting the ODE solver in the middle of its execution when a certain designated amount of time has been exceeded. Unfortunately, you didn't provide runnable code, so I'll have to provide general suggestions that you can adapt to your problem.
One way to do this is via an Output function. This is a function that gets called after every (successful) integration step of a Matlab solver. There are are several examples of Output functions that you can examine the code of to see what you can do: odeplot
, odeprint
, odephas2
, and odephas3
. Just type edit odeplot
in your command window to see the code.
下面是一个示例,该示例说明了如何使用内置示例功能vdp1000
来使用此功能,该功能在ode15s
的帮助中被引用.您需要创建一个持久变量来保存初始时间,对其进行初始化,然后检查相对于您传入的参数的经过时间.然后,如果经过时间超过指定值,则会抛出错误以中止ode15s
. try
-catch
语句可用于捕获错误.
Below is an example of how you might use this capability using the built-in example function vdp1000
that's referred to in the help for ode15s
. You need to create a persistent variable to save the initial time, initialize it, and then check the elapsed time relative to a parameter that you pass in. Then you throw an error to abort ode15s
if the elapsed time exceeds the designated value. A try
-catch
statement can be used to catch the error.
function ode_interupt_demo
tspan = [0 3000]; y0 = [2;0];
interupt_time = 0.05;
outputFun= @(t,y,flag)interuptFun(t,y,flag,interupt_time);
opts = odeset('AbsTol',1e-8,'RelTol',1e-5,'OutputFcn',outputFun);
try
[t,y] = ode15s(@vdp1000,tspan,y0,opts);
catch ME
if strcmp(ME.identifier,'interuptFun:Interupt')
disp(ME.message);
% Do other things
else
rethrow(ME); % It's possible the error was due to something else
end
end
function status = interuptFun(t,y,flag,interupt_time) %#ok<INUSL>
persistent INIT_TIME;
status = 0;
switch(flag)
case 'init'
INIT_TIME = tic;
case 'done'
clear INIT_TIME;
otherwise
elapsed_time = toc(INIT_TIME);
if elapsed_time > interupt_time
clear INIT_TIME;
str = sprintf('%.6f',elapsed_time);
error('interuptFun:Interupt',...
['Interupted integration. Elapsed time is ' str ' seconds.']);
end
end
此方法的一个缺点是您不会从ode15s
获得返回值.这在您的应用程序中可能需要也可能不需要.可能有一些解决方法,但是它们将需要更多代码.您可以做的一件简单的事情就是使错误消息使用传递到输出函数中的t
和y
值返回系统的上次时间和状态(被中断时). 事件函数也可能用于终止根据经过的时间进行积分-可能仍允许您返回ode15s
的输出.
One disadvantage of this approach is that you will not get a return value from ode15s
. This may or may not be desirable in your application. There are likely ways around this, but they'll require more code. One easy thing that you can do is have the error message return the last time and state of the system (when it was interrupted) using the t
and y
values passed into the output function. It's also possible that Event functions could be used to terminate integration based on elapsed time – those might allow you to still return output from ode15s
.
这篇关于在Matlab中指定的时间长度后停止集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!