Cross posted in scicomp.SE.
A friend of mine showed me this initial value problem (IVP) for a linear ordinary differential equation (ODE) with variable coefficient:
$$y''(x)=\left(x^2-1\right) y(x)$$$$y(0)=1$$$$y'(0)=0$$
Seems to be a simple one, right? Actually it can be solved analytically by DSolve
:
asol = DSolve[{y''[x] == (x^2 - 1) y[x], y[0] == 1, y'[0] == 0}, y[x], x]
{{y[x] -> E^(-(x^2/2))}}
But its numerical solution given by NDSolve
runs wild very fast:
l = 10;
nsol = NDSolve[{y''[x] == (x^2 - 1) y[x], y[0] == 1, y'[0] == 0},
y, {x, 0, l}]; // AbsoluteTiming
Manipulate[Plot[y[x] /. nsol // Evaluate, {x, 0, l2},
PlotRange -> {{0, 7}, {-10, 1}}], {l2, 1/10, 7}]
{0.015600, Null}
How to resolve the problem?
Well, actually I found two solution for this problem but one is time-consuming and the other is limited so I'm not quite satisfied.
Solution 1
A higher WorkingPrecision
will help:
l = 10;
nsol = NDSolve[{y''[x] == (x^2 - 1) y[x], y[0] == 1, y'[0] == 0},
y, {x, 0, l}, WorkingPrecision -> 50]; // AbsoluteTiming
Plot[y[x] /. nsol, {x, 0, l}, PlotRange -> All]
{2.857000, Null}
Nonetheless, this solution is slow, and will need a higher WorkingPrecision
and be even slower when l
gets larger.
Solution 2
Noticing the analytic solution involves a Exp
, given the experience that Exp
often causes trouble in numerical calculation, the transformation $y(x)=e^{z(x)}$ is used:
l = 50;
rule = y -> (Exp[z@#] &);
(* z[0] == 0 is manually substituted because it seems that
NDSolveValue has some difficulty in understanding y[0] == 1 /. rule *)
nsol = NDSolveValue[{y''[x] == (x^2 - 1) y[x], z[0] == 0, y'[0] == 0} /. rule,
z, {x, 0, l}]; // AbsoluteTiming
Plot[Exp@nsol[x], {x, 0, l}, PlotRange -> All]
{0.013000, Null}
However, as mentioned above, this solution is limited, I wouldn't have thought it out if I was unaware of the analytic solution, and I really doubt if this method can be extended: I guess there's a sort of problem behind this specific example, once it's solved, more complicated problem might be solved too, for example this and this.
I'd appreciate if anyone can give an in-depth explanation for the problem or find a better solution.