From 40b04be7e7d34391075473aba400fc1eb163f1d0 Mon Sep 17 00:00:00 2001 From: TT Date: Tue, 28 May 2024 10:59:50 +0200 Subject: [PATCH 1/5] changes for FMIBase.jl --- Project.toml | 8 ++--- README.md | 3 +- examples/FMI2/BouncingBall/Project.toml | 4 ++- .../FMI2/BouncingBall/src/BouncingBall.jl | 4 +-- examples/FMI2/Manipulation/Project.toml | 4 ++- .../FMI2/Manipulation/src/Manipulation.jl | 10 +++--- examples/FMI2/NeuralFMU/Project.toml | 4 ++- examples/FMI2/NeuralFMU/src/NeuralFMU.jl | 10 +++--- src/FMI2_md.jl | 5 ++- src/FMI2_simple.jl | 4 +-- src/FMIExport.jl | 31 ++++++++++--------- test/Project.toml | 2 +- 12 files changed, 50 insertions(+), 39 deletions(-) diff --git a/Project.toml b/Project.toml index 2e84639..00c1b73 100644 --- a/Project.toml +++ b/Project.toml @@ -1,17 +1,15 @@ name = "FMIExport" uuid = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" authors = ["TT ", "LM "] -version = "0.3.2" +version = "0.4.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" -EzXML = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615" -FMICore = "8af89139-c281-408e-bce2-3005eb87462f" +FMIBase = "900ee838-d029-460e-b485-d98a826ceef2" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] Dates = "1" -EzXML = "1.1.0" -FMICore = "0.18.0 - 0.20" +FMIBase = "1.0.0" UUIDs = "1" julia = "1.6" diff --git a/README.md b/README.md index a7268c8..7203eff 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,11 @@ To keep dependencies nice and clean, the original package [*FMI.jl*](https://git - [*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 +- [*FMIBase.jl*](https://github.com/ThummeTo/FMIBase.jl): Common concepts for import and export of FMUs - [*FMICore.jl*](https://github.com/ThummeTo/FMICore.jl): C-code wrapper for the FMI-standard - [*FMISensitivity.jl*](https://github.com/ThummeTo/FMISensitivity.jl): Static and dynamic sensitivities over FMUs - [*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) +- [*FMIFlux.jl*](https://github.com/ThummeTo/FMIFlux.jl): Machine Learning with FMUs - [*FMIZoo.jl*](https://github.com/ThummeTo/FMIZoo.jl): A collection of testing and example FMUs ## What Platforms are supported? diff --git a/examples/FMI2/BouncingBall/Project.toml b/examples/FMI2/BouncingBall/Project.toml index fb7408c..141a89c 100644 --- a/examples/FMI2/BouncingBall/Project.toml +++ b/examples/FMI2/BouncingBall/Project.toml @@ -4,9 +4,11 @@ authors = ["TT "] version = "0.1.0" [deps] +FMIBase = "900ee838-d029-460e-b485-d98a826ceef2" FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" +FMICore = "8af89139-c281-408e-bce2-3005eb87462f" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" [compat] -FMIBuild = "0.2.0" +FMIBuild = "0.3.0" julia = "1.6" diff --git a/examples/FMI2/BouncingBall/src/BouncingBall.jl b/examples/FMI2/BouncingBall/src/BouncingBall.jl index 25610b3..763ed64 100644 --- a/examples/FMI2/BouncingBall/src/BouncingBall.jl +++ b/examples/FMI2/BouncingBall/src/BouncingBall.jl @@ -134,8 +134,8 @@ tmpDir = mktempdir(; prefix="fmibuildjl_test_", cleanup=false) 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; debug=true) # <= this must be excluded during export, because fmi2Save would start an infinte build loop with itself (debug=true allows debug messages, but is slow during execution!) +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) # <= this must be excluded during export, because fmi2Save would start an infinte build loop with itself (debug=true allows debug messages, but is slow during execution!) ### some tests ### # using FMI diff --git a/examples/FMI2/Manipulation/Project.toml b/examples/FMI2/Manipulation/Project.toml index 0aa09b0..3c00603 100644 --- a/examples/FMI2/Manipulation/Project.toml +++ b/examples/FMI2/Manipulation/Project.toml @@ -4,11 +4,13 @@ authors = ["TT "] version = "0.1.0" [deps] +FMIBase = "900ee838-d029-460e-b485-d98a826ceef2" FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" +FMICore = "8af89139-c281-408e-bce2-3005eb87462f" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" FMIZoo = "724179cf-c260-40a9-bd27-cccc6fe2f195" [compat] -FMIBuild = "0.2.0" +FMIBuild = "0.3.0" julia = "1.6" diff --git a/examples/FMI2/Manipulation/src/Manipulation.jl b/examples/FMI2/Manipulation/src/Manipulation.jl index 218717b..9df5c12 100644 --- a/examples/FMI2/Manipulation/src/Manipulation.jl +++ b/examples/FMI2/Manipulation/src/Manipulation.jl @@ -6,7 +6,7 @@ using FMIExport: fmi2SetFctGetReal, fmi2CreateEmbedded using FMIExport.FMICore: fmi2Real, fmi2Component, fmi2StatusOK, fmi2ValueReference using FMIExport.FMICore: fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact -using FMIImport: fmi2Load +using FMIImport: loadFMU import FMIExport originalGetReal = nothing # function pointer to the original fmi2GetReal c-function @@ -17,7 +17,7 @@ function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{f global originalGetReal # first, we do what the original function does - status = FMIExport.FMICore.fmi2GetReal!(originalGetReal, c, vr, nvr, value) + 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}) @@ -44,7 +44,7 @@ FMIBUILD_CONSTRUCTOR = function(resPath) global originalGetReal # loads an existing FMU inside the FMU - fmu = fmi2Load(joinpath(resPath, "SpringDamperPendulum1D.fmu")) + fmu = loadFMU(joinpath(resPath, "SpringDamperPendulum1D.fmu")) # create a FMU that embedds the existing FMU fmu = fmi2CreateEmbedded(fmu) @@ -78,8 +78,8 @@ fmu_save_path = joinpath(tmpDir, "Manipulation.fmu") sourceFMU = FMIZoo.get_model_filename("SpringDamperPendulum1D", "Dymola", "2022x") fmu = FMIBUILD_CONSTRUCTOR(dirname(sourceFMU)) -import FMIBuild:fmi2Save # <= this must be excluded during export, because FMIBuild cannot execute itself (but it is able to build) -fmi2Save(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 diff --git a/examples/FMI2/NeuralFMU/Project.toml b/examples/FMI2/NeuralFMU/Project.toml index 66a8fc6..822005b 100644 --- a/examples/FMI2/NeuralFMU/Project.toml +++ b/examples/FMI2/NeuralFMU/Project.toml @@ -4,11 +4,13 @@ authors = ["TT "] version = "0.1.0" [deps] +FMIBase = "900ee838-d029-460e-b485-d98a826ceef2" FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" +FMICore = "8af89139-c281-408e-bce2-3005eb87462f" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" FMIZoo = "724179cf-c260-40a9-bd27-cccc6fe2f195" [compat] -FMIBuild = "0.2.0" +FMIBuild = "0.3.0" julia = "1.6" diff --git a/examples/FMI2/NeuralFMU/src/NeuralFMU.jl b/examples/FMI2/NeuralFMU/src/NeuralFMU.jl index 1a07fbe..5a17a7f 100644 --- a/examples/FMI2/NeuralFMU/src/NeuralFMU.jl +++ b/examples/FMI2/NeuralFMU/src/NeuralFMU.jl @@ -9,7 +9,7 @@ using FMIExport: fmi2CreateEmbedded using FMIExport: fmi2AddRealParameter using FMIExport.FMICore: fmi2Real, fmi2Component, fmi2StatusOK, fmi2ValueReference using FMIExport.FMICore: fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact -using FMIImport: fmi2Load +using FMIImport: loadFMU import FMIExport fmu = nothing @@ -141,7 +141,7 @@ function updateDerivatives(_component::fmi2Component, ndx::Csize_t) if !DERIVATIVES_VALID # first, we do what the original function does - status = FMIExport.FMICore.fmi2GetDerivatives!(originalGetDerivatives, _component, DERIVATIVES, ndx) + status = FMIExport.FMIBase.FMICore.fmi2GetDerivatives!(originalGetDerivatives, _component, DERIVATIVES, ndx) if status != fmi2StatusOK logError(_component, "fmi2GetDerivatives failed!") @@ -305,7 +305,7 @@ FMIBUILD_CONSTRUCTOR = function(resPath) global fmu, ANN_PARAMETERS # loads an existing FMU - fmu = fmi2Load(joinpath(resPath, "SpringDamperPendulum1D.fmu")) + fmu = loadFMU(joinpath(resPath, "SpringDamperPendulum1D.fmu")) # create a FMU that embedds the existing FMU fmu = fmi2CreateEmbedded(fmu) @@ -366,8 +366,8 @@ fmu_save_path = joinpath(tmpDir, "NeuralFMU.fmu") sourceFMU = FMIZoo.get_model_filename("SpringDamperPendulum1D", "Dymola", "2022x") fmu = FMIBUILD_CONSTRUCTOR(dirname(sourceFMU)) -import FMIBuild:fmi2Save # <= this must be excluded during export, because FMIBuild cannot execute itself (but it is able to build) -fmi2Save(fmu, fmu_save_path; compress=false, debug=true, 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; compress=false, debug=true, 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 diff --git a/src/FMI2_md.jl b/src/FMI2_md.jl index ed7f93e..6dc05cc 100644 --- a/src/FMI2_md.jl +++ b/src/FMI2_md.jl @@ -3,10 +3,13 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # -using EzXML +using FMIBase.EzXML import UUIDs import Dates +import FMIBase.FMICore: fmi2ModelDescriptionModelExchange, fmi2ModelDescriptionCoSimulation +import FMIBase.FMICore: fmi2RealAttributesExt, fmi2IntegerAttributesExt, fmi2BooleanAttributesExt, fmi2StringAttributesExt, fmi2EnumerationAttributesExt + function fmi2CreateModelDescription() md = fmi2ModelDescription() md.guid = UUIDs.uuid1() diff --git a/src/FMI2_simple.jl b/src/FMI2_simple.jl index 9c24859..5a561cc 100644 --- a/src/FMI2_simple.jl +++ b/src/FMI2_simple.jl @@ -3,8 +3,8 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # -import FMICore: fmi2ComponentStateEventMode, fmi2ComponentStateInstantiated, fmi2ComponentStateContinuousTimeMode -import FMICore: logInfo, logWarning, logError +#import FMICore: fmi2ComponentStateEventMode, fmi2ComponentStateInstantiated, fmi2ComponentStateContinuousTimeMode +#import FMICore: logInfo, logWarning, logError FMU_NUM_STATES = 0 # FMU_NUM_DERIVATIVES = FMU_NUM_STATES diff --git a/src/FMIExport.jl b/src/FMIExport.jl index fb3a68a..a32a245 100644 --- a/src/FMIExport.jl +++ b/src/FMIExport.jl @@ -5,20 +5,23 @@ module FMIExport -using FMICore -using FMICore: FMU2, FMU2Component, fmi2ModelDescription, fmi2ValueReference, fmi2Component, fmi2ComponentEnvironment, fmi2Status, fmi2EventInfo -using FMICore: fmi2Causality, fmi2CausalityOutput, fmi2CausalityInput -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 -using FMICore: fmi2String, fmi2Boolean, fmi2Integer, fmi2Real -using FMICore: fmi2Type, fmi2TypeModelExchange, fmi2TypeCoSimulation -using FMICore: fmi2CallbackFunctions -using FMICore: fmi2StatusOK, fmi2StatusWarning, fmi2StatusError -using FMICore: fmi2True, fmi2False -using FMICore: fmi2ModelDescriptionModelExchange, fmi2ModelDescriptionCoSimulation +# using FMICore +# using FMICore: FMU2, FMU2Component, fmi2ModelDescription, fmi2ValueReference, fmi2Component, fmi2ComponentEnvironment, fmi2Status, fmi2EventInfo +# using FMICore: fmi2Causality, fmi2CausalityOutput, fmi2CausalityInput +# 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 +# using FMICore: fmi2String, fmi2Boolean, fmi2Integer, fmi2Real +# using FMICore: fmi2Type, fmi2TypeModelExchange, fmi2TypeCoSimulation +# using FMICore: fmi2CallbackFunctions +# using FMICore: fmi2StatusOK, fmi2StatusWarning, fmi2StatusError +# using FMICore: fmi2True, fmi2False +# using FMICore: fmi2ModelDescriptionModelExchange, fmi2ModelDescriptionCoSimulation +using FMIBase +using FMIBase.FMICore +using FMIBase.FMICore: FMI2_SCALAR_VARIABLE_ATTRIBUTE_STRUCT include("FMI2_md.jl") export fmi2CreateModelDescription diff --git a/test/Project.toml b/test/Project.toml index 56a04fd..56391c0 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,10 +1,10 @@ [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" FMIZoo = "724179cf-c260-40a9-bd27-cccc6fe2f195" PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] julia = "1.6" From 9b17b0d1fce2ebc2397a42b9497f251fab0b7c98 Mon Sep 17 00:00:00 2001 From: TT Date: Tue, 18 Jun 2024 17:04:37 +0200 Subject: [PATCH 2/5] adaptions for FMIBase --- examples/FMI2/BouncingBall/Project.toml | 2 -- .../FMI2/BouncingBall/src/BouncingBall.jl | 2 +- examples/FMI2/Manipulation/Project.toml | 2 -- .../FMI2/Manipulation/src/Manipulation.jl | 4 ++-- examples/FMI2/NeuralFMU/Project.toml | 2 -- examples/FMI2/NeuralFMU/src/NeuralFMU.jl | 4 ++-- src/FMI2_simple.jl | 22 +++++++++---------- test/bouncing_ball.jl | 4 +++- test/manipulation.jl | 4 +++- test/neuralFMU.jl | 4 +++- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/FMI2/BouncingBall/Project.toml b/examples/FMI2/BouncingBall/Project.toml index 141a89c..08eec9b 100644 --- a/examples/FMI2/BouncingBall/Project.toml +++ b/examples/FMI2/BouncingBall/Project.toml @@ -4,9 +4,7 @@ authors = ["TT "] version = "0.1.0" [deps] -FMIBase = "900ee838-d029-460e-b485-d98a826ceef2" FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" -FMICore = "8af89139-c281-408e-bce2-3005eb87462f" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" [compat] diff --git a/examples/FMI2/BouncingBall/src/BouncingBall.jl b/examples/FMI2/BouncingBall/src/BouncingBall.jl index 763ed64..6c932e4 100644 --- a/examples/FMI2/BouncingBall/src/BouncingBall.jl +++ b/examples/FMI2/BouncingBall/src/BouncingBall.jl @@ -4,7 +4,7 @@ # using FMIExport -using FMIExport.FMICore: fmi2True, fmi2False +using FMIExport.FMIBase.FMICore: fmi2True, fmi2False FMU_FCT_INIT = function() m = 1.0 # ball mass diff --git a/examples/FMI2/Manipulation/Project.toml b/examples/FMI2/Manipulation/Project.toml index 3c00603..410ee4f 100644 --- a/examples/FMI2/Manipulation/Project.toml +++ b/examples/FMI2/Manipulation/Project.toml @@ -4,9 +4,7 @@ authors = ["TT "] version = "0.1.0" [deps] -FMIBase = "900ee838-d029-460e-b485-d98a826ceef2" FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" -FMICore = "8af89139-c281-408e-bce2-3005eb87462f" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" FMIZoo = "724179cf-c260-40a9-bd27-cccc6fe2f195" diff --git a/examples/FMI2/Manipulation/src/Manipulation.jl b/examples/FMI2/Manipulation/src/Manipulation.jl index 9df5c12..82fff05 100644 --- a/examples/FMI2/Manipulation/src/Manipulation.jl +++ b/examples/FMI2/Manipulation/src/Manipulation.jl @@ -4,8 +4,8 @@ # using FMIExport: fmi2SetFctGetReal, fmi2CreateEmbedded -using FMIExport.FMICore: fmi2Real, fmi2Component, fmi2StatusOK, fmi2ValueReference -using FMIExport.FMICore: fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact +using FMIExport.FMIBase.FMICore: fmi2Real, fmi2Component, fmi2StatusOK, fmi2ValueReference +using FMIExport.FMIBase.FMICore: fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact using FMIImport: loadFMU import FMIExport diff --git a/examples/FMI2/NeuralFMU/Project.toml b/examples/FMI2/NeuralFMU/Project.toml index 822005b..8d407c7 100644 --- a/examples/FMI2/NeuralFMU/Project.toml +++ b/examples/FMI2/NeuralFMU/Project.toml @@ -4,9 +4,7 @@ authors = ["TT "] version = "0.1.0" [deps] -FMIBase = "900ee838-d029-460e-b485-d98a826ceef2" FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" -FMICore = "8af89139-c281-408e-bce2-3005eb87462f" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" FMIZoo = "724179cf-c260-40a9-bd27-cccc6fe2f195" diff --git a/examples/FMI2/NeuralFMU/src/NeuralFMU.jl b/examples/FMI2/NeuralFMU/src/NeuralFMU.jl index 5a17a7f..68e5ebc 100644 --- a/examples/FMI2/NeuralFMU/src/NeuralFMU.jl +++ b/examples/FMI2/NeuralFMU/src/NeuralFMU.jl @@ -7,8 +7,8 @@ using FMIExport: Dense, Chain using FMIExport: fmi2SetFctGetDerivatives, fmi2SetFctGetReal, fmi2SetFctSetReal, fmi2SetFctSetTime, fmi2SetFctSetContinuousStates using FMIExport: fmi2CreateEmbedded using FMIExport: fmi2AddRealParameter -using FMIExport.FMICore: fmi2Real, fmi2Component, fmi2StatusOK, fmi2ValueReference -using FMIExport.FMICore: fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact +using FMIExport.FMIBase.FMICore: fmi2Real, fmi2Component, fmi2StatusOK, fmi2ValueReference +using FMIExport.FMIBase.FMICore: fmi2CausalityParameter, fmi2VariabilityTunable, fmi2InitialExact using FMIImport: loadFMU import FMIExport diff --git a/src/FMI2_simple.jl b/src/FMI2_simple.jl index 5a561cc..97545d4 100644 --- a/src/FMI2_simple.jl +++ b/src/FMI2_simple.jl @@ -24,7 +24,7 @@ FMU_FCT_EVENT = function(t, xc, ẋc, xd, u, p) return [] end function dereferenceInstance(address::fmi2Component) global FMIBUILD_FMU for component in FMIBUILD_FMU.components - if component.compAddr == address + if component.addr == address return component end end @@ -42,7 +42,7 @@ function reset(_component::fmi2Component) component.z = FMU_FCT_EVENT(component.t, xc, ẋc, xd, u, p) y = FMU_FCT_OUTPUT(component.t, xc, ẋc, xd, u, p) - applyValues(component.compAddr, xc, ẋc, xd, u, y, p) + applyValues(component.addr, xc, ẋc, xd, u, y, p) end function evaluate(_component::fmi2Component, eventMode=false) @@ -160,16 +160,16 @@ function simple_fmi2Instantiate(instanceName::fmi2String, global FMIBUILD_FMU component = FMU2Component(FMIBUILD_FMU) - component.loggingOn = loggingOn + component.loggingOn = (loggingOn == fmi2True) component.callbackFunctions = unsafe_load(functions) component.instanceName = unsafe_string(instanceName) - component.compAddr = pointer_from_objref(component) + component.addr = pointer_from_objref(component) push!(FMIBUILD_FMU.components, component) - reset(component.compAddr) + reset(component.addr) - return component.compAddr + return component.addr end function embedded_fmi2Instantiate(instanceName::fmi2String, @@ -187,10 +187,10 @@ function embedded_fmi2Instantiate(instanceName::fmi2String, component.callbackFunctions = unsafe_load(functions) component.instanceName = unsafe_string(instanceName) - component.compAddr = FMICore.fmi2Instantiate(FMIBUILD_FMU.cFunctionPtrs["EMBEDDED_fmi2Instantiate"], instanceName, fmuType, fmuGUID, fmuResourceLocation, functions, visible, loggingOn) + component.addr = FMICore.fmi2Instantiate(FMIBUILD_FMU.cFunctionPtrs["EMBEDDED_fmi2Instantiate"], instanceName, fmuType, fmuGUID, fmuResourceLocation, functions, visible, loggingOn) push!(FMIBUILD_FMU.components, component) - return component.compAddr + return component.addr end function simple_fmi2FreeInstance(_component::fmi2Component) @@ -200,7 +200,7 @@ function simple_fmi2FreeInstance(_component::fmi2Component) global FMIBUILD_FMU for i in 1:length(FMIBUILD_FMU.components) - if FMIBUILD_FMU.components[i].compAddr == component.compAddr + if FMIBUILD_FMU.components[i].addr == component.addr deleteat!(FMIBUILD_FMU.components, i) break end @@ -219,8 +219,8 @@ function embedded_fmi2FreeInstance(_component::fmi2Component) global FMIBUILD_FMU for i in 1:length(FMIBUILD_FMU.components) - if FMIBUILD_FMU.components[i].compAddr == component.compAddr - FMICore.fmi2FreeInstance!(FMIBUILD_FMU.cFunctionPtrs["EMBEDDED_fmi2FreeInstance"], component.compAddr) + if FMIBUILD_FMU.components[i].addr == component.addr + FMICore.fmi2FreeInstance!(FMIBUILD_FMU.cFunctionPtrs["EMBEDDED_fmi2FreeInstance"], component.addr) deleteat!(FMIBUILD_FMU.components, i) break end diff --git a/test/bouncing_ball.jl b/test/bouncing_ball.jl index 46af70d..b10e786 100644 --- a/test/bouncing_ball.jl +++ b/test/bouncing_ball.jl @@ -31,4 +31,6 @@ include(joinpath(@__DIR__, "..", "examples", "FMI2", "BouncingBall", "src", "Bou # solution_FMI_jl = fmiSimulateME(fmu, (0.0, 5.0); dtmax=0.1) # @test solution_FMI_jl.states.t[end] == 5.0 -# @test solution_FMI_jl.states.u[end] == [1.0e-10, 0.0] \ No newline at end of file +# @test solution_FMI_jl.states.u[end] == [1.0e-10, 0.0] + +rm(fmu_save_path) \ No newline at end of file diff --git a/test/manipulation.jl b/test/manipulation.jl index 73a55ba..541752a 100644 --- a/test/manipulation.jl +++ b/test/manipulation.jl @@ -36,4 +36,6 @@ include(joinpath(@__DIR__, "..", "examples", "FMI2", "Manipulation", "src", "Man # ToDo check results # @test solution_FMI_jl.states.t[end] == 5.0 -# @test solution_FMI_jl.states.u[end] == [0.0, 0.0] \ No newline at end of file +# @test solution_FMI_jl.states.u[end] == [0.0, 0.0] + +rm(fmu_save_path) \ No newline at end of file diff --git a/test/neuralFMU.jl b/test/neuralFMU.jl index 52fd0d5..c1e7e2d 100644 --- a/test/neuralFMU.jl +++ b/test/neuralFMU.jl @@ -36,4 +36,6 @@ include(joinpath(@__DIR__, "..", "examples", "FMI2", "NeuralFMU", "src", "Neural # ToDo check results # @test solution_FMI_jl.states.t[end] == 5.0 -# @test solution_FMI_jl.states.u[end] == [0.0, 0.0] \ No newline at end of file +# @test solution_FMI_jl.states.u[end] == [0.0, 0.0] + +rm(fmu_save_path) \ No newline at end of file From 8e0d770eefe76b7866ca072460ac865cec9a1b70 Mon Sep 17 00:00:00 2001 From: TT Date: Fri, 19 Jul 2024 11:49:20 +0200 Subject: [PATCH 3/5] python test action for exported FMUs --- .github/workflows/SimFMU.py | 28 ++++++++++ .github/workflows/SimFMU.yml | 39 ++++++++++++++ .../FMI2/BouncingBall/src/BouncingBall.jl | 9 ++-- src/FMI2_simple.jl | 37 ++++++++----- test/bouncing_ball.jl | 53 ++++++++++++------- test/runtests.jl | 22 ++++---- 6 files changed, 144 insertions(+), 44 deletions(-) create mode 100644 .github/workflows/SimFMU.py create mode 100644 .github/workflows/SimFMU.yml diff --git a/.github/workflows/SimFMU.py b/.github/workflows/SimFMU.py new file mode 100644 index 0000000..494db9c --- /dev/null +++ b/.github/workflows/SimFMU.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import fmpy +import os + +FMU_PATH = "" +START = 0.0 +STOP = 0.0 + +try: + FMU_PATH = os.environ["FMU_PATH"] + START = os.environ["START"] + STOP = os.environ["STOP"] +except KeyError: + print("Can't read inputs!") + sys.exit(1) + +#fmu_save_path = "C:/Users/thummeto/Documents/FMIZoo.jl/models/bin/Dymola/2023x/2.0/BouncingBallGravitySwitch1D.fmu" +#t_start = 0.0 +#t_stop = 5.0 + +solution = fmpy.simulate_fmu(filename=FMU_PATH, + validate=False, + start_time=START, + stop_time=STOP, record_events=True, solver="CVode") + +print(solution[1]) +sys.exit(0) \ No newline at end of file diff --git a/.github/workflows/SimFMU.yml b/.github/workflows/SimFMU.yml new file mode 100644 index 0000000..3fba1c6 --- /dev/null +++ b/.github/workflows/SimFMU.yml @@ -0,0 +1,39 @@ +name: run SimFMU.py + +on: + workflow_dispatch: + inputs: + fmu_path: + type: string + required: true + start: + type: string + required: true + stop: + type: string + required: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: checkout repo content + uses: actions/checkout@v2 # checkout the repository content + + - name: setup python + uses: actions/setup-python@v4 + with: + python-version: '3.10' # install the python version needed + + - name: install python packages + run: | + python -m pip install --upgrade pip + # pip install -r requirements.txt + pip install fmpy + + - name: execute py script # run SimFMU.py + env: + FMU_PATH: ${{ inputs.fmu_path }} + START: ${{ inputs.start }} + STOP: ${{ inputs.stop }} + run: python SimFMU.py \ No newline at end of file diff --git a/examples/FMI2/BouncingBall/src/BouncingBall.jl b/examples/FMI2/BouncingBall/src/BouncingBall.jl index 6c932e4..9ee8d91 100644 --- a/examples/FMI2/BouncingBall/src/BouncingBall.jl +++ b/examples/FMI2/BouncingBall/src/BouncingBall.jl @@ -38,7 +38,7 @@ FMU_FCT_EVALUATE = function(t, x_c, ẋ_c, x_d, u, p, eventMode) if sticking == fmi2True a = 0.0 - else + elseif sticking == fmi2False if eventMode if s < r && v < 0.0 s = r + eps # so that indicator is not triggered again @@ -52,7 +52,10 @@ FMU_FCT_EVALUATE = function(t, x_c, ẋ_c, x_d, u, p, eventMode) end end - a = (m * -g) / m # the system's physical equation + a = (m * -g) / m # the system's physical equation (a little longer than necessary) + else + @error "Unknown value for `sticking` == $(sticking)." + return (x_c, ẋ_c, x_d, p) end x_c = [s, v] @@ -135,7 +138,7 @@ 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) # <= this must be excluded during export, because fmi2Save would start an infinte 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 fmi2Save would start an infinte build loop with itself (debug=true allows debug messages, but is slow during execution!) ### some tests ### # using FMI diff --git a/src/FMI2_simple.jl b/src/FMI2_simple.jl index 97545d4..6e3313f 100644 --- a/src/FMI2_simple.jl +++ b/src/FMI2_simple.jl @@ -306,24 +306,27 @@ function simple_fmi2GetInteger(_component::fmi2Component, _vr::Ptr{fmi2ValueRefe component = dereferenceInstance(_component) # ToDo + logWarning(component, "fmi2GetInteger: Not implemented yet, please open an issue.") - return fmi2StatusOK + return fmi2StatusWarning end function simple_fmi2GetBoolean(_component::fmi2Component, _vr::Ptr{fmi2ValueReference}, nvr::Csize_t, _value::Ptr{fmi2Boolean}) component = dereferenceInstance(_component) # ToDo + logWarning(component, "fmi2GetBoolean: Not implemented yet, please open an issue.") - return fmi2StatusOK + return fmi2StatusWarning end function simple_fmi2GetString(_component::fmi2Component, _vr::Ptr{fmi2ValueReference}, nvr::Csize_t, _value::Ptr{fmi2String}) component = dereferenceInstance(_component) # ToDo + logWarning(component, "fmi2GetString: Not implemented yet, please open an issue.") - return fmi2StatusOK + return fmi2StatusWarning end function simple_fmi2SetReal(_component::fmi2Component, _vr::Ptr{fmi2ValueReference}, nvr::Csize_t, _value::Ptr{fmi2Real}) @@ -352,24 +355,27 @@ function simple_fmi2SetInteger(_component::fmi2Component, _vr::Ptr{fmi2ValueRefe component = dereferenceInstance(_component) # ToDo + logWarning(component, "fmi2SetInteger: Not implemented yet, please open an issue.") - return fmi2StatusOK + return fmi2StatusWarning end function simple_fmi2SetBoolean(_component::fmi2Component, _vr::Ptr{fmi2ValueReference}, nvr::Csize_t, _value::Ptr{fmi2Boolean}) component = dereferenceInstance(_component) # ToDo + logWarning(component, "fmi2SetBoolean: Not implemented yet, please open an issue.") - return fmi2StatusOK + return fmi2StatusWarning end function simple_fmi2SetString(_component::fmi2Component, _vr::Ptr{fmi2ValueReference}, nvr::Csize_t, _value::Ptr{fmi2String}) component = dereferenceInstance(_component) # ToDo + logWarning(component, "fmi2SetString: Not implemented yet, please open an issue.") - return fmi2StatusOK + return fmi2StatusWarning end function simple_fmi2SetTime(_component::fmi2Component, time::fmi2Real) @@ -417,11 +423,11 @@ function simple_fmi2NewDiscreteStates(_component::fmi2Component, _fmi2eventInfo: # ToDo: This is not efficient (copy struct and overwrite), direct memory access would be much nicer! eventInfo = unsafe_load(_fmi2eventInfo) eventInfo.newDiscreteStatesNeeded = component.eventInfo.newDiscreteStatesNeeded - eventInfo.terminateSimulation = fmi2False - eventInfo.nominalsOfContinuousStatesChanged = fmi2False + eventInfo.terminateSimulation = fmi2False # [ToDo] + eventInfo.nominalsOfContinuousStatesChanged = fmi2False # [ToDo] eventInfo.valuesOfContinuousStatesChanged = component.eventInfo.valuesOfContinuousStatesChanged - eventInfo.nextEventTimeDefined = fmi2False - eventInfo.nextEventTime = 0.0 + eventInfo.nextEventTimeDefined = fmi2False # [ToDo] + eventInfo.nextEventTime = 0.0 # [ToDo] unsafe_store!(_fmi2eventInfo, eventInfo); return fmi2StatusOK @@ -439,8 +445,9 @@ function simple_fmi2CompletedIntegratorStep(_component::fmi2Component, noSetFMUS component = dereferenceInstance(_component) # ToDo + logWarning(component, "fmi2CompletedIntegratorStep: Not implemented yet, please open an issue.") - return fmi2StatusOK + return fmi2StatusWarning end function simple_fmi2GetDerivatives(_component::fmi2Component, _derivatives::Ptr{fmi2Real}, nx::Csize_t) @@ -469,13 +476,15 @@ function simple_fmi2GetEventIndicators(_component::fmi2Component, _eventIndicato eventIndicators = unsafe_wrap(Array{fmi2Real}, _eventIndicators, ni) + t = component.t + xc, ẋc, xd, u, y, p = extractValues(_component) + component.z = FMU_FCT_EVENT(t, xc, ẋc, xd, u, p) + for i in 1:ni eventIndicators[i] = component.z[i] end - status = fmi2StatusOK - - return status + return fmi2StatusOK end function simple_fmi2GetContinuousStates(_component::fmi2Component, _x::Ptr{fmi2Real}, nx::Csize_t) diff --git a/test/bouncing_ball.jl b/test/bouncing_ball.jl index b10e786..f045344 100644 --- a/test/bouncing_ball.jl +++ b/test/bouncing_ball.jl @@ -6,31 +6,48 @@ # export FMU script include(joinpath(@__DIR__, "..", "examples", "FMI2", "BouncingBall", "src", "BouncingBall.jl")) +# demo! +using FMIZoo, Test, Plots +#fmu_save_path = FMIZoo.get_model_filename("BouncingBall1D", "Dymola", "2022x") +fmu_save_path = "C:/Users/thummeto/Documents/FMIZoo.jl/models/bin/Dymola/2023x/2.0/BouncingBallGravitySwitch1D.fmu" + # check if FMU exists now @test isfile(fmu_save_path) # Simulate FMU in Python / FMPy -# @info "Installing `fmpy`..." -# using Conda -# Conda.add("fmpy"; channel="conda-forge") +@info "Installing `fmpy`..." +using Conda +Conda.add("fmpy"; channel="conda-forge") # @info "Simulating with `fmpy`..." -# using PyCall -# fmpy = pyimport("fmpy") -# fmpy.dump(fmu_save_path) +using PyCall +@pyimport fmpy +fmpy.dump(fmu_save_path) + +t_start = 0.0 +t_stop = 5.0 + +solution_FMPy = fmpy.simulate_fmu(filename=fmu_save_path, + validate=false, + start_time=t_start, + stop_time=t_stop, record_events=true, solver="CVode") # fmi_call_logger=lambda s: print('[FMI] ' + s) , + +ts = collect(solution_FMPy[i][1] for i in 1:length(solution_FMPy)) +ss = collect(solution_FMPy[i][2] for i in 1:length(solution_FMPy)) +vs = collect(solution_FMPy[i][3] for i in 1:length(solution_FMPy)) + +@test length(solution_FMPy) == 1001 -# ToDo: Unfortunately, this errors ... (but it runs in python shell) -# solution_FMPy = fmpy.simulate_fmu(filename=fmu_save_path, -# validate=false, -# start_time=0.0, -# stop_time=5.0) # , fmi_call_logger=lambda s: print('[FMI] ' + s) , record_events=true, solver="CVode" +@test isapprox(ts[1], t_start; atol=1e-6) +@test isapprox(ss[1], 1.0; atol=1e-6) +@test isapprox(vs[1], 0.0; atol=1e-6) -# Simulate FMU in Julia / FMI.jl -# using FMI -# fmu.executionConfig.loggingOn = true -# solution_FMI_jl = fmiSimulateME(fmu, (0.0, 5.0); dtmax=0.1) +@test isapprox(ts[end], t_stop; atol=1e-6) +@test isapprox(ss[end], 0.23272552; atol=1e-6) +@test isapprox(vs[end], -0.17606235; atol=1e-6) -# @test solution_FMI_jl.states.t[end] == 5.0 -# @test solution_FMI_jl.states.u[end] == [1.0e-10, 0.0] +plot(ts, ss) +plot(ts, vs) -rm(fmu_save_path) \ No newline at end of file +# ToDo: enable the following line +#rm(fmu_save_path) \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 1b52929..4f5706c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,20 +15,24 @@ function runtests() include("bouncing_ball.jl") end - @testset "FMU Manipulation" begin - #@warn "The test `FMU Manipulation` is currently excluded because of insufficient ressources in GitHub-Actions." - include("manipulation.jl") - end + # @testset "FMU Manipulation" begin + # #@warn "The test `FMU Manipulation` is currently excluded because of insufficient ressources in GitHub-Actions." + # include("manipulation.jl") + # end - @testset "NeuralFMU" begin - #@warn "The test `NeuralFMU` is currently excluded because of insufficient ressources in GitHub-Actions." - include("neuralFMU.jl") - end + # @testset "NeuralFMU" begin + # #@warn "The test `NeuralFMU` is currently excluded because of insufficient ressources in GitHub-Actions." + # include("neuralFMU.jl") + # end end @testset "FMIExport.jl" begin - if Sys.iswindows() || Sys.islinux() || Sys.isapple() + if Sys.iswindows() @info "Automated testing is supported on Windows/Linux/Mac." runtests() + else Sys.islinux() || Sys.isapple() + @warn "Tests not supported on Linux and Mac." + else + @warn "Tests not supported on `unknown operation system`." end end \ No newline at end of file From 12bdec8bec1d2a2a2c4a7dad7f221450364acd3c Mon Sep 17 00:00:00 2001 From: TT Date: Fri, 9 Aug 2024 10:26:19 +0200 Subject: [PATCH 4/5] updates for FMIBUild v0.3.1 --- .github/workflows/SimFMU.py | 28 ---------- .github/workflows/SimFMU.yml | 39 ------------- .../FMI2/BouncingBall/src/BouncingBall.jl | 8 ++- src/FMI2_md.jl | 7 ++- src/FMI2_simple.jl | 43 ++++++++++---- test/bouncing_ball.jl | 56 ++++++++++--------- test/runtests.jl | 42 +++++++------- 7 files changed, 91 insertions(+), 132 deletions(-) delete mode 100644 .github/workflows/SimFMU.py delete mode 100644 .github/workflows/SimFMU.yml diff --git a/.github/workflows/SimFMU.py b/.github/workflows/SimFMU.py deleted file mode 100644 index 494db9c..0000000 --- a/.github/workflows/SimFMU.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import fmpy -import os - -FMU_PATH = "" -START = 0.0 -STOP = 0.0 - -try: - FMU_PATH = os.environ["FMU_PATH"] - START = os.environ["START"] - STOP = os.environ["STOP"] -except KeyError: - print("Can't read inputs!") - sys.exit(1) - -#fmu_save_path = "C:/Users/thummeto/Documents/FMIZoo.jl/models/bin/Dymola/2023x/2.0/BouncingBallGravitySwitch1D.fmu" -#t_start = 0.0 -#t_stop = 5.0 - -solution = fmpy.simulate_fmu(filename=FMU_PATH, - validate=False, - start_time=START, - stop_time=STOP, record_events=True, solver="CVode") - -print(solution[1]) -sys.exit(0) \ No newline at end of file diff --git a/.github/workflows/SimFMU.yml b/.github/workflows/SimFMU.yml deleted file mode 100644 index 3fba1c6..0000000 --- a/.github/workflows/SimFMU.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: run SimFMU.py - -on: - workflow_dispatch: - inputs: - fmu_path: - type: string - required: true - start: - type: string - required: true - stop: - type: string - required: true - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: checkout repo content - uses: actions/checkout@v2 # checkout the repository content - - - name: setup python - uses: actions/setup-python@v4 - with: - python-version: '3.10' # install the python version needed - - - name: install python packages - run: | - python -m pip install --upgrade pip - # pip install -r requirements.txt - pip install fmpy - - - name: execute py script # run SimFMU.py - env: - FMU_PATH: ${{ inputs.fmu_path }} - START: ${{ inputs.start }} - STOP: ${{ inputs.stop }} - run: python SimFMU.py \ No newline at end of file diff --git a/examples/FMI2/BouncingBall/src/BouncingBall.jl b/examples/FMI2/BouncingBall/src/BouncingBall.jl index 9ee8d91..d6e631c 100644 --- a/examples/FMI2/BouncingBall/src/BouncingBall.jl +++ b/examples/FMI2/BouncingBall/src/BouncingBall.jl @@ -6,6 +6,8 @@ using FMIExport using FMIExport.FMIBase.FMICore: fmi2True, fmi2False +EPS = 1e-6 + FMU_FCT_INIT = function() m = 1.0 # ball mass r = 0.0 # ball radius @@ -34,14 +36,12 @@ FMU_FCT_EVALUATE = function(t, x_c, ẋ_c, x_d, u, p, eventMode) sticking = x_d[1] _, a = ẋ_c - eps = 1e-10 - if sticking == fmi2True a = 0.0 elseif sticking == fmi2False if eventMode if s < r && v < 0.0 - s = r + eps # so that indicator is not triggered again + s = r + EPS # so that indicator is not triggered again v = -v*d # stop bouncing to prevent high frequency bouncing (and maybe tunneling the floor) @@ -50,6 +50,8 @@ FMU_FCT_EVALUATE = function(t, x_c, ẋ_c, x_d, u, p, eventMode) v = 0.0 end end + else + # no specials in continuos time mode end a = (m * -g) / m # the system's physical equation (a little longer than necessary) diff --git a/src/FMI2_md.jl b/src/FMI2_md.jl index 6dc05cc..19bff82 100644 --- a/src/FMI2_md.jl +++ b/src/FMI2_md.jl @@ -141,7 +141,10 @@ function fmi2ModelDescriptionAddIntegerDiscreteState(md::fmi2ModelDescription, n _Integer = fmi2IntegerAttributesExt() _Integer.start = start - sv = fmi2ModelDescriptionAddModelVariable(md, name; attribute=_Integer, kwargs...) + sv = fmi2ModelDescriptionAddModelVariable(md, name; + attribute=_Integer, + variability=fmi2VariabilityDiscrete, + kwargs...) push!(md.discreteStateValueReferences, sv.valueReference) push!(md.stringValueReferences, sv.name => sv.valueReference) @@ -150,7 +153,7 @@ function fmi2ModelDescriptionAddIntegerDiscreteState(md::fmi2ModelDescription, n end function fmi2ModelDescriptionAddEventIndicator(md::fmi2ModelDescription) - if md.numberOfEventIndicators == nothing + if isnothing(md.numberOfEventIndicators) md.numberOfEventIndicators = 0 end md.numberOfEventIndicators += 1 diff --git a/src/FMI2_simple.jl b/src/FMI2_simple.jl index 6e3313f..41775b5 100644 --- a/src/FMI2_simple.jl +++ b/src/FMI2_simple.jl @@ -48,15 +48,15 @@ end function evaluate(_component::fmi2Component, eventMode=false) component = dereferenceInstance(_component) - xc, ẋc, xd, u, y, p = extractValues(_component) + # eventMode = component.state == fmi2ComponentStateEventMode - #eventMode = (component.state == fmi2ComponentStateEventMode) + xc, ẋc, xd, u, y, p = extractValues(_component) tmp_xc, ẋc, tmp_xd, p = FMU_FCT_EVALUATE(component.t, xc, ẋc, xd, u, p, eventMode) if eventMode # overwrite state vector allowed component.eventInfo.valuesOfContinuousStatesChanged = (xc != tmp_xc ? fmi2True : fmi2False) - component.eventInfo.newDiscreteStatesNeeded = (xd != tmp_xd ? fmi2True : fmi2False) + component.eventInfo.newDiscreteStatesNeeded = (xd != tmp_xd ? fmi2True : fmi2False) xc = tmp_xc xd = tmp_xd @@ -294,7 +294,7 @@ function simple_fmi2GetReal(_component::fmi2Component, _vr::Ptr{fmi2ValueReferen try value[i] = component.values[valueRef] catch e - logError(component, "fmi2SetReal: Unknown value reference $(valueRef).") + logError(component, "fmi2GetReal: Unknown value reference $(valueRef).") return fmi2StatusError end end @@ -305,10 +305,23 @@ end function simple_fmi2GetInteger(_component::fmi2Component, _vr::Ptr{fmi2ValueReference}, nvr::Csize_t, _value::Ptr{fmi2Integer}) component = dereferenceInstance(_component) - # ToDo - logWarning(component, "fmi2GetInteger: Not implemented yet, please open an issue.") + value = unsafe_wrap(Array{fmi2Integer}, _value, nvr) + vr = unsafe_wrap(Array{fmi2ValueReference}, _vr, nvr) - return fmi2StatusWarning + global FMU_NUM_STATES, FMU_NUM_OUTPUTS, FMU_NUM_INPUTS, FMU_NUM_PARAMETERS + + for i in 1:nvr + valueRef = vr[i] + + try + value[i] = component.values[valueRef] + catch e + logError(component, "fmi2GetReal: Unknown value reference $(valueRef).") + return fmi2StatusError + end + end + + return fmi2StatusOK end function simple_fmi2GetBoolean(_component::fmi2Component, _vr::Ptr{fmi2ValueReference}, nvr::Csize_t, _value::Ptr{fmi2Boolean}) @@ -417,6 +430,11 @@ end function simple_fmi2NewDiscreteStates(_component::fmi2Component, _fmi2eventInfo::Ptr{fmi2EventInfo}) component = dereferenceInstance(_component) + + if component.state != fmi2ComponentStateEventMode + logError(component, "fmi2NewDiscreteStates must be called in event mode, mode is `$(component.state )`!") + return fmi2StatusError + end evaluate(_component, true) @@ -441,13 +459,16 @@ function simple_fmi2EnterContinuousTimeMode(_component::fmi2Component) return fmi2StatusOK end -function simple_fmi2CompletedIntegratorStep(_component::fmi2Component, noSetFMUStatePriorToCurrentPoint::fmi2Boolean, enterEventMode::Ptr{fmi2Boolean}, terminateSimulation::Ptr{fmi2Boolean}) +function simple_fmi2CompletedIntegratorStep(_component::fmi2Component, noSetFMUStatePriorToCurrentPoint::fmi2Boolean, _enterEventMode::Ptr{fmi2Boolean}, _terminateSimulation::Ptr{fmi2Boolean}) component = dereferenceInstance(_component) + + enterEventMode = unsafe_wrap(Array{fmi2Boolean}, _enterEventMode, 1) + terminateSimulation = unsafe_wrap(Array{fmi2Boolean}, _terminateSimulation, 1) - # ToDo - logWarning(component, "fmi2CompletedIntegratorStep: Not implemented yet, please open an issue.") + enterEventMode[1] = fmi2False + terminateSimulation[1] = fmi2False - return fmi2StatusWarning + return fmi2StatusOK end function simple_fmi2GetDerivatives(_component::fmi2Component, _derivatives::Ptr{fmi2Real}, nx::Csize_t) diff --git a/test/bouncing_ball.jl b/test/bouncing_ball.jl index f045344..af2c475 100644 --- a/test/bouncing_ball.jl +++ b/test/bouncing_ball.jl @@ -7,47 +7,49 @@ include(joinpath(@__DIR__, "..", "examples", "FMI2", "BouncingBall", "src", "BouncingBall.jl")) # demo! -using FMIZoo, Test, Plots +#using FMIZoo, Test, Plots #fmu_save_path = FMIZoo.get_model_filename("BouncingBall1D", "Dymola", "2022x") -fmu_save_path = "C:/Users/thummeto/Documents/FMIZoo.jl/models/bin/Dymola/2023x/2.0/BouncingBallGravitySwitch1D.fmu" +#fmu_save_path = "C:/Users/thummeto/Documents/BouncingBall.fmu" # "C:/Users/thummeto/Documents/FMIZoo.jl/models/bin/Dymola/2023x/2.0/BouncingBallGravitySwitch1D.fmu" # check if FMU exists now @test isfile(fmu_save_path) +fsize = filesize(fmu_save_path)/1024/1024 +@test fsize > 300 # Simulate FMU in Python / FMPy -@info "Installing `fmpy`..." -using Conda -Conda.add("fmpy"; channel="conda-forge") +# @info "Installing `fmpy`..." +# using Conda +# Conda.add("fmpy"; channel="conda-forge") # @info "Simulating with `fmpy`..." -using PyCall -@pyimport fmpy -fmpy.dump(fmu_save_path) +# using PyCall +# @pyimport fmpy +# fmpy.dump(fmu_save_path) -t_start = 0.0 -t_stop = 5.0 +# t_start = 0.0 +# t_stop = 5.0 -solution_FMPy = fmpy.simulate_fmu(filename=fmu_save_path, - validate=false, - start_time=t_start, - stop_time=t_stop, record_events=true, solver="CVode") # fmi_call_logger=lambda s: print('[FMI] ' + s) , +# solution_FMPy = fmpy.simulate_fmu(filename=fmu_save_path, +# validate=false, +# start_time=t_start, +# stop_time=t_stop, record_events=true, solver="CVode") # fmi_call_logger=lambda s: print('[FMI] ' + s) , -ts = collect(solution_FMPy[i][1] for i in 1:length(solution_FMPy)) -ss = collect(solution_FMPy[i][2] for i in 1:length(solution_FMPy)) -vs = collect(solution_FMPy[i][3] for i in 1:length(solution_FMPy)) +# ts = collect(solution_FMPy[i][1] for i in 1:length(solution_FMPy)) +# ss = collect(solution_FMPy[i][2] for i in 1:length(solution_FMPy)) +# vs = collect(solution_FMPy[i][3] for i in 1:length(solution_FMPy)) -@test length(solution_FMPy) == 1001 +# @test length(solution_FMPy) == 1001 -@test isapprox(ts[1], t_start; atol=1e-6) -@test isapprox(ss[1], 1.0; atol=1e-6) -@test isapprox(vs[1], 0.0; atol=1e-6) +# @test isapprox(ts[1], t_start; atol=1e-6) +# @test isapprox(ss[1], 1.0; atol=1e-6) +# @test isapprox(vs[1], 0.0; atol=1e-6) -@test isapprox(ts[end], t_stop; atol=1e-6) -@test isapprox(ss[end], 0.23272552; atol=1e-6) -@test isapprox(vs[end], -0.17606235; atol=1e-6) +# @test isapprox(ts[end], t_stop; atol=1e-6) +# @test isapprox(ss[end], 0.23272552; atol=1e-6) +# @test isapprox(vs[end], -0.17606235; atol=1e-6) -plot(ts, ss) -plot(ts, vs) +# plot(ts, ss) +# plot(ts, vs) # ToDo: enable the following line -#rm(fmu_save_path) \ No newline at end of file +rm(fmu_save_path) \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 4f5706c..4cda8ca 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,31 +6,29 @@ using FMIExport using Test -function runtests() - @testset "Model Description" begin - include("model_description.jl") - end - - @testset "Bouncing Ball" begin - include("bouncing_ball.jl") - end - - # @testset "FMU Manipulation" begin - # #@warn "The test `FMU Manipulation` is currently excluded because of insufficient ressources in GitHub-Actions." - # include("manipulation.jl") - # end - - # @testset "NeuralFMU" begin - # #@warn "The test `NeuralFMU` is currently excluded because of insufficient ressources in GitHub-Actions." - # include("neuralFMU.jl") - # end -end - @testset "FMIExport.jl" begin if Sys.iswindows() @info "Automated testing is supported on Windows/Linux/Mac." - runtests() - else Sys.islinux() || Sys.isapple() + + @testset "Model Description" begin + include("model_description.jl") + end + + @testset "Bouncing Ball" begin + include("bouncing_ball.jl") + end + + @testset "FMU Manipulation" begin + #@warn "The test `FMU Manipulation` is currently excluded because of insufficient resources in GitHub-Actions." + include("manipulation.jl") + end + + @testset "NeuralFMU" begin + #@warn "The test `NeuralFMU` is currently excluded because of insufficient resources in GitHub-Actions." + include("neuralFMU.jl") + end + + elseif Sys.islinux() || Sys.isapple() @warn "Tests not supported on Linux and Mac." else @warn "Tests not supported on `unknown operation system`." From 4da519f80d8126bf39b4d0b491edbf9dc26f453f Mon Sep 17 00:00:00 2001 From: TT Date: Fri, 9 Aug 2024 14:51:07 +0200 Subject: [PATCH 5/5] updated example deps --- examples/FMI2/BouncingBall/Project.toml | 2 +- examples/FMI2/Manipulation/Project.toml | 2 +- examples/FMI2/NeuralFMU/Project.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/FMI2/BouncingBall/Project.toml b/examples/FMI2/BouncingBall/Project.toml index 08eec9b..c0efd3f 100644 --- a/examples/FMI2/BouncingBall/Project.toml +++ b/examples/FMI2/BouncingBall/Project.toml @@ -8,5 +8,5 @@ FMIBuild = "226f0e26-6dd6-4589-ada7-1d32f6e1d800" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" [compat] -FMIBuild = "0.3.0" +FMIBuild = "0.3.2" julia = "1.6" diff --git a/examples/FMI2/Manipulation/Project.toml b/examples/FMI2/Manipulation/Project.toml index 410ee4f..b13ebbd 100644 --- a/examples/FMI2/Manipulation/Project.toml +++ b/examples/FMI2/Manipulation/Project.toml @@ -10,5 +10,5 @@ FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" FMIZoo = "724179cf-c260-40a9-bd27-cccc6fe2f195" [compat] -FMIBuild = "0.3.0" +FMIBuild = "0.3.2" julia = "1.6" diff --git a/examples/FMI2/NeuralFMU/Project.toml b/examples/FMI2/NeuralFMU/Project.toml index 8d407c7..4ebac4c 100644 --- a/examples/FMI2/NeuralFMU/Project.toml +++ b/examples/FMI2/NeuralFMU/Project.toml @@ -10,5 +10,5 @@ FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" FMIZoo = "724179cf-c260-40a9-bd27-cccc6fe2f195" [compat] -FMIBuild = "0.3.0" +FMIBuild = "0.3.2" julia = "1.6"