计算时间与 ODE 求解器中的积分间隔不成比例?

计算科学 matlab 时间积分 八度
2021-12-12 23:05:47

我正在运行 octave,我一直在尝试使用 ode45、ode54、ode23 等来整合方程`

Q(t)=Bcos(Q)sin(ωt)
Q(t=0)=0.
当要积分的时间间隔增加时,执行时间非线性增加。从 t=0 积分到 t=T 需要 1.2 秒。10T 需要 12 秒,没问题!但是对于 100T,它需要 500 秒,而不是预期的 120 秒。这是为什么呢?我可以绕过它吗?

我必须将 1.2 秒的时间间隔积分大约 1000 倍。1200秒就好了。但4小时后我没有任何结果。

编辑:我在实际方程式中犯了几个错误,现在它是正确的。脚本如下所示:

U=1e-12; # Unit factor to make computation precise and fast. 

B = 0.7 * 6.2 / 2 * 1e26*U^2;
w = 6*pi/800 * 1e17*U;

OPT = odeset ("InitialStep",1e-16/U,"MaxStep", 4e-16/U, ...
"RelTol", 1e-1, "AbsTol", 1e-1);

tSpan=[0 1e-12/U]; #150 ps => 15 deg from 0 deg. 
init=[0 0]; 

tic
[t, g]=ode23( @(t,G)[G(2); B*cos(G(1))*sin(w*t)],tSpan,init,OPT);
t = t*U;
g=g(:,1);
toc
plot(t,g) 
1个回答

大量编辑,因为原始海报改变了他的方程式......

通常,MATLAB(和 Octave)ODE 求解器会根据需要动态调整步长以保持准确的解。如果积分器开始使用较小的步长,则该过程会减慢。

查看您的 ODE 的特定形式,因子的周期约为 0.003,因此需要的时间步长要小得多。设置最大时间步长限制以阻止求解器愚蠢地决定使用太大的时间步长也是明智之举。对于这个问题,0.0001 (1.0e-16/U) 的时间步长对我来说似乎是正确的,这就是 OP 给出的代码所使用的,以及 0.0004 (4e-16/U) 的最大时间步长。 sin(wt)

我们有兴趣在高达 1000 (1000/U) 的时间跨度下求解这个方程,因此我们正在考虑采取一千万步左右(如果求解器决定需要减少时间步长,则更多。)给定我们必须在每个时间步内多次评估函数以及 ODE 求解器的所有其他开销,这是一项相当大的工作。

我尝试在 MATLAB 下运行脚本 1、10、100 和 1000 周期,并得到完全一致的解决方案,经过时间分别为 0.3 秒、3.8 秒、32 秒和 322 秒。这是线性缩放的,因此求解器似乎不会因为时间步长很小而陷入困境。

为了检查解决方案的准确性,我尝试将最大时间步长减少 10 倍并重新运行。我得到了基本相同的解决方案,但经过的时间大约长了 10 倍。因此,我确信提供的初始时间步长和最大时间步长是可以的,并且 MATLAB 生成的解决方案相当准确(比如说 2 位数字。)

我还尝试允许更大的最大时间步长,发现 MATLAB 的 ode23() 被欺骗采取了太长的步长,并且得到的解决方案(虽然非常快)完全不准确。由于方程中的快速振荡,您需要小心限制该方程的最大时间步长。

我还尝试将相对和绝对误差容限从 1.0e-1 收紧到 1.0e-3(MATLAB 的默认值)。解决方案非常相似,但解决方案时间大约翻了一番。

我使用 ode45 而不是 ode23 进行了一些快速检查,得到了基本相同的解决方案,但执行时间大约是原来的两倍。这并不奇怪,因为我们的时间步长有限,并且 ode45 每个时间步长的函数评估次数大约是 ode23 的两倍。

我在 Octave 下的同一台机器上运行脚本,运行时间分别为 1 秒、10 秒、166 秒……(最后一个在超过 45 分钟后仍在运行。)我获得的解决方案看起来与MATLAB解决方案哪个好。但是,这不是线性缩放的,这表明 ode23 的 Octave 实现可能会缩短时间步长,而实际上它不需要这样做。

我建议您将此示例提供给 Octave ODE 包的开发人员,并请他们调查与 MATLAB ode23() 相比的较差性能。