Skip to content

Commit b1e8ca9

Browse files
authored
Merge pull request #140 from ModiaSim/remove_empty_parameter_levels
Remove empty parameter levels
2 parents bd52074 + f6745f8 commit b1e8ca9

File tree

13 files changed

+567
-144
lines changed

13 files changed

+567
-144
lines changed

Manifest.toml

Lines changed: 84 additions & 78 deletions
Large diffs are not rendered by default.

Project.toml

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
1+
authors = ["Hilding Elmqvist <[email protected]>", "Martin Otter <[email protected]>"]
12
name = "Modia"
23
uuid = "cb905087-75eb-5f27-8515-1ce0ec8e839e"
3-
authors = ["Hilding Elmqvist <[email protected]>", "Martin Otter <[email protected]>"]
44
version = "0.8.2"
55

6+
[compat]
7+
DataFrames = "1"
8+
DifferentialEquations = "7"
9+
FiniteDiff = "2"
10+
ForwardDiff = "0.10"
11+
JSON = "0.21"
12+
Measurements = "2"
13+
ModiaBase = "0.11"
14+
ModiaResult = "0.4.1"
15+
MonteCarloMeasurements = "1"
16+
OrderedCollections = "1"
17+
RecursiveFactorization = "0.2"
18+
Reexport = "1"
19+
StaticArrays = "1"
20+
Sundials = "4.4"
21+
TimerOutputs = "0.5"
22+
Unitful = "1"
23+
julia = "1.7"
24+
625
[deps]
726
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
827
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
@@ -25,21 +44,5 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
2544
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
2645
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
2746

28-
[compat]
29-
DataFrames = "1"
30-
DifferentialEquations = "7"
31-
FiniteDiff = "2"
32-
ForwardDiff = "0.10"
33-
JSON = "0.21"
34-
Measurements = "2"
35-
ModiaBase = "0.10"
36-
ModiaResult = "0.4.1"
37-
MonteCarloMeasurements = "1"
38-
OrderedCollections = "1"
39-
RecursiveFactorization = "0.2"
40-
Reexport = "1"
41-
StaticArrays = "1"
42-
Sundials = "4.4"
43-
TimerOutputs = "0.5"
44-
Unitful = "1"
45-
julia = "1.7"
47+
[extras]
48+
CPUSummary = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9"

docs/src/index.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,50 @@ functionalities of these packages.
3838

3939
### Version 0.8.2
4040

