diff --git a/Project.toml b/Project.toml index 8aa6f28..502a835 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ authors = ["Hilding Elmqvist ", "Martin Otter "] name = "Modia" uuid = "cb905087-75eb-5f27-8515-1ce0ec8e839e" -version = "0.10.0" +version = "0.11.0" [deps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" diff --git a/docs/src/index.md b/docs/src/index.md index d4dbb8f..f6db076 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -42,6 +42,20 @@ functionalities of these packages. ## Release Notes +### Version 0.11.0 + +- Require ModiaBase 0.11.1 +- Manifest.toml file removed. +- test.yml for github actions changed to use Julia 1.9.0 + +**Non-backwards** compatible changes + +These changes only influence models that use the new feature of built-in components. + +- `_buildFunction` argument list changed (options of @instantiateModel added) + + + ### Version 0.10.0 - Initial support of segmented simulations where the number of states can change during simulation. diff --git a/models/HeatTransfer/InsulatedRod2.jl b/models/HeatTransfer/InsulatedRod2.jl index c85a8a6..d88fb1b 100644 --- a/models/HeatTransfer/InsulatedRod2.jl +++ b/models/HeatTransfer/InsulatedRod2.jl @@ -24,7 +24,8 @@ end # Called from @instantiateModel(..) before getDerivatives!(..) is generated -function build_InsulatedRod2!(model::AbstractDict, FloatType, TimeType, unitless::Bool, ID, pathAST) +function build_InsulatedRod2!(model::AbstractDict, modelModule, FloatType, TimeType, instantiateModelOptions, ID, pathAST) + unitless = instantiateModelOptions[:unitless] model = model | Model( insRod = Var(hideResult=true), # InsulatedRodStruct instance (an equation to return this variable is generated by _buildFunction) success = Var(hideResult=true), # Dummy return argument diff --git a/src/Modia.jl b/src/Modia.jl index 996187b..7028f63 100644 --- a/src/Modia.jl +++ b/src/Modia.jl @@ -9,8 +9,8 @@ Main module of Modia. module Modia const path = dirname(dirname(@__FILE__)) # Absolute path of package directory -const Version = "0.10.0" -const Date = "2023-05-29" +const Version = "0.11.0" +const Date = "2023-06-04" const modelsPath = joinpath(Modia.path, "models") print(" \n\nWelcome to ") diff --git a/src/ModiaLang.jl b/src/ModiaLang.jl index 39c7a1e..a62c606 100644 --- a/src/ModiaLang.jl +++ b/src/ModiaLang.jl @@ -583,13 +583,15 @@ function stateSelectionAndCodeGeneration(modStructure, Gexplicit, name, modelMod if int_v > 0 value = value / u"s" end - # if length(value) == 1 + if ! (typeof(value) <: AbstractArray) un = unit(value) - else + elseif length(value) > 0 un = unit.(value) @assert all([un[i] == un[1] for i in 2:length(un)]) "The unit of all elements of state vector must be equal: $var::$(value)" un = un[1] + else + un = "" end return SignalTables.unitAsParseableString(un) end @@ -836,14 +838,16 @@ end appendSymbol(path::Nothing, name::Symbol) = name appendSymbol(path , name::Symbol) = :( $path.$name ) + """ - modifiedModel = buildSubmodels!(model, modelModule, FloatType, TimeType, unitless, buildDict::OrderedDict) + modifiedModel = buildSubmodels!(model, modelModule, FloatType, TimeType, + instantiateModelOptions, buildDict::AbstractDict) Traverse `model` and for every `` that is a `Model(..)` and has a key-value pair `:_buildFunction = Par(functionName = )` and optionally `:_buildOption=`, call ``` -updatedSubmodel = (submodel, FloatType::Type, TimeType::Type, unitless::Bool, +updatedSubmodel = (submodel, modelModule, FloatType::Type, TimeType::Type, instantiateModelOptions, ID, pathAST::Union{Expr,Symbol,Nothing}, buildOption = ) ``` @@ -851,8 +855,9 @@ A new `updatedSubmodel` is generated from `submodel` merged with additional code The arguments of ``are: - `updatedSubmodel`: A potentially new reference to the updated `submodel` +- `modelModule`: Module in which the model is defined - `FloatType`, `TimeType`: Types used when instantiating `SimulationModel{FloatType,TimeType}` -- `unitless`: Argument `unitless` of `@instantiateModel`. +- `instantiateModelOptions`: Optional arguments of `@instantiateModel` provided as `OrderedDict{Symbol,Any}`. - `ID`: Unique ID to identify the generated submodel (to be used in the code merged into the submodel) - `pathAST`: Path upto `` as Abstract Syntax Tree, such as: `:( a.b.c )` (this path might be used as part of a variable name in the code merged into the submodel). @@ -860,7 +865,7 @@ The arguments of ``are: Note, keys `_buildFunction` and `_buildOption` have been deleted in the returned `updatedSubmodel`. """ -function buildSubmodels!(model::AbstractDict, modelModule, FloatType::Type, TimeType::Type, unitless::Bool, +function buildSubmodels!(model::AbstractDict, modelModule, FloatType::Type, TimeType::Type, instantiateModelOptions::OrderedDict{Symbol,Any}, buildDict::OrderedDict{String,Any}; pathAST::Union{Expr,Symbol,Nothing}=nothing) if haskey(model, :_buildFunction) _buildFunction = model[:_buildFunction] @@ -868,16 +873,16 @@ function buildSubmodels!(model::AbstractDict, modelModule, FloatType::Type, Time buildFunction = _buildFunction[:functionName] else @error "Model $pathAST has key :_buildFunction but its value has no key :functionName" - end + end delete!(model, :_buildFunction) - ID = modelPathAsString(pathAST) + ID = modelPathAsString(pathAST) quotedPathAST = Meta.quot(pathAST) if haskey(model, :_buildOption) buildOption = model[:_buildOption] delete!(model, :_buildOption) - (model, instantiatedSubmodelStruct) = Core.eval(modelModule, :($buildFunction($model, $FloatType, $TimeType, $unitless, $ID, $quotedPathAST, buildOption=$buildOption)) ) + (model, instantiatedSubmodelStruct) = Core.eval(modelModule, :($buildFunction($model, $modelModule, $FloatType, $TimeType, $instantiateModelOptions, $ID, $quotedPathAST, buildOption=$buildOption))) else - (model, instantiatedSubmodelStruct) = Core.eval(modelModule, :($buildFunction($model, $FloatType, $TimeType, $unitless, $ID, $quotedPathAST))) + (model, instantiatedSubmodelStruct) = Core.eval(modelModule, :($buildFunction($model, $modelModule, $FloatType, $TimeType, $instantiateModelOptions, $ID, $quotedPathAST))) end buildDict[ID] = instantiatedSubmodelStruct return model @@ -885,7 +890,7 @@ function buildSubmodels!(model::AbstractDict, modelModule, FloatType::Type, Time for (key,value) in model if typeof(value) <: OrderedDict && haskey(value, :_class) && value[:_class] == :Model - model[key] = buildSubmodels!(value, modelModule, FloatType, TimeType, unitless, buildDict; pathAST=appendSymbol(pathAST,key)) + model[key] = buildSubmodels!(value, modelModule, FloatType, TimeType, instantiateModelOptions, buildDict; pathAST=appendSymbol(pathAST,key)) end end return model @@ -954,11 +959,28 @@ function instantiateModel(model; modelName="", modelModule=nothing, source=nothi if typeof(model) <: NamedTuple || typeof(model) <: Dict || typeof(model) <: OrderedDict # Traverse model and execute functions _buildFunction(..), to include code into sub-models buildDict = OrderedDict{String,Any}() + instantiateModelOptions = OrderedDict{Symbol, Any}( + :modelName => modelName, + :source => source, + :aliasReduction => aliasReduction, + :unitless => unitless, + :log => log, + :logModel => logModel, + :logDetails => logDetails, + :logStateSelection => logStateSelection, + :logCode => logCode, + :logExecution => logExecution, + :logCalculations => logCalculations, + :logTiming => logTiming, + :logFile => logFile, + :evaluateParameters => evaluateParameters, + :saveCodeOnFile => saveCodeOnFile) + TimeType = if FloatType <: Measurements.Measurement || FloatType <: MonteCarloMeasurements.AbstractParticles; baseType(FloatType) else FloatType end # baseType(..) is defined in CodeGeneration.jl model = deepcopy(model) - model = buildSubmodels!(model, modelModule, FloatType, TimeType, unitless, buildDict) + model = buildSubmodels!(model, modelModule, FloatType, TimeType, instantiateModelOptions, buildDict) if logModel @showModel(model) diff --git a/test/TestLinearSystems.jl b/test/TestLinearSystems.jl index ce68ce1..55eb3f1 100644 --- a/test/TestLinearSystems.jl +++ b/test/TestLinearSystems.jl @@ -121,9 +121,9 @@ mutable struct LinearStateSpaceBuild{FloatType} end -function build_LinearStateSpace!(model::AbstractDict, FloatType::Type, TimeType::Type, unitless::Bool, - ID, pathAST::Union{Expr,Symbol,Nothing}) - # Called from @instantiatedModel, during instantiation of the model. +function build_LinearStateSpace!(model::AbstractDict, modelModule, FloatType::Type, TimeType::Type, + instantiateModelOptions, ID, pathAST::Union{Expr,Symbol,Nothing}) + # Called from @instantiateModel, during instantiation of the model. pathAsString = Modia.modelPathAsString(pathAST) #println("... 1: build_LinearStateSpace! called for path = ", pathAsString) diff --git a/test/TestMultiReturningFunction10.jl b/test/TestMultiReturningFunction10.jl index f58ffd4..6d28122 100644 --- a/test/TestMultiReturningFunction10.jl +++ b/test/TestMultiReturningFunction10.jl @@ -28,8 +28,8 @@ end struct Dummy end; -function myBuildFunction(model::AbstractDict, FloatType::Type, TimeType::Type, unitless::Bool, - ID, modelPathAST; buildOption = "Default") +function myBuildFunction(model::AbstractDict, modelModule, FloatType::Type, TimeType::Type, + instantiateModelOptions, ID, modelPathAST; buildOption = "Default") modelPathAsString = if isnothing(modelPathAST); "" else string(modelPathAST) end println(" TestMultiReturningFunction10: Test output from function myBuildFunction at modelPath = \"$modelPathAsString\":\n Code could be constructed here and merged to the model with buildOption=$buildOption") return (model, Dummy())