From d98cf6f10353896786863e3a3640078291ababd6 Mon Sep 17 00:00:00 2001 From: TT Date: Mon, 19 Aug 2024 15:40:54 +0200 Subject: [PATCH] added docstring and formatting action --- .github/workflows/Formatter.yml | 14 + ext/FMIZooExt.jl | 8 +- src/FMI2/c.jl | 487 ++++++++++----- src/FMI2/ext.jl | 263 +++++--- src/FMI2/int.jl | 234 +++++-- src/FMI2/md.jl | 167 +++-- src/FMI2/prep.jl | 138 +++-- src/FMI3/c.jl | 1014 ++++++++++++++++++++++--------- src/FMI3/ext.jl | 200 +++--- src/FMI3/int.jl | 585 ++++++++++++++---- src/FMI3/md.jl | 233 ++++--- src/FMI3/prep.jl | 152 +++-- src/binary.jl | 39 +- src/convert.jl | 64 +- src/info.jl | 138 +++-- src/jacobian.jl | 113 ++-- src/md_parse.jl | 24 +- src/zip.jl | 24 +- test/FMI2/externalLogging.jl | 17 +- test/FMI2/getter_setter.jl | 29 +- test/FMI2/logging.jl | 19 +- test/FMI2/model_description.jl | 35 +- test/FMI2/state.jl | 2 +- test/FMI3/getter_setter.jl | 25 +- test/FMI3/logging.jl | 19 +- test/FMI3/state.jl | 2 +- test/eval.jl | 6 +- test/runtests.jl | 12 +- 28 files changed, 2867 insertions(+), 1196 deletions(-) create mode 100644 .github/workflows/Formatter.yml diff --git a/.github/workflows/Formatter.yml b/.github/workflows/Formatter.yml new file mode 100644 index 0000000..0155d9b --- /dev/null +++ b/.github/workflows/Formatter.yml @@ -0,0 +1,14 @@ +name: Format suggestions +on: + pull_request: + # this argument is not required if you don't use the `suggestion-label` input + types: [ opened, reopened, synchronize, labeled, unlabeled ] +jobs: + code-style: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/julia-format@v3 + with: + version: '1' # Set `version` to '1.0.54' if you need to use JuliaFormatter.jl v1.0.54 (default: '1') + suggestion-label: 'format-suggest' # leave this unset or empty to show suggestions for all PRs + diff --git a/ext/FMIZooExt.jl b/ext/FMIZooExt.jl index c31ac04..9f381ce 100644 --- a/ext/FMIZooExt.jl +++ b/ext/FMIZooExt.jl @@ -7,7 +7,13 @@ module FMIZooExt using FMIImport, FMIZoo -function FMIImport.loadFMU(modelName::AbstractString, tool::AbstractString, version::AbstractString, fmiversion::AbstractString="2.0"; kwargs...) +function FMIImport.loadFMU( + modelName::AbstractString, + tool::AbstractString, + version::AbstractString, + fmiversion::AbstractString = "2.0"; + kwargs..., +) fname = get_model_filename(modelName, tool, version, fmiversion) return FMIImport.loadFMU(fname; kwargs...) end diff --git a/src/FMI2/c.jl b/src/FMI2/c.jl index 4ca3849..cd75422 100644 --- a/src/FMI2/c.jl +++ b/src/FMI2/c.jl @@ -14,11 +14,13 @@ Source: FMISpec2.0.2[p.21]: 2.1.5 Creation, Destruction and Logging of FMU Insta Function that is called in the FMU, usually if an fmi2XXX function, does not behave as desired. If “logger” is called with “status = fmi2OK”, then the message is a pure information message. “instanceName” is the instance name of the model that calls this function. “category” is the category of the message. The meaning of “category” is defined by the modeling environment that generated the FMU. Depending on this modeling environment, none, some or all allowed values of “category” for this FMU are defined in the modelDescription.xml file via element “”, see section 2.2.4. Only messages are provided by function logger that have a category according to a call to fmi2SetDebugLogging (see below). Argument “message” is provided in the same way and with the same format control as in function “printf” from the C standard library. [Typically, this function prints the message and stores it optionally in a log file.] """ -function fmi2CallbackLogger(_componentEnvironment::Ptr{FMU2ComponentEnvironment}, - _instanceName::Ptr{Cchar}, - _status::Cuint, - _category::Ptr{Cchar}, - _message::Ptr{Cchar}) +function fmi2CallbackLogger( + _componentEnvironment::Ptr{FMU2ComponentEnvironment}, + _instanceName::Ptr{Cchar}, + _status::Cuint, + _category::Ptr{Cchar}, + _message::Ptr{Cchar}, +) message = unsafe_string(_message) category = unsafe_string(_category) @@ -32,8 +34,8 @@ function fmi2CallbackLogger(_componentEnvironment::Ptr{FMU2ComponentEnvironment} (status == fmi2StatusPending && componentEnvironment.logStatusPending) @warn "[$status][$category][$instanceName]: $message" elseif (status == fmi2StatusDiscard && componentEnvironment.logStatusDiscard) || - (status == fmi2StatusError && componentEnvironment.logStatusError) || - (status == fmi2StatusFatal && componentEnvironment.logStatusFatal) + (status == fmi2StatusError && componentEnvironment.logStatusError) || + (status == fmi2StatusFatal && componentEnvironment.logStatusFatal) @error "[$status][$category][$instanceName]: $message" end @@ -48,7 +50,7 @@ Function that is called in the FMU if memory needs to be allocated. If attribute function fmi2CallbackAllocateMemory(nobj::Csize_t, size::Csize_t) ptr = Libc.calloc(nobj, size) @debug "cbAllocateMemory($(nobj), $(size)): Allocated $(nobj) x $(size) bytes at $(ptr)." - ptr + ptr end """ @@ -58,7 +60,7 @@ Function that must be called in the FMU if memory is freed that has been allocat """ function fmi2CallbackFreeMemory(obj::Ptr{Cvoid}) @debug "cbFreeMemory($(obj)): Freeing object at $(obj)." - Libc.free(obj) + Libc.free(obj) nothing end @@ -169,9 +171,20 @@ More detailed: - FMISpec2.0.2[p.22]: 2.1.5 Creation, Destruction and Logging of FMU Instances See also [`fmi2SetDebugLogging`](@ref). """ -function FMICore.fmi2SetDebugLogging(c::FMU2Component, loggingOn::fmi2Boolean, nCategories::Unsigned, categories::Ptr{Nothing}) - - status = fmi2SetDebugLogging(c.fmu.cSetDebugLogging, c.addr, loggingOn, nCategories, categories) +function FMICore.fmi2SetDebugLogging( + c::FMU2Component, + loggingOn::fmi2Boolean, + nCategories::Unsigned, + categories::Ptr{Nothing}, +) + + status = fmi2SetDebugLogging( + c.fmu.cSetDebugLogging, + c.addr, + loggingOn, + nCategories, + categories, + ) checkStatus(c, status) return status end @@ -210,12 +223,14 @@ More detailed: See also [`fmi2SetupExperiment`](@ref). """ -function FMICore.fmi2SetupExperiment(c::FMU2Component, +function FMICore.fmi2SetupExperiment( + c::FMU2Component, toleranceDefined::fmi2Boolean, tolerance::fmi2Real, startTime::fmi2Real, stopTimeDefined::fmi2Boolean, - stopTime::fmi2Real) + stopTime::fmi2Real, +) if c.state != fmi2ComponentStateInstantiated @warn "fmi2SetupExperiment(...): Needs to be called in state `fmi2ComponentStateInstantiated`." @@ -230,8 +245,15 @@ function FMICore.fmi2SetupExperiment(c::FMU2Component, end end - status = fmi2SetupExperiment(c.fmu.cSetupExperiment, - c.addr, toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime) + status = fmi2SetupExperiment( + c.fmu.cSetupExperiment, + c.addr, + toleranceDefined, + tolerance, + startTime, + stopTimeDefined, + stopTime, + ) checkStatus(c, status) # remain in status on success, nothing to do here @@ -347,8 +369,9 @@ More detailed: - FMISpec2.0.2[p.22]: 2.1.6 Initialization, Termination, and Resetting an FMU See also [`fmi2Terminate`](@ref). """ -function FMICore.fmi2Terminate(c::FMU2Component; soft::Bool=false) - if c.state != fmi2ComponentStateContinuousTimeMode && c.state != fmi2ComponentStateEventMode +function FMICore.fmi2Terminate(c::FMU2Component; soft::Bool = false) + if c.state != fmi2ComponentStateContinuousTimeMode && + c.state != fmi2ComponentStateEventMode if soft return fmi2StatusOK else @@ -393,7 +416,7 @@ More detailed: - FMISpec2.0.3[p.22]: 2.1.6 Initialization, Termination, and Resetting an FMU See also [`fmi2Terminate`](@ref). """ -function FMICore.fmi2Reset(c::FMU2Component; soft::Bool=false) +function FMICore.fmi2Reset(c::FMU2Component; soft::Bool = false) # according to FMISpec2.0.3[p.90], fmi2Reset can be called almost always, except before # instantiation and after a fatal error. if c.state == fmi2ComponentStateFatal @@ -407,7 +430,16 @@ function FMICore.fmi2Reset(c::FMU2Component; soft::Bool=false) if c.fmu.cReset == C_NULL fmi2FreeInstance!(c.fmu.cFreeInstance, c.addr) - addr = fmi2Instantiate(c.fmu.cInstantiate, pointer(c.fmu.instanceName), c.fmu.type, pointer(c.fmu.modelDescription.guid), pointer(c.fmu.fmuResourceLocation), Ptr{fmi2CallbackFunctions}(pointer_from_objref(c.callbackFunctions)), fmi2Boolean(false), fmi2Boolean(false)) + addr = fmi2Instantiate( + c.fmu.cInstantiate, + pointer(c.fmu.instanceName), + c.fmu.type, + pointer(c.fmu.modelDescription.guid), + pointer(c.fmu.fmuResourceLocation), + Ptr{fmi2CallbackFunctions}(pointer_from_objref(c.callbackFunctions)), + fmi2Boolean(false), + fmi2Boolean(false), + ) if addr == Ptr{Cvoid}(C_NULL) @error "fmi2Reset(...): Reinstantiation failed!" @@ -455,10 +487,14 @@ More detailed: See also [`fmi2GetReal!`](@ref). """ -function FMICore.fmi2GetReal!(c::FMU2Component, vr::AbstractArray{fmi2ValueReference}, nvr::Csize_t, value::AbstractArray{fmi2Real}) +function FMICore.fmi2GetReal!( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi2Real}, +) - status = fmi2GetReal!(c.fmu.cGetReal, - c.addr, vr, nvr, value) + status = fmi2GetReal!(c.fmu.cGetReal, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -490,26 +526,27 @@ More detailed: See also [`fmi2GetReal`](@ref). """ -function FMICore.fmi2SetReal(c::FMU2Component, - vr::AbstractArray{fmi2ValueReference}, - nvr::Csize_t, +function FMICore.fmi2SetReal( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, value::AbstractArray{fmi2Real}; - track::Bool=true) + track::Bool = true, +) - status = fmi2SetReal(c.fmu.cSetReal, - c.addr, vr, nvr, value) + status = fmi2SetReal(c.fmu.cSetReal, c.addr, vr, nvr, value) checkStatus(c, status) - if track && status == fmi2StatusOK - check_invalidate!(vr, c.∂ẋ_∂x) + if track && status == fmi2StatusOK + check_invalidate!(vr, c.∂ẋ_∂x) check_invalidate!(vr, c.∂ẋ_∂u) check_invalidate!(vr, c.∂ẋ_∂p) - - check_invalidate!(vr, c.∂y_∂x) + + check_invalidate!(vr, c.∂y_∂x) check_invalidate!(vr, c.∂y_∂u) check_invalidate!(vr, c.∂y_∂p) - check_invalidate!(vr, c.∂e_∂x) + check_invalidate!(vr, c.∂e_∂x) check_invalidate!(vr, c.∂e_∂u) check_invalidate!(vr, c.∂e_∂p) @@ -555,10 +592,14 @@ More detailed: See also [`fmi2GetInteger!`](@ref). """ -function FMICore.fmi2GetInteger!(c::FMU2Component, vr::AbstractArray{fmi2ValueReference}, nvr::Csize_t, value::AbstractArray{fmi2Integer}) +function FMICore.fmi2GetInteger!( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi2Integer}, +) - status = fmi2GetInteger!(c.fmu.cGetInteger, - c.addr, vr, nvr, value) + status = fmi2GetInteger!(c.fmu.cGetInteger, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -593,10 +634,14 @@ More detailed: See also [`fmi2GetInteger!`](@ref). """ -function FMICore.fmi2SetInteger(c::FMU2Component, vr::AbstractArray{fmi2ValueReference}, nvr::Csize_t, value::AbstractArray{fmi2Integer}) +function FMICore.fmi2SetInteger( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi2Integer}, +) - status = fmi2SetInteger(c.fmu.cSetInteger, - c.addr, vr, nvr, value) + status = fmi2SetInteger(c.fmu.cSetInteger, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -633,10 +678,14 @@ More detailed: See also [`fmi2GetBoolean!`](@ref). """ -function FMICore.fmi2GetBoolean!(c::FMU2Component, vr::AbstractArray{fmi2ValueReference}, nvr::Csize_t, value::AbstractArray{fmi2Boolean}) +function FMICore.fmi2GetBoolean!( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi2Boolean}, +) - status = fmi2GetBoolean!(c.fmu.cGetBoolean, - c.addr, vr, nvr, value) + status = fmi2GetBoolean!(c.fmu.cGetBoolean, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -669,10 +718,14 @@ More detailed: - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions See also [`fmi2GetBoolean`](@ref). """ -function FMICore.fmi2SetBoolean(c::FMU2Component, vr::AbstractArray{fmi2ValueReference}, nvr::Csize_t, value::AbstractArray{fmi2Boolean}) +function FMICore.fmi2SetBoolean( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi2Boolean}, +) - status = fmi2SetBoolean(c.fmu.cSetBoolean, - c.addr, vr, nvr, value) + status = fmi2SetBoolean(c.fmu.cSetBoolean, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -709,10 +762,14 @@ More detailed: - FMISpec2.0.2[p.24]: 2.1.7 Getting and Setting Variable Values See also [`fmi2GetString!`](@ref). """ -function FMICore.fmi2GetString!(c::FMU2Component, vr::AbstractArray{fmi2ValueReference}, nvr::Csize_t, value::Union{AbstractArray{Ptr{Cchar}}, AbstractArray{Ptr{UInt8}}}) +function FMICore.fmi2GetString!( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, + value::Union{AbstractArray{Ptr{Cchar}},AbstractArray{Ptr{UInt8}}}, +) - status = fmi2GetString!(c.fmu.cGetString, - c.addr, vr, nvr, value) + status = fmi2GetString!(c.fmu.cGetString, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -747,10 +804,14 @@ More detailed: - FMISpec2.0.2[p.24]: 2.1.7 Getting and Setting Variable Values See also [`fmi2GetString!`](@ref). """ -function FMICore.fmi2SetString(c::FMU2Component, vr::AbstractArray{fmi2ValueReference}, nvr::Csize_t, value::Union{AbstractArray{Ptr{Cchar}}, AbstractArray{Ptr{UInt8}}}) +function FMICore.fmi2SetString( + c::FMU2Component, + vr::AbstractArray{fmi2ValueReference}, + nvr::Csize_t, + value::Union{AbstractArray{Ptr{Cchar}},AbstractArray{Ptr{UInt8}}}, +) - status = fmi2SetString(c.fmu.cSetString, - c.addr, vr, nvr, value) + status = fmi2SetString(c.fmu.cSetString, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -784,8 +845,7 @@ See also [`fmi2GetFMUstate!`](@ref). """ function FMICore.fmi2GetFMUstate!(c::FMU2Component, FMUstate::Ref{fmi2FMUstate}) - status = fmi2GetFMUstate!(c.fmu.cGetFMUstate, - c.addr, FMUstate) + status = fmi2GetFMUstate!(c.fmu.cGetFMUstate, c.addr, FMUstate) checkStatus(c, status) return status end @@ -824,8 +884,7 @@ See also [`fmi2GetFMUstate`](@ref). """ function FMICore.fmi2SetFMUstate(c::FMU2Component, FMUstate::fmi2FMUstate) - status = fmi2SetFMUstate(c.fmu.cSetFMUstate, - c.addr, FMUstate) + status = fmi2SetFMUstate(c.fmu.cSetFMUstate, c.addr, FMUstate) checkStatus(c, status) return status end @@ -859,8 +918,7 @@ See also [`fmi2FreeFMUstate!`](@ref). """ function FMICore.fmi2FreeFMUstate(c::FMU2Component, FMUstate::Ref{fmi2FMUstate}) - status = fmi2FreeFMUstate(c.fmu.cFreeFMUstate, - c.addr, FMUstate) + status = fmi2FreeFMUstate(c.fmu.cFreeFMUstate, c.addr, FMUstate) checkStatus(c, status) return status end @@ -892,10 +950,14 @@ More detailed: See also [`fmi2SerializedFMUstateSize!`](@ref). """ -function FMICore.fmi2SerializedFMUstateSize!(c::FMU2Component, FMUstate::fmi2FMUstate, size::Ref{Csize_t}) +function FMICore.fmi2SerializedFMUstateSize!( + c::FMU2Component, + FMUstate::fmi2FMUstate, + size::Ref{Csize_t}, +) - status = fmi2SerializedFMUstateSize!(c.fmu.cSerializedFMUstateSize, - c.addr, FMUstate, size) + status = + fmi2SerializedFMUstateSize!(c.fmu.cSerializedFMUstateSize, c.addr, FMUstate, size) checkStatus(c, status) return status end @@ -930,10 +992,20 @@ More detailed: See also [`fmi2SerializeFMUstate`](@ref). """ -function FMICore.fmi2SerializeFMUstate!(c::FMU2Component, FMUstate::fmi2FMUstate, serialzedState::AbstractArray{fmi2Byte}, size::Csize_t) - - status = fmi2SerializeFMUstate!(c.fmu.cSerializeFMUstate, - c.addr, FMUstate, serialzedState, size) +function FMICore.fmi2SerializeFMUstate!( + c::FMU2Component, + FMUstate::fmi2FMUstate, + serialzedState::AbstractArray{fmi2Byte}, + size::Csize_t, +) + + status = fmi2SerializeFMUstate!( + c.fmu.cSerializeFMUstate, + c.addr, + FMUstate, + serialzedState, + size, + ) checkStatus(c, status) return status end @@ -970,10 +1042,20 @@ More detailed: See also [`fmi2DeSerializeFMUstate!`](@ref). """ -function FMICore.fmi2DeSerializeFMUstate!(c::FMU2Component, serializedState::AbstractArray{fmi2Byte}, size::Csize_t, FMUstate::Ref{fmi2FMUstate}) - - status = fmi2DeSerializeFMUstate!(c.fmu.cDeSerializeFMUstate, - c.addr, serializedState, size, FMUstate) +function FMICore.fmi2DeSerializeFMUstate!( + c::FMU2Component, + serializedState::AbstractArray{fmi2Byte}, + size::Csize_t, + FMUstate::Ref{fmi2FMUstate}, +) + + status = fmi2DeSerializeFMUstate!( + c.fmu.cDeSerializeFMUstate, + c.addr, + serializedState, + size, + FMUstate, + ) checkStatus(c, status) return status end @@ -1031,33 +1113,59 @@ More detailed: - FMISpec2.0.2[p.25]: 2.1.9 Getting Partial Derivatives See also [`fmi2GetDirectionalDerivative!`](@ref). """ -function FMICore.fmi2GetDirectionalDerivative!(c::FMU2Component, - vUnknown_ref::AbstractArray{fmi2ValueReference}, - nUnknown::Csize_t, - vKnown_ref::AbstractArray{fmi2ValueReference}, - nKnown::Csize_t, - dvKnown::AbstractArray{fmi2Real}, - dvUnknown::AbstractArray{fmi2Real}) - - @assert providesDirectionalDerivatives(c.fmu) ["fmi2GetDirectionalDerivative!(...): This FMU does not support build-in directional derivatives!"] - - status = fmi2GetDirectionalDerivative!(c.fmu.cGetDirectionalDerivative, - c.addr, vUnknown_ref, nUnknown, vKnown_ref, nKnown, dvKnown, dvUnknown) +function FMICore.fmi2GetDirectionalDerivative!( + c::FMU2Component, + vUnknown_ref::AbstractArray{fmi2ValueReference}, + nUnknown::Csize_t, + vKnown_ref::AbstractArray{fmi2ValueReference}, + nKnown::Csize_t, + dvKnown::AbstractArray{fmi2Real}, + dvUnknown::AbstractArray{fmi2Real}, +) + + @assert providesDirectionalDerivatives(c.fmu) [ + "fmi2GetDirectionalDerivative!(...): This FMU does not support build-in directional derivatives!", + ] + + status = fmi2GetDirectionalDerivative!( + c.fmu.cGetDirectionalDerivative, + c.addr, + vUnknown_ref, + nUnknown, + vKnown_ref, + nKnown, + dvKnown, + dvUnknown, + ) checkStatus(c, status) return status end -function FMICore.fmi2GetDirectionalDerivative!(c::FMU2Component, +function FMICore.fmi2GetDirectionalDerivative!( + c::FMU2Component, vUnknown_ref::AbstractArray{fmi2ValueReference}, nUnknown::Csize_t, vKnown_ref::AbstractArray{fmi2ValueReference}, nKnown::Csize_t, dvKnown::AbstractArray{fmi2Real}, - dvUnknown::AbstractArray{<:Real}) + dvUnknown::AbstractArray{<:Real}, +) - logWarning(c.fmu, "fmi2GetDirectionalDerivative! is called on `dvUnknown::AbstractArray{<:Real}`, this is slow.\nConsider using `Float64` instead.", 1) + logWarning( + c.fmu, + "fmi2GetDirectionalDerivative! is called on `dvUnknown::AbstractArray{<:Real}`, this is slow.\nConsider using `Float64` instead.", + 1, + ) _dvUnknown = zeros(fmi2Real, length(dvUnknown)) - status = fmi2GetDirectionalDerivative!(c::FMU2Component, vUnknown_ref, nUnknown, vKnown_ref, nKnown, dvKnown, _dvUnknown) + status = fmi2GetDirectionalDerivative!( + c::FMU2Component, + vUnknown_ref, + nUnknown, + vKnown_ref, + nKnown, + dvKnown, + _dvUnknown, + ) dvUnknown[:] = _dvUnknown return status end @@ -1099,10 +1207,22 @@ More detailed: See also [`fmi2SetRealInputDerivatives`](@ref). """ -function FMICore.fmi2SetRealInputDerivatives(c::FMU2Component, vr::Array{fmi2ValueReference}, nvr::Csize_t, order::Array{fmi2Integer}, value::Array{fmi2Real}) - - status = fmi2SetRealInputDerivatives(c.fmu.cSetRealInputDerivatives, - c.addr, vr, nvr, order, value) +function FMICore.fmi2SetRealInputDerivatives( + c::FMU2Component, + vr::Array{fmi2ValueReference}, + nvr::Csize_t, + order::Array{fmi2Integer}, + value::Array{fmi2Real}, +) + + status = fmi2SetRealInputDerivatives( + c.fmu.cSetRealInputDerivatives, + c.addr, + vr, + nvr, + order, + value, + ) checkStatus(c, status) return status end @@ -1139,10 +1259,22 @@ More detailed: - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions - FMISpec2.0.2[p.104]: 4.2.1 Transfer of Input / Output Values and Parameters """ -function FMICore.fmi2GetRealOutputDerivatives!(c::FMU2Component, vr::Array{fmi2ValueReference}, nvr::Csize_t, order::Array{fmi2Integer}, value::Array{fmi2Real}) - - status = fmi2GetRealOutputDerivatives!(c.fmu.cGetRealOutputDerivatives, - c.addr, vr, nvr, order, value) +function FMICore.fmi2GetRealOutputDerivatives!( + c::FMU2Component, + vr::Array{fmi2ValueReference}, + nvr::Csize_t, + order::Array{fmi2Integer}, + value::Array{fmi2Real}, +) + + status = fmi2GetRealOutputDerivatives!( + c.fmu.cGetRealOutputDerivatives, + c.addr, + vr, + nvr, + order, + value, + ) checkStatus(c, status) return status end @@ -1179,11 +1311,23 @@ More detailed: - FMISpec2.0.2[p.104]: 4.2.2 Computation See also [`fmi2DoStep`](@ref). """ -function FMICore.fmi2DoStep(c::FMU2Component, currentCommunicationPoint::fmi2Real, communicationStepSize::fmi2Real, noSetFMUStatePriorToCurrentPoint::fmi2Boolean) - @assert c.fmu.cDoStep != C_NULL ["fmi2DoStep(...): This FMU does not support fmi2DoStep, probably it's a ME-FMU with no CS-support?"] - - status = fmi2DoStep(c.fmu.cDoStep, - c.addr, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint) +function FMICore.fmi2DoStep( + c::FMU2Component, + currentCommunicationPoint::fmi2Real, + communicationStepSize::fmi2Real, + noSetFMUStatePriorToCurrentPoint::fmi2Boolean, +) + @assert c.fmu.cDoStep != C_NULL [ + "fmi2DoStep(...): This FMU does not support fmi2DoStep, probably it's a ME-FMU with no CS-support?", + ] + + status = fmi2DoStep( + c.fmu.cDoStep, + c.addr, + currentCommunicationPoint, + communicationStepSize, + noSetFMUStatePriorToCurrentPoint, + ) checkStatus(c, status) return status end @@ -1266,8 +1410,7 @@ function FMICore.fmi2GetStatus!(c::FMU2Component, s::fmi2StatusKind, value) status = fmi2Error if rtype == fmi2Boolean - status = fmi2GetStatus!(c.fmu.cGetRealStatus, - c.addr, s, Ref(value)) + status = fmi2GetStatus!(c.fmu.cGetRealStatus, c.addr, s, Ref(value)) checkStatus(c, status) end return status @@ -1309,8 +1452,7 @@ See also [`fmi2GetRealStatus!`](@ref). """ function FMICore.fmi2GetRealStatus!(c::FMU2Component, s::fmi2StatusKind, value::fmi2Real) - status = fmi2GetRealStatus!(c.fmu.cGetRealStatus, - c.addr, s, Ref(value)) + status = fmi2GetRealStatus!(c.fmu.cGetRealStatus, c.addr, s, Ref(value)) checkStatus(c, status) return status end @@ -1349,10 +1491,13 @@ More detailed: - FMISpec2.0.2[p.106]: 4.2.3 Retrieving Status Information from the Slave See also [`fmi2GetIntegerStatus!`](@ref). """ -function FMICore.fmi2GetIntegerStatus!(c::FMU2Component, s::fmi2StatusKind, value::fmi2Integer) +function FMICore.fmi2GetIntegerStatus!( + c::FMU2Component, + s::fmi2StatusKind, + value::fmi2Integer, +) - status = fmi2GetIntegerStatus!(c.fmu.cGetIntegerStatus, - c.addr, s, Ref(value)) + status = fmi2GetIntegerStatus!(c.fmu.cGetIntegerStatus, c.addr, s, Ref(value)) checkStatus(c, status) return status end @@ -1391,10 +1536,13 @@ More detailed: - FMISpec2.0.2[p.106]: 4.2.3 Retrieving Status Information from the Slave See also [`fmi2GetBooleanStatus!`](@ref). """ -function FMICore.fmi2GetBooleanStatus!(c::FMU2Component, s::fmi2StatusKind, value::fmi2Boolean) +function FMICore.fmi2GetBooleanStatus!( + c::FMU2Component, + s::fmi2StatusKind, + value::fmi2Boolean, +) - status = fmi2GetBooleanStatus!(c.fmu.cGetBooleanStatus, - c.addr, s, Ref(value)) + status = fmi2GetBooleanStatus!(c.fmu.cGetBooleanStatus, c.addr, s, Ref(value)) checkStatus(c, status) return status end @@ -1433,10 +1581,13 @@ More detailed: - FMISpec2.0.2[p.106]: 4.2.3 Retrieving Status Information from the Slave See also [`fmi2GetStringStatus!`](@ref). """ -function FMICore.fmi2GetStringStatus!(c::FMU2Component, s::fmi2StatusKind, value::fmi2String) +function FMICore.fmi2GetStringStatus!( + c::FMU2Component, + s::fmi2StatusKind, + value::fmi2String, +) - status = fmi2GetStringStatus!(c.fmu.cGetStringStatus, - c.addr, s, Ref(value)) + status = fmi2GetStringStatus!(c.fmu.cGetStringStatus, c.addr, s, Ref(value)) checkStatus(c, status) return status end @@ -1480,7 +1631,14 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.1 Providing Independent Variables and Re-initialization of Caching See also [`fmi2SetTime`](@ref). """ -function FMICore.fmi2SetTime(c::FMU2Component, time::fmi2Real; soft::Bool=false, track::Bool=true, force::Bool=c.force, time_shift::Bool=c.fmu.executionConfig.autoTimeShift) +function FMICore.fmi2SetTime( + c::FMU2Component, + time::fmi2Real; + soft::Bool = false, + track::Bool = true, + force::Bool = c.force, + time_shift::Bool = c.fmu.executionConfig.autoTimeShift, +) # ToDo: Double-check this in the spec. # discrete = (c.fmu.hasStateEvents == true || c.fmu.hasTimeEvents == true) @@ -1498,7 +1656,7 @@ function FMICore.fmi2SetTime(c::FMU2Component, time::fmi2Real; soft::Bool=false, end if !force - if c.t == time + if c.t == time return fmi2StatusOK end end @@ -1550,15 +1708,17 @@ More detailed: See also [`fmi2SetContinuousStates`](@ref). """ -function FMICore.fmi2SetContinuousStates(c::FMU2Component, +function FMICore.fmi2SetContinuousStates( + c::FMU2Component, x::AbstractArray{fmi2Real}, nx::Csize_t; - track::Bool=true, - force::Bool=c.force) + track::Bool = true, + force::Bool = c.force, +) if !force - if c.x == x - return fmi2StatusOK + if c.x == x + return fmi2StatusOK end end @@ -1567,7 +1727,7 @@ function FMICore.fmi2SetContinuousStates(c::FMU2Component, if track if status == fmi2StatusOK - isnothing(c.x) ? (c.x = copy(x);) : copyto!(c.x, x) + isnothing(c.x) ? (c.x = copy(x)) : copyto!(c.x, x) invalidate!(c.∂ẋ_∂x) invalidate!(c.∂y_∂x) @@ -1607,7 +1767,7 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.2 Evaluation of Model Equations See also [`fmi2EnterEventMode`](@ref). """ -function FMICore.fmi2EnterEventMode(c::FMU2Component; soft::Bool=false) +function FMICore.fmi2EnterEventMode(c::FMU2Component; soft::Bool = false) if c.state != fmi2ComponentStateContinuousTimeMode if soft @@ -1617,8 +1777,7 @@ function FMICore.fmi2EnterEventMode(c::FMU2Component; soft::Bool=false) end end - status = fmi2EnterEventMode(c.fmu.cEnterEventMode, - c.addr) + status = fmi2EnterEventMode(c.fmu.cEnterEventMode, c.addr) checkStatus(c, status) if status == fmi2StatusOK c.state = fmi2ComponentStateEventMode @@ -1666,8 +1825,11 @@ function FMICore.fmi2NewDiscreteStates!(c::FMU2Component, eventInfo::fmi2EventIn @warn "fmi2NewDiscreteStates(...): Needs to be called in state `fmi2ComponentStateEventMode` [$(fmi2ComponentStateEventMode)], is in [$(c.state)]." end - status = fmi2NewDiscreteStates!(c.fmu.cNewDiscreteStates, - c.addr, Ptr{fmi2EventInfo}(pointer_from_objref(eventInfo)) ) + status = fmi2NewDiscreteStates!( + c.fmu.cNewDiscreteStates, + c.addr, + Ptr{fmi2EventInfo}(pointer_from_objref(eventInfo)), + ) if eventInfo.nextEventTimeDefined == fmi2True eventInfo.nextEventTime -= c.t_offset @@ -1710,7 +1872,7 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.2 Evaluation of Model Equations See also [`fmi2EnterContinuousTimeMode`](@ref). """ -function FMICore.fmi2EnterContinuousTimeMode(c::FMU2Component; soft::Bool=false) +function FMICore.fmi2EnterContinuousTimeMode(c::FMU2Component; soft::Bool = false) if c.state != fmi2ComponentStateEventMode if soft @@ -1720,8 +1882,7 @@ function FMICore.fmi2EnterContinuousTimeMode(c::FMU2Component; soft::Bool=false) end end - status = fmi2EnterContinuousTimeMode(c.fmu.cEnterContinuousTimeMode, - c.addr) + status = fmi2EnterContinuousTimeMode(c.fmu.cEnterContinuousTimeMode, c.addr) checkStatus(c, status) if status == fmi2StatusOK c.state = fmi2ComponentStateContinuousTimeMode @@ -1759,13 +1920,20 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.2 Evaluation of Model Equations See also [`fmi2CompletedIntegratorStep!`](@ref). """ -function FMICore.fmi2CompletedIntegratorStep!(c::FMU2Component, - noSetFMUStatePriorToCurrentPoint::fmi2Boolean, - enterEventMode::Ptr{fmi2Boolean}, - terminateSimulation::Ptr{fmi2Boolean}) - - status = fmi2CompletedIntegratorStep!(c.fmu.cCompletedIntegratorStep, - c.addr, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation) +function FMICore.fmi2CompletedIntegratorStep!( + c::FMU2Component, + noSetFMUStatePriorToCurrentPoint::fmi2Boolean, + enterEventMode::Ptr{fmi2Boolean}, + terminateSimulation::Ptr{fmi2Boolean}, +) + + status = fmi2CompletedIntegratorStep!( + c.fmu.cCompletedIntegratorStep, + c.addr, + noSetFMUStatePriorToCurrentPoint, + enterEventMode, + terminateSimulation, + ) checkStatus(c, status) return status end @@ -1801,14 +1969,15 @@ More detailed: See also [`fmi2GetDerivatives!`](@ref). """ -function FMICore.fmi2GetDerivatives!(c::FMU2Component, - derivatives::AbstractArray{fmi2Real}, - nx::Csize_t) +function FMICore.fmi2GetDerivatives!( + c::FMU2Component, + derivatives::AbstractArray{fmi2Real}, + nx::Csize_t, +) - status = fmi2GetDerivatives!(c.fmu.cGetDerivatives, - c.addr, derivatives, nx) + status = fmi2GetDerivatives!(c.fmu.cGetDerivatives, c.addr, derivatives, nx) checkStatus(c, status) - + return status end @@ -1839,10 +2008,13 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.2 Evaluation of Model Equations See also [`fmi2GetEventIndicators!`](@ref). """ -function FMICore.fmi2GetEventIndicators!(c::FMU2Component, eventIndicators::AbstractArray{fmi2Real}, ni::Csize_t) +function FMICore.fmi2GetEventIndicators!( + c::FMU2Component, + eventIndicators::AbstractArray{fmi2Real}, + ni::Csize_t, +) - status = fmi2GetEventIndicators!(c.fmu.cGetEventIndicators, - c.addr, eventIndicators, ni) + status = fmi2GetEventIndicators!(c.fmu.cGetEventIndicators, c.addr, eventIndicators, ni) checkStatus(c, status) return status end @@ -1876,12 +2048,13 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.2 Evaluation of Model Equations See also [`fmi2GetEventIndicators!`](@ref). """ -function FMICore.fmi2GetContinuousStates!(c::FMU2Component, - x::AbstractArray{fmi2Real}, - nx::Csize_t) +function FMICore.fmi2GetContinuousStates!( + c::FMU2Component, + x::AbstractArray{fmi2Real}, + nx::Csize_t, +) - status = fmi2GetContinuousStates!(c.fmu.cGetContinuousStates, - c.addr, x, nx) + status = fmi2GetContinuousStates!(c.fmu.cGetContinuousStates, c.addr, x, nx) checkStatus(c, status) return status end @@ -1913,10 +2086,18 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.2 Evaluation of Model Equations See also [`fmi2GetEventIndicators!`](@ref). """ -function FMICore.fmi2GetNominalsOfContinuousStates!(c::FMU2Component, x_nominal::AbstractArray{fmi2Real}, nx::Csize_t) - - status = fmi2GetNominalsOfContinuousStates!(c.fmu.cGetNominalsOfContinuousStates, - c.addr, x_nominal, nx) +function FMICore.fmi2GetNominalsOfContinuousStates!( + c::FMU2Component, + x_nominal::AbstractArray{fmi2Real}, + nx::Csize_t, +) + + status = fmi2GetNominalsOfContinuousStates!( + c.fmu.cGetNominalsOfContinuousStates, + c.addr, + x_nominal, + nx, + ) checkStatus(c, status) return status -end \ No newline at end of file +end diff --git a/src/FMI2/ext.jl b/src/FMI2/ext.jl index b74620e..3b91095 100644 --- a/src/FMI2/ext.jl +++ b/src/FMI2/ext.jl @@ -24,7 +24,12 @@ Retrieves all the pointers of binary functions. # Returns - Returns the instance of the FMU struct. """ -function createFMU2(fmuPath, fmuZipPath; type::Union{Symbol, fmi2Type, Nothing}=nothing, logLevel::Union{FMULogLevel, Symbol}=FMULogLevelWarn) +function createFMU2( + fmuPath, + fmuZipPath; + type::Union{Symbol,fmi2Type,Nothing} = nothing, + logLevel::Union{FMULogLevel,Symbol} = FMULogLevelWarn, +) # Create uninitialized FMU if isa(logLevel, Symbol) @@ -68,7 +73,10 @@ function createFMU2(fmuPath, fmuZipPath; type::Union{Symbol, fmi2Type, Nothing}= else # type==nothing if isCoSimulation(fmu.modelDescription) && isModelExchange(fmu.modelDescription) fmu.type = fmi2TypeCoSimulation - logInfo(fmu, "createFMU2(...): FMU supports both CS and ME, using CS as default if nothing specified.") + logInfo( + fmu, + "createFMU2(...): FMU supports both CS and ME, using CS as default if nothing specified.", + ) elseif isCoSimulation(fmu.modelDescription) fmu.type = fmi2TypeCoSimulation @@ -81,7 +89,7 @@ function createFMU2(fmuPath, fmuZipPath; type::Union{Symbol, fmi2Type, Nothing}= end end - fmuName = getModelIdentifier(fmu.modelDescription; type=fmu.type) # tmpName[length(tmpName)] + fmuName = getModelIdentifier(fmu.modelDescription; type = fmu.type) # tmpName[length(tmpName)] directoryBinary = "" pathToBinary = "" @@ -96,15 +104,18 @@ function createFMU2(fmuPath, fmuZipPath; type::Union{Symbol, fmi2Type, Nothing}= if Sys.iswindows() if juliaArch == 64 - directories = [joinpath("binaries", "win64"), joinpath("binaries","x86_64-windows")] + directories = + [joinpath("binaries", "win64"), joinpath("binaries", "x86_64-windows")] else - directories = [joinpath("binaries", "win32"), joinpath("binaries","i686-windows")] + directories = + [joinpath("binaries", "win32"), joinpath("binaries", "i686-windows")] end osStr = "Windows" fmuExt = "dll" elseif Sys.islinux() if juliaArch == 64 - directories = [joinpath("binaries", "linux64"), joinpath("binaries", "x86_64-linux")] + directories = + [joinpath("binaries", "linux64"), joinpath("binaries", "x86_64-linux")] else directories = [] end @@ -112,7 +123,8 @@ function createFMU2(fmuPath, fmuZipPath; type::Union{Symbol, fmi2Type, Nothing}= fmuExt = "so" elseif Sys.isapple() if juliaArch == 64 - directories = [joinpath("binaries", "darwin64"), joinpath("binaries", "x86_64-darwin")] + directories = + [joinpath("binaries", "darwin64"), joinpath("binaries", "x86_64-darwin")] else directories = [] end @@ -159,90 +171,147 @@ function loadPointers(fmu::FMU2) cd(lastDirectory) # retrieve functions - fmu.cInstantiate = dlsym(fmu.libHandle, :fmi2Instantiate) - fmu.cGetTypesPlatform = dlsym(fmu.libHandle, :fmi2GetTypesPlatform) - fmu.cGetVersion = dlsym(fmu.libHandle, :fmi2GetVersion) - fmu.cFreeInstance = dlsym(fmu.libHandle, :fmi2FreeInstance) - fmu.cSetDebugLogging = dlsym(fmu.libHandle, :fmi2SetDebugLogging) - fmu.cSetupExperiment = dlsym(fmu.libHandle, :fmi2SetupExperiment) - fmu.cEnterInitializationMode = dlsym(fmu.libHandle, :fmi2EnterInitializationMode) - fmu.cExitInitializationMode = dlsym(fmu.libHandle, :fmi2ExitInitializationMode) - fmu.cTerminate = dlsym(fmu.libHandle, :fmi2Terminate) - fmu.cReset = dlsym(fmu.libHandle, :fmi2Reset) - fmu.cGetReal = dlsym(fmu.libHandle, :fmi2GetReal) - fmu.cSetReal = dlsym(fmu.libHandle, :fmi2SetReal) - fmu.cGetInteger = dlsym(fmu.libHandle, :fmi2GetInteger) - fmu.cSetInteger = dlsym(fmu.libHandle, :fmi2SetInteger) - fmu.cGetBoolean = dlsym(fmu.libHandle, :fmi2GetBoolean) - fmu.cSetBoolean = dlsym(fmu.libHandle, :fmi2SetBoolean) - fmu.cGetString = dlsym_opt(fmu, fmu.libHandle, :fmi2GetString) - fmu.cSetString = dlsym_opt(fmu, fmu.libHandle, :fmi2SetString) + fmu.cInstantiate = dlsym(fmu.libHandle, :fmi2Instantiate) + fmu.cGetTypesPlatform = dlsym(fmu.libHandle, :fmi2GetTypesPlatform) + fmu.cGetVersion = dlsym(fmu.libHandle, :fmi2GetVersion) + fmu.cFreeInstance = dlsym(fmu.libHandle, :fmi2FreeInstance) + fmu.cSetDebugLogging = dlsym(fmu.libHandle, :fmi2SetDebugLogging) + fmu.cSetupExperiment = dlsym(fmu.libHandle, :fmi2SetupExperiment) + fmu.cEnterInitializationMode = dlsym(fmu.libHandle, :fmi2EnterInitializationMode) + fmu.cExitInitializationMode = dlsym(fmu.libHandle, :fmi2ExitInitializationMode) + fmu.cTerminate = dlsym(fmu.libHandle, :fmi2Terminate) + fmu.cReset = dlsym(fmu.libHandle, :fmi2Reset) + fmu.cGetReal = dlsym(fmu.libHandle, :fmi2GetReal) + fmu.cSetReal = dlsym(fmu.libHandle, :fmi2SetReal) + fmu.cGetInteger = dlsym(fmu.libHandle, :fmi2GetInteger) + fmu.cSetInteger = dlsym(fmu.libHandle, :fmi2SetInteger) + fmu.cGetBoolean = dlsym(fmu.libHandle, :fmi2GetBoolean) + fmu.cSetBoolean = dlsym(fmu.libHandle, :fmi2SetBoolean) + fmu.cGetString = dlsym_opt(fmu, fmu.libHandle, :fmi2GetString) + fmu.cSetString = dlsym_opt(fmu, fmu.libHandle, :fmi2SetString) if canGetSetFMUState(fmu.modelDescription) - fmu.cGetFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2GetFMUstate) - fmu.cSetFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2SetFMUstate) - fmu.cFreeFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2FreeFMUstate) + fmu.cGetFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2GetFMUstate) + fmu.cSetFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2SetFMUstate) + fmu.cFreeFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2FreeFMUstate) end if canSerializeFMUState(fmu.modelDescription) - fmu.cSerializedFMUstateSize = dlsym_opt(fmu, fmu.libHandle, :fmi2SerializedFMUstateSize) - fmu.cSerializeFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2SerializeFMUstate) - fmu.cDeSerializeFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2DeSerializeFMUstate) + fmu.cSerializedFMUstateSize = + dlsym_opt(fmu, fmu.libHandle, :fmi2SerializedFMUstateSize) + fmu.cSerializeFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2SerializeFMUstate) + fmu.cDeSerializeFMUstate = dlsym_opt(fmu, fmu.libHandle, :fmi2DeSerializeFMUstate) end if providesDirectionalDerivatives(fmu.modelDescription) - fmu.cGetDirectionalDerivative = dlsym_opt(fmu, fmu.libHandle, :fmi2GetDirectionalDerivative) + fmu.cGetDirectionalDerivative = + dlsym_opt(fmu, fmu.libHandle, :fmi2GetDirectionalDerivative) end # CS specific function calls if isCoSimulation(fmu.modelDescription) - fmu.cSetRealInputDerivatives = dlsym(fmu.libHandle, :fmi2SetRealInputDerivatives) - fmu.cGetRealOutputDerivatives = dlsym(fmu.libHandle, :fmi2GetRealOutputDerivatives) - fmu.cDoStep = dlsym(fmu.libHandle, :fmi2DoStep) - fmu.cCancelStep = dlsym(fmu.libHandle, :fmi2CancelStep) - fmu.cGetStatus = dlsym(fmu.libHandle, :fmi2GetStatus) - fmu.cGetRealStatus = dlsym(fmu.libHandle, :fmi2GetRealStatus) - fmu.cGetIntegerStatus = dlsym(fmu.libHandle, :fmi2GetIntegerStatus) - fmu.cGetBooleanStatus = dlsym(fmu.libHandle, :fmi2GetBooleanStatus) - fmu.cGetStringStatus = dlsym(fmu.libHandle, :fmi2GetStringStatus) + fmu.cSetRealInputDerivatives = dlsym(fmu.libHandle, :fmi2SetRealInputDerivatives) + fmu.cGetRealOutputDerivatives = dlsym(fmu.libHandle, :fmi2GetRealOutputDerivatives) + fmu.cDoStep = dlsym(fmu.libHandle, :fmi2DoStep) + fmu.cCancelStep = dlsym(fmu.libHandle, :fmi2CancelStep) + fmu.cGetStatus = dlsym(fmu.libHandle, :fmi2GetStatus) + fmu.cGetRealStatus = dlsym(fmu.libHandle, :fmi2GetRealStatus) + fmu.cGetIntegerStatus = dlsym(fmu.libHandle, :fmi2GetIntegerStatus) + fmu.cGetBooleanStatus = dlsym(fmu.libHandle, :fmi2GetBooleanStatus) + fmu.cGetStringStatus = dlsym(fmu.libHandle, :fmi2GetStringStatus) end # ME specific function calls if isModelExchange(fmu.modelDescription) - fmu.cEnterContinuousTimeMode = dlsym(fmu.libHandle, :fmi2EnterContinuousTimeMode) - fmu.cGetContinuousStates = dlsym(fmu.libHandle, :fmi2GetContinuousStates) - fmu.cGetDerivatives = dlsym(fmu.libHandle, :fmi2GetDerivatives) - fmu.cSetTime = dlsym(fmu.libHandle, :fmi2SetTime) - fmu.cSetContinuousStates = dlsym(fmu.libHandle, :fmi2SetContinuousStates) - fmu.cCompletedIntegratorStep = dlsym(fmu.libHandle, :fmi2CompletedIntegratorStep) - fmu.cEnterEventMode = dlsym(fmu.libHandle, :fmi2EnterEventMode) - fmu.cNewDiscreteStates = dlsym(fmu.libHandle, :fmi2NewDiscreteStates) - fmu.cGetEventIndicators = dlsym(fmu.libHandle, :fmi2GetEventIndicators) - fmu.cGetNominalsOfContinuousStates= dlsym(fmu.libHandle, :fmi2GetNominalsOfContinuousStates) + fmu.cEnterContinuousTimeMode = dlsym(fmu.libHandle, :fmi2EnterContinuousTimeMode) + fmu.cGetContinuousStates = dlsym(fmu.libHandle, :fmi2GetContinuousStates) + fmu.cGetDerivatives = dlsym(fmu.libHandle, :fmi2GetDerivatives) + fmu.cSetTime = dlsym(fmu.libHandle, :fmi2SetTime) + fmu.cSetContinuousStates = dlsym(fmu.libHandle, :fmi2SetContinuousStates) + fmu.cCompletedIntegratorStep = dlsym(fmu.libHandle, :fmi2CompletedIntegratorStep) + fmu.cEnterEventMode = dlsym(fmu.libHandle, :fmi2EnterEventMode) + fmu.cNewDiscreteStates = dlsym(fmu.libHandle, :fmi2NewDiscreteStates) + fmu.cGetEventIndicators = dlsym(fmu.libHandle, :fmi2GetEventIndicators) + fmu.cGetNominalsOfContinuousStates = + dlsym(fmu.libHandle, :fmi2GetNominalsOfContinuousStates) end end function unloadPointers(fmu::FMU2) # retrieve functions - fmu.cInstantiate = @cfunction(FMICore.unload_fmi2Instantiate, fmi2Component, (fmi2String, fmi2Type, fmi2String, fmi2String, Ptr{fmi2CallbackFunctions}, fmi2Boolean, fmi2Boolean)) - fmu.cGetTypesPlatform = @cfunction(FMICore.unload_fmi2GetTypesPlatform, fmi2String, ()) - fmu.cGetVersion = @cfunction(FMICore.unload_fmi2GetVersion, fmi2String, ()) - fmu.cFreeInstance = @cfunction(FMICore.unload_fmi2FreeInstance, Cvoid, (fmi2Component,)) - fmu.cSetDebugLogging = @cfunction(FMICore.unload_fmi2SetDebugLogging, fmi2Status, (fmi2Component, fmi2Boolean, Csize_t, Ptr{fmi2String})) - fmu.cSetupExperiment = @cfunction(FMICore.unload_fmi2SetupExperiment, fmi2Status, (fmi2Component, fmi2Boolean, fmi2Real, fmi2Real, fmi2Boolean, fmi2Real)) - fmu.cEnterInitializationMode = @cfunction(FMICore.unload_fmi2EnterInitializationMode, fmi2Status, (fmi2Component,)) - fmu.cExitInitializationMode = @cfunction(FMICore.unload_fmi2ExitInitializationMode, fmi2Status, (fmi2Component,)) - fmu.cTerminate = @cfunction(FMICore.unload_fmi2Terminate, fmi2Status, (fmi2Component,)) - fmu.cReset = @cfunction(FMICore.unload_fmi2Reset, fmi2Status, (fmi2Component,)) - fmu.cGetReal = @cfunction(FMICore.unload_fmi2GetReal, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Real})) - fmu.cSetReal = @cfunction(FMICore.unload_fmi2SetReal, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Real})) - fmu.cGetInteger = @cfunction(FMICore.unload_fmi2GetInteger, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Integer})) - fmu.cSetInteger = @cfunction(FMICore.unload_fmi2SetInteger, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Integer})) - fmu.cGetBoolean = @cfunction(FMICore.unload_fmi2GetBoolean, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Boolean})) - fmu.cSetBoolean = @cfunction(FMICore.unload_fmi2SetBoolean, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Boolean})) - fmu.cGetString = @cfunction(FMICore.unload_fmi2GetString, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2String})) - fmu.cSetString = @cfunction(FMICore.unload_fmi2SetString, fmi2Status, (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2String})) + fmu.cInstantiate = @cfunction( + FMICore.unload_fmi2Instantiate, + fmi2Component, + ( + fmi2String, + fmi2Type, + fmi2String, + fmi2String, + Ptr{fmi2CallbackFunctions}, + fmi2Boolean, + fmi2Boolean, + ) + ) + fmu.cGetTypesPlatform = @cfunction(FMICore.unload_fmi2GetTypesPlatform, fmi2String, ()) + fmu.cGetVersion = @cfunction(FMICore.unload_fmi2GetVersion, fmi2String, ()) + fmu.cFreeInstance = @cfunction(FMICore.unload_fmi2FreeInstance, Cvoid, (fmi2Component,)) + fmu.cSetDebugLogging = @cfunction( + FMICore.unload_fmi2SetDebugLogging, + fmi2Status, + (fmi2Component, fmi2Boolean, Csize_t, Ptr{fmi2String}) + ) + fmu.cSetupExperiment = @cfunction( + FMICore.unload_fmi2SetupExperiment, + fmi2Status, + (fmi2Component, fmi2Boolean, fmi2Real, fmi2Real, fmi2Boolean, fmi2Real) + ) + fmu.cEnterInitializationMode = + @cfunction(FMICore.unload_fmi2EnterInitializationMode, fmi2Status, (fmi2Component,)) + fmu.cExitInitializationMode = + @cfunction(FMICore.unload_fmi2ExitInitializationMode, fmi2Status, (fmi2Component,)) + fmu.cTerminate = @cfunction(FMICore.unload_fmi2Terminate, fmi2Status, (fmi2Component,)) + fmu.cReset = @cfunction(FMICore.unload_fmi2Reset, fmi2Status, (fmi2Component,)) + fmu.cGetReal = @cfunction( + FMICore.unload_fmi2GetReal, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Real}) + ) + fmu.cSetReal = @cfunction( + FMICore.unload_fmi2SetReal, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Real}) + ) + fmu.cGetInteger = @cfunction( + FMICore.unload_fmi2GetInteger, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Integer}) + ) + fmu.cSetInteger = @cfunction( + FMICore.unload_fmi2SetInteger, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Integer}) + ) + fmu.cGetBoolean = @cfunction( + FMICore.unload_fmi2GetBoolean, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Boolean}) + ) + fmu.cSetBoolean = @cfunction( + FMICore.unload_fmi2SetBoolean, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Boolean}) + ) + fmu.cGetString = @cfunction( + FMICore.unload_fmi2GetString, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2String}) + ) + fmu.cSetString = @cfunction( + FMICore.unload_fmi2SetString, + fmi2Status, + (fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2String}) + ) # ToDo: Implement for pecial functions! # if fmi2CanGetSetState(fmu.modelDescription) @@ -276,15 +345,49 @@ function unloadPointers(fmu::FMU2) # ME specific function calls if isModelExchange(fmu.modelDescription) - fmu.cEnterContinuousTimeMode = @cfunction(FMICore.unload_fmi2EnterContinuousTimeMode, fmi2Status, (fmi2Component,)) - fmu.cGetContinuousStates = @cfunction(FMICore.unload_fmi2GetContinuousStates, fmi2Status, (fmi2Component, Ptr{fmi2Real}, Csize_t)) - fmu.cGetDerivatives = @cfunction(FMICore.unload_fmi2GetDerivatives, fmi2Status, (fmi2Component, Ptr{fmi2Real}, Csize_t)) - fmu.cSetTime = @cfunction(FMICore.unload_fmi2SetTime, fmi2Status, (fmi2Component, fmi2Real)) - fmu.cSetContinuousStates = @cfunction(FMICore.unload_fmi2SetContinuousStates, fmi2Status, (fmi2Component, Ptr{fmi2Real}, Csize_t)) - fmu.cCompletedIntegratorStep = @cfunction(FMICore.unload_fmi2CompletedIntegratorStep, fmi2Status, (fmi2Component, fmi2Boolean, Ptr{fmi2Boolean}, Ptr{fmi2Boolean})) - fmu.cEnterEventMode = @cfunction(FMICore.unload_fmi2EnterEventMode, fmi2Status, (fmi2Component,)) - fmu.cNewDiscreteStates = @cfunction(FMICore.unload_fmi2NewDiscreteStates, fmi2Status, (fmi2Component, Ptr{fmi2EventInfo})) - fmu.cGetEventIndicators = @cfunction(FMICore.unload_fmi2GetEventIndicators, fmi2Status, (fmi2Component, Ptr{fmi2Real}, Csize_t)) - fmu.cGetNominalsOfContinuousStates= @cfunction(FMICore.unload_fmi2GetNominalsOfContinuousStates, fmi2Status, (fmi2Component, Ptr{fmi2Real}, Csize_t)) + fmu.cEnterContinuousTimeMode = @cfunction( + FMICore.unload_fmi2EnterContinuousTimeMode, + fmi2Status, + (fmi2Component,) + ) + fmu.cGetContinuousStates = @cfunction( + FMICore.unload_fmi2GetContinuousStates, + fmi2Status, + (fmi2Component, Ptr{fmi2Real}, Csize_t) + ) + fmu.cGetDerivatives = @cfunction( + FMICore.unload_fmi2GetDerivatives, + fmi2Status, + (fmi2Component, Ptr{fmi2Real}, Csize_t) + ) + fmu.cSetTime = + @cfunction(FMICore.unload_fmi2SetTime, fmi2Status, (fmi2Component, fmi2Real)) + fmu.cSetContinuousStates = @cfunction( + FMICore.unload_fmi2SetContinuousStates, + fmi2Status, + (fmi2Component, Ptr{fmi2Real}, Csize_t) + ) + fmu.cCompletedIntegratorStep = @cfunction( + FMICore.unload_fmi2CompletedIntegratorStep, + fmi2Status, + (fmi2Component, fmi2Boolean, Ptr{fmi2Boolean}, Ptr{fmi2Boolean}) + ) + fmu.cEnterEventMode = + @cfunction(FMICore.unload_fmi2EnterEventMode, fmi2Status, (fmi2Component,)) + fmu.cNewDiscreteStates = @cfunction( + FMICore.unload_fmi2NewDiscreteStates, + fmi2Status, + (fmi2Component, Ptr{fmi2EventInfo}) + ) + fmu.cGetEventIndicators = @cfunction( + FMICore.unload_fmi2GetEventIndicators, + fmi2Status, + (fmi2Component, Ptr{fmi2Real}, Csize_t) + ) + fmu.cGetNominalsOfContinuousStates = @cfunction( + FMICore.unload_fmi2GetNominalsOfContinuousStates, + fmi2Status, + (fmi2Component, Ptr{fmi2Real}, Csize_t) + ) end -end \ No newline at end of file +end diff --git a/src/FMI2/int.jl b/src/FMI2/int.jl index 444914b..4e7f191 100644 --- a/src/FMI2/int.jl +++ b/src/FMI2/int.jl @@ -46,19 +46,21 @@ Create a new instance of the given fmu, adds a logger if logginOn == true. See also [`fmi2Instantiate`](#@ref). """ -function fmi2Instantiate!(fmu::FMU2; - instanceName::String=fmu.modelName, - type::fmi2Type=fmu.type, - pushComponents::Bool = true, - visible::Bool = false, - loggingOn::Bool = fmu.executionConfig.loggingOn, - externalCallbacks::Bool = fmu.executionConfig.externalCallbacks, - logStatusOK::Bool=true, - logStatusWarning::Bool=true, - logStatusDiscard::Bool=true, - logStatusError::Bool=true, - logStatusFatal::Bool=true, - logStatusPending::Bool=true) +function fmi2Instantiate!( + fmu::FMU2; + instanceName::String = fmu.modelName, + type::fmi2Type = fmu.type, + pushComponents::Bool = true, + visible::Bool = false, + loggingOn::Bool = fmu.executionConfig.loggingOn, + externalCallbacks::Bool = fmu.executionConfig.externalCallbacks, + logStatusOK::Bool = true, + logStatusWarning::Bool = true, + logStatusDiscard::Bool = true, + logStatusError::Bool = true, + logStatusFatal::Bool = true, + logStatusPending::Bool = true, +) compEnv = FMU2ComponentEnvironment() compEnv.logStatusOK = logStatusOK @@ -68,7 +70,11 @@ function fmi2Instantiate!(fmu::FMU2; compEnv.logStatusFatal = logStatusFatal compEnv.logStatusPending = logStatusPending - ptrLogger = @cfunction(fmi2CallbackLogger, Cvoid, (Ptr{FMU2ComponentEnvironment}, Ptr{Cchar}, Cuint, Ptr{Cchar}, Ptr{Cchar})) + ptrLogger = @cfunction( + fmi2CallbackLogger, + Cvoid, + (Ptr{FMU2ComponentEnvironment}, Ptr{Cchar}, Cuint, Ptr{Cchar}, Ptr{Cchar}) + ) if externalCallbacks if fmu.callbackLibHandle == C_NULL @assert Sys.WORD_SIZE == 64 "`externalCallbacks=true` is only supported for 64-bit." @@ -88,18 +94,25 @@ function fmi2Instantiate!(fmu::FMU2; perm = filemode(cbLibPath) permRWX = 16895 if perm != permRWX - chmod(cbLibPath, permRWX; recursive=true) + chmod(cbLibPath, permRWX; recursive = true) end fmu.callbackLibHandle = dlopen(cbLibPath) end ptrLogger = dlsym(fmu.callbackLibHandle, :logger) end - ptrAllocateMemory = @cfunction(fmi2CallbackAllocateMemory, Ptr{Cvoid}, (Csize_t, Csize_t)) + ptrAllocateMemory = + @cfunction(fmi2CallbackAllocateMemory, Ptr{Cvoid}, (Csize_t, Csize_t)) ptrFreeMemory = @cfunction(fmi2CallbackFreeMemory, Cvoid, (Ptr{Cvoid},)) ptrStepFinished = C_NULL # ToDo ptrComponentEnvironment = Ptr{FMU2ComponentEnvironment}(pointer_from_objref(compEnv)) - callbackFunctions = fmi2CallbackFunctions(ptrLogger, ptrAllocateMemory, ptrFreeMemory, ptrStepFinished, ptrComponentEnvironment) + callbackFunctions = fmi2CallbackFunctions( + ptrLogger, + ptrAllocateMemory, + ptrFreeMemory, + ptrStepFinished, + ptrComponentEnvironment, + ) guidStr = "$(fmu.modelDescription.guid)" @@ -108,7 +121,16 @@ function fmi2Instantiate!(fmu::FMU2; lock(lk_fmi2Instantiate) do component = nothing - addr = fmi2Instantiate(fmu.cInstantiate, pointer(instanceName), type, pointer(guidStr), pointer(fmu.fmuResourceLocation), Ptr{fmi2CallbackFunctions}(pointer_from_objref(callbackFunctions)), fmi2Boolean(visible), fmi2Boolean(loggingOn)) + addr = fmi2Instantiate( + fmu.cInstantiate, + pointer(instanceName), + type, + pointer(guidStr), + pointer(fmu.fmuResourceLocation), + Ptr{fmi2CallbackFunctions}(pointer_from_objref(callbackFunctions)), + fmi2Boolean(visible), + fmi2Boolean(loggingOn), + ) if addr == Ptr{Cvoid}(C_NULL) @error "fmi2Instantiate!(...): Instantiation failed, see error messages above.\nIf no error messages, enable FMU debug logging.\nIf logging is on and no messages are printed before this, the FMU might not log errors." @@ -124,7 +146,10 @@ function fmi2Instantiate!(fmu::FMU2; end if !isnothing(component) - logWarning(fmu, "fmi2Instantiate!(...): This component was already registered. This may be because you created the FMU by yourself with FMIExport.jl.") + logWarning( + fmu, + "fmi2Instantiate!(...): This component was already registered. This may be because you created the FMU by yourself with FMIExport.jl.", + ) else component = FMU2Component(addr, fmu) @@ -193,7 +218,11 @@ Removes the component from the FMUs component list. See Also [`fmi2FreeInstance!`](@ref). """ lk_fmi2FreeInstance = ReentrantLock() -function fmi2FreeInstance!(c::FMU2Component; popComponent::Bool=true, doccall::Bool=true) +function fmi2FreeInstance!( + c::FMU2Component; + popComponent::Bool = true, + doccall::Bool = true, +) global lk_fmi2FreeInstance @@ -207,13 +236,14 @@ function fmi2FreeInstance!(c::FMU2Component; popComponent::Bool=true, doccall::B @assert c.threadid == Threads.threadid() "Thread #$(Threads.threadid()) tried to free component with address $(c.addr), but doesn't own it.\nThe component is owned by thread $(c.threadid)" if popComponent - lock(lk_fmi2FreeInstance) do + lock(lk_fmi2FreeInstance) do ind = findall(x -> x.addr == addr, c.fmu.components) @assert length(ind) == 1 "fmi2FreeInstance!(...): Freeing $(length(ind)) instances with one call, this is not allowed. Target address `$(addr)` was found $(length(ind)) times at indicies $(ind)." deleteat!(c.fmu.components, ind) for key in keys(c.fmu.threadInstances) - if !isnothing(c.fmu.threadInstances[key]) && c.fmu.threadInstances[key].addr == addr + if !isnothing(c.fmu.threadInstances[key]) && + c.fmu.threadInstances[key].addr == addr c.fmu.threadInstances[key] = nothing end end @@ -295,10 +325,12 @@ More detailed: See also [`fmi2SetupExperiment`](@ref). """ -function fmi2SetupExperiment(c::FMU2Component, - startTime::Union{Real, Nothing} = nothing, - stopTime::Union{Real, Nothing} = nothing; - tolerance::Union{Real, Nothing} = nothing) +function fmi2SetupExperiment( + c::FMU2Component, + startTime::Union{Real,Nothing} = nothing, + stopTime::Union{Real,Nothing} = nothing; + tolerance::Union{Real,Nothing} = nothing, +) if startTime == nothing startTime = getDefaultStartTime(c.fmu.modelDescription) @@ -329,7 +361,14 @@ function fmi2SetupExperiment(c::FMU2Component, stopTime = 0.0 # dummy value, will be ignored end - fmi2SetupExperiment(c, fmi2Boolean(toleranceDefined), fmi2Real(tolerance), fmi2Real(startTime), fmi2Boolean(stopTimeDefined), fmi2Real(stopTime)) + fmi2SetupExperiment( + c, + fmi2Boolean(toleranceDefined), + fmi2Real(tolerance), + fmi2Real(startTime), + fmi2Boolean(stopTimeDefined), + fmi2Real(stopTime), + ) end """ @@ -404,7 +443,11 @@ More detailed: - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions See also [`fmi2GetReal!`](@ref). """ -function fmi2GetReal!(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::AbstractArray{fmi2Real}) +function fmi2GetReal!( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::AbstractArray{fmi2Real}, +) vr = prepareValueReference(c, vr) # values = prepareValue(values) @@ -450,12 +493,18 @@ More detailed: - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions See also [`fmi2SetReal`](@ref). """ -function fmi2SetReal(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::AbstractVector{fmi2Real}; kwargs...) +function fmi2SetReal( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::AbstractVector{fmi2Real}; + kwargs..., +) @assert length(vr) == length(values) "fmi2SetReal(...): `vr` ($(length(vr))) and `values` ($(length(values))) need to be the same length." nvr = Csize_t(length(vr)) fmi2SetReal(c, prepareValueReference(c, vr), nvr, prepareValue(values); kwargs...) end -fmi2SetReal(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::Real; kwargs...) = fmi2SetReal(c, prepareValueReference(c, vr), prepareValue(values); kwargs...) +fmi2SetReal(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::Real; kwargs...) = + fmi2SetReal(c, prepareValueReference(c, vr), prepareValue(values); kwargs...) """ fmi2GetInteger(c::FMU2Component, vr::fmi2ValueReferenceFormat) @@ -534,7 +583,11 @@ More detailed: See also [`fmi2GetInteger!`](@ref). """ -function fmi2GetInteger!(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::AbstractArray{fmi2Integer}) +function fmi2GetInteger!( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::AbstractArray{fmi2Integer}, +) vr = prepareValueReference(c, vr) # values = prepareValue(values) @@ -573,7 +626,11 @@ More detailed: `fmi2ValueReferenceFormat = Union{Nothing, String, Array{String,1 See also [`fmi2SetInteger`](@ref). """ -function fmi2SetInteger(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::Union{AbstractArray{<:Integer}, <:Integer}) +function fmi2SetInteger( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::Union{AbstractArray{<:Integer},<:Integer}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -647,7 +704,11 @@ More detailed: `fmi2ValueReferenceFormat = Union{Nothing, String, Array{String,1 - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions See also [`fmi2GetBoolean!`](@ref). """ -function fmi2GetBoolean!(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::AbstractArray{fmi2Boolean}) +function fmi2GetBoolean!( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::AbstractArray{fmi2Boolean}, +) vr = prepareValueReference(c, vr) # values = prepareValue(values) @@ -690,7 +751,11 @@ More detailed: - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions See also [`fmi2GetBoolean!`](@ref). """ -function fmi2SetBoolean(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::Union{AbstractArray{Bool}, Bool}) +function fmi2SetBoolean( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::Union{AbstractArray{Bool},Bool}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -766,7 +831,11 @@ More detailed: `fmi2ValueReferenceFormat = Union{Nothing, String, Array{String,1 - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions See also [`fmi2GetString!`](@ref). """ -function fmi2GetString!(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::AbstractArray{fmi2String}) +function fmi2GetString!( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::AbstractArray{fmi2String}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi2GetString!(...): `vr` and `values` need to be the same length." @@ -815,7 +884,11 @@ More detailed: - FMISpec2.0.2[p.108]: 4.2.4 State Machine of Calling Sequence from Master to Slave See also [`fmi2SetString`](@ref). """ -function fmi2SetString(c::FMU2Component, vr::fmi2ValueReferenceFormat, values::Union{AbstractArray{String}, String}) +function fmi2SetString( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + values::Union{AbstractArray{String},String}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -852,7 +925,7 @@ function fmi2GetFMUstate(c::FMU2Component) state end # [NOTE] needs to be exported, because FMICore only exports `fmi2GetFMUstate!` -export fmi2GetFMUstate +export fmi2GetFMUstate """ fmi2FreeFMUstate!(c::FMU2Component, state::fmi2FMUstate) @@ -1016,12 +1089,14 @@ Computes a linear combination of the partial derivatives of h with respect to th - FMISpec2.0.2[p.25]: 2.1.9 Getting Partial Derivatives See also [`fmi2GetDirectionalDerivative!`](@ref). """ -function fmi2GetDirectionalDerivative(c::FMU2Component, - vUnknown_ref::AbstractArray{fmi2ValueReference}, - vKnown_ref::AbstractArray{fmi2ValueReference}, - dvKnown::AbstractArray{fmi2Real}) +function fmi2GetDirectionalDerivative( + c::FMU2Component, + vUnknown_ref::AbstractArray{fmi2ValueReference}, + vKnown_ref::AbstractArray{fmi2ValueReference}, + dvKnown::AbstractArray{fmi2Real}, +) - nUnknown = Csize_t(length(vUnknown_ref)) + nUnknown = Csize_t(length(vUnknown_ref)) dvUnknown = zeros(fmi2Real, nUnknown) status = fmi2GetDirectionalDerivative!(c, vUnknown_ref, vKnown_ref, dvKnown, dvUnknown) @@ -1029,7 +1104,12 @@ function fmi2GetDirectionalDerivative(c::FMU2Component, return dvUnknown end -fmi2GetDirectionalDerivative(c::FMU2Component, vUnknown_ref::fmi2ValueReference, vKnown_ref::fmi2ValueReference, dvKnown::fmi2Real) = fmi2GetDirectionalDerivative(c, [vUnknown_ref], [vKnown_ref], [dvKnown])[1] +fmi2GetDirectionalDerivative( + c::FMU2Component, + vUnknown_ref::fmi2ValueReference, + vKnown_ref::fmi2ValueReference, + dvKnown::fmi2Real, +) = fmi2GetDirectionalDerivative(c, [vUnknown_ref], [vKnown_ref], [dvKnown])[1] # [NOTE] needs to be exported, because FMICore only exports `fmi2GetDirectionalDerivative!` export fmi2GetDirectionalDerivative @@ -1083,16 +1163,26 @@ More detailed: - FMISpec2.0.2[p.25]: 2.1.9 Getting Partial Derivatives See also [`fmi2GetDirectionalDerivative!`](@ref). """ -function fmi2GetDirectionalDerivative!(c::FMU2Component, - vUnknown_ref::AbstractArray{fmi2ValueReference}, - vKnown_ref::AbstractArray{fmi2ValueReference}, - dvKnown::AbstractArray{fmi2Real}, - dvUnknown::AbstractArray) +function fmi2GetDirectionalDerivative!( + c::FMU2Component, + vUnknown_ref::AbstractArray{fmi2ValueReference}, + vKnown_ref::AbstractArray{fmi2ValueReference}, + dvKnown::AbstractArray{fmi2Real}, + dvUnknown::AbstractArray, +) nKnown = Csize_t(length(vKnown_ref)) nUnknown = Csize_t(length(vUnknown_ref)) - status = fmi2GetDirectionalDerivative!(c, vUnknown_ref, nUnknown, vKnown_ref, nKnown, dvKnown, dvUnknown) + status = fmi2GetDirectionalDerivative!( + c, + vUnknown_ref, + nUnknown, + vKnown_ref, + nKnown, + dvKnown, + dvUnknown, + ) return status end @@ -1130,7 +1220,12 @@ More detailed: See also [`fmi2SetRealInputDerivatives`](@ref). """ -function fmi2SetRealInputDerivatives(c::FMU2Component, vr::fmi2ValueReferenceFormat, order::AbstractArray{fmi2Integer}, values::AbstractArray{fmi2Real}) +function fmi2SetRealInputDerivatives( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + order::AbstractArray{fmi2Integer}, + values::AbstractArray{fmi2Real}, +) @assert c.type == fmi2TypeCoSimulation "`fmi2SetRealInputDerivatives` only available for CS-FMUs." @@ -1161,7 +1256,11 @@ Sets the n-th time derivative of real input variables. - FMISpec2.0.2[p.104]: 4.2.1 Transfer of Input / Output Values and Parameters """ -function fmi2GetRealOutputDerivatives(c::FMU2Component, vr::fmi2ValueReferenceFormat, order::AbstractArray{fmi2Integer}) +function fmi2GetRealOutputDerivatives( + c::FMU2Component, + vr::fmi2ValueReferenceFormat, + order::AbstractArray{fmi2Integer}, +) @assert c.type == fmi2TypeCoSimulation "`fmi2GetRealOutputDerivatives` only available for CS-FMUs." @@ -1214,7 +1313,12 @@ More detailed: - FMISpec2.0.2[p.104]: 4.2.2 Computation See also [`fmi2DoStep`](@ref). """ -function fmi2DoStep(c::FMU2Component, communicationStepSize::Union{Real, Nothing} = nothing; currentCommunicationPoint::Union{Real, Nothing} = nothing, noSetFMUStatePriorToCurrentPoint::Bool = true) +function fmi2DoStep( + c::FMU2Component, + communicationStepSize::Union{Real,Nothing} = nothing; + currentCommunicationPoint::Union{Real,Nothing} = nothing, + noSetFMUStatePriorToCurrentPoint::Bool = true, +) @assert c.type == fmi2TypeCoSimulation "`fmi2DoStep` only available for CS-FMUs." @@ -1236,7 +1340,12 @@ function fmi2DoStep(c::FMU2Component, communicationStepSize::Union{Real, Nothing end c.t = currentCommunicationPoint - status = fmi2DoStep(c, fmi2Real(currentCommunicationPoint), fmi2Real(communicationStepSize), fmi2Boolean(noSetFMUStatePriorToCurrentPoint)) + status = fmi2DoStep( + c, + fmi2Real(currentCommunicationPoint), + fmi2Real(communicationStepSize), + fmi2Boolean(noSetFMUStatePriorToCurrentPoint), + ) c.t += communicationStepSize return status @@ -1314,7 +1423,8 @@ function fmi2SetContinuousStates(c::FMU2Component, x::AbstractArray{fmi2Real}; k end return status end -fmi2SetContinuousStates(c::FMU2Component, x::AbstractArray{Float32}; kwargs...) = fmi2SetContinuousStates(c, Array{fmi2Real}(x); kwargs...) +fmi2SetContinuousStates(c::FMU2Component, x::AbstractArray{Float32}; kwargs...) = + fmi2SetContinuousStates(c, Array{fmi2Real}(x); kwargs...) """ fmi2NewDiscreteStates(c::FMU2Component) @@ -1375,12 +1485,16 @@ More detailed: - FMISpec2.0.2[p.83]: 3.2.2 Evaluation of Model Equations See also [`fmi2CompletedIntegratorStep`](@ref). """ -function fmi2CompletedIntegratorStep(c::FMU2Component, - noSetFMUStatePriorToCurrentPoint::fmi2Boolean) - status = fmi2CompletedIntegratorStep!(c, - noSetFMUStatePriorToCurrentPoint, - c._ptr_enterEventMode, - c._ptr_terminateSimulation) +function fmi2CompletedIntegratorStep( + c::FMU2Component, + noSetFMUStatePriorToCurrentPoint::fmi2Boolean, +) + status = fmi2CompletedIntegratorStep!( + c, + noSetFMUStatePriorToCurrentPoint, + c._ptr_enterEventMode, + c._ptr_terminateSimulation, + ) return (status, c.enterEventMode, c.terminateSimulation) end diff --git a/src/FMI2/md.jl b/src/FMI2/md.jl index f2d4e9e..5eb44bd 100644 --- a/src/FMI2/md.jl +++ b/src/FMI2/md.jl @@ -9,9 +9,23 @@ # - [Sec. 2] functions to get values from the model description in the format `fmi2Get[value](md::fmi2ModelDescription)` [exported] # - [Sec. 3] additional functions to get useful information from the model description in the format `fmi2Get[value](md::fmi2ModelDescription)` [exported] -using FMIBase.FMICore: fmi2ModelDescriptionModelExchange, fmi2ModelDescriptionCoSimulation, fmi2ModelDescriptionDefaultExperiment, fmi2ModelDescriptionEnumerationItem -using FMIBase.FMICore: fmi2RealAttributesExt, fmi2BooleanAttributesExt, fmi2IntegerAttributesExt, fmi2StringAttributesExt, fmi2EnumerationAttributesExt -using FMIBase.FMICore: fmi2RealAttributes, fmi2BooleanAttributes, fmi2IntegerAttributes, fmi2StringAttributes, fmi2EnumerationAttributes +using FMIBase.FMICore: + fmi2ModelDescriptionModelExchange, + fmi2ModelDescriptionCoSimulation, + fmi2ModelDescriptionDefaultExperiment, + fmi2ModelDescriptionEnumerationItem +using FMIBase.FMICore: + fmi2RealAttributesExt, + fmi2BooleanAttributesExt, + fmi2IntegerAttributesExt, + fmi2StringAttributesExt, + fmi2EnumerationAttributesExt +using FMIBase.FMICore: + fmi2RealAttributes, + fmi2BooleanAttributes, + fmi2IntegerAttributes, + fmi2StringAttributes, + fmi2EnumerationAttributes using FMIBase.FMICore: fmi2ModelDescriptionModelStructure using FMIBase.FMICore: fmi2DependencyKind @@ -34,7 +48,7 @@ Extract the FMU variables and meta data from the ModelDescription function fmi2LoadModelDescription(pathToModelDescription::String) md = fmi2ModelDescription() - md.stringValueReferences = Dict{String, fmi2ValueReference}() + md.stringValueReferences = Dict{String,fmi2ValueReference}() md.outputValueReferences = Array{fmi2ValueReference}(undef, 0) md.inputValueReferences = Array{fmi2ValueReference}(undef, 0) md.stateValueReferences = Array{fmi2ValueReference}(undef, 0) @@ -50,13 +64,29 @@ function fmi2LoadModelDescription(pathToModelDescription::String) md.guid = root["guid"] # optional - md.generationTool = parseNode(root, "generationTool", String; onfail="[Unknown generation tool]") - md.generationDateAndTime = parseNode(root, "generationDateAndTime", String; onfail="[Unknown generation date and time]") - variableNamingConventionStr = parseNode(root, "variableNamingConvention", String; onfail="flat") - @assert (variableNamingConventionStr == "flat" || variableNamingConventionStr == "structured") ["fmi2ReadModelDescription(...): Unknown entry for `variableNamingConvention=$(variableNamingConventionStr)`."] - md.variableNamingConvention = (variableNamingConventionStr == "flat" ? fmi2VariableNamingConventionFlat : fmi2VariableNamingConventionStructured) - md.numberOfEventIndicators = parseNode(root, "numberOfEventIndicators", Int; onfail=0) - md.description = parseNode(root, "description", String; onfail="[Unknown Description]") + md.generationTool = + parseNode(root, "generationTool", String; onfail = "[Unknown generation tool]") + md.generationDateAndTime = parseNode( + root, + "generationDateAndTime", + String; + onfail = "[Unknown generation date and time]", + ) + variableNamingConventionStr = + parseNode(root, "variableNamingConvention", String; onfail = "flat") + @assert ( + variableNamingConventionStr == "flat" || + variableNamingConventionStr == "structured" + ) [ + "fmi2ReadModelDescription(...): Unknown entry for `variableNamingConvention=$(variableNamingConventionStr)`.", + ] + md.variableNamingConvention = ( + variableNamingConventionStr == "flat" ? fmi2VariableNamingConventionFlat : + fmi2VariableNamingConventionStructured + ) + md.numberOfEventIndicators = parseNode(root, "numberOfEventIndicators", Int; onfail = 0) + md.description = + parseNode(root, "description", String; onfail = "[Unknown Description]") # defaults md.modelExchange = nothing @@ -65,30 +95,43 @@ function fmi2LoadModelDescription(pathToModelDescription::String) # additionals md.valueReferences = [] - md.valueReferenceIndicies = Dict{UInt, UInt}() + md.valueReferenceIndicies = Dict{UInt,UInt}() for node in eachelement(root) if node.name == "CoSimulation" || node.name == "ModelExchange" if node.name == "CoSimulation" md.coSimulation = fmi2ModelDescriptionCoSimulation() - md.coSimulation.modelIdentifier = parseNode(node, "modelIdentifier") - md.coSimulation.canHandleVariableCommunicationStepSize = parseNode(node, "canHandleVariableCommunicationStepSize", Bool; onfail=false) - md.coSimulation.canInterpolateInputs = parseNode(node, "canInterpolateInputs", Bool ; onfail=false) - md.coSimulation.maxOutputDerivativeOrder = parseNode(node, "maxOutputDerivativeOrder", Int ; onfail=nothing) - md.coSimulation.canGetAndSetFMUstate = parseNode(node, "canGetAndSetFMUstate", Bool ; onfail=false) - md.coSimulation.canSerializeFMUstate = parseNode(node, "canSerializeFMUstate", Bool ; onfail=false) - md.coSimulation.providesDirectionalDerivative = parseNode(node, "providesDirectionalDerivative", Bool ; onfail=false) + md.coSimulation.modelIdentifier = parseNode(node, "modelIdentifier") + md.coSimulation.canHandleVariableCommunicationStepSize = parseNode( + node, + "canHandleVariableCommunicationStepSize", + Bool; + onfail = false, + ) + md.coSimulation.canInterpolateInputs = + parseNode(node, "canInterpolateInputs", Bool; onfail = false) + md.coSimulation.maxOutputDerivativeOrder = + parseNode(node, "maxOutputDerivativeOrder", Int; onfail = nothing) + md.coSimulation.canGetAndSetFMUstate = + parseNode(node, "canGetAndSetFMUstate", Bool; onfail = false) + md.coSimulation.canSerializeFMUstate = + parseNode(node, "canSerializeFMUstate", Bool; onfail = false) + md.coSimulation.providesDirectionalDerivative = + parseNode(node, "providesDirectionalDerivative", Bool; onfail = false) end if node.name == "ModelExchange" md.modelExchange = fmi2ModelDescriptionModelExchange() - md.modelExchange.modelIdentifier = parseNode(node, "modelIdentifier") - md.modelExchange.canGetAndSetFMUstate = parseNode(node, "canGetAndSetFMUstate", Bool ; onfail=false) - md.modelExchange.canSerializeFMUstate = parseNode(node, "canSerializeFMUstate", Bool ; onfail=false) - md.modelExchange.providesDirectionalDerivative = parseNode(node, "providesDirectionalDerivative", Bool ; onfail=false) + md.modelExchange.modelIdentifier = parseNode(node, "modelIdentifier") + md.modelExchange.canGetAndSetFMUstate = + parseNode(node, "canGetAndSetFMUstate", Bool; onfail = false) + md.modelExchange.canSerializeFMUstate = + parseNode(node, "canSerializeFMUstate", Bool; onfail = false) + md.modelExchange.providesDirectionalDerivative = + parseNode(node, "providesDirectionalDerivative", Bool; onfail = false) end - + elseif node.name == "TypeDefinitions" md.typeDefinitions = parseTypeDefinitions(md, node) @@ -115,15 +158,15 @@ function fmi2LoadModelDescription(pathToModelDescription::String) elseif node.name == "DefaultExperiment" md.defaultExperiment = fmi2ModelDescriptionDefaultExperiment() - md.defaultExperiment.startTime = parseNode(node, "startTime", fmi2Real) - md.defaultExperiment.stopTime = parseNode(node, "stopTime", fmi2Real) - md.defaultExperiment.tolerance = parseNode(node, "tolerance", fmi2Real) - md.defaultExperiment.stepSize = parseNode(node, "stepSize", fmi2Real) + md.defaultExperiment.startTime = parseNode(node, "startTime", fmi2Real) + md.defaultExperiment.stopTime = parseNode(node, "stopTime", fmi2Real) + md.defaultExperiment.tolerance = parseNode(node, "tolerance", fmi2Real) + md.defaultExperiment.stepSize = parseNode(node, "stepSize", fmi2Real) end end # creating an index for value references (fast look-up for dependencies) - for i in 1:length(md.valueReferences) + for i = 1:length(md.valueReferences) md.valueReferenceIndicies[md.valueReferences[i]] = i end @@ -137,14 +180,14 @@ end ####################################### # helper function to parse variable or simple type attributes -function parseAttribute(md::fmi2ModelDescription, defnode; ext::Bool=false) +function parseAttribute(md::fmi2ModelDescription, defnode; ext::Bool = false) typename = defnode.name - typenode = nothing + typenode = nothing if typename == "Real" - if ext + if ext typenode = fmi2RealAttributesExt() typenode.start = parseNode(defnode, "start", fmi2Real) @@ -155,7 +198,7 @@ function parseAttribute(md::fmi2ModelDescription, defnode; ext::Bool=false) else typenode = fmi2RealAttributes() end - + typenode.quantity = parseNode(defnode, "quantity", String) typenode.unit = parseNode(defnode, "unit", String) typenode.displayUnit = parseNode(defnode, "displayUnit", String) @@ -164,10 +207,10 @@ function parseAttribute(md::fmi2ModelDescription, defnode; ext::Bool=false) typenode.max = parseNode(defnode, "max", fmi2Real) typenode.nominal = parseNode(defnode, "nominal", fmi2Real) typenode.unbounded = parseNode(defnode, "unbounded", Bool) - + elseif typename == "String" - if ext + if ext typenode = fmi2StringAttributesExt() typenode.start = parseNode(defnode, "start", String) @@ -178,7 +221,7 @@ function parseAttribute(md::fmi2ModelDescription, defnode; ext::Bool=false) elseif typename == "Boolean" - if ext + if ext typenode = fmi2BooleanAttributesExt() typenode.start = parseNode(defnode, "start", Bool) @@ -188,8 +231,8 @@ function parseAttribute(md::fmi2ModelDescription, defnode; ext::Bool=false) end elseif typename == "Integer" - - if ext + + if ext typenode = fmi2IntegerAttributesExt() typenode.start = parseNode(defnode, "start", Int) @@ -197,14 +240,14 @@ function parseAttribute(md::fmi2ModelDescription, defnode; ext::Bool=false) else typenode = fmi2IntegerAttributes() end - + typenode.quantity = parseNode(defnode, "quantity", String) typenode.min = parseNode(defnode, "min", fmi2Integer) typenode.max = parseNode(defnode, "max", fmi2Integer) elseif typename == "Enumeration" - - if ext + + if ext typenode = fmi2EnumerationAttributesExt() typenode.start = parseNode(defnode, "start", fmi2Integer) @@ -290,7 +333,8 @@ function parseModelVariables(md::fmi2ModelDescription, nodes::EzXML.Node) initial = stringToInitial(md, node["initial"]) end - scalarVariables[index] = fmi2ScalarVariable(name, valueReference, causality, variability, initial) + scalarVariables[index] = + fmi2ScalarVariable(name, valueReference, causality, variability, initial) if !(valueReference in md.valueReferences) push!(md.valueReferences, valueReference) @@ -300,7 +344,7 @@ function parseModelVariables(md::fmi2ModelDescription, nodes::EzXML.Node) # type node defnode = node.firstelement - typenode = parseAttribute(md, defnode; ext=true) + typenode = parseAttribute(md, defnode; ext = true) if isa(typenode, fmi2RealAttributesExt) scalarVariables[index].Real = typenode elseif isa(typenode, fmi2StringAttributesExt) @@ -312,7 +356,7 @@ function parseModelVariables(md::fmi2ModelDescription, nodes::EzXML.Node) elseif isa(typenode, fmi2EnumerationAttributesExt) scalarVariables[index].Enumeration = typenode end - + # generic attributes if !isnothing(typenode) typenode.declaredType = parseNode(node.firstelement, "declaredType", String) @@ -329,7 +373,7 @@ end # Parses the model variables of the FMU model description. function parseTypeDefinitions(md::fmi2ModelDescription, nodes::EzXML.Node) - simpleTypes = Array{fmi2SimpleType, 1}() + simpleTypes = Array{fmi2SimpleType,1}() for node in eachelement(nodes) @@ -340,11 +384,11 @@ function parseTypeDefinitions(md::fmi2ModelDescription, nodes::EzXML.Node) # attribute node (mandatory) defnode = node.firstelement - simpleType.attribute = parseAttribute(md, defnode; ext=false) + simpleType.attribute = parseAttribute(md, defnode; ext = false) # optional simpleType.description = parseNode(node, "description", String) - + push!(simpleTypes, simpleType) end @@ -371,7 +415,9 @@ function parseUnknown(md::fmi2ModelDescription, node::EzXML.Node) if length(dependenciesKind) > 0 dependenciesKindSplit = split(dependenciesKind, " ") if length(dependenciesKindSplit) > 0 - varDep.dependenciesKind = collect(stringToDependencyKind(md, e) for e in dependenciesKindSplit) + varDep.dependenciesKind = collect( + stringToDependencyKind(md, e) for e in dependenciesKindSplit + ) end end end @@ -519,13 +565,25 @@ function fmi2SetDatatypeVariables(node::EzXML.Node, md::fmi2ModelDescription, sv end end - if haskey(typenode, "min") && (type.datatype == fmi2Real || type.datatype == fmi2Integer || type.datatype == fmi2Enum) + if haskey(typenode, "min") && ( + type.datatype == fmi2Real || + type.datatype == fmi2Integer || + type.datatype == fmi2Enum + ) type.min = parseNode(typenode, "min", type.datatype) end - if haskey(typenode, "max") && (type.datatype == fmi2Real || type.datatype == fmi2Integer || type.datatype == fmi2Enum) + if haskey(typenode, "max") && ( + type.datatype == fmi2Real || + type.datatype == fmi2Integer || + type.datatype == fmi2Enum + ) type.max = parseNode(typenode, "max", type.datatype) end - if haskey(typenode, "quantity") && (type.datatype == fmi2Real || type.datatype == fmi2Integer || type.datatype == fmi2Enum) + if haskey(typenode, "quantity") && ( + type.datatype == fmi2Real || + type.datatype == fmi2Integer || + type.datatype == fmi2Enum + ) type.quantity = typenode["quantity"] end if haskey(typenode, "unit") && type.datatype == fmi2Real @@ -586,7 +644,7 @@ function parseDisplayUnits(::fmi2ModelDescription, node) if haskey(node, "offset") setfield!(unit, :offset, parseNode(node, "offset", Float64)) end - + return unit end @@ -598,7 +656,7 @@ function parseUnitDefinitions(md::fmi2ModelDescription, parentNode) unit = fmi2Unit(node["name"]) - for subNode = eachelement(node) + for subNode in eachelement(node) if subNode.name == "BaseUnit" unit.baseUnit = parseBaseUnit(md, subNode) @@ -686,5 +744,6 @@ function isModelStructureDerivativesAvailable(md::fmi2ModelDescription) return true end -isModelStructureDerivativesAvailable(fmu::FMU) = isModelStructureDerivativesAvailable(fmu.modelDescription) +isModelStructureDerivativesAvailable(fmu::FMU) = + isModelStructureDerivativesAvailable(fmu.modelDescription) export isModelStructureDerivativesAvailable diff --git a/src/FMI2/prep.jl b/src/FMI2/prep.jl index d4fa03c..3a4f4e7 100644 --- a/src/FMI2/prep.jl +++ b/src/FMI2/prep.jl @@ -8,33 +8,40 @@ using FMIBase: handleEvents import FMIImport: fmi2VariabilityConstant, fmi2InitialApprox, fmi2InitialExact function setBeforeInitialization(mv::fmi2ScalarVariable) - + causality, variability, initial = getAttributes(mv) - return variability != fmi2VariabilityConstant && initial ∈ (fmi2InitialApprox, fmi2InitialExact) + return variability != fmi2VariabilityConstant && + initial ∈ (fmi2InitialApprox, fmi2InitialExact) end import FMIImport: fmi2CausalityInput, fmi2CausalityParameter, fmi2VariabilityTunable function setInInitialization(mv::fmi2ScalarVariable) causality, variability, initial = getAttributes(mv) - return causality == fmi2CausalityInput || (causality != fmi2CausalityParameter && variability == fmi2VariabilityTunable) || (variability != fmi2VariabilityConstant && initial == fmi2InitialExact) + return causality == fmi2CausalityInput || + (causality != fmi2CausalityParameter && variability == fmi2VariabilityTunable) || + (variability != fmi2VariabilityConstant && initial == fmi2InitialExact) end -function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2Type=fmu.type; - instantiate::Union{Nothing, Bool}=fmu.executionConfig.instantiate, - freeInstance::Union{Nothing, Bool}=fmu.executionConfig.freeInstance, - terminate::Union{Nothing, Bool}=fmu.executionConfig.terminate, - reset::Union{Nothing, Bool}=fmu.executionConfig.reset, - setup::Union{Nothing, Bool}=fmu.executionConfig.setup, - parameters::Union{Dict{<:Any, <:Any}, Nothing}=nothing, - t_start::Real=0.0, - t_stop::Union{Real, Nothing}=nothing, - tolerance::Union{Real, Nothing}=nothing, - x0::Union{AbstractArray{<:Real}, Nothing}=nothing, - inputs::Union{Dict{<:Any, <:Any}, Nothing}=nothing, - cleanup::Bool=false, - handleEvents=handleEvents, - instantiateKwargs...) +function prepareSolveFMU( + fmu::FMU2, + c::Union{Nothing,FMU2Component}, + type::fmi2Type = fmu.type; + instantiate::Union{Nothing,Bool} = fmu.executionConfig.instantiate, + freeInstance::Union{Nothing,Bool} = fmu.executionConfig.freeInstance, + terminate::Union{Nothing,Bool} = fmu.executionConfig.terminate, + reset::Union{Nothing,Bool} = fmu.executionConfig.reset, + setup::Union{Nothing,Bool} = fmu.executionConfig.setup, + parameters::Union{Dict{<:Any,<:Any},Nothing} = nothing, + t_start::Real = 0.0, + t_stop::Union{Real,Nothing} = nothing, + tolerance::Union{Real,Nothing} = nothing, + x0::Union{AbstractArray{<:Real},Nothing} = nothing, + inputs::Union{Dict{<:Any,<:Any},Nothing} = nothing, + cleanup::Bool = false, + handleEvents = handleEvents, + instantiateKwargs..., +) ignore_derivatives() do @@ -42,17 +49,22 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2 if instantiate # remove old one if we missed it (callback) if cleanup && c != nothing - c = finishSolveFMU(fmu, c; freeInstance=freeInstance, terminate=terminate) + c = finishSolveFMU( + fmu, + c; + freeInstance = freeInstance, + terminate = terminate, + ) end - c = fmi2Instantiate!(fmu; type=type, instantiateKwargs...) + c = fmi2Instantiate!(fmu; type = type, instantiateKwargs...) else # use existing instance if c === nothing if hasCurrentInstance(fmu) c = getCurrentInstance(fmu) else @warn "Found no FMU instance, but executionConfig doesn't force allocation. Allocating one.\nUse `fmi2Instantiate(fmu)` to prevent this message." - c = fmi2Instantiate!(fmu; type=type, instantiateKwargs...) + c = fmi2Instantiate!(fmu; type = type, instantiateKwargs...) end end end @@ -67,25 +79,35 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2 # soft reset (if necessary) if reset - retcode = fmi2Reset(c; soft=true) + retcode = fmi2Reset(c; soft = true) @assert retcode == fmi2StatusOK "fmi2Simulate(...): Reset failed with return code $(retcode)." - end + end # setup experiment (hard) if setup - retcode = fmi2SetupExperiment(c, t_start, t_stop; tolerance=tolerance) + retcode = fmi2SetupExperiment(c, t_start, t_stop; tolerance = tolerance) @assert retcode == fmi2StatusOK "fmi2Simulate(...): Setting up experiment failed with return code $(retcode)." end # parameters if parameters !== nothing - retcodes = setValue(c, collect(keys(parameters)), collect(values(parameters)); filter=setBeforeInitialization) + retcodes = setValue( + c, + collect(keys(parameters)), + collect(values(parameters)); + filter = setBeforeInitialization, + ) @assert all(retcodes .== fmi2StatusOK) "fmi2Simulate(...): Setting initial parameters failed with return code $(retcode)." end # inputs if inputs !== nothing - retcodes = setValue(c, collect(keys(inputs)), collect(values(inputs)); filter=setBeforeInitialization) + retcodes = setValue( + c, + collect(keys(inputs)), + collect(values(inputs)); + filter = setBeforeInitialization, + ) @assert all(retcodes .== fmi2StatusOK) "fmi2Simulate(...): Setting initial inputs failed with return code $(retcode)." end @@ -93,7 +115,12 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2 if !isnothing(x0) #retcode = fmi2SetContinuousStates(c, x0) #@assert retcode == fmi2StatusOK "fmi2Simulate(...): Setting initial state failed with return code $(retcode)." - retcodes = setValue(c, fmu.modelDescription.stateValueReferences, x0; filter=setBeforeInitialization) + retcodes = setValue( + c, + fmu.modelDescription.stateValueReferences, + x0; + filter = setBeforeInitialization, + ) @assert all(retcodes .== fmi2StatusOK) "fmi2Simulate(...): Setting initial states failed with return code $(retcode)." end @@ -105,13 +132,23 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2 # parameters if parameters !== nothing - retcodes = setValue(c, collect(keys(parameters)), collect(values(parameters)); filter=setInInitialization) + retcodes = setValue( + c, + collect(keys(parameters)), + collect(values(parameters)); + filter = setInInitialization, + ) @assert all(retcodes .== fmi2StatusOK) "fmi2Simulate(...): Setting initial parameters failed with return code $(retcodes)." end - + # inputs if inputs !== nothing - retcodes = setValue(c, collect(keys(inputs)), collect(values(inputs)); filter=setInInitialization) + retcodes = setValue( + c, + collect(keys(inputs)), + collect(values(inputs)); + filter = setInInitialization, + ) @assert all(retcodes .== fmi2StatusOK) "fmi2Simulate(...): Setting initial inputs failed with return code $(retcodes)." end @@ -119,7 +156,12 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2 if !isnothing(x0) #retcode = fmi2SetContinuousStates(c, x0) #@assert retcode == fmi2StatusOK "fmi2Simulate(...): Setting initial state failed with return code $(retcode)." - retcodes = setValue(c, fmu.modelDescription.stateValueReferences, x0; filter=setInInitialization) + retcodes = setValue( + c, + fmu.modelDescription.stateValueReferences, + x0; + filter = setInInitialization, + ) @assert all(retcodes .== fmi2StatusOK) "fmi2Simulate(...): Setting initial inputs failed with return code $(retcodes)." # safe start state in component @@ -143,7 +185,7 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2 if instantiate || reset # we have a fresh instance @debug "[NEW INST]" - handleEvents(c) + handleEvents(c) end c.fmu.hasStateEvents = (c.fmu.modelDescription.numberOfEventIndicators > 0) @@ -153,7 +195,12 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::fmi2 return c, x0 end -function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::Symbol; kwargs...) +function prepareSolveFMU( + fmu::FMU2, + c::Union{Nothing,FMU2Component}, + type::Symbol; + kwargs..., +) if type == :CS return prepareSolveFMU(fmu, c, fmi2TypeCoSimulation; kwargs...) elseif type == :ME @@ -165,36 +212,39 @@ function prepareSolveFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, type::Symb end end -function finishSolveFMU(fmu::FMU2, c::FMU2Component; - freeInstance::Union{Nothing, Bool}=nothing, - terminate::Union{Nothing, Bool}=nothing, - popComponent::Bool=true) +function finishSolveFMU( + fmu::FMU2, + c::FMU2Component; + freeInstance::Union{Nothing,Bool} = nothing, + terminate::Union{Nothing,Bool} = nothing, + popComponent::Bool = true, +) - if isnothing(c) - return + if isnothing(c) + return end ignore_derivatives() do - if terminate === nothing + if terminate === nothing terminate = fmu.executionConfig.terminate end - if freeInstance === nothing + if freeInstance === nothing freeInstance = fmu.executionConfig.freeInstance end # soft terminate (if necessary) if terminate - retcode = fmi2Terminate(c; soft=true) + retcode = fmi2Terminate(c; soft = true) @assert retcode == fmi2StatusOK "fmi2Simulate(...): Termination failed with return code $(retcode)." end # freeInstance (hard) if freeInstance - fmi2FreeInstance!(c; popComponent=popComponent) # , doccall=freeInstance + fmi2FreeInstance!(c; popComponent = popComponent) # , doccall=freeInstance c = nothing end end return c -end \ No newline at end of file +end diff --git a/src/FMI3/c.jl b/src/FMI3/c.jl index fc6eafa..ce98a80 100644 --- a/src/FMI3/c.jl +++ b/src/FMI3/c.jl @@ -11,20 +11,74 @@ # Any c-function `f(args...)` without a leading `fmi3Instance`-arguemnt is implented as `f(c_ptr, args...)` where `c_ptr` is a pointer to the c-function (inside the DLL). import FMIBase.FMICore: fmi3GetVersion -import FMIBase.FMICore: fmi3SetDebugLogging, fmi3EnterInitializationMode, fmi3ExitInitializationMode, fmi3Terminate, fmi3Reset +import FMIBase.FMICore: + fmi3SetDebugLogging, + fmi3EnterInitializationMode, + fmi3ExitInitializationMode, + fmi3Terminate, + fmi3Reset import FMIBase.FMICore: fmi3GetFloat32!, fmi3SetFloat32, fmi3GetFloat64!, fmi3SetFloat64 -import FMIBase.FMICore: fmi3GetInt8!, fmi3SetInt8, fmi3GetInt16!, fmi3SetInt16,fmi3GetInt32!, fmi3SetInt32, fmi3GetInt64!, fmi3SetInt64 -import FMIBase.FMICore: fmi3GetUInt8!, fmi3SetUInt8, fmi3GetUInt16!, fmi3SetUInt16,fmi3GetUInt32!, fmi3SetUInt32, fmi3GetUInt64!, fmi3SetUInt64 -import FMIBase.FMICore: fmi3GetBoolean!, fmi3SetBoolean, fmi3GetString!, fmi3SetString, fmi3GetBinary!, fmi3SetBinary, fmi3GetClock!, fmi3SetClock -import FMIBase.FMICore: fmi3GetFMUState!, fmi3SetFMUState, fmi3FreeFMUState, fmi3SerializedFMUStateSize!, fmi3SerializeFMUState!, fmi3DeSerializeFMUState! -import FMIBase.FMICore: fmi3SetIntervalDecimal, fmi3SetIntervalFraction, fmi3GetIntervalDecimal!, fmi3GetIntervalFraction!, fmi3GetShiftDecimal!, fmi3GetShiftFraction!, fmi3ActivateModelPartition +import FMIBase.FMICore: + fmi3GetInt8!, + fmi3SetInt8, + fmi3GetInt16!, + fmi3SetInt16, + fmi3GetInt32!, + fmi3SetInt32, + fmi3GetInt64!, + fmi3SetInt64 +import FMIBase.FMICore: + fmi3GetUInt8!, + fmi3SetUInt8, + fmi3GetUInt16!, + fmi3SetUInt16, + fmi3GetUInt32!, + fmi3SetUInt32, + fmi3GetUInt64!, + fmi3SetUInt64 +import FMIBase.FMICore: + fmi3GetBoolean!, + fmi3SetBoolean, + fmi3GetString!, + fmi3SetString, + fmi3GetBinary!, + fmi3SetBinary, + fmi3GetClock!, + fmi3SetClock +import FMIBase.FMICore: + fmi3GetFMUState!, + fmi3SetFMUState, + fmi3FreeFMUState, + fmi3SerializedFMUStateSize!, + fmi3SerializeFMUState!, + fmi3DeSerializeFMUState! +import FMIBase.FMICore: + fmi3SetIntervalDecimal, + fmi3SetIntervalFraction, + fmi3GetIntervalDecimal!, + fmi3GetIntervalFraction!, + fmi3GetShiftDecimal!, + fmi3GetShiftFraction!, + fmi3ActivateModelPartition import FMIBase.FMICore: fmi3GetNumberOfVariableDependencies!, fmi3GetVariableDependencies! -import FMIBase.FMICore: fmi3GetDirectionalDerivative!, fmi3GetAdjointDerivative!, fmi3GetOutputDerivatives! +import FMIBase.FMICore: + fmi3GetDirectionalDerivative!, fmi3GetAdjointDerivative!, fmi3GetOutputDerivatives! import FMIBase.FMICore: fmi3EnterConfigurationMode, fmi3ExitConfigurationMode import FMIBase.FMICore: fmi3GetNumberOfContinuousStates!, fmi3GetNumberOfEventIndicators! import FMIBase.FMICore: fmi3DoStep!, fmi3EnterStepMode -import FMIBase.FMICore: fmi3SetTime, fmi3SetContinuousStates, fmi3EnterEventMode, fmi3UpdateDiscreteStates, fmi3EnterContinuousTimeMode, fmi3CompletedIntegratorStep! -import FMIBase.FMICore: fmi3GetContinuousStateDerivatives!, fmi3GetEventIndicators!, fmi3GetContinuousStates!, fmi3GetNominalsOfContinuousStates!, fmi3EvaluateDiscreteStates +import FMIBase.FMICore: + fmi3SetTime, + fmi3SetContinuousStates, + fmi3EnterEventMode, + fmi3UpdateDiscreteStates, + fmi3EnterContinuousTimeMode, + fmi3CompletedIntegratorStep! +import FMIBase.FMICore: + fmi3GetContinuousStateDerivatives!, + fmi3GetEventIndicators!, + fmi3GetContinuousStates!, + fmi3GetNominalsOfContinuousStates!, + fmi3EvaluateDiscreteStates """ @@ -48,10 +102,12 @@ Function that is called in the FMU, usually if an fmi3XXX function, does not beh - FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec3.0: 2.3.1. Super State: FMU State Setable """ -function fmi3CallbackLogger(_instanceEnvironment::Ptr{FMU3InstanceEnvironment}, +function fmi3CallbackLogger( + _instanceEnvironment::Ptr{FMU3InstanceEnvironment}, status::fmi3Status, _category::Ptr{Cchar}, - _message::Ptr{Cchar}) + _message::Ptr{Cchar}, +) message = unsafe_string(_message) category = unsafe_string(_category) @@ -69,11 +125,11 @@ function fmi3CallbackLogger(_instanceEnvironment::Ptr{FMU3InstanceEnvironment}, if instanceEnvironment.logStatusDiscard @error "[$(status)][$(category)]: $(message)" end - elseif status == fmi3StatusError - if instanceEnvironment.logStatusError + elseif status == fmi3StatusError + if instanceEnvironment.logStatusError @error "[$(status)][$(category)]: $(message)" end - elseif status == fmi3StatusFatal + elseif status == fmi3StatusFatal if instanceEnvironment.logStatusFatal @error "[$(status)][$(category)]: $(message)" end @@ -119,14 +175,16 @@ If the ModelDescription has the "providesIntermediateUpdate" flag, the Intermedi - FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec3.0: 4.2.2. State: Intermediate Update Mode """ -function fmi3CallbackIntermediateUpdate(instanceEnvironment::Ptr{Cvoid}, +function fmi3CallbackIntermediateUpdate( + instanceEnvironment::Ptr{Cvoid}, intermediateUpdateTime::fmi3Float64, intermediateVariableSetRequested::fmi3Boolean, intermediateVariableGetAllowed::fmi3Boolean, intermediateStepFinished::fmi3Boolean, canReturnEarly::fmi3Boolean, earlyReturnRequested::Ptr{fmi3Boolean}, - earlyReturnTime::Ptr{fmi3Float64}) + earlyReturnTime::Ptr{fmi3Float64}, +) @debug "fmi3CallbackIntermediateUpdate be implemented!" # [ToDo] end @@ -152,7 +210,7 @@ A model partition of a Scheduled Execution FMU calls `fmi3CallbackClockUpdate` t - FMISpec3.0, Version D5ef1c1: 5.2.2. State: Clock Activation Mode """ function fmi3CallbackClockUpdate(_instanceEnvironment::Ptr{Cvoid}) - + @debug " fmi3CallbackClockUpdateto be implemented!" # [ToDo] end @@ -197,12 +255,12 @@ end # helper function checkStatus(c::FMU3Instance, status::fmi3Status) @assert (status != fmi3StatusWarning) || !c.fmu.executionConfig.assertOnWarning "Assert on `fmi3StatusWarning`. See stack for errors." - + if status == fmi3StatusError c.state = fmi3InstanceStateError @assert !c.fmu.executionConfig.assertOnError "Assert on `fmi3StatusError`. See stack for errors." - - elseif status == fmi3StatusFatal + + elseif status == fmi3StatusFatal c.state = fmi3InstanceStateFatal @assert false "Assert on `fmi3StatusFatal`. See stack for errors." end @@ -236,8 +294,19 @@ More detailed: - FMISpec3.0: 2.3.1. Super State: FMU State Setable See also [`fmi3SetDebugLogging`](@ref). """ -function fmi3SetDebugLogging(c::FMU3Instance, logginOn::fmi3Boolean, nCategories::UInt, categories::Ptr{Nothing}) - status = fmi3SetDebugLogging(c.fmu.cSetDebugLogging, c.addr, logginOn, nCategories, categories) +function fmi3SetDebugLogging( + c::FMU3Instance, + logginOn::fmi3Boolean, + nCategories::UInt, + categories::Ptr{Nothing}, +) + status = fmi3SetDebugLogging( + c.fmu.cSetDebugLogging, + c.addr, + logginOn, + nCategories, + categories, + ) checkStatus(c, status) return status end @@ -280,16 +349,27 @@ More detailed: - FMISpec3.0: 2.3.2. State: Instantiated See also [`fmi3EnterInitializationMode`](@ref). """ -function fmi3EnterInitializationMode(c::FMU3Instance, toleranceDefined::fmi3Boolean, +function fmi3EnterInitializationMode( + c::FMU3Instance, + toleranceDefined::fmi3Boolean, tolerance::fmi3Float64, startTime::fmi3Float64, stopTimeDefined::fmi3Boolean, - stopTime::fmi3Float64) + stopTime::fmi3Float64, +) if c.state != fmi3InstanceStateInstantiated @warn "fmi3EnterInitializationMode(...): Needs to be called in state `fmi3IntanceStateInstantiated`." end - status = fmi3EnterInitializationMode(c.fmu.cEnterInitializationMode, c.addr, toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime) + status = fmi3EnterInitializationMode( + c.fmu.cEnterInitializationMode, + c.addr, + toleranceDefined, + tolerance, + startTime, + stopTimeDefined, + stopTime, + ) checkStatus(c, status) if status == fmi3StatusOK c.state = fmi3InstanceStateInitializationMode @@ -327,18 +407,19 @@ function fmi3ExitInitializationMode(c::FMU3Instance) if c.state != fmi3InstanceStateInitializationMode @warn "fmi3ExitInitializationMode(...): Needs to be called in state `fmi3InstanceStateInitializationMode`." end - + status = fmi3ExitInitializationMode(c.fmu.cExitInitializationMode, c.addr) checkStatus(c, status) if status == fmi3StatusOK - if c.type == fmi3TypeCoSimulation && !c.fmu.modelDescription.coSimulation.hasEventMode + if c.type == fmi3TypeCoSimulation && + !c.fmu.modelDescription.coSimulation.hasEventMode c.state = fmi3InstanceStateStepMode elseif c.type == fmi3TypeScheduledExecution c.state = fmi3InstanceStateClockActivationMode else c.state = fmi3InstanceStateEventMode end - end + end return status end @@ -371,21 +452,24 @@ More detailed: - FMISpec3.0: 2.3.4. Super State: Initialized See also [`fmi3Terminate`](@ref). """ -function fmi3Terminate(c::FMU3Instance; soft::Bool=false) - if c.state != fmi3InstanceStateContinuousTimeMode && c.state != fmi3InstanceStateEventMode && c.state != fmi3InstanceStateClockActivationMode && c.state != fmi3InstanceStateStepMode - if soft +function fmi3Terminate(c::FMU3Instance; soft::Bool = false) + if c.state != fmi3InstanceStateContinuousTimeMode && + c.state != fmi3InstanceStateEventMode && + c.state != fmi3InstanceStateClockActivationMode && + c.state != fmi3InstanceStateStepMode + if soft return fmi3StatusOK else @warn "fmi3Terminate(_): Needs to be called in state `fmi3InstanceStateContinuousTimeMode`, `fmi3InstanceStateEventMode`, `fmi3InstanceStateClockActivationMode` or `fmi3InstanceStateStepMode`." end end - + status = fmi3Terminate(c.fmu.cTerminate, c.addr) checkStatus(c, status) - if status == fmi3StatusOK + if status == fmi3StatusOK c.state = fmi3InstanceStateTerminated - end - + end + return status end @@ -419,13 +503,13 @@ See also [`fmi3Reset`](@ref). """ function fmi3Reset(c::FMU3Instance; soft::Bool = false) if c.state != fmi3InstanceStateTerminated && c.state != fmi3InstanceStateError - if soft + if soft return fmi3StatusOK else @warn "fmi3Reset(_): Needs to be called in state `fmi3InstanceStateTerminated` or `fmi3InstanceStateError`." end end - + if c.fmu.cReset == C_NULL fmi3FreeInstance!(c.fmu.cFreeInstance, c.addr) if fmi3IsCoSimulation(c.fmu) @@ -448,7 +532,7 @@ function fmi3Reset(c::FMU3Instance; soft::Bool = false) checkStatus(c, status) if status == fmi3StatusOK c.state = fmi3InstanceStateInstantiated - end + end return status end end @@ -483,9 +567,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetFloat32!`](@ref). """ -function fmi3GetFloat32!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Float32}, nvalue::Csize_t) - status = fmi3GetFloat32!(c.fmu.cGetFloat32, - c.addr, vr, nvr, value, nvalue) +function fmi3GetFloat32!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Float32}, + nvalue::Csize_t, +) + status = fmi3GetFloat32!(c.fmu.cGetFloat32, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -520,9 +609,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetFloat32`](@ref). """ -function fmi3SetFloat32(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Float32}, nvalue::Csize_t) - status = fmi3SetFloat32(c.fmu.cSetFloat32, - c.addr, vr, nvr, value, nvalue) +function fmi3SetFloat32( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Float32}, + nvalue::Csize_t, +) + status = fmi3SetFloat32(c.fmu.cSetFloat32, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -556,9 +650,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetFloat64!`](@ref). """ -function fmi3GetFloat64!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Float64}, nvalue::Csize_t) - status = fmi3GetFloat64!(c.fmu.cGetFloat64, - c.addr, vr, nvr, value, nvalue) +function fmi3GetFloat64!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Float64}, + nvalue::Csize_t, +) + status = fmi3GetFloat64!(c.fmu.cGetFloat64, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -593,21 +692,27 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetFloat64`](@ref). """ -function fmi3SetFloat64(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Float64}, nvalue::Csize_t; track::Bool=true) - status = fmi3SetFloat64(c.fmu.cSetFloat64, - c.addr, vr, nvr, value, nvalue) +function fmi3SetFloat64( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Float64}, + nvalue::Csize_t; + track::Bool = true, +) + status = fmi3SetFloat64(c.fmu.cSetFloat64, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) - if track && status == fmi2StatusOK - check_invalidate!(vr, c.∂ẋ_∂x) + if track && status == fmi2StatusOK + check_invalidate!(vr, c.∂ẋ_∂x) check_invalidate!(vr, c.∂ẋ_∂u) check_invalidate!(vr, c.∂ẋ_∂p) - - check_invalidate!(vr, c.∂y_∂x) + + check_invalidate!(vr, c.∂y_∂x) check_invalidate!(vr, c.∂y_∂u) check_invalidate!(vr, c.∂y_∂p) - check_invalidate!(vr, c.∂e_∂x) + check_invalidate!(vr, c.∂e_∂x) check_invalidate!(vr, c.∂e_∂u) check_invalidate!(vr, c.∂e_∂p) @@ -650,9 +755,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetInt8!`](@ref). """ -function fmi3GetInt8!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int8}, nvalue::Csize_t) - status = fmi3GetInt8!(c.fmu.cGetInt8, - c.addr, vr, nvr, value, nvalue) +function fmi3GetInt8!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int8}, + nvalue::Csize_t, +) + status = fmi3GetInt8!(c.fmu.cGetInt8, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -685,9 +795,14 @@ More detailed: - FMISpec3.0: 2.2.4 Status Returned by Functions - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values """ -function fmi3SetInt8(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int8}, nvalue::Csize_t) - status = fmi3SetInt8(c.fmu.cSetInt8, - c.addr, vr, nvr, value, nvalue) +function fmi3SetInt8( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int8}, + nvalue::Csize_t, +) + status = fmi3SetInt8(c.fmu.cSetInt8, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -722,9 +837,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetUInt8!`](@ref). """ -function fmi3GetUInt8!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt8}, nvalue::Csize_t) - status = fmi3GetUInt8!(c.fmu.cGetUInt8, - c.addr, vr, nvr, value, nvalue) +function fmi3GetUInt8!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt8}, + nvalue::Csize_t, +) + status = fmi3GetUInt8!(c.fmu.cGetUInt8, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -758,9 +878,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetUInt8`](@ref). """ -function fmi3SetUInt8(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt8}, nvalue::Csize_t) - status = fmi3SetUInt8(c.fmu.cSetUInt8, - c.addr, vr, nvr, value, nvalue) +function fmi3SetUInt8( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt8}, + nvalue::Csize_t, +) + status = fmi3SetUInt8(c.fmu.cSetUInt8, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -795,11 +920,16 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetInt16!`](@ref). """ -function fmi3GetInt16!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int16}, nvalue::Csize_t) - status = fmi3GetInt16!(c.fmu.cGetInt16, - c.addr, vr, nvr, value, nvalue) +function fmi3GetInt16!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int16}, + nvalue::Csize_t, +) + status = fmi3GetInt16!(c.fmu.cGetInt16, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) - return status + return status end """ @@ -831,9 +961,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetInt16`](@ref). """ -function fmi3SetInt16(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int16}, nvalue::Csize_t) - status = fmi3SetInt16(c.fmu.cSetInt16, - c.addr, vr, nvr, value, nvalue) +function fmi3SetInt16( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int16}, + nvalue::Csize_t, +) + status = fmi3SetInt16(c.fmu.cSetInt16, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -868,9 +1003,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetUInt16!`](@ref). """ -function fmi3GetUInt16!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt16}, nvalue::Csize_t) - status = fmi3GetUInt16!(c.fmu.cGetUInt16, - c.addr, vr, nvr, value, nvalue) +function fmi3GetUInt16!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt16}, + nvalue::Csize_t, +) + status = fmi3GetUInt16!(c.fmu.cGetUInt16, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -903,9 +1043,14 @@ More detailed: - FMISpec3.0: 2.2.4 Status Returned by Functions - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values """ -function fmi3SetUInt16(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt16}, nvalue::Csize_t) - status = fmi3SetUInt16(c.fmu.cSetUInt16, - c.addr, vr, nvr, value, nvalue) +function fmi3SetUInt16( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt16}, + nvalue::Csize_t, +) + status = fmi3SetUInt16(c.fmu.cSetUInt16, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -939,9 +1084,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetInt32!`](@ref). """ -function fmi3GetInt32!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int32}, nvalue::Csize_t) - status = fmi3GetInt32!(c.fmu.cGetInt32, - c.addr, vr, nvr, value, nvalue) +function fmi3GetInt32!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int32}, + nvalue::Csize_t, +) + status = fmi3GetInt32!(c.fmu.cGetInt32, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -975,9 +1125,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetInt32`](@ref). """ -function fmi3SetInt32(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int32}, nvalue::Csize_t) - status = fmi3SetInt32(c.fmu.cSetInt32, - c.addr, vr, nvr, value, nvalue) +function fmi3SetInt32( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int32}, + nvalue::Csize_t, +) + status = fmi3SetInt32(c.fmu.cSetInt32, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1012,9 +1167,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetUInt32!`](@ref). """ -function fmi3GetUInt32!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt32}, nvalue::Csize_t) - status = fmi3GetUInt32!(c.fmu.cGetUInt32, - c.addr, vr, nvr, value, nvalue) +function fmi3GetUInt32!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt32}, + nvalue::Csize_t, +) + status = fmi3GetUInt32!(c.fmu.cGetUInt32, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1048,9 +1208,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetUInt32`](@ref). """ -function fmi3SetUInt32(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt32}, nvalue::Csize_t) - status = fmi3SetUInt32(c.fmu.cSetUInt32, - c.addr, vr, nvr, value, nvalue) +function fmi3SetUInt32( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt32}, + nvalue::Csize_t, +) + status = fmi3SetUInt32(c.fmu.cSetUInt32, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1085,9 +1250,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetInt64!`](@ref). """ -function fmi3GetInt64!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int64}, nvalue::Csize_t) - status = fmi3GetInt64!(c.fmu.cGetInt64, - c.addr, vr, nvr, value, nvalue) +function fmi3GetInt64!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int64}, + nvalue::Csize_t, +) + status = fmi3GetInt64!(c.fmu.cGetInt64, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1121,9 +1291,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetInt64`](@ref). """ -function fmi3SetInt64(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Int64}, nvalue::Csize_t) - status = fmi3SetInt64(c.fmu.cSetInt64, - c.addr, vr, nvr, value, nvalue) +function fmi3SetInt64( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Int64}, + nvalue::Csize_t, +) + status = fmi3SetInt64(c.fmu.cSetInt64, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1158,9 +1333,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetUInt64!`](@ref). """ -function fmi3GetUInt64!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt64}, nvalue::Csize_t) - status = fmi3GetUInt64!(c.fmu.cGetUInt64, - c.addr, vr, nvr, value, nvalue) +function fmi3GetUInt64!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt64}, + nvalue::Csize_t, +) + status = fmi3GetUInt64!(c.fmu.cGetUInt64, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1194,9 +1374,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetUInt64`](@ref). """ -function fmi3SetUInt64(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3UInt64}, nvalue::Csize_t) - status = fmi3SetUInt64(c.fmu.cSetUInt64, - c.addr, vr, nvr, value, nvalue) +function fmi3SetUInt64( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3UInt64}, + nvalue::Csize_t, +) + status = fmi3SetUInt64(c.fmu.cSetUInt64, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1230,9 +1415,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetBoolean!`](@ref). """ -function fmi3GetBoolean!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Boolean}, nvalue::Csize_t) - status = fmi3GetBoolean!(c.fmu.cGetBoolean, - c.addr, vr, nvr, value, nvalue) +function fmi3GetBoolean!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Boolean}, + nvalue::Csize_t, +) + status = fmi3GetBoolean!(c.fmu.cGetBoolean, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1266,9 +1456,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetBoolean`](@ref). """ -function fmi3SetBoolean(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Boolean}, nvalue::Csize_t) - status = fmi3SetBoolean(c.fmu.cSetBoolean, - c.addr, vr, nvr, value, nvalue) +function fmi3SetBoolean( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Boolean}, + nvalue::Csize_t, +) + status = fmi3SetBoolean(c.fmu.cSetBoolean, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1303,9 +1498,14 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetString!`](@ref). """ -function fmi3GetString!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::Vector{Ptr{Cchar}}, nvalue::Csize_t) - status = fmi3GetString!(c.fmu.cGetString, - c.addr, vr, nvr, value, nvalue) +function fmi3GetString!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::Vector{Ptr{Cchar}}, + nvalue::Csize_t, +) + status = fmi3GetString!(c.fmu.cGetString, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1338,10 +1538,15 @@ More detailed: - FMISpec3.0: 2.2.4 Status Returned by Functions - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetString`](@ref). -""" -function fmi3SetString(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::Union{AbstractArray{Ptr{Cchar}}, AbstractArray{Ptr{UInt8}}}, nvalue::Csize_t) - status = fmi3SetString(c.fmu.cSetString, - c.addr, vr, nvr, value, nvalue) +""" +function fmi3SetString( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::Union{AbstractArray{Ptr{Cchar}},AbstractArray{Ptr{UInt8}}}, + nvalue::Csize_t, +) + status = fmi3SetString(c.fmu.cSetString, c.addr, vr, nvr, value, nvalue) checkStatus(c, status) return status end @@ -1376,9 +1581,15 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetBinary!`](@ref). """ -function fmi3GetBinary!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, valueSizes::AbstractArray{Csize_t}, value::AbstractArray{fmi3Binary}, nvalue::Csize_t) - status = fmi3GetBinary!(c.fmu.cGetBinary, - c.addr, vr, nvr, valueSizes, value, nvalue) +function fmi3GetBinary!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + valueSizes::AbstractArray{Csize_t}, + value::AbstractArray{fmi3Binary}, + nvalue::Csize_t, +) + status = fmi3GetBinary!(c.fmu.cGetBinary, c.addr, vr, nvr, valueSizes, value, nvalue) checkStatus(c, status) return status end @@ -1413,9 +1624,15 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetBinary`](@ref). """ -function fmi3SetBinary(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, valueSizes::AbstractArray{Csize_t}, value::AbstractArray{fmi3Binary}, nvalue::Csize_t) - status = fmi3SetBinary(c.fmu.cSetBinary, - c.addr, vr, nvr, valueSizes, value, nvalue) +function fmi3SetBinary( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + valueSizes::AbstractArray{Csize_t}, + value::AbstractArray{fmi3Binary}, + nvalue::Csize_t, +) + status = fmi3SetBinary(c.fmu.cSetBinary, c.addr, vr, nvr, valueSizes, value, nvalue) checkStatus(c, status) return status end @@ -1450,9 +1667,13 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3GetClock!`](@ref). """ -function fmi3GetClock!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Clock}) - status = fmi3GetClock!(c.fmu.cGetClock, - c.addr, vr, nvr, value) +function fmi3GetClock!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Clock}, +) + status = fmi3GetClock!(c.fmu.cGetClock, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -1486,9 +1707,13 @@ More detailed: - FMISpec3.0: 2.2.6.2. Getting and Setting Variable Values See also [`fmi3SetClock`](@ref). """ -function fmi3SetClock(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, value::AbstractArray{fmi3Clock}) - status = fmi3SetClock(c.fmu.cSetClock, - c.addr, vr, nvr, value) +function fmi3SetClock( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + value::AbstractArray{fmi3Clock}, +) + status = fmi3SetClock(c.fmu.cSetClock, c.addr, vr, nvr, value) checkStatus(c, status) return status end @@ -1520,8 +1745,7 @@ More detailed: See also [`fmi3GetFMUState!`](@ref). """ function fmi3GetFMUState!(c::FMU3Instance, FMUstate::Ref{fmi3FMUState}) - status = fmi3GetFMUState!(c.fmu.cGetFMUState, - c.addr, FMUstate) + status = fmi3GetFMUState!(c.fmu.cGetFMUState, c.addr, FMUstate) checkStatus(c, status) return status end @@ -1553,8 +1777,7 @@ More detailed: See also [`fmi3SetFMUState`](@ref). """ function fmi3SetFMUState(c::FMU3Instance, FMUstate::fmi3FMUState) - status = fmi3SetFMUState(c.fmu.cSetFMUState, - c.addr, FMUstate) + status = fmi3SetFMUState(c.fmu.cSetFMUState, c.addr, FMUstate) checkStatus(c, status) return status end @@ -1585,8 +1808,7 @@ More detailed: - FMISpec3.0: 2.2.6.4. Getting and Setting the Complete FMU State """ function fmi3FreeFMUState(c::FMU3Instance, FMUstate::Ref{fmi3FMUState}) - status = fmi3FreeFMUState(c.fmu.cFreeFMUState, - c.addr, FMUstate) + status = fmi3FreeFMUState(c.fmu.cFreeFMUState, c.addr, FMUstate) checkStatus(c, status) return status end @@ -1618,9 +1840,13 @@ More detailed: - FMISpec3.0: 2.2.6.4. Getting and Setting the Complete FMU State See also [`fmi3SerializedFMUStateSize!`](@ref). """ -function fmi3SerializedFMUStateSize!(c::FMU3Instance, FMUstate::fmi3FMUState, size::Ref{Csize_t}) - status = fmi3SerializedFMUStateSize!(c.fmu.cSerializedFMUStateSize, - c.addr, FMUstate, size) +function fmi3SerializedFMUStateSize!( + c::FMU3Instance, + FMUstate::fmi3FMUState, + size::Ref{Csize_t}, +) + status = + fmi3SerializedFMUStateSize!(c.fmu.cSerializedFMUStateSize, c.addr, FMUstate, size) checkStatus(c, status) return status end @@ -1653,11 +1879,21 @@ More detailed: - FMISpec3.0: 2.2.6.4. Getting and Setting the Complete FMU State See also [`fmi3SerializeFMUState!`](@ref). """ -function fmi3SerializeFMUState!(c::FMU3Instance, FMUstate::fmi3FMUState, serialzedState::AbstractArray{fmi3Byte}, size::Csize_t) - status = fmi3SerializeFMUState!(c.fmu.cSerializeFMUState, - c.addr, FMUstate, serialzedState, size) +function fmi3SerializeFMUState!( + c::FMU3Instance, + FMUstate::fmi3FMUState, + serialzedState::AbstractArray{fmi3Byte}, + size::Csize_t, +) + status = fmi3SerializeFMUState!( + c.fmu.cSerializeFMUState, + c.addr, + FMUstate, + serialzedState, + size, + ) checkStatus(c, status) - return status + return status end """ @@ -1688,9 +1924,19 @@ More detailed: - FMISpec3.0: 2.2.6.4. Getting and Setting the Complete FMU State See also [`fmi3DeSerializeFMUState!`](@ref). """ -function fmi3DeSerializeFMUState!(c::FMU3Instance, serialzedState::AbstractArray{fmi3Byte}, size::Csize_t, FMUstate::Ref{fmi3FMUState}) - status = fmi3DeSerializeFMUState!(c.fmu.cDeSerializeFMUState, - c.addr, serialzedState, size, FMUstate) +function fmi3DeSerializeFMUState!( + c::FMU3Instance, + serialzedState::AbstractArray{fmi3Byte}, + size::Csize_t, + FMUstate::Ref{fmi3FMUState}, +) + status = fmi3DeSerializeFMUState!( + c.fmu.cDeSerializeFMUState, + c.addr, + serialzedState, + size, + FMUstate, + ) checkStatus(c, status) return status end @@ -1723,9 +1969,13 @@ More detailed: - FMISpec3.0: 2.2.9. Clocks See also [`fmi3SetIntervalDecimal`](@ref). """ -function fmi3SetIntervalDecimal(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, intervals::AbstractArray{fmi3Float64}) - status = fmi3SetIntervalDecimal(c.fmu.cSetIntervalDecimal, - c.addr, vr, nvr, intervals) +function fmi3SetIntervalDecimal( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + intervals::AbstractArray{fmi3Float64}, +) + status = fmi3SetIntervalDecimal(c.fmu.cSetIntervalDecimal, c.addr, vr, nvr, intervals) checkStatus(c, status) return status end @@ -1759,9 +2009,21 @@ More detailed: - FMISpec3.0: 2.2.9. Clocks See also [`fmi3SetIntervalFraction`](@ref). """ -function fmi3SetIntervalFraction(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, intervalCounters::AbstractArray{fmi3UInt64}, resolutions::AbstractArray{fmi3UInt64}) - status = fmi3SetIntervalFraction(c.fmu.cSetIntervalFraction, - c.addr, vr, nvr, intervalCounters, resolutions) +function fmi3SetIntervalFraction( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + intervalCounters::AbstractArray{fmi3UInt64}, + resolutions::AbstractArray{fmi3UInt64}, +) + status = fmi3SetIntervalFraction( + c.fmu.cSetIntervalFraction, + c.addr, + vr, + nvr, + intervalCounters, + resolutions, + ) checkStatus(c, status) return status end @@ -1802,9 +2064,21 @@ More detailed: - FMISpec3.0: 2.2.9. Clocks See also [`fmi3GetIntervalDecimal!`](@ref). """ -function fmi3GetIntervalDecimal!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, intervals::AbstractArray{fmi3Float64}, qualifiers::fmi3IntervalQualifier) - status = fmi3GetIntervalDecimal!(c.fmu.cGetIntervalDecimal, - c.addr, vr, nvr, intervals, qualifiers) +function fmi3GetIntervalDecimal!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + intervals::AbstractArray{fmi3Float64}, + qualifiers::fmi3IntervalQualifier, +) + status = fmi3GetIntervalDecimal!( + c.fmu.cGetIntervalDecimal, + c.addr, + vr, + nvr, + intervals, + qualifiers, + ) checkStatus(c, status) return status end @@ -1846,9 +2120,23 @@ More detailed: - FMISpec3.0: 2.2.9. Clocks See also [`fmi3GetIntervalFraction!`](@ref). """ -function fmi3GetIntervalFraction!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, intervalCounters::AbstractArray{fmi3UInt64}, resolutions::AbstractArray{fmi3UInt64}, qualifiers::fmi3IntervalQualifier) - status = fmi3GetIntervalFraction!(c.fmu.cGetIntervalFraction, - c.addr, vr, nvr, intervalCounters, resolutions, qualifiers) +function fmi3GetIntervalFraction!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + intervalCounters::AbstractArray{fmi3UInt64}, + resolutions::AbstractArray{fmi3UInt64}, + qualifiers::fmi3IntervalQualifier, +) + status = fmi3GetIntervalFraction!( + c.fmu.cGetIntervalFraction, + c.addr, + vr, + nvr, + intervalCounters, + resolutions, + qualifiers, + ) checkStatus(c, status) return status end @@ -1882,9 +2170,13 @@ More detailed: - FMISpec3.0: 2.2.9. Clocks See also [`fmi3GetShiftDecimal!`](@ref). """ -function fmi3GetShiftDecimal!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, shifts::AbstractArray{fmi3Float64}) - status = fmi3GetShiftDecimal!(c.fmu.cGetShiftDecimal, - c.addr, vr, nvr, shifts) +function fmi3GetShiftDecimal!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + shifts::AbstractArray{fmi3Float64}, +) + status = fmi3GetShiftDecimal!(c.fmu.cGetShiftDecimal, c.addr, vr, nvr, shifts) checkStatus(c, status) return status end @@ -1919,9 +2211,21 @@ More detailed: - FMISpec3.0: 2.2.9. Clocks See also [`fmi3GetShiftFraction!`](@ref). """ -function fmi3GetShiftFraction!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nvr::Csize_t, shiftCounters::AbstractArray{fmi3UInt64}, resolutions::AbstractArray{fmi3UInt64}) - status = fmi3GetShiftFraction!(c.fmu.cGetShiftFraction, - c.addr, vr, nvr, shiftCounters, resolutions) +function fmi3GetShiftFraction!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nvr::Csize_t, + shiftCounters::AbstractArray{fmi3UInt64}, + resolutions::AbstractArray{fmi3UInt64}, +) + status = fmi3GetShiftFraction!( + c.fmu.cGetShiftFraction, + c.addr, + vr, + nvr, + shiftCounters, + resolutions, + ) checkStatus(c, status) return status end @@ -1956,9 +2260,17 @@ More detailed: - FMISpec3.0: 5.2.2. State: Clock Activation Mode See also [`fmi3ActivateModelPartition`](@ref). """ -function fmi3ActivateModelPartition(c::FMU3Instance, vr::fmi3ValueReference, activationTime::AbstractArray{fmi3Float64}) - status = fmi3ActivateModelPartition(c.fmu.cActivateModelPartition, - c.addr, vr, activationTime) +function fmi3ActivateModelPartition( + c::FMU3Instance, + vr::fmi3ValueReference, + activationTime::AbstractArray{fmi3Float64}, +) + status = fmi3ActivateModelPartition( + c.fmu.cActivateModelPartition, + c.addr, + vr, + activationTime, + ) checkStatus(c, status) return status end @@ -1992,9 +2304,17 @@ More detailed: - FMISpec3.0: 2.2.10. Dependencies of Variables See also [`fmi3GetNumberOfVariableDependencies!`](@ref). """ -function fmi3GetNumberOfVariableDependencies!(c::FMU3Instance, vr::fmi3ValueReference, nvr::Ref{Csize_t}) - status = fmi3GetNumberOfVariableDependencies!(c.fmu.cGetNumberOfVariableDependencies, - c.addr, vr, nvr) +function fmi3GetNumberOfVariableDependencies!( + c::FMU3Instance, + vr::fmi3ValueReference, + nvr::Ref{Csize_t}, +) + status = fmi3GetNumberOfVariableDependencies!( + c.fmu.cGetNumberOfVariableDependencies, + c.addr, + vr, + nvr, + ) checkStatus(c, status) return status end @@ -2036,10 +2356,25 @@ More detailed: - FMISpec3.0: 2.2.10. Dependencies of Variables See also [`fmi3GetVariableDependencies!`](@ref). """ -function fmi3GetVariableDependencies!(c::FMU3Instance, vr::fmi3ValueReference, elementIndiceOfDependents::AbstractArray{Csize_t}, independents::AbstractArray{fmi3ValueReference}, - elementIndiceOfInpendents::AbstractArray{Csize_t}, dependencyKind::AbstractArray{fmi3DependencyKind}, ndependencies::Csize_t) - status = fmi3GetVariableDependencies!(c.fmu.cGetVariableDependencies, - c.addr, vr, elementIndiceOfDependents, independents, elementIndiceOfInpendents, dependencyKind, ndependencies) +function fmi3GetVariableDependencies!( + c::FMU3Instance, + vr::fmi3ValueReference, + elementIndiceOfDependents::AbstractArray{Csize_t}, + independents::AbstractArray{fmi3ValueReference}, + elementIndiceOfInpendents::AbstractArray{Csize_t}, + dependencyKind::AbstractArray{fmi3DependencyKind}, + ndependencies::Csize_t, +) + status = fmi3GetVariableDependencies!( + c.fmu.cGetVariableDependencies, + c.addr, + vr, + elementIndiceOfDependents, + independents, + elementIndiceOfInpendents, + dependencyKind, + ndependencies, + ) checkStatus(c, status) return status end @@ -2101,23 +2436,37 @@ More detailed: - FMISpec3.0: 2.2.11. Getting Partial Derivatives See also [`fmi3GetDirectionalDerivative`](@ref). """ -function fmi3GetDirectionalDerivative!(c::FMU3Instance, - unknowns::AbstractArray{fmi3ValueReference}, - nUnknowns::Csize_t, - knowns::AbstractArray{fmi3ValueReference}, - nKnowns::Csize_t, - seed::AbstractArray{fmi3Float64}, - nSeed::Csize_t, - sensitivity::AbstractArray{fmi3Float64}, - nSensitivity::Csize_t) - - @assert providesDirectionalDerivatives(c.fmu) ["fmi3GetDirectionalDerivative!(...): This FMU does not support build-in directional derivatives!"] +function fmi3GetDirectionalDerivative!( + c::FMU3Instance, + unknowns::AbstractArray{fmi3ValueReference}, + nUnknowns::Csize_t, + knowns::AbstractArray{fmi3ValueReference}, + nKnowns::Csize_t, + seed::AbstractArray{fmi3Float64}, + nSeed::Csize_t, + sensitivity::AbstractArray{fmi3Float64}, + nSensitivity::Csize_t, +) + + @assert providesDirectionalDerivatives(c.fmu) [ + "fmi3GetDirectionalDerivative!(...): This FMU does not support build-in directional derivatives!", + ] - status = fmi3GetDirectionalDerivative!(c.fmu.cGetDirectionalDerivative, - c.addr, unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity) + status = fmi3GetDirectionalDerivative!( + c.fmu.cGetDirectionalDerivative, + c.addr, + unknowns, + nUnknowns, + knowns, + nKnowns, + seed, + nSeed, + sensitivity, + nSensitivity, + ) checkStatus(c, status) return status - + end # TODO not tested @@ -2177,22 +2526,36 @@ More detailed: - FMISpec3.0: 2.2.11. Getting Partial Derivatives See also [`fmi3GetAdjointDerivative!`](@ref). """ -function fmi3GetAdjointDerivative!(c::FMU3Instance, - unknowns::AbstractArray{fmi3ValueReference}, - nUnknowns::Csize_t, - knowns::AbstractArray{fmi3ValueReference}, - nKnowns::Csize_t, - seed::AbstractArray{fmi3Float64}, - nSeed::Csize_t, - sensitivity::AbstractArray{fmi3Float64}, - nSensitivity::Csize_t) - @assert providesAdjointDerivatives(c.fmu) ["fmi3GetAdjointDerivative!(...): This FMU does not support build-in adjoint derivatives!"] +function fmi3GetAdjointDerivative!( + c::FMU3Instance, + unknowns::AbstractArray{fmi3ValueReference}, + nUnknowns::Csize_t, + knowns::AbstractArray{fmi3ValueReference}, + nKnowns::Csize_t, + seed::AbstractArray{fmi3Float64}, + nSeed::Csize_t, + sensitivity::AbstractArray{fmi3Float64}, + nSensitivity::Csize_t, +) + @assert providesAdjointDerivatives(c.fmu) [ + "fmi3GetAdjointDerivative!(...): This FMU does not support build-in adjoint derivatives!", + ] - status = fmi3GetAdjointDerivative!(c.fmu.cGetAdjointDerivative, - c.addr, unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity) + status = fmi3GetAdjointDerivative!( + c.fmu.cGetAdjointDerivative, + c.addr, + unknowns, + nUnknowns, + knowns, + nKnowns, + seed, + nSeed, + sensitivity, + nSensitivity, + ) checkStatus(c, status) return status - + end """ @@ -2226,9 +2589,23 @@ More detailed: See also [`fmi3GetOutputDerivatives!`](@ref). """ -function fmi3GetOutputDerivatives!(c::FMU3Instance, vr::AbstractArray{fmi3ValueReference}, nValueReferences::Csize_t, order::AbstractArray{fmi3Int32}, values::AbstractArray{fmi3Float64}, nValues::Csize_t) - status = fmi3GetOutputDerivatives!(c.fmu.cGetOutputDerivatives, - c.addr, vr, nValueReferences, order, values, nValues) +function fmi3GetOutputDerivatives!( + c::FMU3Instance, + vr::AbstractArray{fmi3ValueReference}, + nValueReferences::Csize_t, + order::AbstractArray{fmi3Int32}, + values::AbstractArray{fmi3Float64}, + nValues::Csize_t, +) + status = fmi3GetOutputDerivatives!( + c.fmu.cGetOutputDerivatives, + c.addr, + vr, + nValueReferences, + order, + values, + nValues, + ) checkStatus(c, status) return status end @@ -2262,20 +2639,21 @@ More detailed: See also [`fmi3EnterConfigurationMode`](@ref). """ -function fmi3EnterConfigurationMode(c::FMU3Instance; soft::Bool=false) - if c.state != fmi3InstanceStateInstantiated && (c.state != fmi3InstanceStateStepMode && fmi3IsCoSimulation(c.fmu)) && (c.state != fmi3InstanceEventMode && fmi3IsModelExchange(c.fmu)) - if soft +function fmi3EnterConfigurationMode(c::FMU3Instance; soft::Bool = false) + if c.state != fmi3InstanceStateInstantiated && + (c.state != fmi3InstanceStateStepMode && fmi3IsCoSimulation(c.fmu)) && + (c.state != fmi3InstanceEventMode && fmi3IsModelExchange(c.fmu)) + if soft return fmi3StatusOK else @warn "fmi3EnterConfigurationMode(...): Called at the wrong time." end end - status = fmi3EnterConfigurationMode(c.fmu.cEnterConfigurationMode, - c.addr) + status = fmi3EnterConfigurationMode(c.fmu.cEnterConfigurationMode, c.addr) checkStatus(c, status) if status == fmi3StatusOK - if c.state == fmi3InstanceStateInstantiate + if c.state == fmi3InstanceStateInstantiate c.state = fmi3InstanceStateConfigurationMode else c.state = fmi3InstanceStateReconfigurationMode @@ -2314,20 +2692,20 @@ More detailed: See also [`fmi3ExitConfigurationMode`](@ref). """ function fmi3ExitConfigurationMode(c::FMU3Instance; soft::Bool = false) - if c.state != fmi3InstanceStateConfigurationMode && c.state != fmi3InstanceStateReconfigurationMode - if soft + if c.state != fmi3InstanceStateConfigurationMode && + c.state != fmi3InstanceStateReconfigurationMode + if soft return fmi3StatusOK else @warn "fmi3ExitConfigurationMode(...): Called at the wrong time." end end - status = fmi3ExitConfigurationMode(c.fmu.cExitConfigurationMode, - c.addr) + status = fmi3ExitConfigurationMode(c.fmu.cExitConfigurationMode, c.addr) checkStatus(c, status) if status == fmi3StatusOK if c.state == fmi3InstanceStateConfigurationMode - c.state = fmi3InstanceStateInstantiate + c.state = fmi3InstanceStateInstantiate elseif fmi3IsCoSimulation(c.fmu) c.state = fmi3InstanceStateStepMode elseif fmi3IsModelExchange(c.fmu) @@ -2369,8 +2747,11 @@ More detailed: See also [`fmi3GetNumberOfContinuousStates!`](@ref). """ function fmi3GetNumberOfContinuousStates!(c::FMU3Instance, nContinuousStates::Ref{Csize_t}) - status = fmi3GetNumberOfContinuousStates!(c.fmu.cGetNumberOfContinuousStates, - c.addr, nContinuousStates) + status = fmi3GetNumberOfContinuousStates!( + c.fmu.cGetNumberOfContinuousStates, + c.addr, + nContinuousStates, + ) checkStatus(c, status) return status end @@ -2405,8 +2786,11 @@ More detailed: See also [`fmi3GetNumberOfEventIndicators!`](@ref). """ function fmi3GetNumberOfEventIndicators!(c::FMU3Instance, nEventIndicators::Ref{Csize_t}) - status = fmi3GetNumberOfEventIndicators!(c.fmu.cGetNumberOfEventIndicators, - c.addr, nEventIndicators) + status = fmi3GetNumberOfEventIndicators!( + c.fmu.cGetNumberOfEventIndicators, + c.addr, + nEventIndicators, + ) checkStatus(c, status) return status end @@ -2441,9 +2825,17 @@ More detailed: See also [`fmi3GetContinuousStates!`](@ref). """ -function fmi3GetContinuousStates!(c::FMU3Instance, nominals::AbstractArray{fmi3Float64}, nContinuousStates::Csize_t) - status = fmi3GetContinuousStates!(c.fmu.cGetContinuousStates, - c.addr, nominals, nContinuousStates) +function fmi3GetContinuousStates!( + c::FMU3Instance, + nominals::AbstractArray{fmi3Float64}, + nContinuousStates::Csize_t, +) + status = fmi3GetContinuousStates!( + c.fmu.cGetContinuousStates, + c.addr, + nominals, + nContinuousStates, + ) checkStatus(c, status) return status end @@ -2479,9 +2871,17 @@ More detailed: See also [`fmi3GetNominalsOfContinuousStates!`](@ref). """ -function fmi3GetNominalsOfContinuousStates!(c::FMU3Instance, x_nominal::AbstractArray{fmi3Float64}, nx::Csize_t) - status = fmi3GetNominalsOfContinuousStates!(c.fmu.cGetNominalsOfContinuousStates, - c.addr, x_nominal, nx) +function fmi3GetNominalsOfContinuousStates!( + c::FMU3Instance, + x_nominal::AbstractArray{fmi3Float64}, + nx::Csize_t, +) + status = fmi3GetNominalsOfContinuousStates!( + c.fmu.cGetNominalsOfContinuousStates, + c.addr, + x_nominal, + nx, + ) checkStatus(c, status) return status end @@ -2515,8 +2915,7 @@ More detailed: See also [`fmi3EvaluateDiscreteStates`](@ref). """ function fmi3EvaluateDiscreteStates(c::FMU3Instance) - status = fmi3EvaluateDiscreteStates(c.fmu.cEvaluateDiscreteStates, - c.addr) + status = fmi3EvaluateDiscreteStates(c.fmu.cEvaluateDiscreteStates, c.addr) checkStatus(c, status) return status end @@ -2553,11 +2952,25 @@ More detailed: - FMISpec3.0: 2.3.5. State: Event Mode """ -function fmi3UpdateDiscreteStates(c::FMU3Instance, discreteStatesNeedUpdate::Ref{fmi3Boolean}, terminateSimulation::Ref{fmi3Boolean}, - nominalsOfContinuousStatesChanged::Ref{fmi3Boolean}, valuesOfContinuousStatesChanged::Ref{fmi3Boolean}, - nextEventTimeDefined::Ref{fmi3Boolean}, nextEventTime::Ref{fmi3Float64}) - status = fmi3UpdateDiscreteStates(c.fmu.cUpdateDiscreteStates, - c.addr, discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime) +function fmi3UpdateDiscreteStates( + c::FMU3Instance, + discreteStatesNeedUpdate::Ref{fmi3Boolean}, + terminateSimulation::Ref{fmi3Boolean}, + nominalsOfContinuousStatesChanged::Ref{fmi3Boolean}, + valuesOfContinuousStatesChanged::Ref{fmi3Boolean}, + nextEventTimeDefined::Ref{fmi3Boolean}, + nextEventTime::Ref{fmi3Float64}, +) + status = fmi3UpdateDiscreteStates( + c.fmu.cUpdateDiscreteStates, + c.addr, + discreteStatesNeedUpdate, + terminateSimulation, + nominalsOfContinuousStatesChanged, + valuesOfContinuousStatesChanged, + nextEventTimeDefined, + nextEventTime, + ) checkStatus(c, status) return status end @@ -2592,17 +3005,16 @@ More detailed: See also [`fmi3EnterContinuousTimeMode`](@ref). """ -function fmi3EnterContinuousTimeMode(c::FMU3Instance; soft::Bool=false) +function fmi3EnterContinuousTimeMode(c::FMU3Instance; soft::Bool = false) if c.state != fmi3InstanceStateEventMode - if soft + if soft return fmi3StatusOK else @warn "fmi3EnterContinuousTimeMode(...): Needs to be called in state `fmi3InstanceStateEventMode`." end end - status = fmi3EnterContinuousTimeMode(c.fmu.cEnterContinuousTimeMode, - c.addr) + status = fmi3EnterContinuousTimeMode(c.fmu.cEnterContinuousTimeMode, c.addr) checkStatus(c, status) if status == fmi3StatusOK c.state = fmi3InstanceStateContinuousTimeMode @@ -2641,21 +3053,20 @@ See also [`fmi3EnterStepMode`](@ref). """ function fmi3EnterStepMode(c::FMU3Instance; soft::Bool = false) if c.state != fmi3InstanceStateEventMode - if soft + if soft return fmi3StatusOK else @warn "fmi3EnterStepMode(...): Needs to be called in state `fmi3InstanceStateEventMode`." end end - status = fmi3EnterStepMode(c.fmu.cEnterStepMode, - c.addr) + status = fmi3EnterStepMode(c.fmu.cEnterStepMode, c.addr) checkStatus(c, status) if status == fmi3StatusOK c.state = fmi3InstanceStateStepMode end return status - + end """ @@ -2685,12 +3096,11 @@ More detailed: See also [`fmi3SetTime`](@ref). """ -function fmi3SetTime(c::FMU3Instance, time::fmi3Float64; track::Bool=true) - - status = fmi3SetTime(c.fmu.cSetTime, - c.addr, time + c.t_offset) +function fmi3SetTime(c::FMU3Instance, time::fmi3Float64; track::Bool = true) + + status = fmi3SetTime(c.fmu.cSetTime, c.addr, time + c.t_offset) checkStatus(c, status) - + if track if isStatusOK(c, status) c.t = time @@ -2736,11 +3146,12 @@ More detailed: See also [`fmi3SetContinuousStates`](@ref). """ -function fmi3SetContinuousStates(c::FMU3Instance, - x::AbstractArray{fmi3Float64}, - nx::Csize_t) - status = fmi3SetContinuousStates(c.fmu.cSetContinuousStates, - c.addr, x, nx) +function fmi3SetContinuousStates( + c::FMU3Instance, + x::AbstractArray{fmi3Float64}, + nx::Csize_t, +) + status = fmi3SetContinuousStates(c.fmu.cSetContinuousStates, c.addr, x, nx) checkStatus(c, status) return status end @@ -2775,11 +3186,17 @@ More detailed: See also [`fmi3GetContinuousStateDerivatives!`](@ref). """ -function fmi3GetContinuousStateDerivatives!(c::FMU3Instance, - derivatives::AbstractArray{fmi3Float64}, - nx::Csize_t) - status = fmi3GetContinuousStateDerivatives!(c.fmu.cGetContinuousStateDerivatives, - c.addr, derivatives, nx) +function fmi3GetContinuousStateDerivatives!( + c::FMU3Instance, + derivatives::AbstractArray{fmi3Float64}, + nx::Csize_t, +) + status = fmi3GetContinuousStateDerivatives!( + c.fmu.cGetContinuousStateDerivatives, + c.addr, + derivatives, + nx, + ) checkStatus(c, status) return status end @@ -2812,9 +3229,12 @@ More detailed: See also [`fmi3GetEventIndicators!`](@ref). """ -function fmi3GetEventIndicators!(c::FMU3Instance, eventIndicators::AbstractArray{fmi3Float64}, ni::Csize_t) - status = fmi3GetEventIndicators!(c.fmu.cGetEventIndicators, - c.addr, eventIndicators, ni) +function fmi3GetEventIndicators!( + c::FMU3Instance, + eventIndicators::AbstractArray{fmi3Float64}, + ni::Csize_t, +) + status = fmi3GetEventIndicators!(c.fmu.cGetEventIndicators, c.addr, eventIndicators, ni) checkStatus(c, status) return status end @@ -2852,12 +3272,19 @@ More detailed: - FMISpec3.0: 3.2.1. State: Continuous-Time Mode See also [`fmi3CompletedIntegratorStep!`](@ref). """ -function fmi3CompletedIntegratorStep!(c::FMU3Instance, - noSetFMUStatePriorToCurrentPoint::fmi3Boolean, - enterEventMode::Ref{fmi3Boolean}, - terminateSimulation::Ref{fmi3Boolean}) - status = fmi3CompletedIntegratorStep!(c.fmu.cCompletedIntegratorStep, - c.addr, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation) +function fmi3CompletedIntegratorStep!( + c::FMU3Instance, + noSetFMUStatePriorToCurrentPoint::fmi3Boolean, + enterEventMode::Ref{fmi3Boolean}, + terminateSimulation::Ref{fmi3Boolean}, +) + status = fmi3CompletedIntegratorStep!( + c.fmu.cCompletedIntegratorStep, + c.addr, + noSetFMUStatePriorToCurrentPoint, + enterEventMode, + terminateSimulation, + ) checkStatus(c, status) return status end @@ -2898,23 +3325,39 @@ More detailed: See also [`fmi3EnterEventMode`](@ref). """ -function fmi3EnterEventMode(c::FMU3Instance, stepEvent::fmi3Boolean, stateEvent::fmi3Boolean, rootsFound::AbstractArray{fmi3Int32}, nEventIndicators::Csize_t, timeEvent::fmi3Boolean; soft::Bool=false) - if c.state != fmi3InstanceStateContinuousTimeMode && c.state != fmi3InstanceStateStepMode - if soft +function fmi3EnterEventMode( + c::FMU3Instance, + stepEvent::fmi3Boolean, + stateEvent::fmi3Boolean, + rootsFound::AbstractArray{fmi3Int32}, + nEventIndicators::Csize_t, + timeEvent::fmi3Boolean; + soft::Bool = false, +) + if c.state != fmi3InstanceStateContinuousTimeMode && + c.state != fmi3InstanceStateStepMode + if soft return fmi3StatusOK else @warn "fmi3EnterEventMode(...): Called at the wrong time." end end - status = fmi3EnterEventMode(c.fmu.cEnterEventMode, - c.addr, stepEvent, stateEvent, rootsFound, nEventIndicators, timeEvent) + status = fmi3EnterEventMode( + c.fmu.cEnterEventMode, + c.addr, + stepEvent, + stateEvent, + rootsFound, + nEventIndicators, + timeEvent, + ) checkStatus(c, status) if status == fmi3StatusOK c.state = fmi3InstanceStateEventMode end return status - + end """ @@ -2952,12 +3395,31 @@ More detailed: See also [`fmi3DoStep!`](@ref). """ -function fmi3DoStep!(c::FMU3Instance, currentCommunicationPoint::fmi3Float64, communicationStepSize::fmi3Float64, noSetFMUStatePriorToCurrentPoint::fmi3Boolean, - eventEncountered::Ref{fmi3Boolean}, terminateSimulation::Ref{fmi3Boolean}, earlyReturn::Ref{fmi3Boolean}, lastSuccessfulTime::Ref{fmi3Float64}) - @assert c.fmu.cDoStep != C_NULL ["fmi3DoStep(...): This FMU does not support fmi3DoStep, probably it's a ME-FMU with no CS-support?"] - - status = fmi3DoStep!(c.fmu.cDoStep, - c.addr, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) +function fmi3DoStep!( + c::FMU3Instance, + currentCommunicationPoint::fmi3Float64, + communicationStepSize::fmi3Float64, + noSetFMUStatePriorToCurrentPoint::fmi3Boolean, + eventEncountered::Ref{fmi3Boolean}, + terminateSimulation::Ref{fmi3Boolean}, + earlyReturn::Ref{fmi3Boolean}, + lastSuccessfulTime::Ref{fmi3Float64}, +) + @assert c.fmu.cDoStep != C_NULL [ + "fmi3DoStep(...): This FMU does not support fmi3DoStep, probably it's a ME-FMU with no CS-support?", + ] + + status = fmi3DoStep!( + c.fmu.cDoStep, + c.addr, + currentCommunicationPoint, + communicationStepSize, + noSetFMUStatePriorToCurrentPoint, + eventEncountered, + terminateSimulation, + earlyReturn, + lastSuccessfulTime, + ) checkStatus(c, status) return status -end \ No newline at end of file +end diff --git a/src/FMI3/ext.jl b/src/FMI3/ext.jl index fe87dfb..371313d 100644 --- a/src/FMI3/ext.jl +++ b/src/FMI3/ext.jl @@ -32,7 +32,7 @@ Retrieves all the pointers of binary functions. See also . """ -function createFMU3(fmuPath, fmuZipPath; type::Union{Symbol, Nothing}=nothing) +function createFMU3(fmuPath, fmuZipPath; type::Union{Symbol,Nothing} = nothing) # Create uninitialized FMU fmu = FMU3() @@ -49,17 +49,21 @@ function createFMU3(fmuPath, fmuZipPath; type::Union{Symbol, Nothing}=nothing) fmu.isZeroState = (length(fmu.modelDescription.stateValueReferences) == 0) # TODO special use case? not complete, some combinations are missing - if isCoSimulation(fmu.modelDescription) && isModelExchange(fmu.modelDescription) && type==:CS + if isCoSimulation(fmu.modelDescription) && + isModelExchange(fmu.modelDescription) && + type == :CS fmu.type = fmi3TypeCoSimulation - elseif isCoSimulation(fmu.modelDescription) && isModelExchange(fmu.modelDescription) && type==:ME + elseif isCoSimulation(fmu.modelDescription) && + isModelExchange(fmu.modelDescription) && + type == :ME fmu.type = fmi3TypeModelExchange - elseif isScheduledExecution(fmu.modelDescription) && type==:SE + elseif isScheduledExecution(fmu.modelDescription) && type == :SE fmu.type = fmi3TypeScheduledExecution - elseif isCoSimulation(fmu.modelDescription) && (type===nothing || type==:CS) + elseif isCoSimulation(fmu.modelDescription) && (type === nothing || type == :CS) fmu.type = fmi3TypeCoSimulation - elseif isModelExchange(fmu.modelDescription) && (type===nothing || type==:ME) + elseif isModelExchange(fmu.modelDescription) && (type === nothing || type == :ME) fmu.type = fmi3TypeModelExchange - elseif isScheduledExecution(fmu.modelDescription) && (type === nothing || type ==:SE) + elseif isScheduledExecution(fmu.modelDescription) && (type === nothing || type == :SE) fmu.type = fmi3TypeScheduledExecution else error(unknownFMUType) @@ -77,27 +81,31 @@ function createFMU3(fmuPath, fmuZipPath; type::Union{Symbol, Nothing}=nothing) juliaArch = Sys.WORD_SIZE @assert (juliaArch == 64 || juliaArch == 32) "createFMU3(...): Unknown Julia Architecture with $(juliaArch)-bit, must be 64- or 32-bit." - + if Sys.iswindows() if juliaArch == 64 - directories = [joinpath("binaries", "win64"), joinpath("binaries","x86_64-windows")] - else - directories = [joinpath("binaries", "win32"), joinpath("binaries","i686-windows")] + directories = + [joinpath("binaries", "win64"), joinpath("binaries", "x86_64-windows")] + else + directories = + [joinpath("binaries", "win32"), joinpath("binaries", "i686-windows")] end osStr = "Windows" fmuExt = "dll" elseif Sys.islinux() if juliaArch == 64 - directories = [joinpath("binaries", "linux64"), joinpath("binaries", "x86_64-linux")] - else + directories = + [joinpath("binaries", "linux64"), joinpath("binaries", "x86_64-linux")] + else directories = [] end osStr = "Linux" fmuExt = "so" elseif Sys.isapple() if juliaArch == 64 - directories = [joinpath("binaries", "darwin64"), joinpath("binaries", "x86_64-darwin")] - else + directories = + [joinpath("binaries", "darwin64"), joinpath("binaries", "x86_64-darwin")] + else directories = [] end osStr = "Mac" @@ -119,17 +127,17 @@ function createFMU3(fmuPath, fmuZipPath; type::Union{Symbol, Nothing}=nothing) # make URI ressource location tmpResourceLocation = string("file:///", fmu.path) tmpResourceLocation = joinpath(tmpResourceLocation, "resources") - fmu.fmuResourceLocation = replace(tmpResourceLocation, "\\" => "/") + fmu.fmuResourceLocation = replace(tmpResourceLocation, "\\" => "/") @info "createFMU3(...): FMU resources location is `$(fmu.fmuResourceLocation)`" - if isCoSimulation(fmu) && isModelExchange(fmu) + if isCoSimulation(fmu) && isModelExchange(fmu) @info "createFMU3(...): FMU supports both CS and ME, using CS as default if nothing specified." # TODO ScheduledExecution end fmu.binaryPath = pathToBinary loadPointers(fmu) - + return fmu end @@ -148,104 +156,112 @@ function loadPointers(fmu::FMU3) cd(lastDirectory) # retrieve functions - fmu.cInstantiateModelExchange = dlsym(fmu.libHandle, :fmi3InstantiateModelExchange) - fmu.cInstantiateCoSimulation = dlsym(fmu.libHandle, :fmi3InstantiateCoSimulation) - fmu.cInstantiateScheduledExecution = dlsym(fmu.libHandle, :fmi3InstantiateScheduledExecution) - fmu.cGetVersion = dlsym(fmu.libHandle, :fmi3GetVersion) - fmu.cFreeInstance = dlsym(fmu.libHandle, :fmi3FreeInstance) - fmu.cSetDebugLogging = dlsym(fmu.libHandle, :fmi3SetDebugLogging) - fmu.cEnterConfigurationMode = dlsym(fmu.libHandle, :fmi3EnterConfigurationMode) - fmu.cExitConfigurationMode = dlsym(fmu.libHandle, :fmi3ExitConfigurationMode) - fmu.cEnterInitializationMode = dlsym(fmu.libHandle, :fmi3EnterInitializationMode) - fmu.cExitInitializationMode = dlsym(fmu.libHandle, :fmi3ExitInitializationMode) - fmu.cTerminate = dlsym(fmu.libHandle, :fmi3Terminate) - fmu.cReset = dlsym(fmu.libHandle, :fmi3Reset) - fmu.cEvaluateDiscreteStates = dlsym(fmu.libHandle, :fmi3EvaluateDiscreteStates) - fmu.cGetNumberOfVariableDependencies = dlsym(fmu.libHandle, :fmi3GetNumberOfVariableDependencies) - fmu.cGetVariableDependencies = dlsym(fmu.libHandle, :fmi3GetVariableDependencies) - - fmu.cGetFloat32 = dlsym(fmu.libHandle, :fmi3GetFloat32) - fmu.cSetFloat32 = dlsym(fmu.libHandle, :fmi3SetFloat32) - fmu.cGetFloat64 = dlsym(fmu.libHandle, :fmi3GetFloat64) - fmu.cSetFloat64 = dlsym(fmu.libHandle, :fmi3SetFloat64) - fmu.cGetInt8 = dlsym(fmu.libHandle, :fmi3GetInt8) - fmu.cSetInt8 = dlsym(fmu.libHandle, :fmi3SetInt8) - fmu.cGetUInt8 = dlsym(fmu.libHandle, :fmi3GetUInt8) - fmu.cSetUInt8 = dlsym(fmu.libHandle, :fmi3SetUInt8) - fmu.cGetInt16 = dlsym(fmu.libHandle, :fmi3GetInt16) - fmu.cSetInt16 = dlsym(fmu.libHandle, :fmi3SetInt16) - fmu.cGetUInt16 = dlsym(fmu.libHandle, :fmi3GetUInt16) - fmu.cSetUInt16 = dlsym(fmu.libHandle, :fmi3SetUInt16) - fmu.cGetInt32 = dlsym(fmu.libHandle, :fmi3GetInt32) - fmu.cSetInt32 = dlsym(fmu.libHandle, :fmi3SetInt32) - fmu.cGetUInt32 = dlsym(fmu.libHandle, :fmi3GetUInt32) - fmu.cSetUInt32 = dlsym(fmu.libHandle, :fmi3SetUInt32) - fmu.cGetInt64 = dlsym(fmu.libHandle, :fmi3GetInt64) - fmu.cSetInt64 = dlsym(fmu.libHandle, :fmi3SetInt64) - fmu.cGetUInt64 = dlsym(fmu.libHandle, :fmi3GetUInt64) - fmu.cSetUInt64 = dlsym(fmu.libHandle, :fmi3SetUInt64) - fmu.cGetBoolean = dlsym(fmu.libHandle, :fmi3GetBoolean) - fmu.cSetBoolean = dlsym(fmu.libHandle, :fmi3SetBoolean) - - fmu.cGetString = dlsym_opt(fmu, fmu.libHandle, :fmi3GetString) - fmu.cSetString = dlsym_opt(fmu, fmu.libHandle, :fmi3SetString) - fmu.cGetBinary = dlsym_opt(fmu, fmu.libHandle, :fmi3GetBinary) - fmu.cSetBinary = dlsym_opt(fmu, fmu.libHandle, :fmi3SetBinary) + fmu.cInstantiateModelExchange = dlsym(fmu.libHandle, :fmi3InstantiateModelExchange) + fmu.cInstantiateCoSimulation = dlsym(fmu.libHandle, :fmi3InstantiateCoSimulation) + fmu.cInstantiateScheduledExecution = + dlsym(fmu.libHandle, :fmi3InstantiateScheduledExecution) + fmu.cGetVersion = dlsym(fmu.libHandle, :fmi3GetVersion) + fmu.cFreeInstance = dlsym(fmu.libHandle, :fmi3FreeInstance) + fmu.cSetDebugLogging = dlsym(fmu.libHandle, :fmi3SetDebugLogging) + fmu.cEnterConfigurationMode = dlsym(fmu.libHandle, :fmi3EnterConfigurationMode) + fmu.cExitConfigurationMode = dlsym(fmu.libHandle, :fmi3ExitConfigurationMode) + fmu.cEnterInitializationMode = dlsym(fmu.libHandle, :fmi3EnterInitializationMode) + fmu.cExitInitializationMode = dlsym(fmu.libHandle, :fmi3ExitInitializationMode) + fmu.cTerminate = dlsym(fmu.libHandle, :fmi3Terminate) + fmu.cReset = dlsym(fmu.libHandle, :fmi3Reset) + fmu.cEvaluateDiscreteStates = dlsym(fmu.libHandle, :fmi3EvaluateDiscreteStates) + fmu.cGetNumberOfVariableDependencies = + dlsym(fmu.libHandle, :fmi3GetNumberOfVariableDependencies) + fmu.cGetVariableDependencies = dlsym(fmu.libHandle, :fmi3GetVariableDependencies) + + fmu.cGetFloat32 = dlsym(fmu.libHandle, :fmi3GetFloat32) + fmu.cSetFloat32 = dlsym(fmu.libHandle, :fmi3SetFloat32) + fmu.cGetFloat64 = dlsym(fmu.libHandle, :fmi3GetFloat64) + fmu.cSetFloat64 = dlsym(fmu.libHandle, :fmi3SetFloat64) + fmu.cGetInt8 = dlsym(fmu.libHandle, :fmi3GetInt8) + fmu.cSetInt8 = dlsym(fmu.libHandle, :fmi3SetInt8) + fmu.cGetUInt8 = dlsym(fmu.libHandle, :fmi3GetUInt8) + fmu.cSetUInt8 = dlsym(fmu.libHandle, :fmi3SetUInt8) + fmu.cGetInt16 = dlsym(fmu.libHandle, :fmi3GetInt16) + fmu.cSetInt16 = dlsym(fmu.libHandle, :fmi3SetInt16) + fmu.cGetUInt16 = dlsym(fmu.libHandle, :fmi3GetUInt16) + fmu.cSetUInt16 = dlsym(fmu.libHandle, :fmi3SetUInt16) + fmu.cGetInt32 = dlsym(fmu.libHandle, :fmi3GetInt32) + fmu.cSetInt32 = dlsym(fmu.libHandle, :fmi3SetInt32) + fmu.cGetUInt32 = dlsym(fmu.libHandle, :fmi3GetUInt32) + fmu.cSetUInt32 = dlsym(fmu.libHandle, :fmi3SetUInt32) + fmu.cGetInt64 = dlsym(fmu.libHandle, :fmi3GetInt64) + fmu.cSetInt64 = dlsym(fmu.libHandle, :fmi3SetInt64) + fmu.cGetUInt64 = dlsym(fmu.libHandle, :fmi3GetUInt64) + fmu.cSetUInt64 = dlsym(fmu.libHandle, :fmi3SetUInt64) + fmu.cGetBoolean = dlsym(fmu.libHandle, :fmi3GetBoolean) + fmu.cSetBoolean = dlsym(fmu.libHandle, :fmi3SetBoolean) + + fmu.cGetString = dlsym_opt(fmu, fmu.libHandle, :fmi3GetString) + fmu.cSetString = dlsym_opt(fmu, fmu.libHandle, :fmi3SetString) + fmu.cGetBinary = dlsym_opt(fmu, fmu.libHandle, :fmi3GetBinary) + fmu.cSetBinary = dlsym_opt(fmu, fmu.libHandle, :fmi3SetBinary) if canGetSetFMUState(fmu) - fmu.cGetFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3GetFMUState) - fmu.cSetFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3SetFMUState) - fmu.cFreeFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3FreeFMUState) + fmu.cGetFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3GetFMUState) + fmu.cSetFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3SetFMUState) + fmu.cFreeFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3FreeFMUState) end if canSerializeFMUState(fmu) - fmu.cSerializedFMUStateSize = dlsym_opt(fmu, fmu.libHandle, :fmi3SerializedFMUStateSize) - fmu.cSerializeFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3SerializeFMUState) - fmu.cDeSerializeFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3DeserializeFMUState) + fmu.cSerializedFMUStateSize = + dlsym_opt(fmu, fmu.libHandle, :fmi3SerializedFMUStateSize) + fmu.cSerializeFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3SerializeFMUState) + fmu.cDeSerializeFMUState = dlsym_opt(fmu, fmu.libHandle, :fmi3DeserializeFMUState) end if providesDirectionalDerivatives(fmu) - fmu.cGetDirectionalDerivative = dlsym_opt(fmu, fmu.libHandle, :fmi3GetDirectionalDerivative) + fmu.cGetDirectionalDerivative = + dlsym_opt(fmu, fmu.libHandle, :fmi3GetDirectionalDerivative) end if providesAdjointDerivatives(fmu) - fmu.cGetAdjointDerivative = dlsym_opt(fmu, fmu.libHandle, :fmi3GetAdjointDerivative) + fmu.cGetAdjointDerivative = dlsym_opt(fmu, fmu.libHandle, :fmi3GetAdjointDerivative) end # CS specific function calls if isCoSimulation(fmu) - fmu.cGetOutputDerivatives = dlsym(fmu.libHandle, :fmi3GetOutputDerivatives) - fmu.cEnterStepMode = dlsym(fmu.libHandle, :fmi3EnterStepMode) - fmu.cDoStep = dlsym(fmu.libHandle, :fmi3DoStep) + fmu.cGetOutputDerivatives = dlsym(fmu.libHandle, :fmi3GetOutputDerivatives) + fmu.cEnterStepMode = dlsym(fmu.libHandle, :fmi3EnterStepMode) + fmu.cDoStep = dlsym(fmu.libHandle, :fmi3DoStep) end # ME specific function calls if isModelExchange(fmu) - fmu.cGetNumberOfContinuousStates = dlsym(fmu.libHandle, :fmi3GetNumberOfContinuousStates) - fmu.cGetNumberOfEventIndicators = dlsym(fmu.libHandle, :fmi3GetNumberOfEventIndicators) - fmu.cGetContinuousStates = dlsym(fmu.libHandle, :fmi3GetContinuousStates) - fmu.cGetNominalsOfContinuousStates = dlsym(fmu.libHandle, :fmi3GetNominalsOfContinuousStates) - fmu.cEnterContinuousTimeMode = dlsym(fmu.libHandle, :fmi3EnterContinuousTimeMode) - fmu.cSetTime = dlsym(fmu.libHandle, :fmi3SetTime) - fmu.cSetContinuousStates = dlsym(fmu.libHandle, :fmi3SetContinuousStates) - fmu.cGetContinuousStateDerivatives = dlsym(fmu.libHandle, :fmi3GetContinuousStateDerivatives) - fmu.cGetEventIndicators = dlsym(fmu.libHandle, :fmi3GetEventIndicators) - fmu.cCompletedIntegratorStep = dlsym(fmu.libHandle, :fmi3CompletedIntegratorStep) - fmu.cEnterEventMode = dlsym(fmu.libHandle, :fmi3EnterEventMode) - fmu.cUpdateDiscreteStates = dlsym(fmu.libHandle, :fmi3UpdateDiscreteStates) + fmu.cGetNumberOfContinuousStates = + dlsym(fmu.libHandle, :fmi3GetNumberOfContinuousStates) + fmu.cGetNumberOfEventIndicators = + dlsym(fmu.libHandle, :fmi3GetNumberOfEventIndicators) + fmu.cGetContinuousStates = dlsym(fmu.libHandle, :fmi3GetContinuousStates) + fmu.cGetNominalsOfContinuousStates = + dlsym(fmu.libHandle, :fmi3GetNominalsOfContinuousStates) + fmu.cEnterContinuousTimeMode = dlsym(fmu.libHandle, :fmi3EnterContinuousTimeMode) + fmu.cSetTime = dlsym(fmu.libHandle, :fmi3SetTime) + fmu.cSetContinuousStates = dlsym(fmu.libHandle, :fmi3SetContinuousStates) + fmu.cGetContinuousStateDerivatives = + dlsym(fmu.libHandle, :fmi3GetContinuousStateDerivatives) + fmu.cGetEventIndicators = dlsym(fmu.libHandle, :fmi3GetEventIndicators) + fmu.cCompletedIntegratorStep = dlsym(fmu.libHandle, :fmi3CompletedIntegratorStep) + fmu.cEnterEventMode = dlsym(fmu.libHandle, :fmi3EnterEventMode) + fmu.cUpdateDiscreteStates = dlsym(fmu.libHandle, :fmi3UpdateDiscreteStates) end if isScheduledExecution(fmu) - fmu.cSetIntervalDecimal = dlsym(fmu.libHandle, :fmi3SetIntervalDecimal) - fmu.cSetIntervalFraction = dlsym(fmu.libHandle, :fmi3SetIntervalFraction) - fmu.cGetIntervalDecimal = dlsym(fmu.libHandle, :fmi3GetIntervalDecimal) - fmu.cGetIntervalFraction = dlsym(fmu.libHandle, :fmi3GetIntervalFraction) - fmu.cGetShiftDecimal = dlsym(fmu.libHandle, :fmi3GetShiftDecimal) - fmu.cGetShiftFraction = dlsym(fmu.libHandle, :fmi3GetShiftFraction) - fmu.cActivateModelPartition = dlsym(fmu.libHandle, :fmi3ActivateModelPartition) + fmu.cSetIntervalDecimal = dlsym(fmu.libHandle, :fmi3SetIntervalDecimal) + fmu.cSetIntervalFraction = dlsym(fmu.libHandle, :fmi3SetIntervalFraction) + fmu.cGetIntervalDecimal = dlsym(fmu.libHandle, :fmi3GetIntervalDecimal) + fmu.cGetIntervalFraction = dlsym(fmu.libHandle, :fmi3GetIntervalFraction) + fmu.cGetShiftDecimal = dlsym(fmu.libHandle, :fmi3GetShiftDecimal) + fmu.cGetShiftFraction = dlsym(fmu.libHandle, :fmi3GetShiftFraction) + fmu.cActivateModelPartition = dlsym(fmu.libHandle, :fmi3ActivateModelPartition) end end function unloadPointers(fmu::FMU3) # [TODO]: Write a macro for that. -end \ No newline at end of file +end diff --git a/src/FMI3/int.jl b/src/FMI3/int.jl index 27fe49e..87dbf16 100644 --- a/src/FMI3/int.jl +++ b/src/FMI3/int.jl @@ -36,8 +36,20 @@ Create a new modelExchange instance of the given fmu, adds a logger if `logginOn See also [`fmi3InstantiateModelExchange`](#@ref). """ -function fmi3InstantiateModelExchange!(fmu::FMU3; instanceName::String = fmu.modelName, type::fmi3Type = fmu.type, pushInstances::Bool = true, visible::Bool = false, loggingOn::Bool = fmu.executionConfig.loggingOn, externalCallBacks::Bool = fmu.executionConfig.externalCallbacks, - logStatusOK::Bool=true, logStatusWarning::Bool=true, logStatusDiscard::Bool=true, logStatusError::Bool=true, logStatusFatal::Bool=true) +function fmi3InstantiateModelExchange!( + fmu::FMU3; + instanceName::String = fmu.modelName, + type::fmi3Type = fmu.type, + pushInstances::Bool = true, + visible::Bool = false, + loggingOn::Bool = fmu.executionConfig.loggingOn, + externalCallBacks::Bool = fmu.executionConfig.externalCallbacks, + logStatusOK::Bool = true, + logStatusWarning::Bool = true, + logStatusDiscard::Bool = true, + logStatusError::Bool = true, + logStatusFatal::Bool = true, +) instEnv = FMU3InstanceEnvironment() instEnv.logStatusOK = logStatusOK @@ -46,13 +58,26 @@ function fmi3InstantiateModelExchange!(fmu::FMU3; instanceName::String = fmu.mod instEnv.logStatusError = logStatusError instEnv.logStatusFatal = logStatusFatal - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{FMU3InstanceEnvironment}, Cuint, Ptr{Cchar}, Ptr{Cchar})) + ptrLogger = @cfunction( + fmi3CallbackLogger, + Cvoid, + (Ptr{FMU3InstanceEnvironment}, Cuint, Ptr{Cchar}, Ptr{Cchar}) + ) ptrInstanceEnvironment = Ptr{Cvoid}(pointer_from_objref(instEnv)) - + instantiationTokenStr = "$(fmu.modelDescription.instantiationToken)" - - addr = fmi3InstantiateModelExchange(fmu.cInstantiateModelExchange, pointer(instanceName), pointer(instantiationTokenStr), pointer(fmu.fmuResourceLocation), fmi3Boolean(visible), fmi3Boolean(loggingOn), ptrInstanceEnvironment, ptrLogger) + + addr = fmi3InstantiateModelExchange( + fmu.cInstantiateModelExchange, + pointer(instanceName), + pointer(instantiationTokenStr), + pointer(fmu.fmuResourceLocation), + fmi3Boolean(visible), + fmi3Boolean(loggingOn), + ptrInstanceEnvironment, + ptrLogger, + ) if addr == Ptr{Cvoid}(C_NULL) @error "fmi3InstantiateModelExchange!(...): Instantiation failed!" @@ -65,22 +90,22 @@ function fmi3InstantiateModelExchange!(fmu::FMU3; instanceName::String = fmu.mod for c in fmu.instances if c.addr == addr instance = c - break + break end end if instance !== nothing @info "fmi3InstantiateModelExchange!(...): This component was already registered. This may be because you created the FMU by yourself with FMIExport.jl." else - + instance = FMU3Instance(addr, fmu) instance.instanceEnvironment = instEnv instance.instanceName = instanceName - instance.z_prev = zeros(fmi3Float64, fmi3GetNumberOfEventIndicators(instance)) - instance.rootsFound = zeros(fmi3Int32, fmi3GetNumberOfEventIndicators(instance)) - instance.stateEvent = fmi3False - instance.timeEvent = fmi3False - instance.stepEvent = fmi3False + instance.z_prev = zeros(fmi3Float64, fmi3GetNumberOfEventIndicators(instance)) + instance.rootsFound = zeros(fmi3Int32, fmi3GetNumberOfEventIndicators(instance)) + instance.stateEvent = fmi3False + instance.timeEvent = fmi3False + instance.stepEvent = fmi3False instance.type = fmi3TypeModelExchange if pushInstances @@ -130,8 +155,22 @@ Create a new coSimulation instance of the given fmu, adds a logger if `logginOn See also [`fmi3InstantiateCoSimulation`](#@ref). """ -function fmi3InstantiateCoSimulation!(fmu::FMU3; instanceName::String=fmu.modelName, type::fmi3Type=fmu.type, pushInstances::Bool = true, visible::Bool = false, loggingOn::Bool = fmu.executionConfig.loggingOn, externalCallbacks::Bool = fmu.executionConfig.externalCallbacks, - eventModeUsed::Bool = false, ptrIntermediateUpdate=nothing, logStatusOK::Bool=true, logStatusWarning::Bool=true, logStatusDiscard::Bool=true, logStatusError::Bool=true, logStatusFatal::Bool=true) +function fmi3InstantiateCoSimulation!( + fmu::FMU3; + instanceName::String = fmu.modelName, + type::fmi3Type = fmu.type, + pushInstances::Bool = true, + visible::Bool = false, + loggingOn::Bool = fmu.executionConfig.loggingOn, + externalCallbacks::Bool = fmu.executionConfig.externalCallbacks, + eventModeUsed::Bool = false, + ptrIntermediateUpdate = nothing, + logStatusOK::Bool = true, + logStatusWarning::Bool = true, + logStatusDiscard::Bool = true, + logStatusError::Bool = true, + logStatusFatal::Bool = true, +) instEnv = FMU3InstanceEnvironment() instEnv.logStatusOK = logStatusOK instEnv.logStatusWarning = logStatusWarning @@ -139,10 +178,27 @@ function fmi3InstantiateCoSimulation!(fmu::FMU3; instanceName::String=fmu.modelN instEnv.logStatusError = logStatusError instEnv.logStatusFatal = logStatusFatal - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{FMU3InstanceEnvironment}, Cuint, Ptr{Cchar}, Ptr{Cchar})) - + ptrLogger = @cfunction( + fmi3CallbackLogger, + Cvoid, + (Ptr{FMU3InstanceEnvironment}, Cuint, Ptr{Cchar}, Ptr{Cchar}) + ) + if ptrIntermediateUpdate === nothing - ptrIntermediateUpdate = @cfunction(fmi3CallbackIntermediateUpdate, Cvoid, (Ptr{Cvoid}, fmi3Float64, fmi3Boolean, fmi3Boolean, fmi3Boolean, fmi3Boolean, Ptr{fmi3Boolean}, Ptr{fmi3Float64})) + ptrIntermediateUpdate = @cfunction( + fmi3CallbackIntermediateUpdate, + Cvoid, + ( + Ptr{Cvoid}, + fmi3Float64, + fmi3Boolean, + fmi3Boolean, + fmi3Boolean, + fmi3Boolean, + Ptr{fmi3Boolean}, + Ptr{fmi3Float64}, + ) + ) end if fmu.modelDescription.coSimulation.hasEventMode !== nothing mode = eventModeUsed @@ -150,11 +206,27 @@ function fmi3InstantiateCoSimulation!(fmu::FMU3; instanceName::String=fmu.modelN mode = false end ptrInstanceEnvironment = Ptr{Cvoid}(pointer_from_objref(instEnv)) - + instantiationTokenStr = "$(fmu.modelDescription.instantiationToken)" - - addr = fmi3InstantiateCoSimulation(fmu.cInstantiateCoSimulation, pointer(instanceName), pointer(instantiationTokenStr), pointer(fmu.fmuResourceLocation), fmi3Boolean(visible), fmi3Boolean(loggingOn), - fmi3Boolean(mode), fmi3Boolean(fmu.modelDescription.coSimulation.canReturnEarlyAfterIntermediateUpdate !== nothing), fmu.modelDescription.intermediateUpdateValueReferences, Csize_t(length(fmu.modelDescription.intermediateUpdateValueReferences)), ptrInstanceEnvironment, ptrLogger, ptrIntermediateUpdate) + + addr = fmi3InstantiateCoSimulation( + fmu.cInstantiateCoSimulation, + pointer(instanceName), + pointer(instantiationTokenStr), + pointer(fmu.fmuResourceLocation), + fmi3Boolean(visible), + fmi3Boolean(loggingOn), + fmi3Boolean(mode), + fmi3Boolean( + fmu.modelDescription.coSimulation.canReturnEarlyAfterIntermediateUpdate !== + nothing, + ), + fmu.modelDescription.intermediateUpdateValueReferences, + Csize_t(length(fmu.modelDescription.intermediateUpdateValueReferences)), + ptrInstanceEnvironment, + ptrLogger, + ptrIntermediateUpdate, + ) if addr == Ptr{Cvoid}(C_NULL) @error "fmi3InstantiateCoSimulation!(...): Instantiation failed!" @@ -167,7 +239,7 @@ function fmi3InstantiateCoSimulation!(fmu::FMU3; instanceName::String=fmu.modelN for c in fmu.instances if c.addr == addr instance = c - break + break end end @@ -182,7 +254,7 @@ function fmi3InstantiateCoSimulation!(fmu::FMU3; instanceName::String=fmu.modelN if pushInstances push!(fmu.instances, instance) end - + fmu.threadInstances[Threads.threadid()] = instance end @@ -227,8 +299,22 @@ Create a new ScheduledExecution instance of the given fmu, adds a logger if `log See also [`fmi3InstantiateScheduledExecution`](#@ref). """ -function fmi3InstantiateScheduledExecution!(fmu::FMU3; ptrlockPreemption::Ptr{Cvoid}, ptrunlockPreemption::Ptr{Cvoid}, instanceName::String=fmu.modelName, type::fmi3Type=fmu.type, pushInstances::Bool = true, visible::Bool = false, loggingOn::Bool = fmu.executionConfig.loggingOn, externalCallbacks::Bool = fmu.executionConfig.externalCallbacks, - logStatusOK::Bool=true, logStatusWarning::Bool=true, logStatusDiscard::Bool=true, logStatusError::Bool=true, logStatusFatal::Bool=true) +function fmi3InstantiateScheduledExecution!( + fmu::FMU3; + ptrlockPreemption::Ptr{Cvoid}, + ptrunlockPreemption::Ptr{Cvoid}, + instanceName::String = fmu.modelName, + type::fmi3Type = fmu.type, + pushInstances::Bool = true, + visible::Bool = false, + loggingOn::Bool = fmu.executionConfig.loggingOn, + externalCallbacks::Bool = fmu.executionConfig.externalCallbacks, + logStatusOK::Bool = true, + logStatusWarning::Bool = true, + logStatusDiscard::Bool = true, + logStatusError::Bool = true, + logStatusFatal::Bool = true, +) instEnv = FMU3InstanceEnvironment() instEnv.logStatusOK = logStatusOK @@ -237,14 +323,30 @@ function fmi3InstantiateScheduledExecution!(fmu::FMU3; ptrlockPreemption::Ptr{Cv instEnv.logStatusError = logStatusError instEnv.logStatusFatal = logStatusFatal - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{FMU3InstanceEnvironment}, Cuint, Ptr{Cchar}, Ptr{Cchar})) - ptrClockUpdate = @cfunction(fmi3CallbackClockUpdate, Cvoid, (Ptr{Cvoid}, )) + ptrLogger = @cfunction( + fmi3CallbackLogger, + Cvoid, + (Ptr{FMU3InstanceEnvironment}, Cuint, Ptr{Cchar}, Ptr{Cchar}) + ) + ptrClockUpdate = @cfunction(fmi3CallbackClockUpdate, Cvoid, (Ptr{Cvoid},)) ptrInstanceEnvironment = Ptr{FMU3InstanceEnvironment}(pointer_from_objref(instEnv)) - + instantiationTokenStr = "$(fmu.modelDescription.instantiationToken)" - - addr = fmi3InstantiateScheduledExecution(fmu.cInstantiateScheduledExecution, pointer(instanceName), pointer(instantiationTokenStr), pointer(fmu.fmuResourceLocation), fmi3Boolean(visible), fmi3Boolean(loggingOn), ptrInstanceEnvironment, ptrLogger, ptrClockUpdate, ptrlockPreemption, ptrunlockPreemption) + + addr = fmi3InstantiateScheduledExecution( + fmu.cInstantiateScheduledExecution, + pointer(instanceName), + pointer(instantiationTokenStr), + pointer(fmu.fmuResourceLocation), + fmi3Boolean(visible), + fmi3Boolean(loggingOn), + ptrInstanceEnvironment, + ptrLogger, + ptrClockUpdate, + ptrlockPreemption, + ptrunlockPreemption, + ) if addr == Ptr{Cvoid}(C_NULL) @error "fmi3InstantiateScheduledExecution!(...): Instantiation failed!" @@ -257,7 +359,7 @@ function fmi3InstantiateScheduledExecution!(fmu::FMU3; ptrlockPreemption::Ptr{Cv for c in fmu.instances if c.addr == addr instance = c - break + break end end @@ -272,7 +374,7 @@ function fmi3InstantiateScheduledExecution!(fmu::FMU3; ptrlockPreemption::Ptr{Cv if pushInstances push!(fmu.instances, instance) end - + fmu.threadInstances[Threads.threadid()] = instance end @@ -308,12 +410,13 @@ function fmi3FreeInstance!(c::FMU3Instance; popInstance::Bool = true) addr = c.addr if popInstance - ind = findall(x->x.addr==c.addr, c.fmu.instances) + ind = findall(x -> x.addr == c.addr, c.fmu.instances) @assert length(ind) == 1 "fmi3FreeInstance!(...): Freeing $(length(ind)) instances with one call, this is not allowed." deleteat!(c.fmu.instances, ind) for key in keys(c.fmu.threadInstances) - if !isnothing(c.fmu.threadInstances[key]) && c.fmu.threadInstances[key].addr == addr + if !isnothing(c.fmu.threadInstances[key]) && + c.fmu.threadInstances[key].addr == addr c.fmu.threadInstances[key] = nothing end end @@ -387,7 +490,12 @@ More detailed: See also [`fmi3EnterInitializationMode`](@ref). """ -function fmi3EnterInitializationMode(c::FMU3Instance, startTime::Union{Real, Nothing} = nothing, stopTime::Union{Real, Nothing} = nothing; tolerance::Union{Real, Nothing} = nothing) +function fmi3EnterInitializationMode( + c::FMU3Instance, + startTime::Union{Real,Nothing} = nothing, + stopTime::Union{Real,Nothing} = nothing; + tolerance::Union{Real,Nothing} = nothing, +) if c.state != fmi3InstanceStateInstantiated @warn "fmi3EnterInitializationMode(...): Needs to be called in state `fmi3IntanceStateInstantiated`." end @@ -410,7 +518,15 @@ function fmi3EnterInitializationMode(c::FMU3Instance, startTime::Union{Real, Not stopTime = 0.0 # dummy value, will be ignored end - status = fmi3EnterInitializationMode(c.fmu.cEnterInitializationMode, c.addr, fmi3Boolean(toleranceDefined), fmi3Float64(tolerance), fmi3Float64(startTime), fmi3Boolean(stopTimeDefined), fmi3Float64(stopTime)) + status = fmi3EnterInitializationMode( + c.fmu.cEnterInitializationMode, + c.addr, + fmi3Boolean(toleranceDefined), + fmi3Float64(tolerance), + fmi3Float64(startTime), + fmi3Boolean(stopTimeDefined), + fmi3Float64(stopTime), + ) checkStatus(c, status) if status == fmi3StatusOK c.state = fmi3InstanceStateInitializationMode @@ -486,7 +602,11 @@ More detailed: See also [`fmi3GetFloat32!`](@ref). """ -function fmi3GetFloat32!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Float32}) +function fmi3GetFloat32!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Float32}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetFloat32!(...): `vr` and `values` need to be the same length." @@ -527,7 +647,11 @@ More detailed: See also [`fmi3SetFloat32`](@ref). """ -function fmi3SetFloat32(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3Float32}, fmi3Float32}) +function fmi3SetFloat32( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3Float32},fmi3Float32}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -605,7 +729,11 @@ More detailed: See also [`fmi3GetFloat64!`](@ref). """ -function fmi3GetFloat64!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Float64}) +function fmi3GetFloat64!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Float64}, +) vr = prepareValueReference(c, vr) @@ -647,7 +775,12 @@ More detailed: See also [`fmi3SetFloat64`](@ref). """ -function fmi3SetFloat64(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3Float64}, fmi3Float64}; kwargs...) +function fmi3SetFloat64( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3Float64},fmi3Float64}; + kwargs..., +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -725,7 +858,11 @@ More detailed: See also [`fmi3GetInt8!`](@ref). """ -function fmi3GetInt8!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Int8}) +function fmi3GetInt8!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Int8}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetInt8!(...): `vr` and `values` need to be the same length." @@ -766,7 +903,11 @@ More detailed: See also [`fmi3SetInt8`](@ref). """ -function fmi3SetInt8(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3Int8}, fmi3Int8}) +function fmi3SetInt8( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3Int8},fmi3Int8}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -844,7 +985,11 @@ More detailed: See also [`fmi3GetUInt8!`](@ref). """ -function fmi3GetUInt8!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3UInt8}) +function fmi3GetUInt8!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3UInt8}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetUInt8!(...): `vr` and `values` need to be the same length." @@ -885,7 +1030,11 @@ More detailed: See also [`fmi3SetUInt8`](@ref). """ -function fmi3SetUInt8(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3UInt8}, fmi3UInt8}) +function fmi3SetUInt8( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3UInt8},fmi3UInt8}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -963,7 +1112,11 @@ More detailed: See also [`fmi3GetInt16!`](@ref). """ -function fmi3GetInt16!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Int16}) +function fmi3GetInt16!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Int16}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetInt16!(...): `vr` and `values` need to be the same length." @@ -1004,7 +1157,11 @@ More detailed: See also [`fmi3SetInt16`](@ref). """ -function fmi3SetInt16(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3Int16}, fmi3Int16}) +function fmi3SetInt16( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3Int16},fmi3Int16}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1082,7 +1239,11 @@ More detailed: See also [`fmi3GetUInt16!`](@ref). """ -function fmi3GetUInt16!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3UInt16}) +function fmi3GetUInt16!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3UInt16}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetUInt16!(...): `vr` and `values` need to be the same length." @@ -1123,7 +1284,11 @@ More detailed: See also [`fmi3SetUInt16`](@ref). """ -function fmi3SetUInt16(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3UInt16}, fmi3UInt16}) +function fmi3SetUInt16( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3UInt16},fmi3UInt16}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1201,7 +1366,11 @@ More detailed: See also [`fmi3GetInt32!`](@ref). """ -function fmi3GetInt32!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Int32}) +function fmi3GetInt32!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Int32}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetInt32!(...): `vr` and `values` need to be the same length." @@ -1242,7 +1411,11 @@ More detailed: See also [`fmi3SetInt32`](@ref). """ -function fmi3SetInt32(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3Int32}, fmi3Int32}) +function fmi3SetInt32( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3Int32},fmi3Int32}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1320,7 +1493,11 @@ More detailed: See also [`fmi3GetUInt32!`](@ref). """ -function fmi3GetUInt32!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3UInt32}) +function fmi3GetUInt32!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3UInt32}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetUInt32!(...): `vr` and `values` need to be the same length." @@ -1361,7 +1538,11 @@ More detailed: See also [`fmi3SetUInt32`](@ref). """ -function fmi3SetUInt32(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3UInt32}, fmi3UInt32}) +function fmi3SetUInt32( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3UInt32},fmi3UInt32}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1440,7 +1621,11 @@ More detailed: See also [`fmi3GetInt64!`](@ref). """ -function fmi3GetInt64!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Int64}) +function fmi3GetInt64!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Int64}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetInt64!(...): `vr` and `values` need to be the same length." @@ -1481,7 +1666,11 @@ More detailed: See also [`fmi3SetInt64`](@ref). """ -function fmi3SetInt64(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3Int64}, fmi3Int64}) +function fmi3SetInt64( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3Int64},fmi3Int64}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1559,7 +1748,11 @@ More detailed: See also [`fmi3GetUInt64!`](@ref). """ -function fmi3GetUInt64!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3UInt64}) +function fmi3GetUInt64!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3UInt64}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetUInt64!(...): `vr` and `values` need to be the same length." @@ -1600,7 +1793,11 @@ More detailed: See also [`fmi3SetUInt64`](@ref). """ -function fmi3SetUInt64(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3UInt64}, fmi3UInt64}) +function fmi3SetUInt64( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3UInt64},fmi3UInt64}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1678,7 +1875,11 @@ More detailed: See also [`fmi3GetBoolean!`](@ref). """ -function fmi3GetBoolean!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Boolean}) +function fmi3GetBoolean!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Boolean}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetBoolean!(...): `vr` and `values` need to be the same length." @@ -1720,7 +1921,11 @@ More detailed: See also [`fmi3SetBoolean`](@ref). """ -function fmi3SetBoolean(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{Bool}, Bool}) +function fmi3SetBoolean( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{Bool},Bool}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1800,7 +2005,11 @@ More detailed: See also [`fmi3GetString!`](@ref). """ -function fmi3GetString!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3String}) +function fmi3GetString!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3String}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetString!(...): `vr` and `values` need to be the same length." @@ -1844,7 +2053,11 @@ More detailed: See also [`fmi3SetString`](@ref). """ -function fmi3SetString(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{String}, String}) +function fmi3SetString( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{String},String}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -1923,7 +2136,11 @@ More detailed: See also [`fmi3GetBinary!`](@ref). """ -function fmi3GetBinary!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Binary}) +function fmi3GetBinary!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Binary}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetBinary!(...): `vr` and `values` need to be the same length." @@ -1965,7 +2182,12 @@ More detailed: See also [`fmi3SetBinary`](@ref). """ -function fmi3SetBinary(c::FMU3Instance, vr::fmi3ValueReferenceFormat, valueSizes::Union{AbstractArray{Csize_t}, Csize_t}, values::Union{AbstractArray{fmi3Binary}, fmi3Binary}) +function fmi3SetBinary( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + valueSizes::Union{AbstractArray{Csize_t},Csize_t}, + values::Union{AbstractArray{fmi3Binary},fmi3Binary}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -2043,7 +2265,11 @@ More detailed: See also [`fmi3GetClock!`](@ref). """ -function fmi3GetClock!(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::AbstractArray{fmi3Clock}) +function fmi3GetClock!( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::AbstractArray{fmi3Clock}, +) vr = prepareValueReference(c, vr) @assert length(vr) == length(values) "fmi3GetClock!(...): `vr` and `values` need to be the same length." @@ -2084,7 +2310,11 @@ More detailed: See also [`fmi3SetClock`](@ref). """ -function fmi3SetClock(c::FMU3Instance, vr::fmi3ValueReferenceFormat, values::Union{AbstractArray{fmi3Clock}, fmi3Clock}) +function fmi3SetClock( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + values::Union{AbstractArray{fmi3Clock},fmi3Clock}, +) vr = prepareValueReference(c, vr) values = prepareValue(values) @@ -2233,7 +2463,7 @@ function fmi3DeSerializeFMUState(c::FMU3Instance, serializedState::AbstractArray status = fmi3DeSerializeFMUState!(c, serializedState, Csize_t(size), stateRef) @assert status == Int(fmi3StatusOK) ["Failed with status `$status`."] - + state = stateRef[] end # [NOTE] needs to be exported, because FMICore only exports `fmi3DeSerializeFMUState!` @@ -2279,20 +2509,27 @@ Computes a linear combination of the partial derivatives of h with respect to th See also [`fmi3GetDirectionalDerivative`](@ref). """ -function fmi3GetDirectionalDerivative(c::FMU3Instance, - unknowns::AbstractArray{fmi3ValueReference}, - knowns::AbstractArray{fmi3ValueReference}, - seed::AbstractArray{fmi3Float64}) - +function fmi3GetDirectionalDerivative( + c::FMU3Instance, + unknowns::AbstractArray{fmi3ValueReference}, + knowns::AbstractArray{fmi3ValueReference}, + seed::AbstractArray{fmi3Float64}, +) + nUnknown = Csize_t(length(unknowns)) sensitivity = zeros(fmi3Float64, nUnknown) status = fmi3GetDirectionalDerivative!(c, unknowns, knowns, seed, sensitivity) @assert isStatusOK(c, status) "Failed with status `$(status)`." - + return sensitivity end -fmi3GetDirectionalDerivative(c::FMU3Instance, unknown::fmi3ValueReference, known::fmi3ValueReference, seed::fmi3Float64) = fmi3GetDirectionalDerivative(c, [unknown], [known], [seed])[1] +fmi3GetDirectionalDerivative( + c::FMU3Instance, + unknown::fmi3ValueReference, + known::fmi3ValueReference, + seed::fmi3Float64, +) = fmi3GetDirectionalDerivative(c, [unknown], [known], [seed])[1] # [NOTE] needs to be exported, because FMICore only exports `fmi3GetDirectionalDerivative!` export fmi3GetDirectionalDerivative @@ -2345,11 +2582,13 @@ More detailed: See also [`fmi3GetDirectionalDerivative!`](@ref). """ -function fmi3GetDirectionalDerivative!(c::FMU3Instance, - unknowns::AbstractArray{fmi3ValueReference}, - knowns::AbstractArray{fmi3ValueReference}, - seed::AbstractArray{fmi3Float64}, - sensitivity::AbstractArray{fmi3Float64}) +function fmi3GetDirectionalDerivative!( + c::FMU3Instance, + unknowns::AbstractArray{fmi3ValueReference}, + knowns::AbstractArray{fmi3ValueReference}, + seed::AbstractArray{fmi3Float64}, + sensitivity::AbstractArray{fmi3Float64}, +) nUnknowns = Csize_t(length(unknowns)) nKnowns = Csize_t(length(knowns)) @@ -2357,7 +2596,17 @@ function fmi3GetDirectionalDerivative!(c::FMU3Instance, nSeed = Csize_t(length(seed)) nSensitivity = Csize_t(length(sensitivity)) - status = fmi3GetDirectionalDerivative!(c, unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity) + status = fmi3GetDirectionalDerivative!( + c, + unknowns, + nUnknowns, + knowns, + nKnowns, + seed, + nSeed, + sensitivity, + nSensitivity, + ) return status end @@ -2401,20 +2650,27 @@ Computes a linear combination of the partial derivatives of h with respect to th See also [`fmi3GetAdjointDerivative`](@ref). """ -function fmi3GetAdjointDerivative(c::FMU3Instance, - unknowns::AbstractArray{fmi3ValueReference}, - knowns::AbstractArray{fmi3ValueReference}, - seed::AbstractArray{fmi3Float64}) - +function fmi3GetAdjointDerivative( + c::FMU3Instance, + unknowns::AbstractArray{fmi3ValueReference}, + knowns::AbstractArray{fmi3ValueReference}, + seed::AbstractArray{fmi3Float64}, +) + nUnknown = Csize_t(length(unknowns)) sensitivity = zeros(fmi3Float64, nUnknown) status = fmi3GetAdjointDerivative!(c, unknowns, knowns, seed, sensitivity) @assert status == Int(fmi3StatusOK) ["Failed with status `$status`."] - + return sensitivity end -fmi3GetAdjointDerivative(c::FMU3Instance, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::fmi3Float64) = fmi3GetAdjointDerivative(c, [unknowns], [knowns], [seed])[1] +fmi3GetAdjointDerivative( + c::FMU3Instance, + unknowns::fmi3ValueReference, + knowns::fmi3ValueReference, + seed::fmi3Float64, +) = fmi3GetAdjointDerivative(c, [unknowns], [knowns], [seed])[1] # [NOTE] needs to be exported, because FMICore only exports `fmi3GetAdjointDerivative!` export fmi3GetAdjointDerivative @@ -2467,11 +2723,13 @@ More detailed: See also [`fmi3GetAdjointDerivative!`](@ref). """ -function fmi3GetAdjointDerivative!(c::FMU3Instance, - unknowns::AbstractArray{fmi3ValueReference}, - knowns::AbstractArray{fmi3ValueReference}, - sensitivity::AbstractArray, - seed::AbstractArray{fmi3Float64}) +function fmi3GetAdjointDerivative!( + c::FMU3Instance, + unknowns::AbstractArray{fmi3ValueReference}, + knowns::AbstractArray{fmi3ValueReference}, + sensitivity::AbstractArray, + seed::AbstractArray{fmi3Float64}, +) nKnowns = Csize_t(length(knowns)) nUnknowns = Csize_t(length(unknowns)) @@ -2479,7 +2737,17 @@ function fmi3GetAdjointDerivative!(c::FMU3Instance, nSeed = Csize_t(length(seed)) nSensitivity = Csize_t(length(sensitivity)) - status = fmi3GetAdjointDerivative!(c, unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity) + status = fmi3GetAdjointDerivative!( + c, + unknowns, + nUnknowns, + knowns, + nKnowns, + seed, + nSeed, + sensitivity, + nSensitivity, + ) return status end @@ -2505,13 +2773,17 @@ Retrieves the n-th derivative of output values. See also [`fmi3GetOutputDerivatives`](@ref). """ -function fmi3GetOutputDerivatives(c::FMU3Instance, vr::fmi3ValueReferenceFormat, order::AbstractArray{Integer}) +function fmi3GetOutputDerivatives( + c::FMU3Instance, + vr::fmi3ValueReferenceFormat, + order::AbstractArray{Integer}, +) vr = prepareValueReference(c, vr) order = prepareValue(order) nvr = Csize_t(length(vr)) values = zeros(fmi3Float64, nvr) fmi3GetOutputDerivatives!(c, vr, nvr, order, values, nvr) - + if length(values) == 1 return values[1] else @@ -2605,7 +2877,10 @@ This information can only be retrieved if the 'providesPerElementDependencies' t See also [`fmi3GetNumberOfVariableDependencies`](@ref). """ -function fmi3GetNumberOfVariableDependencies(c::FMU3Instance, vr::Union{fmi3ValueReference, String}) +function fmi3GetNumberOfVariableDependencies( + c::FMU3Instance, + vr::Union{fmi3ValueReference,String}, +) if typeof(vr) == String vr = fmi3String2ValueReference(c.fmu.modelDescription, vr) end @@ -2646,7 +2921,7 @@ The actual dependencies (of type dependenciesKind) can be retrieved by calling t See also [`fmi3GetVariableDependencies!`](@ref). """ -function fmi3GetVariableDependencies(c::FMU3Instance, vr::Union{fmi3ValueReference, String}) +function fmi3GetVariableDependencies(c::FMU3Instance, vr::Union{fmi3ValueReference,String}) if typeof(vr) == String vr = fmi3String2ValueReference(c.fmu.modelDescription, vr) end @@ -2656,9 +2931,20 @@ function fmi3GetVariableDependencies(c::FMU3Instance, vr::Union{fmi3ValueReferen elementIndiceOfIndependents = Array{Csize_t}(undef, nDependencies) dependencyKinds = Array{fmi3DependencyKind}(undef, nDependencies) - fmi3GetVariableDependencies!(c, vr, elementIndiceOfDependents, independents, elementIndiceOfIndependents, dependencyKinds, nDependencies) - - return elementIndiceOfDependents, independents, elementIndiceOfIndependents, dependencyKinds + fmi3GetVariableDependencies!( + c, + vr, + elementIndiceOfDependents, + independents, + elementIndiceOfIndependents, + dependencyKinds, + nDependencies, + ) + + return elementIndiceOfDependents, + independents, + elementIndiceOfIndependents, + dependencyKinds end # [NOTE] needs to be exported, because FMICore only exports `fmi3GetVariableDependencies!` export fmi3GetVariableDependencies @@ -2778,12 +3064,15 @@ More detailed: See also [`fmi3SetContinuousStates`](@ref). """ -function fmi3SetContinuousStates(c::FMU3Instance, x::Union{AbstractArray{Float32}, AbstractArray{Float64}}) +function fmi3SetContinuousStates( + c::FMU3Instance, + x::Union{AbstractArray{Float32},AbstractArray{Float64}}, +) nx = Csize_t(length(x)) status = fmi3SetContinuousStates(c, Array{fmi3Float64}(x), nx) if status == fmi3StatusOK c.x = x - end + end return status end @@ -2807,7 +3096,7 @@ vector. See also [`fmi3GetContinuousStateDerivatives`](@ref). """ -function fmi3GetContinuousStateDerivatives(c::FMU3Instance) +function fmi3GetContinuousStateDerivatives(c::FMU3Instance) nx = Csize_t(c.fmu.modelDescription.numberOfContinuousStates) derivatives = zeros(fmi3Float64, nx) fmi3GetContinuousStateDerivatives!(c, derivatives) @@ -2843,8 +3132,12 @@ More detailed: See also [`fmi3GetContinuousStateDerivatives!`](@ref). """ -function fmi3GetContinuousStateDerivatives!(c::FMU3Instance, derivatives::AbstractArray{fmi3Float64}) - status = fmi3GetContinuousStateDerivatives!(c, derivatives, Csize_t(length(derivatives))) +function fmi3GetContinuousStateDerivatives!( + c::FMU3Instance, + derivatives::AbstractArray{fmi3Float64}, +) + status = + fmi3GetContinuousStateDerivatives!(c, derivatives, Csize_t(length(derivatives))) if status == fmi3StatusOK c.ẋ = derivatives end @@ -2889,16 +3182,21 @@ function fmi3UpdateDiscreteStates(c::FMU3Instance) refnETD = Ref(nextEventTimeDefined) refnET = Ref(nextEventTime) - fmi3UpdateDiscreteStates(c, refdS, reftS, refnOCS, refvOCS, refnETD, refnET) + fmi3UpdateDiscreteStates(c, refdS, reftS, refnOCS, refvOCS, refnETD, refnET) discreteStatesNeedUpdate = refdS[] terminateSimulation = reftS[] - nominalsOfContinuousStatesChanged =refnOCS[] + nominalsOfContinuousStatesChanged = refnOCS[] valuesOfContinuousStatesChanged = refvOCS[] nextEventTimeDefined = refnETD[] nextEventTime = refnET[] - discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime + discreteStatesNeedUpdate, + terminateSimulation, + nominalsOfContinuousStatesChanged, + valuesOfContinuousStatesChanged, + nextEventTimeDefined, + nextEventTime end """ @@ -2919,14 +3217,16 @@ Results are returned, use `fmi3UpdateDiscreteStates` for the out-of-place varian - FMISpec3.0: 2.3.5. State: Event Mode """ function fmi3UpdateDiscreteStates!(c::FMU3Instance) - - status = fmi3UpdateDiscreteStates(c, - c._ptr_discreteStatesNeedUpdate, - c._ptr_terminateSimulation, - c._ptr_nominalsOfContinuousStatesChanged, - c._ptr_valuesOfContinuousStatesChanged, - c._ptr_nextEventTimeDefined, - c._ptr_nextEventTime) + + status = fmi3UpdateDiscreteStates( + c, + c._ptr_discreteStatesNeedUpdate, + c._ptr_terminateSimulation, + c._ptr_nominalsOfContinuousStatesChanged, + c._ptr_valuesOfContinuousStatesChanged, + c._ptr_nextEventTimeDefined, + c._ptr_nextEventTime, + ) return status end @@ -2988,13 +3288,17 @@ More detailed: See also [`fmi3CompletedIntegratorStep`](@ref). """ -function fmi3CompletedIntegratorStep(c::FMU3Instance, - noSetFMUStatePriorToCurrentPoint::fmi3Boolean) - - status = fmi3CompletedIntegratorStep!(c, +function fmi3CompletedIntegratorStep( + c::FMU3Instance, + noSetFMUStatePriorToCurrentPoint::fmi3Boolean, +) + + status = fmi3CompletedIntegratorStep!( + c, noSetFMUStatePriorToCurrentPoint, c._ptr_enterEventMode, - c._ptr_terminateSimulation) + c._ptr_terminateSimulation, + ) return (status, c.enterEventMode, c.terminateSimulation) end @@ -3031,8 +3335,22 @@ More detailed: See also [`fmi3EnterEventMode`](@ref). """ -function fmi3EnterEventMode(c::FMU3Instance, stepEvent::Bool, stateEvent::Bool, rootsFound::AbstractArray{fmi3Int32}, nEventIndicators::Csize_t, timeEvent::Bool) - fmi3EnterEventMode(c, fmi3Boolean(stepEvent), fmi3Boolean(stateEvent), rootsFound, nEventIndicators, fmi3Boolean(timeEvent)) +function fmi3EnterEventMode( + c::FMU3Instance, + stepEvent::Bool, + stateEvent::Bool, + rootsFound::AbstractArray{fmi3Int32}, + nEventIndicators::Csize_t, + timeEvent::Bool, +) + fmi3EnterEventMode( + c, + fmi3Boolean(stepEvent), + fmi3Boolean(stateEvent), + rootsFound, + nEventIndicators, + fmi3Boolean(timeEvent), + ) end """ @@ -3069,8 +3387,16 @@ More detailed: See also [`fmi3DoStep!`](@ref). """ -function fmi3DoStep!(c::FMU3Instance, currentCommunicationPoint::Union{Real, Nothing} = nothing, communicationStepSize::Union{Real, Nothing} = nothing, noSetFMUStatePriorToCurrentPoint::Bool = true, - eventEncountered::fmi3Boolean = fmi3False, terminateSimulation::fmi3Boolean = fmi3False, earlyReturn::fmi3Boolean = fmi3False, lastSuccessfulTime::fmi3Float64 = 0.0) +function fmi3DoStep!( + c::FMU3Instance, + currentCommunicationPoint::Union{Real,Nothing} = nothing, + communicationStepSize::Union{Real,Nothing} = nothing, + noSetFMUStatePriorToCurrentPoint::Bool = true, + eventEncountered::fmi3Boolean = fmi3False, + terminateSimulation::fmi3Boolean = fmi3False, + earlyReturn::fmi3Boolean = fmi3False, + lastSuccessfulTime::fmi3Float64 = 0.0, +) if currentCommunicationPoint === nothing currentCommunicationPoint = c.t @@ -3089,7 +3415,16 @@ function fmi3DoStep!(c::FMU3Instance, currentCommunicationPoint::Union{Real, Not reflastSuccessfulTime = Ref(lastSuccessfulTime) c.t = currentCommunicationPoint - status = fmi3DoStep!(c, fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) + status = fmi3DoStep!( + c, + fmi3Float64(currentCommunicationPoint), + fmi3Float64(communicationStepSize), + fmi3Boolean(noSetFMUStatePriorToCurrentPoint), + refeventEncountered, + refterminateSimulation, + refearlyReturn, + reflastSuccessfulTime, + ) c.t += communicationStepSize eventEncountered = refeventEncountered[] diff --git a/src/FMI3/md.jl b/src/FMI3/md.jl index 5b7edfa..60ac466 100644 --- a/src/FMI3/md.jl +++ b/src/FMI3/md.jl @@ -13,11 +13,29 @@ # [Sec. 1a] fmi3LoadModelDescription # ###################################### -using FMIBase.FMICore: fmi3ModelDescriptionModelExchange, fmi3ModelDescriptionCoSimulation, fmi3ModelDescriptionScheduledExecution, fmi3ModelDescriptionDefaultExperiment -using FMIBase.FMICore: fmi3ModelDescriptionModelStructure, fmi3ModelDescriptionDefaultExperiment +using FMIBase.FMICore: + fmi3ModelDescriptionModelExchange, + fmi3ModelDescriptionCoSimulation, + fmi3ModelDescriptionScheduledExecution, + fmi3ModelDescriptionDefaultExperiment +using FMIBase.FMICore: + fmi3ModelDescriptionModelStructure, fmi3ModelDescriptionDefaultExperiment using FMIBase.FMICore: fmi3VariableFloat32, fmi3VariableFloat64 -using FMIBase.FMICore: fmi3VariableInt8, fmi3VariableUInt8, fmi3VariableInt16, fmi3VariableUInt16, fmi3VariableInt32, fmi3VariableUInt32, fmi3VariableInt64, fmi3VariableUInt64 -using FMIBase.FMICore: fmi3VariableBoolean, fmi3VariableString, fmi3VariableBinary, fmi3VariableClock, fmi3VariableEnumeration +using FMIBase.FMICore: + fmi3VariableInt8, + fmi3VariableUInt8, + fmi3VariableInt16, + fmi3VariableUInt16, + fmi3VariableInt32, + fmi3VariableUInt32, + fmi3VariableInt64, + fmi3VariableUInt64 +using FMIBase.FMICore: + fmi3VariableBoolean, + fmi3VariableString, + fmi3VariableBinary, + fmi3VariableClock, + fmi3VariableEnumeration """ Extract the FMU variables and meta data from the ModelDescription @@ -25,7 +43,7 @@ Extract the FMU variables and meta data from the ModelDescription function fmi3LoadModelDescription(pathToModellDescription::String) md = fmi3ModelDescription() - md.stringValueReferences = Dict{String, fmi3ValueReference}() + md.stringValueReferences = Dict{String,fmi3ValueReference}() md.outputValueReferences = Array{fmi3ValueReference}(undef, 0) md.inputValueReferences = Array{fmi3ValueReference}(undef, 0) md.stateValueReferences = Array{fmi3ValueReference}(undef, 0) @@ -48,12 +66,28 @@ function fmi3LoadModelDescription(pathToModellDescription::String) md.instantiationToken = root["instantiationToken"] # optional - md.generationTool = parseNode(root, "generationTool", String; onfail="[Unknown generation tool]") - md.generationDateAndTime = parseNode(root, "generationDateAndTime", String; onfail="[Unknown generation date and time]") - variableNamingConventionStr = parseNode(root, "variableNamingConvention", String; onfail= "flat") - @assert (variableNamingConventionStr == "flat" || variableNamingConventionStr == "structured") ["fmi3ReadModelDescription(...): Unknown entry for `variableNamingConvention=$(variableNamingConventionStr)`."] - md.variableNamingConvention = (variableNamingConventionStr == "flat" ? fmi3VariableNamingConventionFlat : fmi3VariableNamingConventionStructured) - md.description = parseNode(root, "description", String; onfail="[Unknown Description]") + md.generationTool = + parseNode(root, "generationTool", String; onfail = "[Unknown generation tool]") + md.generationDateAndTime = parseNode( + root, + "generationDateAndTime", + String; + onfail = "[Unknown generation date and time]", + ) + variableNamingConventionStr = + parseNode(root, "variableNamingConvention", String; onfail = "flat") + @assert ( + variableNamingConventionStr == "flat" || + variableNamingConventionStr == "structured" + ) [ + "fmi3ReadModelDescription(...): Unknown entry for `variableNamingConvention=$(variableNamingConventionStr)`.", + ] + md.variableNamingConvention = ( + variableNamingConventionStr == "flat" ? fmi3VariableNamingConventionFlat : + fmi3VariableNamingConventionStructured + ) + md.description = + parseNode(root, "description", String; onfail = "[Unknown Description]") # defaults md.modelExchange = nothing @@ -63,42 +97,65 @@ function fmi3LoadModelDescription(pathToModellDescription::String) # additionals md.valueReferences = [] - md.valueReferenceIndicies = Dict{UInt, UInt}() + md.valueReferenceIndicies = Dict{UInt,UInt}() for node in eachelement(root) if node.name == "CoSimulation" md.coSimulation = fmi3ModelDescriptionCoSimulation() - md.coSimulation.modelIdentifier = node["modelIdentifier"] - md.coSimulation.canHandleVariableCommunicationStepSize = parseNode(node, "canHandleVariableCommunicationStepSize", Bool ; onfail=false) - md.coSimulation.canInterpolateInputs = parseNode(node, "canInterpolateInputs", Bool ; onfail=false) - md.coSimulation.maxOutputDerivativeOrder = parseNode(node, "maxOutputDerivativeOrder", Int ; onfail=nothing) - md.coSimulation.canGetAndSetFMUState = parseNode(node, "canGetAndSetFMUState", Bool ; onfail=false) - md.coSimulation.canSerializeFMUState = parseNode(node, "canSerializeFMUState", Bool ; onfail=false) - md.coSimulation.providesDirectionalDerivatives = parseNode(node, "providesDirectionalDerivatives", Bool ; onfail=false) - md.coSimulation.providesAdjointDerivatives = parseNode(node, "providesAdjointDerivatives", Bool ; onfail=false) - md.coSimulation.hasEventMode = parseNode(node, "hasEventMode", Bool ; onfail=false) + md.coSimulation.modelIdentifier = node["modelIdentifier"] + md.coSimulation.canHandleVariableCommunicationStepSize = parseNode( + node, + "canHandleVariableCommunicationStepSize", + Bool; + onfail = false, + ) + md.coSimulation.canInterpolateInputs = + parseNode(node, "canInterpolateInputs", Bool; onfail = false) + md.coSimulation.maxOutputDerivativeOrder = + parseNode(node, "maxOutputDerivativeOrder", Int; onfail = nothing) + md.coSimulation.canGetAndSetFMUState = + parseNode(node, "canGetAndSetFMUState", Bool; onfail = false) + md.coSimulation.canSerializeFMUState = + parseNode(node, "canSerializeFMUState", Bool; onfail = false) + md.coSimulation.providesDirectionalDerivatives = + parseNode(node, "providesDirectionalDerivatives", Bool; onfail = false) + md.coSimulation.providesAdjointDerivatives = + parseNode(node, "providesAdjointDerivatives", Bool; onfail = false) + md.coSimulation.hasEventMode = + parseNode(node, "hasEventMode", Bool; onfail = false) elseif node.name == "ModelExchange" md.modelExchange = fmi3ModelDescriptionModelExchange() - md.modelExchange.modelIdentifier = node["modelIdentifier"] - md.modelExchange.canGetAndSetFMUState = parseNode(node, "canGetAndSetFMUState", Bool ; onfail=false) - md.modelExchange.canSerializeFMUState = parseNode(node, "canSerializeFMUState", Bool ; onfail=false) - md.modelExchange.providesDirectionalDerivatives = parseNode(node, "providesDirectionalDerivatives", Bool ; onfail=false) - md.modelExchange.providesAdjointDerivatives = parseNode(node, "providesAdjointDerivatives", Bool ; onfail=false) - + md.modelExchange.modelIdentifier = node["modelIdentifier"] + md.modelExchange.canGetAndSetFMUState = + parseNode(node, "canGetAndSetFMUState", Bool; onfail = false) + md.modelExchange.canSerializeFMUState = + parseNode(node, "canSerializeFMUState", Bool; onfail = false) + md.modelExchange.providesDirectionalDerivatives = + parseNode(node, "providesDirectionalDerivatives", Bool; onfail = false) + md.modelExchange.providesAdjointDerivatives = + parseNode(node, "providesAdjointDerivatives", Bool; onfail = false) + elseif node.name == "ScheduledExecution" md.scheduledExecution = fmi3ModelDescriptionScheduledExecution() - md.scheduledExecution.modelIdentifier = node["modelIdentifier"] - md.scheduledExecution.needsExecutionTool = parseNode(node, "needsExecutionTool", Bool ; onfail=false) - md.scheduledExecution.canBeInstantiatedOnlyOncePerProcess = parseNode(node, "canBeInstantiatedOnlyOncePerProcess", Bool ; onfail=false) - md.scheduledExecution.canGetAndSetFMUState = parseNode(node, "canGetAndSetFMUState", Bool ; onfail=false) - md.scheduledExecution.canSerializeFMUState = parseNode(node, "canSerializeFMUState", Bool ; onfail=false) - md.scheduledExecution.providesDirectionalDerivatives = parseNode(node, "providesDirectionalDerivatives", Bool ; onfail=false) - md.scheduledExecution.providesAdjointDerivatives = parseNode(node, "providesAdjointDerivatives", Bool ; onfail=false) - md.scheduledExecution.providesPerElementDependencies = parseNode(node, "providesPerElementDependencies", Bool ; onfail=false) - + md.scheduledExecution.modelIdentifier = node["modelIdentifier"] + md.scheduledExecution.needsExecutionTool = + parseNode(node, "needsExecutionTool", Bool; onfail = false) + md.scheduledExecution.canBeInstantiatedOnlyOncePerProcess = + parseNode(node, "canBeInstantiatedOnlyOncePerProcess", Bool; onfail = false) + md.scheduledExecution.canGetAndSetFMUState = + parseNode(node, "canGetAndSetFMUState", Bool; onfail = false) + md.scheduledExecution.canSerializeFMUState = + parseNode(node, "canSerializeFMUState", Bool; onfail = false) + md.scheduledExecution.providesDirectionalDerivatives = + parseNode(node, "providesDirectionalDerivatives", Bool; onfail = false) + md.scheduledExecution.providesAdjointDerivatives = + parseNode(node, "providesAdjointDerivatives", Bool; onfail = false) + md.scheduledExecution.providesPerElementDependencies = + parseNode(node, "providesPerElementDependencies", Bool; onfail = false) + elseif node.name ∈ ("TypeDefinitions", "LogCategories", "UnitDefinitions") - @warn "FMU has $(node.name), but parsing is not implemented yet." + @warn "FMU has $(node.name), but parsing is not implemented yet." elseif node.name == "ModelVariables" md.modelVariables = parseModelVariables(md, node) @@ -109,13 +166,18 @@ function fmi3LoadModelDescription(pathToModellDescription::String) parseModelStructure(md, node) md.numberOfContinuousStates = length(md.stateValueReferences) - + elseif node.name == "DefaultExperiment" md.defaultExperiment = fmi3ModelDescriptionDefaultExperiment() - md.defaultExperiment.startTime = parseNode(node, "startTime", fmi3Float64) - md.defaultExperiment.stopTime = parseNode(node, "stopTime", fmi3Float64) - md.defaultExperiment.tolerance = parseNode(node, "tolerance", fmi3Float64; onfail = md.defaultExperiment.tolerance) - md.defaultExperiment.stepSize = parseNode(node, "stepSize", fmi3Float64) + md.defaultExperiment.startTime = parseNode(node, "startTime", fmi3Float64) + md.defaultExperiment.stopTime = parseNode(node, "stopTime", fmi3Float64) + md.defaultExperiment.tolerance = parseNode( + node, + "tolerance", + fmi3Float64; + onfail = md.defaultExperiment.tolerance, + ) + md.defaultExperiment.stepSize = parseNode(node, "stepSize", fmi3Float64) else @assert false "Unknwon node named `$(node.name)`, please open an issue on GitHub." @@ -123,9 +185,9 @@ function fmi3LoadModelDescription(pathToModellDescription::String) end # creating an index for value references (fast look-up for dependencies) - for i in 1:length(md.valueReferences) + for i = 1:length(md.valueReferences) md.valueReferenceIndicies[md.valueReferences[i]] = i - end + end # check all intermediateUpdate variables for variable in md.modelVariables @@ -154,7 +216,7 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) for node in eachelement(nodes) name = node["name"] valueReference = parseNode(node, "valueReference", fmi3ValueReference) - + # type node typenode = nothing typename = node.name @@ -189,11 +251,11 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) modelVariables[index] = fmi3VariableClock(name, valueReference) elseif typename == "Enumeration" modelVariables[index] = fmi3VariableEnumeration(name, valueReference) - else + else @warn "Unknown data type `$(typename)`." # ToDo: how to handle unknown types end - + # modelVariables[index] = fmi3Variable(name, valueReference) if !(valueReference in md.valueReferences) @@ -219,16 +281,19 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) if haskey(node, "variability") variability = stringToVariability(md, parseNode(node, "variability", String)) end - modelVariables[index].canHandleMultipleSetPerTimeInstant = parseNode(node, "canHandleMultipleSetPerTimeInstant", Bool) + modelVariables[index].canHandleMultipleSetPerTimeInstant = + parseNode(node, "canHandleMultipleSetPerTimeInstant", Bool) modelVariables[index].annotations = parseNode(node, "annotations", String) - modelVariables[index].clocks = parseArrayValueReferences(md, parseNode(node, "clocks", String)) - + modelVariables[index].clocks = + parseArrayValueReferences(md, parseNode(node, "clocks", String)) + if typename ∉ ("Clock", "String") - modelVariables[index].intermediateUpdate = parseNode(node, "intermediateUpdate", Bool) + modelVariables[index].intermediateUpdate = + parseNode(node, "intermediateUpdate", Bool) else @warn "Unsupported typename `$(typename)` for modelVariable attribute `intermediateUpdate`." end - + if typename ∉ ("Clock", "String") modelVariables[index].previous = parseNode(node, "previous", Bool) else @@ -237,12 +302,13 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) if haskey(node, "initial") if typename ∉ ("Clock", "String", "Enumeration") - modelVariables[index].initial = stringToInitial(md, parseNode(node, "initial", String)) + modelVariables[index].initial = + stringToInitial(md, parseNode(node, "initial", String)) else @warn "Unsupported typename `$(typename)` for modelVariable attribute `initial`." end end - + if typename ∉ ("Clock", "String", "Binary", "Boolean") modelVariables[index].quantity = parseNode(node, "quantity", String) else @@ -253,7 +319,7 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) modelVariables[index].unit = parseNode(node, "unit", String) modelVariables[index].displayUnit = parseNode(node, "displayUnit", String) end - + if typename != "String" modelVariables[index].declaredType = parseNode(node, "declaredType", String) else @@ -261,20 +327,24 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) end if typename ∉ ("Clock", "String", "Binary", "Boolean") - modelVariables[index].min = parseNode(node, "min", stringToDataType(md, typename)) + modelVariables[index].min = + parseNode(node, "min", stringToDataType(md, typename)) else @warn "Unsupported typename `$(typename)` for modelVariable attribute `min`." end if typename ∉ ("Clock", "String", "Binary", "Boolean") - modelVariables[index].max = parseNode(node, "max", stringToDataType(md, typename)) + modelVariables[index].max = + parseNode(node, "max", stringToDataType(md, typename)) else @warn "Unsupported typename `$(typename)` for modelVariable attribute `max`." end if typename == "Float64" || typename == "Float32" - modelVariables[index].nominal = parseNode(node, "nominal", stringToDataType(md, typename)) - modelVariables[index].unbounded = parseNode(node, "unbounded", stringToDataType(md, typename)) + modelVariables[index].nominal = + parseNode(node, "nominal", stringToDataType(md, typename)) + modelVariables[index].unbounded = + parseNode(node, "unbounded", stringToDataType(md, typename)) end if typename ∉ ("Binary", "Clock") @@ -288,13 +358,15 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) end else if typename == "Enum" - for i in 1:length(md.enumerations) + for i = 1:length(md.enumerations) if modelVariables[index].declaredType == md.enumerations[i][1] # identify the enum by the name - modelVariables[index].start = md.enumerations[i][1 + parseNode(node, "start", Int)] # find the enum value and set it + modelVariables[index].start = + md.enumerations[i][1+parseNode(node, "start", Int)] # find the enum value and set it end end else - modelVariables[index].start = parseNode(node, "start", stringToDataType(md, typename)) + modelVariables[index].start = + parseNode(node, "start", stringToDataType(md, typename)) end end else @@ -302,10 +374,11 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) end if typename == "Float64" || typename == "Float32" - modelVariables[index].derivative = parseNode(node, "derivative", fmi3ValueReference) + modelVariables[index].derivative = + parseNode(node, "derivative", fmi3ValueReference) modelVariables[index].reinit = parseNode(node, "reinit", Bool) end - + if typename == "String" for nod in eachelement(node) if nod.name == "Start" @@ -319,7 +392,7 @@ function parseModelVariables(md::fmi3ModelDescription, nodes::EzXML.Node) end end end - + md.stringValueReferences[name] = valueReference index += 1 @@ -329,7 +402,7 @@ end # Parses the model variables of the FMU model description. function parseModelStructure(md::fmi3ModelDescription, nodes::EzXML.Node) - + md.modelStructure.continuousStateDerivatives = [] md.modelStructure.initialUnknowns = [] md.modelStructure.eventIndicators = [] @@ -349,20 +422,21 @@ function parseModelStructure(md::fmi3ModelDescription, nodes::EzXML.Node) # find states and derivatives derValueRef = parseNode(node, "valueReference", fmi3ValueReference) derVar = modelVariablesForValueReference(md, derValueRef)[1] - stateValueRef = modelVariablesForValueReference(md, derVar.derivative)[1].valueReference - + stateValueRef = + modelVariablesForValueReference(md, derVar.derivative)[1].valueReference + if stateValueRef ∉ md.stateValueReferences push!(md.stateValueReferences, stateValueRef) end if derValueRef ∉ md.derivativeValueReferences push!(md.derivativeValueReferences, derValueRef) end - + push!(md.modelStructure.continuousStateDerivatives, varDep) - elseif node.name =="Output" + elseif node.name == "Output" # find outputs outVR = parseNode(node, "valueReference", fmi3ValueReference) - + if outVR ∉ md.outputValueReferences push!(md.outputValueReferences, outVR) end @@ -371,7 +445,7 @@ function parseModelStructure(md::fmi3ModelDescription, nodes::EzXML.Node) else @warn "Unknown entry in `ModelStructure` named `$(node.name)`." end - else + else @warn "Invalid entry for node `$(node.name)` in `ModelStructure`, missing entry `valueReference`." end end @@ -388,26 +462,27 @@ function parseDependencies(md::fmi3ModelDescription, node::EzXML.Node) varDep.dependencies = collect(parse(UInt, e) for e in dependenciesSplit) end end - end + end if haskey(node, "dependenciesKind") dependenciesKind = node["dependenciesKind"] if length(dependenciesKind) > 0 dependenciesKindSplit = split(dependenciesKind, " ") if length(dependenciesKindSplit) > 0 - varDep.dependenciesKind = collect(stringToDependencyKind(md, e) for e in dependenciesKindSplit) + varDep.dependenciesKind = + collect(stringToDependencyKind(md, e) for e in dependenciesKindSplit) end end end if varDep.dependencies !== nothing && varDep.dependenciesKind !== nothing if length(varDep.dependencies) != length(varDep.dependenciesKind) - @warn "Length of field dependencies ($(length(varDep.dependencies))) doesn't match length of dependenciesKind ($(length(varDep.dependenciesKind)))." + @warn "Length of field dependencies ($(length(varDep.dependencies))) doesn't match length of dependenciesKind ($(length(varDep.dependenciesKind)))." end end return varDep -end +end function parseContinuousStateDerivative(md::fmi3ModelDescription, nodes::EzXML.Node) @assert (nodes.name == "ContinuousStateDerivative") "Wrong element name." @@ -430,7 +505,7 @@ function parseContinuousStateDerivative(md::fmi3ModelDescription, nodes::EzXML.N end push!(md.modelStructure.derivatives, varDep) - else + else @warn "Invalid entry for node `Unknown` in `ModelStructure`, missing entry `index`." end elseif node.name == "EventIndicator" @@ -438,6 +513,6 @@ function parseContinuousStateDerivative(md::fmi3ModelDescription, nodes::EzXML.N # TODO parse valueReferences to another array else @warn "Unknown entry in `ModelStructure.Derivatives` named `$(node.name)`." - end + end end -end \ No newline at end of file +end diff --git a/src/FMI3/prep.jl b/src/FMI3/prep.jl index f202922..6301957 100644 --- a/src/FMI3/prep.jl +++ b/src/FMI3/prep.jl @@ -7,33 +7,43 @@ import FMIBase: isEventMode, isContinuousTimeMode, isTrue, isStatusOK using FMIBase: handleEvents function setBeforeInitialization(mv::FMIImport.fmi3Variable) - return mv.variability != fmi3VariabilityConstant && mv.initial ∈ (fmi3InitialApprox, fmi3InitialExact) + return mv.variability != fmi3VariabilityConstant && + mv.initial ∈ (fmi3InitialApprox, fmi3InitialExact) end function setInInitialization(mv::FMIImport.fmi3Variable) - return mv.causality == fmi3CausalityInput || (mv.causality != fmi3CausalityParameter && mv.variability == fmi3VariabilityTunable) || (mv.variability != fmi3VariabilityConstant && mv.initial == fmi3InitialExact) + return mv.causality == fmi3CausalityInput || + ( + mv.causality != fmi3CausalityParameter && + mv.variability == fmi3VariabilityTunable + ) || + (mv.variability != fmi3VariabilityConstant && mv.initial == fmi3InitialExact) end -function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3Type=fmu.type; - instantiate::Union{Nothing, Bool}=fmu.executionConfig.instantiate, - freeInstance::Union{Nothing, Bool}=fmu.executionConfig.freeInstance, - terminate::Union{Nothing, Bool}=fmu.executionConfig.terminate, - reset::Union{Nothing, Bool}=fmu.executionConfig.reset, - setup::Union{Nothing, Bool}=fmu.executionConfig.setup, - parameters::Union{Dict{<:Any, <:Any}, Nothing}=nothing, - t_start::Real=0.0, - t_stop::Union{Real, Nothing}=nothing, - tolerance::Union{Real, Nothing}=nothing, - x0::Union{AbstractArray{<:Real}, Nothing}=nothing, - inputs::Union{Dict{<:Any, <:Any}, Nothing}=nothing, - cleanup::Bool=false, - handleEvents=handleEvents, - instantiateKwargs...) +function prepareSolveFMU( + fmu::FMU3, + c::Union{Nothing,FMU3Instance}, + type::fmi3Type = fmu.type; + instantiate::Union{Nothing,Bool} = fmu.executionConfig.instantiate, + freeInstance::Union{Nothing,Bool} = fmu.executionConfig.freeInstance, + terminate::Union{Nothing,Bool} = fmu.executionConfig.terminate, + reset::Union{Nothing,Bool} = fmu.executionConfig.reset, + setup::Union{Nothing,Bool} = fmu.executionConfig.setup, + parameters::Union{Dict{<:Any,<:Any},Nothing} = nothing, + t_start::Real = 0.0, + t_stop::Union{Real,Nothing} = nothing, + tolerance::Union{Real,Nothing} = nothing, + x0::Union{AbstractArray{<:Real},Nothing} = nothing, + inputs::Union{Dict{<:Any,<:Any},Nothing} = nothing, + cleanup::Bool = false, + handleEvents = handleEvents, + instantiateKwargs..., +) ignore_derivatives() do - + c = nothing - + # instantiate (hard) if instantiate if type == fmi3TypeCoSimulation @@ -65,31 +75,41 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3T end @assert !isnothing(c) "No FMU instance available, allocate one or use `fmu.executionConfig.instantiate=true`." - + # soft terminate (if necessary) if terminate - retcode = fmi3Terminate(c; soft=true) + retcode = fmi3Terminate(c; soft = true) @assert retcode == fmi3StatusOK "fmi3Simulate(...): Termination failed with return code $(retcode)." end # soft reset (if necessary) if reset - retcode = fmi3Reset(c; soft=true) + retcode = fmi3Reset(c; soft = true) @assert retcode == fmi3StatusOK "fmi3Simulate(...): Reset failed with return code $(retcode)." - end + end # setup experiment (hard) # [Note] this part is handled by fmi3EnterInitializationMode - + # parameters if !isnothing(parameters) - retcodes = setValue(c, collect(keys(parameters)), collect(values(parameters)); filter=setBeforeInitialization) + retcodes = setValue( + c, + collect(keys(parameters)), + collect(values(parameters)); + filter = setBeforeInitialization, + ) @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial parameters failed with return code $(retcode)." end # inputs if !isnothing(inputs) - retcodes = setValue(c, collect(keys(inputs)), collect(values(inputs)); filter=setBeforeInitialization) + retcodes = setValue( + c, + collect(keys(inputs)), + collect(values(inputs)); + filter = setBeforeInitialization, + ) @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." end @@ -97,7 +117,12 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3T if !isnothing(x0) #retcode = fmi3SetContinuousStates(c, x0) #@assert retcode == fmi3StatusOK "fmi3Simulate(...): Setting initial state failed with return code $(retcode)." - retcodes = setValue(c, fmu.modelDescription.stateValueReferences, x0; filter=setBeforeInitialization) + retcodes = setValue( + c, + fmu.modelDescription.stateValueReferences, + x0; + filter = setBeforeInitialization, + ) @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." end @@ -109,12 +134,22 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3T # parameters if parameters !== nothing - retcodes = setValue(c, collect(keys(parameters)), collect(values(parameters)); filter=setInInitialization) + retcodes = setValue( + c, + collect(keys(parameters)), + collect(values(parameters)); + filter = setInInitialization, + ) @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial parameters failed with return code $(retcode)." end if inputs !== nothing - retcodes = setValue(c, collect(keys(inputs)), collect(values(inputs)); filter=setInInitialization) + retcodes = setValue( + c, + collect(keys(inputs)), + collect(values(inputs)); + filter = setInInitialization, + ) @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." end @@ -122,7 +157,12 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3T if x0 !== nothing #retcode = fmi3SetContinuousStates(c, x0) #@assert retcode == fmi3StatusOK "fmi3Simulate(...): Setting initial state failed with return code $(retcode)." - retcodes = setValue(c, fmu.modelDescription.stateValueReferences, x0; filter=setInInitialization) + retcodes = setValue( + c, + fmu.modelDescription.stateValueReferences, + x0; + filter = setInInitialization, + ) @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." end @@ -134,7 +174,7 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3T # allocate a solution object c.solution = FMUSolution(c) - + # ME specific if type == fmi3TypeModelExchange if isnothing(x0) && !c.fmu.isZeroState @@ -143,7 +183,7 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3T if instantiate || reset # we have a fresh instance @debug "[NEW INST]" - handleEvents(c) + handleEvents(c) end c.fmu.hasStateEvents = (c.fmu.modelDescription.numberOfEventIndicators > 0) @@ -154,7 +194,7 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3T return c, x0 end -function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::Symbol; kwargs...) +function prepareSolveFMU(fmu::FMU3, c::Union{Nothing,FMU3Instance}, type::Symbol; kwargs...) if type == :CS return prepareSolveFMU(fmu, c, fmi3TypeCoSimulation; kwargs...) elseif type == :ME @@ -166,34 +206,37 @@ function prepareSolveFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::Symbo end end -function finishSolveFMU(fmu::FMU3, c::FMU3Instance; - freeInstance::Union{Nothing, Bool}=nothing, - terminate::Union{Nothing, Bool}=nothing, - popComponent::Bool=true) +function finishSolveFMU( + fmu::FMU3, + c::FMU3Instance; + freeInstance::Union{Nothing,Bool} = nothing, + terminate::Union{Nothing,Bool} = nothing, + popComponent::Bool = true, +) - if isnothing(c) - return + if isnothing(c) + return end ignore_derivatives() do - if c === nothing - return + if c === nothing + return end - - if terminate === nothing + + if terminate === nothing terminate = fmu.executionConfig.terminate end - - if freeInstance === nothing + + if freeInstance === nothing freeInstance = fmu.executionConfig.freeInstance end - + # soft terminate (if necessary) if terminate - retcode = fmi3Terminate(c; soft=true) + retcode = fmi3Terminate(c; soft = true) @assert retcode == fmi3StatusOK "fmi3Simulate(...): Termination failed with return code $(retcode)." end - + # freeInstance (hard) if freeInstance fmi3FreeInstance!(c) @@ -203,10 +246,15 @@ function finishSolveFMU(fmu::FMU3, c::FMU3Instance; return c end -function finishSolveFMU(fmu::Vector{FMU2}, c::AbstractVector{Union{FMU2Component, Nothing}}, freeInstance::Union{Nothing, Bool}, terminate::Union{Nothing, Bool}) +function finishSolveFMU( + fmu::Vector{FMU2}, + c::AbstractVector{Union{FMU2Component,Nothing}}, + freeInstance::Union{Nothing,Bool}, + terminate::Union{Nothing,Bool}, +) ignore_derivatives() do - for i in 1:length(fmu) + for i = 1:length(fmu) if terminate === nothing terminate = fmu[i].executionConfig.terminate end @@ -219,7 +267,7 @@ function finishSolveFMU(fmu::Vector{FMU2}, c::AbstractVector{Union{FMU2Component # soft terminate (if necessary) if terminate - retcode = fmi2Terminate(c[i]; soft=true) + retcode = fmi2Terminate(c[i]; soft = true) @assert retcode == fmi2StatusOK "fmi2Simulate(...): Termination failed with return code $(retcode)." end @@ -234,4 +282,4 @@ function finishSolveFMU(fmu::Vector{FMU2}, c::AbstractVector{Union{FMU2Component end # ignore_derivatives return c -end \ No newline at end of file +end diff --git a/src/binary.jl b/src/binary.jl index 1d6b922..76f53b4 100644 --- a/src/binary.jl +++ b/src/binary.jl @@ -19,7 +19,7 @@ The same as `dlsym(libHandle, symbol)`, but returns - `Ptr{Cvoid}(C_NULL)` if th Library symbol if available, else `Ptr{Cvoid}(C_NULL)`. """ function dlsym_opt(fmu, libHandle, symbol) - addr = dlsym(libHandle, symbol; throw_error=false) + addr = dlsym(libHandle, symbol; throw_error = false) if isnothing(addr) logInfo(fmu, "This FMU does not support the optional function '$symbol'.") addr = Ptr{Cvoid}(C_NULL) @@ -41,9 +41,28 @@ function reload(fmu::FMU) end export reload -function loadFMU(pathToFMU::String; unpackPath=nothing, cleanup=true, type::Union{Symbol, Nothing}=nothing) - - unzippedAbsPath, zipAbsPath = unzip(pathToFMU; unpackPath=unpackPath, cleanup=cleanup) +""" + loadFMU(pathToFMU; unpackPath, cleanup, type) + +Loads an FMU, independent of the used FMI-version (the version is checked during unpacking the archive). + +# Arguments +- `path::String` the path pointing on the FMU file. + +# Keywords +- `unpackPath::Union{String, Nothing}=nothing` the optional unpack path, if `nothing` a temporary directory depending on the OS is picked. +- `cleanup::Bool=true` a boolean indicating whether the temporary directory should be cleaned automatically. +- `type::Union{Symbol, Nothing}=nothing` the type of FMU (:CS, :ME, :SE), if multiple types are available. If `nothing` one of the available types is chosen automatically with the priority CS > ME > SE. +""" +function loadFMU( + pathToFMU::String; + unpackPath::Union{String,Nothing} = nothing, + cleanup::Bool = true, + type::Union{Symbol,Nothing} = nothing, +) + + unzippedAbsPath, zipAbsPath = + unzip(pathToFMU; unpackPath = unpackPath, cleanup = cleanup) # read version tag @@ -55,9 +74,9 @@ function loadFMU(pathToFMU::String; unpackPath=nothing, cleanup=true, type::Unio if version == "1.0" @assert false "FMI version 1.0 deteted, this is (currently) not supported by FMI.jl." elseif version == "2.0" - return createFMU2(unzippedAbsPath, zipAbsPath; type=type) + return createFMU2(unzippedAbsPath, zipAbsPath; type = type) elseif version == "3.0" - return createFMU3(unzippedAbsPath, zipAbsPath; type=type) + return createFMU3(unzippedAbsPath, zipAbsPath; type = type) else @assert false, "Unknwon FMI version `$(version)`." end @@ -77,7 +96,7 @@ Free the allocated memory, close the binaries and remove temporary zip and unzip # Keywords - `secure_pointers=true` whether pointers to C-functions should be overwritten with dummies with Julia assertions, instead of pointing to dead memory (slower, but more user safe) """ -function unloadFMU(fmu::FMU2, cleanUp::Bool=true; secure_pointers::Bool=true) +function unloadFMU(fmu::FMU2, cleanUp::Bool = true; secure_pointers::Bool = true) while length(fmu.components) > 0 c = fmu.components[end] @@ -95,7 +114,7 @@ function unloadFMU(fmu::FMU2, cleanUp::Bool=true; secure_pointers::Bool=true) # the components are removed from the component list via call to fmi2FreeInstance! @assert length(fmu.components) == 0 "fmi2Unload(...): Failure during deleting components, $(length(fmu.components)) remaining in stack." - + if secure_pointers unloadPointers(fmu) end @@ -111,7 +130,7 @@ function unloadFMU(fmu::FMU2, cleanUp::Bool=true; secure_pointers::Bool=true) end end end -function unloadFMU(fmu::FMU3, cleanUp::Bool=true) +function unloadFMU(fmu::FMU3, cleanUp::Bool = true) while length(fmu.instances) > 0 fmi3FreeInstance!(fmu.instances[end]) @@ -131,4 +150,4 @@ function unloadFMU(fmu::FMU3, cleanUp::Bool=true) end end end -export unloadFMU \ No newline at end of file +export unloadFMU diff --git a/src/convert.jl b/src/convert.jl index 082ef4e..c8a9c23 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -8,7 +8,11 @@ Returns the solution state for a given value reference `i` (for `isIndex=false`) or the i-th state (for `isIndex=true`). """ -function getState(solution::FMUSolution, vrs::fmi2ValueReferenceFormat; isIndex::Bool=false) +function getState( + solution::FMUSolution, + vrs::fmi2ValueReferenceFormat; + isIndex::Bool = false, +) indices = [] @@ -25,10 +29,14 @@ function getState(solution::FMUSolution, vrs::fmi2ValueReferenceFormat; isIndex: if !isnothing(solution.states) for vr in vrs found = false - for i in 1:length(solution.component.fmu.modelDescription.stateValueReferences) - if solution.component.fmu.modelDescription.stateValueReferences[i] == vr + for i = + 1:length( + solution.component.fmu.modelDescription.stateValueReferences, + ) + if solution.component.fmu.modelDescription.stateValueReferences[i] == + vr push!(indices, i) - found = true + found = true break end end @@ -46,7 +54,9 @@ function getState(solution::FMUSolution, vrs::fmi2ValueReferenceFormat; isIndex: return collect(u[indices[1]] for u in solution.states.u) else # multi value - return collect(collect(u[indices[i]] for u in solution.states.u) for i in 1:length(indices)) + return collect( + collect(u[indices[i]] for u in solution.states.u) for i = 1:length(indices) + ) end end @@ -60,7 +70,12 @@ export getState Returns the solution state derivative for a given value reference `i` (for `isIndex=false`) or the i-th state (for `isIndex=true`). """ -function getStateDerivative(solution::FMUSolution, vrs::fmi2ValueReferenceFormat; isIndex::Bool=false, order::Integer=1) +function getStateDerivative( + solution::FMUSolution, + vrs::fmi2ValueReferenceFormat; + isIndex::Bool = false, + order::Integer = 1, +) indices = [] if isIndex @@ -76,10 +91,14 @@ function getStateDerivative(solution::FMUSolution, vrs::fmi2ValueReferenceFormat if !isnothing(solution.states) for vr in vrs found = false - for i in 1:length(solution.component.fmu.modelDescription.stateValueReferences) - if solution.component.fmu.modelDescription.stateValueReferences[i] == vr + for i = + 1:length( + solution.component.fmu.modelDescription.stateValueReferences, + ) + if solution.component.fmu.modelDescription.stateValueReferences[i] == + vr push!(indices, i) - found = true + found = true break end end @@ -94,10 +113,16 @@ function getStateDerivative(solution::FMUSolution, vrs::fmi2ValueReferenceFormat if length(indices) == length(vrs) if length(vrs) == 1 # single value - return collect(solution.states(t, Val{order})[indices[1]] for t in solution.states.t) + return collect( + solution.states(t, Val{order})[indices[1]] for t in solution.states.t + ) else # multi value - return collect(collect(solution.states(t, Val{order})[indices[i]] for t in solution.states.t) for i in 1:length(indices)) + return collect( + collect( + solution.states(t, Val{order})[indices[i]] for t in solution.states.t + ) for i = 1:length(indices) + ) end end @@ -111,7 +136,11 @@ export getStateDerivative Returns the values for a given value reference `i` (for `isIndex=false`) or the i-th value (for `isIndex=true`). Recording of values must be enabled. """ -function FMIBase.getValue(solution::FMUSolution, vrs::fmi2ValueReferenceFormat; isIndex::Bool=false) +function FMIBase.getValue( + solution::FMUSolution, + vrs::fmi2ValueReferenceFormat; + isIndex::Bool = false, +) indices = [] @@ -128,10 +157,10 @@ function FMIBase.getValue(solution::FMUSolution, vrs::fmi2ValueReferenceFormat; if !isnothing(solution.values) for vr in vrs found = false - for i in 1:length(solution.valueReferences) + for i = 1:length(solution.valueReferences) if solution.valueReferences[i] == vr push!(indices, i) - found = true + found = true break end end @@ -149,7 +178,10 @@ function FMIBase.getValue(solution::FMUSolution, vrs::fmi2ValueReferenceFormat; return collect(u[indices[1]] for u in solution.values.saveval) else # multi value - return collect(collect(u[indices[i]] for u in solution.values.saveval) for i in 1:length(indices)) + return collect( + collect(u[indices[i]] for u in solution.values.saveval) for + i = 1:length(indices) + ) end end @@ -172,4 +204,4 @@ function getTime(solution::FMUSolution) return nothing end end -export getTime \ No newline at end of file +export getTime diff --git a/src/info.jl b/src/info.jl index d53f5e0..b472e2c 100644 --- a/src/info.jl +++ b/src/info.jl @@ -4,14 +4,14 @@ # # Prints value references, but shortens if the number exceeds `max`. -function printValueReferences(fmu, vrs; max=10) +function printValueReferences(fmu, vrs; max = 10) len = length(vrs) if len <= max for vr in vrs println("\t\t$(vr) $(valueReferenceToString(fmu, vr))") end else - half = floor(Integer, max)-1 + half = floor(Integer, max) - 1 for vr in vrs[1:half] println("\t\t$(vr) $(valueReferenceToString(fmu, vr))") end @@ -68,22 +68,44 @@ function info(fmu::FMU2) println("\tSupports Co-Simulation:\t\t$(isCoSimulation(fmu))") if isCoSimulation(fmu) - println("\t\tModel identifier:\t$(fmu.modelDescription.coSimulation.modelIdentifier)") - println("\t\tGet/Set State:\t\t$(fmu.modelDescription.coSimulation.canGetAndSetFMUstate)") - println("\t\tSerialize State:\t$(fmu.modelDescription.coSimulation.canSerializeFMUstate)") - println("\t\tDir. Derivatives:\t$(fmu.modelDescription.coSimulation.providesDirectionalDerivative)") - - println("\t\tVar. com. steps:\t$(fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize)") - println("\t\tInput interpol.:\t$(fmu.modelDescription.coSimulation.canInterpolateInputs)") - println("\t\tMax order out. der.:\t$(fmu.modelDescription.coSimulation.maxOutputDerivativeOrder)") + println( + "\t\tModel identifier:\t$(fmu.modelDescription.coSimulation.modelIdentifier)", + ) + println( + "\t\tGet/Set State:\t\t$(fmu.modelDescription.coSimulation.canGetAndSetFMUstate)", + ) + println( + "\t\tSerialize State:\t$(fmu.modelDescription.coSimulation.canSerializeFMUstate)", + ) + println( + "\t\tDir. Derivatives:\t$(fmu.modelDescription.coSimulation.providesDirectionalDerivative)", + ) + + println( + "\t\tVar. com. steps:\t$(fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize)", + ) + println( + "\t\tInput interpol.:\t$(fmu.modelDescription.coSimulation.canInterpolateInputs)", + ) + println( + "\t\tMax order out. der.:\t$(fmu.modelDescription.coSimulation.maxOutputDerivativeOrder)", + ) end println("\tSupports Model-Exchange:\t$(isModelExchange(fmu))") if isModelExchange(fmu) - println("\t\tModel identifier:\t$(fmu.modelDescription.modelExchange.modelIdentifier)") - println("\t\tGet/Set State:\t\t$(fmu.modelDescription.modelExchange.canGetAndSetFMUstate)") - println("\t\tSerialize State:\t$(fmu.modelDescription.modelExchange.canSerializeFMUstate)") - println("\t\tDir. Derivatives:\t$(fmu.modelDescription.modelExchange.providesDirectionalDerivative)") + println( + "\t\tModel identifier:\t$(fmu.modelDescription.modelExchange.modelIdentifier)", + ) + println( + "\t\tGet/Set State:\t\t$(fmu.modelDescription.modelExchange.canGetAndSetFMUstate)", + ) + println( + "\t\tSerialize State:\t$(fmu.modelDescription.modelExchange.canSerializeFMUstate)", + ) + println( + "\t\tDir. Derivatives:\t$(fmu.modelDescription.modelExchange.providesDirectionalDerivative)", + ) end println("##################### End information for FMU #####################") @@ -101,7 +123,7 @@ function info(fmu::FMU3) println("flat") elseif getVariableNamingConvention(fmu) == fmi3VariableNamingConventionStructured println("structured") - else + else println("[unknown]") end println("\tEvent indicators:\t\t$(getNumberOfEventIndicators(fmu))") @@ -120,38 +142,80 @@ function info(fmu::FMU3) println("\tSupports Co-Simulation:\t\t$(isCoSimulation(fmu))") if isCoSimulation(fmu) - println("\t\tModel identifier:\t$(fmu.modelDescription.coSimulation.modelIdentifier)") - println("\t\tGet/Set State:\t\t$(fmu.modelDescription.coSimulation.canGetAndSetFMUState)") - println("\t\tSerialize State:\t$(fmu.modelDescription.coSimulation.canSerializeFMUState)") - println("\t\tDir. Derivatives:\t$(fmu.modelDescription.coSimulation.providesDirectionalDerivatives)") - println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.coSimulation.providesAdjointDerivatives)") + println( + "\t\tModel identifier:\t$(fmu.modelDescription.coSimulation.modelIdentifier)", + ) + println( + "\t\tGet/Set State:\t\t$(fmu.modelDescription.coSimulation.canGetAndSetFMUState)", + ) + println( + "\t\tSerialize State:\t$(fmu.modelDescription.coSimulation.canSerializeFMUState)", + ) + println( + "\t\tDir. Derivatives:\t$(fmu.modelDescription.coSimulation.providesDirectionalDerivatives)", + ) + println( + "\t\tAdj. Derivatives:\t$(fmu.modelDescription.coSimulation.providesAdjointDerivatives)", + ) println("\t\tEvent Mode:\t$(fmu.modelDescription.coSimulation.hasEventMode)") - println("\t\tVar. com. steps:\t$(fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize)") - println("\t\tInput interpol.:\t$(fmu.modelDescription.coSimulation.canInterpolateInputs)") - println("\t\tMax order out. der.:\t$(fmu.modelDescription.coSimulation.maxOutputDerivativeOrder)") + println( + "\t\tVar. com. steps:\t$(fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize)", + ) + println( + "\t\tInput interpol.:\t$(fmu.modelDescription.coSimulation.canInterpolateInputs)", + ) + println( + "\t\tMax order out. der.:\t$(fmu.modelDescription.coSimulation.maxOutputDerivativeOrder)", + ) end println("\tSupports Model-Exchange:\t$(isModelExchange(fmu))") if isModelExchange(fmu) - println("\t\tModel identifier:\t$(fmu.modelDescription.modelExchange.modelIdentifier)") - println("\t\tGet/Set State:\t\t$(fmu.modelDescription.modelExchange.canGetAndSetFMUState)") - println("\t\tSerialize State:\t$(fmu.modelDescription.modelExchange.canSerializeFMUState)") - println("\t\tDir. Derivatives:\t$(fmu.modelDescription.modelExchange.providesDirectionalDerivatives)") - println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.modelExchange.providesAdjointDerivatives)") + println( + "\t\tModel identifier:\t$(fmu.modelDescription.modelExchange.modelIdentifier)", + ) + println( + "\t\tGet/Set State:\t\t$(fmu.modelDescription.modelExchange.canGetAndSetFMUState)", + ) + println( + "\t\tSerialize State:\t$(fmu.modelDescription.modelExchange.canSerializeFMUState)", + ) + println( + "\t\tDir. Derivatives:\t$(fmu.modelDescription.modelExchange.providesDirectionalDerivatives)", + ) + println( + "\t\tAdj. Derivatives:\t$(fmu.modelDescription.modelExchange.providesAdjointDerivatives)", + ) end println("\tSupports Scheduled-Execution:\t$(isScheduledExecution(fmu))") if isScheduledExecution(fmu) - println("\t\tModel identifier:\t$(fmu.modelDescription.scheduledExecution.modelIdentifier)") - println("\t\tGet/Set State:\t\t$(fmu.modelDescription.scheduledExecution.canGetAndSetFMUState)") - println("\t\tSerialize State:\t$(fmu.modelDescription.scheduledExecution.canSerializeFMUState)") - println("\t\tNeeds Execution Tool:\t$(fmu.modelDescription.scheduledExecution.needsExecutionTool)") - println("\t\tInstantiated Once Per Process:\t$(fmu.modelDescription.scheduledExecution.canBeInstantiatedOnlyOncePerProcess)") - println("\t\tPer Element Dependencies:\t$(fmu.modelDescription.scheduledExecution.providesPerElementDependencies)") - - println("\t\tDir. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesDirectionalDerivatives)") - println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesAdjointDerivatives)") + println( + "\t\tModel identifier:\t$(fmu.modelDescription.scheduledExecution.modelIdentifier)", + ) + println( + "\t\tGet/Set State:\t\t$(fmu.modelDescription.scheduledExecution.canGetAndSetFMUState)", + ) + println( + "\t\tSerialize State:\t$(fmu.modelDescription.scheduledExecution.canSerializeFMUState)", + ) + println( + "\t\tNeeds Execution Tool:\t$(fmu.modelDescription.scheduledExecution.needsExecutionTool)", + ) + println( + "\t\tInstantiated Once Per Process:\t$(fmu.modelDescription.scheduledExecution.canBeInstantiatedOnlyOncePerProcess)", + ) + println( + "\t\tPer Element Dependencies:\t$(fmu.modelDescription.scheduledExecution.providesPerElementDependencies)", + ) + + println( + "\t\tDir. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesDirectionalDerivatives)", + ) + println( + "\t\tAdj. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesAdjointDerivatives)", + ) end println("##################### End information for FMU #####################") diff --git a/src/jacobian.jl b/src/jacobian.jl index 85324b2..a2b0a44 100644 --- a/src/jacobian.jl +++ b/src/jacobian.jl @@ -41,10 +41,12 @@ Computes a linear combination of the partial derivatives of h with respect to th See also [`fmi2GetDirectionalDerivative!`](@ref). """ -function sampleJacobian(c::FMU2Component, - vUnknown_ref::AbstractArray{fmi2ValueReference}, - vKnown_ref::AbstractArray{fmi2ValueReference}, - steps::Union{AbstractArray{fmi2Real}, Nothing} = nothing) +function sampleJacobian( + c::FMU2Component, + vUnknown_ref::AbstractArray{fmi2ValueReference}, + vKnown_ref::AbstractArray{fmi2ValueReference}, + steps::Union{AbstractArray{fmi2Real},Nothing} = nothing, +) mtx = zeros(fmi2Real, length(vUnknown_ref), length(vKnown_ref)) @@ -95,18 +97,20 @@ Computes a linear combination of the partial derivatives of h with respect to th See also [`fmi2GetDirectionalDerivative!`](@ref). """ -function sampleJacobian!(mtx::Matrix{<:Real}, - c::FMU2Component, - vUnknown_ref::AbstractArray{fmi2ValueReference}, - vKnown_ref::AbstractArray{fmi2ValueReference}, - steps::Union{AbstractArray{fmi2Real}, Nothing} = nothing) +function sampleJacobian!( + mtx::Matrix{<:Real}, + c::FMU2Component, + vUnknown_ref::AbstractArray{fmi2ValueReference}, + vKnown_ref::AbstractArray{fmi2ValueReference}, + steps::Union{AbstractArray{fmi2Real},Nothing} = nothing, +) step = 0.0 negValues = zeros(length(vUnknown_ref)) posValues = zeros(length(vUnknown_ref)) - for i in 1:length(vKnown_ref) + for i = 1:length(vKnown_ref) vKnown = vKnown_ref[i] origValue = fmi2GetReal(c, vKnown) @@ -117,29 +121,31 @@ function sampleJacobian!(mtx::Matrix{<:Real}, step = steps[i] end - fmi2SetReal(c, vKnown, origValue - step; track=false) + fmi2SetReal(c, vKnown, origValue - step; track = false) fmi2GetReal!(c, vUnknown_ref, negValues) - fmi2SetReal(c, vKnown, origValue + step; track=false) + fmi2SetReal(c, vKnown, origValue + step; track = false) fmi2GetReal!(c, vUnknown_ref, posValues) - fmi2SetReal(c, vKnown, origValue; track=false) + fmi2SetReal(c, vKnown, origValue; track = false) if length(vUnknown_ref) == 1 - mtx[1,i] = (posValues-negValues) ./ (step * 2.0) + mtx[1, i] = (posValues - negValues) ./ (step * 2.0) else - mtx[:,i] = (posValues-negValues) ./ (step * 2.0) + mtx[:, i] = (posValues - negValues) ./ (step * 2.0) end end nothing end -function sampleJacobian!(mtx::Matrix{<:Real}, +function sampleJacobian!( + mtx::Matrix{<:Real}, c::FMU2Component, vUnknown_ref::Symbol, vKnown_ref::AbstractArray{fmi2ValueReference}, - steps::Union{AbstractArray{fmi2Real}, Nothing} = nothing) + steps::Union{AbstractArray{fmi2Real},Nothing} = nothing, +) @assert vUnknown_ref == :indicators "vUnknown_ref::Symbol must be `:indicators`!" @@ -150,7 +156,7 @@ function sampleJacobian!(mtx::Matrix{<:Real}, negValues = zeros(len_vUnknown_ref) posValues = zeros(len_vUnknown_ref) - for i in 1:length(vKnown_ref) + for i = 1:length(vKnown_ref) vKnown = vKnown_ref[i] origValue = fmi2GetReal(c, vKnown) @@ -160,29 +166,31 @@ function sampleJacobian!(mtx::Matrix{<:Real}, step = steps[i] end - fmi2SetReal(c, vKnown, origValue - step; track=false) + fmi2SetReal(c, vKnown, origValue - step; track = false) fmi2GetEventIndicators!(c, negValues) - fmi2SetReal(c, vKnown, origValue + step; track=false) + fmi2SetReal(c, vKnown, origValue + step; track = false) fmi2GetEventIndicators!(c, posValues) - fmi2SetReal(c, vKnown, origValue; track=false) + fmi2SetReal(c, vKnown, origValue; track = false) if len_vUnknown_ref == 1 - mtx[1,i] = (posValues-negValues) ./ (step * 2.0) + mtx[1, i] = (posValues - negValues) ./ (step * 2.0) else - mtx[:,i] = (posValues-negValues) ./ (step * 2.0) + mtx[:, i] = (posValues - negValues) ./ (step * 2.0) end end nothing end -function sampleJacobian!(mtx::Matrix{<:Real}, +function sampleJacobian!( + mtx::Matrix{<:Real}, c::FMU2Component, vUnknown_ref::AbstractArray{fmi2ValueReference}, vKnown_ref::Symbol, - steps::Union{AbstractArray{fmi2Real}, Nothing} = nothing) + steps::Union{AbstractArray{fmi2Real},Nothing} = nothing, +) @assert vKnown_ref == :time "vKnown_ref::Symbol must be `:time`!" @@ -191,7 +199,7 @@ function sampleJacobian!(mtx::Matrix{<:Real}, negValues = zeros(length(vUnknown_ref)) posValues = zeros(length(vUnknown_ref)) - for i in 1:length(vKnown_ref) + for i = 1:length(vKnown_ref) vKnown = vKnown_ref[i] origValue = fmi2GetReal(c, vKnown) @@ -201,18 +209,18 @@ function sampleJacobian!(mtx::Matrix{<:Real}, step = steps[i] end - fmi2SetReal(c, vKnown, origValue - step; track=false) + fmi2SetReal(c, vKnown, origValue - step; track = false) fmi2GetEventIndicators!(c, negValues) - fmi2SetReal(c, vKnown, origValue + step; track=false) + fmi2SetReal(c, vKnown, origValue + step; track = false) fmi2GetEventIndicators!(c, posValues) - fmi2SetReal(c, vKnown, origValue; track=false) + fmi2SetReal(c, vKnown, origValue; track = false) if length(vUnknown_ref) == 1 - mtx[1,i] = (posValues-negValues) ./ (step * 2.0) + mtx[1, i] = (posValues - negValues) ./ (step * 2.0) else - mtx[:,i] = (posValues-negValues) ./ (step * 2.0) + mtx[:, i] = (posValues - negValues) ./ (step * 2.0) end end @@ -247,12 +255,14 @@ For optimization, if the FMU's model description has the optional entry 'depende - FMISpec2.0.2: 2.2.7 Definition of Model Variables (ModelVariables) """ -function getJacobian(comp::FMU2Component, - rdx::AbstractArray{fmi2ValueReference}, - rx::AbstractArray{fmi2ValueReference}; - steps::Union{AbstractArray{fmi2Real}, Nothing} = nothing) +function getJacobian( + comp::FMU2Component, + rdx::AbstractArray{fmi2ValueReference}, + rx::AbstractArray{fmi2ValueReference}; + steps::Union{AbstractArray{fmi2Real},Nothing} = nothing, +) mat = zeros(fmi2Real, length(rdx), length(rx)) - fmi2GetJacobian!(mat, comp, rdx, rx; steps=steps) + fmi2GetJacobian!(mat, comp, rdx, rx; steps = steps) return mat end @@ -286,13 +296,17 @@ For optimization, if the FMU's model description has the optional entry 'depende - FMISpec2.0.2: 2.2.7 Definition of Model Variables (ModelVariables) """ -function getJacobian!(jac::AbstractMatrix{fmi2Real}, - comp::FMU2Component, - rdx::AbstractArray{fmi2ValueReference}, - rx::AbstractArray{fmi2ValueReference}; - steps::Union{AbstractArray{fmi2Real}, Nothing} = nothing) - - @assert size(jac) == (length(rdx), length(rx)) ["fmi2GetJacobian!: Dimension missmatch between `jac` $(size(jac)), `rdx` $(length(rdx)) and `rx` $(length(rx))."] +function getJacobian!( + jac::AbstractMatrix{fmi2Real}, + comp::FMU2Component, + rdx::AbstractArray{fmi2ValueReference}, + rx::AbstractArray{fmi2ValueReference}; + steps::Union{AbstractArray{fmi2Real},Nothing} = nothing, +) + + @assert size(jac) == (length(rdx), length(rx)) [ + "fmi2GetJacobian!: Dimension missmatch between `jac` $(size(jac)), `rdx` $(length(rdx)) and `rx` $(length(rx)).", + ] if length(rdx) == 0 || length(rx) == 0 jac = zeros(length(rdx), length(rx)) @@ -302,9 +316,9 @@ function getJacobian!(jac::AbstractMatrix{fmi2Real}, # ToDo: Pick entries based on dependency matrix! #depMtx = fmi2GetDependencies(fmu) rdx_inds = collect(comp.fmu.modelDescription.valueReferenceIndicies[vr] for vr in rdx) - rx_inds = collect(comp.fmu.modelDescription.valueReferenceIndicies[vr] for vr in rx) + rx_inds = collect(comp.fmu.modelDescription.valueReferenceIndicies[vr] for vr in rx) - for i in 1:length(rx) + for i = 1:length(rx) sensitive_rdx_inds = 1:length(rdx) sensitive_rdx = rdx @@ -321,7 +335,12 @@ function getJacobian!(jac::AbstractMatrix{fmi2Real}, if length(sensitive_rdx) > 0 - fmi2GetDirectionalDerivative!(comp, sensitive_rdx, [rx[i]], view(jac, sensitive_rdx_inds, i)) + fmi2GetDirectionalDerivative!( + comp, + sensitive_rdx, + [rx[i]], + view(jac, sensitive_rdx_inds, i), + ) # jac[sensitive_rdx_inds, i] = fmi2GetDirectionalDerivative(comp, sensitive_rdx, [rx[i]]) @@ -329,4 +348,4 @@ function getJacobian!(jac::AbstractMatrix{fmi2Real}, end return nothing -end \ No newline at end of file +end diff --git a/src/md_parse.jl b/src/md_parse.jl index e641aa8..f674449 100644 --- a/src/md_parse.jl +++ b/src/md_parse.jl @@ -3,15 +3,15 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # -function parseNode(node, key, type::DataType=String; onfail=nothing) +function parseNode(node, key, type::DataType = String; onfail = nothing) if haskey(node, key) - return parseType(node[key], type; onfail=onfail) + return parseType(node[key], type; onfail = onfail) else return onfail end end -function parseType(s::Union{String, SubString{String}}, type; onfail=nothing) +function parseType(s::Union{String,SubString{String}}, type; onfail = nothing) if onfail == nothing return _parse(type, s) else @@ -35,7 +35,7 @@ function _parse(type, s) end end -parseNodeBoolean(node, key; onfail=nothing) = parseNode(node, key, Bool; onfail=onfail) +parseNodeBoolean(node, key; onfail = nothing) = parseNode(node, key, Bool; onfail = onfail) # function parseNodeBoolean(node, key; onfail=nothing) # if haskey(node, key) @@ -66,26 +66,32 @@ parseNodeBoolean(node, key; onfail=nothing) = parseNode(node, key, Bool; onfail= # end # [Todo] -function parseArrayValueReferences(md::fmi2ModelDescription, s::Union{String, SubString{String}}) +function parseArrayValueReferences( + md::fmi2ModelDescription, + s::Union{String,SubString{String}}, +) references = Array{fmi2ValueReference}(undef, 0) substrings = split(s, " ") for string in substrings push!(references, parse(fmi2ValueReferenceFormat, string)) end - + return references end -function parseArrayValueReferences(md::fmi3ModelDescription, s::Union{String, SubString{String}}) +function parseArrayValueReferences( + md::fmi3ModelDescription, + s::Union{String,SubString{String}}, +) references = Array{fmi3ValueReference}(undef, 0) substrings = split(s, " ") for string in substrings push!(references, parse(fmi3ValueReferenceFormat, string)) end - + return references end function parseArrayValueReferences(md::fmiModelDescription, s::Nothing) return nothing -end \ No newline at end of file +end diff --git a/src/zip.jl b/src/zip.jl index 0ac39ea..ef4b474 100644 --- a/src/zip.jl +++ b/src/zip.jl @@ -25,7 +25,7 @@ Returns the paths to the zipped and unzipped folders. See also [`mktempdir`](https://docs.julialang.org/en/v1/base/file/#Base.Filesystem.mktempdir-Tuple{AbstractString}). """ -function unzip(pathToFMU::String; unpackPath=nothing, cleanup=true) +function unzip(pathToFMU::String; unpackPath = nothing, cleanup = true) if startswith(pathToFMU, "http") pathToFMU = Downloads.download(pathToFMU) @@ -36,7 +36,7 @@ function unzip(pathToFMU::String; unpackPath=nothing, cleanup=true) if unpackPath == nothing # cleanup = true leads to issues with automatic testing on linux server. - unpackPath = mktempdir(; prefix="fmijl_", cleanup=cleanup) + unpackPath = mktempdir(; prefix = "fmijl_", cleanup = cleanup) end zipPath = joinpath(unpackPath, fileName * ".zip") @@ -44,12 +44,12 @@ function unzip(pathToFMU::String; unpackPath=nothing, cleanup=true) # only copy ZIP if not already there if !isfile(zipPath) - cp(pathToFMU, zipPath; force=true) + cp(pathToFMU, zipPath; force = true) end @assert isfile(zipPath) ["unzip(...): ZIP-Archive couldn't be copied to `$zipPath`."] - zipAbsPath = isabspath(zipPath) ? zipPath : joinpath(pwd(), zipPath) + zipAbsPath = isabspath(zipPath) ? zipPath : joinpath(pwd(), zipPath) unzippedAbsPath = isabspath(unzippedPath) ? unzippedPath : joinpath(pwd(), unzippedPath) @assert isfile(zipAbsPath) ["unzip(...): Can't deploy ZIP-Archive at `$(zipAbsPath)`."] @@ -64,10 +64,12 @@ function unzip(pathToFMU::String; unpackPath=nothing, cleanup=true) for f in zarchive.files fileAbsPath = normpath(joinpath(unzippedAbsPath, f.name)) - if endswith(f.name,"/") || endswith(f.name,"\\") + if endswith(f.name, "/") || endswith(f.name, "\\") mkpath(fileAbsPath) # mkdir(fileAbsPath) - @assert isdir(fileAbsPath) ["unzip(...): Can't create directory `$(f.name)` at `$(fileAbsPath)`."] + @assert isdir(fileAbsPath) [ + "unzip(...): Can't create directory `$(f.name)` at `$(fileAbsPath)`.", + ] else # create directory if not forced by zip file folder mkpath(dirname(fileAbsPath)) @@ -78,15 +80,19 @@ function unzip(pathToFMU::String; unpackPath=nothing, cleanup=true) @debug "unzip(...): Written file `$(f.name)`, but file is empty." end - @assert isfile(fileAbsPath) ["unzip(...): Can't unzip file `$(f.name)` at `$(fileAbsPath)`."] + @assert isfile(fileAbsPath) [ + "unzip(...): Can't unzip file `$(f.name)` at `$(fileAbsPath)`.", + ] numFiles += 1 end end close(zarchive) end - @assert isdir(unzippedAbsPath) ["unzip(...): ZIP-Archive couldn't be unzipped at `$(unzippedPath)`."] + @assert isdir(unzippedAbsPath) [ + "unzip(...): ZIP-Archive couldn't be unzipped at `$(unzippedPath)`.", + ] @debug "funzip(...): Successfully unzipped $numFiles files at `$unzippedAbsPath`." (unzippedAbsPath, zipAbsPath) -end \ No newline at end of file +end diff --git a/test/FMI2/externalLogging.jl b/test/FMI2/externalLogging.jl index 6d2e66a..05a36e2 100644 --- a/test/FMI2/externalLogging.jl +++ b/test/FMI2/externalLogging.jl @@ -9,7 +9,7 @@ myFMU = loadFMU("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION" myFMU.executionConfig.assertOnError = false ### CASE A: Print log ### -comp = fmi2Instantiate!(myFMU; loggingOn=true, externalCallbacks=true) +comp = fmi2Instantiate!(myFMU; loggingOn = true, externalCallbacks = true) @test comp != 0 @info "The following warning is forced and not an issue:" @@ -20,7 +20,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi2SetupExperiment(comp) == fmi2StatusOK end end - end + end end # [ToDo]: the following test is wrong / not working (capture doesn't work for color output) @@ -31,7 +31,12 @@ end ### CASE B: Print log, but catch infos ### -comp = fmi2Instantiate!(myFMU; loggingOn=true, logStatusError=false, externalCallbacks=true) +comp = fmi2Instantiate!( + myFMU; + loggingOn = true, + logStatusError = false, + externalCallbacks = true, +) @test comp != 0 # # deactivate errors to capture them @@ -46,7 +51,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi2ExitInitializationMode(comp) == fmi2StatusError end end - end + end end # ToDo: this test is wrong / not working (capture doesn't work for color output) @@ -64,7 +69,7 @@ end ### CASE C: Disable Log ### -comp = fmi2Instantiate!(myFMU; loggingOn=false, externalCallbacks=true) +comp = fmi2Instantiate!(myFMU; loggingOn = false, externalCallbacks = true) @test comp != 0 @info "The following warning is forced and not an issue:" @@ -75,7 +80,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi2SetupExperiment(comp) == fmi2StatusOK end end - end + end end # ToDo: this test is wrong / not working (capture doesn't work for color output) #output = read(joinpath(pwd(), "stdout"), String) diff --git a/test/FMI2/getter_setter.jl b/test/FMI2/getter_setter.jl index 2b9e3bc..c923386 100644 --- a/test/FMI2/getter_setter.jl +++ b/test/FMI2/getter_setter.jl @@ -9,7 +9,7 @@ myFMU = loadFMU("IO", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -comp = fmi2Instantiate!(myFMU; loggingOn=false) +comp = fmi2Instantiate!(myFMU; loggingOn = false) @test comp != 0 @test fmi2SetupExperiment(comp, 0.0) == 0 @@ -53,12 +53,25 @@ cacheString = "" @test fmi2SetString(comp, stringValueReferences[1], rndString) == 0 @test fmi2GetString(comp, stringValueReferences[1]) == rndString -setValue(comp, - [realValueReferences[1], integerValueReferences[1], booleanValueReferences[1], stringValueReferences[1]], - [rndReal, rndInteger, rndBoolean, rndString]) -@test getValue(comp, - [realValueReferences[1], integerValueReferences[1], booleanValueReferences[1], stringValueReferences[1]]) == - [rndReal, rndInteger, rndBoolean, rndString] +setValue( + comp, + [ + realValueReferences[1], + integerValueReferences[1], + booleanValueReferences[1], + stringValueReferences[1], + ], + [rndReal, rndInteger, rndBoolean, rndString], +) +@test getValue( + comp, + [ + realValueReferences[1], + integerValueReferences[1], + booleanValueReferences[1], + stringValueReferences[1], + ], +) == [rndReal, rndInteger, rndBoolean, rndString] ################## # Testing Arrays # @@ -71,7 +84,7 @@ tmp = Random.randstring(8) rndString = [tmp, tmp] cacheReal = [0.0, 0.0] -cacheInteger = [fmi2Integer(0), fmi2Integer(0)] +cacheInteger = [fmi2Integer(0), fmi2Integer(0)] cacheBoolean = [fmi2Boolean(false), fmi2Boolean(false)] cacheString = [pointer(""), pointer("")] diff --git a/test/FMI2/logging.jl b/test/FMI2/logging.jl index 490c7b7..8cb931b 100644 --- a/test/FMI2/logging.jl +++ b/test/FMI2/logging.jl @@ -10,7 +10,7 @@ myFMU.executionConfig.assertOnError = false myFMU.executionConfig.assertOnWarning = false ### CASE A: Print log ### -comp = fmi2Instantiate!(myFMU; loggingOn=true) +comp = fmi2Instantiate!(myFMU; loggingOn = true) @test comp != 0 @info "The following warning is forced and not an issue:" @@ -21,7 +21,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi2SetupExperiment(comp) == fmi2StatusOK end end - end + end end # ToDo: this test is wrong / not working (capture doesn't work for color output) #output = read(joinpath(pwd(), "stdout"), String) @@ -31,7 +31,7 @@ end ### CASE B: Print log, but catch infos ### -comp = fmi2Instantiate!(myFMU; loggingOn=true, logStatusError=false) +comp = fmi2Instantiate!(myFMU; loggingOn = true, logStatusError = false) @test comp != 0 # # deactivate errors to capture them @@ -46,7 +46,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi2ExitInitializationMode(comp) == fmi2StatusError end end - end + end end if VERSION >= v"1.7.0" @@ -57,12 +57,15 @@ if VERSION >= v"1.7.0" output = read(joinpath(pwd(), "stderr"), String) println(output) - @test startswith(output, "┌ Warning: fmi2ExitInitializationMode(...): Needs to be called in state `fmi2ComponentStateInitializationMode`.\n") -end + @test startswith( + output, + "┌ Warning: fmi2ExitInitializationMode(...): Needs to be called in state `fmi2ComponentStateInitializationMode`.\n", + ) +end ### CASE C: Disable Log ### -comp = fmi2Instantiate!(myFMU; loggingOn=false) +comp = fmi2Instantiate!(myFMU; loggingOn = false) @test comp != 0 @info "The following warning is forced and not an issue:" @@ -73,7 +76,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi2SetupExperiment(comp) == fmi2StatusOK end end - end + end end # [ToDo]: the following test is wrong / not working (capture doesn't work for color output) diff --git a/test/FMI2/model_description.jl b/test/FMI2/model_description.jl index 1cbee24..eb99c61 100644 --- a/test/FMI2/model_description.jl +++ b/test/FMI2/model_description.jl @@ -44,19 +44,34 @@ info(myFMU) # check if there is an error thrown @test length(getOutputNames(myFMU)) == 0 @test length(getParameterNames(myFMU.modelDescription)) == 12 -@test getParameterNames(myFMU) == ["fricScale", "s0", "v0", "fixed.s0", "spring.c", "spring.s_rel0", "mass.smax", "mass.smin", "mass.v_small", "mass.L", "mass.m", "mass.fexp"] +@test getParameterNames(myFMU) == [ + "fricScale", + "s0", + "v0", + "fixed.s0", + "spring.c", + "spring.s_rel0", + "mass.smax", + "mass.smin", + "mass.v_small", + "mass.L", + "mass.m", + "mass.fexp", +] @test length(getStateNames(myFMU.modelDescription)) == 2 @test length(getStateNames(myFMU)) == 2 -@test getStateNames(myFMU; mode=:first) == ["mass.s", "mass.v"] -@test getStateNames(myFMU; mode=:flat) == ["mass.s", "mass.v", "mass.v_relfric"] -@test getStateNames(myFMU; mode=:group) == [["mass.s"], ["mass.v", "mass.v_relfric"]] +@test getStateNames(myFMU; mode = :first) == ["mass.s", "mass.v"] +@test getStateNames(myFMU; mode = :flat) == ["mass.s", "mass.v", "mass.v_relfric"] +@test getStateNames(myFMU; mode = :group) == [["mass.s"], ["mass.v", "mass.v_relfric"]] @test length(getDerivativeNames(myFMU.modelDescription)) == 2 @test length(getDerivativeNames(myFMU)) == 2 -@test getDerivativeNames(myFMU; mode=:first) == ["der(mass.s)", "mass.a_relfric"] -@test getDerivativeNames(myFMU; mode=:flat) == ["der(mass.s)", "mass.a_relfric", "mass.a", "der(mass.v)"] -@test getDerivativeNames(myFMU; mode=:group) == [["der(mass.s)"], ["mass.a_relfric", "mass.a", "der(mass.v)"]] +@test getDerivativeNames(myFMU; mode = :first) == ["der(mass.s)", "mass.a_relfric"] +@test getDerivativeNames(myFMU; mode = :flat) == + ["der(mass.s)", "mass.a_relfric", "mass.a", "der(mass.v)"] +@test getDerivativeNames(myFMU; mode = :group) == + [["der(mass.s)"], ["mass.a_relfric", "mass.a", "der(mass.v)"]] @test length(getNamesAndDescriptions(myFMU.modelDescription)) == 50 @test length(getNamesAndDescriptions(myFMU)) == 50 @@ -81,7 +96,7 @@ dict = getNamesAndInitials(myFMU) dict = getInputNamesAndStarts(myFMU) @test length(dict) == 0 -@test length(myFMU.modelDescription.unitDefinitions) == 10 +@test length(myFMU.modelDescription.unitDefinitions) == 10 @test length(myFMU.modelDescription.typeDefinitions) == 9 @test myFMU.modelDescription.unitDefinitions[5].name == "W" @test myFMU.modelDescription.unitDefinitions[6].baseUnit.kg == 1 @@ -108,7 +123,7 @@ for sv in myFMU.modelDescription.modelVariables @test sv_unit isa fmi2Unit @test sv_unit.name == sv.attribute.unit end - end + end end -unloadFMU(myFMU) \ No newline at end of file +unloadFMU(myFMU) diff --git a/test/FMI2/state.jl b/test/FMI2/state.jl index bf84b92..5fcd64c 100644 --- a/test/FMI2/state.jl +++ b/test/FMI2/state.jl @@ -11,7 +11,7 @@ using FMIImport.FMICore: fmi2FMUstate myFMU = loadFMU("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -comp = fmi2Instantiate!(myFMU; loggingOn=true) +comp = fmi2Instantiate!(myFMU; loggingOn = true) @test comp != 0 @test fmi2EnterInitializationMode(comp) == 0 diff --git a/test/FMI3/getter_setter.jl b/test/FMI3/getter_setter.jl index 28a2fd6..662866c 100644 --- a/test/FMI3/getter_setter.jl +++ b/test/FMI3/getter_setter.jl @@ -8,7 +8,7 @@ ############### myFMU = loadFMU("Feedthrough", "ModelicaReferenceFMUs", "0.0.20", "3.0") -inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn=false) +inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn = false) @test inst != 0 @test fmi3EnterInitializationMode(inst) == 0 @@ -93,14 +93,27 @@ cacheString = "" @test fmi3SetString(inst, stringValueReferences[1], rndString) == 0 @test fmi3GetString(inst, stringValueReferences[1]) == rndString -@test fmi3SetBinary(inst, binaryValueReferences[1], Csize_t(length(rndString)), pointer(rndString)) == 0 +@test fmi3SetBinary( + inst, + binaryValueReferences[1], + Csize_t(length(rndString)), + pointer(rndString), +) == 0 binary = fmi3GetBinary(inst, binaryValueReferences[1]) @test unsafe_string(binary) == rndString # TODO test after latest PR -setValue(inst, - [float64ValueReferences[1], int32ValueReferences[1], booleanValueReferences[1], stringValueReferences[1], binaryValueReferences[1]], - [rndReal, Int32(rndInteger), rndBoolean, rndString, rndString]) +setValue( + inst, + [ + float64ValueReferences[1], + int32ValueReferences[1], + booleanValueReferences[1], + stringValueReferences[1], + binaryValueReferences[1], + ], + [rndReal, Int32(rndInteger), rndBoolean, rndString, rndString], +) # @test getValue(inst, # [float64ValueReferences[1], integerValueReferences[1], booleanValueReferences[1], stringValueReferences[1], binaryValueReferences[1]]) == # [rndReal, Int32(rndInteger), rndBoolean, rndString, unsafe_string(rndString)] @@ -117,7 +130,7 @@ rndString = [tmp, tmp] cacheFloat32 = [Float32(0.0), Float32(0.0)] cacheFloat64 = [0.0, 0.0] -cacheInteger = [fmi3Int32(0), fmi3Int32(0)] +cacheInteger = [fmi3Int32(0), fmi3Int32(0)] cacheBoolean = [fmi3Boolean(false), fmi3Boolean(false)] cacheString = [pointer(""), pointer("")] diff --git a/test/FMI3/logging.jl b/test/FMI3/logging.jl index 28806af..af1f93b 100644 --- a/test/FMI3/logging.jl +++ b/test/FMI3/logging.jl @@ -7,7 +7,7 @@ myFMU = loadFMU("BouncingBall", "ModelicaReferenceFMUs", "0.0.20", "3.0") myFMU.executionConfig.assertOnError = false ### CASE A: Print log ### -inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn=true) +inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn = true) @test inst != 0 @info "The following warning is forced and not an issue:" @@ -18,7 +18,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi3ExitInitializationMode(inst) == fmi3StatusError end end - end + end end # ToDo: this test is wrong / not working (capture doesn't work for color output) #output = read(joinpath(pwd(), "stdout"), String) @@ -28,7 +28,7 @@ end ### CASE B: Print log, but catch infos ### -inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn=true, logStatusError=false) +inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn = true, logStatusError = false) @test inst != 0 @info "The following warning is forced and not an issue:" @@ -39,7 +39,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi3ExitInitializationMode(inst) == fmi3StatusError end end - end + end end output = read(joinpath(pwd(), "stdout"), String) @@ -47,12 +47,15 @@ output = read(joinpath(pwd(), "stdout"), String) if VERSION >= v"1.7.0" output = read(joinpath(pwd(), "stderr"), String) - @test startswith(output, "┌ Warning: fmi3ExitInitializationMode(...): Needs to be called in state `fmi3InstanceStateInitializationMode`.\n") -end + @test startswith( + output, + "┌ Warning: fmi3ExitInitializationMode(...): Needs to be called in state `fmi3InstanceStateInitializationMode`.\n", + ) +end ### CASE C: Disable Log ### -inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn=false) +inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn = false) @test inst != 0 @info "The following warning is forced and not an issue:" @@ -63,7 +66,7 @@ open(joinpath(pwd(), "stdout"), "w") do out @test fmi3ExitInitializationMode(inst) == fmi3StatusError end end - end + end end # ToDo: this test is wrong / not working (capture doesn't work for color output) #output = read(joinpath(pwd(), "stdout"), String) diff --git a/test/FMI3/state.jl b/test/FMI3/state.jl index 7ad774c..7576e6a 100644 --- a/test/FMI3/state.jl +++ b/test/FMI3/state.jl @@ -10,7 +10,7 @@ import FMIImport.FMICore: fmi3FMUState myFMU = loadFMU("BouncingBall", "ModelicaReferenceFMUs", "0.0.20", "3.0") -inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn=true) +inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn = true) @test inst != 0 @test fmi3EnterInitializationMode(inst) == 0 diff --git a/test/eval.jl b/test/eval.jl index f8d1081..59c0248 100644 --- a/test/eval.jl +++ b/test/eval.jl @@ -1,9 +1,9 @@ using PkgEval using FMIImport -config = Configuration(; julia="1.10"); +config = Configuration(; julia = "1.10"); -package = Package(; name="FMIImport"); +package = Package(; name = "FMIImport"); @info "PkgEval" result = evaluate([config], [package]) @@ -12,4 +12,4 @@ result = evaluate([config], [package]) println(result) @info "Log" -println(result.log) \ No newline at end of file +println(result.log) diff --git a/test/runtests.jl b/test/runtests.jl index ec848aa..2151fa6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,7 +9,17 @@ import Random using FMIZoo using FMIImport.FMICore: fmi2Integer, fmi2Boolean, fmi2Real, fmi2String -using FMIImport.FMICore: fmi3Float32, fmi3Float64, fmi3Int8, fmi3UInt8, fmi3Int16, fmi3UInt16, fmi3Int32, fmi3UInt32, fmi3Int64, fmi3UInt64 +using FMIImport.FMICore: + fmi3Float32, + fmi3Float64, + fmi3Int8, + fmi3UInt8, + fmi3Int16, + fmi3UInt16, + fmi3Int32, + fmi3UInt32, + fmi3Int64, + fmi3UInt64 using FMIImport.FMICore: fmi3Boolean, fmi3String, fmi3Binary exportingToolsWindows = [("Dymola", "2022x")]