ode45或四阶Runge-Kutta方法中的Matlab误差解决了耦合ODE系统

时间:2015-03-28 18:08:52

标签: matlab ode numerical-integration

我是Matlab编程的初学者,也是Runge-Kutta方法的初学者。

我尝试使用4阶Runge-Kutta方法为我的项目工作解决耦合ODE系统。

这是我的问题......

G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;

syms n; 
x2 = symfun(sym('x2(n)'),[n]);
x1 = symfun(sym('x1(n)'),[n]);
x3 = symfun(sym('x3(n)'),[n]);
x4 = symfun(sym('x4(n)'),[n]);
x5 = symfun(sym('x5(n)'),[n]);

k1 = [x2 * x1 *n *(1 - z * x2)*(x1 - n) - 2 * x3 * n *(1 - z * x2) - x4^2 * x2 *(1 - z * x2)- G *x3 *x2 ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n];   
k2 = [x2 * (1 - z * x2)*(x1 * x2 * ( x1 - 2 *n)*( x1 - n) + 2* x3 * n + x4^2 * x2 ) ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k3 = [x3 * x2 * (2 * n * x1 - n)^2 * ( 1 - z * x2) + G * x1 * (x1 - 2 *n)* (x1 - n) + x4^2 * G]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k4 = [x4 * ( x1 + n)] ./ [n * (x1- n)];
k5 = - [x5] ./ [n * (x1- n)];

f = @(n,x) [k1;  k2;  k3;  k4; k5];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);

错误

  

使用odearguments时出错(第93行)
  @(N,X)[K1; K2; K3; K4; K5]返回长度为1的向量,但长度为
  初始条件向量是5.返回的向量   @(N,X)[K1; K2; K3; K4; K5]和初始条件向量必须有
  相同数量的元素。

     

ode45错误(第114行)
  [neq,tspan,ntspan,next,t0,tfinal,tdir,y0,f0,odeArgs,
  odeFcn,...

请指导我如何使用四阶Runge-Kutta方法解决上述问题...

2 个答案:

答案 0 :(得分:1)

错误源于使用符号函数(与函数句柄混合)和数值解算器。 您需要为ode45创建数字函数才能正常运行(我还将所有[]替换为()进行分组):< / p>

G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;

k1 = @(n,x) (x(2) * x(1)*n *(1 - z * x(2))*(x(1) - n) - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * x(2) *(1 - z * x(2))- G *x(3) *x(2)) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n);   
k2 = @(n,x) (x(2) * (1 - z * x(2))*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) )) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k3 = @(n,x) (x(3) * x(2) * (2 * n * x(1) - n)^2 * ( 1 - z * x(2)) + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G)./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k4 = @(n,x) (x(4) * (x(1) + n)) ./ (n * (x(1)- n));
k5 = @(n,x) - x(5) ./ (n * (x(1)- n));

f = @(n,x) [k1(n,x);  k2(n,x);  k3(n,x);  k4(n,x); k5(n,x)];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);

这适用于我安装的Matlab。

但是,由于函数生成NaNs,因此输出全部为Infs;我可能通过更换括号引入了错误,但我不知道实际的方程是什么,所以我将把它留给你。 :)

答案 1 :(得分:1)

一般情况下,请先咨询文档。如果不可用,请使用您选择的搜索引擎,例如https://www.google.de/search?q=matlab+ode45+example查找第一个结果https://de.mathworks.com/help/matlab/ref/ode45.html

在那里你找到了一个多维的例子

function dy = rigid(t,y)
    dy = zeros(3,1);    % a column vector
    dy(1) = y(2) * y(3);
    dy(2) = -y(1) * y(3);
    dy(3) = -0.51 * y(1) * y(2);
end

options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
[T,Y] = ode45(@rigid,[0 12],[0 1 1],options);

plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),'.')

可以用作蓝图。在相关页面https://de.mathworks.com/help/matlab/math/ordinary-differential-equations.html中,他们使用与第一个示例中的van der Pol等式更接近的语法

function dydt = vdp1(t,y)
    dydt = [y(2); (1-y(1)^2)*y(2)-y(1)];
end

[t,y] = ode45(@vdp1,[0 20],[2; 0]);

plot(t,y(:,1),'-',t,y(:,2),'--')
title('Solution of van der Pol Equation, \mu = 1');
xlabel('time t');
ylabel('solution y');
legend('y_1','y_2')

按照这些示例,将代码重写为

G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;



function dotx = dxdn(n,x) 
    t1 = n*(x1-n)    
    t2 = x(2)*(1 - z * x(2))

    den123 = ( G * x(3) - (x(1) - n)^2 * t2)

    k1 = ( x(1)*t1*t2 - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * t2- G *x(3) *x(2) ) / (den123*n);   
    k2 = ( t2*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) ) ) / (den123 * t1);
    k3 = ( x(3) *  (2 * n * x(1) - n)^2 * t2 + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G ) / (den123*t1);
    k4 = ( x(4) * ( x(1) + n) ) / t1;
    k5 = - x(5) / t1;

    dotx = [k1;  k2;  k3;  k4; k5];
end 

[n,xa] = ode45(@dxdn,[0.001 1],[1-b; 1/b; 1-b; 0.01; 0.02]);

由于在n=0处除以零,你无法在该奇点中开始迭代。在上面的代码中,通过从一些(非常)小的正n开始来缓解这种情况,您也可以尝试从n=1e-8开始或更小。所有组件的斜率都非常大,因此积分可能很慢,结果可能不会过于精确接近零。要在math.stackexchange论坛中正确处理单数ODE,请