Skip to content

Commit 24a442f

Browse files
Merge pull request #73 from ValentinKaisermayer/fix-der_T
Make thermal models ODEs again
2 parents ec23b6e + 0b09f65 commit 24a442f

File tree

12 files changed

+300
-85
lines changed

12 files changed

+300
-85
lines changed

docs/pages.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pages = [
44
"Tutorials" => [
55
"RC Circuit" => "tutorials/rc_circuit.md",
66
"Custom Components" => "tutorials/custom_component.md",
7+
"Thermal Conduction Model" => "tutorials/thermal_model.md",
78
],
89

910
"API" => [

docs/src/API/thermal.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,7 @@ TemperatureSensor
4343

4444
```@docs
4545
FixedHeatFlow
46-
FixedTemperature
46+
FixedTemperature
47+
PrescribedHeatFlow
48+
PrescribedTemperature
4749
```

docs/src/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Pkg; Pkg.add("ModelingToolkitStandardLibrary")
1616

1717
- [RC Circuit](http://mtkstdlib.sciml.ai/dev/tutorials/rc_circuit/)
1818
- [Custom Component](http://mtkstdlib.sciml.ai/dev/tutorials/custom_component/)
19+
- [Thermal Model](http://mtkstdlib.sciml.ai/dev/tutorials/thermal_model/)
1920

2021
## Libraries
2122

docs/src/tutorials/thermal_model.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Heat Conduction Model
2+
3+
This example demonstrates the thermal response of two masses connected by a conducting element.
4+
The two masses have the same heat capacity but different initial temperatures (T1=100 [°C], T2=0 [°C]).
5+
The mass with the higher temperature will cool off while the mass with the lower temperature heats up.
6+
They will each asymptotically approach the calculated temperature T_final_K that results
7+
from dividing the total initial energy in the system by the sum of the heat capacities of each element.
8+
9+
```julia
10+
using ModelingToolkitStandardLibrary.Thermal, ModelingToolkit, OrdinaryDiffEq, Plots
11+
12+
@parameters t
13+
14+
C1 = 15
15+
C2 = 15
16+
@named mass1 = HeatCapacitor(C=C1, T_start=373.15)
17+
@named mass2 = HeatCapacitor(C=C2, T_start=273.15)
18+
@named conduction = ThermalConductor(G=10)
19+
@named Tsensor1 = TemperatureSensor()
20+
@named Tsensor2 = TemperatureSensor()
21+
22+
connections = [
23+
connect(mass1.port, conduction.port_a),
24+
connect(conduction.port_b, mass2.port),
25+
connect(mass1.port, Tsensor1.port),
26+
connect(mass2.port, Tsensor2.port),
27+
]
28+
29+
@named model = ODESystem(connections, t, systems=[mass1, mass2, conduction, Tsensor1, Tsensor2])
30+
sys = structural_simplify(model)
31+
prob = ODEProblem(sys, Pair[], (0, 5.0))
32+
sol = solve(prob, Tsit5())
33+
34+
T_final_K = sol[(mass1.T * C1 + mass2.T * C2) / (C1 + C2)]
35+
36+
plot(title = "Thermal Conduction Demonstration")
37+
plot!(sol, vars = [mass1.T, mass2.T], labels = ["Mass 1 Temperature" "Mass 2 Temperature"])
38+
plot!(sol.t, T_final_K, label = "Steady-State Temperature")
39+
savefig("thermal_plot.png")
40+
```
41+
![Plot of Temperatures](https://user-images.githubusercontent.com/50108075/173061172-4c7305f5-1193-4b17-9ca4-8f8dcbc0cae7.png)

src/Mechanical/Rotational/Rotational.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Library to model 1-dimensional, rotational mechanical systems
44
module Rotational
55

66
using ModelingToolkit, Symbolics, IfElse, OrdinaryDiffEq
7-
using OffsetArrays
87
using ...Blocks: RealInput, RealOutput
98

109
@parameters t

src/Thermal/HeatTransfer/ideal_components.jl

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
44
Lumped thermal element storing heat
55
6-
# Parameters:
7-
- `C`: [J/K] Heat capacity of element (= cp*m)
8-
- `T_start`: Initial temperature of element
9-
106
# States:
11-
- `T`: [K] Temperature of element
12-
- `der_T`: [K/s] Time derivative of temperature
7+
- `T`: [`K`] Temperature of element
8+
- `der_T`: [`K/s`] Time derivative of temperature
9+
10+
# Connectors:
11+
- `port`
12+
13+
# Parameters:
14+
- `C`: [`J/K`] Heat capacity of element (= cp*m)
15+
- `T_start`: [`K`] Initial temperature of element
1316
"""
1417
function HeatCapacitor(; name, C, T_start=273.15 + 20)
1518
@named port = HeatPort()
@@ -22,8 +25,8 @@ function HeatCapacitor(; name, C, T_start=273.15 + 20)
2225
D = Differential(t)
2326
eqs = [
2427
T ~ port.T
25-
der_T ~ D(T)
26-
D(T) ~ port.Q_flow / C
28+
der_T ~ port.Q_flow / C
29+
D(T) ~ der_T
2730
]
2831
ODESystem(eqs, t, sts, [C]; systems=[port], name=name)
2932
end
@@ -33,8 +36,15 @@ end
3336
3437
Lumped thermal element transporting heat without storing it.
3538
39+
# States:
40+
see [`Element1D`](@ref)
41+
42+
# Connectors:
43+
`port_a`
44+
`port_b`
45+
3646
# Parameters:
37-
- `G`: [W/K] Constant thermal conductance of material
47+
- `G`: [`W/K`] Constant thermal conductance of material
3848
"""
3949
function ThermalConductor(;name, G)
4050
@named element1d = Element1D()
@@ -51,8 +61,16 @@ end
5161
5262
Lumped thermal element transporting heat without storing it.
5363
64+
# States:
65+
- `dT`: [`K`] Temperature difference across the component a.T - b.T
66+
- `Q_flow`: [`W`] Heat flow rate from port a -> port b
67+
68+
# Connectors:
69+
- `port_a`
70+
- `port_b`
71+
5472
# Parameters:
55-
- `R`: [K/W] Constant thermal resistance of material
73+
- `R`: [`K/W`] Constant thermal resistance of material
5674
"""
5775
function ThermalResistor(; name, R)
5876
@named element1d = Element1D()
@@ -70,12 +88,16 @@ end
7088
7189
Lumped thermal element for heat convection.
7290
91+
# States:
92+
- `dT`: [`K`] Temperature difference across the component solid.T - fluid.T
93+
- `Q_flow`: [`W`] Heat flow rate from `solid` -> `fluid`
94+
95+
# Connectors:
96+
- `solid`
97+
- `fluid`
98+
7399
# Parameters:
74100
- `G`: [W/K] Convective thermal conductance
75-
76-
# States:
77-
- `dT`: [K] Temperature difference across the component solid.T - fluid.T
78-
- `Q_flow`: [W] Heat flow rate from solid -> fluid
79101
"""
80102
function ConvectiveConductor(; name, G)
81103
@named solid = HeatPort()
@@ -96,32 +118,44 @@ end
96118
97119
Lumped thermal element for heat convection.
98120
99-
# Parameters:
100-
- `R`: [K/W] Constant thermal resistance of material
101-
102121
# States:
103-
- `dT`: [K] Temperature difference across the component solid.T - fluid.T
104-
- `Q_flow`: [W] Heat flow rate from solid -> fluid
122+
- `dT`: [`K`] Temperature difference across the component solid.T - fluid.T
123+
- `Q_flow`: [`W`] Heat flow rate from `solid` -> `fluid`
124+
125+
# Connectors:
126+
- `solid`
127+
- `fluid`
128+
129+
# Parameters:
130+
- `R`: [`K/W`] Constant thermal resistance of material
105131
"""
106132
function ConvectiveResistor(; name, R)
107-
@named solidport = HeatPort()
108-
@named fluidport = HeatPort()
133+
@named solid = HeatPort()
134+
@named fluid = HeatPort()
109135
@parameters R=R
110136
sts = @variables Q_flow(t)=0.0 dT(t)=0.0
111137
eqs = [
112-
dT ~ solidport.T - fluidport.T
113-
solidport.Q_flow ~ Q_flow
114-
fluidport.Q_flow ~ -Q_flow
138+
dT ~ solid.T - fluid.T
139+
solid.Q_flow ~ Q_flow
140+
fluid.Q_flow ~ -Q_flow
115141
dT ~ R*Q_flow
116142
]
117-
ODESystem(eqs, t, sts, [R]; systems=[solidport, fluidport], name=name)
143+
ODESystem(eqs, t, sts, [R]; systems=[solid, fluid], name=name)
118144
end
119145

120146
"""
121147
BodyRadiation(; name, G)
122148
123149
Lumped thermal element for radiation heat transfer.
124150
151+
# States:
152+
- `dT`: [`K`] Temperature difference across the component a.T - b.T
153+
- `Q_flow`: [`W`] Heat flow rate from port a -> port b
154+
155+
# Connectors:
156+
- `port_a`
157+
- `port_b`
158+
125159
# Parameters:
126160
- `G`: [m^2] Net radiation conductance between two surfaces
127161
"""
@@ -145,6 +179,13 @@ end
145179
Collects `m` heat flows
146180
147181
This is a model to collect the heat flows from `m` heatports to one single heatport.
182+
183+
# States:
184+
185+
# Connectors:
186+
- `port_a1` to `port_am`
187+
- `port_b`
188+
148189
# Parameters:
149190
- `m`: Number of heat ports (e.g. m=2: `port_a1`, `port_a2`)
150191
"""

src/Thermal/HeatTransfer/sensors.jl

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ Absolute temperature sensor in kelvin.
66
This is an ideal absolute temperature sensor which returns the temperature of the connected port in kelvin as an output
77
signal. The sensor itself has no thermal interaction with whatever it is connected to. Furthermore, no thermocouple-like
88
lags are associated with this sensor model.
9+
10+
# States:
11+
- `T(t)`: [`K`] Absolute temperature
12+
13+
# Connectors:
14+
- `port`
915
"""
1016
function TemperatureSensor(; name)
1117
@named port = HeatPort()
12-
@variables T(t) # [K] Absolute temperature
18+
@variables T(t)
1319
eqs = [
1420
T ~ port.T
1521
port.Q_flow ~ 0
@@ -24,11 +30,18 @@ Relative Temperature sensor.
2430
2531
The relative temperature `port_a.T - port_b.T` is determined between the two ports of this component and is provided as
2632
output signal in kelvin.
33+
34+
# States:
35+
- `T(t)`: [`K`] Relative temperature `a.T - b.T`
36+
37+
# Connectors:
38+
- `port_a`
39+
- `port_b`
2740
"""
2841
function RelativeTemperatureSensor(; name)
2942
@named port_a = HeatPort()
3043
@named port_b = HeatPort()
31-
@variables T(t) # [K] Relative temperature a.T - b.T
44+
@variables T(t)
3245
eqs = [
3346
T ~ port_a.T - port_b.T
3447
port_a.Q_flow ~ 0
@@ -46,11 +59,18 @@ This model is capable of monitoring the heat flow rate flowing through this comp
4659
is the amount that passes through this sensor while keeping the temperature drop across the sensor zero. This is an ideal
4760
model so it does not absorb any energy and it has no direct effect on the thermal response of a system it is included in.
4861
The output signal is positive, if the heat flows from `port_a` to `port_b`.
62+
63+
# States:
64+
- `Q_flow(t)`: [`W`] Heat flow from `port_a` to `port_b`
65+
66+
# Connectors:
67+
- `port_a`
68+
- `port_b`
4969
"""
5070
function HeatFlowSensor(; name)
5171
@named port_a = HeatPort()
5272
@named port_b = HeatPort()
53-
@variables Q_flow(t) # [W] Heat flow from port a to port b
73+
@variables Q_flow(t)
5474
eqs = [
5575
port_a.T ~ port_b.T
5676
port_a.Q_flow + port_b.Q_flow ~ 0

src/Thermal/HeatTransfer/sources.jl

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ This model allows a specified amount of heat flow rate to be "injected" into a t
77
The constant amount of heat flow rate `Q_flow` is given as a parameter. The heat flows into the component to which
88
the component FixedHeatFlow is connected, if parameter `Q_flow` is positive.
99
10+
# Connectors:
11+
- `port`
12+
1013
# Parameters:
1114
- `Q_flow`: [W] Fixed heat flow rate at port
1215
- `T_ref`: [K] Reference temperature
@@ -31,7 +34,10 @@ end
3134
3235
Fixed temperature boundary condition in kelvin.
3336
34-
This model defines a fixed temperature T at its port in kelvin, i.e., it defines a fixed temperature as a boundary condition.
37+
This model defines a fixed temperature `T` at its port in kelvin, i.e., it defines a fixed temperature as a boundary condition.
38+
39+
# Connectors:
40+
- `port`
3541
3642
# Parameters:
3743
- `T`: [K] Fixed temperature boundary condition
@@ -44,3 +50,59 @@ function FixedTemperature(; name, T)
4450
]
4551
ODESystem(eqs, t, [], pars; systems=[port], name=name)
4652
end
53+
54+
55+
"""
56+
PrescribedHeatFlow(; name, Q_flow=1.0, T_ref=293.15, alpha=0.0)
57+
58+
Prescribed heat flow boundary condition.
59+
60+
This model allows a specified amount of heat flow rate to be "injected" into a thermal system at a given port.
61+
The amount of heat is given by the input signal `Q_flow` into the model. The heat flows into the component to which
62+
the component `PrescribedHeatFlow` is connected, if the input signal is positive.
63+
If parameter alpha is > 0, the heat flow is multiplied by `1 + alpha*(port.T - T_ref`) in order to simulate temperature
64+
dependent losses (which are given an reference temperature T_ref).
65+
66+
# Connectors:
67+
- `port`
68+
- `Q_flow` Input for the heat flow
69+
70+
# Parameters:
71+
- `T_ref`: [K] Reference temperature
72+
- `alpha`: [1/K] Temperature coefficient of heat flow rate
73+
"""
74+
function PrescribedHeatFlow(; name, T_ref=293.15, alpha=0.0)
75+
pars = @parameters begin
76+
T_ref=T_ref
77+
alpha=alpha
78+
end
79+
@named port = HeatPort()
80+
@named Q_flow = RealInput()
81+
82+
eqs = [
83+
port.Q_flow ~ -Q_flow.u * (1 + alpha * (port.T - T_ref))
84+
]
85+
ODESystem(eqs, t, [], pars; systems=[port, Q_flow], name=name)
86+
end
87+
88+
"""
89+
PrescribedTemperature(; name, T)
90+
91+
This model represents a variable temperature boundary condition.
92+
93+
The temperature in kelvin is given as input signal `T` to the model. The effect is that an instance of
94+
this model acts as an infinite reservoir able to absorb or generate as much energy as required to keep
95+
the temperature at the specified value.
96+
97+
# Connectors:
98+
- `port`
99+
- `T` input for the temperature
100+
"""
101+
function PrescribedTemperature(; name)
102+
@named port = HeatPort()
103+
@named T = RealInput()
104+
eqs = [
105+
port.T ~ T.u
106+
]
107+
ODESystem(eqs, t, [], []; systems=[port, T], name=name)
108+
end

0 commit comments

Comments
 (0)