# Component based modelling with ModelingToolkit.jl

**URL:** https://discourse.julialang.org/t/component-based-modelling-with-modelingtoolkit-jl/41116
**Category:** Modelling & Simulations
**Created:** [June 10, 2020, 9:31am UTC](https://discourse.julialang.org/t/component-based-modelling-with-modelingtoolkit-jl/41116 "2020-06-10T09:31:09Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)
#### Post date: [June 10, 2020, 9:31am UTC](https://discourse.julialang.org/t/component-based-modelling-with-modelingtoolkit-jl/41116/1 "2020-06-10T09:31:09Z")

</div>

I want to model a simple heating system using `ModelingToolkit.jl`. It consists of a _thermal storage_, a _boiler_ and a _heat consumer_.  
The following equations govern this model.

**Thermal Storage**  
The thermal storage has one state variable and is modelled with  
\frac{d}{dt}soc(t) = -\alpha soc(t) - \frac{1}{m\_{max}}(\dot{m}\_{in,A}(t) + \dot{m}\_{out,B}(t))  
where soc(t) is the state-of-charge of the thermal storage. \dot{m}\_{in,A}(t) and \dot{m}\_{out,B}(t) are the in and outflowing massflows of hot water.

**Boiler**  
The boiler has no dynamics and is modelled with  
\dot{m}\_{in,b}(t)T\_{in,b}c\_p+\dot{m}\_{out,b}(t)T\_{out,b}c\_p+\dot{Q}(t)=0  
\dot{Q}(t) = k u(t)  
\dot{m}\_{in,b}(t)+\dot{m}\_{out,b}(t) = 0  
where \dot{m}\_{in,b}(t)\leq0 and \dot{m}\_{out,b}(t)\geq0 are the in and outflowing massflows of water. T\_{in,b} and T\_{out,b} are the respective temperatures and c\_p is the specific heat capacity of water. u(t)\in(0,1) is the control input of the boiler. \dot{Q}(t)\geq0 is therefore the produced heat of the boiler.

**Heat Consumer**  
The heat consumer has no dynamics and is modelled with  
\dot{m}\_{in,hc}(t)T\_{in,hc}c\_p+\dot{m}\_{out,hc}(t)T\_{out,hc}c\_p-\dot{Q}\_{demand}(t)=0  
\dot{m}\_{in,hc}(t)+\dot{m}\_{out,hc}(t) = 0  
where \dot{Q}\_{demand}(t)\geq0 is the known heat demand of the cosumer. Again \dot{m}\_{in,hc}(t)\leq0 and \dot{m}\_{out,hc}(t)\geq0 are the in and outflowing massflows of water. T\_{in,hc} and T\_{out,hc} are the respective temperatures and c\_p is the specific heat capacity of water.

**Connections**  
\dot{m}\_{out,B}(t) + \dot{m}\_{in,hc}(t) = 0  
\dot{m}\_{out,b}(t) + \dot{m}\_{in,A}(t) = 0

For this simple example the whole thing could be condensed into one single ODE  
\frac{d}{dt}soc(t) = -\alpha soc(t) - \frac{1}{m\_{max}}(\frac{1}{(T\_{in,b}-T\_{out,b})c\_p}k u(t) + \frac{1}{(T\_{in,hc}-T\_{out,hc})c\_p}\dot{Q}\_{demand}(t))  
but I want to automate that.

**My questions?**

- The ODE for the thermal storage is quite clear but how can I model the other to _componets_ with `ModelingToolkit.jl`? Is this even possible since they have no state variables?
- How would I provide known variables like \dot{Q}\_{demand}(t) or u(t) using `ModelingToolkit.jl`? u(t) can only change a fixed time steps and \dot{Q}\_{demand}(t) would have to be interpolated for a given t. I guess this is something for a `PeriodicCallback`?

For the manual approach I have:

```julia
mutable struct SimType{T} <: DEDataVector{T}
    x::Vector{T}
    u::T
    Qdot_hc::T
end

function f(du, u, p, t)
    mdot_in_gb = k * u.u / (cp_W * (T_in_gb - T_out_gb))
    mdot_out_hc = u.Qdot_hc / (cp_W * (T_in_hc - T_out_hc))

    du[1] = - alpha * u[1] - 1 / m_max * (mdot_in_gb + mdot_out_hc)
    return
end

function cb(int)
    timestamp = t0 + int.t
    int.u.u = # interpolate from data
    int.u.Qdot_hc = # interpolate from data
    return
end

u0 = SimType([0.5], 0.0, Qdot_hc_0)
tspan = (0.0, 900. * 96) # 24h @ 15min
prob = ODEProblem(f, u0, tspan)
sol = solve(prob, Tsit5(); callback = PeriodicCallback(cb, 900.))

```

However, I do not quite get the correct results. Is there any obvious mistake?

Thanks!

---

<div class="post-metadata">

### Author: ![jonniedie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonniedie/32/12842_2.png) [@jonniedie](https://discourse.julialang.org/u/jonniedie)
#### Post date: [June 27, 2020, 3:59am UTC](https://discourse.julialang.org/t/component-based-modelling-with-modelingtoolkit-jl/41116/2 "2020-06-27T03:59:15Z")

</div>

It looks like you’ve got yourself a DAE. The best way to handle this is probably with a [singular mass matrix](https://docs.sciml.ai/latest/tutorials/advanced_ode_example/#Handling-Mass-Matrices-1).
