Skip to content

Commit

Permalink
v0.1.13 (#24)
Browse files Browse the repository at this point in the history
* updated readme

* FIX: compatability with [email protected] (#23)

Co-authored-by: Henning Scheufler <[email protected]>

* re-added test (bouncing ball), refactor for FMICore 0.16.0

* Update Test.yml

---------

Co-authored-by: Henning Scheufler <[email protected]>
Co-authored-by: Henning Scheufler <[email protected]>
  • Loading branch information
3 people authored Mar 7, 2023
1 parent a235b06 commit 2d048db
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## 1. Create an ssh key pair.
This command is avaible for Windows (`cmd`) and Linux (`bash`).
```
ssh-keygen -N "" -f compathelper_key -t ed25519
ssh-keygen -N "" -f compathelper_key -t ed25519 -C compathelper
```

## 2. Copy the **private** key.
Expand Down
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FMIExport"
uuid = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a"
authors = ["TT <[email protected]>", "LM <[email protected]>"]
version = "0.1.12"
version = "0.1.13"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand All @@ -11,5 +11,5 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
EzXML = "1.1.0"
FMICore = "0.14, 0.15"
FMICore = "0.16"
julia = "1.6"
32 changes: 12 additions & 20 deletions src/FMI2_md.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ function fmi2ModelDescriptionAddRealState(md::fmi2ModelDescription, name::String
start::Union{Real, Nothing}=nothing,
kwargs...)

_Real = fmi2ModelDescriptionReal()
_Real = fmi2RealAttributesExt()
_Real.start = start
sv = fmi2ModelDescriptionAddModelVariable(md, name; _Real=_Real, kwargs...)
sv = fmi2ModelDescriptionAddModelVariable(md, name; attribute=_Real, kwargs...)

push!(md.stateValueReferences, sv.valueReference)
push!(md.stringValueReferences, sv.name => sv.valueReference)
Expand All @@ -57,11 +57,11 @@ function fmi2ModelDescriptionAddRealDerivative(md::fmi2ModelDescription, name::S
derivative::Union{UInt, Nothing}=nothing,
kwargs...)

_Real = fmi2ModelDescriptionReal()
_Real = fmi2RealAttributesExt()
_Real.start = start
_Real.derivative = derivative

sv = fmi2ModelDescriptionAddModelVariable(md, name; _Real=_Real, kwargs...)
sv = fmi2ModelDescriptionAddModelVariable(md, name; attribute=_Real, kwargs...)
index = fmi2GetIndexOfScalarVariable(md, sv)

fmi2ModelDescriptionAddModelStructureDerivatives(md, index)
Expand All @@ -88,10 +88,10 @@ function fmi2ModelDescriptionAddRealInput(md::fmi2ModelDescription, name::String
start::Union{Real, Nothing}=nothing,
kwargs...)

_Real = fmi2ModelDescriptionReal()
_Real = fmi2RealAttributesExt()
_Real.start = start

sv = fmi2ModelDescriptionAddModelVariable(md, name; _Real=_Real, causality=fmi2CausalityInput, kwargs...)
sv = fmi2ModelDescriptionAddModelVariable(md, name; attribute=_Real, causality=fmi2CausalityInput, kwargs...)

push!(md.inputValueReferences, sv.valueReference)
push!(md.stringValueReferences, sv.name => sv.valueReference)
Expand All @@ -103,10 +103,10 @@ function fmi2ModelDescriptionAddRealOutput(md::fmi2ModelDescription, name::Strin
start::Union{Real, Nothing}=nothing,
kwargs...)

_Real = fmi2ModelDescriptionReal()
_Real = fmi2RealAttributesExt()
_Real.start = start

sv = fmi2ModelDescriptionAddModelVariable(md, name; _Real=_Real, causality=fmi2CausalityOutput, kwargs...)
sv = fmi2ModelDescriptionAddModelVariable(md, name; attribute=_Real, causality=fmi2CausalityOutput, kwargs...)
index = fmi2GetIndexOfScalarVariable(md, sv)

fmi2ModelDescriptionAddModelStructureOutputs(md, index)
Expand All @@ -120,10 +120,10 @@ function fmi2ModelDescriptionAddRealParameter(md::fmi2ModelDescription, name::St
start::Union{Real, Nothing}=nothing,
kwargs...)

_Real = fmi2ModelDescriptionReal()
_Real = fmi2RealAttributesExt()
_Real.start = start

sv = fmi2ModelDescriptionAddModelVariable(md, name; _Real=_Real, kwargs...)
sv = fmi2ModelDescriptionAddModelVariable(md, name; attribute=_Real, kwargs...)

push!(md.parameterValueReferences, sv.valueReference)
push!(md.stringValueReferences, sv.name => sv.valueReference)
Expand All @@ -148,11 +148,7 @@ function fmi2ModelDescriptionAddModelVariable(md::fmi2ModelDescription, name::St
variability::Union{fmi2Variability, Nothing}=nothing,
initial::Union{fmi2Initial, Nothing}=nothing,
canHandleMultipleSetPerTimeInstant::Union{Bool, Nothing}=nothing,
_Real::Union{fmi2ModelDescriptionReal, Nothing}=nothing,
_Integer::Union{fmi2ModelDescriptionInteger, Nothing}=nothing,
_Boolean::Union{fmi2ModelDescriptionBoolean, Nothing}=nothing,
_String::Union{fmi2ModelDescriptionString, Nothing}=nothing,
_Enumeration::Union{fmi2ModelDescriptionEnumeration, Nothing}=nothing)
attribute::Union{FMI2_SCALAR_VARIABLE_ATTRIBUTE_STRUCT, Nothing}=nothing)

if valueReference === :auto
valueReference = fmi2ValueReference(length(md.modelVariables)+1)
Expand All @@ -161,11 +157,7 @@ function fmi2ModelDescriptionAddModelVariable(md::fmi2ModelDescription, name::St
sv = fmi2ScalarVariable(name, valueReference, causality, variability, initial)
sv.description = description
sv.canHandleMultipleSetPerTimeInstant = canHandleMultipleSetPerTimeInstant
sv._Real = _Real
sv._Integer = _Integer
sv._Boolean = _Boolean
sv._String = _String
sv._Enumeration = _Enumeration
sv.attribute = attribute

push!(md.modelVariables, sv)
return sv
Expand Down
7 changes: 3 additions & 4 deletions src/FMIExport.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

module FMIExport

using FMICore
using FMICore: FMU2, FMU2Component, fmi2ModelDescription, fmi2ValueReference, fmi2Component, fmi2ComponentEnvironment, fmi2Status, fmi2EventInfo
using FMICore: fmi2Causality, fmi2CausalityOutput, fmi2CausalityInput
using FMICore: fmi2ScalarVariable, fmi2Variability, fmi2Initial
using FMICore: fmi2ModelDescriptionReal, fmi2ModelDescriptionInteger, fmi2ModelDescriptionBoolean, fmi2ModelDescriptionString, fmi2ModelDescriptionEnumeration
using FMICore: fmi2ScalarVariable, fmi2Variability, fmi2Initial, FMI2_SCALAR_VARIABLE_ATTRIBUTE_STRUCT
using FMICore: fmi2RealAttributesExt, fmi2IntegerAttributesExt, fmi2BooleanAttributesExt, fmi2StringAttributesExt, fmi2EnumerationAttributesExt
using FMICore: fmi2VariableDependency, fmi2Unknown, fmi2DependencyKind
using FMICore: fmi2VariableNamingConventionStructured
using FMICore: fmi2CausalityToString, fmi2VariabilityToString, fmi2InitialToString
Expand Down Expand Up @@ -43,8 +44,6 @@ export fmi2SetFctGetDerivatives, fmi2SetFctGetEventIndicators, fmi2SetFctGetCont
include("FMI2_simple.jl")
export fmi2CreateSimple

# export fmi2ComponentStruct

function fmi2SetFctGetTypesPlatform(fmu::FMU2, fun)
c_fun = @cfunction($fun, fmi2String, ())
fmu.cGetTypesPlatform = c_fun.ptr
Expand Down
8 changes: 8 additions & 0 deletions test/FMI2/BouncingBall/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name = "BouncingBall"
uuid = "a60229a6-2119-4702-9088-6d2bb886a221"
authors = ["TT <[email protected]>"]
version = "0.1.0"

[deps]
FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800"
FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a"
125 changes: 125 additions & 0 deletions test/FMI2/BouncingBall/src/BouncingBall.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#
# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons
# Licensed under the MIT license. See LICENSE file in the project root for details.
#

using FMIExport

FMU_FCT_INIT = function()
m = 1.0 # ball mass
r = 0.0 # ball radius
d = 0.7 # ball collision damping
v_min = 1e-1 # ball minimum velocity
g = -9.81 # gravity constant

s = 1.0 # ball position
v = 0.0 # ball velocity
a = 0.0 # ball acceleration

t = 0.0
x = [s, v]
= [v, a]
u = []
p = [m, r, d, v_min, g]

return (t, x, ẋ, u, p)
end

FMU_FCT_EVALUATE = function(t, x, ẋ, u, p)
m, r, d, v_min, g = (p...,)
s, v = (x...,)
_, a = (ẋ...,)

if s <= r && v < 0.0
s = r
v = -v*d

# stop bouncing to prevent high frequency bouncing (and maybe tunneling the floor)
if v < v_min
v = 0.0
g = 0.0
end
end

a = (m * g) / m # the system's physical equation

x = [s, v]
= [v, a]
p = [m, r, d, v_min, g]

return (x, ẋ, p)
end

FMU_FCT_OUTPUT = function(t, x, ẋ, u, p)
m, r, d, v_min, g = (p...,)
s, v = (x...,)
_, a = (ẋ...,)

y = [s]

return y
end

FMU_FCT_EVENT = function(t, x, ẋ, u, p)
m, r, d, v_min, g = (p...,)
s, v = (x...,)
_, a = (ẋ...,)

z1 = (s-r) # event 1: ball hits ground

if s==r && v==0.0
z1 = 1.0 # event 1: ball stay-on-ground
end

z = [z1]

return z
end

# this function is called, as soon as the DLL is loaded and Julia is initialized
# must return a FMU2-instance to work with
FMIBUILD_CONSTRUCTOR = function(resPath="")
fmu = fmi2CreateSimple(initializationFct=FMU_FCT_INIT,
evaluationFct=FMU_FCT_EVALUATE,
outputFct=FMU_FCT_OUTPUT,
eventFct=FMU_FCT_EVENT)

# states [2]
fmi2AddStateAndDerivative(fmu, "ball.s"; stateDescr="Absolute position of ball center of mass", derivativeDescr="Absolute velocity of ball center of mass")
fmi2AddStateAndDerivative(fmu, "ball.v"; stateDescr="Absolute velocity of ball center of mass", derivativeDescr="Absolute acceleration of ball center of mass")

# outputs [1]
fmi2AddRealOutput(fmu, "ball.s"; description="Absolute position of ball center of mass")

# parameters [5]
fmi2AddRealParameter(fmu, "m"; description="Mass of ball")
fmi2AddRealParameter(fmu, "r"; description="Radius of ball")
fmi2AddRealParameter(fmu, "d"; description="Collision damping constant (velocity fraction after hitting the ground)")
fmi2AddRealParameter(fmu, "v_min"; description="Minimal ball velocity to enter on-ground-state")
fmi2AddRealParameter(fmu, "g"; description="Gravity constant")

fmi2AddEventIndicator(fmu)

return fmu
end

### FMIBUILD_NO_EXPORT_BEGIN ###
# The line above is a start-marker for excluded code for the FMU compilation process!

tmpDir = mktempdir(; prefix="fmibuildjl_test_", cleanup=false)
@info "Saving example files at: $(tmpDir)"
fmu_save_path = joinpath(tmpDir, "BouncingBall.fmu")

fmu = FMIBUILD_CONSTRUCTOR()
using FMIBuild: fmi2Save # <= this must be excluded during export, because FMIBuild cannot execute itself (but it is able to build)
fmi2Save(fmu, fmu_save_path) # <= this must be excluded during export, because fmi2Save would start an infinte build loop with itself

### some tests ###
# using FMI
# comp = fmiInstantiate!(fmu; loggingOn=true)
# solution = fmiSimulateME(comp, 0.0, 10.0; dtmax=0.1)
# fmiPlot(fmu, solution)
# fmiFreeInstance!(comp)

# The following line is a end-marker for excluded code for the FMU compilation process!
### FMIBUILD_NO_EXPORT_END ###
2 changes: 1 addition & 1 deletion test/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ julia = "1.6"

[deps]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
FMICore = "8af89139-c281-408e-bce2-3005eb87462f"
FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800"
5 changes: 2 additions & 3 deletions test/model_description.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons
# Licensed under the MIT license. See LICENSE file in the project root for details.
#
using FMICore: fmi2ScalarVariable

using FMIExport.FMICore: fmi2ScalarVariable

md = fmi2CreateModelDescription()
var = fmi2ModelDescriptionAddRealStateAndDerivative(md, "mass.s")
Expand All @@ -21,6 +20,6 @@ var = fmi2ModelDescriptionAddRealStateAndDerivative(md, "mass.v")
@test var[2].valueReference == 4

var = fmi2ModelDescriptionAddRealOutput(md, "mass.f")
@test typeof(var) ==fmi2ScalarVariable
@test typeof(var) == fmi2ScalarVariable
@test var.name == "mass.f"
@test var.valueReference == 5
14 changes: 9 additions & 5 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@
using FMIExport
using Test


function runtests()
@testset "Model Description" begin
include("model_description.jl")
end

@testset "Bouncing Ball" begin
include(joinpath(@__DIR__, "FMI2", "BouncingBall", "src", "BouncingBall.jl"))

@test isfile(fmu_save_path)

# ToDo: simulate FMU in e.g. Python / FMPy
end
end

@testset "FMIExport.jl" begin
if Sys.iswindows() || Sys.islinux()
@info "Automated testing is supported on Windows/Linux."
if Sys.iswindows() || Sys.islinux() || Sys.isapple()
@info "Automated testing is supported on Windows/Linux/Mac."
runtests()
elseif Sys.isapple()
@warn "Test-sets are currrently using Windows- and Linux-FMUs, automated testing for macOS is currently not supported."
end
end

2 comments on commit 2d048db

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

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.1.13 -m "<description of version>" 2d048dbbee25e9730e4b1bb3fbfc6333bc232346
git push origin v0.1.13

Please sign in to comment.