I'm trying to tweak the NDSolve function to perform one elementary integration step (using some explicitly selected stepping algorithm via Method option). Such a possibility is crucial for me, since after each performed step I'd like to check for some condition and modify state vector, then continue the integration. To the best of my knowledge such an operation is not possible with the 'pure' NDSolve, therefore I'm looking for an alternative solution.
So far, I managed to come up with the following solution (please note that the order of a method is selected to mimic the case with a lot of internal steps, this is equivalent to the higher order and longer integration period - tmax):
eq = {{x''[t] == -x[t], x[0] == 0, x'[0] == 1}, x, t};
tmax = 1;
method = {"ExplicitRungeKutta", "DifferenceOrder" -> 2};
Block[{state, options, timer},
options = {MaxSteps -> Infinity, Method -> method};
state = First@NDSolve`ProcessEquations[Sequence @@ eq, options];
timer = First@Timing[NDSolve`Iterate[state, tmax]];
{timer, state@"CurrentTime"["Forward"], state@"TimeStepsUsed"["Forward"], state@"SolutionVector"["Forward"]}
]
(* ==> {0.048003, 1., 7032, {0.841471, 0.540302}} *)
Block[{state, options, ctime, ic, dt, count, timer},
options = {MaxSteps -> 1, Method -> method};
state = First@NDSolve`ProcessEquations[Sequence @@ eq, options];
count = 0;
ctime = state@"CurrentTime"["Forward"];
timer = First@Timing@While[ctime < tmax,
Quiet[NDSolve`Iterate[state, tmax*1.000001], NDSolve::mxst];
ctime = state@"CurrentTime"["Forward"];
ic = state@"SolutionVector"["Forward"];
dt = state@"TimeStep"["Forward"];
state = First@NDSolve`Reinitialize[state, {x[ctime] == ic[[1]], x'[ctime] == ic[[2]]}, StartingStepSize -> dt];
count++;
];
{timer, state@"CurrentTime"["Forward"], count, state@"SolutionVector"["Forward"]}
]
(* ==> {3.1722, 1., 2948, {0.841471, 0.540302}} *)`
Timing results are not optimistic. The situation is worse when one want use step size from the previous step (with StartingStepSize -> dt commented in Reinitialize).
Is there a better (more efficient) way to to this?
StepMonitor? reference.wolfram.com/mathematica/ref/StepMonitor.html but not sure now how to tell it in the StepMonitor Function to stop integrating if that is what you want. – Nasser Sep 28 '12 at 17:55StepMonitordoesn't allow to change the current state of integrated equation. – mmal Sep 28 '12 at 17:58Throw[]to stop the integration. See my answer. – Nasser Sep 28 '12 at 18:04