Skip to content

Commit

Permalink
Merge pull request #140 from ModiaSim/remove_empty_parameter_levels
Browse files Browse the repository at this point in the history
Remove empty parameter levels
  • Loading branch information
MartinOtter authored Mar 6, 2022
2 parents bd52074 + f6745f8 commit b1e8ca9
Show file tree
Hide file tree
Showing 13 changed files with 567 additions and 144 deletions.
162 changes: 84 additions & 78 deletions Manifest.toml

Large diffs are not rendered by default.

41 changes: 22 additions & 19 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
authors = ["Hilding Elmqvist <[email protected]>", "Martin Otter <[email protected]>"]
name = "Modia"
uuid = "cb905087-75eb-5f27-8515-1ce0ec8e839e"
authors = ["Hilding Elmqvist <[email protected]>", "Martin Otter <[email protected]>"]
version = "0.8.2"

[compat]
DataFrames = "1"
DifferentialEquations = "7"
FiniteDiff = "2"
ForwardDiff = "0.10"
JSON = "0.21"
Measurements = "2"
ModiaBase = "0.11"
ModiaResult = "0.4.1"
MonteCarloMeasurements = "1"
OrderedCollections = "1"
RecursiveFactorization = "0.2"
Reexport = "1"
StaticArrays = "1"
Sundials = "4.4"
TimerOutputs = "0.5"
Unitful = "1"
julia = "1.7"

