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

formatted by JuliaFormatter #60

Closed
wants to merge 3 commits into from
Closed
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
86 changes: 57 additions & 29 deletions examples/FMI2/BouncingBall/src/BouncingBall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
# https://github.com/modelica/Reference-FMUs/blob/main/BouncingBall/model.c

using FMIExport
using FMIExport.FMIBase.FMICore: fmi2True, fmi2False
using FMIExport.FMIBase.FMICore: fmi2True, fmi2False

EPS = 1e-8

FMU_FCT_INIT = function()
FMU_FCT_INIT = function ()
m = 1.0 # ball mass
r = 0.0 # ball radius
d = 0.7 # ball collision damping
Expand All @@ -23,8 +23,8 @@ FMU_FCT_INIT = function()
v = 0.0 # ball velocity
a = 0.0 # ball acceleration

t = 0.0
x_c = [s, v]
t = 0.0
x_c = [s, v]
ẋ_c = [v, a]
x_d = [sticking]
u = []
Expand All @@ -33,7 +33,7 @@ FMU_FCT_INIT = function()
return (t, x_c, ẋ_c, x_d, u, p)
end

FMU_FCT_EVALUATE = function(t, x_c, ẋ_c, x_d, u, p, eventMode)
FMU_FCT_EVALUATE = function (t, x_c, ẋ_c, x_d, u, p, eventMode)
m, r, d, v_min, g = p
s, v = x_c
sticking = x_d[1]
Expand All @@ -44,10 +44,10 @@ FMU_FCT_EVALUATE = function(t, x_c, ẋ_c, x_d, u, p, eventMode)
elseif sticking == fmi2False

if eventMode
h = s-r
h = s - r
if h <= 0 && v < 0
s = r + EPS # so that indicator is not triggered again
v = -v*d
v = -v * d

# stop bouncing to prevent high frequency bouncing (and maybe tunneling the floor)
if abs(v) < v_min
Expand All @@ -72,7 +72,7 @@ FMU_FCT_EVALUATE = function(t, x_c, ẋ_c, x_d, u, p, eventMode)
return (x_c, ẋ_c, x_d, p)
end

FMU_FCT_OUTPUT = function(t, x_c, ẋ_c, x_d, u, p)
FMU_FCT_OUTPUT = function (t, x_c, ẋ_c, x_d, u, p)
m, r, d, v_min, g = p
s, v = x_c
_, a = ẋ_c
Expand All @@ -83,22 +83,22 @@ FMU_FCT_OUTPUT = function(t, x_c, ẋ_c, x_d, u, p)
return y
end

FMU_FCT_EVENT = function(t, x_c, ẋ_c, x_d, u, p)
FMU_FCT_EVENT = function (t, x_c, ẋ_c, x_d, u, p)
m, r, d, v_min, g = p
s, v = x_c
_, a = ẋ_c
sticking = x_d[1]

# helpers
z1 = 0.0 # first event indicator
h = s-r # ball height
h = s - r # ball height

if sticking == fmi2True
z1 = 1.0 # event 1: ball stay-on-ground
else
if h > -EPS && h <= 0 && v > 0
z1 = -EPS
else
else
z1 = h
end
end
Expand All @@ -110,33 +110,61 @@ 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)
FMIBUILD_CONSTRUCTOR = function (resPath = "")
fmu = fmi2CreateSimple(
initializationFct = FMU_FCT_INIT,
evaluationFct = FMU_FCT_EVALUATE,
outputFct = FMU_FCT_OUTPUT,
eventFct = FMU_FCT_EVENT,
)

fmu.modelDescription.modelName = "BouncingBall"

# modes
fmi2ModelDescriptionAddModelExchange(fmu.modelDescription, "BouncingBall")

# 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")
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",
)

# discrete state [1]
fmi2AddIntegerDiscreteState(fmu, "sticking"; description="Indicator (boolean) if the mass is sticking on the ground, as soon as abs(v) < v_min")
fmi2AddIntegerDiscreteState(
fmu,
"sticking";
description = "Indicator (boolean) if the mass is sticking on the ground, as soon as abs(v) < v_min",
)

# outputs [1]
fmi2AddRealOutput(fmu, "ball.s_out"; description="Absolute position of ball center of mass")
fmi2AddRealOutput(
fmu,
"ball.s_out";
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")
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)

Expand All @@ -146,18 +174,18 @@ end
### FMIBUILD_NO_EXPORT_BEGIN ###
# The line above is a start-marker for excluded code for the FMU compilation process!

tmpDir = "C:\\Users\\thummeto\\Documents\\FMIExport.jl\\tmp" # mktempdir(; prefix="fmibuildjl_test_", cleanup=false)
tmpDir = mktempdir(; prefix = "fmibuildjl_test_", cleanup = false)
@info "Saving example files at: $(tmpDir)"
fmu_save_path = joinpath(tmpDir, "BouncingBall.fmu")
fmu_save_path = joinpath(tmpDir, "BouncingBall.fmu")

