-
-
Notifications
You must be signed in to change notification settings - Fork 235
Description
Background
In Ribasim we solve a system of ODEs for the water storage in water bodies of the form
i.e. a simple conservation equation per water body with boundary conditions and exchanges with neighboring water bodies. Our first OrdinaryDiffEq.jl implementation of this used the water storages in the water bodies as states. A downside however is that the solver then doesn't tell us the integrated fluxes between the water bodies, which is important for many of our applications. These fluxes can not be reconstructed from the storage changes as this is an underdetermined problem. We can compute the integrated fluxes from the instantaneous fluxes only when using simple algorithms (e.g. Euler forward/backward), but we settled on QNDF because it gives us the best performance (large models have ~50.000 water bodies).
Our next step was to reformulate our ODE in terms of integrated fluxes, i.e the ODEs simply become
where the storages are formulated from the
Current developments
I'm currently working on a PR where I formulate the ODE system in terms of integrated flux states, but solve internally in terms of storage states. The key insight is that the computation from integrated fluxes to storages is linear, so that our ODE system is of the form
using that
where
There are several things we can do to take advantage of this structure of
- For Jacobian computation we can make use of the chain rule to only use AD to compute the
$(n, k)$ sized Jacobian of$g$ instead of the$(n, n)$ sized Jacobian of$f$ ; - For the linear solve we can use the Woodbury matrix identity to solve in terms of
$k$ unknowns instead of$n$ unknowns, see here for the precise derivation.
Recommendations and open questions
- It required quite a bit of overloading internals of
OrdinaryDiffEq.jlto get the above to work. Since it is quite a general procedure (applicable for every conservation based ODE system where accurate integrated flux computation is important), it might merit its own subpackage - I would like to also like to compute
EEstin the reduced space, but this isn't easy to do because of how this computation is incorporated inperform_step!based oncalculate_residuals!andinternalnormin an algorithm specific way - Currently we have to constantly update our reltol in the integrated flux formulation because of the ever growing state values (even in a dynamic equilibrium situation), it would be nice if this could be handled internally
- Generally speaking, it seems that the
OrdinaryDiffEq.jlinternals aren't really designed to incorporate the described kind of 'state space reduction', is there a nice way to get around this? - Maybe there is a way to achieve the above with a state object that contains both
SandQ?