MATLAB求解常微分方程

时间:2014-05-30 20:01:02

标签: matlab differential-equations

如何使用matlab解决以下常微分方程?

x''/ y = y''/ x = - (x''y + 2x'y'+ xy'')

有两个已知点,例如t = 0:x(0)= x0,y(0)= y0; t = 1:x(1)= x1,y(1)= y1? 如果困难,它不需要是一个完整的公式。数值解是可以的,这意味着,给定一个特定的t,我可以得到x(t)和y(t)的值。

如果matlab很难做到这一点,mathematica也行。但由于我不熟悉mathematica,所以如果可能的话我更喜欢matlab。

期待帮助,谢谢!

我在stackexchange上问了同样的问题,但还没有得到很好的答案。 https://math.stackexchange.com/questions/812985/matlab-or-mathematica-solve-ordinary-differential-equations

希望我能在这里解决问题!

我试过的是:

--------- MATLAB

  
    

syms t

  
>> [x, y] = dsolve('(D2x)/y = -(y*D2x + 2Dx*Dy + x*D2y)', '(D2y)/x = -(y*D2x + 2Dx*Dy + x*D2y)','t')


Error using sym>convertExpression (line 2246)
Conversion to 'sym' returned the MuPAD error: Error: Unexpected 'identifier'.
[line 1, col 31]

Error in sym>convertChar (line 2157)
s = convertExpression(x);

Error in sym>convertCharWithOption (line 2140)
    s = convertChar(x);

Error in sym>tomupad (line 1871)
    S = convertCharWithOption(x,a);

Error in sym (line 104)
        S.s = tomupad(x,'');

Error in dsolve>mupadDsolve (line 324)
sys = [sys_sym sym(sys_str)];

Error in dsolve (line 186)
sol = mupadDsolve(args, options);

-------- MATLAB

另外,我尝试添加条件,例如x(0)= 2,y(0)= 8,x(1)= 7,y(1)= 18,并且错误仍然相似。所以我认为dsolve函数无法解决这个问题。

因此,关键问题是,给定两个已知点,例如当t = 0时:x(0)= x0,y(0)= y0; t = 1:x(1)= x1,y(1)= y1,我如何得到x(t)和y(t)的值?

更新: 我尝试过ode45功能。首先,为了将2阶方程转换为1阶,我设置x1 = x,x2 = y,x3 = x',x4 = y'。经过一些计算,方程式变为:

x(1)' = x(3)                                                (1)

x(2)' = x(4)                                                (2)

x(3)' = x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2))     (3)

x(4)' = -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)                 (4)

所以我写的matlab代码是:

myOdes.m

function xdot = myOdes(t,x)

xdot = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)]

end

main.m
t0 = 0;
tf = 1;
x0 = [2 3 5 7]';
[t,x] = ode45('myOdes',[t0,tf],x0);
plot(t,x)

它可以工作。但是,实际上这是不对的。因为,我所知道的是,当t = 0时,x和y的值,即x(1)和x(2);当t = 1时,x和y的值。但是ode函数需要初始值:x0,我只是随机写了条件x0 = [2 3 5 7]'来帮助这个代码工作。那么如何解决这个问题?

更新: 在我意识到这是一个边界值问题并且以下是我的代码之后我尝试使用函数bvp4c(假设两个边界值条件是:当t = 0时:x = 1,y = 3;当t = 1时, x = 6,y = 9.x是x(1),y是x(2)):

1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(@ode,@bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));

plot(t,x(3,:));

plot(t,x(4,:));
x(1,:)
x(2,:)

它可以工作,但我不知道它是否正确。我会再次检查以确保它是正确的代码。

3 个答案:

答案 0 :(得分:0)

编辑: 这就是我解决问题的方法。注意:我不太喜欢matlabFunction创建者,但这只是个人偏好,原因有很多我不会参与。

% Seperate function of the first order state equations
function dz = firstOrderEqns(t,z)
    dz(4,1) = 0;
    dz(1) = -2.*z(3).*z(1).*z(4)./(1 + z(4).^2 + z(2).^2);
    dz(2) = z(1);
    dz(3) = -2.*z(2).*z(3).*z(1)./(1 + z(4).^2 + z(2).^2);
    dz(4) = z(3);
end

% runfirstOrderEqns
%% Initial conditions i.e. @ t=0
z1 = 5; % dy/dt = 5 (you didn't specify these initial conditions, 
%  these will depend on the system which you didn't really specify
z2 = 0; % y = 0
z3 = 5; % dx/dt = 5 (The same as for z1)
z4 = 0; % x = 0
IC = [z1, z2, z3, z4];
%% Run simulation
% Time vector: i.e closed interval [0,20]
t = [0,20]; % This is where you have to know about your system
           % i.e what is it's time domain.
           % Note: when a system has unstable poles at
           % certain places the solver can crash you need
           % to understand these.
% using default settings (See documentation ode45 for 'options') 
[T,Y] = ode45(@firstOrderEqns,t,IC);

%% Plot function
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),':',T,Y(:,4),'.');
legend('dy/dt','y','dx/dt','x')

在我的评论中,我已经做了很多你需要解决的问题,例如,你没有说明状态的一阶导数的初始条件是什么,即(z1,z3),这对于系统的反应。此外,您没有指定您对模拟等感兴趣的时间间隔。

注意:第二个m文件可以与任何状态函数一起使用,格式正确

答案 1 :(得分:0)

如上所述,这不是一个数学网站,所以尝试给出代码或者显示一些努力的东西。 但是,您需要做的第一步是将DE转换为正常形式(即没有二阶导数)。你可以通过使一个单独的变量等于导数来实现。然后,你使用

syms x y % or any variable instead of x or y

将变量定义为符号。使用matlab函数根据这些变量创建符号函数。最后,您可以使用ode45函数在传递变量值时解决符号函数。我建议您在matlab中查找完整的文档以便更好地理解它,但这是一个非常基本的语法:

MyFun= matlabFunction(eq,'vars',{x,y});
[xout,yout]=ode45(@(x,Y) MyFun(variables),[variable values],Options);

希望这会让您朝着正确的方向前进,所以如果您需要更多帮助,请尝试使用它并提供代码。

答案 2 :(得分:0)

以下是我们最终得到的答案@Chriso:使用matlab bvp4c函数来解决这个边界值问题(假设两个边界值条件是:当t = 0时:x = 1,y = 3;当t = 1时,x = 6,y = 9.x是x(1),y是x(2)):

1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(@ode,@bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));

plot(t,x(3,:));

plot(t,x(4,:));
x(1,:)
x(2,:)