fmu = FMIBUILD_CONSTRUCTOR()
using FMIBuild: saveFMU # <= this must be excluded during export, because FMIBuild cannot execute itself (but it is able to build)
saveFMU(fmu, fmu_save_path; debug=true, compress=false) # <= this must be excluded during export, because saveFMU would start an infinite build loop with itself (debug=true allows debug messages, but is slow during execution!)
saveFMU(fmu, fmu_save_path; debug = true, compress = false) # <= this must be excluded during export, because saveFMU would start an infinite build loop with itself (debug=true allows debug messages, but is slow during execution!)

### some tests ###
using FMI, DifferentialEquations
fmu.executionConfig.loggingOn = true
solution = simulate(fmu, (0.0, 3.0); recordValues=["sticking"])
solution = simulate(fmu, (0.0, 3.0); recordValues = ["sticking"])
using Plots
plot(solution)

Expand Down
40 changes: 23 additions & 17 deletions examples/FMI2/Manipulation/src/Manipulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,48 @@

using FMIExport: fmi2SetFctGetReal, fmi2CreateEmbedded
using FMIExport.FMIBase.FMICore: fmi2Real, fmi2Component, fmi2StatusOK, fmi2ValueReference
using FMIExport.FMIBase.FMICore: fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact
using FMIExport.FMIBase.FMICore:
fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact
using FMIImport: loadFMU
import FMIExport
import FMIExport

originalGetReal = nothing # function pointer to the original fmi2GetReal c-function

# custom function for fmi2GetReal!(fmi2Component, Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}}::fmi2Status
# for information on how the FMI2-functions are structured, have a look inside FMICore.jl/src/FMI2_c.jl or the FMI2.0.3-specification on fmi-standard.org
function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})
function myGetReal!(
c::fmi2Component,
vr::Union{Array{fmi2ValueReference},Ptr{fmi2ValueReference}},
nvr::Csize_t,
value::Union{Array{fmi2Real},Ptr{fmi2Real}},
)
global originalGetReal

# first, we do what the original function does
status = FMIExport.FMIBase.FMICore.fmi2GetReal!(originalGetReal, c, vr, nvr, value)

# if we have a pointer to an array, we must interprete it as array to access elements
if isa(value, Ptr{fmi2Real})
value = unsafe_wrap(Array{fmi2Real}, value, nvr, own=false)
value = unsafe_wrap(Array{fmi2Real}, value, nvr, own = false)
end
if isa(vr, Ptr{fmi2ValueReference})
vr = unsafe_wrap(Array{fmi2ValueReference}, vr, nvr, own=false)
vr = unsafe_wrap(Array{fmi2ValueReference}, vr, nvr, own = false)
end

# now, we add noise (just for fun!)
for i in 1:nvr
for i = 1:nvr
if vr[i] == 335544320 # value reference for "positionSensor.s"
value[i] += (-0.5 + rand())*0.25
value[i] += (-0.5 + rand()) * 0.25
end
end
end

# ... and we return the original status
return status
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)
FMIBUILD_CONSTRUCTOR = function (resPath)
global originalGetReal

# loads an existing FMU inside the FMU
Expand All @@ -54,9 +60,9 @@ FMIBUILD_CONSTRUCTOR = function(resPath)
fmu.modelDescription.coSimulation = nothing

# deactivate special features, because they are not implemented yet
fmu.modelDescription.modelExchange.canGetAndSetFMUstate=false
fmu.modelDescription.modelExchange.canSerializeFMUstate=false
fmu.modelDescription.modelExchange.providesDirectionalDerivative=false
fmu.modelDescription.modelExchange.canGetAndSetFMUstate = false
fmu.modelDescription.modelExchange.canSerializeFMUstate = false
fmu.modelDescription.modelExchange.providesDirectionalDerivative = false

# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function
originalGetReal = fmu.cGetReal
Expand All @@ -72,14 +78,14 @@ end

import FMIZoo

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

sourceFMU = FMIZoo.get_model_filename("SpringDamperPendulum1D", "Dymola", "2022x")
fmu = FMIBUILD_CONSTRUCTOR(dirname(sourceFMU))
import FMIBuild:saveFMU # <= this must be excluded during export, because FMIBuild cannot execute itself (but it is able to build)
saveFMU(fmu, fmu_save_path; resources=Dict(sourceFMU=>"SpringDamperPendulum1D.fmu")) # <= this must be excluded during export, because fmi2Save would start an infinte build loop with itself
import FMIBuild: saveFMU # <= this must be excluded during export, because FMIBuild cannot execute itself (but it is able to build)
saveFMU(fmu, fmu_save_path; resources = Dict(sourceFMU => "SpringDamperPendulum1D.fmu")) # <= this must be excluded during export, because fmi2Save would start an infinte build loop with itself

# some tests
# using FMI
Expand Down
Loading
Loading