41+
- New exported functions
42+
- modelToJSON(model; expressionsAsStrings=true)
43+
- JSONToModel(json)
44+
- writeModel(filename, model; log=true)
45+
- readModel(filename; log=true)
46+
writeModel saves the model in JSON format on file and readModel reads the model from a JSON file.
47+
48+
- `Modia/examples/ServoSystem.jl` enhanced, so that the hierarchical model with units is
49+
first stored in JSON format on file, then the model is read from file, a parameter is modified,
50+
and then the model is passed to @instantiateModel(..).
51+
52+
- `@instantiateModel(...)`:
53+
- `@instantiateModel(..., logCode=true, ...)` provides now correct unit type casts for scalars.
54+
- `@instantiateModel(..., saveCodeOnFile=fileName, ...)` stores the generated code on file `fileName`.
55+
- Automatically use `@instantiatedModel(..., unitless=true, ..)`, if `FloatType = MonteCarloMeasurements.XXX`,
56+
because there are easily cases where this fails, if units are present.
57+
58+
- `@showModel model`: Nicer pretty print if model is hierarchical.
59+
60+
- New function `Modia.unitAsString(unitOfQuantity)`,
61+
see Unitful issue 412 (https://github.com/PainterQubits/Unitful.jl/issues/412).
62+
63+
- Remove empty hierarchies in model parameters (seen with `simulate!(..., logParameters=true)`).
64+
4165
- Memory allocation reduced if states or tearing variables are SVectors.
4266

67+
- Improved casting and checking of types in the generated code
68+
(see new test model Modia/test/TestUnitAsString.jl).
69+
70+
- Moved ModiaBase.Symbolic.makeDerVar from ModiaBase to new file `Modia/src/Symbolic.jl` (because makeDerVar needs FloatType for
71+
generating type-stable code and FloatType is available in Modia but not in ModiaBase).
72+
73+
- Github actions workflow added for automatic tests on Linux/Windows/MacOS, for pull requests on main.
74+
75+
**Bug fixes**
76+
77+
- Fixed issue with unit on macOS (exponents had been displayed as Unicode superscripts when converting
78+
the unit to a string, leading to errors in the further processing).
79+
80+
- Hide result only if `Var(hideResult=true)` (previously, hideResult=false was treated as true).
81+
82+
- `Modia/models/Rotational.jl`: Change some Int to Float64 values, because errors occured in some situations.
83+
84+
4385
### Version 0.8.1
4486

4587
- Missing file Modia/test/TestLinearEquations.jl added.

examples/ServoSystem.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,27 +98,31 @@ Servo = Model(
9898

9999

100100
TestServo = Model(
101-
ks = 0.8,
101+
ks = 0.4,
102102
Ts = 0.08u"s",
103103
ramp = Ramp | Map(duration=1.18u"s", height=2.95),
104104
servo = Servo | Map(ks=:(up.ks), Ts=:(up.Ts)),
105-
load = Inertia | Map(J=170u"kg*m^2"),
106-
equations =:[load.flange_b.tau = 0u"N*m"],
105+
load = Inertia | Map(J=170.0u"kg*m^2"),
106+
equations =:[load.flange_b.tau = 0.0u"N*m"],
107107
connect = :[
108108
(ramp.y , servo.refSpeed)
109109
(servo.flange_b, load.flange_a) ]
110110
)
111111

112+
file = joinpath(pwd(), "TestServo.json")
113+
writeModel(file, TestServo)
114+
TestServo = readModel(file) | Map(ks = 0.8)
115+
112116
plotVariables = [("ramp.y", "load.w") "servo.speedError.y";
113117
"servo.gear.spring.phi_rel" "servo.motor.currentSensor.i"]
114118

115-
testServo1 = @instantiateModel(TestServo)
119+
testServo1 = @instantiateModel(TestServo, saveCodeOnFile="TestServo.jl")
116120
println("Simulate")
117121
@time simulate!(testServo1, Tsit5(), stopTime=2.0, tolerance=1e-6, requiredFinalStates =
118122
[7.320842067204029, 9.346410309487013, 355.30389168655955, 2.792544498835712, 429.42665751348284, 311.7812493890421, 4.089776248793499, 2.969353608933471])
119123
plot(testServo1, plotVariables, figure=1)
120124

121-
125+
#=
122126
println("\nServo with uncertainties")
123127
using Modia.Measurements
124128
TestServoWithUncertainties = TestServo | Map(
@@ -139,6 +143,6 @@ TestServoWithMonteCarlo = TestServo | Map(
139143
testServo3 = @instantiateModel(TestServoWithMonteCarlo, FloatType = Modia.MonteCarloMeasurements.StaticParticles{Float64,nparticles}, unitless=true)
140144
@time simulate!(testServo3, Tsit5(), stopTime=2.0, tolerance=1e-6)
141145
plot(testServo3, plotVariables, figure=3)
142-
146+
=#
143147

144148
end

models/Rotational.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ PartialCompliant = Model(
6161
# Linear 1D rotational spring
6262
Spring = PartialCompliant | Model(
6363
c = 1.0u"N*m/rad", # (min = 0, info = "Spring constant")
64-
phi_rel0 = 0u"rad", # (info = "Unstretched spring angle")
64+
phi_rel0 = 0.0u"rad", # (info = "Unstretched spring angle")
6565
equations = :[
6666
tau = c * (phi_rel - phi_rel0) ]
6767
)
@@ -70,7 +70,7 @@ Spring = PartialCompliant | Model(
7070
SpringDamper = PartialCompliant | Model(
7171
c = 1.0*u"N*m/rad", # (min = 0, info = "Spring constant")
7272
d = 0.0u"N*m*s/rad", # (info = "Damping constant")
73-
phi_rel0 = 0u"rad", # (info = "Unstretched spring angle")
73+
phi_rel0 = 0.0u"rad", # (info = "Unstretched spring angle")
7474
equations = :[
7575
tau = c * (phi_rel - phi_rel0) + d * der(phi_rel) ]
7676
)

src/CodeGeneration.jl

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,36 @@ fieldnames(typeof(integrator)) = (:sol, :u, :du, :k, :t, :dt, :f, :p, :uprev, :u
1717
"""
1818
baseType(T)
1919
20-
Return the base type of a type T.
20+
Return the base type of a type T, according to the following definition.
21+
22+
```julia
23+
baseType(::Type{T}) where {T} = T
24+
baseType(::Type{Unitful.Quantity{T,D,U}}) where {T,D,U} = T
25+
baseType(::Type{Measurements.Measurement{T}}) where {T} = T
26+
baseType(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T,N} = T
27+
baseType(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T,N} = T
28+
```
2129
2230
# Examples
2331
```
2432
baseType(Float32) # Float32
2533
baseType(Measurement{Float64}) # Float64
2634
```
2735
"""
28-
baseType(::Type{T}) where {T} = T
29-
baseType(::Type{Measurements.Measurement{T}}) where {T<:AbstractFloat} = T
30-
baseType(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T<:AbstractFloat,N} = T
31-
baseType(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T<:AbstractFloat,N} = T
36+
baseType(::Type{T}) where {T} = T
37+
baseType(::Type{Unitful.Quantity{T,D,U}}) where {T,D,U} = T
38+
baseType(::Type{Measurements.Measurement{T}}) where {T} = T
39+
baseType(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T,N} = T
40+
baseType(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T,N} = T
41+
42+
isQuantity( ::Type{T}) where {T} = T <: Unitful.Quantity || T <: MonteCarloMeasurements.AbstractParticles && baseType(T) <: Unitful.Quantity
43+
isMeasurements( ::Type{T}) where {T} = T <: Measurements.Measurement || T <: Unitful.Quantity && baseType(T) <: Measurements.Measurement
44+
isMonteCarloMeasurements(::Type{T}) where {T} = T <: MonteCarloMeasurements.AbstractParticles
3245

33-
Base.floatmax(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T<:AbstractFloat,N} = Base.floatmax(T)
34-
Base.floatmax(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T<:AbstractFloat,N} = Base.floatmax(T)
46+
Base.floatmax(::Type{Unitful.Quantity{T,D,U}}) where {T,D,U} = Base.floatmax(T)
47+
Base.floatmax(::Type{Measurements.Measurement{T}}) where {T} = Base.floatmax(T)
48+
Base.floatmax(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T,N} = Base.floatmax(T)
49+
Base.floatmax(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T,N} = Base.floatmax(T)
3550

3651

3752
"""
@@ -1528,7 +1543,7 @@ Symbol `functionName` as function name. By `eval(code)` or
15281543
15291544
- `hasUnits::Bool`: = true, if variables have units. Note, the units of the state vector are defined in equationinfo.
15301545
"""
1531-
function generate_getDerivatives!(AST::Vector{Expr}, equationInfo::Modia.EquationInfo,
1546+
function generate_getDerivatives!(FloatType, TimeType, AST::Vector{Expr}, equationInfo::Modia.EquationInfo,
15321547
parameters, variables, previousVars, preVars, holdVars, functionName::Symbol;
15331548
pre::Vector{Symbol} = Symbol[], hasUnits=false)
15341549

@@ -1643,9 +1658,12 @@ function generate_getDerivatives!(AST::Vector{Expr}, equationInfo::Modia.Equatio
16431658
end
16441659

16451660
# Generate code of the function
1661+
# temporarily removed: _m.time = $TimeType(Modia.getValue(_time))
16461662
code = quote
1647-
function $functionName(_x, _m::Modia.SimulationModel{_FloatType,_TimeType}, _time)::Nothing where {_FloatType,_TimeType}
1648-
_m.time = _TimeType(Modia.getValue(_time))
1663+
function $functionName(_x, _m::Modia.SimulationModel{$FloatType,$TimeType}, _time::$TimeType)::Nothing
1664+
_FloatType = $FloatType
1665+
_TimeType = $TimeType
1666+
_m.time = _time
16491667
_m.nGetDerivatives += 1
16501668
instantiatedModel = _m
16511669
_p = _m.evaluatedParameters

src/JSONModel.jl

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Encoding and decoding Modia models as JSON.
88
"""
99
module JSONModel
1010

11-
export modelToJSON, JSONToModel, cloneModel
11+
export modelToJSON, JSONToModel, cloneModel, writeModel, readModel
1212

1313
import JSON
1414
using Modia
@@ -31,7 +31,7 @@ function encodeModel(model, expressionsAsStrings=true)
3131
Base.remove_linenums!(model)
3232
model = removeBlock(model)
3333
if typeof(model) <: Quantity
34-
return Dict(:_value => ustrip.(model), :_unit=>string(unit(model)))
34+
return Dict(:_value => ustrip.(model), :_unit=>Modia.unitAsString(unit(model)))
3535
elseif expressionsAsStrings && typeof(model) == Expr
3636
return Dict(:_Expr=>string(model))
3737
elseif typeof(model) == Expr
@@ -80,10 +80,10 @@ Encodes a model suitable to convert to a JSON string.
8080
function decodeModel(jModel)
8181
if typeof(jModel) <: AbstractDict && length(keys(jModel)) == 2 && "_value" in keys(jModel) && "_unit" in keys(jModel)
8282
unit = jModel["_unit"]
83-
unit = replace(unit, ' ' => '*') # Workaround for https://github.com/PainterQubits/Unitful.jl/issues/391
83+
#unit = replace(unit, ' ' => '*') # Workaround for https://github.com/PainterQubits/Unitful.jl/issues/391 # Remove, since already correctly done in encodeModel(...)
8484
return jModel["_value"]*uparse(unit)
8585
elseif typeof(jModel) <: AbstractDict && length(keys(jModel)) == 1 && "_Expr" in keys(jModel)
86-
return Meta.parse(jModel["_Expr"])
86+
return Base.remove_linenums!( Meta.parse(jModel["_Expr"]) ) # without remove_linenums!, there are errors later with if-expressions.
8787
elseif typeof(jModel) <: AbstractDict && length(keys(jModel)) == 1 && "_Symbol" in keys(jModel)
8888
return Symbol(jModel["_Symbol"])
8989
elseif typeof(jModel) <: AbstractDict && length(keys(jModel)) == 2 && "head" in keys(jModel) && "args" in keys(jModel)
@@ -122,6 +122,32 @@ function JSONToModel(json)
122122
end
123123

124124

125+
"""
126+
writeModel(filename::String, model; log=true)
127+
128+
Write model in JSON format on file `filename`.
129+
"""
130+
function writeModel(filename::String, model::AbstractDict; log=true)
131+
if log
132+
println(" Write model in JSON format on file \"$filename\"")
133+
end
134+
write(filename, modelToJSON(model))
135+
end
136+
137+
138+
"""
139+
model = readModel(filename::AbstractString; log=true)
140+
141+
Read a model that is stored in JSON format on file `filename` and return it.
142+
"""
143+
function readModel(filename::String; log=true)
144+
if log
145+
println(" Read model from JSON file \"$filename\"")
146+
end
147+
JSONToModel( read(filename,String) )
148+
end
149+
150+
125151

126152
"""
127153
modelClone = cloneModel(model; expressionsAsStrings=true)

src/ModelCollections.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ function showModel(m::OrderedDict, level=0)
8383
end
8484
println(" "^level, "]")
8585
elseif k != :_class
86-
println(" "^level, k, " = ", stringifyDefinition(v), ",")
86+
#println(" "^level, k, " = ", stringifyDefinition(v), ",")
87+
print(" "^level, k, " = ")
88+
showModel(v,level)
8789
end
8890
end
8991
println(" "^(level-1), "),")
@@ -546,7 +548,7 @@ function flattenModelTuple!(model, modelStructure, modelName, to; unitless = fal
546548
if :_outer in keys(v) && v[:_outer]
547549
push!(modelStructure.equations, :($k = $(prepend(k, :up))))
548550
end
549-
if :hideResult in keys(v)
551+
if :hideResult in keys(v) && v[:hideResult] == true
550552
push!(modelStructure.hideResults, subMod)
551553
end
552554
elseif isCollection(v) # || typeof(v) == Symbol # instantiate

0 commit comments

Comments
 (0)