Skip to content

Commit

Permalink
0.8.0 (#9)
Browse files Browse the repository at this point in the history
* Added "executionConfig" for FMUs

* executionConfig

* FMUSolution

* FMU2Solution

* ShadowComponents
  • Loading branch information
ThummeTo authored Apr 9, 2022
1 parent 0c9832f commit f891bbc
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FMICore"
uuid = "8af89139-c281-408e-bce2-3005eb87462f"
authors = ["TT <[email protected]>", "LM <[email protected]>", "JK <[email protected]>"]
version = "0.7.1"
version = "0.8.0"

[compat]
julia = "^1.5"
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,31 @@
# FMICore.jl

## What is FMICore.jl?
*FMICore.jl* implements the low-level equivalents of the C-functions and C-data types of the FMI-standard ([fmi-standard.org](http://fmi-standard.org/)) for the Julia programming language.
*FMICore.jl* provides the foundation for the Julia packages [*FMIImport.jl*](https://github.com/ThummeTo/FMIImport.jl) and [*FMIExport.jl*](https://github.com/ThummeTo/FMIExport.jl).
[*FMICore.jl*](https://github.com/ThummeTo/FMICore.jl) implements the low-level equivalents of the C-functions and C-data types of the FMI-standard ([fmi-standard.org](http://fmi-standard.org/)) for the Julia programming language.
[*FMICore.jl*](https://github.com/ThummeTo/FMICore.jl) provides the foundation for the Julia packages [*FMIImport.jl*](https://github.com/ThummeTo/FMIImport.jl) and [*FMIExport.jl*](https://github.com/ThummeTo/FMIExport.jl).

[![CI Testing](https://github.com/ThummeTo/FMICore.jl/actions/workflows/Test.yml/badge.svg)](https://github.com/ThummeTo/FMICore.jl/actions)
[![Coverage](https://codecov.io/gh/ThummeTo/FMICore.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/ThummeTo/FMICore.jl)

## How can I use FMICore.jl?
**Please note:** *FMICore.jl* is not meant to be used as it is, but as part of [*FMI.jl*](https://github.com/ThummeTo/FMI.jl), [*FMIImport.jl*](https://github.com/ThummeTo/FMIImport.jl), [*FMIExport.jl*](https://github.com/ThummeTo/FMIExport.jl) and [*FMIFlux.jl*](https://github.com/ThummeTo/FMIFlux.jl). However you can install *FMICore.jl* by following these steps.
**Please note:** [*FMICore.jl*](https://github.com/ThummeTo/FMICore.jl) is not meant to be used as it is, but as part of [*FMI.jl*](https://github.com/ThummeTo/FMI.jl), [*FMIImport.jl*](https://github.com/ThummeTo/FMIImport.jl), [*FMIExport.jl*](https://github.com/ThummeTo/FMIExport.jl) and [*FMIFlux.jl*](https://github.com/ThummeTo/FMIFlux.jl). However you can install [*FMICore.jl*](https://github.com/ThummeTo/FMICore.jl) by following these steps.
1. open a Julia-Command-Window, activate your prefered environment
1. goto package manager using ```]```
1. type ```add FMICore```

## What FMI.jl-Library should I use?
![FMI.jl Family](https://github.com/ThummeTo/FMI.jl/blob/main/docs/src/assets/FMI_JL_family.png "FMI.jl Family")
To keep dependencies nice and clean, the original package *FMI.jl* had been split into new packages:
To keep dependencies nice and clean, the original package [*FMI.jl*](https://github.com/ThummeTo/FMI.jl) had been split into new packages:
- [*FMI.jl*](https://github.com/ThummeTo/FMI.jl): High level loading, manipulating, saving or building entire FMUs from scratch
- [*FMIImport.jl*](https://github.com/ThummeTo/FMIImport.jl): Importing FMUs into Julia
- [*FMIExport.jl*](https://github.com/ThummeTo/FMIExport.jl): Exporting stand-alone FMUs from Julia Code
- [*FMICore.jl*](https://github.com/ThummeTo/FMICore.jl): C-code wrapper for the FMI-standard
- [*FMIBuild.jl*](https://github.com/ThummeTo/FMIBuild.jl): Compiler/Compilation dependencies for FMIExport.jl
- [*FMIFlux.jl*](https://github.com/ThummeTo/FMIFlux.jl): Machine Learning with FMUs (differentiation over FMUs)
- [*FMIZoo.jl*](https://github.com/ThummeTo/FMIZoo.jl): A collection of testing and example FMUs

## What Platforms are supported?
*FMICore.jl* is tested (and testing) under Julia Versions *1.6.5 LTS* and *latest* on Windows *latest*, Ubuntu *latest* and MacOS *latest*. `x64` and `x86` architectures are tested.
[*FMICore.jl*](https://github.com/ThummeTo/FMICore.jl) is tested (and testing) under Julia Versions *1.6.5 LTS* and *latest* on Windows *latest*, Ubuntu *latest* and MacOS *latest*. `x64` and `x86` architectures are tested.

## How to cite?
Tobias Thummerer, Lars Mikelsons and Josef Kircher. 2021. **NeuralFMU: towards structural integration of FMUs into neural networks.** Martin Sjölund, Lena Buffoni, Adrian Pop and Lennart Ochel (Ed.). Proceedings of 14th Modelica Conference 2021, Linköping, Sweden, September 20-24, 2021. Linköping University Electronic Press, Linköping (Linköping Electronic Conference Proceedings ; 181), 297-306. [DOI: 10.3384/ecp21181297](https://doi.org/10.3384/ecp21181297)
Expand Down
172 changes: 152 additions & 20 deletions src/FMI2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
#

# What is included in this file:
# - the `fmi2ComponentState`-enum which mirrors the internal FMU state (state-machine, not the system state)
# - the `FMU2ComponentEnvironment`-struct
# - the `FMU2Component`-struct
# - the `fmi2ComponentState`--enum which mirrors the internal FMU state (state-machine, not the system state)
# - the `FMU2ComponentEnvironment`- and `FMU2Component`-struct
# - the `FMU2`-struct
# - string/enum-converters for FMI-attribute-structs (e.g. `fmi2StatusToString`, ...)

# this is a custom type to catch the internal state of the component
# this is a custom type to catch the internal mode of the component
@enum fmi2ComponentState begin
fmi2ComponentStateModelSetableFMUstate
fmi2ComponentStateModelUnderEvaluation
fmi2ComponentStateModelInitialized
fmi2ComponentStateInstantiated # after instantiation
fmi2ComponentStateInitializationMode # after finishing initialization
fmi2ComponentStateEventMode
fmi2ComponentStateContinuousTimeMode
fmi2ComponentStateTerminated
fmi2ComponentStateError
fmi2ComponentStateFatal
end

"""
Expand Down Expand Up @@ -53,8 +56,10 @@ mutable struct FMU2Component
callbackFunctions::fmi2CallbackFunctions
instanceName::String
continuousStatesChanged::fmi2Boolean
eventInfo::fmi2EventInfo

t::fmi2Real # the system time
t_offset::fmi2Real # time offset between simulation environment and FMU
x::Union{Array{fmi2Real, 1}, Nothing} # the system states (or sometimes u)
::Union{Array{fmi2Real, 1}, Nothing} # the system state derivative (or sometimes u̇)
::Union{Array{fmi2Real, 1}, Nothing} # the system state second derivative
Expand All @@ -73,9 +78,10 @@ mutable struct FMU2Component
p_vrs::Array{fmi2ValueReference, 1} # the system parameter value references

# deprecated
jac_dxy_x::Matrix{fmi2Real}
jac_dxy_u::Matrix{fmi2Real}
jac_ẋy_x::Matrix{fmi2Real}
jac_ẋy_u::Matrix{fmi2Real}
jac_x::Array{fmi2Real}
jac_u::Union{Array{fmi2Real}, Nothing}
jac_t::fmi2Real

# linearization jacobians
Expand All @@ -84,16 +90,18 @@ mutable struct FMU2Component
C::Union{Matrix{fmi2Real}, Nothing}
D::Union{Matrix{fmi2Real}, Nothing}

jacobianFct # function for a custom jacobian constructor (optimization)
jacobianUpdate! # function for a custom jacobian constructor (optimization)
skipNextDoStep::Bool # allows skipping the next `fmi2DoStep` like it is not called
senseFunc::Symbol # :auto, :full, :sample, :directionalDerivatives, :adjointDerivatives

# constructor

function FMU2Component()
inst = new()
inst.state = fmi2ComponentStateModelUnderEvaluation
inst.state = fmi2ComponentStateInstantiated
inst.t = -Inf
inst.t_offset = 0.0
inst.eventInfo = fmi2EventInfo()

inst.senseFunc = :auto

Expand All @@ -111,9 +119,10 @@ mutable struct FMU2Component

# initialize further variables
inst.jac_x = Array{fmi2Real, 1}()
inst.jac_u = nothing
inst.jac_t = -1.0
inst.jac_dxy_x = zeros(fmi2Real, 0, 0)
inst.jac_dxy_u = zeros(fmi2Real, 0, 0)
inst.jac_ẋy_x = zeros(fmi2Real, 0, 0)
inst.jac_ẋy_u = zeros(fmi2Real, 0, 0)
inst.skipNextDoStep = false

inst.A = nothing
Expand All @@ -132,6 +141,128 @@ mutable struct FMU2Component
end
end

"""
A mutable struct representing the excution configuration of a FMU.
For FMUs that have issues with calls like `fmi2Reset` or `fmi2FreeInstance`, this is pretty useful.
"""
mutable struct FMU2ExecutionConfiguration
terminate::Bool # call fmi2Terminate before every training step / simulation
reset::Bool # call fmi2Reset before every training step / simulation
setup::Bool # call setup functions before every training step / simulation
instantiate::Bool # call fmi2Instantiate before every training step / simulation
freeInstance::Bool # call fmi2FreeInstance after every training step / simulation

handleStateEvents::Bool # handle state events during simulation/training
handleTimeEvents::Bool # handle time events during simulation/training

assertOnError::Bool # wheter an exception is thrown if a fmi2XXX-command fails (>= fmi2StatusError)
assertOnWarning::Bool # wheter an exception is thrown if a fmi2XXX-command warns (>= fmi2StatusWarning)

autoTimeShift::Bool # wheter to shift all time-related functions for simulation intervals not starting at 0.0

sensealg # algorithm for sensitivity estimation over solve call
useComponentShadow::Bool # whether FMU outputs/derivatives/jacobians should be cached for frule/rrule (useful for ForwardDiff)
rootSearchInterpolationPoints::UInt # number of root search interpolation points
inPlace::Bool # whether faster in-place-fx should be used
useVectorCallbacks::Bool # whether to vector (faster) or scalar (slower) callbacks

maxNewDiscreteStateCalls::UInt # max calls for fmi2NewDiscreteStates before throwing an exception

function FMU2ExecutionConfiguration()
inst = new()

inst.terminate = true
inst.reset = true
inst.setup = true
inst.instantiate = false
inst.freeInstance = false

inst.handleStateEvents = true
inst.handleTimeEvents = true

inst.assertOnError = false
inst.assertOnWarning = false

inst.autoTimeShift = true

inst.sensealg = nothing # auto
inst.useComponentShadow = false
inst.rootSearchInterpolationPoints = 100
inst.inPlace = true
inst.useVectorCallbacks = true

inst.maxNewDiscreteStateCalls = 100

return inst
end
end

# default for a "healthy" FMU - this is the fastetst
FMU_EXECUTION_CONFIGURATION_RESET = FMU2ExecutionConfiguration()
FMU_EXECUTION_CONFIGURATION_RESET.terminate = true
FMU_EXECUTION_CONFIGURATION_RESET.reset = true
FMU_EXECUTION_CONFIGURATION_RESET.instantiate = false
FMU_EXECUTION_CONFIGURATION_RESET.freeInstance = false

# if your FMU has a problem with "fmi2Reset" - this is default
FMU_EXECUTION_CONFIGURATION_NO_RESET = FMU2ExecutionConfiguration()
FMU_EXECUTION_CONFIGURATION_NO_RESET.terminate = false
FMU_EXECUTION_CONFIGURATION_NO_RESET.reset = false
FMU_EXECUTION_CONFIGURATION_NO_RESET.instantiate = true
FMU_EXECUTION_CONFIGURATION_NO_RESET.freeInstance = true

# if your FMU has a problem with "fmi2Reset" and "fmi2FreeInstance" - this is for weak FMUs (but slower)
FMU_EXECUTION_CONFIGURATION_NO_FREEING = FMU2ExecutionConfiguration()
FMU_EXECUTION_CONFIGURATION_NO_FREEING.terminate = false
FMU_EXECUTION_CONFIGURATION_NO_FREEING.reset = false
FMU_EXECUTION_CONFIGURATION_NO_FREEING.instantiate = true
FMU_EXECUTION_CONFIGURATION_NO_FREEING.freeInstance = false

"""
ToDo
"""
struct FMU2Event
t::Union{Float32, Float64}
indicator::UInt

x_left::Union{Array{Float64, 1}, Array{Float32, 1}, Nothing}
x_right::Union{Array{Float64, 1}, Array{Float32, 1}, Nothing}

function FMU2Event(t::Union{Float32, Float64}, indicator::UInt = 0, x_left::Union{Array{Float64, 1}, Array{Float32, 1}, Nothing} = nothing, x_right::Union{Array{Float64, 1}, Array{Float32, 1}, Nothing} = nothing)
inst = new(t, indicator, x_left, x_right)
return inst
end
end

"""
ToDo
"""
mutable struct FMU2Solution <: FMUSolution
fmu # FMU2
success::Bool

states # ODESolution

values
valueReferences::Union{Array, Nothing} # Array{fmi2ValueReference}

events::Array{FMU2Event, 1}

function FMU2Solution(fmu)
inst = new()

inst.fmu = fmu
inst.success = false
inst.states = nothing
inst.values = nothing
inst.valueReferences = nothing

inst.events = []

return inst
end
end

"""
The mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard.
Also contains the paths to the FMU and ZIP folder as well als all the FMI 2.0.2 function pointers.
Expand Down Expand Up @@ -201,10 +332,10 @@ mutable struct FMU2 <: FMU
binaryPath::String
zipPath::String

# FMIFlux
t_cache::Array{Float64, 1}
ẋ_cache::Array{Array{Float64, 1}, 1}
ẋ_interp # interpolation polynominal
# execution configuration
executionConfig::FMU2ExecutionConfiguration
hasStateEvents::Union{Bool, Nothing}
hasTimeEvents::Union{Bool, Nothing}

# c-libraries
libHandle::Ptr{Nothing}
Expand All @@ -221,9 +352,10 @@ mutable struct FMU2 <: FMU
inst.components = []
inst.callbackLibHandle = C_NULL

inst.t_cache = []
inst.ẋ_cache = []
inst.ẋ_interp = nothing
inst.hasStateEvents = nothing
inst.hasTimeEvents = nothing

inst.executionConfig = FMU_EXECUTION_CONFIGURATION_NO_RESET

return inst
end
Expand Down
10 changes: 6 additions & 4 deletions src/FMI2_c.jl
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ Removes the component from the FMUs component list.
"""
function fmi2FreeInstance!(cfunc::Ptr{Nothing}, c::fmi2Component)

ccall(cfunc, Cvoid, (Ptr{Cvoid},), c)
ccall(cfunc, Cvoid, (fmi2Component,), c)

nothing
end
Expand Down Expand Up @@ -865,19 +865,21 @@ end
Source: FMISpec2.0.2[p.26]: 2.1.9 Getting Partial Derivatives
This function computes the directional derivatives of an FMU.
ΔvUnknown = ∂h / ∂vKnown ⋅ ΔvKnown
"""
function fmi2GetDirectionalDerivative!(cfunc::Ptr{Nothing},
c::fmi2Component,
vUnknown_ref::Array{fmi2ValueReference},
nUnknown::Csize_t,
vKnown_ref::Array{fmi2ValueReference},
nKnown::Csize_t,
dvKnown::Array{fmi2Real},
dvUnknown::AbstractArray)
ΔvKnown::Array{fmi2Real},
ΔvUnknown::AbstractArray{fmi2Real})
ccall(cfunc,
fmi2Status,
(fmi2Component, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2ValueReference}, Csize_t, Ptr{fmi2Real}, Ptr{fmi2Real}),
c, vUnknown_ref, nUnknown, vKnown_ref, nKnown, dvKnown, dvUnknown)
c, vUnknown_ref, nUnknown, vKnown_ref, nKnown, ΔvKnown, ΔvUnknown)
end

# Functions specificly for isCoSimulation
Expand Down
6 changes: 4 additions & 2 deletions src/FMICore.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ end
The mutable struct representing an abstract (version unknown) FMU.
"""
abstract type FMU end
abstract type FMUSolution end

include("FMI2_c.jl")
include("FMI2.jl")
Expand All @@ -27,9 +28,10 @@ include("FMI3.jl")
### EXPORTING LISTS START ###

export FMU
export FMU2ExecutionConfiguration, FMU_EXECUTION_CONFIGURATION_RESET, FMU_EXECUTION_CONFIGURATION_NO_RESET, FMU_EXECUTION_CONFIGURATION_NO_FREEING

# FMI2.jl
export FMU2, FMU2Component, FMU2ComponentEnvironment
export FMU2, FMU2Component, FMU2ComponentEnvironment, FMU2Solution, FMU2Event
export fmi2StatusToString
export fmi2CausalityToString, fmi2StringToCausality
export fmi2VariabilityToString, fmi2StringToVariability
Expand Down Expand Up @@ -59,7 +61,7 @@ export fmi2VariableNamingConvention, fmi2VariableNamingConventionFlat, fmi2Varia
export fmi2VariableDependency
export fmi2DefaultExperiment, fmi2Unknown, fmi2ModelStructure
export fmi2ModelDescription
export fmi2ComponentState, fmi2ComponentStateModelSetableFMUstate, fmi2ComponentStateModelUnderEvaluation, fmi2ComponentStateModelInitialized
export fmi2ComponentState, fmi2ComponentStateInstantiated, fmi2ComponentStateInitializationMode, fmi2ComponentStateEventMode, fmi2ComponentStateContinuousTimeMode, fmi2ComponentStateTerminated, fmi2ComponentStateError, fmi2ComponentStateFatal

# functions
export fmi2CallbackLogger, fmi2CallbackAllocateMemory, fmi2CallbackFreeMemory, fmi2CallbackStepFinished
Expand Down

2 comments on commit f891bbc

@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/58226

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.8.0 -m "<description of version>" f891bbc2a7e46af9fd5579999eba232a05d6e699
git push origin v0.8.0

Please sign in to comment.