公告:1)网站程序升级:Q2A升级到1.8.6,Wordpress升级到5.7.2
2)修复了头像加载慢与提交问题反应慢等问题
2021-06-16

欢迎来到 Mathematica 问答社区

提问时请贴上文本代码

语法高亮:在编辑器中点击

被禁止的话题:广告破解

请阅读:《提问的智慧》

备用域名:mma.ooo

支持LaTex数学公式
行内公式标识符:\$ 或“$\backslash ($”+“$\backslash )$”,
行间公式标识符:\$\$ 或 “$\backslash [$”+“$\backslash ]$”

社区建议QQ群:365716997

分类

+1 投票
1.1k 浏览
Clear["Global`*"]
f[x_, \[Delta]_] = x (1 - (1 + \[Delta]/x^3)^(-1/3));
w[x_] := x^(-4) + 2 x^2 - 3 + c*(x^4 + 2*x^(-2) - 3)  ;       
pind[\[Lambda]_] = 
  Integrate[D[w[\[Lambda]], \[Lambda]]/(-1 + \[Lambda]^3), \[Lambda], 
   Assumptions -> \[Lambda] > 1];
h[x_, \[Delta]_, c_] = 
  pind[x] - pind[((x^3 + \[Delta])/(1 + \[Delta]))^(1/3)];
g[x_, \[Delta]_] = 
  1/2*((1 + \[Delta]/x^3)^(-4/3) - 4 (1 + \[Delta]/x^3)^(-1/3) + 3);
p[p1_, \[Epsilon]_, \[Omega]_, t_] := p1 + \[Epsilon]*Sin[\[Omega]*t];

tendlist = {2000, 5000};  (*两个不同的截止时间*)


sol = Table[ 
  Block[{p1 = 0.6338, \[Delta] = 1, 
    c = 0.1, \[Omega] = 1.88, \[Epsilon] = 0.001}, 
   NDSolve[{f[x[t], \[Delta]]*x''[t] + g[x[t], \[Delta]]* x'[t]^2 + 
       h[x[t], \[Delta], c] == p[p1, \[Epsilon], \[Omega], t]
     , x[0] == 2.25375, x'[0] == 0}, {x[t], x'[t]}, {t, 0, 
     tend (*此处为截止时间*)}, MaxSteps -> \[Infinity]]], {tend, tendlist}];
tx1 = Plot[Evaluate[x[t] /. sol[[1]]], {t, 0, 100}, 
   AxesLabel -> {"t", "x"}, 
   GridLines -> {None, {{2.25375, {Red, Thick}}}}, 
   PlotStyle -> Dashed];
tx2 = Plot[Evaluate[x[t] /. sol[[2]]], {t, 0, 100}, 
   AxesLabel -> {"t", "x"}, 
   GridLines -> {None, {{2.25375, {Red, Thick}}}}];
Show[tx1, tx2](*对比不同截止时间,相同时间段0--100的数值结果,出现差异现象*)

NDSolve解微分方程为什么会受截止时间的影响?

附对比图如下

其中,虚线 tmax=2000

      实线 tmax=5000

分类:函数 | 用户: keanhy (361 分)

1个回答

+1 投票
 
已采纳

NDSolve的常微分方程初值问题求解器的误差控制我还真没研究过,但是我可以告诉你的是,这两个解其实都不准。非线性常微分方程初值问题在演化足够长的时间后出现明显误差累计是很常见的。唯一的通用对策是增加WorkingPrecision:

tendlist = {100, 101};(*要重现这个问题并不需要这么多时间*)
sol = Table[
  Block[{p1 = 0.6338, \[Delta] = 1, c = 0.1, \[Omega] = 1.88, \[Epsilon] = 0.001}, 
   NDSolve[Rationalize[#, 
       0] &@{f[x[t], \[Delta]]*x''[t] + g[x[t], \[Delta]]*x'[t]^2 + 
        h[x[t], \[Delta], c] == p[p1, \[Epsilon], \[Omega], t], x[0] == 2.25375, 
      x'[0] == 0}, {x[t], x'[t]}, {t, 0, tend }, WorkingPrecision -> 16]], {tend, 
   tendlist}];
   
   Plot[x[t] /. sol[[All, 1]] // Evaluate, {t, 0, 100}, AxesLabel -> {"t", "x"}, 
 GridLines -> {None, {{2.25375, {Red, Thick}}}}, 
 PlotStyle -> {Automatic, {Orange, Thick, Dashed}}]

此外,针对特定的方程似乎还有一些更经济的方法。(什么守恒格式之类的。)当然这个我也不懂,就此打住。

用户: xzczd (2.1k 分)
采纳于 用户:keanhy
{100,101}时间相差很小结果是一致的,当时间相差很大时,{2000,5000}这样的,结果就有明显的不同了!
初值都是一样的,如果算法相同,在相同的时间节点上误差累计也会相同的。会是NDSolve根据不同的积分范围改变了内部算法吗?
对于更长的时间必须使用更多位数的WorkingPrecision,当然限于计算机性能这个方法也会很快就变得不适用……“初值都是一样的,如果算法相同,在相同的时间节点上误差累计也会相同的。”不,选择参数的策略不同的话,就算算法相同,结果也会不一样,比如"Extrapolation"方法里就有个显然会影响最终结果的“初始步长”。实际上你加个StartingStepSize -> 0.1就会发现两个结果一样了。
谢谢,数值积分只用一个NDSolve求解看起来很简洁,但是考虑到细节的时候总感觉不好理解,很多地方都是“自适应”...
...