Scaling Independent Variables in Composed `ODESystem`s

I have code that implements the nondimensional form of a simplified three-body problem. The length units are scaled by the distance between the two celestial bodies, a, and the time units are scaled by the orbital period of the two bodies, T, about their common center of mass.

I have the nondimensional form as an ODESystem. A simplified system is shown below in f. Now I’m trying to implement the dimensioned system, which scales all of the variables appropriately, as in g. So g.x ~ f.x / a. That works fine.

But f and g have different independent variables… specifically, the independent variable in f is equivalent to the independent variable in g divided by T.

Is this possible to do? Can I relate one system’s iv to another’s? The goal here is for the user to never have to interact with nondimensioned units. They can specify initial conditions in the dimensioned units, and under the hood structural_simplify scales the conditions and dynamics.

I can accomplish all of this by pasting the equations of f inline within g, as opposed to composing the two systems, but I was wondering if there’s a way to do this through model composition.

using ModelingToolkit

function f()
   @parameters t p
   @variables x(t)
   d = Differential(t)
   
   return ODESystem([d(x) ~ -p * x], t, [x], [p]; name=:f)
end

function g()
   @parameters τ p₁ p₂ a
   @variables x(τ)
   
   T = 2π * sqrt(a^3 / (p₁+p₂))
   s = f()
   return compose(ODESystem([s.p ~ p₂ / (p₁+p₂), x ~ a * s.x, s.t ~ τ / T], τ, [x], [p₁, p₂, a]; name=:g), s)
end

g()
ERROR: ArgumentError: System f: variable t does not exist
Stacktrace:
 [1] getvar(sys::ODESystem, name::Symbol; namespace::Bool)
   @ ModelingToolkit ~/.julia/packages/ModelingToolkit/FbXPg/src/systems/abstractsystem.jl:358
 [2] getvar
   @ ~/.julia/packages/ModelingToolkit/FbXPg/src/systems/abstractsystem.jl:311 [inlined]
 [3] getproperty(sys::ODESystem, name::Symbol; namespace::Bool)
   @ ModelingToolkit ~/.julia/packages/ModelingToolkit/FbXPg/src/systems/abstractsystem.jl:309
 [4] getproperty
   @ ~/.julia/packages/ModelingToolkit/FbXPg/src/systems/abstractsystem.jl:308 [inlined]
 [5] g()
   @ Main ./REPL[8]:7
 [6] top-level scope
   @ REPL[10]:1

Right now you can only compose systems with the same independent variable, but I think with an equation relating independent variables it would be possible in theory, so open an issue as this might be a fun project down the line.

1 Like