As in this question, I’m hoping to combine two ODE solutions, but I really need some of the nice features of the solutions — mostly dense output. And maybe in some ways my problem is easier because I really have the same ODEProblem, but just have to solve it both forwards and backwards in time.
So my question is primarily: How do I combine the two to get dense output? (Secondarily: are there any other features that might come in handy that I should try to retain?)
Schematically, I have something like this:
using DifferentialEquations, DiffEqBase
problem_forwards = ODEProblem(RHS!, uᵢ, (0, T))
solution_forwards = solve(problem_forwards, <...>)
problem_backwards = remake(problem_forwards; tspan=(0, -T))
solution_backwards = solve(problem_backwards, <...>)
solution_backwards = solution_backwards[end:-1:2]
(In that last line, I’ve just reversed the solution and dropped the 1 element because it’s identical to the 1 element of solution_forwards.)
My naive attempt to combine them looks like this:
alg = solution_forwards.alg
t = = [solution_backwards.t; solution_forwards.t]
u = [solution_backwards.u; solution_forwards.u]
k = [solution_backwards.k; solution_forwards.k]
retcode = solution_forwards.retcode # Could be something more clever; maybe worse retcode?
problem = remake(solution_forwards.prob, tspan=(t[1], t[end]))
sol = DiffEqBase.build_solution(
problem, alg, t, u,
dense=true, k=k, retcode=retcode
)
But evidently it’s not enough to just copy u, t, and k, because sol.interp is a different type than solution_*.interp, and achieves significantly different results — presumably because it’s using the default LinearInterpolation(t, u). I can’t figure out how to construct a new interp to pass to this function. It felt a bit hacky, but I tried
interp = OrdinaryDiffEq.InterpolationData(
solution_forwards.interp.f,
u,
t,
k,
solution_forwards.interp.dense,
solution_forwards.interp.cache
)
Unfortunately, this gives incorrect results for times in the solution_backwards regime. (Also, for at least some choices of time stepper, I would apparently need to construct a CompositeInterpolationData.)
I’m not sure how much this matters, but it also seems that at least for some time steppers, alg is not the same for forwards and backwards integration. Specifically, if I use AutoVern9(Rodas5()), there’s this tiny difference in the alg that may just be some unique tag.
Is there some way to do this joining more correctly and/or elegantly?