Skip to content

Commit

Permalink
V0.15.2 (#83)
Browse files Browse the repository at this point in the history
* Preparations for multi-threading

* version inc

* fixed sensitivities

* updated dependencies

* test on SciMLSensitivity 7.27.0
  • Loading branch information
ThummeTo committed Mar 24, 2023
1 parent 4be373d commit c1a9be4
Show file tree
Hide file tree
Showing 12 changed files with 574 additions and 266 deletions.
8 changes: 4 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
name = "FMIImport"
uuid = "9fcbc62e-52a0-44e9-a616-1359a0008194"
authors = ["TT <[email protected]>", "LM <[email protected]>", "JK <[email protected]>"]
version = "0.15.1"
version = "0.15.2"

[deps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
EzXML = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615"
FMICore = "8af89139-c281-408e-bce2-3005eb87462f"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
ForwardDiffChainRules = "c9556dd2-1aed-4cfe-8560-1557cf593001"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
SciMLSensitivity = "1ed8b502-d754-442c-8d5d-10ac956f44a1"
ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"

[compat]
ChainRulesCore = "1.15.0"
EzXML = "1.1.0"
FMICore = "0.16.0"
ForwardDiff = "0.10.32"
FMICore = "0.16.1"
ForwardDiffChainRules = "0.1.1"
SciMLSensitivity = "7.27.0"
ZipFile = "0.10.0"
julia = "1.6"
25 changes: 19 additions & 6 deletions src/FMI2/c.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,28 @@ Removes the component from the FMUs component list.
- FMISpec2.0.2[p.16]: 2.1.2 Platform Dependent Definitions
See Also [`fmi2FreeInstance!`](@ref).
"""
lk_fmi2FreeInstance = ReentrantLock()
function fmi2FreeInstance!(c::FMU2Component; popComponent::Bool = true)

global lk_fmi2FreeInstance

compAddr = c.compAddr

if popComponent
ind = findall(x -> x.compAddr==c.compAddr, c.fmu.components)
@assert length(ind) == 1 "fmi2FreeInstance!(...): Freeing $(length(ind)) instances with one call, this is not allowed."
deleteat!(c.fmu.components, ind)
lock(lk_fmi2FreeInstance) do
ind = findall(x -> x.compAddr == compAddr, c.fmu.components)
@assert length(ind) == 1 "fmi2FreeInstance!(...): Freeing $(length(ind)) instances with one call, this is not allowed. Target address `$(compAddr)` was found $(length(ind)) times at indicies $(ind)."
deleteat!(c.fmu.components, ind)

for key in keys(c.fmu.threadComponents)
if !isnothing(c.fmu.threadComponents[key]) && c.fmu.threadComponents[key].compAddr == compAddr
c.fmu.threadComponents[key] = nothing
end
end
end
end

fmi2FreeInstance!(c.fmu.cFreeInstance, c.compAddr)
fmi2FreeInstance!(c.fmu.cFreeInstance, compAddr)

nothing
end
Expand Down Expand Up @@ -1515,7 +1528,7 @@ More detailed:
- FMISpec2.0.2[p.83]: 3.2.1 Providing Independent Variables and Re-initialization of Caching
See also [`fmi2SetTime`](@ref).
"""
function fmi2SetTime(c::FMU2Component, time::fmi2Real; soft::Bool=false, track::Bool=true, force::Bool=c.fmu.executionConfig.force, time_shift::Bool=c.fmu.executionConfig.autoTimeShift)
function 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)
Expand Down Expand Up @@ -1590,7 +1603,7 @@ function fmi2SetContinuousStates(c::FMU2Component,
x::AbstractArray{fmi2Real},
nx::Csize_t;
track::Bool=true,
force::Bool=c.fmu.executionConfig.force)
force::Bool=c.force)

if !force
if c.x == x
Expand Down
2 changes: 1 addition & 1 deletion src/FMI2/convert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#

using ChainRulesCore: ignore_derivatives
import ForwardDiff
import SciMLSensitivity.ForwardDiff

# Receives one or an array of value references in an arbitrary format (see fmi2ValueReferenceFormat) and converts it into an Array{fmi2ValueReference} (if not already).
function prepareValueReference(md::fmi2ModelDescription, vr::fmi2ValueReferenceFormat)
Expand Down
70 changes: 45 additions & 25 deletions src/FMI2/ext.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ function loadBinary(fmu::FMU2)
end
end

