Skip to content

Commit cef4660

Browse files
committed
Adapt docs to new ModiaLang version (0.11.2).
1 parent 72f68ea commit cef4660

File tree

6 files changed

+340
-64
lines changed

6 files changed

+340
-64
lines changed

docs/src/index.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,27 @@ julia> ]add Measurements, MonteCarloMeasurements, Distributions
4545

4646
### Version 0.6.1
4747

48+
Non-backwards compatible changes
49+
50+
- Equations can only be defined with key `equations` and no other key.
51+
52+
- Parameter values in the code are now type cast to the type of the parameter value from the
53+
`@instantiatedModel(..)` call. The benefit is that access of parameter values in the code is type stable
54+
and operations with the parameter value are more efficient and at run-time no memory is allocated.
55+
Existing models can no longer be simulated, if parameter values provided via `simulate!(.., merge=xx)` are not
56+
type compatible to their definition. For example, an error is thrown if the @instantedModel(..) uses a Float64 value and the
57+
`simulate!(.., merge=xx)` uses a `Measurement{Float64}` value for the same parameter
58+
59+
Other changes:
60+
4861
- See release notes of [ModiaLang](https://github.com/ModiaSim/ModiaLang.jl/releases/tag/v0.11.0) and
4962
of [Modia3D](https://github.com/ModiaSim/Modia3D.jl/releases/tag/v0.9.0).
63+
5064
- Project.toml and Manifest.toml updated due to new versions of Modia3D and ModiaLang
65+
5166
- docu: fix some typing and formatting
5267

68+
5369
### Version 0.6.0
5470

5571
- Modia is restricted to Julia 1.7

docs/src/tutorial/Appendix.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ in column 2 and 3. These constants can be used as shortcuts:
1616
| flow | flow | Var(flow = true) | If true, flow variable |
1717
| init | -- | -- | Initial value of ODE state (defines unit and size) |
1818
| start | -- | -- | Start value of variable (defines unit and size) |
19+
| hideResult | -- | -- | If true, the variable is not stored in the result |
20+
1921

2022
Example:
2123

@@ -99,24 +101,30 @@ Such a merge semantic allows for unification of parameter modifications and inhe
99101
The basics of the `mergeModels` algorithm and the merge operator `|` are defined as follows (without logging):
100102

101103
```julia
102-
function mergeModels(m1::OrderedDict, m2::OrderedDict, env=Symbol())
104+
function mergeModels(m1::AbstractDict, m2::AbstractDict, env=Symbol())
103105
result = deepcopy(m1)
104106
for (k,v) in m2)
105-
if typeof(v) <: OrderedDict
107+
if typeof(v) <: AbstractDict
106108
if k in keys(result) && ! (:_redeclare in keys(v))
107-
result[k] = mergeModels(result[k], v, k)
109+
if typeof(result[k]) <: AbstractDict
110+
result[k] = mergeModels(result[k], v, k)
111+
end
108112
else
109113
result[k] = v
110114
end
111115
elseif v === nothing
112116
delete!(result, k)
117+
elseif k in keys(result) && k == :equations
118+
equa = copy(result[k])
119+
push!(equa.args, v.args...)
120+
result[k] = equa
113121
else
114122
result[k] = v
115123
end
116124
end
117125
return result
118126
end
119127

120-
|(m::OrderedDict, n::OrderedDict) = mergeModels(m, n)
128+
|(m::AbstractDict, n::AbstractDict) = mergeModels(m, n)
121129

122130
```

docs/src/tutorial/GettingStarted.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ T \cdot \frac{dx}{dt} + x = 1; \;\;\; x(t_0) = 0.2
99
can be defined, simulated and plotted with the following commands:
1010

1111
```julia
12-
using Modia # reexports exported symbols from
12+
using Modia # reexports exported symbols from
1313
# DifferentialEquations and from Unitful
14-
@usingModiaPlot # Use plot package defined with
14+
@usingModiaPlot # Use plot package defined with
1515
# ENV["MODIA_PLOT"] or usePlotPackage(..)
1616

1717

1818
# Define model
1919
SimpleModel = Model(
2020
T = 0.4,
2121
x = Var(init=0.2),
22-
equation = :[T * der(x) + x = 1],
22+
equations = :[T * der(x) + x = 1],
2323
)
2424

2525
# Transform to ODE form
@@ -37,7 +37,7 @@ plot(simpleModel, ("x", "der(x)"))
3737

3838
A model is defined with a constructor `Model` taking a comma separated list of name/value pairs.
3939
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`.
4141

4242
The macro `@instantiateModel(..)` symbolically processes the model, in particular solves the equation
4343
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.
5151

5252
The first [`simulate!`](@ref) function performs one simulation with the Modia default integrator
5353
`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`.
5555

5656
Function call `plot(..)` produces a line plot. Variables to be plotted
5757
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
6060

6161
![SimpleModel Plot](../../resources/images/SimpleModel_GLMakie.png)
6262

6363
When `ENV["MODIA_PLOT"] = "PyPlot"` is set, the following image is produced:
6464

6565
![SimpleModel Plot](../../resources/images/SimpleModel_PyPlot.png)
6666

67-
Note, the tool bar of PyPlot provides various interactive commands, for example to zoom into the
67+
Note, the tool bar of PyPlot provides various interactive commands, for example to zoom into the
6868
plot or to store the plot in different formats on file (for example in `png` or `svg` format).

docs/src/tutorial/Modeling.md

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ LowPassFilter = Model(
2222
u = input,
2323
y = output | Var(:x),
2424
x = Var(init=0),
25-
equation = :[T * der(x) + x = u],
25+
equations = :[T * der(x) + x = u],
2626
)
2727
```
2828
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.
@@ -128,28 +128,39 @@ table = CubicSplineInterpolation(0:0.5:2.0, [0.0, 0.7, 2.0, 1.8, 1.2])
128128
TestLowAndHighPassFilter2 = TestLowAndHighPassFilter | Map(u = :(table(time*u"1/s")*u"V"))
129129
```
130130

131-
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:
133132

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+
function ref(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+
)
140146
```
141147

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:
143154

144155
```
145156
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
149159
]
150160
```
151161

152162

163+
153164
## 2.4 Hierarchical modeling
154165

155166
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(
262273
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:
263274

264275
```julia
265-
Resistor = OnePort | Model( R = 1.0u"Ω", equation = :[ R*i = v ], )
276+
Resistor = OnePort | Model( R = 1.0u"Ω", equations = :[ R*i = v ], )
266277

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 ] )
268279

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 ] )
270281

