如何用matlab ode23s解决ODE第四顺序?

时间:2015-03-19 17:53:24

标签: matlab ode

实际上我正在尝试使用ode23s来解决以下ODE。不幸的是,我真的不知道该怎么做。

颂歌如下:

bo(t)*y + b1(t)*y' + b2(t)*y'' + b3(t)*y''' + b4(t)*y''' = ao(t)*cst 

(那些衍生物应该用点标记,因为它们都是时间导数,例如y'= dy / dt,y''= d2y / dt2等。参数bo,b1,..., b4和ao作为matlab函数给出.'cst'是常量。

首先,我将这个等式转换为一个ODE系统,这使我得到以下函数:

function [dy] = odetest(y,cst,ao,bo,b1,b2,b3,b4)
  dy = [ y(2); ...
         y(3); ...
         y(4); ...
         (-b1*y(2) + ao*cst - b2*y(3) - b3*y(4) + bo*y(1))*(1/(b4)) ];
end

所以...为了简化程序(并作为第一个近似),我想保持每个时间步长的时间相关参数ao,bo,b1,... b4不变。

现在问题开始了:我不知道如何将这个函数放在ode23s中,它可以在给定的初始条件下以任意时间步长求解。也许我在转换时间导数时犯了一个错误......

我猜测解决方案必须是类似的,但遗憾的是无法正常工作

% file where the Ode has to be solved
% Loop over all time-steps

for i=1:number_timesteps

   time0 = i-1;
   time  = i;

   ao = function_ao(i); % function of parameter a, which is now constant in each timestep

   bo = function_bo(i);
   b1 = function_b1(i);
   b2 = function_b2(i);
   b3 = function_b3(i);
   b4 = function_b4(i);

   y = value1;   % initial conditions for y
   dy = value2;
   ddy = value3;
   dddy = value4;

   cst = value5; % value of cst in the actual timestep

   [T, Y] = ode23s(@odetest, [time0 time1] [y; dy; ddy; dddy], ...
   cst, ao, bo, b1, b2, b3, b4 ); % the arguments are the inital conditions, parameters ao, bo, ...

end

但是......我真的不明白我做错了什么。如果参数ao,bo,b1,...,b4在一个时间步长内发生变化,我不知道如何解决问题,所以ode23s必须以某种方式使用它们的函数。

如果有人可以帮助我,那就太棒了。提前谢谢!

修改 - 实施

我现在修改了我的代码如下,但不幸的是得到一个错误“使用odetest时出错(第5行)没有足够的输入参数。”我不知道为什么:/

odetest.m:

    function [ dy ] = odetest( ttime, y, cst, ff1, ff2, ff3, ff4, ...
                  df1, df2, df3, df4, dd2, dd31, dd32, dd33, ...
                  dd34, ttk, tt0, EE1)

    EE0 = fe0(ff1, ff2, ff3, ff4, ttk, tt0, ttime);
    e1 = fe1(df1, dd2, dd31, ttk, tt0, ttime);
    e2 = fe2(df2, dd2, dd32, ttk, tt0, ttime);
    e3 = fe3(df3, dd2, dd33, ttk, tt0, ttime);
    e4 = fe4(df4, dd2, dd34, ttk, tt0, ttime);

    a0 = fa0(EE0, e1, e2, e3, e4);    
    b0 = fb0(e1, e2, e3, e4);
    b1 = fb1(EE0, EE1, EE1, EE1, EE1, e1, e2, e3, e4);
    b2 = fb2(EE0, EE1, EE1, EE1, EE1, e1, e2, e3, e4);
    b3 = fb3(EE0, EE1, EE1, EE1, EE1, e1, e2, e3, e4);
    b4 = fb4(EE0, EE1, EE1, EE1, EE1);

    dy = [ y(2); ...
           y(3); ...
           y(4); ...
           (-bb_1*y(2) + aa_0*cst - bb_2*y(3) - bb_3*y(4) + bb_0*y(1))*(1/(bb_4))];

end

我调用此函数的文件本身是

% something before (set constant parameters val_i and define initial
% conditions yy_t0 for first step ...
for i=1:n

   dbl_t0 = t(i-1,1);
   dbl_t  = t(i,1);

   cst = act(i,1) - act(i-1);


   [T, Y] = ode23s(@odetest, [dbl_t0 dbl_t], [yy_t0 ...
            dyy_t0 ddy_t0 dddy_t0],cst, ...
            val_f1, val_f2, val_f3, val_f4, val_d1, val_d2, val_d3, val_d4, val_dd2, ...
            val_dk1, val_dk2, val_dk3, val_dk4, val_tk, val_t0, val_E1);

   yy_t = Y(1);
   dyy_t = Y(2);
   ddyy_t = Y(3);
   dddyy_t = Y(4);

   yy_t0 = yy_t;
   dyy_t0 = dyy_t;
   ddyy_t0 = ddyy_t;
   dddyy_t0 = dddyy_t;

end

......有没有人在这里看到错误?

上次修改

我发现了错误。 - 我必须通过以下方式拨打ode23s:

[T, Y] = ode23s(@(ttime,y)odetest(ttime, y, cst, ...
            f_1, f_2, f_3, f_4, d_11, d_12, d_13, d_14, d_2, d_31, ...
            d_32, d_33, d_34, t_k, t_0, E_1), [dbl_t0 dbl_t], ...
            [yy_t0 dyy_t0 ddyy_t0 dddyy_t0]);

......现在有效。

1 个答案:

答案 0 :(得分:0)

不要将ode23s用于单个时间步,而是让它集成整个时间序列,并利用odetest函数(差分系统函数)重新评估每个时间步的参数。尽管您需要确保参数功能正确设置以适应您使用的时间跨度,但您将获得更高的准确性。顺便说一下,ODEFUN的第一个参数是时间,而不是你的状态!

function [dy] = odetest(t, y, cst)
    ao = function_ao(t);
    b1 = function_b1(t);

    % ...re-evaluate all your parameters here...

    dy = [ y(2); ...
           y(3); ...
           y(4); ...
           (-b1*y(2) + ao*cst - b2*y(3) - b3*y(4) + bo*y(1))*(1/(b4)) ];
end

...

% Somewhere else in your code
y = value1;   % initial conditions for y
dy = value2;
ddy = value3;
dddy = value4;
[T, Y] = ode23s( @odetest, [0 number_of_timesteps], [y dy ddy dddy], cst );

此样式在切换求解器时特别有用,因为它们将使用跳过不同时间位置的不同集成技术(它们并不总是在特定时间点集成)。

如果您希望在特定的时间点进行整合,您还可以传递时间序列(1:number_of_timesteps),而不是如上所示的时间跨度。