Converting parameters to variables

This can be useful to replace a parameter that does not change in time in a model component with one specified by another system that does change in time (or space). For example, the code below specifies a first-order loss equation, and then changes the temperature (which determines the loss rate) with a temperature value that varies in time.

As an example, we will create a loss equation that depends on the temperature, starting with a constant temperature. We will then create a temperature equation that varies in time, and use the param_to_var function to replace the constant temperature in the loss equation with the time-varying temperature.

So first, let's specify the original system with constant temperature.

using ModelingToolkit, EarthSciMLBase, Unitful

struct Loss <: EarthSciMLODESystem
    sys::ODESystem
    Loss(sys::ModelingToolkit.ODESystem) = new(sys)
    function Loss(t)
        @variables A(t)=1 [unit=u"kg"]
        @parameters k=1 [unit=u"s^-1"]
        @parameters T=300 [unit=u"K"]
        @constants T₀=300 [unit=u"K"]
        eq = Differential(t)(A) ~ -k*exp(T/T₀) * A
        new(ODESystem([eq]; name=:loss))
    end
end

Next, we specify the temperature that varies in time.

struct Temperature <: EarthSciMLODESystem
    sys::ODESystem
    function Temperature(t)
        @variables T(t)=300 [unit=u"K"]
        @constants Tc=1.0 [unit=u"K/s"]
        @constants tc=1.0 [unit=u"s"]
        eq = Differential(t)(T) ~ sin(t/tc)*Tc
        new(ODESystem([eq]; name=:temperature))
    end
end

Now, we specify how to compose the two systems using param_to_var.

function Base.:(+)(loss::Loss, temp::Temperature)
    loss = Loss(param_to_var(loss.sys, :T))
    losseqn = loss.sys
    teqn = temp.sys
    ComposedEarthSciMLSystem(
        ConnectorSystem([losseqn.T ~ teqn.T], loss, temp),
        loss, temp,
    )
end

Finally, we create the system components and the composed system.

@variables t [unit=u"s", description="time"]
l = Loss(t)
t = Temperature(t)
variable_loss = l+t

get_mtk(variable_loss)

\[ \begin{align} loss_{+}T\left( t \right) =& temperature_{+}T\left( t \right) \\ \frac{\mathrm{d} loss_{+}A\left( t \right)}{\mathrm{d}t} =& - loss_{+}k e^{\frac{loss_{+}T\left( t \right)}{loss_{+}T_0}} loss_{+}A\left( t \right) \\ \frac{\mathrm{d} temperature_{+}T\left( t \right)}{\mathrm{d}t} =& temperature_{+}Tc \sin\left( \frac{t}{temperature_{+}tc} \right) \end{align} \]

If we wanted to, we could then run a simulation with the composed system.