271-
ConstantVoltage = OnePort | Model( V = 1.0u"V", equation = :[ v = V ] )
282+
ConstantVoltage = OnePort | Model( V = 1.0u"V", equations = :[ v = V ] )
272283
```
273284

274285
The merged `Resistor` is shown below:
@@ -288,6 +299,9 @@ Resistor = Model(
288299
),
289300
```
290301

302+
Note, there is a special merge-rule that the vectors of keys `equations` are appended.
303+
304+
291305
### 2.5.4 Connections
292306

293307
Connections are described as an array of tuples listing the connectors that are connected:
@@ -439,15 +453,13 @@ StateSpace = Model(
439453
and used as:
440454

441455
```julia
442-
col(args...) = hvcat(1, args...) # Construct a column matrix from a vector
443-
444456
SecondOrder = Model(
445457
w = 20.0,
446458
D = 0.1,
447459
k = 2.0,
448460
sys = StateSpace | Map(A = :([ 0 1;
449461
-w^2 -2*D*w]),
450-
B = :(col([0; w^2])),
462+
B = :([0; w^2;;]), # Julia 1.7: Trailing ";;" defines a column matrix
451463
C = :([k 0]),
452464
D = :(zeros(1,1)),
453465
x = Var(init = zeros(2)) ),
@@ -457,8 +469,9 @@ SecondOrder = Model(
457469

458470
Variables `sys.u` and `sys.y` are vectors with one element each.
459471

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;;]`
462475

463476
Array equations remain array equations during symbolic transformation and in the generated code,
464477
so the code is both compact and efficient.
@@ -484,6 +497,44 @@ equations = :[
484497
]
485498
```
486499

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:
503+
504+
```julia
505+
using StaticArrays
506+
TestArray1 = Model
507+
v = Var(init=SVector{3,Float64}(1.0, 2.0, 3.0)),
508+
equations = :[der(v) = -v]
509+
)
510+
testArray1 = @instantiateModel(TestArray1, logCode=true)
511+
```
512+
513+
Note, the generated code is shown in the REPL if `logCode=true` is defined:
514+
515+
```julia
516+
function getDerivatives(_x, _m::ModiaLang.SimulationModel{_FloatType,_TimeType} ...
517+
...
518+
v::ModiaBase.SVector{3,_FloatType} = ModiaBase.SVector{3,_FloatType}(_x[1:3])
519+
var"der(v)" = -v
520+
...
521+
```
522+
523+
The sizes of StaticArrays variables cannot be changed, after `@instantiatedModel` was called.
524+
However, the sizes of standard array variables can be changed with keyword argument `merge` in `simulate!`
525+
(so no re-generation and re-compilation of the code is needed):
526+
527+
```julia
528+
TestArray2 = Model(
529+
v = Var(init=[1.0, 2.0, 3.0]), # length(v) = 3
530+
equations = :[der(v) = -v]
531+
)
532+
testArray2 = @instantiateModel(TestArray2)
533+
simulate!(testArray2, stopTime=2.0, merge=Map(v = [4.0, 3.0, 2.0, 1.0])) # length(v) = 4
534+
plot(testArray2, "v", figure=5)
535+
```
536+
537+
487538
## 2.7 Model libraries
488539
489540
Modia provides a small set of pre-defined model components in directory `Modia.modelsPath`:
@@ -496,15 +547,16 @@ Modia provides a small set of pre-defined model components in directory `Modia.m
496547
- `Translational.jl` - 1D translational, mechanical component models
497548
- [PathPlanning](@ref) - Defining reference trajectories and access them.
498549
499-
These models are included in package `Modia`, but are not exported, so must be access with `Modia.xxx`.
500-
501-
The circuit of section [2.5.5 Connected models](@ref) can be for example constructed with these libraries in the following way:
550+
The desired libraries must be explicitly included with the help of utility
551+
path variable `Modia.modelsPath`. For example, the circuit of section [2.5.5 Connected models](@ref)
552+
is constructed with these libraries in the following way:
502553
503554
```julia
504555
using Modia
505-
using DifferentialEquations
506556
@usingModiaPlot
507557

558+
include("$(Modia.modelsPath)/Electric.jl")
559+
508560
FilterCircuit = Model(
509561
R = Modia.Resistor | Map(R=0.5u"Ω"),
510562
C = Modia.Capacitor | Map(C=2.0u"F", v=Var(init=0.1u"V")),

0 commit comments

Comments
 (0)