From 2c95b7702b6b6544e066595971a8d89c4c9528bb Mon Sep 17 00:00:00 2001 From: JoKircher Date: Wed, 1 Jun 2022 15:20:59 +0000 Subject: [PATCH 01/41] Jupyter nbconvert synch - modified, paired .ipynb files --- docs/src/examples/manipulation.md | 20 +- .../manipulation_files/manipulation_10_0.svg | 78 ++--- .../manipulation_files/manipulation_18_0.svg | 96 +++--- docs/src/examples/modelica_conference_2021.md | 26 +- .../modelica_conference_2021_8_0.svg | 64 ++-- docs/src/examples/multiple_instances.md | 16 +- .../multiple_instances_10_0.svg | 64 ++-- .../multiple_instances_18_0.svg | 68 ++--- docs/src/examples/parameterize.md | 28 +- docs/src/examples/simulate.md | 16 +- .../examples/simulate_files/simulate_12_0.svg | 72 ++--- .../examples/simulate_files/simulate_13_0.svg | 86 +++--- example/manipulation.ipynb | 281 +++++++++--------- example/modelica_conference_2021.ipynb | 177 ++++++----- example/multiple_instances.ipynb | 236 +++++++-------- example/parameterize.ipynb | 140 ++++----- example/simulate.ipynb | 245 ++++++++------- 17 files changed, 837 insertions(+), 876 deletions(-) diff --git a/docs/src/examples/manipulation.md b/docs/src/examples/manipulation.md index 01e54c6c..adea4344 100644 --- a/docs/src/examples/manipulation.md +++ b/docs/src/examples/manipulation.md @@ -47,10 +47,6 @@ using FMICore using Plots ``` - ┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMU2Solution}` in module `FMI` - └ @ Base.Docs docs/Docs.jl:240 - - ### Simulation setup Next, the start time and end time of the simulation are set. @@ -82,12 +78,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_AxClYk/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AxClYk/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -130,7 +126,7 @@ vrs = ["mass.s"] simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs) ``` - Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:13 + Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10 @@ -206,7 +202,7 @@ originalGetReal = myFMU.cGetReal - Ptr{Nothing} @0x00007fa504ca1faf + Ptr{Nothing} @0x00007f52e9530faf @@ -254,7 +250,7 @@ fmiSetFctGetReal(myFMU, myGetReal!) - Ptr{Nothing} @0x00007fa54dafdfc0 + Ptr{Nothing} @0x00007f533e325fc0 diff --git a/docs/src/examples/manipulation_files/manipulation_10_0.svg b/docs/src/examples/manipulation_files/manipulation_10_0.svg index c9ae6c2d..b86d3be2 100644 --- a/docs/src/examples/manipulation_files/manipulation_10_0.svg +++ b/docs/src/examples/manipulation_files/manipulation_10_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/manipulation_files/manipulation_18_0.svg b/docs/src/examples/manipulation_files/manipulation_18_0.svg index a319441a..d9cf606b 100644 --- a/docs/src/examples/manipulation_files/manipulation_18_0.svg +++ b/docs/src/examples/manipulation_files/manipulation_18_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/modelica_conference_2021.md b/docs/src/examples/modelica_conference_2021.md index e4612a31..c77e978a 100644 --- a/docs/src/examples/modelica_conference_2021.md +++ b/docs/src/examples/modelica_conference_2021.md @@ -45,10 +45,6 @@ using FMIZoo using Plots ``` - ┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI` - └ @ Base.Docs docs/Docs.jl:240 - - ### Simulation setup Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. @@ -81,12 +77,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_dg2hpy/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_dg2hpy/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -151,12 +147,12 @@ In the following type of simulation a more advanced variant is presented, which myFMU = fmiLoad(pathToFMU); ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HuQTow/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HuQTow/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. @@ -171,7 +167,7 @@ instanceFMU = fmiInstantiate!(myFMU) FMU: SpringFrictionPendulum1D InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000005fcca40 + Address: Ptr{Nothing} @0x00000000064853f0 State: fmi2ComponentStateInstantiated Logging: false FMU time: -Inf diff --git a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg index 0a7ac6a2..c714d93e 100644 --- a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg +++ b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/multiple_instances.md b/docs/src/examples/multiple_instances.md index 79a1461b..d20d0c7f 100644 --- a/docs/src/examples/multiple_instances.md +++ b/docs/src/examples/multiple_instances.md @@ -78,12 +78,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_KBJT4J/SpringPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_KBJT4J/SpringPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -128,7 +128,7 @@ println(comp1) FMU: SpringPendulum1D InstanceName: [not defined] - Address: Ptr{Nothing} @0x000000000348d080 + Address: Ptr{Nothing} @0x0000000003954580 State: fmi2ComponentStateInstantiated Logging: false FMU time: -Inf @@ -173,9 +173,9 @@ println(comp2) FMU: SpringPendulum1D InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000006214590 + Address: Ptr{Nothing} @0x000000000529d440 State: fmi2ComponentStateInstantiated - Logging: true + Logging: false FMU time: -Inf FMU states: nothing diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg index 48bec0bb..cf0fca99 100644 --- a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg +++ b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg index 04f52296..8004ffcf 100644 --- a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg +++ b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/parameterize.md b/docs/src/examples/parameterize.md index d45d0e1d..67856f28 100644 --- a/docs/src/examples/parameterize.md +++ b/docs/src/examples/parameterize.md @@ -70,12 +70,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_E6omKF/IO`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_E6omKF/IO/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -125,9 +125,9 @@ fmiInstantiate!(myFMU; loggingOn=true) FMU: IO InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000003ae6b10 + Address: Ptr{Nothing} @0x00000000029c12e0 State: fmi2ComponentStateInstantiated - Logging: false + Logging: true FMU time: -Inf FMU states: nothing @@ -212,7 +212,7 @@ The previously defined function is called and the results are displayed in the c paramsVal = generateRandomNumbers(); ``` - Any[41.68976766058903, 91, false, "Random number 18.117421661942835!"] + Any[27.27027116078753, 50, true, "Random number 83.09640957659121!"] #### First variant @@ -228,7 +228,7 @@ print(values) @assert paramsVal == values ``` - Any[41.68976766058903, 91, 0, "Random number 18.117421661942835!"] + Any[27.27027116078753, 50, 1, "Random number 83.09640957659121!"] #### Second variant @@ -239,7 +239,7 @@ To make sure that the functions work it is necessary to generate random numbers rndReal, rndInteger, rndBoolean, rndString = generateRandomNumbers(); ``` - Any[32.87773039642885, 58, false, "Random number 22.4054218867213!"] + Any[54.98169316988619, 76, true, "Random number 39.54384075977397!"] In the second variant, the value for each data type is set separately by the corresponding command. By this variant one has the maximum control and can be sure that also the correct data type is set. To illustrate the functionality of the parameterization with the separate functions, the corresponding get function is also called separately for each data type: @@ -264,19 +264,19 @@ display("$rndString == $(fmiGetString(myFMU, "p_string"))") ``` - "32.87773039642885 == 32.87773039642885" + "54.98169316988619 == 54.98169316988619" - "58 == 58" + "76 == 76" - "false == 0" + "true == 1" - "Random number 22.4054218867213! == Random number 22.4054218867213!" + "Random number 39.54384075977397! == Random number 39.54384075977397!" After seeing that both variants set the parameters correctly, the initialization mode is terminated with the function `fmiExitInitializationMode()`. diff --git a/docs/src/examples/simulate.md b/docs/src/examples/simulate.md index 56874dd7..b208de41 100644 --- a/docs/src/examples/simulate.md +++ b/docs/src/examples/simulate.md @@ -45,10 +45,6 @@ using FMIZoo using Plots ``` - ┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI` - └ @ Base.Docs docs/Docs.jl:240 - - ### Simulation setup Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. @@ -83,12 +79,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_TJndII/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_TJndII/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -168,7 +164,7 @@ In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (M dataME = fmiSimulateME(myFMU, tStart, tStop; saveat=tSave) ``` - Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:11 + Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09 diff --git a/docs/src/examples/simulate_files/simulate_12_0.svg b/docs/src/examples/simulate_files/simulate_12_0.svg index e3cf1302..6f603526 100644 --- a/docs/src/examples/simulate_files/simulate_12_0.svg +++ b/docs/src/examples/simulate_files/simulate_12_0.svg @@ -1,99 +1,99 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/simulate_files/simulate_13_0.svg b/docs/src/examples/simulate_files/simulate_13_0.svg index e4c9bcdd..2dc08e6e 100644 --- a/docs/src/examples/simulate_files/simulate_13_0.svg +++ b/docs/src/examples/simulate_files/simulate_13_0.svg @@ -1,99 +1,99 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/example/manipulation.ipynb b/example/manipulation.ipynb index f7f16b44..eb98a208 100644 --- a/example/manipulation.ipynb +++ b/example/manipulation.ipynb @@ -55,23 +55,14 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:05.916000Z", - "iopub.status.busy": "2022-05-24T15:05:04.955000Z", - "iopub.status.idle": "2022-05-24T15:05:35.479000Z", - "shell.execute_reply": "2022-05-24T15:05:35.382000Z" + "iopub.execute_input": "2022-06-01T15:15:09.601000Z", + "iopub.status.busy": "2022-06-01T15:15:08.923000Z", + "iopub.status.idle": "2022-06-01T15:15:32.386000Z", + "shell.execute_reply": "2022-06-01T15:15:32.310000Z" }, "scrolled": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], + "outputs": [], "source": [ "# imports\n", "using FMI\n", @@ -94,10 +85,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:46.559000Z", - "iopub.status.busy": "2022-05-24T15:05:35.482000Z", - "iopub.status.idle": "2022-05-24T15:05:47.511000Z", - "shell.execute_reply": "2022-05-24T15:05:47.511000Z" + "iopub.execute_input": "2022-06-01T15:15:41.170000Z", + "iopub.status.busy": "2022-06-01T15:15:32.388000Z", + "iopub.status.idle": "2022-06-01T15:15:41.848000Z", + "shell.execute_reply": "2022-06-01T15:15:41.848000Z" }, "scrolled": false }, @@ -132,10 +123,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:47.516000Z", - "iopub.status.busy": "2022-05-24T15:05:47.515000Z", - "iopub.status.idle": "2022-05-24T15:05:53.086000Z", - "shell.execute_reply": "2022-05-24T15:05:53.085000Z" + "iopub.execute_input": "2022-06-01T15:15:41.877000Z", + "iopub.status.busy": "2022-06-01T15:15:41.877000Z", + "iopub.status.idle": "2022-06-01T15:15:46.248000Z", + "shell.execute_reply": "2022-06-01T15:15:46.248000Z" }, "scrolled": false }, @@ -144,12 +135,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_AxClYk/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AxClYk/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -209,10 +200,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:53.089000Z", - "iopub.status.busy": "2022-05-24T15:05:53.089000Z", - "iopub.status.idle": "2022-05-24T15:06:16.714000Z", - "shell.execute_reply": "2022-05-24T15:06:16.714000Z" + "iopub.execute_input": "2022-06-01T15:15:46.250000Z", + "iopub.status.busy": "2022-06-01T15:15:46.250000Z", + "iopub.status.idle": "2022-06-01T15:16:04.451000Z", + "shell.execute_reply": "2022-06-01T15:16:04.450000Z" } }, "outputs": [ @@ -220,7 +211,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:13\u001b[39m\n" + "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10\u001b[39m\n" ] }, { @@ -288,10 +279,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:16.718000Z", - "iopub.status.busy": "2022-05-24T15:06:16.718000Z", - "iopub.status.idle": "2022-05-24T15:06:41.814000Z", - "shell.execute_reply": "2022-05-24T15:06:41.814000Z" + "iopub.execute_input": "2022-06-01T15:16:04.454000Z", + "iopub.status.busy": "2022-06-01T15:16:04.454000Z", + "iopub.status.idle": "2022-06-01T15:16:23.184000Z", + "shell.execute_reply": "2022-06-01T15:16:23.184000Z" }, "scrolled": false }, @@ -302,93 +293,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 5, @@ -458,17 +449,17 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:41.820000Z", - "iopub.status.busy": "2022-05-24T15:06:41.819000Z", - "iopub.status.idle": "2022-05-24T15:06:42.710000Z", - "shell.execute_reply": "2022-05-24T15:06:42.710000Z" + "iopub.execute_input": "2022-06-01T15:16:23.189000Z", + "iopub.status.busy": "2022-06-01T15:16:23.188000Z", + "iopub.status.idle": "2022-06-01T15:16:23.780000Z", + "shell.execute_reply": "2022-06-01T15:16:23.780000Z" } }, "outputs": [ { "data": { "text/plain": [ - "Ptr{Nothing} @0x00007fa504ca1faf" + "Ptr{Nothing} @0x00007f52e9530faf" ] }, "execution_count": 6, @@ -495,10 +486,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:42.716000Z", - "iopub.status.busy": "2022-05-24T15:06:42.716000Z", - "iopub.status.idle": "2022-05-24T15:06:43.882000Z", - "shell.execute_reply": "2022-05-24T15:06:43.882000Z" + "iopub.execute_input": "2022-06-01T15:16:23.784000Z", + "iopub.status.busy": "2022-06-01T15:16:23.784000Z", + "iopub.status.idle": "2022-06-01T15:16:24.562000Z", + "shell.execute_reply": "2022-06-01T15:16:24.562000Z" } }, "outputs": [ @@ -546,17 +537,17 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:43.887000Z", - "iopub.status.busy": "2022-05-24T15:06:43.887000Z", - "iopub.status.idle": "2022-05-24T15:06:43.906000Z", - "shell.execute_reply": "2022-05-24T15:06:43.906000Z" + "iopub.execute_input": "2022-06-01T15:16:24.566000Z", + "iopub.status.busy": "2022-06-01T15:16:24.565000Z", + "iopub.status.idle": "2022-06-01T15:16:24.578000Z", + "shell.execute_reply": "2022-06-01T15:16:24.578000Z" } }, "outputs": [ { "data": { "text/plain": [ - "Ptr{Nothing} @0x00007fa54dafdfc0" + "Ptr{Nothing} @0x00007f533e325fc0" ] }, "execution_count": 8, @@ -583,10 +574,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:43.910000Z", - "iopub.status.busy": "2022-05-24T15:06:43.910000Z", - "iopub.status.idle": "2022-05-24T15:06:44.437000Z", - "shell.execute_reply": "2022-05-24T15:06:44.437000Z" + "iopub.execute_input": "2022-06-01T15:16:24.581000Z", + "iopub.status.busy": "2022-06-01T15:16:24.581000Z", + "iopub.status.idle": "2022-06-01T15:16:24.963000Z", + "shell.execute_reply": "2022-06-01T15:16:24.963000Z" } }, "outputs": [ @@ -596,93 +587,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 9, @@ -798,10 +789,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:44.442000Z", - "iopub.status.busy": "2022-05-24T15:06:44.442000Z", - "iopub.status.idle": "2022-05-24T15:06:44.500000Z", - "shell.execute_reply": "2022-05-24T15:06:44.500000Z" + "iopub.execute_input": "2022-06-01T15:16:24.967000Z", + "iopub.status.busy": "2022-06-01T15:16:24.967000Z", + "iopub.status.idle": "2022-06-01T15:16:25.011000Z", + "shell.execute_reply": "2022-06-01T15:16:25.011000Z" } }, "outputs": [], diff --git a/example/modelica_conference_2021.ipynb b/example/modelica_conference_2021.ipynb index 7f6e2473..7210b368 100644 --- a/example/modelica_conference_2021.ipynb +++ b/example/modelica_conference_2021.ipynb @@ -54,23 +54,14 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:56.032000Z", - "iopub.status.busy": "2022-05-24T15:06:55.083000Z", - "iopub.status.idle": "2022-05-24T15:07:25.235000Z", - "shell.execute_reply": "2022-05-24T15:07:25.141000Z" + "iopub.execute_input": "2022-06-01T15:16:34.235000Z", + "iopub.status.busy": "2022-06-01T15:16:33.558000Z", + "iopub.status.idle": "2022-06-01T15:16:56.948000Z", + "shell.execute_reply": "2022-06-01T15:16:56.869000Z" }, "scrolled": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], + "outputs": [], "source": [ "# imports\n", "using FMI\n", @@ -92,10 +83,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:07:36.354000Z", - "iopub.status.busy": "2022-05-24T15:07:25.239000Z", - "iopub.status.idle": "2022-05-24T15:07:37.433000Z", - "shell.execute_reply": "2022-05-24T15:07:37.433000Z" + "iopub.execute_input": "2022-06-01T15:17:05.805000Z", + "iopub.status.busy": "2022-06-01T15:16:56.951000Z", + "iopub.status.idle": "2022-06-01T15:17:06.600000Z", + "shell.execute_reply": "2022-06-01T15:17:06.600000Z" }, "scrolled": false }, @@ -132,10 +123,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:07:37.438000Z", - "iopub.status.busy": "2022-05-24T15:07:37.438000Z", - "iopub.status.idle": "2022-05-24T15:07:43.049000Z", - "shell.execute_reply": "2022-05-24T15:07:43.049000Z" + "iopub.execute_input": "2022-06-01T15:17:06.604000Z", + "iopub.status.busy": "2022-06-01T15:17:06.604000Z", + "iopub.status.idle": "2022-06-01T15:17:10.951000Z", + "shell.execute_reply": "2022-06-01T15:17:10.951000Z" } }, "outputs": [ @@ -143,12 +134,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_dg2hpy/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_dg2hpy/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -205,10 +196,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:07:43.052000Z", - "iopub.status.busy": "2022-05-24T15:07:43.052000Z", - "iopub.status.idle": "2022-05-24T15:08:18.695000Z", - "shell.execute_reply": "2022-05-24T15:08:18.695000Z" + "iopub.execute_input": "2022-06-01T15:17:10.954000Z", + "iopub.status.busy": "2022-06-01T15:17:10.953000Z", + "iopub.status.idle": "2022-06-01T15:17:37.913000Z", + "shell.execute_reply": "2022-06-01T15:17:37.913000Z" }, "scrolled": false }, @@ -219,93 +210,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 4, @@ -350,10 +341,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.700000Z", - "iopub.status.busy": "2022-05-24T15:08:18.700000Z", - "iopub.status.idle": "2022-05-24T15:08:18.758000Z", - "shell.execute_reply": "2022-05-24T15:08:18.758000Z" + "iopub.execute_input": "2022-06-01T15:17:37.918000Z", + "iopub.status.busy": "2022-06-01T15:17:37.917000Z", + "iopub.status.idle": "2022-06-01T15:17:37.960000Z", + "shell.execute_reply": "2022-06-01T15:17:37.960000Z" } }, "outputs": [], @@ -375,10 +366,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.761000Z", - "iopub.status.busy": "2022-05-24T15:08:18.760000Z", - "iopub.status.idle": "2022-05-24T15:08:18.835000Z", - "shell.execute_reply": "2022-05-24T15:08:18.835000Z" + "iopub.execute_input": "2022-06-01T15:17:37.962000Z", + "iopub.status.busy": "2022-06-01T15:17:37.962000Z", + "iopub.status.idle": "2022-06-01T15:17:38.024000Z", + "shell.execute_reply": "2022-06-01T15:17:38.024000Z" } }, "outputs": [ @@ -386,12 +377,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HuQTow/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HuQTow/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] } ], @@ -411,10 +402,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.840000Z", - "iopub.status.busy": "2022-05-24T15:08:18.839000Z", - "iopub.status.idle": "2022-05-24T15:08:19.277000Z", - "shell.execute_reply": "2022-05-24T15:08:19.277000Z" + "iopub.execute_input": "2022-06-01T15:17:38.028000Z", + "iopub.status.busy": "2022-06-01T15:17:38.027000Z", + "iopub.status.idle": "2022-06-01T15:17:38.349000Z", + "shell.execute_reply": "2022-06-01T15:17:38.349000Z" } }, "outputs": [ @@ -423,7 +414,7 @@ "text/plain": [ "FMU: SpringFrictionPendulum1D\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000005fcca40\n", + "Address: Ptr{Nothing} @0x00000000064853f0\n", "State: fmi2ComponentStateInstantiated\n", "Logging: false\n", "FMU time: -Inf\n", @@ -451,10 +442,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.282000Z", - "iopub.status.busy": "2022-05-24T15:08:19.282000Z", - "iopub.status.idle": "2022-05-24T15:08:19.638000Z", - "shell.execute_reply": "2022-05-24T15:08:19.638000Z" + "iopub.execute_input": "2022-06-01T15:17:38.353000Z", + "iopub.status.busy": "2022-06-01T15:17:38.352000Z", + "iopub.status.idle": "2022-06-01T15:17:38.617000Z", + "shell.execute_reply": "2022-06-01T15:17:38.617000Z" } }, "outputs": [ @@ -488,10 +479,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.642000Z", - "iopub.status.busy": "2022-05-24T15:08:19.642000Z", - "iopub.status.idle": "2022-05-24T15:08:19.692000Z", - "shell.execute_reply": "2022-05-24T15:08:19.692000Z" + "iopub.execute_input": "2022-06-01T15:17:38.620000Z", + "iopub.status.busy": "2022-06-01T15:17:38.620000Z", + "iopub.status.idle": "2022-06-01T15:17:38.657000Z", + "shell.execute_reply": "2022-06-01T15:17:38.657000Z" } }, "outputs": [], @@ -517,10 +508,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.695000Z", - "iopub.status.busy": "2022-05-24T15:08:19.695000Z", - "iopub.status.idle": "2022-05-24T15:08:19.705000Z", - "shell.execute_reply": "2022-05-24T15:08:19.705000Z" + "iopub.execute_input": "2022-06-01T15:17:38.660000Z", + "iopub.status.busy": "2022-06-01T15:17:38.660000Z", + "iopub.status.idle": "2022-06-01T15:17:38.668000Z", + "shell.execute_reply": "2022-06-01T15:17:38.667000Z" } }, "outputs": [], diff --git a/example/multiple_instances.ipynb b/example/multiple_instances.ipynb index df73564a..93f49f93 100644 --- a/example/multiple_instances.ipynb +++ b/example/multiple_instances.ipynb @@ -54,10 +54,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:49:29.382000Z", - "iopub.status.busy": "2022-05-25T10:49:28.749000Z", - "iopub.status.idle": "2022-05-25T10:49:50.382000Z", - "shell.execute_reply": "2022-05-25T10:49:50.309000Z" + "iopub.execute_input": "2022-06-01T15:17:48.035000Z", + "iopub.status.busy": "2022-06-01T15:17:47.343000Z", + "iopub.status.idle": "2022-06-01T15:18:10.300000Z", + "shell.execute_reply": "2022-06-01T15:18:10.226000Z" }, "scrolled": false }, @@ -83,10 +83,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:49:58.432000Z", - "iopub.status.busy": "2022-05-25T10:49:50.384000Z", - "iopub.status.idle": "2022-05-25T10:50:01.238000Z", - "shell.execute_reply": "2022-05-25T10:50:01.238000Z" + "iopub.execute_input": "2022-06-01T15:18:19.079000Z", + "iopub.status.busy": "2022-06-01T15:18:10.303000Z", + "iopub.status.idle": "2022-06-01T15:18:21.932000Z", + "shell.execute_reply": "2022-06-01T15:18:21.932000Z" }, "scrolled": false }, @@ -124,10 +124,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:01.262000Z", - "iopub.status.busy": "2022-05-25T10:50:01.262000Z", - "iopub.status.idle": "2022-05-25T10:50:05.354000Z", - "shell.execute_reply": "2022-05-25T10:50:05.354000Z" + "iopub.execute_input": "2022-06-01T15:18:21.935000Z", + "iopub.status.busy": "2022-06-01T15:18:21.935000Z", + "iopub.status.idle": "2022-06-01T15:18:26.345000Z", + "shell.execute_reply": "2022-06-01T15:18:26.345000Z" }, "scrolled": false }, @@ -136,12 +136,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_KBJT4J/SpringPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_KBJT4J/SpringPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -200,10 +200,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:05.356000Z", - "iopub.status.busy": "2022-05-25T10:50:05.356000Z", - "iopub.status.idle": "2022-05-25T10:50:05.919000Z", - "shell.execute_reply": "2022-05-25T10:50:05.919000Z" + "iopub.execute_input": "2022-06-01T15:18:26.348000Z", + "iopub.status.busy": "2022-06-01T15:18:26.348000Z", + "iopub.status.idle": "2022-06-01T15:18:26.776000Z", + "shell.execute_reply": "2022-06-01T15:18:26.776000Z" } }, "outputs": [ @@ -213,7 +213,7 @@ "text": [ "FMU: SpringPendulum1D\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x000000000348d080\n", + "Address: Ptr{Nothing} @0x0000000003954580\n", "State: fmi2ComponentStateInstantiated\n", "Logging: false\n", "FMU time: -Inf\n", @@ -239,10 +239,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:05.922000Z", - "iopub.status.busy": "2022-05-25T10:50:05.922000Z", - "iopub.status.idle": "2022-05-25T10:50:31.527000Z", - "shell.execute_reply": "2022-05-25T10:50:31.526000Z" + "iopub.execute_input": "2022-06-01T15:18:26.779000Z", + "iopub.status.busy": "2022-06-01T15:18:26.779000Z", + "iopub.status.idle": "2022-06-01T15:18:52.116000Z", + "shell.execute_reply": "2022-06-01T15:18:52.116000Z" } }, "outputs": [ @@ -252,93 +252,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 5, @@ -1176,10 +1176,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.532000Z", - "iopub.status.busy": "2022-05-25T10:50:31.531000Z", - "iopub.status.idle": "2022-05-25T10:50:31.566000Z", - "shell.execute_reply": "2022-05-25T10:50:31.566000Z" + "iopub.execute_input": "2022-06-01T15:18:52.122000Z", + "iopub.status.busy": "2022-06-01T15:18:52.122000Z", + "iopub.status.idle": "2022-06-01T15:18:52.160000Z", + "shell.execute_reply": "2022-06-01T15:18:52.160000Z" } }, "outputs": [], @@ -1201,10 +1201,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.568000Z", - "iopub.status.busy": "2022-05-25T10:50:31.568000Z", - "iopub.status.idle": "2022-05-25T10:50:31.571000Z", - "shell.execute_reply": "2022-05-25T10:50:31.570000Z" + "iopub.execute_input": "2022-06-01T15:18:52.163000Z", + "iopub.status.busy": "2022-06-01T15:18:52.163000Z", + "iopub.status.idle": "2022-06-01T15:18:52.166000Z", + "shell.execute_reply": "2022-06-01T15:18:52.166000Z" } }, "outputs": [ @@ -1214,9 +1214,9 @@ "text": [ "FMU: SpringPendulum1D\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000006214590\n", + "Address: Ptr{Nothing} @0x000000000529d440\n", "State: fmi2ComponentStateInstantiated\n", - "Logging: true\n", + "Logging: false\n", "FMU time: -Inf\n", "FMU states: nothing\n" ] @@ -1240,10 +1240,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.573000Z", - "iopub.status.busy": "2022-05-25T10:50:31.573000Z", - "iopub.status.idle": "2022-05-25T10:50:31.573000Z", - "shell.execute_reply": "2022-05-25T10:50:31.573000Z" + "iopub.execute_input": "2022-06-01T15:18:52.168000Z", + "iopub.status.busy": "2022-06-01T15:18:52.168000Z", + "iopub.status.idle": "2022-06-01T15:18:52.169000Z", + "shell.execute_reply": "2022-06-01T15:18:52.169000Z" } }, "outputs": [], @@ -1263,10 +1263,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.576000Z", - "iopub.status.busy": "2022-05-25T10:50:31.575000Z", - "iopub.status.idle": "2022-05-25T10:50:31.676000Z", - "shell.execute_reply": "2022-05-25T10:50:31.676000Z" + "iopub.execute_input": "2022-06-01T15:18:52.171000Z", + "iopub.status.busy": "2022-06-01T15:18:52.171000Z", + "iopub.status.idle": "2022-06-01T15:18:52.280000Z", + "shell.execute_reply": "2022-06-01T15:18:52.280000Z" } }, "outputs": [ @@ -1276,93 +1276,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 9, @@ -3006,10 +3006,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.682000Z", - "iopub.status.busy": "2022-05-25T10:50:31.682000Z", - "iopub.status.idle": "2022-05-25T10:50:31.683000Z", - "shell.execute_reply": "2022-05-25T10:50:31.683000Z" + "iopub.execute_input": "2022-06-01T15:18:52.288000Z", + "iopub.status.busy": "2022-06-01T15:18:52.288000Z", + "iopub.status.idle": "2022-06-01T15:18:52.289000Z", + "shell.execute_reply": "2022-06-01T15:18:52.289000Z" } }, "outputs": [], @@ -3031,10 +3031,10 @@ "execution_count": 11, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.685000Z", - "iopub.status.busy": "2022-05-25T10:50:31.685000Z", - "iopub.status.idle": "2022-05-25T10:50:31.724000Z", - "shell.execute_reply": "2022-05-25T10:50:31.724000Z" + "iopub.execute_input": "2022-06-01T15:18:52.291000Z", + "iopub.status.busy": "2022-06-01T15:18:52.291000Z", + "iopub.status.idle": "2022-06-01T15:18:52.333000Z", + "shell.execute_reply": "2022-06-01T15:18:52.333000Z" } }, "outputs": [], diff --git a/example/parameterize.ipynb b/example/parameterize.ipynb index 61715634..65099b87 100644 --- a/example/parameterize.ipynb +++ b/example/parameterize.ipynb @@ -50,10 +50,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:40.626000Z", - "iopub.status.busy": "2022-05-25T10:50:39.995000Z", - "iopub.status.idle": "2022-05-25T10:50:53.067000Z", - "shell.execute_reply": "2022-05-25T10:50:52.995000Z" + "iopub.execute_input": "2022-06-01T15:19:01.571000Z", + "iopub.status.busy": "2022-06-01T15:19:00.892000Z", + "iopub.status.idle": "2022-06-01T15:19:15.010000Z", + "shell.execute_reply": "2022-06-01T15:19:14.933000Z" }, "scrolled": false }, @@ -78,10 +78,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:53.403000Z", - "iopub.status.busy": "2022-05-25T10:50:53.069000Z", - "iopub.status.idle": "2022-05-25T10:50:54.070000Z", - "shell.execute_reply": "2022-05-25T10:50:54.070000Z" + "iopub.execute_input": "2022-06-01T15:19:15.205000Z", + "iopub.status.busy": "2022-06-01T15:19:15.013000Z", + "iopub.status.idle": "2022-06-01T15:19:16.256000Z", + "shell.execute_reply": "2022-06-01T15:19:16.255000Z" }, "scrolled": false }, @@ -116,10 +116,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:54.073000Z", - "iopub.status.busy": "2022-05-25T10:50:54.073000Z", - "iopub.status.idle": "2022-05-25T10:50:58.301000Z", - "shell.execute_reply": "2022-05-25T10:50:58.301000Z" + "iopub.execute_input": "2022-06-01T15:19:16.259000Z", + "iopub.status.busy": "2022-06-01T15:19:16.259000Z", + "iopub.status.idle": "2022-06-01T15:19:20.487000Z", + "shell.execute_reply": "2022-06-01T15:19:20.486000Z" }, "scrolled": false }, @@ -128,12 +128,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_E6omKF/IO`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_E6omKF/IO/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -196,10 +196,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:58.303000Z", - "iopub.status.busy": "2022-05-25T10:50:58.303000Z", - "iopub.status.idle": "2022-05-25T10:50:59.044000Z", - "shell.execute_reply": "2022-05-25T10:50:59.044000Z" + "iopub.execute_input": "2022-06-01T15:19:20.489000Z", + "iopub.status.busy": "2022-06-01T15:19:20.489000Z", + "iopub.status.idle": "2022-06-01T15:19:21.252000Z", + "shell.execute_reply": "2022-06-01T15:19:21.252000Z" } }, "outputs": [ @@ -208,9 +208,9 @@ "text/plain": [ "FMU: IO\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000003ae6b10\n", + "Address: Ptr{Nothing} @0x00000000029c12e0\n", "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", + "Logging: true\n", "FMU time: -Inf\n", "FMU states: nothing" ] @@ -236,10 +236,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.047000Z", - "iopub.status.busy": "2022-05-25T10:50:59.047000Z", - "iopub.status.idle": "2022-05-25T10:50:59.362000Z", - "shell.execute_reply": "2022-05-25T10:50:59.362000Z" + "iopub.execute_input": "2022-06-01T15:19:21.256000Z", + "iopub.status.busy": "2022-06-01T15:19:21.256000Z", + "iopub.status.idle": "2022-06-01T15:19:21.603000Z", + "shell.execute_reply": "2022-06-01T15:19:21.603000Z" } }, "outputs": [ @@ -272,10 +272,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.365000Z", - "iopub.status.busy": "2022-05-25T10:50:59.365000Z", - "iopub.status.idle": "2022-05-25T10:50:59.397000Z", - "shell.execute_reply": "2022-05-25T10:50:59.397000Z" + "iopub.execute_input": "2022-06-01T15:19:21.607000Z", + "iopub.status.busy": "2022-06-01T15:19:21.606000Z", + "iopub.status.idle": "2022-06-01T15:19:21.639000Z", + "shell.execute_reply": "2022-06-01T15:19:21.639000Z" } }, "outputs": [ @@ -306,10 +306,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.399000Z", - "iopub.status.busy": "2022-05-25T10:50:59.399000Z", - "iopub.status.idle": "2022-05-25T10:51:02.699000Z", - "shell.execute_reply": "2022-05-25T10:51:02.699000Z" + "iopub.execute_input": "2022-06-01T15:19:21.643000Z", + "iopub.status.busy": "2022-06-01T15:19:21.643000Z", + "iopub.status.idle": "2022-06-01T15:19:25.228000Z", + "shell.execute_reply": "2022-06-01T15:19:25.228000Z" } }, "outputs": [ @@ -345,10 +345,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:02.702000Z", - "iopub.status.busy": "2022-05-25T10:51:02.702000Z", - "iopub.status.idle": "2022-05-25T10:51:03.392000Z", - "shell.execute_reply": "2022-05-25T10:51:03.392000Z" + "iopub.execute_input": "2022-06-01T15:19:25.232000Z", + "iopub.status.busy": "2022-06-01T15:19:25.232000Z", + "iopub.status.idle": "2022-06-01T15:19:25.951000Z", + "shell.execute_reply": "2022-06-01T15:19:25.951000Z" } }, "outputs": [ @@ -388,10 +388,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:03.395000Z", - "iopub.status.busy": "2022-05-25T10:51:03.395000Z", - "iopub.status.idle": "2022-05-25T10:51:04.098000Z", - "shell.execute_reply": "2022-05-25T10:51:04.098000Z" + "iopub.execute_input": "2022-06-01T15:19:25.955000Z", + "iopub.status.busy": "2022-06-01T15:19:25.955000Z", + "iopub.status.idle": "2022-06-01T15:19:26.678000Z", + "shell.execute_reply": "2022-06-01T15:19:26.678000Z" } }, "outputs": [ @@ -399,7 +399,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Any[41.68976766058903, 91, false, \"Random number 18.117421661942835!\"]\n" + "Any[27.27027116078753, 50, true, \"Random number 83.09640957659121!\"]\n" ] } ], @@ -421,10 +421,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.102000Z", - "iopub.status.busy": "2022-05-25T10:51:04.102000Z", - "iopub.status.idle": "2022-05-25T10:51:04.571000Z", - "shell.execute_reply": "2022-05-25T10:51:04.571000Z" + "iopub.execute_input": "2022-06-01T15:19:26.682000Z", + "iopub.status.busy": "2022-06-01T15:19:26.682000Z", + "iopub.status.idle": "2022-06-01T15:19:27.242000Z", + "shell.execute_reply": "2022-06-01T15:19:27.242000Z" } }, "outputs": [ @@ -432,7 +432,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Any[41.68976766058903, 91, 0, \"Random number 18.117421661942835!\"]" + "Any[27.27027116078753, 50, 1, \"Random number 83.09640957659121!\"]" ] } ], @@ -458,10 +458,10 @@ "execution_count": 11, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.574000Z", - "iopub.status.busy": "2022-05-25T10:51:04.574000Z", - "iopub.status.idle": "2022-05-25T10:51:04.575000Z", - "shell.execute_reply": "2022-05-25T10:51:04.575000Z" + "iopub.execute_input": "2022-06-01T15:19:27.246000Z", + "iopub.status.busy": "2022-06-01T15:19:27.246000Z", + "iopub.status.idle": "2022-06-01T15:19:27.247000Z", + "shell.execute_reply": "2022-06-01T15:19:27.247000Z" } }, "outputs": [ @@ -469,7 +469,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Any[32.87773039642885, 58, false, \"Random number 22.4054218867213!\"]\n" + "Any[54.98169316988619, 76, true, \"Random number 39.54384075977397!\"]\n" ] } ], @@ -493,17 +493,17 @@ "execution_count": 12, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.579000Z", - "iopub.status.busy": "2022-05-25T10:51:04.578000Z", - "iopub.status.idle": "2022-05-25T10:51:06.093000Z", - "shell.execute_reply": "2022-05-25T10:51:06.093000Z" + "iopub.execute_input": "2022-06-01T15:19:27.250000Z", + "iopub.status.busy": "2022-06-01T15:19:27.250000Z", + "iopub.status.idle": "2022-06-01T15:19:28.917000Z", + "shell.execute_reply": "2022-06-01T15:19:28.917000Z" } }, "outputs": [ { "data": { "text/plain": [ - "\"32.87773039642885 == 32.87773039642885\"" + "\"54.98169316988619 == 54.98169316988619\"" ] }, "metadata": {}, @@ -512,7 +512,7 @@ { "data": { "text/plain": [ - "\"58 == 58\"" + "\"76 == 76\"" ] }, "metadata": {}, @@ -521,7 +521,7 @@ { "data": { "text/plain": [ - "\"false == 0\"" + "\"true == 1\"" ] }, "metadata": {}, @@ -530,7 +530,7 @@ { "data": { "text/plain": [ - "\"Random number 22.4054218867213! == Random number 22.4054218867213!\"" + "\"Random number 39.54384075977397! == Random number 39.54384075977397!\"" ] }, "metadata": {}, @@ -563,10 +563,10 @@ "execution_count": 13, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:06.096000Z", - "iopub.status.busy": "2022-05-25T10:51:06.096000Z", - "iopub.status.idle": "2022-05-25T10:51:06.127000Z", - "shell.execute_reply": "2022-05-25T10:51:06.127000Z" + "iopub.execute_input": "2022-06-01T15:19:28.920000Z", + "iopub.status.busy": "2022-06-01T15:19:28.920000Z", + "iopub.status.idle": "2022-06-01T15:19:28.956000Z", + "shell.execute_reply": "2022-06-01T15:19:28.955000Z" } }, "outputs": [ @@ -609,10 +609,10 @@ "execution_count": 14, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:06.129000Z", - "iopub.status.busy": "2022-05-25T10:51:06.129000Z", - "iopub.status.idle": "2022-05-25T10:51:06.239000Z", - "shell.execute_reply": "2022-05-25T10:51:06.239000Z" + "iopub.execute_input": "2022-06-01T15:19:28.959000Z", + "iopub.status.busy": "2022-06-01T15:19:28.959000Z", + "iopub.status.idle": "2022-06-01T15:19:29.101000Z", + "shell.execute_reply": "2022-06-01T15:19:29.101000Z" } }, "outputs": [], diff --git a/example/simulate.ipynb b/example/simulate.ipynb index d1b94962..f3ef7b84 100644 --- a/example/simulate.ipynb +++ b/example/simulate.ipynb @@ -54,23 +54,14 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:10:58.160000Z", - "iopub.status.busy": "2022-05-24T15:10:57.200000Z", - "iopub.status.idle": "2022-05-24T15:11:28.115000Z", - "shell.execute_reply": "2022-05-24T15:11:28.004000Z" + "iopub.execute_input": "2022-06-01T15:19:38.296000Z", + "iopub.status.busy": "2022-06-01T15:19:37.619000Z", + "iopub.status.idle": "2022-06-01T15:20:00.542000Z", + "shell.execute_reply": "2022-06-01T15:20:00.469000Z" }, "scrolled": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], + "outputs": [], "source": [ "# imports\n", "using FMI\n", @@ -92,10 +83,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:39.107000Z", - "iopub.status.busy": "2022-05-24T15:11:28.118000Z", - "iopub.status.idle": "2022-05-24T15:11:40.147000Z", - "shell.execute_reply": "2022-05-24T15:11:40.147000Z" + "iopub.execute_input": "2022-06-01T15:20:09.276000Z", + "iopub.status.busy": "2022-06-01T15:20:00.544000Z", + "iopub.status.idle": "2022-06-01T15:20:10.061000Z", + "shell.execute_reply": "2022-06-01T15:20:10.061000Z" }, "scrolled": false }, @@ -132,10 +123,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:40.151000Z", - "iopub.status.busy": "2022-05-24T15:11:40.151000Z", - "iopub.status.idle": "2022-05-24T15:11:45.736000Z", - "shell.execute_reply": "2022-05-24T15:11:45.736000Z" + "iopub.execute_input": "2022-06-01T15:20:10.065000Z", + "iopub.status.busy": "2022-06-01T15:20:10.065000Z", + "iopub.status.idle": "2022-06-01T15:20:14.405000Z", + "shell.execute_reply": "2022-06-01T15:20:14.404000Z" }, "scrolled": false }, @@ -144,12 +135,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_TJndII/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_TJndII/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -214,10 +205,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:45.739000Z", - "iopub.status.busy": "2022-05-24T15:11:45.739000Z", - "iopub.status.idle": "2022-05-24T15:11:52.663000Z", - "shell.execute_reply": "2022-05-24T15:11:52.663000Z" + "iopub.execute_input": "2022-06-01T15:20:14.407000Z", + "iopub.status.busy": "2022-06-01T15:20:14.407000Z", + "iopub.status.idle": "2022-06-01T15:20:19.739000Z", + "shell.execute_reply": "2022-06-01T15:20:19.739000Z" } }, "outputs": [ @@ -268,10 +259,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:52.667000Z", - "iopub.status.busy": "2022-05-24T15:11:52.667000Z", - "iopub.status.idle": "2022-05-24T15:12:09.582000Z", - "shell.execute_reply": "2022-05-24T15:12:09.582000Z" + "iopub.execute_input": "2022-06-01T15:20:19.742000Z", + "iopub.status.busy": "2022-06-01T15:20:19.742000Z", + "iopub.status.idle": "2022-06-01T15:20:32.777000Z", + "shell.execute_reply": "2022-06-01T15:20:32.777000Z" } }, "outputs": [ @@ -279,7 +270,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:11\u001b[39m\n" + "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09\u001b[39m\n" ] }, { @@ -333,10 +324,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:12:09.586000Z", - "iopub.status.busy": "2022-05-24T15:12:09.586000Z", - "iopub.status.idle": "2022-05-24T15:12:34.657000Z", - "shell.execute_reply": "2022-05-24T15:12:34.657000Z" + "iopub.execute_input": "2022-06-01T15:20:32.781000Z", + "iopub.status.busy": "2022-06-01T15:20:32.780000Z", + "iopub.status.idle": "2022-06-01T15:20:51.657000Z", + "shell.execute_reply": "2022-06-01T15:20:51.657000Z" }, "scrolled": false }, @@ -347,99 +338,99 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 6, @@ -634,10 +625,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:12:34.663000Z", - "iopub.status.busy": "2022-05-24T15:12:34.663000Z", - "iopub.status.idle": "2022-05-24T15:12:34.960000Z", - "shell.execute_reply": "2022-05-24T15:12:34.959000Z" + "iopub.execute_input": "2022-06-01T15:20:51.662000Z", + "iopub.status.busy": "2022-06-01T15:20:51.662000Z", + "iopub.status.idle": "2022-06-01T15:20:51.876000Z", + "shell.execute_reply": "2022-06-01T15:20:51.876000Z" } }, "outputs": [ @@ -647,99 +638,99 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 7, @@ -971,10 +962,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:12:34.965000Z", - "iopub.status.busy": "2022-05-24T15:12:34.965000Z", - "iopub.status.idle": "2022-05-24T15:12:35.028000Z", - "shell.execute_reply": "2022-05-24T15:12:35.028000Z" + "iopub.execute_input": "2022-06-01T15:20:51.880000Z", + "iopub.status.busy": "2022-06-01T15:20:51.880000Z", + "iopub.status.idle": "2022-06-01T15:20:51.922000Z", + "shell.execute_reply": "2022-06-01T15:20:51.922000Z" } }, "outputs": [], From f974e57b3b1ea1e7db95e6c45bf116a58c522a74 Mon Sep 17 00:00:00 2001 From: ThummeTo <83663542+ThummeTo@users.noreply.github.com> Date: Tue, 7 Jun 2022 09:22:04 +0200 Subject: [PATCH 02/41] Fmi3 beta (#114) * minor change * version inc --- Project.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 80ad9224..dc8ff32b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,10 +1,11 @@ name = "FMI" uuid = "14a09403-18e3-468f-ad8a-74f8dda2d9ac" authors = ["TT ", "LM ", "JK "] -version = "0.8.5" +version = "0.9.0" [deps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def" DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa" FMIExport = "31b88311-cab6-44ed-ba9c-fe5a9abbd67a" @@ -19,8 +20,8 @@ SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" ChainRulesCore = "^1.13.0" DiffEqCallbacks = "^2.21.0" DifferentialEquations = "7.1.0" -FMIExport = "0.1.2" -FMIImport = "0.8.3" +FMIExport = "0.1.4" +FMIImport = "0.9.0" ForwardDiff = "0.10.25" OrdinaryDiffEq = "^6.7.0" ProgressMeter = "1.7.2" From 07cddfdd8b5d4e87b2dcc2bff9e49fd5f483f894 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 7 Jun 2022 13:11:09 +0200 Subject: [PATCH 03/41] move additional functions to the end --- src/FMI2_comp_wraps.jl | 54 +- src/FMI3_comp_wraps.jl | 1141 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 1167 insertions(+), 28 deletions(-) diff --git a/src/FMI2_comp_wraps.jl b/src/FMI2_comp_wraps.jl index 06d3af2f..3eacee12 100644 --- a/src/FMI2_comp_wraps.jl +++ b/src/FMI2_comp_wraps.jl @@ -8,33 +8,6 @@ # - wrappers to call fmi2ComponentFunctions from FMUs (additional functions, last instantiated component is used) [exported] # FMI-spec -""" - fmi2Simulate(fmu::FMU2, args...; kwargs...) - -Wrapper for fmi2Simulate() in FMI/FMI2_sim.jl -""" -function fmi2Simulate(fmu::FMU2, args...; kwargs...) - return fmi2Simulate(fmu, nothing, args...; kwargs...) -end - -""" - fmi2SimulateCS(fmu::FMU2, args...; kwargs...) - -Wrapper for fmi2SimulateCS() in FMI/FMI2_sim.jl -""" -function fmi2SimulateCS(fmu::FMU2, args...; kwargs...) - return fmi2SimulateCS(fmu, nothing, args...; kwargs...) -end - -""" - fmi2SimulateME(fmu::FMU2, args...; kwargs...) - -Wrapper for fmi2SimulateME() in FMI/FMI2_sim.jl -""" -function fmi2SimulateME(fmu::FMU2, args...; kwargs...) - return fmi2SimulateME(fmu, nothing, args...; kwargs...) -end - """ fmi2FreeInstance!(fmu::FMU2) @@ -566,6 +539,33 @@ function fmi2GetNominalsOfContinuousStates(fmu::FMU2) end # additionals +""" + fmi2Simulate(fmu::FMU2, args...; kwargs...) + +Wrapper for fmi2Simulate() in FMI/FMI2_sim.jl +""" +function fmi2Simulate(fmu::FMU2, args...; kwargs...) + return fmi2Simulate(fmu, nothing, args...; kwargs...) +end + +""" + fmi2SimulateCS(fmu::FMU2, args...; kwargs...) + +Wrapper for fmi2SimulateCS() in FMI/FMI2_sim.jl +""" +function fmi2SimulateCS(fmu::FMU2, args...; kwargs...) + return fmi2SimulateCS(fmu, nothing, args...; kwargs...) +end + +""" + fmi2SimulateME(fmu::FMU2, args...; kwargs...) + +Wrapper for fmi2SimulateME() in FMI/FMI2_sim.jl +""" +function fmi2SimulateME(fmu::FMU2, args...; kwargs...) + return fmi2SimulateME(fmu, nothing, args...; kwargs...) +end + """ fmi2GetStartValue(fmu::FMU2, args...; kwargs...) diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index 1ed16699..d41583b7 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -1,4 +1,1143 @@ # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher # Licensed under the MIT license. See LICENSE file in the project root for details. -# \ No newline at end of file +# + +# What is included in the file `FMI3_comp_wraps.jl` (FMU instance wrappers)? +# - wrappers to call fmi3InstanceFunctions from FMUs (FMI-functions, last instantiated component is used) [exported] +# - wrappers to call fmi3InstanceFunctions from FMUs (additional functions, last instantiated component is used) [exported] + + +using FMIImport: FMU3, fmi3ModelDescription +using FMIImport: fmi3Float32, fmi3Float64, fmi3Int8, fmi3Int16, fmi3Int32, fmi3Int64, fmi3Boolean, fmi3String, fmi3Binary, fmi3UInt8, fmi3UInt16, fmi3UInt32, fmi3UInt64, fmi3Byte +using FMIImport: fmi3Clock, fmi3FMUState +using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate +""" + fmi3FreeInstance!(fmu::FMU3) + +Wrapper for fmi3FreeInstance!() in FMIImport/FMI3_c.jl +""" +function fmi3FreeInstance!(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi2FreeInstance!(fmu.instances[end]) # this command also removes the instance from the array +end + +""" +fmi3SetDebugLogging(fmu::FMU3) + +Wrapper for fmi3SetDebugLogging() in FMIImport/FMI3_int.jl +""" +function fmi3SetDebugLogging(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetDebugLogging(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated + +FMU enters Initialization mode. + +For more information call ?fmi3EnterInitializationMode +""" +function fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterInitializationMode(fmu.instances[end], startTime, stopTime; tolerance = tolerance) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode + +FMU exits Initialization mode. + +For more information call ?fmi3ExitInitializationMode +""" +function fmi3ExitInitializationMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3ExitInitializationMode(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.4. Super State: Initialized + +Informs FMU that simulation run is terminated. + +For more information call ?fmi3Terminate +""" +function fmi3Terminate(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3Terminate(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.1. Super State: FMU State Setable + +Resets FMU. + +For more information call ?fmi3Reset +""" +function fmi3Reset(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3Reset(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Float32 variables. + +For more information call ?fmi3GetFloat32 +""" +function fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat32(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Float32 variables. + +For more information call ?fmi3GetFloat32! +""" +function fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat32!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Float32 variables. + +For more information call ?fmi3SetFloat32 +""" +function fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetFloat32(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Float64 variables. + +For more information call ?fmi3GetFloat64 +""" +function fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat64(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Float64 variables. + +For more information call ?fmi3GetFloat64! +""" +function fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat64!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Float64 variables. + +For more information call ?fmi3SetFloat64 +""" +function fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetFloat64(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int8 variables. + +For more information call ?fmi3GetInt8 +""" +function fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt8(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int8 variables. + +For more information call ?fmi3GetInt8! +""" +function fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt8!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Int8 variables. + +For more information call ?fmi3SetInt8 +""" +function fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt8(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt8 variables. + +For more information call ?fmi3GetUInt8 +""" +function fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt8(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt8 variables. + +For more information call ?fmi3GetUInt8! +""" +function fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt8!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3UInt8 variables. + +For more information call ?fmi3SetUInt8 +""" +function fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt8(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int16 variables. + +For more information call ?fmi3GetInt16 +""" +function fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt16(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int16 variables. + +For more information call ?fmi3GetInt16! +""" +function fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt16!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Int16 variables. + +For more information call ?fmi3SetInt16 +""" +function fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt16(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt16 variables. + +For more information call ?fmi3GetUInt16 +""" +function fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt16(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt16 variables. + +For more information call ?fmi3GetUInt16! +""" +function fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt16!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3UInt16 variables. + +For more information call ?fmi3SetUInt16 +""" +function fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt16(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int32 variables. + +For more information call ?fmi3GetInt32 +""" +function fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt32(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int32 variables. + +For more information call ?fmi3GetInt32! +""" +function fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt32!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Int32 variables. + +For more information call ?fmi3SetInt32 +""" +function fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt32(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt32 variables. + +For more information call ?fmi3GetUInt32 +""" +function fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt32(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt32 variables. + +For more information call ?fmi3GetUInt32! +""" +function fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt32!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3UInt32 variables. + +For more information call ?fmi3SetUInt32 +""" +function fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt32(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int64 variables. + +For more information call ?fmi3GetInt64 +""" +function fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt64(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Int64 variables. + +For more information call ?fmi3GetInt64! +""" +function fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt64!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Int64 variables. + +For more information call ?fmi3SetInt64 +""" +function fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt64(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt64 variables. + +For more information call ?fmi3GetUInt64 +""" +function fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt64(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3UInt64 variables. + +For more information call ?fmi3GetUInt64! +""" +function fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt64!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3UInt64 variables. + +For more information call ?fmi3SetUInt64 +""" +function fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt64(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Boolean variables. + +For more information call ?fmi3GetBoolean +""" +function fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBoolean(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Boolean variables. + +For more information call ?fmi3GetBoolean! +""" +function fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBoolean!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Boolean variables. + +For more information call ?fmi3SetBoolean +""" +function fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetBoolean(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3String variables. + +For more information call ?fmi3GetString +""" +function fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetString(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3String variables. + +For more information call ?fmi3GetString! +""" +function fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetString!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3String variables. + +For more information call ?fmi3SetString +""" +function fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetString(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Binary variables. + +For more information call ?fmi3GetBinary +""" +function fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBinary(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Binary variables. + +For more information call ?fmi3GetBinary! +""" +function fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBinary!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Binary variables. + +For more information call ?fmi3SetBinary +""" +function fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, valueSizes::Union{Array{Csize_t}, Csize_t}, values::Union{Array{fmi3Binary}, fmi3Binary}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetBinary(fmu.instances[end], vr, valueSizes, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Clock variables. + +For more information call ?fmi3GetClock +""" +function fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetClock(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Get the values of an array of fmi3Clock variables. + +For more information call ?fmi3GetClock! +""" +function fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetClock!(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + +Set the values of an array of fmi3Clock variables. + +For more information call ?fmi3SetClock +""" +function fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetClock(fmu.instances[end], vr, values) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State + +Get the pointer to the current FMU state. + +For more information call ?fmi3GetFMUState +""" +function fmi3GetFMUState(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFMUState(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State + +Set the FMU to the given fmi3FMUstate. + +For more information call ?fmi3SetFMUState +""" +function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetFMUState(fmu.instances[end], state) +end + +""" +function fmi3FreeFMUState(c::fmi3Component, FMUstate::Ref{fmi3FMUState}) + +Free the allocated memory for the FMU state. + +For more information call ?fmi3FreeFMUState +""" +function fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + stateRef = Ref(state) + fmi3FreeFMUState(fmu.instances[end], stateRef) + state = stateRef[] +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State + +Returns the size of a byte vector the FMU can be stored in. + +For more information call ?fmi3SerzializedFMUStateSize +""" +function fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SerializedFMUStateSize(fmu.instances[end], state) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State + +Serialize the data in the FMU state pointer. + +For more information call ?fmi3SerializeFMUState +""" +function fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SerializeFMUState(fmu.instances[end], state) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State + +Deserialize the data in the serializedState fmi3Byte field. + +For more information call ?fmi3DeSerializeFMUState +""" +function fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3DeSerializeFMUState(fmu.instances[end], serializedState) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + +Retrieves directional derivatives. + +For more information call ?fmi3GetDirectionalDerivative +""" +function fmi3GetDirectionalDerivative(fmu::FMU3, + unknowns::fmi3ValueReference, + knowns::fmi3ValueReference, + seed::fmi3Float64 = 1.0) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetDirectionalDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + +Retrieves directional derivatives. + +For more information call ?fmi3GetDirectionalDerivative +""" +function fmi3GetDirectionalDerivative(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetDirectionalDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + +Retrieves directional derivatives in-place. + +For more information call ?fmi3GetDirectionalDerivative +""" +function fmi3GetDirectionalDerivative!(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + sensitivity::Array{fmi3Float64}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetDirectionalDerivative!(fmu.instances[end], unknowns, knowns, sensitivity, seed) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + +Retrieves adjoint derivatives. + +For more information call ?fmi3GetAdjointDerivative +""" +function fmi3GetAdjointDerivative(fmu::FMU3, + unknowns::fmi3ValueReference, + knowns::fmi3ValueReference, + seed::fmi3Float64 = 1.0) + + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetAdjointDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + +Retrieves adjoint derivatives. + +For more information call ?fmi3GetAdjointDerivative +""" +function fmi3GetAdjointDerivative(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetAdjointDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + +Retrieves adjoint derivatives. + +For more information call ?fmi3GetAdjointDerivative +""" +function fmi3GetAdjointDerivative!(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + sensitivity::Array{fmi3Float64}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetAdjointDerivative!(fmu.instances[end], unknowns, knowns, sensitivity, seed) +end +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs + +Retrieves the n-th derivative of output values. + +vr defines the value references of the variables +the array order specifies the corresponding order of derivation of the variables + +For more information call ?fmi3GetOutputDerivatives +""" +function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetOutputDerivatives(fmu.instances[end], vr, order) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs + +Retrieves the n-th derivative of output values. + +vr defines the value references of the variables +the array order specifies the corresponding order of derivation of the variables + +For more information call ?fmi3GetOutputDerivatives +""" +function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReference, order::Integer) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetOutputDerivatives(fmu.instances[end], vr, order) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated + +If the importer needs to change structural parameters, it must move the FMU into Configuration Mode using fmi3EnterConfigurationMode. +For more information call ?fmi3EnterConfigurationMode +""" +function fmi3EnterConfigurationMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterConfigurationMode(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated + +This function returns the number of continuous states. +This function can only be called in Model Exchange. +For more information call ?fmi3GetNumberOfContinuousStates +""" +function fmi3GetNumberOfContinuousStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNumberOfContinuousStates(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated + +This function returns the number of event indicators. +This function can only be called in Model Exchange. +For more information call ?fmi3GetNumberOfEventIndicators +""" +function fmi3GetNumberOfEventIndicators(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNumberOfEventIndicators(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables + +The number of dependencies of a given variable, which may change if structural parameters are changed, can be retrieved by calling the following function: +For more information call ?fmi3GetNumberOfVariableDependencies +""" +function fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNumberOfVariableDependencies(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode + +Return the states at the current time instant. +For more information call ?fmi3GetContinuousStates +""" +function fmi3GetContinuousStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetContinuousStates(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables + +The dependencies (of type dependenciesKind) can be retrieved by calling the function fmi3GetVariableDependencies. +For more information call ?fmi3GetVariableDependencies +""" +function fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetVariableDependencies(fmu.instances[end], vr) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode + +Return the nominal values of the continuous states. + +For more information call ?fmi3GetNominalsOfContinuousStates +""" +function fmi3GetNominalsOfContinuousStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNominalsOfContinuousStates(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode + +This function is called to trigger the evaluation of fdisc to compute the current values of discrete states from previous values. +The FMU signals the support of fmi3EvaluateDiscreteStates via the capability flag providesEvaluateDiscreteStates. + +For more information call ?fmi3EvaluateDiscreteStates +""" +function fmi3EvaluateDiscreteStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EvaluateDiscreteStates(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode + +This function is called to signal a converged solution at the current super-dense time instant. fmi3UpdateDiscreteStates must be called at least once per super-dense time instant. + +For more information call ?fmi3UpdateDiscreteStates +""" +function fmi3UpdateDiscreteStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3UpdateDiscreteStates(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode + +The model enters Continuous-Time Mode. + +For more information call ?fmi3EnterContinuousTimeMode +""" +function fmi3EnterContinuousTimeMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterContinuousTimeMode(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode + +This function must be called to change from Event Mode into Step Mode in Co-Simulation. + +For more information call ?fmi3EnterStepMode +""" +function fmi3EnterStepMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterStepMode(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 2.3.6. State: Configuration Mode + +Exits the Configuration Mode and returns to state Instantiated. + +For more information call ?fmi3ExitConfigurationMode +""" +function fmi3ExitConfigurationMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3ExitConfigurationMode(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + +Set independent variable time and reinitialize chaching of variables that depend on time. + +For more information call ?fmi3SetTime +""" +function fmi3SetTime(fmu::FMU3, time::Real) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmu.t = time + fmi3SetTime(fmu.instances[end], fmi3Float64(time)) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + +Set a new (continuous) state vector and reinitialize chaching of variables that depend on states. + +For more information call ?fmi3SetContinuousStates +""" +function fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + nx = Csize_t(length(x)) + fmu.x = x + fmi3SetContinuousStates(fmu.instances[end], Array{fmi3Float64}(x), nx) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + +Compute state derivatives at the current time instant and for the current states. + +For more information call ?fmi3GetContinuousStateDerivatives +""" +function fmi3GetContinuousStateDerivatives(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetContinuousStateDerivatives(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + +Returns the event indicators of the FMU. + +For more information call ?fmi3GetEventIndicators +""" +function fmi3GetEventIndicators(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetEventIndicators(fmu.instances[end]) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + +This function must be called by the environment after every completed step +If enterEventMode == fmi3True, the event mode must be entered +If terminateSimulation == fmi3True, the simulation shall be terminated + +For more information call ?fmi3CompletedIntegratorStep +""" +function fmi3CompletedIntegratorStep(fmu::FMU3, + noSetFMUStatePriorToCurrentPoint::fmi3Boolean) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3CompletedIntegratorStep(fmu.instances[end], noSetFMUStatePriorToCurrentPoint) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + +The model enters Event Mode. + +For more information call ?fmi3EnterEventMode +""" +function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterEventMode(fmu.instances[end], stepEvent, stateEvent, rootsFound, nEventIndicators, timeEvent) +end + +""" +Source: FMISpec3.0, Version D5ef1c1: 4.2.1. State: Step Mode + +The computation of a time step is started. + +For more information call ?fmi3DoStep +""" +function fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + refeventEncountered = Ref(eventEncountered) + refterminateSimulation = Ref(terminateSimulation) + refearlyReturn = Ref(earlyReturn) + reflastSuccessfulTime = Ref(lastSuccessfulTime) + fmi3DoStep(fmu.instances[end], fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) + eventEncountered = refeventEncountered[] + terminateSimulation = refterminateSimulation[] + earlyReturn = refearlyReturn[] + lastSuccessfulTime = reflastSuccessfulTime[] +end + +""" +Starts a simulation of the fmu instance for the matching fmu type. If both types are available, CS is preferred over ME. +""" +function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; + recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3Simulate(fmu.instances[end], t_start, t_stop; + recordValues=recordValues, saveat=saveat, setup=setup) +end +""" +Starts a simulation of a FMU in CS-mode. +""" +function fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; + recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SimulateCS(fmu.instances[end], t_start, t_stop; + recordValues=recordValues, saveat=saveat, setup=setup) +end + +""" +Starts a simulation of a FMU in ME-mode. +""" +function fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SimulateME(fmu.instances[end], t_start, t_stop; kwargs...) +end + +""" +Returns the start/default value for a given value reference. + +TODO: Add this command in the documentation. +""" +function fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetStartValue(fmu.instances[end], vr) +end \ No newline at end of file From 8e97b31b2239440d697fee151fe6dcb027ec41af Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 7 Jun 2022 13:11:39 +0200 Subject: [PATCH 04/41] refactor FMI3_additional.jl --- src/FMI3_additional.jl | 1402 ++++------------------------------------ 1 file changed, 121 insertions(+), 1281 deletions(-) diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 9d6747d5..727ae045 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -3,1317 +3,157 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # +# What is included in the file `FMI3_additional.jl` (FMU add functions)? +# - high-level functions, that are useful, but not part of the FMI-spec [exported] + +using Base.Filesystem: mktempdir + using FMIImport: FMU3, fmi3ModelDescription using FMIImport: fmi3Float32, fmi3Float64, fmi3Int8, fmi3Int16, fmi3Int32, fmi3Int64, fmi3Boolean, fmi3String, fmi3Binary, fmi3UInt8, fmi3UInt16, fmi3UInt32, fmi3UInt64, fmi3Byte using FMIImport: fmi3Clock, fmi3FMUState -using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate - -# wrapper functions on the model description -function fmi3GetModelName(fmu::FMU3) - fmi3GetModelName(fmu.modelDescription) -end -function fmi3GetInstantiationToken(fmu::FMU3) - fmi3GetInstantiationToken(fmu.modelDescription) -end -function fmi3GetGenerationTool(fmu::FMU3) - fmi3GetGenerationTool(fmu.modelDescription) -end -function fmi3GetGenerationDateAndTime(fmu::FMU3) - fmi3GetGenerationDateAndTime(fmu.modelDescription) -end -function fmi3GetVariableNamingConvention(fmu::FMU3) - fmi3GetVariableNamingConvention(fmu.modelDescription) -end - -function fmi3CanGetSetState(fmu::FMU3) - fmi3CanGetSetState(fmu.modelDescription) -end -function fmi3CanSerializeFMUstate(fmu::FMU3) - fmi3CanSerializeFMUstate(fmu.modelDescription) -end -function fmi3ProvidesDirectionalDerivatives(fmu::FMU3) - fmi3ProvidesDirectionalDerivatives(fmu.modelDescription) -end -function fmi3ProvidesAdjointDerivatives(fmu::FMU3) - fmi3ProvidesAdjointDerivatives(fmu.modelDescription) -end -function fmi3IsCoSimulation(fmu::FMU3) - fmi3IsCoSimulation(fmu.modelDescription) -end -function fmi3IsModelExchange(fmu::FMU3) - fmi3IsModelExchange(fmu.modelDescription) -end -function fmi3IsScheduledExecution(fmu::FMU3) - fmi3IsScheduledExecution(fmu.modelDescription) -end +using FMIImport: fmi3True, fmi3False +using FMIImport: fmi3DependencyKindDependent, fmi3DependencyKindFixed +using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate, fmi3Instance +import FMIImport: fmi3VariableNamingConventionFlat, fmi3VariableNamingConventionStructured +""" +Returns how a variable depends on another variable based on the model description. """ -Returns an array of ValueReferences coresponding to the variable names. -""" -function fmi3String2ValueReference(md::fmi3ModelDescription, names::Array{String}) - vr = Array{fmi3ValueReference}(undef,0) - for name in names - reference = fmi3String2ValueReference(md, name) - if reference === nothing - @warn "Value reference for variable '$name' not found, skipping." - else - push!(vr, reference) - end - end - vr -end - -""" -Returns the ValueReference coresponding to the variable name. -""" -function fmi3String2ValueReference(md::fmi3ModelDescription, name::String) - reference = nothing - if haskey(md.stringValueReferences, name) - reference = md.stringValueReferences[name] - else - @warn "No variable named '$name' found." - end - reference -end - -function fmi3String2ValueReference(fmu::FMU3, name::Union{String, Array{String}}) - fmi3String2ValueReference(fmu.modelDescription, name) +function fmi3VariableDependsOnVariable(fmu::FMU3, vr1::fmi3ValueReference, vr2::fmi3ValueReference) + i1 = fmu.modelDescription.valueReferenceIndicies[vr1] + i2 = fmu.modelDescription.valueReferenceIndicies[vr2] + return fmi3GetDependencies(fmu)[i1, i2] end """ -Returns an array of variable names matching a fmi3ValueReference. -""" -function fmi3ValueReference2String(md::fmi3ModelDescription, reference::fmi3ValueReference) - [k for (k,v) in md.stringValueReferences if v == reference] -end -function fmi3ValueReference2String(md::fmi3ModelDescription, reference::Int64) - fmi3ValueReference2String(md, fmi3ValueReference(reference)) -end - -function fmi3ValueReference2String(fmu::FMU3, reference::Union{fmi3ValueReference, Int64}) - fmi3ValueReference2String(fmu.modelDescription, reference) -end +Returns the FMU's dependency-matrix for fast look-ups on dependencies between value references. +Entries are from type fmi3DependencyKind. """ -Source: FMISpec3.0, Version D5ef1c1:: 2.3.1. Super State: FMU State Setable +function fmi3GetDependencies(fmu::FMU3) + if !isdefined(fmu, :dependencies) + dim = length(fmu.modelDescription.valueReferences) + @info "fmi3GetDependencies: Started building dependency matrix $(dim) x $(dim) ..." -Create a new instance of the given fmu, adds a logger if logginOn == true. + if fmi3DependenciesSupported(fmu.modelDescription) + fmu.dependencies = fill(nothing, dim, dim) -Returns the instance of a new FMU component. + for i in 1:dim + modelVariable = fmi3ModelVariablesForValueReference(fmu.modelDescription, fmu.modelDescription.valueReferences[i])[1] + + if modelVariable.dependencies !== nothing + indicies = collect(fmu.modelDescription.valueReferenceIndicies[fmu.modelDescription.modelVariables[dependency].valueReference] for dependency in modelVariable.dependencies) + dependenciesKind = modelVariable.dependenciesKind + + k = 1 + for j in 1:dim + if j in indicies + if dependenciesKind[k] == "fixed" + fmu.dependencies[i,j] = fmi3DependencyKindFixed + elseif dependenciesKind[k] == "dependent" + fmu.dependencies[i,j] = fmi3DependencyKindDependent + else + @warn "Unknown dependency kind for index ($i, $j) = `$(dependenciesKind[k])`." + end + k += 1 + end + end + end + end + else + fmu.dependencies = fill(nothing, dim, dim) + end -For more information call ?fmi3InstantiateModelExchange -""" -function fmi3InstantiateModelExchange!(fmu::FMU3; visible::Bool = false, loggingOn::Bool = false) + @info "fmi3GetDependencies: Building dependency matrix $(dim) x $(dim) finished." + end - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{Cvoid}, Ptr{Cchar}, Cuint, Ptr{Cchar})) + fmu.dependencies +end - compAddr = fmi3InstantiateModelExchange(fmu.cInstantiateModelExchange, fmu.instanceName, fmu.modelDescription.instantiationToken, fmu.fmuResourceLocation, fmi3Boolean(visible), fmi3Boolean(loggingOn), fmu.instanceEnvironment, ptrLogger) +function fmi3PrintDependencies(fmu::FMU2) + dep = fmi3GetDependencies(fmu) + ni, nj = size(dep) - if compAddr == Ptr{Cvoid}(C_NULL) - @error "fmi3InstantiateModelExchange!(...): Instantiation failed!" - return nothing + for i in 1:ni + str = "" + for j in 1:nj + str = "$(str) $(Integer(dep[i,j]))" + end + println(str) end - previous_z = zeros(fmi3Float64, fmi3GetEventIndicators(fmu.modelDescription)) - rootsFound = zeros(fmi3Int32, fmi3GetEventIndicators(fmu.modelDescription)) - stateEvent = fmi3False - timeEvent = fmi3False - stepEvent = fmi3False - component = fmi3Component(compAddr, fmu, previous_z, rootsFound, stateEvent, timeEvent, stepEvent) - push!(fmu.components, component) - component end """ -Source: FMISpec3.0, Version D5ef1c1:: 2.3.1. Super State: FMU State Setable - -Create a new instance of the given fmu, adds a logger if logginOn == true. - -Returns the instance of a new FMU component. - -For more information call ?fmi3InstantiateCoSimulation +Prints FMU related information. """ -function fmi3InstantiateCoSimulation!(fmu::FMU3; visible::Bool = false, loggingOn::Bool = false, eventModeUsed::Bool = false, ptrIntermediateUpdate=nothing) +function fmi3Info(fmu::FMU3) + println("#################### Begin information for FMU ####################") - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{Cvoid}, Ptr{Cchar}, Cuint, Ptr{Cchar})) - if ptrIntermediateUpdate === nothing - ptrIntermediateUpdate = @cfunction(fmi3CallbackIntermediateUpdate, Cvoid, (Ptr{Cvoid}, fmi3Float64, fmi3Boolean, fmi3Boolean, fmi3Boolean, fmi3Boolean, Ptr{fmi3Boolean}, Ptr{fmi3Float64})) + println("\tModel name:\t\t\t$(fmi3GetModelName(fmu))") + println("\tFMI-Version:\t\t\t$(fmi3GetVersion(fmu))") + println("\tInstantiation Token:\t\t\t\t$(fmi3GetInstantiationToken(fmu))") + println("\tGeneration tool:\t\t$(fmi3GetGenerationTool(fmu))") + println("\tGeneration time:\t\t$(fmi3GetGenerationDateAndTime(fmu))") + print("\tVar. naming conv.:\t\t") + if fmi3GetVariableNamingConvention(fmu) == fmi3VariableNamingConventionFlat + println("flat") + elseif fmi3GetVariableNamingConvention(fmu) == fmi3VariableNamingConventionStructured + println("structured") + else + println("[unknown]") end - if fmu.modelDescription.CShasEventMode - mode = eventModeUsed - else - mode = false - end - - compAddr = fmi3InstantiateCoSimulation(fmu.cInstantiateCoSimulation, fmu.instanceName, fmu.modelDescription.instantiationToken, fmu.fmuResourceLocation, fmi3Boolean(visible), fmi3Boolean(loggingOn), - fmi3Boolean(mode), fmi3Boolean(fmu.modelDescription.CScanReturnEarlyAfterIntermediateUpdate), fmu.modelDescription.intermediateUpdateValueReferences, Csize_t(length(fmu.modelDescription.intermediateUpdateValueReferences)), fmu.instanceEnvironment, ptrLogger, ptrIntermediateUpdate) + println("\tEvent indicators:\t\t$(fmi3GetNumberOfEventIndicators(fmu))") - if compAddr == Ptr{Cvoid}(C_NULL) - @error "fmi3InstantiateCoSimulation!(...): Instantiation failed!" - return nothing + println("\tInputs:\t\t\t\t$(length(fmu.modelDescription.inputValueReferences))") + for vr in fmu.modelDescription.inputValueReferences + println("\t\t$(vr) $(fmi3ValueReferenceToString(fmu, vr))") end - component = fmi3Component(compAddr, fmu) - push!(fmu.components, component) - component -end - -# TODO not tested -""" -Source: FMISpec3.0, Version D5ef1c1:: 2.3.1. Super State: FMU State Setable - -Create a new instance of the given fmu, adds a logger if logginOn == true. - -Returns the instance of a new FMU component. - -For more information call ?fmi3InstantiateScheduledExecution -""" -function fmi3InstantiateScheduledExecution!(fmu::FMU3, ptrlockPreemption::Ptr{Cvoid}, ptrunlockPreemption::Ptr{Cvoid}; visible::Bool = false, loggingOn::Bool = false) - - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{Cvoid}, Ptr{Cchar}, Cuint, Ptr{Cchar})) - ptrClockUpdate = @cfunction(fmi3CallbackClockUpdate, Cvoid, (Ptr{Cvoid}, )) - - compAddr = fmi3InstantiateScheduledExecution(fmu.cInstantiateScheduledExecution, fmu.instanceName, fmu.modelDescription.instantiationToken, fmu.fmuResourceLocation, fmi3Boolean(visible), fmi3Boolean(loggingOn), fmu.instanceEnvironment, ptrLogger, ptrClockUpdate, ptrlockPreemption, ptrunlockPreemption) - - if compAddr == Ptr{Cvoid}(C_NULL) - @error "fmi3InstantiateScheduledExecution!(...): Instantiation failed!" - return nothing + println("\tOutputs:\t\t\t$(length(fmu.modelDescription.outputValueReferences))") + for vr in fmu.modelDescription.outputValueReferences + println("\t\t$(vr) $(fmi3ValueReferenceToString(fmu, vr))") end - component = fmi3Component(compAddr, fmu) - push!(fmu.components, component) - component -end - - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.4. Inquire Version Number of Header Files - -Returns the version of the FMI Standard used in this FMU. - -For more information call ?fmi3GetVersion -""" -function fmi3GetVersion(fmu::FMU3) - fmi3GetVersion(fmu.cGetVersion) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.1. Super State: FMU State Setable - -Sets debug logging for the FMU. - -For more information call ?fmi3SetDebugLogging -""" -function fmi3SetDebugLogging(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetDebugLogging(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -FMU enters Initialization mode. - -For more information call ?fmi3EnterInitializationMode -""" -function fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterInitializationMode(fmu.components[end], startTime, stopTime; tolerance = tolerance) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -FMU exits Initialization mode. - -For more information call ?fmi3ExitInitializationMode -""" -function fmi3ExitInitializationMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3ExitInitializationMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.4. Super State: Initialized - -Informs FMU that simulation run is terminated. - -For more information call ?fmi3Terminate -""" -function fmi3Terminate(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3Terminate(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.1. Super State: FMU State Setable - -Resets FMU. - -For more information call ?fmi3Reset -""" -function fmi3Reset(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3Reset(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float32 variables. - -For more information call ?fmi3GetFloat32 -""" -function fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat32(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float32 variables. - -For more information call ?fmi3GetFloat32! -""" -function fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat32!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Float32 variables. - -For more information call ?fmi3SetFloat32 -""" -function fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFloat32(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float64 variables. - -For more information call ?fmi3GetFloat64 -""" -function fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat64(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float64 variables. - -For more information call ?fmi3GetFloat64! -""" -function fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat64!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Float64 variables. - -For more information call ?fmi3SetFloat64 -""" -function fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFloat64(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int8 variables. - -For more information call ?fmi3GetInt8 -""" -function fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt8(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int8 variables. - -For more information call ?fmi3GetInt8! -""" -function fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt8!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int8 variables. - -For more information call ?fmi3SetInt8 -""" -function fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt8(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt8 variables. - -For more information call ?fmi3GetUInt8 -""" -function fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt8(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt8 variables. - -For more information call ?fmi3GetUInt8! -""" -function fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt8!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt8 variables. - -For more information call ?fmi3SetUInt8 -""" -function fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt8(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int16 variables. - -For more information call ?fmi3GetInt16 -""" -function fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt16(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int16 variables. - -For more information call ?fmi3GetInt16! -""" -function fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt16!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int16 variables. - -For more information call ?fmi3SetInt16 -""" -function fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt16(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt16 variables. - -For more information call ?fmi3GetUInt16 -""" -function fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt16(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt16 variables. - -For more information call ?fmi3GetUInt16! -""" -function fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt16!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt16 variables. - -For more information call ?fmi3SetUInt16 -""" -function fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt16(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int32 variables. - -For more information call ?fmi3GetInt32 -""" -function fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt32(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int32 variables. - -For more information call ?fmi3GetInt32! -""" -function fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt32!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int32 variables. - -For more information call ?fmi3SetInt32 -""" -function fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt32(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt32 variables. - -For more information call ?fmi3GetUInt32 -""" -function fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt32(fmu.components[end], vr) -end + println("\tStates:\t\t\t\t$(length(fmu.modelDescription.stateValueReferences))") + for vr in fmu.modelDescription.stateValueReferences + println("\t\t$(vr) $(fmi3ValueReferenceToString(fmu, vr))") + end -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + println("\tSupports Co-Simulation:\t\t$(fmi3IsCoSimulation(fmu))") + if fmi3IsCoSimulation(fmu) + println("\t\tModel identifier:\t$(fmu.modelDescription.coSimulation.modelIdentifier)") + println("\t\tGet/Set State:\t\t$(fmu.modelDescription.coSimulation.canGetAndSetFMUstate)") + println("\t\tSerialize State:\t$(fmu.modelDescription.coSimulation.canSerializeFMUstate)") + println("\t\tDir. Derivatives:\t$(fmu.modelDescription.coSimulation.providesDirectionalDerivatives)") + println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.coSimulation.providesAdjointDerivatives)") + println("\t\tEvent Mode:\t$(fmu.modelDescription.coSimulation.hasEventMode)") + + println("\t\tVar. com. steps:\t$(fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize)") + println("\t\tInput interpol.:\t$(fmu.modelDescription.coSimulation.canInterpolateInputs)") + println("\t\tMax order out. der.:\t$(fmu.modelDescription.coSimulation.maxOutputDerivativeOrder)") + end -Get the values of an array of fmi3UInt32 variables. + println("\tSupports Model-Exchange:\t$(fmi3IsModelExchange(fmu))") + if fmi3IsModelExchange(fmu) + println("\t\tModel identifier:\t$(fmu.modelDescription.modelExchange.modelIdentifier)") + println("\t\tGet/Set State:\t\t$(fmu.modelDescription.modelExchange.canGetAndSetFMUstate)") + println("\t\tSerialize State:\t$(fmu.modelDescription.modelExchange.canSerializeFMUstate)") + println("\t\tDir. Derivatives:\t$(fmu.modelDescription.modelExchange.providesDirectionalDerivatives)") + println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.modelExchange.providesAdjointDerivatives)") + end -For more information call ?fmi3GetUInt32! -""" -function fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + println("\tSupports Scheduled-Execution:\t$(fmi3IsScheduledExecution(fmu))") + if fmi3IsScheduledExecution(fmu) + println("\t\tModel identifier:\t$(fmu.modelDescription.scheduledExecution.modelIdentifier)") + println("\t\tGet/Set State:\t\t$(fmu.modelDescription.scheduledExecution.canGetAndSetFMUstate)") + println("\t\tSerialize State:\t$(fmu.modelDescription.scheduledExecution.canSerializeFMUstate)") + println("\t\tNeeds Execution Tool:\t$(fmu.modelDescription.scheduledExecution.needsExecutionTool)") + println("\t\tInstantiated Once Per Process:\t$(fmu.modelDescription.scheduledExecution.canBeInstantiatedOnlyOncePerProcess)") + println("\t\tPer Element Dependencies:\t$(fmu.modelDescription.scheduledExecution.providesPerElementDependencies)") + + println("\t\tDir. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesDirectionalDerivatives)") + println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesAdjointDerivatives)") + end - fmi3GetUInt32!(fmu.components[end], vr, values) + println("##################### End information for FMU #####################") end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt32 variables. - -For more information call ?fmi3SetUInt32 -""" -function fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt32(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int64 variables. - -For more information call ?fmi3GetInt64 -""" -function fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt64(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int64 variables. - -For more information call ?fmi3GetInt64! -""" -function fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt64!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int64 variables. - -For more information call ?fmi3SetInt64 -""" -function fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt64(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3GetUInt64 -""" -function fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt64(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3GetUInt64! -""" -function fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt64!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3SetUInt64 -""" -function fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt64(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Boolean variables. - -For more information call ?fmi3GetBoolean -""" -function fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBoolean(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Boolean variables. - -For more information call ?fmi3GetBoolean! -""" -function fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBoolean!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Boolean variables. - -For more information call ?fmi3SetBoolean -""" -function fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetBoolean(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3String variables. - -For more information call ?fmi3GetString -""" -function fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetString(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3String variables. - -For more information call ?fmi3GetString! -""" -function fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetString!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3String variables. - -For more information call ?fmi3SetString -""" -function fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetString(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Binary variables. - -For more information call ?fmi3GetBinary -""" -function fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBinary(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Binary variables. - -For more information call ?fmi3GetBinary! -""" -function fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBinary!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Binary variables. - -For more information call ?fmi3SetBinary -""" -function fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, valueSizes::Union{Array{Csize_t}, Csize_t}, values::Union{Array{fmi3Binary}, fmi3Binary}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetBinary(fmu.components[end], vr, valueSizes, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Clock variables. - -For more information call ?fmi3GetClock -""" -function fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetClock(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Clock variables. - -For more information call ?fmi3GetClock! -""" -function fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetClock!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Clock variables. - -For more information call ?fmi3SetClock -""" -function fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetClock(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Get the pointer to the current FMU state. - -For more information call ?fmi3GetFMUState -""" -function fmi3GetFMUState(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFMUState(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Set the FMU to the given fmi3FMUstate. - -For more information call ?fmi3SetFMUState -""" -function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFMUState(fmu.components[end], state) -end - -""" -function fmi3FreeFMUState(c::fmi3Component, FMUstate::Ref{fmi3FMUState}) - -Free the allocated memory for the FMU state. - -For more information call ?fmi3FreeFMUState -""" -function fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - stateRef = Ref(state) - fmi3FreeFMUState(fmu.components[end], stateRef) - state = stateRef[] -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Returns the size of a byte vector the FMU can be stored in. - -For more information call ?fmi3SerzializedFMUStateSize -""" -function fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SerializedFMUStateSize(fmu.components[end], state) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Serialize the data in the FMU state pointer. - -For more information call ?fmi3SerializeFMUState -""" -function fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SerializeFMUState(fmu.components[end], state) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Deserialize the data in the serializedState fmi3Byte field. - -For more information call ?fmi3DeSerializeFMUState -""" -function fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3DeSerializeFMUState(fmu.components[end], serializedState) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives. - -For more information call ?fmi3GetDirectionalDerivative -""" -function fmi3GetDirectionalDerivative(fmu::FMU3, - unknowns::fmi3ValueReference, - knowns::fmi3ValueReference, - seed::fmi3Float64 = 1.0) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives. - -For more information call ?fmi3GetDirectionalDerivative -""" -function fmi3GetDirectionalDerivative(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives in-place. - -For more information call ?fmi3GetDirectionalDerivative -""" -function fmi3GetDirectionalDerivative!(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - sensitivity::Array{fmi3Float64}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative!(fmu.components[end], unknowns, knowns, sensitivity, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative -""" -function fmi3GetAdjointDerivative(fmu::FMU3, - unknowns::fmi3ValueReference, - knowns::fmi3ValueReference, - seed::fmi3Float64 = 1.0) - - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative -""" -function fmi3GetAdjointDerivative(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative -""" -function fmi3GetAdjointDerivative!(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - sensitivity::Array{fmi3Float64}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative!(fmu.components[end], unknowns, knowns, sensitivity, seed) -end -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs - -Retrieves the n-th derivative of output values. - -vr defines the value references of the variables -the array order specifies the corresponding order of derivation of the variables - -For more information call ?fmi3GetOutputDerivatives -""" -function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetOutputDerivatives(fmu.components[end], vr, order) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs - -Retrieves the n-th derivative of output values. - -vr defines the value references of the variables -the array order specifies the corresponding order of derivation of the variables - -For more information call ?fmi3GetOutputDerivatives -""" -function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReference, order::Integer) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetOutputDerivatives(fmu.components[end], vr, order) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -If the importer needs to change structural parameters, it must move the FMU into Configuration Mode using fmi3EnterConfigurationMode. -For more information call ?fmi3EnterConfigurationMode -""" -function fmi3EnterConfigurationMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterConfigurationMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -This function returns the number of continuous states. -This function can only be called in Model Exchange. -For more information call ?fmi3GetNumberOfContinuousStates -""" -function fmi3GetNumberOfContinuousStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfContinuousStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -This function returns the number of event indicators. -This function can only be called in Model Exchange. -For more information call ?fmi3GetNumberOfEventIndicators -""" -function fmi3GetNumberOfEventIndicators(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfEventIndicators(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables - -The number of dependencies of a given variable, which may change if structural parameters are changed, can be retrieved by calling the following function: -For more information call ?fmi3GetNumberOfVariableDependencies -""" -function fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfVariableDependencies(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -Return the states at the current time instant. -For more information call ?fmi3GetContinuousStates -""" -function fmi3GetContinuousStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetContinuousStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables - -The dependencies (of type dependenciesKind) can be retrieved by calling the function fmi3GetVariableDependencies. -For more information call ?fmi3GetVariableDependencies -""" -function fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetVariableDependencies(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -Return the nominal values of the continuous states. - -For more information call ?fmi3GetNominalsOfContinuousStates -""" -function fmi3GetNominalsOfContinuousStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNominalsOfContinuousStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -This function is called to trigger the evaluation of fdisc to compute the current values of discrete states from previous values. -The FMU signals the support of fmi3EvaluateDiscreteStates via the capability flag providesEvaluateDiscreteStates. - -For more information call ?fmi3EvaluateDiscreteStates -""" -function fmi3EvaluateDiscreteStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EvaluateDiscreteStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -This function is called to signal a converged solution at the current super-dense time instant. fmi3UpdateDiscreteStates must be called at least once per super-dense time instant. - -For more information call ?fmi3UpdateDiscreteStates -""" -function fmi3UpdateDiscreteStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3UpdateDiscreteStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -The model enters Continuous-Time Mode. - -For more information call ?fmi3EnterContinuousTimeMode -""" -function fmi3EnterContinuousTimeMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterContinuousTimeMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -This function must be called to change from Event Mode into Step Mode in Co-Simulation. - -For more information call ?fmi3EnterStepMode -""" -function fmi3EnterStepMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterStepMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.6. State: Configuration Mode - -Exits the Configuration Mode and returns to state Instantiated. - -For more information call ?fmi3ExitConfigurationMode -""" -function fmi3ExitConfigurationMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3ExitConfigurationMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Set independent variable time and reinitialize chaching of variables that depend on time. - -For more information call ?fmi3SetTime -""" -function fmi3SetTime(fmu::FMU3, time::Real) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmu.t = time - fmi3SetTime(fmu.components[end], fmi3Float64(time)) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Set a new (continuous) state vector and reinitialize chaching of variables that depend on states. - -For more information call ?fmi3SetContinuousStates -""" -function fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - nx = Csize_t(length(x)) - fmu.x = x - fmi3SetContinuousStates(fmu.components[end], Array{fmi3Float64}(x), nx) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Compute state derivatives at the current time instant and for the current states. - -For more information call ?fmi3GetContinuousStateDerivatives -""" -function fmi3GetContinuousStateDerivatives(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetContinuousStateDerivatives(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Returns the event indicators of the FMU. - -For more information call ?fmi3GetEventIndicators -""" -function fmi3GetEventIndicators(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetEventIndicators(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -This function must be called by the environment after every completed step -If enterEventMode == fmi3True, the event mode must be entered -If terminateSimulation == fmi3True, the simulation shall be terminated - -For more information call ?fmi3CompletedIntegratorStep -""" -function fmi3CompletedIntegratorStep(fmu::FMU3, - noSetFMUStatePriorToCurrentPoint::fmi3Boolean) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3CompletedIntegratorStep(fmu.components[end], noSetFMUStatePriorToCurrentPoint) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -The model enters Event Mode. - -For more information call ?fmi3EnterEventMode -""" -function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterEventMode(fmu.components[end], stepEvent, stateEvent, rootsFound, nEventIndicators, timeEvent) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 4.2.1. State: Step Mode - -The computation of a time step is started. - -For more information call ?fmi3DoStep -""" -function fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - refeventEncountered = Ref(eventEncountered) - refterminateSimulation = Ref(terminateSimulation) - refearlyReturn = Ref(earlyReturn) - reflastSuccessfulTime = Ref(lastSuccessfulTime) - fmi3DoStep(fmu.components[end], fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) - eventEncountered = refeventEncountered[] - terminateSimulation = refterminateSimulation[] - earlyReturn = refearlyReturn[] - lastSuccessfulTime = reflastSuccessfulTime[] -end - -""" -Starts a simulation of the fmu instance for the matching fmu type. If both types are available, CS is preferred over ME. -""" -function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; - recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3Simulate(fmu.components[end], t_start, t_stop; - recordValues=recordValues, saveat=saveat, setup=setup) -end -""" -Starts a simulation of a FMU in CS-mode. -""" -function fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; - recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SimulateCS(fmu.components[end], t_start, t_stop; - recordValues=recordValues, saveat=saveat, setup=setup) -end - -""" -Starts a simulation of a FMU in ME-mode. -""" -function fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SimulateME(fmu.components[end], t_start, t_stop; kwargs...) -end - -""" -Returns the start/default value for a given value reference. - -TODO: Add this command in the documentation. -""" -function fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetStartValue(fmu.components[end], vr) -end \ No newline at end of file From b047c62e87c97f3dd5bdb21154d50306131769fb Mon Sep 17 00:00:00 2001 From: TT Date: Tue, 7 Jun 2022 13:19:11 +0200 Subject: [PATCH 05/41] update readme --- README.md | 27 +++++++++++++++------------ src/FMI.jl | 11 +++++++---- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 16e8e6ff..3bdda0f7 100644 --- a/README.md +++ b/README.md @@ -35,26 +35,29 @@ fmiUnload(myFMU) ``` ## What is currently supported in FMI.jl? -- importing the full FMI 2.0.3 command set, including optional specials like `fmi2GetState`, `fmi2SetState` and `fmi2GetDirectionalDerivatives` +- importing the full FMI 2.0.3 and FMI 3.0.0 command set, including optional specials like `fmi2GetState`, `fmi2SetState` and `fmi2GetDirectionalDerivatives` - parameterization, simulation & plotting of CS- and ME-FMUs - event-handling for imported discontinuous ME-FMUs -| | **FMI2.0.3** | | **FMI3.0 beta** | | +| | **FMI2.0.3** | | **FMI3.0** | | |-----------------------------------|--------------|--------|-----------------|--------| | | Import | Export | Import | Export | -| CS | ✓✓ | ~~ | ~~ | ~ | -| ME (continuous) | ✓✓ | ✓✓ | ~~ | ~ | -| ME (discontinuous) | ✓✓ | ✓✓ | ~~ | ~ | -| Explicit solvers | ✓✓ | ~~ | ~~ | ~ | -| Implicit solvers (autodiff=false) | ✓✓ | ~~ | ~~ | ~ | -| Implicit solvers (autodiff=true) | ~~ | ~~ | ~~ | ~ | -| get/setState | ✓✓ | ~ | ~~ | ~ | -| getDirectionalDerivatives | ✓✓ | ~ | ~~ | ~ | -| getAdjointDerivatives | - | - | ~~ | ~ | +| CS | ✓✓ | ~~ | ✓ | ~ | +| SE | - | - | [B] | ~ | +| ME (continuous) | ✓✓ | ✓✓ | ✓ | ~ | +| ME (discontinuous) | ✓✓ | ✓✓ | [B] | ~ | +| Explicit solvers | ✓✓ | ~~ | [B] | ~ | +| Implicit solvers (autodiff=false) | ✓✓ | ~~ | [B] | ~ | +| Implicit solvers (autodiff=true) | [B] | ~~ | ~~ | ~ | +| get/setState | ✓✓ | ~ | ✓ | ~ | +| getDirectionalDerivatives | ✓✓ | ~ | ✓ | ~ | +| getAdjointDerivatives | - | - | ✓ | ~ | ✓✓ supported & tested -✓ supported (beta) +✓ supported + +[B] implemented, untested, beta ~~ work in progress diff --git a/src/FMI.jl b/src/FMI.jl index 36258366..919c7656 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -42,11 +42,14 @@ using FMIExport: fmi2Create, fmi2CreateSimple using FMIImport.FMICore: fmi2ValueReference, fmi3ValueReference using FMIImport: fmi2ValueReferenceFormat, fmi3ValueReferenceFormat, fmi2StructMD, fmi3StructMD, fmi2Struct, fmi3Struct -using FMIImport.FMICore: FMU2, FMU3, FMU2Component, FMU3Component -export FMU2, FMU3, FMU2Component, FMU3Component +using FMIImport.FMICore: FMU2, FMU3, FMU2Component, FMU3Instance +export FMU2, FMU3, FMU2Component, FMU3Instance -using FMIImport.FMICore: FMU2ExecutionConfiguration, FMU_EXECUTION_CONFIGURATION_RESET, FMU_EXECUTION_CONFIGURATION_NO_RESET, FMU_EXECUTION_CONFIGURATION_NO_FREEING -export FMU2ExecutionConfiguration, FMU_EXECUTION_CONFIGURATION_RESET, FMU_EXECUTION_CONFIGURATION_NO_RESET, FMU_EXECUTION_CONFIGURATION_NO_FREEING +using FMIImport.FMICore: FMU2ExecutionConfiguration, FMU2_EXECUTION_CONFIGURATION_RESET, FMU2_EXECUTION_CONFIGURATION_NO_RESET, FMU2_EXECUTION_CONFIGURATION_NO_FREEING +export FMU2ExecutionConfiguration, FMU2_EXECUTION_CONFIGURATION_RESET, FMU2_EXECUTION_CONFIGURATION_NO_RESET, FMU2_EXECUTION_CONFIGURATION_NO_FREEING + +using FMIImport.FMICore: FMU3ExecutionConfiguration, FMU3_EXECUTION_CONFIGURATION_RESET, FMU3_EXECUTION_CONFIGURATION_NO_RESET, FMU3_EXECUTION_CONFIGURATION_NO_FREEING +export FMU3ExecutionConfiguration, FMU3_EXECUTION_CONFIGURATION_RESET, FMU3_EXECUTION_CONFIGURATION_NO_RESET, FMU3_EXECUTION_CONFIGURATION_NO_FREEING using FMIImport: prepareValue, prepareValueReference From f321189226eb04e49b222e56b43c2773fbe8048a Mon Sep 17 00:00:00 2001 From: TT Date: Tue, 7 Jun 2022 13:42:09 +0200 Subject: [PATCH 06/41] readme updated --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3bdda0f7..5433783e 100644 --- a/README.md +++ b/README.md @@ -40,24 +40,22 @@ fmiUnload(myFMU) - event-handling for imported discontinuous ME-FMUs | | **FMI2.0.3** | | **FMI3.0** | | -|-----------------------------------|--------------|--------|-----------------|--------| | | Import | Export | Import | Export | +|-----------------------------------|--------------|--------|-----------------|--------| | CS | ✓✓ | ~~ | ✓ | ~ | -| SE | - | - | [B] | ~ | | ME (continuous) | ✓✓ | ✓✓ | ✓ | ~ | -| ME (discontinuous) | ✓✓ | ✓✓ | [B] | ~ | -| Explicit solvers | ✓✓ | ~~ | [B] | ~ | -| Implicit solvers (autodiff=false) | ✓✓ | ~~ | [B] | ~ | -| Implicit solvers (autodiff=true) | [B] | ~~ | ~~ | ~ | +| ME (discontinuous) | ✓✓ | ✓✓ | ✓ | ~ | +| SE | - | - | ✓ | ~ | +| Explicit solvers | ✓✓ | ✓✓ | ✓ | ~ | +| Implicit solvers (autodiff=false) | ✓✓ | ~~ | ✓ | ~ | +| Implicit solvers (autodiff=true) | ✓ | ~~ | ~~ | ~ | | get/setState | ✓✓ | ~ | ✓ | ~ | | getDirectionalDerivatives | ✓✓ | ~ | ✓ | ~ | | getAdjointDerivatives | - | - | ✓ | ~ | ✓✓ supported & tested -✓ supported - -[B] implemented, untested, beta +✓ beta supported, untested ~~ work in progress From f6906b1b941038500107b873a9bf92a4fad9f0de Mon Sep 17 00:00:00 2001 From: TT Date: Tue, 7 Jun 2022 13:43:10 +0200 Subject: [PATCH 07/41] ... --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5433783e..20251b54 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,8 @@ fmiUnload(myFMU) - event-handling for imported discontinuous ME-FMUs | | **FMI2.0.3** | | **FMI3.0** | | -| | Import | Export | Import | Export | |-----------------------------------|--------------|--------|-----------------|--------| +| | Import | Export | Import | Export | | CS | ✓✓ | ~~ | ✓ | ~ | | ME (continuous) | ✓✓ | ✓✓ | ✓ | ~ | | ME (discontinuous) | ✓✓ | ✓✓ | ✓ | ~ | From 86762733d6fc0298a28c58958b90eab5b84d60c8 Mon Sep 17 00:00:00 2001 From: ThummeTo <83663542+ThummeTo@users.noreply.github.com> Date: Tue, 7 Jun 2022 14:14:49 +0200 Subject: [PATCH 08/41] Update README.md --- README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 20251b54..40974648 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # FMI.jl ## What is FMI.jl? -[*FMI.jl*](https://github.com/ThummeTo/FMI.jl) is a free-to-use software library for the Julia programming language which integrates FMI ([fmi-standard.org](http://fmi-standard.org/)): load, instantiate, parameterize and simulate FMUs seamlessly inside the Julia programming language! +[*FMI.jl*](https://github.com/ThummeTo/FMI.jl) is a free-to-use software library for the Julia programming language which integrates the **F**unctional **M**ock-Up **I**nterface ([fmi-standard.org](http://fmi-standard.org/)): load or create, parameterize, simulate and plot FMUs seamlessly inside the Julia programming language! [![Dev Docs](https://img.shields.io/badge/docs-dev-blue.svg)](https://ThummeTo.github.io/FMI.jl/dev) [![CI Testing](https://github.com/ThummeTo/FMI.jl/actions/workflows/Test.yml/badge.svg)](https://github.com/ThummeTo/FMI.jl/actions) @@ -12,10 +12,10 @@ ## How can I use FMI.jl? -1. open a Julia-Command-Window, activate your preferred environment -1. goto package manager using ```]``` -1. type ```add FMI``` or ```add "https://github.com/ThummeTo/FMI.jl"``` -1. have a look inside the ```example``` folder +1. Open a Julia-Command-Window, activate your preferred environment. +1. Goto package manager using ```]```. +1. Type ```add FMI``` or ```add "https://github.com/ThummeTo/FMI.jl"```. +1. Have a look inside the [examples folder](https://github.com/ThummeTo/FMI.jl/tree/main/example) or the [examples section](https://thummeto.github.io/FMI.jl/dev/examples/overview/) of the documentation. All examples are available as Julia-Script (*.jl*), Jupyter-Notebook (*.ipynb*) and Markdown (*.md*). ## How can I simulate a FMU and plot values? ```julia @@ -77,14 +77,13 @@ To keep dependencies nice and clean, the original package [*FMI.jl*](https://git - [*FMIZoo.jl*](https://github.com/ThummeTo/FMIZoo.jl): A collection of testing and example FMUs ## What is further under development in FMI.jl? -- FMI Cross Checks -- nice documentation -- more examples +- FMI Cross Checks (as soon as the successor is available) +- nice documentation & doc-strings +- more examples/tutorials - ... ## What is planned for FMI.jl? - SSP 1.0 support -- more examples - ... ## What Platforms are supported? From 06360e8c5e03225c1e5255e9bb854f673991182e Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 7 Jun 2022 15:15:32 +0200 Subject: [PATCH 09/41] update docstrings for wrapper functions --- src/FMI3_comp_wraps.jl | 546 +++++++++++++++-------------------------- 1 file changed, 196 insertions(+), 350 deletions(-) diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index d41583b7..451eb292 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -12,6 +12,8 @@ using FMIImport: FMU3, fmi3ModelDescription using FMIImport: fmi3Float32, fmi3Float64, fmi3Int8, fmi3Int16, fmi3Int32, fmi3Int64, fmi3Boolean, fmi3String, fmi3Binary, fmi3UInt8, fmi3UInt16, fmi3UInt32, fmi3UInt64, fmi3Byte using FMIImport: fmi3Clock, fmi3FMUState using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate + +# fmi-spec """ fmi3FreeInstance!(fmu::FMU3) @@ -23,7 +25,7 @@ function fmi3FreeInstance!(fmu::FMU3) end """ -fmi3SetDebugLogging(fmu::FMU3) + fmi3SetDebugLogging(fmu::FMU3) Wrapper for fmi3SetDebugLogging() in FMIImport/FMI3_int.jl """ @@ -34,11 +36,9 @@ function fmi3SetDebugLogging(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -FMU enters Initialization mode. + fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) -For more information call ?fmi3EnterInitializationMode +Wrapper for fmi3EnterInitializationMode() in FMIImport/FMI3_c.jl """ function fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -47,11 +47,9 @@ function fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime: end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode + fmi3ExitInitializationMode(fmu::FMU2) -FMU exits Initialization mode. - -For more information call ?fmi3ExitInitializationMode +Wrapper for fmi3ExitInitializationMode() in FMIImport/FMI3_c.jl """ function fmi3ExitInitializationMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -60,11 +58,9 @@ function fmi3ExitInitializationMode(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.4. Super State: Initialized - -Informs FMU that simulation run is terminated. + fmi3Terminate(fmu::FMU3) -For more information call ?fmi3Terminate +Wrapper for fmi3Terminate() in FMIImport/FMI3_c.jl """ function fmi3Terminate(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -73,11 +69,9 @@ function fmi3Terminate(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.1. Super State: FMU State Setable + fmi3Reset(fmu::FMU3) -Resets FMU. - -For more information call ?fmi3Reset +Wrapper for fmi2Reset() in FMIImport/FMI3_c.jl """ function fmi3Reset(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -86,11 +80,9 @@ function fmi3Reset(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float32 variables. + fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) -For more information call ?fmi3GetFloat32 +Wrapper for fmi3GetFloat32() in FMIImport/FMI3_int.jl """ function fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -99,11 +91,9 @@ function fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) -Get the values of an array of fmi3Float32 variables. - -For more information call ?fmi3GetFloat32! +Wrapper for fmi3GetFloat32!() in FMIImport/FMI3_int.jl """ function fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -112,11 +102,9 @@ function fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{ end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Float32 variables. +fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) -For more information call ?fmi3SetFloat32 +Wrapper for fmi3SetFloat32() in FMIImport/FMI3_int.jl """ function fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -125,11 +113,9 @@ function fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) -Get the values of an array of fmi3Float64 variables. - -For more information call ?fmi3GetFloat64 +Wrapper for fmi3GetFloat64() in FMIImport/FMI3_int.jl """ function fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -138,11 +124,9 @@ function fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float64 variables. + fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) -For more information call ?fmi3GetFloat64! +Wrapper for fmi3GetFloat64!() in FMIImport/FMI3_int.jl """ function fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -151,11 +135,9 @@ function fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{ end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) -Set the values of an array of fmi3Float64 variables. - -For more information call ?fmi3SetFloat64 +Wrapper for fmi3SetFloat64() in FMIImport/FMI3_int.jl """ function fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -164,11 +146,9 @@ function fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int8 variables. + fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) -For more information call ?fmi3GetInt8 +Wrapper for fmi3GetInt8() in FMIImport/FMI3_int.jl """ function fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -177,11 +157,9 @@ function fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) -Get the values of an array of fmi3Int8 variables. - -For more information call ?fmi3GetInt8! +Wrapper for fmi3GetInt8!() in FMIImport/FMI3_int.jl """ function fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -190,11 +168,9 @@ function fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Arr end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int8 variables. + fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) -For more information call ?fmi3SetInt8 +Wrapper for fmi3SetInt8() in FMIImport/FMI3_int.jl """ function fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -203,11 +179,9 @@ function fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Arra end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt8 variables. + fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) -For more information call ?fmi3GetUInt8 +Wrapper for fmi3GetUInt8() in FMIImport/FMI3_int.jl """ function fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -216,11 +190,9 @@ function fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) -Get the values of an array of fmi3UInt8 variables. - -For more information call ?fmi3GetUInt8! +Wrapper for fmi3GetUInt8!() in FMIImport/FMI3_int.jl """ function fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -229,11 +201,9 @@ function fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt8 variables. + fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) -For more information call ?fmi3SetUInt8 +Wrapper for fmi3SetUInt8() in FMIImport/FMI3_int.jl """ function fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -242,11 +212,9 @@ function fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Arr end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) -Get the values of an array of fmi3Int16 variables. - -For more information call ?fmi3GetInt16 +Wrapper for fmi3GetInt16() in FMIImport/FMI3_int.jl """ function fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -255,11 +223,9 @@ function fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int16 variables. + fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) -For more information call ?fmi3GetInt16! +Wrapper for fmi3GetInt16!() in FMIImport/FMI3_int.jl """ function fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -268,11 +234,9 @@ function fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) -Set the values of an array of fmi3Int16 variables. - -For more information call ?fmi3SetInt16 +Wrapper for fmi3SetInt16() in FMIImport/FMI3_int.jl """ function fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -281,11 +245,9 @@ function fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Arr end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt16 variables. + fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) -For more information call ?fmi3GetUInt16 +Wrapper for fmi3GetUInt16() in FMIImport/FMI3_int.jl """ function fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -294,11 +256,9 @@ function fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) -Get the values of an array of fmi3UInt16 variables. - -For more information call ?fmi3GetUInt16! +Wrapper for fmi3GetUInt16!() in FMIImport/FMI3_int.jl """ function fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -307,11 +267,9 @@ function fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt16 variables. + fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) -For more information call ?fmi3SetUInt16 +Wrapper for fmi3SetUInt16() in FMIImport/FMI3_int.jl """ function fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -320,11 +278,9 @@ function fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) -Get the values of an array of fmi3Int32 variables. - -For more information call ?fmi3GetInt32 +Wrapper for fmi3GetInt32() in FMIImport/FMI3_int.jl """ function fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -333,11 +289,9 @@ function fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int32 variables. + fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) -For more information call ?fmi3GetInt32! +Wrapper for fmi3GetInt32!() in FMIImport/FMI3_int.jl """ function fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -346,11 +300,9 @@ function fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) -Set the values of an array of fmi3Int32 variables. - -For more information call ?fmi3SetInt32 +Wrapper for fmi3SetInt32() in FMIImport/FMI3_int.jl """ function fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -359,11 +311,9 @@ function fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Arr end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt32 variables. + fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) -For more information call ?fmi3GetUInt32 +Wrapper for fmi3GetUInt32() in FMIImport/FMI3_int.jl """ function fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -372,11 +322,9 @@ function fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) -Get the values of an array of fmi3UInt32 variables. - -For more information call ?fmi3GetUInt32! +Wrapper for fmi3GetUInt32!() in FMIImport/FMI3_int.jl """ function fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -385,11 +333,9 @@ function fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt32 variables. + fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) -For more information call ?fmi3SetUInt32 +Wrapper for fmi3SetUInt32() in FMIImport/FMI3_int.jl """ function fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -398,11 +344,9 @@ function fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int64 variables. + fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) -For more information call ?fmi3GetInt64 +Wrapper for fmi3GetInt64() in FMIImport/FMI3_int.jl """ function fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -411,11 +355,9 @@ function fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) -Get the values of an array of fmi3Int64 variables. - -For more information call ?fmi3GetInt64! +Wrapper for fmi3GetInt64!() in FMIImport/FMI3_int.jl """ function fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -424,11 +366,9 @@ function fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int64 variables. + fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) -For more information call ?fmi3SetInt64 +Wrapper for fmi3SetInt64() in FMIImport/FMI3_int.jl """ function fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -437,11 +377,9 @@ function fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Arr end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3GetUInt64 + fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetUInt64() in FMIImport/FMI3_int.jl """ function fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -450,11 +388,9 @@ function fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3GetUInt64! + fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + +Wrapper for fmi3GetUInt64!() in FMIImport/FMI3_int.jl """ function fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -463,11 +399,9 @@ function fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3SetUInt64 + fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + +Wrapper for fmi3SetUInt64() in FMIImport/FMI3_int.jl """ function fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -476,11 +410,9 @@ function fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Boolean variables. + fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) -For more information call ?fmi3GetBoolean +Wrapper for fmi3GetBoolean() in FMIImport/FMI3_int.jl """ function fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -489,11 +421,9 @@ function fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) -Get the values of an array of fmi3Boolean variables. - -For more information call ?fmi3GetBoolean! +Wrapper for fmi3GetBoolean!() in FMIImport/FMI3_int.jl """ function fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -502,11 +432,9 @@ function fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{ end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Boolean variables. + fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) -For more information call ?fmi3SetBoolean +Wrapper for fmi3SetBoolean!() in FMIImport/FMI3_int.jl """ function fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -515,11 +443,9 @@ function fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3String variables. - -For more information call ?fmi3GetString + fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetString() in FMIImport/FMI3_int.jl """ function fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -528,11 +454,9 @@ function fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3String variables. - -For more information call ?fmi3GetString! + fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + +Wrapper for fmi3GetString!() in FMIImport/FMI3_int.jl """ function fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -541,11 +465,9 @@ function fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3String variables. - -For more information call ?fmi3SetString + fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + +Wrapper for fmi3SetString() in FMIImport/FMI3_int.jl """ function fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -554,11 +476,9 @@ function fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Binary variables. - -For more information call ?fmi3GetBinary + fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetBinary() in FMIImport/FMI3_int.jl """ function fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -567,11 +487,9 @@ function fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Binary variables. - -For more information call ?fmi3GetBinary! + fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + +Wrapper for fmi3GetBinary!() in FMIImport/FMI3_int.jl """ function fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -580,11 +498,9 @@ function fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{A end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Binary variables. - -For more information call ?fmi3SetBinary + fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + +Wrapper for fmi3SetBinary() in FMIImport/FMI3_int.jl """ function fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, valueSizes::Union{Array{Csize_t}, Csize_t}, values::Union{Array{fmi3Binary}, fmi3Binary}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -593,11 +509,9 @@ function fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, valueSizes::Unio end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Clock variables. - -For more information call ?fmi3GetClock + fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetClock() in FMIImport/FMI3_int.jl """ function fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -606,11 +520,9 @@ function fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Clock variables. - -For more information call ?fmi3GetClock! + fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + +Wrapper for fmi3GetClock!() in FMIImport/FMI3_int.jl """ function fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -619,11 +531,9 @@ function fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Ar end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Clock variables. - -For more information call ?fmi3SetClock + fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + +Wrapper for fmi3SetClock() in FMIImport/FMI3_int.jl """ function fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -632,11 +542,9 @@ function fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Arr end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State + fmi3GetFMUstate(fmu::FMU3) -Get the pointer to the current FMU state. - -For more information call ?fmi3GetFMUState +Wrapper for fmi3GetFMUstate() in FMIImport/FMI3_int.jl """ function fmi3GetFMUState(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -645,11 +553,9 @@ function fmi3GetFMUState(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Set the FMU to the given fmi3FMUstate. + fmi3SetFMUstate(fmu::FMU3,state::fmi3FMUState) -For more information call ?fmi3SetFMUState +Wrapper for fmi3SetFMUstate() in FMIImport/FMI3_c.jl """ function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -658,26 +564,20 @@ function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) end """ -function fmi3FreeFMUState(c::fmi3Component, FMUstate::Ref{fmi3FMUState}) + fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) -Free the allocated memory for the FMU state. - -For more information call ?fmi3FreeFMUState +Wrapper for fmi3FreeFMUState() in FMIImport/FMI3_int.jl """ function fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - stateRef = Ref(state) - fmi3FreeFMUState(fmu.instances[end], stateRef) - state = stateRef[] + fmi3FreeFMUState(fmu.instances[end], state) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Returns the size of a byte vector the FMU can be stored in. + fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) -For more information call ?fmi3SerzializedFMUStateSize +Wrapper for fmi3SerializedFMUStateSize() in FMIImport/FMI3_int.jl """ function fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -686,11 +586,9 @@ function fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Serialize the data in the FMU state pointer. + fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) -For more information call ?fmi3SerializeFMUState +Wrapper for fmi3SerializeFMUState() in FMIImport/FMI3_int.jl """ function fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -699,11 +597,9 @@ function fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State + fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) -Deserialize the data in the serializedState fmi3Byte field. - -For more information call ?fmi3DeSerializeFMUState +Wrapper for fmi3DeSerializeFMUState() in FMIImport/FMI3_int.jl """ function fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -712,11 +608,9 @@ function fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives. + fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::fmi3Float64 = 1.0)) -For more information call ?fmi3GetDirectionalDerivative +Wrapper for fmi3GetDirectionalDerivative() in FMIImport/FMI3_int.jl """ function fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::fmi3ValueReference, @@ -728,11 +622,9 @@ function fmi3GetDirectionalDerivative(fmu::FMU3, end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) -Retrieves directional derivatives. - -For more information call ?fmi3GetDirectionalDerivative +Wrapper for fmi3GetDirectionalDerivative() in FMIImport/FMI3_int.jl """ function fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::Array{fmi3ValueReference}, @@ -744,11 +636,9 @@ function fmi3GetDirectionalDerivative(fmu::FMU3, end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives in-place. - -For more information call ?fmi3GetDirectionalDerivative + fmi3GetDirectionalDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, knowns::Array{fmi3ValueReference}, sensitivity::Array{fmi3Float64}, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + +Wrapper for fmi3GetDirectionalDerivative!() in FMIImport/FMI3_int.jl """ function fmi3GetDirectionalDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, @@ -761,11 +651,9 @@ function fmi3GetDirectionalDerivative!(fmu::FMU3, end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. + fmi3GetAdjointDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::fmi3Float64 = 1.0)) -For more information call ?fmi3GetAdjointDerivative +Wrapper for fmi3GetAdjointDerivative() in FMIImport/FMI3_int.jl """ function fmi3GetAdjointDerivative(fmu::FMU3, unknowns::fmi3ValueReference, @@ -778,11 +666,9 @@ function fmi3GetAdjointDerivative(fmu::FMU3, end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives + fmi3GetAdjointDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative +Wrapper for fmi3GetAdjointDerivative() in FMIImport/FMI3_int.jl """ function fmi3GetAdjointDerivative(fmu::FMU3, unknowns::Array{fmi3ValueReference}, @@ -795,11 +681,9 @@ function fmi3GetAdjointDerivative(fmu::FMU3, end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative + fmi3GetAdjointDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, knowns::Array{fmi3ValueReference}, sensitivity::Array{fmi3Float64}, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + +Wrapper for fmi3GetAdjointDerivative!() in FMIImport/FMI3_int.jl """ function fmi3GetAdjointDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, @@ -812,14 +696,9 @@ function fmi3GetAdjointDerivative!(fmu::FMU3, fmi3GetAdjointDerivative!(fmu.instances[end], unknowns, knowns, sensitivity, seed) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs - -Retrieves the n-th derivative of output values. - -vr defines the value references of the variables -the array order specifies the corresponding order of derivation of the variables - -For more information call ?fmi3GetOutputDerivatives + fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) + +Wrapper for fmi3GetOutputDerivatives() in FMIImport/FMI3_int.jl """ function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -828,14 +707,9 @@ function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs - -Retrieves the n-th derivative of output values. - -vr defines the value references of the variables -the array order specifies the corresponding order of derivation of the variables - -For more information call ?fmi3GetOutputDerivatives + fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Integer) + +Wrapper for fmi3GetOutputDerivatives() in FMIImport/FMI3_int.jl """ function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReference, order::Integer) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -844,10 +718,9 @@ function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReference, order::Inte end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -If the importer needs to change structural parameters, it must move the FMU into Configuration Mode using fmi3EnterConfigurationMode. -For more information call ?fmi3EnterConfigurationMode + fmi3EnterConfigurationMode(fmu::FMU3) + +Wrapper for fmi3EnterConfigurationMode() in FMIImport/FMI3_c.jl """ function fmi3EnterConfigurationMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -856,11 +729,9 @@ function fmi3EnterConfigurationMode(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -This function returns the number of continuous states. -This function can only be called in Model Exchange. -For more information call ?fmi3GetNumberOfContinuousStates + fmi3GetNumberOfContinuousStates(fmu::FMU3) + +Wrapper for fmi3GetNumberOfContinuousStates() in FMIImport/FMI3_c.jl """ function fmi3GetNumberOfContinuousStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -869,11 +740,9 @@ function fmi3GetNumberOfContinuousStates(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated + fmi3GetNumberOfEventIndicators(fmu::FMU3) -This function returns the number of event indicators. -This function can only be called in Model Exchange. -For more information call ?fmi3GetNumberOfEventIndicators +Wrapper for fmi3GetNumberOfEventIndicators() in FMIImport/FMI3_c.jl """ function fmi3GetNumberOfEventIndicators(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -882,10 +751,9 @@ function fmi3GetNumberOfEventIndicators(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables - -The number of dependencies of a given variable, which may change if structural parameters are changed, can be retrieved by calling the following function: -For more information call ?fmi3GetNumberOfVariableDependencies + fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) + +Wrapper for fmi3GetNumberOfVariableDependencies() in FMIImport/FMI3_c.jl """ function fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -894,10 +762,9 @@ function fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueRefer end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode + fmi3GetContinuousStates(fmu::FMU3) -Return the states at the current time instant. -For more information call ?fmi3GetContinuousStates +Wrapper for fmi3GetContinuousStates() in FMIImport/FMI3_c.jl """ function fmi3GetContinuousStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -906,10 +773,9 @@ function fmi3GetContinuousStates(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables + fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) -The dependencies (of type dependenciesKind) can be retrieved by calling the function fmi3GetVariableDependencies. -For more information call ?fmi3GetVariableDependencies +Wrapper for fmi3GetVariableDependencies() in FMIImport/FMI3_c.jl """ function fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -918,11 +784,9 @@ function fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, St end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -Return the nominal values of the continuous states. + fmi3GetNominalsOfContinuousStates(fmu::FMU3) -For more information call ?fmi3GetNominalsOfContinuousStates +Wrapper for fmi3GetNominalsOfContinuousStates() in FMIImport/FMI3_c.jl """ function fmi3GetNominalsOfContinuousStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -931,12 +795,9 @@ function fmi3GetNominalsOfContinuousStates(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode +fmi3EvaluateDiscreteStates(fmu::FMU3) -This function is called to trigger the evaluation of fdisc to compute the current values of discrete states from previous values. -The FMU signals the support of fmi3EvaluateDiscreteStates via the capability flag providesEvaluateDiscreteStates. - -For more information call ?fmi3EvaluateDiscreteStates +Wrapper for fmi3EvaluateDiscreteStates() in FMIImport/FMI3_c.jl """ function fmi3EvaluateDiscreteStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -945,11 +806,9 @@ function fmi3EvaluateDiscreteStates(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -This function is called to signal a converged solution at the current super-dense time instant. fmi3UpdateDiscreteStates must be called at least once per super-dense time instant. + fmi3UpdateDiscreteStates(fmu::FMU3) -For more information call ?fmi3UpdateDiscreteStates +Wrapper for fmi3UpdateDiscreteStates() in FMIImport/FMI3_c.jl """ function fmi3UpdateDiscreteStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -958,11 +817,9 @@ function fmi3UpdateDiscreteStates(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -The model enters Continuous-Time Mode. + fmi3EnterContinuousTimeMode(fmu::FMU3) -For more information call ?fmi3EnterContinuousTimeMode +Wrapper for fmi3EnterContinuousTimeMode() in FMIImport/FMI3_c.jl """ function fmi3EnterContinuousTimeMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -971,11 +828,9 @@ function fmi3EnterContinuousTimeMode(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode + fmi3EnterStepMode(fmu::FMU3) -This function must be called to change from Event Mode into Step Mode in Co-Simulation. - -For more information call ?fmi3EnterStepMode +Wrapper for fmi3EnterStepMode() in FMIImport/FMI3_c.jl """ function fmi3EnterStepMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -984,11 +839,9 @@ function fmi3EnterStepMode(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 2.3.6. State: Configuration Mode - -Exits the Configuration Mode and returns to state Instantiated. + fmi3ExitConfigurationMode(fmu::FMU3) -For more information call ?fmi3ExitConfigurationMode +Wrapper for fmi3ExitConfigurationMode() in FMIImport/FMI3_c.jl """ function fmi3ExitConfigurationMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -997,11 +850,9 @@ function fmi3ExitConfigurationMode(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + fmi3SetTime(fmu::FMU3, time::Real) -Set independent variable time and reinitialize chaching of variables that depend on time. - -For more information call ?fmi3SetTime +Wrapper for fmi3SetTime() in FMIImport/FMI3_c.jl """ function fmi3SetTime(fmu::FMU3, time::Real) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -1011,11 +862,9 @@ function fmi3SetTime(fmu::FMU3, time::Real) end """ -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Set a new (continuous) state vector and reinitialize chaching of variables that depend on states. + fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) -For more information call ?fmi3SetContinuousStates +Wrapper for fmi3SetContinuousStates() in FMIImport/FMI3_c.jl """ function fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -1026,11 +875,9 @@ function fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float end """ -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode +fmi3GetContinuousStateDerivatives(fmu::FMU3) -Compute state derivatives at the current time instant and for the current states. - -For more information call ?fmi3GetContinuousStateDerivatives +Wrapper for fmi3GetContinuousStateDerivatives() in FMIImport/FMI3_c.jl """ function fmi3GetContinuousStateDerivatives(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -1039,11 +886,9 @@ function fmi3GetContinuousStateDerivatives(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Returns the event indicators of the FMU. + fmi3GetEventIndicators(fmu::FMU3) -For more information call ?fmi3GetEventIndicators +Wrapper for fmi3GetEventIndicators() in FMIImport/FMI3_c.jl """ function fmi3GetEventIndicators(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -1052,13 +897,9 @@ function fmi3GetEventIndicators(fmu::FMU3) end """ -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -This function must be called by the environment after every completed step -If enterEventMode == fmi3True, the event mode must be entered -If terminateSimulation == fmi3True, the simulation shall be terminated +fmi3CompletedIntegratorStep(fmu::FMU3, noSetFMUStatePriorToCurrentPoint::fmi3Boolean) -For more information call ?fmi3CompletedIntegratorStep +Wrapper for fmi3CompletedIntegratorStep() in FMIImport/FMI3_c.jl """ function fmi3CompletedIntegratorStep(fmu::FMU3, noSetFMUStatePriorToCurrentPoint::fmi3Boolean) @@ -1068,11 +909,9 @@ function fmi3CompletedIntegratorStep(fmu::FMU3, end """ -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode + fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) -The model enters Event Mode. - -For more information call ?fmi3EnterEventMode +Wrapper for fmi3EnterEventMode() in FMIImport/FMI3_c.jl """ function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -1081,11 +920,9 @@ function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsF end """ -Source: FMISpec3.0, Version D5ef1c1: 4.2.1. State: Step Mode - -The computation of a time step is started. + fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) -For more information call ?fmi3DoStep +Wrapper for fmi3DoStep() in FMIImport/FMI3_c.jl """ function fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -1101,8 +938,12 @@ function fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationSte lastSuccessfulTime = reflastSuccessfulTime[] end +#additional """ -Starts a simulation of the fmu instance for the matching fmu type. If both types are available, CS is preferred over ME. + fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; + recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + +Wrapper for fmi3Simulate() in FMI/FMI3_sim.jl """ function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) @@ -1112,7 +953,10 @@ function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; recordValues=recordValues, saveat=saveat, setup=setup) end """ -Starts a simulation of a FMU in CS-mode. +fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; +recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + +Wrapper for fmi3SimulateCS() in FMI/FMI3_sim.jl """ function fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) @@ -1123,7 +967,9 @@ function fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; end """ -Starts a simulation of a FMU in ME-mode. + fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) + +Wrapper for fmi3SimulateME() in FMI/FMI3_sim.jl """ function fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] @@ -1132,9 +978,9 @@ function fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) end """ -Returns the start/default value for a given value reference. - -TODO: Add this command in the documentation. + fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetStartValue() in FMIImport/FMI3_c.jl """ function fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] From 4cee313a8e4311cefee54333a8087f3fdc881d02 Mon Sep 17 00:00:00 2001 From: TT Date: Wed, 8 Jun 2022 12:21:49 +0200 Subject: [PATCH 10/41] optimized simulation calling order --- docs/src/features.md | 29 ++++++++++++++++++++++------- src/FMI2_sim.jl | 16 ++++++++-------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/docs/src/features.md b/docs/src/features.md index 5ea19b00..afab70f8 100644 --- a/docs/src/features.md +++ b/docs/src/features.md @@ -7,17 +7,27 @@ Not all FMUs support all features they should according to the FMI-standard, so This configuration is also respected by *FMIFlux.jl*. The content of the execution configuration may change in future (together with new or deprecated features of linked libraries), but the most important core features will be kept over time. Because not all users need the full potential of this configuration tool, there are three presets given: -- `myFMU.executionConfig = FMU_EXECUTION_CONFIGURATION_NO_RESET` is the default operation mode for FMUs. FMUs are not reset via `fmi2Reset`, but new instantiated for every simulation run (or training step). This is not the most efficient way, but many FMU have problems with resetting. -- `myFMU.executionConfig = FMU_EXECUTION_CONFIGURATION_RESET` is faster for well-implemented FMUs, but needs a fully working `fmi2Reset`-function. So if you know you have a fully working `fmi2Reset`, you may be faster with that option. -- `myFMU.executionConfig = FMU_EXECUTION_CONFIGURATION_NO_FREEING` should only be the very last choise. If your FMU neither supports `fmi2Reset` nor a proper `fmi2FreeInstance`, you could use this configuration as a last way out. Keep in mind, that new FMU instances are allocated but not freed, as long as your Julia instance is running (memory leak). In general, the amount of leaked memory is small, but you need to know what you are doing, if you do thousands or ten-thousands of simulation runs with such a FMU. +- `myFMU.executionConfig = FMU2_EXECUTION_CONFIGURATION_NO_RESET` is the default operation mode for FMUs. FMUs are not reset via `fmi2Reset`, but new instantiated for every simulation run (or training step). This is not the most efficient way, but many FMUs have problems with resetting. +- `myFMU.executionConfig = FMU2_EXECUTION_CONFIGURATION_RESET` is faster for well-implemented FMUs, but needs a fully working `fmi2Reset`-function. So if you know you have a fully working `fmi2Reset`, you may be faster with that option. +- `myFMU.executionConfig = FMU2_EXECUTION_CONFIGURATION_NO_FREEING` should only be the very last choise. If your FMU neither supports `fmi2Reset` nor a proper `fmi2FreeInstance`, you could use this configuration as a last way out. Keep in mind, that new FMU instances are allocated but not freed, as long as your Julia instance is running (memory leak). In general, the amount of leaked memory is small, but you need to know what you are doing, if you do thousands or ten-thousands of simulation runs with such a FMU. + +## Debugging / Logging +Many FMUs support for printing debugging messages. To force message printing, you can use the keyword `logginOn=true` either ... +- in the call `fmiInstantiate`, for example `fmiInstantiate(myFMU; loggingOn=true)` or +- as part of the `executionConfig`, for example `myFMU.executionConfig.loggingOn=true` +You can further control which message types - like `OK`, `Warning`, `Discard`, `Error`, `Fatal`, `Pending` - should be logged by using the keywords `logStatus{TYPE}=true` as part of `fmiInstantiate` or the execution configuration. By default, all are activated. +If the FMU uses a variadic callback function for messages (this is not supported by Julia at this time), you may need to activate external callbacks with the keyword `externalCallbacks=true` either ... +- in the call `fmiInstantiate`, for example `fmiInstantiate(myFMU; loggingOn=true, externalCallbacks=true)` or +- as part of the `executionConfig`, for example `myFMU.executionConfig.loggingOn=true; myFMU.executionConfig.externalCallbacks=true` +Note, that external callbacks are currently only supported on windows. ## Model variable identification *FMI.jl* offers multiple ways to retrieve your model variables. Any function that accepts a variable identifier can handle the following argument types: - `UInt32` or `fmi2ValueReference` for example `1610612742` or `0x16000001`: This is the most performant way of passing a variable identifier, but you need to know the *value reference* (you can determine them by having a look in the `modelDescription.xml`). - `Array{UInt32}` or `Array{fmi2ValueReference}` for example `[1610612742, 1610612743]` or `[0x16000001, 0x16000002]`: This is the most performant way of passing multiple variable identifiers, but you need to know the *value references*. - `String` for example `"ball.s"`: This is the most intuitive way, because you might already know the variable name from your modelling environment or model documentation. -- `Array{String]` for example `["ball.s", "der(ball.s)"]`: This is the most intuitive way, because you might already know the variable names from your modelling environment or model documentation. -- `Symbol` for example `:states`: There are multiple symbol wildcards for interesting variable groups like `:all`, `:none`, `:states`, `:derivatives`, `:inputs` and `:outputs`. +- `Array{String}` for example `["ball.s", "der(ball.s)"]`: This is the most intuitive way for multiple variable identifiers, because you might already know the variable names from your modelling environment or model documentation. +- `Symbol` for example `:states`: There are multiple symbol-wildcards for interesting variable groups like `:all`, `:none`, `:states`, `:derivatives`, `:inputs` and `:outputs`. - `nothing`: If you don't want to record anything (same as `:none`) ## Event handling @@ -37,14 +47,19 @@ Because many FMUs don't support `startTime != 0.0` and will throw an error or wa If you don't want this feature (maybe because you are simulating time-dependent systems), you may use the execution configuration `myFMU.executionConfig.autoTimeShift=false` while providing a `startTime != 0.0`. ## Performance -Many commands in *FMI.jl* are available in in-place and out-of-place semantics. Of course, in-place-calls are faster, because they don't need to allocate new memory at every call (for the return values). +**In- and Out-of-Place:** Many commands in *FMI.jl* are available in in-place and out-of-place semantics. Of course, in-place-calls are faster, because they don't need to allocate new memory at every call (for the return values). So if you have an eye on performance (or *must* have), a good starting point is to substitute out-of-place- with in-place-calls. Typical improvements are: - `valueArray = fmi2GetReal(args...)` -> `fmi2GetReal!(args..., valueArray)` - `valueArray = fmi2GetDerivatives(args...)` -> `fmi2GetDerivatives!(args..., valueArray)` - `valueArray = fmi2NewDiscreteStates(args...)` -> `fmi2NewDiscreteStates!(args..., valueArray)` Of course, you have to use the same piece of memory (to write your return values in) for multiple calls - otherwise there will be no improvement because the number of allocations stays the same. +**Views:** You can use [array-views](https://docs.julialang.org/en/v1/base/arrays/#Views-(SubArrays-and-other-view-types)) instead of array-slices as input for in-place-functions, which further reduces memory allocations. + ## Watch your progress When simulating FMUs with *FMI.jl*, a progress meter is shown per default. You can control the appearance via the keyword argument `showProgress` for `fmiSimulate`, `fmiSimulateME` and `fmiSimulateCS`. Progress meters are also available for *FMIFlux.jl*, but deactivated by default (during training, this can be a bit too much). When evaluating a NeuralFMU, you can use the same keyword with `showProgress=true` to show a progress bar during training, too. -The simulation trajectory (also called the *solution* of your FMU's ODE system) can be plotted using `fmiPlot(myFMU, solution)`, all axis will be labeled automatically. \ No newline at end of file +The simulation trajectory (also called the *solution* of your FMU's ODE system) can be plotted using `fmiPlot(myFMU, solution)`, all axis will be labeled automatically. + +## Parallelization +A native integrated support for multi-threaded and multi-process FMU-simulation will be deployed soon. \ No newline at end of file diff --git a/src/FMI2_sim.jl b/src/FMI2_sim.jl index b25694bf..06cf620d 100644 --- a/src/FMI2_sim.jl +++ b/src/FMI2_sim.jl @@ -514,6 +514,12 @@ function prepareFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, instantiate::Un @assert retcode == fmi2StatusOK "fmi2Simulate(...): Reset failed with return code $(retcode)." end + # enter setup (hard) + if setup + retcode = fmi2SetupExperiment(c, t_start, t_stop; tolerance=tolerance) + @assert retcode == fmi2StatusOK "fmi2Simulate(...): Setting up experiment failed with return code $(retcode)." + end + # parameters if parameters !== nothing retcodes = fmi2Set(c, collect(keys(parameters)), collect(values(parameters)) ) @@ -526,17 +532,11 @@ function prepareFMU(fmu::FMU2, c::Union{Nothing, FMU2Component}, instantiate::Un @assert all(retcodes .== fmi2StatusOK) "fmi2Simulate(...): Setting initial inputs failed with return code $(retcode)." end - # enter setup (hard) + # exit setup (hard) if setup - retcode = fmi2SetupExperiment(c, t_start, t_stop; tolerance=tolerance) - @assert retcode == fmi2StatusOK "fmi2Simulate(...): Setting up experiment failed with return code $(retcode)." - retcode = fmi2EnterInitializationMode(c) @assert retcode == fmi2StatusOK "fmi2Simulate(...): Entering initialization mode failed with return code $(retcode)." - end - - # exit setup (hard) - if setup + retcode = fmi2ExitInitializationMode(c) @assert retcode == fmi2StatusOK "fmi2Simulate(...): Exiting initialization mode failed with return code $(retcode)." end From b701ff0bfb7528f06597525b8ee17360e3212e06 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Sat, 18 Jun 2022 14:25:54 +0000 Subject: [PATCH 11/41] Jupyter nbconvert synch - modified, paired .ipynb files --- docs/src/examples/multiprocessing.md | 99 ++++++++------- docs/src/examples/multithreading.md | 56 ++++----- example/multiprocessing.ipynb | 179 ++++++++++++++------------- example/multithreading.ipynb | 128 +++++++++---------- 4 files changed, 238 insertions(+), 224 deletions(-) diff --git a/docs/src/examples/multiprocessing.md b/docs/src/examples/multiprocessing.md index 61656784..365cdee4 100644 --- a/docs/src/examples/multiprocessing.md +++ b/docs/src/examples/multiprocessing.md @@ -90,10 +90,10 @@ workers() # @everywhere println(Threads.nthreads()) ``` - From worker 3: Hello World! + Hello World! From worker 2: Hello World! From worker 4: Hello World! - Hello World! + From worker 3: Hello World! From worker 5: Hello World! @@ -115,22 +115,22 @@ input_values = collect(collect.(eachrow(rand(batchSize,2)))) 16-element Vector{Vector{Float64}}: - [0.8522478954672708, 0.7209431226036078] - [0.909306253617912, 0.6209402039669427] - [0.4596043790366431, 0.2389289971087898] - [0.4934930898692784, 0.8535888352523144] - [0.9008166213933464, 0.48097066683100986] - [0.30695689796078574, 0.8999444231606255] - [0.5676033936598277, 0.0170782917662895] - [0.43299006096393633, 0.6018253815343202] - [0.8863999765881179, 0.5879607966583695] - [0.9250498940640433, 0.676688143062196] - [0.5927221115688299, 0.13661645859930105] - [0.5274125466018458, 0.6019662513572075] - [0.7212113914423361, 0.6184174840746639] - [0.5904677676104344, 0.9526791253940541] - [0.7887765751716826, 0.32324579460992675] - [0.867048815207933, 0.728198232394913] + [0.053272555584304104, 0.45774751559489646] + [0.5896778258750763, 0.12435199368996086] + [0.5651662129022856, 0.8764873667695812] + [0.6176612662918868, 0.2785804850450695] + [0.9274233385552415, 0.38275426899967724] + [0.46094177953642124, 0.6554519159504497] + [0.73421590884579, 0.28177572874256906] + [0.5575198504784948, 0.3212214708846175] + [0.271126562512229, 0.6499895887749823] + [0.5289045741655536, 0.4873381265273107] + [0.8565770844036877, 0.2312687408548988] + [0.06332369482582334, 0.44807066874864065] + [0.08611017776660712, 0.960898209225902] + [0.3191189843443898, 0.30014344015893846] + [0.028884098958377402, 0.5285860311385517] + [0.7282727650515579, 0.7584435212215901] @@ -153,23 +153,23 @@ For Distributed we need to embed the FMU into its own `module`. This prevents Di end ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ywfEtU/SpringPendulum1D`. + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ywfEtU/SpringPendulum1D/resources` + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources` └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_WvJUQ4/SpringPendulum1D`. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_kty5Tc/SpringPendulum1D`. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ElhvF8/SpringPendulum1D`. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_WvJUQ4/SpringPendulum1D/resources` + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`. + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_kty5Tc/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ElhvF8/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_RvaFkX/SpringPendulum1D`. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RvaFkX/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. @@ -193,16 +193,16 @@ Running a single evaluation is pretty quick, therefore the speed can be better t - BenchmarkTools.Trial: 16 samples with 1 evaluation. - Range (min … max): 301.517 ms … 343.653 ms ┊ GC (min … max): 6.30% … 8.37% - Time (median): 325.148 ms ┊ GC (median): 5.92% - Time (mean ± σ): 324.977 ms ±  11.601 ms ┊ GC (mean ± σ): 6.39% ± 1.09% + BenchmarkTools.Trial: 17 samples with 1 evaluation. + Range (min … max): 304.291 ms … 325.332 ms ┊ GC (min … max): 7.41% … 6.89% + Time (median): 307.274 ms ┊ GC (median): 7.37% + Time (mean ± σ): 309.397 ms ±  5.860 ms ┊ GC (mean ± σ): 7.94% ± 1.32% - ▁        ▁      ▁    ▁  ▁   ▁▁   ▁ ▁        ██     ▁▁       ▁  - █▁▁▁▁▁▁▁▁█▁▁▁▁▁▁█▁▁▁▁█▁▁█▁▁▁██▁▁▁█▁█▁▁▁▁▁▁▁▁██▁▁▁▁▁██▁▁▁▁▁▁▁█ ▁ - 302 ms Histogram: frequency by time 344 ms < + █▁▁ ▁█ ▁▁  █▁▁                   ▁ ▁ ▁                      ▁  + ███▁██▁██▁▁███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁█▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 304 ms Histogram: frequency by time 325 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002431. + Memory estimate: 146.80 MiB, allocs estimate: 3002433. @@ -221,9 +221,16 @@ println("Single Threaded") - BenchmarkTools.Trial: 1 sample with 1 evaluation. - Single result which took 5.128 s (6.62% GC) to evaluate, - with a memory estimate of 2.29 GiB, over 48038884 allocations. + BenchmarkTools.Trial: 2 samples with 1 evaluation. + Range (min … max): 4.966 s …  4.967 s ┊ GC (min … max): 8.58% … 8.12% + Time (median): 4.966 s ┊ GC (median): 8.35% + Time (mean ± σ): 4.966 s ± 1.039 ms ┊ GC (mean ± σ): 8.35% ± 0.33% + + █                                                      █  + █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 4.97 s Histogram: frequency by time 4.97 s < + + Memory estimate: 2.29 GiB, allocs estimate: 48038916. @@ -244,15 +251,15 @@ println("Multi Threaded") BenchmarkTools.Trial: 2 samples with 1 evaluation. - Range (min … max): 3.323 s …  3.367 s ┊ GC (min … max): 0.00% … 0.00% - Time (median): 3.345 s ┊ GC (median): 0.00% - Time (mean ± σ): 3.345 s ± 31.349 ms ┊ GC (mean ± σ): 0.00% ± 0.00% + Range (min … max): 3.069 s …  3.078 s ┊ GC (min … max): 0.00% … 0.00% + Time (median): 3.074 s ┊ GC (median): 0.00% + Time (mean ± σ): 3.074 s ± 6.467 ms ┊ GC (mean ± σ): 0.00% ± 0.00% - █                                                       █  - █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 3.32 s Histogram: frequency by time 3.37 s < + █                                                      █  + █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 3.07 s Histogram: frequency by time 3.08 s < - Memory estimate: 81.44 KiB, allocs estimate: 1198. + Memory estimate: 81.31 KiB, allocs estimate: 1192. diff --git a/docs/src/examples/multithreading.md b/docs/src/examples/multithreading.md index 47ce6dac..3f1d0979 100644 --- a/docs/src/examples/multithreading.md +++ b/docs/src/examples/multithreading.md @@ -94,7 +94,7 @@ input_values = collect(collect.(eachrow(rand(batchSize,2)))) 1-element Vector{Vector{Float64}}: - [0.7810829477429659, 0.42733298165721023] + [0.769193342919982, 0.5516183754569333] @@ -109,15 +109,15 @@ realFMU = fmiLoad("SpringPendulum1D", "Dymola", "2022x") realFMUBatch = [fmiLoad("SpringPendulum1D", "Dymola", "2022x") for _ in 1:batchSize] ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_AeQVGo/SpringPendulum1D`. + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AeQVGo/SpringPendulum1D/resources` + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources` └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_6YywFr/SpringPendulum1D`. + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_6YywFr/SpringPendulum1D/resources` + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources` └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 @@ -159,16 +159,16 @@ Running a single evaluation is pretty quick, therefore the speed can be better t - BenchmarkTools.Trial: 14 samples with 1 evaluation. - Range (min … max): 337.440 ms … 389.386 ms ┊ GC (min … max): 5.75% … 5.28% - Time (median): 372.244 ms ┊ GC (median): 5.52% - Time (mean ± σ): 368.214 ms ±  15.573 ms ┊ GC (mean ± σ): 5.91% ± 0.96% + BenchmarkTools.Trial: 15 samples with 1 evaluation. + Range (min … max): 337.943 ms … 357.340 ms ┊ GC (min … max): 7.03% … 6.55% + Time (median): 339.287 ms ┊ GC (median): 7.00% + Time (mean ± σ): 342.299 ms ±  5.982 ms ┊ GC (mean ± σ): 7.39% ± 1.12% - █              █ █    █ █  █          █   █ █   ██   █    █ █  - █▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁█▁▁▁▁█▁█▁▁█▁▁▁▁▁▁▁▁▁▁█▁▁▁█▁█▁▁▁██▁▁▁█▁▁▁▁█▁█ ▁ - 337 ms Histogram: frequency by time 389 ms < + ▃█                                                             + ██▇▇▇▇▁▁▇▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇ ▁ + 338 ms Histogram: frequency by time 357 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002431. + Memory estimate: 146.80 MiB, allocs estimate: 3002433. @@ -188,15 +188,15 @@ println("Single Threaded") BenchmarkTools.Trial: 15 samples with 1 evaluation. - Range (min … max): 340.025 ms … 386.317 ms ┊ GC (min … max): 6.05% … 5.51% - Time (median): 353.427 ms ┊ GC (median): 5.97% - Time (mean ± σ): 355.542 ms ±  12.557 ms ┊ GC (mean ± σ): 6.24% ± 1.07% + Range (min … max): 338.941 ms … 359.792 ms ┊ GC (min … max): 7.42% … 7.05% + Time (median): 340.880 ms ┊ GC (median): 7.45% + Time (mean ± σ): 343.682 ms ±  6.291 ms ┊ GC (mean ± σ): 7.89% ± 1.20% - █  ▁  ▁▁      ▁ ▁▁  ▁    ▁  ▁▁      █                       ▁  - █▁▁█▁▁██▁▁▁▁▁▁█▁██▁▁█▁▁▁▁█▁▁██▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 340 ms Histogram: frequency by time 386 ms < + █▁▁▁▁█  ▁▁▁    ▁                        ▁▁                  ▁  + ██████▁▁███▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 339 ms Histogram: frequency by time 360 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002434. + Memory estimate: 146.80 MiB, allocs estimate: 3002436. @@ -216,16 +216,16 @@ println("Multi Threaded") - BenchmarkTools.Trial: 16 samples with 1 evaluation. - Range (min … max): 304.578 ms … 342.615 ms ┊ GC (min … max): 7.13% … 6.47% - Time (median): 314.032 ms ┊ GC (median): 6.84% - Time (mean ± σ): 316.672 ms ±  10.042 ms ┊ GC (mean ± σ): 6.99% ± 0.78% + BenchmarkTools.Trial: 17 samples with 1 evaluation. + Range (min … max): 307.665 ms … 325.644 ms ┊ GC (min … max): 8.44% … 8.13% + Time (median): 308.448 ms ┊ GC (median): 8.55% + Time (mean ± σ): 310.319 ms ±  4.970 ms ┊ GC (mean ± σ): 8.72% ± 0.86% - ▁     █▁  ▁  ▁█▁ ▁   ▁▁█                           ▁        ▁  - █▁▁▁▁▁██▁▁█▁▁███▁█▁▁▁███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁█ ▁ - 305 ms Histogram: frequency by time 343 ms < + █ █ ▁   ▁                                                      + █▆█▆█▁▆▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆ ▁ + 308 ms Histogram: frequency by time 326 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002438. + Memory estimate: 146.80 MiB, allocs estimate: 3002440. diff --git a/example/multiprocessing.ipynb b/example/multiprocessing.ipynb index b0ead9a2..736d07d5 100644 --- a/example/multiprocessing.ipynb +++ b/example/multiprocessing.ipynb @@ -67,10 +67,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:29:32.352000Z", - "iopub.status.busy": "2022-06-10T09:29:31.633000Z", - "iopub.status.idle": "2022-06-10T09:29:44.600000Z", - "shell.execute_reply": "2022-06-10T09:29:44.571000Z" + "iopub.execute_input": "2022-06-18T14:20:33.662000Z", + "iopub.status.busy": "2022-06-18T14:20:32.980000Z", + "iopub.status.idle": "2022-06-18T14:20:45.287000Z", + "shell.execute_reply": "2022-06-18T14:20:45.259000Z" } }, "outputs": [ @@ -107,10 +107,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:29:44.603000Z", - "iopub.status.busy": "2022-06-10T09:29:44.603000Z", - "iopub.status.idle": "2022-06-10T09:30:32.194000Z", - "shell.execute_reply": "2022-06-10T09:30:32.193000Z" + "iopub.execute_input": "2022-06-18T14:20:45.290000Z", + "iopub.status.busy": "2022-06-18T14:20:45.289000Z", + "iopub.status.idle": "2022-06-18T14:21:31.517000Z", + "shell.execute_reply": "2022-06-18T14:21:31.517000Z" } }, "outputs": [], @@ -133,10 +133,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:32.394000Z", - "iopub.status.busy": "2022-06-10T09:30:32.197000Z", - "iopub.status.idle": "2022-06-10T09:30:32.491000Z", - "shell.execute_reply": "2022-06-10T09:30:32.490000Z" + "iopub.execute_input": "2022-06-18T14:21:31.917000Z", + "iopub.status.busy": "2022-06-18T14:21:31.520000Z", + "iopub.status.idle": "2022-06-18T14:21:32.071000Z", + "shell.execute_reply": "2022-06-18T14:21:32.071000Z" } }, "outputs": [ @@ -144,10 +144,10 @@ "name": "stdout", "output_type": "stream", "text": [ - " From worker 3:\tHello World!\n", + "Hello World!\n", " From worker 2:\tHello World!\n", " From worker 4:\tHello World!\n", - "Hello World!\n", + " From worker 3:\tHello World!\n", " From worker 5:\tHello World!\n" ] } @@ -179,10 +179,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:32.494000Z", - "iopub.status.busy": "2022-06-10T09:30:32.494000Z", - "iopub.status.idle": "2022-06-10T09:30:36.509000Z", - "shell.execute_reply": "2022-06-10T09:30:36.509000Z" + "iopub.execute_input": "2022-06-18T14:21:32.074000Z", + "iopub.status.busy": "2022-06-18T14:21:32.074000Z", + "iopub.status.idle": "2022-06-18T14:21:35.419000Z", + "shell.execute_reply": "2022-06-18T14:21:35.419000Z" } }, "outputs": [ @@ -190,22 +190,22 @@ "data": { "text/plain": [ "16-element Vector{Vector{Float64}}:\n", - " [0.8522478954672708, 0.7209431226036078]\n", - " [0.909306253617912, 0.6209402039669427]\n", - " [0.4596043790366431, 0.2389289971087898]\n", - " [0.4934930898692784, 0.8535888352523144]\n", - " [0.9008166213933464, 0.48097066683100986]\n", - " [0.30695689796078574, 0.8999444231606255]\n", - " [0.5676033936598277, 0.0170782917662895]\n", - " [0.43299006096393633, 0.6018253815343202]\n", - " [0.8863999765881179, 0.5879607966583695]\n", - " [0.9250498940640433, 0.676688143062196]\n", - " [0.5927221115688299, 0.13661645859930105]\n", - " [0.5274125466018458, 0.6019662513572075]\n", - " [0.7212113914423361, 0.6184174840746639]\n", - " [0.5904677676104344, 0.9526791253940541]\n", - " [0.7887765751716826, 0.32324579460992675]\n", - " [0.867048815207933, 0.728198232394913]" + " [0.053272555584304104, 0.45774751559489646]\n", + " [0.5896778258750763, 0.12435199368996086]\n", + " [0.5651662129022856, 0.8764873667695812]\n", + " [0.6176612662918868, 0.2785804850450695]\n", + " [0.9274233385552415, 0.38275426899967724]\n", + " [0.46094177953642124, 0.6554519159504497]\n", + " [0.73421590884579, 0.28177572874256906]\n", + " [0.5575198504784948, 0.3212214708846175]\n", + " [0.271126562512229, 0.6499895887749823]\n", + " [0.5289045741655536, 0.4873381265273107]\n", + " [0.8565770844036877, 0.2312687408548988]\n", + " [0.06332369482582334, 0.44807066874864065]\n", + " [0.08611017776660712, 0.960898209225902]\n", + " [0.3191189843443898, 0.30014344015893846]\n", + " [0.028884098958377402, 0.5285860311385517]\n", + " [0.7282727650515579, 0.7584435212215901]" ] }, "execution_count": 4, @@ -235,10 +235,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:36.519000Z", - "iopub.status.busy": "2022-06-10T09:30:36.518000Z", - "iopub.status.idle": "2022-06-10T09:30:49.331000Z", - "shell.execute_reply": "2022-06-10T09:30:49.331000Z" + "iopub.execute_input": "2022-06-18T14:21:35.423000Z", + "iopub.status.busy": "2022-06-18T14:21:35.422000Z", + "iopub.status.idle": "2022-06-18T14:21:47.166000Z", + "shell.execute_reply": "2022-06-18T14:21:47.166000Z" } }, "outputs": [ @@ -246,23 +246,23 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ywfEtU/SpringPendulum1D`.\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ywfEtU/SpringPendulum1D/resources`\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources`\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_WvJUQ4/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_kty5Tc/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ElhvF8/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_WvJUQ4/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_kty5Tc/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_ElhvF8/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_RvaFkX/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_RvaFkX/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n" ] } @@ -294,10 +294,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:49.333000Z", - "iopub.status.busy": "2022-06-10T09:30:49.333000Z", - "iopub.status.idle": "2022-06-10T09:30:49.493000Z", - "shell.execute_reply": "2022-06-10T09:30:49.493000Z" + "iopub.execute_input": "2022-06-18T14:21:47.169000Z", + "iopub.status.busy": "2022-06-18T14:21:47.169000Z", + "iopub.status.idle": "2022-06-18T14:21:47.459000Z", + "shell.execute_reply": "2022-06-18T14:21:47.458000Z" } }, "outputs": [], @@ -320,26 +320,26 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:49.496000Z", - "iopub.status.busy": "2022-06-10T09:30:49.496000Z", - "iopub.status.idle": "2022-06-10T09:31:25.888000Z", - "shell.execute_reply": "2022-06-10T09:31:25.888000Z" + "iopub.execute_input": "2022-06-18T14:21:47.461000Z", + "iopub.status.busy": "2022-06-18T14:21:47.461000Z", + "iopub.status.idle": "2022-06-18T14:22:23.804000Z", + "shell.execute_reply": "2022-06-18T14:22:23.804000Z" } }, "outputs": [ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 16 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m301.517 ms\u001b[22m\u001b[39m … \u001b[35m343.653 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m6.30% … 8.37%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m325.148 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m5.92%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m324.977 ms\u001b[22m\u001b[39m ± \u001b[32m 11.601 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.39% ± 1.09%\n", + "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m304.291 ms\u001b[22m\u001b[39m … \u001b[35m325.332 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.41% … 6.89%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m307.274 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.37%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m309.397 ms\u001b[22m\u001b[39m ± \u001b[32m 5.860 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.94% ± 1.32%\n", "\n", - " \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[34m▁\u001b[39m\u001b[32m \u001b[39m\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[34m█\u001b[39m\u001b[32m▁\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 302 ms\u001b[90m Histogram: frequency by time\u001b[39m 344 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\u001b[34m▁\u001b[39m\u001b[39m \u001b[39m \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 304 ms\u001b[90m Histogram: frequency by time\u001b[39m 325 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002431\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." ] }, "execution_count": 7, @@ -364,10 +364,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:31:25.895000Z", - "iopub.status.busy": "2022-06-10T09:31:25.894000Z", - "iopub.status.idle": "2022-06-10T09:31:49.051000Z", - "shell.execute_reply": "2022-06-10T09:31:49.051000Z" + "iopub.execute_input": "2022-06-18T14:22:23.808000Z", + "iopub.status.busy": "2022-06-18T14:22:23.807000Z", + "iopub.status.idle": "2022-06-18T14:23:01.441000Z", + "shell.execute_reply": "2022-06-18T14:23:01.440000Z" } }, "outputs": [ @@ -381,9 +381,16 @@ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 1 sample with 1 evaluation.\n", - " Single result which took \u001b[34m5.128 s\u001b[39m (6.62% GC) to evaluate,\n", - " with a memory estimate of \u001b[33m2.29 GiB\u001b[39m, over \u001b[33m48038884\u001b[39m allocations." + "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m4.966 s\u001b[22m\u001b[39m … \u001b[35m 4.967 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.58% … 8.12%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m4.966 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.35%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m4.966 s\u001b[22m\u001b[39m ± \u001b[32m1.039 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.35% ± 0.33%\n", + "\n", + " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", + " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 4.97 s\u001b[90m Histogram: frequency by time\u001b[39m 4.97 s \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m2.29 GiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m48038916\u001b[39m." ] }, "execution_count": 8, @@ -410,10 +417,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:31:49.055000Z", - "iopub.status.busy": "2022-06-10T09:31:49.055000Z", - "iopub.status.idle": "2022-06-10T09:32:55.782000Z", - "shell.execute_reply": "2022-06-10T09:32:55.781000Z" + "iopub.execute_input": "2022-06-18T14:23:01.444000Z", + "iopub.status.busy": "2022-06-18T14:23:01.444000Z", + "iopub.status.idle": "2022-06-18T14:24:04.804000Z", + "shell.execute_reply": "2022-06-18T14:24:04.804000Z" } }, "outputs": [ @@ -428,15 +435,15 @@ "data": { "text/plain": [ "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m3.323 s\u001b[22m\u001b[39m … \u001b[35m 3.367 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m3.345 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m3.345 s\u001b[22m\u001b[39m ± \u001b[32m31.349 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m0.00% ± 0.00%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m3.069 s\u001b[22m\u001b[39m … \u001b[35m 3.078 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m3.074 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m3.074 s\u001b[22m\u001b[39m ± \u001b[32m6.467 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m0.00% ± 0.00%\n", "\n", - " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", - " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 3.32 s\u001b[90m Histogram: frequency by time\u001b[39m 3.37 s \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", + " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 3.07 s\u001b[90m Histogram: frequency by time\u001b[39m 3.08 s \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m81.44 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m1198\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m81.31 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m1192\u001b[39m." ] }, "execution_count": 9, @@ -470,10 +477,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:32:55.785000Z", - "iopub.status.busy": "2022-06-10T09:32:55.785000Z", - "iopub.status.idle": "2022-06-10T09:32:55.922000Z", - "shell.execute_reply": "2022-06-10T09:32:55.922000Z" + "iopub.execute_input": "2022-06-18T14:24:04.807000Z", + "iopub.status.busy": "2022-06-18T14:24:04.807000Z", + "iopub.status.idle": "2022-06-18T14:24:04.974000Z", + "shell.execute_reply": "2022-06-18T14:24:04.974000Z" } }, "outputs": [], diff --git a/example/multithreading.ipynb b/example/multithreading.ipynb index 1d478bb4..7076dfb7 100644 --- a/example/multithreading.ipynb +++ b/example/multithreading.ipynb @@ -62,10 +62,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:06.584000Z", - "iopub.status.busy": "2022-06-10T09:33:05.835000Z", - "iopub.status.idle": "2022-06-10T09:33:21.452000Z", - "shell.execute_reply": "2022-06-10T09:33:21.370000Z" + "iopub.execute_input": "2022-06-18T14:24:15.415000Z", + "iopub.status.busy": "2022-06-18T14:24:14.716000Z", + "iopub.status.idle": "2022-06-18T14:24:29.648000Z", + "shell.execute_reply": "2022-06-18T14:24:29.574000Z" } }, "outputs": [], @@ -89,10 +89,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:21.660000Z", - "iopub.status.busy": "2022-06-10T09:33:21.456000Z", - "iopub.status.idle": "2022-06-10T09:33:22.514000Z", - "shell.execute_reply": "2022-06-10T09:33:22.514000Z" + "iopub.execute_input": "2022-06-18T14:24:29.989000Z", + "iopub.status.busy": "2022-06-18T14:24:29.651000Z", + "iopub.status.idle": "2022-06-18T14:24:30.845000Z", + "shell.execute_reply": "2022-06-18T14:24:30.845000Z" } }, "outputs": [ @@ -132,10 +132,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:22.520000Z", - "iopub.status.busy": "2022-06-10T09:33:22.520000Z", - "iopub.status.idle": "2022-06-10T09:33:26.459000Z", - "shell.execute_reply": "2022-06-10T09:33:26.459000Z" + "iopub.execute_input": "2022-06-18T14:24:30.849000Z", + "iopub.status.busy": "2022-06-18T14:24:30.849000Z", + "iopub.status.idle": "2022-06-18T14:24:34.809000Z", + "shell.execute_reply": "2022-06-18T14:24:34.809000Z" } }, "outputs": [ @@ -143,7 +143,7 @@ "data": { "text/plain": [ "1-element Vector{Vector{Float64}}:\n", - " [0.7810829477429659, 0.42733298165721023]" + " [0.769193342919982, 0.5516183754569333]" ] }, "execution_count": 3, @@ -177,10 +177,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:26.463000Z", - "iopub.status.busy": "2022-06-10T09:33:26.462000Z", - "iopub.status.idle": "2022-06-10T09:33:31.974000Z", - "shell.execute_reply": "2022-06-10T09:33:31.974000Z" + "iopub.execute_input": "2022-06-18T14:24:34.812000Z", + "iopub.status.busy": "2022-06-18T14:24:34.812000Z", + "iopub.status.idle": "2022-06-18T14:24:40.193000Z", + "shell.execute_reply": "2022-06-18T14:24:40.193000Z" } }, "outputs": [ @@ -188,15 +188,15 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_AeQVGo/SpringPendulum1D`.\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AeQVGo/SpringPendulum1D/resources`\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources`\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_6YywFr/SpringPendulum1D`.\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_6YywFr/SpringPendulum1D/resources`\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources`\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n" @@ -235,10 +235,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:31.978000Z", - "iopub.status.busy": "2022-06-10T09:33:31.977000Z", - "iopub.status.idle": "2022-06-10T09:33:32.656000Z", - "shell.execute_reply": "2022-06-10T09:33:32.656000Z" + "iopub.execute_input": "2022-06-18T14:24:40.198000Z", + "iopub.status.busy": "2022-06-18T14:24:40.197000Z", + "iopub.status.idle": "2022-06-18T14:24:40.840000Z", + "shell.execute_reply": "2022-06-18T14:24:40.839000Z" } }, "outputs": [ @@ -272,26 +272,26 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:32.660000Z", - "iopub.status.busy": "2022-06-10T09:33:32.660000Z", - "iopub.status.idle": "2022-06-10T09:34:08.088000Z", - "shell.execute_reply": "2022-06-10T09:34:08.088000Z" + "iopub.execute_input": "2022-06-18T14:24:40.843000Z", + "iopub.status.busy": "2022-06-18T14:24:40.843000Z", + "iopub.status.idle": "2022-06-18T14:25:15.703000Z", + "shell.execute_reply": "2022-06-18T14:25:15.703000Z" } }, "outputs": [ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 14 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m337.440 ms\u001b[22m\u001b[39m … \u001b[35m389.386 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m5.75% … 5.28%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m372.244 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m5.52%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m368.214 ms\u001b[22m\u001b[39m ± \u001b[32m 15.573 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m5.91% ± 0.96%\n", + "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m337.943 ms\u001b[22m\u001b[39m … \u001b[35m357.340 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.03% … 6.55%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m339.287 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m342.299 ms\u001b[22m\u001b[39m ± \u001b[32m 5.982 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.39% ± 1.12%\n", "\n", - " \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m█\u001b[34m \u001b[39m\u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m█\u001b[34m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 337 ms\u001b[90m Histogram: frequency by time\u001b[39m 389 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m▃\u001b[39m█\u001b[39m \u001b[34m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m▇\u001b[34m▇\u001b[39m\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m \u001b[39m▁\n", + " 338 ms\u001b[90m Histogram: frequency by time\u001b[39m 357 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002431\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." ] }, "execution_count": 6, @@ -316,10 +316,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:34:08.093000Z", - "iopub.status.busy": "2022-06-10T09:34:08.093000Z", - "iopub.status.idle": "2022-06-10T09:34:21.799000Z", - "shell.execute_reply": "2022-06-10T09:34:21.799000Z" + "iopub.execute_input": "2022-06-18T14:25:15.707000Z", + "iopub.status.busy": "2022-06-18T14:25:15.707000Z", + "iopub.status.idle": "2022-06-18T14:25:29.068000Z", + "shell.execute_reply": "2022-06-18T14:25:29.068000Z" } }, "outputs": [ @@ -334,15 +334,15 @@ "data": { "text/plain": [ "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m340.025 ms\u001b[22m\u001b[39m … \u001b[35m386.317 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m6.05% … 5.51%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m353.427 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m5.97%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m355.542 ms\u001b[22m\u001b[39m ± \u001b[32m 12.557 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.24% ± 1.07%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m338.941 ms\u001b[22m\u001b[39m … \u001b[35m359.792 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.42% … 7.05%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m340.880 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.45%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m343.682 ms\u001b[22m\u001b[39m ± \u001b[32m 6.291 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.89% ± 1.20%\n", "\n", - " \u001b[39m█\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[34m▁\u001b[39m\u001b[39m \u001b[39m \u001b[32m▁\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[32m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 340 ms\u001b[90m Histogram: frequency by time\u001b[39m 386 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 339 ms\u001b[90m Histogram: frequency by time\u001b[39m 360 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002434\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002436\u001b[39m." ] }, "execution_count": 7, @@ -369,10 +369,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:34:21.806000Z", - "iopub.status.busy": "2022-06-10T09:34:21.805000Z", - "iopub.status.idle": "2022-06-10T09:34:38.654000Z", - "shell.execute_reply": "2022-06-10T09:34:38.654000Z" + "iopub.execute_input": "2022-06-18T14:25:29.072000Z", + "iopub.status.busy": "2022-06-18T14:25:29.072000Z", + "iopub.status.idle": "2022-06-18T14:25:46.159000Z", + "shell.execute_reply": "2022-06-18T14:25:46.159000Z" } }, "outputs": [ @@ -386,16 +386,16 @@ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 16 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m304.578 ms\u001b[22m\u001b[39m … \u001b[35m342.615 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.13% … 6.47%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m314.032 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m6.84%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m316.672 ms\u001b[22m\u001b[39m ± \u001b[32m 10.042 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.99% ± 0.78%\n", + "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m307.665 ms\u001b[22m\u001b[39m … \u001b[35m325.644 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.44% … 8.13%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m308.448 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.55%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m310.319 ms\u001b[22m\u001b[39m ± \u001b[32m 4.970 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.72% ± 0.86%\n", "\n", - " \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 305 ms\u001b[90m Histogram: frequency by time\u001b[39m 343 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m█\u001b[39m \u001b[34m█\u001b[39m\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m▆\u001b[34m█\u001b[39m\u001b[39m▆\u001b[39m█\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m█\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m \u001b[39m▁\n", + " 308 ms\u001b[90m Histogram: frequency by time\u001b[39m 326 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002438\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002440\u001b[39m." ] }, "execution_count": 8, @@ -429,10 +429,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:34:38.658000Z", - "iopub.status.busy": "2022-06-10T09:34:38.658000Z", - "iopub.status.idle": "2022-06-10T09:34:39.762000Z", - "shell.execute_reply": "2022-06-10T09:34:39.762000Z" + "iopub.execute_input": "2022-06-18T14:25:46.162000Z", + "iopub.status.busy": "2022-06-18T14:25:46.162000Z", + "iopub.status.idle": "2022-06-18T14:25:47.297000Z", + "shell.execute_reply": "2022-06-18T14:25:47.296000Z" } }, "outputs": [ From 69c3146485e5062e65f5a803abf9c44ad00f93cc Mon Sep 17 00:00:00 2001 From: JoKircher Date: Sat, 18 Jun 2022 17:36:11 +0200 Subject: [PATCH 12/41] added FMI3_JLD2.jl --- src/FMI3_JLD2.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/FMI3_JLD2.jl diff --git a/src/FMI3_JLD2.jl b/src/FMI3_JLD2.jl new file mode 100644 index 00000000..c93ba612 --- /dev/null +++ b/src/FMI3_JLD2.jl @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using FMIImport: FMU3Solution + +""" +Saves a FMU3Solution for later use. +""" +function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") + return JLD2.save(filepath, Dict(keyword=>solution)) +end + +""" +Loads a FMU3Solution. Returns a previously saved `FMU3Solution`. +""" +function fmiLoadSolution(filepath::AbstractString; keyword="solution") + return JLD2.load(filepath, keyword) +end \ No newline at end of file From 0e9a7f97a832e0cb20deab83e131d12cea5bd262 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Sat, 18 Jun 2022 18:12:23 +0200 Subject: [PATCH 13/41] WIP: fmi3 refactor --- src/FMI.jl | 221 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 180 insertions(+), 41 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 36258366..8be46c54 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -10,6 +10,8 @@ module FMI using Requires using FMIImport + +# fmi2 imports import FMIImport: fmi2CallbackLogger, fmi2CallbackAllocateMemory, fmi2CallbackFreeMemory, fmi2CallbackStepFinished import FMIImport: fmi2ComponentState, fmi2ComponentStateInstantiated, fmi2ComponentStateInitializationMode, fmi2ComponentStateEventMode, fmi2ComponentStateContinuousTimeMode, fmi2ComponentStateTerminated, fmi2ComponentStateError, fmi2ComponentStateFatal import FMIImport: fmi2Instantiate, fmi2FreeInstance!, fmi2GetTypesPlatform, fmi2GetVersion @@ -36,14 +38,49 @@ import FMIImport: fmi2Get, fmi2Get!, fmi2Set import FMIImport: fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue export fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue +# FMI3 imports +import FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate +import FMIImport: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmi3InstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal +import FMIImport: fmi3InstantiateModelExchange, fmi3InstantiateCoSimulation, fmi3InstantiateScheduledExecution, fmi3FreeInstance!, fmi3GetVersion +import FMIImport: fmi3SetDebugLogging, fmi3EnterInitializationMode, fmi3ExitInitializationMode, fmi3Terminate, fmi3Reset +import FMIImport: fmi3GetFloat32!, fmi3SetFloat32, fmi3GetFloat64!, fmi3SetFloat64 +import FMIImport: fmi3GetInt8!, fmi3SetInt8, fmi3GetUInt8!, fmi3SetUInt8, fmi3GetInt16!, fmi3SetInt16, fmi3GetUInt16!, fmi3SetUInt16, fmi3GetInt32!, fmi3SetInt32, fmi3GetUInt32!, fmi3SetUInt32, fmi3GetInt64!, fmi3SetInt64, fmi3GetUInt64!, fmi3SetUInt64 +import FMIImport: fmi3GetBoolean!, fmi3SetBoolean, fmi3GetString!, fmi3SetString, fmi3GetBinary!, fmi3SetBinary, fmi3GetClock!, fmi3SetClock +import FMIImport: fmi3GetFMUState!, fmi3SetFMUState, fmi3FreeFMUState!, fmi3SerializedFMUStateSize!, fmi3SerializeFMUState!, fmi3DeSerializeFMUState! +import FMIImport: fmi3SetIntervalDecimal, fmi3SetIntervalFraction, fmi3GetIntervalDecimal!, fmi3GetIntervalFraction!, fmi3GetShiftDecimal!, fmi3GetShiftFraction! +import FMIImport: fmi3ActivateModelPartition +import FMIImport: fmi3GetNumberOfVariableDependencies!, fmi3GetVariableDependencies! +import FMIImport: fmi3GetDirectionalDerivative!, fmi3GetAdjointDerivative!, fmi3GetOutputDerivatives! +import FMIImport: fmi3DoStep +import FMIImport: fmi3EnterConfigurationMode, fmi3ExitConfigurationMode, fmi3GetNumberOfContinuousStates!, fmi3GetNumberOfEventIndicators!, fmi3GetContinuousStates!, fmi3GetNominalsOfContinuousStates! +import FMIImport: fmi3EvaluateDiscreteStates, fmi3EnterStepMode +import FMIImport: fmi3SetTime, fmi3SetContinuousStates, fmi3EnterEventMode, fmi3UpdateDiscreteStates, fmi3EnterContinuousTimeMode, fmi3CompletedIntegratorStep! +import FMIImport: fmi3GetContinuousStateDerivatives, fmi3GetEventIndicators, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates +import FMIImport: fmi3StringToValueReference, fmi3ValueReferenceToString, fmi3ModelVariablesForValueReference +import FMIImport: fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString +import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmiDeSerializeFMUState +import FMIImport: fmi3GetDirectionalDerivative, fmi3GetAdjointDerivative +import FMIImport: fmi3GetStartValue, fmi3SampleDirectionalDerivative, fmi3CompletedIntegratorStep +import FMIImport: fmi3Unzip, fmi3Load, loadBinary, fmi3Reload, fmi3Unload, fmi3InstantiateModelExchange!, fmi3InstantiateCoSimulation!, fmi3InstantiateScheduledExecution! +import FMIImport: fmi3SampleDirectionalDerivative! +import FMIImport: fmi3GetJacobian, fmi3GetJacobian!, fmi3GetFullJacobian, fmi3GetFullJacobian! +import FMIImport: fmi3LoadModelDescription +import FMIImport: fmi3GetDefaultStartTime, fmi3GetDefaultStopTime, fmi3GetDefaultTolerance, fmi3GetDefaultStepSize +import FMIImport: fmi3GetModelName, fmi3GetInstantiationToken, fmi3GetGenerationTool, fmi3GetGenerationDateAndTime, fmi3GetVariableNamingConvention, fmi3GetNumberOfEventIndicators, fmi3GetNumberOfStates, fmi3IsCoSimulation, fmi3IsModelExchange, fmi3IsScheduledExecution +import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetSetState, fmi3CanSerializeFMUState, fmi3ProvidesDirectionalDerivatives, fmi3ProvidesAdjointDerivatves +import FMIImport: fmi3Get, fmi3Get!, fmi3Set +import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue +export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue + + using FMIExport using FMIExport: fmi2Create, fmi2CreateSimple using FMIImport.FMICore: fmi2ValueReference, fmi3ValueReference using FMIImport: fmi2ValueReferenceFormat, fmi3ValueReferenceFormat, fmi2StructMD, fmi3StructMD, fmi2Struct, fmi3Struct -using FMIImport.FMICore: FMU2, FMU3, FMU2Component, FMU3Component -export FMU2, FMU3, FMU2Component, FMU3Component +using FMIImport.FMICore: FMU2, FMU3, FMU2Component, FMU3Instance +export FMU2, FMU3, FMU2Component, FMU3Instance using FMIImport.FMICore: FMU2ExecutionConfiguration, FMU_EXECUTION_CONFIGURATION_RESET, FMU_EXECUTION_CONFIGURATION_NO_RESET, FMU_EXECUTION_CONFIGURATION_NO_FREEING export FMU2ExecutionConfiguration, FMU_EXECUTION_CONFIGURATION_RESET, FMU_EXECUTION_CONFIGURATION_NO_RESET, FMU_EXECUTION_CONFIGURATION_NO_FREEING @@ -80,6 +117,25 @@ function fmiLoadSolution(path::AbstractString; keyword="solution") end export fmiSaveSolution, fmiLoadSolution +# from FMI3_plot.jl +function fmiPlot(solution::FMU3Solution; kwargs...) + @warn "fmiPlot(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +end +function fmiPlot!(fig, solution::FMU3Solution; kwargs...) + @warn "fmiPlot!(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +end +export fmiPlot, fmiPlot! + +# from FMI3_JLD2.jl +function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") + @warn "fmiSave(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." +end +function fmiLoadSolution(path::AbstractString; keyword="solution") + @warn "fmiLoad(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." +end + +export fmiSaveSolution, fmiLoadSolution + # Requires init function __init__() @require Plots="91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin @@ -90,6 +146,7 @@ function __init__() @require JLD2="033835bb-8acc-5ee8-8aae-3f567f8a3819" begin import .JLD2 include("FMI2_JLD2.jl") + include("FMI3_JLD3.jl") end end @@ -169,15 +226,15 @@ Returns the tag 'modelName' from the model description. # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: - `Union{fmi2StructMD, fmi3StructMD} = Union{FMU2, FMU2Component, fmi2ModelDescription, FMU3, FMU3Component, fmi3ModelDescription}` + `Union{fmi2StructMD, fmi3StructMD} = Union{FMU2, FMU2Component, fmi2ModelDescription, FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). - - `str::FMU3Component`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. -See also [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`FMU3`](@ref), [`FMU3Component`](@ref), [`fmi3ModelDescription`](@ref). +See also [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetModelName(str::fmi2StructMD) fmi2GetModelName(str) @@ -186,6 +243,7 @@ function fmiGetModelName(str::fmi3StructMD) fmi3GetModelName(str) end +# TODO call differently in fmi3: getInstantationToken """ fmiGetGUID(str::fmi2StructMD) @@ -204,227 +262,308 @@ function fmiGetGUID(str::fmi2StructMD) fmi2GetGUID(str) end +# TODO how wo work with docstring """ - fmiGetGenerationTool(str::fmi2StructMD) + fmiGetGenerationTool(str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'generationtool' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: + `Union{fmi2StructMD, fmi3StructMD} = Union{FMU2, FMU2Component, fmi2ModelDescription, FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.generationtool`: The function `fmi2GetGenerationTool` returns the tag 'generationtool' from the struct, representing a FMU (`str`). -See also [`fmi2GetGenerationTool`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2GetGenerationTool`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref),[`fmi3GetGenerationTool`](@ref), [`fmi3StructMD`](@ref),[`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetGenerationTool(str::fmi2StructMD) fmi2GetGenerationTool(str) end - +function fmiGetGenerationTool(str::fmi3StructMD) + fmi3GetGenerationTool(str) +end """ - fmiGetGenerationDateAndTime(str::fmi2StructMD) + fmiGetGenerationDateAndTime(str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'generationdateandtime' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.generationDateAndTime`: The function `fmi2GetGenerationDateAndTime` returns the tag 'generationDateAndTime' from the struct, representing a FMU (`str`). -See also [`fmi2GetGenerationDateAndTime`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2GetGenerationDateAndTime`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref),[`fmi3GetGenerationDateAndTime`](@ref), [`fmi3StructMD`](@ref),[`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetGenerationDateAndTime(str::fmi2StructMD) fmi2GetGenerationDateAndTime(str) end +function fmiGetGenerationDateAndTime(str::fmi3StructMD) + fmi3GetGenerationDateAndTime(str) +end """ - fmiGetVariableNamingConvention(str::fmi2StructMD) + fmiGetVariableNamingConvention(str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'varaiblenamingconvention' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.variableNamingConvention`: The function `fmi2GetVariableNamingConvention` returns the tag 'variableNamingConvention' from the struct, representing a FMU (`str`). +See also [`fmi2GetVariableNamingConvention`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3GetVariableNamingConvention`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). -See also [`fmi2GetVariableNamingConvention`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). """ function fmiGetVariableNamingConvention(str::fmi2StructMD) fmi2GetVariableNamingConvention(str) end +function fmiGetVariableNamingConvention(str::fmi3StructMD) + fmi3GetVariableNamingConvention(str) +end """ - fmiGetNumberOfEventIndicators(str::fmi2StructMD) + fmiGetNumberOfEventIndicators(str::str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'numberOfEventIndicators' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.numberOfEventIndicators`: The function `fmi2GetNumberOfEventIndicators` returns the tag 'numberOfEventIndicators' from the struct, representing a FMU (`str`). -See also [`fmi2GetNumberOfEventIndicators`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2GetNumberOfEventIndicators`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3GetNumberOfEventIndicators`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetNumberOfEventIndicators(str::fmi2StructMD) fmi2GetNumberOfEventIndicators(str) end +function fmiGetNumberOfEventIndicators(str::fmi3StructMD) + fmi3GetNumberOfEventIndicators(str) +end """ - fmiGetModelIdentifier(fmu::FMU2) + fmiGetModelIdentifier(fmu::Union{FMU2, FMU3}) Returns the tag 'modelIdentifier' from CS or ME section. # Arguments - `fmu::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - + - `fmu::FMU3`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- `fmu.modelDescription.coSimulation.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'coSimulation.modelIdentifier' from the model description of the FMU2-struct (`fmu.modelDescription`), if the FMU supports co simulation. -- `fmu.modelDescription.modelExchange.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'modelExchange.modelIdentifier' from the model description of the FMU2-struct (`fmu.modelDescription`), if the FMU supports model exchange +- `fmu.modelDescription.coSimulation.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'coSimulation.modelIdentifier' from the model description of the FMU2 or FMU3-struct (`fmu.modelDescription`), if the FMU supports co simulation. +- `fmu.modelDescription.modelExchange.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'modelExchange.modelIdentifier' from the model description of the FMU2 or FMU3-struct (`fmu.modelDescription`), if the FMU supports model exchange +- `fmu.modelDescription.modelExchange.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'scheduledExecution.modelIdentifier' from the model description of the FMU3-struct (`fmu.modelDescription`), if the FMU supports scheduled execution -Also see [`fmi2GetModelIdentifier`](@ref), [`FMU2`](@ref). +Also see [`fmi2GetModelIdentifier`](@ref), [`FMU2`](@ref), [`fmi3GetModelIdentifier`](@ref), [`FMU3`](@ref). """ function fmiGetModelIdentifier(fmu::FMU2) fmi2GetModelIdentifier(fmu.modelDescription; type=fmu.type) end - +function fmiGetModelIdentifier(fmu::FMU3) + fmi3GetModelIdentifier(fmu.modelDescription; type=fmu.type) +end """ - fmiCanGetSetState(str::fmi2StructMD) + fmiCanGetSetState(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU supports the getting/setting of states # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2CanGetSetState` returns True, if the FMU supports the getting/setting of states. -See also [`fmi2CanGetSetState`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2CanGetSetState`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3CanGetSetState`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiCanGetSetState(str::fmi2StructMD) fmi2CanGetSetState(str) end +function fmiCanGetSetState(str::fmi3StructMD) + fmi3CanGetSetState(str) +end """ - fmiCanSerializeFMUstate(str::fmi2StructMD) + fmiCanSerializeFMUstate(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU state can be serialized # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2CanSerializeFMUstate` returns True, if the FMU state can be serialized. -See also [`fmi2CanSerializeFMUstate`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2CanSerializeFMUstate`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3CanSerializeFMUstate`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiCanSerializeFMUstate(str::fmi2StructMD) fmi2CanSerializeFMUstate(str) end +function fmiCanSerializeFMUstate(str::fmi3StructMD) + fmi3CanSerializeFMUstate(str) +end +# TODO fmi3Call fmiProvidesDirectionalDerivatives +# TODO how to handle AdjointDerivatives, easiest fmiProvidesAdjointDerivative """ - fmiProvidesDirectionalDerivative(str::fmi2StructMD) + fmiProvidesDirectionalDerivative(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU provides directional derivatives # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2ProvidesDirectionalDerivative` returns True, if the FMU provides directional derivatives. -See also [`fmi2ProvidesDirectionalDerivative`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2ProvidesDirectionalDerivative`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3ProvidesDirectionalDerivative`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiProvidesDirectionalDerivative(str::fmi2StructMD) fmi2ProvidesDirectionalDerivative(str) end +function fmiProvidesDirectionalDerivative(str::fmi3StructMD) + fmi3ProvidesDirectionalDerivative(str) +end """ - fmiIsCoSimulation(str::fmi2StructMD) + fmiIsCoSimulation(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU supports co simulation # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2IsCoSimulation` returns True, if the FMU supports co simulation -See also [`fmi2IsCoSimulation`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2IsCoSimulation`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3IsCoSimulation`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiIsCoSimulation(str::fmi2StructMD) fmi2IsCoSimulation(str) end +function fmiIsCoSimulation(str::fmi3StructMD) + fmi3IsCoSimulation(str) +end """ - fmiIsModelExchange(str::fmi2StructMD) + fmiIsModelExchange(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU supports model exchange # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - - `::Bool`: The function `fmi2IsCoSimulation` returns True, if the FMU supports model exchange. + - `::Bool`: The function `fmi2IsModelExchange` returns True, if the FMU supports model exchange. -See also [`fmi2IsModelExchange`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2IsModelExchange`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3IsModelExchange`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiIsModelExchange(str::fmi2StructMD) fmi2IsModelExchange(str) end +function fmiIsModelExchange(str::fmi3StructMD) + fmi3IsModelExchange(str) +end + +""" + + fmiIsScheduledExecution(str::fmi3StructMD) + +Returns true, if the FMU supports scheduled execution + +# Arguments +- `str::fmi3StructMD`: Representative for an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. + +# Returns + - `::Bool`: The function `fmi3IsScheduledExecution` returns True, if the FMU supports scheduled execution. + +See also [`fmi3IsScheduledExecution`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). +""" +function fmiIsScheduledExecution(str::fmi2StructMD) + fmi3IsScheduledExecution(str) +end # Multiple Dispatch variants for FMUs with version 2.0.X From 1b2ac265016d8407d6283842d65309260edfec2e Mon Sep 17 00:00:00 2001 From: JoKircher Date: Sat, 18 Jun 2022 18:19:21 +0200 Subject: [PATCH 14/41] update tests for FMI3 --- test/{ => FMI2}/cs_me.jl | 0 test/{ => FMI2}/dir_ders.jl | 0 test/{ => FMI2}/getter_setter.jl | 0 test/{ => FMI2}/load_save.jl | 0 test/{ => FMI2}/model_description.jl | 0 test/{ => FMI2}/plots.jl | 0 test/{ => FMI2}/sens.jl | 0 test/{ => FMI2}/sim_CS.jl | 0 test/{ => FMI2}/sim_ME.jl | 0 test/{ => FMI2}/sim_auto.jl | 0 test/{ => FMI2}/state.jl | 0 test/FMI3/cs_me.jl | 57 ++++++ test/FMI3/dir_ders.jl | 55 ++++++ test/FMI3/getter_setter.jl | 142 +++++++++++++++ test/FMI3/load_save.jl | 45 +++++ test/FMI3/model_description.jl | 35 ++++ test/FMI3/plots.jl | 37 ++++ test/FMI3/sens.jl | 61 +++++++ test/FMI3/sim_CS.jl | 86 +++++++++ test/FMI3/sim_ME.jl | 261 +++++++++++++++++++++++++++ test/FMI3/sim_auto.jl | 61 +++++++ test/FMI3/state.jl | 65 +++++++ test/runtests.jl | 72 ++++++-- 23 files changed, 965 insertions(+), 12 deletions(-) rename test/{ => FMI2}/cs_me.jl (100%) rename test/{ => FMI2}/dir_ders.jl (100%) rename test/{ => FMI2}/getter_setter.jl (100%) rename test/{ => FMI2}/load_save.jl (100%) rename test/{ => FMI2}/model_description.jl (100%) rename test/{ => FMI2}/plots.jl (100%) rename test/{ => FMI2}/sens.jl (100%) rename test/{ => FMI2}/sim_CS.jl (100%) rename test/{ => FMI2}/sim_ME.jl (100%) rename test/{ => FMI2}/sim_auto.jl (100%) rename test/{ => FMI2}/state.jl (100%) create mode 100644 test/FMI3/cs_me.jl create mode 100644 test/FMI3/dir_ders.jl create mode 100644 test/FMI3/getter_setter.jl create mode 100644 test/FMI3/load_save.jl create mode 100644 test/FMI3/model_description.jl create mode 100644 test/FMI3/plots.jl create mode 100644 test/FMI3/sens.jl create mode 100644 test/FMI3/sim_CS.jl create mode 100644 test/FMI3/sim_ME.jl create mode 100644 test/FMI3/sim_auto.jl create mode 100644 test/FMI3/state.jl diff --git a/test/cs_me.jl b/test/FMI2/cs_me.jl similarity index 100% rename from test/cs_me.jl rename to test/FMI2/cs_me.jl diff --git a/test/dir_ders.jl b/test/FMI2/dir_ders.jl similarity index 100% rename from test/dir_ders.jl rename to test/FMI2/dir_ders.jl diff --git a/test/getter_setter.jl b/test/FMI2/getter_setter.jl similarity index 100% rename from test/getter_setter.jl rename to test/FMI2/getter_setter.jl diff --git a/test/load_save.jl b/test/FMI2/load_save.jl similarity index 100% rename from test/load_save.jl rename to test/FMI2/load_save.jl diff --git a/test/model_description.jl b/test/FMI2/model_description.jl similarity index 100% rename from test/model_description.jl rename to test/FMI2/model_description.jl diff --git a/test/plots.jl b/test/FMI2/plots.jl similarity index 100% rename from test/plots.jl rename to test/FMI2/plots.jl diff --git a/test/sens.jl b/test/FMI2/sens.jl similarity index 100% rename from test/sens.jl rename to test/FMI2/sens.jl diff --git a/test/sim_CS.jl b/test/FMI2/sim_CS.jl similarity index 100% rename from test/sim_CS.jl rename to test/FMI2/sim_CS.jl diff --git a/test/sim_ME.jl b/test/FMI2/sim_ME.jl similarity index 100% rename from test/sim_ME.jl rename to test/FMI2/sim_ME.jl diff --git a/test/sim_auto.jl b/test/FMI2/sim_auto.jl similarity index 100% rename from test/sim_auto.jl rename to test/FMI2/sim_auto.jl diff --git a/test/state.jl b/test/FMI2/state.jl similarity index 100% rename from test/state.jl rename to test/FMI2/state.jl diff --git a/test/FMI3/cs_me.jl b/test/FMI3/cs_me.jl new file mode 100644 index 00000000..0c7f1641 --- /dev/null +++ b/test/FMI3/cs_me.jl @@ -0,0 +1,57 @@ +############### +# Prepare FMU # +############### + +t_start = 0.0 +t_stop = 1.0 + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +@test fmiIsCoSimulation(myFMU) +@test fmiIsModelExchange(myFMU) +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +sol = fmiSimulateCS(fmuStruct, t_start, t_stop) +@test sol.success +sol = fmiSimulateME(fmuStruct, t_start, t_stop) +@test sol.success +fmiUnload(myFMU) + + + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:ME) +@test myFMU.type == FMI.fmi2TypeModelExchange +comp = fmiInstantiate!(myFMU; loggingOn=false) +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +sol = fmiSimulate(fmuStruct, t_start, t_stop) +@test sol.success +fmiUnload(myFMU) + + + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:CS) +@test myFMU.type == FMI.fmi2TypeCoSimulation +comp = fmiInstantiate!(myFMU; loggingOn=false) +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +sol = fmiSimulate(fmuStruct, t_start, t_stop) +@test sol.success +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/dir_ders.jl b/test/FMI3/dir_ders.jl new file mode 100644 index 00000000..6e19ba32 --- /dev/null +++ b/test/FMI3/dir_ders.jl @@ -0,0 +1,55 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using FMI.FMIImport.FMICore: fmi2Real + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknwon fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +@test fmiSetupExperiment(fmuStruct) == 0 +@test fmiEnterInitializationMode(fmuStruct) == 0 +@test fmiExitInitializationMode(fmuStruct) == 0 + +targetValues = [[0.0, -10.0], [1.0, 0.0]] +dir_ders_buffer = zeros(fmi2Real, 2) +sample_ders_buffer = zeros(fmi2Real, 2, 1) +for i in 1:fmiGetNumberOfStates(myFMU) + + if fmiProvidesDirectionalDerivative(myFMU) + # multi derivatives calls + sample_ders = fmiSampleDirectionalDerivative(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]]) + fmiSampleDirectionalDerivative!(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]], sample_ders_buffer) + + @test sum(abs.(sample_ders[:,1] - targetValues[i])) < 1e-3 + @test sum(abs.(sample_ders_buffer[:,1] - targetValues[i])) < 1e-3 + + dir_ders = fmiGetDirectionalDerivative(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]]) + @test fmiGetDirectionalDerivative!(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]], dir_ders_buffer) == 0 + + @test sum(abs.(dir_ders - targetValues[i])) < 1e-3 + @test sum(abs.(dir_ders_buffer - targetValues[i])) < 1e-3 + + # single derivative call + dir_der = fmiGetDirectionalDerivative(fmuStruct, myFMU.modelDescription.derivativeValueReferences[1], myFMU.modelDescription.stateValueReferences[1]) + @test dir_der == targetValues[1][1] + + else + @warn "Skipping directional derivative testing, FMU from $(ENV["EXPORTINGTOOL"]) doesn't support directional derivatives." + end + +end + +fmiUnload(myFMU) diff --git a/test/FMI3/getter_setter.jl b/test/FMI3/getter_setter.jl new file mode 100644 index 00000000..4fed4967 --- /dev/null +++ b/test/FMI3/getter_setter.jl @@ -0,0 +1,142 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +############### +# Prepare FMU # +############### + +myFMU = fmiLoad("IO", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +@test fmiSetupExperiment(fmuStruct, 0.0) == 0 + +@test fmiEnterInitializationMode(fmuStruct) == 0 + +realValueReferences = ["p_real", "u_real"] +integerValueReferences = ["p_integer", "u_integer"] +booleanValueReferences = ["p_boolean", "u_boolean"] +stringValueReferences = ["p_string", "p_string"] + +######################### +# Testing Single Values # +######################### + +rndReal = 100 * rand() +rndInteger = round(Integer, 100 * rand()) +rndBoolean = rand() > 0.5 +rndString = Random.randstring(12) + +cacheReal = 0.0 +cacheInteger = 0 +cacheBoolean = false +cacheString = "" + +@test fmiSetReal(fmuStruct, realValueReferences[1], rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences[1]) == rndReal +@test fmiSetReal(fmuStruct, realValueReferences[1], -rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences[1]) == -rndReal + +@test fmiSetInteger(fmuStruct, integerValueReferences[1], rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences[1]) == rndInteger +@test fmiSetInteger(fmuStruct, integerValueReferences[1], -rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences[1]) == -rndInteger + +@test fmiSetBoolean(fmuStruct, booleanValueReferences[1], rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences[1]) == rndBoolean +@test fmiSetBoolean(fmuStruct, booleanValueReferences[1], !rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences[1]) == !rndBoolean + +@test fmiSetString(fmuStruct, stringValueReferences[1], rndString) == 0 +@test fmiGetString(fmuStruct, stringValueReferences[1]) == rndString + +fmiSet(fmuStruct, + [realValueReferences[1], integerValueReferences[1], booleanValueReferences[1], stringValueReferences[1]], + [rndReal, rndInteger, rndBoolean, rndString]) +@test fmiGet(fmuStruct, + [realValueReferences[1], integerValueReferences[1], booleanValueReferences[1], stringValueReferences[1]]) == + [rndReal, rndInteger, rndBoolean, rndString] + +#@test fmiGetStartValue(fmuStruct, "p_enumeration") == "myEnumeration1" +@test fmiGetStartValue(fmuStruct, "p_string") == "Hello World!" +@test fmiGetStartValue(fmuStruct, "p_real") == 0.0 + +################## +# Testing Arrays # +################## + +rndReal = [100 * rand(), 100 * rand()] +rndInteger = [round(Integer, 100 * rand()), round(Integer, 100 * rand())] +rndBoolean = [(rand() > 0.5), (rand() > 0.5)] +tmp = Random.randstring(8) +rndString = [tmp, tmp] + +cacheReal = [0.0, 0.0] +cacheInteger = [FMI.fmi2Integer(0), FMI.fmi2Integer(0)] +cacheBoolean = [FMI.fmi2Boolean(false), FMI.fmi2Boolean(false)] +cacheString = [pointer(""), pointer("")] + +@test fmiSetReal(fmuStruct, realValueReferences, rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences) == rndReal +fmiGetReal!(fmuStruct, realValueReferences, cacheReal) +@test cacheReal == rndReal +@test fmiSetReal(fmuStruct, realValueReferences, -rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences) == -rndReal +fmiGetReal!(fmuStruct, realValueReferences, cacheReal) +@test cacheReal == -rndReal + +@test fmiSetInteger(fmuStruct, integerValueReferences, rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences) == rndInteger +fmiGetInteger!(fmuStruct, integerValueReferences, cacheInteger) +@test cacheInteger == rndInteger +@test fmiSetInteger(fmuStruct, integerValueReferences, -rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences) == -rndInteger +fmiGetInteger!(fmuStruct, integerValueReferences, cacheInteger) +@test cacheInteger == -rndInteger + +@test fmiSetBoolean(fmuStruct, booleanValueReferences, rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences) == rndBoolean +fmiGetBoolean!(fmuStruct, booleanValueReferences, cacheBoolean) +@test cacheBoolean == rndBoolean +not_rndBoolean = collect(!b for b in rndBoolean) +@test fmiSetBoolean(fmuStruct, booleanValueReferences, not_rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences) == not_rndBoolean +fmiGetBoolean!(fmuStruct, booleanValueReferences, cacheBoolean) +@test cacheBoolean == not_rndBoolean + +@test fmiSetString(fmuStruct, stringValueReferences, rndString) == 0 +@test fmiGetString(fmuStruct, stringValueReferences) == rndString +fmiGetString!(fmuStruct, stringValueReferences, cacheString) +@test unsafe_string.(cacheString) == rndString + +#@test fmiGetStartValue(fmuStruct, ["p_enumeration", "p_string", "p_real"]) == ["myEnumeration1", "Hello World!", 0.0] +@test fmiGetStartValue(fmuStruct, ["p_string", "p_real"]) == ["Hello World!", 0.0] + +# Testing input/output derivatives +dirs = fmiGetRealOutputDerivatives(fmuStruct, ["y_real"], ones(FMI.fmi2Integer, 1)) +@test dirs == -Inf # at this point, derivative is undefined +@test fmiSetRealInputDerivatives(fmuStruct, ["u_real"], ones(FMI.fmi2Integer, 1), zeros(1)) == 0 + +@test fmiExitInitializationMode(fmuStruct) == 0 +@test fmiDoStep(fmuStruct, 0.1) == 0 + +dirs = fmiGetRealOutputDerivatives(fmuStruct, ["y_real"], ones(FMI.fmi2Integer, 1)) +@test dirs == 0.0 + +############ +# Clean up # +############ + +fmiUnload(myFMU) diff --git a/test/FMI3/load_save.jl b/test/FMI3/load_save.jl new file mode 100644 index 00000000..235bec76 --- /dev/null +++ b/test/FMI3/load_save.jl @@ -0,0 +1,45 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using JLD2 + +# our simulation setup +t_start = 0.0 +t_stop = 8.0 + +# load the FMU container +myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +recordValues = ["mass.s", "mass.v"] +solutionME = fmiSimulateME(myFMU, t_start, t_stop; recordValues=recordValues) +solutionCS = fmiSimulateCS(myFMU, t_start, t_stop; recordValues=recordValues) + +# ME + +fmiSaveSolution(solutionME, "solutionME.jld2") +anotherSolutionME = fmiLoadSolution("solutionME.jld2") + +@test solutionME.success == true +@test solutionME.success == anotherSolutionME.success +@test solutionME.states.u == anotherSolutionME.states.u +@test solutionME.states.t == anotherSolutionME.states.t +@test solutionME.values.saveval == anotherSolutionME.values.saveval +@test solutionME.values.t == anotherSolutionME.values.t + +# ME-BONUS: events +@test solutionME.events == anotherSolutionME.events + +# CS + +fmiSaveSolution(solutionCS, "solutionCS.jld2") +anotherSolutionCS = fmiLoadSolution("solutionCS.jld2") + +@test solutionCS.success == true +@test solutionCS.success == anotherSolutionCS.success +@test solutionCS.values.saveval == anotherSolutionCS.values.saveval +@test solutionCS.values.t == anotherSolutionCS.values.t + +# unload the FMU, remove unpacked data on disc ("clean up") +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/model_description.jl b/test/FMI3/model_description.jl new file mode 100644 index 00000000..af364e98 --- /dev/null +++ b/test/FMI3/model_description.jl @@ -0,0 +1,35 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using FMI: fmi2VariableNamingConventionStructured, fmi2DependencyKindDependent, fmi2DependencyKindFixed + +myFMU = fmiLoad("SpringDFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +@test fmiGetVersion(myFMU) == "2.0" +@test fmiGetTypesPlatform(myFMU) == "default" + +@test fmiGetModelName(myFMU) == "SpringFrictionPendulum1D" +@test fmiGetVariableNamingConvention(myFMU) == fmi2VariableNamingConventionStructured +@test fmiIsCoSimulation(myFMU) == true +@test fmiIsModelExchange(myFMU) == true + +@test fmiGetGUID(myFMU) == "{df491d8d-0598-4495-913e-5b025e54d7f2}" +@test fmiGetGenerationTool(myFMU) == "Dymola Version 2022x (64-bit), 2021-10-08" +@test fmiGetGenerationDateAndTime(myFMU) == "2022-03-03T15:09:18Z" +@test fmiGetNumberOfEventIndicators(myFMU) == 24 +@test fmiCanGetSetState(myFMU) == true +@test fmiCanSerializeFMUstate(myFMU) == true +@test fmiProvidesDirectionalDerivative(myFMU) == true + +depMtx = fmi2GetDependencies(myFMU) +@test fmi2DependencyKindFixed in depMtx +@test fmi2DependencyKindDependent in depMtx + +@test fmi2GetDefaultStartTime(myFMU.modelDescription) ≈ 0.0 +@test fmi2GetDefaultStopTime(myFMU.modelDescription) ≈ 1.0 +@test fmi2GetDefaultTolerance(myFMU.modelDescription) ≈ 1e-4 +@test fmi2GetDefaultStepSize(myFMU.modelDescription) === nothing + +fmiUnload(myFMU) diff --git a/test/FMI3/plots.jl b/test/FMI3/plots.jl new file mode 100644 index 00000000..217ce953 --- /dev/null +++ b/test/FMI3/plots.jl @@ -0,0 +1,37 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using Plots + +# our simulation setup +t_start = 0.0 +t_stop = 8.0 + +# load the FMU container +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +# print some useful FMU-information into the REPL +fmiInfo(myFMU) + +# make an instance from the FMU +fmiInstantiate!(myFMU) + +recordValues = ["mass.s", "mass.v"] +solutionME = fmiSimulateME(myFMU, t_start, t_stop; recordValues=recordValues) +solutionCS = fmiSimulateCS(myFMU, t_start, t_stop; recordValues=recordValues) + +# plot the results +fig = fmiPlot(solutionME) + +fig = Plots.plot() +fmiPlot!(fig, solutionME) + +fig = fmiPlot(solutionCS) + +fig = Plots.plot() +fmiPlot!(fig, solutionCS) + +# unload the FMU, remove unpacked data on disc ("clean up") +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/sens.jl b/test/FMI3/sens.jl new file mode 100644 index 00000000..77b20aad --- /dev/null +++ b/test/FMI3/sens.jl @@ -0,0 +1,61 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +import ForwardDiff +import Zygote + +using FMI.FMIImport: fmi2SampleDirectionalDerivative, fmi2GetJacobian, fmi2SetContinuousStates + +FMUPaths = [get_model_filename("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]), + get_model_filename("BouncingBall1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"])] + +t_start = 0.0 +t_step = 0.01 +t_stop = 5.0 +tData = t_start:t_step:t_stop + +for FMUPath in FMUPaths + myFMU = fmiLoad(FMUPath) + comp = fmiInstantiate!(myFMU; loggingOn=false) + + fmiSetupExperiment(comp, t_start, t_stop) + fmiEnterInitializationMode(comp) + fmiExitInitializationMode(comp) + + x0 = fmiGetContinuousStates(comp) + numStates = length(x0) + + dx = zeros(numStates) + t = 0.0 + p = [] + + # Jacobians for x0 + FD_jac = ForwardDiff.jacobian(x -> FMI.fx(comp, dx, x, p, t), x0) + ZG_jac = Zygote.jacobian(FMI.fx, comp, dx, x0, p, t)[3] + fmiSetContinuousStates(comp, x0) + samp_jac = fmi2SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + auto_jac = fmi2GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + + @test (abs.(auto_jac - FD_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - ZG_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - samp_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + #@info "A: $(auto_jac)" + #@info "S: $(samp_jac)" + + # Jacobians for random x0 / dx + x0 = x0 + rand(numStates) + dx = dx + rand(numStates) + FD_jac = ForwardDiff.jacobian(x -> FMI.fx(comp, dx, x, p, t), x0) + ZG_jac = Zygote.jacobian(FMI.fx, comp, dx, x0, p, t)[3] + fmi2SetContinuousStates(comp, x0) + samp_jac = fmi2SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + auto_jac = fmi2GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + + @test (abs.(auto_jac - FD_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - ZG_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - samp_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + + fmiUnload(myFMU) +end diff --git a/test/FMI3/sim_CS.jl b/test/FMI3/sim_CS.jl new file mode 100644 index 00000000..282687c4 --- /dev/null +++ b/test/FMI3/sim_CS.jl @@ -0,0 +1,86 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +# case 1: CS-FMU Simulation + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct !== nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +t_start = 0.0 +t_stop = 8.0 + +# test without recording values (but why?) +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2) +@test solution.success + +# test with recording values +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"]) +@test solution.success +@test length(solution.values.saveval) == t_start:1e-2:t_stop |> length +@test length(solution.values.saveval[1]) == 2 + +t = solution.values.t +s = collect(d[1] for d in solution.values.saveval) +v = collect(d[2] for d in solution.values.saveval) +@test t[1] == t_start +@test t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test s[1] == 0.5 +@test v[1] == 0.0 + +if ENV["EXPORTINGTOOL"] == "Dymola/2020x" # ToDo: Linux FMU was corrupted + @test s[end] ≈ 0.509219 atol=1e-1 + @test v[end] ≈ 0.314074 atol=1e-1 +end + +fmiUnload(myFMU) + +# case 2: CS-FMU with input signal + +function extForce(t) + [sin(t)] +end + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct !== nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"], inputValueReferences=["extForce"], inputFunction=extForce) +@test solution.success +@test length(solution.values.saveval) > 0 +@test length(solution.values.t) > 0 + +@test t[1] == t_start +@test t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test [solution.values.saveval[1]...] == [0.5, 0.0] +@test sum(abs.([solution.values.saveval[end]...] - [0.613371, 0.188633])) < 0.2 +fmiUnload(myFMU) + diff --git a/test/FMI3/sim_ME.jl b/test/FMI3/sim_ME.jl new file mode 100644 index 00000000..8754f3d4 --- /dev/null +++ b/test/FMI3/sim_ME.jl @@ -0,0 +1,261 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using DifferentialEquations: Tsit5, Rosenbrock23 + +t_start = 0.0 +t_stop = 8.0 + +# case 1: ME-FMU with state events + +myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop) +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [1.06736, -1.03552e-10])) < 0.1 +fmiUnload(myFMU) + +# case 2: ME-FMU with state and time events + +myFMU = fmiLoad("SpringTimeFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +### test without recording values + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 + +### test with recording values (variable step record values) + +solution= fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", dtmax=0.001) # dtmax to force resolution +dataLength = length(solution.states.u) +@test dataLength > 0 +@test length(solution.states.t) == dataLength +@test length(solution.values.saveval) == dataLength +@test length(solution.values.t) == dataLength + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop +@test solution.values.t[1] == t_start +@test solution.values.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 +@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 +@test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 +@test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 + +### test with recording values (fixed step record values) + +tData = t_start:0.1:t_stop +solution = fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", saveat=tData, dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) == length(tData) +@test length(solution.states.t) == length(tData) +@test length(solution.values.saveval) == length(tData) +@test length(solution.values.t) == length(tData) + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop +@test solution.values.t[1] == t_start +@test solution.values.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 +@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 +@test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 +@test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 + +fmiUnload(myFMU) + +# case 3a: ME-FMU without events, but with input signal (explicit solver: Tsit5) + +function extForce(t) + [sin(t)] +end + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Tsit5(), dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.012 +fmiUnload(myFMU) + +# case 3b: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, autodiff) + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +# ToDo: autodiff=true not working currently! +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=true), dtmax=0.001) # dtmax to force resolution +# @test length(solution.states.u) > 0 +# @test length(solution.states.t) > 0 + +# @test solution.states.t[1] == t_start +# @test solution.states.t[end] == t_stop + +# # reference values from Simulation in Dymola2020x (Dassl) +# @test solution.states.u[1] == [0.5, 0.0] +# @test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 +fmiUnload(myFMU) + +# case 3c: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, no autodiff) + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=false), dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 +fmiUnload(myFMU) + +# case 4: ME-FMU without events, but saving value interpolation + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; saveat=tData, recordValues=myFMU.modelDescription.stateValueReferences) +@test length(solution.states.u) == length(tData) +@test length(solution.states.t) == length(tData) +@test length(solution.values.saveval) == length(tData) +@test length(solution.values.t) == length(tData) + +for i in 1:length(tData) + @test sum(abs(solution.states.t[i] - solution.states.t[i])) < 1e-6 + @test sum(abs(solution.states.u[i][1] - solution.values.saveval[i][1])) < 1e-6 + @test sum(abs(solution.states.u[i][2] - solution.values.saveval[i][2])) < 1e-6 +end + +fmiUnload(myFMU) + +# case 5: ME-FMU with different (random) start state + +myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +rand_x0 = rand(2) +solution = fmiSimulateME(fmuStruct, t_start, t_stop; x0=rand_x0) +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +@test solution.states.u[1] == rand_x0 +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/sim_auto.jl b/test/FMI3/sim_auto.jl new file mode 100644 index 00000000..b1c61c8f --- /dev/null +++ b/test/FMI3/sim_auto.jl @@ -0,0 +1,61 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +pathToFMU = get_model_filename("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +# load FMU in temporary directory +myFMU = fmiLoad(pathToFMU) +@test isfile(myFMU.zipPath) == true +@test isdir(splitext(myFMU.zipPath)[1]) == true +fmiUnload(myFMU) + +# load FMU in source directory +fmuDir = joinpath(splitpath(pathToFMU)[1:end-1]...) +myFMU = fmiLoad(pathToFMU; unpackPath=fmuDir) +@test isfile(splitext(pathToFMU)[1] * ".zip") == true +@test isdir(splitext(pathToFMU)[1]) == true + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +t_start = 0.0 +t_stop = 8.0 + +# test without recording values (but why?) +sol = fmiSimulate(fmuStruct, t_start, t_stop; dt=1e-2) +@test sol.success + +# test with recording values +solution = fmiSimulate(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"], setup=true) +@test solution.success +@test length(solution.values.saveval) == t_start:1e-2:t_stop |> length +@test length(solution.values.saveval[1]) == 2 + +t = solution.values.t +s = collect(d[1] for d in solution.values.saveval) +v = collect(d[2] for d in solution.values.saveval) +@test t[1] == t_start +@test t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test s[1] == 0.5 +@test v[1] == 0.0 + +if ENV["EXPORTINGTOOL"] == "Dymola/2020x" # ToDo: Linux FMU was corrupted + @test s[end] ≈ 0.509219 atol=1e-1 + @test v[end] ≈ 0.314074 atol=1e-1 +end + +fmiUnload(myFMU) diff --git a/test/FMI3/state.jl b/test/FMI3/state.jl new file mode 100644 index 00000000..983ff203 --- /dev/null +++ b/test/FMI3/state.jl @@ -0,0 +1,65 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +############### +# Prepare FMU # +############### + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=true) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +@test fmiEnterInitializationMode(fmuStruct) == 0 +@test fmiExitInitializationMode(fmuStruct) == 0 + +@test fmiSetupExperiment(fmuStruct, 0.0) == 0 + +########################### +# Testing state functions # +########################### + +if fmiCanGetSetState(myFMU) && fmiCanSerializeFMUstate(myFMU) + @test fmiGetReal(fmuStruct, "mass.s") == 0.5 + FMUstate = fmiGetFMUstate(fmuStruct) + @test typeof(FMUstate) == FMI.fmi2FMUstate + len = fmiSerializedFMUstateSize(fmuStruct, FMUstate) + @test len > 0 + serial = fmiSerializeFMUstate(fmuStruct, FMUstate) + @test length(serial) == len + @test typeof(serial) == Array{Char,1} + + fmiSetReal(fmuStruct, "mass.s", 10.0) + FMUstate = fmiGetFMUstate(fmuStruct) + @test fmiGetReal(fmuStruct, "mass.s") == 10.0 + + FMUstate2 = fmiDeSerializeFMUstate(fmuStruct, serial) + @test typeof(FMUstate2) == FMI.fmi2FMUstate + fmiSetFMUstate(fmuStruct, FMUstate2) + @test fmiGetReal(fmuStruct, "mass.s") == 0.5 + fmiSetFMUstate(fmuStruct, FMUstate) + @test fmiGetReal(fmuStruct, "mass.s") == 10.0 + fmiFreeFMUstate!(fmuStruct, FMUstate) + fmiFreeFMUstate!(fmuStruct, FMUstate2) +else + @info "The FMU provided from the tool `$(ENV["EXPORTINGTOOL"])` does not support state get, set, serialization and deserialization. Skipping related tests." +end + +############ +# Clean up # +############ + +@test fmiTerminate(myFMU) == 0 +fmiUnload(myFMU) diff --git a/test/runtests.jl b/test/runtests.jl index 8d16adb1..916ad430 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,13 +12,59 @@ exportingToolsWindows = [("Dymola", "2022x")] exportingToolsLinux = [("Dymola", "2022x")] fmuStructs = ["FMU", "FMUCOMPONENT"] -function runtests(exportingTool) +function runtestsFMI2(exportingTool) ENV["EXPORTINGTOOL"] = exportingTool[1] ENV["EXPORTINGVERSION"] = exportingTool[2] @testset "Testing FMUs exported from $exportingTool" begin @testset "Sensitivities" begin + include("FMI2/sens.jl") + end + + for str in fmuStructs + @testset "Functions for $str" begin + ENV["FMUSTRUCT"] = str + @testset "Variable Getters / Setters" begin + include("FMI2/getter_setter.jl") + end + @testset "State Manipulation" begin + include("FMI2/state.jl") + end + @testset "Directional derivatives" begin + include("FMI2/dir_ders.jl") + end + @testset "Automatic Simulation (CS or ME)" begin + include("FMI2/sim_auto.jl") + end + @testset "CS Simulation" begin + include("FMI2/sim_CS.jl") + end + @testset "ME Simulation" begin + include("FMI2/sim_ME.jl") + end + @testset "Support CS and ME simultaneously" begin + include("FMI2/cs_me.jl") + end + @testset "Loading/Saving simulation results" begin + include("FMI2/load_save.jl") + end + end + end + + @testset "Plotting" begin + include("FMI2/plots.jl") + end + end +end + +function runtestsFMI3(exportingTool) + ENV["EXPORTINGTOOL"] = exportingTool[1] + ENV["EXPORTINGVERSION"] = exportingTool[2] + + @testset "Testing FMUs exported from $exportingTool" begin + + @testset "FMI3/Sensitivities" begin include("sens.jl") end @@ -26,34 +72,34 @@ function runtests(exportingTool) @testset "Functions for $str" begin ENV["FMUSTRUCT"] = str @testset "Variable Getters / Setters" begin - include("getter_setter.jl") + include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - include("state.jl") + include("FMI3/state.jl") end @testset "Directional derivatives" begin - include("dir_ders.jl") + include("FMI3/dir_ders.jl") end @testset "Automatic Simulation (CS or ME)" begin - include("sim_auto.jl") + include("FMI3/sim_auto.jl") end @testset "CS Simulation" begin - include("sim_CS.jl") + include("FMI3/sim_CS.jl") end @testset "ME Simulation" begin - include("sim_ME.jl") + include("FMI3/sim_ME.jl") end @testset "Support CS and ME simultaneously" begin - include("cs_me.jl") + include("FMI3/cs_me.jl") end @testset "Loading/Saving simulation results" begin - include("load_save.jl") + include("FMI3/load_save.jl") end end end @testset "Plotting" begin - include("plots.jl") + include("FMI3/plots.jl") end end end @@ -62,12 +108,14 @@ end if Sys.iswindows() @info "Automated testing is supported on Windows." for exportingTool in exportingToolsWindows - runtests(exportingTool) + runtestsFMI2(exportingTool) + runtestsFMI3(exportingTool) end elseif Sys.islinux() @info "Automated testing is supported on Linux." for exportingTool in exportingToolsLinux - runtests(exportingTool) + runtestsFMI2(exportingTool) + runtestsFMI3(exportingTool) end elseif Sys.isapple() @warn "Test-sets are currrently using Windows- and Linux-FMUs, automated testing for macOS is currently not supported." From 4156285d850880b84bcc2ec20303b6810e9ede21 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Mon, 20 Jun 2022 13:18:11 +0200 Subject: [PATCH 15/41] WIP: added more fmi3 calls --- src/FMI.jl | 215 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 173 insertions(+), 42 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 8be46c54..8f00bd5e 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -591,19 +591,22 @@ end """ - fmiReload(fmu::FMU2) + fmiReload(fmu::Union{FMU2, FMU3}) Reloads the FMU-binary. This is useful, if the FMU does not support a clean reset implementation. # Arguments - `fmu::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `fmu::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). - -See also [`fmi2Reload`](@ref). +See also [`fmi2Reload`](@ref), [`fmi3Reload`](@ref). """ function fmiReload(fmu::FMU2, args...; kwargs...) fmi2Reload(fmu, args...; kwargs...) end +function fmiReload(fmu::FMU3, args...; kwargs...) + fmi3Reload(fmu, args...; kwargs...) +end """ @@ -771,39 +774,48 @@ end """ - fmiUnload(fmu::FMU2) + fmiUnload(fmu::Union{FMU2, FMU3}) Unloads the FMU and all its instances and frees the allocated memory. # Arguments - `fmu::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `fmu::FMU3`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 3.0 Standard](https://fmi-standard.org/). -See also [`fmi2Unload`](@ref). +See also [`fmi2Unload`](@ref), [`fmi3Unload`](@ref). """ function fmiUnload(fmu::FMU2) fmi2Unload(fmu) end +function fmiUnload(fmu::FMU3) + fmi3Unload(fmu) +end """ - fmiGetNumberOfStates(str::fmi2Struct) + fmiGetNumberOfStates(str::Union{fmi2Struct, fmi3Struct}) Returns the number of states of the FMU. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- Returns the length of the `str.stateValueReferences` array, which consists of `fmi2ValueReference` constants. +- Returns the length of the `str.stateValueReferences` array, which consists of `fmi2ValueReference` or `fmi3ValueReference` constants. -See also [`fmi2GetNumberOfStates`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2GetNumberOfStates`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3GetNumberOfStates`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiGetNumberOfStates(str::fmi2Struct) fmi2GetNumberOfStates(str) end +function fmiGetNumberOfStates(str::fmi3Struct) + fmi3GetNumberOfStates(str) +end """ @@ -828,30 +840,36 @@ end """ - fmiGetVersion(str::fmi2Struct) + fmiGetVersion(str::Union{fmi2Struct, fmi3Struct}) Returns the version of the FMU, version independent. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- Returns a string from the address of a C-style (NUL-terminated) string. The string represents the version of the “fmi2Functions.h” header file which was used to compile the functions of the FMU. The function returns “fmiVersion” which is defined in this header file. The standard header file as documented in this specification has version “2.0” +- Returns a string from the address of a C-style (NUL-terminated) string. The string represents the version of the “fmiXFunctions.h” header file which was used to compile the functions of the FMU. The function returns “fmiVersion” which is defined in this header file. The standard header file as documented in this specification has version “2.0” or "3.0" # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.22]: 2.1.4 Inquire Platform and Version Number of Header Files - FMISpec2.0.2[p.16]: 2.1.2 Platform Dependent Definitions + - FMISpec3.0[p. ]: 2.2.5. Inquire Version Number of Header Files -See also [`fmi2GetVersion`](@ref), [`unsafe_string`](https://docs.julialang.org/en/v1/base/strings/#Base.unsafe_string), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2GetVersion`](@ref), [`unsafe_string`](https://docs.julialang.org/en/v1/base/strings/#Base.unsafe_string), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3GetVersion`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiGetVersion(str::fmi2Struct) fmi2GetVersion(str) end - +function fmiGetVersion(str::fmi3Struct) + fmi3GetVersion(str) +end +# TODO not available so far """ fmiInfo(str::fmi2Struct) @@ -872,7 +890,7 @@ See also [`fmi2Info`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Compone function fmiInfo(str::fmi2Struct) fmi2Info(str) end - +# TODO how to handle different calls for CS, ME, SE in FMI3 """ fmiInstantiate!(fmu::FMU2; pushComponents::Bool = true, visible::Bool = false, loggingOn::Bool = false, externalCallbacks::Bool = false, @@ -913,49 +931,65 @@ end """ - fmiFreeInstance!(str::fmi2Struct) + fmiFreeInstance!(str::Union{fmi2Struct, fmi3Struct}) Frees the allocated memory of the last instance of the FMU. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns - `status::fmi2Status`: returned by all functions to indicate the success of the function call +- `status::fmi3Status`: returned by all functions to indicate the success of the function call # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.23]: 2.1.6 Initialization, Termination, and Resetting an FMU - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0[p. ]: 2.3.1. Super State: FMU State Settable +- FMISpec3.0[p. ]: 2.2.4. Status Returned by Functions -See also [fmi2FreeInstance](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [fmi2FreeInstance](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [fmi3FreeInstance](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiFreeInstance!(str::fmi2Struct) fmi2FreeInstance!(str) end +function fmiFreeInstance!(str::fmi3Struct) + fmi3FreeInstance!(str) +end """ - fmiSetDebugLogging(str::fmi2Struct) + fmiSetDebugLogging(str::Union{fmi2Struct, fmi3Struct}) Control the use of the logging callback function, version independent. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.22]: 2.1.5 Creation, Destruction and Logging of FMU Instances +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0[p. ]: 2.3.1. Super State: FMU State Settable """ function fmiSetDebugLogging(str::fmi2Struct) fmi2SetDebugLogging(str) end +function fmiSetDebugLogging(str::fmi3Struct) + fmi3SetDebugLogging(str) +end """ @@ -988,7 +1022,7 @@ See also [fmi2SetupExperiment](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FM function fmiSetupExperiment(str::fmi2Struct, args...; kwargs...) fmi2SetupExperiment(str, args...; kwargs...) end - +# TODO different function call in fmi3 more arguments """ fmiEnterInitializationMode(str::fmi2Struct) @@ -1018,30 +1052,39 @@ end """ - fmiExitInitializationMode(str::fmi2Struct) + fmiExitInitializationMode(str::Union{fmi2Struct, fmi3Struct}) Informs the FMU to exit initialization mode, version independent. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- Returns a warning if `str.state` is not called in `fmi2ComponentStateInitializationMode`. +- Returns a warning if `str.state` is not called in `fmi2ComponentStateInitializationMode` or `fmi3InstanceInitializationMode`. - `status::fmi2Status`: returned by all functions to indicate the success of the function call +- `status::fmi3Status`: returned by all functions to indicate the success of the function call # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.23]: 2.1.6 Initialization, Termination, and Resetting an FMU - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0[p. ]: 2.3.3. State: Initialization Mode +- FMISpec3.0[p. ]: 2.2.4. Status Returned by Functions - See also [fmi2ExitInitializationMode](@ref) + See also [fmi2ExitInitializationMode](@ref), [fmi3ExitInitializationMode](@ref). """ function fmiExitInitializationMode(str::fmi2Struct) fmi2ExitInitializationMode(str) end +function fmiExitInitializationMode(str::fmi3Struct) + fmi3ExitInitializationMode(str) +end """ Informs the FMU that the simulation run is terminated, version independent. @@ -1049,13 +1092,18 @@ Informs the FMU that the simulation run is terminated, version independent. function fmiTerminate(str::fmi2Struct) fmi2Terminate(str) end - +function fmiTerminate(str::fmi3Struct) + fmi3Terminate(str) +end """ Resets the FMU after a simulation run, version independent. """ function fmiReset(str::fmi2Struct) fmi2Reset(str) end +function fmiReset(str::fmi3Struct) + fmi3Reset(str) +end """ ToDo @@ -1063,20 +1111,27 @@ ToDo function fmiGet(str::fmi2Struct, args...; kwargs...) fmi2Get(str, args...; kwargs...) end - +function fmiGet(str::fmi3Struct, args...; kwargs...) + fmi3Get(str, args...; kwargs...) +end """ ToDo """ function fmiGet!(str::fmi2Struct, args...; kwargs...) fmi2Get!(str, args...; kwargs...) end - +function fmiGet!(str::fmi3Struct, args...; kwargs...) + fmi3Get!(str, args...; kwargs...) +end """ ToDo """ function fmiSet(str::fmi2Struct, args...; kwargs...) fmi2Set(str, args...; kwargs...) end +function fmiSet(str::fmi3Struct, args...; kwargs...) + fmi3Set(str, args...; kwargs...) +end """ Returns the real values of an array of variables @@ -1084,46 +1139,49 @@ Returns the real values of an array of variables function fmiGetReal(str::fmi2Struct, args...; kwargs...) fmi2GetReal(str, args...; kwargs...) end - +function fmiGetReal(str::fmi3Struct, args...; kwargs...) + fmi3GetReal(str, args...; kwargs...) +end +# TODO different call in fmi3 fmi3GetOuputDerivatives function fmiGetRealOutputDerivatives(str::fmi2Struct, args...; kwargs...) fmi2GetRealOutputDerivatives(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Writes the real values of an array of variables in the given field """ function fmiGetReal!(str::fmi2Struct, args...; kwargs...) fmi2GetReal!(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Set the values of an array of real variables """ function fmiSetReal(str::fmi2Struct, args...; kwargs...) fmi2SetReal(str, args...; kwargs...) end - +# TODO different call in fmi3 """ ToDo """ function fmiSetRealInputDerivatives(str::fmi2Struct, args...; kwargs...) fmi2SetRealInputDerivatives(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Returns the integer values of an array of variables """ function fmiGetInteger(str::fmi2Struct,args...; kwargs...) fmi2GetInteger(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Writes the integer values of an array of variables in the given field """ function fmiGetInteger!(str::fmi2Struct, args...; kwargs...) fmi2GetInteger!(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Set the values of an array of integer variables """ @@ -1137,6 +1195,9 @@ Returns the boolean values of an array of variables function fmiGetBoolean(str::fmi2Struct, args...; kwargs...) fmi2GetBoolean(str, args...; kwargs...) end +function fmiGetBoolean(str::fmi3Struct, args...; kwargs...) + fmi3GetBoolean(str, args...; kwargs...) +end """ Writes the boolean values of an array of variables in the given field @@ -1144,6 +1205,9 @@ Writes the boolean values of an array of variables in the given field function fmiGetBoolean!(str::fmi2Struct, args...; kwargs...) fmi2GetBoolean!(str, args...; kwargs...) end +function fmiGetBoolean!(str::fmi3Struct, args...; kwargs...) + fmi3GetBoolean!(str, args...; kwargs...) +end """ Set the values of an array of boolean variables @@ -1151,6 +1215,9 @@ Set the values of an array of boolean variables function fmiSetBoolean(str::fmi2Struct, args...; kwargs...) fmi2SetBoolean(str, args...; kwargs...) end +function fmiSetBoolean(str::fmi3Struct, args...; kwargs...) + fmi3SetBoolean(str, args...; kwargs...) +end """ Returns the string values of an array of variables @@ -1158,6 +1225,9 @@ Returns the string values of an array of variables function fmiGetString(str::fmi2Struct, args...; kwargs...) fmi2GetString(str, args...; kwargs...) end +function fmiGetString(str::fmi3Struct, args...; kwargs...) + fmi3GetString(str, args...; kwargs...) +end """ Writes the string values of an array of variables in the given field @@ -1165,6 +1235,9 @@ Writes the string values of an array of variables in the given field function fmiGetString!(str::fmi2Struct, args...; kwargs...) fmi2GetString!(str, args...; kwargs...) end +function fmiGetString!(str::fmi3Struct, args...; kwargs...) + fmi3GetString!(str, args...; kwargs...) +end """ Set the values of an array of string variables @@ -1172,13 +1245,17 @@ Set the values of an array of string variables function fmiSetString(str::fmi2Struct, args...; kwargs...) fmi2SetString(str, args...; kwargs...) end - +function fmiSetString(str::fmi3Struct, args...; kwargs...) + fmi3SetString(str, args...; kwargs...) +end +# TODO different call in fmi3 """ Returns the FMU state of the fmu """ function fmiGetFMUstate(str::fmi2Struct) fmi2GetFMUstate(str) end +# TODO different call in fmi3 """ Sets the FMU to the given state @@ -1186,6 +1263,7 @@ Sets the FMU to the given state function fmiSetFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SetFMUstate(str, args...; kwargs...) end +# TODO different call in fmi3 """ Free the memory for the allocated FMU state @@ -1193,6 +1271,7 @@ Free the memory for the allocated FMU state function fmiFreeFMUstate!(str::fmi2Struct, args...; kwargs...) fmi2FreeFMUstate!(str, args...; kwargs...) end +# TODO different call in fmi3 """ Returns the size of the byte vector the FMU can be stored in @@ -1200,6 +1279,7 @@ Returns the size of the byte vector the FMU can be stored in function fmiSerializedFMUstateSize(str::fmi2Struct, args...; kwargs...) fmi2SerializedFMUstateSize(str, args...; kwargs...) end +# TODO different call in fmi3 """ Serialize the data in the FMU state pointer @@ -1207,6 +1287,7 @@ Serialize the data in the FMU state pointer function fmiSerializeFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SerializeFMUstate(str, args...; kwargs...) end +# TODO different call in fmi3 """ Deserialize the data in the FMU state pointer @@ -1221,6 +1302,9 @@ Returns the values of the directional derivatives. function fmiGetDirectionalDerivative(str::fmi2Struct, args...; kwargs...) fmi2GetDirectionalDerivative(str, args...; kwargs...) end +function fmiGetDirectionalDerivative(str::fmi3Struct, args...; kwargs...) + fmi3GetDirectionalDerivative(str, args...; kwargs...) +end """ Returns the values of the directional derivatives (in-place). @@ -1228,6 +1312,23 @@ Returns the values of the directional derivatives (in-place). function fmiGetDirectionalDerivative!(str::fmi2Struct, args...; kwargs...) fmi2GetDirectionalDerivative!(str, args...; kwargs...) end +function fmiGetDirectionalDerivative!(str::fmi3Struct, args...; kwargs...) + fmi3GetDirectionalDerivative!(str, args...; kwargs...) +end + +""" +Returns the values of the adjoint derivatives. +""" +function fmiGetAdjointDerivative(str::fmi3Struct, args...; kwargs...) + fmi3GetAdjointDerivative(str, args...; kwargs...) +end + +""" +Returns the values of the adjoint derivatives (in-place). +""" +function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) + fmi3GetAdjointDerivative!(str, args...; kwargs...) +end """ Does one step in the CoSimulation FMU @@ -1235,6 +1336,9 @@ Does one step in the CoSimulation FMU function fmiDoStep(str::fmi2Struct, args...; kwargs...) fmi2DoStep(str, args...; kwargs...) end +function fmiDoStep(str::fmi3Struct, args...; kwargs...) + fmi3DoStep(str, args...; kwargs...) +end """ Samples the values of the directional derivatives. @@ -1242,6 +1346,9 @@ Samples the values of the directional derivatives. function fmiSampleDirectionalDerivative(str::fmi2Struct, args...; kwargs...) fmi2SampleDirectionalDerivative(str, args...; kwargs...) end +function fmiSampleDirectionalDerivative(str::fmi3Struct, args...; kwargs...) + fmi3SampleDirectionalDerivative(str, args...; kwargs...) +end """ Samples the values of the directional derivatives (in-place). @@ -1249,12 +1356,18 @@ Samples the values of the directional derivatives (in-place). function fmiSampleDirectionalDerivative!(str::fmi2Struct, args...; kwargs...) fmi2SampleDirectionalDerivative!(str, args...; kwargs...) end +function fmiSampleDirectionalDerivative!(str::fmi3Struct, args...; kwargs...) + fmi3SampleDirectionalDerivative!(str, args...; kwargs...) +end """ Set a time instant """ -function fmiSetTime(c::fmi2Struct, args...; kwargs...) - fmi2SetTime(c, args...; kwargs...) +function fmiSetTime(str::fmi2Struct, args...; kwargs...) + fmi2SetTime(str, args...; kwargs...) +end +function fmiSetTime(str::fmi3Struct, args...; kwargs...) + fmi3SetTime(str, args...; kwargs...) end """ @@ -1263,14 +1376,14 @@ Set a new (continuous) state vector function fmiSetContinuousStates(str::fmi2Struct, args...; kwargs...) fmi2SetContinuousStates(str, args...; kwargs...) end - +# TODO more arguments in fmi3 """ The model enters Event Mode """ function fmi2EnterEventMode(str::fmi2Struct) fmi2EnterEventMode(str) end - +# TODO different function call in fmi3 """ Returns the next discrete states """ @@ -1284,6 +1397,9 @@ The model enters Continuous-Time Mode function fmiEnterContinuousTimeMode(str::fmi2Struct) fmi2EnterContinuousTimeMode(str) end +function fmiEnterContinuousTimeMode(str::fmi3Struct) + fmi3EnterContinuousTimeMode(str) +end """ This function must be called by the environment after every completed step @@ -1291,7 +1407,10 @@ This function must be called by the environment after every completed step function fmiCompletedIntegratorStep(str::fmi2Struct, args...; kwargs...) fmi2CompletedIntegratorStep(str, args...; kwargs...) end - +function fmiCompletedIntegratorStep(str::fmi3Struct, args...; kwargs...) + fmi3CompletedIntegratorStep(str, args...; kwargs...) +end +# TODO different function call """ Compute state derivatives at the current time instant and for the current states """ @@ -1305,6 +1424,9 @@ Returns the event indicators of the FMU function fmiGetEventIndicators(str::fmi2Struct) fmi2GetEventIndicators(str) end +function fmiGetEventIndicators(str::fmi3Struct) + fmi3GetEventIndicators(str) +end """ Return the new (continuous) state vector x @@ -1312,6 +1434,9 @@ Return the new (continuous) state vector x function fmiGetContinuousStates(s::fmi2Struct) fmi2GetContinuousStates(s) end +function fmiGetContinuousStates(s::fmi3Struct) + fmi3GetContinuousStates(s) +end """ Return the new (continuous) state vector x @@ -1319,6 +1444,9 @@ Return the new (continuous) state vector x function fmiGetNominalsOfContinuousStates(s::fmi2Struct) fmi2GetNominalsOfContinuousStates(s) end +function fmiGetNominalsOfContinuousStates(s::fmi3Struct) + fmi3GetNominalsOfContinuousStates(s) +end """ Returns the start/default value for a given value reference. @@ -1328,6 +1456,9 @@ TODO: Add this command in the documentation. function fmiGetStartValue(s::fmi2Struct, vr::fmi2ValueReferenceFormat) fmi2GetStartValue(s, vr) end +function fmiGetStartValue(s::fmi3Struct, vr::fmi3ValueReferenceFormat) + fmi3GetStartValue(s, vr) +end ##### function setters @@ -1457,7 +1588,7 @@ end ##### Multiple Dispatch fallback for FMUs with unsupported versions ##### -unsupportedFMUs = Union{FMU1,FMU3} +unsupportedFMUs = FMU1 function fmiDoStep(fmu::unsupportedFMUs, args...; kwargs...) error(unsupportedFMU::errorType) end From d85abcb66ba573bfd78dfeeb3ea26be93183b390 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Thu, 23 Jun 2022 12:18:51 +0200 Subject: [PATCH 16/41] add help function for fmiLoad --- src/FMI.jl | 43 +++++++++++++++++++++-- src/FMI3_additional.jl | 80 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 8f00bd5e..fcbfdc85 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -458,7 +458,6 @@ function fmiCanSerializeFMUstate(str::fmi3StructMD) end # TODO fmi3Call fmiProvidesDirectionalDerivatives -# TODO how to handle AdjointDerivatives, easiest fmiProvidesAdjointDerivative """ fmiProvidesDirectionalDerivative(str::Union{fmi2StructMD, fmi3StructMD}) @@ -484,7 +483,29 @@ function fmiProvidesDirectionalDerivative(str::fmi2StructMD) fmi2ProvidesDirectionalDerivative(str) end function fmiProvidesDirectionalDerivative(str::fmi3StructMD) - fmi3ProvidesDirectionalDerivative(str) + fmi3ProvidesDirectionalDerivatives(str) +end + +""" + + fmiProvidesAdjointDerivative(str::fmi3StructMD) + +Returns true, if the FMU provides adjoint derivatives + +# Arguments +- `str::fmi3StructMD`: Representative for an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: +More detailed: `fmi3StructMD = Union{FMU3, FMU3Component, fmi3ModelDescription}` + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. + +# Returns +- `::Bool`: The function `fmi3ProvidesAdjointDerivatives` returns True, if the FMU provides adjoint derivatives. + +See also [`fmi3ProvidesAdjointDerivatves`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). +""" +function fmiProvidesAdjointDerivative(str::fmi3StructMD) + fmi3ProvidesAdjointDerivatives(str) end """ @@ -567,6 +588,7 @@ end # Multiple Dispatch variants for FMUs with version 2.0.X +# TODO check version in MD """ fmiLoad(pathToFMU::String; unpackPath=nothing, type=nothing) @@ -586,7 +608,14 @@ Load FMUs independent of the FMI version, currently supporting version 2.0.X. See also [`fmi2Load`](@ref). """ function fmiLoad(args...; kwargs...) - fmi2Load(args...; kwargs...) + version = fmiCheckVersion(pathToFMU) + if version == "2.0" + fmi2Load(args...; kwargs...) + else if version == "3.0" + fmi3Load(args...; kwargs...) + else + @warn "fmiLoad(...): Unknown FMU version" + end end """ @@ -1316,6 +1345,7 @@ function fmiGetDirectionalDerivative!(str::fmi3Struct, args...; kwargs...) fmi3GetDirectionalDerivative!(str, args...; kwargs...) end +# Add unsupportedFMU for call with FMU2 """ Returns the values of the adjoint derivatives. """ @@ -1808,5 +1838,12 @@ end function fmiIsModelExchange(fmu::unsupportedFMUs) error(unsupportedFMU::errorType) end +function fmiGetAdjointDerivative(str::fmi2Struct, args...; kwargs...) + error(unsupportedFMU::errorType) +end +function fmiGetAdjointDerivative!(str::fmi2Struct, args...; kwargs...) + error(unsupportedFMU::errorType) +end + end # module FMI diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 727ae045..66dad1fe 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -157,3 +157,83 @@ function fmi3Info(fmu::FMU3) println("##################### End information for FMU #####################") end + +function fmiCheckVersion(pathToFMU::String; unpackPath=nothing) + # Unzip MD + + # Download FMU if necessary + if startswith(pathToFMU, "http") + @info "Downloading FMU for Version extraction from `$(pathToFMU)`." + pathToFMU = download(pathToFMU) + end + + pathToFMU = normpath(pathToFMU) + + fileNameExt = basename(pathToFMU) + (fileName, fileExt) = splitext(fileNameExt) + + if unpackPath === nothing + # cleanup=true leads to issues with automatic testing on linux server. + unpackPath = mktempdir(; prefix="fmijl_", cleanup=false) + end + + zipPath = joinpath(unpackPath, fileName * ".zip") + unzippedPath = joinpath(unpackPath, fileName) + + # only copy ZIP if not already there + if !isfile(zipPath) + cp(pathToFMU, zipPath; force=true) + end + + @assert isfile(zipPath) ["fmi3Unzip(...): ZIP-Archive couldn't be copied to `$zipPath`."] + + zipAbsPath = isabspath(zipPath) ? zipPath : joinpath(pwd(), zipPath) + unzippedAbsPath = isabspath(unzippedPath) ? unzippedPath : joinpath(pwd(), unzippedPath) + + @assert isfile(zipAbsPath) ["fmi3Unzip(...): Can't deploy ZIP-Archive at `$(zipAbsPath)`."] + + # only unzip if not already done + if !isdir(unzippedAbsPath) + mkpath(unzippedAbsPath) + + zarchive = ZipFile.Reader(zipAbsPath) + for f in zarchive.files + if f.name == "modelDescription.xml" + fileAbsPath = normpath(joinpath(unzippedAbsPath, f.name)) + + # create directory if not forced by zip file folder + mkpath(dirname(fileAbsPath)) + + numBytes = write(fileAbsPath, read(f)) + + if numBytes == 0 + @info "fmi3Unzip(...): Written file `$(f.name)`, but file is empty." + end + + @assert isfile(fileAbsPath) ["fmi3Unzip(...): Can't unzip file `$(f.name)` at `$(fileAbsPath)`."] + end + + end + close(zarchive) + end + + @assert isdir(unzippedAbsPath) ["fmi3Unzip(...): ZIP-Archive couldn't be unzipped at `$(unzippedPath)`."] + @info "fmiUnzipVersion(...): Successfully unzipped modelDescription.xml at `$unzippedAbsPath`." + + # read version tag + + doc = readxml(unzippedAbsPath) + + version = root["fmiVersion"] + + # cleanup unzipped modelDescription + try + rm(unzippedAbsPath; recursive = true, force = true) + rm(zipAbsPath; recursive = true, force = true) + catch e + @warn "Cannot delete unpacked data on disc. Maybe some files are opened in another application." + end + + # return version + version +end From 184ddffadaf0854f2788c36f04a9930abc80dabf Mon Sep 17 00:00:00 2001 From: JoKircher Date: Thu, 23 Jun 2022 13:12:36 +0200 Subject: [PATCH 17/41] WIP: updated all fmi functions --- src/FMI.jl | 119 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 29 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index fcbfdc85..c08e3e0e 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -271,8 +271,9 @@ Returns the tag 'generationtool' from the model description. # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: - `Union{fmi2StructMD, fmi3StructMD} = Union{FMU2, FMU2Component, fmi2ModelDescription, FMU3, FMU3Instance, fmi3ModelDescription}` - - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +`fmi2StructMD= Union{FMU2, FMU2Component, fmi2ModelDescription}` +`fmi3StructMD= Union{FMU3, FMU3Instance, fmi3ModelDescription}` +- `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -300,6 +301,7 @@ Returns the tag 'generationdateandtime' from the model description. # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` + More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. @@ -329,6 +331,7 @@ Returns the tag 'varaiblenamingconvention' from the model description. # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` + More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. @@ -358,6 +361,7 @@ Returns the tag 'numberOfEventIndicators' from the model description. # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. @@ -410,6 +414,7 @@ Returns true, if the FMU supports the getting/setting of states # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. @@ -438,7 +443,8 @@ Returns true, if the FMU state can be serialized # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` +- `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -467,6 +473,7 @@ Returns true, if the FMU provides directional derivatives # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. @@ -494,7 +501,7 @@ Returns true, if the FMU provides adjoint derivatives # Arguments - `str::fmi3StructMD`: Representative for an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: -More detailed: `fmi3StructMD = Union{FMU3, FMU3Component, fmi3ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Component, fmi3ModelDescription}` - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. @@ -516,8 +523,9 @@ Returns true, if the FMU supports co simulation # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: -More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` +- `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -544,7 +552,8 @@ Returns true, if the FMU supports model exchange # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: -More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. @@ -593,19 +602,19 @@ end fmiLoad(pathToFMU::String; unpackPath=nothing, type=nothing) -Load FMUs independent of the FMI version, currently supporting version 2.0.X. +Load FMUs independent of the FMI version, currently supporting version 2.0.X and 3.0. # Arguments - `pathToFMU::String`: String that contains the paths of ziped and unziped FMU folders. # Keywords - `unpackPath=nothing`: Via optional argument ```unpackPath```, a path to unpack the FMU can be specified (default: system temporary directory). -- `type::Union{CS, ME} = nothing`: Via ```type```, a FMU type can be selected. If none of the unified type set is used, the default value `type = nothing` will be used. +- `type::Union{CS, ME, SE} = nothing`: Via ```type```, a FMU type can be selected. If none of the unified type set is used, the default value `type = nothing` will be used. # Returns - Returns the instance of the FMU struct. -See also [`fmi2Load`](@ref). +See also [`fmi2Load`](@ref), [`fmi3Load`](@ref). """ function fmiLoad(args...; kwargs...) version = fmiCheckVersion(pathToFMU) @@ -639,7 +648,7 @@ end """ - fmiSimulate(str::fmi2Struct, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + fmiSimulate(str::Union{fmi2Struct, fmi3Struct}, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; tolerance::Union{Real, Nothing} = nothing, dt::Union{Real, Nothing} = nothing, solver = nothing, @@ -658,12 +667,15 @@ Starts a simulation of the FMU instance for the matching FMU type, if both types # Arguments -- - `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). -- `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. -- `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. + - `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. # Keywords - `tolerance::Union{Real, Nothing} = nothing`: Real number to set the tolerance for any OED-solver @@ -686,16 +698,18 @@ More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - if keyword `recordValues` is set, a tuple of type (success::Bool, DiffEqCallbacks.SavedValues) for CS-FMUs - if keyword `recordValues` is set, a tuple of type (ODESolution, DiffEqCallbacks.SavedValues) for ME-FMUs -See also [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2SimulateCS`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). - +See also [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2SimulateCS`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3Simulate`](@ref), [`fmi3SimulateME`](@ref), [`fmi3SimulateCS`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiSimulate(str::fmi2Struct, args...; kwargs...) fmi2Simulate(str, args...; kwargs...) end +function fmiSimulate(str::fmi3Struct, args...; kwargs...) + fmi3Simulate(str, args...; kwargs...) +end """ - fmiSimulateCS(str::fmi2Struct, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + fmiSimulateCS(str::Union{fmi2Struct,fmi3Struct}, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; tolerance::Union{Real, Nothing} = nothing, dt::Union{Real, Nothing} = nothing, solver = nothing, @@ -714,10 +728,13 @@ Starts a simulation of the Co-Simulation FMU instance. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). - `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. - `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. @@ -740,16 +757,19 @@ More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - If keyword `recordValues` is not set, a boolean `success` is returned (simulation success). - If keyword `recordValues` is set, a tuple of type (true, DiffEqCallbacks.SavedValues) or (false, nothing). -See also [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3SimulateCS`](@ref), [`fmi3Simulate`](@ref), [`fmi3SimulateME`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiSimulateCS(str::fmi2Struct, args...; kwargs...) fmi2SimulateCS(str, args...; kwargs...) +end +function fmiSimulateCS(str::fmi3Struct, args...; kwargs...) + fmi3SimulateCS(str, args...; kwargs...) end """ - fmiSimulateME(str::fmi2Struct, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + fmiSimulateME(str::Union{fmi2Struct,fmi3Struct}, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; tolerance::Union{Real, Nothing} = nothing, dt::Union{Real, Nothing} = nothing, solver = nothing, @@ -768,10 +788,13 @@ Simulates a FMU instance for the given simulation time interval. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). - `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. - `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. @@ -794,12 +817,15 @@ More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - If keyword `recordValues` is not set, a struct of type `ODESolution`. - If keyword `recordValues` is set, a tuple of type (ODESolution, DiffEqCallbacks.SavedValues). -See also [`fmi2SimulateME`](@ref) [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2SimulateME`](@ref) [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3SimulateME`](@ref) [`fmi3SimulateCS`](@ref), [`fmi3Simulate`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiSimulateME(str::fmi2Struct, args...; kwargs...) fmi2SimulateME(str, args...; kwargs...) end +function fmiSimulateME(str::fmi3Struct, args...; kwargs...) + fmi3SimulateME(str, args...; kwargs...) +end """ @@ -829,6 +855,7 @@ Returns the number of states of the FMU. # Arguments - `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -876,6 +903,7 @@ Returns the version of the FMU, version independent. # Arguments - `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -898,7 +926,7 @@ end function fmiGetVersion(str::fmi3Struct) fmi3GetVersion(str) end -# TODO not available so far + """ fmiInfo(str::fmi2Struct) @@ -906,19 +934,26 @@ end Prints FMU-specific information into the REPL. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Source - - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) -See also [`fmi2Info`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2Info`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3Info`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiInfo(str::fmi2Struct) fmi2Info(str) end +function fmiInfo(str::fmi3Struct) + fmi3Info(str) +end # TODO how to handle different calls for CS, ME, SE in FMI3 """ @@ -967,6 +1002,7 @@ Frees the allocated memory of the last instance of the FMU. # Arguments - `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -1002,6 +1038,7 @@ Control the use of the logging callback function, version independent. # Arguments - `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -1088,6 +1125,7 @@ Informs the FMU to exit initialization mode, version independent. # Arguments - `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). @@ -1284,6 +1322,9 @@ Returns the FMU state of the fmu function fmiGetFMUstate(str::fmi2Struct) fmi2GetFMUstate(str) end +function fmiGetFMUstate(str::fmi3Struct) + fmi3GetFMUstate(str) +end # TODO different call in fmi3 """ @@ -1292,6 +1333,9 @@ Sets the FMU to the given state function fmiSetFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SetFMUstate(str, args...; kwargs...) end +function fmiSetFMUstate(str::fmi3Struct, args...; kwargs...) + fmi3SetFMUstate(str, args...; kwargs...) +end # TODO different call in fmi3 """ @@ -1300,6 +1344,9 @@ Free the memory for the allocated FMU state function fmiFreeFMUstate!(str::fmi2Struct, args...; kwargs...) fmi2FreeFMUstate!(str, args...; kwargs...) end +function fmiFreeFMUstate!(str::fmi3Struct, args...; kwargs...) + fmi3FreeFMUstate!(str, args...; kwargs...) +end # TODO different call in fmi3 """ @@ -1308,6 +1355,9 @@ Returns the size of the byte vector the FMU can be stored in function fmiSerializedFMUstateSize(str::fmi2Struct, args...; kwargs...) fmi2SerializedFMUstateSize(str, args...; kwargs...) end +function fmiSerializedFMUstateSize(str::fmi3Struct, args...; kwargs...) + fmi3SerializedFMUstateSize(str, args...; kwargs...) +end # TODO different call in fmi3 """ @@ -1316,6 +1366,9 @@ Serialize the data in the FMU state pointer function fmiSerializeFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SerializeFMUstate(str, args...; kwargs...) end +function fmiSerializeFMUstate(str::fmi3Struct, args...; kwargs...) + fmi3SerializeFMUstate(str, args...; kwargs...) +end # TODO different call in fmi3 """ @@ -1324,6 +1377,9 @@ Deserialize the data in the FMU state pointer function fmiDeSerializeFMUstate(str::fmi2Struct, args...; kwargs...) fmi2DeSerializeFMUstate(str, args...; kwargs...) end +function fmiDeSerializeFMUstate(str::fmi3Struct, args...; kwargs...) + fmi3DeSerializeFMUstate(str, args...; kwargs...) +end """ Returns the values of the directional derivatives. @@ -1345,7 +1401,6 @@ function fmiGetDirectionalDerivative!(str::fmi3Struct, args...; kwargs...) fmi3GetDirectionalDerivative!(str, args...; kwargs...) end -# Add unsupportedFMU for call with FMU2 """ Returns the values of the adjoint derivatives. """ @@ -1406,13 +1461,19 @@ Set a new (continuous) state vector function fmiSetContinuousStates(str::fmi2Struct, args...; kwargs...) fmi2SetContinuousStates(str, args...; kwargs...) end -# TODO more arguments in fmi3 +function fmiSetContinuousStates(str::fmi3Struct, args...; kwargs...) + fmi3SetContinuousStates(str, args...; kwargs...) +end + """ The model enters Event Mode """ -function fmi2EnterEventMode(str::fmi2Struct) +function fmiEnterEventMode(str::fmi2Struct) fmi2EnterEventMode(str) end +function fmiEnterEventMode(str::fmi3Struct) + fmi3EnterEventMode(str) +end # TODO different function call in fmi3 """ Returns the next discrete states From f0a4f9e5f291a392376bf074f50c0b9ac29b9a58 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Fri, 24 Jun 2022 10:45:06 +0200 Subject: [PATCH 18/41] comment tests for fmi3 out for now --- src/FMI.jl | 2 +- test/runtests.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index c08e3e0e..003fe40d 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -620,7 +620,7 @@ function fmiLoad(args...; kwargs...) version = fmiCheckVersion(pathToFMU) if version == "2.0" fmi2Load(args...; kwargs...) - else if version == "3.0" + elseif version == "3.0" fmi3Load(args...; kwargs...) else @warn "fmiLoad(...): Unknown FMU version" diff --git a/test/runtests.jl b/test/runtests.jl index 916ad430..86c0f2a8 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -109,13 +109,13 @@ end @info "Automated testing is supported on Windows." for exportingTool in exportingToolsWindows runtestsFMI2(exportingTool) - runtestsFMI3(exportingTool) + #runtestsFMI3(exportingTool) end elseif Sys.islinux() @info "Automated testing is supported on Linux." for exportingTool in exportingToolsLinux runtestsFMI2(exportingTool) - runtestsFMI3(exportingTool) + #runtestsFMI3(exportingTool) end elseif Sys.isapple() @warn "Test-sets are currrently using Windows- and Linux-FMUs, automated testing for macOS is currently not supported." From d4e821217cc6108dfe411be86bf2f353e8d41c1e Mon Sep 17 00:00:00 2001 From: JoKircher <79573182+JoKircher@users.noreply.github.com> Date: Mon, 27 Jun 2022 12:51:06 +0200 Subject: [PATCH 19/41] WIP: Fmi3 refactor (#126) * Jupyter nbconvert synch - modified, paired .ipynb files * move additional functions to the end * refactor FMI3_additional.jl * update docstrings for wrapper functions * Jupyter nbconvert synch - modified, paired .ipynb files * added FMI3_JLD2.jl * WIP: fmi3 refactor * update tests for FMI3 * WIP: added more fmi3 calls * add help function for fmiLoad * WIP: updated all fmi functions * comment tests for fmi3 out for now Co-authored-by: JoKircher --- docs/src/examples/manipulation.md | 20 +- .../manipulation_files/manipulation_10_0.svg | 78 +- .../manipulation_files/manipulation_18_0.svg | 96 +- docs/src/examples/modelica_conference_2021.md | 26 +- .../modelica_conference_2021_8_0.svg | 64 +- docs/src/examples/multiple_instances.md | 16 +- .../multiple_instances_10_0.svg | 64 +- .../multiple_instances_18_0.svg | 68 +- docs/src/examples/multiprocessing.md | 99 +- docs/src/examples/multithreading.md | 56 +- docs/src/examples/parameterize.md | 28 +- docs/src/examples/simulate.md | 16 +- .../examples/simulate_files/simulate_12_0.svg | 72 +- .../examples/simulate_files/simulate_13_0.svg | 86 +- example/manipulation.ipynb | 281 ++-- example/modelica_conference_2021.ipynb | 177 +- example/multiple_instances.ipynb | 236 +-- example/multiprocessing.ipynb | 179 +- example/multithreading.ipynb | 128 +- example/parameterize.ipynb | 140 +- example/simulate.ipynb | 245 ++- src/FMI.jl | 575 +++++-- src/FMI2_comp_wraps.jl | 54 +- src/FMI3_JLD2.jl | 20 + src/FMI3_additional.jl | 1440 +++-------------- src/FMI3_comp_wraps.jl | 987 ++++++++++- test/{ => FMI2}/cs_me.jl | 0 test/{ => FMI2}/dir_ders.jl | 0 test/{ => FMI2}/getter_setter.jl | 0 test/{ => FMI2}/load_save.jl | 0 test/{ => FMI2}/model_description.jl | 0 test/{ => FMI2}/plots.jl | 0 test/{ => FMI2}/sens.jl | 0 test/{ => FMI2}/sim_CS.jl | 0 test/{ => FMI2}/sim_ME.jl | 0 test/{ => FMI2}/sim_auto.jl | 0 test/{ => FMI2}/state.jl | 0 test/FMI3/cs_me.jl | 57 + test/FMI3/dir_ders.jl | 55 + test/FMI3/getter_setter.jl | 142 ++ test/FMI3/load_save.jl | 45 + test/FMI3/model_description.jl | 35 + test/FMI3/plots.jl | 37 + test/FMI3/sens.jl | 61 + test/FMI3/sim_CS.jl | 86 + test/FMI3/sim_ME.jl | 261 +++ test/FMI3/sim_auto.jl | 61 + test/FMI3/state.jl | 65 + test/runtests.jl | 72 +- 49 files changed, 3723 insertions(+), 2505 deletions(-) create mode 100644 src/FMI3_JLD2.jl rename test/{ => FMI2}/cs_me.jl (100%) rename test/{ => FMI2}/dir_ders.jl (100%) rename test/{ => FMI2}/getter_setter.jl (100%) rename test/{ => FMI2}/load_save.jl (100%) rename test/{ => FMI2}/model_description.jl (100%) rename test/{ => FMI2}/plots.jl (100%) rename test/{ => FMI2}/sens.jl (100%) rename test/{ => FMI2}/sim_CS.jl (100%) rename test/{ => FMI2}/sim_ME.jl (100%) rename test/{ => FMI2}/sim_auto.jl (100%) rename test/{ => FMI2}/state.jl (100%) create mode 100644 test/FMI3/cs_me.jl create mode 100644 test/FMI3/dir_ders.jl create mode 100644 test/FMI3/getter_setter.jl create mode 100644 test/FMI3/load_save.jl create mode 100644 test/FMI3/model_description.jl create mode 100644 test/FMI3/plots.jl create mode 100644 test/FMI3/sens.jl create mode 100644 test/FMI3/sim_CS.jl create mode 100644 test/FMI3/sim_ME.jl create mode 100644 test/FMI3/sim_auto.jl create mode 100644 test/FMI3/state.jl diff --git a/docs/src/examples/manipulation.md b/docs/src/examples/manipulation.md index 01e54c6c..adea4344 100644 --- a/docs/src/examples/manipulation.md +++ b/docs/src/examples/manipulation.md @@ -47,10 +47,6 @@ using FMICore using Plots ``` - ┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMU2Solution}` in module `FMI` - └ @ Base.Docs docs/Docs.jl:240 - - ### Simulation setup Next, the start time and end time of the simulation are set. @@ -82,12 +78,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_AxClYk/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AxClYk/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -130,7 +126,7 @@ vrs = ["mass.s"] simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs) ``` - Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:13 + Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10 @@ -206,7 +202,7 @@ originalGetReal = myFMU.cGetReal - Ptr{Nothing} @0x00007fa504ca1faf + Ptr{Nothing} @0x00007f52e9530faf @@ -254,7 +250,7 @@ fmiSetFctGetReal(myFMU, myGetReal!) - Ptr{Nothing} @0x00007fa54dafdfc0 + Ptr{Nothing} @0x00007f533e325fc0 diff --git a/docs/src/examples/manipulation_files/manipulation_10_0.svg b/docs/src/examples/manipulation_files/manipulation_10_0.svg index c9ae6c2d..b86d3be2 100644 --- a/docs/src/examples/manipulation_files/manipulation_10_0.svg +++ b/docs/src/examples/manipulation_files/manipulation_10_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/manipulation_files/manipulation_18_0.svg b/docs/src/examples/manipulation_files/manipulation_18_0.svg index a319441a..d9cf606b 100644 --- a/docs/src/examples/manipulation_files/manipulation_18_0.svg +++ b/docs/src/examples/manipulation_files/manipulation_18_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/modelica_conference_2021.md b/docs/src/examples/modelica_conference_2021.md index e4612a31..c77e978a 100644 --- a/docs/src/examples/modelica_conference_2021.md +++ b/docs/src/examples/modelica_conference_2021.md @@ -45,10 +45,6 @@ using FMIZoo using Plots ``` - ┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI` - └ @ Base.Docs docs/Docs.jl:240 - - ### Simulation setup Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. @@ -81,12 +77,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_dg2hpy/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_dg2hpy/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -151,12 +147,12 @@ In the following type of simulation a more advanced variant is presented, which myFMU = fmiLoad(pathToFMU); ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HuQTow/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HuQTow/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. @@ -171,7 +167,7 @@ instanceFMU = fmiInstantiate!(myFMU) FMU: SpringFrictionPendulum1D InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000005fcca40 + Address: Ptr{Nothing} @0x00000000064853f0 State: fmi2ComponentStateInstantiated Logging: false FMU time: -Inf diff --git a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg index 0a7ac6a2..c714d93e 100644 --- a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg +++ b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/multiple_instances.md b/docs/src/examples/multiple_instances.md index 79a1461b..d20d0c7f 100644 --- a/docs/src/examples/multiple_instances.md +++ b/docs/src/examples/multiple_instances.md @@ -78,12 +78,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_KBJT4J/SpringPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_KBJT4J/SpringPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -128,7 +128,7 @@ println(comp1) FMU: SpringPendulum1D InstanceName: [not defined] - Address: Ptr{Nothing} @0x000000000348d080 + Address: Ptr{Nothing} @0x0000000003954580 State: fmi2ComponentStateInstantiated Logging: false FMU time: -Inf @@ -173,9 +173,9 @@ println(comp2) FMU: SpringPendulum1D InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000006214590 + Address: Ptr{Nothing} @0x000000000529d440 State: fmi2ComponentStateInstantiated - Logging: true + Logging: false FMU time: -Inf FMU states: nothing diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg index 48bec0bb..cf0fca99 100644 --- a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg +++ b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg index 04f52296..8004ffcf 100644 --- a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg +++ b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg @@ -1,93 +1,93 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/multiprocessing.md b/docs/src/examples/multiprocessing.md index 61656784..365cdee4 100644 --- a/docs/src/examples/multiprocessing.md +++ b/docs/src/examples/multiprocessing.md @@ -90,10 +90,10 @@ workers() # @everywhere println(Threads.nthreads()) ``` - From worker 3: Hello World! + Hello World! From worker 2: Hello World! From worker 4: Hello World! - Hello World! + From worker 3: Hello World! From worker 5: Hello World! @@ -115,22 +115,22 @@ input_values = collect(collect.(eachrow(rand(batchSize,2)))) 16-element Vector{Vector{Float64}}: - [0.8522478954672708, 0.7209431226036078] - [0.909306253617912, 0.6209402039669427] - [0.4596043790366431, 0.2389289971087898] - [0.4934930898692784, 0.8535888352523144] - [0.9008166213933464, 0.48097066683100986] - [0.30695689796078574, 0.8999444231606255] - [0.5676033936598277, 0.0170782917662895] - [0.43299006096393633, 0.6018253815343202] - [0.8863999765881179, 0.5879607966583695] - [0.9250498940640433, 0.676688143062196] - [0.5927221115688299, 0.13661645859930105] - [0.5274125466018458, 0.6019662513572075] - [0.7212113914423361, 0.6184174840746639] - [0.5904677676104344, 0.9526791253940541] - [0.7887765751716826, 0.32324579460992675] - [0.867048815207933, 0.728198232394913] + [0.053272555584304104, 0.45774751559489646] + [0.5896778258750763, 0.12435199368996086] + [0.5651662129022856, 0.8764873667695812] + [0.6176612662918868, 0.2785804850450695] + [0.9274233385552415, 0.38275426899967724] + [0.46094177953642124, 0.6554519159504497] + [0.73421590884579, 0.28177572874256906] + [0.5575198504784948, 0.3212214708846175] + [0.271126562512229, 0.6499895887749823] + [0.5289045741655536, 0.4873381265273107] + [0.8565770844036877, 0.2312687408548988] + [0.06332369482582334, 0.44807066874864065] + [0.08611017776660712, 0.960898209225902] + [0.3191189843443898, 0.30014344015893846] + [0.028884098958377402, 0.5285860311385517] + [0.7282727650515579, 0.7584435212215901] @@ -153,23 +153,23 @@ For Distributed we need to embed the FMU into its own `module`. This prevents Di end ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ywfEtU/SpringPendulum1D`. + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ywfEtU/SpringPendulum1D/resources` + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources` └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_WvJUQ4/SpringPendulum1D`. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_kty5Tc/SpringPendulum1D`. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ElhvF8/SpringPendulum1D`. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_WvJUQ4/SpringPendulum1D/resources` + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`. + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_kty5Tc/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ElhvF8/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_RvaFkX/SpringPendulum1D`. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RvaFkX/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources` [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. @@ -193,16 +193,16 @@ Running a single evaluation is pretty quick, therefore the speed can be better t - BenchmarkTools.Trial: 16 samples with 1 evaluation. - Range (min … max): 301.517 ms … 343.653 ms ┊ GC (min … max): 6.30% … 8.37% - Time (median): 325.148 ms ┊ GC (median): 5.92% - Time (mean ± σ): 324.977 ms ±  11.601 ms ┊ GC (mean ± σ): 6.39% ± 1.09% + BenchmarkTools.Trial: 17 samples with 1 evaluation. + Range (min … max): 304.291 ms … 325.332 ms ┊ GC (min … max): 7.41% … 6.89% + Time (median): 307.274 ms ┊ GC (median): 7.37% + Time (mean ± σ): 309.397 ms ±  5.860 ms ┊ GC (mean ± σ): 7.94% ± 1.32% - ▁        ▁      ▁    ▁  ▁   ▁▁   ▁ ▁        ██     ▁▁       ▁  - █▁▁▁▁▁▁▁▁█▁▁▁▁▁▁█▁▁▁▁█▁▁█▁▁▁██▁▁▁█▁█▁▁▁▁▁▁▁▁██▁▁▁▁▁██▁▁▁▁▁▁▁█ ▁ - 302 ms Histogram: frequency by time 344 ms < + █▁▁ ▁█ ▁▁  █▁▁                   ▁ ▁ ▁                      ▁  + ███▁██▁██▁▁███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁█▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 304 ms Histogram: frequency by time 325 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002431. + Memory estimate: 146.80 MiB, allocs estimate: 3002433. @@ -221,9 +221,16 @@ println("Single Threaded") - BenchmarkTools.Trial: 1 sample with 1 evaluation. - Single result which took 5.128 s (6.62% GC) to evaluate, - with a memory estimate of 2.29 GiB, over 48038884 allocations. + BenchmarkTools.Trial: 2 samples with 1 evaluation. + Range (min … max): 4.966 s …  4.967 s ┊ GC (min … max): 8.58% … 8.12% + Time (median): 4.966 s ┊ GC (median): 8.35% + Time (mean ± σ): 4.966 s ± 1.039 ms ┊ GC (mean ± σ): 8.35% ± 0.33% + + █                                                      █  + █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 4.97 s Histogram: frequency by time 4.97 s < + + Memory estimate: 2.29 GiB, allocs estimate: 48038916. @@ -244,15 +251,15 @@ println("Multi Threaded") BenchmarkTools.Trial: 2 samples with 1 evaluation. - Range (min … max): 3.323 s …  3.367 s ┊ GC (min … max): 0.00% … 0.00% - Time (median): 3.345 s ┊ GC (median): 0.00% - Time (mean ± σ): 3.345 s ± 31.349 ms ┊ GC (mean ± σ): 0.00% ± 0.00% + Range (min … max): 3.069 s …  3.078 s ┊ GC (min … max): 0.00% … 0.00% + Time (median): 3.074 s ┊ GC (median): 0.00% + Time (mean ± σ): 3.074 s ± 6.467 ms ┊ GC (mean ± σ): 0.00% ± 0.00% - █                                                       █  - █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 3.32 s Histogram: frequency by time 3.37 s < + █                                                      █  + █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 3.07 s Histogram: frequency by time 3.08 s < - Memory estimate: 81.44 KiB, allocs estimate: 1198. + Memory estimate: 81.31 KiB, allocs estimate: 1192. diff --git a/docs/src/examples/multithreading.md b/docs/src/examples/multithreading.md index 47ce6dac..3f1d0979 100644 --- a/docs/src/examples/multithreading.md +++ b/docs/src/examples/multithreading.md @@ -94,7 +94,7 @@ input_values = collect(collect.(eachrow(rand(batchSize,2)))) 1-element Vector{Vector{Float64}}: - [0.7810829477429659, 0.42733298165721023] + [0.769193342919982, 0.5516183754569333] @@ -109,15 +109,15 @@ realFMU = fmiLoad("SpringPendulum1D", "Dymola", "2022x") realFMUBatch = [fmiLoad("SpringPendulum1D", "Dymola", "2022x") for _ in 1:batchSize] ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_AeQVGo/SpringPendulum1D`. + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AeQVGo/SpringPendulum1D/resources` + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources` └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_6YywFr/SpringPendulum1D`. + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_6YywFr/SpringPendulum1D/resources` + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources` └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 @@ -159,16 +159,16 @@ Running a single evaluation is pretty quick, therefore the speed can be better t - BenchmarkTools.Trial: 14 samples with 1 evaluation. - Range (min … max): 337.440 ms … 389.386 ms ┊ GC (min … max): 5.75% … 5.28% - Time (median): 372.244 ms ┊ GC (median): 5.52% - Time (mean ± σ): 368.214 ms ±  15.573 ms ┊ GC (mean ± σ): 5.91% ± 0.96% + BenchmarkTools.Trial: 15 samples with 1 evaluation. + Range (min … max): 337.943 ms … 357.340 ms ┊ GC (min … max): 7.03% … 6.55% + Time (median): 339.287 ms ┊ GC (median): 7.00% + Time (mean ± σ): 342.299 ms ±  5.982 ms ┊ GC (mean ± σ): 7.39% ± 1.12% - █              █ █    █ █  █          █   █ █   ██   █    █ █  - █▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁█▁▁▁▁█▁█▁▁█▁▁▁▁▁▁▁▁▁▁█▁▁▁█▁█▁▁▁██▁▁▁█▁▁▁▁█▁█ ▁ - 337 ms Histogram: frequency by time 389 ms < + ▃█                                                             + ██▇▇▇▇▁▁▇▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇ ▁ + 338 ms Histogram: frequency by time 357 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002431. + Memory estimate: 146.80 MiB, allocs estimate: 3002433. @@ -188,15 +188,15 @@ println("Single Threaded") BenchmarkTools.Trial: 15 samples with 1 evaluation. - Range (min … max): 340.025 ms … 386.317 ms ┊ GC (min … max): 6.05% … 5.51% - Time (median): 353.427 ms ┊ GC (median): 5.97% - Time (mean ± σ): 355.542 ms ±  12.557 ms ┊ GC (mean ± σ): 6.24% ± 1.07% + Range (min … max): 338.941 ms … 359.792 ms ┊ GC (min … max): 7.42% … 7.05% + Time (median): 340.880 ms ┊ GC (median): 7.45% + Time (mean ± σ): 343.682 ms ±  6.291 ms ┊ GC (mean ± σ): 7.89% ± 1.20% - █  ▁  ▁▁      ▁ ▁▁  ▁    ▁  ▁▁      █                       ▁  - █▁▁█▁▁██▁▁▁▁▁▁█▁██▁▁█▁▁▁▁█▁▁██▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 340 ms Histogram: frequency by time 386 ms < + █▁▁▁▁█  ▁▁▁    ▁                        ▁▁                  ▁  + ██████▁▁███▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 339 ms Histogram: frequency by time 360 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002434. + Memory estimate: 146.80 MiB, allocs estimate: 3002436. @@ -216,16 +216,16 @@ println("Multi Threaded") - BenchmarkTools.Trial: 16 samples with 1 evaluation. - Range (min … max): 304.578 ms … 342.615 ms ┊ GC (min … max): 7.13% … 6.47% - Time (median): 314.032 ms ┊ GC (median): 6.84% - Time (mean ± σ): 316.672 ms ±  10.042 ms ┊ GC (mean ± σ): 6.99% ± 0.78% + BenchmarkTools.Trial: 17 samples with 1 evaluation. + Range (min … max): 307.665 ms … 325.644 ms ┊ GC (min … max): 8.44% … 8.13% + Time (median): 308.448 ms ┊ GC (median): 8.55% + Time (mean ± σ): 310.319 ms ±  4.970 ms ┊ GC (mean ± σ): 8.72% ± 0.86% - ▁     █▁  ▁  ▁█▁ ▁   ▁▁█                           ▁        ▁  - █▁▁▁▁▁██▁▁█▁▁███▁█▁▁▁███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁█ ▁ - 305 ms Histogram: frequency by time 343 ms < + █ █ ▁   ▁                                                      + █▆█▆█▁▆▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆ ▁ + 308 ms Histogram: frequency by time 326 ms < - Memory estimate: 146.80 MiB, allocs estimate: 3002438. + Memory estimate: 146.80 MiB, allocs estimate: 3002440. diff --git a/docs/src/examples/parameterize.md b/docs/src/examples/parameterize.md index d45d0e1d..67856f28 100644 --- a/docs/src/examples/parameterize.md +++ b/docs/src/examples/parameterize.md @@ -70,12 +70,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_E6omKF/IO`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_E6omKF/IO/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -125,9 +125,9 @@ fmiInstantiate!(myFMU; loggingOn=true) FMU: IO InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000003ae6b10 + Address: Ptr{Nothing} @0x00000000029c12e0 State: fmi2ComponentStateInstantiated - Logging: false + Logging: true FMU time: -Inf FMU states: nothing @@ -212,7 +212,7 @@ The previously defined function is called and the results are displayed in the c paramsVal = generateRandomNumbers(); ``` - Any[41.68976766058903, 91, false, "Random number 18.117421661942835!"] + Any[27.27027116078753, 50, true, "Random number 83.09640957659121!"] #### First variant @@ -228,7 +228,7 @@ print(values) @assert paramsVal == values ``` - Any[41.68976766058903, 91, 0, "Random number 18.117421661942835!"] + Any[27.27027116078753, 50, 1, "Random number 83.09640957659121!"] #### Second variant @@ -239,7 +239,7 @@ To make sure that the functions work it is necessary to generate random numbers rndReal, rndInteger, rndBoolean, rndString = generateRandomNumbers(); ``` - Any[32.87773039642885, 58, false, "Random number 22.4054218867213!"] + Any[54.98169316988619, 76, true, "Random number 39.54384075977397!"] In the second variant, the value for each data type is set separately by the corresponding command. By this variant one has the maximum control and can be sure that also the correct data type is set. To illustrate the functionality of the parameterization with the separate functions, the corresponding get function is also called separately for each data type: @@ -264,19 +264,19 @@ display("$rndString == $(fmiGetString(myFMU, "p_string"))") ``` - "32.87773039642885 == 32.87773039642885" + "54.98169316988619 == 54.98169316988619" - "58 == 58" + "76 == 76" - "false == 0" + "true == 1" - "Random number 22.4054218867213! == Random number 22.4054218867213!" + "Random number 39.54384075977397! == Random number 39.54384075977397!" After seeing that both variants set the parameters correctly, the initialization mode is terminated with the function `fmiExitInitializationMode()`. diff --git a/docs/src/examples/simulate.md b/docs/src/examples/simulate.md index 56874dd7..b208de41 100644 --- a/docs/src/examples/simulate.md +++ b/docs/src/examples/simulate.md @@ -45,10 +45,6 @@ using FMIZoo using Plots ``` - ┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI` - └ @ Base.Docs docs/Docs.jl:240 - - ### Simulation setup Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. @@ -83,12 +79,12 @@ myFMU = fmiLoad(pathToFMU) fmiInfo(myFMU) ``` - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_TJndII/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_TJndII/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 #################### Begin information for FMU #################### @@ -168,7 +164,7 @@ In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (M dataME = fmiSimulateME(myFMU, tStart, tStop; saveat=tSave) ``` - Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:11 + Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09 diff --git a/docs/src/examples/simulate_files/simulate_12_0.svg b/docs/src/examples/simulate_files/simulate_12_0.svg index e3cf1302..6f603526 100644 --- a/docs/src/examples/simulate_files/simulate_12_0.svg +++ b/docs/src/examples/simulate_files/simulate_12_0.svg @@ -1,99 +1,99 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/src/examples/simulate_files/simulate_13_0.svg b/docs/src/examples/simulate_files/simulate_13_0.svg index e4c9bcdd..2dc08e6e 100644 --- a/docs/src/examples/simulate_files/simulate_13_0.svg +++ b/docs/src/examples/simulate_files/simulate_13_0.svg @@ -1,99 +1,99 @@ - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/example/manipulation.ipynb b/example/manipulation.ipynb index f7f16b44..eb98a208 100644 --- a/example/manipulation.ipynb +++ b/example/manipulation.ipynb @@ -55,23 +55,14 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:05.916000Z", - "iopub.status.busy": "2022-05-24T15:05:04.955000Z", - "iopub.status.idle": "2022-05-24T15:05:35.479000Z", - "shell.execute_reply": "2022-05-24T15:05:35.382000Z" + "iopub.execute_input": "2022-06-01T15:15:09.601000Z", + "iopub.status.busy": "2022-06-01T15:15:08.923000Z", + "iopub.status.idle": "2022-06-01T15:15:32.386000Z", + "shell.execute_reply": "2022-06-01T15:15:32.310000Z" }, "scrolled": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], + "outputs": [], "source": [ "# imports\n", "using FMI\n", @@ -94,10 +85,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:46.559000Z", - "iopub.status.busy": "2022-05-24T15:05:35.482000Z", - "iopub.status.idle": "2022-05-24T15:05:47.511000Z", - "shell.execute_reply": "2022-05-24T15:05:47.511000Z" + "iopub.execute_input": "2022-06-01T15:15:41.170000Z", + "iopub.status.busy": "2022-06-01T15:15:32.388000Z", + "iopub.status.idle": "2022-06-01T15:15:41.848000Z", + "shell.execute_reply": "2022-06-01T15:15:41.848000Z" }, "scrolled": false }, @@ -132,10 +123,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:47.516000Z", - "iopub.status.busy": "2022-05-24T15:05:47.515000Z", - "iopub.status.idle": "2022-05-24T15:05:53.086000Z", - "shell.execute_reply": "2022-05-24T15:05:53.085000Z" + "iopub.execute_input": "2022-06-01T15:15:41.877000Z", + "iopub.status.busy": "2022-06-01T15:15:41.877000Z", + "iopub.status.idle": "2022-06-01T15:15:46.248000Z", + "shell.execute_reply": "2022-06-01T15:15:46.248000Z" }, "scrolled": false }, @@ -144,12 +135,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_AxClYk/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AxClYk/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -209,10 +200,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:05:53.089000Z", - "iopub.status.busy": "2022-05-24T15:05:53.089000Z", - "iopub.status.idle": "2022-05-24T15:06:16.714000Z", - "shell.execute_reply": "2022-05-24T15:06:16.714000Z" + "iopub.execute_input": "2022-06-01T15:15:46.250000Z", + "iopub.status.busy": "2022-06-01T15:15:46.250000Z", + "iopub.status.idle": "2022-06-01T15:16:04.451000Z", + "shell.execute_reply": "2022-06-01T15:16:04.450000Z" } }, "outputs": [ @@ -220,7 +211,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:13\u001b[39m\n" + "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10\u001b[39m\n" ] }, { @@ -288,10 +279,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:16.718000Z", - "iopub.status.busy": "2022-05-24T15:06:16.718000Z", - "iopub.status.idle": "2022-05-24T15:06:41.814000Z", - "shell.execute_reply": "2022-05-24T15:06:41.814000Z" + "iopub.execute_input": "2022-06-01T15:16:04.454000Z", + "iopub.status.busy": "2022-06-01T15:16:04.454000Z", + "iopub.status.idle": "2022-06-01T15:16:23.184000Z", + "shell.execute_reply": "2022-06-01T15:16:23.184000Z" }, "scrolled": false }, @@ -302,93 +293,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 5, @@ -458,17 +449,17 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:41.820000Z", - "iopub.status.busy": "2022-05-24T15:06:41.819000Z", - "iopub.status.idle": "2022-05-24T15:06:42.710000Z", - "shell.execute_reply": "2022-05-24T15:06:42.710000Z" + "iopub.execute_input": "2022-06-01T15:16:23.189000Z", + "iopub.status.busy": "2022-06-01T15:16:23.188000Z", + "iopub.status.idle": "2022-06-01T15:16:23.780000Z", + "shell.execute_reply": "2022-06-01T15:16:23.780000Z" } }, "outputs": [ { "data": { "text/plain": [ - "Ptr{Nothing} @0x00007fa504ca1faf" + "Ptr{Nothing} @0x00007f52e9530faf" ] }, "execution_count": 6, @@ -495,10 +486,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:42.716000Z", - "iopub.status.busy": "2022-05-24T15:06:42.716000Z", - "iopub.status.idle": "2022-05-24T15:06:43.882000Z", - "shell.execute_reply": "2022-05-24T15:06:43.882000Z" + "iopub.execute_input": "2022-06-01T15:16:23.784000Z", + "iopub.status.busy": "2022-06-01T15:16:23.784000Z", + "iopub.status.idle": "2022-06-01T15:16:24.562000Z", + "shell.execute_reply": "2022-06-01T15:16:24.562000Z" } }, "outputs": [ @@ -546,17 +537,17 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:43.887000Z", - "iopub.status.busy": "2022-05-24T15:06:43.887000Z", - "iopub.status.idle": "2022-05-24T15:06:43.906000Z", - "shell.execute_reply": "2022-05-24T15:06:43.906000Z" + "iopub.execute_input": "2022-06-01T15:16:24.566000Z", + "iopub.status.busy": "2022-06-01T15:16:24.565000Z", + "iopub.status.idle": "2022-06-01T15:16:24.578000Z", + "shell.execute_reply": "2022-06-01T15:16:24.578000Z" } }, "outputs": [ { "data": { "text/plain": [ - "Ptr{Nothing} @0x00007fa54dafdfc0" + "Ptr{Nothing} @0x00007f533e325fc0" ] }, "execution_count": 8, @@ -583,10 +574,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:43.910000Z", - "iopub.status.busy": "2022-05-24T15:06:43.910000Z", - "iopub.status.idle": "2022-05-24T15:06:44.437000Z", - "shell.execute_reply": "2022-05-24T15:06:44.437000Z" + "iopub.execute_input": "2022-06-01T15:16:24.581000Z", + "iopub.status.busy": "2022-06-01T15:16:24.581000Z", + "iopub.status.idle": "2022-06-01T15:16:24.963000Z", + "shell.execute_reply": "2022-06-01T15:16:24.963000Z" } }, "outputs": [ @@ -596,93 +587,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 9, @@ -798,10 +789,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:44.442000Z", - "iopub.status.busy": "2022-05-24T15:06:44.442000Z", - "iopub.status.idle": "2022-05-24T15:06:44.500000Z", - "shell.execute_reply": "2022-05-24T15:06:44.500000Z" + "iopub.execute_input": "2022-06-01T15:16:24.967000Z", + "iopub.status.busy": "2022-06-01T15:16:24.967000Z", + "iopub.status.idle": "2022-06-01T15:16:25.011000Z", + "shell.execute_reply": "2022-06-01T15:16:25.011000Z" } }, "outputs": [], diff --git a/example/modelica_conference_2021.ipynb b/example/modelica_conference_2021.ipynb index 7f6e2473..7210b368 100644 --- a/example/modelica_conference_2021.ipynb +++ b/example/modelica_conference_2021.ipynb @@ -54,23 +54,14 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:06:56.032000Z", - "iopub.status.busy": "2022-05-24T15:06:55.083000Z", - "iopub.status.idle": "2022-05-24T15:07:25.235000Z", - "shell.execute_reply": "2022-05-24T15:07:25.141000Z" + "iopub.execute_input": "2022-06-01T15:16:34.235000Z", + "iopub.status.busy": "2022-06-01T15:16:33.558000Z", + "iopub.status.idle": "2022-06-01T15:16:56.948000Z", + "shell.execute_reply": "2022-06-01T15:16:56.869000Z" }, "scrolled": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], + "outputs": [], "source": [ "# imports\n", "using FMI\n", @@ -92,10 +83,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:07:36.354000Z", - "iopub.status.busy": "2022-05-24T15:07:25.239000Z", - "iopub.status.idle": "2022-05-24T15:07:37.433000Z", - "shell.execute_reply": "2022-05-24T15:07:37.433000Z" + "iopub.execute_input": "2022-06-01T15:17:05.805000Z", + "iopub.status.busy": "2022-06-01T15:16:56.951000Z", + "iopub.status.idle": "2022-06-01T15:17:06.600000Z", + "shell.execute_reply": "2022-06-01T15:17:06.600000Z" }, "scrolled": false }, @@ -132,10 +123,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:07:37.438000Z", - "iopub.status.busy": "2022-05-24T15:07:37.438000Z", - "iopub.status.idle": "2022-05-24T15:07:43.049000Z", - "shell.execute_reply": "2022-05-24T15:07:43.049000Z" + "iopub.execute_input": "2022-06-01T15:17:06.604000Z", + "iopub.status.busy": "2022-06-01T15:17:06.604000Z", + "iopub.status.idle": "2022-06-01T15:17:10.951000Z", + "shell.execute_reply": "2022-06-01T15:17:10.951000Z" } }, "outputs": [ @@ -143,12 +134,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_dg2hpy/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_dg2hpy/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -205,10 +196,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:07:43.052000Z", - "iopub.status.busy": "2022-05-24T15:07:43.052000Z", - "iopub.status.idle": "2022-05-24T15:08:18.695000Z", - "shell.execute_reply": "2022-05-24T15:08:18.695000Z" + "iopub.execute_input": "2022-06-01T15:17:10.954000Z", + "iopub.status.busy": "2022-06-01T15:17:10.953000Z", + "iopub.status.idle": "2022-06-01T15:17:37.913000Z", + "shell.execute_reply": "2022-06-01T15:17:37.913000Z" }, "scrolled": false }, @@ -219,93 +210,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 4, @@ -350,10 +341,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.700000Z", - "iopub.status.busy": "2022-05-24T15:08:18.700000Z", - "iopub.status.idle": "2022-05-24T15:08:18.758000Z", - "shell.execute_reply": "2022-05-24T15:08:18.758000Z" + "iopub.execute_input": "2022-06-01T15:17:37.918000Z", + "iopub.status.busy": "2022-06-01T15:17:37.917000Z", + "iopub.status.idle": "2022-06-01T15:17:37.960000Z", + "shell.execute_reply": "2022-06-01T15:17:37.960000Z" } }, "outputs": [], @@ -375,10 +366,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.761000Z", - "iopub.status.busy": "2022-05-24T15:08:18.760000Z", - "iopub.status.idle": "2022-05-24T15:08:18.835000Z", - "shell.execute_reply": "2022-05-24T15:08:18.835000Z" + "iopub.execute_input": "2022-06-01T15:17:37.962000Z", + "iopub.status.busy": "2022-06-01T15:17:37.962000Z", + "iopub.status.idle": "2022-06-01T15:17:38.024000Z", + "shell.execute_reply": "2022-06-01T15:17:38.024000Z" } }, "outputs": [ @@ -386,12 +377,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HuQTow/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HuQTow/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] } ], @@ -411,10 +402,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.840000Z", - "iopub.status.busy": "2022-05-24T15:08:18.839000Z", - "iopub.status.idle": "2022-05-24T15:08:19.277000Z", - "shell.execute_reply": "2022-05-24T15:08:19.277000Z" + "iopub.execute_input": "2022-06-01T15:17:38.028000Z", + "iopub.status.busy": "2022-06-01T15:17:38.027000Z", + "iopub.status.idle": "2022-06-01T15:17:38.349000Z", + "shell.execute_reply": "2022-06-01T15:17:38.349000Z" } }, "outputs": [ @@ -423,7 +414,7 @@ "text/plain": [ "FMU: SpringFrictionPendulum1D\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000005fcca40\n", + "Address: Ptr{Nothing} @0x00000000064853f0\n", "State: fmi2ComponentStateInstantiated\n", "Logging: false\n", "FMU time: -Inf\n", @@ -451,10 +442,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.282000Z", - "iopub.status.busy": "2022-05-24T15:08:19.282000Z", - "iopub.status.idle": "2022-05-24T15:08:19.638000Z", - "shell.execute_reply": "2022-05-24T15:08:19.638000Z" + "iopub.execute_input": "2022-06-01T15:17:38.353000Z", + "iopub.status.busy": "2022-06-01T15:17:38.352000Z", + "iopub.status.idle": "2022-06-01T15:17:38.617000Z", + "shell.execute_reply": "2022-06-01T15:17:38.617000Z" } }, "outputs": [ @@ -488,10 +479,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.642000Z", - "iopub.status.busy": "2022-05-24T15:08:19.642000Z", - "iopub.status.idle": "2022-05-24T15:08:19.692000Z", - "shell.execute_reply": "2022-05-24T15:08:19.692000Z" + "iopub.execute_input": "2022-06-01T15:17:38.620000Z", + "iopub.status.busy": "2022-06-01T15:17:38.620000Z", + "iopub.status.idle": "2022-06-01T15:17:38.657000Z", + "shell.execute_reply": "2022-06-01T15:17:38.657000Z" } }, "outputs": [], @@ -517,10 +508,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.695000Z", - "iopub.status.busy": "2022-05-24T15:08:19.695000Z", - "iopub.status.idle": "2022-05-24T15:08:19.705000Z", - "shell.execute_reply": "2022-05-24T15:08:19.705000Z" + "iopub.execute_input": "2022-06-01T15:17:38.660000Z", + "iopub.status.busy": "2022-06-01T15:17:38.660000Z", + "iopub.status.idle": "2022-06-01T15:17:38.668000Z", + "shell.execute_reply": "2022-06-01T15:17:38.667000Z" } }, "outputs": [], diff --git a/example/multiple_instances.ipynb b/example/multiple_instances.ipynb index df73564a..93f49f93 100644 --- a/example/multiple_instances.ipynb +++ b/example/multiple_instances.ipynb @@ -54,10 +54,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:49:29.382000Z", - "iopub.status.busy": "2022-05-25T10:49:28.749000Z", - "iopub.status.idle": "2022-05-25T10:49:50.382000Z", - "shell.execute_reply": "2022-05-25T10:49:50.309000Z" + "iopub.execute_input": "2022-06-01T15:17:48.035000Z", + "iopub.status.busy": "2022-06-01T15:17:47.343000Z", + "iopub.status.idle": "2022-06-01T15:18:10.300000Z", + "shell.execute_reply": "2022-06-01T15:18:10.226000Z" }, "scrolled": false }, @@ -83,10 +83,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:49:58.432000Z", - "iopub.status.busy": "2022-05-25T10:49:50.384000Z", - "iopub.status.idle": "2022-05-25T10:50:01.238000Z", - "shell.execute_reply": "2022-05-25T10:50:01.238000Z" + "iopub.execute_input": "2022-06-01T15:18:19.079000Z", + "iopub.status.busy": "2022-06-01T15:18:10.303000Z", + "iopub.status.idle": "2022-06-01T15:18:21.932000Z", + "shell.execute_reply": "2022-06-01T15:18:21.932000Z" }, "scrolled": false }, @@ -124,10 +124,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:01.262000Z", - "iopub.status.busy": "2022-05-25T10:50:01.262000Z", - "iopub.status.idle": "2022-05-25T10:50:05.354000Z", - "shell.execute_reply": "2022-05-25T10:50:05.354000Z" + "iopub.execute_input": "2022-06-01T15:18:21.935000Z", + "iopub.status.busy": "2022-06-01T15:18:21.935000Z", + "iopub.status.idle": "2022-06-01T15:18:26.345000Z", + "shell.execute_reply": "2022-06-01T15:18:26.345000Z" }, "scrolled": false }, @@ -136,12 +136,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_KBJT4J/SpringPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_KBJT4J/SpringPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -200,10 +200,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:05.356000Z", - "iopub.status.busy": "2022-05-25T10:50:05.356000Z", - "iopub.status.idle": "2022-05-25T10:50:05.919000Z", - "shell.execute_reply": "2022-05-25T10:50:05.919000Z" + "iopub.execute_input": "2022-06-01T15:18:26.348000Z", + "iopub.status.busy": "2022-06-01T15:18:26.348000Z", + "iopub.status.idle": "2022-06-01T15:18:26.776000Z", + "shell.execute_reply": "2022-06-01T15:18:26.776000Z" } }, "outputs": [ @@ -213,7 +213,7 @@ "text": [ "FMU: SpringPendulum1D\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x000000000348d080\n", + "Address: Ptr{Nothing} @0x0000000003954580\n", "State: fmi2ComponentStateInstantiated\n", "Logging: false\n", "FMU time: -Inf\n", @@ -239,10 +239,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:05.922000Z", - "iopub.status.busy": "2022-05-25T10:50:05.922000Z", - "iopub.status.idle": "2022-05-25T10:50:31.527000Z", - "shell.execute_reply": "2022-05-25T10:50:31.526000Z" + "iopub.execute_input": "2022-06-01T15:18:26.779000Z", + "iopub.status.busy": "2022-06-01T15:18:26.779000Z", + "iopub.status.idle": "2022-06-01T15:18:52.116000Z", + "shell.execute_reply": "2022-06-01T15:18:52.116000Z" } }, "outputs": [ @@ -252,93 +252,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 5, @@ -1176,10 +1176,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.532000Z", - "iopub.status.busy": "2022-05-25T10:50:31.531000Z", - "iopub.status.idle": "2022-05-25T10:50:31.566000Z", - "shell.execute_reply": "2022-05-25T10:50:31.566000Z" + "iopub.execute_input": "2022-06-01T15:18:52.122000Z", + "iopub.status.busy": "2022-06-01T15:18:52.122000Z", + "iopub.status.idle": "2022-06-01T15:18:52.160000Z", + "shell.execute_reply": "2022-06-01T15:18:52.160000Z" } }, "outputs": [], @@ -1201,10 +1201,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.568000Z", - "iopub.status.busy": "2022-05-25T10:50:31.568000Z", - "iopub.status.idle": "2022-05-25T10:50:31.571000Z", - "shell.execute_reply": "2022-05-25T10:50:31.570000Z" + "iopub.execute_input": "2022-06-01T15:18:52.163000Z", + "iopub.status.busy": "2022-06-01T15:18:52.163000Z", + "iopub.status.idle": "2022-06-01T15:18:52.166000Z", + "shell.execute_reply": "2022-06-01T15:18:52.166000Z" } }, "outputs": [ @@ -1214,9 +1214,9 @@ "text": [ "FMU: SpringPendulum1D\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000006214590\n", + "Address: Ptr{Nothing} @0x000000000529d440\n", "State: fmi2ComponentStateInstantiated\n", - "Logging: true\n", + "Logging: false\n", "FMU time: -Inf\n", "FMU states: nothing\n" ] @@ -1240,10 +1240,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.573000Z", - "iopub.status.busy": "2022-05-25T10:50:31.573000Z", - "iopub.status.idle": "2022-05-25T10:50:31.573000Z", - "shell.execute_reply": "2022-05-25T10:50:31.573000Z" + "iopub.execute_input": "2022-06-01T15:18:52.168000Z", + "iopub.status.busy": "2022-06-01T15:18:52.168000Z", + "iopub.status.idle": "2022-06-01T15:18:52.169000Z", + "shell.execute_reply": "2022-06-01T15:18:52.169000Z" } }, "outputs": [], @@ -1263,10 +1263,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.576000Z", - "iopub.status.busy": "2022-05-25T10:50:31.575000Z", - "iopub.status.idle": "2022-05-25T10:50:31.676000Z", - "shell.execute_reply": "2022-05-25T10:50:31.676000Z" + "iopub.execute_input": "2022-06-01T15:18:52.171000Z", + "iopub.status.busy": "2022-06-01T15:18:52.171000Z", + "iopub.status.idle": "2022-06-01T15:18:52.280000Z", + "shell.execute_reply": "2022-06-01T15:18:52.280000Z" } }, "outputs": [ @@ -1276,93 +1276,93 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 9, @@ -3006,10 +3006,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.682000Z", - "iopub.status.busy": "2022-05-25T10:50:31.682000Z", - "iopub.status.idle": "2022-05-25T10:50:31.683000Z", - "shell.execute_reply": "2022-05-25T10:50:31.683000Z" + "iopub.execute_input": "2022-06-01T15:18:52.288000Z", + "iopub.status.busy": "2022-06-01T15:18:52.288000Z", + "iopub.status.idle": "2022-06-01T15:18:52.289000Z", + "shell.execute_reply": "2022-06-01T15:18:52.289000Z" } }, "outputs": [], @@ -3031,10 +3031,10 @@ "execution_count": 11, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.685000Z", - "iopub.status.busy": "2022-05-25T10:50:31.685000Z", - "iopub.status.idle": "2022-05-25T10:50:31.724000Z", - "shell.execute_reply": "2022-05-25T10:50:31.724000Z" + "iopub.execute_input": "2022-06-01T15:18:52.291000Z", + "iopub.status.busy": "2022-06-01T15:18:52.291000Z", + "iopub.status.idle": "2022-06-01T15:18:52.333000Z", + "shell.execute_reply": "2022-06-01T15:18:52.333000Z" } }, "outputs": [], diff --git a/example/multiprocessing.ipynb b/example/multiprocessing.ipynb index b0ead9a2..736d07d5 100644 --- a/example/multiprocessing.ipynb +++ b/example/multiprocessing.ipynb @@ -67,10 +67,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:29:32.352000Z", - "iopub.status.busy": "2022-06-10T09:29:31.633000Z", - "iopub.status.idle": "2022-06-10T09:29:44.600000Z", - "shell.execute_reply": "2022-06-10T09:29:44.571000Z" + "iopub.execute_input": "2022-06-18T14:20:33.662000Z", + "iopub.status.busy": "2022-06-18T14:20:32.980000Z", + "iopub.status.idle": "2022-06-18T14:20:45.287000Z", + "shell.execute_reply": "2022-06-18T14:20:45.259000Z" } }, "outputs": [ @@ -107,10 +107,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:29:44.603000Z", - "iopub.status.busy": "2022-06-10T09:29:44.603000Z", - "iopub.status.idle": "2022-06-10T09:30:32.194000Z", - "shell.execute_reply": "2022-06-10T09:30:32.193000Z" + "iopub.execute_input": "2022-06-18T14:20:45.290000Z", + "iopub.status.busy": "2022-06-18T14:20:45.289000Z", + "iopub.status.idle": "2022-06-18T14:21:31.517000Z", + "shell.execute_reply": "2022-06-18T14:21:31.517000Z" } }, "outputs": [], @@ -133,10 +133,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:32.394000Z", - "iopub.status.busy": "2022-06-10T09:30:32.197000Z", - "iopub.status.idle": "2022-06-10T09:30:32.491000Z", - "shell.execute_reply": "2022-06-10T09:30:32.490000Z" + "iopub.execute_input": "2022-06-18T14:21:31.917000Z", + "iopub.status.busy": "2022-06-18T14:21:31.520000Z", + "iopub.status.idle": "2022-06-18T14:21:32.071000Z", + "shell.execute_reply": "2022-06-18T14:21:32.071000Z" } }, "outputs": [ @@ -144,10 +144,10 @@ "name": "stdout", "output_type": "stream", "text": [ - " From worker 3:\tHello World!\n", + "Hello World!\n", " From worker 2:\tHello World!\n", " From worker 4:\tHello World!\n", - "Hello World!\n", + " From worker 3:\tHello World!\n", " From worker 5:\tHello World!\n" ] } @@ -179,10 +179,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:32.494000Z", - "iopub.status.busy": "2022-06-10T09:30:32.494000Z", - "iopub.status.idle": "2022-06-10T09:30:36.509000Z", - "shell.execute_reply": "2022-06-10T09:30:36.509000Z" + "iopub.execute_input": "2022-06-18T14:21:32.074000Z", + "iopub.status.busy": "2022-06-18T14:21:32.074000Z", + "iopub.status.idle": "2022-06-18T14:21:35.419000Z", + "shell.execute_reply": "2022-06-18T14:21:35.419000Z" } }, "outputs": [ @@ -190,22 +190,22 @@ "data": { "text/plain": [ "16-element Vector{Vector{Float64}}:\n", - " [0.8522478954672708, 0.7209431226036078]\n", - " [0.909306253617912, 0.6209402039669427]\n", - " [0.4596043790366431, 0.2389289971087898]\n", - " [0.4934930898692784, 0.8535888352523144]\n", - " [0.9008166213933464, 0.48097066683100986]\n", - " [0.30695689796078574, 0.8999444231606255]\n", - " [0.5676033936598277, 0.0170782917662895]\n", - " [0.43299006096393633, 0.6018253815343202]\n", - " [0.8863999765881179, 0.5879607966583695]\n", - " [0.9250498940640433, 0.676688143062196]\n", - " [0.5927221115688299, 0.13661645859930105]\n", - " [0.5274125466018458, 0.6019662513572075]\n", - " [0.7212113914423361, 0.6184174840746639]\n", - " [0.5904677676104344, 0.9526791253940541]\n", - " [0.7887765751716826, 0.32324579460992675]\n", - " [0.867048815207933, 0.728198232394913]" + " [0.053272555584304104, 0.45774751559489646]\n", + " [0.5896778258750763, 0.12435199368996086]\n", + " [0.5651662129022856, 0.8764873667695812]\n", + " [0.6176612662918868, 0.2785804850450695]\n", + " [0.9274233385552415, 0.38275426899967724]\n", + " [0.46094177953642124, 0.6554519159504497]\n", + " [0.73421590884579, 0.28177572874256906]\n", + " [0.5575198504784948, 0.3212214708846175]\n", + " [0.271126562512229, 0.6499895887749823]\n", + " [0.5289045741655536, 0.4873381265273107]\n", + " [0.8565770844036877, 0.2312687408548988]\n", + " [0.06332369482582334, 0.44807066874864065]\n", + " [0.08611017776660712, 0.960898209225902]\n", + " [0.3191189843443898, 0.30014344015893846]\n", + " [0.028884098958377402, 0.5285860311385517]\n", + " [0.7282727650515579, 0.7584435212215901]" ] }, "execution_count": 4, @@ -235,10 +235,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:36.519000Z", - "iopub.status.busy": "2022-06-10T09:30:36.518000Z", - "iopub.status.idle": "2022-06-10T09:30:49.331000Z", - "shell.execute_reply": "2022-06-10T09:30:49.331000Z" + "iopub.execute_input": "2022-06-18T14:21:35.423000Z", + "iopub.status.busy": "2022-06-18T14:21:35.422000Z", + "iopub.status.idle": "2022-06-18T14:21:47.166000Z", + "shell.execute_reply": "2022-06-18T14:21:47.166000Z" } }, "outputs": [ @@ -246,23 +246,23 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ywfEtU/SpringPendulum1D`.\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ywfEtU/SpringPendulum1D/resources`\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources`\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_WvJUQ4/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_kty5Tc/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_ElhvF8/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_WvJUQ4/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_kty5Tc/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_ElhvF8/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_RvaFkX/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_RvaFkX/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources`\n", "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n" ] } @@ -294,10 +294,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:49.333000Z", - "iopub.status.busy": "2022-06-10T09:30:49.333000Z", - "iopub.status.idle": "2022-06-10T09:30:49.493000Z", - "shell.execute_reply": "2022-06-10T09:30:49.493000Z" + "iopub.execute_input": "2022-06-18T14:21:47.169000Z", + "iopub.status.busy": "2022-06-18T14:21:47.169000Z", + "iopub.status.idle": "2022-06-18T14:21:47.459000Z", + "shell.execute_reply": "2022-06-18T14:21:47.458000Z" } }, "outputs": [], @@ -320,26 +320,26 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:30:49.496000Z", - "iopub.status.busy": "2022-06-10T09:30:49.496000Z", - "iopub.status.idle": "2022-06-10T09:31:25.888000Z", - "shell.execute_reply": "2022-06-10T09:31:25.888000Z" + "iopub.execute_input": "2022-06-18T14:21:47.461000Z", + "iopub.status.busy": "2022-06-18T14:21:47.461000Z", + "iopub.status.idle": "2022-06-18T14:22:23.804000Z", + "shell.execute_reply": "2022-06-18T14:22:23.804000Z" } }, "outputs": [ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 16 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m301.517 ms\u001b[22m\u001b[39m … \u001b[35m343.653 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m6.30% … 8.37%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m325.148 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m5.92%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m324.977 ms\u001b[22m\u001b[39m ± \u001b[32m 11.601 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.39% ± 1.09%\n", + "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m304.291 ms\u001b[22m\u001b[39m … \u001b[35m325.332 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.41% … 6.89%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m307.274 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.37%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m309.397 ms\u001b[22m\u001b[39m ± \u001b[32m 5.860 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.94% ± 1.32%\n", "\n", - " \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[34m▁\u001b[39m\u001b[32m \u001b[39m\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[34m█\u001b[39m\u001b[32m▁\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 302 ms\u001b[90m Histogram: frequency by time\u001b[39m 344 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\u001b[34m▁\u001b[39m\u001b[39m \u001b[39m \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 304 ms\u001b[90m Histogram: frequency by time\u001b[39m 325 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002431\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." ] }, "execution_count": 7, @@ -364,10 +364,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:31:25.895000Z", - "iopub.status.busy": "2022-06-10T09:31:25.894000Z", - "iopub.status.idle": "2022-06-10T09:31:49.051000Z", - "shell.execute_reply": "2022-06-10T09:31:49.051000Z" + "iopub.execute_input": "2022-06-18T14:22:23.808000Z", + "iopub.status.busy": "2022-06-18T14:22:23.807000Z", + "iopub.status.idle": "2022-06-18T14:23:01.441000Z", + "shell.execute_reply": "2022-06-18T14:23:01.440000Z" } }, "outputs": [ @@ -381,9 +381,16 @@ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 1 sample with 1 evaluation.\n", - " Single result which took \u001b[34m5.128 s\u001b[39m (6.62% GC) to evaluate,\n", - " with a memory estimate of \u001b[33m2.29 GiB\u001b[39m, over \u001b[33m48038884\u001b[39m allocations." + "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m4.966 s\u001b[22m\u001b[39m … \u001b[35m 4.967 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.58% … 8.12%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m4.966 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.35%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m4.966 s\u001b[22m\u001b[39m ± \u001b[32m1.039 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.35% ± 0.33%\n", + "\n", + " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", + " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 4.97 s\u001b[90m Histogram: frequency by time\u001b[39m 4.97 s \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m2.29 GiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m48038916\u001b[39m." ] }, "execution_count": 8, @@ -410,10 +417,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:31:49.055000Z", - "iopub.status.busy": "2022-06-10T09:31:49.055000Z", - "iopub.status.idle": "2022-06-10T09:32:55.782000Z", - "shell.execute_reply": "2022-06-10T09:32:55.781000Z" + "iopub.execute_input": "2022-06-18T14:23:01.444000Z", + "iopub.status.busy": "2022-06-18T14:23:01.444000Z", + "iopub.status.idle": "2022-06-18T14:24:04.804000Z", + "shell.execute_reply": "2022-06-18T14:24:04.804000Z" } }, "outputs": [ @@ -428,15 +435,15 @@ "data": { "text/plain": [ "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m3.323 s\u001b[22m\u001b[39m … \u001b[35m 3.367 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m3.345 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m3.345 s\u001b[22m\u001b[39m ± \u001b[32m31.349 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m0.00% ± 0.00%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m3.069 s\u001b[22m\u001b[39m … \u001b[35m 3.078 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m3.074 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m3.074 s\u001b[22m\u001b[39m ± \u001b[32m6.467 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m0.00% ± 0.00%\n", "\n", - " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", - " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 3.32 s\u001b[90m Histogram: frequency by time\u001b[39m 3.37 s \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", + " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 3.07 s\u001b[90m Histogram: frequency by time\u001b[39m 3.08 s \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m81.44 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m1198\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m81.31 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m1192\u001b[39m." ] }, "execution_count": 9, @@ -470,10 +477,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:32:55.785000Z", - "iopub.status.busy": "2022-06-10T09:32:55.785000Z", - "iopub.status.idle": "2022-06-10T09:32:55.922000Z", - "shell.execute_reply": "2022-06-10T09:32:55.922000Z" + "iopub.execute_input": "2022-06-18T14:24:04.807000Z", + "iopub.status.busy": "2022-06-18T14:24:04.807000Z", + "iopub.status.idle": "2022-06-18T14:24:04.974000Z", + "shell.execute_reply": "2022-06-18T14:24:04.974000Z" } }, "outputs": [], diff --git a/example/multithreading.ipynb b/example/multithreading.ipynb index 1d478bb4..7076dfb7 100644 --- a/example/multithreading.ipynb +++ b/example/multithreading.ipynb @@ -62,10 +62,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:06.584000Z", - "iopub.status.busy": "2022-06-10T09:33:05.835000Z", - "iopub.status.idle": "2022-06-10T09:33:21.452000Z", - "shell.execute_reply": "2022-06-10T09:33:21.370000Z" + "iopub.execute_input": "2022-06-18T14:24:15.415000Z", + "iopub.status.busy": "2022-06-18T14:24:14.716000Z", + "iopub.status.idle": "2022-06-18T14:24:29.648000Z", + "shell.execute_reply": "2022-06-18T14:24:29.574000Z" } }, "outputs": [], @@ -89,10 +89,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:21.660000Z", - "iopub.status.busy": "2022-06-10T09:33:21.456000Z", - "iopub.status.idle": "2022-06-10T09:33:22.514000Z", - "shell.execute_reply": "2022-06-10T09:33:22.514000Z" + "iopub.execute_input": "2022-06-18T14:24:29.989000Z", + "iopub.status.busy": "2022-06-18T14:24:29.651000Z", + "iopub.status.idle": "2022-06-18T14:24:30.845000Z", + "shell.execute_reply": "2022-06-18T14:24:30.845000Z" } }, "outputs": [ @@ -132,10 +132,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:22.520000Z", - "iopub.status.busy": "2022-06-10T09:33:22.520000Z", - "iopub.status.idle": "2022-06-10T09:33:26.459000Z", - "shell.execute_reply": "2022-06-10T09:33:26.459000Z" + "iopub.execute_input": "2022-06-18T14:24:30.849000Z", + "iopub.status.busy": "2022-06-18T14:24:30.849000Z", + "iopub.status.idle": "2022-06-18T14:24:34.809000Z", + "shell.execute_reply": "2022-06-18T14:24:34.809000Z" } }, "outputs": [ @@ -143,7 +143,7 @@ "data": { "text/plain": [ "1-element Vector{Vector{Float64}}:\n", - " [0.7810829477429659, 0.42733298165721023]" + " [0.769193342919982, 0.5516183754569333]" ] }, "execution_count": 3, @@ -177,10 +177,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:26.463000Z", - "iopub.status.busy": "2022-06-10T09:33:26.462000Z", - "iopub.status.idle": "2022-06-10T09:33:31.974000Z", - "shell.execute_reply": "2022-06-10T09:33:31.974000Z" + "iopub.execute_input": "2022-06-18T14:24:34.812000Z", + "iopub.status.busy": "2022-06-18T14:24:34.812000Z", + "iopub.status.idle": "2022-06-18T14:24:40.193000Z", + "shell.execute_reply": "2022-06-18T14:24:40.193000Z" } }, "outputs": [ @@ -188,15 +188,15 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_AeQVGo/SpringPendulum1D`.\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AeQVGo/SpringPendulum1D/resources`\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources`\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_6YywFr/SpringPendulum1D`.\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_6YywFr/SpringPendulum1D/resources`\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources`\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n" @@ -235,10 +235,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:31.978000Z", - "iopub.status.busy": "2022-06-10T09:33:31.977000Z", - "iopub.status.idle": "2022-06-10T09:33:32.656000Z", - "shell.execute_reply": "2022-06-10T09:33:32.656000Z" + "iopub.execute_input": "2022-06-18T14:24:40.198000Z", + "iopub.status.busy": "2022-06-18T14:24:40.197000Z", + "iopub.status.idle": "2022-06-18T14:24:40.840000Z", + "shell.execute_reply": "2022-06-18T14:24:40.839000Z" } }, "outputs": [ @@ -272,26 +272,26 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:33:32.660000Z", - "iopub.status.busy": "2022-06-10T09:33:32.660000Z", - "iopub.status.idle": "2022-06-10T09:34:08.088000Z", - "shell.execute_reply": "2022-06-10T09:34:08.088000Z" + "iopub.execute_input": "2022-06-18T14:24:40.843000Z", + "iopub.status.busy": "2022-06-18T14:24:40.843000Z", + "iopub.status.idle": "2022-06-18T14:25:15.703000Z", + "shell.execute_reply": "2022-06-18T14:25:15.703000Z" } }, "outputs": [ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 14 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m337.440 ms\u001b[22m\u001b[39m … \u001b[35m389.386 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m5.75% … 5.28%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m372.244 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m5.52%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m368.214 ms\u001b[22m\u001b[39m ± \u001b[32m 15.573 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m5.91% ± 0.96%\n", + "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m337.943 ms\u001b[22m\u001b[39m … \u001b[35m357.340 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.03% … 6.55%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m339.287 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m342.299 ms\u001b[22m\u001b[39m ± \u001b[32m 5.982 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.39% ± 1.12%\n", "\n", - " \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m█\u001b[34m \u001b[39m\u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m█\u001b[34m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 337 ms\u001b[90m Histogram: frequency by time\u001b[39m 389 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m▃\u001b[39m█\u001b[39m \u001b[34m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m▇\u001b[34m▇\u001b[39m\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m \u001b[39m▁\n", + " 338 ms\u001b[90m Histogram: frequency by time\u001b[39m 357 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002431\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." ] }, "execution_count": 6, @@ -316,10 +316,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:34:08.093000Z", - "iopub.status.busy": "2022-06-10T09:34:08.093000Z", - "iopub.status.idle": "2022-06-10T09:34:21.799000Z", - "shell.execute_reply": "2022-06-10T09:34:21.799000Z" + "iopub.execute_input": "2022-06-18T14:25:15.707000Z", + "iopub.status.busy": "2022-06-18T14:25:15.707000Z", + "iopub.status.idle": "2022-06-18T14:25:29.068000Z", + "shell.execute_reply": "2022-06-18T14:25:29.068000Z" } }, "outputs": [ @@ -334,15 +334,15 @@ "data": { "text/plain": [ "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m340.025 ms\u001b[22m\u001b[39m … \u001b[35m386.317 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m6.05% … 5.51%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m353.427 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m5.97%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m355.542 ms\u001b[22m\u001b[39m ± \u001b[32m 12.557 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.24% ± 1.07%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m338.941 ms\u001b[22m\u001b[39m … \u001b[35m359.792 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.42% … 7.05%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m340.880 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.45%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m343.682 ms\u001b[22m\u001b[39m ± \u001b[32m 6.291 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.89% ± 1.20%\n", "\n", - " \u001b[39m█\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[34m▁\u001b[39m\u001b[39m \u001b[39m \u001b[32m▁\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[32m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 340 ms\u001b[90m Histogram: frequency by time\u001b[39m 386 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 339 ms\u001b[90m Histogram: frequency by time\u001b[39m 360 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002434\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002436\u001b[39m." ] }, "execution_count": 7, @@ -369,10 +369,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:34:21.806000Z", - "iopub.status.busy": "2022-06-10T09:34:21.805000Z", - "iopub.status.idle": "2022-06-10T09:34:38.654000Z", - "shell.execute_reply": "2022-06-10T09:34:38.654000Z" + "iopub.execute_input": "2022-06-18T14:25:29.072000Z", + "iopub.status.busy": "2022-06-18T14:25:29.072000Z", + "iopub.status.idle": "2022-06-18T14:25:46.159000Z", + "shell.execute_reply": "2022-06-18T14:25:46.159000Z" } }, "outputs": [ @@ -386,16 +386,16 @@ { "data": { "text/plain": [ - "BenchmarkTools.Trial: 16 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m304.578 ms\u001b[22m\u001b[39m … \u001b[35m342.615 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.13% … 6.47%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m314.032 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m6.84%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m316.672 ms\u001b[22m\u001b[39m ± \u001b[32m 10.042 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.99% ± 0.78%\n", + "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m307.665 ms\u001b[22m\u001b[39m … \u001b[35m325.644 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.44% … 8.13%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m308.448 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.55%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m310.319 ms\u001b[22m\u001b[39m ± \u001b[32m 4.970 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.72% ± 0.86%\n", "\n", - " \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 305 ms\u001b[90m Histogram: frequency by time\u001b[39m 343 ms \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m█\u001b[39m \u001b[34m█\u001b[39m\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m▆\u001b[34m█\u001b[39m\u001b[39m▆\u001b[39m█\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m█\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m \u001b[39m▁\n", + " 308 ms\u001b[90m Histogram: frequency by time\u001b[39m 326 ms \u001b[0m\u001b[1m<\u001b[22m\n", "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002438\u001b[39m." + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002440\u001b[39m." ] }, "execution_count": 8, @@ -429,10 +429,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-06-10T09:34:38.658000Z", - "iopub.status.busy": "2022-06-10T09:34:38.658000Z", - "iopub.status.idle": "2022-06-10T09:34:39.762000Z", - "shell.execute_reply": "2022-06-10T09:34:39.762000Z" + "iopub.execute_input": "2022-06-18T14:25:46.162000Z", + "iopub.status.busy": "2022-06-18T14:25:46.162000Z", + "iopub.status.idle": "2022-06-18T14:25:47.297000Z", + "shell.execute_reply": "2022-06-18T14:25:47.296000Z" } }, "outputs": [ diff --git a/example/parameterize.ipynb b/example/parameterize.ipynb index 61715634..65099b87 100644 --- a/example/parameterize.ipynb +++ b/example/parameterize.ipynb @@ -50,10 +50,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:40.626000Z", - "iopub.status.busy": "2022-05-25T10:50:39.995000Z", - "iopub.status.idle": "2022-05-25T10:50:53.067000Z", - "shell.execute_reply": "2022-05-25T10:50:52.995000Z" + "iopub.execute_input": "2022-06-01T15:19:01.571000Z", + "iopub.status.busy": "2022-06-01T15:19:00.892000Z", + "iopub.status.idle": "2022-06-01T15:19:15.010000Z", + "shell.execute_reply": "2022-06-01T15:19:14.933000Z" }, "scrolled": false }, @@ -78,10 +78,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:53.403000Z", - "iopub.status.busy": "2022-05-25T10:50:53.069000Z", - "iopub.status.idle": "2022-05-25T10:50:54.070000Z", - "shell.execute_reply": "2022-05-25T10:50:54.070000Z" + "iopub.execute_input": "2022-06-01T15:19:15.205000Z", + "iopub.status.busy": "2022-06-01T15:19:15.013000Z", + "iopub.status.idle": "2022-06-01T15:19:16.256000Z", + "shell.execute_reply": "2022-06-01T15:19:16.255000Z" }, "scrolled": false }, @@ -116,10 +116,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:54.073000Z", - "iopub.status.busy": "2022-05-25T10:50:54.073000Z", - "iopub.status.idle": "2022-05-25T10:50:58.301000Z", - "shell.execute_reply": "2022-05-25T10:50:58.301000Z" + "iopub.execute_input": "2022-06-01T15:19:16.259000Z", + "iopub.status.busy": "2022-06-01T15:19:16.259000Z", + "iopub.status.idle": "2022-06-01T15:19:20.487000Z", + "shell.execute_reply": "2022-06-01T15:19:20.486000Z" }, "scrolled": false }, @@ -128,12 +128,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_E6omKF/IO`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_E6omKF/IO/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -196,10 +196,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:58.303000Z", - "iopub.status.busy": "2022-05-25T10:50:58.303000Z", - "iopub.status.idle": "2022-05-25T10:50:59.044000Z", - "shell.execute_reply": "2022-05-25T10:50:59.044000Z" + "iopub.execute_input": "2022-06-01T15:19:20.489000Z", + "iopub.status.busy": "2022-06-01T15:19:20.489000Z", + "iopub.status.idle": "2022-06-01T15:19:21.252000Z", + "shell.execute_reply": "2022-06-01T15:19:21.252000Z" } }, "outputs": [ @@ -208,9 +208,9 @@ "text/plain": [ "FMU: IO\n", "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000003ae6b10\n", + "Address: Ptr{Nothing} @0x00000000029c12e0\n", "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", + "Logging: true\n", "FMU time: -Inf\n", "FMU states: nothing" ] @@ -236,10 +236,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.047000Z", - "iopub.status.busy": "2022-05-25T10:50:59.047000Z", - "iopub.status.idle": "2022-05-25T10:50:59.362000Z", - "shell.execute_reply": "2022-05-25T10:50:59.362000Z" + "iopub.execute_input": "2022-06-01T15:19:21.256000Z", + "iopub.status.busy": "2022-06-01T15:19:21.256000Z", + "iopub.status.idle": "2022-06-01T15:19:21.603000Z", + "shell.execute_reply": "2022-06-01T15:19:21.603000Z" } }, "outputs": [ @@ -272,10 +272,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.365000Z", - "iopub.status.busy": "2022-05-25T10:50:59.365000Z", - "iopub.status.idle": "2022-05-25T10:50:59.397000Z", - "shell.execute_reply": "2022-05-25T10:50:59.397000Z" + "iopub.execute_input": "2022-06-01T15:19:21.607000Z", + "iopub.status.busy": "2022-06-01T15:19:21.606000Z", + "iopub.status.idle": "2022-06-01T15:19:21.639000Z", + "shell.execute_reply": "2022-06-01T15:19:21.639000Z" } }, "outputs": [ @@ -306,10 +306,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.399000Z", - "iopub.status.busy": "2022-05-25T10:50:59.399000Z", - "iopub.status.idle": "2022-05-25T10:51:02.699000Z", - "shell.execute_reply": "2022-05-25T10:51:02.699000Z" + "iopub.execute_input": "2022-06-01T15:19:21.643000Z", + "iopub.status.busy": "2022-06-01T15:19:21.643000Z", + "iopub.status.idle": "2022-06-01T15:19:25.228000Z", + "shell.execute_reply": "2022-06-01T15:19:25.228000Z" } }, "outputs": [ @@ -345,10 +345,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:02.702000Z", - "iopub.status.busy": "2022-05-25T10:51:02.702000Z", - "iopub.status.idle": "2022-05-25T10:51:03.392000Z", - "shell.execute_reply": "2022-05-25T10:51:03.392000Z" + "iopub.execute_input": "2022-06-01T15:19:25.232000Z", + "iopub.status.busy": "2022-06-01T15:19:25.232000Z", + "iopub.status.idle": "2022-06-01T15:19:25.951000Z", + "shell.execute_reply": "2022-06-01T15:19:25.951000Z" } }, "outputs": [ @@ -388,10 +388,10 @@ "execution_count": 9, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:03.395000Z", - "iopub.status.busy": "2022-05-25T10:51:03.395000Z", - "iopub.status.idle": "2022-05-25T10:51:04.098000Z", - "shell.execute_reply": "2022-05-25T10:51:04.098000Z" + "iopub.execute_input": "2022-06-01T15:19:25.955000Z", + "iopub.status.busy": "2022-06-01T15:19:25.955000Z", + "iopub.status.idle": "2022-06-01T15:19:26.678000Z", + "shell.execute_reply": "2022-06-01T15:19:26.678000Z" } }, "outputs": [ @@ -399,7 +399,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Any[41.68976766058903, 91, false, \"Random number 18.117421661942835!\"]\n" + "Any[27.27027116078753, 50, true, \"Random number 83.09640957659121!\"]\n" ] } ], @@ -421,10 +421,10 @@ "execution_count": 10, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.102000Z", - "iopub.status.busy": "2022-05-25T10:51:04.102000Z", - "iopub.status.idle": "2022-05-25T10:51:04.571000Z", - "shell.execute_reply": "2022-05-25T10:51:04.571000Z" + "iopub.execute_input": "2022-06-01T15:19:26.682000Z", + "iopub.status.busy": "2022-06-01T15:19:26.682000Z", + "iopub.status.idle": "2022-06-01T15:19:27.242000Z", + "shell.execute_reply": "2022-06-01T15:19:27.242000Z" } }, "outputs": [ @@ -432,7 +432,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Any[41.68976766058903, 91, 0, \"Random number 18.117421661942835!\"]" + "Any[27.27027116078753, 50, 1, \"Random number 83.09640957659121!\"]" ] } ], @@ -458,10 +458,10 @@ "execution_count": 11, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.574000Z", - "iopub.status.busy": "2022-05-25T10:51:04.574000Z", - "iopub.status.idle": "2022-05-25T10:51:04.575000Z", - "shell.execute_reply": "2022-05-25T10:51:04.575000Z" + "iopub.execute_input": "2022-06-01T15:19:27.246000Z", + "iopub.status.busy": "2022-06-01T15:19:27.246000Z", + "iopub.status.idle": "2022-06-01T15:19:27.247000Z", + "shell.execute_reply": "2022-06-01T15:19:27.247000Z" } }, "outputs": [ @@ -469,7 +469,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Any[32.87773039642885, 58, false, \"Random number 22.4054218867213!\"]\n" + "Any[54.98169316988619, 76, true, \"Random number 39.54384075977397!\"]\n" ] } ], @@ -493,17 +493,17 @@ "execution_count": 12, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.579000Z", - "iopub.status.busy": "2022-05-25T10:51:04.578000Z", - "iopub.status.idle": "2022-05-25T10:51:06.093000Z", - "shell.execute_reply": "2022-05-25T10:51:06.093000Z" + "iopub.execute_input": "2022-06-01T15:19:27.250000Z", + "iopub.status.busy": "2022-06-01T15:19:27.250000Z", + "iopub.status.idle": "2022-06-01T15:19:28.917000Z", + "shell.execute_reply": "2022-06-01T15:19:28.917000Z" } }, "outputs": [ { "data": { "text/plain": [ - "\"32.87773039642885 == 32.87773039642885\"" + "\"54.98169316988619 == 54.98169316988619\"" ] }, "metadata": {}, @@ -512,7 +512,7 @@ { "data": { "text/plain": [ - "\"58 == 58\"" + "\"76 == 76\"" ] }, "metadata": {}, @@ -521,7 +521,7 @@ { "data": { "text/plain": [ - "\"false == 0\"" + "\"true == 1\"" ] }, "metadata": {}, @@ -530,7 +530,7 @@ { "data": { "text/plain": [ - "\"Random number 22.4054218867213! == Random number 22.4054218867213!\"" + "\"Random number 39.54384075977397! == Random number 39.54384075977397!\"" ] }, "metadata": {}, @@ -563,10 +563,10 @@ "execution_count": 13, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:06.096000Z", - "iopub.status.busy": "2022-05-25T10:51:06.096000Z", - "iopub.status.idle": "2022-05-25T10:51:06.127000Z", - "shell.execute_reply": "2022-05-25T10:51:06.127000Z" + "iopub.execute_input": "2022-06-01T15:19:28.920000Z", + "iopub.status.busy": "2022-06-01T15:19:28.920000Z", + "iopub.status.idle": "2022-06-01T15:19:28.956000Z", + "shell.execute_reply": "2022-06-01T15:19:28.955000Z" } }, "outputs": [ @@ -609,10 +609,10 @@ "execution_count": 14, "metadata": { "execution": { - "iopub.execute_input": "2022-05-25T10:51:06.129000Z", - "iopub.status.busy": "2022-05-25T10:51:06.129000Z", - "iopub.status.idle": "2022-05-25T10:51:06.239000Z", - "shell.execute_reply": "2022-05-25T10:51:06.239000Z" + "iopub.execute_input": "2022-06-01T15:19:28.959000Z", + "iopub.status.busy": "2022-06-01T15:19:28.959000Z", + "iopub.status.idle": "2022-06-01T15:19:29.101000Z", + "shell.execute_reply": "2022-06-01T15:19:29.101000Z" } }, "outputs": [], diff --git a/example/simulate.ipynb b/example/simulate.ipynb index d1b94962..f3ef7b84 100644 --- a/example/simulate.ipynb +++ b/example/simulate.ipynb @@ -54,23 +54,14 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:10:58.160000Z", - "iopub.status.busy": "2022-05-24T15:10:57.200000Z", - "iopub.status.idle": "2022-05-24T15:11:28.115000Z", - "shell.execute_reply": "2022-05-24T15:11:28.004000Z" + "iopub.execute_input": "2022-06-01T15:19:38.296000Z", + "iopub.status.busy": "2022-06-01T15:19:37.619000Z", + "iopub.status.idle": "2022-06-01T15:20:00.542000Z", + "shell.execute_reply": "2022-06-01T15:20:00.469000Z" }, "scrolled": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], + "outputs": [], "source": [ "# imports\n", "using FMI\n", @@ -92,10 +83,10 @@ "execution_count": 2, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:39.107000Z", - "iopub.status.busy": "2022-05-24T15:11:28.118000Z", - "iopub.status.idle": "2022-05-24T15:11:40.147000Z", - "shell.execute_reply": "2022-05-24T15:11:40.147000Z" + "iopub.execute_input": "2022-06-01T15:20:09.276000Z", + "iopub.status.busy": "2022-06-01T15:20:00.544000Z", + "iopub.status.idle": "2022-06-01T15:20:10.061000Z", + "shell.execute_reply": "2022-06-01T15:20:10.061000Z" }, "scrolled": false }, @@ -132,10 +123,10 @@ "execution_count": 3, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:40.151000Z", - "iopub.status.busy": "2022-05-24T15:11:40.151000Z", - "iopub.status.idle": "2022-05-24T15:11:45.736000Z", - "shell.execute_reply": "2022-05-24T15:11:45.736000Z" + "iopub.execute_input": "2022-06-01T15:20:10.065000Z", + "iopub.status.busy": "2022-06-01T15:20:10.065000Z", + "iopub.status.idle": "2022-06-01T15:20:14.405000Z", + "shell.execute_reply": "2022-06-01T15:20:14.404000Z" }, "scrolled": false }, @@ -144,12 +135,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_TJndII/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_TJndII/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" ] }, { @@ -214,10 +205,10 @@ "execution_count": 4, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:45.739000Z", - "iopub.status.busy": "2022-05-24T15:11:45.739000Z", - "iopub.status.idle": "2022-05-24T15:11:52.663000Z", - "shell.execute_reply": "2022-05-24T15:11:52.663000Z" + "iopub.execute_input": "2022-06-01T15:20:14.407000Z", + "iopub.status.busy": "2022-06-01T15:20:14.407000Z", + "iopub.status.idle": "2022-06-01T15:20:19.739000Z", + "shell.execute_reply": "2022-06-01T15:20:19.739000Z" } }, "outputs": [ @@ -268,10 +259,10 @@ "execution_count": 5, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:11:52.667000Z", - "iopub.status.busy": "2022-05-24T15:11:52.667000Z", - "iopub.status.idle": "2022-05-24T15:12:09.582000Z", - "shell.execute_reply": "2022-05-24T15:12:09.582000Z" + "iopub.execute_input": "2022-06-01T15:20:19.742000Z", + "iopub.status.busy": "2022-06-01T15:20:19.742000Z", + "iopub.status.idle": "2022-06-01T15:20:32.777000Z", + "shell.execute_reply": "2022-06-01T15:20:32.777000Z" } }, "outputs": [ @@ -279,7 +270,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:11\u001b[39m\n" + "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09\u001b[39m\n" ] }, { @@ -333,10 +324,10 @@ "execution_count": 6, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:12:09.586000Z", - "iopub.status.busy": "2022-05-24T15:12:09.586000Z", - "iopub.status.idle": "2022-05-24T15:12:34.657000Z", - "shell.execute_reply": "2022-05-24T15:12:34.657000Z" + "iopub.execute_input": "2022-06-01T15:20:32.781000Z", + "iopub.status.busy": "2022-06-01T15:20:32.780000Z", + "iopub.status.idle": "2022-06-01T15:20:51.657000Z", + "shell.execute_reply": "2022-06-01T15:20:51.657000Z" }, "scrolled": false }, @@ -347,99 +338,99 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 6, @@ -634,10 +625,10 @@ "execution_count": 7, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:12:34.663000Z", - "iopub.status.busy": "2022-05-24T15:12:34.663000Z", - "iopub.status.idle": "2022-05-24T15:12:34.960000Z", - "shell.execute_reply": "2022-05-24T15:12:34.959000Z" + "iopub.execute_input": "2022-06-01T15:20:51.662000Z", + "iopub.status.busy": "2022-06-01T15:20:51.662000Z", + "iopub.status.idle": "2022-06-01T15:20:51.876000Z", + "shell.execute_reply": "2022-06-01T15:20:51.876000Z" } }, "outputs": [ @@ -647,99 +638,99 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n" ] }, "execution_count": 7, @@ -971,10 +962,10 @@ "execution_count": 8, "metadata": { "execution": { - "iopub.execute_input": "2022-05-24T15:12:34.965000Z", - "iopub.status.busy": "2022-05-24T15:12:34.965000Z", - "iopub.status.idle": "2022-05-24T15:12:35.028000Z", - "shell.execute_reply": "2022-05-24T15:12:35.028000Z" + "iopub.execute_input": "2022-06-01T15:20:51.880000Z", + "iopub.status.busy": "2022-06-01T15:20:51.880000Z", + "iopub.status.idle": "2022-06-01T15:20:51.922000Z", + "shell.execute_reply": "2022-06-01T15:20:51.922000Z" } }, "outputs": [], diff --git a/src/FMI.jl b/src/FMI.jl index 885fd9d3..e3f521d3 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -10,6 +10,8 @@ module FMI using Requires using FMIImport + +# fmi2 imports import FMIImport: fmi2CallbackLogger, fmi2CallbackAllocateMemory, fmi2CallbackFreeMemory, fmi2CallbackStepFinished import FMIImport: fmi2ComponentState, fmi2ComponentStateInstantiated, fmi2ComponentStateInitializationMode, fmi2ComponentStateEventMode, fmi2ComponentStateContinuousTimeMode, fmi2ComponentStateTerminated, fmi2ComponentStateError, fmi2ComponentStateFatal import FMIImport: fmi2Instantiate, fmi2FreeInstance!, fmi2GetTypesPlatform, fmi2GetVersion @@ -36,11 +38,43 @@ import FMIImport: fmi2Get, fmi2Get!, fmi2Set import FMIImport: fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue export fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue +import FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate +import FMIImport: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmi3InstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal +import FMIImport: fmi3InstantiateModelExchange, fmi3InstantiateCoSimulation, fmi3InstantiateScheduledExecution, fmi3FreeInstance!, fmi3GetVersion +import FMIImport: fmi3SetDebugLogging, fmi3EnterInitializationMode, fmi3ExitInitializationMode, fmi3Terminate, fmi3Reset +import FMIImport: fmi3GetFloat32!, fmi3SetFloat32, fmi3GetFloat64!, fmi3SetFloat64 +import FMIImport: fmi3GetInt8!, fmi3SetInt8, fmi3GetUInt8!, fmi3SetUInt8, fmi3GetInt16!, fmi3SetInt16, fmi3GetUInt16!, fmi3SetUInt16, fmi3GetInt32!, fmi3SetInt32, fmi3GetUInt32!, fmi3SetUInt32, fmi3GetInt64!, fmi3SetInt64, fmi3GetUInt64!, fmi3SetUInt64 +import FMIImport: fmi3GetBoolean!, fmi3SetBoolean, fmi3GetString!, fmi3SetString, fmi3GetBinary!, fmi3SetBinary, fmi3GetClock!, fmi3SetClock +import FMIImport: fmi3GetFMUState!, fmi3SetFMUState, fmi3FreeFMUState!, fmi3SerializedFMUStateSize!, fmi3SerializeFMUState!, fmi3DeSerializeFMUState! +import FMIImport: fmi3SetIntervalDecimal, fmi3SetIntervalFraction, fmi3GetIntervalDecimal!, fmi3GetIntervalFraction!, fmi3GetShiftDecimal!, fmi3GetShiftFraction! +import FMIImport: fmi3ActivateModelPartition +import FMIImport: fmi3GetNumberOfVariableDependencies!, fmi3GetVariableDependencies! +import FMIImport: fmi3GetDirectionalDerivative!, fmi3GetAdjointDerivative!, fmi3GetOutputDerivatives! +import FMIImport: fmi3DoStep +import FMIImport: fmi3EnterConfigurationMode, fmi3ExitConfigurationMode, fmi3GetNumberOfContinuousStates!, fmi3GetNumberOfEventIndicators!, fmi3GetContinuousStates!, fmi3GetNominalsOfContinuousStates! +import FMIImport: fmi3EvaluateDiscreteStates, fmi3EnterStepMode +import FMIImport: fmi3SetTime, fmi3SetContinuousStates, fmi3EnterEventMode, fmi3UpdateDiscreteStates, fmi3EnterContinuousTimeMode, fmi3CompletedIntegratorStep! +import FMIImport: fmi3GetContinuousStateDerivatives, fmi3GetEventIndicators, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates +import FMIImport: fmi3StringToValueReference, fmi3ValueReferenceToString, fmi3ModelVariablesForValueReference +import FMIImport: fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString +import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmiDeSerializeFMUState +import FMIImport: fmi3GetDirectionalDerivative, fmi3GetAdjointDerivative +import FMIImport: fmi3GetStartValue, fmi3SampleDirectionalDerivative, fmi3CompletedIntegratorStep +import FMIImport: fmi3Unzip, fmi3Load, loadBinary, fmi3Reload, fmi3Unload, fmi3InstantiateModelExchange!, fmi3InstantiateCoSimulation!, fmi3InstantiateScheduledExecution! +import FMIImport: fmi3SampleDirectionalDerivative! +import FMIImport: fmi3GetJacobian, fmi3GetJacobian!, fmi3GetFullJacobian, fmi3GetFullJacobian! +import FMIImport: fmi3LoadModelDescription +import FMIImport: fmi3GetDefaultStartTime, fmi3GetDefaultStopTime, fmi3GetDefaultTolerance, fmi3GetDefaultStepSize +import FMIImport: fmi3GetModelName, fmi3GetInstantiationToken, fmi3GetGenerationTool, fmi3GetGenerationDateAndTime, fmi3GetVariableNamingConvention, fmi3GetNumberOfEventIndicators, fmi3GetNumberOfStates, fmi3IsCoSimulation, fmi3IsModelExchange, fmi3IsScheduledExecution +import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetSetState, fmi3CanSerializeFMUState, fmi3ProvidesDirectionalDerivatives, fmi3ProvidesAdjointDerivatves +import FMIImport: fmi3Get, fmi3Get!, fmi3Set +import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue +export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue + import FMIImport: fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type export fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type using FMIExport -using FMIExport: fmi2Create, fmi2CreateSimple using FMIImport.FMICore: fmi2ValueReference, fmi3ValueReference using FMIImport: fmi2ValueReferenceFormat, fmi3ValueReferenceFormat, fmi2StructMD, fmi3StructMD, fmi2Struct, fmi3Struct @@ -86,6 +120,25 @@ function fmiLoadSolution(path::AbstractString; keyword="solution") end export fmiSaveSolution, fmiLoadSolution +# from FMI3_plot.jl +function fmiPlot(solution::FMU3Solution; kwargs...) + @warn "fmiPlot(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +end +function fmiPlot!(fig, solution::FMU3Solution; kwargs...) + @warn "fmiPlot!(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +end +export fmiPlot, fmiPlot! + +# from FMI3_JLD2.jl +function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") + @warn "fmiSave(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." +end +function fmiLoadSolution(path::AbstractString; keyword="solution") + @warn "fmiLoad(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." +end + +export fmiSaveSolution, fmiLoadSolution + # Requires init function __init__() @require Plots="91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin @@ -96,6 +149,7 @@ function __init__() @require JLD2="033835bb-8acc-5ee8-8aae-3f567f8a3819" begin import .JLD2 include("FMI2_JLD2.jl") + include("FMI3_JLD3.jl") end end @@ -175,15 +229,15 @@ Returns the tag 'modelName' from the model description. # Arguments - `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: - `Union{fmi2StructMD, fmi3StructMD} = Union{FMU2, FMU2Component, fmi2ModelDescription, FMU3, FMU3Component, fmi3ModelDescription}` + `Union{fmi2StructMD, fmi3StructMD} = Union{FMU2, FMU2Component, fmi2ModelDescription, FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). - - `str::FMU3Component`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. -See also [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`FMU3`](@ref), [`FMU3Component`](@ref), [`fmi3ModelDescription`](@ref). +See also [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetModelName(str::fmi2StructMD) fmi2GetModelName(str) @@ -192,6 +246,7 @@ function fmiGetModelName(str::fmi3StructMD) fmi3GetModelName(str) end +# TODO call differently in fmi3: getInstantationToken """ fmiGetGUID(str::fmi2StructMD) @@ -210,271 +265,393 @@ function fmiGetGUID(str::fmi2StructMD) fmi2GetGUID(str) end +# TODO how wo work with docstring """ - fmiGetGenerationTool(str::fmi2StructMD) + fmiGetGenerationTool(str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'generationtool' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: +`fmi2StructMD= Union{FMU2, FMU2Component, fmi2ModelDescription}` +`fmi3StructMD= Union{FMU3, FMU3Instance, fmi3ModelDescription}` +- `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.generationtool`: The function `fmi2GetGenerationTool` returns the tag 'generationtool' from the struct, representing a FMU (`str`). -See also [`fmi2GetGenerationTool`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2GetGenerationTool`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref),[`fmi3GetGenerationTool`](@ref), [`fmi3StructMD`](@ref),[`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetGenerationTool(str::fmi2StructMD) fmi2GetGenerationTool(str) end - +function fmiGetGenerationTool(str::fmi3StructMD) + fmi3GetGenerationTool(str) +end """ - fmiGetGenerationDateAndTime(str::fmi2StructMD) + fmiGetGenerationDateAndTime(str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'generationdateandtime' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` + More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.generationDateAndTime`: The function `fmi2GetGenerationDateAndTime` returns the tag 'generationDateAndTime' from the struct, representing a FMU (`str`). -See also [`fmi2GetGenerationDateAndTime`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2GetGenerationDateAndTime`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref),[`fmi3GetGenerationDateAndTime`](@ref), [`fmi3StructMD`](@ref),[`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetGenerationDateAndTime(str::fmi2StructMD) fmi2GetGenerationDateAndTime(str) end +function fmiGetGenerationDateAndTime(str::fmi3StructMD) + fmi3GetGenerationDateAndTime(str) +end """ - fmiGetVariableNamingConvention(str::fmi2StructMD) + fmiGetVariableNamingConvention(str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'varaiblenamingconvention' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` + More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.variableNamingConvention`: The function `fmi2GetVariableNamingConvention` returns the tag 'variableNamingConvention' from the struct, representing a FMU (`str`). +See also [`fmi2GetVariableNamingConvention`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3GetVariableNamingConvention`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). -See also [`fmi2GetVariableNamingConvention`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). """ function fmiGetVariableNamingConvention(str::fmi2StructMD) fmi2GetVariableNamingConvention(str) end +function fmiGetVariableNamingConvention(str::fmi3StructMD) + fmi3GetVariableNamingConvention(str) +end """ - fmiGetNumberOfEventIndicators(str::fmi2StructMD) + fmiGetNumberOfEventIndicators(str::str::Union{fmi2StructMD, fmi3StructMD}) Returns the tag 'numberOfEventIndicators' from the model description. # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `str.numberOfEventIndicators`: The function `fmi2GetNumberOfEventIndicators` returns the tag 'numberOfEventIndicators' from the struct, representing a FMU (`str`). -See also [`fmi2GetNumberOfEventIndicators`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2GetNumberOfEventIndicators`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3GetNumberOfEventIndicators`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiGetNumberOfEventIndicators(str::fmi2StructMD) fmi2GetNumberOfEventIndicators(str) end +function fmiGetNumberOfEventIndicators(str::fmi3StructMD) + fmi3GetNumberOfEventIndicators(str) +end """ - fmiGetModelIdentifier(fmu::FMU2) + fmiGetModelIdentifier(fmu::Union{FMU2, FMU3}) Returns the tag 'modelIdentifier' from CS or ME section. # Arguments - `fmu::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - + - `fmu::FMU3`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- `fmu.modelDescription.coSimulation.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'coSimulation.modelIdentifier' from the model description of the FMU2-struct (`fmu.modelDescription`), if the FMU supports co simulation. -- `fmu.modelDescription.modelExchange.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'modelExchange.modelIdentifier' from the model description of the FMU2-struct (`fmu.modelDescription`), if the FMU supports model exchange +- `fmu.modelDescription.coSimulation.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'coSimulation.modelIdentifier' from the model description of the FMU2 or FMU3-struct (`fmu.modelDescription`), if the FMU supports co simulation. +- `fmu.modelDescription.modelExchange.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'modelExchange.modelIdentifier' from the model description of the FMU2 or FMU3-struct (`fmu.modelDescription`), if the FMU supports model exchange +- `fmu.modelDescription.modelExchange.modelIdentifier`: The function `fmiGetModelIdentifier` returns the tag 'scheduledExecution.modelIdentifier' from the model description of the FMU3-struct (`fmu.modelDescription`), if the FMU supports scheduled execution -Also see [`fmi2GetModelIdentifier`](@ref), [`FMU2`](@ref). +Also see [`fmi2GetModelIdentifier`](@ref), [`FMU2`](@ref), [`fmi3GetModelIdentifier`](@ref), [`FMU3`](@ref). """ function fmiGetModelIdentifier(fmu::FMU2) fmi2GetModelIdentifier(fmu.modelDescription; type=fmu.type) end - +function fmiGetModelIdentifier(fmu::FMU3) + fmi3GetModelIdentifier(fmu.modelDescription; type=fmu.type) +end """ - fmiCanGetSetState(str::fmi2StructMD) + fmiCanGetSetState(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU supports the getting/setting of states # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2CanGetSetState` returns True, if the FMU supports the getting/setting of states. -See also [`fmi2CanGetSetState`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2CanGetSetState`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3CanGetSetState`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiCanGetSetState(str::fmi2StructMD) fmi2CanGetSetState(str) end +function fmiCanGetSetState(str::fmi3StructMD) + fmi3CanGetSetState(str) +end """ - fmiCanSerializeFMUstate(str::fmi2StructMD) + fmiCanSerializeFMUstate(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU state can be serialized # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` +- `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct wich provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2CanSerializeFMUstate` returns True, if the FMU state can be serialized. -See also [`fmi2CanSerializeFMUstate`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2CanSerializeFMUstate`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3CanSerializeFMUstate`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiCanSerializeFMUstate(str::fmi2StructMD) fmi2CanSerializeFMUstate(str) end +function fmiCanSerializeFMUstate(str::fmi3StructMD) + fmi3CanSerializeFMUstate(str) +end +# TODO fmi3Call fmiProvidesDirectionalDerivatives """ - fmiProvidesDirectionalDerivative(str::fmi2StructMD) + fmiProvidesDirectionalDerivative(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU provides directional derivatives # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2ProvidesDirectionalDerivative` returns True, if the FMU provides directional derivatives. -See also [`fmi2ProvidesDirectionalDerivative`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2ProvidesDirectionalDerivative`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3ProvidesDirectionalDerivative`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiProvidesDirectionalDerivative(str::fmi2StructMD) fmi2ProvidesDirectionalDerivative(str) end +function fmiProvidesDirectionalDerivative(str::fmi3StructMD) + fmi3ProvidesDirectionalDerivatives(str) +end """ - fmiIsCoSimulation(str::fmi2StructMD) + fmiProvidesAdjointDerivative(str::fmi3StructMD) + +Returns true, if the FMU provides adjoint derivatives + +# Arguments +- `str::fmi3StructMD`: Representative for an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: +More detailed: `fmi3StructMD = Union{FMU3, FMU3Component, fmi3ModelDescription}` + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. + +# Returns +- `::Bool`: The function `fmi3ProvidesAdjointDerivatives` returns True, if the FMU provides adjoint derivatives. + +See also [`fmi3ProvidesAdjointDerivatves`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). +""" +function fmiProvidesAdjointDerivative(str::fmi3StructMD) + fmi3ProvidesAdjointDerivatives(str) +end + +""" + + fmiIsCoSimulation(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU supports co simulation # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). -More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` - - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: +More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` +- `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - `::Bool`: The function `fmi2IsCoSimulation` returns True, if the FMU supports co simulation -See also [`fmi2IsCoSimulation`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2IsCoSimulation`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3IsCoSimulation`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiIsCoSimulation(str::fmi2StructMD) fmi2IsCoSimulation(str) end +function fmiIsCoSimulation(str::fmi3StructMD) + fmi3IsCoSimulation(str) +end """ - fmiIsModelExchange(str::fmi2StructMD) + fmiIsModelExchange(str::Union{fmi2StructMD, fmi3StructMD}) Returns true, if the FMU supports model exchange # Arguments -- `str::fmi2StructMD`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). -More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: +More detailed: `fmi2StructMD = Union{FMU2, FMU2Component, fmi2ModelDescription}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::fmi2ModelDescription`: Struct witch provides the static information of ModelVariables. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. # Returns - - `::Bool`: The function `fmi2IsCoSimulation` returns True, if the FMU supports model exchange. + - `::Bool`: The function `fmi2IsModelExchange` returns True, if the FMU supports model exchange. -See also [`fmi2IsModelExchange`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref). +See also [`fmi2IsModelExchange`](@ref), [`fmi2StructMD`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi2ModelDescription`](@ref), [`fmi3IsModelExchange`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). """ function fmiIsModelExchange(str::fmi2StructMD) fmi2IsModelExchange(str) end +function fmiIsModelExchange(str::fmi3StructMD) + fmi3IsModelExchange(str) +end + +""" + + fmiIsScheduledExecution(str::fmi3StructMD) + +Returns true, if the FMU supports scheduled execution + +# Arguments +- `str::fmi3StructMD`: Representative for an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::fmi3ModelDescription`: Struct witch provides the static information of ModelVariables. + +# Returns + - `::Bool`: The function `fmi3IsScheduledExecution` returns True, if the FMU supports scheduled execution. + +See also [`fmi3IsScheduledExecution`](@ref), [`fmi3StructMD`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref), [`fmi3ModelDescription`](@ref). +""" +function fmiIsScheduledExecution(str::fmi2StructMD) + fmi3IsScheduledExecution(str) +end # Multiple Dispatch variants for FMUs with version 2.0.X +# TODO check version in MD """ fmiLoad(pathToFMU::String; unpackPath=nothing, type=nothing) -Load FMUs independent of the FMI version, currently supporting version 2.0.X. +Load FMUs independent of the FMI version, currently supporting version 2.0.X and 3.0. # Arguments - `pathToFMU::String`: String that contains the paths of ziped and unziped FMU folders. # Keywords - `unpackPath=nothing`: Via optional argument ```unpackPath```, a path to unpack the FMU can be specified (default: system temporary directory). -- `type::Union{CS, ME} = nothing`: Via ```type```, a FMU type can be selected. If none of the unified type set is used, the default value `type = nothing` will be used. +- `type::Union{CS, ME, SE} = nothing`: Via ```type```, a FMU type can be selected. If none of the unified type set is used, the default value `type = nothing` will be used. # Returns - Returns the instance of the FMU struct. -See also [`fmi2Load`](@ref). +See also [`fmi2Load`](@ref), [`fmi3Load`](@ref). """ function fmiLoad(args...; kwargs...) - fmi2Load(args...; kwargs...) + version = fmiCheckVersion(pathToFMU) + if version == "2.0" + fmi2Load(args...; kwargs...) + elseif version == "3.0" + fmi3Load(args...; kwargs...) + else + @warn "fmiLoad(...): Unknown FMU version" + end end """ - fmiReload(fmu::FMU2) + fmiReload(fmu::Union{FMU2, FMU3}) Reloads the FMU-binary. This is useful, if the FMU does not support a clean reset implementation. # Arguments - `fmu::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `fmu::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). - -See also [`fmi2Reload`](@ref). +See also [`fmi2Reload`](@ref), [`fmi3Reload`](@ref). """ function fmiReload(fmu::FMU2, args...; kwargs...) fmi2Reload(fmu, args...; kwargs...) end +function fmiReload(fmu::FMU3, args...; kwargs...) + fmi3Reload(fmu, args...; kwargs...) +end """ - fmiSimulate(str::fmi2Struct, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + fmiSimulate(str::Union{fmi2Struct, fmi3Struct}, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; tolerance::Union{Real, Nothing} = nothing, dt::Union{Real, Nothing} = nothing, solver = nothing, @@ -493,12 +670,15 @@ Starts a simulation of the FMU instance for the matching FMU type, if both types # Arguments -- - `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). -- `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. -- `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). + - `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. + - `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. # Keywords - `tolerance::Union{Real, Nothing} = nothing`: Real number to set the tolerance for any OED-solver @@ -521,16 +701,18 @@ More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - if keyword `recordValues` is set, a tuple of type (success::Bool, DiffEqCallbacks.SavedValues) for CS-FMUs - if keyword `recordValues` is set, a tuple of type (ODESolution, DiffEqCallbacks.SavedValues) for ME-FMUs -See also [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2SimulateCS`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). - +See also [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2SimulateCS`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3Simulate`](@ref), [`fmi3SimulateME`](@ref), [`fmi3SimulateCS`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiSimulate(str::fmi2Struct, args...; kwargs...) fmi2Simulate(str, args...; kwargs...) end +function fmiSimulate(str::fmi3Struct, args...; kwargs...) + fmi3Simulate(str, args...; kwargs...) +end """ - fmiSimulateCS(str::fmi2Struct, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + fmiSimulateCS(str::Union{fmi2Struct,fmi3Struct}, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; tolerance::Union{Real, Nothing} = nothing, dt::Union{Real, Nothing} = nothing, solver = nothing, @@ -549,10 +731,13 @@ Starts a simulation of the Co-Simulation FMU instance. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). - `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. - `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. @@ -575,16 +760,19 @@ More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - If keyword `recordValues` is not set, a boolean `success` is returned (simulation success). - If keyword `recordValues` is set, a tuple of type (true, DiffEqCallbacks.SavedValues) or (false, nothing). -See also [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2SimulateME`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3SimulateCS`](@ref), [`fmi3Simulate`](@ref), [`fmi3SimulateME`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiSimulateCS(str::fmi2Struct, args...; kwargs...) fmi2SimulateCS(str, args...; kwargs...) +end +function fmiSimulateCS(str::fmi3Struct, args...; kwargs...) + fmi3SimulateCS(str, args...; kwargs...) end """ - fmiSimulateME(str::fmi2Struct, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + fmiSimulateME(str::Union{fmi2Struct,fmi3Struct}, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; tolerance::Union{Real, Nothing} = nothing, dt::Union{Real, Nothing} = nothing, solver = nothing, @@ -603,10 +791,13 @@ Simulates a FMU instance for the given simulation time interval. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2StructMD, fmi3StructMD}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). - `t_start::Union{Real, Nothing} = nothing`: Set the start time to a value of type Real or the default value from the model description is used. - `t_stop::Union{Real, Nothing} = nothing`: Set the end time to a value of type Real or the default value from the model description is used. @@ -629,48 +820,61 @@ More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` - If keyword `recordValues` is not set, a struct of type `ODESolution`. - If keyword `recordValues` is set, a tuple of type (ODESolution, DiffEqCallbacks.SavedValues). -See also [`fmi2SimulateME`](@ref) [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2SimulateME`](@ref) [`fmi2SimulateCS`](@ref), [`fmi2Simulate`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3SimulateME`](@ref) [`fmi3SimulateCS`](@ref), [`fmi3Simulate`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiSimulateME(str::fmi2Struct, args...; kwargs...) fmi2SimulateME(str, args...; kwargs...) end +function fmiSimulateME(str::fmi3Struct, args...; kwargs...) + fmi3SimulateME(str, args...; kwargs...) +end """ - fmiUnload(fmu::FMU2) + fmiUnload(fmu::Union{FMU2, FMU3}) Unloads the FMU and all its instances and frees the allocated memory. # Arguments - `fmu::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `fmu::FMU3`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 3.0 Standard](https://fmi-standard.org/). -See also [`fmi2Unload`](@ref). +See also [`fmi2Unload`](@ref), [`fmi3Unload`](@ref). """ function fmiUnload(fmu::FMU2) fmi2Unload(fmu) end +function fmiUnload(fmu::FMU3) + fmi3Unload(fmu) +end """ - fmiGetNumberOfStates(str::fmi2Struct) + fmiGetNumberOfStates(str::Union{fmi2Struct, fmi3Struct}) Returns the number of states of the FMU. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the [FMI 2.0.2 Standard](https://fmi-standard.org/). - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/). + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- Returns the length of the `str.stateValueReferences` array, which consists of `fmi2ValueReference` constants. +- Returns the length of the `str.stateValueReferences` array, which consists of `fmi2ValueReference` or `fmi3ValueReference` constants. -See also [`fmi2GetNumberOfStates`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2GetNumberOfStates`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3GetNumberOfStates`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiGetNumberOfStates(str::fmi2Struct) fmi2GetNumberOfStates(str) end +function fmiGetNumberOfStates(str::fmi3Struct) + fmi3GetNumberOfStates(str) +end """ @@ -695,29 +899,36 @@ end """ - fmiGetVersion(str::fmi2Struct) + fmiGetVersion(str::Union{fmi2Struct, fmi3Struct}) Returns the version of the FMU, version independent. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- Returns a string from the address of a C-style (NUL-terminated) string. The string represents the version of the “fmi2Functions.h” header file which was used to compile the functions of the FMU. The function returns “fmiVersion” which is defined in this header file. The standard header file as documented in this specification has version “2.0” +- Returns a string from the address of a C-style (NUL-terminated) string. The string represents the version of the “fmiXFunctions.h” header file which was used to compile the functions of the FMU. The function returns “fmiVersion” which is defined in this header file. The standard header file as documented in this specification has version “2.0” or "3.0" # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.22]: 2.1.4 Inquire Platform and Version Number of Header Files - FMISpec2.0.2[p.16]: 2.1.2 Platform Dependent Definitions + - FMISpec3.0[p. ]: 2.2.5. Inquire Version Number of Header Files -See also [`fmi2GetVersion`](@ref), [`unsafe_string`](https://docs.julialang.org/en/v1/base/strings/#Base.unsafe_string), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2GetVersion`](@ref), [`unsafe_string`](https://docs.julialang.org/en/v1/base/strings/#Base.unsafe_string), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3GetVersion`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiGetVersion(str::fmi2Struct) fmi2GetVersion(str) end +function fmiGetVersion(str::fmi3Struct) + fmi3GetVersion(str) +end """ @@ -726,20 +937,27 @@ end Prints FMU-specific information into the REPL. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3StructMD = Union{FMU3, FMU3Instance, fmi3ModelDescription}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Source - - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) -See also [`fmi2Info`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [`fmi2Info`](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [`fmi3Info`](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiInfo(str::fmi2Struct) fmi2Info(str) end - +function fmiInfo(str::fmi3Struct) + fmi3Info(str) +end +# TODO how to handle different calls for CS, ME, SE in FMI3 """ fmiInstantiate!(fmu::FMU2; pushComponents::Bool = true, visible::Bool = false, loggingOn::Bool = false, externalCallbacks::Bool = false, @@ -780,49 +998,67 @@ end """ - fmiFreeInstance!(str::fmi2Struct) + fmiFreeInstance!(str::Union{fmi2Struct, fmi3Struct}) Frees the allocated memory of the last instance of the FMU. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns - `status::fmi2Status`: returned by all functions to indicate the success of the function call +- `status::fmi3Status`: returned by all functions to indicate the success of the function call # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.23]: 2.1.6 Initialization, Termination, and Resetting an FMU - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0[p. ]: 2.3.1. Super State: FMU State Settable +- FMISpec3.0[p. ]: 2.2.4. Status Returned by Functions -See also [fmi2FreeInstance](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref). +See also [fmi2FreeInstance](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FMU2Component`](@ref), [fmi3FreeInstance](@ref), [`fmi3Struct`](@ref), [`FMU3`](@ref), [`FMU3Instance`](@ref). """ function fmiFreeInstance!(str::fmi2Struct) fmi2FreeInstance!(str) end +function fmiFreeInstance!(str::fmi3Struct) + fmi3FreeInstance!(str) +end """ - fmiSetDebugLogging(str::fmi2Struct) + fmiSetDebugLogging(str::Union{fmi2Struct, fmi3Struct}) Control the use of the logging callback function, version independent. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.22]: 2.1.5 Creation, Destruction and Logging of FMU Instances +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0[p. ]: 2.3.1. Super State: FMU State Settable """ function fmiSetDebugLogging(str::fmi2Struct) fmi2SetDebugLogging(str) end +function fmiSetDebugLogging(str::fmi3Struct) + fmi3SetDebugLogging(str) +end """ @@ -855,7 +1091,7 @@ See also [fmi2SetupExperiment](@ref), [`fmi2Struct`](@ref), [`FMU2`](@ref), [`FM function fmiSetupExperiment(str::fmi2Struct, args...; kwargs...) fmi2SetupExperiment(str, args...; kwargs...) end - +# TODO different function call in fmi3 more arguments """ fmiEnterInitializationMode(str::fmi2Struct) @@ -885,30 +1121,40 @@ end """ - fmiExitInitializationMode(str::fmi2Struct) + fmiExitInitializationMode(str::Union{fmi2Struct, fmi3Struct}) Informs the FMU to exit initialization mode, version independent. # Arguments -- `str::fmi2Struct`: Representative for an FMU in the FMI 2.0.2 Standard. +- `str::Union{fmi2Struct, fmi3Struct}`: Representative for an FMU in the [FMI 2.0.2 Standard](https://fmi-standard.org/) or [FMI 3.0 Standard](https://fmi-standard.org/). Other notation: More detailed: `fmi2Struct = Union{FMU2, FMU2Component}` +More detailed: `fmi3Struct = Union{FMU3, FMU3Instance}` - `str::FMU2`: Mutable struct representing a FMU and all it instantiated instances in the FMI 2.0.2 Standard. - `str::FMU2Component`: Mutable struct represents an instantiated instance of an FMU in the FMI 2.0.2 Standard. + - `str::FMU3`: Mutable struct representing an FMU in the [FMI 3.0 Standard](https://fmi-standard.org/). + - `str::FMU3Instance`: Mutable struct represents a pointer to an FMU specific data structure that contains the information needed. Also in [FMI 3.0 Standard](https://fmi-standard.org/). # Returns -- Returns a warning if `str.state` is not called in `fmi2ComponentStateInitializationMode`. +- Returns a warning if `str.state` is not called in `fmi2ComponentStateInitializationMode` or `fmi3InstanceInitializationMode`. - `status::fmi2Status`: returned by all functions to indicate the success of the function call +- `status::fmi3Status`: returned by all functions to indicate the success of the function call # Source - FMISpec2.0.2 Link: [https://fmi-standard.org/](https://fmi-standard.org/) - FMISpec2.0.2[p.23]: 2.1.6 Initialization, Termination, and Resetting an FMU - FMISpec2.0.2[p.18]: 2.1.3 Status Returned by Functions +- FMISpec3.0 Link: [https://fmi-standard.org/](https://fmi-standard.org/) +- FMISpec3.0[p. ]: 2.3.3. State: Initialization Mode +- FMISpec3.0[p. ]: 2.2.4. Status Returned by Functions - See also [fmi2ExitInitializationMode](@ref) + See also [fmi2ExitInitializationMode](@ref), [fmi3ExitInitializationMode](@ref). """ function fmiExitInitializationMode(str::fmi2Struct) fmi2ExitInitializationMode(str) end +function fmiExitInitializationMode(str::fmi3Struct) + fmi3ExitInitializationMode(str) +end """ Informs the FMU that the simulation run is terminated, version independent. @@ -916,13 +1162,18 @@ Informs the FMU that the simulation run is terminated, version independent. function fmiTerminate(str::fmi2Struct) fmi2Terminate(str) end - +function fmiTerminate(str::fmi3Struct) + fmi3Terminate(str) +end """ Resets the FMU after a simulation run, version independent. """ function fmiReset(str::fmi2Struct) fmi2Reset(str) end +function fmiReset(str::fmi3Struct) + fmi3Reset(str) +end """ ToDo @@ -930,20 +1181,27 @@ ToDo function fmiGet(str::fmi2Struct, args...; kwargs...) fmi2Get(str, args...; kwargs...) end - +function fmiGet(str::fmi3Struct, args...; kwargs...) + fmi3Get(str, args...; kwargs...) +end """ ToDo """ function fmiGet!(str::fmi2Struct, args...; kwargs...) fmi2Get!(str, args...; kwargs...) end - +function fmiGet!(str::fmi3Struct, args...; kwargs...) + fmi3Get!(str, args...; kwargs...) +end """ ToDo """ function fmiSet(str::fmi2Struct, args...; kwargs...) fmi2Set(str, args...; kwargs...) end +function fmiSet(str::fmi3Struct, args...; kwargs...) + fmi3Set(str, args...; kwargs...) +end """ Returns the real values of an array of variables @@ -951,46 +1209,49 @@ Returns the real values of an array of variables function fmiGetReal(str::fmi2Struct, args...; kwargs...) fmi2GetReal(str, args...; kwargs...) end - +function fmiGetReal(str::fmi3Struct, args...; kwargs...) + fmi3GetReal(str, args...; kwargs...) +end +# TODO different call in fmi3 fmi3GetOuputDerivatives function fmiGetRealOutputDerivatives(str::fmi2Struct, args...; kwargs...) fmi2GetRealOutputDerivatives(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Writes the real values of an array of variables in the given field """ function fmiGetReal!(str::fmi2Struct, args...; kwargs...) fmi2GetReal!(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Set the values of an array of real variables """ function fmiSetReal(str::fmi2Struct, args...; kwargs...) fmi2SetReal(str, args...; kwargs...) end - +# TODO different call in fmi3 """ ToDo """ function fmiSetRealInputDerivatives(str::fmi2Struct, args...; kwargs...) fmi2SetRealInputDerivatives(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Returns the integer values of an array of variables """ function fmiGetInteger(str::fmi2Struct,args...; kwargs...) fmi2GetInteger(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Writes the integer values of an array of variables in the given field """ function fmiGetInteger!(str::fmi2Struct, args...; kwargs...) fmi2GetInteger!(str, args...; kwargs...) end - +# TODO different call in fmi3 """ Set the values of an array of integer variables """ @@ -1004,6 +1265,9 @@ Returns the boolean values of an array of variables function fmiGetBoolean(str::fmi2Struct, args...; kwargs...) fmi2GetBoolean(str, args...; kwargs...) end +function fmiGetBoolean(str::fmi3Struct, args...; kwargs...) + fmi3GetBoolean(str, args...; kwargs...) +end """ Writes the boolean values of an array of variables in the given field @@ -1011,6 +1275,9 @@ Writes the boolean values of an array of variables in the given field function fmiGetBoolean!(str::fmi2Struct, args...; kwargs...) fmi2GetBoolean!(str, args...; kwargs...) end +function fmiGetBoolean!(str::fmi3Struct, args...; kwargs...) + fmi3GetBoolean!(str, args...; kwargs...) +end """ Set the values of an array of boolean variables @@ -1018,6 +1285,9 @@ Set the values of an array of boolean variables function fmiSetBoolean(str::fmi2Struct, args...; kwargs...) fmi2SetBoolean(str, args...; kwargs...) end +function fmiSetBoolean(str::fmi3Struct, args...; kwargs...) + fmi3SetBoolean(str, args...; kwargs...) +end """ Returns the string values of an array of variables @@ -1025,6 +1295,9 @@ Returns the string values of an array of variables function fmiGetString(str::fmi2Struct, args...; kwargs...) fmi2GetString(str, args...; kwargs...) end +function fmiGetString(str::fmi3Struct, args...; kwargs...) + fmi3GetString(str, args...; kwargs...) +end """ Writes the string values of an array of variables in the given field @@ -1032,6 +1305,9 @@ Writes the string values of an array of variables in the given field function fmiGetString!(str::fmi2Struct, args...; kwargs...) fmi2GetString!(str, args...; kwargs...) end +function fmiGetString!(str::fmi3Struct, args...; kwargs...) + fmi3GetString!(str, args...; kwargs...) +end """ Set the values of an array of string variables @@ -1039,13 +1315,20 @@ Set the values of an array of string variables function fmiSetString(str::fmi2Struct, args...; kwargs...) fmi2SetString(str, args...; kwargs...) end - +function fmiSetString(str::fmi3Struct, args...; kwargs...) + fmi3SetString(str, args...; kwargs...) +end +# TODO different call in fmi3 """ Returns the FMU state of the fmu """ function fmiGetFMUstate(str::fmi2Struct) fmi2GetFMUstate(str) end +function fmiGetFMUstate(str::fmi3Struct) + fmi3GetFMUstate(str) +end +# TODO different call in fmi3 """ Sets the FMU to the given state @@ -1053,6 +1336,10 @@ Sets the FMU to the given state function fmiSetFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SetFMUstate(str, args...; kwargs...) end +function fmiSetFMUstate(str::fmi3Struct, args...; kwargs...) + fmi3SetFMUstate(str, args...; kwargs...) +end +# TODO different call in fmi3 """ Free the memory for the allocated FMU state @@ -1060,6 +1347,10 @@ Free the memory for the allocated FMU state function fmiFreeFMUstate!(str::fmi2Struct, args...; kwargs...) fmi2FreeFMUstate!(str, args...; kwargs...) end +function fmiFreeFMUstate!(str::fmi3Struct, args...; kwargs...) + fmi3FreeFMUstate!(str, args...; kwargs...) +end +# TODO different call in fmi3 """ Returns the size of the byte vector the FMU can be stored in @@ -1067,6 +1358,10 @@ Returns the size of the byte vector the FMU can be stored in function fmiSerializedFMUstateSize(str::fmi2Struct, args...; kwargs...) fmi2SerializedFMUstateSize(str, args...; kwargs...) end +function fmiSerializedFMUstateSize(str::fmi3Struct, args...; kwargs...) + fmi3SerializedFMUstateSize(str, args...; kwargs...) +end +# TODO different call in fmi3 """ Serialize the data in the FMU state pointer @@ -1074,6 +1369,10 @@ Serialize the data in the FMU state pointer function fmiSerializeFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SerializeFMUstate(str, args...; kwargs...) end +function fmiSerializeFMUstate(str::fmi3Struct, args...; kwargs...) + fmi3SerializeFMUstate(str, args...; kwargs...) +end +# TODO different call in fmi3 """ Deserialize the data in the FMU state pointer @@ -1081,6 +1380,9 @@ Deserialize the data in the FMU state pointer function fmiDeSerializeFMUstate(str::fmi2Struct, args...; kwargs...) fmi2DeSerializeFMUstate(str, args...; kwargs...) end +function fmiDeSerializeFMUstate(str::fmi3Struct, args...; kwargs...) + fmi3DeSerializeFMUstate(str, args...; kwargs...) +end """ Returns the values of the directional derivatives. @@ -1088,6 +1390,9 @@ Returns the values of the directional derivatives. function fmiGetDirectionalDerivative(str::fmi2Struct, args...; kwargs...) fmi2GetDirectionalDerivative(str, args...; kwargs...) end +function fmiGetDirectionalDerivative(str::fmi3Struct, args...; kwargs...) + fmi3GetDirectionalDerivative(str, args...; kwargs...) +end """ Returns the values of the directional derivatives (in-place). @@ -1095,6 +1400,23 @@ Returns the values of the directional derivatives (in-place). function fmiGetDirectionalDerivative!(str::fmi2Struct, args...; kwargs...) fmi2GetDirectionalDerivative!(str, args...; kwargs...) end +function fmiGetDirectionalDerivative!(str::fmi3Struct, args...; kwargs...) + fmi3GetDirectionalDerivative!(str, args...; kwargs...) +end + +""" +Returns the values of the adjoint derivatives. +""" +function fmiGetAdjointDerivative(str::fmi3Struct, args...; kwargs...) + fmi3GetAdjointDerivative(str, args...; kwargs...) +end + +""" +Returns the values of the adjoint derivatives (in-place). +""" +function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) + fmi3GetAdjointDerivative!(str, args...; kwargs...) +end """ Does one step in the CoSimulation FMU @@ -1102,6 +1424,9 @@ Does one step in the CoSimulation FMU function fmiDoStep(str::fmi2Struct, args...; kwargs...) fmi2DoStep(str, args...; kwargs...) end +function fmiDoStep(str::fmi3Struct, args...; kwargs...) + fmi3DoStep(str, args...; kwargs...) +end """ Samples the values of the directional derivatives. @@ -1109,6 +1434,9 @@ Samples the values of the directional derivatives. function fmiSampleDirectionalDerivative(str::fmi2Struct, args...; kwargs...) fmi2SampleDirectionalDerivative(str, args...; kwargs...) end +function fmiSampleDirectionalDerivative(str::fmi3Struct, args...; kwargs...) + fmi3SampleDirectionalDerivative(str, args...; kwargs...) +end """ Samples the values of the directional derivatives (in-place). @@ -1116,12 +1444,18 @@ Samples the values of the directional derivatives (in-place). function fmiSampleDirectionalDerivative!(str::fmi2Struct, args...; kwargs...) fmi2SampleDirectionalDerivative!(str, args...; kwargs...) end +function fmiSampleDirectionalDerivative!(str::fmi3Struct, args...; kwargs...) + fmi3SampleDirectionalDerivative!(str, args...; kwargs...) +end """ Set a time instant """ -function fmiSetTime(c::fmi2Struct, args...; kwargs...) - fmi2SetTime(c, args...; kwargs...) +function fmiSetTime(str::fmi2Struct, args...; kwargs...) + fmi2SetTime(str, args...; kwargs...) +end +function fmiSetTime(str::fmi3Struct, args...; kwargs...) + fmi3SetTime(str, args...; kwargs...) end """ @@ -1130,14 +1464,20 @@ Set a new (continuous) state vector function fmiSetContinuousStates(str::fmi2Struct, args...; kwargs...) fmi2SetContinuousStates(str, args...; kwargs...) end +function fmiSetContinuousStates(str::fmi3Struct, args...; kwargs...) + fmi3SetContinuousStates(str, args...; kwargs...) +end """ The model enters Event Mode """ -function fmi2EnterEventMode(str::fmi2Struct) +function fmiEnterEventMode(str::fmi2Struct) fmi2EnterEventMode(str) end - +function fmiEnterEventMode(str::fmi3Struct) + fmi3EnterEventMode(str) +end +# TODO different function call in fmi3 """ Returns the next discrete states """ @@ -1151,6 +1491,9 @@ The model enters Continuous-Time Mode function fmiEnterContinuousTimeMode(str::fmi2Struct) fmi2EnterContinuousTimeMode(str) end +function fmiEnterContinuousTimeMode(str::fmi3Struct) + fmi3EnterContinuousTimeMode(str) +end """ This function must be called by the environment after every completed step @@ -1158,7 +1501,10 @@ This function must be called by the environment after every completed step function fmiCompletedIntegratorStep(str::fmi2Struct, args...; kwargs...) fmi2CompletedIntegratorStep(str, args...; kwargs...) end - +function fmiCompletedIntegratorStep(str::fmi3Struct, args...; kwargs...) + fmi3CompletedIntegratorStep(str, args...; kwargs...) +end +# TODO different function call """ Compute state derivatives at the current time instant and for the current states """ @@ -1172,6 +1518,9 @@ Returns the event indicators of the FMU function fmiGetEventIndicators(str::fmi2Struct) fmi2GetEventIndicators(str) end +function fmiGetEventIndicators(str::fmi3Struct) + fmi3GetEventIndicators(str) +end """ Return the new (continuous) state vector x @@ -1179,6 +1528,9 @@ Return the new (continuous) state vector x function fmiGetContinuousStates(s::fmi2Struct) fmi2GetContinuousStates(s) end +function fmiGetContinuousStates(s::fmi3Struct) + fmi3GetContinuousStates(s) +end """ Return the new (continuous) state vector x @@ -1186,6 +1538,9 @@ Return the new (continuous) state vector x function fmiGetNominalsOfContinuousStates(s::fmi2Struct) fmi2GetNominalsOfContinuousStates(s) end +function fmiGetNominalsOfContinuousStates(s::fmi3Struct) + fmi3GetNominalsOfContinuousStates(s) +end """ Returns the start/default value for a given value reference. @@ -1195,6 +1550,9 @@ TODO: Add this command in the documentation. function fmiGetStartValue(s::fmi2Struct, vr::fmi2ValueReferenceFormat) fmi2GetStartValue(s, vr) end +function fmiGetStartValue(s::fmi3Struct, vr::fmi3ValueReferenceFormat) + fmi3GetStartValue(s, vr) +end ##### function setters @@ -1324,7 +1682,7 @@ end ##### Multiple Dispatch fallback for FMUs with unsupported versions ##### -unsupportedFMUs = Union{FMU1,FMU3} +unsupportedFMUs = FMU1 function fmiDoStep(fmu::unsupportedFMUs, args...; kwargs...) error(unsupportedFMU::errorType) end @@ -1544,5 +1902,12 @@ end function fmiIsModelExchange(fmu::unsupportedFMUs) error(unsupportedFMU::errorType) end +function fmiGetAdjointDerivative(str::fmi2Struct, args...; kwargs...) + error(unsupportedFMU::errorType) +end +function fmiGetAdjointDerivative!(str::fmi2Struct, args...; kwargs...) + error(unsupportedFMU::errorType) +end + end # module FMI diff --git a/src/FMI2_comp_wraps.jl b/src/FMI2_comp_wraps.jl index 06d3af2f..3eacee12 100644 --- a/src/FMI2_comp_wraps.jl +++ b/src/FMI2_comp_wraps.jl @@ -8,33 +8,6 @@ # - wrappers to call fmi2ComponentFunctions from FMUs (additional functions, last instantiated component is used) [exported] # FMI-spec -""" - fmi2Simulate(fmu::FMU2, args...; kwargs...) - -Wrapper for fmi2Simulate() in FMI/FMI2_sim.jl -""" -function fmi2Simulate(fmu::FMU2, args...; kwargs...) - return fmi2Simulate(fmu, nothing, args...; kwargs...) -end - -""" - fmi2SimulateCS(fmu::FMU2, args...; kwargs...) - -Wrapper for fmi2SimulateCS() in FMI/FMI2_sim.jl -""" -function fmi2SimulateCS(fmu::FMU2, args...; kwargs...) - return fmi2SimulateCS(fmu, nothing, args...; kwargs...) -end - -""" - fmi2SimulateME(fmu::FMU2, args...; kwargs...) - -Wrapper for fmi2SimulateME() in FMI/FMI2_sim.jl -""" -function fmi2SimulateME(fmu::FMU2, args...; kwargs...) - return fmi2SimulateME(fmu, nothing, args...; kwargs...) -end - """ fmi2FreeInstance!(fmu::FMU2) @@ -566,6 +539,33 @@ function fmi2GetNominalsOfContinuousStates(fmu::FMU2) end # additionals +""" + fmi2Simulate(fmu::FMU2, args...; kwargs...) + +Wrapper for fmi2Simulate() in FMI/FMI2_sim.jl +""" +function fmi2Simulate(fmu::FMU2, args...; kwargs...) + return fmi2Simulate(fmu, nothing, args...; kwargs...) +end + +""" + fmi2SimulateCS(fmu::FMU2, args...; kwargs...) + +Wrapper for fmi2SimulateCS() in FMI/FMI2_sim.jl +""" +function fmi2SimulateCS(fmu::FMU2, args...; kwargs...) + return fmi2SimulateCS(fmu, nothing, args...; kwargs...) +end + +""" + fmi2SimulateME(fmu::FMU2, args...; kwargs...) + +Wrapper for fmi2SimulateME() in FMI/FMI2_sim.jl +""" +function fmi2SimulateME(fmu::FMU2, args...; kwargs...) + return fmi2SimulateME(fmu, nothing, args...; kwargs...) +end + """ fmi2GetStartValue(fmu::FMU2, args...; kwargs...) diff --git a/src/FMI3_JLD2.jl b/src/FMI3_JLD2.jl new file mode 100644 index 00000000..c93ba612 --- /dev/null +++ b/src/FMI3_JLD2.jl @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using FMIImport: FMU3Solution + +""" +Saves a FMU3Solution for later use. +""" +function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") + return JLD2.save(filepath, Dict(keyword=>solution)) +end + +""" +Loads a FMU3Solution. Returns a previously saved `FMU3Solution`. +""" +function fmiLoadSolution(filepath::AbstractString; keyword="solution") + return JLD2.load(filepath, keyword) +end \ No newline at end of file diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 9d6747d5..66dad1fe 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -3,1317 +3,237 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # +# What is included in the file `FMI3_additional.jl` (FMU add functions)? +# - high-level functions, that are useful, but not part of the FMI-spec [exported] + +using Base.Filesystem: mktempdir + using FMIImport: FMU3, fmi3ModelDescription using FMIImport: fmi3Float32, fmi3Float64, fmi3Int8, fmi3Int16, fmi3Int32, fmi3Int64, fmi3Boolean, fmi3String, fmi3Binary, fmi3UInt8, fmi3UInt16, fmi3UInt32, fmi3UInt64, fmi3Byte using FMIImport: fmi3Clock, fmi3FMUState -using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate - -# wrapper functions on the model description -function fmi3GetModelName(fmu::FMU3) - fmi3GetModelName(fmu.modelDescription) -end -function fmi3GetInstantiationToken(fmu::FMU3) - fmi3GetInstantiationToken(fmu.modelDescription) -end -function fmi3GetGenerationTool(fmu::FMU3) - fmi3GetGenerationTool(fmu.modelDescription) -end -function fmi3GetGenerationDateAndTime(fmu::FMU3) - fmi3GetGenerationDateAndTime(fmu.modelDescription) -end -function fmi3GetVariableNamingConvention(fmu::FMU3) - fmi3GetVariableNamingConvention(fmu.modelDescription) -end - -function fmi3CanGetSetState(fmu::FMU3) - fmi3CanGetSetState(fmu.modelDescription) -end -function fmi3CanSerializeFMUstate(fmu::FMU3) - fmi3CanSerializeFMUstate(fmu.modelDescription) -end -function fmi3ProvidesDirectionalDerivatives(fmu::FMU3) - fmi3ProvidesDirectionalDerivatives(fmu.modelDescription) -end -function fmi3ProvidesAdjointDerivatives(fmu::FMU3) - fmi3ProvidesAdjointDerivatives(fmu.modelDescription) -end -function fmi3IsCoSimulation(fmu::FMU3) - fmi3IsCoSimulation(fmu.modelDescription) -end -function fmi3IsModelExchange(fmu::FMU3) - fmi3IsModelExchange(fmu.modelDescription) -end -function fmi3IsScheduledExecution(fmu::FMU3) - fmi3IsScheduledExecution(fmu.modelDescription) -end +using FMIImport: fmi3True, fmi3False +using FMIImport: fmi3DependencyKindDependent, fmi3DependencyKindFixed +using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate, fmi3Instance +import FMIImport: fmi3VariableNamingConventionFlat, fmi3VariableNamingConventionStructured +""" +Returns how a variable depends on another variable based on the model description. """ -Returns an array of ValueReferences coresponding to the variable names. -""" -function fmi3String2ValueReference(md::fmi3ModelDescription, names::Array{String}) - vr = Array{fmi3ValueReference}(undef,0) - for name in names - reference = fmi3String2ValueReference(md, name) - if reference === nothing - @warn "Value reference for variable '$name' not found, skipping." - else - push!(vr, reference) - end - end - vr -end - -""" -Returns the ValueReference coresponding to the variable name. -""" -function fmi3String2ValueReference(md::fmi3ModelDescription, name::String) - reference = nothing - if haskey(md.stringValueReferences, name) - reference = md.stringValueReferences[name] - else - @warn "No variable named '$name' found." - end - reference -end - -function fmi3String2ValueReference(fmu::FMU3, name::Union{String, Array{String}}) - fmi3String2ValueReference(fmu.modelDescription, name) +function fmi3VariableDependsOnVariable(fmu::FMU3, vr1::fmi3ValueReference, vr2::fmi3ValueReference) + i1 = fmu.modelDescription.valueReferenceIndicies[vr1] + i2 = fmu.modelDescription.valueReferenceIndicies[vr2] + return fmi3GetDependencies(fmu)[i1, i2] end """ -Returns an array of variable names matching a fmi3ValueReference. -""" -function fmi3ValueReference2String(md::fmi3ModelDescription, reference::fmi3ValueReference) - [k for (k,v) in md.stringValueReferences if v == reference] -end -function fmi3ValueReference2String(md::fmi3ModelDescription, reference::Int64) - fmi3ValueReference2String(md, fmi3ValueReference(reference)) -end - -function fmi3ValueReference2String(fmu::FMU3, reference::Union{fmi3ValueReference, Int64}) - fmi3ValueReference2String(fmu.modelDescription, reference) -end +Returns the FMU's dependency-matrix for fast look-ups on dependencies between value references. +Entries are from type fmi3DependencyKind. """ -Source: FMISpec3.0, Version D5ef1c1:: 2.3.1. Super State: FMU State Setable +function fmi3GetDependencies(fmu::FMU3) + if !isdefined(fmu, :dependencies) + dim = length(fmu.modelDescription.valueReferences) + @info "fmi3GetDependencies: Started building dependency matrix $(dim) x $(dim) ..." -Create a new instance of the given fmu, adds a logger if logginOn == true. + if fmi3DependenciesSupported(fmu.modelDescription) + fmu.dependencies = fill(nothing, dim, dim) -Returns the instance of a new FMU component. + for i in 1:dim + modelVariable = fmi3ModelVariablesForValueReference(fmu.modelDescription, fmu.modelDescription.valueReferences[i])[1] + + if modelVariable.dependencies !== nothing + indicies = collect(fmu.modelDescription.valueReferenceIndicies[fmu.modelDescription.modelVariables[dependency].valueReference] for dependency in modelVariable.dependencies) + dependenciesKind = modelVariable.dependenciesKind + + k = 1 + for j in 1:dim + if j in indicies + if dependenciesKind[k] == "fixed" + fmu.dependencies[i,j] = fmi3DependencyKindFixed + elseif dependenciesKind[k] == "dependent" + fmu.dependencies[i,j] = fmi3DependencyKindDependent + else + @warn "Unknown dependency kind for index ($i, $j) = `$(dependenciesKind[k])`." + end + k += 1 + end + end + end + end + else + fmu.dependencies = fill(nothing, dim, dim) + end -For more information call ?fmi3InstantiateModelExchange -""" -function fmi3InstantiateModelExchange!(fmu::FMU3; visible::Bool = false, loggingOn::Bool = false) + @info "fmi3GetDependencies: Building dependency matrix $(dim) x $(dim) finished." + end - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{Cvoid}, Ptr{Cchar}, Cuint, Ptr{Cchar})) + fmu.dependencies +end - compAddr = fmi3InstantiateModelExchange(fmu.cInstantiateModelExchange, fmu.instanceName, fmu.modelDescription.instantiationToken, fmu.fmuResourceLocation, fmi3Boolean(visible), fmi3Boolean(loggingOn), fmu.instanceEnvironment, ptrLogger) +function fmi3PrintDependencies(fmu::FMU2) + dep = fmi3GetDependencies(fmu) + ni, nj = size(dep) - if compAddr == Ptr{Cvoid}(C_NULL) - @error "fmi3InstantiateModelExchange!(...): Instantiation failed!" - return nothing + for i in 1:ni + str = "" + for j in 1:nj + str = "$(str) $(Integer(dep[i,j]))" + end + println(str) end - previous_z = zeros(fmi3Float64, fmi3GetEventIndicators(fmu.modelDescription)) - rootsFound = zeros(fmi3Int32, fmi3GetEventIndicators(fmu.modelDescription)) - stateEvent = fmi3False - timeEvent = fmi3False - stepEvent = fmi3False - component = fmi3Component(compAddr, fmu, previous_z, rootsFound, stateEvent, timeEvent, stepEvent) - push!(fmu.components, component) - component end """ -Source: FMISpec3.0, Version D5ef1c1:: 2.3.1. Super State: FMU State Setable - -Create a new instance of the given fmu, adds a logger if logginOn == true. - -Returns the instance of a new FMU component. - -For more information call ?fmi3InstantiateCoSimulation +Prints FMU related information. """ -function fmi3InstantiateCoSimulation!(fmu::FMU3; visible::Bool = false, loggingOn::Bool = false, eventModeUsed::Bool = false, ptrIntermediateUpdate=nothing) +function fmi3Info(fmu::FMU3) + println("#################### Begin information for FMU ####################") - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{Cvoid}, Ptr{Cchar}, Cuint, Ptr{Cchar})) - if ptrIntermediateUpdate === nothing - ptrIntermediateUpdate = @cfunction(fmi3CallbackIntermediateUpdate, Cvoid, (Ptr{Cvoid}, fmi3Float64, fmi3Boolean, fmi3Boolean, fmi3Boolean, fmi3Boolean, Ptr{fmi3Boolean}, Ptr{fmi3Float64})) + println("\tModel name:\t\t\t$(fmi3GetModelName(fmu))") + println("\tFMI-Version:\t\t\t$(fmi3GetVersion(fmu))") + println("\tInstantiation Token:\t\t\t\t$(fmi3GetInstantiationToken(fmu))") + println("\tGeneration tool:\t\t$(fmi3GetGenerationTool(fmu))") + println("\tGeneration time:\t\t$(fmi3GetGenerationDateAndTime(fmu))") + print("\tVar. naming conv.:\t\t") + if fmi3GetVariableNamingConvention(fmu) == fmi3VariableNamingConventionFlat + println("flat") + elseif fmi3GetVariableNamingConvention(fmu) == fmi3VariableNamingConventionStructured + println("structured") + else + println("[unknown]") end - if fmu.modelDescription.CShasEventMode - mode = eventModeUsed - else - mode = false - end - - compAddr = fmi3InstantiateCoSimulation(fmu.cInstantiateCoSimulation, fmu.instanceName, fmu.modelDescription.instantiationToken, fmu.fmuResourceLocation, fmi3Boolean(visible), fmi3Boolean(loggingOn), - fmi3Boolean(mode), fmi3Boolean(fmu.modelDescription.CScanReturnEarlyAfterIntermediateUpdate), fmu.modelDescription.intermediateUpdateValueReferences, Csize_t(length(fmu.modelDescription.intermediateUpdateValueReferences)), fmu.instanceEnvironment, ptrLogger, ptrIntermediateUpdate) + println("\tEvent indicators:\t\t$(fmi3GetNumberOfEventIndicators(fmu))") - if compAddr == Ptr{Cvoid}(C_NULL) - @error "fmi3InstantiateCoSimulation!(...): Instantiation failed!" - return nothing + println("\tInputs:\t\t\t\t$(length(fmu.modelDescription.inputValueReferences))") + for vr in fmu.modelDescription.inputValueReferences + println("\t\t$(vr) $(fmi3ValueReferenceToString(fmu, vr))") end - component = fmi3Component(compAddr, fmu) - push!(fmu.components, component) - component -end - -# TODO not tested -""" -Source: FMISpec3.0, Version D5ef1c1:: 2.3.1. Super State: FMU State Setable - -Create a new instance of the given fmu, adds a logger if logginOn == true. - -Returns the instance of a new FMU component. - -For more information call ?fmi3InstantiateScheduledExecution -""" -function fmi3InstantiateScheduledExecution!(fmu::FMU3, ptrlockPreemption::Ptr{Cvoid}, ptrunlockPreemption::Ptr{Cvoid}; visible::Bool = false, loggingOn::Bool = false) - - ptrLogger = @cfunction(fmi3CallbackLogger, Cvoid, (Ptr{Cvoid}, Ptr{Cchar}, Cuint, Ptr{Cchar})) - ptrClockUpdate = @cfunction(fmi3CallbackClockUpdate, Cvoid, (Ptr{Cvoid}, )) - - compAddr = fmi3InstantiateScheduledExecution(fmu.cInstantiateScheduledExecution, fmu.instanceName, fmu.modelDescription.instantiationToken, fmu.fmuResourceLocation, fmi3Boolean(visible), fmi3Boolean(loggingOn), fmu.instanceEnvironment, ptrLogger, ptrClockUpdate, ptrlockPreemption, ptrunlockPreemption) - - if compAddr == Ptr{Cvoid}(C_NULL) - @error "fmi3InstantiateScheduledExecution!(...): Instantiation failed!" - return nothing + println("\tOutputs:\t\t\t$(length(fmu.modelDescription.outputValueReferences))") + for vr in fmu.modelDescription.outputValueReferences + println("\t\t$(vr) $(fmi3ValueReferenceToString(fmu, vr))") end - component = fmi3Component(compAddr, fmu) - push!(fmu.components, component) - component -end - - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.4. Inquire Version Number of Header Files - -Returns the version of the FMI Standard used in this FMU. - -For more information call ?fmi3GetVersion -""" -function fmi3GetVersion(fmu::FMU3) - fmi3GetVersion(fmu.cGetVersion) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.1. Super State: FMU State Setable - -Sets debug logging for the FMU. - -For more information call ?fmi3SetDebugLogging -""" -function fmi3SetDebugLogging(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetDebugLogging(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -FMU enters Initialization mode. - -For more information call ?fmi3EnterInitializationMode -""" -function fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterInitializationMode(fmu.components[end], startTime, stopTime; tolerance = tolerance) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -FMU exits Initialization mode. - -For more information call ?fmi3ExitInitializationMode -""" -function fmi3ExitInitializationMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3ExitInitializationMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.4. Super State: Initialized - -Informs FMU that simulation run is terminated. - -For more information call ?fmi3Terminate -""" -function fmi3Terminate(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3Terminate(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.1. Super State: FMU State Setable - -Resets FMU. - -For more information call ?fmi3Reset -""" -function fmi3Reset(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3Reset(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float32 variables. - -For more information call ?fmi3GetFloat32 -""" -function fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat32(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float32 variables. - -For more information call ?fmi3GetFloat32! -""" -function fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat32!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Float32 variables. - -For more information call ?fmi3SetFloat32 -""" -function fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFloat32(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float64 variables. - -For more information call ?fmi3GetFloat64 -""" -function fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat64(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Float64 variables. - -For more information call ?fmi3GetFloat64! -""" -function fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat64!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Float64 variables. - -For more information call ?fmi3SetFloat64 -""" -function fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFloat64(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int8 variables. - -For more information call ?fmi3GetInt8 -""" -function fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt8(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int8 variables. - -For more information call ?fmi3GetInt8! -""" -function fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt8!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int8 variables. - -For more information call ?fmi3SetInt8 -""" -function fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt8(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt8 variables. - -For more information call ?fmi3GetUInt8 -""" -function fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt8(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt8 variables. - -For more information call ?fmi3GetUInt8! -""" -function fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt8!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt8 variables. - -For more information call ?fmi3SetUInt8 -""" -function fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt8(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int16 variables. - -For more information call ?fmi3GetInt16 -""" -function fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt16(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int16 variables. - -For more information call ?fmi3GetInt16! -""" -function fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt16!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int16 variables. - -For more information call ?fmi3SetInt16 -""" -function fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt16(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt16 variables. - -For more information call ?fmi3GetUInt16 -""" -function fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt16(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt16 variables. - -For more information call ?fmi3GetUInt16! -""" -function fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt16!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt16 variables. - -For more information call ?fmi3SetUInt16 -""" -function fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt16(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int32 variables. - -For more information call ?fmi3GetInt32 -""" -function fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt32(fmu.components[end], vr) -end + println("\tStates:\t\t\t\t$(length(fmu.modelDescription.stateValueReferences))") + for vr in fmu.modelDescription.stateValueReferences + println("\t\t$(vr) $(fmi3ValueReferenceToString(fmu, vr))") + end -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + println("\tSupports Co-Simulation:\t\t$(fmi3IsCoSimulation(fmu))") + if fmi3IsCoSimulation(fmu) + println("\t\tModel identifier:\t$(fmu.modelDescription.coSimulation.modelIdentifier)") + println("\t\tGet/Set State:\t\t$(fmu.modelDescription.coSimulation.canGetAndSetFMUstate)") + println("\t\tSerialize State:\t$(fmu.modelDescription.coSimulation.canSerializeFMUstate)") + println("\t\tDir. Derivatives:\t$(fmu.modelDescription.coSimulation.providesDirectionalDerivatives)") + println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.coSimulation.providesAdjointDerivatives)") + println("\t\tEvent Mode:\t$(fmu.modelDescription.coSimulation.hasEventMode)") + + println("\t\tVar. com. steps:\t$(fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize)") + println("\t\tInput interpol.:\t$(fmu.modelDescription.coSimulation.canInterpolateInputs)") + println("\t\tMax order out. der.:\t$(fmu.modelDescription.coSimulation.maxOutputDerivativeOrder)") + end -Get the values of an array of fmi3Int32 variables. + println("\tSupports Model-Exchange:\t$(fmi3IsModelExchange(fmu))") + if fmi3IsModelExchange(fmu) + println("\t\tModel identifier:\t$(fmu.modelDescription.modelExchange.modelIdentifier)") + println("\t\tGet/Set State:\t\t$(fmu.modelDescription.modelExchange.canGetAndSetFMUstate)") + println("\t\tSerialize State:\t$(fmu.modelDescription.modelExchange.canSerializeFMUstate)") + println("\t\tDir. Derivatives:\t$(fmu.modelDescription.modelExchange.providesDirectionalDerivatives)") + println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.modelExchange.providesAdjointDerivatives)") + end -For more information call ?fmi3GetInt32! -""" -function fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + println("\tSupports Scheduled-Execution:\t$(fmi3IsScheduledExecution(fmu))") + if fmi3IsScheduledExecution(fmu) + println("\t\tModel identifier:\t$(fmu.modelDescription.scheduledExecution.modelIdentifier)") + println("\t\tGet/Set State:\t\t$(fmu.modelDescription.scheduledExecution.canGetAndSetFMUstate)") + println("\t\tSerialize State:\t$(fmu.modelDescription.scheduledExecution.canSerializeFMUstate)") + println("\t\tNeeds Execution Tool:\t$(fmu.modelDescription.scheduledExecution.needsExecutionTool)") + println("\t\tInstantiated Once Per Process:\t$(fmu.modelDescription.scheduledExecution.canBeInstantiatedOnlyOncePerProcess)") + println("\t\tPer Element Dependencies:\t$(fmu.modelDescription.scheduledExecution.providesPerElementDependencies)") + + println("\t\tDir. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesDirectionalDerivatives)") + println("\t\tAdj. Derivatives:\t$(fmu.modelDescription.scheduledExecution.providesAdjointDerivatives)") + end - fmi3GetInt32!(fmu.components[end], vr, values) + println("##################### End information for FMU #####################") end -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values +function fmiCheckVersion(pathToFMU::String; unpackPath=nothing) + # Unzip MD -Set the values of an array of fmi3Int32 variables. + # Download FMU if necessary + if startswith(pathToFMU, "http") + @info "Downloading FMU for Version extraction from `$(pathToFMU)`." + pathToFMU = download(pathToFMU) + end -For more information call ?fmi3SetInt32 -""" -function fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + pathToFMU = normpath(pathToFMU) - fmi3SetInt32(fmu.components[end], vr, values) -end + fileNameExt = basename(pathToFMU) + (fileName, fileExt) = splitext(fileNameExt) + + if unpackPath === nothing + # cleanup=true leads to issues with automatic testing on linux server. + unpackPath = mktempdir(; prefix="fmijl_", cleanup=false) + end -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + zipPath = joinpath(unpackPath, fileName * ".zip") + unzippedPath = joinpath(unpackPath, fileName) -Get the values of an array of fmi3UInt32 variables. + # only copy ZIP if not already there + if !isfile(zipPath) + cp(pathToFMU, zipPath; force=true) + end -For more information call ?fmi3GetUInt32 -""" -function fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + @assert isfile(zipPath) ["fmi3Unzip(...): ZIP-Archive couldn't be copied to `$zipPath`."] - fmi3GetUInt32(fmu.components[end], vr) -end + zipAbsPath = isabspath(zipPath) ? zipPath : joinpath(pwd(), zipPath) + unzippedAbsPath = isabspath(unzippedPath) ? unzippedPath : joinpath(pwd(), unzippedPath) -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + @assert isfile(zipAbsPath) ["fmi3Unzip(...): Can't deploy ZIP-Archive at `$(zipAbsPath)`."] -Get the values of an array of fmi3UInt32 variables. + # only unzip if not already done + if !isdir(unzippedAbsPath) + mkpath(unzippedAbsPath) -For more information call ?fmi3GetUInt32! -""" -function fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + zarchive = ZipFile.Reader(zipAbsPath) + for f in zarchive.files + if f.name == "modelDescription.xml" + fileAbsPath = normpath(joinpath(unzippedAbsPath, f.name)) - fmi3GetUInt32!(fmu.components[end], vr, values) -end + # create directory if not forced by zip file folder + mkpath(dirname(fileAbsPath)) -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + numBytes = write(fileAbsPath, read(f)) + + if numBytes == 0 + @info "fmi3Unzip(...): Written file `$(f.name)`, but file is empty." + end -Set the values of an array of fmi3UInt32 variables. + @assert isfile(fileAbsPath) ["fmi3Unzip(...): Can't unzip file `$(f.name)` at `$(fileAbsPath)`."] + end + + end + close(zarchive) + end -For more information call ?fmi3SetUInt32 -""" -function fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + @assert isdir(unzippedAbsPath) ["fmi3Unzip(...): ZIP-Archive couldn't be unzipped at `$(unzippedPath)`."] + @info "fmiUnzipVersion(...): Successfully unzipped modelDescription.xml at `$unzippedAbsPath`." - fmi3SetUInt32(fmu.components[end], vr, values) -end + # read version tag -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values + doc = readxml(unzippedAbsPath) -Get the values of an array of fmi3Int64 variables. + version = root["fmiVersion"] -For more information call ?fmi3GetInt64 -""" -function fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + # cleanup unzipped modelDescription + try + rm(unzippedAbsPath; recursive = true, force = true) + rm(zipAbsPath; recursive = true, force = true) + catch e + @warn "Cannot delete unpacked data on disc. Maybe some files are opened in another application." + end - fmi3GetInt64(fmu.components[end], vr) + # return version + version end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Int64 variables. - -For more information call ?fmi3GetInt64! -""" -function fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt64!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Int64 variables. - -For more information call ?fmi3SetInt64 -""" -function fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt64(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3GetUInt64 -""" -function fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt64(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3GetUInt64! -""" -function fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt64!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3UInt64 variables. - -For more information call ?fmi3SetUInt64 -""" -function fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt64(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Boolean variables. - -For more information call ?fmi3GetBoolean -""" -function fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBoolean(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Boolean variables. - -For more information call ?fmi3GetBoolean! -""" -function fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBoolean!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Boolean variables. - -For more information call ?fmi3SetBoolean -""" -function fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetBoolean(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3String variables. - -For more information call ?fmi3GetString -""" -function fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetString(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3String variables. - -For more information call ?fmi3GetString! -""" -function fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetString!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3String variables. - -For more information call ?fmi3SetString -""" -function fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetString(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Binary variables. - -For more information call ?fmi3GetBinary -""" -function fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBinary(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Binary variables. - -For more information call ?fmi3GetBinary! -""" -function fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBinary!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Binary variables. - -For more information call ?fmi3SetBinary -""" -function fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, valueSizes::Union{Array{Csize_t}, Csize_t}, values::Union{Array{fmi3Binary}, fmi3Binary}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetBinary(fmu.components[end], vr, valueSizes, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Clock variables. - -For more information call ?fmi3GetClock -""" -function fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetClock(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Get the values of an array of fmi3Clock variables. - -For more information call ?fmi3GetClock! -""" -function fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetClock!(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.2. Getting and Setting Variable Values - -Set the values of an array of fmi3Clock variables. - -For more information call ?fmi3SetClock -""" -function fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetClock(fmu.components[end], vr, values) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Get the pointer to the current FMU state. - -For more information call ?fmi3GetFMUState -""" -function fmi3GetFMUState(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFMUState(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Set the FMU to the given fmi3FMUstate. - -For more information call ?fmi3SetFMUState -""" -function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFMUState(fmu.components[end], state) -end - -""" -function fmi3FreeFMUState(c::fmi3Component, FMUstate::Ref{fmi3FMUState}) - -Free the allocated memory for the FMU state. - -For more information call ?fmi3FreeFMUState -""" -function fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - stateRef = Ref(state) - fmi3FreeFMUState(fmu.components[end], stateRef) - state = stateRef[] -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Returns the size of a byte vector the FMU can be stored in. - -For more information call ?fmi3SerzializedFMUStateSize -""" -function fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SerializedFMUStateSize(fmu.components[end], state) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Serialize the data in the FMU state pointer. - -For more information call ?fmi3SerializeFMUState -""" -function fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SerializeFMUState(fmu.components[end], state) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.6.4. Getting and Setting the Complete FMU State - -Deserialize the data in the serializedState fmi3Byte field. - -For more information call ?fmi3DeSerializeFMUState -""" -function fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3DeSerializeFMUState(fmu.components[end], serializedState) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives. - -For more information call ?fmi3GetDirectionalDerivative -""" -function fmi3GetDirectionalDerivative(fmu::FMU3, - unknowns::fmi3ValueReference, - knowns::fmi3ValueReference, - seed::fmi3Float64 = 1.0) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives. - -For more information call ?fmi3GetDirectionalDerivative -""" -function fmi3GetDirectionalDerivative(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves directional derivatives in-place. - -For more information call ?fmi3GetDirectionalDerivative -""" -function fmi3GetDirectionalDerivative!(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - sensitivity::Array{fmi3Float64}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative!(fmu.components[end], unknowns, knowns, sensitivity, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative -""" -function fmi3GetAdjointDerivative(fmu::FMU3, - unknowns::fmi3ValueReference, - knowns::fmi3ValueReference, - seed::fmi3Float64 = 1.0) - - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative -""" -function fmi3GetAdjointDerivative(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative(fmu.components[end], unknowns, knowns, seed) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.11. Getting Partial Derivatives - -Retrieves adjoint derivatives. - -For more information call ?fmi3GetAdjointDerivative -""" -function fmi3GetAdjointDerivative!(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - sensitivity::Array{fmi3Float64}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative!(fmu.components[end], unknowns, knowns, sensitivity, seed) -end -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs - -Retrieves the n-th derivative of output values. - -vr defines the value references of the variables -the array order specifies the corresponding order of derivation of the variables - -For more information call ?fmi3GetOutputDerivatives -""" -function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetOutputDerivatives(fmu.components[end], vr, order) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.12. Getting Derivatives of Continuous Outputs - -Retrieves the n-th derivative of output values. - -vr defines the value references of the variables -the array order specifies the corresponding order of derivation of the variables - -For more information call ?fmi3GetOutputDerivatives -""" -function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReference, order::Integer) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetOutputDerivatives(fmu.components[end], vr, order) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -If the importer needs to change structural parameters, it must move the FMU into Configuration Mode using fmi3EnterConfigurationMode. -For more information call ?fmi3EnterConfigurationMode -""" -function fmi3EnterConfigurationMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterConfigurationMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -This function returns the number of continuous states. -This function can only be called in Model Exchange. -For more information call ?fmi3GetNumberOfContinuousStates -""" -function fmi3GetNumberOfContinuousStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfContinuousStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.2. State: Instantiated - -This function returns the number of event indicators. -This function can only be called in Model Exchange. -For more information call ?fmi3GetNumberOfEventIndicators -""" -function fmi3GetNumberOfEventIndicators(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfEventIndicators(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables - -The number of dependencies of a given variable, which may change if structural parameters are changed, can be retrieved by calling the following function: -For more information call ?fmi3GetNumberOfVariableDependencies -""" -function fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfVariableDependencies(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -Return the states at the current time instant. -For more information call ?fmi3GetContinuousStates -""" -function fmi3GetContinuousStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetContinuousStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.2.10. Dependencies of Variables - -The dependencies (of type dependenciesKind) can be retrieved by calling the function fmi3GetVariableDependencies. -For more information call ?fmi3GetVariableDependencies -""" -function fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetVariableDependencies(fmu.components[end], vr) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -Return the nominal values of the continuous states. - -For more information call ?fmi3GetNominalsOfContinuousStates -""" -function fmi3GetNominalsOfContinuousStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNominalsOfContinuousStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.3. State: Initialization Mode - -This function is called to trigger the evaluation of fdisc to compute the current values of discrete states from previous values. -The FMU signals the support of fmi3EvaluateDiscreteStates via the capability flag providesEvaluateDiscreteStates. - -For more information call ?fmi3EvaluateDiscreteStates -""" -function fmi3EvaluateDiscreteStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EvaluateDiscreteStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -This function is called to signal a converged solution at the current super-dense time instant. fmi3UpdateDiscreteStates must be called at least once per super-dense time instant. - -For more information call ?fmi3UpdateDiscreteStates -""" -function fmi3UpdateDiscreteStates(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3UpdateDiscreteStates(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -The model enters Continuous-Time Mode. - -For more information call ?fmi3EnterContinuousTimeMode -""" -function fmi3EnterContinuousTimeMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterContinuousTimeMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.5. State: Event Mode - -This function must be called to change from Event Mode into Step Mode in Co-Simulation. - -For more information call ?fmi3EnterStepMode -""" -function fmi3EnterStepMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterStepMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 2.3.6. State: Configuration Mode - -Exits the Configuration Mode and returns to state Instantiated. - -For more information call ?fmi3ExitConfigurationMode -""" -function fmi3ExitConfigurationMode(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3ExitConfigurationMode(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Set independent variable time and reinitialize chaching of variables that depend on time. - -For more information call ?fmi3SetTime -""" -function fmi3SetTime(fmu::FMU3, time::Real) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmu.t = time - fmi3SetTime(fmu.components[end], fmi3Float64(time)) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Set a new (continuous) state vector and reinitialize chaching of variables that depend on states. - -For more information call ?fmi3SetContinuousStates -""" -function fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - nx = Csize_t(length(x)) - fmu.x = x - fmi3SetContinuousStates(fmu.components[end], Array{fmi3Float64}(x), nx) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Compute state derivatives at the current time instant and for the current states. - -For more information call ?fmi3GetContinuousStateDerivatives -""" -function fmi3GetContinuousStateDerivatives(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetContinuousStateDerivatives(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -Returns the event indicators of the FMU. - -For more information call ?fmi3GetEventIndicators -""" -function fmi3GetEventIndicators(fmu::FMU3) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetEventIndicators(fmu.components[end]) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -This function must be called by the environment after every completed step -If enterEventMode == fmi3True, the event mode must be entered -If terminateSimulation == fmi3True, the simulation shall be terminated - -For more information call ?fmi3CompletedIntegratorStep -""" -function fmi3CompletedIntegratorStep(fmu::FMU3, - noSetFMUStatePriorToCurrentPoint::fmi3Boolean) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3CompletedIntegratorStep(fmu.components[end], noSetFMUStatePriorToCurrentPoint) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 3.2.1. State: Continuous-Time Mode - -The model enters Event Mode. - -For more information call ?fmi3EnterEventMode -""" -function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterEventMode(fmu.components[end], stepEvent, stateEvent, rootsFound, nEventIndicators, timeEvent) -end - -""" -Source: FMISpec3.0, Version D5ef1c1: 4.2.1. State: Step Mode - -The computation of a time step is started. - -For more information call ?fmi3DoStep -""" -function fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - refeventEncountered = Ref(eventEncountered) - refterminateSimulation = Ref(terminateSimulation) - refearlyReturn = Ref(earlyReturn) - reflastSuccessfulTime = Ref(lastSuccessfulTime) - fmi3DoStep(fmu.components[end], fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) - eventEncountered = refeventEncountered[] - terminateSimulation = refterminateSimulation[] - earlyReturn = refearlyReturn[] - lastSuccessfulTime = reflastSuccessfulTime[] -end - -""" -Starts a simulation of the fmu instance for the matching fmu type. If both types are available, CS is preferred over ME. -""" -function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; - recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3Simulate(fmu.components[end], t_start, t_stop; - recordValues=recordValues, saveat=saveat, setup=setup) -end -""" -Starts a simulation of a FMU in CS-mode. -""" -function fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; - recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SimulateCS(fmu.components[end], t_start, t_stop; - recordValues=recordValues, saveat=saveat, setup=setup) -end - -""" -Starts a simulation of a FMU in ME-mode. -""" -function fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SimulateME(fmu.components[end], t_start, t_stop; kwargs...) -end - -""" -Returns the start/default value for a given value reference. - -TODO: Add this command in the documentation. -""" -function fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) - @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetStartValue(fmu.components[end], vr) -end \ No newline at end of file diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index 1ed16699..451eb292 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -1,4 +1,989 @@ # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher # Licensed under the MIT license. See LICENSE file in the project root for details. -# \ No newline at end of file +# + +# What is included in the file `FMI3_comp_wraps.jl` (FMU instance wrappers)? +# - wrappers to call fmi3InstanceFunctions from FMUs (FMI-functions, last instantiated component is used) [exported] +# - wrappers to call fmi3InstanceFunctions from FMUs (additional functions, last instantiated component is used) [exported] + + +using FMIImport: FMU3, fmi3ModelDescription +using FMIImport: fmi3Float32, fmi3Float64, fmi3Int8, fmi3Int16, fmi3Int32, fmi3Int64, fmi3Boolean, fmi3String, fmi3Binary, fmi3UInt8, fmi3UInt16, fmi3UInt32, fmi3UInt64, fmi3Byte +using FMIImport: fmi3Clock, fmi3FMUState +using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate + +# fmi-spec +""" + fmi3FreeInstance!(fmu::FMU3) + +Wrapper for fmi3FreeInstance!() in FMIImport/FMI3_c.jl +""" +function fmi3FreeInstance!(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi2FreeInstance!(fmu.instances[end]) # this command also removes the instance from the array +end + +""" + fmi3SetDebugLogging(fmu::FMU3) + +Wrapper for fmi3SetDebugLogging() in FMIImport/FMI3_int.jl +""" +function fmi3SetDebugLogging(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetDebugLogging(fmu.instances[end]) +end + +""" + fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) + +Wrapper for fmi3EnterInitializationMode() in FMIImport/FMI3_c.jl +""" +function fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterInitializationMode(fmu.instances[end], startTime, stopTime; tolerance = tolerance) +end + +""" + fmi3ExitInitializationMode(fmu::FMU2) + +Wrapper for fmi3ExitInitializationMode() in FMIImport/FMI3_c.jl +""" +function fmi3ExitInitializationMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3ExitInitializationMode(fmu.instances[end]) +end + +""" + fmi3Terminate(fmu::FMU3) + +Wrapper for fmi3Terminate() in FMIImport/FMI3_c.jl +""" +function fmi3Terminate(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3Terminate(fmu.instances[end]) +end + +""" + fmi3Reset(fmu::FMU3) + +Wrapper for fmi2Reset() in FMIImport/FMI3_c.jl +""" +function fmi3Reset(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3Reset(fmu.instances[end]) +end + +""" + fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetFloat32() in FMIImport/FMI3_int.jl +""" +function fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat32(fmu.instances[end], vr) +end + +""" + fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) + +Wrapper for fmi3GetFloat32!() in FMIImport/FMI3_int.jl +""" +function fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat32!(fmu.instances[end], vr, values) +end + +""" +fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) + +Wrapper for fmi3SetFloat32() in FMIImport/FMI3_int.jl +""" +function fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetFloat32(fmu.instances[end], vr, values) +end + +""" + fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetFloat64() in FMIImport/FMI3_int.jl +""" +function fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat64(fmu.instances[end], vr) +end + +""" + fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + +Wrapper for fmi3GetFloat64!() in FMIImport/FMI3_int.jl +""" +function fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFloat64!(fmu.instances[end], vr, values) +end + +""" + fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + +Wrapper for fmi3SetFloat64() in FMIImport/FMI3_int.jl +""" +function fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetFloat64(fmu.instances[end], vr, values) +end + +""" + fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetInt8() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt8(fmu.instances[end], vr) +end + +""" + fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + +Wrapper for fmi3GetInt8!() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt8!(fmu.instances[end], vr, values) +end + +""" + fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + +Wrapper for fmi3SetInt8() in FMIImport/FMI3_int.jl +""" +function fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt8(fmu.instances[end], vr, values) +end + +""" + fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetUInt8() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt8(fmu.instances[end], vr) +end + +""" + fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + +Wrapper for fmi3GetUInt8!() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt8!(fmu.instances[end], vr, values) +end + +""" + fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + +Wrapper for fmi3SetUInt8() in FMIImport/FMI3_int.jl +""" +function fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt8(fmu.instances[end], vr, values) +end + +""" + fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetInt16() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt16(fmu.instances[end], vr) +end + +""" + fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + +Wrapper for fmi3GetInt16!() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt16!(fmu.instances[end], vr, values) +end + +""" + fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + +Wrapper for fmi3SetInt16() in FMIImport/FMI3_int.jl +""" +function fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt16(fmu.instances[end], vr, values) +end + +""" + fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetUInt16() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt16(fmu.instances[end], vr) +end + +""" + fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + +Wrapper for fmi3GetUInt16!() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt16!(fmu.instances[end], vr, values) +end + +""" + fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + +Wrapper for fmi3SetUInt16() in FMIImport/FMI3_int.jl +""" +function fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt16(fmu.instances[end], vr, values) +end + +""" + fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetInt32() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt32(fmu.instances[end], vr) +end + +""" + fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + +Wrapper for fmi3GetInt32!() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt32!(fmu.instances[end], vr, values) +end + +""" + fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + +Wrapper for fmi3SetInt32() in FMIImport/FMI3_int.jl +""" +function fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt32(fmu.instances[end], vr, values) +end + +""" + fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetUInt32() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt32(fmu.instances[end], vr) +end + +""" + fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + +Wrapper for fmi3GetUInt32!() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt32!(fmu.instances[end], vr, values) +end + +""" + fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + +Wrapper for fmi3SetUInt32() in FMIImport/FMI3_int.jl +""" +function fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt32(fmu.instances[end], vr, values) +end + +""" + fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetInt64() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt64(fmu.instances[end], vr) +end + +""" + fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + +Wrapper for fmi3GetInt64!() in FMIImport/FMI3_int.jl +""" +function fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetInt64!(fmu.instances[end], vr, values) +end + +""" + fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + +Wrapper for fmi3SetInt64() in FMIImport/FMI3_int.jl +""" +function fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetInt64(fmu.instances[end], vr, values) +end + +""" + fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetUInt64() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt64(fmu.instances[end], vr) +end + +""" + fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + +Wrapper for fmi3GetUInt64!() in FMIImport/FMI3_int.jl +""" +function fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetUInt64!(fmu.instances[end], vr, values) +end + +""" + fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + +Wrapper for fmi3SetUInt64() in FMIImport/FMI3_int.jl +""" +function fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetUInt64(fmu.instances[end], vr, values) +end + +""" + fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetBoolean() in FMIImport/FMI3_int.jl +""" +function fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBoolean(fmu.instances[end], vr) +end + +""" + fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) + +Wrapper for fmi3GetBoolean!() in FMIImport/FMI3_int.jl +""" +function fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBoolean!(fmu.instances[end], vr, values) +end + +""" + fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) + +Wrapper for fmi3SetBoolean!() in FMIImport/FMI3_int.jl +""" +function fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetBoolean(fmu.instances[end], vr, values) +end + +""" + fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetString() in FMIImport/FMI3_int.jl +""" +function fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetString(fmu.instances[end], vr) +end + +""" + fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + +Wrapper for fmi3GetString!() in FMIImport/FMI3_int.jl +""" +function fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetString!(fmu.instances[end], vr, values) +end + +""" + fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + +Wrapper for fmi3SetString() in FMIImport/FMI3_int.jl +""" +function fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetString(fmu.instances[end], vr, values) +end + +""" + fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetBinary() in FMIImport/FMI3_int.jl +""" +function fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBinary(fmu.instances[end], vr) +end + +""" + fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + +Wrapper for fmi3GetBinary!() in FMIImport/FMI3_int.jl +""" +function fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetBinary!(fmu.instances[end], vr, values) +end + +""" + fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + +Wrapper for fmi3SetBinary() in FMIImport/FMI3_int.jl +""" +function fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, valueSizes::Union{Array{Csize_t}, Csize_t}, values::Union{Array{fmi3Binary}, fmi3Binary}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetBinary(fmu.instances[end], vr, valueSizes, values) +end + +""" + fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetClock() in FMIImport/FMI3_int.jl +""" +function fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetClock(fmu.instances[end], vr) +end + +""" + fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + +Wrapper for fmi3GetClock!() in FMIImport/FMI3_int.jl +""" +function fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetClock!(fmu.instances[end], vr, values) +end + +""" + fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + +Wrapper for fmi3SetClock() in FMIImport/FMI3_int.jl +""" +function fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetClock(fmu.instances[end], vr, values) +end + +""" + fmi3GetFMUstate(fmu::FMU3) + +Wrapper for fmi3GetFMUstate() in FMIImport/FMI3_int.jl +""" +function fmi3GetFMUState(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetFMUState(fmu.instances[end]) +end + +""" + fmi3SetFMUstate(fmu::FMU3,state::fmi3FMUState) + +Wrapper for fmi3SetFMUstate() in FMIImport/FMI3_c.jl +""" +function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SetFMUState(fmu.instances[end], state) +end + +""" + fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) + +Wrapper for fmi3FreeFMUState() in FMIImport/FMI3_int.jl +""" +function fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3FreeFMUState(fmu.instances[end], state) +end + +""" + fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) + +Wrapper for fmi3SerializedFMUStateSize() in FMIImport/FMI3_int.jl +""" +function fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SerializedFMUStateSize(fmu.instances[end], state) +end + +""" + fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) + +Wrapper for fmi3SerializeFMUState() in FMIImport/FMI3_int.jl +""" +function fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SerializeFMUState(fmu.instances[end], state) +end + +""" + fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) + +Wrapper for fmi3DeSerializeFMUState() in FMIImport/FMI3_int.jl +""" +function fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3DeSerializeFMUState(fmu.instances[end], serializedState) +end + +""" + fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::fmi3Float64 = 1.0)) + +Wrapper for fmi3GetDirectionalDerivative() in FMIImport/FMI3_int.jl +""" +function fmi3GetDirectionalDerivative(fmu::FMU3, + unknowns::fmi3ValueReference, + knowns::fmi3ValueReference, + seed::fmi3Float64 = 1.0) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetDirectionalDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" + fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + +Wrapper for fmi3GetDirectionalDerivative() in FMIImport/FMI3_int.jl +""" +function fmi3GetDirectionalDerivative(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetDirectionalDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" + fmi3GetDirectionalDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, knowns::Array{fmi3ValueReference}, sensitivity::Array{fmi3Float64}, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + +Wrapper for fmi3GetDirectionalDerivative!() in FMIImport/FMI3_int.jl +""" +function fmi3GetDirectionalDerivative!(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + sensitivity::Array{fmi3Float64}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetDirectionalDerivative!(fmu.instances[end], unknowns, knowns, sensitivity, seed) +end + +""" + fmi3GetAdjointDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::fmi3Float64 = 1.0)) + +Wrapper for fmi3GetAdjointDerivative() in FMIImport/FMI3_int.jl +""" +function fmi3GetAdjointDerivative(fmu::FMU3, + unknowns::fmi3ValueReference, + knowns::fmi3ValueReference, + seed::fmi3Float64 = 1.0) + + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetAdjointDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" + fmi3GetAdjointDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + +Wrapper for fmi3GetAdjointDerivative() in FMIImport/FMI3_int.jl +""" +function fmi3GetAdjointDerivative(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetAdjointDerivative(fmu.instances[end], unknowns, knowns, seed) +end + +""" + fmi3GetAdjointDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, knowns::Array{fmi3ValueReference}, sensitivity::Array{fmi3Float64}, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + +Wrapper for fmi3GetAdjointDerivative!() in FMIImport/FMI3_int.jl +""" +function fmi3GetAdjointDerivative!(fmu::FMU3, + unknowns::Array{fmi3ValueReference}, + knowns::Array{fmi3ValueReference}, + sensitivity::Array{fmi3Float64}, + seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetAdjointDerivative!(fmu.instances[end], unknowns, knowns, sensitivity, seed) +end +""" + fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) + +Wrapper for fmi3GetOutputDerivatives() in FMIImport/FMI3_int.jl +""" +function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetOutputDerivatives(fmu.instances[end], vr, order) +end + +""" + fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Integer) + +Wrapper for fmi3GetOutputDerivatives() in FMIImport/FMI3_int.jl +""" +function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReference, order::Integer) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetOutputDerivatives(fmu.instances[end], vr, order) +end + +""" + fmi3EnterConfigurationMode(fmu::FMU3) + +Wrapper for fmi3EnterConfigurationMode() in FMIImport/FMI3_c.jl +""" +function fmi3EnterConfigurationMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterConfigurationMode(fmu.instances[end]) +end + +""" + fmi3GetNumberOfContinuousStates(fmu::FMU3) + +Wrapper for fmi3GetNumberOfContinuousStates() in FMIImport/FMI3_c.jl +""" +function fmi3GetNumberOfContinuousStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNumberOfContinuousStates(fmu.instances[end]) +end + +""" + fmi3GetNumberOfEventIndicators(fmu::FMU3) + +Wrapper for fmi3GetNumberOfEventIndicators() in FMIImport/FMI3_c.jl +""" +function fmi3GetNumberOfEventIndicators(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNumberOfEventIndicators(fmu.instances[end]) +end + +""" + fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) + +Wrapper for fmi3GetNumberOfVariableDependencies() in FMIImport/FMI3_c.jl +""" +function fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNumberOfVariableDependencies(fmu.instances[end], vr) +end + +""" + fmi3GetContinuousStates(fmu::FMU3) + +Wrapper for fmi3GetContinuousStates() in FMIImport/FMI3_c.jl +""" +function fmi3GetContinuousStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetContinuousStates(fmu.instances[end]) +end + +""" + fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) + +Wrapper for fmi3GetVariableDependencies() in FMIImport/FMI3_c.jl +""" +function fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetVariableDependencies(fmu.instances[end], vr) +end + +""" + fmi3GetNominalsOfContinuousStates(fmu::FMU3) + +Wrapper for fmi3GetNominalsOfContinuousStates() in FMIImport/FMI3_c.jl +""" +function fmi3GetNominalsOfContinuousStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetNominalsOfContinuousStates(fmu.instances[end]) +end + +""" +fmi3EvaluateDiscreteStates(fmu::FMU3) + +Wrapper for fmi3EvaluateDiscreteStates() in FMIImport/FMI3_c.jl +""" +function fmi3EvaluateDiscreteStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EvaluateDiscreteStates(fmu.instances[end]) +end + +""" + fmi3UpdateDiscreteStates(fmu::FMU3) + +Wrapper for fmi3UpdateDiscreteStates() in FMIImport/FMI3_c.jl +""" +function fmi3UpdateDiscreteStates(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3UpdateDiscreteStates(fmu.instances[end]) +end + +""" + fmi3EnterContinuousTimeMode(fmu::FMU3) + +Wrapper for fmi3EnterContinuousTimeMode() in FMIImport/FMI3_c.jl +""" +function fmi3EnterContinuousTimeMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterContinuousTimeMode(fmu.instances[end]) +end + +""" + fmi3EnterStepMode(fmu::FMU3) + +Wrapper for fmi3EnterStepMode() in FMIImport/FMI3_c.jl +""" +function fmi3EnterStepMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterStepMode(fmu.instances[end]) +end + +""" + fmi3ExitConfigurationMode(fmu::FMU3) + +Wrapper for fmi3ExitConfigurationMode() in FMIImport/FMI3_c.jl +""" +function fmi3ExitConfigurationMode(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3ExitConfigurationMode(fmu.instances[end]) +end + +""" + fmi3SetTime(fmu::FMU3, time::Real) + +Wrapper for fmi3SetTime() in FMIImport/FMI3_c.jl +""" +function fmi3SetTime(fmu::FMU3, time::Real) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmu.t = time + fmi3SetTime(fmu.instances[end], fmi3Float64(time)) +end + +""" + fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) + +Wrapper for fmi3SetContinuousStates() in FMIImport/FMI3_c.jl +""" +function fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + nx = Csize_t(length(x)) + fmu.x = x + fmi3SetContinuousStates(fmu.instances[end], Array{fmi3Float64}(x), nx) +end + +""" +fmi3GetContinuousStateDerivatives(fmu::FMU3) + +Wrapper for fmi3GetContinuousStateDerivatives() in FMIImport/FMI3_c.jl +""" +function fmi3GetContinuousStateDerivatives(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetContinuousStateDerivatives(fmu.instances[end]) +end + +""" + fmi3GetEventIndicators(fmu::FMU3) + +Wrapper for fmi3GetEventIndicators() in FMIImport/FMI3_c.jl +""" +function fmi3GetEventIndicators(fmu::FMU3) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetEventIndicators(fmu.instances[end]) +end + +""" +fmi3CompletedIntegratorStep(fmu::FMU3, noSetFMUStatePriorToCurrentPoint::fmi3Boolean) + +Wrapper for fmi3CompletedIntegratorStep() in FMIImport/FMI3_c.jl +""" +function fmi3CompletedIntegratorStep(fmu::FMU3, + noSetFMUStatePriorToCurrentPoint::fmi3Boolean) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3CompletedIntegratorStep(fmu.instances[end], noSetFMUStatePriorToCurrentPoint) +end + +""" + fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) + +Wrapper for fmi3EnterEventMode() in FMIImport/FMI3_c.jl +""" +function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3EnterEventMode(fmu.instances[end], stepEvent, stateEvent, rootsFound, nEventIndicators, timeEvent) +end + +""" + fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) + +Wrapper for fmi3DoStep() in FMIImport/FMI3_c.jl +""" +function fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + refeventEncountered = Ref(eventEncountered) + refterminateSimulation = Ref(terminateSimulation) + refearlyReturn = Ref(earlyReturn) + reflastSuccessfulTime = Ref(lastSuccessfulTime) + fmi3DoStep(fmu.instances[end], fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) + eventEncountered = refeventEncountered[] + terminateSimulation = refterminateSimulation[] + earlyReturn = refearlyReturn[] + lastSuccessfulTime = reflastSuccessfulTime[] +end + +#additional +""" + fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; + recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + +Wrapper for fmi3Simulate() in FMI/FMI3_sim.jl +""" +function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; + recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3Simulate(fmu.instances[end], t_start, t_stop; + recordValues=recordValues, saveat=saveat, setup=setup) +end +""" +fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; +recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + +Wrapper for fmi3SimulateCS() in FMI/FMI3_sim.jl +""" +function fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; + recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SimulateCS(fmu.instances[end], t_start, t_stop; + recordValues=recordValues, saveat=saveat, setup=setup) +end + +""" + fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) + +Wrapper for fmi3SimulateME() in FMI/FMI3_sim.jl +""" +function fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3SimulateME(fmu.instances[end], t_start, t_stop; kwargs...) +end + +""" + fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) + +Wrapper for fmi3GetStartValue() in FMIImport/FMI3_c.jl +""" +function fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + + fmi3GetStartValue(fmu.instances[end], vr) +end \ No newline at end of file diff --git a/test/cs_me.jl b/test/FMI2/cs_me.jl similarity index 100% rename from test/cs_me.jl rename to test/FMI2/cs_me.jl diff --git a/test/dir_ders.jl b/test/FMI2/dir_ders.jl similarity index 100% rename from test/dir_ders.jl rename to test/FMI2/dir_ders.jl diff --git a/test/getter_setter.jl b/test/FMI2/getter_setter.jl similarity index 100% rename from test/getter_setter.jl rename to test/FMI2/getter_setter.jl diff --git a/test/load_save.jl b/test/FMI2/load_save.jl similarity index 100% rename from test/load_save.jl rename to test/FMI2/load_save.jl diff --git a/test/model_description.jl b/test/FMI2/model_description.jl similarity index 100% rename from test/model_description.jl rename to test/FMI2/model_description.jl diff --git a/test/plots.jl b/test/FMI2/plots.jl similarity index 100% rename from test/plots.jl rename to test/FMI2/plots.jl diff --git a/test/sens.jl b/test/FMI2/sens.jl similarity index 100% rename from test/sens.jl rename to test/FMI2/sens.jl diff --git a/test/sim_CS.jl b/test/FMI2/sim_CS.jl similarity index 100% rename from test/sim_CS.jl rename to test/FMI2/sim_CS.jl diff --git a/test/sim_ME.jl b/test/FMI2/sim_ME.jl similarity index 100% rename from test/sim_ME.jl rename to test/FMI2/sim_ME.jl diff --git a/test/sim_auto.jl b/test/FMI2/sim_auto.jl similarity index 100% rename from test/sim_auto.jl rename to test/FMI2/sim_auto.jl diff --git a/test/state.jl b/test/FMI2/state.jl similarity index 100% rename from test/state.jl rename to test/FMI2/state.jl diff --git a/test/FMI3/cs_me.jl b/test/FMI3/cs_me.jl new file mode 100644 index 00000000..0c7f1641 --- /dev/null +++ b/test/FMI3/cs_me.jl @@ -0,0 +1,57 @@ +############### +# Prepare FMU # +############### + +t_start = 0.0 +t_stop = 1.0 + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +@test fmiIsCoSimulation(myFMU) +@test fmiIsModelExchange(myFMU) +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +sol = fmiSimulateCS(fmuStruct, t_start, t_stop) +@test sol.success +sol = fmiSimulateME(fmuStruct, t_start, t_stop) +@test sol.success +fmiUnload(myFMU) + + + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:ME) +@test myFMU.type == FMI.fmi2TypeModelExchange +comp = fmiInstantiate!(myFMU; loggingOn=false) +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +sol = fmiSimulate(fmuStruct, t_start, t_stop) +@test sol.success +fmiUnload(myFMU) + + + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:CS) +@test myFMU.type == FMI.fmi2TypeCoSimulation +comp = fmiInstantiate!(myFMU; loggingOn=false) +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +sol = fmiSimulate(fmuStruct, t_start, t_stop) +@test sol.success +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/dir_ders.jl b/test/FMI3/dir_ders.jl new file mode 100644 index 00000000..6e19ba32 --- /dev/null +++ b/test/FMI3/dir_ders.jl @@ -0,0 +1,55 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using FMI.FMIImport.FMICore: fmi2Real + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknwon fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +@test fmiSetupExperiment(fmuStruct) == 0 +@test fmiEnterInitializationMode(fmuStruct) == 0 +@test fmiExitInitializationMode(fmuStruct) == 0 + +targetValues = [[0.0, -10.0], [1.0, 0.0]] +dir_ders_buffer = zeros(fmi2Real, 2) +sample_ders_buffer = zeros(fmi2Real, 2, 1) +for i in 1:fmiGetNumberOfStates(myFMU) + + if fmiProvidesDirectionalDerivative(myFMU) + # multi derivatives calls + sample_ders = fmiSampleDirectionalDerivative(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]]) + fmiSampleDirectionalDerivative!(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]], sample_ders_buffer) + + @test sum(abs.(sample_ders[:,1] - targetValues[i])) < 1e-3 + @test sum(abs.(sample_ders_buffer[:,1] - targetValues[i])) < 1e-3 + + dir_ders = fmiGetDirectionalDerivative(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]]) + @test fmiGetDirectionalDerivative!(fmuStruct, myFMU.modelDescription.derivativeValueReferences, [myFMU.modelDescription.stateValueReferences[i]], dir_ders_buffer) == 0 + + @test sum(abs.(dir_ders - targetValues[i])) < 1e-3 + @test sum(abs.(dir_ders_buffer - targetValues[i])) < 1e-3 + + # single derivative call + dir_der = fmiGetDirectionalDerivative(fmuStruct, myFMU.modelDescription.derivativeValueReferences[1], myFMU.modelDescription.stateValueReferences[1]) + @test dir_der == targetValues[1][1] + + else + @warn "Skipping directional derivative testing, FMU from $(ENV["EXPORTINGTOOL"]) doesn't support directional derivatives." + end + +end + +fmiUnload(myFMU) diff --git a/test/FMI3/getter_setter.jl b/test/FMI3/getter_setter.jl new file mode 100644 index 00000000..4fed4967 --- /dev/null +++ b/test/FMI3/getter_setter.jl @@ -0,0 +1,142 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +############### +# Prepare FMU # +############### + +myFMU = fmiLoad("IO", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +@test fmiSetupExperiment(fmuStruct, 0.0) == 0 + +@test fmiEnterInitializationMode(fmuStruct) == 0 + +realValueReferences = ["p_real", "u_real"] +integerValueReferences = ["p_integer", "u_integer"] +booleanValueReferences = ["p_boolean", "u_boolean"] +stringValueReferences = ["p_string", "p_string"] + +######################### +# Testing Single Values # +######################### + +rndReal = 100 * rand() +rndInteger = round(Integer, 100 * rand()) +rndBoolean = rand() > 0.5 +rndString = Random.randstring(12) + +cacheReal = 0.0 +cacheInteger = 0 +cacheBoolean = false +cacheString = "" + +@test fmiSetReal(fmuStruct, realValueReferences[1], rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences[1]) == rndReal +@test fmiSetReal(fmuStruct, realValueReferences[1], -rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences[1]) == -rndReal + +@test fmiSetInteger(fmuStruct, integerValueReferences[1], rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences[1]) == rndInteger +@test fmiSetInteger(fmuStruct, integerValueReferences[1], -rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences[1]) == -rndInteger + +@test fmiSetBoolean(fmuStruct, booleanValueReferences[1], rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences[1]) == rndBoolean +@test fmiSetBoolean(fmuStruct, booleanValueReferences[1], !rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences[1]) == !rndBoolean + +@test fmiSetString(fmuStruct, stringValueReferences[1], rndString) == 0 +@test fmiGetString(fmuStruct, stringValueReferences[1]) == rndString + +fmiSet(fmuStruct, + [realValueReferences[1], integerValueReferences[1], booleanValueReferences[1], stringValueReferences[1]], + [rndReal, rndInteger, rndBoolean, rndString]) +@test fmiGet(fmuStruct, + [realValueReferences[1], integerValueReferences[1], booleanValueReferences[1], stringValueReferences[1]]) == + [rndReal, rndInteger, rndBoolean, rndString] + +#@test fmiGetStartValue(fmuStruct, "p_enumeration") == "myEnumeration1" +@test fmiGetStartValue(fmuStruct, "p_string") == "Hello World!" +@test fmiGetStartValue(fmuStruct, "p_real") == 0.0 + +################## +# Testing Arrays # +################## + +rndReal = [100 * rand(), 100 * rand()] +rndInteger = [round(Integer, 100 * rand()), round(Integer, 100 * rand())] +rndBoolean = [(rand() > 0.5), (rand() > 0.5)] +tmp = Random.randstring(8) +rndString = [tmp, tmp] + +cacheReal = [0.0, 0.0] +cacheInteger = [FMI.fmi2Integer(0), FMI.fmi2Integer(0)] +cacheBoolean = [FMI.fmi2Boolean(false), FMI.fmi2Boolean(false)] +cacheString = [pointer(""), pointer("")] + +@test fmiSetReal(fmuStruct, realValueReferences, rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences) == rndReal +fmiGetReal!(fmuStruct, realValueReferences, cacheReal) +@test cacheReal == rndReal +@test fmiSetReal(fmuStruct, realValueReferences, -rndReal) == 0 +@test fmiGetReal(fmuStruct, realValueReferences) == -rndReal +fmiGetReal!(fmuStruct, realValueReferences, cacheReal) +@test cacheReal == -rndReal + +@test fmiSetInteger(fmuStruct, integerValueReferences, rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences) == rndInteger +fmiGetInteger!(fmuStruct, integerValueReferences, cacheInteger) +@test cacheInteger == rndInteger +@test fmiSetInteger(fmuStruct, integerValueReferences, -rndInteger) == 0 +@test fmiGetInteger(fmuStruct, integerValueReferences) == -rndInteger +fmiGetInteger!(fmuStruct, integerValueReferences, cacheInteger) +@test cacheInteger == -rndInteger + +@test fmiSetBoolean(fmuStruct, booleanValueReferences, rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences) == rndBoolean +fmiGetBoolean!(fmuStruct, booleanValueReferences, cacheBoolean) +@test cacheBoolean == rndBoolean +not_rndBoolean = collect(!b for b in rndBoolean) +@test fmiSetBoolean(fmuStruct, booleanValueReferences, not_rndBoolean) == 0 +@test fmiGetBoolean(fmuStruct, booleanValueReferences) == not_rndBoolean +fmiGetBoolean!(fmuStruct, booleanValueReferences, cacheBoolean) +@test cacheBoolean == not_rndBoolean + +@test fmiSetString(fmuStruct, stringValueReferences, rndString) == 0 +@test fmiGetString(fmuStruct, stringValueReferences) == rndString +fmiGetString!(fmuStruct, stringValueReferences, cacheString) +@test unsafe_string.(cacheString) == rndString + +#@test fmiGetStartValue(fmuStruct, ["p_enumeration", "p_string", "p_real"]) == ["myEnumeration1", "Hello World!", 0.0] +@test fmiGetStartValue(fmuStruct, ["p_string", "p_real"]) == ["Hello World!", 0.0] + +# Testing input/output derivatives +dirs = fmiGetRealOutputDerivatives(fmuStruct, ["y_real"], ones(FMI.fmi2Integer, 1)) +@test dirs == -Inf # at this point, derivative is undefined +@test fmiSetRealInputDerivatives(fmuStruct, ["u_real"], ones(FMI.fmi2Integer, 1), zeros(1)) == 0 + +@test fmiExitInitializationMode(fmuStruct) == 0 +@test fmiDoStep(fmuStruct, 0.1) == 0 + +dirs = fmiGetRealOutputDerivatives(fmuStruct, ["y_real"], ones(FMI.fmi2Integer, 1)) +@test dirs == 0.0 + +############ +# Clean up # +############ + +fmiUnload(myFMU) diff --git a/test/FMI3/load_save.jl b/test/FMI3/load_save.jl new file mode 100644 index 00000000..235bec76 --- /dev/null +++ b/test/FMI3/load_save.jl @@ -0,0 +1,45 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using JLD2 + +# our simulation setup +t_start = 0.0 +t_stop = 8.0 + +# load the FMU container +myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +recordValues = ["mass.s", "mass.v"] +solutionME = fmiSimulateME(myFMU, t_start, t_stop; recordValues=recordValues) +solutionCS = fmiSimulateCS(myFMU, t_start, t_stop; recordValues=recordValues) + +# ME + +fmiSaveSolution(solutionME, "solutionME.jld2") +anotherSolutionME = fmiLoadSolution("solutionME.jld2") + +@test solutionME.success == true +@test solutionME.success == anotherSolutionME.success +@test solutionME.states.u == anotherSolutionME.states.u +@test solutionME.states.t == anotherSolutionME.states.t +@test solutionME.values.saveval == anotherSolutionME.values.saveval +@test solutionME.values.t == anotherSolutionME.values.t + +# ME-BONUS: events +@test solutionME.events == anotherSolutionME.events + +# CS + +fmiSaveSolution(solutionCS, "solutionCS.jld2") +anotherSolutionCS = fmiLoadSolution("solutionCS.jld2") + +@test solutionCS.success == true +@test solutionCS.success == anotherSolutionCS.success +@test solutionCS.values.saveval == anotherSolutionCS.values.saveval +@test solutionCS.values.t == anotherSolutionCS.values.t + +# unload the FMU, remove unpacked data on disc ("clean up") +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/model_description.jl b/test/FMI3/model_description.jl new file mode 100644 index 00000000..af364e98 --- /dev/null +++ b/test/FMI3/model_description.jl @@ -0,0 +1,35 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using FMI: fmi2VariableNamingConventionStructured, fmi2DependencyKindDependent, fmi2DependencyKindFixed + +myFMU = fmiLoad("SpringDFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +@test fmiGetVersion(myFMU) == "2.0" +@test fmiGetTypesPlatform(myFMU) == "default" + +@test fmiGetModelName(myFMU) == "SpringFrictionPendulum1D" +@test fmiGetVariableNamingConvention(myFMU) == fmi2VariableNamingConventionStructured +@test fmiIsCoSimulation(myFMU) == true +@test fmiIsModelExchange(myFMU) == true + +@test fmiGetGUID(myFMU) == "{df491d8d-0598-4495-913e-5b025e54d7f2}" +@test fmiGetGenerationTool(myFMU) == "Dymola Version 2022x (64-bit), 2021-10-08" +@test fmiGetGenerationDateAndTime(myFMU) == "2022-03-03T15:09:18Z" +@test fmiGetNumberOfEventIndicators(myFMU) == 24 +@test fmiCanGetSetState(myFMU) == true +@test fmiCanSerializeFMUstate(myFMU) == true +@test fmiProvidesDirectionalDerivative(myFMU) == true + +depMtx = fmi2GetDependencies(myFMU) +@test fmi2DependencyKindFixed in depMtx +@test fmi2DependencyKindDependent in depMtx + +@test fmi2GetDefaultStartTime(myFMU.modelDescription) ≈ 0.0 +@test fmi2GetDefaultStopTime(myFMU.modelDescription) ≈ 1.0 +@test fmi2GetDefaultTolerance(myFMU.modelDescription) ≈ 1e-4 +@test fmi2GetDefaultStepSize(myFMU.modelDescription) === nothing + +fmiUnload(myFMU) diff --git a/test/FMI3/plots.jl b/test/FMI3/plots.jl new file mode 100644 index 00000000..217ce953 --- /dev/null +++ b/test/FMI3/plots.jl @@ -0,0 +1,37 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using Plots + +# our simulation setup +t_start = 0.0 +t_stop = 8.0 + +# load the FMU container +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +# print some useful FMU-information into the REPL +fmiInfo(myFMU) + +# make an instance from the FMU +fmiInstantiate!(myFMU) + +recordValues = ["mass.s", "mass.v"] +solutionME = fmiSimulateME(myFMU, t_start, t_stop; recordValues=recordValues) +solutionCS = fmiSimulateCS(myFMU, t_start, t_stop; recordValues=recordValues) + +# plot the results +fig = fmiPlot(solutionME) + +fig = Plots.plot() +fmiPlot!(fig, solutionME) + +fig = fmiPlot(solutionCS) + +fig = Plots.plot() +fmiPlot!(fig, solutionCS) + +# unload the FMU, remove unpacked data on disc ("clean up") +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/sens.jl b/test/FMI3/sens.jl new file mode 100644 index 00000000..77b20aad --- /dev/null +++ b/test/FMI3/sens.jl @@ -0,0 +1,61 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +import ForwardDiff +import Zygote + +using FMI.FMIImport: fmi2SampleDirectionalDerivative, fmi2GetJacobian, fmi2SetContinuousStates + +FMUPaths = [get_model_filename("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]), + get_model_filename("BouncingBall1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"])] + +t_start = 0.0 +t_step = 0.01 +t_stop = 5.0 +tData = t_start:t_step:t_stop + +for FMUPath in FMUPaths + myFMU = fmiLoad(FMUPath) + comp = fmiInstantiate!(myFMU; loggingOn=false) + + fmiSetupExperiment(comp, t_start, t_stop) + fmiEnterInitializationMode(comp) + fmiExitInitializationMode(comp) + + x0 = fmiGetContinuousStates(comp) + numStates = length(x0) + + dx = zeros(numStates) + t = 0.0 + p = [] + + # Jacobians for x0 + FD_jac = ForwardDiff.jacobian(x -> FMI.fx(comp, dx, x, p, t), x0) + ZG_jac = Zygote.jacobian(FMI.fx, comp, dx, x0, p, t)[3] + fmiSetContinuousStates(comp, x0) + samp_jac = fmi2SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + auto_jac = fmi2GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + + @test (abs.(auto_jac - FD_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - ZG_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - samp_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + #@info "A: $(auto_jac)" + #@info "S: $(samp_jac)" + + # Jacobians for random x0 / dx + x0 = x0 + rand(numStates) + dx = dx + rand(numStates) + FD_jac = ForwardDiff.jacobian(x -> FMI.fx(comp, dx, x, p, t), x0) + ZG_jac = Zygote.jacobian(FMI.fx, comp, dx, x0, p, t)[3] + fmi2SetContinuousStates(comp, x0) + samp_jac = fmi2SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + auto_jac = fmi2GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + + @test (abs.(auto_jac - FD_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - ZG_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + @test (abs.(auto_jac - samp_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) + + fmiUnload(myFMU) +end diff --git a/test/FMI3/sim_CS.jl b/test/FMI3/sim_CS.jl new file mode 100644 index 00000000..282687c4 --- /dev/null +++ b/test/FMI3/sim_CS.jl @@ -0,0 +1,86 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +# case 1: CS-FMU Simulation + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct !== nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +t_start = 0.0 +t_stop = 8.0 + +# test without recording values (but why?) +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2) +@test solution.success + +# test with recording values +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"]) +@test solution.success +@test length(solution.values.saveval) == t_start:1e-2:t_stop |> length +@test length(solution.values.saveval[1]) == 2 + +t = solution.values.t +s = collect(d[1] for d in solution.values.saveval) +v = collect(d[2] for d in solution.values.saveval) +@test t[1] == t_start +@test t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test s[1] == 0.5 +@test v[1] == 0.0 + +if ENV["EXPORTINGTOOL"] == "Dymola/2020x" # ToDo: Linux FMU was corrupted + @test s[end] ≈ 0.509219 atol=1e-1 + @test v[end] ≈ 0.314074 atol=1e-1 +end + +fmiUnload(myFMU) + +# case 2: CS-FMU with input signal + +function extForce(t) + [sin(t)] +end + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct !== nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"], inputValueReferences=["extForce"], inputFunction=extForce) +@test solution.success +@test length(solution.values.saveval) > 0 +@test length(solution.values.t) > 0 + +@test t[1] == t_start +@test t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test [solution.values.saveval[1]...] == [0.5, 0.0] +@test sum(abs.([solution.values.saveval[end]...] - [0.613371, 0.188633])) < 0.2 +fmiUnload(myFMU) + diff --git a/test/FMI3/sim_ME.jl b/test/FMI3/sim_ME.jl new file mode 100644 index 00000000..8754f3d4 --- /dev/null +++ b/test/FMI3/sim_ME.jl @@ -0,0 +1,261 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using DifferentialEquations: Tsit5, Rosenbrock23 + +t_start = 0.0 +t_stop = 8.0 + +# case 1: ME-FMU with state events + +myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop) +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [1.06736, -1.03552e-10])) < 0.1 +fmiUnload(myFMU) + +# case 2: ME-FMU with state and time events + +myFMU = fmiLoad("SpringTimeFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +### test without recording values + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 + +### test with recording values (variable step record values) + +solution= fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", dtmax=0.001) # dtmax to force resolution +dataLength = length(solution.states.u) +@test dataLength > 0 +@test length(solution.states.t) == dataLength +@test length(solution.values.saveval) == dataLength +@test length(solution.values.t) == dataLength + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop +@test solution.values.t[1] == t_start +@test solution.values.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 +@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 +@test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 +@test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 + +### test with recording values (fixed step record values) + +tData = t_start:0.1:t_stop +solution = fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", saveat=tData, dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) == length(tData) +@test length(solution.states.t) == length(tData) +@test length(solution.values.saveval) == length(tData) +@test length(solution.values.t) == length(tData) + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop +@test solution.values.t[1] == t_start +@test solution.values.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 +@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 +@test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 +@test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 + +fmiUnload(myFMU) + +# case 3a: ME-FMU without events, but with input signal (explicit solver: Tsit5) + +function extForce(t) + [sin(t)] +end + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Tsit5(), dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.012 +fmiUnload(myFMU) + +# case 3b: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, autodiff) + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +# ToDo: autodiff=true not working currently! +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=true), dtmax=0.001) # dtmax to force resolution +# @test length(solution.states.u) > 0 +# @test length(solution.states.t) > 0 + +# @test solution.states.t[1] == t_start +# @test solution.states.t[end] == t_stop + +# # reference values from Simulation in Dymola2020x (Dassl) +# @test solution.states.u[1] == [0.5, 0.0] +# @test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 +fmiUnload(myFMU) + +# case 3c: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, no autodiff) + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=false), dtmax=0.001) # dtmax to force resolution +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test solution.states.u[1] == [0.5, 0.0] +@test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 +fmiUnload(myFMU) + +# case 4: ME-FMU without events, but saving value interpolation + +myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +solution = fmiSimulateME(fmuStruct, t_start, t_stop; saveat=tData, recordValues=myFMU.modelDescription.stateValueReferences) +@test length(solution.states.u) == length(tData) +@test length(solution.states.t) == length(tData) +@test length(solution.values.saveval) == length(tData) +@test length(solution.values.t) == length(tData) + +for i in 1:length(tData) + @test sum(abs(solution.states.t[i] - solution.states.t[i])) < 1e-6 + @test sum(abs(solution.states.u[i][1] - solution.values.saveval[i][1])) < 1e-6 + @test sum(abs(solution.states.u[i][2] - solution.values.saveval[i][2])) < 1e-6 +end + +fmiUnload(myFMU) + +# case 5: ME-FMU with different (random) start state + +myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +rand_x0 = rand(2) +solution = fmiSimulateME(fmuStruct, t_start, t_stop; x0=rand_x0) +@test length(solution.states.u) > 0 +@test length(solution.states.t) > 0 + +@test solution.states.t[1] == t_start +@test solution.states.t[end] == t_stop + +@test solution.states.u[1] == rand_x0 +fmiUnload(myFMU) \ No newline at end of file diff --git a/test/FMI3/sim_auto.jl b/test/FMI3/sim_auto.jl new file mode 100644 index 00000000..b1c61c8f --- /dev/null +++ b/test/FMI3/sim_auto.jl @@ -0,0 +1,61 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +pathToFMU = get_model_filename("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +# load FMU in temporary directory +myFMU = fmiLoad(pathToFMU) +@test isfile(myFMU.zipPath) == true +@test isdir(splitext(myFMU.zipPath)[1]) == true +fmiUnload(myFMU) + +# load FMU in source directory +fmuDir = joinpath(splitpath(pathToFMU)[1:end-1]...) +myFMU = fmiLoad(pathToFMU; unpackPath=fmuDir) +@test isfile(splitext(pathToFMU)[1] * ".zip") == true +@test isdir(splitext(pathToFMU)[1]) == true + +comp = fmiInstantiate!(myFMU; loggingOn=false) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +t_start = 0.0 +t_stop = 8.0 + +# test without recording values (but why?) +sol = fmiSimulate(fmuStruct, t_start, t_stop; dt=1e-2) +@test sol.success + +# test with recording values +solution = fmiSimulate(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"], setup=true) +@test solution.success +@test length(solution.values.saveval) == t_start:1e-2:t_stop |> length +@test length(solution.values.saveval[1]) == 2 + +t = solution.values.t +s = collect(d[1] for d in solution.values.saveval) +v = collect(d[2] for d in solution.values.saveval) +@test t[1] == t_start +@test t[end] == t_stop + +# reference values from Simulation in Dymola2020x (Dassl) +@test s[1] == 0.5 +@test v[1] == 0.0 + +if ENV["EXPORTINGTOOL"] == "Dymola/2020x" # ToDo: Linux FMU was corrupted + @test s[end] ≈ 0.509219 atol=1e-1 + @test v[end] ≈ 0.314074 atol=1e-1 +end + +fmiUnload(myFMU) diff --git a/test/FMI3/state.jl b/test/FMI3/state.jl new file mode 100644 index 00000000..983ff203 --- /dev/null +++ b/test/FMI3/state.jl @@ -0,0 +1,65 @@ +# +# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +############### +# Prepare FMU # +############### + +myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +comp = fmiInstantiate!(myFMU; loggingOn=true) +@test comp != 0 + +# choose FMU or FMUComponent +fmuStruct = nothing +envFMUSTRUCT = ENV["FMUSTRUCT"] +if envFMUSTRUCT == "FMU" + fmuStruct = myFMU +elseif envFMUSTRUCT == "FMUCOMPONENT" + fmuStruct = comp +end +@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +@test fmiEnterInitializationMode(fmuStruct) == 0 +@test fmiExitInitializationMode(fmuStruct) == 0 + +@test fmiSetupExperiment(fmuStruct, 0.0) == 0 + +########################### +# Testing state functions # +########################### + +if fmiCanGetSetState(myFMU) && fmiCanSerializeFMUstate(myFMU) + @test fmiGetReal(fmuStruct, "mass.s") == 0.5 + FMUstate = fmiGetFMUstate(fmuStruct) + @test typeof(FMUstate) == FMI.fmi2FMUstate + len = fmiSerializedFMUstateSize(fmuStruct, FMUstate) + @test len > 0 + serial = fmiSerializeFMUstate(fmuStruct, FMUstate) + @test length(serial) == len + @test typeof(serial) == Array{Char,1} + + fmiSetReal(fmuStruct, "mass.s", 10.0) + FMUstate = fmiGetFMUstate(fmuStruct) + @test fmiGetReal(fmuStruct, "mass.s") == 10.0 + + FMUstate2 = fmiDeSerializeFMUstate(fmuStruct, serial) + @test typeof(FMUstate2) == FMI.fmi2FMUstate + fmiSetFMUstate(fmuStruct, FMUstate2) + @test fmiGetReal(fmuStruct, "mass.s") == 0.5 + fmiSetFMUstate(fmuStruct, FMUstate) + @test fmiGetReal(fmuStruct, "mass.s") == 10.0 + fmiFreeFMUstate!(fmuStruct, FMUstate) + fmiFreeFMUstate!(fmuStruct, FMUstate2) +else + @info "The FMU provided from the tool `$(ENV["EXPORTINGTOOL"])` does not support state get, set, serialization and deserialization. Skipping related tests." +end + +############ +# Clean up # +############ + +@test fmiTerminate(myFMU) == 0 +fmiUnload(myFMU) diff --git a/test/runtests.jl b/test/runtests.jl index 8d16adb1..86c0f2a8 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,13 +12,59 @@ exportingToolsWindows = [("Dymola", "2022x")] exportingToolsLinux = [("Dymola", "2022x")] fmuStructs = ["FMU", "FMUCOMPONENT"] -function runtests(exportingTool) +function runtestsFMI2(exportingTool) ENV["EXPORTINGTOOL"] = exportingTool[1] ENV["EXPORTINGVERSION"] = exportingTool[2] @testset "Testing FMUs exported from $exportingTool" begin @testset "Sensitivities" begin + include("FMI2/sens.jl") + end + + for str in fmuStructs + @testset "Functions for $str" begin + ENV["FMUSTRUCT"] = str + @testset "Variable Getters / Setters" begin + include("FMI2/getter_setter.jl") + end + @testset "State Manipulation" begin + include("FMI2/state.jl") + end + @testset "Directional derivatives" begin + include("FMI2/dir_ders.jl") + end + @testset "Automatic Simulation (CS or ME)" begin + include("FMI2/sim_auto.jl") + end + @testset "CS Simulation" begin + include("FMI2/sim_CS.jl") + end + @testset "ME Simulation" begin + include("FMI2/sim_ME.jl") + end + @testset "Support CS and ME simultaneously" begin + include("FMI2/cs_me.jl") + end + @testset "Loading/Saving simulation results" begin + include("FMI2/load_save.jl") + end + end + end + + @testset "Plotting" begin + include("FMI2/plots.jl") + end + end +end + +function runtestsFMI3(exportingTool) + ENV["EXPORTINGTOOL"] = exportingTool[1] + ENV["EXPORTINGVERSION"] = exportingTool[2] + + @testset "Testing FMUs exported from $exportingTool" begin + + @testset "FMI3/Sensitivities" begin include("sens.jl") end @@ -26,34 +72,34 @@ function runtests(exportingTool) @testset "Functions for $str" begin ENV["FMUSTRUCT"] = str @testset "Variable Getters / Setters" begin - include("getter_setter.jl") + include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - include("state.jl") + include("FMI3/state.jl") end @testset "Directional derivatives" begin - include("dir_ders.jl") + include("FMI3/dir_ders.jl") end @testset "Automatic Simulation (CS or ME)" begin - include("sim_auto.jl") + include("FMI3/sim_auto.jl") end @testset "CS Simulation" begin - include("sim_CS.jl") + include("FMI3/sim_CS.jl") end @testset "ME Simulation" begin - include("sim_ME.jl") + include("FMI3/sim_ME.jl") end @testset "Support CS and ME simultaneously" begin - include("cs_me.jl") + include("FMI3/cs_me.jl") end @testset "Loading/Saving simulation results" begin - include("load_save.jl") + include("FMI3/load_save.jl") end end end @testset "Plotting" begin - include("plots.jl") + include("FMI3/plots.jl") end end end @@ -62,12 +108,14 @@ end if Sys.iswindows() @info "Automated testing is supported on Windows." for exportingTool in exportingToolsWindows - runtests(exportingTool) + runtestsFMI2(exportingTool) + #runtestsFMI3(exportingTool) end elseif Sys.islinux() @info "Automated testing is supported on Linux." for exportingTool in exportingToolsLinux - runtests(exportingTool) + runtestsFMI2(exportingTool) + #runtestsFMI3(exportingTool) end elseif Sys.isapple() @warn "Test-sets are currrently using Windows- and Linux-FMUs, automated testing for macOS is currently not supported." From 9618700e7c773039c010f78f6fa0a0386b8e5bbe Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 28 Jun 2022 12:43:12 +0200 Subject: [PATCH 20/41] WIP: merge --- src/FMI.jl | 24 ++++++++++++------------ src/FMI3_additional.jl | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index e3f521d3..9579fa5f 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -121,18 +121,18 @@ end export fmiSaveSolution, fmiLoadSolution # from FMI3_plot.jl -function fmiPlot(solution::FMU3Solution; kwargs...) - @warn "fmiPlot(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." -end -function fmiPlot!(fig, solution::FMU3Solution; kwargs...) - @warn "fmiPlot!(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." -end -export fmiPlot, fmiPlot! +# function fmiPlot(solution::FMU3Solution; kwargs...) +# @warn "fmiPlot(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +# end +# function fmiPlot!(fig, solution::FMU3Solution; kwargs...) +# @warn "fmiPlot!(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +# end +# export fmiPlot, fmiPlot! # from FMI3_JLD2.jl -function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") - @warn "fmiSave(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." -end +# function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") +# @warn "fmiSave(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." +# end function fmiLoadSolution(path::AbstractString; keyword="solution") @warn "fmiLoad(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." end @@ -149,7 +149,7 @@ function __init__() @require JLD2="033835bb-8acc-5ee8-8aae-3f567f8a3819" begin import .JLD2 include("FMI2_JLD2.jl") - include("FMI3_JLD3.jl") + include("FMI3_JLD2.jl") end end @@ -619,7 +619,7 @@ Load FMUs independent of the FMI version, currently supporting version 2.0.X and See also [`fmi2Load`](@ref), [`fmi3Load`](@ref). """ -function fmiLoad(args...; kwargs...) +function fmiLoad(pathToFMU::AbstractString, args...; kwargs...) version = fmiCheckVersion(pathToFMU) if version == "2.0" fmi2Load(args...; kwargs...) diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 66dad1fe..5314ad08 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -16,6 +16,8 @@ using FMIImport: fmi3DependencyKindDependent, fmi3DependencyKindFixed using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate, fmi3Instance import FMIImport: fmi3VariableNamingConventionFlat, fmi3VariableNamingConventionStructured +using ZipFile + """ Returns how a variable depends on another variable based on the model description. """ From f1bc7b33798eba8c9d8bd7efc7658f3f49f70433 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 28 Jun 2022 14:28:52 +0200 Subject: [PATCH 21/41] fixed fmiLoad --- src/FMI.jl | 16 +++++++--------- src/FMI3_additional.jl | 5 +++-- src/FMI3_comp_wraps.jl | 11 ----------- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 9579fa5f..80d4d998 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -38,6 +38,7 @@ import FMIImport: fmi2Get, fmi2Get!, fmi2Set import FMIImport: fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue export fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue +# fmi3 imports import FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate import FMIImport: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmi3InstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal import FMIImport: fmi3InstantiateModelExchange, fmi3InstantiateCoSimulation, fmi3InstantiateScheduledExecution, fmi3FreeInstance!, fmi3GetVersion @@ -50,14 +51,14 @@ import FMIImport: fmi3SetIntervalDecimal, fmi3SetIntervalFraction, fmi3GetInterv import FMIImport: fmi3ActivateModelPartition import FMIImport: fmi3GetNumberOfVariableDependencies!, fmi3GetVariableDependencies! import FMIImport: fmi3GetDirectionalDerivative!, fmi3GetAdjointDerivative!, fmi3GetOutputDerivatives! -import FMIImport: fmi3DoStep +import FMIImport: fmi3DoStep! import FMIImport: fmi3EnterConfigurationMode, fmi3ExitConfigurationMode, fmi3GetNumberOfContinuousStates!, fmi3GetNumberOfEventIndicators!, fmi3GetContinuousStates!, fmi3GetNominalsOfContinuousStates! import FMIImport: fmi3EvaluateDiscreteStates, fmi3EnterStepMode import FMIImport: fmi3SetTime, fmi3SetContinuousStates, fmi3EnterEventMode, fmi3UpdateDiscreteStates, fmi3EnterContinuousTimeMode, fmi3CompletedIntegratorStep! import FMIImport: fmi3GetContinuousStateDerivatives, fmi3GetEventIndicators, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates import FMIImport: fmi3StringToValueReference, fmi3ValueReferenceToString, fmi3ModelVariablesForValueReference import FMIImport: fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString -import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmiDeSerializeFMUState +import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmi3DeSerializeFMUState import FMIImport: fmi3GetDirectionalDerivative, fmi3GetAdjointDerivative import FMIImport: fmi3GetStartValue, fmi3SampleDirectionalDerivative, fmi3CompletedIntegratorStep import FMIImport: fmi3Unzip, fmi3Load, loadBinary, fmi3Reload, fmi3Unload, fmi3InstantiateModelExchange!, fmi3InstantiateCoSimulation!, fmi3InstantiateScheduledExecution! @@ -65,8 +66,8 @@ import FMIImport: fmi3SampleDirectionalDerivative! import FMIImport: fmi3GetJacobian, fmi3GetJacobian!, fmi3GetFullJacobian, fmi3GetFullJacobian! import FMIImport: fmi3LoadModelDescription import FMIImport: fmi3GetDefaultStartTime, fmi3GetDefaultStopTime, fmi3GetDefaultTolerance, fmi3GetDefaultStepSize -import FMIImport: fmi3GetModelName, fmi3GetInstantiationToken, fmi3GetGenerationTool, fmi3GetGenerationDateAndTime, fmi3GetVariableNamingConvention, fmi3GetNumberOfEventIndicators, fmi3GetNumberOfStates, fmi3IsCoSimulation, fmi3IsModelExchange, fmi3IsScheduledExecution -import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetSetState, fmi3CanSerializeFMUState, fmi3ProvidesDirectionalDerivatives, fmi3ProvidesAdjointDerivatves +import FMIImport: fmi3GetModelName, fmi3GetInstantiationToken, fmi3GetGenerationTool, fmi3GetGenerationDateAndTime, fmi3GetVariableNamingConvention, fmi3GetNumberOfEventIndicators, fmi3GetNumberOfContinuousStates, fmi3IsCoSimulation, fmi3IsModelExchange, fmi3IsScheduledExecution +import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetSetState, fmi3CanSerializeFMUState, fmi3ProvidesDirectionalDerivatives, fmi3ProvidesAdjointDerivatives import FMIImport: fmi3Get, fmi3Get!, fmi3Set import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue @@ -133,9 +134,6 @@ export fmiSaveSolution, fmiLoadSolution # function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") # @warn "fmiSave(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." # end -function fmiLoadSolution(path::AbstractString; keyword="solution") - @warn "fmiLoad(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." -end export fmiSaveSolution, fmiLoadSolution @@ -622,9 +620,9 @@ See also [`fmi2Load`](@ref), [`fmi3Load`](@ref). function fmiLoad(pathToFMU::AbstractString, args...; kwargs...) version = fmiCheckVersion(pathToFMU) if version == "2.0" - fmi2Load(args...; kwargs...) + fmi2Load(pathToFMU, args...; kwargs...) elseif version == "3.0" - fmi3Load(args...; kwargs...) + fmi3Load(pathToFMU, args...; kwargs...) else @warn "fmiLoad(...): Unknown FMU version" end diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 5314ad08..dc3cd9ee 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -16,7 +16,7 @@ using FMIImport: fmi3DependencyKindDependent, fmi3DependencyKindFixed using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate, fmi3Instance import FMIImport: fmi3VariableNamingConventionFlat, fmi3VariableNamingConventionStructured -using ZipFile +using ZipFile, EzXML """ Returns how a variable depends on another variable based on the model description. @@ -224,8 +224,9 @@ function fmiCheckVersion(pathToFMU::String; unpackPath=nothing) # read version tag - doc = readxml(unzippedAbsPath) + doc = readxml(normpath(joinpath(unzippedAbsPath, "modelDescription.xml"))) + root = doc.root version = root["fmiVersion"] # cleanup unzipped modelDescription diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index 451eb292..f23a9034 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -739,17 +739,6 @@ function fmi3GetNumberOfContinuousStates(fmu::FMU3) fmi3GetNumberOfContinuousStates(fmu.instances[end]) end -""" - fmi3GetNumberOfEventIndicators(fmu::FMU3) - -Wrapper for fmi3GetNumberOfEventIndicators() in FMIImport/FMI3_c.jl -""" -function fmi3GetNumberOfEventIndicators(fmu::FMU3) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfEventIndicators(fmu.instances[end]) -end - """ fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) From f9bc8f1a074e170cf9eb17dba6b17628745f9882 Mon Sep 17 00:00:00 2001 From: TT Date: Tue, 28 Jun 2022 15:35:19 +0200 Subject: [PATCH 22/41] removed files --- .../manipulation_files/manipulation_10_0.svg | 134 - .../manipulation_files/manipulation_18_0.svg | 172 - docs/src/examples/modelica_conference_2021.md | 223 -- .../modelica_conference_2021_8_0.svg | 110 - .../multiple_instances_10_0.svg | 902 ----- .../multiple_instances_18_0.svg | 1708 --------- .../examples/simulate_files/simulate_12_0.svg | 274 -- .../examples/simulate_files/simulate_13_0.svg | 295 -- example/manipulation.ipynb | 848 ----- example/modelica_conference_2021.ipynb | 569 --- example/multiple_instances.ipynb | 3081 ----------------- example/parameterize.ipynb | 659 ---- example/simulate.ipynb | 1021 ------ 13 files changed, 9996 deletions(-) delete mode 100644 docs/src/examples/manipulation_files/manipulation_10_0.svg delete mode 100644 docs/src/examples/manipulation_files/manipulation_18_0.svg delete mode 100644 docs/src/examples/modelica_conference_2021.md delete mode 100644 docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg delete mode 100644 docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg delete mode 100644 docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg delete mode 100644 docs/src/examples/simulate_files/simulate_12_0.svg delete mode 100644 docs/src/examples/simulate_files/simulate_13_0.svg delete mode 100644 example/manipulation.ipynb delete mode 100644 example/modelica_conference_2021.ipynb delete mode 100644 example/multiple_instances.ipynb delete mode 100644 example/parameterize.ipynb delete mode 100644 example/simulate.ipynb diff --git a/docs/src/examples/manipulation_files/manipulation_10_0.svg b/docs/src/examples/manipulation_files/manipulation_10_0.svg deleted file mode 100644 index c9ae6c2d..00000000 --- a/docs/src/examples/manipulation_files/manipulation_10_0.svg +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/manipulation_files/manipulation_18_0.svg b/docs/src/examples/manipulation_files/manipulation_18_0.svg deleted file mode 100644 index a319441a..00000000 --- a/docs/src/examples/manipulation_files/manipulation_18_0.svg +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/modelica_conference_2021.md b/docs/src/examples/modelica_conference_2021.md deleted file mode 100644 index e4612a31..00000000 --- a/docs/src/examples/modelica_conference_2021.md +++ /dev/null @@ -1,223 +0,0 @@ -# Advanced Simulation of an FMU -Tutorial by Johannes Stoljar, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -In this example we would like to show that besides the simple simulation of an FMU there is also a more advanced version of the simulation. The advantage of the more advanced variant is that there are more possibilities to intervene in the simulation to make changes. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. - -![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) - - -## Target group -The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/modelica_conference_2021.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | -| 4. | Install Plots via | add Plots | | - -## Code section - -To run the example, the previously installed packages must be included. - - -```julia -# imports -using FMI -using FMIZoo -using Plots -``` - - ┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI` - └ @ Base.Docs docs/Docs.jl:240 - - -### Simulation setup - -Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. - - -```julia -tStart = 0.0 -tStep = 0.1 -tStop = 8.0 -tSave = tStart:tStep:tStop -``` - - - - - 0.0:0.1:8.0 - - - -### Simple FMU Simulation - -In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. - - -```julia -# we use an FMU from the FMIZoo.jl -pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x") - -myFMU = fmiLoad(pathToFMU) -fmiInfo(myFMU) -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_dg2hpy/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_dg2hpy/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 - - - #################### Begin information for FMU #################### - Model name: SpringFrictionPendulum1D - FMI-Version: 2.0 - GUID: {df491d8d-0598-4495-913e-5b025e54d7f2} - Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 - Generation time: 2022-03-03T15:09:18Z - Var. naming conv.: structured - Event indicators: 24 - Inputs: 0 - Outputs: 0 - States: 2 - 33554432 ["mass.s"] - 33554433 ["mass.v", "mass.v_relfric"] - Supports Co-Simulation: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - Var. com. steps: true - Input interpol.: true - Max order out. der.: 1 - Supports Model-Exchange: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - ##################### End information for FMU ##################### - - -In the next commands the FMU is simulated, for which the start and end time and recorded variables are declared. Afterwards the simulation result is shown in a graph. In the plot for the FMU, it can be seen that the oscillation keeps decreasing due to the effect of friction. If one simulates long enough, the oscillation comes to a standstill after a certain time. - - -```julia -simData = fmiSimulate(myFMU, tStart, tStop; recordValues=["mass.s"], saveat=tSave) -fmiPlot(simData) -``` - - - - - -![svg](modelica_conference_2021_files/modelica_conference_2021_8_0.svg) - - - - -After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. - - -```julia -fmiUnload(myFMU) -``` - -### Advanced FMU Simulation - -In the following type of simulation a more advanced variant is presented, which allows intervening more in the simulation process. Analogous to the simple variant, an FMU model must be loaded. - - -```julia -myFMU = fmiLoad(pathToFMU); -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HuQTow/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HuQTow/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193 - - -Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. - - -```julia -instanceFMU = fmiInstantiate!(myFMU) -``` - - - - - FMU: SpringFrictionPendulum1D - InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000005fcca40 - State: fmi2ComponentStateInstantiated - Logging: false - FMU time: -Inf - FMU states: nothing - - - -In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. Next, the FMU is initialized by the calls of `fmiEnterInitializationMode()` and `fmiExitInitializationMode()`. It would also be possible to set initial states for the FMU between these two commands. - - -```julia -fmiSetupExperiment(instanceFMU, tStart, tStop) -fmiEnterInitializationMode(instanceFMU) -# set initial model states -fmiExitInitializationMode(instanceFMU) -``` - - - - - 0x00000000 - - - -The actual simulation loop is shown in the following block. Here a simulation step `fmiDoStep()` with the fixed step size `tStep` is executed. As indicated in the code by the comments, the input values and output values of the FMU could be changed in the simulation loop as desired, whereby the higher possibility of adjustments arises. - - -```julia -for t in tSave - # set model inputs - # ... - fmiDoStep(instanceFMU, tStep) - # get model outputs - # ... -end -``` - -The instantiated FMU must be terminated and then the memory area for the instance can also be deallocated. The last step is to unload the FMU to remove all unpacked data on disc. - - -```julia -fmiTerminate(instanceFMU) -fmiFreeInstance!(instanceFMU) -fmiUnload(myFMU) -``` - -### Summary - -The tutorial has shown that besides the usual simple variant of simulating an FMU, there is another way to make more adjustments. diff --git a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg deleted file mode 100644 index 0a7ac6a2..00000000 --- a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg deleted file mode 100644 index 48bec0bb..00000000 --- a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg +++ /dev/null @@ -1,902 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg deleted file mode 100644 index 04f52296..00000000 --- a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg +++ /dev/null @@ -1,1708 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/simulate_files/simulate_12_0.svg b/docs/src/examples/simulate_files/simulate_12_0.svg deleted file mode 100644 index e3cf1302..00000000 --- a/docs/src/examples/simulate_files/simulate_12_0.svg +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/simulate_files/simulate_13_0.svg b/docs/src/examples/simulate_files/simulate_13_0.svg deleted file mode 100644 index e4c9bcdd..00000000 --- a/docs/src/examples/simulate_files/simulate_13_0.svg +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/manipulation.ipynb b/example/manipulation.ipynb deleted file mode 100644 index f7f16b44..00000000 --- a/example/manipulation.ipynb +++ /dev/null @@ -1,848 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Manipulate a function\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "This example shows how to overwrite a library function with an own function. For this the FMU model is simulated first without changes. Then the function `fmi2GetReal()` is overwritten and simulated again. Both simulations are displayed in a graph to show the change caused by overwriting the function. The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/manipulation.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install FMICore via | add FMICore | add \" https://github.com/ThummeTo/FMICore.jl \" |\n", - "| 5. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:05:05.916000Z", - "iopub.status.busy": "2022-05-24T15:05:04.955000Z", - "iopub.status.idle": "2022-05-24T15:05:35.479000Z", - "shell.execute_reply": "2022-05-24T15:05:35.382000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using FMICore\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:05:46.559000Z", - "iopub.status.busy": "2022-05-24T15:05:35.482000Z", - "iopub.status.idle": "2022-05-24T15:05:47.511000Z", - "shell.execute_reply": "2022-05-24T15:05:47.511000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStop = 8.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:05:47.516000Z", - "iopub.status.busy": "2022-05-24T15:05:47.515000Z", - "iopub.status.idle": "2022-05-24T15:05:53.086000Z", - "shell.execute_reply": "2022-05-24T15:05:53.085000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_AxClYk/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_AxClYk/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringFrictionPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t24\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulate FMU\n", - "\n", - "In the next steps the recorded value is defined. The recorded value is the position of the mass. In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size. In addition, the start and end time and the recorded variables are specified." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:05:53.089000Z", - "iopub.status.busy": "2022-05-24T15:05:53.089000Z", - "iopub.status.idle": "2022-05-24T15:06:16.714000Z", - "shell.execute_reply": "2022-05-24T15:06:16.714000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:13\u001b[39m\n" - ] - }, - { - "data": { - "text/plain": [ - "Model name:\n", - "\tSpringFrictionPendulum1D\n", - "Success:\n", - "\ttrue\n", - "States [110]:\n", - "\t0.0\t[0.5, 0.0]\n", - "\t2.3529411764719727e-11\t[0.5, 1.0e-10]\n", - "\t1.0000023529411766e-5\t[0.5000000002125017, 4.250030186348503e-5]\n", - "\t0.00011000002352941177\t[0.5000000257134062, 0.0004675245102952289]\n", - "\t0.0011100000235294118\t[0.5000026191281834, 0.004719970360497647]\n", - "\t0.011110000023529413\t[0.5002631686645611, 0.047449647283752144]\n", - "\t0.03982466736770743\t[0.5034050123596227, 0.17168075110950387]\n", - "\t0.09972054285078226\t[0.5215006197560228, 0.43204954153497455]\n", - "\t0.16481836271111422\t[0.5585747156842935, 0.703758265932321]\n", - "\t...\n", - "\t8.0\t[1.0668213438183276, -1.0000099359121942e-10]\n", - "Values [110]:\n", - "\t0.0\t(0.5,)\n", - "\t2.3529411764719727e-11\t(0.5,)\n", - "\t1.0000023529411766e-5\t(0.5000000002125017,)\n", - "\t0.00011000002352941177\t(0.5000000257134062,)\n", - "\t0.0011100000235294118\t(0.5000026191281834,)\n", - "\t0.011110000023529413\t(0.5002631686645611,)\n", - "\t0.03982466736770743\t(0.5034050123596227,)\n", - "\t0.09972054285078226\t(0.5215006197560228,)\n", - "\t0.16481836271111422\t(0.5585747156842935,)\n", - "\t...\n", - "\t8.0\t(1.0668213438183276,)\n", - "Events [6]:\n", - "\tState-Event #11 @ 0.0s\n", - "\tState-Event #11 @ 0.9939s\n", - "\tState-Event #19 @ 1.9881s\n", - "\tState-Event #11 @ 2.9829s\n", - "\tState-Event #19 @ 3.9787s\n", - "\tState-Event #11 @ 4.9768s\n" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vrs = [\"mass.s\"]\n", - "\n", - "simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plotting FMU\n", - "\n", - "After the simulation is finished, the result of the FMU for the model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:06:16.718000Z", - "iopub.status.busy": "2022-05-24T15:06:16.718000Z", - "iopub.status.idle": "2022-05-24T15:06:41.814000Z", - "shell.execute_reply": "2022-05-24T15:06:41.814000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig = fmiPlot(simData, states=false)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Override Function\n", - "\n", - "After overwriting a function, the previous one is no longer accessible. The original function `fmi2GetReal()` is cached by storing the address of the pointer. The addresses of the pointers are kept in the FMU and are thus accessible." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:06:41.820000Z", - "iopub.status.busy": "2022-05-24T15:06:41.819000Z", - "iopub.status.idle": "2022-05-24T15:06:42.710000Z", - "shell.execute_reply": "2022-05-24T15:06:42.710000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Ptr{Nothing} @0x00007fa504ca1faf" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function\n", - "originalGetReal = myFMU.cGetReal" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To overwrite the function `fmi2GetReal!()`, the function header of the new custom function must be identical to the previous one. The function header looks like `fmi2GetReal!(cfunc::Ptr{Nothing}, c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})::fmi2Status`. The information how the FMI2 function are structured can be seen from [FMICore.jl](https://github.com/ThummeTo/FMICore.jl/blob/main/src/FMI2_c.jl#L718) or the FMI2.0.3-specification.\n", - "\n", - "In the new implementation the original function is called by the previously stored pointer. Next there is a special handling if `value` is a pointer to an array. In this case the pointer is treated as an array, so that the entries are accessible. Otherwise, each value in `value` is multiplied by two. Finally, the original state of the original function is output." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:06:42.716000Z", - "iopub.status.busy": "2022-05-24T15:06:42.716000Z", - "iopub.status.idle": "2022-05-24T15:06:43.882000Z", - "shell.execute_reply": "2022-05-24T15:06:43.882000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "myGetReal! (generic function with 1 method)" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, \n", - " nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})\n", - " # first, we do what the original function does\n", - " status = fmi2GetReal!(originalGetReal, c, vr, nvr, value)\n", - "\n", - " # if we have a pointer to an array, we must interprete it as array to access elements\n", - " if isa(value, Ptr{fmi2Real})\n", - " value = unsafe_wrap(Array{fmi2Real}, value, nvr, own=false)\n", - " end\n", - "\n", - " # now, we multiply every value by two (just for fun!)\n", - " for i in 1:nvr \n", - " value[i] *= 2.0 \n", - " end \n", - "\n", - " # return the original status\n", - " return status\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next command the original function is overwritten with the new defined function, for which the command `fmiSetFctGetReal()` is called." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:06:43.887000Z", - "iopub.status.busy": "2022-05-24T15:06:43.887000Z", - "iopub.status.idle": "2022-05-24T15:06:43.906000Z", - "shell.execute_reply": "2022-05-24T15:06:43.906000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Ptr{Nothing} @0x00007fa54dafdfc0" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# no we overwrite the original function\n", - "fmiSetFctGetReal(myFMU, myGetReal!)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulate and Plot FMU with modified function\n", - "\n", - "As before, the identical command is called here for simulation. This is also a model exchange simulation. Immediately afterwards, the results are added to the previous graph as a dashed line." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:06:43.910000Z", - "iopub.status.busy": "2022-05-24T15:06:43.910000Z", - "iopub.status.idle": "2022-05-24T15:06:44.437000Z", - "shell.execute_reply": "2022-05-24T15:06:44.437000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)\n", - "fmiPlot!(fig, simData; states=false, style=:dash)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As expected by overwriting the function, all values are doubled." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:06:44.442000Z", - "iopub.status.busy": "2022-05-24T15:06:44.442000Z", - "iopub.status.idle": "2022-05-24T15:06:44.500000Z", - "shell.execute_reply": "2022-05-24T15:06:44.500000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "In this tutorial it is shown how an existing function of the library can be replaced by an own implementation. Through this possibility, there are almost no limits for the user, whereby the user can customize the function to his liking." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/modelica_conference_2021.ipynb b/example/modelica_conference_2021.ipynb deleted file mode 100644 index 7f6e2473..00000000 --- a/example/modelica_conference_2021.ipynb +++ /dev/null @@ -1,569 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Advanced Simulation of an FMU\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "In this example we would like to show that besides the simple simulation of an FMU there is also a more advanced version of the simulation. The advantage of the more advanced variant is that there are more possibilities to intervene in the simulation to make changes. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/modelica_conference_2021.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:06:56.032000Z", - "iopub.status.busy": "2022-05-24T15:06:55.083000Z", - "iopub.status.idle": "2022-05-24T15:07:25.235000Z", - "shell.execute_reply": "2022-05-24T15:07:25.141000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:07:36.354000Z", - "iopub.status.busy": "2022-05-24T15:07:25.239000Z", - "iopub.status.idle": "2022-05-24T15:07:37.433000Z", - "shell.execute_reply": "2022-05-24T15:07:37.433000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0.0:0.1:8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStep = 0.1\n", - "tStop = 8.0\n", - "tSave = tStart:tStep:tStop" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simple FMU Simulation\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:07:37.438000Z", - "iopub.status.busy": "2022-05-24T15:07:37.438000Z", - "iopub.status.idle": "2022-05-24T15:07:43.049000Z", - "shell.execute_reply": "2022-05-24T15:07:43.049000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_dg2hpy/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_dg2hpy/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringFrictionPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t24\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next commands the FMU is simulated, for which the start and end time and recorded variables are declared. Afterwards the simulation result is shown in a graph. In the plot for the FMU, it can be seen that the oscillation keeps decreasing due to the effect of friction. If one simulates long enough, the oscillation comes to a standstill after a certain time." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:07:43.052000Z", - "iopub.status.busy": "2022-05-24T15:07:43.052000Z", - "iopub.status.idle": "2022-05-24T15:08:18.695000Z", - "shell.execute_reply": "2022-05-24T15:08:18.695000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "simData = fmiSimulate(myFMU, tStart, tStop; recordValues=[\"mass.s\"], saveat=tSave)\n", - "fmiPlot(simData)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.700000Z", - "iopub.status.busy": "2022-05-24T15:08:18.700000Z", - "iopub.status.idle": "2022-05-24T15:08:18.758000Z", - "shell.execute_reply": "2022-05-24T15:08:18.758000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Advanced FMU Simulation\n", - "\n", - "In the following type of simulation a more advanced variant is presented, which allows intervening more in the simulation process. Analogous to the simple variant, an FMU model must be loaded." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.761000Z", - "iopub.status.busy": "2022-05-24T15:08:18.760000Z", - "iopub.status.idle": "2022-05-24T15:08:18.835000Z", - "shell.execute_reply": "2022-05-24T15:08:18.835000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HuQTow/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HuQTow/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" - ] - } - ], - "source": [ - "myFMU = fmiLoad(pathToFMU);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. " - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:08:18.840000Z", - "iopub.status.busy": "2022-05-24T15:08:18.839000Z", - "iopub.status.idle": "2022-05-24T15:08:19.277000Z", - "shell.execute_reply": "2022-05-24T15:08:19.277000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "FMU: SpringFrictionPendulum1D\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000005fcca40\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", - "FMU time: -Inf\n", - "FMU states: nothing" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "instanceFMU = fmiInstantiate!(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. Next, the FMU is initialized by the calls of `fmiEnterInitializationMode()` and `fmiExitInitializationMode()`. It would also be possible to set initial states for the FMU between these two commands. " - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.282000Z", - "iopub.status.busy": "2022-05-24T15:08:19.282000Z", - "iopub.status.idle": "2022-05-24T15:08:19.638000Z", - "shell.execute_reply": "2022-05-24T15:08:19.638000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiSetupExperiment(instanceFMU, tStart, tStop)\n", - "fmiEnterInitializationMode(instanceFMU)\n", - "# set initial model states\n", - "fmiExitInitializationMode(instanceFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The actual simulation loop is shown in the following block. Here a simulation step `fmiDoStep()` with the fixed step size `tStep` is executed. As indicated in the code by the comments, the input values and output values of the FMU could be changed in the simulation loop as desired, whereby the higher possibility of adjustments arises." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.642000Z", - "iopub.status.busy": "2022-05-24T15:08:19.642000Z", - "iopub.status.idle": "2022-05-24T15:08:19.692000Z", - "shell.execute_reply": "2022-05-24T15:08:19.692000Z" - } - }, - "outputs": [], - "source": [ - "for t in tSave\n", - " # set model inputs \n", - " # ...\n", - " fmiDoStep(instanceFMU, tStep)\n", - " # get model outputs\n", - " # ...\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The instantiated FMU must be terminated and then the memory area for the instance can also be deallocated. The last step is to unload the FMU to remove all unpacked data on disc. " - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:08:19.695000Z", - "iopub.status.busy": "2022-05-24T15:08:19.695000Z", - "iopub.status.idle": "2022-05-24T15:08:19.705000Z", - "shell.execute_reply": "2022-05-24T15:08:19.705000Z" - } - }, - "outputs": [], - "source": [ - "fmiTerminate(instanceFMU)\n", - "fmiFreeInstance!(instanceFMU)\n", - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "The tutorial has shown that besides the usual simple variant of simulating an FMU, there is another way to make more adjustments." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/multiple_instances.ipynb b/example/multiple_instances.ipynb deleted file mode 100644 index df73564a..00000000 --- a/example/multiple_instances.ipynb +++ /dev/null @@ -1,3081 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Multiple Instances of an FMU\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "In this example we want to show that it is possible to create different instances of an FMU. The different instances can then be used to run independent simulations. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum without friction. The object-orientated structure of the *SpringPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/multiple_instances.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:49:29.382000Z", - "iopub.status.busy": "2022-05-25T10:49:28.749000Z", - "iopub.status.idle": "2022-05-25T10:49:50.382000Z", - "shell.execute_reply": "2022-05-25T10:49:50.309000Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set. Finally, the recorded values are specified to store the results of the simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:49:58.432000Z", - "iopub.status.busy": "2022-05-25T10:49:50.384000Z", - "iopub.status.idle": "2022-05-25T10:50:01.238000Z", - "shell.execute_reply": "2022-05-25T10:50:01.238000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "1-element Vector{String}:\n", - " \"mass.s\"" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStop = 8.0\n", - "\n", - "vrs = [\"mass.s\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:01.262000Z", - "iopub.status.busy": "2022-05-25T10:50:01.262000Z", - "iopub.status.idle": "2022-05-25T10:50:05.354000Z", - "shell.execute_reply": "2022-05-25T10:50:05.354000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_KBJT4J/SpringPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_KBJT4J/SpringPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{a3e886fa-675c-4308-8e91-3490e598ba11}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:08:57Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t0\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### First Instance\n", - "\n", - "To create an instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:05.356000Z", - "iopub.status.busy": "2022-05-25T10:50:05.356000Z", - "iopub.status.idle": "2022-05-25T10:50:05.919000Z", - "shell.execute_reply": "2022-05-25T10:50:05.919000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "FMU: SpringPendulum1D\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x000000000348d080\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", - "FMU time: -Inf\n", - "FMU states: nothing\n" - ] - } - ], - "source": [ - "comp1 = fmiInstantiate!(myFMU; loggingOn=true)\n", - "comp1Address= comp1.compAddr\n", - "println(comp1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $10.0 \\frac{N}{m}$ and for the position of the mass `mass.s` a value of $1.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:05.922000Z", - "iopub.status.busy": "2022-05-25T10:50:05.922000Z", - "iopub.status.idle": "2022-05-25T10:50:31.527000Z", - "shell.execute_reply": "2022-05-25T10:50:31.526000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "param1 = Dict(\"spring.c\"=>10.0, \"mass_s0\"=>1.0)\n", - "data1 = fmiSimulate(comp1, tStart, tStop; parameters=param1, recordValues=vrs, instantiate=false)\n", - "fig = fmiPlot(data1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For control, you can compare again the address of the instance to the previous address, and it should be the same address. As soon as this is not the case an error would be thrown by the macro `@assert`." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.532000Z", - "iopub.status.busy": "2022-05-25T10:50:31.531000Z", - "iopub.status.idle": "2022-05-25T10:50:31.566000Z", - "shell.execute_reply": "2022-05-25T10:50:31.566000Z" - } - }, - "outputs": [], - "source": [ - "@assert comp1.compAddr === comp1Address" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Second Instance\n", - "\n", - "To create a second instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.568000Z", - "iopub.status.busy": "2022-05-25T10:50:31.568000Z", - "iopub.status.idle": "2022-05-25T10:50:31.571000Z", - "shell.execute_reply": "2022-05-25T10:50:31.570000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "FMU: SpringPendulum1D\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000006214590\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: true\n", - "FMU time: -Inf\n", - "FMU states: nothing\n" - ] - } - ], - "source": [ - "comp2 = fmiInstantiate!(myFMU; loggingOn=true)\n", - "comp2Address= comp2.compAddr\n", - "println(comp2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The addresses of the instantiated FMUs must differ, and you can see that in the comparison below." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.573000Z", - "iopub.status.busy": "2022-05-25T10:50:31.573000Z", - "iopub.status.idle": "2022-05-25T10:50:31.573000Z", - "shell.execute_reply": "2022-05-25T10:50:31.573000Z" - } - }, - "outputs": [], - "source": [ - "@assert comp1Address !== comp2Address" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Again, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $1.0 \\frac{N}{m}$ and for the position of the mass `mass.s` a value of $2.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.576000Z", - "iopub.status.busy": "2022-05-25T10:50:31.575000Z", - "iopub.status.idle": "2022-05-25T10:50:31.676000Z", - "shell.execute_reply": "2022-05-25T10:50:31.676000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "param2 = Dict(\"spring.c\"=>1.0, \"mass.s\"=>2.0)\n", - "data2 = fmiSimulateCS(comp2, tStart, tStop; parameters=param2, recordValues=vrs, instantiate=false)\n", - "fmiPlot!(fig, data2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For control, you can compare again the address of the instance `comp2` to the previous address `comp2Address` and it should be the same address." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.682000Z", - "iopub.status.busy": "2022-05-25T10:50:31.682000Z", - "iopub.status.idle": "2022-05-25T10:50:31.683000Z", - "shell.execute_reply": "2022-05-25T10:50:31.683000Z" - } - }, - "outputs": [], - "source": [ - "@assert comp2.compAddr === comp2Address" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:31.685000Z", - "iopub.status.busy": "2022-05-25T10:50:31.685000Z", - "iopub.status.idle": "2022-05-25T10:50:31.724000Z", - "shell.execute_reply": "2022-05-25T10:50:31.724000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "Based on the example it can be seen that it is possible to create different instances of an FMU. The different instances can then be used to perform different simulations." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/parameterize.ipynb b/example/parameterize.ipynb deleted file mode 100644 index 61715634..00000000 --- a/example/parameterize.ipynb +++ /dev/null @@ -1,659 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Manually parameterize an FMU\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "This example shows how the manually parameterization of an FMU works if very specific adjustments during system initialization is needed. For this purpose, an IO-FMU model is loaded and the various commands for parameterization are shown on the basis of this model. With this example the user shall be guided how to make certain settings at an FMU. Please note, that parameterization of a simulation is possible in a much easier fashion: Using `fmiSimulate`, `fmiSimulateME` or `fmiSimulateCS` together with a parameter dictionary for the keyword `parameters`.\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulation exchange. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/CS_simulate.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:40.626000Z", - "iopub.status.busy": "2022-05-25T10:50:39.995000Z", - "iopub.status.idle": "2022-05-25T10:50:53.067000Z", - "shell.execute_reply": "2022-05-25T10:50:52.995000Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:53.403000Z", - "iopub.status.busy": "2022-05-25T10:50:53.069000Z", - "iopub.status.idle": "2022-05-25T10:50:54.070000Z", - "shell.execute_reply": "2022-05-25T10:50:54.070000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStop = 8.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:54.073000Z", - "iopub.status.busy": "2022-05-25T10:50:54.073000Z", - "iopub.status.idle": "2022-05-25T10:50:58.301000Z", - "shell.execute_reply": "2022-05-25T10:50:58.301000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_E6omKF/IO`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_E6omKF/IO/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/OUODz/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tIO\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{ac3b4a99-4908-40f7-89da-2d5c08b3c4ac}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-17T07:40:55Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t4\n", - "\tInputs:\t\t\t\t3\n", - "\t\t352321536 [\"u_real\"]\n", - "\t\t352321537 [\"u_boolean\"]\n", - "\t\t352321538 [\"u_integer\"]\n", - "\tOutputs:\t\t\t3\n", - "\t\t335544320 [\"y_real\"]\n", - "\t\t335544321 [\"y_boolean\"]\n", - "\t\t335544322 [\"y_integer\"]\n", - "\tStates:\t\t\t\t0\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tIO\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tIO\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"IO\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Instantiate and Setup FMU\n", - "\n", - "Next it is necessary to create an instance of the FMU. This is achieved by the command `fmiInstantiate!()`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:58.303000Z", - "iopub.status.busy": "2022-05-25T10:50:58.303000Z", - "iopub.status.idle": "2022-05-25T10:50:59.044000Z", - "shell.execute_reply": "2022-05-25T10:50:59.044000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "FMU: IO\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000003ae6b10\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", - "FMU time: -Inf\n", - "FMU states: nothing" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiInstantiate!(myFMU; loggingOn=true)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.047000Z", - "iopub.status.busy": "2022-05-25T10:50:59.047000Z", - "iopub.status.idle": "2022-05-25T10:50:59.362000Z", - "shell.execute_reply": "2022-05-25T10:50:59.362000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiSetupExperiment(myFMU, tStart, tStop)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Parameterize FMU\n", - "\n", - "To parameterize an FMU, the FMU must be in the initialization mode, which is reached with the `fmiEnterInitializationMode()` command." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.365000Z", - "iopub.status.busy": "2022-05-25T10:50:59.365000Z", - "iopub.status.idle": "2022-05-25T10:50:59.397000Z", - "shell.execute_reply": "2022-05-25T10:50:59.397000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiEnterInitializationMode(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Within this mode it is then possible to change the different parameters. In this example, for each data type (`real`, `integer`, `boolean` and `string)` a corresponding parameter is selected. At the beginning the initial state of these parameters is displayed with `fmiGet()`." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:50:59.399000Z", - "iopub.status.busy": "2022-05-25T10:50:59.399000Z", - "iopub.status.idle": "2022-05-25T10:51:02.699000Z", - "shell.execute_reply": "2022-05-25T10:51:02.699000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Any}:\n", - " 0.0\n", - " 0\n", - " 0\n", - " \"Hello World!\"" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "params = [\"p_real\", \"p_integer\", \"p_boolean\", \"p_string\"]\n", - "fmiGet(myFMU, params)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next step, a function is defined that generates a random value for each parameter. For the parameter `p_string` a random number is inserted into the string. All parameters are combined to a vector and output." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:51:02.702000Z", - "iopub.status.busy": "2022-05-25T10:51:02.702000Z", - "iopub.status.idle": "2022-05-25T10:51:03.392000Z", - "shell.execute_reply": "2022-05-25T10:51:03.392000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "generateRandomNumbers (generic function with 1 method)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function generateRandomNumbers()\n", - " rndReal = 100 * rand()\n", - " rndInteger = round(Integer, 100 * rand())\n", - " rndBoolean = rand() > 0.5\n", - " rndString = \"Random number $(100 * rand())!\"\n", - "\n", - " randValues = [rndReal, rndInteger, rndBoolean, rndString]\n", - " println(randValues)\n", - " return randValues\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The previously defined function is called and the results are displayed in the console." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:51:03.395000Z", - "iopub.status.busy": "2022-05-25T10:51:03.395000Z", - "iopub.status.idle": "2022-05-25T10:51:04.098000Z", - "shell.execute_reply": "2022-05-25T10:51:04.098000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Any[41.68976766058903, 91, false, \"Random number 18.117421661942835!\"]\n" - ] - } - ], - "source": [ - "paramsVal = generateRandomNumbers();" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### First variant\n", - "\n", - "With this variant it is quickly possible to set all parameters at once. Even different data types can be set with only one command. The command `fmiSet()` selects itself which function is chosen for which data type. After setting the parameters, it is checked whether the corresponding parameters were set correctly. For this the function `fmiGet()` is used as above and afterwards with the macro `@assert` also tested whether the correct values are set." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.102000Z", - "iopub.status.busy": "2022-05-25T10:51:04.102000Z", - "iopub.status.idle": "2022-05-25T10:51:04.571000Z", - "shell.execute_reply": "2022-05-25T10:51:04.571000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Any[41.68976766058903, 91, 0, \"Random number 18.117421661942835!\"]" - ] - } - ], - "source": [ - "fmiSet(myFMU, params, paramsVal)\n", - "values = fmiGet(myFMU, params)\n", - "print(values)\n", - "\n", - "@assert paramsVal == values" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Second variant\n", - "\n", - "To make sure that the functions work it is necessary to generate random numbers again. As shown already, we call the defined function `generateRandomNumbers()` and output the values." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.574000Z", - "iopub.status.busy": "2022-05-25T10:51:04.574000Z", - "iopub.status.idle": "2022-05-25T10:51:04.575000Z", - "shell.execute_reply": "2022-05-25T10:51:04.575000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Any[32.87773039642885, 58, false, \"Random number 22.4054218867213!\"]\n" - ] - } - ], - "source": [ - "rndReal, rndInteger, rndBoolean, rndString = generateRandomNumbers();" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the second variant, the value for each data type is set separately by the corresponding command. By this variant one has the maximum control and can be sure that also the correct data type is set. To illustrate the functionality of the parameterization with the separate functions, the corresponding get function is also called separately for each data type:\n", - "* `fmiSetReal()` <---> `fmiGetReal()`\n", - "* `fmiSetInteger()` <---> `fmiGetInteger()`\n", - "* `fmiSetBoolean()` <---> `fmiGetBoolean()`\n", - "* `fmiSetString()` <---> `fmiGetString()`." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:51:04.579000Z", - "iopub.status.busy": "2022-05-25T10:51:04.578000Z", - "iopub.status.idle": "2022-05-25T10:51:06.093000Z", - "shell.execute_reply": "2022-05-25T10:51:06.093000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "\"32.87773039642885 == 32.87773039642885\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\"58 == 58\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\"false == 0\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\"Random number 22.4054218867213! == Random number 22.4054218867213!\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fmiSetReal(myFMU, \"p_real\", rndReal)\n", - "display(\"$rndReal == $(fmiGetReal(myFMU, \"p_real\"))\")\n", - "\n", - "fmiSetInteger(myFMU, \"p_integer\", rndInteger)\n", - "display(\"$rndInteger == $(fmiGetInteger(myFMU, \"p_integer\"))\")\n", - "\n", - "fmiSetBoolean(myFMU, \"p_boolean\", rndBoolean)\n", - "display(\"$rndBoolean == $(fmiGetBoolean(myFMU, \"p_boolean\"))\")\n", - "\n", - "fmiSetString(myFMU, \"p_string\", rndString)\n", - "display(\"$rndString == $(fmiGetString(myFMU, \"p_string\"))\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After seeing that both variants set the parameters correctly, the initialization mode is terminated with the function `fmiExitInitializationMode()`." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:51:06.096000Z", - "iopub.status.busy": "2022-05-25T10:51:06.096000Z", - "iopub.status.idle": "2022-05-25T10:51:06.127000Z", - "shell.execute_reply": "2022-05-25T10:51:06.127000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiExitInitializationMode(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From here on, you may want to simulate the FMU. Please note, that with the default `executionConfig`, it is necessary to prevent a new instantiation using the keyword `instantiate=false`. Otherwise, a new instance is allocated for the simulation-call and the parameters set for the previous instance are not transfered.\n", - "\n", - "Example:\n", - "`fmiSimulate(...; instantiate=false, ...)`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "The FMU will be unloaded and all unpacked data on disc will be removed." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-25T10:51:06.129000Z", - "iopub.status.busy": "2022-05-25T10:51:06.129000Z", - "iopub.status.idle": "2022-05-25T10:51:06.239000Z", - "shell.execute_reply": "2022-05-25T10:51:06.239000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "Based on this tutorial it can be seen that there are two different variants to set and get parameters.These examples should make it clear to the user how parameters can also be set with different data types." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/simulate.ipynb b/example/simulate.ipynb deleted file mode 100644 index d1b94962..00000000 --- a/example/simulate.ipynb +++ /dev/null @@ -1,1021 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Simulate an FMU in different modes\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "In this example we want to show how fast and easy the simulation for an FMU is. For this purpose, the FMU is simulated in co-simulation mode and in model-exchange mode. After the FMU has been simulated, the simulation results are displayed in a graph. The graphs of the different modes are compared with each other. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/simulate.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:10:58.160000Z", - "iopub.status.busy": "2022-05-24T15:10:57.200000Z", - "iopub.status.idle": "2022-05-24T15:11:28.115000Z", - "shell.execute_reply": "2022-05-24T15:11:28.004000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Replacing docs for `FMI.fmiPlot :: Tuple{FMICore.FMU2Solution}` in module `FMI`\n", - "└ @ Base.Docs docs/Docs.jl:240\n" - ] - } - ], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:11:39.107000Z", - "iopub.status.busy": "2022-05-24T15:11:28.118000Z", - "iopub.status.idle": "2022-05-24T15:11:40.147000Z", - "shell.execute_reply": "2022-05-24T15:11:40.147000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0.0:0.01:8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStep = 0.01\n", - "tStop = 8.0\n", - "tSave = tStart:tStep:tStop" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:11:40.151000Z", - "iopub.status.busy": "2022-05-24T15:11:40.151000Z", - "iopub.status.idle": "2022-05-24T15:11:45.736000Z", - "shell.execute_reply": "2022-05-24T15:11:45.736000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_TJndII/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_TJndII/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/S8pFT/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringFrictionPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t24\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "# fmiLoad(\"path/to/myFMU.fmu\"; unpackPath = \"path/to/unpacked/fmu/\")\n", - "\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulate FMU\n", - "\n", - "In the following, the FMU is simulated in the two different simulation modes.\n", - "\n", - "#### Simulate as Co-Simulation\n", - "\n", - "In the next steps the recorded values are defined. The first state is the position of the mass and the second state is the velocity. In the function `fmiSimulateCS()` the FMU is simulated in co-simulation mode (CS) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time and the recorded variables are specified." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:11:45.739000Z", - "iopub.status.busy": "2022-05-24T15:11:45.739000Z", - "iopub.status.idle": "2022-05-24T15:11:52.663000Z", - "shell.execute_reply": "2022-05-24T15:11:52.663000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Model name:\n", - "\tSpringFrictionPendulum1D\n", - "Success:\n", - "\ttrue\n", - "Values [801]:\n", - "\t0.0\t(0.5, 0.0)\n", - "\t0.01\t(0.5002235448486548, 0.042692491939260585)\n", - "\t0.02\t(0.5008715291319449, 0.08568000508550636)\n", - "\t0.03\t(0.5019478597521578, 0.12892136998736314)\n", - "\t0.04\t(0.5034570452098334, 0.17232325681284336)\n", - "\t0.05\t(0.5053993458877354, 0.2158440857658765)\n", - "\t0.06\t(0.5077764240578201, 0.259420181133082)\n", - "\t0.07\t(0.5105886522837868, 0.30295578207463486)\n", - "\t0.08\t(0.5138351439717114, 0.3464184707972189)\n", - "\t...\n", - "\t8.0\t(1.071367253976742, -1.000814138594347e-10)\n", - "Events [0]:\n" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vrs = [\"mass.s\", \"mass.v\"]\n", - "\n", - "dataCS = fmiSimulateCS(myFMU, tStart, tStop; recordValues=vrs, saveat=tSave)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Simulate as Model-Exchange\n", - "\n", - "In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time are specified. In contrast to the co-simulation, the values to be stored are not specified here, since the states and events of the FMU are always output as well. The identifiers given above just correspond to the states of the FMU." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:11:52.667000Z", - "iopub.status.busy": "2022-05-24T15:11:52.667000Z", - "iopub.status.idle": "2022-05-24T15:12:09.582000Z", - "shell.execute_reply": "2022-05-24T15:12:09.582000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:11\u001b[39m\n" - ] - }, - { - "data": { - "text/plain": [ - "Model name:\n", - "\tSpringFrictionPendulum1D\n", - "Success:\n", - "\ttrue\n", - "States [801]:\n", - "\t0.0\t[0.5, 0.0]\n", - "\t0.01\t[0.5002131418344649, 0.042689450666241]\n", - "\t0.02\t[0.5008548874805565, 0.08570846215523381]\n", - "\t0.03\t[0.5019281653120716, 0.12898389312495082]\n", - "\t0.04\t[0.5034351805057593, 0.17244393475170294]\n", - "\t0.05\t[0.5053774287967188, 0.2160182432854046]\n", - "\t0.06\t[0.5077556967622916, 0.25963796675862466]\n", - "\t0.07\t[0.5105701003205937, 0.3032358690888718]\n", - "\t0.08\t[0.5138201049458624, 0.34674641820324037]\n", - "\t...\n", - "\t8.0\t[1.0668213438183276, -1.0000099359121942e-10]\n", - "Events [6]:\n", - "\tState-Event #11 @ 0.0s\n", - "\tState-Event #11 @ 0.9939s\n", - "\tState-Event #19 @ 1.9881s\n", - "\tState-Event #11 @ 2.9829s\n", - "\tState-Event #19 @ 3.9787s\n", - "\tState-Event #11 @ 4.9768s\n" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dataME = fmiSimulateME(myFMU, tStart, tStop; saveat=tSave)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plotting FMU\n", - "\n", - "After the simulation is finished the results of the FMU for the co-simulation and model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:12:09.586000Z", - "iopub.status.busy": "2022-05-24T15:12:09.586000Z", - "iopub.status.idle": "2022-05-24T15:12:34.657000Z", - "shell.execute_reply": "2022-05-24T15:12:34.657000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiPlot(dataCS)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:12:34.663000Z", - "iopub.status.busy": "2022-05-24T15:12:34.663000Z", - "iopub.status.idle": "2022-05-24T15:12:34.960000Z", - "shell.execute_reply": "2022-05-24T15:12:34.959000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiPlot(dataME)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From both graphs it can be seen that the simulation calculates exactly the same results." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-05-24T15:12:34.965000Z", - "iopub.status.busy": "2022-05-24T15:12:34.965000Z", - "iopub.status.idle": "2022-05-24T15:12:35.028000Z", - "shell.execute_reply": "2022-05-24T15:12:35.028000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "Based on this tutorial it can be seen that simulating in the different mode is very easy, and it only takes a few commands to simulate the FMU. " - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 2682ab6dd2e22dca0ecd20d5a679a6c4fbfe105b Mon Sep 17 00:00:00 2001 From: JoKircher <79573182+JoKircher@users.noreply.github.com> Date: Tue, 28 Jun 2022 15:46:56 +0200 Subject: [PATCH 23/41] tests for fmi2 passing (#134) * Jupyter nbconvert synch - modified, paired .ipynb files * move additional functions to the end * refactor FMI3_additional.jl * update docstrings for wrapper functions * Jupyter nbconvert synch - modified, paired .ipynb files * added FMI3_JLD2.jl * WIP: fmi3 refactor * update tests for FMI3 * WIP: added more fmi3 calls * add help function for fmiLoad * WIP: updated all fmi functions * comment tests for fmi3 out for now * WIP: merge * fixed fmiLoad Co-authored-by: JoKircher Co-authored-by: ThummeTo <83663542+ThummeTo@users.noreply.github.com> --- docs/src/examples/manipulation.md | 289 ++ .../manipulation_files/manipulation_10_0.svg | 134 + .../manipulation_files/manipulation_18_0.svg | 172 + docs/src/examples/modelica_conference_2021.md | 219 ++ .../modelica_conference_2021_8_0.svg | 110 + docs/src/examples/multiple_instances.md | 226 ++ .../multiple_instances_10_0.svg | 902 +++++ .../multiple_instances_18_0.svg | 1708 +++++++++ docs/src/examples/multiprocessing.md | 279 ++ docs/src/examples/multithreading.md | 254 ++ docs/src/examples/parameterize.md | 312 ++ docs/src/examples/simulate.md | 245 ++ .../examples/simulate_files/simulate_12_0.svg | 274 ++ .../examples/simulate_files/simulate_13_0.svg | 295 ++ example/manipulation.ipynb | 839 +++++ example/modelica_conference_2021.ipynb | 560 +++ example/multiple_instances.ipynb | 3081 +++++++++++++++++ example/multiprocessing.ipynb | 516 +++ example/multithreading.ipynb | 481 +++ example/parameterize.ipynb | 659 ++++ example/simulate.ipynb | 1012 ++++++ src/FMI.jl | 36 +- src/FMI3_additional.jl | 5 +- 23 files changed, 12599 insertions(+), 9 deletions(-) create mode 100644 docs/src/examples/manipulation.md create mode 100644 docs/src/examples/manipulation_files/manipulation_10_0.svg create mode 100644 docs/src/examples/manipulation_files/manipulation_18_0.svg create mode 100644 docs/src/examples/modelica_conference_2021.md create mode 100644 docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg create mode 100644 docs/src/examples/multiple_instances.md create mode 100644 docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg create mode 100644 docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg create mode 100644 docs/src/examples/multiprocessing.md create mode 100644 docs/src/examples/multithreading.md create mode 100644 docs/src/examples/parameterize.md create mode 100644 docs/src/examples/simulate.md create mode 100644 docs/src/examples/simulate_files/simulate_12_0.svg create mode 100644 docs/src/examples/simulate_files/simulate_13_0.svg create mode 100644 example/manipulation.ipynb create mode 100644 example/modelica_conference_2021.ipynb create mode 100644 example/multiple_instances.ipynb create mode 100644 example/multiprocessing.ipynb create mode 100644 example/multithreading.ipynb create mode 100644 example/parameterize.ipynb create mode 100644 example/simulate.ipynb diff --git a/docs/src/examples/manipulation.md b/docs/src/examples/manipulation.md new file mode 100644 index 00000000..adea4344 --- /dev/null +++ b/docs/src/examples/manipulation.md @@ -0,0 +1,289 @@ +# Manipulate a function +Tutorial by Johannes Stoljar, Tobias Thummerer + +## License +Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar + +Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. + +## Motivation +This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. + +## Introduction to the example +This example shows how to overwrite a library function with an own function. For this the FMU model is simulated first without changes. Then the function `fmi2GetReal()` is overwritten and simulated again. Both simulations are displayed in a graph to show the change caused by overwriting the function. The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. + +![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) + + +## Target group +The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. + + +## Other formats +Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/manipulation.md) corresponding to the notebook. + + +## Getting started + +### Installation prerequisites +| | Description | Command | Alternative | +|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| +| 1. | Enter Package Manager via | ] | | +| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | +| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | +| 4. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " | +| 5. | Install Plots via | add Plots | | + +## Code section + +To run the example, the previously installed packages must be included. + + +```julia +# imports +using FMI +using FMIZoo +using FMICore +using Plots +``` + +### Simulation setup + +Next, the start time and end time of the simulation are set. + + +```julia +tStart = 0.0 +tStop = 8.0 +``` + + + + + 8.0 + + + +### Import FMU + +In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. + + +```julia +# we use an FMU from the FMIZoo.jl +pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x") + +myFMU = fmiLoad(pathToFMU) + +fmiInfo(myFMU) +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 + + + #################### Begin information for FMU #################### + Model name: SpringFrictionPendulum1D + FMI-Version: 2.0 + GUID: {df491d8d-0598-4495-913e-5b025e54d7f2} + Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 + Generation time: 2022-03-03T15:09:18Z + Var. naming conv.: structured + Event indicators: 24 + Inputs: 0 + Outputs: 0 + States: 2 + 33554432 ["mass.s"] + 33554433 ["mass.v", "mass.v_relfric"] + Supports Co-Simulation: true + Model identifier: SpringFrictionPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + Var. com. steps: true + Input interpol.: true + Max order out. der.: 1 + Supports Model-Exchange: true + Model identifier: SpringFrictionPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + ##################### End information for FMU ##################### + + +### Simulate FMU + +In the next steps the recorded value is defined. The recorded value is the position of the mass. In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size. In addition, the start and end time and the recorded variables are specified. + + +```julia +vrs = ["mass.s"] + +simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs) +``` + + Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10 + + + + + + Model name: + SpringFrictionPendulum1D + Success: + true + States [110]: + 0.0 [0.5, 0.0] + 2.3529411764719727e-11 [0.5, 1.0e-10] + 1.0000023529411766e-5 [0.5000000002125017, 4.250030186348503e-5] + 0.00011000002352941177 [0.5000000257134062, 0.0004675245102952289] + 0.0011100000235294118 [0.5000026191281834, 0.004719970360497647] + 0.011110000023529413 [0.5002631686645611, 0.047449647283752144] + 0.03982466736770743 [0.5034050123596227, 0.17168075110950387] + 0.09972054285078226 [0.5215006197560228, 0.43204954153497455] + 0.16481836271111422 [0.5585747156842935, 0.703758265932321] + ... + 8.0 [1.0668213438183276, -1.0000099359121942e-10] + Values [110]: + 0.0 (0.5,) + 2.3529411764719727e-11 (0.5,) + 1.0000023529411766e-5 (0.5000000002125017,) + 0.00011000002352941177 (0.5000000257134062,) + 0.0011100000235294118 (0.5000026191281834,) + 0.011110000023529413 (0.5002631686645611,) + 0.03982466736770743 (0.5034050123596227,) + 0.09972054285078226 (0.5215006197560228,) + 0.16481836271111422 (0.5585747156842935,) + ... + 8.0 (1.0668213438183276,) + Events [6]: + State-Event #11 @ 0.0s + State-Event #11 @ 0.9939s + State-Event #19 @ 1.9881s + State-Event #11 @ 2.9829s + State-Event #19 @ 3.9787s + State-Event #11 @ 4.9768s + + + + +### Plotting FMU + +After the simulation is finished, the result of the FMU for the model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time. + + +```julia +fig = fmiPlot(simData, states=false) +``` + + + + + +![svg](manipulation_files/manipulation_10_0.svg) + + + + +### Override Function + +After overwriting a function, the previous one is no longer accessible. The original function `fmi2GetReal()` is cached by storing the address of the pointer. The addresses of the pointers are kept in the FMU and are thus accessible. + + +```julia +# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function +originalGetReal = myFMU.cGetReal +``` + + + + + Ptr{Nothing} @0x00007f52e9530faf + + + +To overwrite the function `fmi2GetReal!()`, the function header of the new custom function must be identical to the previous one. The function header looks like `fmi2GetReal!(cfunc::Ptr{Nothing}, c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})::fmi2Status`. The information how the FMI2 function are structured can be seen from [FMICore.jl](https://github.com/ThummeTo/FMICore.jl/blob/main/src/FMI2_c.jl#L718) or the FMI2.0.3-specification. + +In the new implementation the original function is called by the previously stored pointer. Next there is a special handling if `value` is a pointer to an array. In this case the pointer is treated as an array, so that the entries are accessible. Otherwise, each value in `value` is multiplied by two. Finally, the original state of the original function is output. + + +```julia +function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, + nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}}) + # first, we do what the original function does + status = 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) + end + + # now, we multiply every value by two (just for fun!) + for i in 1:nvr + value[i] *= 2.0 + end + + # return the original status + return status +end +``` + + + + + myGetReal! (generic function with 1 method) + + + +In the next command the original function is overwritten with the new defined function, for which the command `fmiSetFctGetReal()` is called. + + +```julia +# no we overwrite the original function +fmiSetFctGetReal(myFMU, myGetReal!) +``` + + + + + Ptr{Nothing} @0x00007f533e325fc0 + + + +### Simulate and Plot FMU with modified function + +As before, the identical command is called here for simulation. This is also a model exchange simulation. Immediately afterwards, the results are added to the previous graph as a dashed line. + + +```julia +simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs) +fmiPlot!(fig, simData; states=false, style=:dash) +``` + + + + + +![svg](manipulation_files/manipulation_18_0.svg) + + + + +As expected by overwriting the function, all values are doubled. + +### Unload FMU + +After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. + + +```julia +fmiUnload(myFMU) +``` + +### Summary + +In this tutorial it is shown how an existing function of the library can be replaced by an own implementation. Through this possibility, there are almost no limits for the user, whereby the user can customize the function to his liking. diff --git a/docs/src/examples/manipulation_files/manipulation_10_0.svg b/docs/src/examples/manipulation_files/manipulation_10_0.svg new file mode 100644 index 00000000..b86d3be2 --- /dev/null +++ b/docs/src/examples/manipulation_files/manipulation_10_0.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/examples/manipulation_files/manipulation_18_0.svg b/docs/src/examples/manipulation_files/manipulation_18_0.svg new file mode 100644 index 00000000..d9cf606b --- /dev/null +++ b/docs/src/examples/manipulation_files/manipulation_18_0.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/examples/modelica_conference_2021.md b/docs/src/examples/modelica_conference_2021.md new file mode 100644 index 00000000..c77e978a --- /dev/null +++ b/docs/src/examples/modelica_conference_2021.md @@ -0,0 +1,219 @@ +# Advanced Simulation of an FMU +Tutorial by Johannes Stoljar, Tobias Thummerer + +## License +Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar + +Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. + +## Motivation +This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. + +## Introduction to the example +In this example we would like to show that besides the simple simulation of an FMU there is also a more advanced version of the simulation. The advantage of the more advanced variant is that there are more possibilities to intervene in the simulation to make changes. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. + +![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) + + +## Target group +The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. + + +## Other formats +Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/modelica_conference_2021.md) corresponding to the notebook. + + +## Getting started + +### Installation prerequisites +| | Description | Command | Alternative | +|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| +| 1. | Enter Package Manager via | ] | | +| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | +| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | +| 4. | Install Plots via | add Plots | | + +## Code section + +To run the example, the previously installed packages must be included. + + +```julia +# imports +using FMI +using FMIZoo +using Plots +``` + +### Simulation setup + +Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. + + +```julia +tStart = 0.0 +tStep = 0.1 +tStop = 8.0 +tSave = tStart:tStep:tStop +``` + + + + + 0.0:0.1:8.0 + + + +### Simple FMU Simulation + +In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. + + +```julia +# we use an FMU from the FMIZoo.jl +pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x") + +myFMU = fmiLoad(pathToFMU) +fmiInfo(myFMU) +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 + + + #################### Begin information for FMU #################### + Model name: SpringFrictionPendulum1D + FMI-Version: 2.0 + GUID: {df491d8d-0598-4495-913e-5b025e54d7f2} + Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 + Generation time: 2022-03-03T15:09:18Z + Var. naming conv.: structured + Event indicators: 24 + Inputs: 0 + Outputs: 0 + States: 2 + 33554432 ["mass.s"] + 33554433 ["mass.v", "mass.v_relfric"] + Supports Co-Simulation: true + Model identifier: SpringFrictionPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + Var. com. steps: true + Input interpol.: true + Max order out. der.: 1 + Supports Model-Exchange: true + Model identifier: SpringFrictionPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + ##################### End information for FMU ##################### + + +In the next commands the FMU is simulated, for which the start and end time and recorded variables are declared. Afterwards the simulation result is shown in a graph. In the plot for the FMU, it can be seen that the oscillation keeps decreasing due to the effect of friction. If one simulates long enough, the oscillation comes to a standstill after a certain time. + + +```julia +simData = fmiSimulate(myFMU, tStart, tStop; recordValues=["mass.s"], saveat=tSave) +fmiPlot(simData) +``` + + + + + +![svg](modelica_conference_2021_files/modelica_conference_2021_8_0.svg) + + + + +After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. + + +```julia +fmiUnload(myFMU) +``` + +### Advanced FMU Simulation + +In the following type of simulation a more advanced variant is presented, which allows intervening more in the simulation process. Analogous to the simple variant, an FMU model must be loaded. + + +```julia +myFMU = fmiLoad(pathToFMU); +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 + + +Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. + + +```julia +instanceFMU = fmiInstantiate!(myFMU) +``` + + + + + FMU: SpringFrictionPendulum1D + InstanceName: [not defined] + Address: Ptr{Nothing} @0x00000000064853f0 + State: fmi2ComponentStateInstantiated + Logging: false + FMU time: -Inf + FMU states: nothing + + + +In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. Next, the FMU is initialized by the calls of `fmiEnterInitializationMode()` and `fmiExitInitializationMode()`. It would also be possible to set initial states for the FMU between these two commands. + + +```julia +fmiSetupExperiment(instanceFMU, tStart, tStop) +fmiEnterInitializationMode(instanceFMU) +# set initial model states +fmiExitInitializationMode(instanceFMU) +``` + + + + + 0x00000000 + + + +The actual simulation loop is shown in the following block. Here a simulation step `fmiDoStep()` with the fixed step size `tStep` is executed. As indicated in the code by the comments, the input values and output values of the FMU could be changed in the simulation loop as desired, whereby the higher possibility of adjustments arises. + + +```julia +for t in tSave + # set model inputs + # ... + fmiDoStep(instanceFMU, tStep) + # get model outputs + # ... +end +``` + +The instantiated FMU must be terminated and then the memory area for the instance can also be deallocated. The last step is to unload the FMU to remove all unpacked data on disc. + + +```julia +fmiTerminate(instanceFMU) +fmiFreeInstance!(instanceFMU) +fmiUnload(myFMU) +``` + +### Summary + +The tutorial has shown that besides the usual simple variant of simulating an FMU, there is another way to make more adjustments. diff --git a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg new file mode 100644 index 00000000..c714d93e --- /dev/null +++ b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/examples/multiple_instances.md b/docs/src/examples/multiple_instances.md new file mode 100644 index 00000000..d20d0c7f --- /dev/null +++ b/docs/src/examples/multiple_instances.md @@ -0,0 +1,226 @@ +# Multiple Instances of an FMU +Tutorial by Johannes Stoljar, Tobias Thummerer + +## License +Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar + +Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. + +## Motivation +This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. + +## Introduction to the example +In this example we want to show that it is possible to create different instances of an FMU. The different instances can then be used to run independent simulations. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum without friction. The object-orientated structure of the *SpringPendulum1D* can be seen in the following graphic. + +![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringPendulum1D.svg?raw=true) + + +## Target group +The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. + + +## Other formats +Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/multiple_instances.md) corresponding to the notebook. + + +## Getting started + +### Installation prerequisites +| | Description | Command | Alternative | +|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| +| 1. | Enter Package Manager via | ] | | +| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | +| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | +| 4. | Install Plots via | add Plots | | + +## Code section + +To run the example, the previously installed packages must be included. + + +```julia +# imports +using FMI +using FMIZoo +using Plots +``` + +### Simulation setup + +Next, the start time and end time of the simulation are set. Finally, the recorded values are specified to store the results of the simulation. + + +```julia +tStart = 0.0 +tStop = 8.0 + +vrs = ["mass.s"] +``` + + + + + 1-element Vector{String}: + "mass.s" + + + +### Import FMU + +In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. + + +```julia +# we use an FMU from the FMIZoo.jl +pathToFMU = get_model_filename("SpringPendulum1D", "Dymola", "2022x") + +myFMU = fmiLoad(pathToFMU) +fmiInfo(myFMU) +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 + + + #################### Begin information for FMU #################### + Model name: SpringPendulum1D + FMI-Version: 2.0 + GUID: {a3e886fa-675c-4308-8e91-3490e598ba11} + Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 + Generation time: 2022-03-03T15:08:57Z + Var. naming conv.: structured + Event indicators: 0 + Inputs: 0 + Outputs: 0 + States: 2 + 33554432 ["mass.s"] + 33554433 ["mass.v"] + Supports Co-Simulation: true + Model identifier: SpringPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + Var. com. steps: true + Input interpol.: true + Max order out. der.: 1 + Supports Model-Exchange: true + Model identifier: SpringPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + ##################### End information for FMU ##################### + + +### First Instance + +To create an instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU. + + +```julia +comp1 = fmiInstantiate!(myFMU; loggingOn=true) +comp1Address= comp1.compAddr +println(comp1) +``` + + FMU: SpringPendulum1D + InstanceName: [not defined] + Address: Ptr{Nothing} @0x0000000003954580 + State: fmi2ComponentStateInstantiated + Logging: false + FMU time: -Inf + FMU states: nothing + + +Next, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $10.0 \frac{N}{m}$ and for the position of the mass `mass.s` a value of $1.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation. + + +```julia +param1 = Dict("spring.c"=>10.0, "mass_s0"=>1.0) +data1 = fmiSimulate(comp1, tStart, tStop; parameters=param1, recordValues=vrs, instantiate=false) +fig = fmiPlot(data1) +``` + + + + + +![svg](multiple_instances_files/multiple_instances_10_0.svg) + + + + +For control, you can compare again the address of the instance to the previous address, and it should be the same address. As soon as this is not the case an error would be thrown by the macro `@assert`. + + +```julia +@assert comp1.compAddr === comp1Address +``` + +### Second Instance + +To create a second instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU. + + +```julia +comp2 = fmiInstantiate!(myFMU; loggingOn=true) +comp2Address= comp2.compAddr +println(comp2) +``` + + FMU: SpringPendulum1D + InstanceName: [not defined] + Address: Ptr{Nothing} @0x000000000529d440 + State: fmi2ComponentStateInstantiated + Logging: false + FMU time: -Inf + FMU states: nothing + + +The addresses of the instantiated FMUs must differ, and you can see that in the comparison below. + + +```julia +@assert comp1Address !== comp2Address +``` + +Again, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $1.0 \frac{N}{m}$ and for the position of the mass `mass.s` a value of $2.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation. + + +```julia +param2 = Dict("spring.c"=>1.0, "mass.s"=>2.0) +data2 = fmiSimulateCS(comp2, tStart, tStop; parameters=param2, recordValues=vrs, instantiate=false) +fmiPlot!(fig, data2) +``` + + + + + +![svg](multiple_instances_files/multiple_instances_18_0.svg) + + + + +For control, you can compare again the address of the instance `comp2` to the previous address `comp2Address` and it should be the same address. + + +```julia +@assert comp2.compAddr === comp2Address +``` + +### Unload FMU + +After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. + + +```julia +fmiUnload(myFMU) +``` + +### Summary + +Based on the example it can be seen that it is possible to create different instances of an FMU. The different instances can then be used to perform different simulations. diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg new file mode 100644 index 00000000..cf0fca99 --- /dev/null +++ b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg @@ -0,0 +1,902 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg new file mode 100644 index 00000000..8004ffcf --- /dev/null +++ b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg @@ -0,0 +1,1708 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/examples/multiprocessing.md b/docs/src/examples/multiprocessing.md new file mode 100644 index 00000000..365cdee4 --- /dev/null +++ b/docs/src/examples/multiprocessing.md @@ -0,0 +1,279 @@ +# Multiprocessing +Tutorial by Jonas Wilfert, Tobias Thummerer + +## License +Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert + +Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. + +## Motivation +This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. + +## Introduction to the example +This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings. +Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multiprocessing**, check `multithreading.ipynb` for multithreading. +Advantage of multithreading is a lower communication overhead as well as lower RAM usage. +However in some cases multiprocessing can be faster as the garbage collector is not shared. + + +The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. + +![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) + + +## Target group +The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. + + +## Other formats +Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/distributed.md) corresponding to the notebook. + + +## Getting started + +### Installation prerequisites +| | Description | Command | Alternative | +|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| +| 1. | Enter Package Manager via | ] | | +| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | +| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | +| 4. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " | +| 5. | Install BenchmarkTools via | add BenchmarkTools | | + +## Code section + + + +Adding your desired amount of processes: + + +```julia +using Distributed +n_procs = 4 +addprocs(n_procs; exeflags=`--project=$(Base.active_project()) --threads=auto`, restrict=false) +``` + + + + + 4-element Vector{Int64}: + 2 + 3 + 4 + 5 + + + +To run the example, the previously installed packages must be included. + + +```julia +# imports +@everywhere using FMI +@everywhere using FMIZoo +@everywhere using BenchmarkTools +``` + +Checking that we workers have been correctly initialized: + + +```julia +workers() + +@everywhere println("Hello World!") + +# The following lines can be uncommented for more advanced informations about the subprocesses +# @everywhere println(pwd()) +# @everywhere println(Base.active_project()) +# @everywhere println(gethostname()) +# @everywhere println(VERSION) +# @everywhere println(Threads.nthreads()) +``` + + Hello World! + From worker 2: Hello World! + From worker 4: Hello World! + From worker 3: Hello World! + From worker 5: Hello World! + + +### Simulation setup + +Next, the batch size and input values are defined. + + +```julia + +# Best if batchSize is a multiple of the threads/cores +batchSize = 16 + +# Define an array of arrays randomly +input_values = collect(collect.(eachrow(rand(batchSize,2)))) +``` + + + + + 16-element Vector{Vector{Float64}}: + [0.053272555584304104, 0.45774751559489646] + [0.5896778258750763, 0.12435199368996086] + [0.5651662129022856, 0.8764873667695812] + [0.6176612662918868, 0.2785804850450695] + [0.9274233385552415, 0.38275426899967724] + [0.46094177953642124, 0.6554519159504497] + [0.73421590884579, 0.28177572874256906] + [0.5575198504784948, 0.3212214708846175] + [0.271126562512229, 0.6499895887749823] + [0.5289045741655536, 0.4873381265273107] + [0.8565770844036877, 0.2312687408548988] + [0.06332369482582334, 0.44807066874864065] + [0.08611017776660712, 0.960898209225902] + [0.3191189843443898, 0.30014344015893846] + [0.028884098958377402, 0.5285860311385517] + [0.7282727650515579, 0.7584435212215901] + + + +### Shared Module +For Distributed we need to embed the FMU into its own `module`. This prevents Distributed from trying to serialize and send the FMU over the network, as this can cause issues. This module needs to be made available on all processes using `@everywhere`. + + +```julia +@everywhere module SharedModule + using FMIZoo + using FMI + + t_start = 0.0 + t_step = 0.1 + t_stop = 10.0 + tspan = (t_start, t_stop) + tData = collect(t_start:t_step:t_stop) + + model_fmu = FMIZoo.fmiLoad("SpringPendulum1D", "Dymola", "2022x") +end +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`. + [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`. + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources` + [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + + +We define a helper function to calculate the FMU and combine it into an Matrix. + + +```julia +@everywhere function runCalcFormatted(fmu, x0, recordValues=["mass.s", "mass.v"]) + data = fmiSimulateME(fmu, SharedModule.t_start, SharedModule.t_stop; recordValues=recordValues, saveat=SharedModule.tData, x0=x0, showProgress=false, dtmax=1e-4) + return reduce(hcat, data.states.u) +end +``` + +Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools. + + +```julia +@benchmark data = runCalcFormatted(SharedModule.model_fmu, rand(2)) +``` + + + + + BenchmarkTools.Trial: 17 samples with 1 evaluation. + Range (min … max): 304.291 ms … 325.332 ms ┊ GC (min … max): 7.41% … 6.89% + Time (median): 307.274 ms ┊ GC (median): 7.37% + Time (mean ± σ): 309.397 ms ±  5.860 ms ┊ GC (mean ± σ): 7.94% ± 1.32% + + █▁▁ ▁█ ▁▁  █▁▁                   ▁ ▁ ▁                      ▁  + ███▁██▁██▁▁███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁█▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 304 ms Histogram: frequency by time 325 ms < + + Memory estimate: 146.80 MiB, allocs estimate: 3002433. + + + +### Single Threaded Batch Execution +To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call. + + +```julia +println("Single Threaded") +@benchmark collect(runCalcFormatted(SharedModule.model_fmu, i) for i in input_values) +``` + + Single Threaded + + + + + + BenchmarkTools.Trial: 2 samples with 1 evaluation. + Range (min … max): 4.966 s …  4.967 s ┊ GC (min … max): 8.58% … 8.12% + Time (median): 4.966 s ┊ GC (median): 8.35% + Time (mean ± σ): 4.966 s ± 1.039 ms ┊ GC (mean ± σ): 8.35% ± 0.33% + + █                                                      █  + █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 4.97 s Histogram: frequency by time 4.97 s < + + Memory estimate: 2.29 GiB, allocs estimate: 48038916. + + + +### Multithreaded Batch Execution +In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe. +To spread the execution of a function to multiple processes, the function `pmap` can be used. + + +```julia +println("Multi Threaded") +@benchmark pmap(i -> runCalcFormatted(SharedModule.model_fmu, i), input_values) +``` + + Multi Threaded + + + + + + BenchmarkTools.Trial: 2 samples with 1 evaluation. + Range (min … max): 3.069 s …  3.078 s ┊ GC (min … max): 0.00% … 0.00% + Time (median): 3.074 s ┊ GC (median): 0.00% + Time (mean ± σ): 3.074 s ± 6.467 ms ┊ GC (mean ± σ): 0.00% ± 0.00% + + █                                                      █  + █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 3.07 s Histogram: frequency by time 3.08 s < + + Memory estimate: 81.31 KiB, allocs estimate: 1192. + + + +As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `n_procs` (or the number of physical cores of your CPU), this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` Julia processes. + +### Unload FMU + +After calculating the data, the FMU is unloaded and all unpacked data on disc is removed. + + +```julia +@everywhere fmiUnload(SharedModule.model_fmu) +``` + +### Summary + +In this tutorial it is shown how multi processing with `Distributed.jl` can be used to improve the performance for calculating a Batch of FMUs. diff --git a/docs/src/examples/multithreading.md b/docs/src/examples/multithreading.md new file mode 100644 index 00000000..3f1d0979 --- /dev/null +++ b/docs/src/examples/multithreading.md @@ -0,0 +1,254 @@ +# Multithreading +Tutorial by Jonas Wilfert, Tobias Thummerer + +## License +Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert + +Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. + +## Motivation +This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. + +## Introduction to the example +This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings. +Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multithreading**, check `multiprocessing.ipynb` for multiprocessing. +Advantage of multithreading is a lower communication overhead as well as lower RAM usage. +However in some cases multiprocessing can be faster as the garbage collector is not shared. + + +The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. + +![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) + + +## Target group +The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. + + +## Other formats +Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/parallel.md) corresponding to the notebook. + + +## Getting started + +### Installation prerequisites +| | Description | Command | Alternative | +|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| +| 1. | Enter Package Manager via | ] | | +| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | +| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | +| 4. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " | +| 5. | Install Folds via | add Folds | | +| 6. | Install BenchmarkTools via | add BenchmarkTools | | + +## Code section + +To run the example, the previously installed packages must be included. + + +```julia +# imports +using FMI +using FMIZoo +using Folds +using BenchmarkTools +``` + +First, check the amount of available threads: + + +```julia +Threads.nthreads() +``` + + + + + 1 + + + +If the number of available threads doesn't match your expections, you can increase the number of threads available to the Julia process like described [here](https://docs.julialang.org/en/v1/manual/multi-threading/#Starting-Julia-with-multiple-threads). + +### Simulation setup + +Next, the start time and end time of the simulation are set. Here we also decide the size of the batch. + + +```julia +t_start = 0.0 +t_step = 0.1 +t_stop = 10.0 +tspan = (t_start, t_stop) +tData = collect(t_start:t_step:t_stop) + +# Best if batchSize is a multiple of the threads/cores +batchSize = Threads.nthreads() + +# Define an array of arrays randomly +input_values = collect(collect.(eachrow(rand(batchSize,2)))) + +``` + + + + + 1-element Vector{Vector{Float64}}: + [0.769193342919982, 0.5516183754569333] + + + +We need to instantiate one FMU for each parallel execution, as they cannot be easily shared among different threads. + + +```julia +# a single FMU to compare the performance +realFMU = fmiLoad("SpringPendulum1D", "Dymola", "2022x") + +# the FMU batch +realFMUBatch = [fmiLoad("SpringPendulum1D", "Dymola", "2022x") for _ in 1:batchSize] +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 + ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 + + + + + + 1-element Vector{FMU2}: + Model name: SpringPendulum1D + Type: 1 + + + +We define a helper function to calculate the FMU solution and combine it into an Matrix. + + +```julia +function runCalcFormatted(fmu::FMU2, x0::Vector{Float64}, recordValues::Vector{String}=["mass.s", "mass.v"]) + data = fmiSimulateME(fmu, t_start, t_stop; recordValues=recordValues, saveat=tData, x0=x0, showProgress=false, dtmax=1e-4) + return reduce(hcat, data.states.u) +end +``` + + + + + runCalcFormatted (generic function with 2 methods) + + + +Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools. + + +```julia +@benchmark data = runCalcFormatted(realFMU, rand(2)) +``` + + + + + BenchmarkTools.Trial: 15 samples with 1 evaluation. + Range (min … max): 337.943 ms … 357.340 ms ┊ GC (min … max): 7.03% … 6.55% + Time (median): 339.287 ms ┊ GC (median): 7.00% + Time (mean ± σ): 342.299 ms ±  5.982 ms ┊ GC (mean ± σ): 7.39% ± 1.12% + + ▃█                                                             + ██▇▇▇▇▁▁▇▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇ ▁ + 338 ms Histogram: frequency by time 357 ms < + + Memory estimate: 146.80 MiB, allocs estimate: 3002433. + + + +### Single Threaded Batch Execution +To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call. + + +```julia +println("Single Threaded") +@benchmark collect(runCalcFormatted(realFMU, i) for i in input_values) +``` + + Single Threaded + + + + + + BenchmarkTools.Trial: 15 samples with 1 evaluation. + Range (min … max): 338.941 ms … 359.792 ms ┊ GC (min … max): 7.42% … 7.05% + Time (median): 340.880 ms ┊ GC (median): 7.45% + Time (mean ± σ): 343.682 ms ±  6.291 ms ┊ GC (mean ± σ): 7.89% ± 1.20% + + █▁▁▁▁█  ▁▁▁    ▁                        ▁▁                  ▁  + ██████▁▁███▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ + 339 ms Histogram: frequency by time 360 ms < + + Memory estimate: 146.80 MiB, allocs estimate: 3002436. + + + +### Multithreaded Batch Execution +In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe. +To spread the execution of a function to multiple threads, the library `Folds` can be used. + + +```julia +println("Multi Threaded") +@benchmark Folds.collect(runCalcFormatted(fmu, i) for (fmu, i) in zip(realFMUBatch, input_values)) +``` + + Multi Threaded + + + + + + BenchmarkTools.Trial: 17 samples with 1 evaluation. + Range (min … max): 307.665 ms … 325.644 ms ┊ GC (min … max): 8.44% … 8.13% + Time (median): 308.448 ms ┊ GC (median): 8.55% + Time (mean ± σ): 310.319 ms ±  4.970 ms ┊ GC (mean ± σ): 8.72% ± 0.86% + + █ █ ▁   ▁                                                      + █▆█▆█▁▆▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆ ▁ + 308 ms Histogram: frequency by time 326 ms < + + Memory estimate: 146.80 MiB, allocs estimate: 3002440. + + + +As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `Threads.nthreads()`, this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` threads for the Julia process. + +### Unload FMU + +After calculating the data, the FMU is unloaded and all unpacked data on disc is removed. + + +```julia +fmiUnload(realFMU) +fmiUnload.(realFMUBatch) +``` + + + + + 1-element Vector{Nothing}: + nothing + + + +### Summary + +In this tutorial it is shown how multi threading with `Folds.jl` can be used to improve the performance for calculating a Batch of FMUs. diff --git a/docs/src/examples/parameterize.md b/docs/src/examples/parameterize.md new file mode 100644 index 00000000..67856f28 --- /dev/null +++ b/docs/src/examples/parameterize.md @@ -0,0 +1,312 @@ +# Manually parameterize an FMU +Tutorial by Johannes Stoljar, Tobias Thummerer + +## License +Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar + +Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. + +## Motivation +This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. + +## Introduction to the example +This example shows how the manually parameterization of an FMU works if very specific adjustments during system initialization is needed. For this purpose, an IO-FMU model is loaded and the various commands for parameterization are shown on the basis of this model. With this example the user shall be guided how to make certain settings at an FMU. Please note, that parameterization of a simulation is possible in a much easier fashion: Using `fmiSimulate`, `fmiSimulateME` or `fmiSimulateCS` together with a parameter dictionary for the keyword `parameters`. + +## Target group +The example is primarily intended for users who work in the field of simulation exchange. The example wants to show how simple it is to use FMUs in Julia. + + +## Other formats +Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/CS_simulate.md) corresponding to the notebook. + + +## Getting started + +### Installation prerequisites +| | Description | Command | Alternative | +|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| +| 1. | Enter Package Manager via | ] | | +| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | +| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | + +## Code section + +To run the example, the previously installed packages must be included. + + +```julia +# imports +using FMI +using FMIZoo +``` + +### Simulation setup + +Next, the start time and end time of the simulation are set. + + +```julia +tStart = 0.0 +tStop = 8.0 +``` + + + + + 8.0 + + + +### Import FMU + +In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. + + +```julia +# we use an FMU from the FMIZoo.jl +pathToFMU = get_model_filename("IO", "Dymola", "2022x") + +myFMU = fmiLoad(pathToFMU) +fmiInfo(myFMU) +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 + + + #################### Begin information for FMU #################### + Model name: IO + FMI-Version: 2.0 + GUID: {ac3b4a99-4908-40f7-89da-2d5c08b3c4ac} + Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 + Generation time: 2022-03-17T07:40:55Z + Var. naming conv.: structured + Event indicators: 4 + Inputs: 3 + 352321536 ["u_real"] + 352321537 ["u_boolean"] + 352321538 ["u_integer"] + Outputs: 3 + 335544320 ["y_real"] + 335544321 ["y_boolean"] + 335544322 ["y_integer"] + States: 0 + Supports Co-Simulation: true + Model identifier: IO + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + Var. com. steps: true + Input interpol.: true + Max order out. der.: 1 + Supports Model-Exchange: true + Model identifier: IO + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + ##################### End information for FMU ##################### + + +### Instantiate and Setup FMU + +Next it is necessary to create an instance of the FMU. This is achieved by the command `fmiInstantiate!()`. + + +```julia +fmiInstantiate!(myFMU; loggingOn=true) +``` + + + + + FMU: IO + InstanceName: [not defined] + Address: Ptr{Nothing} @0x00000000029c12e0 + State: fmi2ComponentStateInstantiated + Logging: true + FMU time: -Inf + FMU states: nothing + + + +In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. + + +```julia +fmiSetupExperiment(myFMU, tStart, tStop) +``` + + + + + 0x00000000 + + + +### Parameterize FMU + +To parameterize an FMU, the FMU must be in the initialization mode, which is reached with the `fmiEnterInitializationMode()` command. + + +```julia +fmiEnterInitializationMode(myFMU) +``` + + + + + 0x00000000 + + + +Within this mode it is then possible to change the different parameters. In this example, for each data type (`real`, `integer`, `boolean` and `string)` a corresponding parameter is selected. At the beginning the initial state of these parameters is displayed with `fmiGet()`. + + +```julia +params = ["p_real", "p_integer", "p_boolean", "p_string"] +fmiGet(myFMU, params) +``` + + + + + 4-element Vector{Any}: + 0.0 + 0 + 0 + "Hello World!" + + + +In the next step, a function is defined that generates a random value for each parameter. For the parameter `p_string` a random number is inserted into the string. All parameters are combined to a vector and output. + + +```julia +function generateRandomNumbers() + rndReal = 100 * rand() + rndInteger = round(Integer, 100 * rand()) + rndBoolean = rand() > 0.5 + rndString = "Random number $(100 * rand())!" + + randValues = [rndReal, rndInteger, rndBoolean, rndString] + println(randValues) + return randValues +end +``` + + + + + generateRandomNumbers (generic function with 1 method) + + + +The previously defined function is called and the results are displayed in the console. + + +```julia +paramsVal = generateRandomNumbers(); +``` + + Any[27.27027116078753, 50, true, "Random number 83.09640957659121!"] + + +#### First variant + +With this variant it is quickly possible to set all parameters at once. Even different data types can be set with only one command. The command `fmiSet()` selects itself which function is chosen for which data type. After setting the parameters, it is checked whether the corresponding parameters were set correctly. For this the function `fmiGet()` is used as above and afterwards with the macro `@assert` also tested whether the correct values are set. + + +```julia +fmiSet(myFMU, params, paramsVal) +values = fmiGet(myFMU, params) +print(values) + +@assert paramsVal == values +``` + + Any[27.27027116078753, 50, 1, "Random number 83.09640957659121!"] + +#### Second variant + +To make sure that the functions work it is necessary to generate random numbers again. As shown already, we call the defined function `generateRandomNumbers()` and output the values. + + +```julia +rndReal, rndInteger, rndBoolean, rndString = generateRandomNumbers(); +``` + + Any[54.98169316988619, 76, true, "Random number 39.54384075977397!"] + + +In the second variant, the value for each data type is set separately by the corresponding command. By this variant one has the maximum control and can be sure that also the correct data type is set. To illustrate the functionality of the parameterization with the separate functions, the corresponding get function is also called separately for each data type: +* `fmiSetReal()` <---> `fmiGetReal()` +* `fmiSetInteger()` <---> `fmiGetInteger()` +* `fmiSetBoolean()` <---> `fmiGetBoolean()` +* `fmiSetString()` <---> `fmiGetString()`. + + +```julia +fmiSetReal(myFMU, "p_real", rndReal) +display("$rndReal == $(fmiGetReal(myFMU, "p_real"))") + +fmiSetInteger(myFMU, "p_integer", rndInteger) +display("$rndInteger == $(fmiGetInteger(myFMU, "p_integer"))") + +fmiSetBoolean(myFMU, "p_boolean", rndBoolean) +display("$rndBoolean == $(fmiGetBoolean(myFMU, "p_boolean"))") + +fmiSetString(myFMU, "p_string", rndString) +display("$rndString == $(fmiGetString(myFMU, "p_string"))") +``` + + + "54.98169316988619 == 54.98169316988619" + + + + "76 == 76" + + + + "true == 1" + + + + "Random number 39.54384075977397! == Random number 39.54384075977397!" + + +After seeing that both variants set the parameters correctly, the initialization mode is terminated with the function `fmiExitInitializationMode()`. + + +```julia +fmiExitInitializationMode(myFMU) +``` + + + + + 0x00000000 + + + +From here on, you may want to simulate the FMU. Please note, that with the default `executionConfig`, it is necessary to prevent a new instantiation using the keyword `instantiate=false`. Otherwise, a new instance is allocated for the simulation-call and the parameters set for the previous instance are not transfered. + +Example: +`fmiSimulate(...; instantiate=false, ...)` + +### Unload FMU + +The FMU will be unloaded and all unpacked data on disc will be removed. + + +```julia +fmiUnload(myFMU) +``` + +### Summary + +Based on this tutorial it can be seen that there are two different variants to set and get parameters.These examples should make it clear to the user how parameters can also be set with different data types. diff --git a/docs/src/examples/simulate.md b/docs/src/examples/simulate.md new file mode 100644 index 00000000..b208de41 --- /dev/null +++ b/docs/src/examples/simulate.md @@ -0,0 +1,245 @@ +# Simulate an FMU in different modes +Tutorial by Johannes Stoljar, Tobias Thummerer + +## License +Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar + +Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. + +## Motivation +This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. + +## Introduction to the example +In this example we want to show how fast and easy the simulation for an FMU is. For this purpose, the FMU is simulated in co-simulation mode and in model-exchange mode. After the FMU has been simulated, the simulation results are displayed in a graph. The graphs of the different modes are compared with each other. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. + +![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) + + +## Target group +The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. + + +## Other formats +Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/simulate.md) corresponding to the notebook. + + +## Getting started + +### Installation prerequisites +| | Description | Command | Alternative | +|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| +| 1. | Enter Package Manager via | ] | | +| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | +| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | +| 4. | Install Plots via | add Plots | | + +## Code section + +To run the example, the previously installed packages must be included. + + +```julia +# imports +using FMI +using FMIZoo +using Plots +``` + +### Simulation setup + +Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. + + +```julia +tStart = 0.0 +tStep = 0.01 +tStop = 8.0 +tSave = tStart:tStep:tStop +``` + + + + + 0.0:0.01:8.0 + + + +### Import FMU + +In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. + + +```julia +# we use an FMU from the FMIZoo.jl +pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x") + +myFMU = fmiLoad(pathToFMU) +# fmiLoad("path/to/myFMU.fmu"; unpackPath = "path/to/unpacked/fmu/") + +fmiInfo(myFMU) +``` + + ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 + ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources` + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 + ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. + └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 + + + #################### Begin information for FMU #################### + Model name: SpringFrictionPendulum1D + FMI-Version: 2.0 + GUID: {df491d8d-0598-4495-913e-5b025e54d7f2} + Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 + Generation time: 2022-03-03T15:09:18Z + Var. naming conv.: structured + Event indicators: 24 + Inputs: 0 + Outputs: 0 + States: 2 + 33554432 ["mass.s"] + 33554433 ["mass.v", "mass.v_relfric"] + Supports Co-Simulation: true + Model identifier: SpringFrictionPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + Var. com. steps: true + Input interpol.: true + Max order out. der.: 1 + Supports Model-Exchange: true + Model identifier: SpringFrictionPendulum1D + Get/Set State: true + Serialize State: true + Dir. Derivatives: true + ##################### End information for FMU ##################### + + +### Simulate FMU + +In the following, the FMU is simulated in the two different simulation modes. + +#### Simulate as Co-Simulation + +In the next steps the recorded values are defined. The first state is the position of the mass and the second state is the velocity. In the function `fmiSimulateCS()` the FMU is simulated in co-simulation mode (CS) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time and the recorded variables are specified. + + +```julia +vrs = ["mass.s", "mass.v"] + +dataCS = fmiSimulateCS(myFMU, tStart, tStop; recordValues=vrs, saveat=tSave) +``` + + + + + Model name: + SpringFrictionPendulum1D + Success: + true + Values [801]: + 0.0 (0.5, 0.0) + 0.01 (0.5002235448486548, 0.042692491939260585) + 0.02 (0.5008715291319449, 0.08568000508550636) + 0.03 (0.5019478597521578, 0.12892136998736314) + 0.04 (0.5034570452098334, 0.17232325681284336) + 0.05 (0.5053993458877354, 0.2158440857658765) + 0.06 (0.5077764240578201, 0.259420181133082) + 0.07 (0.5105886522837868, 0.30295578207463486) + 0.08 (0.5138351439717114, 0.3464184707972189) + ... + 8.0 (1.071367253976742, -1.000814138594347e-10) + Events [0]: + + + + +#### Simulate as Model-Exchange + +In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time are specified. In contrast to the co-simulation, the values to be stored are not specified here, since the states and events of the FMU are always output as well. The identifiers given above just correspond to the states of the FMU. + + +```julia +dataME = fmiSimulateME(myFMU, tStart, tStop; saveat=tSave) +``` + + Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09 + + + + + + Model name: + SpringFrictionPendulum1D + Success: + true + States [801]: + 0.0 [0.5, 0.0] + 0.01 [0.5002131418344649, 0.042689450666241] + 0.02 [0.5008548874805565, 0.08570846215523381] + 0.03 [0.5019281653120716, 0.12898389312495082] + 0.04 [0.5034351805057593, 0.17244393475170294] + 0.05 [0.5053774287967188, 0.2160182432854046] + 0.06 [0.5077556967622916, 0.25963796675862466] + 0.07 [0.5105701003205937, 0.3032358690888718] + 0.08 [0.5138201049458624, 0.34674641820324037] + ... + 8.0 [1.0668213438183276, -1.0000099359121942e-10] + Events [6]: + State-Event #11 @ 0.0s + State-Event #11 @ 0.9939s + State-Event #19 @ 1.9881s + State-Event #11 @ 2.9829s + State-Event #19 @ 3.9787s + State-Event #11 @ 4.9768s + + + + +### Plotting FMU + +After the simulation is finished the results of the FMU for the co-simulation and model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time. + + +```julia +fmiPlot(dataCS) +``` + + + + + +![svg](simulate_files/simulate_12_0.svg) + + + + + +```julia +fmiPlot(dataME) +``` + + + + + +![svg](simulate_files/simulate_13_0.svg) + + + + +From both graphs it can be seen that the simulation calculates exactly the same results. + +### Unload FMU + +After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. + + +```julia +fmiUnload(myFMU) +``` + +### Summary + +Based on this tutorial it can be seen that simulating in the different mode is very easy, and it only takes a few commands to simulate the FMU. diff --git a/docs/src/examples/simulate_files/simulate_12_0.svg b/docs/src/examples/simulate_files/simulate_12_0.svg new file mode 100644 index 00000000..6f603526 --- /dev/null +++ b/docs/src/examples/simulate_files/simulate_12_0.svg @@ -0,0 +1,274 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/examples/simulate_files/simulate_13_0.svg b/docs/src/examples/simulate_files/simulate_13_0.svg new file mode 100644 index 00000000..2dc08e6e --- /dev/null +++ b/docs/src/examples/simulate_files/simulate_13_0.svg @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/manipulation.ipynb b/example/manipulation.ipynb new file mode 100644 index 00000000..eb98a208 --- /dev/null +++ b/example/manipulation.ipynb @@ -0,0 +1,839 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Manipulate a function\n", + "Tutorial by Johannes Stoljar, Tobias Thummerer\n", + "\n", + "## License\n", + "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", + "\n", + "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", + "\n", + "## Motivation\n", + "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", + "\n", + "## Introduction to the example\n", + "This example shows how to overwrite a library function with an own function. For this the FMU model is simulated first without changes. Then the function `fmi2GetReal()` is overwritten and simulated again. Both simulations are displayed in a graph to show the change caused by overwriting the function. The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", + "\n", + "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", + "\n", + "\n", + "## Target group\n", + "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", + "\n", + "\n", + "## Other formats\n", + "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/manipulation.md) corresponding to the notebook. \n", + "\n", + "\n", + "## Getting started\n", + "\n", + "### Installation prerequisites\n", + "| | Description | Command | Alternative | \n", + "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", + "| 1. | Enter Package Manager via | ] | |\n", + "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", + "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", + "| 4. | Install FMICore via | add FMICore | add \" https://github.com/ThummeTo/FMICore.jl \" |\n", + "| 5. | Install Plots via | add Plots | |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code section\n", + "\n", + "To run the example, the previously installed packages must be included. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:15:09.601000Z", + "iopub.status.busy": "2022-06-01T15:15:08.923000Z", + "iopub.status.idle": "2022-06-01T15:15:32.386000Z", + "shell.execute_reply": "2022-06-01T15:15:32.310000Z" + }, + "scrolled": false + }, + "outputs": [], + "source": [ + "# imports\n", + "using FMI\n", + "using FMIZoo\n", + "using FMICore\n", + "using Plots" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulation setup\n", + "\n", + "Next, the start time and end time of the simulation are set." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:15:41.170000Z", + "iopub.status.busy": "2022-06-01T15:15:32.388000Z", + "iopub.status.idle": "2022-06-01T15:15:41.848000Z", + "shell.execute_reply": "2022-06-01T15:15:41.848000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "8.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tStart = 0.0\n", + "tStop = 8.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import FMU\n", + "\n", + "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:15:41.877000Z", + "iopub.status.busy": "2022-06-01T15:15:41.877000Z", + "iopub.status.idle": "2022-06-01T15:15:46.248000Z", + "shell.execute_reply": "2022-06-01T15:15:46.248000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#################### Begin information for FMU ####################\n", + "\tModel name:\t\t\tSpringFrictionPendulum1D\n", + "\tFMI-Version:\t\t\t2.0\n", + "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", + "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", + "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", + "\tVar. naming conv.:\t\tstructured\n", + "\tEvent indicators:\t\t24\n", + "\tInputs:\t\t\t\t0\n", + "\tOutputs:\t\t\t0\n", + "\tStates:\t\t\t\t2\n", + "\t\t33554432 [\"mass.s\"]\n", + "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", + "\tSupports Co-Simulation:\t\ttrue\n", + "\t\tModel identifier:\tSpringFrictionPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "\t\tVar. com. steps:\ttrue\n", + "\t\tInput interpol.:\ttrue\n", + "\t\tMax order out. der.:\t1\n", + "\tSupports Model-Exchange:\ttrue\n", + "\t\tModel identifier:\tSpringFrictionPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "##################### End information for FMU #####################\n" + ] + } + ], + "source": [ + "# we use an FMU from the FMIZoo.jl\n", + "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", + "\n", + "myFMU = fmiLoad(pathToFMU)\n", + "\n", + "fmiInfo(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulate FMU\n", + "\n", + "In the next steps the recorded value is defined. The recorded value is the position of the mass. In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size. In addition, the start and end time and the recorded variables are specified." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:15:46.250000Z", + "iopub.status.busy": "2022-06-01T15:15:46.250000Z", + "iopub.status.idle": "2022-06-01T15:16:04.451000Z", + "shell.execute_reply": "2022-06-01T15:16:04.450000Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10\u001b[39m\n" + ] + }, + { + "data": { + "text/plain": [ + "Model name:\n", + "\tSpringFrictionPendulum1D\n", + "Success:\n", + "\ttrue\n", + "States [110]:\n", + "\t0.0\t[0.5, 0.0]\n", + "\t2.3529411764719727e-11\t[0.5, 1.0e-10]\n", + "\t1.0000023529411766e-5\t[0.5000000002125017, 4.250030186348503e-5]\n", + "\t0.00011000002352941177\t[0.5000000257134062, 0.0004675245102952289]\n", + "\t0.0011100000235294118\t[0.5000026191281834, 0.004719970360497647]\n", + "\t0.011110000023529413\t[0.5002631686645611, 0.047449647283752144]\n", + "\t0.03982466736770743\t[0.5034050123596227, 0.17168075110950387]\n", + "\t0.09972054285078226\t[0.5215006197560228, 0.43204954153497455]\n", + "\t0.16481836271111422\t[0.5585747156842935, 0.703758265932321]\n", + "\t...\n", + "\t8.0\t[1.0668213438183276, -1.0000099359121942e-10]\n", + "Values [110]:\n", + "\t0.0\t(0.5,)\n", + "\t2.3529411764719727e-11\t(0.5,)\n", + "\t1.0000023529411766e-5\t(0.5000000002125017,)\n", + "\t0.00011000002352941177\t(0.5000000257134062,)\n", + "\t0.0011100000235294118\t(0.5000026191281834,)\n", + "\t0.011110000023529413\t(0.5002631686645611,)\n", + "\t0.03982466736770743\t(0.5034050123596227,)\n", + "\t0.09972054285078226\t(0.5215006197560228,)\n", + "\t0.16481836271111422\t(0.5585747156842935,)\n", + "\t...\n", + "\t8.0\t(1.0668213438183276,)\n", + "Events [6]:\n", + "\tState-Event #11 @ 0.0s\n", + "\tState-Event #11 @ 0.9939s\n", + "\tState-Event #19 @ 1.9881s\n", + "\tState-Event #11 @ 2.9829s\n", + "\tState-Event #19 @ 3.9787s\n", + "\tState-Event #11 @ 4.9768s\n" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vrs = [\"mass.s\"]\n", + "\n", + "simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plotting FMU\n", + "\n", + "After the simulation is finished, the result of the FMU for the model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:16:04.454000Z", + "iopub.status.busy": "2022-06-01T15:16:04.454000Z", + "iopub.status.idle": "2022-06-01T15:16:23.184000Z", + "shell.execute_reply": "2022-06-01T15:16:23.184000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig = fmiPlot(simData, states=false)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Override Function\n", + "\n", + "After overwriting a function, the previous one is no longer accessible. The original function `fmi2GetReal()` is cached by storing the address of the pointer. The addresses of the pointers are kept in the FMU and are thus accessible." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:16:23.189000Z", + "iopub.status.busy": "2022-06-01T15:16:23.188000Z", + "iopub.status.idle": "2022-06-01T15:16:23.780000Z", + "shell.execute_reply": "2022-06-01T15:16:23.780000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Ptr{Nothing} @0x00007f52e9530faf" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function\n", + "originalGetReal = myFMU.cGetReal" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To overwrite the function `fmi2GetReal!()`, the function header of the new custom function must be identical to the previous one. The function header looks like `fmi2GetReal!(cfunc::Ptr{Nothing}, c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})::fmi2Status`. The information how the FMI2 function are structured can be seen from [FMICore.jl](https://github.com/ThummeTo/FMICore.jl/blob/main/src/FMI2_c.jl#L718) or the FMI2.0.3-specification.\n", + "\n", + "In the new implementation the original function is called by the previously stored pointer. Next there is a special handling if `value` is a pointer to an array. In this case the pointer is treated as an array, so that the entries are accessible. Otherwise, each value in `value` is multiplied by two. Finally, the original state of the original function is output." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:16:23.784000Z", + "iopub.status.busy": "2022-06-01T15:16:23.784000Z", + "iopub.status.idle": "2022-06-01T15:16:24.562000Z", + "shell.execute_reply": "2022-06-01T15:16:24.562000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "myGetReal! (generic function with 1 method)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, \n", + " nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})\n", + " # first, we do what the original function does\n", + " status = fmi2GetReal!(originalGetReal, c, vr, nvr, value)\n", + "\n", + " # if we have a pointer to an array, we must interprete it as array to access elements\n", + " if isa(value, Ptr{fmi2Real})\n", + " value = unsafe_wrap(Array{fmi2Real}, value, nvr, own=false)\n", + " end\n", + "\n", + " # now, we multiply every value by two (just for fun!)\n", + " for i in 1:nvr \n", + " value[i] *= 2.0 \n", + " end \n", + "\n", + " # return the original status\n", + " return status\n", + "end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the next command the original function is overwritten with the new defined function, for which the command `fmiSetFctGetReal()` is called." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:16:24.566000Z", + "iopub.status.busy": "2022-06-01T15:16:24.565000Z", + "iopub.status.idle": "2022-06-01T15:16:24.578000Z", + "shell.execute_reply": "2022-06-01T15:16:24.578000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Ptr{Nothing} @0x00007f533e325fc0" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# no we overwrite the original function\n", + "fmiSetFctGetReal(myFMU, myGetReal!)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulate and Plot FMU with modified function\n", + "\n", + "As before, the identical command is called here for simulation. This is also a model exchange simulation. Immediately afterwards, the results are added to the previous graph as a dashed line." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:16:24.581000Z", + "iopub.status.busy": "2022-06-01T15:16:24.581000Z", + "iopub.status.idle": "2022-06-01T15:16:24.963000Z", + "shell.execute_reply": "2022-06-01T15:16:24.963000Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)\n", + "fmiPlot!(fig, simData; states=false, style=:dash)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As expected by overwriting the function, all values are doubled." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unload FMU\n", + "\n", + "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:16:24.967000Z", + "iopub.status.busy": "2022-06-01T15:16:24.967000Z", + "iopub.status.idle": "2022-06-01T15:16:25.011000Z", + "shell.execute_reply": "2022-06-01T15:16:25.011000Z" + } + }, + "outputs": [], + "source": [ + "fmiUnload(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary\n", + "\n", + "In this tutorial it is shown how an existing function of the library can be replaced by an own implementation. Through this possibility, there are almost no limits for the user, whereby the user can customize the function to his liking." + ] + } + ], + "metadata": { + "interpreter": { + "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" + }, + "jupytext": { + "cell_metadata_filter": "-all", + "comment_magics": "false", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "Julia 1.6.6", + "language": "julia", + "name": "julia-1.6" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.6.6" + }, + "nteract": { + "version": "0.28.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example/modelica_conference_2021.ipynb b/example/modelica_conference_2021.ipynb new file mode 100644 index 00000000..7210b368 --- /dev/null +++ b/example/modelica_conference_2021.ipynb @@ -0,0 +1,560 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Advanced Simulation of an FMU\n", + "Tutorial by Johannes Stoljar, Tobias Thummerer\n", + "\n", + "## License\n", + "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", + "\n", + "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", + "\n", + "## Motivation\n", + "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", + "\n", + "## Introduction to the example\n", + "In this example we would like to show that besides the simple simulation of an FMU there is also a more advanced version of the simulation. The advantage of the more advanced variant is that there are more possibilities to intervene in the simulation to make changes. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", + "\n", + "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", + "\n", + "\n", + "## Target group\n", + "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", + "\n", + "\n", + "## Other formats\n", + "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/modelica_conference_2021.md) corresponding to the notebook. \n", + "\n", + "\n", + "## Getting started\n", + "\n", + "### Installation prerequisites\n", + "| | Description | Command | Alternative | \n", + "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", + "| 1. | Enter Package Manager via | ] | |\n", + "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", + "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", + "| 4. | Install Plots via | add Plots | |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code section\n", + "\n", + "To run the example, the previously installed packages must be included. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:16:34.235000Z", + "iopub.status.busy": "2022-06-01T15:16:33.558000Z", + "iopub.status.idle": "2022-06-01T15:16:56.948000Z", + "shell.execute_reply": "2022-06-01T15:16:56.869000Z" + }, + "scrolled": false + }, + "outputs": [], + "source": [ + "# imports\n", + "using FMI\n", + "using FMIZoo\n", + "using Plots" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulation setup\n", + "\n", + "Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:05.805000Z", + "iopub.status.busy": "2022-06-01T15:16:56.951000Z", + "iopub.status.idle": "2022-06-01T15:17:06.600000Z", + "shell.execute_reply": "2022-06-01T15:17:06.600000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0:0.1:8.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tStart = 0.0\n", + "tStep = 0.1\n", + "tStop = 8.0\n", + "tSave = tStart:tStep:tStop" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simple FMU Simulation\n", + "\n", + "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:06.604000Z", + "iopub.status.busy": "2022-06-01T15:17:06.604000Z", + "iopub.status.idle": "2022-06-01T15:17:10.951000Z", + "shell.execute_reply": "2022-06-01T15:17:10.951000Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#################### Begin information for FMU ####################\n", + "\tModel name:\t\t\tSpringFrictionPendulum1D\n", + "\tFMI-Version:\t\t\t2.0\n", + "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", + "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", + "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", + "\tVar. naming conv.:\t\tstructured\n", + "\tEvent indicators:\t\t24\n", + "\tInputs:\t\t\t\t0\n", + "\tOutputs:\t\t\t0\n", + "\tStates:\t\t\t\t2\n", + "\t\t33554432 [\"mass.s\"]\n", + "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", + "\tSupports Co-Simulation:\t\ttrue\n", + "\t\tModel identifier:\tSpringFrictionPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "\t\tVar. com. steps:\ttrue\n", + "\t\tInput interpol.:\ttrue\n", + "\t\tMax order out. der.:\t1\n", + "\tSupports Model-Exchange:\ttrue\n", + "\t\tModel identifier:\tSpringFrictionPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "##################### End information for FMU #####################\n" + ] + } + ], + "source": [ + "# we use an FMU from the FMIZoo.jl\n", + "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", + "\n", + "myFMU = fmiLoad(pathToFMU)\n", + "fmiInfo(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the next commands the FMU is simulated, for which the start and end time and recorded variables are declared. Afterwards the simulation result is shown in a graph. In the plot for the FMU, it can be seen that the oscillation keeps decreasing due to the effect of friction. If one simulates long enough, the oscillation comes to a standstill after a certain time." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:10.954000Z", + "iopub.status.busy": "2022-06-01T15:17:10.953000Z", + "iopub.status.idle": "2022-06-01T15:17:37.913000Z", + "shell.execute_reply": "2022-06-01T15:17:37.913000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "simData = fmiSimulate(myFMU, tStart, tStop; recordValues=[\"mass.s\"], saveat=tSave)\n", + "fmiPlot(simData)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:37.918000Z", + "iopub.status.busy": "2022-06-01T15:17:37.917000Z", + "iopub.status.idle": "2022-06-01T15:17:37.960000Z", + "shell.execute_reply": "2022-06-01T15:17:37.960000Z" + } + }, + "outputs": [], + "source": [ + "fmiUnload(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Advanced FMU Simulation\n", + "\n", + "In the following type of simulation a more advanced variant is presented, which allows intervening more in the simulation process. Analogous to the simple variant, an FMU model must be loaded." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:37.962000Z", + "iopub.status.busy": "2022-06-01T15:17:37.962000Z", + "iopub.status.idle": "2022-06-01T15:17:38.024000Z", + "shell.execute_reply": "2022-06-01T15:17:38.024000Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" + ] + } + ], + "source": [ + "myFMU = fmiLoad(pathToFMU);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:38.028000Z", + "iopub.status.busy": "2022-06-01T15:17:38.027000Z", + "iopub.status.idle": "2022-06-01T15:17:38.349000Z", + "shell.execute_reply": "2022-06-01T15:17:38.349000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "FMU: SpringFrictionPendulum1D\n", + "InstanceName: [not defined]\n", + "Address: Ptr{Nothing} @0x00000000064853f0\n", + "State: fmi2ComponentStateInstantiated\n", + "Logging: false\n", + "FMU time: -Inf\n", + "FMU states: nothing" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "instanceFMU = fmiInstantiate!(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. Next, the FMU is initialized by the calls of `fmiEnterInitializationMode()` and `fmiExitInitializationMode()`. It would also be possible to set initial states for the FMU between these two commands. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:38.353000Z", + "iopub.status.busy": "2022-06-01T15:17:38.352000Z", + "iopub.status.idle": "2022-06-01T15:17:38.617000Z", + "shell.execute_reply": "2022-06-01T15:17:38.617000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0x00000000" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiSetupExperiment(instanceFMU, tStart, tStop)\n", + "fmiEnterInitializationMode(instanceFMU)\n", + "# set initial model states\n", + "fmiExitInitializationMode(instanceFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The actual simulation loop is shown in the following block. Here a simulation step `fmiDoStep()` with the fixed step size `tStep` is executed. As indicated in the code by the comments, the input values and output values of the FMU could be changed in the simulation loop as desired, whereby the higher possibility of adjustments arises." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:38.620000Z", + "iopub.status.busy": "2022-06-01T15:17:38.620000Z", + "iopub.status.idle": "2022-06-01T15:17:38.657000Z", + "shell.execute_reply": "2022-06-01T15:17:38.657000Z" + } + }, + "outputs": [], + "source": [ + "for t in tSave\n", + " # set model inputs \n", + " # ...\n", + " fmiDoStep(instanceFMU, tStep)\n", + " # get model outputs\n", + " # ...\n", + "end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The instantiated FMU must be terminated and then the memory area for the instance can also be deallocated. The last step is to unload the FMU to remove all unpacked data on disc. " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:38.660000Z", + "iopub.status.busy": "2022-06-01T15:17:38.660000Z", + "iopub.status.idle": "2022-06-01T15:17:38.668000Z", + "shell.execute_reply": "2022-06-01T15:17:38.667000Z" + } + }, + "outputs": [], + "source": [ + "fmiTerminate(instanceFMU)\n", + "fmiFreeInstance!(instanceFMU)\n", + "fmiUnload(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary\n", + "\n", + "The tutorial has shown that besides the usual simple variant of simulating an FMU, there is another way to make more adjustments." + ] + } + ], + "metadata": { + "interpreter": { + "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" + }, + "jupytext": { + "cell_metadata_filter": "-all", + "comment_magics": "false", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "Julia 1.6.6", + "language": "julia", + "name": "julia-1.6" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.6.6" + }, + "nteract": { + "version": "0.28.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example/multiple_instances.ipynb b/example/multiple_instances.ipynb new file mode 100644 index 00000000..93f49f93 --- /dev/null +++ b/example/multiple_instances.ipynb @@ -0,0 +1,3081 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multiple Instances of an FMU\n", + "Tutorial by Johannes Stoljar, Tobias Thummerer\n", + "\n", + "## License\n", + "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", + "\n", + "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", + "\n", + "## Motivation\n", + "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", + "\n", + "## Introduction to the example\n", + "In this example we want to show that it is possible to create different instances of an FMU. The different instances can then be used to run independent simulations. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum without friction. The object-orientated structure of the *SpringPendulum1D* can be seen in the following graphic.\n", + "\n", + "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringPendulum1D.svg?raw=true) \n", + "\n", + "\n", + "## Target group\n", + "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", + "\n", + "\n", + "## Other formats\n", + "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/multiple_instances.md) corresponding to the notebook. \n", + "\n", + "\n", + "## Getting started\n", + "\n", + "### Installation prerequisites\n", + "| | Description | Command | Alternative | \n", + "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", + "| 1. | Enter Package Manager via | ] | |\n", + "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", + "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", + "| 4. | Install Plots via | add Plots | |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code section\n", + "\n", + "To run the example, the previously installed packages must be included. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:17:48.035000Z", + "iopub.status.busy": "2022-06-01T15:17:47.343000Z", + "iopub.status.idle": "2022-06-01T15:18:10.300000Z", + "shell.execute_reply": "2022-06-01T15:18:10.226000Z" + }, + "scrolled": false + }, + "outputs": [], + "source": [ + "# imports\n", + "using FMI\n", + "using FMIZoo\n", + "using Plots" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulation setup\n", + "\n", + "Next, the start time and end time of the simulation are set. Finally, the recorded values are specified to store the results of the simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:19.079000Z", + "iopub.status.busy": "2022-06-01T15:18:10.303000Z", + "iopub.status.idle": "2022-06-01T15:18:21.932000Z", + "shell.execute_reply": "2022-06-01T15:18:21.932000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1-element Vector{String}:\n", + " \"mass.s\"" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tStart = 0.0\n", + "tStop = 8.0\n", + "\n", + "vrs = [\"mass.s\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import FMU\n", + "\n", + "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:21.935000Z", + "iopub.status.busy": "2022-06-01T15:18:21.935000Z", + "iopub.status.idle": "2022-06-01T15:18:26.345000Z", + "shell.execute_reply": "2022-06-01T15:18:26.345000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#################### Begin information for FMU ####################\n", + "\tModel name:\t\t\tSpringPendulum1D\n", + "\tFMI-Version:\t\t\t2.0\n", + "\tGUID:\t\t\t\t{a3e886fa-675c-4308-8e91-3490e598ba11}\n", + "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", + "\tGeneration time:\t\t2022-03-03T15:08:57Z\n", + "\tVar. naming conv.:\t\tstructured\n", + "\tEvent indicators:\t\t0\n", + "\tInputs:\t\t\t\t0\n", + "\tOutputs:\t\t\t0\n", + "\tStates:\t\t\t\t2\n", + "\t\t33554432 [\"mass.s\"]\n", + "\t\t33554433 [\"mass.v\"]\n", + "\tSupports Co-Simulation:\t\ttrue\n", + "\t\tModel identifier:\tSpringPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "\t\tVar. com. steps:\ttrue\n", + "\t\tInput interpol.:\ttrue\n", + "\t\tMax order out. der.:\t1\n", + "\tSupports Model-Exchange:\ttrue\n", + "\t\tModel identifier:\tSpringPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "##################### End information for FMU #####################\n" + ] + } + ], + "source": [ + "# we use an FMU from the FMIZoo.jl\n", + "pathToFMU = get_model_filename(\"SpringPendulum1D\", \"Dymola\", \"2022x\")\n", + "\n", + "myFMU = fmiLoad(pathToFMU)\n", + "fmiInfo(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### First Instance\n", + "\n", + "To create an instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:26.348000Z", + "iopub.status.busy": "2022-06-01T15:18:26.348000Z", + "iopub.status.idle": "2022-06-01T15:18:26.776000Z", + "shell.execute_reply": "2022-06-01T15:18:26.776000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FMU: SpringPendulum1D\n", + "InstanceName: [not defined]\n", + "Address: Ptr{Nothing} @0x0000000003954580\n", + "State: fmi2ComponentStateInstantiated\n", + "Logging: false\n", + "FMU time: -Inf\n", + "FMU states: nothing\n" + ] + } + ], + "source": [ + "comp1 = fmiInstantiate!(myFMU; loggingOn=true)\n", + "comp1Address= comp1.compAddr\n", + "println(comp1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $10.0 \\frac{N}{m}$ and for the position of the mass `mass.s` a value of $1.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:26.779000Z", + "iopub.status.busy": "2022-06-01T15:18:26.779000Z", + "iopub.status.idle": "2022-06-01T15:18:52.116000Z", + "shell.execute_reply": "2022-06-01T15:18:52.116000Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "param1 = Dict(\"spring.c\"=>10.0, \"mass_s0\"=>1.0)\n", + "data1 = fmiSimulate(comp1, tStart, tStop; parameters=param1, recordValues=vrs, instantiate=false)\n", + "fig = fmiPlot(data1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For control, you can compare again the address of the instance to the previous address, and it should be the same address. As soon as this is not the case an error would be thrown by the macro `@assert`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:52.122000Z", + "iopub.status.busy": "2022-06-01T15:18:52.122000Z", + "iopub.status.idle": "2022-06-01T15:18:52.160000Z", + "shell.execute_reply": "2022-06-01T15:18:52.160000Z" + } + }, + "outputs": [], + "source": [ + "@assert comp1.compAddr === comp1Address" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Second Instance\n", + "\n", + "To create a second instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:52.163000Z", + "iopub.status.busy": "2022-06-01T15:18:52.163000Z", + "iopub.status.idle": "2022-06-01T15:18:52.166000Z", + "shell.execute_reply": "2022-06-01T15:18:52.166000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FMU: SpringPendulum1D\n", + "InstanceName: [not defined]\n", + "Address: Ptr{Nothing} @0x000000000529d440\n", + "State: fmi2ComponentStateInstantiated\n", + "Logging: false\n", + "FMU time: -Inf\n", + "FMU states: nothing\n" + ] + } + ], + "source": [ + "comp2 = fmiInstantiate!(myFMU; loggingOn=true)\n", + "comp2Address= comp2.compAddr\n", + "println(comp2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The addresses of the instantiated FMUs must differ, and you can see that in the comparison below." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:52.168000Z", + "iopub.status.busy": "2022-06-01T15:18:52.168000Z", + "iopub.status.idle": "2022-06-01T15:18:52.169000Z", + "shell.execute_reply": "2022-06-01T15:18:52.169000Z" + } + }, + "outputs": [], + "source": [ + "@assert comp1Address !== comp2Address" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Again, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $1.0 \\frac{N}{m}$ and for the position of the mass `mass.s` a value of $2.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:52.171000Z", + "iopub.status.busy": "2022-06-01T15:18:52.171000Z", + "iopub.status.idle": "2022-06-01T15:18:52.280000Z", + "shell.execute_reply": "2022-06-01T15:18:52.280000Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "param2 = Dict(\"spring.c\"=>1.0, \"mass.s\"=>2.0)\n", + "data2 = fmiSimulateCS(comp2, tStart, tStop; parameters=param2, recordValues=vrs, instantiate=false)\n", + "fmiPlot!(fig, data2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For control, you can compare again the address of the instance `comp2` to the previous address `comp2Address` and it should be the same address." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:52.288000Z", + "iopub.status.busy": "2022-06-01T15:18:52.288000Z", + "iopub.status.idle": "2022-06-01T15:18:52.289000Z", + "shell.execute_reply": "2022-06-01T15:18:52.289000Z" + } + }, + "outputs": [], + "source": [ + "@assert comp2.compAddr === comp2Address" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unload FMU\n", + "\n", + "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:18:52.291000Z", + "iopub.status.busy": "2022-06-01T15:18:52.291000Z", + "iopub.status.idle": "2022-06-01T15:18:52.333000Z", + "shell.execute_reply": "2022-06-01T15:18:52.333000Z" + } + }, + "outputs": [], + "source": [ + "fmiUnload(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary\n", + "\n", + "Based on the example it can be seen that it is possible to create different instances of an FMU. The different instances can then be used to perform different simulations." + ] + } + ], + "metadata": { + "interpreter": { + "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" + }, + "jupytext": { + "cell_metadata_filter": "-all", + "comment_magics": "false", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "Julia 1.6.6", + "language": "julia", + "name": "julia-1.6" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.6.6" + }, + "nteract": { + "version": "0.28.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example/multiprocessing.ipynb b/example/multiprocessing.ipynb new file mode 100644 index 00000000..736d07d5 --- /dev/null +++ b/example/multiprocessing.ipynb @@ -0,0 +1,516 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multiprocessing\n", + "Tutorial by Jonas Wilfert, Tobias Thummerer\n", + "\n", + "## License\n", + "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert\n", + "\n", + "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", + "\n", + "## Motivation\n", + "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", + "\n", + "## Introduction to the example\n", + "This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings.\n", + "Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multiprocessing**, check `multithreading.ipynb` for multithreading.\n", + "Advantage of multithreading is a lower communication overhead as well as lower RAM usage.\n", + "However in some cases multiprocessing can be faster as the garbage collector is not shared.\n", + "\n", + "\n", + "The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", + "\n", + "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", + "\n", + "\n", + "## Target group\n", + "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", + "\n", + "\n", + "## Other formats\n", + "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/distributed.md) corresponding to the notebook. \n", + "\n", + "\n", + "## Getting started\n", + "\n", + "### Installation prerequisites\n", + "| | Description | Command | Alternative | \n", + "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", + "| 1. | Enter Package Manager via | ] | |\n", + "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", + "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", + "| 4. | Install FMICore via | add FMICore | add \" https://github.com/ThummeTo/FMICore.jl \" |\n", + "| 5. | Install BenchmarkTools via | add BenchmarkTools | |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code section\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding your desired amount of processes:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:20:33.662000Z", + "iopub.status.busy": "2022-06-18T14:20:32.980000Z", + "iopub.status.idle": "2022-06-18T14:20:45.287000Z", + "shell.execute_reply": "2022-06-18T14:20:45.259000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4-element Vector{Int64}:\n", + " 2\n", + " 3\n", + " 4\n", + " 5" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "using Distributed\n", + "n_procs = 4\n", + "addprocs(n_procs; exeflags=`--project=$(Base.active_project()) --threads=auto`, restrict=false)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run the example, the previously installed packages must be included. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:20:45.290000Z", + "iopub.status.busy": "2022-06-18T14:20:45.289000Z", + "iopub.status.idle": "2022-06-18T14:21:31.517000Z", + "shell.execute_reply": "2022-06-18T14:21:31.517000Z" + } + }, + "outputs": [], + "source": [ + "# imports\n", + "@everywhere using FMI\n", + "@everywhere using FMIZoo\n", + "@everywhere using BenchmarkTools" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Checking that we workers have been correctly initialized:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:21:31.917000Z", + "iopub.status.busy": "2022-06-18T14:21:31.520000Z", + "iopub.status.idle": "2022-06-18T14:21:32.071000Z", + "shell.execute_reply": "2022-06-18T14:21:32.071000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World!\n", + " From worker 2:\tHello World!\n", + " From worker 4:\tHello World!\n", + " From worker 3:\tHello World!\n", + " From worker 5:\tHello World!\n" + ] + } + ], + "source": [ + "workers()\n", + "\n", + "@everywhere println(\"Hello World!\")\n", + "\n", + "# The following lines can be uncommented for more advanced informations about the subprocesses\n", + "# @everywhere println(pwd())\n", + "# @everywhere println(Base.active_project())\n", + "# @everywhere println(gethostname())\n", + "# @everywhere println(VERSION)\n", + "# @everywhere println(Threads.nthreads())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulation setup\n", + "\n", + "Next, the batch size and input values are defined." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:21:32.074000Z", + "iopub.status.busy": "2022-06-18T14:21:32.074000Z", + "iopub.status.idle": "2022-06-18T14:21:35.419000Z", + "shell.execute_reply": "2022-06-18T14:21:35.419000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "16-element Vector{Vector{Float64}}:\n", + " [0.053272555584304104, 0.45774751559489646]\n", + " [0.5896778258750763, 0.12435199368996086]\n", + " [0.5651662129022856, 0.8764873667695812]\n", + " [0.6176612662918868, 0.2785804850450695]\n", + " [0.9274233385552415, 0.38275426899967724]\n", + " [0.46094177953642124, 0.6554519159504497]\n", + " [0.73421590884579, 0.28177572874256906]\n", + " [0.5575198504784948, 0.3212214708846175]\n", + " [0.271126562512229, 0.6499895887749823]\n", + " [0.5289045741655536, 0.4873381265273107]\n", + " [0.8565770844036877, 0.2312687408548988]\n", + " [0.06332369482582334, 0.44807066874864065]\n", + " [0.08611017776660712, 0.960898209225902]\n", + " [0.3191189843443898, 0.30014344015893846]\n", + " [0.028884098958377402, 0.5285860311385517]\n", + " [0.7282727650515579, 0.7584435212215901]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "# Best if batchSize is a multiple of the threads/cores\n", + "batchSize = 16\n", + "\n", + "# Define an array of arrays randomly\n", + "input_values = collect(collect.(eachrow(rand(batchSize,2))))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Shared Module\n", + "For Distributed we need to embed the FMU into its own `module`. This prevents Distributed from trying to serialize and send the FMU over the network, as this can cause issues. This module needs to be made available on all processes using `@everywhere`." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:21:35.423000Z", + "iopub.status.busy": "2022-06-18T14:21:35.422000Z", + "iopub.status.idle": "2022-06-18T14:21:47.166000Z", + "shell.execute_reply": "2022-06-18T14:21:47.166000Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources`\n", + "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n" + ] + } + ], + "source": [ + "@everywhere module SharedModule\n", + " using FMIZoo\n", + " using FMI\n", + "\n", + " t_start = 0.0\n", + " t_step = 0.1\n", + " t_stop = 10.0\n", + " tspan = (t_start, t_stop)\n", + " tData = collect(t_start:t_step:t_stop)\n", + "\n", + " model_fmu = FMIZoo.fmiLoad(\"SpringPendulum1D\", \"Dymola\", \"2022x\")\n", + "end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We define a helper function to calculate the FMU and combine it into an Matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:21:47.169000Z", + "iopub.status.busy": "2022-06-18T14:21:47.169000Z", + "iopub.status.idle": "2022-06-18T14:21:47.459000Z", + "shell.execute_reply": "2022-06-18T14:21:47.458000Z" + } + }, + "outputs": [], + "source": [ + "@everywhere function runCalcFormatted(fmu, x0, recordValues=[\"mass.s\", \"mass.v\"])\n", + " data = fmiSimulateME(fmu, SharedModule.t_start, SharedModule.t_stop; recordValues=recordValues, saveat=SharedModule.tData, x0=x0, showProgress=false, dtmax=1e-4)\n", + " return reduce(hcat, data.states.u)\n", + "end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:21:47.461000Z", + "iopub.status.busy": "2022-06-18T14:21:47.461000Z", + "iopub.status.idle": "2022-06-18T14:22:23.804000Z", + "shell.execute_reply": "2022-06-18T14:22:23.804000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m304.291 ms\u001b[22m\u001b[39m … \u001b[35m325.332 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.41% … 6.89%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m307.274 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.37%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m309.397 ms\u001b[22m\u001b[39m ± \u001b[32m 5.860 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.94% ± 1.32%\n", + "\n", + " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\u001b[34m▁\u001b[39m\u001b[39m \u001b[39m \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 304 ms\u001b[90m Histogram: frequency by time\u001b[39m 325 ms \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@benchmark data = runCalcFormatted(SharedModule.model_fmu, rand(2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Single Threaded Batch Execution\n", + "To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:22:23.808000Z", + "iopub.status.busy": "2022-06-18T14:22:23.807000Z", + "iopub.status.idle": "2022-06-18T14:23:01.441000Z", + "shell.execute_reply": "2022-06-18T14:23:01.440000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Single Threaded\n" + ] + }, + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m4.966 s\u001b[22m\u001b[39m … \u001b[35m 4.967 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.58% … 8.12%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m4.966 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.35%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m4.966 s\u001b[22m\u001b[39m ± \u001b[32m1.039 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.35% ± 0.33%\n", + "\n", + " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", + " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 4.97 s\u001b[90m Histogram: frequency by time\u001b[39m 4.97 s \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m2.29 GiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m48038916\u001b[39m." + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "println(\"Single Threaded\")\n", + "@benchmark collect(runCalcFormatted(SharedModule.model_fmu, i) for i in input_values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multithreaded Batch Execution\n", + "In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe.\n", + "To spread the execution of a function to multiple processes, the function `pmap` can be used." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:23:01.444000Z", + "iopub.status.busy": "2022-06-18T14:23:01.444000Z", + "iopub.status.idle": "2022-06-18T14:24:04.804000Z", + "shell.execute_reply": "2022-06-18T14:24:04.804000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Multi Threaded\n" + ] + }, + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m3.069 s\u001b[22m\u001b[39m … \u001b[35m 3.078 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m3.074 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m3.074 s\u001b[22m\u001b[39m ± \u001b[32m6.467 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m0.00% ± 0.00%\n", + "\n", + " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", + " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 3.07 s\u001b[90m Histogram: frequency by time\u001b[39m 3.08 s \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m81.31 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m1192\u001b[39m." + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "println(\"Multi Threaded\")\n", + "@benchmark pmap(i -> runCalcFormatted(SharedModule.model_fmu, i), input_values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `n_procs` (or the number of physical cores of your CPU), this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` Julia processes." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unload FMU\n", + "\n", + "After calculating the data, the FMU is unloaded and all unpacked data on disc is removed." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:24:04.807000Z", + "iopub.status.busy": "2022-06-18T14:24:04.807000Z", + "iopub.status.idle": "2022-06-18T14:24:04.974000Z", + "shell.execute_reply": "2022-06-18T14:24:04.974000Z" + } + }, + "outputs": [], + "source": [ + "@everywhere fmiUnload(SharedModule.model_fmu)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary\n", + "\n", + "In this tutorial it is shown how multi processing with `Distributed.jl` can be used to improve the performance for calculating a Batch of FMUs." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia 1.6.6", + "language": "julia", + "name": "julia-1.6" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.6.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example/multithreading.ipynb b/example/multithreading.ipynb new file mode 100644 index 00000000..7076dfb7 --- /dev/null +++ b/example/multithreading.ipynb @@ -0,0 +1,481 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multithreading\n", + "Tutorial by Jonas Wilfert, Tobias Thummerer\n", + "\n", + "## License\n", + "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert\n", + "\n", + "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", + "\n", + "## Motivation\n", + "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", + "\n", + "## Introduction to the example\n", + "This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings.\n", + "Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multithreading**, check `multiprocessing.ipynb` for multiprocessing.\n", + "Advantage of multithreading is a lower communication overhead as well as lower RAM usage.\n", + "However in some cases multiprocessing can be faster as the garbage collector is not shared.\n", + "\n", + "\n", + "The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", + "\n", + "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", + "\n", + "\n", + "## Target group\n", + "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", + "\n", + "\n", + "## Other formats\n", + "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/parallel.md) corresponding to the notebook. \n", + "\n", + "\n", + "## Getting started\n", + "\n", + "### Installation prerequisites\n", + "| | Description | Command | Alternative | \n", + "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", + "| 1. | Enter Package Manager via | ] | |\n", + "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", + "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", + "| 4. | Install FMICore via | add FMICore | add \" https://github.com/ThummeTo/FMICore.jl \" |\n", + "| 5. | Install Folds via | add Folds | |\n", + "| 6. | Install BenchmarkTools via | add BenchmarkTools | |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code section\n", + "\n", + "To run the example, the previously installed packages must be included. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:24:15.415000Z", + "iopub.status.busy": "2022-06-18T14:24:14.716000Z", + "iopub.status.idle": "2022-06-18T14:24:29.648000Z", + "shell.execute_reply": "2022-06-18T14:24:29.574000Z" + } + }, + "outputs": [], + "source": [ + "# imports\n", + "using FMI\n", + "using FMIZoo\n", + "using Folds\n", + "using BenchmarkTools" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, check the amount of available threads:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:24:29.989000Z", + "iopub.status.busy": "2022-06-18T14:24:29.651000Z", + "iopub.status.idle": "2022-06-18T14:24:30.845000Z", + "shell.execute_reply": "2022-06-18T14:24:30.845000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Threads.nthreads()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the number of available threads doesn't match your expections, you can increase the number of threads available to the Julia process like described [here](https://docs.julialang.org/en/v1/manual/multi-threading/#Starting-Julia-with-multiple-threads)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulation setup\n", + "\n", + "Next, the start time and end time of the simulation are set. Here we also decide the size of the batch." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:24:30.849000Z", + "iopub.status.busy": "2022-06-18T14:24:30.849000Z", + "iopub.status.idle": "2022-06-18T14:24:34.809000Z", + "shell.execute_reply": "2022-06-18T14:24:34.809000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1-element Vector{Vector{Float64}}:\n", + " [0.769193342919982, 0.5516183754569333]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t_start = 0.0\n", + "t_step = 0.1\n", + "t_stop = 10.0\n", + "tspan = (t_start, t_stop)\n", + "tData = collect(t_start:t_step:t_stop)\n", + "\n", + "# Best if batchSize is a multiple of the threads/cores\n", + "batchSize = Threads.nthreads()\n", + "\n", + "# Define an array of arrays randomly\n", + "input_values = collect(collect.(eachrow(rand(batchSize,2))))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need to instantiate one FMU for each parallel execution, as they cannot be easily shared among different threads." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:24:34.812000Z", + "iopub.status.busy": "2022-06-18T14:24:34.812000Z", + "iopub.status.idle": "2022-06-18T14:24:40.193000Z", + "shell.execute_reply": "2022-06-18T14:24:40.193000Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", + "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n" + ] + }, + { + "data": { + "text/plain": [ + "1-element Vector{FMU2}:\n", + " Model name: SpringPendulum1D\n", + "Type: 1" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# a single FMU to compare the performance\n", + "realFMU = fmiLoad(\"SpringPendulum1D\", \"Dymola\", \"2022x\")\n", + "\n", + "# the FMU batch\n", + "realFMUBatch = [fmiLoad(\"SpringPendulum1D\", \"Dymola\", \"2022x\") for _ in 1:batchSize]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We define a helper function to calculate the FMU solution and combine it into an Matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:24:40.198000Z", + "iopub.status.busy": "2022-06-18T14:24:40.197000Z", + "iopub.status.idle": "2022-06-18T14:24:40.840000Z", + "shell.execute_reply": "2022-06-18T14:24:40.839000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "runCalcFormatted (generic function with 2 methods)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "function runCalcFormatted(fmu::FMU2, x0::Vector{Float64}, recordValues::Vector{String}=[\"mass.s\", \"mass.v\"])\n", + " data = fmiSimulateME(fmu, t_start, t_stop; recordValues=recordValues, saveat=tData, x0=x0, showProgress=false, dtmax=1e-4)\n", + " return reduce(hcat, data.states.u)\n", + "end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:24:40.843000Z", + "iopub.status.busy": "2022-06-18T14:24:40.843000Z", + "iopub.status.idle": "2022-06-18T14:25:15.703000Z", + "shell.execute_reply": "2022-06-18T14:25:15.703000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m337.943 ms\u001b[22m\u001b[39m … \u001b[35m357.340 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.03% … 6.55%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m339.287 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m342.299 ms\u001b[22m\u001b[39m ± \u001b[32m 5.982 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.39% ± 1.12%\n", + "\n", + " \u001b[39m▃\u001b[39m█\u001b[39m \u001b[34m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m▇\u001b[34m▇\u001b[39m\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m \u001b[39m▁\n", + " 338 ms\u001b[90m Histogram: frequency by time\u001b[39m 357 ms \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@benchmark data = runCalcFormatted(realFMU, rand(2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Single Threaded Batch Execution\n", + "To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:25:15.707000Z", + "iopub.status.busy": "2022-06-18T14:25:15.707000Z", + "iopub.status.idle": "2022-06-18T14:25:29.068000Z", + "shell.execute_reply": "2022-06-18T14:25:29.068000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Single Threaded\n" + ] + }, + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m338.941 ms\u001b[22m\u001b[39m … \u001b[35m359.792 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.42% … 7.05%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m340.880 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.45%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m343.682 ms\u001b[22m\u001b[39m ± \u001b[32m 6.291 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.89% ± 1.20%\n", + "\n", + " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", + " 339 ms\u001b[90m Histogram: frequency by time\u001b[39m 360 ms \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002436\u001b[39m." + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "println(\"Single Threaded\")\n", + "@benchmark collect(runCalcFormatted(realFMU, i) for i in input_values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multithreaded Batch Execution\n", + "In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe.\n", + "To spread the execution of a function to multiple threads, the library `Folds` can be used." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:25:29.072000Z", + "iopub.status.busy": "2022-06-18T14:25:29.072000Z", + "iopub.status.idle": "2022-06-18T14:25:46.159000Z", + "shell.execute_reply": "2022-06-18T14:25:46.159000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Multi Threaded\n" + ] + }, + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m307.665 ms\u001b[22m\u001b[39m … \u001b[35m325.644 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.44% … 8.13%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m308.448 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.55%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m310.319 ms\u001b[22m\u001b[39m ± \u001b[32m 4.970 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.72% ± 0.86%\n", + "\n", + " \u001b[39m█\u001b[39m \u001b[34m█\u001b[39m\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", + " \u001b[39m█\u001b[39m▆\u001b[34m█\u001b[39m\u001b[39m▆\u001b[39m█\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m█\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m \u001b[39m▁\n", + " 308 ms\u001b[90m Histogram: frequency by time\u001b[39m 326 ms \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002440\u001b[39m." + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "println(\"Multi Threaded\")\n", + "@benchmark Folds.collect(runCalcFormatted(fmu, i) for (fmu, i) in zip(realFMUBatch, input_values))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `Threads.nthreads()`, this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` threads for the Julia process." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unload FMU\n", + "\n", + "After calculating the data, the FMU is unloaded and all unpacked data on disc is removed." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-18T14:25:46.162000Z", + "iopub.status.busy": "2022-06-18T14:25:46.162000Z", + "iopub.status.idle": "2022-06-18T14:25:47.297000Z", + "shell.execute_reply": "2022-06-18T14:25:47.296000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1-element Vector{Nothing}:\n", + " nothing" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiUnload(realFMU)\n", + "fmiUnload.(realFMUBatch)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary\n", + "\n", + "In this tutorial it is shown how multi threading with `Folds.jl` can be used to improve the performance for calculating a Batch of FMUs." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia 1.7.1", + "language": "julia", + "name": "julia-1.7" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.6.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example/parameterize.ipynb b/example/parameterize.ipynb new file mode 100644 index 00000000..65099b87 --- /dev/null +++ b/example/parameterize.ipynb @@ -0,0 +1,659 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Manually parameterize an FMU\n", + "Tutorial by Johannes Stoljar, Tobias Thummerer\n", + "\n", + "## License\n", + "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", + "\n", + "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", + "\n", + "## Motivation\n", + "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", + "\n", + "## Introduction to the example\n", + "This example shows how the manually parameterization of an FMU works if very specific adjustments during system initialization is needed. For this purpose, an IO-FMU model is loaded and the various commands for parameterization are shown on the basis of this model. With this example the user shall be guided how to make certain settings at an FMU. Please note, that parameterization of a simulation is possible in a much easier fashion: Using `fmiSimulate`, `fmiSimulateME` or `fmiSimulateCS` together with a parameter dictionary for the keyword `parameters`.\n", + "\n", + "## Target group\n", + "The example is primarily intended for users who work in the field of simulation exchange. The example wants to show how simple it is to use FMUs in Julia.\n", + "\n", + "\n", + "## Other formats\n", + "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/CS_simulate.md) corresponding to the notebook. \n", + "\n", + "\n", + "## Getting started\n", + "\n", + "### Installation prerequisites\n", + "| | Description | Command | Alternative | \n", + "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", + "| 1. | Enter Package Manager via | ] | |\n", + "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", + "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code section\n", + "\n", + "To run the example, the previously installed packages must be included. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:01.571000Z", + "iopub.status.busy": "2022-06-01T15:19:00.892000Z", + "iopub.status.idle": "2022-06-01T15:19:15.010000Z", + "shell.execute_reply": "2022-06-01T15:19:14.933000Z" + }, + "scrolled": false + }, + "outputs": [], + "source": [ + "# imports\n", + "using FMI\n", + "using FMIZoo" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulation setup\n", + "\n", + "Next, the start time and end time of the simulation are set." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:15.205000Z", + "iopub.status.busy": "2022-06-01T15:19:15.013000Z", + "iopub.status.idle": "2022-06-01T15:19:16.256000Z", + "shell.execute_reply": "2022-06-01T15:19:16.255000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "8.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tStart = 0.0\n", + "tStop = 8.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import FMU\n", + "\n", + "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:16.259000Z", + "iopub.status.busy": "2022-06-01T15:19:16.259000Z", + "iopub.status.idle": "2022-06-01T15:19:20.487000Z", + "shell.execute_reply": "2022-06-01T15:19:20.486000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#################### Begin information for FMU ####################\n", + "\tModel name:\t\t\tIO\n", + "\tFMI-Version:\t\t\t2.0\n", + "\tGUID:\t\t\t\t{ac3b4a99-4908-40f7-89da-2d5c08b3c4ac}\n", + "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", + "\tGeneration time:\t\t2022-03-17T07:40:55Z\n", + "\tVar. naming conv.:\t\tstructured\n", + "\tEvent indicators:\t\t4\n", + "\tInputs:\t\t\t\t3\n", + "\t\t352321536 [\"u_real\"]\n", + "\t\t352321537 [\"u_boolean\"]\n", + "\t\t352321538 [\"u_integer\"]\n", + "\tOutputs:\t\t\t3\n", + "\t\t335544320 [\"y_real\"]\n", + "\t\t335544321 [\"y_boolean\"]\n", + "\t\t335544322 [\"y_integer\"]\n", + "\tStates:\t\t\t\t0\n", + "\tSupports Co-Simulation:\t\ttrue\n", + "\t\tModel identifier:\tIO\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "\t\tVar. com. steps:\ttrue\n", + "\t\tInput interpol.:\ttrue\n", + "\t\tMax order out. der.:\t1\n", + "\tSupports Model-Exchange:\ttrue\n", + "\t\tModel identifier:\tIO\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "##################### End information for FMU #####################\n" + ] + } + ], + "source": [ + "# we use an FMU from the FMIZoo.jl\n", + "pathToFMU = get_model_filename(\"IO\", \"Dymola\", \"2022x\")\n", + "\n", + "myFMU = fmiLoad(pathToFMU)\n", + "fmiInfo(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Instantiate and Setup FMU\n", + "\n", + "Next it is necessary to create an instance of the FMU. This is achieved by the command `fmiInstantiate!()`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:20.489000Z", + "iopub.status.busy": "2022-06-01T15:19:20.489000Z", + "iopub.status.idle": "2022-06-01T15:19:21.252000Z", + "shell.execute_reply": "2022-06-01T15:19:21.252000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "FMU: IO\n", + "InstanceName: [not defined]\n", + "Address: Ptr{Nothing} @0x00000000029c12e0\n", + "State: fmi2ComponentStateInstantiated\n", + "Logging: true\n", + "FMU time: -Inf\n", + "FMU states: nothing" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiInstantiate!(myFMU; loggingOn=true)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:21.256000Z", + "iopub.status.busy": "2022-06-01T15:19:21.256000Z", + "iopub.status.idle": "2022-06-01T15:19:21.603000Z", + "shell.execute_reply": "2022-06-01T15:19:21.603000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0x00000000" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiSetupExperiment(myFMU, tStart, tStop)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parameterize FMU\n", + "\n", + "To parameterize an FMU, the FMU must be in the initialization mode, which is reached with the `fmiEnterInitializationMode()` command." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:21.607000Z", + "iopub.status.busy": "2022-06-01T15:19:21.606000Z", + "iopub.status.idle": "2022-06-01T15:19:21.639000Z", + "shell.execute_reply": "2022-06-01T15:19:21.639000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0x00000000" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiEnterInitializationMode(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Within this mode it is then possible to change the different parameters. In this example, for each data type (`real`, `integer`, `boolean` and `string)` a corresponding parameter is selected. At the beginning the initial state of these parameters is displayed with `fmiGet()`." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:21.643000Z", + "iopub.status.busy": "2022-06-01T15:19:21.643000Z", + "iopub.status.idle": "2022-06-01T15:19:25.228000Z", + "shell.execute_reply": "2022-06-01T15:19:25.228000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4-element Vector{Any}:\n", + " 0.0\n", + " 0\n", + " 0\n", + " \"Hello World!\"" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "params = [\"p_real\", \"p_integer\", \"p_boolean\", \"p_string\"]\n", + "fmiGet(myFMU, params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the next step, a function is defined that generates a random value for each parameter. For the parameter `p_string` a random number is inserted into the string. All parameters are combined to a vector and output." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:25.232000Z", + "iopub.status.busy": "2022-06-01T15:19:25.232000Z", + "iopub.status.idle": "2022-06-01T15:19:25.951000Z", + "shell.execute_reply": "2022-06-01T15:19:25.951000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "generateRandomNumbers (generic function with 1 method)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "function generateRandomNumbers()\n", + " rndReal = 100 * rand()\n", + " rndInteger = round(Integer, 100 * rand())\n", + " rndBoolean = rand() > 0.5\n", + " rndString = \"Random number $(100 * rand())!\"\n", + "\n", + " randValues = [rndReal, rndInteger, rndBoolean, rndString]\n", + " println(randValues)\n", + " return randValues\n", + "end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The previously defined function is called and the results are displayed in the console." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:25.955000Z", + "iopub.status.busy": "2022-06-01T15:19:25.955000Z", + "iopub.status.idle": "2022-06-01T15:19:26.678000Z", + "shell.execute_reply": "2022-06-01T15:19:26.678000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Any[27.27027116078753, 50, true, \"Random number 83.09640957659121!\"]\n" + ] + } + ], + "source": [ + "paramsVal = generateRandomNumbers();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### First variant\n", + "\n", + "With this variant it is quickly possible to set all parameters at once. Even different data types can be set with only one command. The command `fmiSet()` selects itself which function is chosen for which data type. After setting the parameters, it is checked whether the corresponding parameters were set correctly. For this the function `fmiGet()` is used as above and afterwards with the macro `@assert` also tested whether the correct values are set." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:26.682000Z", + "iopub.status.busy": "2022-06-01T15:19:26.682000Z", + "iopub.status.idle": "2022-06-01T15:19:27.242000Z", + "shell.execute_reply": "2022-06-01T15:19:27.242000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Any[27.27027116078753, 50, 1, \"Random number 83.09640957659121!\"]" + ] + } + ], + "source": [ + "fmiSet(myFMU, params, paramsVal)\n", + "values = fmiGet(myFMU, params)\n", + "print(values)\n", + "\n", + "@assert paramsVal == values" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Second variant\n", + "\n", + "To make sure that the functions work it is necessary to generate random numbers again. As shown already, we call the defined function `generateRandomNumbers()` and output the values." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:27.246000Z", + "iopub.status.busy": "2022-06-01T15:19:27.246000Z", + "iopub.status.idle": "2022-06-01T15:19:27.247000Z", + "shell.execute_reply": "2022-06-01T15:19:27.247000Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Any[54.98169316988619, 76, true, \"Random number 39.54384075977397!\"]\n" + ] + } + ], + "source": [ + "rndReal, rndInteger, rndBoolean, rndString = generateRandomNumbers();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the second variant, the value for each data type is set separately by the corresponding command. By this variant one has the maximum control and can be sure that also the correct data type is set. To illustrate the functionality of the parameterization with the separate functions, the corresponding get function is also called separately for each data type:\n", + "* `fmiSetReal()` <---> `fmiGetReal()`\n", + "* `fmiSetInteger()` <---> `fmiGetInteger()`\n", + "* `fmiSetBoolean()` <---> `fmiGetBoolean()`\n", + "* `fmiSetString()` <---> `fmiGetString()`." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:27.250000Z", + "iopub.status.busy": "2022-06-01T15:19:27.250000Z", + "iopub.status.idle": "2022-06-01T15:19:28.917000Z", + "shell.execute_reply": "2022-06-01T15:19:28.917000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\"54.98169316988619 == 54.98169316988619\"" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "\"76 == 76\"" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "\"true == 1\"" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "\"Random number 39.54384075977397! == Random number 39.54384075977397!\"" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fmiSetReal(myFMU, \"p_real\", rndReal)\n", + "display(\"$rndReal == $(fmiGetReal(myFMU, \"p_real\"))\")\n", + "\n", + "fmiSetInteger(myFMU, \"p_integer\", rndInteger)\n", + "display(\"$rndInteger == $(fmiGetInteger(myFMU, \"p_integer\"))\")\n", + "\n", + "fmiSetBoolean(myFMU, \"p_boolean\", rndBoolean)\n", + "display(\"$rndBoolean == $(fmiGetBoolean(myFMU, \"p_boolean\"))\")\n", + "\n", + "fmiSetString(myFMU, \"p_string\", rndString)\n", + "display(\"$rndString == $(fmiGetString(myFMU, \"p_string\"))\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After seeing that both variants set the parameters correctly, the initialization mode is terminated with the function `fmiExitInitializationMode()`." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:28.920000Z", + "iopub.status.busy": "2022-06-01T15:19:28.920000Z", + "iopub.status.idle": "2022-06-01T15:19:28.956000Z", + "shell.execute_reply": "2022-06-01T15:19:28.955000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0x00000000" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiExitInitializationMode(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From here on, you may want to simulate the FMU. Please note, that with the default `executionConfig`, it is necessary to prevent a new instantiation using the keyword `instantiate=false`. Otherwise, a new instance is allocated for the simulation-call and the parameters set for the previous instance are not transfered.\n", + "\n", + "Example:\n", + "`fmiSimulate(...; instantiate=false, ...)`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unload FMU\n", + "\n", + "The FMU will be unloaded and all unpacked data on disc will be removed." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:28.959000Z", + "iopub.status.busy": "2022-06-01T15:19:28.959000Z", + "iopub.status.idle": "2022-06-01T15:19:29.101000Z", + "shell.execute_reply": "2022-06-01T15:19:29.101000Z" + } + }, + "outputs": [], + "source": [ + "fmiUnload(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary\n", + "\n", + "Based on this tutorial it can be seen that there are two different variants to set and get parameters.These examples should make it clear to the user how parameters can also be set with different data types." + ] + } + ], + "metadata": { + "interpreter": { + "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" + }, + "jupytext": { + "cell_metadata_filter": "-all", + "comment_magics": "false", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "Julia 1.6.6", + "language": "julia", + "name": "julia-1.6" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.6.6" + }, + "nteract": { + "version": "0.28.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example/simulate.ipynb b/example/simulate.ipynb new file mode 100644 index 00000000..f3ef7b84 --- /dev/null +++ b/example/simulate.ipynb @@ -0,0 +1,1012 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Simulate an FMU in different modes\n", + "Tutorial by Johannes Stoljar, Tobias Thummerer\n", + "\n", + "## License\n", + "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", + "\n", + "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", + "\n", + "## Motivation\n", + "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", + "\n", + "## Introduction to the example\n", + "In this example we want to show how fast and easy the simulation for an FMU is. For this purpose, the FMU is simulated in co-simulation mode and in model-exchange mode. After the FMU has been simulated, the simulation results are displayed in a graph. The graphs of the different modes are compared with each other. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", + "\n", + "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", + "\n", + "\n", + "## Target group\n", + "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", + "\n", + "\n", + "## Other formats\n", + "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/simulate.md) corresponding to the notebook. \n", + "\n", + "\n", + "## Getting started\n", + "\n", + "### Installation prerequisites\n", + "| | Description | Command | Alternative | \n", + "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", + "| 1. | Enter Package Manager via | ] | |\n", + "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", + "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", + "| 4. | Install Plots via | add Plots | |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code section\n", + "\n", + "To run the example, the previously installed packages must be included. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:19:38.296000Z", + "iopub.status.busy": "2022-06-01T15:19:37.619000Z", + "iopub.status.idle": "2022-06-01T15:20:00.542000Z", + "shell.execute_reply": "2022-06-01T15:20:00.469000Z" + }, + "scrolled": false + }, + "outputs": [], + "source": [ + "# imports\n", + "using FMI\n", + "using FMIZoo\n", + "using Plots" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulation setup\n", + "\n", + "Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:20:09.276000Z", + "iopub.status.busy": "2022-06-01T15:20:00.544000Z", + "iopub.status.idle": "2022-06-01T15:20:10.061000Z", + "shell.execute_reply": "2022-06-01T15:20:10.061000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0:0.01:8.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tStart = 0.0\n", + "tStep = 0.01\n", + "tStop = 8.0\n", + "tSave = tStart:tStep:tStop" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import FMU\n", + "\n", + "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:20:10.065000Z", + "iopub.status.busy": "2022-06-01T15:20:10.065000Z", + "iopub.status.idle": "2022-06-01T15:20:14.405000Z", + "shell.execute_reply": "2022-06-01T15:20:14.404000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", + "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources`\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", + "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", + "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#################### Begin information for FMU ####################\n", + "\tModel name:\t\t\tSpringFrictionPendulum1D\n", + "\tFMI-Version:\t\t\t2.0\n", + "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", + "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", + "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", + "\tVar. naming conv.:\t\tstructured\n", + "\tEvent indicators:\t\t24\n", + "\tInputs:\t\t\t\t0\n", + "\tOutputs:\t\t\t0\n", + "\tStates:\t\t\t\t2\n", + "\t\t33554432 [\"mass.s\"]\n", + "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", + "\tSupports Co-Simulation:\t\ttrue\n", + "\t\tModel identifier:\tSpringFrictionPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "\t\tVar. com. steps:\ttrue\n", + "\t\tInput interpol.:\ttrue\n", + "\t\tMax order out. der.:\t1\n", + "\tSupports Model-Exchange:\ttrue\n", + "\t\tModel identifier:\tSpringFrictionPendulum1D\n", + "\t\tGet/Set State:\t\ttrue\n", + "\t\tSerialize State:\ttrue\n", + "\t\tDir. Derivatives:\ttrue\n", + "##################### End information for FMU #####################\n" + ] + } + ], + "source": [ + "# we use an FMU from the FMIZoo.jl\n", + "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", + "\n", + "myFMU = fmiLoad(pathToFMU)\n", + "# fmiLoad(\"path/to/myFMU.fmu\"; unpackPath = \"path/to/unpacked/fmu/\")\n", + "\n", + "fmiInfo(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulate FMU\n", + "\n", + "In the following, the FMU is simulated in the two different simulation modes.\n", + "\n", + "#### Simulate as Co-Simulation\n", + "\n", + "In the next steps the recorded values are defined. The first state is the position of the mass and the second state is the velocity. In the function `fmiSimulateCS()` the FMU is simulated in co-simulation mode (CS) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time and the recorded variables are specified." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:20:14.407000Z", + "iopub.status.busy": "2022-06-01T15:20:14.407000Z", + "iopub.status.idle": "2022-06-01T15:20:19.739000Z", + "shell.execute_reply": "2022-06-01T15:20:19.739000Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Model name:\n", + "\tSpringFrictionPendulum1D\n", + "Success:\n", + "\ttrue\n", + "Values [801]:\n", + "\t0.0\t(0.5, 0.0)\n", + "\t0.01\t(0.5002235448486548, 0.042692491939260585)\n", + "\t0.02\t(0.5008715291319449, 0.08568000508550636)\n", + "\t0.03\t(0.5019478597521578, 0.12892136998736314)\n", + "\t0.04\t(0.5034570452098334, 0.17232325681284336)\n", + "\t0.05\t(0.5053993458877354, 0.2158440857658765)\n", + "\t0.06\t(0.5077764240578201, 0.259420181133082)\n", + "\t0.07\t(0.5105886522837868, 0.30295578207463486)\n", + "\t0.08\t(0.5138351439717114, 0.3464184707972189)\n", + "\t...\n", + "\t8.0\t(1.071367253976742, -1.000814138594347e-10)\n", + "Events [0]:\n" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vrs = [\"mass.s\", \"mass.v\"]\n", + "\n", + "dataCS = fmiSimulateCS(myFMU, tStart, tStop; recordValues=vrs, saveat=tSave)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Simulate as Model-Exchange\n", + "\n", + "In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time are specified. In contrast to the co-simulation, the values to be stored are not specified here, since the states and events of the FMU are always output as well. The identifiers given above just correspond to the states of the FMU." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:20:19.742000Z", + "iopub.status.busy": "2022-06-01T15:20:19.742000Z", + "iopub.status.idle": "2022-06-01T15:20:32.777000Z", + "shell.execute_reply": "2022-06-01T15:20:32.777000Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09\u001b[39m\n" + ] + }, + { + "data": { + "text/plain": [ + "Model name:\n", + "\tSpringFrictionPendulum1D\n", + "Success:\n", + "\ttrue\n", + "States [801]:\n", + "\t0.0\t[0.5, 0.0]\n", + "\t0.01\t[0.5002131418344649, 0.042689450666241]\n", + "\t0.02\t[0.5008548874805565, 0.08570846215523381]\n", + "\t0.03\t[0.5019281653120716, 0.12898389312495082]\n", + "\t0.04\t[0.5034351805057593, 0.17244393475170294]\n", + "\t0.05\t[0.5053774287967188, 0.2160182432854046]\n", + "\t0.06\t[0.5077556967622916, 0.25963796675862466]\n", + "\t0.07\t[0.5105701003205937, 0.3032358690888718]\n", + "\t0.08\t[0.5138201049458624, 0.34674641820324037]\n", + "\t...\n", + "\t8.0\t[1.0668213438183276, -1.0000099359121942e-10]\n", + "Events [6]:\n", + "\tState-Event #11 @ 0.0s\n", + "\tState-Event #11 @ 0.9939s\n", + "\tState-Event #19 @ 1.9881s\n", + "\tState-Event #11 @ 2.9829s\n", + "\tState-Event #19 @ 3.9787s\n", + "\tState-Event #11 @ 4.9768s\n" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataME = fmiSimulateME(myFMU, tStart, tStop; saveat=tSave)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plotting FMU\n", + "\n", + "After the simulation is finished the results of the FMU for the co-simulation and model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:20:32.781000Z", + "iopub.status.busy": "2022-06-01T15:20:32.780000Z", + "iopub.status.idle": "2022-06-01T15:20:51.657000Z", + "shell.execute_reply": "2022-06-01T15:20:51.657000Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiPlot(dataCS)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:20:51.662000Z", + "iopub.status.busy": "2022-06-01T15:20:51.662000Z", + "iopub.status.idle": "2022-06-01T15:20:51.876000Z", + "shell.execute_reply": "2022-06-01T15:20:51.876000Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fmiPlot(dataME)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From both graphs it can be seen that the simulation calculates exactly the same results." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unload FMU\n", + "\n", + "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2022-06-01T15:20:51.880000Z", + "iopub.status.busy": "2022-06-01T15:20:51.880000Z", + "iopub.status.idle": "2022-06-01T15:20:51.922000Z", + "shell.execute_reply": "2022-06-01T15:20:51.922000Z" + } + }, + "outputs": [], + "source": [ + "fmiUnload(myFMU)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary\n", + "\n", + "Based on this tutorial it can be seen that simulating in the different mode is very easy, and it only takes a few commands to simulate the FMU. " + ] + } + ], + "metadata": { + "interpreter": { + "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" + }, + "jupytext": { + "cell_metadata_filter": "-all", + "comment_magics": "false", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "Julia 1.6.6", + "language": "julia", + "name": "julia-1.6" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.6.6" + }, + "nteract": { + "version": "0.28.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/FMI.jl b/src/FMI.jl index 3345312a..f49acae3 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -38,6 +38,7 @@ import FMIImport: fmi2Get, fmi2Get!, fmi2Set import FMIImport: fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue export fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue +# fmi3 imports import FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate import FMIImport: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmi3InstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal import FMIImport: fmi3InstantiateModelExchange, fmi3InstantiateCoSimulation, fmi3InstantiateScheduledExecution, fmi3FreeInstance!, fmi3GetVersion @@ -50,14 +51,15 @@ import FMIImport: fmi3SetIntervalDecimal, fmi3SetIntervalFraction, fmi3GetInterv import FMIImport: fmi3ActivateModelPartition import FMIImport: fmi3GetNumberOfVariableDependencies!, fmi3GetVariableDependencies! import FMIImport: fmi3GetDirectionalDerivative!, fmi3GetAdjointDerivative!, fmi3GetOutputDerivatives! -import FMIImport: fmi3DoStep +import FMIImport: fmi3DoStep! + import FMIImport: fmi3EnterConfigurationMode, fmi3ExitConfigurationMode, fmi3GetNumberOfContinuousStates!, fmi3GetNumberOfEventIndicators!, fmi3GetContinuousStates!, fmi3GetNominalsOfContinuousStates! import FMIImport: fmi3EvaluateDiscreteStates, fmi3EnterStepMode import FMIImport: fmi3SetTime, fmi3SetContinuousStates, fmi3EnterEventMode, fmi3UpdateDiscreteStates, fmi3EnterContinuousTimeMode, fmi3CompletedIntegratorStep! import FMIImport: fmi3GetContinuousStateDerivatives, fmi3GetEventIndicators, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates import FMIImport: fmi3StringToValueReference, fmi3ValueReferenceToString, fmi3ModelVariablesForValueReference import FMIImport: fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString -import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmiDeSerializeFMUState +import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmi3DeSerializeFMUState import FMIImport: fmi3GetDirectionalDerivative, fmi3GetAdjointDerivative import FMIImport: fmi3GetStartValue, fmi3SampleDirectionalDerivative, fmi3CompletedIntegratorStep import FMIImport: fmi3Unzip, fmi3Load, loadBinary, fmi3Reload, fmi3Unload, fmi3InstantiateModelExchange!, fmi3InstantiateCoSimulation!, fmi3InstantiateScheduledExecution! @@ -65,8 +67,8 @@ import FMIImport: fmi3SampleDirectionalDerivative! import FMIImport: fmi3GetJacobian, fmi3GetJacobian!, fmi3GetFullJacobian, fmi3GetFullJacobian! import FMIImport: fmi3LoadModelDescription import FMIImport: fmi3GetDefaultStartTime, fmi3GetDefaultStopTime, fmi3GetDefaultTolerance, fmi3GetDefaultStepSize -import FMIImport: fmi3GetModelName, fmi3GetInstantiationToken, fmi3GetGenerationTool, fmi3GetGenerationDateAndTime, fmi3GetVariableNamingConvention, fmi3GetNumberOfEventIndicators, fmi3GetNumberOfStates, fmi3IsCoSimulation, fmi3IsModelExchange, fmi3IsScheduledExecution -import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetSetState, fmi3CanSerializeFMUState, fmi3ProvidesDirectionalDerivatives, fmi3ProvidesAdjointDerivatves +import FMIImport: fmi3GetModelName, fmi3GetInstantiationToken, fmi3GetGenerationTool, fmi3GetGenerationDateAndTime, fmi3GetVariableNamingConvention, fmi3GetNumberOfEventIndicators, fmi3GetNumberOfContinuousStates, fmi3IsCoSimulation, fmi3IsModelExchange, fmi3IsScheduledExecution +import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetSetState, fmi3CanSerializeFMUState, fmi3ProvidesDirectionalDerivatives, fmi3ProvidesAdjointDerivatives import FMIImport: fmi3Get, fmi3Get!, fmi3Set import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue @@ -149,7 +151,7 @@ function __init__() @require JLD2="033835bb-8acc-5ee8-8aae-3f567f8a3819" begin import .JLD2 include("FMI2_JLD2.jl") - include("FMI3_JLD3.jl") + include("FMI3_JLD2.jl") end end @@ -619,12 +621,12 @@ Load FMUs independent of the FMI version, currently supporting version 2.0.X and See also [`fmi2Load`](@ref), [`fmi3Load`](@ref). """ -function fmiLoad(args...; kwargs...) +function fmiLoad(pathToFMU::AbstractString, args...; kwargs...) version = fmiCheckVersion(pathToFMU) if version == "2.0" - fmi2Load(args...; kwargs...) + fmi2Load(pathToFMU, args...; kwargs...) elseif version == "3.0" - fmi3Load(args...; kwargs...) + fmi3Load(pathToFMU, args...; kwargs...) else @warn "fmiLoad(...): Unknown FMU version" end @@ -1034,6 +1036,7 @@ end """ fmiSetDebugLogging(str::Union{fmi2Struct, fmi3Struct}) + Control the use of the logging callback function, version independent. # Arguments @@ -1509,6 +1512,9 @@ function fmiGetInteger!(str::fmi2Struct, args...; kwargs...) fmi2GetInteger!(str, args...; kwargs...) end # TODO different call in fmi3 + +Set the values of an array of integer variables + """ fmiSetInteger(str::fmi2Struct, c::FMU2Component, vr::fmi2ValueReferenceFormat, values::Union{Array{<:Integer}, <:Integer}) @@ -2098,6 +2104,20 @@ function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) fmi3GetAdjointDerivative!(str, args...; kwargs...) end +""" +Returns the values of the adjoint derivatives. +""" +function fmiGetAdjointDerivative(str::fmi3Struct, args...; kwargs...) + fmi3GetAdjointDerivative(str, args...; kwargs...) +end + +""" +Returns the values of the adjoint derivatives (in-place). +""" +function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) + fmi3GetAdjointDerivative!(str, args...; kwargs...) +end + """ fmiDoStep(str::fmi2Struct, c::FMU2Component, communicationStepSize::Union{Real, Nothing} = nothing; currentCommunicationPoint::Union{Real, Nothing} = nothing, noSetFMUStatePriorToCurrentPoint::Bool = true) diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 66dad1fe..dc3cd9ee 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -16,6 +16,8 @@ using FMIImport: fmi3DependencyKindDependent, fmi3DependencyKindFixed using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate, fmi3Instance import FMIImport: fmi3VariableNamingConventionFlat, fmi3VariableNamingConventionStructured +using ZipFile, EzXML + """ Returns how a variable depends on another variable based on the model description. """ @@ -222,8 +224,9 @@ function fmiCheckVersion(pathToFMU::String; unpackPath=nothing) # read version tag - doc = readxml(unzippedAbsPath) + doc = readxml(normpath(joinpath(unzippedAbsPath, "modelDescription.xml"))) + root = doc.root version = root["fmiVersion"] # cleanup unzipped modelDescription From 8bb51dce9be7013de697ae75401720514b43840d Mon Sep 17 00:00:00 2001 From: TT Date: Tue, 28 Jun 2022 16:04:53 +0200 Subject: [PATCH 24/41] deleted files --- docs/src/examples/manipulation.md | 289 -- .../manipulation_files/manipulation_10_0.svg | 134 - .../manipulation_files/manipulation_18_0.svg | 172 - docs/src/examples/modelica_conference_2021.md | 219 -- .../modelica_conference_2021_8_0.svg | 110 - docs/src/examples/multiple_instances.md | 226 -- .../multiple_instances_10_0.svg | 902 ----- .../multiple_instances_18_0.svg | 1708 --------- docs/src/examples/multiprocessing.md | 279 -- docs/src/examples/multithreading.md | 254 -- docs/src/examples/parameterize.md | 312 -- docs/src/examples/simulate.md | 245 -- .../examples/simulate_files/simulate_12_0.svg | 274 -- .../examples/simulate_files/simulate_13_0.svg | 295 -- example/manipulation.ipynb | 839 ----- example/modelica_conference_2021.ipynb | 560 --- example/multiple_instances.ipynb | 3081 ----------------- example/multiprocessing.ipynb | 516 --- example/multithreading.ipynb | 481 --- example/parameterize.ipynb | 659 ---- example/simulate.ipynb | 1012 ------ 21 files changed, 12567 deletions(-) delete mode 100644 docs/src/examples/manipulation.md delete mode 100644 docs/src/examples/manipulation_files/manipulation_10_0.svg delete mode 100644 docs/src/examples/manipulation_files/manipulation_18_0.svg delete mode 100644 docs/src/examples/modelica_conference_2021.md delete mode 100644 docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg delete mode 100644 docs/src/examples/multiple_instances.md delete mode 100644 docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg delete mode 100644 docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg delete mode 100644 docs/src/examples/multiprocessing.md delete mode 100644 docs/src/examples/multithreading.md delete mode 100644 docs/src/examples/parameterize.md delete mode 100644 docs/src/examples/simulate.md delete mode 100644 docs/src/examples/simulate_files/simulate_12_0.svg delete mode 100644 docs/src/examples/simulate_files/simulate_13_0.svg delete mode 100644 example/manipulation.ipynb delete mode 100644 example/modelica_conference_2021.ipynb delete mode 100644 example/multiple_instances.ipynb delete mode 100644 example/multiprocessing.ipynb delete mode 100644 example/multithreading.ipynb delete mode 100644 example/parameterize.ipynb delete mode 100644 example/simulate.ipynb diff --git a/docs/src/examples/manipulation.md b/docs/src/examples/manipulation.md deleted file mode 100644 index adea4344..00000000 --- a/docs/src/examples/manipulation.md +++ /dev/null @@ -1,289 +0,0 @@ -# Manipulate a function -Tutorial by Johannes Stoljar, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -This example shows how to overwrite a library function with an own function. For this the FMU model is simulated first without changes. Then the function `fmi2GetReal()` is overwritten and simulated again. Both simulations are displayed in a graph to show the change caused by overwriting the function. The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. - -![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) - - -## Target group -The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/manipulation.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | -| 4. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " | -| 5. | Install Plots via | add Plots | | - -## Code section - -To run the example, the previously installed packages must be included. - - -```julia -# imports -using FMI -using FMIZoo -using FMICore -using Plots -``` - -### Simulation setup - -Next, the start time and end time of the simulation are set. - - -```julia -tStart = 0.0 -tStop = 8.0 -``` - - - - - 8.0 - - - -### Import FMU - -In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. - - -```julia -# we use an FMU from the FMIZoo.jl -pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x") - -myFMU = fmiLoad(pathToFMU) - -fmiInfo(myFMU) -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 - - - #################### Begin information for FMU #################### - Model name: SpringFrictionPendulum1D - FMI-Version: 2.0 - GUID: {df491d8d-0598-4495-913e-5b025e54d7f2} - Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 - Generation time: 2022-03-03T15:09:18Z - Var. naming conv.: structured - Event indicators: 24 - Inputs: 0 - Outputs: 0 - States: 2 - 33554432 ["mass.s"] - 33554433 ["mass.v", "mass.v_relfric"] - Supports Co-Simulation: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - Var. com. steps: true - Input interpol.: true - Max order out. der.: 1 - Supports Model-Exchange: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - ##################### End information for FMU ##################### - - -### Simulate FMU - -In the next steps the recorded value is defined. The recorded value is the position of the mass. In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size. In addition, the start and end time and the recorded variables are specified. - - -```julia -vrs = ["mass.s"] - -simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs) -``` - - Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10 - - - - - - Model name: - SpringFrictionPendulum1D - Success: - true - States [110]: - 0.0 [0.5, 0.0] - 2.3529411764719727e-11 [0.5, 1.0e-10] - 1.0000023529411766e-5 [0.5000000002125017, 4.250030186348503e-5] - 0.00011000002352941177 [0.5000000257134062, 0.0004675245102952289] - 0.0011100000235294118 [0.5000026191281834, 0.004719970360497647] - 0.011110000023529413 [0.5002631686645611, 0.047449647283752144] - 0.03982466736770743 [0.5034050123596227, 0.17168075110950387] - 0.09972054285078226 [0.5215006197560228, 0.43204954153497455] - 0.16481836271111422 [0.5585747156842935, 0.703758265932321] - ... - 8.0 [1.0668213438183276, -1.0000099359121942e-10] - Values [110]: - 0.0 (0.5,) - 2.3529411764719727e-11 (0.5,) - 1.0000023529411766e-5 (0.5000000002125017,) - 0.00011000002352941177 (0.5000000257134062,) - 0.0011100000235294118 (0.5000026191281834,) - 0.011110000023529413 (0.5002631686645611,) - 0.03982466736770743 (0.5034050123596227,) - 0.09972054285078226 (0.5215006197560228,) - 0.16481836271111422 (0.5585747156842935,) - ... - 8.0 (1.0668213438183276,) - Events [6]: - State-Event #11 @ 0.0s - State-Event #11 @ 0.9939s - State-Event #19 @ 1.9881s - State-Event #11 @ 2.9829s - State-Event #19 @ 3.9787s - State-Event #11 @ 4.9768s - - - - -### Plotting FMU - -After the simulation is finished, the result of the FMU for the model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time. - - -```julia -fig = fmiPlot(simData, states=false) -``` - - - - - -![svg](manipulation_files/manipulation_10_0.svg) - - - - -### Override Function - -After overwriting a function, the previous one is no longer accessible. The original function `fmi2GetReal()` is cached by storing the address of the pointer. The addresses of the pointers are kept in the FMU and are thus accessible. - - -```julia -# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function -originalGetReal = myFMU.cGetReal -``` - - - - - Ptr{Nothing} @0x00007f52e9530faf - - - -To overwrite the function `fmi2GetReal!()`, the function header of the new custom function must be identical to the previous one. The function header looks like `fmi2GetReal!(cfunc::Ptr{Nothing}, c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})::fmi2Status`. The information how the FMI2 function are structured can be seen from [FMICore.jl](https://github.com/ThummeTo/FMICore.jl/blob/main/src/FMI2_c.jl#L718) or the FMI2.0.3-specification. - -In the new implementation the original function is called by the previously stored pointer. Next there is a special handling if `value` is a pointer to an array. In this case the pointer is treated as an array, so that the entries are accessible. Otherwise, each value in `value` is multiplied by two. Finally, the original state of the original function is output. - - -```julia -function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, - nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}}) - # first, we do what the original function does - status = 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) - end - - # now, we multiply every value by two (just for fun!) - for i in 1:nvr - value[i] *= 2.0 - end - - # return the original status - return status -end -``` - - - - - myGetReal! (generic function with 1 method) - - - -In the next command the original function is overwritten with the new defined function, for which the command `fmiSetFctGetReal()` is called. - - -```julia -# no we overwrite the original function -fmiSetFctGetReal(myFMU, myGetReal!) -``` - - - - - Ptr{Nothing} @0x00007f533e325fc0 - - - -### Simulate and Plot FMU with modified function - -As before, the identical command is called here for simulation. This is also a model exchange simulation. Immediately afterwards, the results are added to the previous graph as a dashed line. - - -```julia -simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs) -fmiPlot!(fig, simData; states=false, style=:dash) -``` - - - - - -![svg](manipulation_files/manipulation_18_0.svg) - - - - -As expected by overwriting the function, all values are doubled. - -### Unload FMU - -After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. - - -```julia -fmiUnload(myFMU) -``` - -### Summary - -In this tutorial it is shown how an existing function of the library can be replaced by an own implementation. Through this possibility, there are almost no limits for the user, whereby the user can customize the function to his liking. diff --git a/docs/src/examples/manipulation_files/manipulation_10_0.svg b/docs/src/examples/manipulation_files/manipulation_10_0.svg deleted file mode 100644 index b86d3be2..00000000 --- a/docs/src/examples/manipulation_files/manipulation_10_0.svg +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/manipulation_files/manipulation_18_0.svg b/docs/src/examples/manipulation_files/manipulation_18_0.svg deleted file mode 100644 index d9cf606b..00000000 --- a/docs/src/examples/manipulation_files/manipulation_18_0.svg +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/modelica_conference_2021.md b/docs/src/examples/modelica_conference_2021.md deleted file mode 100644 index c77e978a..00000000 --- a/docs/src/examples/modelica_conference_2021.md +++ /dev/null @@ -1,219 +0,0 @@ -# Advanced Simulation of an FMU -Tutorial by Johannes Stoljar, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -In this example we would like to show that besides the simple simulation of an FMU there is also a more advanced version of the simulation. The advantage of the more advanced variant is that there are more possibilities to intervene in the simulation to make changes. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. - -![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) - - -## Target group -The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/modelica_conference_2021.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | -| 4. | Install Plots via | add Plots | | - -## Code section - -To run the example, the previously installed packages must be included. - - -```julia -# imports -using FMI -using FMIZoo -using Plots -``` - -### Simulation setup - -Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. - - -```julia -tStart = 0.0 -tStep = 0.1 -tStop = 8.0 -tSave = tStart:tStep:tStop -``` - - - - - 0.0:0.1:8.0 - - - -### Simple FMU Simulation - -In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. - - -```julia -# we use an FMU from the FMIZoo.jl -pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x") - -myFMU = fmiLoad(pathToFMU) -fmiInfo(myFMU) -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 - - - #################### Begin information for FMU #################### - Model name: SpringFrictionPendulum1D - FMI-Version: 2.0 - GUID: {df491d8d-0598-4495-913e-5b025e54d7f2} - Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 - Generation time: 2022-03-03T15:09:18Z - Var. naming conv.: structured - Event indicators: 24 - Inputs: 0 - Outputs: 0 - States: 2 - 33554432 ["mass.s"] - 33554433 ["mass.v", "mass.v_relfric"] - Supports Co-Simulation: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - Var. com. steps: true - Input interpol.: true - Max order out. der.: 1 - Supports Model-Exchange: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - ##################### End information for FMU ##################### - - -In the next commands the FMU is simulated, for which the start and end time and recorded variables are declared. Afterwards the simulation result is shown in a graph. In the plot for the FMU, it can be seen that the oscillation keeps decreasing due to the effect of friction. If one simulates long enough, the oscillation comes to a standstill after a certain time. - - -```julia -simData = fmiSimulate(myFMU, tStart, tStop; recordValues=["mass.s"], saveat=tSave) -fmiPlot(simData) -``` - - - - - -![svg](modelica_conference_2021_files/modelica_conference_2021_8_0.svg) - - - - -After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. - - -```julia -fmiUnload(myFMU) -``` - -### Advanced FMU Simulation - -In the following type of simulation a more advanced variant is presented, which allows intervening more in the simulation process. Analogous to the simple variant, an FMU model must be loaded. - - -```julia -myFMU = fmiLoad(pathToFMU); -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 - - -Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. - - -```julia -instanceFMU = fmiInstantiate!(myFMU) -``` - - - - - FMU: SpringFrictionPendulum1D - InstanceName: [not defined] - Address: Ptr{Nothing} @0x00000000064853f0 - State: fmi2ComponentStateInstantiated - Logging: false - FMU time: -Inf - FMU states: nothing - - - -In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. Next, the FMU is initialized by the calls of `fmiEnterInitializationMode()` and `fmiExitInitializationMode()`. It would also be possible to set initial states for the FMU between these two commands. - - -```julia -fmiSetupExperiment(instanceFMU, tStart, tStop) -fmiEnterInitializationMode(instanceFMU) -# set initial model states -fmiExitInitializationMode(instanceFMU) -``` - - - - - 0x00000000 - - - -The actual simulation loop is shown in the following block. Here a simulation step `fmiDoStep()` with the fixed step size `tStep` is executed. As indicated in the code by the comments, the input values and output values of the FMU could be changed in the simulation loop as desired, whereby the higher possibility of adjustments arises. - - -```julia -for t in tSave - # set model inputs - # ... - fmiDoStep(instanceFMU, tStep) - # get model outputs - # ... -end -``` - -The instantiated FMU must be terminated and then the memory area for the instance can also be deallocated. The last step is to unload the FMU to remove all unpacked data on disc. - - -```julia -fmiTerminate(instanceFMU) -fmiFreeInstance!(instanceFMU) -fmiUnload(myFMU) -``` - -### Summary - -The tutorial has shown that besides the usual simple variant of simulating an FMU, there is another way to make more adjustments. diff --git a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg b/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg deleted file mode 100644 index c714d93e..00000000 --- a/docs/src/examples/modelica_conference_2021_files/modelica_conference_2021_8_0.svg +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/multiple_instances.md b/docs/src/examples/multiple_instances.md deleted file mode 100644 index d20d0c7f..00000000 --- a/docs/src/examples/multiple_instances.md +++ /dev/null @@ -1,226 +0,0 @@ -# Multiple Instances of an FMU -Tutorial by Johannes Stoljar, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -In this example we want to show that it is possible to create different instances of an FMU. The different instances can then be used to run independent simulations. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum without friction. The object-orientated structure of the *SpringPendulum1D* can be seen in the following graphic. - -![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringPendulum1D.svg?raw=true) - - -## Target group -The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/multiple_instances.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | -| 4. | Install Plots via | add Plots | | - -## Code section - -To run the example, the previously installed packages must be included. - - -```julia -# imports -using FMI -using FMIZoo -using Plots -``` - -### Simulation setup - -Next, the start time and end time of the simulation are set. Finally, the recorded values are specified to store the results of the simulation. - - -```julia -tStart = 0.0 -tStop = 8.0 - -vrs = ["mass.s"] -``` - - - - - 1-element Vector{String}: - "mass.s" - - - -### Import FMU - -In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. - - -```julia -# we use an FMU from the FMIZoo.jl -pathToFMU = get_model_filename("SpringPendulum1D", "Dymola", "2022x") - -myFMU = fmiLoad(pathToFMU) -fmiInfo(myFMU) -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 - - - #################### Begin information for FMU #################### - Model name: SpringPendulum1D - FMI-Version: 2.0 - GUID: {a3e886fa-675c-4308-8e91-3490e598ba11} - Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 - Generation time: 2022-03-03T15:08:57Z - Var. naming conv.: structured - Event indicators: 0 - Inputs: 0 - Outputs: 0 - States: 2 - 33554432 ["mass.s"] - 33554433 ["mass.v"] - Supports Co-Simulation: true - Model identifier: SpringPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - Var. com. steps: true - Input interpol.: true - Max order out. der.: 1 - Supports Model-Exchange: true - Model identifier: SpringPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - ##################### End information for FMU ##################### - - -### First Instance - -To create an instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU. - - -```julia -comp1 = fmiInstantiate!(myFMU; loggingOn=true) -comp1Address= comp1.compAddr -println(comp1) -``` - - FMU: SpringPendulum1D - InstanceName: [not defined] - Address: Ptr{Nothing} @0x0000000003954580 - State: fmi2ComponentStateInstantiated - Logging: false - FMU time: -Inf - FMU states: nothing - - -Next, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $10.0 \frac{N}{m}$ and for the position of the mass `mass.s` a value of $1.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation. - - -```julia -param1 = Dict("spring.c"=>10.0, "mass_s0"=>1.0) -data1 = fmiSimulate(comp1, tStart, tStop; parameters=param1, recordValues=vrs, instantiate=false) -fig = fmiPlot(data1) -``` - - - - - -![svg](multiple_instances_files/multiple_instances_10_0.svg) - - - - -For control, you can compare again the address of the instance to the previous address, and it should be the same address. As soon as this is not the case an error would be thrown by the macro `@assert`. - - -```julia -@assert comp1.compAddr === comp1Address -``` - -### Second Instance - -To create a second instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU. - - -```julia -comp2 = fmiInstantiate!(myFMU; loggingOn=true) -comp2Address= comp2.compAddr -println(comp2) -``` - - FMU: SpringPendulum1D - InstanceName: [not defined] - Address: Ptr{Nothing} @0x000000000529d440 - State: fmi2ComponentStateInstantiated - Logging: false - FMU time: -Inf - FMU states: nothing - - -The addresses of the instantiated FMUs must differ, and you can see that in the comparison below. - - -```julia -@assert comp1Address !== comp2Address -``` - -Again, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $1.0 \frac{N}{m}$ and for the position of the mass `mass.s` a value of $2.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation. - - -```julia -param2 = Dict("spring.c"=>1.0, "mass.s"=>2.0) -data2 = fmiSimulateCS(comp2, tStart, tStop; parameters=param2, recordValues=vrs, instantiate=false) -fmiPlot!(fig, data2) -``` - - - - - -![svg](multiple_instances_files/multiple_instances_18_0.svg) - - - - -For control, you can compare again the address of the instance `comp2` to the previous address `comp2Address` and it should be the same address. - - -```julia -@assert comp2.compAddr === comp2Address -``` - -### Unload FMU - -After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. - - -```julia -fmiUnload(myFMU) -``` - -### Summary - -Based on the example it can be seen that it is possible to create different instances of an FMU. The different instances can then be used to perform different simulations. diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg deleted file mode 100644 index cf0fca99..00000000 --- a/docs/src/examples/multiple_instances_files/multiple_instances_10_0.svg +++ /dev/null @@ -1,902 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg b/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg deleted file mode 100644 index 8004ffcf..00000000 --- a/docs/src/examples/multiple_instances_files/multiple_instances_18_0.svg +++ /dev/null @@ -1,1708 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/multiprocessing.md b/docs/src/examples/multiprocessing.md deleted file mode 100644 index 365cdee4..00000000 --- a/docs/src/examples/multiprocessing.md +++ /dev/null @@ -1,279 +0,0 @@ -# Multiprocessing -Tutorial by Jonas Wilfert, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings. -Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multiprocessing**, check `multithreading.ipynb` for multithreading. -Advantage of multithreading is a lower communication overhead as well as lower RAM usage. -However in some cases multiprocessing can be faster as the garbage collector is not shared. - - -The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. - -![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) - - -## Target group -The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/distributed.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | -| 4. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " | -| 5. | Install BenchmarkTools via | add BenchmarkTools | | - -## Code section - - - -Adding your desired amount of processes: - - -```julia -using Distributed -n_procs = 4 -addprocs(n_procs; exeflags=`--project=$(Base.active_project()) --threads=auto`, restrict=false) -``` - - - - - 4-element Vector{Int64}: - 2 - 3 - 4 - 5 - - - -To run the example, the previously installed packages must be included. - - -```julia -# imports -@everywhere using FMI -@everywhere using FMIZoo -@everywhere using BenchmarkTools -``` - -Checking that we workers have been correctly initialized: - - -```julia -workers() - -@everywhere println("Hello World!") - -# The following lines can be uncommented for more advanced informations about the subprocesses -# @everywhere println(pwd()) -# @everywhere println(Base.active_project()) -# @everywhere println(gethostname()) -# @everywhere println(VERSION) -# @everywhere println(Threads.nthreads()) -``` - - Hello World! - From worker 2: Hello World! - From worker 4: Hello World! - From worker 3: Hello World! - From worker 5: Hello World! - - -### Simulation setup - -Next, the batch size and input values are defined. - - -```julia - -# Best if batchSize is a multiple of the threads/cores -batchSize = 16 - -# Define an array of arrays randomly -input_values = collect(collect.(eachrow(rand(batchSize,2)))) -``` - - - - - 16-element Vector{Vector{Float64}}: - [0.053272555584304104, 0.45774751559489646] - [0.5896778258750763, 0.12435199368996086] - [0.5651662129022856, 0.8764873667695812] - [0.6176612662918868, 0.2785804850450695] - [0.9274233385552415, 0.38275426899967724] - [0.46094177953642124, 0.6554519159504497] - [0.73421590884579, 0.28177572874256906] - [0.5575198504784948, 0.3212214708846175] - [0.271126562512229, 0.6499895887749823] - [0.5289045741655536, 0.4873381265273107] - [0.8565770844036877, 0.2312687408548988] - [0.06332369482582334, 0.44807066874864065] - [0.08611017776660712, 0.960898209225902] - [0.3191189843443898, 0.30014344015893846] - [0.028884098958377402, 0.5285860311385517] - [0.7282727650515579, 0.7584435212215901] - - - -### Shared Module -For Distributed we need to embed the FMU into its own `module`. This prevents Distributed from trying to serialize and send the FMU over the network, as this can cause issues. This module needs to be made available on all processes using `@everywhere`. - - -```julia -@everywhere module SharedModule - using FMIZoo - using FMI - - t_start = 0.0 - t_step = 0.1 - t_stop = 10.0 - tspan = (t_start, t_stop) - tData = collect(t_start:t_step:t_stop) - - model_fmu = FMIZoo.fmiLoad("SpringPendulum1D", "Dymola", "2022x") -end -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`. - [ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources` - [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources` - [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources` - [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - [ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources` - [ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - - -We define a helper function to calculate the FMU and combine it into an Matrix. - - -```julia -@everywhere function runCalcFormatted(fmu, x0, recordValues=["mass.s", "mass.v"]) - data = fmiSimulateME(fmu, SharedModule.t_start, SharedModule.t_stop; recordValues=recordValues, saveat=SharedModule.tData, x0=x0, showProgress=false, dtmax=1e-4) - return reduce(hcat, data.states.u) -end -``` - -Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools. - - -```julia -@benchmark data = runCalcFormatted(SharedModule.model_fmu, rand(2)) -``` - - - - - BenchmarkTools.Trial: 17 samples with 1 evaluation. - Range (min … max): 304.291 ms … 325.332 ms ┊ GC (min … max): 7.41% … 6.89% - Time (median): 307.274 ms ┊ GC (median): 7.37% - Time (mean ± σ): 309.397 ms ±  5.860 ms ┊ GC (mean ± σ): 7.94% ± 1.32% - - █▁▁ ▁█ ▁▁  █▁▁                   ▁ ▁ ▁                      ▁  - ███▁██▁██▁▁███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁█▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 304 ms Histogram: frequency by time 325 ms < - - Memory estimate: 146.80 MiB, allocs estimate: 3002433. - - - -### Single Threaded Batch Execution -To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call. - - -```julia -println("Single Threaded") -@benchmark collect(runCalcFormatted(SharedModule.model_fmu, i) for i in input_values) -``` - - Single Threaded - - - - - - BenchmarkTools.Trial: 2 samples with 1 evaluation. - Range (min … max): 4.966 s …  4.967 s ┊ GC (min … max): 8.58% … 8.12% - Time (median): 4.966 s ┊ GC (median): 8.35% - Time (mean ± σ): 4.966 s ± 1.039 ms ┊ GC (mean ± σ): 8.35% ± 0.33% - - █                                                      █  - █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 4.97 s Histogram: frequency by time 4.97 s < - - Memory estimate: 2.29 GiB, allocs estimate: 48038916. - - - -### Multithreaded Batch Execution -In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe. -To spread the execution of a function to multiple processes, the function `pmap` can be used. - - -```julia -println("Multi Threaded") -@benchmark pmap(i -> runCalcFormatted(SharedModule.model_fmu, i), input_values) -``` - - Multi Threaded - - - - - - BenchmarkTools.Trial: 2 samples with 1 evaluation. - Range (min … max): 3.069 s …  3.078 s ┊ GC (min … max): 0.00% … 0.00% - Time (median): 3.074 s ┊ GC (median): 0.00% - Time (mean ± σ): 3.074 s ± 6.467 ms ┊ GC (mean ± σ): 0.00% ± 0.00% - - █                                                      █  - █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 3.07 s Histogram: frequency by time 3.08 s < - - Memory estimate: 81.31 KiB, allocs estimate: 1192. - - - -As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `n_procs` (or the number of physical cores of your CPU), this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` Julia processes. - -### Unload FMU - -After calculating the data, the FMU is unloaded and all unpacked data on disc is removed. - - -```julia -@everywhere fmiUnload(SharedModule.model_fmu) -``` - -### Summary - -In this tutorial it is shown how multi processing with `Distributed.jl` can be used to improve the performance for calculating a Batch of FMUs. diff --git a/docs/src/examples/multithreading.md b/docs/src/examples/multithreading.md deleted file mode 100644 index 3f1d0979..00000000 --- a/docs/src/examples/multithreading.md +++ /dev/null @@ -1,254 +0,0 @@ -# Multithreading -Tutorial by Jonas Wilfert, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings. -Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multithreading**, check `multiprocessing.ipynb` for multiprocessing. -Advantage of multithreading is a lower communication overhead as well as lower RAM usage. -However in some cases multiprocessing can be faster as the garbage collector is not shared. - - -The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. - -![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) - - -## Target group -The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/parallel.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | -| 4. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " | -| 5. | Install Folds via | add Folds | | -| 6. | Install BenchmarkTools via | add BenchmarkTools | | - -## Code section - -To run the example, the previously installed packages must be included. - - -```julia -# imports -using FMI -using FMIZoo -using Folds -using BenchmarkTools -``` - -First, check the amount of available threads: - - -```julia -Threads.nthreads() -``` - - - - - 1 - - - -If the number of available threads doesn't match your expections, you can increase the number of threads available to the Julia process like described [here](https://docs.julialang.org/en/v1/manual/multi-threading/#Starting-Julia-with-multiple-threads). - -### Simulation setup - -Next, the start time and end time of the simulation are set. Here we also decide the size of the batch. - - -```julia -t_start = 0.0 -t_step = 0.1 -t_stop = 10.0 -tspan = (t_start, t_stop) -tData = collect(t_start:t_step:t_stop) - -# Best if batchSize is a multiple of the threads/cores -batchSize = Threads.nthreads() - -# Define an array of arrays randomly -input_values = collect(collect.(eachrow(rand(batchSize,2)))) - -``` - - - - - 1-element Vector{Vector{Float64}}: - [0.769193342919982, 0.5516183754569333] - - - -We need to instantiate one FMU for each parallel execution, as they cannot be easily shared among different threads. - - -```julia -# a single FMU to compare the performance -realFMU = fmiLoad("SpringPendulum1D", "Dymola", "2022x") - -# the FMU batch -realFMUBatch = [fmiLoad("SpringPendulum1D", "Dymola", "2022x") for _ in 1:batchSize] -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 - ┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193 - - - - - - 1-element Vector{FMU2}: - Model name: SpringPendulum1D - Type: 1 - - - -We define a helper function to calculate the FMU solution and combine it into an Matrix. - - -```julia -function runCalcFormatted(fmu::FMU2, x0::Vector{Float64}, recordValues::Vector{String}=["mass.s", "mass.v"]) - data = fmiSimulateME(fmu, t_start, t_stop; recordValues=recordValues, saveat=tData, x0=x0, showProgress=false, dtmax=1e-4) - return reduce(hcat, data.states.u) -end -``` - - - - - runCalcFormatted (generic function with 2 methods) - - - -Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools. - - -```julia -@benchmark data = runCalcFormatted(realFMU, rand(2)) -``` - - - - - BenchmarkTools.Trial: 15 samples with 1 evaluation. - Range (min … max): 337.943 ms … 357.340 ms ┊ GC (min … max): 7.03% … 6.55% - Time (median): 339.287 ms ┊ GC (median): 7.00% - Time (mean ± σ): 342.299 ms ±  5.982 ms ┊ GC (mean ± σ): 7.39% ± 1.12% - - ▃█                                                             - ██▇▇▇▇▁▁▇▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇ ▁ - 338 ms Histogram: frequency by time 357 ms < - - Memory estimate: 146.80 MiB, allocs estimate: 3002433. - - - -### Single Threaded Batch Execution -To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call. - - -```julia -println("Single Threaded") -@benchmark collect(runCalcFormatted(realFMU, i) for i in input_values) -``` - - Single Threaded - - - - - - BenchmarkTools.Trial: 15 samples with 1 evaluation. - Range (min … max): 338.941 ms … 359.792 ms ┊ GC (min … max): 7.42% … 7.05% - Time (median): 340.880 ms ┊ GC (median): 7.45% - Time (mean ± σ): 343.682 ms ±  6.291 ms ┊ GC (mean ± σ): 7.89% ± 1.20% - - █▁▁▁▁█  ▁▁▁    ▁                        ▁▁                  ▁  - ██████▁▁███▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ - 339 ms Histogram: frequency by time 360 ms < - - Memory estimate: 146.80 MiB, allocs estimate: 3002436. - - - -### Multithreaded Batch Execution -In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe. -To spread the execution of a function to multiple threads, the library `Folds` can be used. - - -```julia -println("Multi Threaded") -@benchmark Folds.collect(runCalcFormatted(fmu, i) for (fmu, i) in zip(realFMUBatch, input_values)) -``` - - Multi Threaded - - - - - - BenchmarkTools.Trial: 17 samples with 1 evaluation. - Range (min … max): 307.665 ms … 325.644 ms ┊ GC (min … max): 8.44% … 8.13% - Time (median): 308.448 ms ┊ GC (median): 8.55% - Time (mean ± σ): 310.319 ms ±  4.970 ms ┊ GC (mean ± σ): 8.72% ± 0.86% - - █ █ ▁   ▁                                                      - █▆█▆█▁▆▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆ ▁ - 308 ms Histogram: frequency by time 326 ms < - - Memory estimate: 146.80 MiB, allocs estimate: 3002440. - - - -As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `Threads.nthreads()`, this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` threads for the Julia process. - -### Unload FMU - -After calculating the data, the FMU is unloaded and all unpacked data on disc is removed. - - -```julia -fmiUnload(realFMU) -fmiUnload.(realFMUBatch) -``` - - - - - 1-element Vector{Nothing}: - nothing - - - -### Summary - -In this tutorial it is shown how multi threading with `Folds.jl` can be used to improve the performance for calculating a Batch of FMUs. diff --git a/docs/src/examples/parameterize.md b/docs/src/examples/parameterize.md deleted file mode 100644 index 67856f28..00000000 --- a/docs/src/examples/parameterize.md +++ /dev/null @@ -1,312 +0,0 @@ -# Manually parameterize an FMU -Tutorial by Johannes Stoljar, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -This example shows how the manually parameterization of an FMU works if very specific adjustments during system initialization is needed. For this purpose, an IO-FMU model is loaded and the various commands for parameterization are shown on the basis of this model. With this example the user shall be guided how to make certain settings at an FMU. Please note, that parameterization of a simulation is possible in a much easier fashion: Using `fmiSimulate`, `fmiSimulateME` or `fmiSimulateCS` together with a parameter dictionary for the keyword `parameters`. - -## Target group -The example is primarily intended for users who work in the field of simulation exchange. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/CS_simulate.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | - -## Code section - -To run the example, the previously installed packages must be included. - - -```julia -# imports -using FMI -using FMIZoo -``` - -### Simulation setup - -Next, the start time and end time of the simulation are set. - - -```julia -tStart = 0.0 -tStop = 8.0 -``` - - - - - 8.0 - - - -### Import FMU - -In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. - - -```julia -# we use an FMU from the FMIZoo.jl -pathToFMU = get_model_filename("IO", "Dymola", "2022x") - -myFMU = fmiLoad(pathToFMU) -fmiInfo(myFMU) -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 - - - #################### Begin information for FMU #################### - Model name: IO - FMI-Version: 2.0 - GUID: {ac3b4a99-4908-40f7-89da-2d5c08b3c4ac} - Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 - Generation time: 2022-03-17T07:40:55Z - Var. naming conv.: structured - Event indicators: 4 - Inputs: 3 - 352321536 ["u_real"] - 352321537 ["u_boolean"] - 352321538 ["u_integer"] - Outputs: 3 - 335544320 ["y_real"] - 335544321 ["y_boolean"] - 335544322 ["y_integer"] - States: 0 - Supports Co-Simulation: true - Model identifier: IO - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - Var. com. steps: true - Input interpol.: true - Max order out. der.: 1 - Supports Model-Exchange: true - Model identifier: IO - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - ##################### End information for FMU ##################### - - -### Instantiate and Setup FMU - -Next it is necessary to create an instance of the FMU. This is achieved by the command `fmiInstantiate!()`. - - -```julia -fmiInstantiate!(myFMU; loggingOn=true) -``` - - - - - FMU: IO - InstanceName: [not defined] - Address: Ptr{Nothing} @0x00000000029c12e0 - State: fmi2ComponentStateInstantiated - Logging: true - FMU time: -Inf - FMU states: nothing - - - -In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. - - -```julia -fmiSetupExperiment(myFMU, tStart, tStop) -``` - - - - - 0x00000000 - - - -### Parameterize FMU - -To parameterize an FMU, the FMU must be in the initialization mode, which is reached with the `fmiEnterInitializationMode()` command. - - -```julia -fmiEnterInitializationMode(myFMU) -``` - - - - - 0x00000000 - - - -Within this mode it is then possible to change the different parameters. In this example, for each data type (`real`, `integer`, `boolean` and `string)` a corresponding parameter is selected. At the beginning the initial state of these parameters is displayed with `fmiGet()`. - - -```julia -params = ["p_real", "p_integer", "p_boolean", "p_string"] -fmiGet(myFMU, params) -``` - - - - - 4-element Vector{Any}: - 0.0 - 0 - 0 - "Hello World!" - - - -In the next step, a function is defined that generates a random value for each parameter. For the parameter `p_string` a random number is inserted into the string. All parameters are combined to a vector and output. - - -```julia -function generateRandomNumbers() - rndReal = 100 * rand() - rndInteger = round(Integer, 100 * rand()) - rndBoolean = rand() > 0.5 - rndString = "Random number $(100 * rand())!" - - randValues = [rndReal, rndInteger, rndBoolean, rndString] - println(randValues) - return randValues -end -``` - - - - - generateRandomNumbers (generic function with 1 method) - - - -The previously defined function is called and the results are displayed in the console. - - -```julia -paramsVal = generateRandomNumbers(); -``` - - Any[27.27027116078753, 50, true, "Random number 83.09640957659121!"] - - -#### First variant - -With this variant it is quickly possible to set all parameters at once. Even different data types can be set with only one command. The command `fmiSet()` selects itself which function is chosen for which data type. After setting the parameters, it is checked whether the corresponding parameters were set correctly. For this the function `fmiGet()` is used as above and afterwards with the macro `@assert` also tested whether the correct values are set. - - -```julia -fmiSet(myFMU, params, paramsVal) -values = fmiGet(myFMU, params) -print(values) - -@assert paramsVal == values -``` - - Any[27.27027116078753, 50, 1, "Random number 83.09640957659121!"] - -#### Second variant - -To make sure that the functions work it is necessary to generate random numbers again. As shown already, we call the defined function `generateRandomNumbers()` and output the values. - - -```julia -rndReal, rndInteger, rndBoolean, rndString = generateRandomNumbers(); -``` - - Any[54.98169316988619, 76, true, "Random number 39.54384075977397!"] - - -In the second variant, the value for each data type is set separately by the corresponding command. By this variant one has the maximum control and can be sure that also the correct data type is set. To illustrate the functionality of the parameterization with the separate functions, the corresponding get function is also called separately for each data type: -* `fmiSetReal()` <---> `fmiGetReal()` -* `fmiSetInteger()` <---> `fmiGetInteger()` -* `fmiSetBoolean()` <---> `fmiGetBoolean()` -* `fmiSetString()` <---> `fmiGetString()`. - - -```julia -fmiSetReal(myFMU, "p_real", rndReal) -display("$rndReal == $(fmiGetReal(myFMU, "p_real"))") - -fmiSetInteger(myFMU, "p_integer", rndInteger) -display("$rndInteger == $(fmiGetInteger(myFMU, "p_integer"))") - -fmiSetBoolean(myFMU, "p_boolean", rndBoolean) -display("$rndBoolean == $(fmiGetBoolean(myFMU, "p_boolean"))") - -fmiSetString(myFMU, "p_string", rndString) -display("$rndString == $(fmiGetString(myFMU, "p_string"))") -``` - - - "54.98169316988619 == 54.98169316988619" - - - - "76 == 76" - - - - "true == 1" - - - - "Random number 39.54384075977397! == Random number 39.54384075977397!" - - -After seeing that both variants set the parameters correctly, the initialization mode is terminated with the function `fmiExitInitializationMode()`. - - -```julia -fmiExitInitializationMode(myFMU) -``` - - - - - 0x00000000 - - - -From here on, you may want to simulate the FMU. Please note, that with the default `executionConfig`, it is necessary to prevent a new instantiation using the keyword `instantiate=false`. Otherwise, a new instance is allocated for the simulation-call and the parameters set for the previous instance are not transfered. - -Example: -`fmiSimulate(...; instantiate=false, ...)` - -### Unload FMU - -The FMU will be unloaded and all unpacked data on disc will be removed. - - -```julia -fmiUnload(myFMU) -``` - -### Summary - -Based on this tutorial it can be seen that there are two different variants to set and get parameters.These examples should make it clear to the user how parameters can also be set with different data types. diff --git a/docs/src/examples/simulate.md b/docs/src/examples/simulate.md deleted file mode 100644 index b208de41..00000000 --- a/docs/src/examples/simulate.md +++ /dev/null @@ -1,245 +0,0 @@ -# Simulate an FMU in different modes -Tutorial by Johannes Stoljar, Tobias Thummerer - -## License -Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar - -Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details. - -## Motivation -This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation. - -## Introduction to the example -In this example we want to show how fast and easy the simulation for an FMU is. For this purpose, the FMU is simulated in co-simulation mode and in model-exchange mode. After the FMU has been simulated, the simulation results are displayed in a graph. The graphs of the different modes are compared with each other. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic. - -![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) - - -## Target group -The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia. - - -## Other formats -Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/simulate.md) corresponding to the notebook. - - -## Getting started - -### Installation prerequisites -| | Description | Command | Alternative | -|:----|:----------------------------------|:--------------------------|:-----------------------------------------------| -| 1. | Enter Package Manager via | ] | | -| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " | -| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " | -| 4. | Install Plots via | add Plots | | - -## Code section - -To run the example, the previously installed packages must be included. - - -```julia -# imports -using FMI -using FMIZoo -using Plots -``` - -### Simulation setup - -Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. - - -```julia -tStart = 0.0 -tStep = 0.01 -tStop = 8.0 -tSave = tStart:tStep:tStop -``` - - - - - 0.0:0.01:8.0 - - - -### Import FMU - -In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown. - - -```julia -# we use an FMU from the FMIZoo.jl -pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x") - -myFMU = fmiLoad(pathToFMU) -# fmiLoad("path/to/myFMU.fmu"; unpackPath = "path/to/unpacked/fmu/") - -fmiInfo(myFMU) -``` - - ┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75 - ┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources` - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190 - ┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified. - └ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193 - - - #################### Begin information for FMU #################### - Model name: SpringFrictionPendulum1D - FMI-Version: 2.0 - GUID: {df491d8d-0598-4495-913e-5b025e54d7f2} - Generation tool: Dymola Version 2022x (64-bit), 2021-10-08 - Generation time: 2022-03-03T15:09:18Z - Var. naming conv.: structured - Event indicators: 24 - Inputs: 0 - Outputs: 0 - States: 2 - 33554432 ["mass.s"] - 33554433 ["mass.v", "mass.v_relfric"] - Supports Co-Simulation: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - Var. com. steps: true - Input interpol.: true - Max order out. der.: 1 - Supports Model-Exchange: true - Model identifier: SpringFrictionPendulum1D - Get/Set State: true - Serialize State: true - Dir. Derivatives: true - ##################### End information for FMU ##################### - - -### Simulate FMU - -In the following, the FMU is simulated in the two different simulation modes. - -#### Simulate as Co-Simulation - -In the next steps the recorded values are defined. The first state is the position of the mass and the second state is the velocity. In the function `fmiSimulateCS()` the FMU is simulated in co-simulation mode (CS) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time and the recorded variables are specified. - - -```julia -vrs = ["mass.s", "mass.v"] - -dataCS = fmiSimulateCS(myFMU, tStart, tStop; recordValues=vrs, saveat=tSave) -``` - - - - - Model name: - SpringFrictionPendulum1D - Success: - true - Values [801]: - 0.0 (0.5, 0.0) - 0.01 (0.5002235448486548, 0.042692491939260585) - 0.02 (0.5008715291319449, 0.08568000508550636) - 0.03 (0.5019478597521578, 0.12892136998736314) - 0.04 (0.5034570452098334, 0.17232325681284336) - 0.05 (0.5053993458877354, 0.2158440857658765) - 0.06 (0.5077764240578201, 0.259420181133082) - 0.07 (0.5105886522837868, 0.30295578207463486) - 0.08 (0.5138351439717114, 0.3464184707972189) - ... - 8.0 (1.071367253976742, -1.000814138594347e-10) - Events [0]: - - - - -#### Simulate as Model-Exchange - -In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time are specified. In contrast to the co-simulation, the values to be stored are not specified here, since the states and events of the FMU are always output as well. The identifiers given above just correspond to the states of the FMU. - - -```julia -dataME = fmiSimulateME(myFMU, tStart, tStop; saveat=tSave) -``` - - Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09 - - - - - - Model name: - SpringFrictionPendulum1D - Success: - true - States [801]: - 0.0 [0.5, 0.0] - 0.01 [0.5002131418344649, 0.042689450666241] - 0.02 [0.5008548874805565, 0.08570846215523381] - 0.03 [0.5019281653120716, 0.12898389312495082] - 0.04 [0.5034351805057593, 0.17244393475170294] - 0.05 [0.5053774287967188, 0.2160182432854046] - 0.06 [0.5077556967622916, 0.25963796675862466] - 0.07 [0.5105701003205937, 0.3032358690888718] - 0.08 [0.5138201049458624, 0.34674641820324037] - ... - 8.0 [1.0668213438183276, -1.0000099359121942e-10] - Events [6]: - State-Event #11 @ 0.0s - State-Event #11 @ 0.9939s - State-Event #19 @ 1.9881s - State-Event #11 @ 2.9829s - State-Event #19 @ 3.9787s - State-Event #11 @ 4.9768s - - - - -### Plotting FMU - -After the simulation is finished the results of the FMU for the co-simulation and model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time. - - -```julia -fmiPlot(dataCS) -``` - - - - - -![svg](simulate_files/simulate_12_0.svg) - - - - - -```julia -fmiPlot(dataME) -``` - - - - - -![svg](simulate_files/simulate_13_0.svg) - - - - -From both graphs it can be seen that the simulation calculates exactly the same results. - -### Unload FMU - -After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. - - -```julia -fmiUnload(myFMU) -``` - -### Summary - -Based on this tutorial it can be seen that simulating in the different mode is very easy, and it only takes a few commands to simulate the FMU. diff --git a/docs/src/examples/simulate_files/simulate_12_0.svg b/docs/src/examples/simulate_files/simulate_12_0.svg deleted file mode 100644 index 6f603526..00000000 --- a/docs/src/examples/simulate_files/simulate_12_0.svg +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/examples/simulate_files/simulate_13_0.svg b/docs/src/examples/simulate_files/simulate_13_0.svg deleted file mode 100644 index 2dc08e6e..00000000 --- a/docs/src/examples/simulate_files/simulate_13_0.svg +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/manipulation.ipynb b/example/manipulation.ipynb deleted file mode 100644 index eb98a208..00000000 --- a/example/manipulation.ipynb +++ /dev/null @@ -1,839 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Manipulate a function\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "This example shows how to overwrite a library function with an own function. For this the FMU model is simulated first without changes. Then the function `fmi2GetReal()` is overwritten and simulated again. Both simulations are displayed in a graph to show the change caused by overwriting the function. The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/manipulation.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install FMICore via | add FMICore | add \" https://github.com/ThummeTo/FMICore.jl \" |\n", - "| 5. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:15:09.601000Z", - "iopub.status.busy": "2022-06-01T15:15:08.923000Z", - "iopub.status.idle": "2022-06-01T15:15:32.386000Z", - "shell.execute_reply": "2022-06-01T15:15:32.310000Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using FMICore\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:15:41.170000Z", - "iopub.status.busy": "2022-06-01T15:15:32.388000Z", - "iopub.status.idle": "2022-06-01T15:15:41.848000Z", - "shell.execute_reply": "2022-06-01T15:15:41.848000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStop = 8.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:15:41.877000Z", - "iopub.status.busy": "2022-06-01T15:15:41.877000Z", - "iopub.status.idle": "2022-06-01T15:15:46.248000Z", - "shell.execute_reply": "2022-06-01T15:15:46.248000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringFrictionPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t24\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulate FMU\n", - "\n", - "In the next steps the recorded value is defined. The recorded value is the position of the mass. In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size. In addition, the start and end time and the recorded variables are specified." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:15:46.250000Z", - "iopub.status.busy": "2022-06-01T15:15:46.250000Z", - "iopub.status.idle": "2022-06-01T15:16:04.451000Z", - "shell.execute_reply": "2022-06-01T15:16:04.450000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10\u001b[39m\n" - ] - }, - { - "data": { - "text/plain": [ - "Model name:\n", - "\tSpringFrictionPendulum1D\n", - "Success:\n", - "\ttrue\n", - "States [110]:\n", - "\t0.0\t[0.5, 0.0]\n", - "\t2.3529411764719727e-11\t[0.5, 1.0e-10]\n", - "\t1.0000023529411766e-5\t[0.5000000002125017, 4.250030186348503e-5]\n", - "\t0.00011000002352941177\t[0.5000000257134062, 0.0004675245102952289]\n", - "\t0.0011100000235294118\t[0.5000026191281834, 0.004719970360497647]\n", - "\t0.011110000023529413\t[0.5002631686645611, 0.047449647283752144]\n", - "\t0.03982466736770743\t[0.5034050123596227, 0.17168075110950387]\n", - "\t0.09972054285078226\t[0.5215006197560228, 0.43204954153497455]\n", - "\t0.16481836271111422\t[0.5585747156842935, 0.703758265932321]\n", - "\t...\n", - "\t8.0\t[1.0668213438183276, -1.0000099359121942e-10]\n", - "Values [110]:\n", - "\t0.0\t(0.5,)\n", - "\t2.3529411764719727e-11\t(0.5,)\n", - "\t1.0000023529411766e-5\t(0.5000000002125017,)\n", - "\t0.00011000002352941177\t(0.5000000257134062,)\n", - "\t0.0011100000235294118\t(0.5000026191281834,)\n", - "\t0.011110000023529413\t(0.5002631686645611,)\n", - "\t0.03982466736770743\t(0.5034050123596227,)\n", - "\t0.09972054285078226\t(0.5215006197560228,)\n", - "\t0.16481836271111422\t(0.5585747156842935,)\n", - "\t...\n", - "\t8.0\t(1.0668213438183276,)\n", - "Events [6]:\n", - "\tState-Event #11 @ 0.0s\n", - "\tState-Event #11 @ 0.9939s\n", - "\tState-Event #19 @ 1.9881s\n", - "\tState-Event #11 @ 2.9829s\n", - "\tState-Event #19 @ 3.9787s\n", - "\tState-Event #11 @ 4.9768s\n" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vrs = [\"mass.s\"]\n", - "\n", - "simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plotting FMU\n", - "\n", - "After the simulation is finished, the result of the FMU for the model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:16:04.454000Z", - "iopub.status.busy": "2022-06-01T15:16:04.454000Z", - "iopub.status.idle": "2022-06-01T15:16:23.184000Z", - "shell.execute_reply": "2022-06-01T15:16:23.184000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig = fmiPlot(simData, states=false)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Override Function\n", - "\n", - "After overwriting a function, the previous one is no longer accessible. The original function `fmi2GetReal()` is cached by storing the address of the pointer. The addresses of the pointers are kept in the FMU and are thus accessible." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:16:23.189000Z", - "iopub.status.busy": "2022-06-01T15:16:23.188000Z", - "iopub.status.idle": "2022-06-01T15:16:23.780000Z", - "shell.execute_reply": "2022-06-01T15:16:23.780000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Ptr{Nothing} @0x00007f52e9530faf" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function\n", - "originalGetReal = myFMU.cGetReal" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To overwrite the function `fmi2GetReal!()`, the function header of the new custom function must be identical to the previous one. The function header looks like `fmi2GetReal!(cfunc::Ptr{Nothing}, c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})::fmi2Status`. The information how the FMI2 function are structured can be seen from [FMICore.jl](https://github.com/ThummeTo/FMICore.jl/blob/main/src/FMI2_c.jl#L718) or the FMI2.0.3-specification.\n", - "\n", - "In the new implementation the original function is called by the previously stored pointer. Next there is a special handling if `value` is a pointer to an array. In this case the pointer is treated as an array, so that the entries are accessible. Otherwise, each value in `value` is multiplied by two. Finally, the original state of the original function is output." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:16:23.784000Z", - "iopub.status.busy": "2022-06-01T15:16:23.784000Z", - "iopub.status.idle": "2022-06-01T15:16:24.562000Z", - "shell.execute_reply": "2022-06-01T15:16:24.562000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "myGetReal! (generic function with 1 method)" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, \n", - " nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})\n", - " # first, we do what the original function does\n", - " status = fmi2GetReal!(originalGetReal, c, vr, nvr, value)\n", - "\n", - " # if we have a pointer to an array, we must interprete it as array to access elements\n", - " if isa(value, Ptr{fmi2Real})\n", - " value = unsafe_wrap(Array{fmi2Real}, value, nvr, own=false)\n", - " end\n", - "\n", - " # now, we multiply every value by two (just for fun!)\n", - " for i in 1:nvr \n", - " value[i] *= 2.0 \n", - " end \n", - "\n", - " # return the original status\n", - " return status\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next command the original function is overwritten with the new defined function, for which the command `fmiSetFctGetReal()` is called." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:16:24.566000Z", - "iopub.status.busy": "2022-06-01T15:16:24.565000Z", - "iopub.status.idle": "2022-06-01T15:16:24.578000Z", - "shell.execute_reply": "2022-06-01T15:16:24.578000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Ptr{Nothing} @0x00007f533e325fc0" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# no we overwrite the original function\n", - "fmiSetFctGetReal(myFMU, myGetReal!)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulate and Plot FMU with modified function\n", - "\n", - "As before, the identical command is called here for simulation. This is also a model exchange simulation. Immediately afterwards, the results are added to the previous graph as a dashed line." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:16:24.581000Z", - "iopub.status.busy": "2022-06-01T15:16:24.581000Z", - "iopub.status.idle": "2022-06-01T15:16:24.963000Z", - "shell.execute_reply": "2022-06-01T15:16:24.963000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)\n", - "fmiPlot!(fig, simData; states=false, style=:dash)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As expected by overwriting the function, all values are doubled." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:16:24.967000Z", - "iopub.status.busy": "2022-06-01T15:16:24.967000Z", - "iopub.status.idle": "2022-06-01T15:16:25.011000Z", - "shell.execute_reply": "2022-06-01T15:16:25.011000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "In this tutorial it is shown how an existing function of the library can be replaced by an own implementation. Through this possibility, there are almost no limits for the user, whereby the user can customize the function to his liking." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/modelica_conference_2021.ipynb b/example/modelica_conference_2021.ipynb deleted file mode 100644 index 7210b368..00000000 --- a/example/modelica_conference_2021.ipynb +++ /dev/null @@ -1,560 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Advanced Simulation of an FMU\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "In this example we would like to show that besides the simple simulation of an FMU there is also a more advanced version of the simulation. The advantage of the more advanced variant is that there are more possibilities to intervene in the simulation to make changes. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/modelica_conference_2021.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/modelica_conference_2021.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:16:34.235000Z", - "iopub.status.busy": "2022-06-01T15:16:33.558000Z", - "iopub.status.idle": "2022-06-01T15:16:56.948000Z", - "shell.execute_reply": "2022-06-01T15:16:56.869000Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:05.805000Z", - "iopub.status.busy": "2022-06-01T15:16:56.951000Z", - "iopub.status.idle": "2022-06-01T15:17:06.600000Z", - "shell.execute_reply": "2022-06-01T15:17:06.600000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0.0:0.1:8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStep = 0.1\n", - "tStop = 8.0\n", - "tSave = tStart:tStep:tStop" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simple FMU Simulation\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:06.604000Z", - "iopub.status.busy": "2022-06-01T15:17:06.604000Z", - "iopub.status.idle": "2022-06-01T15:17:10.951000Z", - "shell.execute_reply": "2022-06-01T15:17:10.951000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_ksTsah/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_ksTsah/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringFrictionPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t24\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next commands the FMU is simulated, for which the start and end time and recorded variables are declared. Afterwards the simulation result is shown in a graph. In the plot for the FMU, it can be seen that the oscillation keeps decreasing due to the effect of friction. If one simulates long enough, the oscillation comes to a standstill after a certain time." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:10.954000Z", - "iopub.status.busy": "2022-06-01T15:17:10.953000Z", - "iopub.status.idle": "2022-06-01T15:17:37.913000Z", - "shell.execute_reply": "2022-06-01T15:17:37.913000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "simData = fmiSimulate(myFMU, tStart, tStop; recordValues=[\"mass.s\"], saveat=tSave)\n", - "fmiPlot(simData)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:37.918000Z", - "iopub.status.busy": "2022-06-01T15:17:37.917000Z", - "iopub.status.idle": "2022-06-01T15:17:37.960000Z", - "shell.execute_reply": "2022-06-01T15:17:37.960000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Advanced FMU Simulation\n", - "\n", - "In the following type of simulation a more advanced variant is presented, which allows intervening more in the simulation process. Analogous to the simple variant, an FMU model must be loaded." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:37.962000Z", - "iopub.status.busy": "2022-06-01T15:17:37.962000Z", - "iopub.status.idle": "2022-06-01T15:17:38.024000Z", - "shell.execute_reply": "2022-06-01T15:17:38.024000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_NQAhCe/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_NQAhCe/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" - ] - } - ], - "source": [ - "myFMU = fmiLoad(pathToFMU);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, it is necessary to create an instance of the FMU, this is achieved by the command `fmiInstantiate!()`. " - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:38.028000Z", - "iopub.status.busy": "2022-06-01T15:17:38.027000Z", - "iopub.status.idle": "2022-06-01T15:17:38.349000Z", - "shell.execute_reply": "2022-06-01T15:17:38.349000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "FMU: SpringFrictionPendulum1D\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x00000000064853f0\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", - "FMU time: -Inf\n", - "FMU states: nothing" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "instanceFMU = fmiInstantiate!(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command. Next, the FMU is initialized by the calls of `fmiEnterInitializationMode()` and `fmiExitInitializationMode()`. It would also be possible to set initial states for the FMU between these two commands. " - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:38.353000Z", - "iopub.status.busy": "2022-06-01T15:17:38.352000Z", - "iopub.status.idle": "2022-06-01T15:17:38.617000Z", - "shell.execute_reply": "2022-06-01T15:17:38.617000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiSetupExperiment(instanceFMU, tStart, tStop)\n", - "fmiEnterInitializationMode(instanceFMU)\n", - "# set initial model states\n", - "fmiExitInitializationMode(instanceFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The actual simulation loop is shown in the following block. Here a simulation step `fmiDoStep()` with the fixed step size `tStep` is executed. As indicated in the code by the comments, the input values and output values of the FMU could be changed in the simulation loop as desired, whereby the higher possibility of adjustments arises." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:38.620000Z", - "iopub.status.busy": "2022-06-01T15:17:38.620000Z", - "iopub.status.idle": "2022-06-01T15:17:38.657000Z", - "shell.execute_reply": "2022-06-01T15:17:38.657000Z" - } - }, - "outputs": [], - "source": [ - "for t in tSave\n", - " # set model inputs \n", - " # ...\n", - " fmiDoStep(instanceFMU, tStep)\n", - " # get model outputs\n", - " # ...\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The instantiated FMU must be terminated and then the memory area for the instance can also be deallocated. The last step is to unload the FMU to remove all unpacked data on disc. " - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:38.660000Z", - "iopub.status.busy": "2022-06-01T15:17:38.660000Z", - "iopub.status.idle": "2022-06-01T15:17:38.668000Z", - "shell.execute_reply": "2022-06-01T15:17:38.667000Z" - } - }, - "outputs": [], - "source": [ - "fmiTerminate(instanceFMU)\n", - "fmiFreeInstance!(instanceFMU)\n", - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "The tutorial has shown that besides the usual simple variant of simulating an FMU, there is another way to make more adjustments." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/multiple_instances.ipynb b/example/multiple_instances.ipynb deleted file mode 100644 index 93f49f93..00000000 --- a/example/multiple_instances.ipynb +++ /dev/null @@ -1,3081 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Multiple Instances of an FMU\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "In this example we want to show that it is possible to create different instances of an FMU. The different instances can then be used to run independent simulations. After the FMU has been simulated, the simulation results are displayed in a graph. The used model is a one-dimensional spring pendulum without friction. The object-orientated structure of the *SpringPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/multiple_instances.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/multiple_instances.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:17:48.035000Z", - "iopub.status.busy": "2022-06-01T15:17:47.343000Z", - "iopub.status.idle": "2022-06-01T15:18:10.300000Z", - "shell.execute_reply": "2022-06-01T15:18:10.226000Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set. Finally, the recorded values are specified to store the results of the simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:19.079000Z", - "iopub.status.busy": "2022-06-01T15:18:10.303000Z", - "iopub.status.idle": "2022-06-01T15:18:21.932000Z", - "shell.execute_reply": "2022-06-01T15:18:21.932000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "1-element Vector{String}:\n", - " \"mass.s\"" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStop = 8.0\n", - "\n", - "vrs = [\"mass.s\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:21.935000Z", - "iopub.status.busy": "2022-06-01T15:18:21.935000Z", - "iopub.status.idle": "2022-06-01T15:18:26.345000Z", - "shell.execute_reply": "2022-06-01T15:18:26.345000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_RGs05M/SpringPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_RGs05M/SpringPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{a3e886fa-675c-4308-8e91-3490e598ba11}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:08:57Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t0\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### First Instance\n", - "\n", - "To create an instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:26.348000Z", - "iopub.status.busy": "2022-06-01T15:18:26.348000Z", - "iopub.status.idle": "2022-06-01T15:18:26.776000Z", - "shell.execute_reply": "2022-06-01T15:18:26.776000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "FMU: SpringPendulum1D\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x0000000003954580\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", - "FMU time: -Inf\n", - "FMU states: nothing\n" - ] - } - ], - "source": [ - "comp1 = fmiInstantiate!(myFMU; loggingOn=true)\n", - "comp1Address= comp1.compAddr\n", - "println(comp1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $10.0 \\frac{N}{m}$ and for the position of the mass `mass.s` a value of $1.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:26.779000Z", - "iopub.status.busy": "2022-06-01T15:18:26.779000Z", - "iopub.status.idle": "2022-06-01T15:18:52.116000Z", - "shell.execute_reply": "2022-06-01T15:18:52.116000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "param1 = Dict(\"spring.c\"=>10.0, \"mass_s0\"=>1.0)\n", - "data1 = fmiSimulate(comp1, tStart, tStop; parameters=param1, recordValues=vrs, instantiate=false)\n", - "fig = fmiPlot(data1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For control, you can compare again the address of the instance to the previous address, and it should be the same address. As soon as this is not the case an error would be thrown by the macro `@assert`." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:52.122000Z", - "iopub.status.busy": "2022-06-01T15:18:52.122000Z", - "iopub.status.idle": "2022-06-01T15:18:52.160000Z", - "shell.execute_reply": "2022-06-01T15:18:52.160000Z" - } - }, - "outputs": [], - "source": [ - "@assert comp1.compAddr === comp1Address" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Second Instance\n", - "\n", - "To create a second instance of the FMU it is necessary to call the command `fmiInstantiate!()`. With the component address you now have a unique instance of the FMU." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:52.163000Z", - "iopub.status.busy": "2022-06-01T15:18:52.163000Z", - "iopub.status.idle": "2022-06-01T15:18:52.166000Z", - "shell.execute_reply": "2022-06-01T15:18:52.166000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "FMU: SpringPendulum1D\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x000000000529d440\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: false\n", - "FMU time: -Inf\n", - "FMU states: nothing\n" - ] - } - ], - "source": [ - "comp2 = fmiInstantiate!(myFMU; loggingOn=true)\n", - "comp2Address= comp2.compAddr\n", - "println(comp2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The addresses of the instantiated FMUs must differ, and you can see that in the comparison below." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:52.168000Z", - "iopub.status.busy": "2022-06-01T15:18:52.168000Z", - "iopub.status.idle": "2022-06-01T15:18:52.169000Z", - "shell.execute_reply": "2022-06-01T15:18:52.169000Z" - } - }, - "outputs": [], - "source": [ - "@assert comp1Address !== comp2Address" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Again, a dictionary for the parameters is created. With this dictionary you can set the initial states of the variables of the FMU. For the spring constant `spring.c` a value of $1.0 \\frac{N}{m}$ and for the position of the mass `mass.s` a value of $2.0 m$ is set. The created dictionary with the specified variables for recording are passed to the command for simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:52.171000Z", - "iopub.status.busy": "2022-06-01T15:18:52.171000Z", - "iopub.status.idle": "2022-06-01T15:18:52.280000Z", - "shell.execute_reply": "2022-06-01T15:18:52.280000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "param2 = Dict(\"spring.c\"=>1.0, \"mass.s\"=>2.0)\n", - "data2 = fmiSimulateCS(comp2, tStart, tStop; parameters=param2, recordValues=vrs, instantiate=false)\n", - "fmiPlot!(fig, data2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For control, you can compare again the address of the instance `comp2` to the previous address `comp2Address` and it should be the same address." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:52.288000Z", - "iopub.status.busy": "2022-06-01T15:18:52.288000Z", - "iopub.status.idle": "2022-06-01T15:18:52.289000Z", - "shell.execute_reply": "2022-06-01T15:18:52.289000Z" - } - }, - "outputs": [], - "source": [ - "@assert comp2.compAddr === comp2Address" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:18:52.291000Z", - "iopub.status.busy": "2022-06-01T15:18:52.291000Z", - "iopub.status.idle": "2022-06-01T15:18:52.333000Z", - "shell.execute_reply": "2022-06-01T15:18:52.333000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "Based on the example it can be seen that it is possible to create different instances of an FMU. The different instances can then be used to perform different simulations." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/multiprocessing.ipynb b/example/multiprocessing.ipynb deleted file mode 100644 index 736d07d5..00000000 --- a/example/multiprocessing.ipynb +++ /dev/null @@ -1,516 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Multiprocessing\n", - "Tutorial by Jonas Wilfert, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings.\n", - "Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multiprocessing**, check `multithreading.ipynb` for multithreading.\n", - "Advantage of multithreading is a lower communication overhead as well as lower RAM usage.\n", - "However in some cases multiprocessing can be faster as the garbage collector is not shared.\n", - "\n", - "\n", - "The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/distributed.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/distributed.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install FMICore via | add FMICore | add \" https://github.com/ThummeTo/FMICore.jl \" |\n", - "| 5. | Install BenchmarkTools via | add BenchmarkTools | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Adding your desired amount of processes:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:20:33.662000Z", - "iopub.status.busy": "2022-06-18T14:20:32.980000Z", - "iopub.status.idle": "2022-06-18T14:20:45.287000Z", - "shell.execute_reply": "2022-06-18T14:20:45.259000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Int64}:\n", - " 2\n", - " 3\n", - " 4\n", - " 5" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "using Distributed\n", - "n_procs = 4\n", - "addprocs(n_procs; exeflags=`--project=$(Base.active_project()) --threads=auto`, restrict=false)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:20:45.290000Z", - "iopub.status.busy": "2022-06-18T14:20:45.289000Z", - "iopub.status.idle": "2022-06-18T14:21:31.517000Z", - "shell.execute_reply": "2022-06-18T14:21:31.517000Z" - } - }, - "outputs": [], - "source": [ - "# imports\n", - "@everywhere using FMI\n", - "@everywhere using FMIZoo\n", - "@everywhere using BenchmarkTools" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Checking that we workers have been correctly initialized:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:21:31.917000Z", - "iopub.status.busy": "2022-06-18T14:21:31.520000Z", - "iopub.status.idle": "2022-06-18T14:21:32.071000Z", - "shell.execute_reply": "2022-06-18T14:21:32.071000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello World!\n", - " From worker 2:\tHello World!\n", - " From worker 4:\tHello World!\n", - " From worker 3:\tHello World!\n", - " From worker 5:\tHello World!\n" - ] - } - ], - "source": [ - "workers()\n", - "\n", - "@everywhere println(\"Hello World!\")\n", - "\n", - "# The following lines can be uncommented for more advanced informations about the subprocesses\n", - "# @everywhere println(pwd())\n", - "# @everywhere println(Base.active_project())\n", - "# @everywhere println(gethostname())\n", - "# @everywhere println(VERSION)\n", - "# @everywhere println(Threads.nthreads())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the batch size and input values are defined." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:21:32.074000Z", - "iopub.status.busy": "2022-06-18T14:21:32.074000Z", - "iopub.status.idle": "2022-06-18T14:21:35.419000Z", - "shell.execute_reply": "2022-06-18T14:21:35.419000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "16-element Vector{Vector{Float64}}:\n", - " [0.053272555584304104, 0.45774751559489646]\n", - " [0.5896778258750763, 0.12435199368996086]\n", - " [0.5651662129022856, 0.8764873667695812]\n", - " [0.6176612662918868, 0.2785804850450695]\n", - " [0.9274233385552415, 0.38275426899967724]\n", - " [0.46094177953642124, 0.6554519159504497]\n", - " [0.73421590884579, 0.28177572874256906]\n", - " [0.5575198504784948, 0.3212214708846175]\n", - " [0.271126562512229, 0.6499895887749823]\n", - " [0.5289045741655536, 0.4873381265273107]\n", - " [0.8565770844036877, 0.2312687408548988]\n", - " [0.06332369482582334, 0.44807066874864065]\n", - " [0.08611017776660712, 0.960898209225902]\n", - " [0.3191189843443898, 0.30014344015893846]\n", - " [0.028884098958377402, 0.5285860311385517]\n", - " [0.7282727650515579, 0.7584435212215901]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "\n", - "# Best if batchSize is a multiple of the threads/cores\n", - "batchSize = 16\n", - "\n", - "# Define an array of arrays randomly\n", - "input_values = collect(collect.(eachrow(rand(batchSize,2))))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Shared Module\n", - "For Distributed we need to embed the FMU into its own `module`. This prevents Distributed from trying to serialize and send the FMU over the network, as this can cause issues. This module needs to be made available on all processes using `@everywhere`." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:21:35.423000Z", - "iopub.status.busy": "2022-06-18T14:21:35.422000Z", - "iopub.status.idle": "2022-06-18T14:21:47.166000Z", - "shell.execute_reply": "2022-06-18T14:21:47.166000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_R8823R/SpringPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_R8823R/SpringPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_xI4R81/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_qUcQP8/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_S33uq0/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_M7VjAQ/SpringPendulum1D`.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_xI4R81/SpringPendulum1D/resources`\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_qUcQP8/SpringPendulum1D/resources`\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_S33uq0/SpringPendulum1D/resources`\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU resources location is `file:////tmp/fmijl_M7VjAQ/SpringPendulum1D/resources`\n", - "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mfmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n" - ] - } - ], - "source": [ - "@everywhere module SharedModule\n", - " using FMIZoo\n", - " using FMI\n", - "\n", - " t_start = 0.0\n", - " t_step = 0.1\n", - " t_stop = 10.0\n", - " tspan = (t_start, t_stop)\n", - " tData = collect(t_start:t_step:t_stop)\n", - "\n", - " model_fmu = FMIZoo.fmiLoad(\"SpringPendulum1D\", \"Dymola\", \"2022x\")\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We define a helper function to calculate the FMU and combine it into an Matrix." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:21:47.169000Z", - "iopub.status.busy": "2022-06-18T14:21:47.169000Z", - "iopub.status.idle": "2022-06-18T14:21:47.459000Z", - "shell.execute_reply": "2022-06-18T14:21:47.458000Z" - } - }, - "outputs": [], - "source": [ - "@everywhere function runCalcFormatted(fmu, x0, recordValues=[\"mass.s\", \"mass.v\"])\n", - " data = fmiSimulateME(fmu, SharedModule.t_start, SharedModule.t_stop; recordValues=recordValues, saveat=SharedModule.tData, x0=x0, showProgress=false, dtmax=1e-4)\n", - " return reduce(hcat, data.states.u)\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:21:47.461000Z", - "iopub.status.busy": "2022-06-18T14:21:47.461000Z", - "iopub.status.idle": "2022-06-18T14:22:23.804000Z", - "shell.execute_reply": "2022-06-18T14:22:23.804000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m304.291 ms\u001b[22m\u001b[39m … \u001b[35m325.332 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.41% … 6.89%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m307.274 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.37%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m309.397 ms\u001b[22m\u001b[39m ± \u001b[32m 5.860 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.94% ± 1.32%\n", - "\n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\u001b[34m▁\u001b[39m\u001b[39m \u001b[39m \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 304 ms\u001b[90m Histogram: frequency by time\u001b[39m 325 ms \u001b[0m\u001b[1m<\u001b[22m\n", - "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "@benchmark data = runCalcFormatted(SharedModule.model_fmu, rand(2))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Single Threaded Batch Execution\n", - "To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:22:23.808000Z", - "iopub.status.busy": "2022-06-18T14:22:23.807000Z", - "iopub.status.idle": "2022-06-18T14:23:01.441000Z", - "shell.execute_reply": "2022-06-18T14:23:01.440000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Single Threaded\n" - ] - }, - { - "data": { - "text/plain": [ - "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m4.966 s\u001b[22m\u001b[39m … \u001b[35m 4.967 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.58% … 8.12%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m4.966 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.35%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m4.966 s\u001b[22m\u001b[39m ± \u001b[32m1.039 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.35% ± 0.33%\n", - "\n", - " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", - " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 4.97 s\u001b[90m Histogram: frequency by time\u001b[39m 4.97 s \u001b[0m\u001b[1m<\u001b[22m\n", - "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m2.29 GiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m48038916\u001b[39m." - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "println(\"Single Threaded\")\n", - "@benchmark collect(runCalcFormatted(SharedModule.model_fmu, i) for i in input_values)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Multithreaded Batch Execution\n", - "In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe.\n", - "To spread the execution of a function to multiple processes, the function `pmap` can be used." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:23:01.444000Z", - "iopub.status.busy": "2022-06-18T14:23:01.444000Z", - "iopub.status.idle": "2022-06-18T14:24:04.804000Z", - "shell.execute_reply": "2022-06-18T14:24:04.804000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Multi Threaded\n" - ] - }, - { - "data": { - "text/plain": [ - "BenchmarkTools.Trial: 2 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m3.069 s\u001b[22m\u001b[39m … \u001b[35m 3.078 s\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m3.074 s \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m3.074 s\u001b[22m\u001b[39m ± \u001b[32m6.467 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m0.00% ± 0.00%\n", - "\n", - " \u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m█\u001b[39m \u001b[39m \n", - " \u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 3.07 s\u001b[90m Histogram: frequency by time\u001b[39m 3.08 s \u001b[0m\u001b[1m<\u001b[22m\n", - "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m81.31 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m1192\u001b[39m." - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "println(\"Multi Threaded\")\n", - "@benchmark pmap(i -> runCalcFormatted(SharedModule.model_fmu, i), input_values)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `n_procs` (or the number of physical cores of your CPU), this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` Julia processes." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After calculating the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:24:04.807000Z", - "iopub.status.busy": "2022-06-18T14:24:04.807000Z", - "iopub.status.idle": "2022-06-18T14:24:04.974000Z", - "shell.execute_reply": "2022-06-18T14:24:04.974000Z" - } - }, - "outputs": [], - "source": [ - "@everywhere fmiUnload(SharedModule.model_fmu)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "In this tutorial it is shown how multi processing with `Distributed.jl` can be used to improve the performance for calculating a Batch of FMUs." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/multithreading.ipynb b/example/multithreading.ipynb deleted file mode 100644 index 7076dfb7..00000000 --- a/example/multithreading.ipynb +++ /dev/null @@ -1,481 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Multithreading\n", - "Tutorial by Jonas Wilfert, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar, Jonas Wilfert\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "This example shows how to parallelize the computation of an FMU in FMI.jl. We can compute a batch of FMU-evaluations in parallel with different initial settings.\n", - "Parallelization can be achieved using multithreading or using multiprocessing. This example shows **multithreading**, check `multiprocessing.ipynb` for multiprocessing.\n", - "Advantage of multithreading is a lower communication overhead as well as lower RAM usage.\n", - "However in some cases multiprocessing can be faster as the garbage collector is not shared.\n", - "\n", - "\n", - "The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/parallel.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/parallel.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install FMICore via | add FMICore | add \" https://github.com/ThummeTo/FMICore.jl \" |\n", - "| 5. | Install Folds via | add Folds | |\n", - "| 6. | Install BenchmarkTools via | add BenchmarkTools | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:24:15.415000Z", - "iopub.status.busy": "2022-06-18T14:24:14.716000Z", - "iopub.status.idle": "2022-06-18T14:24:29.648000Z", - "shell.execute_reply": "2022-06-18T14:24:29.574000Z" - } - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using Folds\n", - "using BenchmarkTools" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First, check the amount of available threads:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:24:29.989000Z", - "iopub.status.busy": "2022-06-18T14:24:29.651000Z", - "iopub.status.idle": "2022-06-18T14:24:30.845000Z", - "shell.execute_reply": "2022-06-18T14:24:30.845000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Threads.nthreads()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the number of available threads doesn't match your expections, you can increase the number of threads available to the Julia process like described [here](https://docs.julialang.org/en/v1/manual/multi-threading/#Starting-Julia-with-multiple-threads)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set. Here we also decide the size of the batch." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:24:30.849000Z", - "iopub.status.busy": "2022-06-18T14:24:30.849000Z", - "iopub.status.idle": "2022-06-18T14:24:34.809000Z", - "shell.execute_reply": "2022-06-18T14:24:34.809000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "1-element Vector{Vector{Float64}}:\n", - " [0.769193342919982, 0.5516183754569333]" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "t_start = 0.0\n", - "t_step = 0.1\n", - "t_stop = 10.0\n", - "tspan = (t_start, t_stop)\n", - "tData = collect(t_start:t_step:t_stop)\n", - "\n", - "# Best if batchSize is a multiple of the threads/cores\n", - "batchSize = Threads.nthreads()\n", - "\n", - "# Define an array of arrays randomly\n", - "input_values = collect(collect.(eachrow(rand(batchSize,2))))\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We need to instantiate one FMU for each parallel execution, as they cannot be easily shared among different threads." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:24:34.812000Z", - "iopub.status.busy": "2022-06-18T14:24:34.812000Z", - "iopub.status.idle": "2022-06-18T14:24:40.193000Z", - "shell.execute_reply": "2022-06-18T14:24:40.193000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_guexAq/SpringPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_guexAq/SpringPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n", - "┌ Info: fmi2Unzip(...): Successfully unzipped 153 files at `/tmp/fmijl_83Dthm/SpringPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_83Dthm/SpringPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/DJ6oi/src/FMI2_ext.jl:193\n" - ] - }, - { - "data": { - "text/plain": [ - "1-element Vector{FMU2}:\n", - " Model name: SpringPendulum1D\n", - "Type: 1" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# a single FMU to compare the performance\n", - "realFMU = fmiLoad(\"SpringPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "# the FMU batch\n", - "realFMUBatch = [fmiLoad(\"SpringPendulum1D\", \"Dymola\", \"2022x\") for _ in 1:batchSize]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We define a helper function to calculate the FMU solution and combine it into an Matrix." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:24:40.198000Z", - "iopub.status.busy": "2022-06-18T14:24:40.197000Z", - "iopub.status.idle": "2022-06-18T14:24:40.840000Z", - "shell.execute_reply": "2022-06-18T14:24:40.839000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "runCalcFormatted (generic function with 2 methods)" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function runCalcFormatted(fmu::FMU2, x0::Vector{Float64}, recordValues::Vector{String}=[\"mass.s\", \"mass.v\"])\n", - " data = fmiSimulateME(fmu, t_start, t_stop; recordValues=recordValues, saveat=tData, x0=x0, showProgress=false, dtmax=1e-4)\n", - " return reduce(hcat, data.states.u)\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Running a single evaluation is pretty quick, therefore the speed can be better tested with BenchmarkTools." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:24:40.843000Z", - "iopub.status.busy": "2022-06-18T14:24:40.843000Z", - "iopub.status.idle": "2022-06-18T14:25:15.703000Z", - "shell.execute_reply": "2022-06-18T14:25:15.703000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m337.943 ms\u001b[22m\u001b[39m … \u001b[35m357.340 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.03% … 6.55%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m339.287 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m342.299 ms\u001b[22m\u001b[39m ± \u001b[32m 5.982 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.39% ± 1.12%\n", - "\n", - " \u001b[39m▃\u001b[39m█\u001b[39m \u001b[34m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m█\u001b[39m▇\u001b[34m▇\u001b[39m\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m▇\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▇\u001b[39m \u001b[39m▁\n", - " 338 ms\u001b[90m Histogram: frequency by time\u001b[39m 357 ms \u001b[0m\u001b[1m<\u001b[22m\n", - "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002433\u001b[39m." - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "@benchmark data = runCalcFormatted(realFMU, rand(2))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Single Threaded Batch Execution\n", - "To compute a batch we can collect multiple evaluations. In a single threaded context we can use the same FMU for every call." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:25:15.707000Z", - "iopub.status.busy": "2022-06-18T14:25:15.707000Z", - "iopub.status.idle": "2022-06-18T14:25:29.068000Z", - "shell.execute_reply": "2022-06-18T14:25:29.068000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Single Threaded\n" - ] - }, - { - "data": { - "text/plain": [ - "BenchmarkTools.Trial: 15 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m338.941 ms\u001b[22m\u001b[39m … \u001b[35m359.792 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m7.42% … 7.05%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m340.880 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m7.45%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m343.682 ms\u001b[22m\u001b[39m ± \u001b[32m 6.291 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m7.89% ± 1.20%\n", - "\n", - " \u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[34m█\u001b[39m\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m█\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m█\u001b[39m \u001b[39m▁\n", - " 339 ms\u001b[90m Histogram: frequency by time\u001b[39m 360 ms \u001b[0m\u001b[1m<\u001b[22m\n", - "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002436\u001b[39m." - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "println(\"Single Threaded\")\n", - "@benchmark collect(runCalcFormatted(realFMU, i) for i in input_values)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Multithreaded Batch Execution\n", - "In a multithreaded context we have to provide each thread it's own fmu, as they are not thread safe.\n", - "To spread the execution of a function to multiple threads, the library `Folds` can be used." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:25:29.072000Z", - "iopub.status.busy": "2022-06-18T14:25:29.072000Z", - "iopub.status.idle": "2022-06-18T14:25:46.159000Z", - "shell.execute_reply": "2022-06-18T14:25:46.159000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Multi Threaded\n" - ] - }, - { - "data": { - "text/plain": [ - "BenchmarkTools.Trial: 17 samples with 1 evaluation.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m307.665 ms\u001b[22m\u001b[39m … \u001b[35m325.644 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m8.44% … 8.13%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m308.448 ms \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m8.55%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m310.319 ms\u001b[22m\u001b[39m ± \u001b[32m 4.970 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m8.72% ± 0.86%\n", - "\n", - " \u001b[39m█\u001b[39m \u001b[34m█\u001b[39m\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", - " \u001b[39m█\u001b[39m▆\u001b[34m█\u001b[39m\u001b[39m▆\u001b[39m█\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m█\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▆\u001b[39m \u001b[39m▁\n", - " 308 ms\u001b[90m Histogram: frequency by time\u001b[39m 326 ms \u001b[0m\u001b[1m<\u001b[22m\n", - "\n", - " Memory estimate\u001b[90m: \u001b[39m\u001b[33m146.80 MiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m3002440\u001b[39m." - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "println(\"Multi Threaded\")\n", - "@benchmark Folds.collect(runCalcFormatted(fmu, i) for (fmu, i) in zip(realFMUBatch, input_values))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you can see, there is a significant speed-up in the median execution time. But: The speed-up is often much smaller than `Threads.nthreads()`, this has different reasons. For a rule of thumb, the speed-up should be around `n/2` on a `n`-core-processor with `n` threads for the Julia process." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After calculating the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-18T14:25:46.162000Z", - "iopub.status.busy": "2022-06-18T14:25:46.162000Z", - "iopub.status.idle": "2022-06-18T14:25:47.297000Z", - "shell.execute_reply": "2022-06-18T14:25:47.296000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "1-element Vector{Nothing}:\n", - " nothing" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiUnload(realFMU)\n", - "fmiUnload.(realFMUBatch)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "In this tutorial it is shown how multi threading with `Folds.jl` can be used to improve the performance for calculating a Batch of FMUs." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Julia 1.7.1", - "language": "julia", - "name": "julia-1.7" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/parameterize.ipynb b/example/parameterize.ipynb deleted file mode 100644 index 65099b87..00000000 --- a/example/parameterize.ipynb +++ /dev/null @@ -1,659 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Manually parameterize an FMU\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "This example shows how the manually parameterization of an FMU works if very specific adjustments during system initialization is needed. For this purpose, an IO-FMU model is loaded and the various commands for parameterization are shown on the basis of this model. With this example the user shall be guided how to make certain settings at an FMU. Please note, that parameterization of a simulation is possible in a much easier fashion: Using `fmiSimulate`, `fmiSimulateME` or `fmiSimulateCS` together with a parameter dictionary for the keyword `parameters`.\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulation exchange. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/CS_simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/CS_simulate.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:01.571000Z", - "iopub.status.busy": "2022-06-01T15:19:00.892000Z", - "iopub.status.idle": "2022-06-01T15:19:15.010000Z", - "shell.execute_reply": "2022-06-01T15:19:14.933000Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:15.205000Z", - "iopub.status.busy": "2022-06-01T15:19:15.013000Z", - "iopub.status.idle": "2022-06-01T15:19:16.256000Z", - "shell.execute_reply": "2022-06-01T15:19:16.255000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStop = 8.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:16.259000Z", - "iopub.status.busy": "2022-06-01T15:19:16.259000Z", - "iopub.status.idle": "2022-06-01T15:19:20.487000Z", - "shell.execute_reply": "2022-06-01T15:19:20.486000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_sXqX3p/IO`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_sXqX3p/IO/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tIO\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{ac3b4a99-4908-40f7-89da-2d5c08b3c4ac}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-17T07:40:55Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t4\n", - "\tInputs:\t\t\t\t3\n", - "\t\t352321536 [\"u_real\"]\n", - "\t\t352321537 [\"u_boolean\"]\n", - "\t\t352321538 [\"u_integer\"]\n", - "\tOutputs:\t\t\t3\n", - "\t\t335544320 [\"y_real\"]\n", - "\t\t335544321 [\"y_boolean\"]\n", - "\t\t335544322 [\"y_integer\"]\n", - "\tStates:\t\t\t\t0\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tIO\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tIO\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"IO\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Instantiate and Setup FMU\n", - "\n", - "Next it is necessary to create an instance of the FMU. This is achieved by the command `fmiInstantiate!()`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:20.489000Z", - "iopub.status.busy": "2022-06-01T15:19:20.489000Z", - "iopub.status.idle": "2022-06-01T15:19:21.252000Z", - "shell.execute_reply": "2022-06-01T15:19:21.252000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "FMU: IO\n", - "InstanceName: [not defined]\n", - "Address: Ptr{Nothing} @0x00000000029c12e0\n", - "State: fmi2ComponentStateInstantiated\n", - "Logging: true\n", - "FMU time: -Inf\n", - "FMU states: nothing" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiInstantiate!(myFMU; loggingOn=true)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the following code block, start and end time for the simulation is set by the `fmiSetupExperiment()` command." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:21.256000Z", - "iopub.status.busy": "2022-06-01T15:19:21.256000Z", - "iopub.status.idle": "2022-06-01T15:19:21.603000Z", - "shell.execute_reply": "2022-06-01T15:19:21.603000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiSetupExperiment(myFMU, tStart, tStop)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Parameterize FMU\n", - "\n", - "To parameterize an FMU, the FMU must be in the initialization mode, which is reached with the `fmiEnterInitializationMode()` command." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:21.607000Z", - "iopub.status.busy": "2022-06-01T15:19:21.606000Z", - "iopub.status.idle": "2022-06-01T15:19:21.639000Z", - "shell.execute_reply": "2022-06-01T15:19:21.639000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiEnterInitializationMode(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Within this mode it is then possible to change the different parameters. In this example, for each data type (`real`, `integer`, `boolean` and `string)` a corresponding parameter is selected. At the beginning the initial state of these parameters is displayed with `fmiGet()`." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:21.643000Z", - "iopub.status.busy": "2022-06-01T15:19:21.643000Z", - "iopub.status.idle": "2022-06-01T15:19:25.228000Z", - "shell.execute_reply": "2022-06-01T15:19:25.228000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Any}:\n", - " 0.0\n", - " 0\n", - " 0\n", - " \"Hello World!\"" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "params = [\"p_real\", \"p_integer\", \"p_boolean\", \"p_string\"]\n", - "fmiGet(myFMU, params)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next step, a function is defined that generates a random value for each parameter. For the parameter `p_string` a random number is inserted into the string. All parameters are combined to a vector and output." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:25.232000Z", - "iopub.status.busy": "2022-06-01T15:19:25.232000Z", - "iopub.status.idle": "2022-06-01T15:19:25.951000Z", - "shell.execute_reply": "2022-06-01T15:19:25.951000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "generateRandomNumbers (generic function with 1 method)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function generateRandomNumbers()\n", - " rndReal = 100 * rand()\n", - " rndInteger = round(Integer, 100 * rand())\n", - " rndBoolean = rand() > 0.5\n", - " rndString = \"Random number $(100 * rand())!\"\n", - "\n", - " randValues = [rndReal, rndInteger, rndBoolean, rndString]\n", - " println(randValues)\n", - " return randValues\n", - "end" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The previously defined function is called and the results are displayed in the console." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:25.955000Z", - "iopub.status.busy": "2022-06-01T15:19:25.955000Z", - "iopub.status.idle": "2022-06-01T15:19:26.678000Z", - "shell.execute_reply": "2022-06-01T15:19:26.678000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Any[27.27027116078753, 50, true, \"Random number 83.09640957659121!\"]\n" - ] - } - ], - "source": [ - "paramsVal = generateRandomNumbers();" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### First variant\n", - "\n", - "With this variant it is quickly possible to set all parameters at once. Even different data types can be set with only one command. The command `fmiSet()` selects itself which function is chosen for which data type. After setting the parameters, it is checked whether the corresponding parameters were set correctly. For this the function `fmiGet()` is used as above and afterwards with the macro `@assert` also tested whether the correct values are set." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:26.682000Z", - "iopub.status.busy": "2022-06-01T15:19:26.682000Z", - "iopub.status.idle": "2022-06-01T15:19:27.242000Z", - "shell.execute_reply": "2022-06-01T15:19:27.242000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Any[27.27027116078753, 50, 1, \"Random number 83.09640957659121!\"]" - ] - } - ], - "source": [ - "fmiSet(myFMU, params, paramsVal)\n", - "values = fmiGet(myFMU, params)\n", - "print(values)\n", - "\n", - "@assert paramsVal == values" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Second variant\n", - "\n", - "To make sure that the functions work it is necessary to generate random numbers again. As shown already, we call the defined function `generateRandomNumbers()` and output the values." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:27.246000Z", - "iopub.status.busy": "2022-06-01T15:19:27.246000Z", - "iopub.status.idle": "2022-06-01T15:19:27.247000Z", - "shell.execute_reply": "2022-06-01T15:19:27.247000Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Any[54.98169316988619, 76, true, \"Random number 39.54384075977397!\"]\n" - ] - } - ], - "source": [ - "rndReal, rndInteger, rndBoolean, rndString = generateRandomNumbers();" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the second variant, the value for each data type is set separately by the corresponding command. By this variant one has the maximum control and can be sure that also the correct data type is set. To illustrate the functionality of the parameterization with the separate functions, the corresponding get function is also called separately for each data type:\n", - "* `fmiSetReal()` <---> `fmiGetReal()`\n", - "* `fmiSetInteger()` <---> `fmiGetInteger()`\n", - "* `fmiSetBoolean()` <---> `fmiGetBoolean()`\n", - "* `fmiSetString()` <---> `fmiGetString()`." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:27.250000Z", - "iopub.status.busy": "2022-06-01T15:19:27.250000Z", - "iopub.status.idle": "2022-06-01T15:19:28.917000Z", - "shell.execute_reply": "2022-06-01T15:19:28.917000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "\"54.98169316988619 == 54.98169316988619\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\"76 == 76\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\"true == 1\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\"Random number 39.54384075977397! == Random number 39.54384075977397!\"" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fmiSetReal(myFMU, \"p_real\", rndReal)\n", - "display(\"$rndReal == $(fmiGetReal(myFMU, \"p_real\"))\")\n", - "\n", - "fmiSetInteger(myFMU, \"p_integer\", rndInteger)\n", - "display(\"$rndInteger == $(fmiGetInteger(myFMU, \"p_integer\"))\")\n", - "\n", - "fmiSetBoolean(myFMU, \"p_boolean\", rndBoolean)\n", - "display(\"$rndBoolean == $(fmiGetBoolean(myFMU, \"p_boolean\"))\")\n", - "\n", - "fmiSetString(myFMU, \"p_string\", rndString)\n", - "display(\"$rndString == $(fmiGetString(myFMU, \"p_string\"))\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After seeing that both variants set the parameters correctly, the initialization mode is terminated with the function `fmiExitInitializationMode()`." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:28.920000Z", - "iopub.status.busy": "2022-06-01T15:19:28.920000Z", - "iopub.status.idle": "2022-06-01T15:19:28.956000Z", - "shell.execute_reply": "2022-06-01T15:19:28.955000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0x00000000" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiExitInitializationMode(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From here on, you may want to simulate the FMU. Please note, that with the default `executionConfig`, it is necessary to prevent a new instantiation using the keyword `instantiate=false`. Otherwise, a new instance is allocated for the simulation-call and the parameters set for the previous instance are not transfered.\n", - "\n", - "Example:\n", - "`fmiSimulate(...; instantiate=false, ...)`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "The FMU will be unloaded and all unpacked data on disc will be removed." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:28.959000Z", - "iopub.status.busy": "2022-06-01T15:19:28.959000Z", - "iopub.status.idle": "2022-06-01T15:19:29.101000Z", - "shell.execute_reply": "2022-06-01T15:19:29.101000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "Based on this tutorial it can be seen that there are two different variants to set and get parameters.These examples should make it clear to the user how parameters can also be set with different data types." - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/example/simulate.ipynb b/example/simulate.ipynb deleted file mode 100644 index f3ef7b84..00000000 --- a/example/simulate.ipynb +++ /dev/null @@ -1,1012 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Simulate an FMU in different modes\n", - "Tutorial by Johannes Stoljar, Tobias Thummerer\n", - "\n", - "## License\n", - "Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar\n", - "\n", - "Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.\n", - "\n", - "## Motivation\n", - "This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.\n", - "\n", - "## Introduction to the example\n", - "In this example we want to show how fast and easy the simulation for an FMU is. For this purpose, the FMU is simulated in co-simulation mode and in model-exchange mode. After the FMU has been simulated, the simulation results are displayed in a graph. The graphs of the different modes are compared with each other. The used model is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.\n", - "\n", - "![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true) \n", - "\n", - "\n", - "## Target group\n", - "The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.\n", - "\n", - "\n", - "## Other formats\n", - "Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/simulate.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/simulate.md) corresponding to the notebook. \n", - "\n", - "\n", - "## Getting started\n", - "\n", - "### Installation prerequisites\n", - "| | Description | Command | Alternative | \n", - "|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|\n", - "| 1. | Enter Package Manager via | ] | |\n", - "| 2. | Install FMI via | add FMI | add \" https://github.com/ThummeTo/FMI.jl \" |\n", - "| 3. | Install FMIZoo via | add FMIZoo | add \" https://github.com/ThummeTo/FMIZoo.jl \" |\n", - "| 4. | Install Plots via | add Plots | |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Code section\n", - "\n", - "To run the example, the previously installed packages must be included. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:19:38.296000Z", - "iopub.status.busy": "2022-06-01T15:19:37.619000Z", - "iopub.status.idle": "2022-06-01T15:20:00.542000Z", - "shell.execute_reply": "2022-06-01T15:20:00.469000Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# imports\n", - "using FMI\n", - "using FMIZoo\n", - "using Plots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulation setup\n", - "\n", - "Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:20:09.276000Z", - "iopub.status.busy": "2022-06-01T15:20:00.544000Z", - "iopub.status.idle": "2022-06-01T15:20:10.061000Z", - "shell.execute_reply": "2022-06-01T15:20:10.061000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0.0:0.01:8.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tStart = 0.0\n", - "tStep = 0.01\n", - "tStop = 8.0\n", - "tSave = tStart:tStep:tStop" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import FMU\n", - "\n", - "In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:20:10.065000Z", - "iopub.status.busy": "2022-06-01T15:20:10.065000Z", - "iopub.status.idle": "2022-06-01T15:20:14.405000Z", - "shell.execute_reply": "2022-06-01T15:20:14.404000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_OQnfcn/SpringFrictionPendulum1D`.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75\n", - "┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_OQnfcn/SpringFrictionPendulum1D/resources`\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190\n", - "┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.\n", - "└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#################### Begin information for FMU ####################\n", - "\tModel name:\t\t\tSpringFrictionPendulum1D\n", - "\tFMI-Version:\t\t\t2.0\n", - "\tGUID:\t\t\t\t{df491d8d-0598-4495-913e-5b025e54d7f2}\n", - "\tGeneration tool:\t\tDymola Version 2022x (64-bit), 2021-10-08\n", - "\tGeneration time:\t\t2022-03-03T15:09:18Z\n", - "\tVar. naming conv.:\t\tstructured\n", - "\tEvent indicators:\t\t24\n", - "\tInputs:\t\t\t\t0\n", - "\tOutputs:\t\t\t0\n", - "\tStates:\t\t\t\t2\n", - "\t\t33554432 [\"mass.s\"]\n", - "\t\t33554433 [\"mass.v\", \"mass.v_relfric\"]\n", - "\tSupports Co-Simulation:\t\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "\t\tVar. com. steps:\ttrue\n", - "\t\tInput interpol.:\ttrue\n", - "\t\tMax order out. der.:\t1\n", - "\tSupports Model-Exchange:\ttrue\n", - "\t\tModel identifier:\tSpringFrictionPendulum1D\n", - "\t\tGet/Set State:\t\ttrue\n", - "\t\tSerialize State:\ttrue\n", - "\t\tDir. Derivatives:\ttrue\n", - "##################### End information for FMU #####################\n" - ] - } - ], - "source": [ - "# we use an FMU from the FMIZoo.jl\n", - "pathToFMU = get_model_filename(\"SpringFrictionPendulum1D\", \"Dymola\", \"2022x\")\n", - "\n", - "myFMU = fmiLoad(pathToFMU)\n", - "# fmiLoad(\"path/to/myFMU.fmu\"; unpackPath = \"path/to/unpacked/fmu/\")\n", - "\n", - "fmiInfo(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Simulate FMU\n", - "\n", - "In the following, the FMU is simulated in the two different simulation modes.\n", - "\n", - "#### Simulate as Co-Simulation\n", - "\n", - "In the next steps the recorded values are defined. The first state is the position of the mass and the second state is the velocity. In the function `fmiSimulateCS()` the FMU is simulated in co-simulation mode (CS) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time and the recorded variables are specified." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:20:14.407000Z", - "iopub.status.busy": "2022-06-01T15:20:14.407000Z", - "iopub.status.idle": "2022-06-01T15:20:19.739000Z", - "shell.execute_reply": "2022-06-01T15:20:19.739000Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Model name:\n", - "\tSpringFrictionPendulum1D\n", - "Success:\n", - "\ttrue\n", - "Values [801]:\n", - "\t0.0\t(0.5, 0.0)\n", - "\t0.01\t(0.5002235448486548, 0.042692491939260585)\n", - "\t0.02\t(0.5008715291319449, 0.08568000508550636)\n", - "\t0.03\t(0.5019478597521578, 0.12892136998736314)\n", - "\t0.04\t(0.5034570452098334, 0.17232325681284336)\n", - "\t0.05\t(0.5053993458877354, 0.2158440857658765)\n", - "\t0.06\t(0.5077764240578201, 0.259420181133082)\n", - "\t0.07\t(0.5105886522837868, 0.30295578207463486)\n", - "\t0.08\t(0.5138351439717114, 0.3464184707972189)\n", - "\t...\n", - "\t8.0\t(1.071367253976742, -1.000814138594347e-10)\n", - "Events [0]:\n" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vrs = [\"mass.s\", \"mass.v\"]\n", - "\n", - "dataCS = fmiSimulateCS(myFMU, tStart, tStop; recordValues=vrs, saveat=tSave)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Simulate as Model-Exchange\n", - "\n", - "In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time are specified. In contrast to the co-simulation, the values to be stored are not specified here, since the states and events of the FMU are always output as well. The identifiers given above just correspond to the states of the FMU." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:20:19.742000Z", - "iopub.status.busy": "2022-06-01T15:20:19.742000Z", - "iopub.status.idle": "2022-06-01T15:20:32.777000Z", - "shell.execute_reply": "2022-06-01T15:20:32.777000Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[34mSimulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:09\u001b[39m\n" - ] - }, - { - "data": { - "text/plain": [ - "Model name:\n", - "\tSpringFrictionPendulum1D\n", - "Success:\n", - "\ttrue\n", - "States [801]:\n", - "\t0.0\t[0.5, 0.0]\n", - "\t0.01\t[0.5002131418344649, 0.042689450666241]\n", - "\t0.02\t[0.5008548874805565, 0.08570846215523381]\n", - "\t0.03\t[0.5019281653120716, 0.12898389312495082]\n", - "\t0.04\t[0.5034351805057593, 0.17244393475170294]\n", - "\t0.05\t[0.5053774287967188, 0.2160182432854046]\n", - "\t0.06\t[0.5077556967622916, 0.25963796675862466]\n", - "\t0.07\t[0.5105701003205937, 0.3032358690888718]\n", - "\t0.08\t[0.5138201049458624, 0.34674641820324037]\n", - "\t...\n", - "\t8.0\t[1.0668213438183276, -1.0000099359121942e-10]\n", - "Events [6]:\n", - "\tState-Event #11 @ 0.0s\n", - "\tState-Event #11 @ 0.9939s\n", - "\tState-Event #19 @ 1.9881s\n", - "\tState-Event #11 @ 2.9829s\n", - "\tState-Event #19 @ 3.9787s\n", - "\tState-Event #11 @ 4.9768s\n" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dataME = fmiSimulateME(myFMU, tStart, tStop; saveat=tSave)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plotting FMU\n", - "\n", - "After the simulation is finished the results of the FMU for the co-simulation and model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:20:32.781000Z", - "iopub.status.busy": "2022-06-01T15:20:32.780000Z", - "iopub.status.idle": "2022-06-01T15:20:51.657000Z", - "shell.execute_reply": "2022-06-01T15:20:51.657000Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiPlot(dataCS)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:20:51.662000Z", - "iopub.status.busy": "2022-06-01T15:20:51.662000Z", - "iopub.status.idle": "2022-06-01T15:20:51.876000Z", - "shell.execute_reply": "2022-06-01T15:20:51.876000Z" - } - }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fmiPlot(dataME)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From both graphs it can be seen that the simulation calculates exactly the same results." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unload FMU\n", - "\n", - "After plotting the data, the FMU is unloaded and all unpacked data on disc is removed." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "execution": { - "iopub.execute_input": "2022-06-01T15:20:51.880000Z", - "iopub.status.busy": "2022-06-01T15:20:51.880000Z", - "iopub.status.idle": "2022-06-01T15:20:51.922000Z", - "shell.execute_reply": "2022-06-01T15:20:51.922000Z" - } - }, - "outputs": [], - "source": [ - "fmiUnload(myFMU)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Summary\n", - "\n", - "Based on this tutorial it can be seen that simulating in the different mode is very easy, and it only takes a few commands to simulate the FMU. " - ] - } - ], - "metadata": { - "interpreter": { - "hash": "037537ff7419c497b9325f7d495147943224d408cf5d5ed915294a5b960167b0" - }, - "jupytext": { - "cell_metadata_filter": "-all", - "comment_magics": "false", - "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Julia 1.6.6", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.6" - }, - "nteract": { - "version": "0.28.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 67bd7fa441611060f27c5ae0e800541c9ad4bd74 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 28 Jun 2022 16:28:44 +0200 Subject: [PATCH 25/41] WIP: started tests --- src/FMI.jl | 8 ++++-- test/FMI3/cs_me.jl | 58 +++++++++++++++++++-------------------- test/FMI3/sim_CS.jl | 66 ++++++++++++++++++++++----------------------- test/runtests.jl | 26 +++++++++--------- 4 files changed, 81 insertions(+), 77 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 80d4d998..07186cce 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -41,7 +41,7 @@ export fmi2GetSolutionTime, fmi2GetSolutionState, fmi2GetSolutionValue # fmi3 imports import FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate import FMIImport: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmi3InstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal -import FMIImport: fmi3InstantiateModelExchange, fmi3InstantiateCoSimulation, fmi3InstantiateScheduledExecution, fmi3FreeInstance!, fmi3GetVersion +import FMIImport: fmi3InstantiateModelExchange!, fmi3InstantiateCoSimulation!, fmi3InstantiateScheduledExecution!, fmi3FreeInstance!, fmi3GetVersion import FMIImport: fmi3SetDebugLogging, fmi3EnterInitializationMode, fmi3ExitInitializationMode, fmi3Terminate, fmi3Reset import FMIImport: fmi3GetFloat32!, fmi3SetFloat32, fmi3GetFloat64!, fmi3SetFloat64 import FMIImport: fmi3GetInt8!, fmi3SetInt8, fmi3GetUInt8!, fmi3SetUInt8, fmi3GetInt16!, fmi3SetInt16, fmi3GetUInt16!, fmi3SetUInt16, fmi3GetInt32!, fmi3SetInt32, fmi3GetUInt32!, fmi3SetUInt32, fmi3GetInt64!, fmi3SetInt64, fmi3GetUInt64!, fmi3SetUInt64 @@ -61,7 +61,7 @@ import FMIImport: fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmi3DeSerializeFMUState import FMIImport: fmi3GetDirectionalDerivative, fmi3GetAdjointDerivative import FMIImport: fmi3GetStartValue, fmi3SampleDirectionalDerivative, fmi3CompletedIntegratorStep -import FMIImport: fmi3Unzip, fmi3Load, loadBinary, fmi3Reload, fmi3Unload, fmi3InstantiateModelExchange!, fmi3InstantiateCoSimulation!, fmi3InstantiateScheduledExecution! +import FMIImport: fmi3Unzip, fmi3Load, loadBinary, fmi3Reload, fmi3Unload import FMIImport: fmi3SampleDirectionalDerivative! import FMIImport: fmi3GetJacobian, fmi3GetJacobian!, fmi3GetFullJacobian, fmi3GetFullJacobian! import FMIImport: fmi3LoadModelDescription @@ -71,10 +71,14 @@ import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetS import FMIImport: fmi3Get, fmi3Get!, fmi3Set import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue +export fmi3InstantiateCoSimulation!, fmi3InstantiateModelExchange!, fmi3InstantiateScheduledExecution! import FMIImport: fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type export fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type +import FMIImport: fmi3TypeModelExchange, fmi3TypeCoSimulation, fmi3TypeScheduledExecution, fmi3Type +export fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi3TypeScheduledExecution, fmi2Type + using FMIExport using FMIImport.FMICore: fmi2ValueReference, fmi3ValueReference diff --git a/test/FMI3/cs_me.jl b/test/FMI3/cs_me.jl index 0c7f1641..fc633702 100644 --- a/test/FMI3/cs_me.jl +++ b/test/FMI3/cs_me.jl @@ -5,36 +5,36 @@ t_start = 0.0 t_stop = 1.0 -myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -@test fmiIsCoSimulation(myFMU) -@test fmiIsModelExchange(myFMU) -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 -# choose FMU or FMUComponent +myFMU = fmiLoad("BouncingBall", "ModelicaReferenceFMUs", "0.0.16", "3.0") +# @test fmiIsCoSimulation(myFMU) +# @test fmiIsModelExchange(myFMU) +# inst = fmiInstantiate!(myFMU; loggingOn=false) +# @test inst != 0 +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = inst +# end +# sol = fmiSimulateCS(fmuStruct, t_start, t_stop) +# @test sol.success +# sol = fmiSimulateME(fmuStruct, t_start, t_stop) +# @test sol.success +# fmiUnload(myFMU) + + + +# myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:ME) +@test myFMU.type == FMI.fmi3TypeModelExchange +inst = fmi3InstantiateModelExchange!(myFMU; loggingOn=false) fmuStruct = nothing envFMUSTRUCT = ENV["FMUSTRUCT"] if envFMUSTRUCT == "FMU" fmuStruct = myFMU elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -sol = fmiSimulateCS(fmuStruct, t_start, t_stop) -@test sol.success -sol = fmiSimulateME(fmuStruct, t_start, t_stop) -@test sol.success -fmiUnload(myFMU) - - - -myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:ME) -@test myFMU.type == FMI.fmi2TypeModelExchange -comp = fmiInstantiate!(myFMU; loggingOn=false) -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp + fmuStruct = inst end sol = fmiSimulate(fmuStruct, t_start, t_stop) @test sol.success @@ -42,15 +42,15 @@ fmiUnload(myFMU) -myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:CS) -@test myFMU.type == FMI.fmi2TypeCoSimulation -comp = fmiInstantiate!(myFMU; loggingOn=false) +# myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:CS) +@test myFMU.type == FMI.fmi3TypeCoSimulation +inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn=false) fmuStruct = nothing envFMUSTRUCT = ENV["FMUSTRUCT"] if envFMUSTRUCT == "FMU" fmuStruct = myFMU elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp + fmuStruct = inst end sol = fmiSimulate(fmuStruct, t_start, t_stop) @test sol.success diff --git a/test/FMI3/sim_CS.jl b/test/FMI3/sim_CS.jl index 282687c4..ca25fa1f 100644 --- a/test/FMI3/sim_CS.jl +++ b/test/FMI3/sim_CS.jl @@ -5,9 +5,9 @@ # case 1: CS-FMU Simulation -myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +myFMU = fmiLoad("BouncingBall", "ModelicaReferenceFMUs", "0.0.16", "3.0") -comp = fmiInstantiate!(myFMU; loggingOn=false) +comp = fmi3InstantiateCoSimulation!(myFMU; loggingOn=false) @test comp != 0 # choose FMU or FMUComponent @@ -21,7 +21,7 @@ end @assert fmuStruct !== nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" t_start = 0.0 -t_stop = 8.0 +t_stop = 3.0 # test without recording values (but why?) solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2) @@ -40,47 +40,47 @@ v = collect(d[2] for d in solution.values.saveval) @test t[end] == t_stop # reference values from Simulation in Dymola2020x (Dassl) -@test s[1] == 0.5 +@test s[1] == 1.0 @test v[1] == 0.0 -if ENV["EXPORTINGTOOL"] == "Dymola/2020x" # ToDo: Linux FMU was corrupted - @test s[end] ≈ 0.509219 atol=1e-1 - @test v[end] ≈ 0.314074 atol=1e-1 +if ENV["EXPORTINGTOOL"] == "ModelicaReferenceFMUs" # ToDo: Linux FMU was corrupted + @test s[end] ≈ 0.0 atol=1e-1 + @test v[end] ≈ 0.0 atol=1e-1 end fmiUnload(myFMU) -# case 2: CS-FMU with input signal +# case 2: CS-FMU with input signal not supported with BouncingBall FMU -function extForce(t) - [sin(t)] -end +# function extForce(t) +# [sin(t)] +# end -myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +# myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 +# comp = fmiInstantiate!(myFMU; loggingOn=false) +# @test comp != 0 -# choose FMU or FMUComponent -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -@assert fmuStruct !== nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = comp +# end +# @assert fmuStruct !== nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" -solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"], inputValueReferences=["extForce"], inputFunction=extForce) -@test solution.success -@test length(solution.values.saveval) > 0 -@test length(solution.values.t) > 0 +# solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"], inputValueReferences=["extForce"], inputFunction=extForce) +# @test solution.success +# @test length(solution.values.saveval) > 0 +# @test length(solution.values.t) > 0 -@test t[1] == t_start -@test t[end] == t_stop +# @test t[1] == t_start +# @test t[end] == t_stop -# reference values from Simulation in Dymola2020x (Dassl) -@test [solution.values.saveval[1]...] == [0.5, 0.0] -@test sum(abs.([solution.values.saveval[end]...] - [0.613371, 0.188633])) < 0.2 -fmiUnload(myFMU) +# # reference values from Simulation in Dymola2020x (Dassl) +# @test [solution.values.saveval[1]...] == [0.5, 0.0] +# @test sum(abs.([solution.values.saveval[end]...] - [0.613371, 0.188633])) < 0.2 +# fmiUnload(myFMU) diff --git a/test/runtests.jl b/test/runtests.jl index 86c0f2a8..67fe73a9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -65,41 +65,41 @@ function runtestsFMI3(exportingTool) @testset "Testing FMUs exported from $exportingTool" begin @testset "FMI3/Sensitivities" begin - include("sens.jl") + # include("sens.jl") end for str in fmuStructs @testset "Functions for $str" begin ENV["FMUSTRUCT"] = str @testset "Variable Getters / Setters" begin - include("FMI3/getter_setter.jl") + #include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - include("FMI3/state.jl") + #include("FMI3/state.jl") end @testset "Directional derivatives" begin - include("FMI3/dir_ders.jl") + #include("FMI3/dir_ders.jl") end @testset "Automatic Simulation (CS or ME)" begin - include("FMI3/sim_auto.jl") + #include("FMI3/sim_auto.jl") end @testset "CS Simulation" begin include("FMI3/sim_CS.jl") end @testset "ME Simulation" begin - include("FMI3/sim_ME.jl") + #include("FMI3/sim_ME.jl") end @testset "Support CS and ME simultaneously" begin - include("FMI3/cs_me.jl") + # include("FMI3/cs_me.jl") end @testset "Loading/Saving simulation results" begin - include("FMI3/load_save.jl") + #include("FMI3/load_save.jl") end end end @testset "Plotting" begin - include("FMI3/plots.jl") + #include("FMI3/plots.jl") end end end @@ -108,14 +108,14 @@ end if Sys.iswindows() @info "Automated testing is supported on Windows." for exportingTool in exportingToolsWindows - runtestsFMI2(exportingTool) - #runtestsFMI3(exportingTool) + # runtestsFMI2(exportingTool) + runtestsFMI3(exportingTool) end elseif Sys.islinux() @info "Automated testing is supported on Linux." for exportingTool in exportingToolsLinux - runtestsFMI2(exportingTool) - #runtestsFMI3(exportingTool) + # runtestsFMI2(exportingTool) + runtestsFMI3(exportingTool) end elseif Sys.isapple() @warn "Test-sets are currrently using Windows- and Linux-FMUs, automated testing for macOS is currently not supported." From 778f4cd26b8ec594f45b5a38363e5ee75412fbc6 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Wed, 29 Jun 2022 11:32:16 +0200 Subject: [PATCH 26/41] WIP: change sim and comments --- src/FMI.jl | 1 - src/FMI2_sim.jl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 729bee9f..978edd5e 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -1517,7 +1517,6 @@ function fmiGetInteger!(str::fmi2Struct, args...; kwargs...) end # TODO different call in fmi3 -Set the values of an array of integer variables """ diff --git a/src/FMI2_sim.jl b/src/FMI2_sim.jl index dcf08189..0385907c 100644 --- a/src/FMI2_sim.jl +++ b/src/FMI2_sim.jl @@ -657,7 +657,7 @@ function fmi2SimulateME(fmu::FMU2, c::Union{FMU2Component, Nothing}=nothing, t_s showProgress::Bool = true, kwargs...) - @assert fmi2IsModelExchange(fmu) "fmi2SimulateME(...): This function supports Model Excahnge FMUs only." + @assert fmi2IsModelExchange(fmu) "fmi2SimulateME(...): This function supports Model Exchange FMUs only." #@assert fmu.type == fmi2TypeModelExchange "fmi2SimulateME(...): This FMU supports Model Exchange, but was instantiated in CS mode. Use `fmiLoad(...; type=:ME)`." recordValues = prepareValueReference(fmu, recordValues) From 60b3ca071bc55bafb205309cbf0d0b13a2f64251 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Thu, 30 Jun 2022 10:37:09 +0200 Subject: [PATCH 27/41] WIP: working on tests --- src/FMI.jl | 26 +++++++++++++------------- src/FMI3_comp_wraps.jl | 23 +++++++++-------------- src/FMI3_sim.jl | 14 ++++++++++++-- test/FMI3/sim_CS.jl | 6 +++--- test/FMI3/sim_ME.jl | 6 +++--- test/FMI3/state.jl | 26 ++++++++++++-------------- test/runtests.jl | 6 +++--- 7 files changed, 55 insertions(+), 52 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 978edd5e..38304d1b 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -127,21 +127,21 @@ end export fmiSaveSolution, fmiLoadSolution # from FMI3_plot.jl -function fmiPlot(solution::FMU3Solution; kwargs...) - @warn "fmiPlot(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." -end -function fmiPlot!(fig, solution::FMU3Solution; kwargs...) - @warn "fmiPlot!(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." -end -export fmiPlot, fmiPlot! +# function fmiPlot(solution::FMU3Solution; kwargs...) +# @warn "fmiPlot(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +# end +# function fmiPlot!(fig, solution::FMU3Solution; kwargs...) +# @warn "fmiPlot!(...) needs `Plots` package. Please install `Plots` and do `using Plots` or `import Plots`." +# end +# export fmiPlot, fmiPlot! # from FMI3_JLD2.jl -function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") - @warn "fmiSave(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." -end -function fmiLoadSolution(path::AbstractString; keyword="solution") - @warn "fmiLoad(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." -end +# function fmiSaveSolution(solution::FMU3Solution, filepath::AbstractString; keyword="solution") +# @warn "fmiSave(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." +# end +# function fmiLoadSolution(path::AbstractString; keyword="solution") +# @warn "fmiLoad(...) needs `JLD2` package. Please install `JLD2` and do `using JLD2` or `import JLD2`." +# end export fmiSaveSolution, fmiLoadSolution diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index 451eb292..fe773875 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -952,31 +952,26 @@ function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; fmi3Simulate(fmu.instances[end], t_start, t_stop; recordValues=recordValues, saveat=saveat, setup=setup) end -""" -fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; -recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) -Wrapper for fmi3SimulateCS() in FMI/FMI3_sim.jl """ -function fmi3SimulateCS(fmu::FMU3, t_start::Real, t_stop::Real; - recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3SimulateCS(fmu::FMU3, args...; kwargs...) - fmi3SimulateCS(fmu.instances[end], t_start, t_stop; - recordValues=recordValues, saveat=saveat, setup=setup) +Wrapper for fmi3SimulateCS() in FMI/FMI2_sim.jl +""" +function fmi3SimulateCS(fmu::FMU3, args...; kwargs...) + return fmi3SimulateCS(fmu, nothing, args...; kwargs...) end """ - fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) + fmi3SimulateME(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SimulateME() in FMI/FMI3_sim.jl """ -function fmi3SimulateME(fmu::FMU3, t_start::Real, t_stop::Real; kwargs...) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SimulateME(fmu.instances[end], t_start, t_stop; kwargs...) +function fmi3SimulateME(fmu::FMU3, args...; kwargs...) + return fmi3SimulateME(fmu, nothing, args...; kwargs...) end + """ fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index ca4a35d4..41b220b5 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -160,6 +160,11 @@ function saveValues(c::fmi3Instance, recordValues, u, t, integrator) (fmi3GetFloat64(c, recordValues)...,) end +# wrapper +function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) + fmi3SimulateME(c.fmu, c, t_start, t_stop; kwargs...) +end + """ Source: FMISpec3.0, Version D5ef1c1: 3.3. Code Example @@ -169,7 +174,7 @@ State- and Time-Events are handled correctly. Returns a tuple of type (ODESolution, DiffEqCallbacks.SavedValues). If keyword `recordValues` is not set, a tuple of type (ODESolution, nothing) is returned for consitency. """ -function fmi3SimulateME(c::fmi3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; +function fmi3SimulateME(fmu::FMU3, c::fmi3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; solver = nothing, customFx = nothing, recordValues::fmi3ValueReferenceFormat = nothing, @@ -295,6 +300,11 @@ function fmi3SimulateME(c::fmi3Instance, t_start::Union{Real, Nothing} = nothing end end +# wrapper +function fmi3SimulateCS(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) + fmi3SimulateCS(c.fmu, c, t_start, t_stop; kwargs...) +end + """ Source: FMISpec3.0, Version D5ef1c1: 4.3. Code Examples @@ -305,7 +315,7 @@ If keyword `recordValues` is not set, a tuple of type (success::Bool, nothing) i ToDo: Improve Documentation. """ -function fmi3SimulateCS(c::fmi3Instance, t_start::Real, t_stop::Real; +function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; recordValues::fmi3ValueReferenceFormat = nothing, saveat = [], setup::Bool = true, diff --git a/test/FMI3/sim_CS.jl b/test/FMI3/sim_CS.jl index ca25fa1f..4d6f86f3 100644 --- a/test/FMI3/sim_CS.jl +++ b/test/FMI3/sim_CS.jl @@ -24,11 +24,11 @@ t_start = 0.0 t_stop = 3.0 # test without recording values (but why?) -solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2) -@test solution.success +# solution = fmiSimulateCS(fmuStruct, t_start, t_stop) +# @test solution.success # test with recording values -solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["mass.s", "mass.v"]) +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; recordValues=["mass.h", "mass.v"]) @test solution.success @test length(solution.values.saveval) == t_start:1e-2:t_stop |> length @test length(solution.values.saveval[1]) == 2 diff --git a/test/FMI3/sim_ME.jl b/test/FMI3/sim_ME.jl index 8754f3d4..ddc1d797 100644 --- a/test/FMI3/sim_ME.jl +++ b/test/FMI3/sim_ME.jl @@ -6,13 +6,13 @@ using DifferentialEquations: Tsit5, Rosenbrock23 t_start = 0.0 -t_stop = 8.0 +t_stop = 3.0 # case 1: ME-FMU with state events -myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +myFMU = fmiLoad("BouncingBall", "ModelicaReferenceFMUs", "0.0.16", "3.0") -comp = fmiInstantiate!(myFMU; loggingOn=false) +comp = fmi3InstantiateModelExchange!(myFMU; loggingOn=false) @test comp != 0 # choose FMU or FMUComponent diff --git a/test/FMI3/state.jl b/test/FMI3/state.jl index 983ff203..e1e23099 100644 --- a/test/FMI3/state.jl +++ b/test/FMI3/state.jl @@ -7,10 +7,10 @@ # Prepare FMU # ############### -myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +myFMU = fmiLoad("BouncingBall", "ModelicaReferenceFMUs", "0.0.16", "3.0") -comp = fmiInstantiate!(myFMU; loggingOn=true) -@test comp != 0 +inst = fmi3InstantiateCoSimulation!(myFMU; loggingOn=true) +@test inst != 0 # choose FMU or FMUComponent fmuStruct = nothing @@ -18,39 +18,37 @@ envFMUSTRUCT = ENV["FMUSTRUCT"] if envFMUSTRUCT == "FMU" fmuStruct = myFMU elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp + fmuStruct = inst end @assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" -@test fmiEnterInitializationMode(fmuStruct) == 0 -@test fmiExitInitializationMode(fmuStruct) == 0 - -@test fmiSetupExperiment(fmuStruct, 0.0) == 0 +@test fmi3EnterInitializationMode(fmuStruct) == 0 +@test fmi3ExitInitializationMode(fmuStruct) == 0 ########################### # Testing state functions # ########################### if fmiCanGetSetState(myFMU) && fmiCanSerializeFMUstate(myFMU) - @test fmiGetReal(fmuStruct, "mass.s") == 0.5 + @test fmi3GetFloat64(fmuStruct, "s") == 0.5 FMUstate = fmiGetFMUstate(fmuStruct) - @test typeof(FMUstate) == FMI.fmi2FMUstate + @test typeof(FMUstate) == FMI.fmi3FMUstate len = fmiSerializedFMUstateSize(fmuStruct, FMUstate) @test len > 0 serial = fmiSerializeFMUstate(fmuStruct, FMUstate) @test length(serial) == len @test typeof(serial) == Array{Char,1} - fmiSetReal(fmuStruct, "mass.s", 10.0) + fmi3SetFloat64(fmuStruct, "mass.s", 10.0) FMUstate = fmiGetFMUstate(fmuStruct) - @test fmiGetReal(fmuStruct, "mass.s") == 10.0 + @test fmi3GetFloat64(fmuStruct, "mass.s") == 10.0 FMUstate2 = fmiDeSerializeFMUstate(fmuStruct, serial) @test typeof(FMUstate2) == FMI.fmi2FMUstate fmiSetFMUstate(fmuStruct, FMUstate2) - @test fmiGetReal(fmuStruct, "mass.s") == 0.5 + @test fmi3GetFloat64(fmuStruct, "mass.s") == 0.5 fmiSetFMUstate(fmuStruct, FMUstate) - @test fmiGetReal(fmuStruct, "mass.s") == 10.0 + @test fmi3GetFloat64(fmuStruct, "mass.s") == 10.0 fmiFreeFMUstate!(fmuStruct, FMUstate) fmiFreeFMUstate!(fmuStruct, FMUstate2) else diff --git a/test/runtests.jl b/test/runtests.jl index 67fe73a9..1b3869b5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -75,7 +75,7 @@ function runtestsFMI3(exportingTool) #include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - #include("FMI3/state.jl") + include("FMI3/state.jl") end @testset "Directional derivatives" begin #include("FMI3/dir_ders.jl") @@ -84,10 +84,10 @@ function runtestsFMI3(exportingTool) #include("FMI3/sim_auto.jl") end @testset "CS Simulation" begin - include("FMI3/sim_CS.jl") + # include("FMI3/sim_CS.jl") end @testset "ME Simulation" begin - #include("FMI3/sim_ME.jl") + # include("FMI3/sim_ME.jl") end @testset "Support CS and ME simultaneously" begin # include("FMI3/cs_me.jl") From 140e18bb754aa3acb211fecb5b97343e920b7ba7 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Wed, 6 Jul 2022 09:37:07 +0200 Subject: [PATCH 28/41] WIP: finished state.jl test --- src/FMI.jl | 32 +++++++++++--------------------- src/FMI3_comp_wraps.jl | 8 ++++---- test/FMI3/state.jl | 16 ++++++++-------- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 942c8291..f79bcf66 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -59,6 +59,7 @@ import FMIImport: fmi3SetTime, fmi3SetContinuousStates, fmi3EnterEventMode, fmi3 import FMIImport: fmi3GetContinuousStateDerivatives, fmi3GetEventIndicators, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates import FMIImport: fmi3StringToValueReference, fmi3ValueReferenceToString, fmi3ModelVariablesForValueReference import FMIImport: fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString +import FMIImport: fmi3SetFloat32, fmi3SetFloat64, fmi3SetInt8, fmi3SetUInt8, fmi3SetInt16, fmi3SetUInt16, fmi3SetInt32, fmi3SetUInt32, fmi3SetInt64, fmi3SetUInt64, fmi3SetBoolean, fmi3SetBinary, fmi3SetClock, fmi3SetString import FMIImport: fmi3GetFMUState, fmi3SerializedFMUStateSize, fmi3SerializeFMUState, fmi3DeSerializeFMUState import FMIImport: fmi3GetDirectionalDerivative, fmi3GetAdjointDerivative import FMIImport: fmi3GetStartValue, fmi3SampleDirectionalDerivative, fmi3CompletedIntegratorStep @@ -73,6 +74,9 @@ import FMIImport: fmi3Get, fmi3Get!, fmi3Set import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue export fmi3InstantiateCoSimulation!, fmi3InstantiateModelExchange!, fmi3InstantiateScheduledExecution! +export fmi3EnterInitializationMode, fmi3ExitInitializationMode +export fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString +export fmi3SetFloat64 import FMIImport: fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type export fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type @@ -468,7 +472,7 @@ function fmiCanSerializeFMUstate(str::fmi2StructMD) fmi2CanSerializeFMUstate(str) end function fmiCanSerializeFMUstate(str::fmi3StructMD) - fmi3CanSerializeFMUstate(str) + fmi3CanSerializeFMUState(str) end # TODO fmi3Call fmiProvidesDirectionalDerivatives @@ -1819,7 +1823,7 @@ function fmiGetFMUstate(str::fmi2Struct) fmi2GetFMUstate(str) end function fmiGetFMUstate(str::fmi3Struct) - fmi3GetFMUstate(str) + fmi3GetFMUState(str) end # TODO different call in fmi3 @@ -1859,7 +1863,7 @@ function fmiSetFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SetFMUstate(str, args...; kwargs...) end function fmiSetFMUstate(str::fmi3Struct, args...; kwargs...) - fmi3SetFMUstate(str, args...; kwargs...) + fmi3SetFMUState(str, args...; kwargs...) end # TODO different call in fmi3 @@ -1902,7 +1906,7 @@ function fmiFreeFMUstate!(str::fmi2Struct, args...; kwargs...) fmi2FreeFMUstate!(str, args...; kwargs...) end function fmiFreeFMUstate!(str::fmi3Struct, args...; kwargs...) - fmi3FreeFMUstate!(str, args...; kwargs...) + fmi3FreeFMUState!(str, args...; kwargs...) end # TODO different call in fmi3 @@ -1936,7 +1940,7 @@ function fmiSerializedFMUstateSize(str::fmi2Struct, args...; kwargs...) fmi2SerializedFMUstateSize(str, args...; kwargs...) end function fmiSerializedFMUstateSize(str::fmi3Struct, args...; kwargs...) - fmi3SerializedFMUstateSize(str, args...; kwargs...) + fmi3SerializedFMUStateSize(str, args...; kwargs...) end # TODO different call in fmi3 @@ -1968,7 +1972,7 @@ function fmiSerializeFMUstate(str::fmi2Struct, args...; kwargs...) fmi2SerializeFMUstate(str, args...; kwargs...) end function fmiSerializeFMUstate(str::fmi3Struct, args...; kwargs...) - fmi3SerializeFMUstate(str, args...; kwargs...) + fmi3SerializeFMUState(str, args...; kwargs...) end # TODO different call in fmi3 @@ -2000,7 +2004,7 @@ function fmiDeSerializeFMUstate(str::fmi2Struct, args...; kwargs...) fmi2DeSerializeFMUstate(str, args...; kwargs...) end function fmiDeSerializeFMUstate(str::fmi3Struct, args...; kwargs...) - fmi3DeSerializeFMUstate(str, args...; kwargs...) + fmi3DeSerializeFMUState(str, args...; kwargs...) end """ @@ -2106,20 +2110,6 @@ function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) fmi3GetAdjointDerivative!(str, args...; kwargs...) end -""" -Returns the values of the adjoint derivatives. -""" -function fmiGetAdjointDerivative(str::fmi3Struct, args...; kwargs...) - fmi3GetAdjointDerivative(str, args...; kwargs...) -end - -""" -Returns the values of the adjoint derivatives (in-place). -""" -function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) - fmi3GetAdjointDerivative!(str, args...; kwargs...) -end - """ fmiDoStep(str::fmi2Struct, c::FMU2Component, communicationStepSize::Union{Real, Nothing} = nothing; currentCommunicationPoint::Union{Real, Nothing} = nothing, noSetFMUStatePriorToCurrentPoint::Bool = true) diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index fe773875..51a362ab 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -564,14 +564,14 @@ function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) end """ - fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) + fmi3FreeFMUState!(fmu::FMU3, state::fmi3FMUState) -Wrapper for fmi3FreeFMUState() in FMIImport/FMI3_int.jl +Wrapper for fmi3FreeFMUState!() in FMIImport/FMI3_int.jl """ -function fmi3FreeFMUState(fmu::FMU3, state::fmi3FMUState) +function fmi3FreeFMUState!(fmu::FMU3, state::fmi3FMUState) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3FreeFMUState(fmu.instances[end], state) + fmi3FreeFMUState!(fmu.instances[end], state) end """ diff --git a/test/FMI3/state.jl b/test/FMI3/state.jl index e1e23099..5de45d6b 100644 --- a/test/FMI3/state.jl +++ b/test/FMI3/state.jl @@ -30,25 +30,25 @@ end ########################### if fmiCanGetSetState(myFMU) && fmiCanSerializeFMUstate(myFMU) - @test fmi3GetFloat64(fmuStruct, "s") == 0.5 + @test fmi3GetFloat64(fmuStruct, "h") == 1.0 FMUstate = fmiGetFMUstate(fmuStruct) - @test typeof(FMUstate) == FMI.fmi3FMUstate + @test typeof(FMUstate) == FMI.fmi3FMUState len = fmiSerializedFMUstateSize(fmuStruct, FMUstate) @test len > 0 serial = fmiSerializeFMUstate(fmuStruct, FMUstate) @test length(serial) == len - @test typeof(serial) == Array{Char,1} + @test typeof(serial) == Array{UInt8,1} - fmi3SetFloat64(fmuStruct, "mass.s", 10.0) + fmi3SetFloat64(fmuStruct, "h", 10.0) FMUstate = fmiGetFMUstate(fmuStruct) - @test fmi3GetFloat64(fmuStruct, "mass.s") == 10.0 + @test fmi3GetFloat64(fmuStruct, "h") == 10.0 FMUstate2 = fmiDeSerializeFMUstate(fmuStruct, serial) - @test typeof(FMUstate2) == FMI.fmi2FMUstate + @test typeof(FMUstate2) == FMI.fmi3FMUState fmiSetFMUstate(fmuStruct, FMUstate2) - @test fmi3GetFloat64(fmuStruct, "mass.s") == 0.5 + @test fmi3GetFloat64(fmuStruct, "h") == 1.0 fmiSetFMUstate(fmuStruct, FMUstate) - @test fmi3GetFloat64(fmuStruct, "mass.s") == 10.0 + @test fmi3GetFloat64(fmuStruct, "h") == 10.0 fmiFreeFMUstate!(fmuStruct, FMUstate) fmiFreeFMUstate!(fmuStruct, FMUstate2) else From 4cc5e914e5aa1526a775b2910ef5ef46b74b8345 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Wed, 6 Jul 2022 11:37:40 +0200 Subject: [PATCH 29/41] WIP: finished CSsim --- src/FMI3_comp_wraps.jl | 8 ++++---- src/FMI3_sim.jl | 26 +++++++++++++------------- test/FMI3/sim_CS.jl | 17 +++++++++-------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index 51a362ab..b0e4be51 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -920,18 +920,18 @@ function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsF end """ - fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) + fmi3DoStep!(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) -Wrapper for fmi3DoStep() in FMIImport/FMI3_c.jl +Wrapper for fmi3DoStep!() in FMIImport/FMI3_c.jl """ -function fmi3DoStep(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) +function fmi3DoStep!(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::fmi3Boolean, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] refeventEncountered = Ref(eventEncountered) refterminateSimulation = Ref(terminateSimulation) refearlyReturn = Ref(earlyReturn) reflastSuccessfulTime = Ref(lastSuccessfulTime) - fmi3DoStep(fmu.instances[end], fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) + fmi3DoStep!(fmu.instances[end], fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) eventEncountered = refeventEncountered[] terminateSimulation = refterminateSimulation[] earlyReturn = refearlyReturn[] diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index 41b220b5..1711ec73 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -315,7 +315,7 @@ If keyword `recordValues` is not set, a tuple of type (success::Bool, nothing) i ToDo: Improve Documentation. """ -function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; +function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; recordValues::fmi3ValueReferenceFormat = nothing, saveat = [], setup::Bool = true, @@ -323,9 +323,9 @@ function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; inputValues::fmi3ValueReferenceFormat = nothing, inputFunction = nothing) - recordValues = prepareValueReference(c, recordValues) - inputValues = prepareValueReference(c, inputValues) - variableSteps = c.fmu.modelDescription.CScanHandleVariableCommunicationStepSize + recordValues = prepareValueReference(fmu, recordValues) + inputValues = prepareValueReference(fmu, inputValues) + variableSteps = fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize success = false savedValues = nothing @@ -351,12 +351,12 @@ function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; if reset - fmi3Reset(c) + fmi3Reset(fmu) end if setup - fmi3EnterInitializationMode(c, t_start, t_stop) - fmi3ExitInitializationMode(c) + fmi3EnterInitializationMode(fmu, t_start, t_stop) + fmi3ExitInitializationMode(fmu) end t = t_start @@ -375,7 +375,7 @@ function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; i = 1 - values = (fmi3GetFloat64(c, recordValues)...,) + values = (fmi3GetFloat64(fmu, recordValues)...,) DiffEqCallbacks.copyat_or_push!(savedValues.t, i, t) DiffEqCallbacks.copyat_or_push!(savedValues.saveval, i, values, Val{false}) @@ -389,10 +389,10 @@ function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; end if inputFunction !== nothing - fmi3SetFloat64(c, inputValues, inputFunction(t)) + fmi3SetFloat64(fmu, inputValues, inputFunction(t)) end - fmi3DoStep(c, t, dt, fmi3True, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) + fmi3DoStep!(fmu, t, dt, fmi3True, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) if eventEncountered == fmi3True @warn "Event handling" end @@ -405,7 +405,7 @@ function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; t = t + dt #round(t + dt, digits=numDigits) i += 1 - values = (fmi3GetFloat64(c, recordValues)...,) + values = (fmi3GetFloat64(fmu, recordValues)...,) DiffEqCallbacks.copyat_or_push!(savedValues.t, i, t) DiffEqCallbacks.copyat_or_push!(savedValues.saveval, i, values, Val{false}) end @@ -424,10 +424,10 @@ function fmi3SimulateCS(fmu::FMU3, c::fmi3Instance, t_start::Real, t_stop::Real; end if inputFunction !== nothing - fmi3SetFloat64(c, inputValues, inputFunction(t)) + fmi3SetFloat64(fmu, inputValues, inputFunction(t)) end - fmi3DoStep(c, t, dt, fmi3True, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) + fmi3DoStep!(fmu, t, dt, fmi3True, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) if eventEncountered == fmi3True @warn "Event handling" end diff --git a/test/FMI3/sim_CS.jl b/test/FMI3/sim_CS.jl index 4d6f86f3..a7325c25 100644 --- a/test/FMI3/sim_CS.jl +++ b/test/FMI3/sim_CS.jl @@ -28,14 +28,15 @@ t_stop = 3.0 # @test solution.success # test with recording values -solution = fmiSimulateCS(fmuStruct, t_start, t_stop; recordValues=["mass.h", "mass.v"]) -@test solution.success -@test length(solution.values.saveval) == t_start:1e-2:t_stop |> length -@test length(solution.values.saveval[1]) == 2 - -t = solution.values.t -s = collect(d[1] for d in solution.values.saveval) -v = collect(d[2] for d in solution.values.saveval) +success,savedValues = fmiSimulateCS(fmuStruct, t_start, t_stop; recordValues=["h", "v"]) +@test success +@test length(savedValues.t) == 100 +#@test length(savedValues.t) == t_start:1e-2:t_stop |> length +@test length(savedValues.saveval[1]) == 2 + +t = savedValues.t +s = collect(d[1] for d in savedValues.saveval) +v = collect(d[2] for d in savedValues.saveval) @test t[1] == t_start @test t[end] == t_stop From b5ae46694765c864a9e9c45056ab15784dfe1974 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Thu, 7 Jul 2022 15:29:26 +0200 Subject: [PATCH 30/41] WIP: working on ME simulation --- src/FMI.jl | 3 +- src/FMI3_comp_wraps.jl | 6 ++-- src/FMI3_sim.jl | 75 ++++++++++++++++++++++++++---------------- test/runtests.jl | 4 +-- 4 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index f79bcf66..5055f57d 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -56,7 +56,7 @@ import FMIImport: fmi3DoStep! import FMIImport: fmi3EnterConfigurationMode, fmi3ExitConfigurationMode, fmi3GetNumberOfContinuousStates!, fmi3GetNumberOfEventIndicators!, fmi3GetContinuousStates!, fmi3GetNominalsOfContinuousStates! import FMIImport: fmi3EvaluateDiscreteStates, fmi3EnterStepMode import FMIImport: fmi3SetTime, fmi3SetContinuousStates, fmi3EnterEventMode, fmi3UpdateDiscreteStates, fmi3EnterContinuousTimeMode, fmi3CompletedIntegratorStep! -import FMIImport: fmi3GetContinuousStateDerivatives, fmi3GetEventIndicators, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates +import FMIImport: fmi3GetContinuousStateDerivatives, fmi3GetContinuousStateDerivatives!, fmi3GetEventIndicators, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates import FMIImport: fmi3StringToValueReference, fmi3ValueReferenceToString, fmi3ModelVariablesForValueReference import FMIImport: fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString import FMIImport: fmi3SetFloat32, fmi3SetFloat64, fmi3SetInt8, fmi3SetUInt8, fmi3SetInt16, fmi3SetUInt16, fmi3SetInt32, fmi3SetUInt32, fmi3SetInt64, fmi3SetUInt64, fmi3SetBoolean, fmi3SetBinary, fmi3SetClock, fmi3SetString @@ -77,6 +77,7 @@ export fmi3InstantiateCoSimulation!, fmi3InstantiateModelExchange!, fmi3Instanti export fmi3EnterInitializationMode, fmi3ExitInitializationMode export fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString export fmi3SetFloat64 +export fmi3UpdateDiscreteStates, fmi3GetContinuousStateDerivatives! import FMIImport: fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type export fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index b0e4be51..56dd1414 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -4,8 +4,8 @@ # # What is included in the file `FMI3_comp_wraps.jl` (FMU instance wrappers)? -# - wrappers to call fmi3InstanceFunctions from FMUs (FMI-functions, last instantiated component is used) [exported] -# - wrappers to call fmi3InstanceFunctions from FMUs (additional functions, last instantiated component is used) [exported] +# - wrappers to call fmi3InstanceFunctions from FMUs (FMI-functions, last instantiated instance is used) [exported] +# - wrappers to call fmi3InstanceFunctions from FMUs (additional functions, last instantiated instance is used) [exported] using FMIImport: FMU3, fmi3ModelDescription @@ -968,7 +968,7 @@ end Wrapper for fmi3SimulateME() in FMI/FMI3_sim.jl """ function fmi3SimulateME(fmu::FMU3, args...; kwargs...) - return fmi3SimulateME(fmu, nothing, args...; kwargs...) + return fmi3SimulateME(fmu.instances[end], args...; kwargs...) end diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index 1711ec73..f7f0697a 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -5,12 +5,12 @@ using DifferentialEquations, DiffEqCallbacks -using FMIImport: fmi3Instance +using FMIImport: FMU3Instance ############ Model-Exchange ############ # Read next time event from FMU and provide it to the integrator -function time_choice(c::fmi3Instance, integrator) +function time_choice(c::FMU3Instance, integrator) @debug "time_choice(_, _): Time event @ t=$(integrator.t)" discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime = fmi3UpdateDiscreteStates(c) @@ -24,17 +24,19 @@ function time_choice(c::fmi3Instance, integrator) end # Handles events and returns the values and nominals of the changed continuous states. -function handleEvents(c::fmi3Instance, enterEventMode::Bool, exitInContinuousMode::Bool) +function handleEvents(c::FMU3Instance, enterEventMode::Bool, exitInContinuousMode::Bool) nominalsChanged = fmi3False valuesChanged = fmi3False + println(enterEventMode) if enterEventMode fmi3EnterEventMode(c, c.stepEvent, c.stateEvent, c.rootsFound, Csize_t(c.fmu.modelDescription.numberOfEventIndicators), c.timeEvent) # TODO inputEvent handling - + println("before loop") + println("---------------------") discreteStatesNeedUpdate = fmi3True while discreteStatesNeedUpdate == fmi3True - + println(discreteStatesNeedUpdate) # update discrete states discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime = fmi3UpdateDiscreteStates(c) @@ -52,17 +54,19 @@ function handleEvents(c::fmi3Instance, enterEventMode::Bool, exitInContinuousMod end end - + println("afterLoop") if exitInContinuousMode + println("enterinContTimeMode") fmi3EnterContinuousTimeMode(c) end + println("after if") @debug "handleEvents(_, $(enterEventMode), $(exitInContinuousMode)): rootsFound: $(c.rootsFound) valuesChanged: $(valuesChanged) continuousStates: $(fmi3GetContinuousStates(c))", return valuesChanged, nominalsChanged end # Returns the event indicators for an FMU. -function condition(c::fmi3Instance, out, x, t, integrator, inputFunction, inputValues::Array{fmi3ValueReference}) # Event when event_f(u,t) == 0 +function condition(c::FMU3Instance, out, x, t, integrator, inputFunction, inputValues::Array{fmi3ValueReference}) # Event when event_f(u,t) == 0 if inputFunction !== nothing fmi3SetFloat64(c, inputValues, inputFunction(integrator.t)) end @@ -89,26 +93,32 @@ function condition(c::fmi3Instance, out, x, t, integrator, inputFunction, inputV end # Handles the upcoming events. -function affectFMU!(c::fmi3Instance, integrator, idx, inputFunction, inputValues::Array{fmi3ValueReference}, force=false) +function affectFMU!(c::FMU3Instance, integrator, idx, inputFunction, inputValues::Array{fmi3ValueReference}, force=false) # Event found - handle it - + # println(c) + # println(integrator) + # println(idx) + # println(inputFunction) + # println(inputValues) + # println("-------------------") + # println() @debug "affectFMU!(_, _, $(idx), _, _): x:$(integrator.u) [before handle events]" - + println("beforeSetContState") fmi3SetContinuousStates(c, integrator.u) - + println("beforeHandleEvents") continuousStatesChanged, nominalsChanged = handleEvents(c, true, Bool(sign(idx))) @debug "affectFMU!(_, _, $(idx), _, _): continuousStatesChanged=$(continuousStatesChanged) x_int:$(integrator.u) x_fmu:$(fmi3GetContinuousStates(c)) [after handle events]" - + println("beforeSetINputs") if inputFunction !== nothing fmi3SetFloat64(c, inputValues, inputFunction(integrator.t)) end - + println("beforeSetNewStates") if continuousStatesChanged == fmi3True integrator.u = fmi3GetContinuousStates(c) @debug "affectFMU!(_, _, $(idx), _, _): Set new state $(integrator.u)" end - + println("beforeSetNomsOfContState") if nominalsChanged == fmi3True x_nom = fmi3GetNominalsOfContinuousStates(c) end @@ -116,12 +126,12 @@ function affectFMU!(c::fmi3Instance, integrator, idx, inputFunction, inputValues end # Does one step in the simulation. -function stepCompleted(c::fmi3Instance, x, t, integrator, inputFunction, inputValues::Array{fmi3ValueReference}) +function stepCompleted(c::FMU3Instance, x, t, integrator, inputFunction, inputValues::Array{fmi3ValueReference}) fmi3SetContinuousStates(c, x) indicators = fmi3GetEventIndicators(c) - if length(indicators) > 0 + if length(indicators) > 0 c.stateEvent = fmi3False for i in 1:length(indicators) @@ -144,7 +154,7 @@ function stepCompleted(c::fmi3Instance, x, t, integrator, inputFunction, inputVa end # Returns the state derivatives of the FMU. -function fx(c::fmi3Instance, x, p, t) +function fx(c::FMU3Instance, x, p, t) @debug "fx($(x), _, $(t))" fmi3SetTime(c, t) fmi3SetContinuousStates(c, x) @@ -152,7 +162,7 @@ function fx(c::fmi3Instance, x, p, t) end # save FMU values -function saveValues(c::fmi3Instance, recordValues, u, t, integrator) +function saveValues(c::FMU3Instance, recordValues, u, t, integrator) fmi3SetTime(c, t) x = integrator.sol(t) fmi3SetContinuousStates(c, x) @@ -161,20 +171,18 @@ function saveValues(c::fmi3Instance, recordValues, u, t, integrator) end # wrapper -function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) - fmi3SimulateME(c.fmu, c, t_start, t_stop; kwargs...) -end +# function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) +# fmi3SimulateME(c.fmu.instances[end], t_start, t_stop; kwargs...) +# end """ Source: FMISpec3.0, Version D5ef1c1: 3.3. Code Example - Simulates a FMU instance for the given simulation time interval. State- and Time-Events are handled correctly. - Returns a tuple of type (ODESolution, DiffEqCallbacks.SavedValues). If keyword `recordValues` is not set, a tuple of type (ODESolution, nothing) is returned for consitency. """ -function fmi3SimulateME(fmu::FMU3, c::fmi3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; +function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; solver = nothing, customFx = nothing, recordValues::fmi3ValueReferenceFormat = nothing, @@ -203,7 +211,12 @@ function fmi3SimulateME(fmu::FMU3, c::fmi3Instance, t_start::Union{Real, Nothing savingValues = (length(recordValues) > 0) hasInputs = (length(inputValues) > 0) - + # println(t_start) + # println(t_stop) + # println(recordValues) + # println(inputValues) + # println(savingValues) + # println(hasInputs) if savingValues savedValues = SavedValues(Float64, Tuple{collect(Float64 for i in 1:length(recordValues))...}) @@ -212,7 +225,7 @@ function fmi3SimulateME(fmu::FMU3, c::fmi3Instance, t_start::Union{Real, Nothing saveat=saveat) push!(callbacks, savingCB) end - + # println(c.fmu.instances[end].state) # auto correct reset if only setup is given if reset === nothing reset = setup @@ -223,13 +236,16 @@ function fmi3SimulateME(fmu::FMU3, c::fmi3Instance, t_start::Union{Real, Nothing if reset fmi3Reset(c) end - + # println(c.fmu.instances[end].state) + # println(fmi3IsModelExchange(c.fmu)) if setup fmi3EnterInitializationMode(c, t_start, t_stop) fmi3ExitInitializationMode(c) end + println(c.state) eventHandling = c.fmu.modelDescription.numberOfEventIndicators > 0 + # println(eventHandling) timeEventHandling = false if eventHandling @@ -246,15 +262,16 @@ function fmi3SimulateME(fmu::FMU3, c::fmi3Instance, t_start::Union{Real, Nothing end fmi3EnterContinuousTimeMode(c) + # println(c.state) if eventHandling c.z_prev = fmi3GetEventIndicators(c) end - + # println(c.z_prev) # First evaluation of the FMU x0 = fmi3GetContinuousStates(c) x0_nom = fmi3GetNominalsOfContinuousStates(c) - + # println(x0) p = [] problem = ODEProblem(customFx, x0, (t_start, t_stop), p,) diff --git a/test/runtests.jl b/test/runtests.jl index 1b3869b5..0eed0057 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -75,7 +75,7 @@ function runtestsFMI3(exportingTool) #include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - include("FMI3/state.jl") + # include("FMI3/state.jl") end @testset "Directional derivatives" begin #include("FMI3/dir_ders.jl") @@ -87,7 +87,7 @@ function runtestsFMI3(exportingTool) # include("FMI3/sim_CS.jl") end @testset "ME Simulation" begin - # include("FMI3/sim_ME.jl") + include("FMI3/sim_ME.jl") end @testset "Support CS and ME simultaneously" begin # include("FMI3/cs_me.jl") From 77d71f0f95ba4a8c7e56bcbb3ba091daf94ece69 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 12 Jul 2022 15:01:50 +0200 Subject: [PATCH 31/41] WIP: still no ME simulation --- src/FMI.jl | 12 ++++++------ src/FMI3_sim.jl | 17 +++++++++-------- test/FMI3/getter_setter.jl | 5 +++-- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 5055f57d..7677a04f 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -72,12 +72,12 @@ import FMIImport: fmi3GetModelName, fmi3GetInstantiationToken, fmi3GetGeneration import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetSetState, fmi3CanSerializeFMUState, fmi3ProvidesDirectionalDerivatives, fmi3ProvidesAdjointDerivatives import FMIImport: fmi3Get, fmi3Get!, fmi3Set import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue -export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue -export fmi3InstantiateCoSimulation!, fmi3InstantiateModelExchange!, fmi3InstantiateScheduledExecution! -export fmi3EnterInitializationMode, fmi3ExitInitializationMode -export fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString -export fmi3SetFloat64 -export fmi3UpdateDiscreteStates, fmi3GetContinuousStateDerivatives! +# export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue +# export fmi3InstantiateCoSimulation!, fmi3InstantiateModelExchange!, fmi3InstantiateScheduledExecution! +# export fmi3EnterInitializationMode, fmi3ExitInitializationMode +# export fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString +# export fmi3SetFloat64 +# export fmi3UpdateDiscreteStates, fmi3GetContinuousStateDerivatives! import FMIImport: fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type export fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index f7f0697a..bdde6623 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -5,7 +5,8 @@ using DifferentialEquations, DiffEqCallbacks -using FMIImport: FMU3Instance + +using FMIImport ############ Model-Exchange ############ @@ -95,13 +96,13 @@ end # Handles the upcoming events. function affectFMU!(c::FMU3Instance, integrator, idx, inputFunction, inputValues::Array{fmi3ValueReference}, force=false) # Event found - handle it - # println(c) - # println(integrator) - # println(idx) - # println(inputFunction) - # println(inputValues) - # println("-------------------") - # println() + println(c) + println(integrator) + println(idx) + println(inputFunction) + println(inputValues) + println("-------------------") + println() @debug "affectFMU!(_, _, $(idx), _, _): x:$(integrator.u) [before handle events]" println("beforeSetContState") fmi3SetContinuousStates(c, integrator.u) diff --git a/test/FMI3/getter_setter.jl b/test/FMI3/getter_setter.jl index 4fed4967..09efb54e 100644 --- a/test/FMI3/getter_setter.jl +++ b/test/FMI3/getter_setter.jl @@ -70,8 +70,9 @@ fmiSet(fmuStruct, [rndReal, rndInteger, rndBoolean, rndString] #@test fmiGetStartValue(fmuStruct, "p_enumeration") == "myEnumeration1" -@test fmiGetStartValue(fmuStruct, "p_string") == "Hello World!" -@test fmiGetStartValue(fmuStruct, "p_real") == 0.0 +# TODO implement for fmi3 +# @test fmiGetStartValue(fmuStruct, "p_string") == "Hello World!" +# @test fmiGetStartValue(fmuStruct, "p_real") == 0.0 ################## # Testing Arrays # From 553bcbc9281c4093000b1147ee875dba850bdfcb Mon Sep 17 00:00:00 2001 From: JoKircher Date: Fri, 30 Sep 2022 13:02:48 +0200 Subject: [PATCH 32/41] WIP: fix ME simulation --- src/FMI.jl | 10 +++++----- src/FMI3_additional.jl | 1 + src/FMI3_sim.jl | 17 +++++++++++------ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index 553bf96a..8e69f0c9 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -73,11 +73,11 @@ import FMIImport: fmi3DependenciesSupported, fmi3GetModelIdentifier, fmi3CanGetS import FMIImport: fmi3Get, fmi3Get!, fmi3Set import FMIImport: fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue # export fmi3GetSolutionTime, fmi3GetSolutionState, fmi3GetSolutionValue -# export fmi3InstantiateCoSimulation!, fmi3InstantiateModelExchange!, fmi3InstantiateScheduledExecution! -# export fmi3EnterInitializationMode, fmi3ExitInitializationMode -# export fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString -# export fmi3SetFloat64 -# export fmi3UpdateDiscreteStates, fmi3GetContinuousStateDerivatives! +export fmi3InstantiateCoSimulation!, fmi3InstantiateModelExchange!, fmi3InstantiateScheduledExecution! +export fmi3EnterInitializationMode, fmi3ExitInitializationMode +export fmi3GetFloat32, fmi3GetFloat64, fmi3GetInt8, fmi3GetUInt8, fmi3GetInt16, fmi3GetUInt16, fmi3GetInt32, fmi3GetUInt32, fmi3GetInt64, fmi3GetUInt64, fmi3GetBoolean, fmi3GetBinary, fmi3GetClock, fmi3GetString +export fmi3SetFloat64 +export fmi3UpdateDiscreteStates, fmi3GetContinuousStateDerivatives! import FMIImport: fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type export fmi2TypeModelExchange, fmi2TypeCoSimulation, fmi2Type diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index dc3cd9ee..929570a0 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -18,6 +18,7 @@ import FMIImport: fmi3VariableNamingConventionFlat, fmi3VariableNamingConvention using ZipFile, EzXML + """ Returns how a variable depends on another variable based on the model description. """ diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index bdde6623..ef3dfba8 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -28,7 +28,7 @@ end function handleEvents(c::FMU3Instance, enterEventMode::Bool, exitInContinuousMode::Bool) nominalsChanged = fmi3False valuesChanged = fmi3False - println(enterEventMode) + # println(enterEventMode) if enterEventMode fmi3EnterEventMode(c, c.stepEvent, c.stateEvent, c.rootsFound, Csize_t(c.fmu.modelDescription.numberOfEventIndicators), c.timeEvent) @@ -60,7 +60,9 @@ function handleEvents(c::FMU3Instance, enterEventMode::Bool, exitInContinuousMod println("enterinContTimeMode") fmi3EnterContinuousTimeMode(c) end - println("after if") + # println(valuesChanged) + # println(nominalsChanged) + println(c) @debug "handleEvents(_, $(enterEventMode), $(exitInContinuousMode)): rootsFound: $(c.rootsFound) valuesChanged: $(valuesChanged) continuousStates: $(fmi3GetContinuousStates(c))", return valuesChanged, nominalsChanged @@ -69,6 +71,7 @@ end # Returns the event indicators for an FMU. function condition(c::FMU3Instance, out, x, t, integrator, inputFunction, inputValues::Array{fmi3ValueReference}) # Event when event_f(u,t) == 0 if inputFunction !== nothing + println("try to work with nothing1") fmi3SetFloat64(c, inputValues, inputFunction(integrator.t)) end @@ -89,6 +92,8 @@ function condition(c::FMU3Instance, out, x, t, integrator, inputFunction, inputV # c.z_prev[i] = indicators[i] end end + # print("condition: out: ") + # println(indicators) @debug "condition(_, _, $(x), $(t), _, _, _): eventIndicators $indicators rootsFound $(c.rootsFound) stateEvent $(c.stateEvent)" copy!(out, indicators) end @@ -110,8 +115,9 @@ function affectFMU!(c::FMU3Instance, integrator, idx, inputFunction, inputValues continuousStatesChanged, nominalsChanged = handleEvents(c, true, Bool(sign(idx))) @debug "affectFMU!(_, _, $(idx), _, _): continuousStatesChanged=$(continuousStatesChanged) x_int:$(integrator.u) x_fmu:$(fmi3GetContinuousStates(c)) [after handle events]" - println("beforeSetINputs") + println("beforeSetInputs") if inputFunction !== nothing + println("try to work with nothing2") fmi3SetFloat64(c, inputValues, inputFunction(integrator.t)) end println("beforeSetNewStates") @@ -289,11 +295,10 @@ function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing if eventHandling eventCb = VectorContinuousCallback((out, x, t, integrator) -> condition(c, out, x, t, integrator, inputFunction, inputValues), - (integrator, idx) -> affectFMU!(c, integrator, idx, inputFunction, inputValues, true), + (integrator, idx) -> affectFMU!(c, integrator, idx, inputFunction, inputValues), Int64(c.fmu.modelDescription.numberOfEventIndicators); rootfind = RightRootFind, - save_positions=(saveAtEvent,saveAtEvent), - interp_points=rootSearchInterpolationPoints)#,abstol=1e-16, reltol=1e-12, repeat_nudge=1//100) + save_positions=(saveAtEvent,saveAtEvent))#, interp_points=rootSearchInterpolationPoints,abstol=1e-16, reltol=1e-12, repeat_nudge=1//100) push!(callbacks, eventCb) if timeEventHandling From d97033c903bdbae58aaa41be70e2cddeccf84002 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Mon, 10 Oct 2022 13:18:14 +0200 Subject: [PATCH 33/41] added status tag for next meeting --- src/FMI3_additional.jl | 2 ++ src/FMI3_comp_wraps.jl | 3 +++ src/FMI3_sim.jl | 19 ++++++++++++++----- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 929570a0..392fdad3 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -1,3 +1,5 @@ +# STATUS: no todos + # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher # Licensed under the MIT license. See LICENSE file in the project root for details. diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index 56dd1414..80358304 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -1,3 +1,6 @@ +# STATUS: no todos + + # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher # Licensed under the MIT license. See LICENSE file in the project root for details. diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index ef3dfba8..8d7f26b5 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -1,3 +1,7 @@ +# STATUS: simulation of ME is not working, needs fixing, +# other TODOs include adding simulation for SE + + # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher # Licensed under the MIT license. See LICENSE file in the project root for details. @@ -490,13 +494,18 @@ Returns: ToDo: Improve Documentation. """ -function fmi3Simulate(c::fmi3Instance, t_start::Real = 0.0, t_stop::Real = 1.0;kwargs...) +function fmi3Simulate(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) - if fmi3IsCoSimulation(c.fmu) - return fmi3SimulateCS(c, t_start, t_stop; kwargs...) - elseif fmi3IsModelExchange(c.fmu) - return fmi3SimulateME(c, t_start, t_stop; kwargs...) + if fmu.type == fmi3TypeCoSimulation + return fmi3SimulateCS(fmu, c, t_start, t_stop; kwargs...) + elseif fmu.type == fmi3TypeModelExchange + return fmi3SimulateME(fmu, c, t_start, t_stop; kwargs...) else error(unknownFMUType) end end + + +function fmi3Simulate(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) + fmi3Simulate(c.fmu, c, t_start, t_stop; kwargs...) +end From 0af0aca011587b1cc413223fdb1ea165a64a7717 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Mon, 10 Oct 2022 13:40:35 +0200 Subject: [PATCH 34/41] FMI3additional up to fmi2 structure --- src/FMI3_additional.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FMI3_additional.jl b/src/FMI3_additional.jl index 392fdad3..e535b53d 100644 --- a/src/FMI3_additional.jl +++ b/src/FMI3_additional.jl @@ -1,4 +1,5 @@ # STATUS: no todos +# ABM: done # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher From f254edfe40a27146bcb9a4e291ff405bd9c5f0d3 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 11 Oct 2022 13:29:54 +0200 Subject: [PATCH 35/41] fmi3_comp_wraps.jl up to fmi2 standard --- src/FMI3_comp_wraps.jl | 618 ++++++++++++++++++----------------------- src/FMI3_sim.jl | 4 +- 2 files changed, 267 insertions(+), 355 deletions(-) diff --git a/src/FMI3_comp_wraps.jl b/src/FMI3_comp_wraps.jl index 80358304..4b769075 100644 --- a/src/FMI3_comp_wraps.jl +++ b/src/FMI3_comp_wraps.jl @@ -1,5 +1,5 @@ # STATUS: no todos - +# ABM: done # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher @@ -10,11 +10,11 @@ # - wrappers to call fmi3InstanceFunctions from FMUs (FMI-functions, last instantiated instance is used) [exported] # - wrappers to call fmi3InstanceFunctions from FMUs (additional functions, last instantiated instance is used) [exported] - -using FMIImport: FMU3, fmi3ModelDescription -using FMIImport: fmi3Float32, fmi3Float64, fmi3Int8, fmi3Int16, fmi3Int32, fmi3Int64, fmi3Boolean, fmi3String, fmi3Binary, fmi3UInt8, fmi3UInt16, fmi3UInt32, fmi3UInt64, fmi3Byte -using FMIImport: fmi3Clock, fmi3FMUState -using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate +# TODO why is this here? +# using FMIImport: FMU3, fmi3ModelDescription +# using FMIImport: fmi3Float32, fmi3Float64, fmi3Int8, fmi3Int16, fmi3Int32, fmi3Int64, fmi3Boolean, fmi3String, fmi3Binary, fmi3UInt8, fmi3UInt16, fmi3UInt32, fmi3UInt64, fmi3Byte +# using FMIImport: fmi3Clock, fmi3FMUState +# using FMIImport: fmi3CallbackLogger, fmi3CallbackIntermediateUpdate, fmi3CallbackClockUpdate # fmi-spec """ @@ -24,7 +24,7 @@ Wrapper for fmi3FreeInstance!() in FMIImport/FMI3_c.jl """ function fmi3FreeInstance!(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi2FreeInstance!(fmu.instances[end]) # this command also removes the instance from the array + fmi3FreeInstance!(fmu.instances[end]) # this command also removes the instance from the array end """ @@ -34,19 +34,17 @@ Wrapper for fmi3SetDebugLogging() in FMIImport/FMI3_int.jl """ function fmi3SetDebugLogging(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3SetDebugLogging(fmu.instances[end]) end """ - fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) + fmi3EnterInitializationMode(fmu::FMU3, args...; kwargs...) Wrapper for fmi3EnterInitializationMode() in FMIImport/FMI3_c.jl """ -function fmi3EnterInitializationMode(fmu::FMU3, startTime::Real = 0.0, stopTime::Real = startTime; tolerance::Real = 0.0) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterInitializationMode(fmu.instances[end], startTime, stopTime; tolerance = tolerance) +function fmi3EnterInitializationMode(fmu::FMU3, args...; kwargs...) + @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3EnterInitializationMode(fmu.instances[end], args...; kwargs...) end """ @@ -56,7 +54,6 @@ Wrapper for fmi3ExitInitializationMode() in FMIImport/FMI3_c.jl """ function fmi3ExitInitializationMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3ExitInitializationMode(fmu.instances[end]) end @@ -67,657 +64,619 @@ Wrapper for fmi3Terminate() in FMIImport/FMI3_c.jl """ function fmi3Terminate(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3Terminate(fmu.instances[end]) end """ fmi3Reset(fmu::FMU3) -Wrapper for fmi2Reset() in FMIImport/FMI3_c.jl +Wrapper for fmi3Reset() in FMIImport/FMI3_c.jl """ function fmi3Reset(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3Reset(fmu.instances[end]) end """ - fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetFloat32(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetFloat32() in FMIImport/FMI3_int.jl """ -function fmi3GetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetFloat32(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat32(fmu.instances[end], vr) + fmi3GetFloat32(fmu.instances[end], args...; kwargs...) end """ - fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) + fmi3GetFloat32!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetFloat32!() in FMIImport/FMI3_int.jl """ -function fmi3GetFloat32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) +function fmi3GetFloat32!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat32!(fmu.instances[end], vr, values) + fmi3GetFloat32!(fmu.instances[end], args...; kwargs...) end """ -fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) +fmi3SetFloat32(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetFloat32() in FMIImport/FMI3_int.jl """ -function fmi3SetFloat32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float32}, fmi3Float32}) +function fmi3SetFloat32(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFloat32(fmu.instances[end], vr, values) + fmi3SetFloat32(fmu.instances[end], args...; kwargs...) end """ - fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetFloat64(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetFloat64() in FMIImport/FMI3_int.jl """ -function fmi3GetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetFloat64(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat64(fmu.instances[end], vr) + fmi3GetFloat64(fmu.instances[end], args...; kwargs...) end """ - fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + fmi3GetFloat64!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetFloat64!() in FMIImport/FMI3_int.jl """ -function fmi3GetFloat64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) +function fmi3GetFloat64!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetFloat64!(fmu.instances[end], vr, values) + fmi3GetFloat64!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) + fmi3SetFloat64(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetFloat64() in FMIImport/FMI3_int.jl """ -function fmi3SetFloat64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Float64}, fmi3Float64}) +function fmi3SetFloat64(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFloat64(fmu.instances[end], vr, values) + fmi3SetFloat64(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetInt8(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt8() in FMIImport/FMI3_int.jl """ -function fmi3GetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetInt8(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt8(fmu.instances[end], vr) + fmi3GetInt8(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + fmi3GetInt8!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt8!() in FMIImport/FMI3_int.jl """ -function fmi3GetInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) +function fmi3GetInt8!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt8!(fmu.instances[end], vr, values) + fmi3GetInt8!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) + fmi3SetInt8(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetInt8() in FMIImport/FMI3_int.jl """ -function fmi3SetInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int8}, fmi3Int8}) +function fmi3SetInt8(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt8(fmu.instances[end], vr, values) + fmi3SetInt8(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetUInt8(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt8() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetUInt8(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt8(fmu.instances[end], vr) + fmi3GetUInt8(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + fmi3GetUInt8!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt8!() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt8!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) +function fmi3GetUInt8!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt8!(fmu.instances[end], vr, values) + fmi3GetUInt8!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) + fmi3SetUInt8(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetUInt8() in FMIImport/FMI3_int.jl """ -function fmi3SetUInt8(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt8}, fmi3UInt8}) +function fmi3SetUInt8(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt8(fmu.instances[end], vr, values) + fmi3SetUInt8(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetInt16(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt16() in FMIImport/FMI3_int.jl """ -function fmi3GetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetInt16(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt16(fmu.instances[end], vr) + fmi3GetInt16(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + fmi3GetInt16!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt16!() in FMIImport/FMI3_int.jl """ -function fmi3GetInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) +function fmi3GetInt16!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt16!(fmu.instances[end], vr, values) + fmi3GetInt16!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) + fmi3SetInt16(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetInt16() in FMIImport/FMI3_int.jl """ -function fmi3SetInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int16}, fmi3Int16}) +function fmi3SetInt16(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt16(fmu.instances[end], vr, values) + fmi3SetInt16(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetUInt16(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt16() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetUInt16(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt16(fmu.instances[end], vr) + fmi3GetUInt16(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + fmi3GetUInt16!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt16!() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt16!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) +function fmi3GetUInt16!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt16!(fmu.instances[end], vr, values) + fmi3GetUInt16!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) + fmi3SetUInt16(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetUInt16() in FMIImport/FMI3_int.jl """ -function fmi3SetUInt16(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt16}, fmi3UInt16}) +function fmi3SetUInt16(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt16(fmu.instances[end], vr, values) + fmi3SetUInt16(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetInt32(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt32() in FMIImport/FMI3_int.jl """ -function fmi3GetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetInt32(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt32(fmu.instances[end], vr) + fmi3GetInt32(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + fmi3GetInt32!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt32!() in FMIImport/FMI3_int.jl """ -function fmi3GetInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) +function fmi3GetInt32!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt32!(fmu.instances[end], vr, values) + fmi3GetInt32!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) + fmi3SetInt32(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetInt32() in FMIImport/FMI3_int.jl """ -function fmi3SetInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int32}, fmi3Int32}) +function fmi3SetInt32(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt32(fmu.instances[end], vr, values) + fmi3SetInt32(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetUInt32(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt32() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetUInt32(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt32(fmu.instances[end], vr) + fmi3GetUInt32(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + fmi3GetUInt32!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt32!() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt32!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) +function fmi3GetUInt32!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt32!(fmu.instances[end], vr, values) + fmi3GetUInt32!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) + fmi3SetUInt32(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetUInt32() in FMIImport/FMI3_int.jl """ -function fmi3SetUInt32(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt32}, fmi3UInt32}) +function fmi3SetUInt32(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt32(fmu.instances[end], vr, values) + fmi3SetUInt32(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetInt64(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt64() in FMIImport/FMI3_int.jl """ -function fmi3GetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetInt64(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt64(fmu.instances[end], vr) + fmi3GetInt64(fmu.instances[end], args...; kwargs...) end """ - fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + fmi3GetInt64!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetInt64!() in FMIImport/FMI3_int.jl """ -function fmi3GetInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) +function fmi3GetInt64!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetInt64!(fmu.instances[end], vr, values) + fmi3GetInt64!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) + fmi3SetInt64(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetInt64() in FMIImport/FMI3_int.jl """ -function fmi3SetInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Int64}, fmi3Int64}) +function fmi3SetInt64(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetInt64(fmu.instances[end], vr, values) + fmi3SetInt64(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetUInt64(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt64() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetUInt64(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt64(fmu.instances[end], vr) + fmi3GetUInt64(fmu.instances[end], args...; kwargs...) end """ - fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + fmi3GetUInt64!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetUInt64!() in FMIImport/FMI3_int.jl """ -function fmi3GetUInt64!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) +function fmi3GetUInt64!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetUInt64!(fmu.instances[end], vr, values) + fmi3GetUInt64!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) + fmi3SetUInt64(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetUInt64() in FMIImport/FMI3_int.jl """ -function fmi3SetUInt64(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3UInt64}, fmi3UInt64}) +function fmi3SetUInt64(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetUInt64(fmu.instances[end], vr, values) + fmi3SetUInt64(fmu.instances[end], args...; kwargs...) end """ - fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetBoolean(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetBoolean() in FMIImport/FMI3_int.jl """ -function fmi3GetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetBoolean(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBoolean(fmu.instances[end], vr) + fmi3GetBoolean(fmu.instances[end], args...; kwargs...) end """ - fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) + fmi3GetBoolean!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetBoolean!() in FMIImport/FMI3_int.jl """ -function fmi3GetBoolean!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) +function fmi3GetBoolean!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBoolean!(fmu.instances[end], vr, values) + fmi3GetBoolean!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool, Array{fmi3Boolean}}) + fmi3SetBoolean(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetBoolean!() in FMIImport/FMI3_int.jl """ -function fmi3SetBoolean(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{Bool}, Bool}) +function fmi3SetBoolean(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetBoolean(fmu.instances[end], vr, values) + fmi3SetBoolean(fmu.instances[end], args...; kwargs...) end """ - fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetString(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetString() in FMIImport/FMI3_int.jl """ -function fmi3GetString(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetString(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetString(fmu.instances[end], vr) + fmi3GetString(fmu.instances[end], args...; kwargs...) end """ - fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + fmi3GetString!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetString!() in FMIImport/FMI3_int.jl """ -function fmi3GetString!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) +function fmi3GetString!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetString!(fmu.instances[end], vr, values) + fmi3GetString!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) + fmi3SetString(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetString() in FMIImport/FMI3_int.jl """ -function fmi3SetString(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{String}, String}) +function fmi3SetString(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetString(fmu.instances[end], vr, values) + fmi3SetString(fmu.instances[end], args...; kwargs...) end """ - fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetBinary(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetBinary() in FMIImport/FMI3_int.jl """ -function fmi3GetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetBinary(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBinary(fmu.instances[end], vr) + fmi3GetBinary(fmu.instances[end], args...; kwargs...) end """ - fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + fmi3GetBinary!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetBinary!() in FMIImport/FMI3_int.jl """ -function fmi3GetBinary!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) +function fmi3GetBinary!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetBinary!(fmu.instances[end], vr, values) + fmi3GetBinary!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Binary}, fmi3Binary}) + fmi3SetBinary(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetBinary() in FMIImport/FMI3_int.jl """ -function fmi3SetBinary(fmu::FMU3, vr::fmi3ValueReferenceFormat, valueSizes::Union{Array{Csize_t}, Csize_t}, values::Union{Array{fmi3Binary}, fmi3Binary}) +function fmi3SetBinary(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetBinary(fmu.instances[end], vr, valueSizes, values) + fmi3SetBinary(fmu.instances[end], args...; kwargs...) end """ - fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetClock(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetClock() in FMIImport/FMI3_int.jl """ -function fmi3GetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetClock(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetClock(fmu.instances[end], vr) + fmi3GetClock(fmu.instances[end], args...; kwargs...) end """ - fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + fmi3GetClock!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetClock!() in FMIImport/FMI3_int.jl """ -function fmi3GetClock!(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) +function fmi3GetClock!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetClock!(fmu.instances[end], vr, values) + fmi3GetClock!(fmu.instances[end], args...; kwargs...) end """ - fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) + fmi3SetClock(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetClock() in FMIImport/FMI3_int.jl """ -function fmi3SetClock(fmu::FMU3, vr::fmi3ValueReferenceFormat, values::Union{Array{fmi3Clock}, fmi3Clock}) +function fmi3SetClock(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3SetClock(fmu.instances[end], args...; kwargs...) +end + +""" + fmiGet(fmu::FMU3, args...; kwargs...) - fmi3SetClock(fmu.instances[end], vr, values) +Wrapper for fmiGet() in FMIImport/FMI3_ext.jl +""" +function fmiGet(fmu::FMU3, args...; kwargs...) + @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3Get(fmu.components[end], args...; kwargs...) end """ - fmi3GetFMUstate(fmu::FMU3) + fmiGet!(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3GetFMUstate() in FMIImport/FMI3_int.jl +Wrapper for fmiGet!() in FMIImport/FMI3_ext.jl """ -function fmi3GetFMUState(fmu::FMU3) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] +function fmiGet!(fmu::FMU3, args...; kwargs...) + @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3Get!(fmu.components[end], args...; kwargs...) +end - fmi3GetFMUState(fmu.instances[end]) +""" + fmiSet(fmu::FMU3, args...; kwargs...) + +Wrapper for fmiSet() in FMIImport/FMI3_ext.jl +""" +function fmiSet(fmu::FMU3, args...; kwargs...) + @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3Set(fmu.components[end], args...; kwargs...) end """ - fmi3SetFMUstate(fmu::FMU3,state::fmi3FMUState) + fmi3GetFMUstate(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3SetFMUstate() in FMIImport/FMI3_c.jl +Wrapper for fmi3GetFMUstate() in FMIImport/FMI3_int.jl """ -function fmi3SetFMUState(fmu::FMU3, state::fmi3FMUState) +function fmi3GetFMUState(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SetFMUState(fmu.instances[end], state) + fmi3GetFMUState(fmu.instances[end], args...; kwargs...) end """ - fmi3FreeFMUState!(fmu::FMU3, state::fmi3FMUState) + fmi3SetFMUstate(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3FreeFMUState!() in FMIImport/FMI3_int.jl +Wrapper for fmi3SetFMUstate() in FMIImport/FMI3_c.jl """ -function fmi3FreeFMUState!(fmu::FMU3, state::fmi3FMUState) +function fmi3SetFMUState(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3FreeFMUState!(fmu.instances[end], state) + fmi3SetFMUState(fmu.instances[end], args...; kwargs...) end """ - fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) + fmi3FreeFMUState!(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3SerializedFMUStateSize() in FMIImport/FMI3_int.jl +Wrapper for fmi3FreeFMUState!() in FMIImport/FMI3_int.jl """ -function fmi3SerializedFMUStateSize(fmu::FMU3, state::fmi3FMUState) +function fmi3FreeFMUState!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SerializedFMUStateSize(fmu.instances[end], state) + fmi3FreeFMUState!(fmu.instances[end], args...; kwargs...) end """ - fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) + fmi3SerializedFMUStateSize(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3SerializeFMUState() in FMIImport/FMI3_int.jl +Wrapper for fmi3SerializedFMUStateSize() in FMIImport/FMI3_int.jl """ -function fmi3SerializeFMUState(fmu::FMU3, state::fmi3FMUState) +function fmi3SerializedFMUStateSize(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3SerializeFMUState(fmu.instances[end], state) + fmi3SerializedFMUStateSize(fmu.instances[end], args...; kwargs...) end """ - fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) + fmi3SerializeFMUState(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3DeSerializeFMUState() in FMIImport/FMI3_int.jl +Wrapper for fmi3SerializeFMUState() in FMIImport/FMI3_int.jl """ -function fmi3DeSerializeFMUState(fmu::FMU3, serializedState::Array{fmi3Byte}) +function fmi3SerializeFMUState(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3DeSerializeFMUState(fmu.instances[end], serializedState) + fmi3SerializeFMUState(fmu.instances[end], args...; kwargs...) end """ - fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::fmi3Float64 = 1.0)) + fmi3DeSerializeFMUState(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3GetDirectionalDerivative() in FMIImport/FMI3_int.jl +Wrapper for fmi3DeSerializeFMUState() in FMIImport/FMI3_int.jl """ -function fmi3GetDirectionalDerivative(fmu::FMU3, - unknowns::fmi3ValueReference, - knowns::fmi3ValueReference, - seed::fmi3Float64 = 1.0) +function fmi3DeSerializeFMUState(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative(fmu.instances[end], unknowns, knowns, seed) + fmi3DeSerializeFMUState(fmu.instances[end], args...; kwargs...) end """ - fmi3GetDirectionalDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + fmi3GetDirectionalDerivative(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetDirectionalDerivative() in FMIImport/FMI3_int.jl """ -function fmi3GetDirectionalDerivative(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) +function fmi3GetDirectionalDerivative(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative(fmu.instances[end], unknowns, knowns, seed) + fmi3GetDirectionalDerivative(fmu.instances[end], args...; kwargs...) end """ - fmi3GetDirectionalDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, knowns::Array{fmi3ValueReference}, sensitivity::Array{fmi3Float64}, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) + fmi3GetDirectionalDerivative!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetDirectionalDerivative!() in FMIImport/FMI3_int.jl """ -function fmi3GetDirectionalDerivative!(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - sensitivity::Array{fmi3Float64}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) +function fmi3GetDirectionalDerivative!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetDirectionalDerivative!(fmu.instances[end], unknowns, knowns, sensitivity, seed) + fmi3GetDirectionalDerivative!(fmu.instances[end], args...; kwargs...) end """ - fmi3GetAdjointDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::fmi3Float64 = 1.0)) + fmi3GetAdjointDerivative(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetAdjointDerivative() in FMIImport/FMI3_int.jl """ -function fmi3GetAdjointDerivative(fmu::FMU3, - unknowns::fmi3ValueReference, - knowns::fmi3ValueReference, - seed::fmi3Float64 = 1.0) +function fmi3GetAdjointDerivative(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative(fmu.instances[end], unknowns, knowns, seed) + fmi3GetAdjointDerivative(fmu.instances[end], args...; kwargs...) end """ - fmi3GetAdjointDerivative(fmu::FMU3, unknowns::fmi3ValueReference, knowns::fmi3ValueReference, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - -Wrapper for fmi3GetAdjointDerivative() in FMIImport/FMI3_int.jl + fmi3GetAdjointDerivative!(fmu::FMU3, args...; kwargs...) + +Wrapper for fmi3GetAdjointDerivative!() in FMIImport/FMI3_int.jl """ -function fmi3GetAdjointDerivative(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) +function fmi3GetAdjointDerivative!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetAdjointDerivative(fmu.instances[end], unknowns, knowns, seed) + fmi3GetAdjointDerivative!(fmu.instances[end], args...; kwargs...) end """ - fmi3GetAdjointDerivative!(fmu::FMU3, unknowns::Array{fmi3ValueReference}, knowns::Array{fmi3ValueReference}, sensitivity::Array{fmi3Float64}, seed::Array{fmi3Float64} = Array{fmi3Float64}([])) - -Wrapper for fmi3GetAdjointDerivative!() in FMIImport/FMI3_int.jl + fmi3SampleDirectionalDerivative!(fmu::FMU3, args...; kwargs...) + +Wrapper for fmi3SampleDirectionalDerivative!() in FMIImport/FMI3_ext.jl """ -function fmi3GetAdjointDerivative!(fmu::FMU3, - unknowns::Array{fmi3ValueReference}, - knowns::Array{fmi3ValueReference}, - sensitivity::Array{fmi3Float64}, - seed::Array{fmi3Float64} = Array{fmi3Float64}([])) +function fmi3SampleDirectionalDerivative!(fmu::FMU3, args...; kwargs...) + @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3SampleDirectionalDerivative!(fmu.components[end], args...; kwargs...) +end - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] +""" + fmi3SampleDirectionalDerivative(fmu::FMU3, args...; kwargs...) - fmi3GetAdjointDerivative!(fmu.instances[end], unknowns, knowns, sensitivity, seed) +Wrapper for fmi3SampleDirectionalDerivative() in FMIImport/FMI3_ext.jl +""" +function fmi3SampleDirectionalDerivative(fmu::FMU3, args...; kwargs...) + @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3SampleDirectionalDerivative(fmu.components[end], args...; kwargs...) end + """ - fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) - -Wrapper for fmi3GetOutputDerivatives() in FMIImport/FMI3_int.jl + fmi3GetJacobian!(fmu::FMU3, args...; kwargs...) + +Wrapper for fmi3GetJacobian!() in FMIImport/FMI3_ext.jl """ -function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Array{Integer}) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] +function fmi3GetJacobian!(fmu::FMU3, args...; kwargs...) + @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3GetJacobian!(fmu.components[end], args...; kwargs...) +end + +""" + fmi3GetJacobian(fmu::FMU3, args...; kwargs...) - fmi3GetOutputDerivatives(fmu.instances[end], vr, order) +Wrapper for fmi3GetJacobian() in FMIImport/FMI3_ext.jl +""" +function fmi3GetJacobian(fmu::FMU3, args...; kwargs...) + @assert length(fmu.components) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] + fmi3GetJacobian(fmu.components[end], args...; kwargs...) end """ - fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReferenceFormat, order::Integer) + fmi3GetOutputDerivatives(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetOutputDerivatives() in FMIImport/FMI3_int.jl """ -function fmi3GetOutputDerivatives(fmu::FMU3, vr::fmi3ValueReference, order::Integer) +function fmi3GetOutputDerivatives(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetOutputDerivatives(fmu.instances[end], vr, order) + fmi3GetOutputDerivatives(fmu.instances[end], args...; kwargs...) end """ @@ -727,7 +686,6 @@ Wrapper for fmi3EnterConfigurationMode() in FMIImport/FMI3_c.jl """ function fmi3EnterConfigurationMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3EnterConfigurationMode(fmu.instances[end]) end @@ -738,30 +696,27 @@ Wrapper for fmi3GetNumberOfContinuousStates() in FMIImport/FMI3_c.jl """ function fmi3GetNumberOfContinuousStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3GetNumberOfContinuousStates(fmu.instances[end]) end """ - fmi3GetNumberOfEventIndicators(fmu::FMU3) - -Wrapper for fmi3GetNumberOfEventIndicators() in FMIImport/FMI3_c.jl + fmi3GetNumberOfVariableDependencies(fmu::FMU3, args...; kwargs...) + +Wrapper for fmi3GetNumberOfVariableDependencies() in FMIImport/FMI3_c.jl """ -function fmi3GetNumberOfEventIndicators(fmu::FMU3) +function fmi3GetNumberOfVariableDependencies(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfEventIndicators(fmu.instances[end]) + fmi3GetNumberOfVariableDependencies(fmu.instances[end], args...; kwargs...) end """ - fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) - -Wrapper for fmi3GetNumberOfVariableDependencies() in FMIImport/FMI3_c.jl + fmi3GetVariableDependencies(fmu::FMU3, args...; kwargs...) + +Wrapper for fmi3GetVariableDependencies() in FMIImport/FMI3_c.jl """ -function fmi3GetNumberOfVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) +function fmi3GetVariableDependencies(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetNumberOfVariableDependencies(fmu.instances[end], vr) + fmi3GetVariableDependencies(fmu.instances[end], args...; kwargs...) end """ @@ -771,21 +726,9 @@ Wrapper for fmi3GetContinuousStates() in FMIImport/FMI3_c.jl """ function fmi3GetContinuousStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3GetContinuousStates(fmu.instances[end]) end -""" - fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) - -Wrapper for fmi3GetVariableDependencies() in FMIImport/FMI3_c.jl -""" -function fmi3GetVariableDependencies(fmu::FMU3, vr::Union{fmi3ValueReference, String}) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetVariableDependencies(fmu.instances[end], vr) -end - """ fmi3GetNominalsOfContinuousStates(fmu::FMU3) @@ -793,7 +736,6 @@ Wrapper for fmi3GetNominalsOfContinuousStates() in FMIImport/FMI3_c.jl """ function fmi3GetNominalsOfContinuousStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3GetNominalsOfContinuousStates(fmu.instances[end]) end @@ -804,7 +746,6 @@ Wrapper for fmi3EvaluateDiscreteStates() in FMIImport/FMI3_c.jl """ function fmi3EvaluateDiscreteStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3EvaluateDiscreteStates(fmu.instances[end]) end @@ -815,7 +756,6 @@ Wrapper for fmi3UpdateDiscreteStates() in FMIImport/FMI3_c.jl """ function fmi3UpdateDiscreteStates(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3UpdateDiscreteStates(fmu.instances[end]) end @@ -826,7 +766,6 @@ Wrapper for fmi3EnterContinuousTimeMode() in FMIImport/FMI3_c.jl """ function fmi3EnterContinuousTimeMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3EnterContinuousTimeMode(fmu.instances[end]) end @@ -837,7 +776,6 @@ Wrapper for fmi3EnterStepMode() in FMIImport/FMI3_c.jl """ function fmi3EnterStepMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3EnterStepMode(fmu.instances[end]) end @@ -848,33 +786,27 @@ Wrapper for fmi3ExitConfigurationMode() in FMIImport/FMI3_c.jl """ function fmi3ExitConfigurationMode(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3ExitConfigurationMode(fmu.instances[end]) end """ - fmi3SetTime(fmu::FMU3, time::Real) + fmi3SetTime(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetTime() in FMIImport/FMI3_c.jl """ -function fmi3SetTime(fmu::FMU3, time::Real) +function fmi3SetTime(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmu.t = time - fmi3SetTime(fmu.instances[end], fmi3Float64(time)) + fmi3SetTime(fmu.instances[end], args...; kwargs...) end """ - fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) + fmi3SetContinuousStates(fmu::FMU3, args...; kwargs...) Wrapper for fmi3SetContinuousStates() in FMIImport/FMI3_c.jl """ -function fmi3SetContinuousStates(fmu::FMU3, x::Union{Array{Float32}, Array{Float64}}) +function fmi3SetContinuousStates(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - nx = Csize_t(length(x)) - fmu.x = x - fmi3SetContinuousStates(fmu.instances[end], Array{fmi3Float64}(x), nx) + fmi3SetContinuousStates(fmu.instances[end], args...; kwargs...) end """ @@ -884,7 +816,6 @@ Wrapper for fmi3GetContinuousStateDerivatives() in FMIImport/FMI3_c.jl """ function fmi3GetContinuousStateDerivatives(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3GetContinuousStateDerivatives(fmu.instances[end]) end @@ -895,71 +826,53 @@ Wrapper for fmi3GetEventIndicators() in FMIImport/FMI3_c.jl """ function fmi3GetEventIndicators(fmu::FMU3) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - fmi3GetEventIndicators(fmu.instances[end]) end """ -fmi3CompletedIntegratorStep(fmu::FMU3, noSetFMUStatePriorToCurrentPoint::fmi3Boolean) +fmi3CompletedIntegratorStep(fmu::FMU3, args...; kwargs...) Wrapper for fmi3CompletedIntegratorStep() in FMIImport/FMI3_c.jl """ -function fmi3CompletedIntegratorStep(fmu::FMU3, - noSetFMUStatePriorToCurrentPoint::fmi3Boolean) +function fmi3CompletedIntegratorStep(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3CompletedIntegratorStep(fmu.instances[end], noSetFMUStatePriorToCurrentPoint) + fmi3CompletedIntegratorStep(fmu.instances[end], args...; kwargs...) end """ - fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) + fmi3EnterEventMode(fmu::FMU3, args...; kwargs...) Wrapper for fmi3EnterEventMode() in FMIImport/FMI3_c.jl """ -function fmi3EnterEventMode(fmu::FMU3, stepEvent::Bool, stateEvent::Bool, rootsFound::Array{fmi3Int32}, nEventIndicators::Integer, timeEvent::Bool) +function fmi3EnterEventMode(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3EnterEventMode(fmu.instances[end], stepEvent, stateEvent, rootsFound, nEventIndicators, timeEvent) + fmi3EnterEventMode(fmu.instances[end], args...; kwargs...) end """ - fmi3DoStep!(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::Bool, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) + fmi3DoStep!(fmu::FMU3, args...; kwargs...) Wrapper for fmi3DoStep!() in FMIImport/FMI3_c.jl """ -function fmi3DoStep!(fmu::FMU3, currentCommunicationPoint::Real, communicationStepSize::Real, noSetFMUStatePriorToCurrentPoint::fmi3Boolean, eventEncountered::fmi3Boolean, terminateSimulation::fmi3Boolean, earlyReturn::fmi3Boolean, lastSuccessfulTime::fmi3Float64) +function fmi3DoStep!(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - refeventEncountered = Ref(eventEncountered) - refterminateSimulation = Ref(terminateSimulation) - refearlyReturn = Ref(earlyReturn) - reflastSuccessfulTime = Ref(lastSuccessfulTime) - fmi3DoStep!(fmu.instances[end], fmi3Float64(currentCommunicationPoint), fmi3Float64(communicationStepSize), fmi3Boolean(noSetFMUStatePriorToCurrentPoint), refeventEncountered, refterminateSimulation, refearlyReturn, reflastSuccessfulTime) - eventEncountered = refeventEncountered[] - terminateSimulation = refterminateSimulation[] - earlyReturn = refearlyReturn[] - lastSuccessfulTime = reflastSuccessfulTime[] + fmi3DoStep!(fmu.instances[end], args...; kwargs...) end #additional """ - fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; - recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) + fmi3Simulate(fmu::FMU3, args...; kwargs...) Wrapper for fmi3Simulate() in FMI/FMI3_sim.jl """ -function fmi3Simulate(fmu::FMU3, t_start::Real = 0.0, t_stop::Real = 1.0; - recordValues::fmi3ValueReferenceFormat = nothing, saveat=[], setup=true) - @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3Simulate(fmu.instances[end], t_start, t_stop; - recordValues=recordValues, saveat=saveat, setup=setup) +function fmi3Simulate(fmu::FMU3, args...; kwargs...) + fmi3Simulate(fmu, nothing, args...; kwargs...) end """ fmi3SimulateCS(fmu::FMU3, args...; kwargs...) -Wrapper for fmi3SimulateCS() in FMI/FMI2_sim.jl +Wrapper for fmi3SimulateCS() in FMI/FMI3_sim.jl """ function fmi3SimulateCS(fmu::FMU3, args...; kwargs...) return fmi3SimulateCS(fmu, nothing, args...; kwargs...) @@ -971,17 +884,16 @@ end Wrapper for fmi3SimulateME() in FMI/FMI3_sim.jl """ function fmi3SimulateME(fmu::FMU3, args...; kwargs...) - return fmi3SimulateME(fmu.instances[end], args...; kwargs...) + return fmi3SimulateME(fmu, nothing, args...; kwargs...) end """ - fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) + fmi3GetStartValue(fmu::FMU3, args...; kwargs...) Wrapper for fmi3GetStartValue() in FMIImport/FMI3_c.jl """ -function fmi3GetStartValue(fmu::FMU3, vr::fmi3ValueReferenceFormat) +function fmi3GetStartValue(fmu::FMU3, args...; kwargs...) @assert length(fmu.instances) > 0 ["No FMU instance allocated, have you already called fmiInstantiate?"] - - fmi3GetStartValue(fmu.instances[end], vr) + fmi3GetStartValue(fmu.instances[end], args...; kwargs...) end \ No newline at end of file diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index 8d7f26b5..e725b126 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -419,7 +419,7 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st fmi3SetFloat64(fmu, inputValues, inputFunction(t)) end - fmi3DoStep!(fmu, t, dt, fmi3True, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) + fmi3DoStep!(fmu, t, dt, true, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) if eventEncountered == fmi3True @warn "Event handling" end @@ -454,7 +454,7 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st fmi3SetFloat64(fmu, inputValues, inputFunction(t)) end - fmi3DoStep!(fmu, t, dt, fmi3True, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) + fmi3DoStep!(fmu, t, dt, true, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) if eventEncountered == fmi3True @warn "Event handling" end From 9204c247d99b147faec27e821cc7bf70a869111b Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 11 Oct 2022 13:30:16 +0200 Subject: [PATCH 36/41] delete replicate functions --- src/FMI.jl | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/FMI.jl b/src/FMI.jl index cfb1d589..7b73aa7c 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -2267,20 +2267,6 @@ function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) fmi3GetAdjointDerivative!(str, args...; kwargs...) end -""" -Returns the values of the adjoint derivatives. -""" -function fmiGetAdjointDerivative(str::fmi3Struct, args...; kwargs...) - fmi3GetAdjointDerivative(str, args...; kwargs...) -end - -""" -Returns the values of the adjoint derivatives (in-place). -""" -function fmiGetAdjointDerivative!(str::fmi3Struct, args...; kwargs...) - fmi3GetAdjointDerivative!(str, args...; kwargs...) -end - """ fmiDoStep(str::fmi2Struct, c::FMU2Component, communicationStepSize::Union{Real, Nothing} = nothing; currentCommunicationPoint::Union{Real, Nothing} = nothing, noSetFMUStatePriorToCurrentPoint::Bool = true) From f8641afb47ab61901cc76d25f254aea457c6d649 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 11 Oct 2022 13:44:19 +0200 Subject: [PATCH 37/41] fmi3Plot.jl up to fmi2standard --- src/FMI3_plot.jl | 201 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 152 insertions(+), 49 deletions(-) diff --git a/src/FMI3_plot.jl b/src/FMI3_plot.jl index b56dd818..9105b137 100644 --- a/src/FMI3_plot.jl +++ b/src/FMI3_plot.jl @@ -1,9 +1,13 @@ +# ABM: done + + # # Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher # Licensed under the MIT license. See LICENSE file in the project root for details. # -using SciMLBase: ODESolution +using FMIImport: FMU3Solution +import ForwardDiff """ Plots data from a ME-FMU. @@ -11,70 +15,169 @@ Plots data from a ME-FMU. Optional `t_in_solution` controls if the first state in the solution is interpreted as t(ime). Optional keyword argument `maxLabelLength` controls the maximum length for legend labels (too long labels are cut from front). """ -function fmiPlot(fmu::FMU3, solution::ODESolution; maxLabelLength=64) +function fmiPlot(solution::FMU3Solution; kwargs...) + fig = Plots.plot(; xlabel="t [s]") + fmiPlot!(fig, solution; kwargs...) + return fig +end +function fmiPlot!(fig, solution::FMU3Solution; + states::Union{Bool, Nothing}=nothing, + values::Union{Bool, Nothing}=nothing, + stateEvents::Union{Bool, Nothing}=nothing, + timeEvents::Union{Bool, Nothing}=nothing, + stateIndices=nothing, + valueIndices=nothing, + maxLabelLength=64, + plotkwargs...) + + numStateEvents = 0 + numTimeEvents = 0 + for e in solution.events + if e.indicator > 0 + numStateEvents += 1 + else + numTimeEvents += 1 + end + end - t = solution.t - - numStates = length(solution.u[1]) - - fig = Plots.plot(xlabel="t [s]") - for s in 1:numStates - vr = fmu.modelDescription.stateValueReferences[s] - vrName = fmi3ValueReference2String(fmu, vr)[1] + if states === nothing + states = (solution.states !== nothing) + end - values = collect(data[s] for data in solution.u) + if values === nothing + values = (solution.values !== nothing) + end - # prevent legend labels from getting too long - label = "$vrName ($vr)" - labelLength = length(label) - if labelLength > maxLabelLength - label = "..." * label[labelLength-maxLabelLength:end] + if stateEvents === nothing + stateEvents = false + for e in solution.events + if e.indicator > 0 + stateEvents = true + break + end + end + + if numStateEvents > 100 + @info "fmiPlot(...): Number of state events ($(numStateEvents)) exceeding 100, disabling automatic plotting of state events (can be forced with keyword `stateEvents=true`)." + stateEvents = false end - - Plots.plot!(fig, t, values, label=label) end - fig -end - -""" -Extended the original plot-command by plotting FMUs. -""" -function Plots.plot(fmu::FMU3, solution::ODESolution) - fmiPlot(fmu, solution) -end - -""" -Plots data from a CS-FMU. -""" -function fmiPlot(fmu::FMU3, recordValues::fmi3ValueReferenceFormat, savedValues::DiffEqCallbacks.SavedValues; maxLabelLength=64) - ts = savedValues.t + if timeEvents === nothing + timeEvents = false + for e in solution.events + if e.indicator == 0 + timeEvents = true + break + end + end + + if numTimeEvents > 100 + @info "fmiPlot(...): Number of time events ($(numTimeEvents)) exceeding 100, disabling automatic plotting of time events (can be forced with keyword `timeEvents=true`)." + timeEvents = false + end + end - recordValues = prepareValueReference(fmu, recordValues) + if stateIndices === nothing + stateIndices = 1:length(solution.fmu.modelDescription.stateValueReferences) + end - numVars = length(recordValues) + if valueIndices === nothing + if solution.values !== nothing + valueIndices = 1:length(solution.values.saveval[1]) + end + end - fig = Plots.plot(xlabel="t [s]") - for i in 1:numVars - vr = recordValues[i] - vrName = fmi3ValueReference2String(fmu, vr)[1] - values = collect(data[i] for data in savedValues.saveval) + plot_min = Inf + plot_max = -Inf + + # plot states + if states + t = collect(ForwardDiff.value(e) for e in solution.states.t) + numValues = length(solution.states.u[1]) + + for v in 1:numValues + if v ∈ stateIndices + vr = solution.fmu.modelDescription.stateValueReferences[v] + vrNames = fmi3ValueReferenceToString(solution.fmu, vr) + vrName = vrNames[1] + + vals = collect(ForwardDiff.value(data[v]) for data in solution.states.u) + + plot_min = min(plot_min, vals...) + plot_max = max(plot_max, vals...) + + # prevent legend labels from getting too long + label = "$vrName ($vr)" + labelLength = length(label) + if labelLength > maxLabelLength + label = "..." * label[labelLength-maxLabelLength:end] + end + + Plots.plot!(fig, t, vals; label=label, plotkwargs...) + end + end + end + + # plot recorded values + if values + t = collect(ForwardDiff.value(e) for e in solution.values.t) + numValues = length(solution.values.saveval[1]) + + for v in 1:numValues + if v ∈ valueIndices + vr = solution.valueReferences[v] + vrNames = fmi3ValueReferenceToString(solution.fmu, vr) + vrName = vrNames[1] + + vals = collect(ForwardDiff.value(data[v]) for data in solution.values.saveval) + + plot_min = min(plot_min, vals...) + plot_max = max(plot_max, vals...) + + # prevent legend labels from getting too long + label = "$vrName ($vr)" + labelLength = length(label) + if labelLength > maxLabelLength + label = "..." * label[labelLength-maxLabelLength:end] + end + + Plots.plot!(fig, t, vals; label=label, plotkwargs...) + end + end + end - # prevent legend labels from getting too long - label = "$vrName ($vr)" - labelLength = length(label) - if labelLength > maxLabelLength - label = "..." * label[labelLength-maxLabelLength:end] + if stateEvents + first = true + for e in solution.events + if e.indicator > 0 + Plots.plot!(fig, [e.t, e.t], [plot_min, plot_max]; label=(first ? "State event(s)" : nothing), style=:dash, color=:blue) + first = false + end end + end - Plots.plot!(fig, ts, values, label=label) + if timeEvents + first = true + for e in solution.events + if e.indicator == 0 + Plots.plot!(fig, [e.t, e.t], [plot_min, plot_max]; label=(first ? "Time event(s)" : nothing), style=:dash, color=:red) + first = false + end + end end - fig + + return fig end """ Extended the original plot-command by plotting FMUs. + +For further information seek `?fmiPlot`. """ -function Plots.plot(fmu::FMU3, recordValues::fmi3ValueReferenceFormat, savedValues::DiffEqCallbacks.SavedValues) - fmiPlot(fmu, recordValues, savedValues) +function Plots.plot(solution::FMU3Solution, args...; kwargs...) + fmiPlot(solution, args...; kwargs...) end +function Plots.plot!(fig, solution::FMU3Solution, args...; kwargs...) + fmiPlot!(fig, solution, args...; kwargs...) +end \ No newline at end of file From 0c430bcd12c4d300cb257bbecee2aed7e7188c1e Mon Sep 17 00:00:00 2001 From: JoKircher Date: Mon, 17 Oct 2022 14:18:59 +0200 Subject: [PATCH 38/41] WIP commit to update branch --- src/FMI3_sim.jl | 10 +++++++++- test/FMI3/cs_me.jl | 24 ++++++++++++------------ test/FMI3/sens.jl | 10 +++++----- test/runtests.jl | 18 +++++++++--------- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index e725b126..43dfe8d5 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -8,9 +8,17 @@ # using DifferentialEquations, DiffEqCallbacks +import SciMLBase: RightRootFind +using FMIImport: fmi3EnterInitializationMode, fmi3ExitInitializationMode, fmi3UpdateDiscreteStates, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates, fmi3SetContinuousStates, fmi3GetContinuousStateDerivatives! +using FMIImport.FMICore: fmi3StatusOK, fmi3TypeCoSimulation, fmi3TypeModelExchange +using FMIImport.FMICore: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmiInstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal +using FMIImport: FMU3Solution, FMU3Event -using FMIImport +using ChainRulesCore +import ForwardDiff + +import ProgressMeter ############ Model-Exchange ############ diff --git a/test/FMI3/cs_me.jl b/test/FMI3/cs_me.jl index fc633702..52dca0c6 100644 --- a/test/FMI3/cs_me.jl +++ b/test/FMI3/cs_me.jl @@ -27,18 +27,18 @@ myFMU = fmiLoad("BouncingBall", "ModelicaReferenceFMUs", "0.0.16", "3.0") # myFMU = fmiLoad("SpringPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]; type=:ME) -@test myFMU.type == FMI.fmi3TypeModelExchange -inst = fmi3InstantiateModelExchange!(myFMU; loggingOn=false) -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = inst -end -sol = fmiSimulate(fmuStruct, t_start, t_stop) -@test sol.success -fmiUnload(myFMU) +# @test myFMU.type == FMI.fmi3TypeModelExchange +# inst = fmi3InstantiateModelExchange!(myFMU; loggingOn=false) +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = inst +# end +# sol = fmiSimulate(fmuStruct, t_start, t_stop) +# @test sol.success +# fmiUnload(myFMU) diff --git a/test/FMI3/sens.jl b/test/FMI3/sens.jl index 77b20aad..f34a5813 100644 --- a/test/FMI3/sens.jl +++ b/test/FMI3/sens.jl @@ -6,7 +6,7 @@ import ForwardDiff import Zygote -using FMI.FMIImport: fmi2SampleDirectionalDerivative, fmi2GetJacobian, fmi2SetContinuousStates +using FMI.FMIImport: fmi3SampleDirectionalDerivative, fmi3GetJacobian, fmi3SetContinuousStates FMUPaths = [get_model_filename("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]), get_model_filename("BouncingBall1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"])] @@ -35,8 +35,8 @@ for FMUPath in FMUPaths FD_jac = ForwardDiff.jacobian(x -> FMI.fx(comp, dx, x, p, t), x0) ZG_jac = Zygote.jacobian(FMI.fx, comp, dx, x0, p, t)[3] fmiSetContinuousStates(comp, x0) - samp_jac = fmi2SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) - auto_jac = fmi2GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + samp_jac = fmi3SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + auto_jac = fmi3GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) @test (abs.(auto_jac - FD_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) @test (abs.(auto_jac - ZG_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) @@ -50,8 +50,8 @@ for FMUPath in FMUPaths FD_jac = ForwardDiff.jacobian(x -> FMI.fx(comp, dx, x, p, t), x0) ZG_jac = Zygote.jacobian(FMI.fx, comp, dx, x0, p, t)[3] fmi2SetContinuousStates(comp, x0) - samp_jac = fmi2SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) - auto_jac = fmi2GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + samp_jac = fmi3SampleDirectionalDerivative(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + auto_jac = fmi3GetJacobian(comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) @test (abs.(auto_jac - FD_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) @test (abs.(auto_jac - ZG_jac) .< ones(numStates, numStates).*1e-6) == ones(Bool, numStates, numStates) diff --git a/test/runtests.jl b/test/runtests.jl index 8bd55d74..c83e0974 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -69,41 +69,41 @@ function runtestsFMI3(exportingTool) @testset "Testing FMUs exported from $exportingTool" begin @testset "FMI3/Sensitivities" begin - # include("sens.jl") + # include("FMI3/sens.jl") end for str in fmuStructs @testset "Functions for $str" begin ENV["FMUSTRUCT"] = str @testset "Variable Getters / Setters" begin - #include("FMI3/getter_setter.jl") + # include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - # include("FMI3/state.jl") + include("FMI3/state.jl") end @testset "Directional derivatives" begin - #include("FMI3/dir_ders.jl") + # include("FMI3/dir_ders.jl") end @testset "Automatic Simulation (CS or ME)" begin - #include("FMI3/sim_auto.jl") + # include("FMI3/sim_auto.jl") end @testset "CS Simulation" begin - # include("FMI3/sim_CS.jl") + include("FMI3/sim_CS.jl") end @testset "ME Simulation" begin - include("FMI3/sim_ME.jl") + # include("FMI3/sim_ME.jl") end @testset "Support CS and ME simultaneously" begin # include("FMI3/cs_me.jl") end @testset "Loading/Saving simulation results" begin - #include("FMI3/load_save.jl") + # include("FMI3/load_save.jl") end end end @testset "Plotting" begin - #include("FMI3/plots.jl") + # include("FMI3/plots.jl") end end end From 6163950890b54c1d0a34c7b33bc17daf953854a1 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Sun, 6 Nov 2022 17:02:45 +0100 Subject: [PATCH 39/41] build simulation loops after fmi2 structure --- src/FMI3_sim.jl | 1272 ++++++++++++++++++++++++++++++++++--------- test/FMI3/sim_CS.jl | 18 +- test/FMI3/sim_ME.jl | 354 ++++++------ test/runtests.jl | 2 +- 4 files changed, 1206 insertions(+), 440 deletions(-) diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index 43dfe8d5..58bfc551 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -12,7 +12,7 @@ import SciMLBase: RightRootFind using FMIImport: fmi3EnterInitializationMode, fmi3ExitInitializationMode, fmi3UpdateDiscreteStates, fmi3GetContinuousStates, fmi3GetNominalsOfContinuousStates, fmi3SetContinuousStates, fmi3GetContinuousStateDerivatives! using FMIImport.FMICore: fmi3StatusOK, fmi3TypeCoSimulation, fmi3TypeModelExchange -using FMIImport.FMICore: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmiInstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal +using FMIImport.FMICore: fmi3InstanceState, fmi3InstanceStateInstantiated, fmi3InstanceStateInitializationMode, fmi3InstanceStateEventMode, fmi3InstanceStateContinuousTimeMode, fmi3InstanceStateTerminated, fmi3InstanceStateError, fmi3InstanceStateFatal using FMIImport: FMU3Solution, FMU3Event using ChainRulesCore @@ -23,26 +23,41 @@ import ProgressMeter ############ Model-Exchange ############ # Read next time event from FMU and provide it to the integrator -function time_choice(c::FMU3Instance, integrator) - @debug "time_choice(_, _): Time event @ t=$(integrator.t)" - +function time_choice(c::FMU3Instance, integrator, tStart, tStop) + #@info "TC" + discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime = fmi3UpdateDiscreteStates(c) - fmi3EnterContinuousTimeMode(c) - if Bool(nextEventTimeDefined) - c.timeEvent = integrator.t >= nextEventTime - nextEventTime + + if nextEventTimeDefined == fmi3True + + if nextEventTime >= tStart && nextEventTime <= tStop + return nextEventTime + else + # the time event is outside the simulation range! + @debug "Next time event @$(c.eventInfo.nextEventTime)s is outside simulation time range ($(tStart), $(tStop)), skipping." + return nothing + end else - Inf + return nothing end end # Handles events and returns the values and nominals of the changed continuous states. -function handleEvents(c::FMU3Instance, enterEventMode::Bool, exitInContinuousMode::Bool) +function handleEvents(c::FMU3Instance) + # @assert c.state == fmi3InstanceStateEventMode "handleEvents(...): Must be in event mode!" + + # trigger the loop + discreteStatesNeedUpdate = fmi3True nominalsChanged = fmi3False valuesChanged = fmi3False - # println(enterEventMode) - if enterEventMode + nextEventTimeDefined = fmi3False + nextEventTime = 0.0 + + while discreteStatesNeedUpdate == fmi3True + # TODO set inputs + discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime = fmi3UpdateDiscreteStates(c) + fmi3EnterEventMode(c, c.stepEvent, c.stateEvent, c.rootsFound, Csize_t(c.fmu.modelDescription.numberOfEventIndicators), c.timeEvent) # TODO inputEvent handling println("before loop") @@ -68,10 +83,7 @@ function handleEvents(c::FMU3Instance, enterEventMode::Bool, exitInContinuousMod end println("afterLoop") - if exitInContinuousMode - println("enterinContTimeMode") - fmi3EnterContinuousTimeMode(c) - end + fmi3EnterContinuousTimeMode(c) # println(valuesChanged) # println(nominalsChanged) println(c) @@ -81,295 +93,1020 @@ function handleEvents(c::FMU3Instance, enterEventMode::Bool, exitInContinuousMod end # Returns the event indicators for an FMU. -function condition(c::FMU3Instance, out, x, t, integrator, inputFunction, inputValues::Array{fmi3ValueReference}) # Event when event_f(u,t) == 0 +function condition(c::FMU3Instance, out::AbstractArray{<:Real}, x, t, integrator, inputFunction, inputValues::AbstractArray{fmi3ValueReference}) if inputFunction !== nothing - println("try to work with nothing1") - fmi3SetFloat64(c, inputValues, inputFunction(integrator.t)) + fmi3SetFloat64(c, inputValues, inputFunction(c, x, t)) end - c.stateEvent = fmi3False - fmi3SetTime(c, t) + @assert c.state == fmi3InstanceStateContinuousTimeMode "condition(...): Must be called in mode continuous time." + fmi3SetContinuousStates(c, x) - indicators = fmi3GetEventIndicators(c) - if length(indicators) > 0 - for i in 1:length(indicators) - if c.z_prev[i] < 0 && indicators[i] >= 0 - c.rootsFound[i] = 1 - elseif c.z_prev[i] > 0 && indicators[i] <= 0 - c.rootsFound[i] = -1 - else - c.rootsFound[i] = 0 - end - c.stateEvent |= (c.rootsFound[i] != 0) - # c.z_prev[i] = indicators[i] - end + fmi3SetTime(c, t) + if inputFunction !== nothing + fmi3SetFloat64(c, inputValues, inputFunction(c, x, t)) end - # print("condition: out: ") - # println(indicators) - @debug "condition(_, _, $(x), $(t), _, _, _): eventIndicators $indicators rootsFound $(c.rootsFound) stateEvent $(c.stateEvent)" - copy!(out, indicators) + + # TODO check implementation of fmi3GetEventIndicators! mit abstract array + fmi3GetEventIndicators!(c, out, UInt(length(out))) + + # if length(indicators) > 0 + # for i in 1:length(indicators) + # if c.z_prev[i] < 0 && indicators[i] >= 0 + # c.rootsFound[i] = 1 + # elseif c.z_prev[i] > 0 && indicators[i] <= 0 + # c.rootsFound[i] = -1 + # else + # c.rootsFound[i] = 0 + # end + # c.stateEvent |= (c.rootsFound[i] != 0) + # # c.z_prev[i] = indicators[i] + # end + # end + + return nothing end # Handles the upcoming events. -function affectFMU!(c::FMU3Instance, integrator, idx, inputFunction, inputValues::Array{fmi3ValueReference}, force=false) - # Event found - handle it - println(c) - println(integrator) - println(idx) - println(inputFunction) - println(inputValues) - println("-------------------") - println() - @debug "affectFMU!(_, _, $(idx), _, _): x:$(integrator.u) [before handle events]" - println("beforeSetContState") +function affectFMU!(c::FMU3Instance, integrator, idx, inputFunction, inputValues::Array{fmi3ValueReference}, solution::FMU3Solution) + + @assert c.state == fmi3ComponentStateContinuousTimeMode "affectFMU!(...): Must be in continuous time mode!" + + # there are fx-evaluations before the event is handled, reset the FMU state to the current integrator step fmi3SetContinuousStates(c, integrator.u) - println("beforeHandleEvents") - continuousStatesChanged, nominalsChanged = handleEvents(c, true, Bool(sign(idx))) - - @debug "affectFMU!(_, _, $(idx), _, _): continuousStatesChanged=$(continuousStatesChanged) x_int:$(integrator.u) x_fmu:$(fmi3GetContinuousStates(c)) [after handle events]" - println("beforeSetInputs") + fmi3SetTime(c, integrator.t) if inputFunction !== nothing - println("try to work with nothing2") - fmi3SetFloat64(c, inputValues, inputFunction(integrator.t)) + fmi3SetFloat64(c, inputValues, inputFunction(c, integrator.u, integrator.t)) end - println("beforeSetNewStates") - if continuousStatesChanged == fmi3True - integrator.u = fmi3GetContinuousStates(c) - @debug "affectFMU!(_, _, $(idx), _, _): Set new state $(integrator.u)" + + fmi3EnterEventMode(c, c.stepEvent, c.stateEvent, c.rootsFound, Csize_t(c.fmu.modelDescription.numberOfEventIndicators), c.timeEvent) + + # Event found - handle it + handleEvents(c) + + left_x = nothing + right_x = nothing + + if c.eventInfo.valuesOfContinuousStatesChanged == fmi3True + left_x = integrator.u + right_x = fmi3GetContinuousStates(c) + @debug "affectFMU!(...): Handled event at t=$(integrator.t), new state is $(new_u)" + integrator.u = right_x + + u_modified!(integrator, true) + #set_proposed_dt!(integrator, 1e-10) + else + u_modified!(integrator, false) + @debug "affectFMU!(...): Handled event at t=$(integrator.t), no new state." end - println("beforeSetNomsOfContState") - if nominalsChanged == fmi3True + + if c.eventInfo.nominalsOfContinuousStatesChanged == fmi3True x_nom = fmi3GetNominalsOfContinuousStates(c) end - # timeEventCb = PresetTimeCallback(2.0, (integrator) -> affect!(c, integrator, 0)) + + ignore_derivatives() do + if idx != -1 # -1 no event, 0, time event, >=1 state event with indicator + e = FMU3Event(integrator.t, UInt64(idx), left_x, right_x) + push!(solution.events, e) + end + end + + #fmi3EnterContinuousTimeMode(c) end # Does one step in the simulation. -function stepCompleted(c::FMU3Instance, x, t, integrator, inputFunction, inputValues::Array{fmi3ValueReference}) +function stepCompleted(c::FMU3Instance, x, t, integrator, inputFunction, inputValues::AbstractArray{fmi3ValueReference}, progressMeter, tStart, tStop, solution::FMU3Solution) + + @assert c.state == fmi3InstanceStateContinuousTimeMode "stepCompleted(...): Must be in continuous time mode." + #@info "Step completed" + if progressMeter !== nothing + stat = 1000.0*(t-tStart)/(tStop-tStart) + if !isnan(stat) + stat = floor(Integer, stat) + ProgressMeter.update!(progressMeter, stat) + end + end - fmi3SetContinuousStates(c, x) + # if length(indicators) > 0 + # c.stateEvent = fmi3False - indicators = fmi3GetEventIndicators(c) - if length(indicators) > 0 - c.stateEvent = fmi3False + # for i in 1:length(indicators) + # if c.z_prev[i] < 0 && indicators[i] >= 0 + # c.rootsFound[i] = 1 + # elseif c.z_prev[i] > 0 && indicators[i] <= 0 + # c.rootsFound[i] = -1 + # else + # c.rootsFound[i] = 0 + # end + # c.stateEvent |= (c.rootsFound[i] != 0) + # c.z_prev[i] = indicators[i] + # end + # end + (status, enterEventMode, terminateSimulation) = fmi3CompletedIntegratorStep(c, fmi3True) - for i in 1:length(indicators) - if c.z_prev[i] < 0 && indicators[i] >= 0 - c.rootsFound[i] = 1 - elseif c.z_prev[i] > 0 && indicators[i] <= 0 - c.rootsFound[i] = -1 - else - c.rootsFound[i] = 0 - end - c.stateEvent |= (c.rootsFound[i] != 0) - c.z_prev[i] = indicators[i] + if terminateSimulation == fmi3True + @error "stepCompleted(...): FMU requested termination!" + end + + if enterEventMode == fmi3True + affectFMU!(c, integrator, -1, inputFunction, inputValues, solution) + else + if inputFunction !== nothing + fmi3SetFloat64(c, inputValues, inputFunction(c, x, t)) end end +end + +# save FMU values +function saveValues(c::FMU3Instance, recordValues, x, t, integrator, inputFunction, inputValues) + + @assert c.state == fmi3ComponentStateContinuousTimeMode "saveValues(...): Must be in continuous time mode." + + #x_old = fmi3GetContinuousStates(c) + #t_old = c.t + + fmi3SetContinuousStates(c, x) + fmi3SetTime(c, t) + if inputFunction !== nothing + fmi3SetFloat64(c, inputValues, inputFunction(c, x, t)) + end - (status, c.stepEvent, terminateSimulation) = fmi3CompletedIntegratorStep(c, fmi3True) - @debug "stepCompleted(_, $(x), $(t), _, _, _): stepEvent $(c.stepEvent)" - @assert terminateSimulation == fmi3False "completed Integratorstep failed!" + #fmi3SetContinuousStates(c, x_old) + #fmi3SetTime(c, t_old) + return (fmiGetFloat64(c, recordValues)...,) end # Returns the state derivatives of the FMU. -function fx(c::FMU3Instance, x, p, t) +function fx(c::FMU3Instance, + dx::AbstractArray{<:Real}, + x::AbstractArray{<:Real}, + p::AbstractArray, + t::Real) + + # if isa(t, ForwardDiff.Dual) + # t = ForwardDiff.value(t) + # end @debug "fx($(x), _, $(t))" fmi3SetTime(c, t) fmi3SetContinuousStates(c, x) dx = fmi3GetContinuousStateDerivatives(c) + + # if all(isa.(dx, ForwardDiff.Dual)) + # dx_tmp = collect(ForwardDiff.value(e) for e in dx) + # fmi3GetContinuousStateDerivatives!(c, dx_tmp) + # T, V, N = fd_eltypes(dx) + # dx[:] = collect(ForwardDiff.Dual{T, V, N}(dx_tmp[i], ForwardDiff.partials(dx[i]) ) for i in 1:length(dx)) + # else + # fmi3GetContinuousStateDerivatives!(c, dx) + # end + + # y, dx = FMIImport.eval!(c, dx, nothing, nothing, x, nothing, nothing, t) + + return dx end -# save FMU values -function saveValues(c::FMU3Instance, recordValues, u, t, integrator) - fmi3SetTime(c, t) - x = integrator.sol(t) - fmi3SetContinuousStates(c, x) +# same function as in FMI2_sim.jl +function fd_eltypes(e::ForwardDiff.Dual{T, V, N}) where {T, V, N} + return (T, V, N) +end +function fd_eltypes(e::AbstractArray{<:ForwardDiff.Dual{T, V, N}}) where {T, V, N} + return (T, V, N) +end + +# same function as in FMI2_sim.jl +function _fx_fd(comp, dx, x, p, t) + + ȧrgs = [] + args = [] + + push!(ȧrgs, NoTangent()) + push!(args, fx) + + push!(ȧrgs, NoTangent()) + push!(args, comp) + + T = nothing + V = nothing + + dx_set = length(dx) > 0 && all(isa.(dx, ForwardDiff.Dual)) + x_set = length(x) > 0 && all(isa.(x, ForwardDiff.Dual)) + p_set = length(p) > 0 && all(isa.(p, ForwardDiff.Dual)) + t_set = isa(t, ForwardDiff.Dual) + + if dx_set + T, V, N = fd_eltypes(dx) + push!(ȧrgs, collect(ForwardDiff.partials(e) for e in dx)) + push!(args, collect(ForwardDiff.value(e) for e in dx)) + #@info "dx_set num=$(length(dx)) partials=$(length(ForwardDiff.partials(dx[1])))" + else + push!(ȧrgs, NoTangent()) + push!(args, dx) + end + + if x_set + T, V, N = fd_eltypes(x) + push!(ȧrgs, collect(ForwardDiff.partials(e) for e in x)) + push!(args, collect(ForwardDiff.value(e) for e in x)) + #@info "x_set num=$(length(x)) partials=$(length(ForwardDiff.partials(x[1])))" + else + push!(ȧrgs, NoTangent()) + push!(args, x) + end + + if p_set + T, V, N = fd_eltypes(p) + push!(ȧrgs, collect(ForwardDiff.partials(e) for e in p)) + push!(args, collect(ForwardDiff.value(e) for e in p)) + else + push!(ȧrgs, NoTangent()) + push!(args, p) + end + + if t_set + T, V, N = fd_eltypes(t) + push!(ȧrgs, ForwardDiff.partials(t)) + push!(args, ForwardDiff.value(t)) + else + push!(ȧrgs, NoTangent()) + push!(args, t) + end + + ȧrgs = (ȧrgs...,) + args = (args...,) + + y, _, sdx, sx, sp, st = ChainRulesCore.frule(ȧrgs, args...) + + ys = [] + + #[collect( ForwardDiff.Dual{Tx, Vx, Nx}(y[i], ForwardDiff.partials(x_partials[i], t_partials[i])) for i in 1:length(y) )...] + for i in 1:length(y) + is = NoTangent() + + if dx_set + is = sdx[i]#.values + end + if x_set + is = sx[i]#.values + end + + if p_set + is = sp[i]#.values + end + if t_set + is = st[i]#.values + end + + #display("dx: $dx") + #display("sdx: $sdx") + + #partials = (isdx, isx, isp, ist) + + #display(partials) + + + #V = Float64 + #N = length(partials) + #display("$T $V $N") + + #display(is) + + @assert is != ZeroTangent() && is != NoTangent() "is: $(is)" + + push!(ys, ForwardDiff.Dual{T, V, N}(y[i], is ) ) # ForwardDiff.Partials{N, V}(partials) + end + + ys +end + +# same functionhead as in FMI2_sim.jl +# frule for fx +function ChainRulesCore.frule((Δself, Δcomp, Δdx, Δx, Δp, Δt), + ::typeof(fx), + comp, #::FMU3Instance, + dx, + x,#::AbstractArray{<:Real}, + p, + t) + + y = fx(comp, dx, x, p, t) + function fx_pullforward(Δdx, Δx, Δt) + + # if t >= 0.0 + # fmi3SetTime(comp, t) + # end + + # if all(isa.(x, ForwardDiff.Dual)) + # xf = collect(ForwardDiff.value(e) for e in x) + # fmi3SetContinuousStates(comp, xf) + # else + # fmi3SetContinuousStates(comp, x) + # end + + c̄omp = ZeroTangent() + d̄x = ZeroTangent() + x̄ = ZeroTangent() + p̄ = ZeroTangent() + t̄ = ZeroTangent() + + if Δdx != NoTangent() + d̄x = Δdx + end + + if Δx != NoTangent() + if comp.A === nothing || size(comp.A) != (length(comp.fmu.modelDescription.derivativeValueReferences), length(comp.fmu.modelDescription.stateValueReferences)) + comp.A = zeros(length(comp.fmu.modelDescription.derivativeValueReferences), length(comp.fmu.modelDescription.stateValueReferences)) + end + comp.jacobianUpdate!(comp.A, comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + x̄ = comp.A * Δx + end + + if Δt != NoTangent() + dt = 1e-6 + dx1 = fmi3GetContinuousStateDerivatives(comp) + fmi3SetTime(comp, t + dt) + dx2 = fmi3GetContinuousStateDerivatives(comp) + ∂t = (dx2-dx1)/dt + t̄ = ∂t * Δt + end + + return (c̄omp, d̄x, x̄, p̄, t̄) + end + return (y, fx_pullforward(Δdx, Δx, Δt)...) +end + +# rrule for fx +function ChainRulesCore.rrule(::typeof(fx), + comp::FMU3Instance, + dx, + x, + p, + t) + + y = fx(comp, dx, x, p, t) + function fx_pullback(ȳ) + + if t >= 0.0 + fmi3SetTime(comp, t) + end + + fmi3SetContinuousStates(comp, x) + + if comp.A === nothing || size(comp.A) != (length(comp.fmu.modelDescription.derivativeValueReferences), length(comp.fmu.modelDescription.stateValueReferences)) + comp.A = zeros(length(comp.fmu.modelDescription.derivativeValueReferences), length(comp.fmu.modelDescription.stateValueReferences)) + end + comp.jacobianUpdate!(comp.A, comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + + n_dx_x = @thunk(comp.A' * ȳ) + + f̄ = NoTangent() + c̄omp = ZeroTangent() + d̄x = ZeroTangent() + x̄ = n_dx_x + p̄ = ZeroTangent() + t̄ = ZeroTangent() + + return f̄, c̄omp, d̄x, x̄, p̄, t̄ + end + return (y, fx_pullback) +end + +# frule for fx +# function ChainRulesCore.frule((Δself, Δcomp, Δdx, Δx, Δp, Δt), +# ::typeof(fx), +# comp, #::FMU3Instance, +# dx, +# x,#::AbstractArray{<:Real}, +# p, +# t) + +# y = fx(comp, dx, x, p, t) +# function fx_pullforward(Δx) + +# if t >= 0.0 +# fmi3SetTime(comp, t) +# end + +# if all(isa.(x, ForwardDiff.Dual)) +# xf = collect(ForwardDiff.value(e) for e in x) +# fmi3SetContinuousStates(comp, xf) +# else +# fmi3SetContinuousStates(comp, x) +# end + +# if comp.A == nothing || size(comp.A) != (length(comp.fmu.modelDescription.derivativeValueReferences), length(comp.fmu.modelDescription.stateValueReferences)) +# comp.A = zeros(length(comp.fmu.modelDescription.derivativeValueReferences), length(comp.fmu.modelDescription.stateValueReferences)) +# end +# comp.jacobianUpdate!(comp.A, comp, comp.fmu.modelDescription.derivativeValueReferences, comp.fmu.modelDescription.stateValueReferences) + +# n_dx_x = comp.A * Δx + +# c̄omp = ZeroTangent() +# d̄x = ZeroTangent() +# x̄ = n_dx_x +# p̄ = ZeroTangent() +# t̄ = ZeroTangent() + +# return (c̄omp, d̄x, x̄, p̄, t̄) +# end +# return (y, fx_pullforward(Δx)...) +# end + +import FMIImport: fmi3VariabilityConstant, fmi3InitialApprox, fmi3InitialExact +function setBeforeInitialization(mv::FMIImport.fmi3ModelVariable) + return mv.variability != fmi3VariabilityConstant && mv.initial ∈ (fmi3InitialApprox, fmi3InitialExact) +end + +import FMIImport: fmi3CausalityInput, fmi3CausalityParameter, fmi3VariabilityTunable +function setInInitialization(mv::FMIImport.fmi3ModelVariable) + return mv.causality == fmi3CausalityInput || (mv.causality != fmi3CausalityParameter && mv.variability == fmi3VariabilityTunable) || (mv.variability != fmi3VariabilityConstant && mv.initial == fmi3InitialExact) +end + +function prepareFMU(fmu::FMU3, c::Union{Nothing, FMU3Instance}, type::fmi3Type, instantiate::Union{Nothing, Bool}, terminate::Union{Nothing, Bool}, reset::Union{Nothing, Bool}, setup::Union{Nothing, Bool}, parameters::Union{Dict{<:Any, <:Any}, Nothing}, t_start, t_stop, tolerance; + x0::Union{AbstractArray{<:Real}, Nothing}=nothing, inputFunction=nothing, inputValueReferences=nothing) + + if instantiate === nothing + instantiate = fmu.executionConfig.instantiate + end + + if terminate === nothing + terminate = fmu.executionConfig.terminate + end + + if reset === nothing + reset = fmu.executionConfig.reset + end + + if setup === nothing + setup = fmu.executionConfig.setup + end + + c = nothing + + # instantiate (hard) + if instantiate + if type == fmi3TypeCoSimulation + c = fmi3InstantiateCoSimulation!(fmu) + elseif type == fmi3TypeModelExchange + c = fmi3InstantiateModelExchange!(fmu) + else + c = fmi3InstantiateScheduledExecution!(fmu) + end + else + if c === nothing + c = fmu.components[end] + end + end + + # soft terminate (if necessary) + if terminate + retcode = fmi3Terminate(c; soft=true) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Termination failed with return code $(retcode)." + end + + # soft reset (if necessary) + if reset + retcode = fmi3Reset(c; soft=true) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Reset failed with return code $(retcode)." + end + + # setup experiment (hard) + # TODO this part is handled by fmi3EnterInitializationMode + # if setup + # retcode = fmi2SetupExperiment(c, t_start, t_stop; tolerance=tolerance) + # @assert retcode == fmi3StatusOK "fmi3Simulate(...): Setting up experiment failed with return code $(retcode)." + # end + + # parameters + if parameters !== nothing + retcodes = fmi3Set(c, collect(keys(parameters)), collect(values(parameters)); filter=setBeforeInitialization) + @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial parameters failed with return code $(retcode)." + end + + # inputs + inputs = nothing + if inputFunction !== nothing && inputValueReferences !== nothing + # set inputs + inputs = Dict{fmi3ValueReference, Any}() + + inputValues = nothing + if hasmethod(inputFunction, Tuple{FMU3Instance, fmi3Float64}) # CS + inputValues = inputFunction(c, t_start) + else # ME + inputValues = inputFunction(c, nothing, t_start) + end + + for i in 1:length(inputValueReferences) + vr = inputValueReferences[i] + inputs[vr] = inputValues[i] + end + end + + # inputs + if inputs !== nothing + retcodes = fmi3Set(c, collect(keys(inputs)), collect(values(inputs)); filter=setBeforeInitialization) + @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." + end + + # start state + if x0 !== nothing + #retcode = fmi3SetContinuousStates(c, x0) + #@assert retcode == fmi3StatusOK "fmi3Simulate(...): Setting initial state failed with return code $(retcode)." + retcodes = fmi3Set(c, fmu.modelDescription.stateValueReferences, x0; filter=setBeforeInitialization) + @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." + end + + # enter (hard) + if setup + retcode = fmi3EnterInitializationMode(c, t_start, t_stop; tolerance = tolerance) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Entering initialization mode failed with return code $(retcode)." + end + + # parameters + if parameters !== nothing + retcodes = fmi3Set(c, collect(keys(parameters)), collect(values(parameters)); filter=setInInitialization) + @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial parameters failed with return code $(retcode)." + end + + if inputs !== nothing + retcodes = fmi3Set(c, collect(keys(inputs)), collect(values(inputs)); filter=setInInitialization) + @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." + end + + # start state + if x0 !== nothing + #retcode = fmi3SetContinuousStates(c, x0) + #@assert retcode == fmi3StatusOK "fmi3Simulate(...): Setting initial state failed with return code $(retcode)." + retcodes = fmi3Set(c, fmu.modelDescription.stateValueReferences, x0; filter=setInInitialization) + @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial inputs failed with return code $(retcode)." + end + + # exit setup (hard) + if setup + retcode = fmi3ExitInitializationMode(c) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Exiting initialization mode failed with return code $(retcode)." + end + + if type == fmi3TypeModelExchange + if x0 === nothing + x0 = fmi3GetContinuousStates(c) + end + end + + return c, x0 +end + +function prepareFMU(fmu::Vector{FMU3}, c::Vector{Union{Nothing, FMU3Instance}}, type::Vector{fmi3Type}, instantiate::Union{Nothing, Bool}, freeInstance::Union{Nothing, Bool}, terminate::Union{Nothing, Bool}, reset::Union{Nothing, Bool}, setup::Union{Nothing, Bool}, parameters::Union{Vector{Union{Dict{<:Any, <:Any}, Nothing}}, Nothing}, t_start, t_stop, tolerance; + x0::Union{Vector{Union{Array{<:Real}, Nothing}}, Nothing}=nothing, initFct=nothing) + + ignore_derivatives() do + for i in 1:length(fmu) + + if instantiate === nothing + instantiate = fmu[i].executionConfig.instantiate + end + + if freeInstance === nothing + freeInstance = fmu[i].executionConfig.freeInstance + end + + if terminate === nothing + terminate = fmu[i].executionConfig.terminate + end + + if reset === nothing + reset = fmu[i].executionConfig.reset + end + + if setup === nothing + setup = fmu[i].executionConfig.setup + end + + # instantiate (hard) + if instantiate + # remove old one if we missed it (callback) + if c[i] !== nothing + if freeInstance + fmi3FreeInstance!(c[i]) + @debug "[AUTO-RELEASE INST]" + end + end + + if type[i] == fmi3TypeCoSimulation + c[i] = fmi3InstantiateCoSimulation!(fmu[i]) + elseif type[i] == fmi3TypeModelExchange + c[i] = fmi3InstantiateModelExchange!(fmu[i]) + else + c[i] = fmi3InstantiateScheduledExecution!(fmu[i]) + end + @debug "[NEW INST]" + else + if c[i] === nothing + c[i] = fmu[i].components[end] + end + end + + # soft terminate (if necessary) + if terminate + retcode = fmi3Terminate(c[i]; soft=true) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Termination failed with return code $(retcode)." + end + + # soft reset (if necessary) + if reset + retcode = fmi3Reset(c[i]; soft=true) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Reset failed with return code $(retcode)." + end + + # enter setup (hard) + if setup + # retcode = fmi2SetupExperiment(c[i], t_start, t_stop; tolerance=tolerance) + # @assert retcode == fmi2StatusOK "fmi2Simulate(...): Setting up experiment failed with return code $(retcode)." + + retcode = fmi3EnterInitializationMode(c[i], t_start, t_stop; tolerance=tolerance) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Entering initialization mode failed with return code $(retcode)." + end + + if x0 !== nothing + if x0[i] !== nothing + retcode = fmi3SetContinuousStates(c[i], x0[i]) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Setting initial state failed with return code $(retcode)." + end + end + + if parameters !== nothing + if parameters[i] !== nothing + retcodes = fmi3Set(c[i], collect(keys(parameters[i])), collect(values(parameters[i])) ) + @assert all(retcodes .== fmi3StatusOK) "fmi3Simulate(...): Setting initial parameters failed with return code $(retcode)." + end + end + + if initFct !== nothing + initFct() + end + + # exit setup (hard) + if setup + retcode = fmi3ExitInitializationMode(c[i]) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Exiting initialization mode failed with return code $(retcode)." + end + + if type == fmi3TypeModelExchange + if x0 === nothing + if x0[i] === nothing + x0[i] = fmi3GetContinuousStates(c[i]) + end + end + end + end + + end # ignore_derivatives + + return c, x0 +end + +function finishFMU(fmu::FMU3, c::FMU3Instance, terminate::Union{Nothing, Bool}, freeInstance::Union{Nothing, Bool}) + + if c === nothing + return + end + + if terminate === nothing + terminate = fmu.executionConfig.terminate + end + + if freeInstance === nothing + freeInstance = fmu.executionConfig.freeInstance + end - (fmi3GetFloat64(c, recordValues)...,) + # soft terminate (if necessary) + if terminate + retcode = fmi3Terminate(c; soft=true) + @assert retcode == fmi3StatusOK "fmi3Simulate(...): Termination failed with return code $(retcode)." + end + + # freeInstance (hard) + if freeInstance + fmi3FreeInstance!(c) + end end # wrapper -# function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) -# fmi3SimulateME(c.fmu.instances[end], t_start, t_stop; kwargs...) -# end +function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) + fmi3SimulateME(c.fmu, c, t_start, t_stop; kwargs...) +end + +# sets up the ODEProblem for simulating a ME-FMU +function setupODEProblem(c::FMU3Instance, x0::AbstractArray{fmi3Float64}, t_start::fmi3Float64, t_stop::fmi3Float64; p=[], customFx=nothing) + if customFx === nothing + customFx = (dx, x, p, t) -> fx(c, dx, x, p, t) + end + + p = [] + c.problem = ODEProblem(customFx, x0, (t_start, t_stop), p,) + + return c.problem +end """ -Source: FMISpec3.0, Version D5ef1c1: 3.3. Code Example Simulates a FMU instance for the given simulation time interval. State- and Time-Events are handled correctly. -Returns a tuple of type (ODESolution, DiffEqCallbacks.SavedValues). -If keyword `recordValues` is not set, a tuple of type (ODESolution, nothing) is returned for consitency. + +Via the optional keyword arguemnts `inputValues` and `inputFunction`, a custom input function `f(c, u, t)`, `f(c, t)`, `f(u, t)`, `f(c, u)` or `f(t)` with `c` current component, `u` current state and `t` current time can be defined, that should return a array of values for `fmi3SetFloat64(..., inputValues, inputFunction(...))`. + +Keywords: + - solver: Any Julia-supported ODE-solver (default is Tsit5) + - customFx: [deperecated] Ability to give a custom state derivative function ẋ=f(x,t) + - recordValues: Array of variables (strings or variableIdentifiers) to record. Results are returned as `DiffEqCallbacks.SavedValues` + - saveat: Time points to save values at (interpolated) + - setup: Boolean, if FMU should be setup (default=true) + - reset: Union{Bool, :auto}, if FMU should be reset before simulation (default reset=:auto) + - inputValueReferences: Array of input variables (strings or variableIdentifiers) to set at every simulation step + - inputFunction: Function to retrieve the values to set the inputs to + - parameters: Dictionary of parameter variables (strings or variableIdentifiers) and values (Real, Integer, Boolean, String) to set parameters during initialization + - `callbacks`: custom callbacks to add + +Returns: + - If keyword `recordValues` is not set, a struct of type `ODESolution`. + - If keyword `recordValues` is set, a tuple of type (ODESolution, DiffEqCallbacks.SavedValues). """ -function fmi3SimulateME(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; +function fmi3SimulateME(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + tolerance::Union{Real, Nothing} = nothing, + dt::Union{Real, Nothing} = nothing, solver = nothing, customFx = nothing, recordValues::fmi3ValueReferenceFormat = nothing, - saveat = [], - saveAtEvent::Bool = false, - setup::Bool = true, - reset = nothing, # nothing = auto - inputValues::fmi3ValueReferenceFormat = nothing, + saveat = nothing, + x0::Union{AbstractArray{<:Real}, Nothing} = nothing, + setup::Union{Bool, Nothing} = nothing, + reset::Union{Bool, Nothing} = nothing, + instantiate::Union{Bool, Nothing} = nothing, + freeInstance::Union{Bool, Nothing} = nothing, + terminate::Union{Bool, Nothing} = nothing, + inputValueReferences::fmi3ValueReferenceFormat = nothing, inputFunction = nothing, - rootSearchInterpolationPoints = 100, + parameters::Union{Dict{<:Any, <:Any}, Nothing} = nothing, + dtmax::Union{Real, Nothing} = nothing, + callbacks = [], + showProgress::Bool = true, kwargs...) - if t_start == nothing - t_start = c.fmu.modelDescription.defaultStartTime - end + + @assert fmi3IsModelExchange(fmu) "fmi3SimulateME(...): This function supports Model Exchange FMUs only." + #@assert fmu.type == fmi3TypeModelExchange "fmi3SimulateME(...): This FMU supports Model Exchange, but was instantiated in CS mode. Use `fmiLoad(...; type=:ME)`." - if t_stop == nothing - t_stop = c.fmu.modelDescription.defaultStopTime + # input function handling + _inputFunction = nothing + if inputFunction !== nothing + if hasmethod(inputFunction, Tuple{fmi3Float64}) + _inputFunction = (c, u, t) -> inputFunction(t) + elseif hasmethod(inputFunction, Tuple{Union{FMU3Instance, Nothing}, fmi3Float64}) + _inputFunction = (c, u, t) -> inputFunction(c, t) + elseif hasmethod(inputFunction, Tuple{Union{FMU3Instance, Nothing}, AbstractArray{fmi3Float64,1}}) + _inputFunction = (c, u, t) -> inputFunction(c, u) + elseif hasmethod(inputFunction, Tuple{AbstractArray{fmi3Float64,1}, fmi3Float64}) + _inputFunction = (c, u, t) -> inputFunction(u, t) + else + _inputFunction = inputFunction + end + @assert hasmethod(_inputFunction, Tuple{FMU3Instance, Union{AbstractArray{fmi3Float64,1}, Nothing}, fmi3Float64}) "The given input function does not fit the needed input function pattern for ME-FMUs, which are: \n- `inputFunction(t::fmi3Float64)`\n- `inputFunction(comp::FMU3Instance, t::fmi3Float64)`\n- `inputFunction(comp::FMU3Instance, u::Union{AbstractArray{fmi3Float64,1}, Nothing})`\n- `inputFunction(u::Union{AbstractArray{fmi3Float64,1}, Nothing}, t::fmi3Float64)`\n- `inputFunction(comp::FMU3Instance, u::Union{AbstractArray{fmi3Float64,1}, Nothing}, t::fmi3Float64)`" end - recordValues = prepareValueReference(c, recordValues) - inputValues = prepareValueReference(c, inputValues) - solution = nothing - callbacks = [] - savedValues = nothing + recordValues = prepareValueReference(fmu, recordValues) + inputValueReferences = prepareValueReference(fmu, inputValueReferences) + + fmusol = FMU3Solution(fmu) savingValues = (length(recordValues) > 0) - hasInputs = (length(inputValues) > 0) - # println(t_start) - # println(t_stop) - # println(recordValues) - # println(inputValues) - # println(savingValues) - # println(hasInputs) - if savingValues - savedValues = SavedValues(Float64, Tuple{collect(Float64 for i in 1:length(recordValues))...}) + hasInputs = (length(inputValueReferences) > 0) + hasParameters = (parameters !== nothing) + hasStartState = (x0 !== nothing) - savingCB = SavingCallback((u,t,integrator) -> saveValues(c, recordValues, u, t, integrator), - savedValues, - saveat=saveat) - push!(callbacks, savingCB) - end - # println(c.fmu.instances[end].state) - # auto correct reset if only setup is given - if reset === nothing - reset = setup + cbs = [] + + for cb in callbacks + push!(cbs, cb) end - @assert !(setup==false && reset==true) "fmi3SimulateME(...): keyword argument `setup=false`, but `reset=true`. This may cause a FMU crash." + if t_start === nothing + t_start = fmi3GetDefaultStartTime(fmu.modelDescription) + + if t_start === nothing + t_start = 0.0 + @info "No `t_start` choosen, no `t_start` availabel in the FMU, auto-picked `t_start=0.0`." + end + end + + if t_stop === nothing + t_stop = fmi3GetDefaultStopTime(fmu.modelDescription) - if reset - fmi3Reset(c) + if t_stop === nothing + t_stop = 1.0 + @warn "No `t_stop` choosen, no `t_stop` availabel in the FMU, auto-picked `t_stop=1.0`." + end end - # println(c.fmu.instances[end].state) - # println(fmi3IsModelExchange(c.fmu)) - if setup - fmi3EnterInitializationMode(c, t_start, t_stop) - fmi3ExitInitializationMode(c) + + if tolerance === nothing + tolerance = fmi3GetDefaultTolerance(fmu.modelDescription) + # if no tolerance is given, pick auto-setting from DifferentialEquations.jl end - println(c.state) - eventHandling = c.fmu.modelDescription.numberOfEventIndicators > 0 - # println(eventHandling) - timeEventHandling = false - - if eventHandling - discreteStatesNeedUpdate = fmi3True - while discreteStatesNeedUpdate == fmi3True - discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime = fmi3UpdateDiscreteStates(c) - @assert terminateSimulation == fmi3False ["Initial Event handling failed!"] - timeEventHandling |= (nextEventTimeDefined == fmi3True) - end + if dt === nothing + dt = fmi3GetDefaultStepSize(fmu.modelDescription) + # if no dt is given, pick auto-setting from DifferentialEquations.jl end - - if customFx === nothing - customFx = (x, p, t) -> fx(c, x, p, t) + + if dtmax === nothing + dtmax = (t_stop-t_start)/100.0 end - fmi3EnterContinuousTimeMode(c) - # println(c.state) + # argument `tolerance=nothing` here, because ME-FMUs doesn't support tolerance control (no solver included) + # tolerance for the solver is set-up later in this function + c, x0 = prepareFMU(fmu, c, fmi3TypeModelExchange, instantiate, terminate, reset, setup, parameters, t_start, t_stop, nothing; x0=x0, inputFunction=_inputFunction, inputValueReferences=inputValueReferences) - if eventHandling - c.z_prev = fmi3GetEventIndicators(c) - end - # println(c.z_prev) - # First evaluation of the FMU - x0 = fmi3GetContinuousStates(c) - x0_nom = fmi3GetNominalsOfContinuousStates(c) - # println(x0) - p = [] - problem = ODEProblem(customFx, x0, (t_start, t_stop), p,) + # from here on, we are in event mode, if `setup=false` this is the job of the user + #@assert c.state == fmi3InstanceStateEventMode "FMU needs to be in event mode after setup." + + # if x0 === nothing + # x0 = fmi3GetContinuousStates(c) + # x0_nom = fmi3GetNominalsOfContinuousStates(c) + # end + + # initial event handling + fmi3EnterEventMode(c, c.stepEvent, c.stateEvent, c.rootsFound, Csize_t(c.fmu.modelDescription.numberOfEventIndicators), c.timeEvent) + handleEvents(c) + #fmi3EnterContinuousTimeMode(c) + + c.fmu.hasStateEvents = (c.fmu.modelDescription.numberOfEventIndicators > 0) + # c.fmu.hasTimeEvents = (c.eventInfo.nextEventTimeDefined == fmi2True) + c.fmu.hasTimeEvents = fmi3True + setupODEProblem(c, x0, t_start, t_stop; customFx=customFx) + + progressMeter = nothing + if showProgress + progressMeter = ProgressMeter.Progress(1000; desc="Simulating ME-FMU ...", color=:blue, dt=1.0) #, barglyphs=ProgressMeter.BarGlyphs("[=> ]")) + ProgressMeter.update!(progressMeter, 0) # show it! + end + # callback functions - # use step callback always if we have inputs or need evenet handling - if hasInputs || eventHandling - stepCb = FunctionCallingCallback((x, t, integrator) -> stepCompleted(c, x, t, integrator, inputFunction, inputValues); - func_everystep = true, - func_start = true) - push!(callbacks, stepCb) + if c.fmu.hasTimeEvents + timeEventCb = IterativeCallback((integrator) -> time_choice(c, integrator, t_start, t_stop), + (integrator) -> affectFMU!(c, integrator, 0, _inputFunction, inputValueReferences, fmusol), Float64; + initial_affect = false, # (c.eventInfo.nextEventTime == t_start) + save_positions=(false,false)) + push!(cbs, timeEventCb) end - if eventHandling + if c.fmu.hasStateEvents - eventCb = VectorContinuousCallback((out, x, t, integrator) -> condition(c, out, x, t, integrator, inputFunction, inputValues), - (integrator, idx) -> affectFMU!(c, integrator, idx, inputFunction, inputValues), + eventCb = VectorContinuousCallback((out, x, t, integrator) -> condition(c, out, x, t, integrator, _inputFunction, inputValueReferences), + (integrator, idx) -> affectFMU!(c, integrator, idx, _inputFunction, inputValueReferences, fmusol), Int64(c.fmu.modelDescription.numberOfEventIndicators); rootfind = RightRootFind, - save_positions=(saveAtEvent,saveAtEvent))#, interp_points=rootSearchInterpolationPoints,abstol=1e-16, reltol=1e-12, repeat_nudge=1//100) - push!(callbacks, eventCb) - - if timeEventHandling - timeEventCb = IterativeCallback((integrator) -> time_choice(c, integrator), - (integrator) -> affectFMU!(c, integrator, 0, inputFunction, inputValues), Float64; - initial_affect = true, - save_positions=(saveAtEvent,saveAtEvent)) - push!(callbacks, timeEventCb) + save_positions=(false,false)) + push!(cbs, eventCb) + end + + # use step callback always if we have inputs or need event handling (or just want to see our simulation progress) + if hasInputs || c.fmu.hasStateEvents || c.fmu.hasTimeEvents || showProgress + stepCb = FunctionCallingCallback((x, t, integrator) -> stepCompleted(c, x, t, integrator, _inputFunction, inputValueReferences, progressMeter, t_start, t_stop, fmusol); + func_everystep = true, + func_start = true) + push!(cbs, stepCb) + end + + if savingValues + fmusol.values = SavedValues(Float64, Tuple{collect(Float64 for i in 1:length(recordValues))...}) + fmusol.valueReferences = copy(recordValues) + + if saveat === nothing + savingCB = SavingCallback((u,t,integrator) -> saveValues(c, recordValues, u, t, integrator, _inputFunction, inputValueReferences), + fmusol.values) + else + savingCB = SavingCallback((u,t,integrator) -> saveValues(c, recordValues, u, t, integrator, _inputFunction, inputValueReferences), + fmusol.values, + saveat=saveat) end + + push!(cbs, savingCB) + end + + # if auto_dt == true + # @assert solver !== nothing "fmi2SimulateME(...): `auto_dt=true` but no solver specified, this is not allowed." + # tmpIntegrator = init(c.problem, solver) + # dt = auto_dt_reset!(tmpIntegrator) + # end + + solveKwargs = Dict{Symbol, Any}() + + if dt !== nothing + solveKwargs[:dt] = dt + end + + if tolerance !== nothing + solveKwargs[:reltol] = tolerance + end + + if saveat !== nothing + solveKwargs[:saveat] = saveat end if solver === nothing - solution = solve(problem; callback = CallbackSet(callbacks...), saveat = saveat, kwargs...) + fmusol.states = solve(c.problem; callback = CallbackSet(cbs...), dtmax=dtmax, solveKwargs..., kwargs...) else - solution = solve(problem, solver; callback = CallbackSet(callbacks...), saveat = saveat, kwargs...) + fmusol.states = solve(c.problem, solver; callback = CallbackSet(cbs...), dtmax=dtmax, solveKwargs..., kwargs...) end - if savingValues - return solution, savedValues - else - return solution + fmusol.success = (fmusol.states.retcode == :Success) + + # cleanup progress meter + if showProgress + ProgressMeter.finish!(progressMeter) end + + finishFMU(fmu, c, terminate, freeInstance) + + return fmusol end + # wrapper function fmi3SimulateCS(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) fmi3SimulateCS(c.fmu, c, t_start, t_stop; kwargs...) end -""" -Source: FMISpec3.0, Version D5ef1c1: 4.3. Code Examples +############ Co-Simulation ############ +""" Starts a simulation of the Co-Simulation FMU instance. -Returns a tuple of (success::Bool, DiffEqCallbacks.SavedValues) with success = `true` or `false`. -If keyword `recordValues` is not set, a tuple of type (success::Bool, nothing) is returned for consitency. +Via the optional keyword arguments `inputValues` and `inputFunction`, a custom input function `f(c, t)` or `f(t)` with time `t` and component `c` can be defined, that should return a array of values for `fmi3SetFloat64(..., inputValues, inputFunction(...))`. -ToDo: Improve Documentation. +Keywords: + - recordValues: Array of variables (strings or variableIdentifiers) to record. Results are returned as `DiffEqCallbacks.SavedValues` + - saveat: Time points to save values at (interpolated) + - setup: Boolean, if FMU should be setup (default=true) + - reset: Boolean, if FMU should be reset before simulation (default reset=setup) + - inputValueReferences: Array of input variables (strings or variableIdentifiers) to set at every simulation step + - inputFunction: Function to retrieve the values to set the inputs to + - parameters: Dictionary of parameter variables (strings or variableIdentifiers) and values (Real, Integer, Boolean, String) to set parameters during initialization +Returns: + - If keyword `recordValues` is not set, a boolean `success` is returned (simulation success). + - If keyword `recordValues` is set, a tuple of type (true, DiffEqCallbacks.SavedValues) or (false, nothing). """ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; - recordValues::fmi3ValueReferenceFormat = nothing, - saveat = [], - setup::Bool = true, - reset = nothing, - inputValues::fmi3ValueReferenceFormat = nothing, - inputFunction = nothing) + tolerance::Union{Real, Nothing} = nothing, + dt::Union{Real, Nothing} = nothing, + recordValues::fmi3ValueReferenceFormat = nothing, + saveat = [], + setup::Union{Bool, Nothing} = nothing, + reset::Union{Bool, Nothing} = nothing, + instantiate::Union{Bool, Nothing} = nothing, + freeInstance::Union{Bool, Nothing} = nothing, + terminate::Union{Bool, Nothing} = nothing, + inputValueReferences::fmi3ValueReferenceFormat = nothing, + inputFunction = nothing, + showProgress::Bool=true, + parameters::Union{Dict{<:Any, <:Any}, Nothing} = nothing) + + @assert fmi3IsCoSimulation(fmu) "fmi3SimulateCS(...): This function supports Co-Simulation FMUs only." + + # input function handling + _inputFunction = nothing + if inputFunction != nothing + if hasmethod(inputFunction, Tuple{fmi3Float64}) + _inputFunction = (c, t) -> inputFunction(t) + else + _inputFunction = inputFunctiont + end + @assert hasmethod(_inputFunction, Tuple{FMU3Instance, fmi3Float64}) "The given input function does not fit the needed input function pattern for CS-FMUs, which are: \n- `inputFunction(t::fmi3Float64)`\n- `inputFunction(comp::FMU3Instance, t::fmi3Float64)`" + end + + fmusol = FMU3Solution(fmu) + recordValues = prepareValueReference(fmu, recordValues) - inputValues = prepareValueReference(fmu, inputValues) - variableSteps = fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize + inputValueReferences = prepareValueReference(fmu, inputValueReferences) + hasInputs = (length(inputValueReferences) > 0) + + variableSteps = fmi3IsCoSimulation(fmu) && fmu.modelDescription.coSimulation.canHandleVariableCommunicationStepSize + + t_start = t_start === nothing ? fmi3GetDefaultStartTime(fmu.modelDescription) : t_start + t_start = t_start === nothing ? 0.0 : t_start + t_stop = t_stop === nothing ? fmi3GetDefaultStopTime(fmu.modelDescription) : t_stop + t_stop = t_stop === nothing ? 1.0 : t_stop + tolerance = tolerance === nothing ? fmi3GetDefaultTolerance(fmu.modelDescription) : tolerance + tolerance = tolerance === nothing ? 0.0 : tolerance + dt = dt === nothing ? fmi3GetDefaultStepSize(fmu.modelDescription) : dt + dt = dt === nothing ? 1e-3 : dt - success = false - savedValues = nothing + c, _ = prepareFMU(fmu, c, fmi3TypeCoSimulation, instantiate, terminate, reset, setup, parameters, t_start, t_stop, tolerance; inputFunction=_inputFunction, inputValueReferences=inputValueReferences) # default setup if length(saveat) == 0 - saveat = LinRange(t_start, t_stop, 100) + saveat = t_start:dt:t_stop end - dt = (t_stop - t_start) / length(saveat) # setup if no variable steps if variableSteps == false @@ -378,26 +1115,16 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st end end - # auto correct reset if only setup is given - if reset === nothing - reset = setup - end - @assert !(setup==false && reset==true) "fmi3SimulateME(...): keyword argument `setup=false`, but `reset=true`. This may cause a FMU crash." - - - if reset - fmi3Reset(fmu) - end - - if setup - fmi3EnterInitializationMode(fmu, t_start, t_stop) - fmi3ExitInitializationMode(fmu) - end - t = t_start record = length(recordValues) > 0 + progressMeter = nothing + if showProgress + progressMeter = ProgressMeter.Progress(1000; desc="Simulating CS-FMU ...", color=:blue, dt=1.0) #, barglyphs=ProgressMeter.BarGlyphs("[=> ]")) + ProgressMeter.update!(progressMeter, 0) # show it! + end + #numDigits = length(string(round(Integer, 1/dt))) noSetFMUStatePriorToCurrentPoint = fmi3False eventEncountered = fmi3False @@ -406,13 +1133,14 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st lastSuccessfulTime = fmi3Float64(0.0) if record - savedValues = SavedValues(Float64, Tuple{collect(Float64 for i in 1:length(recordValues))...}) + fmusol.values = SavedValues(Float64, Tuple{collect(Float64 for i in 1:length(recordValues))...} ) + fmusol.valueReferences = copy(recordValues) i = 1 - values = (fmi3GetFloat64(fmu, recordValues)...,) - DiffEqCallbacks.copyat_or_push!(savedValues.t, i, t) - DiffEqCallbacks.copyat_or_push!(savedValues.saveval, i, values, Val{false}) + svalues = (fmi3GetFloat64(c, recordValues)...,) + DiffEqCallbacks.copyat_or_push!(fmusol.values.t, i, t) + DiffEqCallbacks.copyat_or_push!(fmusol.values.saveval, i, svalues, Val{false}) while t < t_stop if variableSteps @@ -423,8 +1151,8 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st end end - if inputFunction !== nothing - fmi3SetFloat64(fmu, inputValues, inputFunction(t)) + if _inputFunction !== nothing + fmi3SetFloat64(fmu, inputValueReferences, _inputFunction(c, t)) end fmi3DoStep!(fmu, t, dt, true, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) @@ -440,13 +1168,21 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st t = t + dt #round(t + dt, digits=numDigits) i += 1 - values = (fmi3GetFloat64(fmu, recordValues)...,) - DiffEqCallbacks.copyat_or_push!(savedValues.t, i, t) - DiffEqCallbacks.copyat_or_push!(savedValues.saveval, i, values, Val{false}) + svalues = (fmi3GetFloat64(c, recordValues)...,) + DiffEqCallbacks.copyat_or_push!(fmusol.values.t, i, t) + DiffEqCallbacks.copyat_or_push!(fmusol.values.saveval, i, svalues, Val{false}) + + if progressMeter !== nothing + ProgressMeter.update!(progressMeter, floor(Integer, 1000.0*(t-t_start)/(t_stop-t_start)) ) + end + end + + if progressMeter !== nothing + ProgressMeter.finish!(progressMeter) end - success = true - return success, savedValues + fmusol.success = true + else i = 1 while t < t_stop @@ -458,8 +1194,8 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st end end - if inputFunction !== nothing - fmi3SetFloat64(fmu, inputValues, inputFunction(t)) + if _inputFunction !== nothing + fmi3SetFloat64(fmu, inputValues, _inputFunction(c, t)) end fmi3DoStep!(fmu, t, dt, true, eventEncountered, terminateSimulation, earlyReturn, lastSuccessfulTime) @@ -474,33 +1210,66 @@ function fmi3SimulateCS(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st end t = t + dt #round(t + dt, digits=numDigits) i += 1 + + if progressMeter !== nothing + ProgressMeter.update!(progressMeter, floor(Integer, 1000.0*(t-t_start)/(t_stop-t_start)) ) + end + end + + if progressMeter !== nothing + ProgressMeter.finish!(progressMeter) end - success = true - return success + fmusol.success = true end + + finishFMU(fmu, c, terminate, freeInstance) + + return fmusol end # TODO simulate ScheduledExecution -function fmi3SimulateSE(c::fmi3Instance, t_start::Real, t_stop::Real; +function fmi3SimulateSE(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; + tolerance::Union{Real, Nothing} = nothing, + dt::Union{Real, Nothing} = nothing, recordValues::fmi3ValueReferenceFormat = nothing, saveat = [], - setup::Bool = true, - reset = nothing, - inputValues::fmi3ValueReferenceFormat = nothing, - inputFunction = nothing) - @assert false "Not implemented" + setup::Union{Bool, Nothing} = nothing, + reset::Union{Bool, Nothing} = nothing, + instantiate::Union{Bool, Nothing} = nothing, + freeInstance::Union{Bool, Nothing} = nothing, + terminate::Union{Bool, Nothing} = nothing, + inputValueReferences::fmi3ValueReferenceFormat = nothing, + inputFunction = nothing, + showProgress::Bool=true, + parameters::Union{Dict{<:Any, <:Any}, Nothing} = nothing) @assert false "Not implemented" end +##### CS & ME ##### + +# wrapper +function fmi3Simulate(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) + fmi3Simulate(c.fmu, c, t_start, t_stop; kwargs...) +end + """ -Starts a simulation of the fmu instance for the matching fmu type, if both types are available, CS is preferred. +Starts a simulation of the FMU instance for the matching FMU type, if both types are available, CS is preferred. + +Keywords: + - recordValues: Array of variables (strings or variableIdentifiers) to record. Results are returned as `DiffEqCallbacks.SavedValues` + - setup: Boolean, if FMU should be setup (default=true) + - reset: Boolean, if FMU should be reset before simulation (default reset=setup) + - inputValues: Array of input variables (strings or variableIdentifiers) to set at every simulation step + - inputFunction: Function to retrieve the values to set the inputs to + - saveat: [ME only] Time points to save values at (interpolated) + - solver: [ME only] Any Julia-supported ODE-solver (default is Tsit5) + - customFx: [ME only, deperecated] Ability to give a custom state derivative function ẋ=f(x,t) Returns: - - a tuple of (success::Bool, DiffEqCallbacks.SavedValues) with success = `true` or `false` for CS-FMUs - - a tuple of (ODESolution, DiffEqCallbacks.SavedValues) for ME-FMUs - - if keyword `recordValues` is not set, a tuple of type (..., nothing) - -ToDo: Improve Documentation. + - `success::Bool` for CS-FMUs + - `ODESolution` for ME-FMUs + - if keyword `recordValues` is set, a tuple of type (success::Bool, DiffEqCallbacks.SavedValues) for CS-FMUs + - if keyword `recordValues` is set, a tuple of type (ODESolution, DiffEqCallbacks.SavedValues) for ME-FMUs """ function fmi3Simulate(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) @@ -508,12 +1277,9 @@ function fmi3Simulate(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_star return fmi3SimulateCS(fmu, c, t_start, t_stop; kwargs...) elseif fmu.type == fmi3TypeModelExchange return fmi3SimulateME(fmu, c, t_start, t_stop; kwargs...) + elseif fmu.type == fmi3TypeScheduledExecution + return fmi3SimulateSE(fmu, c, t_start, t_stop; kwargs...) else error(unknownFMUType) end end - - -function fmi3Simulate(c::FMU3Instance, t_start::Union{Real, Nothing} = nothing, t_stop::Union{Real, Nothing} = nothing; kwargs...) - fmi3Simulate(c.fmu, c, t_start, t_stop; kwargs...) -end diff --git a/test/FMI3/sim_CS.jl b/test/FMI3/sim_CS.jl index a7325c25..4f1d6dfb 100644 --- a/test/FMI3/sim_CS.jl +++ b/test/FMI3/sim_CS.jl @@ -28,18 +28,18 @@ t_stop = 3.0 # @test solution.success # test with recording values -success,savedValues = fmiSimulateCS(fmuStruct, t_start, t_stop; recordValues=["h", "v"]) -@test success -@test length(savedValues.t) == 100 -#@test length(savedValues.t) == t_start:1e-2:t_stop |> length -@test length(savedValues.saveval[1]) == 2 - -t = savedValues.t -s = collect(d[1] for d in savedValues.saveval) -v = collect(d[2] for d in savedValues.saveval) +solution = fmiSimulateCS(fmuStruct, t_start, t_stop; dt=1e-2, recordValues=["h", "v"]) +@test solution.success +@test length(solution.values.saveval) == t_start:1e-2:t_stop |> length +@test length(solution.values.saveval[1]) == 2 + +t = solution.values.t +s = collect(d[1] for d in solution.values.saveval) +v = collect(d[2] for d in solution.values.saveval) @test t[1] == t_start @test t[end] == t_stop + # reference values from Simulation in Dymola2020x (Dassl) @test s[1] == 1.0 @test v[1] == 0.0 diff --git a/test/FMI3/sim_ME.jl b/test/FMI3/sim_ME.jl index ddc1d797..d0e9e0dd 100644 --- a/test/FMI3/sim_ME.jl +++ b/test/FMI3/sim_ME.jl @@ -33,134 +33,104 @@ solution = fmiSimulateME(fmuStruct, t_start, t_stop) @test solution.states.t[end] == t_stop # reference values from Simulation in Dymola2020x (Dassl) -@test solution.states.u[1] == [0.5, 0.0] -@test sum(abs.(solution.states.u[end] - [1.06736, -1.03552e-10])) < 0.1 +@test solution.states.u[1] == [1.0, 0.0] +@test sum(abs.(solution.states.u[end] - [1.0, 0.0])) < 0.1 fmiUnload(myFMU) # case 2: ME-FMU with state and time events -myFMU = fmiLoad("SpringTimeFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +# myFMU = fmiLoad("SpringTimeFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 - -# choose FMU or FMUComponent -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" - -### test without recording values - -solution = fmiSimulateME(fmuStruct, t_start, t_stop; dtmax=0.001) # dtmax to force resolution -@test length(solution.states.u) > 0 -@test length(solution.states.t) > 0 - -@test solution.states.t[1] == t_start -@test solution.states.t[end] == t_stop - -# reference values from Simulation in Dymola2020x (Dassl) -@test solution.states.u[1] == [0.5, 0.0] -@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 +# comp = fmiInstantiate!(myFMU; loggingOn=false) +# @test comp != 0 -### test with recording values (variable step record values) +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = comp +# end +# @assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" -solution= fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", dtmax=0.001) # dtmax to force resolution -dataLength = length(solution.states.u) -@test dataLength > 0 -@test length(solution.states.t) == dataLength -@test length(solution.values.saveval) == dataLength -@test length(solution.values.t) == dataLength +# ### test without recording values -@test solution.states.t[1] == t_start -@test solution.states.t[end] == t_stop -@test solution.values.t[1] == t_start -@test solution.values.t[end] == t_stop - -# reference values from Simulation in Dymola2020x (Dassl) -@test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 -@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 -@test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 -@test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; dtmax=0.001) # dtmax to force resolution +# @test length(solution.states.u) > 0 +# @test length(solution.states.t) > 0 -### test with recording values (fixed step record values) +# @test solution.states.t[1] == t_start +# @test solution.states.t[end] == t_stop -tData = t_start:0.1:t_stop -solution = fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", saveat=tData, dtmax=0.001) # dtmax to force resolution -@test length(solution.states.u) == length(tData) -@test length(solution.states.t) == length(tData) -@test length(solution.values.saveval) == length(tData) -@test length(solution.values.t) == length(tData) +# # reference values from Simulation in Dymola2020x (Dassl) +# @test solution.states.u[1] == [0.5, 0.0] +# @test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 -@test solution.states.t[1] == t_start -@test solution.states.t[end] == t_stop -@test solution.values.t[1] == t_start -@test solution.values.t[end] == t_stop +# ### test with recording values (variable step record values) -# reference values from Simulation in Dymola2020x (Dassl) -@test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 -@test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 -@test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 -@test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 +# solution= fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", dtmax=0.001) # dtmax to force resolution +# dataLength = length(solution.states.u) +# @test dataLength > 0 +# @test length(solution.states.t) == dataLength +# @test length(solution.values.saveval) == dataLength +# @test length(solution.values.t) == dataLength -fmiUnload(myFMU) +# @test solution.states.t[1] == t_start +# @test solution.states.t[end] == t_stop +# @test solution.values.t[1] == t_start +# @test solution.values.t[end] == t_stop -# case 3a: ME-FMU without events, but with input signal (explicit solver: Tsit5) +# # reference values from Simulation in Dymola2020x (Dassl) +# @test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 +# @test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 +# @test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 +# @test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 -function extForce(t) - [sin(t)] -end +# ### test with recording values (fixed step record values) -myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +# tData = t_start:0.1:t_stop +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; recordValues="mass.f", saveat=tData, dtmax=0.001) # dtmax to force resolution +# @test length(solution.states.u) == length(tData) +# @test length(solution.states.t) == length(tData) +# @test length(solution.values.saveval) == length(tData) +# @test length(solution.values.t) == length(tData) -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 +# @test solution.states.t[1] == t_start +# @test solution.states.t[end] == t_stop +# @test solution.values.t[1] == t_start +# @test solution.values.t[end] == t_stop -# choose FMU or FMUComponent -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" +# # reference values from Simulation in Dymola2020x (Dassl) +# @test sum(abs.(solution.states.u[1] - [0.5, 0.0])) < 1e-4 +# @test sum(abs.(solution.states.u[end] - [1.05444, 1e-10])) < 0.01 +# @test abs(solution.values.saveval[1][1] - 0.75) < 1e-4 +# @test sum(abs.(solution.values.saveval[end][1] - -0.54435 )) < 0.015 -solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Tsit5(), dtmax=0.001) # dtmax to force resolution -@test length(solution.states.u) > 0 -@test length(solution.states.t) > 0 +# fmiUnload(myFMU) -@test solution.states.t[1] == t_start -@test solution.states.t[end] == t_stop +# # case 3a: ME-FMU without events, but with input signal (explicit solver: Tsit5) -# reference values from Simulation in Dymola2020x (Dassl) -@test solution.states.u[1] == [0.5, 0.0] -@test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.012 -fmiUnload(myFMU) +# function extForce(t) +# [sin(t)] +# end -# case 3b: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, autodiff) +# myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +# comp = fmiInstantiate!(myFMU; loggingOn=false) +# @test comp != 0 -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = comp +# end +# @assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" -# choose FMU or FMUComponent -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" - -# ToDo: autodiff=true not working currently! -# solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=true), dtmax=0.001) # dtmax to force resolution +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Tsit5(), dtmax=0.001) # dtmax to force resolution # @test length(solution.states.u) > 0 # @test length(solution.states.t) > 0 @@ -169,93 +139,123 @@ end # # reference values from Simulation in Dymola2020x (Dassl) # @test solution.states.u[1] == [0.5, 0.0] -# @test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 -fmiUnload(myFMU) - -# case 3c: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, no autodiff) +# @test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.012 +# fmiUnload(myFMU) -myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +# # case 3b: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, autodiff) -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 +# myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -# choose FMU or FMUComponent -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" +# comp = fmiInstantiate!(myFMU; loggingOn=false) +# @test comp != 0 -solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=false), dtmax=0.001) # dtmax to force resolution -@test length(solution.states.u) > 0 -@test length(solution.states.t) > 0 +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = comp +# end +# @assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" -@test solution.states.t[1] == t_start -@test solution.states.t[end] == t_stop +# # ToDo: autodiff=true not working currently! +# # solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=true), dtmax=0.001) # dtmax to force resolution +# # @test length(solution.states.u) > 0 +# # @test length(solution.states.t) > 0 -# reference values from Simulation in Dymola2020x (Dassl) -@test solution.states.u[1] == [0.5, 0.0] -@test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 -fmiUnload(myFMU) +# # @test solution.states.t[1] == t_start +# # @test solution.states.t[end] == t_stop -# case 4: ME-FMU without events, but saving value interpolation +# # # reference values from Simulation in Dymola2020x (Dassl) +# # @test solution.states.u[1] == [0.5, 0.0] +# # @test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 +# fmiUnload(myFMU) -myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) +# # case 3c: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, no autodiff) -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 +# myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) -# choose FMU or FMUComponent -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" +# comp = fmiInstantiate!(myFMU; loggingOn=false) +# @test comp != 0 -solution = fmiSimulateME(fmuStruct, t_start, t_stop; saveat=tData, recordValues=myFMU.modelDescription.stateValueReferences) -@test length(solution.states.u) == length(tData) -@test length(solution.states.t) == length(tData) -@test length(solution.values.saveval) == length(tData) -@test length(solution.values.t) == length(tData) +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = comp +# end +# @assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" -for i in 1:length(tData) - @test sum(abs(solution.states.t[i] - solution.states.t[i])) < 1e-6 - @test sum(abs(solution.states.u[i][1] - solution.values.saveval[i][1])) < 1e-6 - @test sum(abs(solution.states.u[i][2] - solution.values.saveval[i][2])) < 1e-6 -end - -fmiUnload(myFMU) - -# case 5: ME-FMU with different (random) start state - -myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) - -comp = fmiInstantiate!(myFMU; loggingOn=false) -@test comp != 0 +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=false), dtmax=0.001) # dtmax to force resolution +# @test length(solution.states.u) > 0 +# @test length(solution.states.t) > 0 -# choose FMU or FMUComponent -fmuStruct = nothing -envFMUSTRUCT = ENV["FMUSTRUCT"] -if envFMUSTRUCT == "FMU" - fmuStruct = myFMU -elseif envFMUSTRUCT == "FMUCOMPONENT" - fmuStruct = comp -end -@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" +# @test solution.states.t[1] == t_start +# @test solution.states.t[end] == t_stop -rand_x0 = rand(2) -solution = fmiSimulateME(fmuStruct, t_start, t_stop; x0=rand_x0) -@test length(solution.states.u) > 0 -@test length(solution.states.t) > 0 +# # reference values from Simulation in Dymola2020x (Dassl) +# @test solution.states.u[1] == [0.5, 0.0] +# @test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01 +# fmiUnload(myFMU) + +# # case 4: ME-FMU without events, but saving value interpolation + +# myFMU = fmiLoad("SpringPendulumExtForce1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +# comp = fmiInstantiate!(myFMU; loggingOn=false) +# @test comp != 0 + +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = comp +# end +# @assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; saveat=tData, recordValues=myFMU.modelDescription.stateValueReferences) +# @test length(solution.states.u) == length(tData) +# @test length(solution.states.t) == length(tData) +# @test length(solution.values.saveval) == length(tData) +# @test length(solution.values.t) == length(tData) + +# for i in 1:length(tData) +# @test sum(abs(solution.states.t[i] - solution.states.t[i])) < 1e-6 +# @test sum(abs(solution.states.u[i][1] - solution.values.saveval[i][1])) < 1e-6 +# @test sum(abs(solution.states.u[i][2] - solution.values.saveval[i][2])) < 1e-6 +# end + +# fmiUnload(myFMU) + +# # case 5: ME-FMU with different (random) start state + +# myFMU = fmiLoad("SpringFrictionPendulum1D", ENV["EXPORTINGTOOL"], ENV["EXPORTINGVERSION"]) + +# comp = fmiInstantiate!(myFMU; loggingOn=false) +# @test comp != 0 + +# # choose FMU or FMUComponent +# fmuStruct = nothing +# envFMUSTRUCT = ENV["FMUSTRUCT"] +# if envFMUSTRUCT == "FMU" +# fmuStruct = myFMU +# elseif envFMUSTRUCT == "FMUCOMPONENT" +# fmuStruct = comp +# end +# @assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`" + +# rand_x0 = rand(2) +# solution = fmiSimulateME(fmuStruct, t_start, t_stop; x0=rand_x0) +# @test length(solution.states.u) > 0 +# @test length(solution.states.t) > 0 -@test solution.states.t[1] == t_start -@test solution.states.t[end] == t_stop +# @test solution.states.t[1] == t_start +# @test solution.states.t[end] == t_stop -@test solution.states.u[1] == rand_x0 -fmiUnload(myFMU) \ No newline at end of file +# @test solution.states.u[1] == rand_x0 +# fmiUnload(myFMU) \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 0c7a2ba0..5e59e9a4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -85,7 +85,7 @@ function runtestsFMI3(exportingTool) # include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - include("FMI3/state.jl") + # include("FMI3/state.jl") end @testset "Directional derivatives" begin # include("FMI3/dir_ders.jl") From cabee8efbe52fe950b5abb40013efad743e3215b Mon Sep 17 00:00:00 2001 From: JoKircher Date: Tue, 8 Nov 2022 09:55:21 +0100 Subject: [PATCH 40/41] delete unnecessary prints --- src/FMI3_sim.jl | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/FMI3_sim.jl b/src/FMI3_sim.jl index 58bfc551..d6087de8 100644 --- a/src/FMI3_sim.jl +++ b/src/FMI3_sim.jl @@ -60,11 +60,8 @@ function handleEvents(c::FMU3Instance) fmi3EnterEventMode(c, c.stepEvent, c.stateEvent, c.rootsFound, Csize_t(c.fmu.modelDescription.numberOfEventIndicators), c.timeEvent) # TODO inputEvent handling - println("before loop") - println("---------------------") discreteStatesNeedUpdate = fmi3True while discreteStatesNeedUpdate == fmi3True - println(discreteStatesNeedUpdate) # update discrete states discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime = fmi3UpdateDiscreteStates(c) @@ -82,11 +79,7 @@ function handleEvents(c::FMU3Instance) end end - println("afterLoop") fmi3EnterContinuousTimeMode(c) - # println(valuesChanged) - # println(nominalsChanged) - println(c) @debug "handleEvents(_, $(enterEventMode), $(exitInContinuousMode)): rootsFound: $(c.rootsFound) valuesChanged: $(valuesChanged) continuousStates: $(fmi3GetContinuousStates(c))", return valuesChanged, nominalsChanged @@ -938,7 +931,7 @@ function fmi3SimulateME(fmu::FMU3, c::Union{FMU3Instance, Nothing}=nothing, t_st c.fmu.hasStateEvents = (c.fmu.modelDescription.numberOfEventIndicators > 0) # c.fmu.hasTimeEvents = (c.eventInfo.nextEventTimeDefined == fmi2True) - c.fmu.hasTimeEvents = fmi3True + c.fmu.hasTimeEvents = fmi3False setupODEProblem(c, x0, t_start, t_stop; customFx=customFx) From d49a7dd12f94137ccc535793b64c988b5edd4ec0 Mon Sep 17 00:00:00 2001 From: JoKircher Date: Mon, 14 Nov 2022 15:28:29 +0100 Subject: [PATCH 41/41] Update runtests.jl --- test/runtests.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 92f877fe..e501ef81 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,7 +20,7 @@ for exec in [FMU2_EXECUTION_CONFIGURATION_NO_FREEING, FMU2_EXECUTION_CONFIGURATI exec.assertOnWarning = true end -function runtests(exportingTool) +function runtestsFMI2(exportingTool) ENV["EXPORTINGTOOL"] = exportingTool[1] ENV["EXPORTINGVERSION"] = exportingTool[2] @@ -33,7 +33,7 @@ function runtests(exportingTool) @info "Model Description (model_description.jl)" @testset "Model Description" begin - include("model_description.jl") + include("FMI2/model_description.jl") end for str in fmuStructs @@ -103,10 +103,10 @@ function runtestsFMI3(exportingTool) @testset "Functions for $str" begin ENV["FMUSTRUCT"] = str @testset "Variable Getters / Setters" begin - # include("FMI3/getter_setter.jl") + include("FMI3/getter_setter.jl") end @testset "State Manipulation" begin - # include("FMI3/state.jl") + include("FMI3/state.jl") end @testset "Directional derivatives" begin # include("FMI3/dir_ders.jl") @@ -118,7 +118,7 @@ function runtestsFMI3(exportingTool) include("FMI3/sim_CS.jl") end @testset "ME Simulation" begin - # include("FMI3/sim_ME.jl") + include("FMI3/sim_ME.jl") end @testset "Support CS and ME simultaneously" begin # include("FMI3/cs_me.jl") @@ -139,13 +139,13 @@ end if Sys.iswindows() @info "Automated testing is supported on Windows." for exportingTool in exportingToolsWindows - # runtestsFMI2(exportingTool) + runtestsFMI2(exportingTool) runtestsFMI3(exportingTool) end elseif Sys.islinux() @info "Automated testing is supported on Linux." for exportingTool in exportingToolsLinux - # runtestsFMI2(exportingTool) + runtestsFMI2(exportingTool) runtestsFMI3(exportingTool) end elseif Sys.isapple()