lk_fmi2Instantiate = ReentrantLock()
"""
fmi2Instantiate!(fmu::FMU2;
instanceName::String=fmu.modelName,
Expand Down Expand Up @@ -415,34 +416,43 @@ function fmi2Instantiate!(fmu::FMU2;

guidStr = "$(fmu.modelDescription.guid)"

compAddr = fmi2Instantiate(fmu.cInstantiate, pointer(instanceName), type, pointer(guidStr), pointer(fmu.fmuResourceLocation), Ptr{fmi2CallbackFunctions}(pointer_from_objref(callbackFunctions)), fmi2Boolean(visible), fmi2Boolean(loggingOn))
global lk_fmi2Instantiate
component = nothing

lock(lk_fmi2Instantiate) do
compAddr = fmi2Instantiate(fmu.cInstantiate, pointer(instanceName), type, pointer(guidStr), pointer(fmu.fmuResourceLocation), Ptr{fmi2CallbackFunctions}(pointer_from_objref(callbackFunctions)), fmi2Boolean(visible), fmi2Boolean(loggingOn))

if compAddr == Ptr{Cvoid}(C_NULL)
@error "fmi2Instantiate!(...): Instantiation failed!"
return nothing
end
if compAddr == Ptr{Cvoid}(C_NULL)
@error "fmi2Instantiate!(...): Instantiation failed!"
return nothing
end

component = nothing
# check if address is already inside of the components (this may be in FMIExport.jl)
for c in fmu.components
if c.compAddr == compAddr
component = c
break
end
end

# check if address is already inside of the components (this may be in FMIExport.jl)
for c in fmu.components
if c.compAddr == compAddr
component = c
break
if !isnothing(component)
logWarn(fmu, "fmi2Instantiate!(...): This component was already registered. This may be because you created the FMU by yourself with FMIExport.jl.")
else
component = FMU2Component(compAddr, fmu)

component.callbackFunctions = callbackFunctions
component.instanceName = instanceName
component.type = type

if pushComponents
push!(fmu.components, component)
end
end
end

if component != nothing
logInfo(fmu, "fmi2Instantiate!(...): This component was already registered. This may be because you created the FMU by yourself with FMIExport.jl.")
else
component = FMU2Component(compAddr, fmu)
component.jacobianUpdate! = fmi2SampleJacobian!
component.componentEnvironment = compEnv
component.callbackFunctions = callbackFunctions
component.instanceName = instanceName
component.type = type
component.jacobianUpdate! = fmi2SampleJacobian!

updateFct = nothing
updFct = nothing
if fmi2ProvidesDirectionalDerivative(fmu)
updFct = (jac, ∂f_refs, ∂x_refs) -> fmi2GetJacobian!(jac.mtx, component, ∂f_refs, ∂x_refs)
else
Expand All @@ -454,12 +464,22 @@ function fmi2Instantiate!(fmu::FMU2;
component.C = FMICore.FMUJacobian{fmi2Real, fmi2ValueReference}(fmu.modelDescription.outputValueReferences, fmu.modelDescription.stateValueReferences, updFct)
component.D = FMICore.FMUJacobian{fmi2Real, fmi2ValueReference}(fmu.modelDescription.outputValueReferences, fmu.modelDescription.inputValueReferences, updFct)

if pushComponents
push!(fmu.components, component)
end
# register component for current thread
fmu.threadComponents[Threads.threadid()] = component
end

return component
end

function hasCurrentComponent(fmu::FMU2)
tid = Threads.threadid()
return haskey(fmu.threadComponents, tid) && fmu.threadComponents[tid] != nothing
end

component
function getCurrentComponent(fmu::FMU2)
tid = Threads.threadid()
@assert hasCurrentComponent(fmu) ["No FMU instance allocated (in current thread with ID `$(tid)`), have you already called fmiInstantiate?"]
return fmu.threadComponents[tid]
end

"""
Expand Down
8 changes: 7 additions & 1 deletion src/FMI2/md.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,13 @@ Returns true, if the FMU provides directional derivatives
"""
function fmi2ProvidesDirectionalDerivative(md::fmi2ModelDescription)
return (md.coSimulation != nothing && md.coSimulation.providesDirectionalDerivative) || (md.modelExchange != nothing && md.modelExchange.providesDirectionalDerivative)
if md.coSimulation != nothing
return (md.coSimulation.providesDirectionalDerivative == true)
elseif md.modelExchange != nothing
return (md.modelExchange.providesDirectionalDerivative == true)
end

return false
end

"""
Expand Down
Loading

2 comments on commit c1a9be4

@ThummeTo
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/80252

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.15.2 -m "<description of version>" c1a9be444d194472962628c6e119a1f382d3b7f9
git push origin v0.15.2

Please sign in to comment.