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, DynamicQuantities
using ModelingToolkit: t, D
struct LossCoupler sys end
function Loss()
@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 = D(A) ~ -k*exp(T/T₀) * A
ODESystem([eq], t; name=:Loss, metadata=Dict(:coupletype=>LossCoupler))
end
Loss()
\[ \begin{align} \frac{\mathrm{d} A\left( t \right)}{\mathrm{d}t} &= - k e^{\frac{T}{\mathtt{T{_0}}}} A\left( t \right) \end{align} \]
Next, we specify the temperature that varies in time.
struct TemperatureCoupler sys end
function Temperature()
@variables T(t)=300 [unit=u"K"]
@constants Tc=1.0 [unit=u"K/s"]
@constants tc=1.0 [unit=u"s"]
eq = D(T) ~ sin(t/tc)*Tc
ODESystem([eq], t; name=:Temperature, metadata=Dict(:coupletype=>TemperatureCoupler))
end
Temperature()
\[ \begin{align} \frac{\mathrm{d} T\left( t \right)}{\mathrm{d}t} &= \mathtt{Tc} \sin\left( \frac{t}{\mathtt{tc}} \right) \end{align} \]
Now, we specify how to compose the two systems using param_to_var
.
function EarthSciMLBase.couple2(loss::LossCoupler, temp::TemperatureCoupler)
loss, temp = loss.sys, temp.sys
loss = param_to_var(loss, :T)
ConnectorSystem([loss.T ~ temp.T], loss, temp)
end
Finally, we create the system components and the composed system.
l = Loss()
temp = Temperature()
variable_loss = couple(l, temp)
convert(ODESystem, variable_loss)
\[ \begin{align} \frac{\mathrm{d} \mathtt{Loss.A}\left( t \right)}{\mathrm{d}t} &= - \mathtt{Loss.k} e^{\frac{\mathtt{Loss.T}\left( t \right)}{\mathtt{Loss.T{_0}}}} \mathtt{Loss.A}\left( t \right) \\ \frac{\mathrm{d} \mathtt{Temperature.T}\left( t \right)}{\mathrm{d}t} &= \mathtt{Temperature.Tc} \sin\left( \frac{t}{\mathtt{Temperature.tc}} \right) \end{align} \]
If we wanted to, we could then run a simulation with the composed system.