I am using NDSolver and WhenEvent to solve a system of differential equations. I get this message:
NDSolve::ndsz: At t == 49169.954923435114`, step size is effectively zero; singularity or stiff system suspected.
The solution I get is pretty stable until that time, then blows off completely. At each evaluation I get the same behaviour at different times.
I understand that the problem might lie with the fact that I am solving for very long times, and eventually the algorithm just starts having problems handling all the data.
Is there a way to stop the solver as soon as the error comes up?
Answer
First, a test case:
sol = NDSolve[{x'[t] == -1/x[t], x[0] == -1}, x, {t, 0, 2}]
NDSolve::ndsz: At t == 0.499999735845871`, step size is effectively zero; singularity or stiff system suspected. >>

Consult What's inside InterpolatingFunction[{{1., 4.}}, <>]? or InterpolatingFunctionAnatomy and you will discover that InterpolatingFunction comes with lots of utilities and methods that give access to a wealth of information. In particular, the method "Domain" will yield the domain of the InterpolatingFunction, which in this case will be the interval over which NDSolve successfully integrated the ODE (up to the point where stiffness stopped it).
{tstart, tstop} = Flatten[x["Domain"] /. sol]
(* {0.`, 0.499999735845871`} *)
A couple of ways to plot. Note for ListLinePlot, you don't need to know the domain; it and ListPlot handle InterpolatingFunction as a special case.
ListLinePlot[x /. sol]
Plot @@ {{x[t], x'[t]} /. First[sol], Flatten@{t, x["Domain"] /. sol}}

By default, going past the ends of the domain results in extrapolation.
Plot[x[t] /. First[sol], {t, 0, 2}]

One can use the option, mentioned in a comment in the linked question, "ExtrapolationHandler" to override the default extrapolation.
sol2 = NDSolve[{x'[t] == -1/x[t], x[0] == -1}, x, {t, 0, 10},
"ExtrapolationHandler" -> {Indeterminate &}];
Plot[x[t] /. First[sol2], {t, 0, 2}]
NDSolve::ndsz: At t == 0.4999997164125506`....

Comments
Post a Comment