Breaking down NDSolveValue
into its component steps and inserting a hook back to the numerical function that computes the derivative:
({state} =
NDSolve`ProcessEquations[{y'[x] == -x, y[0] == 1},
y[x], {x, 0, 100}, StepMonitor :> Sow[First@nf[x, {y[x]}]]];
nf = state@"NumericalFunction";
NDSolve`Iterate[state, 100];
y[x] /. NDSolve`ProcessSolutions[state]) // Reap
(*
InterpolatingFunction[{{0., 100.}}, <<4>>][x],
{{-0.000171081, -0.000342162, -0.000684323, -0.00102648, \
-0.00136865, -0.00479026, -0.00821188, -0.0116335, -0.0458497, \
-0.0800658, -0.114282, -0.456444, -0.798605, -1.14077, -4.56238, \
-7.984, -11.4056, -21.4056, -31.4056, -41.4056, -51.4056, -61.4056, \
-71.4056, -81.4056, -90.7028, -100.}}}
*)
Remark: First@nf[x, {y[x]}]
returns the first element of the derivative vector, which is of the form {y'[x]}
in this case. For higher order equations and higher dimensional systems, omitting First
will give the derivatives of all the variables. Here's an example that uses the built-in utilities described in the tutorial Components and Data Structures to construct a step monitor that does not depend on how NDSolve
orders the values in the derivative vector. It returns substitution rules that may be used to get whichever derivative values are desired.
({state} =
NDSolve`ProcessEquations[{y''[x] == -x, y[0] == 1, y'[0] == 0},
y[x], {x, 0, 100},
StepMonitor :> Sow[Thread[
NDSolve`SolutionDataComponent[state@"Variables", "X'"] ->
nf[
NDSolve`SolutionDataComponent[state@"Variables", "T"],
Through[
NDSolve`SolutionDataComponent[state@"Variables", "X"]@
NDSolve`SolutionDataComponent[state@"Variables", "T"]
]
]]]];
nf = state@"NumericalFunction";
NDSolve`Iterate[state, 100];
y[x] /. NDSolve`ProcessSolutions[state]) // Reap // Last
(* omit "// Last" to get solution and derivative values
{{{y' -> -2.06958*10^-8, y''] -> -0.00014386},
{y' -> -6.20874*10^-8, y'' -> -0.000287721},
...
{y' -> -5000., y'' -> -100.}}}
*)
Or to get just y''[x]
and z''[x]
, in that order, from a system of second-order equations:
Clear[state, nf, ypp, zpp];
({state} =
NDSolve`ProcessEquations[{y''[x] == -x, y[0] == 1, y'[0] == 0,
z''[x] == -y[x] - 10, z[0] == 0, z'[0] == 0},
{y[x], z[x]}, {x, 0, 100},
StepMonitor :> Sow[Extract[ (* extract second derivatives from nf[] *)
nf[
NDSolve`SolutionDataComponent[state@"Variables", "T"],
Through[
NDSolve`SolutionDataComponent[state@"Variables", "X"]@
NDSolve`SolutionDataComponent[state@"Variables", "T"]
]],
Join[ypp, zpp]]]];
ypp = Position[NDSolve`SolutionDataComponent[state@"Variables", "X'"], y''];
zpp = Position[NDSolve`SolutionDataComponent[state@"Variables", "X'"], z''];
nf = state@"NumericalFunction";
NDSolve`Iterate[state, 100];
{y[x], z[x]} /. NDSolve`ProcessSolutions[state]) // Reap
MonitorMethod
of the plug-in framework $\endgroup$ – Michael E2 Apr 7 '19 at 15:19