I have a question that probably has a simple answer and is more conceptual, so I haven’t yet written a MWE.
I have a small system with low error tolerance that, ignoring any callbacks, is reasonably efficient in terms of allocations
@benchmark solve(testprob,Vern9(),save_everystep=false,reltol=1e-9,abstol=1e-9)
BenchmarkTools.Trial:
memory estimate: 9.11 KiB
allocs estimate: 22
--------------
minimum time: 21.803 ms (0.00% GC)
median time: 22.289 ms (0.00% GC)
mean time: 22.467 ms (0.00% GC)
maximum time: 24.702 ms (0.00% GC)
--------------
samples: 223
evals/sample: 1
I also have a callback that uses terminate!(integrator)
when some variable gets too large. With this callback, the time to solve is obviously much shorter, but the allocations are much larger:
BenchmarkTools.Trial:
memory estimate: 638.00 KiB
allocs estimate: 11803
--------------
minimum time: 566.178 μs (0.00% GC)
median time: 588.638 μs (0.00% GC)
mean time: 645.192 μs (7.58% GC)
maximum time: 8.254 ms (92.18% GC)
--------------
samples: 7743
evals/sample: 1
Is there a simple way to avoid these allocations? I.e, should I be doing anything special with the setup of the callback functions beyond stating the condition
and affect!
? They currently read something like:
function condition(out,u,t,integrator)
out[1] = ... #variable 1 zerocrossing
out[2] = ... #variable 2 zerocrossing
end
affect!(integrator,idx) = terminate!(integrator)
cb = VectorContinuousCallback(condition,affect!,2)