# Stopping NDSolver at time of error

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?

• Doesn't the solver already stop exactly at the point mentioned? – J. M.'s discontentment Jul 4 '15 at 10:52
• Maybe it does, but the solution is then just extrapolated for the remaining time. Is there a way to return the last time t before the error? I am thinking of something like WhenEvent["error", tfinal = t] – Andrea Jul 4 '15 at 11:29
• – Mariusz Iwaniuk Jul 4 '15 at 13:13
• Unfortunately the system does not hit a singularity, so I have no way to analytically identify a point where to stop the integration, like in the link. There is no way to make it stop in response to the error itself? – Andrea Jul 4 '15 at 13:28
• Let's say you have sol = NDSolve[..., x, {t, 0, 100000}]. The x["Domain"] /. sol will yield {{{0, 49169.954923435114}}}, and you can get the time it stopped. You can also use the option NDSolve[..., "ExtrapolationHandler" -> {Indeterminate&}] and the solution won't extrapolate; however, it will return Indeterminate, which may be good or may cause other problems. Without explicit code, we're just guessing. – Michael E2 Jul 4 '15 at 17:43

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`....