Ahh yes, systems dynamics is something I’ve been looking at for a decade. Actually, fun fact, a long time ago I wrote pieces for a scripting language for a system modeling software (see the “Chris Rackauckas, June 2012” at the bottom ) which is now known as Numerus. So I’ve built and played with these things quite a bit. One of the big choices one has to make in this kind of model is how continuous is interpreted between components. There are really two choices: either every continuous piece is solved together, or in isolation as a cosimulation.

Most simulation tools take the later choice, with Causal.jl being one of them. This can be very natural and allows any simulation to be composed together. For example, piecing a stochastic differential equation with a delay differential equation requires you specify two sets of equations, two solvers, and link them. There are mathematical and numerical problems with this of course though. For one, the composition of those two equations actually falls into the class of stochastic delay differential equations, and so you need specialized solvers to actually accurately capture the composition of the two. The delay differential equation piece in particular will be overly confident in its steps and have O(dt^{1/2}) accuracy while it things it has a lot more (usually O(dt^5)), which is mostly a theoretical concern (because “the equations aren’t exact/real”) until you start looking into things like “why won’t this stay positive?” with the answer being induced numerical error. The other problem associated with this approach is the handling of algebraic loops where, if you want to keep separate simulations intact, you need to jump through some hoops to get stability, or sometimes it might not be possible. Indeed, these explicit systems can become differential-algebraic equations through the connections, sometimes higher index DAEs, so things like Pantelides etc. are required to simulate them efficiently and accurately, and breaking of algebraic loops is a crude approximation to this.

This is not to harp on Causal.jl though. For such multi-clocked simulation environments, I would say that Causal.jl is probably the best one that I’ve ever seen. It’s just that the approach, while being by far the most common, has some major limitations for someone looking to achieve top level performance.

In contrast, the ModelingToolkit approach, based on the Modelica approach, considers the whole system as a single unit and simulates it together. Handling of algebraic loops becomes the symbolic tooling around differential-algebraic equations. A global symbolic view of the set of equations allows for symbolic simplifications, index reduction, tearing, etc. to all happen automatically. Everything generates into a single simulation code that can be orders of magnitude faster than having separate simulators within the components. Numerical accuracy is kept because you are forced to use a solver appropriate for the whole. There is a downside that supporting some more advanced functionality, like stochastic pieces + delays, is much more difficult, and sometimes the “faked” composed version is “fine enough” (and if it is fine enough for someone, it can be a lot faster than resorting to full SDE simulations which are much more expensive). However, I plan to get ModelingToolkit to cover those cases anyways, so we’ll get there.

Thus expect to see systems dynamics examples coming out of ModelingToolkit and related graphical tooling of JuliaSim.