Matlab中ode45两种求解方案结果差异原因问询
两种ODE45求解方案结果差异的原因分析
首先明确你要解的非线性微分方程为:
$$\frac{dT}{dt} = \frac{(1-\alpha)Q - \sigma T^4}{R}$$
对应的参数定义如下:
R=2.912; Q = 342; alpha=0.3; sigm=5.67*(10^(-8)); TT=20; t0=0;
两段代码的核心差异拆解
先把你的两段代码清晰展示出来,再逐一分析差异根源:
Code#1
tspan1 = t0:0.05:TT; [t1,y1] = ode45(@(t1,T) ((1-alpha)*Q-sigm*(T.^4))/R, tspan1, t0); h1=(TT-t0)/(size(y1,1)-1); Tspan1=t0:h1:TT; figure(55);plot(Tspan1,y1,'b');
Code#2
tspan=[t0 TT]; [t,y] = ode45(@(t,T) ((1-alpha)*Q-sigm*(T.^4))/R, tspan, t0); h=(TT-t0)/(size(y1,1)-1); Tspan=t0:h:TT; figure(5);plot(Tspan,y,'b');
差异的具体原因
ODE45的
tspan调用逻辑不同- 在Code#1中,你传入的是等间隔的时间点序列
tspan1 = t0:0.05:TT。此时ode45会先用自身的自适应步长完成数值求解,再将计算结果插值到你指定的每个时间点上输出,所以y1的长度和tspan1完全一致。 - 在Code#2中,你传入的是仅包含起止时间的二元向量
tspan=[t0 TT]。这种情况下,ode45会根据解的变化快慢自动选择输出时间点(自适应步长策略,目的是控制求解误差),输出的t和y的长度远小于Code#1中的序列长度。
- 在Code#1中,你传入的是等间隔的时间点序列
Code#2存在变量复用错误
这是导致结果差异最直接的问题:- Code#2里计算步长
h时,调用了Code#1生成的变量y1的尺寸size(y1,1),这意味着h和Code#1的h1完全相同(都是0.05),进而生成的Tspan和Code#1的Tspan1是完全一样的等间隔序列。 - 但Code#2中
ode45返回的y的长度远小于Tspan的长度,执行plot(Tspan,y,'b')时,MATLAB会因维度不匹配要么直接报错,要么自动做不合理的元素填充(比如重复y的元素),这直接导致绘图结果和Code#1完全偏离。
- Code#2里计算步长
插值逻辑的隐性差异(次要)
就算你把Code#2中的size(y1,1)改成size(y,1),结果仍会和Code#1有细微差异:- Code#1是求解器内部将自适应步长的结果插值到等间隔点;
- 若你手动用
interp1(t,y,Tspan)插值Code#2的结果,虽然都是插值,但原始采样点是求解器自动选取的,和Code#1内部的插值过程会存在细微数值偏差(不过这个差异通常很小,远不如变量复用错误导致的差异明显)。
Code#2的修正方案
如果你想让Code#2得到和Code#1一致的结果,可修改为:
tspan=[t0 TT]; [t,y] = ode45(@(t,T) ((1-alpha)*Q-sigm*(T.^4))/R, tspan, t0); % 生成和Code#1一致的等间隔时间点 Tspan = t0:0.05:TT; % 将ode45的结果插值到等间隔点 y_interp = interp1(t,y,Tspan); figure(5);plot(Tspan,y_interp,'b');
修改后两段代码的绘图结果会基本一致(数值上的细微差异可忽略)。
内容的提问来源于stack exchange,提问作者Morteza
相关产品推荐
相关产品推荐

