You should be aware of the fact that using either StepMonitor
or EvaluationMonitor
willcould considerably slow down the execution of NDSolve
, so the progress indication willmight come at a price. As there might be several evaluations per step, StepMonitor
will be excecuted less often than EvaluationMonitor
so might be a better choice in most cases. It also is one of those cases where restricting the update of the progress indiciation might make sense. Of course, the more expensive a single step/evaluation within NDSolve
is, the less will the percentual effort for the updates. Here are some example with which you can experiment, of course timings might be very different for different problems...
A simple example from the documentation:
p = 20; tmax = 100;
runNDSolve[opts___] := NDSolve[
{x''[t] + x'[t]/10 + x[t]/(1 + x[t]^2) == Sin[t], x[0] == 1,
x'[0] == 0}, x, {t, 0, tmax},
PrecisionGoal -> p, AccuracyGoal -> p, WorkingPrecision -> 2*p,
MaxSteps -> Infinity,
Method -> {"ExplicitRungeKutta", "DifferenceOrder" -> 8},
opts
]
you might adjust the precision to adjust runtimes to a few seconds so you can see what actually happens. Here is a run with no monitoring at all as a reference:
AbsoluteTiming[runNDSolve[];]
Compare EvaluationMonitor
to StepMonitor
:
AbsoluteTiming[runNDSolve[EvaluationMonitor :> (tt = t)];]
AbsoluteTiming[runNDSolve[StepMonitor :> (tt = t)];]
For this example on my computer the restriction of dynamic updating doesn't make much difference, but I have seen examples where doing this was crucial to not slow down the evaluation unacceptably, which can easily happen if you do something more expensive than update a progressbar, like e.g. show a plot.
tt = 0;
PrintTemporary@ProgressIndicator[Dynamic[tt], {0, tmax}];
AbsoluteTiming[runNDSolve[StepMonitor :> (tt = t)];]
tt = 0;
PrintTemporary@ProgressIndicator[Dynamic[
Refresh[tt, UpdateInterval -> 1, TrackedSymbols :> {}]
], {0, tmax}];
AbsoluteTiming[runNDSolve[StepMonitor :> (tt = t)];]
Here is a version of Feyre's elegant solution using Monitor
which restricts the update to a given interval. AFAIK this is not really documented but doesn't come as a surprise when assuming that the second argument will be wrapped in a Dynamic
at some point:
AbsoluteTiming[
Monitor[runNDSolve[StepMonitor :> (tt = t)],
Refresh[ProgressIndicator[tt/tmax], UpdateInterval -> 1,
TrackedSymbols :> {}]];]