[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
Expand All @@ -25,21 +44,5 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[compat]
DataFrames = "1"
DifferentialEquations = "7"
FiniteDiff = "2"
ForwardDiff = "0.10"
JSON = "0.21"
Measurements = "2"
ModiaBase = "0.10"
ModiaResult = "0.4.1"
MonteCarloMeasurements = "1"
OrderedCollections = "1"
RecursiveFactorization = "0.2"
Reexport = "1"
StaticArrays = "1"
Sundials = "4.4"
TimerOutputs = "0.5"
Unitful = "1"
julia = "1.7"
[extras]
CPUSummary = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9"
42 changes: 42 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,50 @@ functionalities of these packages.

### Version 0.8.2

- New exported functions
- modelToJSON(model; expressionsAsStrings=true)
- JSONToModel(json)
- writeModel(filename, model; log=true)
- readModel(filename; log=true)
writeModel saves the model in JSON format on file and readModel reads the model from a JSON file.

- `Modia/examples/ServoSystem.jl` enhanced, so that the hierarchical model with units is
first stored in JSON format on file, then the model is read from file, a parameter is modified,
and then the model is passed to @instantiateModel(..).

- `@instantiateModel(...)`:
- `@instantiateModel(..., logCode=true, ...)` provides now correct unit type casts for scalars.
- `@instantiateModel(..., saveCodeOnFile=fileName, ...)` stores the generated code on file `fileName`.
- Automatically use `@instantiatedModel(..., unitless=true, ..)`, if `FloatType = MonteCarloMeasurements.XXX`,
because there are easily cases where this fails, if units are present.

- `@showModel model`: Nicer pretty print if model is hierarchical.

- New function `Modia.unitAsString(unitOfQuantity)`,
see Unitful issue 412 (https://github.com/PainterQubits/Unitful.jl/issues/412).

- Remove empty hierarchies in model parameters (seen with `simulate!(..., logParameters=true)`).

- Memory allocation reduced if states or tearing variables are SVectors.

- Improved casting and checking of types in the generated code
(see new test model Modia/test/TestUnitAsString.jl).

- Moved ModiaBase.Symbolic.makeDerVar from ModiaBase to new file `Modia/src/Symbolic.jl` (because makeDerVar needs FloatType for
generating type-stable code and FloatType is available in Modia but not in ModiaBase).

- Github actions workflow added for automatic tests on Linux/Windows/MacOS, for pull requests on main.

**Bug fixes**

- Fixed issue with unit on macOS (exponents had been displayed as Unicode superscripts when converting
the unit to a string, leading to errors in the further processing).

- Hide result only if `Var(hideResult=true)` (previously, hideResult=false was treated as true).

- `Modia/models/Rotational.jl`: Change some Int to Float64 values, because errors occured in some situations.


### Version 0.8.1

- Missing file Modia/test/TestLinearEquations.jl added.
Expand Down
16 changes: 10 additions & 6 deletions examples/ServoSystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,27 +98,31 @@ Servo = Model(


TestServo = Model(
ks = 0.8,
ks = 0.4,
Ts = 0.08u"s",
ramp = Ramp | Map(duration=1.18u"s", height=2.95),
servo = Servo | Map(ks=:(up.ks), Ts=:(up.Ts)),
load = Inertia | Map(J=170u"kg*m^2"),
equations =:[load.flange_b.tau = 0u"N*m"],
load = Inertia | Map(J=170.0u"kg*m^2"),
equations =:[load.flange_b.tau = 0.0u"N*m"],
connect = :[
(ramp.y , servo.refSpeed)
(servo.flange_b, load.flange_a) ]
)

file = joinpath(pwd(), "TestServo.json")
writeModel(file, TestServo)
TestServo = readModel(file) | Map(ks = 0.8)

plotVariables = [("ramp.y", "load.w") "servo.speedError.y";
"servo.gear.spring.phi_rel" "servo.motor.currentSensor.i"]

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


#=
println("\nServo with uncertainties")
using Modia.Measurements
TestServoWithUncertainties = TestServo | Map(
Expand All @@ -139,6 +143,6 @@ TestServoWithMonteCarlo = TestServo | Map(
testServo3 = @instantiateModel(TestServoWithMonteCarlo, FloatType = Modia.MonteCarloMeasurements.StaticParticles{Float64,nparticles}, unitless=true)
@time simulate!(testServo3, Tsit5(), stopTime=2.0, tolerance=1e-6)
plot(testServo3, plotVariables, figure=3)

=#

end
4 changes: 2 additions & 2 deletions models/Rotational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ PartialCompliant = Model(
# Linear 1D rotational spring
Spring = PartialCompliant | Model(
c = 1.0u"N*m/rad", # (min = 0, info = "Spring constant")
phi_rel0 = 0u"rad", # (info = "Unstretched spring angle")
phi_rel0 = 0.0u"rad", # (info = "Unstretched spring angle")
equations = :[
tau = c * (phi_rel - phi_rel0) ]
)
Expand All @@ -70,7 +70,7 @@ Spring = PartialCompliant | Model(
SpringDamper = PartialCompliant | Model(
c = 1.0*u"N*m/rad", # (min = 0, info = "Spring constant")
d = 0.0u"N*m*s/rad", # (info = "Damping constant")
phi_rel0 = 0u"rad", # (info = "Unstretched spring angle")
phi_rel0 = 0.0u"rad", # (info = "Unstretched spring angle")
equations = :[
tau = c * (phi_rel - phi_rel0) + d * der(phi_rel) ]
)
Expand Down
38 changes: 28 additions & 10 deletions src/CodeGeneration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,36 @@ fieldnames(typeof(integrator)) = (:sol, :u, :du, :k, :t, :dt, :f, :p, :uprev, :u
"""
baseType(T)
Return the base type of a type T.
Return the base type of a type T, according to the following definition.
```julia
baseType(::Type{T}) where {T} = T
baseType(::Type{Unitful.Quantity{T,D,U}}) where {T,D,U} = T
baseType(::Type{Measurements.Measurement{T}}) where {T} = T
baseType(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T,N} = T
baseType(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T,N} = T
```
# Examples
```
baseType(Float32) # Float32
baseType(Measurement{Float64}) # Float64
```
"""
baseType(::Type{T}) where {T} = T
baseType(::Type{Measurements.Measurement{T}}) where {T<:AbstractFloat} = T
baseType(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T<:AbstractFloat,N} = T
baseType(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T<:AbstractFloat,N} = T
baseType(::Type{T}) where {T} = T
baseType(::Type{Unitful.Quantity{T,D,U}}) where {T,D,U} = T
baseType(::Type{Measurements.Measurement{T}}) where {T} = T
baseType(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T,N} = T
baseType(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T,N} = T

isQuantity( ::Type{T}) where {T} = T <: Unitful.Quantity || T <: MonteCarloMeasurements.AbstractParticles && baseType(T) <: Unitful.Quantity
isMeasurements( ::Type{T}) where {T} = T <: Measurements.Measurement || T <: Unitful.Quantity && baseType(T) <: Measurements.Measurement
isMonteCarloMeasurements(::Type{T}) where {T} = T <: MonteCarloMeasurements.AbstractParticles

Base.floatmax(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T<:AbstractFloat,N} = Base.floatmax(T)
Base.floatmax(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T<:AbstractFloat,N} = Base.floatmax(T)
Base.floatmax(::Type{Unitful.Quantity{T,D,U}}) where {T,D,U} = Base.floatmax(T)
Base.floatmax(::Type{Measurements.Measurement{T}}) where {T} = Base.floatmax(T)
Base.floatmax(::Type{MonteCarloMeasurements.Particles{T,N}}) where {T,N} = Base.floatmax(T)
Base.floatmax(::Type{MonteCarloMeasurements.StaticParticles{T,N}}) where {T,N} = Base.floatmax(T)


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

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

# Generate code of the function
# temporarily removed: _m.time = $TimeType(Modia.getValue(_time))
code = quote
function $functionName(_x, _m::Modia.SimulationModel{_FloatType,_TimeType}, _time)::Nothing where {_FloatType,_TimeType}
_m.time = _TimeType(Modia.getValue(_time))
function $functionName(_x, _m::Modia.SimulationModel{$FloatType,$TimeType}, _time::$TimeType)::Nothing
_FloatType = $FloatType
_TimeType = $TimeType
_m.time = _time
_m.nGetDerivatives += 1
instantiatedModel = _m
_p = _m.evaluatedParameters
Expand Down
34 changes: 30 additions & 4 deletions src/JSONModel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Encoding and decoding Modia models as JSON.
"""
module JSONModel

export modelToJSON, JSONToModel, cloneModel
export modelToJSON, JSONToModel, cloneModel, writeModel, readModel

import JSON
using Modia
Expand All @@ -31,7 +31,7 @@ function encodeModel(model, expressionsAsStrings=true)
Base.remove_linenums!(model)
model = removeBlock(model)
if typeof(model) <: Quantity
return Dict(:_value => ustrip.(model), :_unit=>string(unit(model)))
return Dict(:_value => ustrip.(model), :_unit=>Modia.unitAsString(unit(model)))
elseif expressionsAsStrings && typeof(model) == Expr
return Dict(:_Expr=>string(model))
elseif typeof(model) == Expr
Expand Down Expand Up @@ -80,10 +80,10 @@ Encodes a model suitable to convert to a JSON string.
function decodeModel(jModel)
if typeof(jModel) <: AbstractDict && length(keys(jModel)) == 2 && "_value" in keys(jModel) && "_unit" in keys(jModel)
unit = jModel["_unit"]
unit = replace(unit, ' ' => '*') # Workaround for https://github.com/PainterQubits/Unitful.jl/issues/391
#unit = replace(unit, ' ' => '*') # Workaround for https://github.com/PainterQubits/Unitful.jl/issues/391 # Remove, since already correctly done in encodeModel(...)
return jModel["_value"]*uparse(unit)
elseif typeof(jModel) <: AbstractDict && length(keys(jModel)) == 1 && "_Expr" in keys(jModel)
return Meta.parse(jModel["_Expr"])
return Base.remove_linenums!( Meta.parse(jModel["_Expr"]) ) # without remove_linenums!, there are errors later with if-expressions.
elseif typeof(jModel) <: AbstractDict && length(keys(jModel)) == 1 && "_Symbol" in keys(jModel)
return Symbol(jModel["_Symbol"])
elseif typeof(jModel) <: AbstractDict && length(keys(jModel)) == 2 && "head" in keys(jModel) && "args" in keys(jModel)
Expand Down Expand Up @@ -122,6 +122,32 @@ function JSONToModel(json)
end


"""
writeModel(filename::String, model; log=true)
Write model in JSON format on file `filename`.
"""
function writeModel(filename::String, model::AbstractDict; log=true)
if log
println(" Write model in JSON format on file \"$filename\"")
end
write(filename, modelToJSON(model))
end


"""
model = readModel(filename::AbstractString; log=true)
Read a model that is stored in JSON format on file `filename` and return it.
"""
function readModel(filename::String; log=true)
if log
println(" Read model from JSON file \"$filename\"")
end
JSONToModel( read(filename,String) )
end



"""
modelClone = cloneModel(model; expressionsAsStrings=true)
Expand Down
6 changes: 4 additions & 2 deletions src/ModelCollections.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ function showModel(m::OrderedDict, level=0)
end
println(" "^level, "]")
elseif k != :_class
println(" "^level, k, " = ", stringifyDefinition(v), ",")
#println(" "^level, k, " = ", stringifyDefinition(v), ",")
print(" "^level, k, " = ")
showModel(v,level)
end
end
println(" "^(level-1), "),")
Expand Down Expand Up @@ -546,7 +548,7 @@ function flattenModelTuple!(model, modelStructure, modelName, to; unitless = fal
if :_outer in keys(v) && v[:_outer]
push!(modelStructure.equations, :($k = $(prepend(k, :up))))
end
if :hideResult in keys(v)
if :hideResult in keys(v) && v[:hideResult] == true
push!(modelStructure.hideResults, subMod)
end
elseif isCollection(v) # || typeof(v) == Symbol # instantiate
Expand Down
Loading

0 comments on commit b1e8ca9

Please sign in to comment.