Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.16.4 #110

Merged
merged 6 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FMIImport"
uuid = "9fcbc62e-52a0-44e9-a616-1359a0008194"
authors = ["TT <tobias.thummerer@informatik.uni-augsburg.de>", "LM <lars.mikelsons@informatik.uni-augsburg.de>", "JK <josef.kircher@student.uni-augsburg.de>"]
version = "0.16.3"
version = "0.16.4"

[deps]
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
Expand All @@ -14,7 +14,7 @@ ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"
[compat]
Downloads = "1"
EzXML = "1.1.0"
FMICore = "0.19.0"
FMICore = "0.20.0"
Libdl = "1"
RelocatableFolders = "1"
ZipFile = "0.10.0"
Expand Down
30 changes: 26 additions & 4 deletions src/FMI2/c.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import FMICore: fmi2DoStep, fmi2CancelStep, fmi2GetStatus!, fmi2GetRealStatus!,
import FMICore: fmi2SetTime, fmi2SetContinuousStates, fmi2EnterEventMode, fmi2NewDiscreteStates!, fmi2EnterContinuousTimeMode, fmi2CompletedIntegratorStep!
import FMICore: fmi2GetDerivatives!, fmi2GetEventIndicators!, fmi2GetContinuousStates!, fmi2GetNominalsOfContinuousStates!

using FMICore: invalidate!, check_invalidate!

"""
Source: FMISpec2.0.2[p.21]: 2.1.5 Creation, Destruction and Logging of FMU Instances

Expand Down Expand Up @@ -116,12 +114,17 @@ Removes the component from the FMUs component list.
See Also [`fmi2FreeInstance!`](@ref).
"""
lk_fmi2FreeInstance = ReentrantLock()
function fmi2FreeInstance!(c::FMU2Component; popComponent::Bool = true)
function fmi2FreeInstance!(c::FMU2Component; popComponent::Bool=true, doccall::Bool=true)

global lk_fmi2FreeInstance

compAddr = c.compAddr

# invalidate all active snapshots
while length(c.snapshots) > 0
FMICore.freeSnapshot!(c.snapshots[end])
end

@assert c.threadid == Threads.threadid() "Thread #$(Threads.threadid()) tried to free component with address $(c.compAddr), but doesn't own it.\nThe component is owned by thread $(c.threadid)"

if popComponent
Expand All @@ -138,7 +141,9 @@ function fmi2FreeInstance!(c::FMU2Component; popComponent::Bool = true)
end
end

fmi2FreeInstance!(c.fmu.cFreeInstance, compAddr)
if doccall
fmi2FreeInstance!(c.fmu.cFreeInstance, compAddr)
end

nothing
end
Expand Down Expand Up @@ -1144,6 +1149,23 @@ function fmi2GetDirectionalDerivative!(c::FMU2Component,
return status
end

# for AD primitives
function fmi2GetDirectionalDerivative!(c::FMU2Component,
vUnknown_ref::AbstractArray{fmi2ValueReference},
nUnknown::Csize_t,
vKnown_ref::AbstractArray{fmi2ValueReference},
nKnown::Csize_t,
dvKnown::AbstractArray{fmi2Real},
dvUnknown::AbstractArray{<:Real})

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)
dvUnknown[:] = _dvUnknown
return status
end

# Functions specificly for isCoSimulation
"""
fmi2SetRealInputDerivatives(c::FMU2Component,
Expand Down
81 changes: 76 additions & 5 deletions src/FMI2/ext.jl
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ function fmi2Reload(fmu::FMU2)
end

"""
fmi2Unload(fmu::FMU2, cleanUp::Bool = true)
fmi2Unload(fmu::FMU2, cleanUp::Bool=true; secure_pointers::Bool=true)

Unload a FMU.
Free the allocated memory, close the binaries and remove temporary zip and unziped FMU model description.
Expand All @@ -598,15 +598,25 @@ 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 fmi2Unload(fmu::FMU2, cleanUp::Bool = true; secure_pointers::Bool=true)
function fmi2Unload(fmu::FMU2, cleanUp::Bool=true; secure_pointers::Bool=true)

while length(fmu.components) > 0
fmi2FreeInstance!(fmu.components[end])
c = fmu.components[end]

# release allocated memory for snapshots (they might be used elsewhere too)
# if !isnothing(c.solution)
# for iter in c.solution.snapshots
# t, snapshot = iter
# cleanup!(c, snapshot)
# end
# end

fmi2FreeInstance!(c)
end

# 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
unloadBinary(fmu)
end
Expand Down Expand Up @@ -1171,7 +1181,7 @@ More detailed:
function fmi2Set(comp::FMU2Component, vrs::fmi2ValueReferenceFormat, srcArray::AbstractArray; filter=nothing)
vrs = prepareValueReference(comp, vrs)

@assert length(vrs) == length(srcArray) "fmi2Set(...): Number of value references doesn't match number of `srcArray` elements."
@assert length(vrs) == length(srcArray) "fmi2Set(...): Number of value references [$(length(vrs))] doesn't match number of `srcArray` elements [$(length(srcArray))]."

retcodes = zeros(fmi2Status, length(vrs)) # fmi2StatusOK

