简介
我使用Matlab通过使用ODE45数值求解二阶常微分方程组来模拟一些动态系统。我从Mathworks(最后的教程链接)找到了一个很棒的教程,介绍了如何做到这一点。
在本教程中,方程组在x和y中是明确的,如下所示:
x''=-D(y) * x' * sqrt(x'^2 + y'^2)
y''=-D(y) * y' * sqrt(x'^2 + y'^2) + g(y)
上述两个等式都形成了y'' = f(x,x',y,y')
问题
然而,我遇到了方程组,其中变量无法明确求解,如示例所示。例如,其中一个系统具有以下3个二阶常微分方程组:
y双素数方程
y'' - .5*L*(x''*sin(x) + x'^2*cos(x) + (k/m)*y - g = 0
x双素数方程
.33*L^2*x'' - .5*L*y''sin(x) - .33*L^2*C*cos(x) + .5*g*L*sin(x) = 0
单个素数是一阶导数 双素数是二阶导数 给出L,g,m,k和C参数。
如何使用Matlab数值求解一组二阶常微分方程,其中二阶无法明确求解?
谢谢!
答案 0 :(得分:1)
您的第二个系统的格式为
a11*x'' + a12*y'' = f1(x,y,x',y')
a21*x'' + a22*y'' = f2(x,y,x',y')
您可以将其解析为线性系统
[x'', y''] = A\f
或在这种情况下明确使用Cramer的规则
x'' = ( a22*f1 - a12*f2 ) / (a11*a22 - a12*a21)
相应地 y''
。
我强烈建议在代码中保留中间变量,以减少键入错误的机会,避免多次计算相同的表达式。
代码看起来像这样(未经测试)
function dz = odefunc(t,z)
x=z(1); dx=z(2); y=z(3); dy=z(4);
A = [ [-.5*L*sin(x), 1] ; [.33*L^2, -0.5*L*sin(x)] ]
b = [ [dx^2*cos(x) + (k/m)*y-g]; [-.33*L^2*C*cos(x) + .5*g*L*sin(x)] ]
d2 = A\b
dz = [ dx, d2(1), dy, d2(2) ]
end
答案 1 :(得分:0)
是的,你的方法是正确的! 我在下面发布以下代码:
count
这是ode45的函数句柄文件:
%Rotating Pendulum Sym Main
clc
clear all;
%Define parameters
global M K L g C;
M = 1;
K = 25.6;
L = 1;
C = 1;
g = 9.8;
% define initial values for theta, thetad, del, deld
e_0 = 1;
ed_0 = 0;
theta_0 = 0;
thetad_0 = .5;
initialValues = [e_0, ed_0, theta_0, thetad_0];
% Set a timespan
t_initial = 0;
t_final = 36;
dt = .01;
N = (t_final - t_initial)/dt;
timeSpan = linspace(t_final, t_initial, N);
% Run ode45 to get z (theta, thetad, del, deld)
[t, z] = ode45(@RotSpngHndl, timeSpan, initialValues);
%initialize variables
e = zeros(N,1);
ed = zeros(N,1);
theta = zeros(N,1);
thetad = zeros(N,1);
T = zeros(N,1);
V = zeros(N,1);
x = zeros(N,1);
y = zeros(N,1);
for i = 1:N
e(i) = z(i, 1);
ed(i) = z(i, 2);
theta(i) = z(i, 3);
thetad(i) = z(i, 4);
T(i) = .5*M*(ed(i)^2 + (1/3)*L^2*C*sin(theta(i)) + (1/3)*L^2*thetad(i)^2 - L*ed(i)*thetad(i)*sin(theta(i)));
V(i) = -M*g*(e(i) + .5*L*cos(theta(i)));
E(i) = T(i) + V(i);
end
figure(1)
plot(t, T,'r');
hold on;
plot(t, V,'b');
plot(t,E,'y');
title('Energy');
xlabel('time(sec)');
legend('Kinetic Energy', 'Potential Energy', 'Total Energy');