You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A model is defined with a constructor `Model` taking a comma separated list of name/value pairs.
39
39
The model consists of a definition of a parameter `T` with default value 0.2.
40
-
Constructor `Var` with an `init` key is used to define the initial condition `0.2` of the state `x`, and one equation. Equations can have a Julia expression on both sides of the equal sign and are given as a *quoted* array expression `:[ ]` assigned to a unique identifier such as `equation`.
40
+
Constructor `Var` with an `init` key is used to define the initial condition `0.2` of the state `x`, and one equation. Equations can have a Julia expression on both sides of the equal sign and are given as a *quoted* array expression `:[ ]` assigned to key `equations`.
41
41
42
42
The macro `@instantiateModel(..)` symbolically processes the model, in particular solves the equation
43
43
for the derivative `der(x)`, so the following equation will be used by the integrator:
@@ -51,18 +51,18 @@ returns an instance containing all the information needed for the next steps.
51
51
52
52
The first [`simulate!`](@ref) function performs one simulation with the Modia default integrator
53
53
`Sundials.CVODE_BDF()`. The second `simulate!` call defines the integrator as second argument.
54
-
Integrator `Tsit5` is an [adaptive Runge-Kutta method of order 5/4 from Tsitouras](https://www.sciencedirect.com/science/article/pii/S0898122111004706). There are > 100 ODE integrators provided. For details, see [here](https://docs.sciml.ai/stable/solvers/ode_solve/). The simulation result is stored inside `simpleModel`.
54
+
Integrator `Tsit5` is an [adaptive Runge-Kutta method of order 5/4 from Tsitouras](https://www.sciencedirect.com/science/article/pii/S0898122111004706). There are > 100 ODE integrators provided. For details, see [here](https://diffeq.sciml.ai/stable/solvers/ode_solve/). The simulation result is stored inside `simpleModel`.
55
55
56
56
Function call `plot(..)` produces a line plot. Variables to be plotted
57
57
are defined as tuples or arrays of variable names. Tuples are displayed in one diagram. A Vector or
58
-
matrix of tuples or strings are displayed as vector or matrix of diagrams.
59
-
When `ENV["MODIA_PLOT"] = "GLMakie"` is set, then command `plot(..)` produces the following image
58
+
matrix of tuples or strings are displayed as vector or matrix of diagrams.
59
+
When `ENV["MODIA_PLOT"] = "GLMakie"` is set, then command `plot(..)` produces the following image
Copy file name to clipboardExpand all lines: docs/src/tutorial/Modeling.md
+78-26Lines changed: 78 additions & 26 deletions
Original file line number
Diff line number
Diff line change
@@ -22,7 +22,7 @@ LowPassFilter = Model(
22
22
u = input,
23
23
y = output |Var(:x),
24
24
x =Var(init=0),
25
-
equation= :[T *der(x) + x = u],
25
+
equations= :[T *der(x) + x = u],
26
26
)
27
27
```
28
28
The symbols `input` and `output` refer to predefined variable constructors to define the input and output variables. If an equation has just a unique variable in the left hand side, `y`, the right hand side can be given as a quoted expression in a Var-constructor `Var(:x)` after the `output` constructor combined with the merge operator, `|`, see below.
A function cannot return more as one variable and a function cannot modify
132
-
one of its arguments:
131
+
It is possible to call Julia functions that have more as one return argument:
133
132
134
-
```
135
-
equations = :[
136
-
(y1, y1) = fc1(u1,u2) # Error: Two return arguments
137
-
fc2!(u,y) # Error: Not known that fc2! computes y
138
-
println("This is a test") # Fine
139
-
]
133
+
```julia
134
+
functionref(time)
135
+
y1 =sin(time)
136
+
y2 =cos(time)
137
+
return (y1,y2)
138
+
end
139
+
140
+
TestMultiReturningFunction1 =Model(
141
+
equations = :[
142
+
(y1,y2) =ref(time)
143
+
y3 = y1+y2
144
+
]
145
+
)
140
146
```
141
147
142
-
The first issue can be fixed by rewriting the function call:
148
+
The returned arguments are typically numbers or arrays (see below).
149
+
It is also possible to return an instance of a struct and, say,
150
+
pass this instance as input to another function call.
151
+
152
+
However, it is currently not supported that a function call modifies one of its arguments,
153
+
or that a function call returns no argument at all:
143
154
144
155
```
145
156
equations = :[
146
-
v = fc1(u1,u2)
147
-
y1 = v[1]
148
-
y2 = v[2]
157
+
fc!(u,y) # Error: Not known that fc! computes y
158
+
println("This is a test") # Error: One equation is introduced but no unknown
149
159
]
150
160
```
151
161
152
162
163
+
153
164
## 2.4 Hierarchical modeling
154
165
155
166
So far, the composition of models has resulted in dictionaries of key/value pairs with values being numeric values or quoted expressions.
@@ -262,13 +273,13 @@ OnePort = Model(
262
273
Having such a `OnePort` definition makes it convenient to define electrical component models by merging `OnePort` with specific parameter definitions with default values and equations:
263
274
264
275
```julia
265
-
Resistor = OnePort |Model( R =1.0u"Ω", equation= :[ R*i = v ], )
276
+
Resistor = OnePort |Model( R =1.0u"Ω", equations= :[ R*i = v ], )
266
277
267
-
Capacitor = OnePort |Model( C =1.0u"F", v=Map(init=0.0u"V"), equation= :[ C*der(v) = i ] )
278
+
Capacitor = OnePort |Model( C =1.0u"F", v=Map(init=0.0u"V"), equations= :[ C*der(v) = i ] )
268
279
269
-
Inductor = OnePort |Model( L =1.0u"H", i=Map(init=0.0u"A"), equation= :[ L*der(i) = v ] )
280
+
Inductor = OnePort |Model( L =1.0u"H", i=Map(init=0.0u"A"), equations= :[ L*der(i) = v ] )
270
281
271
-
ConstantVoltage = OnePort |Model( V =1.0u"V", equation= :[ v = V ] )
282
+
ConstantVoltage = OnePort |Model( V =1.0u"V", equations= :[ v = V ] )
272
283
```
273
284
274
285
The merged `Resistor` is shown below:
@@ -288,6 +299,9 @@ Resistor = Model(
288
299
),
289
300
```
290
301
302
+
Note, there is a special merge-rule that the vectors of keys `equations` are appended.
303
+
304
+
291
305
### 2.5.4 Connections
292
306
293
307
Connections are described as an array of tuples listing the connectors that are connected:
@@ -439,15 +453,13 @@ StateSpace = Model(
439
453
and used as:
440
454
441
455
```julia
442
-
col(args...) =hvcat(1, args...) # Construct a column matrix from a vector
443
-
444
456
SecondOrder =Model(
445
457
w =20.0,
446
458
D =0.1,
447
459
k =2.0,
448
460
sys = StateSpace |Map(A = :([ 01;
449
461
-w^2-2*D*w]),
450
-
B = :(col([0; w^2])),
462
+
B = :([0; w^2;;]), # Julia 1.7: Trailing ";;" defines a column matrix
451
463
C = :([k 0]),
452
464
D = :(zeros(1,1)),
453
465
x =Var(init =zeros(2)) ),
@@ -457,8 +469,9 @@ SecondOrder = Model(
457
469
458
470
Variables `sys.u` and `sys.y` are vectors with one element each.
459
471
460
-
Note, `[0; w^2]` is a vector in Julia and not a column matrix (see the discussion [here](https://discourse.julialang.org/t/construct-a-2-d-column-array/30617)).
461
-
In order that `B` is defined as column matrix, the function `col(..)` is used.
472
+
Note, `[0; w^2]` is a vector in Julia and not a column matrix.
473
+
In order that `B` is defined as column matrix, the Julia 1.7 feature is used to append two semikolons, that is,
474
+
`[0; w^2;;]`
462
475
463
476
Array equations remain array equations during symbolic transformation and in the generated code,
464
477
so the code is both compact and efficient.
@@ -484,6 +497,44 @@ equations = :[
484
497
]
485
498
```
486
499
500
+
When the init or start value of an array variable is defined as a [StaticArrays](https://github.com/JuliaArrays/StaticArrays.jl) array,
501
+
then the value of this array remains to be a StaticArrays variable also in the generated code.
502
+
The benefit is that array operations are more efficient:
0 commit comments