Expand Down Expand Up @@ -1585,3 +1595,64 @@ function fmi2SampleJacobian!(c::FMU2Component,

nothing
end

"""
fmi2SetDiscreteStates(c::FMU2Component,
x::Union{AbstractArray{Float32},AbstractArray{Float64}})

Set a new (discrete) state vector and reinitialize chaching of variables that depend on states.

# Arguments
[ToDo]
"""
function fmi2SetDiscreteStates(c::FMU2Component, xd::AbstractArray{Union{fmi2Real, fmi2Integer, fmi2Boolean}})

if length(c.fmu.modelDescription.discreteStateValueReferences) <= 0
return fmi2StatusOK
end

status = fmi2Set(c, c.fmu.modelDescription.discreteStateValueReferences, xd)
if status == fmi2StatusOK
fast_copy!(c, :x_d, xd)
end
return status
end

"""
fmi2GetDiscreteStates!(c::FMU2Component,
x::Union{AbstractArray{Float32},AbstractArray{Float64}})

Set a new (discrete) state vector and reinitialize chaching of variables that depend on states.

# Arguments
[ToDo]
"""
function fmi2GetDiscreteStates!(c::FMU2Component, xd::AbstractArray{Union{fmi2Real, fmi2Integer, fmi2Boolean}})

if length(c.fmu.modelDescription.discreteStateValueReferences) <= 0
return fmi2StatusOK
end

status = fmi2Get!(c, c.fmu.modelDescription.discreteStateValueReferences, xd)
if status == fmi2StatusOK
fast_copy!(c, :x_d, xd)
end
return status
end

"""
fmi2GetDiscreteStates(c::FMU2Component,
x::Union{AbstractArray{Float32},AbstractArray{Float64}})

Set a new (discrete) state vector and reinitialize chaching of variables that depend on states.

# Arguments
[ToDo]
"""
function fmi2GetDiscreteStates(c::FMU2Component)

ndx = length(c.fmu.modelDescription.discreteStateValueReferences)
xd = Vector{Union{fmi2Real, fmi2Integer, fmi2Boolean}}()
fmi2GetDiscreteStates!(c, xd)
return xd
end
19 changes: 18 additions & 1 deletion src/FMI2/prep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ function prepareSolveFMU(fmu::FMU2,
#@assert retcode == fmi2StatusOK "fmi2Simulate(...): Setting initial state failed with return code $(retcode)."
retcodes = fmi2Set(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
c.x = copy(x0)
end

# exit setup (hard)
Expand Down Expand Up @@ -173,6 +176,20 @@ function handleEvents(c::FMU2Component)

@assert c.state == fmi2ComponentStateEventMode "handleEvents(...): Must be in event mode!"

# invalidate all cached jacobians/gradients
invalidate!(c.∂ẋ_∂x)
invalidate!(c.∂ẋ_∂u)
invalidate!(c.∂ẋ_∂p)
invalidate!(c.∂y_∂x)
invalidate!(c.∂y_∂u)
invalidate!(c.∂y_∂p)
invalidate!(c.∂e_∂x)
invalidate!(c.∂e_∂u)
invalidate!(c.∂e_∂p)
invalidate!(c.∂ẋ_∂t)
invalidate!(c.∂y_∂t)
invalidate!(c.∂e_∂t)

#@debug "Handle Events..."

# trigger the loop
Expand Down Expand Up @@ -354,7 +371,7 @@ function finishSolveFMU(fmu::FMU2, c::FMU2Component, freeInstance::Union{Nothing

# freeInstance (hard)
if freeInstance
fmi2FreeInstance!(c; popComponent=popComponent)
fmi2FreeInstance!(c; popComponent=popComponent) # , doccall=freeInstance
c = nothing
end
end
Expand Down
2 changes: 2 additions & 0 deletions src/FMIImport.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ using FMICore.Requires
import FMICore.ChainRulesCore: ignore_derivatives

using RelocatableFolders
using FMICore: invalidate!, check_invalidate!

# functions that have (currently) no better place

Expand Down Expand Up @@ -54,6 +55,7 @@ export fmi2GetFMUstate!, fmi2SetFMUstate, fmi2FreeFMUstate!, fmi2SerializedFMUst
export fmi2GetDirectionalDerivative!, fmi2SetRealInputDerivatives, fmi2GetRealOutputDerivatives
export fmi2DoStep, fmi2CancelStep, fmi2GetStatus!, fmi2GetRealStatus!, fmi2GetIntegerStatus!, fmi2GetBooleanStatus!, fmi2GetStringStatus!
export fmi2SetTime, fmi2SetContinuousStates, fmi2EnterEventMode, fmi2NewDiscreteStates!, fmi2EnterContinuousTimeMode, fmi2CompletedIntegratorStep!
export fmi2SetDiscreteStates, fmi2GetDiscreteStates!, fmi2GetDiscreteStates
export fmi2GetDerivatives!, fmi2GetEventIndicators!, fmi2GetContinuousStates!, fmi2GetNominalsOfContinuousStates!, fmi2GetRealOutputDerivatives!

# FMI2_convert.jl
Expand Down
Loading