6

I would like to solve a system of ODEs numerically using NDSolve on an interval {t,t0,tf}.

For the systems I currently solve, calculations take quite long, and if I pick tf too large, it would be nice to have an option to break at some point without losing all data NDSolve has obtained so far.

Is there a way, say, to break with the press of the button, but without throwing away the data? So I want to stop the thing, but not abort.

Roman
  • 47,322
  • 2
  • 55
  • 121
Britzel
  • 663
  • 3
  • 10
  • 2
    Maybe you can use the following WhenEvent example from the documentation? – Carl Woll Jun 05 '19 at 17:59
  • Related: https://mathematica.stackexchange.com/questions/161560/output-of-intermediate-results-from-very-long-ndsolve-computation-into-sequenced/199228#199228 – Michael E2 Jun 05 '19 at 18:16
  • Related and disappointing in V12 (doesn't work any more): How to pause a running evaluation (and continue it later) – Roman Jun 05 '19 at 21:17
  • @CarlWoll I tried to use the stop button. While it worked in the example given in the help file, it doesn't seem to work in the application I would like to use it for. I opened a separate thread to ask for help. If you know what I am doing wrong, help would be much appreciated! : ) https://mathematica.stackexchange.com/questions/199890/ndsolve-stopintegration-button-using-whenevent-does-work – Britzel Jun 06 '19 at 21:40

1 Answers1

3

Aside from the stop Button[] example in the docs that Carl pointed out, here are a couple of ways.

The first saves the result periodically using NDSolve`ProcessSolutions[].

ClearAll[sol0];
NDSolve[{y''[x] == -y[x], y[0] == 1, y'[0] == 0, 
  WhenEvent[Mod[x, 10] == 0, 
   sol0 = NDSolve`ProcessSolutions[NDSolve`Self]; {}]},
  y, {x, 0, 1000000}]
(*  $Aborted   <-- because I aborted evalutation *)

sol0

enter image description here

Another way to advance the integration bit by bit using NDSolve`Iterate[]. This has the advantage that after being aborted, one can continue iterating without any further setup.

ClearAll[sol0];
{state} = NDSolve`ProcessEquations[{y''[x] == -y[x], y[0] == 1, y'[0] == 0}, 
  y, {x, 0, 1000000}];

Do[NDSolve`Iterate[state, tt], {tt, 10, 1000000, 10}]
(*  $Aborted   <-- because I aborted evalutation *)

state
(*  NDSolve`StateData[< 0., 12740.>]  <-- shows how far it got (12740.) *)

sol = NDSolve`ProcessSolutions[state]

enter image description here

Here's a way that saves every 1000 steps:

ClearAll[sol0];
nsteps = 0;
NDSolve[{y''[x] == -(1 + x/100) y[x], y[0] == 1, y'[0] == 0, 
  WhenEvent[Mod[nsteps, 1000] == 0, 
   sol0 = NDSolve`ProcessSolutions[NDSolve`Self]; {}]},
  y, {x, 0, 1000000}, StepMonitor :> ++nsteps]
(*  $Aborted   <-- because I aborted evalutation *)

y["Grid"] /. sol0 // Length
nsteps
(*
  49001
  49602
*)
Michael E2
  • 235,386
  • 17
  • 334
  • 747