在Matlab中指定的时间长度后停止集成 [英] Stop integration after designated length of time in Matlab

查看:68
本文介绍了在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.

一种方法是通过输出函数.这是在Matlab求解器的每个(成功)集成步骤之后调用的函数.有几个Output函数示例,您可以检查其代码以查看可以执行的操作:odeplotodeprintodephas2odephas3.只需在命令窗口中键入edit odeplot即可查看代码.

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获得返回值.这在您的应用程序中可能需要也可能不需要.可能有一些解决方法,但是它们将需要更多代码.您可以做的一件简单的事情就是使错误消息使用传递到输出函数中的ty值返回系统的上次时间和状态(被中断时). 事件函数也可能用于终止根据经过的时间进行积分-可能仍允许您返回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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