贡献者: addis
若程序中给出拉格朗日量拉格朗日方程的数值函数 ,输入和输出均为数值(例如双精度实数),那么如何数值求解运动方程呢?
问题的关键是如何列出一个一阶常微分方程组。如果可以给出系统哈密顿量的数值函数,那么数值解哈密顿正则方程是首选的做法,因为它本身已经是一阶常微分方程组,可以直接用解算器进行数值解。但对于较复杂的系统,哈密顿量比拉格朗日量难算得多,甚至可能没有解析表达式。
相比之下,拉格朗日量虽然容易写出,但方程的数值解比哈密顿正则方程要难一些,且如果用差分法计算微分会引入一定的数值误差。
由拉格朗日方程(式 3 )
根据
全微分,左边有
代入得
这样,二阶导数只存在于左边的 ,其他项都只是 的函数。该式中的偏微最好计算出解析表达式,但也可以通过
差分来计算(会引入更多误差)。数值解线性方程
1,就可以得到(令 )(
定理 2 )
就得到了 条方程组成的一阶常微分方程组,变量一共有 个。可以使用
四阶龙格库塔法等方法求解。
代码依赖 “偏导与差分” 中的 D2_ij.m
,以及 “导数与差分” 的 D_i.m
。
未完成:dL, d2L, Q 参数未测试
代码 1:lagr_solve.m
function qq = lagr_solve(L, qq0, t, RelTol, dL, d2L, Q, vpa_flag)
h = 1e-5;
h2 = 1e-5;
N = numel(qq0)/2;
if ~exist('vpa_flag', 'var') || isempty(vpa_flag)
vpa_flag = false;
end
if ~exist('d2L', 'var') || isempty(d2L)
if ~exist('dL', 'var') || isempty(dL) || isnan(dL(N+1,[qq0, tmin]))
if vpa_flag
d2L = @(i,j,qqt)D2_ij_vpa(L,i,j,qqt,h2);
else
d2L = @(i,j,qqt)D2_ij(L,i,j,qqt,h2);
end
else
d2L = @(i,j,qqt)d2L_dif1(dL,i,j,qqt,h);
end
end
if ~exist('dL', 'var') || isempty(dL)
if vpa_flag
dL = @(i, qqt)D_i_vpa(L, i, qqt, h);
else
dL = @(i, qqt)D_i(L, i, qqt, h);
end
end
if ~exist('Q', 'var') || isempty(Q)
Q = @(i,qqt) 0;
end
options = odeset('RelTol', RelTol);
[T, QQ] = ode45(@(t,qq)ode_fun(t, qq, dL, d2L, Q), ...
[t(1), t(end)], qq0, options);
qq = zeros(numel(t), 2*N);
for i = 1:2*N
qq(:,i) = interp1(T, QQ(:,i), t, 'spline');
end
end
function dqq = ode_fun(t, qq, dL, d2L, Q)
N = numel(qq)/2;
dqq = zeros(2*N, 1);
dqq(1:N) = qq(N+1:end);
qqt = [qq; t];
A = zeros(N, N);
for i = 1:N
for j = i:N
A(i,j) = d2L(i+N, j+N, qqt);
if i ~= j
A(j,i) = A(i,j);
end
end
end
b = zeros(N, 1);
for i = 1:N
b(i) = dL(i, qqt) - d2L(i+N,2*N+1,qqt) + Q(i,qqt);
for j = 1:N
b(i) = b(i) - d2L(N+i,j,qqt)*qqt(j+N);
end
end
dqq(N+1:end) = A \ b;
if any(isnan(dqq) | isinf(dqq))
error('wrong!');
end
end
function ret = d2L_dif1(dL, i, j, qqt, h)
qqt(j) = qqt(j) - 0.5*h;
L1 = dL(i, qqt, h);
h = (qqt(j) + h) - qqt(j);
qqt(j) = qqt(j) + h;
L2 = dL(i, qqt, h);
ret = (L2 - L1) / h;
end
用双摆的例子来测试,比较 “双摆的数值计算(Matlab)” 的结果:
代码 2:lagr_solve_demo.m
1. ^ 如果 不大可以直接用克拉默法则,甚至写出解析解。
致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择大量广告以及内容付费等。 因此,我们请求广大读者
热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 20 元,我们一周就能脱离亏损, 并在接下来的一年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。