From fc65893b8fca472c9f3a97f1d205222a184a1318 Mon Sep 17 00:00:00 2001 From: Benjamin Uekermann Date: Fri, 15 Mar 2024 18:19:56 +0100 Subject: [PATCH] Add FMU participants to oscillator tutorial (#466) Co-authored-by: Leonard Willeke Co-authored-by: LeonardWilleke <82214922+LeonardWilleke@users.noreply.github.com> Co-authored-by: Gerasimos Chourdakis --- oscillator/.gitignore | 1 + oscillator/README.md | 25 +- oscillator/fmi/MassLeft/fmi-settings.json | 20 + oscillator/fmi/MassLeft/precice-settings.json | 9 + oscillator/fmi/MassRight/fmi-settings.json | 20 + .../fmi/MassRight/precice-settings.json | 9 + oscillator/fmi/calculate-error.py | 93 + oscillator/fmi/clean.sh | 8 + oscillator/fmi/fmu/CMakeLists.txt | 273 +++ oscillator/fmi/fmu/Oscillator/FMI2.xml | 167 ++ oscillator/fmi/fmu/Oscillator/FMI3.xml | 163 ++ .../fmi/fmu/Oscillator/buildDescription.xml | 11 + oscillator/fmi/fmu/Oscillator/config.h | 51 + oscillator/fmi/fmu/Oscillator/model.c | 171 ++ oscillator/fmi/fmu/Oscillator/readme.html | 51 + oscillator/fmi/fmu/README.md | 19 + oscillator/fmi/fmu/include/FMI.h | 160 ++ oscillator/fmi/fmu/include/FMI2.h | 219 +++ oscillator/fmi/fmu/include/FMI3.h | 560 ++++++ oscillator/fmi/fmu/include/cosimulation.h | 8 + .../fmi/fmu/include/fmi2FunctionTypes.h | 266 +++ oscillator/fmi/fmu/include/fmi2Functions.h | 321 ++++ .../fmi/fmu/include/fmi2TypesPlatform.h | 107 ++ .../fmi/fmu/include/fmi3FunctionTypes.h | 637 +++++++ oscillator/fmi/fmu/include/fmi3Functions.h | 343 ++++ .../fmi/fmu/include/fmi3PlatformTypes.h | 93 + oscillator/fmi/fmu/include/fmiFunctions.h | 228 +++ .../fmi/fmu/include/fmiModelFunctions.h | 207 +++ oscillator/fmi/fmu/include/fmiModelTypes.h | 91 + oscillator/fmi/fmu/include/fmiPlatformTypes.h | 73 + oscillator/fmi/fmu/include/model.h | 235 +++ oscillator/fmi/fmu/set_tool_version.py | 45 + oscillator/fmi/fmu/src/FMI.c | 329 ++++ oscillator/fmi/fmu/src/FMI2.c | 569 ++++++ oscillator/fmi/fmu/src/FMI3.c | 1186 +++++++++++++ oscillator/fmi/fmu/src/cosimulation.c | 620 +++++++ oscillator/fmi/fmu/src/fmi2Functions.c | 923 ++++++++++ oscillator/fmi/fmu/src/fmi3Functions.c | 1544 +++++++++++++++++ oscillator/fmi/fmu/thirdparty/LICENSE.txt | 148 ++ oscillator/fmi/run.sh | 40 + oscillator/plot-trajectory.py | 46 +- 41 files changed, 10063 insertions(+), 26 deletions(-) create mode 100644 oscillator/.gitignore create mode 100644 oscillator/fmi/MassLeft/fmi-settings.json create mode 100644 oscillator/fmi/MassLeft/precice-settings.json create mode 100644 oscillator/fmi/MassRight/fmi-settings.json create mode 100644 oscillator/fmi/MassRight/precice-settings.json create mode 100644 oscillator/fmi/calculate-error.py create mode 100755 oscillator/fmi/clean.sh create mode 100644 oscillator/fmi/fmu/CMakeLists.txt create mode 100644 oscillator/fmi/fmu/Oscillator/FMI2.xml create mode 100644 oscillator/fmi/fmu/Oscillator/FMI3.xml create mode 100644 oscillator/fmi/fmu/Oscillator/buildDescription.xml create mode 100644 oscillator/fmi/fmu/Oscillator/config.h create mode 100644 oscillator/fmi/fmu/Oscillator/model.c create mode 100644 oscillator/fmi/fmu/Oscillator/readme.html create mode 100644 oscillator/fmi/fmu/README.md create mode 100644 oscillator/fmi/fmu/include/FMI.h create mode 100644 oscillator/fmi/fmu/include/FMI2.h create mode 100644 oscillator/fmi/fmu/include/FMI3.h create mode 100644 oscillator/fmi/fmu/include/cosimulation.h create mode 100644 oscillator/fmi/fmu/include/fmi2FunctionTypes.h create mode 100644 oscillator/fmi/fmu/include/fmi2Functions.h create mode 100644 oscillator/fmi/fmu/include/fmi2TypesPlatform.h create mode 100644 oscillator/fmi/fmu/include/fmi3FunctionTypes.h create mode 100644 oscillator/fmi/fmu/include/fmi3Functions.h create mode 100644 oscillator/fmi/fmu/include/fmi3PlatformTypes.h create mode 100644 oscillator/fmi/fmu/include/fmiFunctions.h create mode 100644 oscillator/fmi/fmu/include/fmiModelFunctions.h create mode 100644 oscillator/fmi/fmu/include/fmiModelTypes.h create mode 100644 oscillator/fmi/fmu/include/fmiPlatformTypes.h create mode 100644 oscillator/fmi/fmu/include/model.h create mode 100644 oscillator/fmi/fmu/set_tool_version.py create mode 100644 oscillator/fmi/fmu/src/FMI.c create mode 100644 oscillator/fmi/fmu/src/FMI2.c create mode 100644 oscillator/fmi/fmu/src/FMI3.c create mode 100644 oscillator/fmi/fmu/src/cosimulation.c create mode 100644 oscillator/fmi/fmu/src/fmi2Functions.c create mode 100644 oscillator/fmi/fmu/src/fmi3Functions.c create mode 100644 oscillator/fmi/fmu/thirdparty/LICENSE.txt create mode 100755 oscillator/fmi/run.sh diff --git a/oscillator/.gitignore b/oscillator/.gitignore new file mode 100644 index 000000000..69310321e --- /dev/null +++ b/oscillator/.gitignore @@ -0,0 +1 @@ +fmi/Oscillator.fmu diff --git a/oscillator/README.md b/oscillator/README.md index c5e33582d..be8e9e506 100644 --- a/oscillator/README.md +++ b/oscillator/README.md @@ -1,7 +1,7 @@ --- title: Oscillator permalink: tutorials-oscillator.html -keywords: Python, ODE +keywords: Python, ODE, FMI summary: We solve an oscillator with two masses in a partitioned fashion. Each mass is solved by an independent ODE. --- @@ -17,19 +17,16 @@ This tutorial solves a simple mass-spring oscillator with two masses and three s Note that this case applies a Schwarz-type coupling method and not (like most other tutorials in this repository) a Dirichlet-Neumann coupling. This results in a symmetric setup of the solvers. We will refer to the solver computing the trajectory of $m_1$ as `Mass-Left` and to the solver computing the trajectory of $m_2$ as `Mass-Right`. For more information, please refer to [1]. -This tutorial is useful to study different time stepping and coupling schemes. It uses subcycling and time interpolation: Each solver performs 4 time steps in each time window. The data of these 4 substeps is used to create a third order B-spline interpolation (`waveform-degree="3"` in `precice-config.xml`). - ## Available solvers -This tutorial is only available in Python. You need to have preCICE and the Python bindings installed on your system. - -- *Python*: An example solver using the preCICE [Python bindings](https://www.precice.org/installation-bindings-python.html). This solver also depends on the Python libraries `numpy`, which you can get from your system package manager or with `pip3 install --user `. Using the option `-ts` allows to pick the time stepping scheme being used. Available choices are Newmark beta, generalized alpha, explicit Runge Kutta 4, and implicit RadauIIA. +There are two different implementations: -## Running the Simulation +- *Python*: A solver using the preCICE [Python bindings](https://www.precice.org/installation-bindings-python.html). This solver also depends on the Python libraries `numpy`, which you can get from your system package manager or with `pip3 install --user `. Using the option `-ts` allows you to pick the time stepping scheme being used. Available choices are Newmark beta, generalized alpha, explicit Runge Kutta 4, and implicit RadauIIA. The solver uses subcycling: Each participant performs 4 time steps in each time window. The data of these 4 substeps is then used by preCICE to create a third order B-spline interpolation (`waveform-degree="3"` in `precice-config.xml`). +- *FMI*: A solver using the [preCICE-FMI runner](https://github.com/precice/fmi-runner) (requires at least v0.2). The Runner executes the FMU model `Oscillator.fmu` for computation. The provided run script (see below) builds this model if not already there. If you want to change the model parameters or the initial conditions of the simulation, have a look inside the setting files for [MassLeft](https://github.com/precice/tutorials/tree/master/oscillator/fmi/MassLeft) and [MassRight](https://github.com/precice/tutorials/tree/master/oscillator/fmi/MassRight). For more information, please refer to [2]. -### Python +## Running the simulation -Open two separate terminals and start both participants by calling: +Open two separate terminals and start both participants. For example, you can run a simulation where the left participant is computed in Python and the right participant is computed with FMI with these commands: ```bash cd python @@ -39,19 +36,21 @@ cd python and ```bash -cd python +cd fmi ./run.sh -r ``` +Of course, you can also use the same solver for both sides. + ## Post-processing -Each simulation run creates two files containing position and velocity of the two masses over time. These files are called `trajectory-Mass-Left.csv` and `trajectory-Mass-Right.csv`. You can use the script `plot-trajectory.py` for post-processing. Type `python3 plot-trajectory --help` to see available options. You can, for example plot the trajectory by running +Each simulation run creates two files containing position and velocity of the two masses over time. These files are called `trajectory-Mass-Left.csv` and `trajectory-Mass-Right.csv`. You can use the script `plot-trajectory.py` for post-processing. Type `python3 plot-trajectory --help` to see available options. You can, for example, plot the trajectory of the Python solver by running ```bash python3 plot-trajectory.py python/output/trajectory-Mass-Left.csv TRAJECTORY ``` -This allows you to study the effect of different time stepping schemes on energy conservation. Newmark beta conserves energy: +The solvers allow you to study the effect of different time stepping schemes on energy conservation. Newmark beta conserves energy: ![Trajectory for Newmark beta scheme](images/tutorials-oscillator-trajectory-newmark-beta.png) @@ -64,3 +63,5 @@ For details, refer to [1]. ## References [1] V. Schüller, B. Rodenberg, B. Uekermann and H. Bungartz, A Simple Test Case for Convergence Order in Time and Energy Conservation of Black-Box Coupling Schemes, in: WCCM-APCOM2022. [URL](https://www.scipedia.com/public/Rodenberg_2022a) + +[2] L. Willeke, D. Schneider and B. Uekermann, A preCICE-FMI Runner to Couple FMUs to PDE-Based Simulations, Proceedings 15th Intern. Modelica Conference, 2023. [DOI](https://doi.org/10.3384/ecp204) diff --git a/oscillator/fmi/MassLeft/fmi-settings.json b/oscillator/fmi/MassLeft/fmi-settings.json new file mode 100644 index 000000000..1b7006286 --- /dev/null +++ b/oscillator/fmi/MassLeft/fmi-settings.json @@ -0,0 +1,20 @@ +{ + "model_params": { + "mass.m": 1, + "spring_fixed.c": 39.4784176044, + "spring_middle.c": 157.913670417 + }, + "initial_conditions": { + "mass.u": 1, + "mass.v": 0, + "mass.a": -197.392088022 + }, + "simulation_params": { + "fmu_file_name": "./Oscillator.fmu", + "output_file_name": "./output/trajectory-Mass-Left.csv", + "output": ["mass.u", "mass.v"], + "fmu_read_data_names": ["force_in"], + "fmu_write_data_names": ["force_out"], + "fmu_instance_name": "instance_left" + } +} diff --git a/oscillator/fmi/MassLeft/precice-settings.json b/oscillator/fmi/MassLeft/precice-settings.json new file mode 100644 index 000000000..48e3bb98c --- /dev/null +++ b/oscillator/fmi/MassLeft/precice-settings.json @@ -0,0 +1,9 @@ +{ + "coupling_params": { + "participant_name": "Mass-Left", + "config_file_name": "../precice-config.xml", + "mesh_name": "Mass-Left-Mesh", + "write_data_name": "Force-Left", + "read_data_name": "Force-Right" + } +} diff --git a/oscillator/fmi/MassRight/fmi-settings.json b/oscillator/fmi/MassRight/fmi-settings.json new file mode 100644 index 000000000..3fdb5875b --- /dev/null +++ b/oscillator/fmi/MassRight/fmi-settings.json @@ -0,0 +1,20 @@ +{ + "model_params": { + "mass.m": 1, + "spring_fixed.c": 39.4784176044, + "spring_middle.c": 157.913670417 + }, + "initial_conditions": { + "mass.u": 0, + "mass.v": 0, + "mass.a": 157.913670417 + }, + "simulation_params": { + "fmu_file_name": "./Oscillator.fmu", + "output_file_name": "./output/trajectory-Mass-Right.csv", + "output": ["mass.u", "mass.v"], + "fmu_read_data_names": ["force_in"], + "fmu_write_data_names": ["force_out"], + "fmu_instance_name": "instance_right" + } +} diff --git a/oscillator/fmi/MassRight/precice-settings.json b/oscillator/fmi/MassRight/precice-settings.json new file mode 100644 index 000000000..0142520b9 --- /dev/null +++ b/oscillator/fmi/MassRight/precice-settings.json @@ -0,0 +1,9 @@ +{ + "coupling_params": { + "participant_name": "Mass-Right", + "config_file_name": "../precice-config.xml", + "mesh_name": "Mass-Right-Mesh", + "write_data_name": "Force-Right", + "read_data_name": "Force-Left" + } +} diff --git a/oscillator/fmi/calculate-error.py b/oscillator/fmi/calculate-error.py new file mode 100644 index 000000000..baecc291b --- /dev/null +++ b/oscillator/fmi/calculate-error.py @@ -0,0 +1,93 @@ +import numpy as np +import pandas as pd +import json +import os +import argparse +from enum import Enum +import sys + + +class Participant(Enum): + MASS_LEFT = "Mass-Left" + MASS_RIGHT = "Mass-Right" + + +parser = argparse.ArgumentParser() +parser.add_argument("fmi_setting_file_left", help="Path to the fmi setting file for MassLeft.", type=str) +parser.add_argument("precice_setting_file_left", help="Path to the precice setting file for MassLeft.", type=str) +parser.add_argument("fmi_setting_file_right", help="Path to the fmi setting file for MassRight.", type=str) +parser.add_argument("precice_setting_file_right", help="Path to the precice setting file for MassRight.", type=str) +parser.add_argument("participant_name", help="Participant for which the error should be calculated", type=str, + choices=[p.value for p in Participant]) +args = parser.parse_args() + +# Get input files +fmi_file_left = args.fmi_setting_file_left +precice_file_left = args.precice_setting_file_left +fmi_file_right = args.fmi_setting_file_right +precice_file_right = args.precice_setting_file_right +participant_name = args.participant_name + +# Read json files +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), fmi_file_left)) +path = os.path.join(folder, os.path.basename(fmi_file_left)) +read_file = open(path, "r") +fmi_data_left = json.load(read_file) + +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), precice_file_left)) +path = os.path.join(folder, os.path.basename(precice_file_left)) +read_file = open(path, "r") +precice_data_left = json.load(read_file) + +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), fmi_file_right)) +path = os.path.join(folder, os.path.basename(fmi_file_right)) +read_file = open(path, "r") +fmi_data_right = json.load(read_file) + +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), precice_file_right)) +path = os.path.join(folder, os.path.basename(precice_file_right)) +read_file = open(path, "r") +precice_data_right = json.load(read_file) + + +# Define variables +k_1 = fmi_data_left["model_params"]["spring_fixed.c"] +k_2 = fmi_data_right["model_params"]["spring_fixed.c"] +u0_1 = fmi_data_left["initial_conditions"]["mass.u"] +u0_2 = fmi_data_right["initial_conditions"]["mass.u"] +k_12_left = fmi_data_left["model_params"]["spring_middle.c"] +k_12_right = fmi_data_right["model_params"]["spring_middle.c"] + +if k_12_left == k_12_right: + k_12 = k_12_left +else: + raise Exception("k_12 has to be equal in both participants. Please adjust input values.") + + +# Define analytical solution and read computed results +K = np.array([[k_1 + k_12, -k_12], [-k_12, k_2 + k_12]]) +eigenvalues, eigenvectors = np.linalg.eig(K) +omega = np.sqrt(eigenvalues) +A, B = eigenvectors +c = np.linalg.solve(eigenvectors, [u0_1, u0_2]) + +if participant_name == Participant.MASS_LEFT.value: + filename = fmi_data_left["simulation_params"]["output_file_name"] + df = pd.read_csv(filename, delimiter=',') + + def u_analytical(t): return c[0] * A[0] * np.cos(omega[0] * t) + c[1] * A[1] * np.cos(omega[1] * t) + +elif participant_name == Participant.MASS_RIGHT.value: + filename = fmi_data_right["simulation_params"]["output_file_name"] + df = pd.read_csv(filename, delimiter=',') + + def u_analytical(t): return c[0] * B[0] * np.cos(omega[0] * t) + c[1] * B[1] * np.cos(omega[1] * t) + +times = df.iloc[:, 0] +positions = df.iloc[:, 1] + + +# Calculate error +error = np.max(abs(u_analytical(np.array(times)) - np.array(positions))) +print("Error w.r.t analytical solution:") +print(f"{error}") diff --git a/oscillator/fmi/clean.sh b/oscillator/fmi/clean.sh new file mode 100755 index 000000000..c7e3552ac --- /dev/null +++ b/oscillator/fmi/clean.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +rm -rfv ./output/ + +clean_precice_logs . diff --git a/oscillator/fmi/fmu/CMakeLists.txt b/oscillator/fmi/fmu/CMakeLists.txt new file mode 100644 index 000000000..974cef937 --- /dev/null +++ b/oscillator/fmi/fmu/CMakeLists.txt @@ -0,0 +1,273 @@ +cmake_minimum_required (VERSION 3.16) + +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + +FUNCTION(cat IN_FILE OUT_FILE) + file(READ ${IN_FILE} CONTENTS) + file(APPEND ${OUT_FILE} "${CONTENTS}") +ENDFUNCTION() + +project (Reference-FMUs) + +find_package (Python3) +find_package (Git) + +set(FMI_VERSION 2 CACHE STRING "FMI Version") +set_property(CACHE FMI_VERSION PROPERTY STRINGS 1 2 3) + +set(FMI_TYPE ME CACHE STRING "FMI Type (FMI 1.0 only)") +set_property(CACHE FMI_TYPE PROPERTY STRINGS ME CS) + +if (${FMI_VERSION} GREATER 1) + set(FMI_TYPE "") +endif () + +set(WITH_FMUSIM OFF CACHE BOOL "Add fmusim project") + +if (MSVC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + + # Minimum supported MSVC version is 1800 = Visual Studio 12.0/2013 + # See also https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html + if (MSVC_VERSION VERSION_LESS 1800) + message (SEND_ERROR "MSVC_VERSION ${MSVC_VERSION} is not a supported Visual Studio compiler version. Please use Visual Studio 2013 or any later version.") + endif () +endif () + +add_compile_definitions(FMI_VERSION=${FMI_VERSION}) + +if (${FMI_VERSION} GREATER 2) + + if (WIN32) + set(FMI_PLATFORM windows) + elseif (APPLE) + set(FMI_PLATFORM darwin) + else () + set(FMI_PLATFORM linux) + endif () + + if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set (FMI_PLATFORM x86_64-${FMI_PLATFORM}) + else () + set (FMI_PLATFORM x86-${FMI_PLATFORM}) + endif () + +else () + + if (WIN32) + set(FMI_PLATFORM win) + elseif (APPLE) + set(FMI_PLATFORM darwin) + else () + set(FMI_PLATFORM linux) + endif () + + if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set (FMI_PLATFORM ${FMI_PLATFORM}64) + else () + set (FMI_PLATFORM ${FMI_PLATFORM}32) + endif () + +endif () + +MESSAGE("FMI_PLATFORM: " ${FMI_PLATFORM}) + +if (${FMI_VERSION} LESS 3) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/all.c" "#define FMI_VERSION ${FMI_VERSION} + +#include \"fmi${FMI_VERSION}Functions.c\" +#include \"model.c\" +#include \"cosimulation.c\" +") +endif () + +set (MODEL_NAMES Oscillator) + +foreach (MODEL_NAME ${MODEL_NAMES}) + +set(TARGET_NAME ${MODEL_NAME}) + +SET(HEADERS + ${MODEL_NAME}/config.h + include/cosimulation.h + include/model.h +) + +if (${FMI_VERSION} EQUAL 2) + SET(HEADERS + ${HEADERS} + include/fmi2Functions.h + include/fmi2FunctionTypes.h + include/fmi2TypesPlatform.h + ) +elseif (${FMI_VERSION} EQUAL 3) + SET(HEADERS + ${HEADERS} + include/fmi3Functions.h + include/fmi3FunctionTypes.h + include/fmi3PlatformTypes.h + ) +endif() + +SET(SOURCES + ${MODEL_NAME}/model.c + src/fmi${FMI_VERSION}Functions.c + src/cosimulation.c +) + +add_library(${TARGET_NAME} SHARED + ${HEADERS} + ${SOURCES} + ${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml +) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../..) + +target_compile_definitions(${TARGET_NAME} PRIVATE + DISABLE_PREFIX +) + +if (MSVC) + target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX) +else() + target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror) +endif() + +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET_NAME} PRIVATE "-static-libgcc") +endif() + +if (CMAKE_C_COMPILER_ID STREQUAL "Intel") + target_link_options(${TARGET_NAME} PRIVATE "-static-intel" "-static-libgcc") +endif() + +if (${FMI_VERSION} EQUAL 1 AND "${FMI_TYPE}" STREQUAL CS) + target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION) +endif() + +target_include_directories(${TARGET_NAME} PRIVATE + include + ${MODEL_NAME} +) + +set(FMU_BUILD_DIR temp/${MODEL_NAME}) + +set_target_properties(${TARGET_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" +) + +set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "") +set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME}) + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) + +# modelDescription.xml +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml + "${FMU_BUILD_DIR}/modelDescription.xml" +) + +if (${Python3_Interpreter_FOUND} AND ${Git_FOUND}) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/set_tool_version.py" + "${FMU_BUILD_DIR}/modelDescription.xml" "${GIT_EXECUTABLE}" + ) +endif() + +# model specific header and source +foreach (SOURCE_FILE config.h model.c) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# documentation +if (${FMI_VERSION} EQUAL 1) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/readme.html" + "${FMU_BUILD_DIR}/documentation/_main.html" + ) +else() + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/readme.html" + "${FMU_BUILD_DIR}/documentation/index.html" + ) +endif() + +# license +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/LICENSE.txt" + "${FMU_BUILD_DIR}/documentation/LICENSE.txt" +) + +# common headers +foreach (SOURCE_FILE model.h cosimulation.h) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/include/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# common sources +foreach (SOURCE_FILE fmi${FMI_VERSION}Functions.c cosimulation.c) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/src/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# all.c / buildDescription.xml +if (${FMI_VERSION} LESS 3) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_BINARY_DIR}/all.c" + "${FMU_BUILD_DIR}/sources/all.c" + ) +else() + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/buildDescription.xml" + "${FMU_BUILD_DIR}/sources/buildDescription.xml" + ) +endif() + +set(ARCHIVE_FILES "modelDescription.xml" "binaries" "documentation" "sources") + +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources") + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources" + "${FMU_BUILD_DIR}/resources/" + ) + set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources") +endif() + +# delete unintended files from binaries (Release configuration only) +if (MSVC) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND if $ neq 0 ( + ${CMAKE_COMMAND} -E rm -f + "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}/${MODEL_NAME}.exp" + "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}/${MODEL_NAME}.lib" + ) + ) +endif() + +# create ZIP archive +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.fmu --format=zip + ${ARCHIVE_FILES} + WORKING_DIRECTORY ${FMU_BUILD_DIR} COMMENT "Creating ZIP archive" +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.fmu DESTINATION ${CMAKE_INSTALL_PREFIX}) + +endforeach(MODEL_NAME) + +if (WITH_FMUSIM) + add_subdirectory(fmusim) +endif () diff --git a/oscillator/fmi/fmu/Oscillator/FMI2.xml b/oscillator/fmi/fmu/Oscillator/FMI2.xml new file mode 100644 index 000000000..1a518ac3f --- /dev/null +++ b/oscillator/fmi/fmu/Oscillator/FMI2.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oscillator/fmi/fmu/Oscillator/FMI3.xml b/oscillator/fmi/fmu/Oscillator/FMI3.xml new file mode 100644 index 000000000..27a6a02db --- /dev/null +++ b/oscillator/fmi/fmu/Oscillator/FMI3.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oscillator/fmi/fmu/Oscillator/buildDescription.xml b/oscillator/fmi/fmu/Oscillator/buildDescription.xml new file mode 100644 index 000000000..7afd19366 --- /dev/null +++ b/oscillator/fmi/fmu/Oscillator/buildDescription.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/oscillator/fmi/fmu/Oscillator/config.h b/oscillator/fmi/fmu/Oscillator/config.h new file mode 100644 index 000000000..e5d7f94d9 --- /dev/null +++ b/oscillator/fmi/fmu/Oscillator/config.h @@ -0,0 +1,51 @@ +#ifndef config_h +#define config_h + +// define class name and unique id +#define MODEL_IDENTIFIER Oscillator +#define INSTANTIATION_TOKEN "{1AE5E10D-9521-4DE3-80B9-D0EAAA7D5AF1}" + +#define CO_SIMULATION +#define MODEL_EXCHANGE + +// define model size +#define NX 2 +#define NZ 1 + +#define SET_FLOAT64 +#define GET_OUTPUT_DERIVATIVE +#define EVENT_UPDATE + +#define FIXED_SOLVER_STEP 1e-3 +#define DEFAULT_STOP_TIME 3 + +typedef enum { + vr_time, + vr_mass_m, + vr_mass_u, + vr_mass_v, + vr_mass_a, + vr_spring_fixed_c, + vr_spring_middle_c, + vr_force_in, + vr_force_out, + vr_alpha_f, + vr_alpha_m +} ValueReference; + +typedef struct { + + double mass_m; + double mass_u; + double mass_v; + double mass_a; + double spring_fixed_c; + double spring_middle_c; + double force_in; + double force_out; + double alpha_f; + double alpha_m; + +} ModelData; + +#endif /* config_h */ diff --git a/oscillator/fmi/fmu/Oscillator/model.c b/oscillator/fmi/fmu/Oscillator/model.c new file mode 100644 index 000000000..26a2b8d95 --- /dev/null +++ b/oscillator/fmi/fmu/Oscillator/model.c @@ -0,0 +1,171 @@ +#include "model.h" +#include // for DBL_MIN +#include // for fabs() +#include "config.h" + +#define V_MIN (0.1) +#define EVENT_EPSILON (1e-10) + +void setStartValues(ModelInstance *comp) +{ + M(mass_m) = 1; + M(mass_u) = 0; + M(mass_v) = 0; + M(spring_fixed_c) = 4 * 3.1416; + M(spring_middle_c) = 16 * 3.1416; + M(force_in) = 0; + M(force_out) = 0; + M(alpha_f) = 0; + M(alpha_m) = 0; + M(mass_a) = (M(force_in) - (M(spring_fixed_c) + M(spring_middle_c)) * M(mass_u)) / M(mass_m); +} + +Status calculateValues(ModelInstance *comp) +{ + + UNUSED(comp); + return OK; +} + +Status getFloat64(ModelInstance *comp, ValueReference vr, double *value, size_t *index) +{ + switch (vr) { + case vr_time: + value[(*index)++] = comp->time; + return OK; + case vr_mass_m: + value[(*index)++] = M(mass_m); + return OK; + case vr_mass_u: + value[(*index)++] = M(mass_u); + return OK; + case vr_mass_v: + value[(*index)++] = M(mass_v); + return OK; + case vr_mass_a: + value[(*index)++] = M(mass_a); + return OK; + case vr_spring_fixed_c: + value[(*index)++] = M(spring_fixed_c); + return OK; + case vr_spring_middle_c: + value[(*index)++] = M(spring_middle_c); + return OK; + case vr_force_in: + value[(*index)++] = M(force_in); + return OK; + case vr_force_out: + value[(*index)++] = M(force_out); + return OK; + case vr_alpha_f: + value[(*index)++] = M(alpha_f); + return OK; + case vr_alpha_m: + value[(*index)++] = M(alpha_m); + return OK; + default: + logError(comp, "Get Float64 is not allowed for value reference %u.", vr); + return Error; + } +} + +Status setFloat64(ModelInstance *comp, ValueReference vr, const double *value, size_t *index) +{ + switch (vr) { + + case vr_mass_m: + M(mass_m) = value[(*index)++]; + return OK; + case vr_mass_u: + M(mass_u) = value[(*index)++]; + return OK; + case vr_mass_v: + M(mass_v) = value[(*index)++]; + return OK; + case vr_mass_a: + M(mass_a) = value[(*index)++]; + return OK; + case vr_spring_fixed_c: + M(spring_fixed_c) = value[(*index)++]; + return OK; + case vr_spring_middle_c: + M(spring_middle_c) = value[(*index)++]; + return OK; + case vr_force_in: + M(force_in) = value[(*index)++]; + return OK; + case vr_force_out: + M(force_out) = value[(*index)++]; + return OK; + case vr_alpha_f: + M(alpha_f) = value[(*index)++]; + return OK; + case vr_alpha_m: + M(alpha_m) = value[(*index)++]; + return OK; + default: + logError(comp, "Unexpected value reference: %u.", vr); + return Error; + } +} + +Status getOutputDerivative(ModelInstance *comp, ValueReference valueReference, int order, double *value) +{ + + if (order != 1) { + logError(comp, "The output derivative order %d for value reference %u is not available.", order, valueReference); + return Error; + } + + switch (valueReference) { + + default: + logError(comp, "The output derivative for value reference %u is not available.", valueReference); + return Error; + } + + UNUSED(value); +} + +void eventUpdate(ModelInstance *comp) +{ + + if (false) { + + } else { + comp->valuesOfContinuousStatesChanged = false; + } + + comp->nominalsOfContinuousStatesChanged = false; + comp->terminateSimulation = false; + comp->nextEventTimeDefined = false; +} + +void getContinuousStates(ModelInstance *comp, double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(x); +} + +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(x); +} + +void getDerivatives(ModelInstance *comp, double dx[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(dx); +} + +void getEventIndicators(ModelInstance *comp, double z[], size_t nz) +{ + + UNUSED(nz); + UNUSED(comp); + UNUSED(z); +} diff --git a/oscillator/fmi/fmu/Oscillator/readme.html b/oscillator/fmi/fmu/Oscillator/readme.html new file mode 100644 index 000000000..ace31f418 --- /dev/null +++ b/oscillator/fmi/fmu/Oscillator/readme.html @@ -0,0 +1,51 @@ + + + +Oscillator + + + +
+

Oscillator

+ +

This model is used for the partitioned simulation of an oscillator with three springs and two masses. The oscillator is cut in the middle spring for partitioning. Here, two springs with one mass between them are calculated. This model can be used to simulate the left partition as well as the right partition, as they are symmetric.

+ +
+ + diff --git a/oscillator/fmi/fmu/README.md b/oscillator/fmi/fmu/README.md new file mode 100644 index 000000000..6f837c3cb --- /dev/null +++ b/oscillator/fmi/fmu/README.md @@ -0,0 +1,19 @@ +# Build instruction + +To build the Oscillator FMU you need [CMake](https://cmake.org/) ≥ 3.16 and a supported [build tool](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) e.g. Visual Studio ≥ 2013 , Xcode or make. + +Generate the build files with the following commands: + +```bash +mkdir build +cd build +cmake -DFMI_TYPE=CS -DFMI_VERSION=3 .. +make +cp ./Oscillator.fmu ../.. +``` + +Instead of `make`, you can also use your preferred build tool to create the FMU. + +## License + +The FMU model `Oscillator.fmu` used for this tutorial is based on the [Reference-FMUs](https://github.com/modelica/Reference-FMUs) from the Modelica Association Project "FMI", which are released under the [2-Clause BSD License](https://github.com/precice/tutorials/blob/master/oscillator/fmi/fmu/thirdparty/LICENSE.txt). diff --git a/oscillator/fmi/fmu/include/FMI.h b/oscillator/fmi/fmu/include/FMI.h new file mode 100644 index 000000000..33eed8279 --- /dev/null +++ b/oscillator/fmi/fmu/include/FMI.h @@ -0,0 +1,160 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + +#include +#include + +#ifndef FMI_MAX_MESSAGE_LENGTH +#define FMI_MAX_MESSAGE_LENGTH 4096 +#endif + +#ifndef FMI_STATIC +#define FMI_STATIC +#endif + +typedef enum { + FMIOK, + FMIWarning, + FMIDiscard, + FMIError, + FMIFatal, + FMIPending +} FMIStatus; + +typedef enum { + + // FMI 3.0 variable types + FMIFloat32Type, + FMIDiscreteFloat32Type, + FMIFloat64Type, + FMIDiscreteFloat64Type, + FMIInt8Type, + FMIUInt8Type, + FMIInt16Type, + FMIUInt16Type, + FMIInt32Type, + FMIUInt32Type, + FMIInt64Type, + FMIUInt64Type, + FMIBooleanType, + FMIStringType, + FMIBinaryType, + FMIClockType, + + // Aliases for FMI 1.0 and 2.0 + FMIRealType = FMIFloat64Type, + FMIDiscreteRealType = FMIDiscreteFloat64Type, + FMIIntegerType = FMIInt32Type, + +} FMIVariableType; + +typedef enum { + FMIVersion1 = 1, + FMIVersion2 = 2, + FMIVersion3 = 3 +} FMIVersion; + +typedef enum { + FMIModelExchange, + FMICoSimulation, + FMIScheduledExecution +} FMIInterfaceType; + +typedef enum { + FMI2StartAndEndState = 1 << 0, + FMI2InstantiatedState = 1 << 1, + FMI2InitializationModeState = 1 << 2, + + // model exchange states + FMI2EventModeState = 1 << 3, + FMI2ContinuousTimeModeState = 1 << 4, + + // co-simulation states + FMI2StepCompleteState = 1 << 5, + FMI2StepInProgressState = 1 << 6, + FMI2StepFailedState = 1 << 7, + FMI2StepCanceledState = 1 << 8, + + FMI2TerminatedState = 1 << 9, + FMI2ErrorState = 1 << 10, + FMI2FatalState = 1 << 11, +} FMI2State; + +typedef unsigned int FMIValueReference; + +typedef struct FMIInstance_ FMIInstance; + +typedef struct FMI2Functions_ FMI2Functions; + +typedef struct FMI3Functions_ FMI3Functions; + +typedef void FMILogFunctionCall(FMIInstance *instance, FMIStatus status, const char *message, ...); + +typedef void FMILogMessage(FMIInstance *instance, FMIStatus status, const char *category, const char *message); + +struct FMIInstance_ { + + FMI2Functions *fmi2Functions; + FMI3Functions *fmi3Functions; + +#ifdef _WIN32 + HMODULE libraryHandle; +#else + void *libraryHandle; +#endif + + void *userData; + + FMILogMessage * logMessage; + FMILogFunctionCall *logFunctionCall; + + double time; + + char *buf1; + char *buf2; + + size_t bufsize1; + size_t bufsize2; + + void *component; + + const char *name; + + bool logFMICalls; + + FMI2State state; + + FMIStatus status; + + FMIVersion fmiVersion; + + FMIInterfaceType interfaceType; +}; + +FMI_STATIC FMIInstance *FMICreateInstance(const char *instanceName, const char *libraryPath, FMILogMessage *logMessage, FMILogFunctionCall *logFunctionCall); + +FMI_STATIC void FMIFreeInstance(FMIInstance *instance); + +FMI_STATIC const char *FMIValueReferencesToString(FMIInstance *instance, const FMIValueReference vr[], size_t nvr); + +FMI_STATIC const char *FMIValuesToString(FMIInstance *instance, size_t vValues, const size_t sizes[], const void *values, FMIVariableType variableType); + +FMI_STATIC FMIStatus FMIURIToPath(const char *uri, char *path, const size_t pathLength); + +FMI_STATIC FMIStatus FMIPathToURI(const char *path, char *uri, const size_t uriLength); + +FMI_STATIC FMIStatus FMIPlatformBinaryPath(const char *unzipdir, const char *modelIdentifier, FMIVersion fmiVersion, char *platformBinaryPath, size_t size); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/oscillator/fmi/fmu/include/FMI2.h b/oscillator/fmi/fmu/include/FMI2.h new file mode 100644 index 000000000..5deb36a47 --- /dev/null +++ b/oscillator/fmi/fmu/include/FMI2.h @@ -0,0 +1,219 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "FMI.h" +#include "fmi2Functions.h" + +struct FMI2Functions_ { + + fmi2CallbackFunctions callbacks; + fmi2EventInfo eventInfo; + + /*************************************************** + Common Functions for FMI 2.0 + ****************************************************/ + + /* required functions */ + fmi2GetTypesPlatformTYPE * fmi2GetTypesPlatform; + fmi2GetVersionTYPE * fmi2GetVersion; + fmi2SetDebugLoggingTYPE * fmi2SetDebugLogging; + fmi2InstantiateTYPE * fmi2Instantiate; + fmi2FreeInstanceTYPE * fmi2FreeInstance; + fmi2SetupExperimentTYPE * fmi2SetupExperiment; + fmi2EnterInitializationModeTYPE *fmi2EnterInitializationMode; + fmi2ExitInitializationModeTYPE * fmi2ExitInitializationMode; + fmi2TerminateTYPE * fmi2Terminate; + fmi2ResetTYPE * fmi2Reset; + fmi2GetRealTYPE * fmi2GetReal; + fmi2GetIntegerTYPE * fmi2GetInteger; + fmi2GetBooleanTYPE * fmi2GetBoolean; + fmi2GetStringTYPE * fmi2GetString; + fmi2SetRealTYPE * fmi2SetReal; + fmi2SetIntegerTYPE * fmi2SetInteger; + fmi2SetBooleanTYPE * fmi2SetBoolean; + fmi2SetStringTYPE * fmi2SetString; + + /* optional functions */ + fmi2GetFMUstateTYPE * fmi2GetFMUstate; + fmi2SetFMUstateTYPE * fmi2SetFMUstate; + fmi2FreeFMUstateTYPE * fmi2FreeFMUstate; + fmi2SerializedFMUstateSizeTYPE * fmi2SerializedFMUstateSize; + fmi2SerializeFMUstateTYPE * fmi2SerializeFMUstate; + fmi2DeSerializeFMUstateTYPE * fmi2DeSerializeFMUstate; + fmi2GetDirectionalDerivativeTYPE *fmi2GetDirectionalDerivative; + + /*************************************************** + Functions for FMI 2.0 for Model Exchange + ****************************************************/ + + fmi2EnterEventModeTYPE * fmi2EnterEventMode; + fmi2NewDiscreteStatesTYPE * fmi2NewDiscreteStates; + fmi2EnterContinuousTimeModeTYPE * fmi2EnterContinuousTimeMode; + fmi2CompletedIntegratorStepTYPE * fmi2CompletedIntegratorStep; + fmi2SetTimeTYPE * fmi2SetTime; + fmi2SetContinuousStatesTYPE * fmi2SetContinuousStates; + fmi2GetDerivativesTYPE * fmi2GetDerivatives; + fmi2GetEventIndicatorsTYPE * fmi2GetEventIndicators; + fmi2GetContinuousStatesTYPE * fmi2GetContinuousStates; + fmi2GetNominalsOfContinuousStatesTYPE *fmi2GetNominalsOfContinuousStates; + + /*************************************************** + Functions for FMI 2.0 for Co-Simulation + ****************************************************/ + + fmi2SetRealInputDerivativesTYPE * fmi2SetRealInputDerivatives; + fmi2GetRealOutputDerivativesTYPE *fmi2GetRealOutputDerivatives; + fmi2DoStepTYPE * fmi2DoStep; + fmi2CancelStepTYPE * fmi2CancelStep; + fmi2GetStatusTYPE * fmi2GetStatus; + fmi2GetRealStatusTYPE * fmi2GetRealStatus; + fmi2GetIntegerStatusTYPE * fmi2GetIntegerStatus; + fmi2GetBooleanStatusTYPE * fmi2GetBooleanStatus; + fmi2GetStringStatusTYPE * fmi2GetStringStatus; +}; + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +FMI_STATIC const char *FMI2GetTypesPlatform(FMIInstance *instance); + +FMI_STATIC const char *FMI2GetVersion(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2SetDebugLogging(FMIInstance *instance, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]); + +FMI_STATIC FMIStatus FMI2Instantiate(FMIInstance *instance, const char *fmuResourceLocation, fmi2Type fmuType, fmi2String fmuGUID, + fmi2Boolean visible, fmi2Boolean loggingOn); + +FMI_STATIC void FMI2FreeInstance(FMIInstance *instance); + +/* Enter and exit initialization mode, terminate and reset */ +FMI_STATIC FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); + +FMI_STATIC FMIStatus FMI2EnterInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2ExitInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2Terminate(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2Reset(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); + +/* Getting and setting variable values */ +FMI_STATIC FMIStatus FMI2GetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2GetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); + +FMI_STATIC FMIStatus FMI2GetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); + +FMI_STATIC FMIStatus FMI2GetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); + +FMI_STATIC FMIStatus FMI2SetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2SetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); + +FMI_STATIC FMIStatus FMI2SetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); + +FMI_STATIC FMIStatus FMI2SetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); + +/* Getting and setting the internal FMU state */ +FMI_STATIC FMIStatus FMI2GetFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate); + +FMI_STATIC FMIStatus FMI2SetFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate); + +FMI_STATIC FMIStatus FMI2FreeFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate); + +FMI_STATIC FMIStatus FMI2SerializedFMUstateSize(FMIInstance *instance, fmi2FMUstate FMUstate, size_t *size); + +FMI_STATIC FMIStatus FMI2SerializeFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size); + +FMI_STATIC FMIStatus FMI2DeSerializeFMUstate(FMIInstance *instance, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate); + +/* Getting partial derivatives */ +FMI_STATIC FMIStatus FMI2GetDirectionalDerivative(FMIInstance * instance, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]); + +/*************************************************** +Types for Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMI_STATIC FMIStatus FMI2EnterEventMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2NewDiscreteStates(FMIInstance *instance, fmi2EventInfo *eventInfo); + +FMI_STATIC FMIStatus FMI2EnterContinuousTimeMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2CompletedIntegratorStep(FMIInstance *instance, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +FMI_STATIC FMIStatus FMI2SetTime(FMIInstance *instance, fmi2Real time); + +FMI_STATIC FMIStatus FMI2SetContinuousStates(FMIInstance *instance, const fmi2Real x[], size_t nx); + +/* Evaluation of the model equations */ +FMI_STATIC FMIStatus FMI2GetDerivatives(FMIInstance *instance, fmi2Real derivatives[], size_t nx); + +FMI_STATIC FMIStatus FMI2GetEventIndicators(FMIInstance *instance, fmi2Real eventIndicators[], size_t ni); + +FMI_STATIC FMIStatus FMI2GetContinuousStates(FMIInstance *instance, fmi2Real x[], size_t nx); + +FMI_STATIC FMIStatus FMI2GetNominalsOfContinuousStates(FMIInstance *instance, fmi2Real x_nominal[], size_t nx); + +/*************************************************** +Types for Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMI_STATIC FMIStatus FMI2SetRealInputDerivatives(FMIInstance * instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2GetRealOutputDerivatives(FMIInstance * instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2DoStep(FMIInstance *instance, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint); + +FMI_STATIC FMIStatus FMI2CancelStep(FMIInstance *instance); + +/* Inquire slave status */ +FMI_STATIC FMIStatus FMI2GetStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Status *value); + +FMI_STATIC FMIStatus FMI2GetRealStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Real *value); + +FMI_STATIC FMIStatus FMI2GetIntegerStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Integer *value); + +FMI_STATIC FMIStatus FMI2GetBooleanStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Boolean *value); + +FMI_STATIC FMIStatus FMI2GetStringStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2String *value); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/oscillator/fmi/fmu/include/FMI3.h b/oscillator/fmi/fmu/include/FMI3.h new file mode 100644 index 000000000..8af3ec956 --- /dev/null +++ b/oscillator/fmi/fmu/include/FMI3.h @@ -0,0 +1,560 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "FMI.h" +#include "fmi3FunctionTypes.h" + +struct FMI3Functions_ { + + fmi3Boolean eventModeUsed; + + fmi3Boolean discreteStatesNeedUpdate; + fmi3Boolean terminateSimulation; + fmi3Boolean nominalsOfContinuousStatesChanged; + fmi3Boolean valuesOfContinuousStatesChanged; + fmi3Boolean nextEventTimeDefined; + fmi3Float64 nextEventTime; + + /*************************************************** + Common Functions for FMI 3.0 + ****************************************************/ + + /* Inquire version numbers and set debug logging */ + fmi3GetVersionTYPE * fmi3GetVersion; + fmi3SetDebugLoggingTYPE *fmi3SetDebugLogging; + + /* Creation and destruction of FMU instances */ + fmi3InstantiateModelExchangeTYPE * fmi3InstantiateModelExchange; + fmi3InstantiateCoSimulationTYPE * fmi3InstantiateCoSimulation; + fmi3InstantiateScheduledExecutionTYPE *fmi3InstantiateScheduledExecution; + fmi3FreeInstanceTYPE * fmi3FreeInstance; + + /* Enter and exit initialization mode, terminate and reset */ + fmi3EnterInitializationModeTYPE *fmi3EnterInitializationMode; + fmi3ExitInitializationModeTYPE * fmi3ExitInitializationMode; + fmi3EnterEventModeTYPE * fmi3EnterEventMode; + fmi3TerminateTYPE * fmi3Terminate; + fmi3ResetTYPE * fmi3Reset; + + /* Getting and setting variable values */ + fmi3GetFloat32TYPE *fmi3GetFloat32; + fmi3GetFloat64TYPE *fmi3GetFloat64; + fmi3GetInt8TYPE * fmi3GetInt8; + fmi3GetUInt8TYPE * fmi3GetUInt8; + fmi3GetInt16TYPE * fmi3GetInt16; + fmi3GetUInt16TYPE * fmi3GetUInt16; + fmi3GetInt32TYPE * fmi3GetInt32; + fmi3GetUInt32TYPE * fmi3GetUInt32; + fmi3GetInt64TYPE * fmi3GetInt64; + fmi3GetUInt64TYPE * fmi3GetUInt64; + fmi3GetBooleanTYPE *fmi3GetBoolean; + fmi3GetStringTYPE * fmi3GetString; + fmi3GetBinaryTYPE * fmi3GetBinary; + fmi3GetClockTYPE * fmi3GetClock; + fmi3SetFloat32TYPE *fmi3SetFloat32; + fmi3SetFloat64TYPE *fmi3SetFloat64; + fmi3SetInt8TYPE * fmi3SetInt8; + fmi3SetUInt8TYPE * fmi3SetUInt8; + fmi3SetInt16TYPE * fmi3SetInt16; + fmi3SetUInt16TYPE * fmi3SetUInt16; + fmi3SetInt32TYPE * fmi3SetInt32; + fmi3SetUInt32TYPE * fmi3SetUInt32; + fmi3SetInt64TYPE * fmi3SetInt64; + fmi3SetUInt64TYPE * fmi3SetUInt64; + fmi3SetBooleanTYPE *fmi3SetBoolean; + fmi3SetStringTYPE * fmi3SetString; + fmi3SetBinaryTYPE * fmi3SetBinary; + fmi3SetClockTYPE * fmi3SetClock; + + /* Getting Variable Dependency Information */ + fmi3GetNumberOfVariableDependenciesTYPE *fmi3GetNumberOfVariableDependencies; + fmi3GetVariableDependenciesTYPE * fmi3GetVariableDependencies; + + /* Getting and setting the internal FMU state */ + fmi3GetFMUStateTYPE * fmi3GetFMUState; + fmi3SetFMUStateTYPE * fmi3SetFMUState; + fmi3FreeFMUStateTYPE * fmi3FreeFMUState; + fmi3SerializedFMUStateSizeTYPE *fmi3SerializedFMUStateSize; + fmi3SerializeFMUStateTYPE * fmi3SerializeFMUState; + fmi3DeserializeFMUStateTYPE * fmi3DeserializeFMUState; + + /* Getting partial derivatives */ + fmi3GetDirectionalDerivativeTYPE *fmi3GetDirectionalDerivative; + fmi3GetAdjointDerivativeTYPE * fmi3GetAdjointDerivative; + + /* Entering and exiting the Configuration or Reconfiguration Mode */ + fmi3EnterConfigurationModeTYPE *fmi3EnterConfigurationMode; + fmi3ExitConfigurationModeTYPE * fmi3ExitConfigurationMode; + + /* Clock related functions */ + fmi3GetIntervalDecimalTYPE * fmi3GetIntervalDecimal; + fmi3GetIntervalFractionTYPE * fmi3GetIntervalFraction; + fmi3GetShiftDecimalTYPE * fmi3GetShiftDecimal; + fmi3GetShiftFractionTYPE * fmi3GetShiftFraction; + fmi3SetIntervalDecimalTYPE * fmi3SetIntervalDecimal; + fmi3SetIntervalFractionTYPE * fmi3SetIntervalFraction; + fmi3SetShiftDecimalTYPE * fmi3SetShiftDecimal; + fmi3SetShiftFractionTYPE * fmi3SetShiftFraction; + fmi3EvaluateDiscreteStatesTYPE *fmi3EvaluateDiscreteStates; + fmi3UpdateDiscreteStatesTYPE * fmi3UpdateDiscreteStates; + + /*************************************************** + Functions for Model Exchange + ****************************************************/ + + fmi3EnterContinuousTimeModeTYPE *fmi3EnterContinuousTimeMode; + fmi3CompletedIntegratorStepTYPE *fmi3CompletedIntegratorStep; + + /* Providing independent variables and re-initialization of caching */ + fmi3SetTimeTYPE * fmi3SetTime; + fmi3SetContinuousStatesTYPE *fmi3SetContinuousStates; + + /* Evaluation of the model equations */ + fmi3GetContinuousStateDerivativesTYPE *fmi3GetContinuousStateDerivatives; + fmi3GetEventIndicatorsTYPE * fmi3GetEventIndicators; + fmi3GetContinuousStatesTYPE * fmi3GetContinuousStates; + fmi3GetNominalsOfContinuousStatesTYPE *fmi3GetNominalsOfContinuousStates; + fmi3GetNumberOfEventIndicatorsTYPE * fmi3GetNumberOfEventIndicators; + fmi3GetNumberOfContinuousStatesTYPE * fmi3GetNumberOfContinuousStates; + + /*************************************************** + Functions for FMI 3.0 for Co-Simulation + ****************************************************/ + + fmi3EnterStepModeTYPE * fmi3EnterStepMode; + fmi3GetOutputDerivativesTYPE *fmi3GetOutputDerivatives; + fmi3DoStepTYPE * fmi3DoStep; + + /*************************************************** + Functions for Scheduled Execution + ****************************************************/ + + fmi3ActivateModelPartitionTYPE *fmi3ActivateModelPartition; +}; + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +FMI_STATIC const char *FMI3GetVersion(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3SetDebugLogging(FMIInstance * instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]); + +/* Creation and destruction of FMU instances and setting debug status */ +FMI_STATIC FMIStatus FMI3InstantiateModelExchange( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn); + +FMI_STATIC FMIStatus FMI3InstantiateCoSimulation( + FMIInstance * instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3IntermediateUpdateCallback intermediateUpdate); + +FMI_STATIC FMIStatus FMI3InstantiateScheduledExecution( + FMIInstance * instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption); + +FMI_STATIC FMIStatus FMI3FreeInstance(FMIInstance *instance); + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +FMI_STATIC FMIStatus FMI3EnterInitializationMode(FMIInstance *instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime); + +FMI_STATIC FMIStatus FMI3ExitInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3EnterEventMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3Terminate(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3Reset(FMIInstance *instance); + +/* Getting and setting variable values */ +FMI_STATIC FMIStatus FMI3GetFloat32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetFloat64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetBoolean(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetString(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetBinary(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t sizes[], + fmi3Binary values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetClock(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]); + +FMI_STATIC FMIStatus FMI3SetFloat32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetFloat64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetBoolean(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetString(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetBinary(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t sizes[], + const fmi3Binary values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetClock(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]); + +/* Getting Variable Dependency Information */ +FMI_STATIC FMIStatus FMI3GetNumberOfVariableDependencies(FMIInstance * instance, + fmi3ValueReference valueReference, + size_t * nDependencies); + +FMI_STATIC FMIStatus FMI3GetVariableDependencies(FMIInstance * instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies); + +/* Getting and setting the internal FMU state */ +FMI_STATIC FMIStatus FMI3GetFMUState(FMIInstance *instance, fmi3FMUState *FMUState); + +FMI_STATIC FMIStatus FMI3SetFMUState(FMIInstance *instance, fmi3FMUState FMUState); + +FMI_STATIC FMIStatus FMI3FreeFMUState(FMIInstance *instance, fmi3FMUState *FMUState); + +FMI_STATIC FMIStatus FMI3SerializedFMUStateSize(FMIInstance *instance, + fmi3FMUState FMUState, + size_t * size); + +FMI_STATIC FMIStatus FMI3SerializeFMUState(FMIInstance *instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size); + +FMI_STATIC FMIStatus FMI3DeserializeFMUState(FMIInstance * instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState * FMUState); + +/* Getting partial derivatives */ +FMI_STATIC FMIStatus FMI3GetDirectionalDerivative(FMIInstance * instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); + +FMI_STATIC FMIStatus FMI3GetAdjointDerivative(FMIInstance * instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMI_STATIC FMIStatus FMI3EnterConfigurationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3ExitConfigurationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3GetIntervalDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]); + +FMI_STATIC FMIStatus FMI3GetIntervalFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]); + +FMI_STATIC FMIStatus FMI3GetShiftDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]); + +FMI_STATIC FMIStatus FMI3GetShiftFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3SetIntervalDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]); + +FMI_STATIC FMIStatus FMI3SetIntervalFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3SetShiftDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]); + +FMI_STATIC FMIStatus FMI3SetShiftFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3EvaluateDiscreteStates(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3UpdateDiscreteStates(FMIInstance *instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime); + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +FMI_STATIC FMIStatus FMI3EnterContinuousTimeMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3CompletedIntegratorStep(FMIInstance *instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +FMI_STATIC FMIStatus FMI3SetTime(FMIInstance *instance, fmi3Float64 time); + +FMI_STATIC FMIStatus FMI3SetContinuousStates(FMIInstance * instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates); + +/* Evaluation of the model equations */ +FMI_STATIC FMIStatus FMI3GetContinuousStateDerivatives(FMIInstance *instance, + fmi3Float64 derivatives[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetEventIndicators(FMIInstance *instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators); + +FMI_STATIC FMIStatus FMI3GetContinuousStates(FMIInstance *instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetNominalsOfContinuousStates(FMIInstance *instance, + fmi3Float64 nominals[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetNumberOfEventIndicators(FMIInstance *instance, + size_t * nEventIndicators); + +FMI_STATIC FMIStatus FMI3GetNumberOfContinuousStates(FMIInstance *instance, + size_t * nContinuousStates); + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +FMI_STATIC FMIStatus FMI3EnterStepMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3GetOutputDerivatives(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3DoStep(FMIInstance *instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime); + +/*************************************************** +Functions for Scheduled Execution +****************************************************/ + +FMI_STATIC FMIStatus FMI3ActivateModelPartition(FMIInstance * instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/oscillator/fmi/fmu/include/cosimulation.h b/oscillator/fmi/fmu/include/cosimulation.h new file mode 100644 index 000000000..291f38618 --- /dev/null +++ b/oscillator/fmi/fmu/include/cosimulation.h @@ -0,0 +1,8 @@ +#pragma once + +#include "model.h" + +#define EPSILON (FIXED_SOLVER_STEP * 1e-6) + +void doFixedStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent); +void doAlphaStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent); diff --git a/oscillator/fmi/fmu/include/fmi2FunctionTypes.h b/oscillator/fmi/fmu/include/fmi2FunctionTypes.h new file mode 100644 index 000000000..916a6edee --- /dev/null +++ b/oscillator/fmi/fmu/include/fmi2FunctionTypes.h @@ -0,0 +1,266 @@ +#ifndef fmi2FunctionTypes_h +#define fmi2FunctionTypes_h + +#include "fmi2TypesPlatform.h" + +/* This header file must be utilized when compiling an FMU or an FMI master. + It declares data and function types for FMI 2.0.1 + + Revisions: + - Sep. 30, 2019: License changed to 2-clause BSD License (without extensions) + - Jul. 5, 2019: Remove const modifier from fields of fmi2CallbackFunctions (#216) + - Sep. 6, 2018: Parameter names added to function prototypes + - Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Apr. 3, 2014: Added #include for size_t definition + - Mar. 27, 2014: Added #include "fmiTypesPlatform.h" (#179) + - Mar. 26, 2014: Introduced function argument "void" for the functions (#171) + fmiGetTypesPlatformTYPE and fmiGetVersionTYPE + - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: + fmiInstantiateModelTYPE , fmiInstantiateSlaveTYPE -> fmiInstantiateTYPE + fmiFreeModelInstanceTYPE, fmiFreeSlaveInstanceTYPE -> fmiFreeInstanceTYPE + fmiEnterModelInitializationModeTYPE, fmiEnterSlaveInitializationModeTYPE -> fmiEnterInitializationModeTYPE + fmiExitModelInitializationModeTYPE , fmiExitSlaveInitializationModeTYPE -> fmiExitInitializationModeTYPE + fmiTerminateModelTYPE , fmiTerminateSlaveTYPE -> fmiTerminate + fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) + Functions renamed + fmiUpdateDiscreteStatesTYPE -> fmiNewDiscreteStatesTYPE + Renamed elements of the enumeration fmiEventInfo + upcomingTimeEvent -> nextEventTimeDefined // due to generic naming scheme: varDefined + var + newUpdateDiscreteStatesNeeded -> newDiscreteStatesNeeded; + - June 13, 2013: Changed type fmiEventInfo + Functions removed: + fmiInitializeModelTYPE + fmiEventUpdateTYPE + fmiCompletedEventIterationTYPE + fmiInitializeSlaveTYPE + Functions added: + fmiEnterModelInitializationModeTYPE + fmiExitModelInitializationModeTYPE + fmiEnterEventModeTYPE + fmiUpdateDiscreteStatesTYPE + fmiEnterContinuousTimeModeTYPE + fmiEnterSlaveInitializationModeTYPE; + fmiExitSlaveInitializationModeTYPE; + - Feb. 17, 2013: Added third argument to fmiCompletedIntegratorStepTYPE + Changed function name "fmiTerminateType" to "fmiTerminateModelType" (due to #113) + Changed function name "fmiGetNominalContinuousStateTYPE" to + "fmiGetNominalsOfContinuousStatesTYPE" + Removed fmiGetStateValueReferencesTYPE. + - Nov. 14, 2011: First public Version + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* make sure all compiler use the same alignment policies for structures */ +#if defined _MSC_VER || defined __GNUC__ +#pragma pack(push, 8) +#endif + +/* Include stddef.h, in order that size_t etc. is defined */ +#include + +/* Type definitions */ +typedef enum { + fmi2OK, + fmi2Warning, + fmi2Discard, + fmi2Error, + fmi2Fatal, + fmi2Pending +} fmi2Status; + +typedef enum { + fmi2ModelExchange, + fmi2CoSimulation +} fmi2Type; + +typedef enum { + fmi2DoStepStatus, + fmi2PendingStatus, + fmi2LastSuccessfulTime, + fmi2Terminated +} fmi2StatusKind; + +typedef void (*fmi2CallbackLogger)(fmi2ComponentEnvironment componentEnvironment, + fmi2String instanceName, + fmi2Status status, + fmi2String category, + fmi2String message, + ...); +typedef void *(*fmi2CallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmi2CallbackFreeMemory)(void *obj); +typedef void (*fmi2StepFinished)(fmi2ComponentEnvironment componentEnvironment, + fmi2Status status); + +typedef struct { + fmi2CallbackLogger logger; + fmi2CallbackAllocateMemory allocateMemory; + fmi2CallbackFreeMemory freeMemory; + fmi2StepFinished stepFinished; + fmi2ComponentEnvironment componentEnvironment; +} fmi2CallbackFunctions; + +typedef struct { + fmi2Boolean newDiscreteStatesNeeded; + fmi2Boolean terminateSimulation; + fmi2Boolean nominalsOfContinuousStatesChanged; + fmi2Boolean valuesOfContinuousStatesChanged; + fmi2Boolean nextEventTimeDefined; + fmi2Real nextEventTime; +} fmi2EventInfo; + +/* reset alignment policy to the one set before reading this file */ +#if defined _MSC_VER || defined __GNUC__ +#pragma pack(pop) +#endif + +/* Define fmi2 function pointer types to simplify dynamic loading */ + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +typedef const char *fmi2GetTypesPlatformTYPE(void); +typedef const char *fmi2GetVersionTYPE(void); +typedef fmi2Status fmi2SetDebugLoggingTYPE(fmi2Component c, + fmi2Boolean loggingOn, + size_t nCategories, + const fmi2String categories[]); + +/* Creation and destruction of FMU instances and setting debug status */ +typedef fmi2Component fmi2InstantiateTYPE(fmi2String instanceName, + fmi2Type fmuType, + fmi2String fmuGUID, + fmi2String fmuResourceLocation, + const fmi2CallbackFunctions *functions, + fmi2Boolean visible, + fmi2Boolean loggingOn); +typedef void fmi2FreeInstanceTYPE(fmi2Component c); + +/* Enter and exit initialization mode, terminate and reset */ +typedef fmi2Status fmi2SetupExperimentTYPE(fmi2Component c, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); +typedef fmi2Status fmi2EnterInitializationModeTYPE(fmi2Component c); +typedef fmi2Status fmi2ExitInitializationModeTYPE(fmi2Component c); +typedef fmi2Status fmi2TerminateTYPE(fmi2Component c); +typedef fmi2Status fmi2ResetTYPE(fmi2Component c); + +/* Getting and setting variable values */ +typedef fmi2Status fmi2GetRealTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); +typedef fmi2Status fmi2GetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); +typedef fmi2Status fmi2GetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); +typedef fmi2Status fmi2GetStringTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); + +typedef fmi2Status fmi2SetRealTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); +typedef fmi2Status fmi2SetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); +typedef fmi2Status fmi2SetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); +typedef fmi2Status fmi2SetStringTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); + +/* Getting and setting the internal FMU state */ +typedef fmi2Status fmi2GetFMUstateTYPE(fmi2Component c, fmi2FMUstate *FMUstate); +typedef fmi2Status fmi2SetFMUstateTYPE(fmi2Component c, fmi2FMUstate FMUstate); +typedef fmi2Status fmi2FreeFMUstateTYPE(fmi2Component c, fmi2FMUstate *FMUstate); +typedef fmi2Status fmi2SerializedFMUstateSizeTYPE(fmi2Component c, fmi2FMUstate FMUstate, size_t *size); +typedef fmi2Status fmi2SerializeFMUstateTYPE(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte[], size_t size); +typedef fmi2Status fmi2DeSerializeFMUstateTYPE(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate); + +/* Getting partial derivatives */ +typedef fmi2Status fmi2GetDirectionalDerivativeTYPE(fmi2Component c, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]); + +/*************************************************** +Types for Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +typedef fmi2Status fmi2EnterEventModeTYPE(fmi2Component c); +typedef fmi2Status fmi2NewDiscreteStatesTYPE(fmi2Component c, fmi2EventInfo *fmi2eventInfo); +typedef fmi2Status fmi2EnterContinuousTimeModeTYPE(fmi2Component c); +typedef fmi2Status fmi2CompletedIntegratorStepTYPE(fmi2Component c, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean * enterEventMode, + fmi2Boolean * terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +typedef fmi2Status fmi2SetTimeTYPE(fmi2Component c, fmi2Real time); +typedef fmi2Status fmi2SetContinuousStatesTYPE(fmi2Component c, const fmi2Real x[], size_t nx); + +/* Evaluation of the model equations */ +typedef fmi2Status fmi2GetDerivativesTYPE(fmi2Component c, fmi2Real derivatives[], size_t nx); +typedef fmi2Status fmi2GetEventIndicatorsTYPE(fmi2Component c, fmi2Real eventIndicators[], size_t ni); +typedef fmi2Status fmi2GetContinuousStatesTYPE(fmi2Component c, fmi2Real x[], size_t nx); +typedef fmi2Status fmi2GetNominalsOfContinuousStatesTYPE(fmi2Component c, fmi2Real x_nominal[], size_t nx); + +/*************************************************** +Types for Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +typedef fmi2Status fmi2SetRealInputDerivativesTYPE(fmi2Component c, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]); +typedef fmi2Status fmi2GetRealOutputDerivativesTYPE(fmi2Component c, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]); +typedef fmi2Status fmi2DoStepTYPE(fmi2Component c, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint); +typedef fmi2Status fmi2CancelStepTYPE(fmi2Component c); + +/* Inquire slave status */ +typedef fmi2Status fmi2GetStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Status *value); +typedef fmi2Status fmi2GetRealStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Real *value); +typedef fmi2Status fmi2GetIntegerStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value); +typedef fmi2Status fmi2GetBooleanStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value); +typedef fmi2Status fmi2GetStringStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2String *value); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi2FunctionTypes_h */ diff --git a/oscillator/fmi/fmu/include/fmi2Functions.h b/oscillator/fmi/fmu/include/fmi2Functions.h new file mode 100644 index 000000000..dbdb03ee2 --- /dev/null +++ b/oscillator/fmi/fmu/include/fmi2Functions.h @@ -0,0 +1,321 @@ +#ifndef fmi2Functions_h +#define fmi2Functions_h + +/* This header file must be utilized when compiling a FMU. + It defines all functions of the + FMI 2.0.1 Model Exchange and Co-Simulation Interface. + + In order to have unique function names even if several FMUs + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by "FMI2_FUNCTION_PREFIX". + Therefore, the typical usage is: + + #define FMI2_FUNCTION_PREFIX MyModel_ + #include "fmi2Functions.h" + + As a result, a function that is defined as "fmi2GetDerivatives" in this header file, + is actually getting the name "MyModel_fmi2GetDerivatives". + + This only holds if the FMU is shipped in C source code, or is compiled in a + static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function + names are used and "FMI2_FUNCTION_PREFIX" must not be defined. + + Revisions: + - Sep. 29, 2019: License changed to 2-clause BSD License (without extensions) + - Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Mar. 26, 2014: FMI_Export set to empty value if FMI_Export and FMI_FUNCTION_PREFIX + are not defined (#173) + - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: + fmiInstantiateModel , fmiInstantiateSlave -> fmiInstantiate + fmiFreeModelInstance, fmiFreeSlaveInstance -> fmiFreeInstance + fmiEnterModelInitializationMode, fmiEnterSlaveInitializationMode -> fmiEnterInitializationMode + fmiExitModelInitializationMode , fmiExitSlaveInitializationMode -> fmiExitInitializationMode + fmiTerminateModel, fmiTerminateSlave -> fmiTerminate + fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) + Functions renamed: + fmiUpdateDiscreteStates -> fmiNewDiscreteStates + - June 13, 2013: Functions removed: + fmiInitializeModel + fmiEventUpdate + fmiCompletedEventIteration + fmiInitializeSlave + Functions added: + fmiEnterModelInitializationMode + fmiExitModelInitializationMode + fmiEnterEventMode + fmiUpdateDiscreteStates + fmiEnterContinuousTimeMode + fmiEnterSlaveInitializationMode; + fmiExitSlaveInitializationMode; + - Feb. 17, 2013: Portability improvements: + o DllExport changed to FMI_Export + o FUNCTION_PREFIX changed to FMI_FUNCTION_PREFIX + o Allow undefined FMI_FUNCTION_PREFIX (meaning no prefix is used) + Changed function name "fmiTerminate" to "fmiTerminateModel" (due to #113) + Changed function name "fmiGetNominalContinuousState" to + "fmiGetNominalsOfContinuousStates" + Removed fmiGetStateValueReferences. + - Nov. 14, 2011: Adapted to FMI 2.0: + o Split into two files (fmiFunctions.h, fmiTypes.h) in order + that code that dynamically loads an FMU can directly + utilize the header files). + o Added C++ encapsulation of C-part, in order that the header + file can be directly utilized in C++ code. + o fmiCallbackFunctions is passed as pointer to fmiInstantiateXXX + o stepFinished within fmiCallbackFunctions has as first + argument "fmiComponentEnvironment" and not "fmiComponent". + o New functions to get and set the complete FMU state + and to compute partial derivatives. + - Nov. 4, 2010: Adapted to specification text: + o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform + o fmiInstantiateSlave: Argument GUID replaced by fmuGUID + Argument mimetype replaced by mimeType + o tabs replaced by spaces + - Oct. 16, 2010: Functions for FMI for Co-simulation added + - Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27) + (by M. Otter, DLR) + Added WIN32 pragma to define the struct layout (ticket #34) + (by J. Mauss, QTronic) + - Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize + Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion + Renamed macro fmiModelFunctionsVersion to fmiVersion + Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel + (by J. Mauss, QTronic) + - Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR). + - Dez. 14, 2009: Added eventInfo to meInitialize and added + meGetNominalContinuousStates (by Martin Otter, DLR) + - Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion) + (by A. Junghanns, QTronic) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + meInquireModelTypesVersion -> meGetModelTypesPlatform + meInquireModelFunctionsVersion -> meGetModelFunctionsVersion + meSetStates -> meSetContinuousStates + meGetStates -> meGetContinuousStates + removal of meInitializeModelClass + removal of meGetTime + change of arguments of meInstantiateModel + change of arguments of meCompletedIntegratorStep + (by Martin Otter, DLR): + - July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR). + - March 2, 2009: Changed function definitions according to the last design + meeting with additional improvements (by Martin Otter, DLR). + - Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim). + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fmi2FunctionTypes.h" +#include "fmi2TypesPlatform.h" + +/* + Export FMI2 API functions on Windows and under GCC. + If custom linking is desired then the FMI2_Export must be + defined before including this file. For instance, + it may be set to __declspec(dllimport). +*/ +#if !defined(FMI2_Export) +#if !defined(FMI2_FUNCTION_PREFIX) +#if defined _WIN32 || defined __CYGWIN__ +/* Note: both gcc & MSVC on Windows support this syntax. */ +#define FMI2_Export __declspec(dllexport) +#else +#if __GNUC__ >= 4 +#define FMI2_Export __attribute__((visibility("default"))) +#else +#define FMI2_Export +#endif +#endif +#else +#define FMI2_Export +#endif +#endif + +/* Macros to construct the real function name + (prepend function name by FMI2_FUNCTION_PREFIX) */ +#if defined(FMI2_FUNCTION_PREFIX) +#define fmi2Paste(a, b) a##b +#define fmi2PasteB(a, b) fmi2Paste(a, b) +#define fmi2FullName(name) fmi2PasteB(FMI2_FUNCTION_PREFIX, name) +#else +#define fmi2FullName(name) name +#endif + +/*************************************************** +Common Functions +****************************************************/ +#define fmi2GetTypesPlatform fmi2FullName(fmi2GetTypesPlatform) +#define fmi2GetVersion fmi2FullName(fmi2GetVersion) +#define fmi2SetDebugLogging fmi2FullName(fmi2SetDebugLogging) +#define fmi2Instantiate fmi2FullName(fmi2Instantiate) +#define fmi2FreeInstance fmi2FullName(fmi2FreeInstance) +#define fmi2SetupExperiment fmi2FullName(fmi2SetupExperiment) +#define fmi2EnterInitializationMode fmi2FullName(fmi2EnterInitializationMode) +#define fmi2ExitInitializationMode fmi2FullName(fmi2ExitInitializationMode) +#define fmi2Terminate fmi2FullName(fmi2Terminate) +#define fmi2Reset fmi2FullName(fmi2Reset) +#define fmi2GetReal fmi2FullName(fmi2GetReal) +#define fmi2GetInteger fmi2FullName(fmi2GetInteger) +#define fmi2GetBoolean fmi2FullName(fmi2GetBoolean) +#define fmi2GetString fmi2FullName(fmi2GetString) +#define fmi2SetReal fmi2FullName(fmi2SetReal) +#define fmi2SetInteger fmi2FullName(fmi2SetInteger) +#define fmi2SetBoolean fmi2FullName(fmi2SetBoolean) +#define fmi2SetString fmi2FullName(fmi2SetString) +#define fmi2GetFMUstate fmi2FullName(fmi2GetFMUstate) +#define fmi2SetFMUstate fmi2FullName(fmi2SetFMUstate) +#define fmi2FreeFMUstate fmi2FullName(fmi2FreeFMUstate) +#define fmi2SerializedFMUstateSize fmi2FullName(fmi2SerializedFMUstateSize) +#define fmi2SerializeFMUstate fmi2FullName(fmi2SerializeFMUstate) +#define fmi2DeSerializeFMUstate fmi2FullName(fmi2DeSerializeFMUstate) +#define fmi2GetDirectionalDerivative fmi2FullName(fmi2GetDirectionalDerivative) + +/*************************************************** +Functions for FMI2 for Model Exchange +****************************************************/ +#define fmi2EnterEventMode fmi2FullName(fmi2EnterEventMode) +#define fmi2NewDiscreteStates fmi2FullName(fmi2NewDiscreteStates) +#define fmi2EnterContinuousTimeMode fmi2FullName(fmi2EnterContinuousTimeMode) +#define fmi2CompletedIntegratorStep fmi2FullName(fmi2CompletedIntegratorStep) +#define fmi2SetTime fmi2FullName(fmi2SetTime) +#define fmi2SetContinuousStates fmi2FullName(fmi2SetContinuousStates) +#define fmi2GetDerivatives fmi2FullName(fmi2GetDerivatives) +#define fmi2GetEventIndicators fmi2FullName(fmi2GetEventIndicators) +#define fmi2GetContinuousStates fmi2FullName(fmi2GetContinuousStates) +#define fmi2GetNominalsOfContinuousStates fmi2FullName(fmi2GetNominalsOfContinuousStates) + +/*************************************************** +Functions for FMI2 for Co-Simulation +****************************************************/ +#define fmi2SetRealInputDerivatives fmi2FullName(fmi2SetRealInputDerivatives) +#define fmi2GetRealOutputDerivatives fmi2FullName(fmi2GetRealOutputDerivatives) +#define fmi2DoStep fmi2FullName(fmi2DoStep) +#define fmi2CancelStep fmi2FullName(fmi2CancelStep) +#define fmi2GetStatus fmi2FullName(fmi2GetStatus) +#define fmi2GetRealStatus fmi2FullName(fmi2GetRealStatus) +#define fmi2GetIntegerStatus fmi2FullName(fmi2GetIntegerStatus) +#define fmi2GetBooleanStatus fmi2FullName(fmi2GetBooleanStatus) +#define fmi2GetStringStatus fmi2FullName(fmi2GetStringStatus) + +/* Version number */ +#define fmi2Version "2.0" + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files */ +FMI2_Export fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform; +FMI2_Export fmi2GetVersionTYPE fmi2GetVersion; +FMI2_Export fmi2SetDebugLoggingTYPE fmi2SetDebugLogging; + +/* Creation and destruction of FMU instances */ +FMI2_Export fmi2InstantiateTYPE fmi2Instantiate; +FMI2_Export fmi2FreeInstanceTYPE fmi2FreeInstance; + +/* Enter and exit initialization mode, terminate and reset */ +FMI2_Export fmi2SetupExperimentTYPE fmi2SetupExperiment; +FMI2_Export fmi2EnterInitializationModeTYPE fmi2EnterInitializationMode; +FMI2_Export fmi2ExitInitializationModeTYPE fmi2ExitInitializationMode; +FMI2_Export fmi2TerminateTYPE fmi2Terminate; +FMI2_Export fmi2ResetTYPE fmi2Reset; + +/* Getting and setting variables values */ +FMI2_Export fmi2GetRealTYPE fmi2GetReal; +FMI2_Export fmi2GetIntegerTYPE fmi2GetInteger; +FMI2_Export fmi2GetBooleanTYPE fmi2GetBoolean; +FMI2_Export fmi2GetStringTYPE fmi2GetString; + +FMI2_Export fmi2SetRealTYPE fmi2SetReal; +FMI2_Export fmi2SetIntegerTYPE fmi2SetInteger; +FMI2_Export fmi2SetBooleanTYPE fmi2SetBoolean; +FMI2_Export fmi2SetStringTYPE fmi2SetString; + +/* Getting and setting the internal FMU state */ +FMI2_Export fmi2GetFMUstateTYPE fmi2GetFMUstate; +FMI2_Export fmi2SetFMUstateTYPE fmi2SetFMUstate; +FMI2_Export fmi2FreeFMUstateTYPE fmi2FreeFMUstate; +FMI2_Export fmi2SerializedFMUstateSizeTYPE fmi2SerializedFMUstateSize; +FMI2_Export fmi2SerializeFMUstateTYPE fmi2SerializeFMUstate; +FMI2_Export fmi2DeSerializeFMUstateTYPE fmi2DeSerializeFMUstate; + +/* Getting partial derivatives */ +FMI2_Export fmi2GetDirectionalDerivativeTYPE fmi2GetDirectionalDerivative; + +/*************************************************** +Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMI2_Export fmi2EnterEventModeTYPE fmi2EnterEventMode; +FMI2_Export fmi2NewDiscreteStatesTYPE fmi2NewDiscreteStates; +FMI2_Export fmi2EnterContinuousTimeModeTYPE fmi2EnterContinuousTimeMode; +FMI2_Export fmi2CompletedIntegratorStepTYPE fmi2CompletedIntegratorStep; + +/* Providing independent variables and re-initialization of caching */ +FMI2_Export fmi2SetTimeTYPE fmi2SetTime; +FMI2_Export fmi2SetContinuousStatesTYPE fmi2SetContinuousStates; + +/* Evaluation of the model equations */ +FMI2_Export fmi2GetDerivativesTYPE fmi2GetDerivatives; +FMI2_Export fmi2GetEventIndicatorsTYPE fmi2GetEventIndicators; +FMI2_Export fmi2GetContinuousStatesTYPE fmi2GetContinuousStates; +FMI2_Export fmi2GetNominalsOfContinuousStatesTYPE fmi2GetNominalsOfContinuousStates; + +/*************************************************** +Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMI2_Export fmi2SetRealInputDerivativesTYPE fmi2SetRealInputDerivatives; +FMI2_Export fmi2GetRealOutputDerivativesTYPE fmi2GetRealOutputDerivatives; + +FMI2_Export fmi2DoStepTYPE fmi2DoStep; +FMI2_Export fmi2CancelStepTYPE fmi2CancelStep; + +/* Inquire slave status */ +FMI2_Export fmi2GetStatusTYPE fmi2GetStatus; +FMI2_Export fmi2GetRealStatusTYPE fmi2GetRealStatus; +FMI2_Export fmi2GetIntegerStatusTYPE fmi2GetIntegerStatus; +FMI2_Export fmi2GetBooleanStatusTYPE fmi2GetBooleanStatus; +FMI2_Export fmi2GetStringStatusTYPE fmi2GetStringStatus; + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi2Functions_h */ diff --git a/oscillator/fmi/fmu/include/fmi2TypesPlatform.h b/oscillator/fmi/fmu/include/fmi2TypesPlatform.h new file mode 100644 index 000000000..21439522d --- /dev/null +++ b/oscillator/fmi/fmu/include/fmi2TypesPlatform.h @@ -0,0 +1,107 @@ +#ifndef fmi2TypesPlatform_h +#define fmi2TypesPlatform_h + +/* Standard header file to define the argument types of the + functions of the Functional Mock-up Interface 2.0.1 + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - Sep. 29, 2019: License changed to 2-clause BSD License (without extensions) + - Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Mar 31, 2014: New datatype fmiChar introduced. + - Feb. 17, 2013: Changed fmiTypesPlatform from "standard32" to "default". + Removed fmiUndefinedValueReference since no longer needed + (because every state is defined in ScalarVariables). + - March 20, 2012: Renamed from fmiPlatformTypes.h to fmiTypesPlatform.h + - Nov. 14, 2011: Use the header file "fmiPlatformTypes.h" for FMI 2.0 + both for "FMI for model exchange" and for "FMI for co-simulation" + New types "fmiComponentEnvironment", "fmiState", and "fmiByte". + The implementation of "fmiBoolean" is change from "char" to "int". + The #define "fmiPlatform" changed to "fmiTypesPlatform" + (in order that #define and function call are consistent) + - Oct. 4, 2010: Renamed header file from "fmiModelTypes.h" to fmiPlatformTypes.h" + for the co-simulation interface + - Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic) + - Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent" + according to meeting on Dec. 18 (by Martin Otter, DLR) + - Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + Changed "version" to "platform", "standard" to "standard32", + Added a precise definition of "standard32" as comment + (by Martin Otter, DLR) + - July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse, + and changed meValueReferenced from int to unsigned int + (by Martin Otter, DLR). + - March 2, 2009: Moved enums and function pointer definitions to + ModelFunctions.h (by Martin Otter, DLR). + - Dec. 3, 2008 : First version by Martin Otter (DLR) and + Hans Olsson (Dynasim). + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +/* Platform (unique identification of this header file) */ +#define fmi2TypesPlatform "default" + +/* Type definitions of variables passed as arguments + Version "default" means: + + fmi2Component : an opaque object pointer + fmi2ComponentEnvironment: an opaque object pointer + fmi2FMUstate : an opaque object pointer + fmi2ValueReference : handle to the value of a variable + fmi2Real : double precision floating-point data type + fmi2Integer : basic signed integer data type + fmi2Boolean : basic signed integer data type + fmi2Char : character data type + fmi2String : a pointer to a vector of fmi2Char characters + ('\0' terminated, UTF8 encoded) + fmi2Byte : smallest addressable unit of the machine, typically one byte. +*/ +typedef void * fmi2Component; /* Pointer to FMU instance */ +typedef void * fmi2ComponentEnvironment; /* Pointer to FMU environment */ +typedef void * fmi2FMUstate; /* Pointer to internal FMU state */ +typedef unsigned int fmi2ValueReference; +typedef double fmi2Real; +typedef int fmi2Integer; +typedef int fmi2Boolean; +typedef char fmi2Char; +typedef const fmi2Char *fmi2String; +typedef char fmi2Byte; + +/* Values for fmi2Boolean */ +#define fmi2True 1 +#define fmi2False 0 + +#endif /* fmi2TypesPlatform_h */ diff --git a/oscillator/fmi/fmu/include/fmi3FunctionTypes.h b/oscillator/fmi/fmu/include/fmi3FunctionTypes.h new file mode 100644 index 000000000..1e76c4a82 --- /dev/null +++ b/oscillator/fmi/fmu/include/fmi3FunctionTypes.h @@ -0,0 +1,637 @@ +#ifndef fmi3FunctionTypes_h +#define fmi3FunctionTypes_h + +#include "fmi3PlatformTypes.h" + +/* +This header file defines the data and function types of FMI 3.0. +It must be used when compiling an FMU or an FMI importer. + +Copyright (C) 2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include stddef.h, in order that size_t etc. is defined */ +#include + +/* Type definitions */ + +/* tag::Status[] */ +typedef enum { + fmi3OK, + fmi3Warning, + fmi3Discard, + fmi3Error, + fmi3Fatal, +} fmi3Status; +/* end::Status[] */ + +/* tag::DependencyKind[] */ +typedef enum { + fmi3Independent, + fmi3Constant, + fmi3Fixed, + fmi3Tunable, + fmi3Discrete, + fmi3Dependent +} fmi3DependencyKind; +/* end::DependencyKind[] */ + +/* tag::IntervalQualifier[] */ +typedef enum { + fmi3IntervalNotYetKnown, + fmi3IntervalUnchanged, + fmi3IntervalChanged +} fmi3IntervalQualifier; +/* end::IntervalQualifier[] */ + +/* tag::CallbackLogMessage[] */ +typedef void (*fmi3LogMessageCallback)(fmi3InstanceEnvironment instanceEnvironment, + fmi3Status status, + fmi3String category, + fmi3String message); +/* end::CallbackLogMessage[] */ + +/* tag::CallbackClockUpdate[] */ +typedef void (*fmi3ClockUpdateCallback)( + fmi3InstanceEnvironment instanceEnvironment); +/* end::CallbackClockUpdate[] */ + +/* tag::CallbackIntermediateUpdate[] */ +typedef void (*fmi3IntermediateUpdateCallback)( + fmi3InstanceEnvironment instanceEnvironment, + fmi3Float64 intermediateUpdateTime, + fmi3Boolean intermediateVariableSetRequested, + fmi3Boolean intermediateVariableGetAllowed, + fmi3Boolean intermediateStepFinished, + fmi3Boolean canReturnEarly, + fmi3Boolean * earlyReturnRequested, + fmi3Float64 * earlyReturnTime); +/* end::CallbackIntermediateUpdate[] */ + +/* tag::CallbackPreemptionLock[] */ +typedef void (*fmi3LockPreemptionCallback)(); +typedef void (*fmi3UnlockPreemptionCallback)(); +/* end::CallbackPreemptionLock[] */ + +/* Define fmi3 function pointer types to simplify dynamic loading */ + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +/* tag::GetVersion[] */ +typedef const char *fmi3GetVersionTYPE(void); +/* end::GetVersion[] */ + +/* tag::SetDebugLogging[] */ +typedef fmi3Status fmi3SetDebugLoggingTYPE(fmi3Instance instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]); +/* end::SetDebugLogging[] */ + +/* Creation and destruction of FMU instances and setting debug status */ +/* tag::Instantiate[] */ +typedef fmi3Instance fmi3InstantiateModelExchangeTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage); + +typedef fmi3Instance fmi3InstantiateCoSimulationTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3IntermediateUpdateCallback intermediateUpdate); + +typedef fmi3Instance fmi3InstantiateScheduledExecutionTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption); +/* end::Instantiate[] */ + +/* tag::FreeInstance[] */ +typedef void fmi3FreeInstanceTYPE(fmi3Instance instance); +/* end::FreeInstance[] */ + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +/* tag::EnterInitializationMode[] */ +typedef fmi3Status fmi3EnterInitializationModeTYPE(fmi3Instance instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime); +/* end::EnterInitializationMode[] */ + +/* tag::ExitInitializationMode[] */ +typedef fmi3Status fmi3ExitInitializationModeTYPE(fmi3Instance instance); +/* end::ExitInitializationMode[] */ + +/* tag::EnterEventMode[] */ +typedef fmi3Status fmi3EnterEventModeTYPE(fmi3Instance instance); +/* end::EnterEventMode[] */ + +/* tag::Terminate[] */ +typedef fmi3Status fmi3TerminateTYPE(fmi3Instance instance); +/* end::Terminate[] */ + +/* tag::Reset[] */ +typedef fmi3Status fmi3ResetTYPE(fmi3Instance instance); +/* end::Reset[] */ + +/* Getting and setting variable values */ +/* tag::Getters[] */ +typedef fmi3Status fmi3GetFloat32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetFloat64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetBooleanTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues); + +typedef fmi3Status fmi3GetStringTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues); + +typedef fmi3Status fmi3GetBinaryTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t valueSizes[], + fmi3Binary values[], + size_t nValues); +/* end::Getters[] */ + +/* tag::GetClock[] */ +typedef fmi3Status fmi3GetClockTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]); +/* end::GetClock[] */ + +/* tag::Setters[] */ +typedef fmi3Status fmi3SetFloat32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetFloat64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetBooleanTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues); + +typedef fmi3Status fmi3SetStringTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues); + +typedef fmi3Status fmi3SetBinaryTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t valueSizes[], + const fmi3Binary values[], + size_t nValues); +/* end::Setters[] */ +/* tag::SetClock[] */ +typedef fmi3Status fmi3SetClockTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]); +/* end::SetClock[] */ + +/* Getting Variable Dependency Information */ +/* tag::GetNumberOfVariableDependencies[] */ +typedef fmi3Status fmi3GetNumberOfVariableDependenciesTYPE(fmi3Instance instance, + fmi3ValueReference valueReference, + size_t * nDependencies); +/* end::GetNumberOfVariableDependencies[] */ + +/* tag::GetVariableDependencies[] */ +typedef fmi3Status fmi3GetVariableDependenciesTYPE(fmi3Instance instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies); +/* end::GetVariableDependencies[] */ + +/* Getting and setting the internal FMU state */ +/* tag::GetFMUState[] */ +typedef fmi3Status fmi3GetFMUStateTYPE(fmi3Instance instance, fmi3FMUState *FMUState); +/* end::GetFMUState[] */ + +/* tag::SetFMUState[] */ +typedef fmi3Status fmi3SetFMUStateTYPE(fmi3Instance instance, fmi3FMUState FMUState); +/* end::SetFMUState[] */ + +/* tag::FreeFMUState[] */ +typedef fmi3Status fmi3FreeFMUStateTYPE(fmi3Instance instance, fmi3FMUState *FMUState); +/* end::FreeFMUState[] */ + +/* tag::SerializedFMUStateSize[] */ +typedef fmi3Status fmi3SerializedFMUStateSizeTYPE(fmi3Instance instance, + fmi3FMUState FMUState, + size_t * size); +/* end::SerializedFMUStateSize[] */ + +/* tag::SerializeFMUState[] */ +typedef fmi3Status fmi3SerializeFMUStateTYPE(fmi3Instance instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size); +/* end::SerializeFMUState[] */ + +/* tag::DeserializeFMUState[] */ +typedef fmi3Status fmi3DeserializeFMUStateTYPE(fmi3Instance instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState * FMUState); +/* end::DeserializeFMUState[] */ + +/* Getting partial derivatives */ +/* tag::GetDirectionalDerivative[] */ +typedef fmi3Status fmi3GetDirectionalDerivativeTYPE(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); +/* end::GetDirectionalDerivative[] */ + +/* tag::GetAdjointDerivative[] */ +typedef fmi3Status fmi3GetAdjointDerivativeTYPE(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); +/* end::GetAdjointDerivative[] */ + +/* Entering and exiting the Configuration or Reconfiguration Mode */ + +/* tag::EnterConfigurationMode[] */ +typedef fmi3Status fmi3EnterConfigurationModeTYPE(fmi3Instance instance); +/* end::EnterConfigurationMode[] */ + +/* tag::ExitConfigurationMode[] */ +typedef fmi3Status fmi3ExitConfigurationModeTYPE(fmi3Instance instance); +/* end::ExitConfigurationMode[] */ + +/* tag::GetIntervalDecimal[] */ +typedef fmi3Status fmi3GetIntervalDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]); +/* end::GetIntervalDecimal[] */ + +/* tag::GetIntervalFraction[] */ +typedef fmi3Status fmi3GetIntervalFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 counters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]); +/* end::GetIntervalFraction[] */ + +/* tag::GetShiftDecimal[] */ +typedef fmi3Status fmi3GetShiftDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]); +/* end::GetShiftDecimal[] */ + +/* tag::GetShiftFraction[] */ +typedef fmi3Status fmi3GetShiftFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 counters[], + fmi3UInt64 resolutions[]); +/* end::GetShiftFraction[] */ + +/* tag::SetIntervalDecimal[] */ +typedef fmi3Status fmi3SetIntervalDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]); +/* end::SetIntervalDecimal[] */ + +/* tag::SetIntervalFraction[] */ +typedef fmi3Status fmi3SetIntervalFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 counters[], + const fmi3UInt64 resolutions[]); +/* end::SetIntervalFraction[] */ + +/* tag::SetShiftDecimal[] */ +typedef fmi3Status fmi3SetShiftDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]); +/* end::SetShiftDecimal[] */ + +/* tag::SetShiftFraction[] */ +typedef fmi3Status fmi3SetShiftFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 counters[], + const fmi3UInt64 resolutions[]); +/* end::SetShiftFraction[] */ + +/* tag::EvaluateDiscreteStates[] */ +typedef fmi3Status fmi3EvaluateDiscreteStatesTYPE(fmi3Instance instance); +/* end::EvaluateDiscreteStates[] */ + +/* tag::UpdateDiscreteStates[] */ +typedef fmi3Status fmi3UpdateDiscreteStatesTYPE(fmi3Instance instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime); +/* end::UpdateDiscreteStates[] */ + +/*************************************************** +Types for Functions for Model Exchange +****************************************************/ + +/* tag::EnterContinuousTimeMode[] */ +typedef fmi3Status fmi3EnterContinuousTimeModeTYPE(fmi3Instance instance); +/* end::EnterContinuousTimeMode[] */ + +/* tag::CompletedIntegratorStep[] */ +typedef fmi3Status fmi3CompletedIntegratorStepTYPE(fmi3Instance instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation); +/* end::CompletedIntegratorStep[] */ + +/* Providing independent variables and re-initialization of caching */ +/* tag::SetTime[] */ +typedef fmi3Status fmi3SetTimeTYPE(fmi3Instance instance, fmi3Float64 time); +/* end::SetTime[] */ + +/* tag::SetContinuousStates[] */ +typedef fmi3Status fmi3SetContinuousStatesTYPE(fmi3Instance instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates); +/* end::SetContinuousStates[] */ + +/* Evaluation of the model equations */ +/* tag::GetDerivatives[] */ +typedef fmi3Status fmi3GetContinuousStateDerivativesTYPE(fmi3Instance instance, + fmi3Float64 derivatives[], + size_t nContinuousStates); +/* end::GetDerivatives[] */ + +/* tag::GetEventIndicators[] */ +typedef fmi3Status fmi3GetEventIndicatorsTYPE(fmi3Instance instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators); +/* end::GetEventIndicators[] */ + +/* tag::GetContinuousStates[] */ +typedef fmi3Status fmi3GetContinuousStatesTYPE(fmi3Instance instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates); +/* end::GetContinuousStates[] */ + +/* tag::GetNominalsOfContinuousStates[] */ +typedef fmi3Status fmi3GetNominalsOfContinuousStatesTYPE(fmi3Instance instance, + fmi3Float64 nominals[], + size_t nContinuousStates); +/* end::GetNominalsOfContinuousStates[] */ + +/* tag::GetNumberOfEventIndicators[] */ +typedef fmi3Status fmi3GetNumberOfEventIndicatorsTYPE(fmi3Instance instance, + size_t * nEventIndicators); +/* end::GetNumberOfEventIndicators[] */ + +/* tag::GetNumberOfContinuousStates[] */ +typedef fmi3Status fmi3GetNumberOfContinuousStatesTYPE(fmi3Instance instance, + size_t * nContinuousStates); +/* end::GetNumberOfContinuousStates[] */ + +/*************************************************** +Types for Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +/* tag::EnterStepMode[] */ +typedef fmi3Status fmi3EnterStepModeTYPE(fmi3Instance instance); +/* end::EnterStepMode[] */ + +/* tag::GetOutputDerivatives[] */ +typedef fmi3Status fmi3GetOutputDerivativesTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues); +/* end::GetOutputDerivatives[] */ + +/* tag::DoStep[] */ +typedef fmi3Status fmi3DoStepTYPE(fmi3Instance instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime); +/* end::DoStep[] */ + +/*************************************************** +Types for Functions for Scheduled Execution +****************************************************/ + +/* tag::ActivateModelPartition[] */ +typedef fmi3Status fmi3ActivateModelPartitionTYPE(fmi3Instance instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime); +/* end::ActivateModelPartition[] */ + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi3FunctionTypes_h */ diff --git a/oscillator/fmi/fmu/include/fmi3Functions.h b/oscillator/fmi/fmu/include/fmi3Functions.h new file mode 100644 index 000000000..36733ebf1 --- /dev/null +++ b/oscillator/fmi/fmu/include/fmi3Functions.h @@ -0,0 +1,343 @@ +#ifndef fmi3Functions_h +#define fmi3Functions_h + +/* +This header file declares the functions of FMI 3.0. +It must be used when compiling an FMU. + +In order to have unique function names even if several FMUs +are compiled together (e.g. for embedded systems), every "real" function name +is constructed by prepending the function name by "FMI3_FUNCTION_PREFIX". +Therefore, the typical usage is: + + #define FMI3_FUNCTION_PREFIX MyModel_ + #include "fmi3Functions.h" + +As a result, a function that is defined as "fmi3GetContinuousStateDerivatives" in this header file, +is actually getting the name "MyModel_fmi3GetContinuousStateDerivatives". + +This only holds if the FMU is shipped in C source code, or is compiled in a +static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function +names are used and "FMI3_FUNCTION_PREFIX" must not be defined. + +Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fmi3FunctionTypes.h" +#include "fmi3PlatformTypes.h" + +/* +Allow override of FMI3_FUNCTION_PREFIX: If FMI3_OVERRIDE_FUNCTION_PREFIX +is defined, then FMI3_ACTUAL_FUNCTION_PREFIX will be used, if defined, +or no prefix if undefined. Otherwise FMI3_FUNCTION_PREFIX will be used, +if defined. +*/ +#if !defined(FMI3_OVERRIDE_FUNCTION_PREFIX) && defined(FMI3_FUNCTION_PREFIX) +#define FMI3_ACTUAL_FUNCTION_PREFIX FMI3_FUNCTION_PREFIX +#endif + +/* +Export FMI3 API functions on Windows and under GCC. +If custom linking is desired then the FMI3_Export must be +defined before including this file. For instance, +it may be set to __declspec(dllimport). +*/ +#if !defined(FMI3_Export) +#if !defined(FMI3_ACTUAL_FUNCTION_PREFIX) +#if defined _WIN32 || defined __CYGWIN__ +/* Note: both gcc & MSVC on Windows support this syntax. */ +#define FMI3_Export __declspec(dllexport) +#else +#if __GNUC__ >= 4 +#define FMI3_Export __attribute__((visibility("default"))) +#else +#define FMI3_Export +#endif +#endif +#else +#define FMI3_Export +#endif +#endif + +/* Macros to construct the real function name (prepend function name by FMI3_FUNCTION_PREFIX) */ +#if defined(FMI3_ACTUAL_FUNCTION_PREFIX) +#define fmi3Paste(a, b) a##b +#define fmi3PasteB(a, b) fmi3Paste(a, b) +#define fmi3FullName(name) fmi3PasteB(FMI3_ACTUAL_FUNCTION_PREFIX, name) +#else +#define fmi3FullName(name) name +#endif + +/* FMI version */ +#define fmi3Version "3.0" + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and set debug logging */ +#define fmi3GetVersion fmi3FullName(fmi3GetVersion) +#define fmi3SetDebugLogging fmi3FullName(fmi3SetDebugLogging) + +/* Creation and destruction of FMU instances */ +#define fmi3InstantiateModelExchange fmi3FullName(fmi3InstantiateModelExchange) +#define fmi3InstantiateCoSimulation fmi3FullName(fmi3InstantiateCoSimulation) +#define fmi3InstantiateScheduledExecution fmi3FullName(fmi3InstantiateScheduledExecution) +#define fmi3FreeInstance fmi3FullName(fmi3FreeInstance) + +/* Enter and exit initialization mode, terminate and reset */ +#define fmi3EnterInitializationMode fmi3FullName(fmi3EnterInitializationMode) +#define fmi3ExitInitializationMode fmi3FullName(fmi3ExitInitializationMode) +#define fmi3EnterEventMode fmi3FullName(fmi3EnterEventMode) +#define fmi3Terminate fmi3FullName(fmi3Terminate) +#define fmi3Reset fmi3FullName(fmi3Reset) + +/* Getting and setting variable values */ +#define fmi3GetFloat32 fmi3FullName(fmi3GetFloat32) +#define fmi3GetFloat64 fmi3FullName(fmi3GetFloat64) +#define fmi3GetInt8 fmi3FullName(fmi3GetInt8) +#define fmi3GetUInt8 fmi3FullName(fmi3GetUInt8) +#define fmi3GetInt16 fmi3FullName(fmi3GetInt16) +#define fmi3GetUInt16 fmi3FullName(fmi3GetUInt16) +#define fmi3GetInt32 fmi3FullName(fmi3GetInt32) +#define fmi3GetUInt32 fmi3FullName(fmi3GetUInt32) +#define fmi3GetInt64 fmi3FullName(fmi3GetInt64) +#define fmi3GetUInt64 fmi3FullName(fmi3GetUInt64) +#define fmi3GetBoolean fmi3FullName(fmi3GetBoolean) +#define fmi3GetString fmi3FullName(fmi3GetString) +#define fmi3GetBinary fmi3FullName(fmi3GetBinary) +#define fmi3GetClock fmi3FullName(fmi3GetClock) +#define fmi3SetFloat32 fmi3FullName(fmi3SetFloat32) +#define fmi3SetFloat64 fmi3FullName(fmi3SetFloat64) +#define fmi3SetInt8 fmi3FullName(fmi3SetInt8) +#define fmi3SetUInt8 fmi3FullName(fmi3SetUInt8) +#define fmi3SetInt16 fmi3FullName(fmi3SetInt16) +#define fmi3SetUInt16 fmi3FullName(fmi3SetUInt16) +#define fmi3SetInt32 fmi3FullName(fmi3SetInt32) +#define fmi3SetUInt32 fmi3FullName(fmi3SetUInt32) +#define fmi3SetInt64 fmi3FullName(fmi3SetInt64) +#define fmi3SetUInt64 fmi3FullName(fmi3SetUInt64) +#define fmi3SetBoolean fmi3FullName(fmi3SetBoolean) +#define fmi3SetString fmi3FullName(fmi3SetString) +#define fmi3SetBinary fmi3FullName(fmi3SetBinary) +#define fmi3SetClock fmi3FullName(fmi3SetClock) + +/* Getting Variable Dependency Information */ +#define fmi3GetNumberOfVariableDependencies fmi3FullName(fmi3GetNumberOfVariableDependencies) +#define fmi3GetVariableDependencies fmi3FullName(fmi3GetVariableDependencies) + +/* Getting and setting the internal FMU state */ +#define fmi3GetFMUState fmi3FullName(fmi3GetFMUState) +#define fmi3SetFMUState fmi3FullName(fmi3SetFMUState) +#define fmi3FreeFMUState fmi3FullName(fmi3FreeFMUState) +#define fmi3SerializedFMUStateSize fmi3FullName(fmi3SerializedFMUStateSize) +#define fmi3SerializeFMUState fmi3FullName(fmi3SerializeFMUState) +#define fmi3DeserializeFMUState fmi3FullName(fmi3DeserializeFMUState) + +/* Getting partial derivatives */ +#define fmi3GetDirectionalDerivative fmi3FullName(fmi3GetDirectionalDerivative) +#define fmi3GetAdjointDerivative fmi3FullName(fmi3GetAdjointDerivative) + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +#define fmi3EnterConfigurationMode fmi3FullName(fmi3EnterConfigurationMode) +#define fmi3ExitConfigurationMode fmi3FullName(fmi3ExitConfigurationMode) + +/* Clock related functions */ +#define fmi3GetIntervalDecimal fmi3FullName(fmi3GetIntervalDecimal) +#define fmi3GetIntervalFraction fmi3FullName(fmi3GetIntervalFraction) +#define fmi3GetShiftDecimal fmi3FullName(fmi3GetShiftDecimal) +#define fmi3GetShiftFraction fmi3FullName(fmi3GetShiftFraction) +#define fmi3SetIntervalDecimal fmi3FullName(fmi3SetIntervalDecimal) +#define fmi3SetIntervalFraction fmi3FullName(fmi3SetIntervalFraction) +#define fmi3SetShiftDecimal fmi3FullName(fmi3SetShiftDecimal) +#define fmi3SetShiftFraction fmi3FullName(fmi3SetShiftFraction) +#define fmi3EvaluateDiscreteStates fmi3FullName(fmi3EvaluateDiscreteStates) +#define fmi3UpdateDiscreteStates fmi3FullName(fmi3UpdateDiscreteStates) + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +#define fmi3EnterContinuousTimeMode fmi3FullName(fmi3EnterContinuousTimeMode) +#define fmi3CompletedIntegratorStep fmi3FullName(fmi3CompletedIntegratorStep) + +/* Providing independent variables and re-initialization of caching */ +#define fmi3SetTime fmi3FullName(fmi3SetTime) +#define fmi3SetContinuousStates fmi3FullName(fmi3SetContinuousStates) + +/* Evaluation of the model equations */ +#define fmi3GetContinuousStateDerivatives fmi3FullName(fmi3GetContinuousStateDerivatives) +#define fmi3GetEventIndicators fmi3FullName(fmi3GetEventIndicators) +#define fmi3GetContinuousStates fmi3FullName(fmi3GetContinuousStates) +#define fmi3GetNominalsOfContinuousStates fmi3FullName(fmi3GetNominalsOfContinuousStates) +#define fmi3GetNumberOfEventIndicators fmi3FullName(fmi3GetNumberOfEventIndicators) +#define fmi3GetNumberOfContinuousStates fmi3FullName(fmi3GetNumberOfContinuousStates) + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ +#define fmi3EnterStepMode fmi3FullName(fmi3EnterStepMode) +#define fmi3GetOutputDerivatives fmi3FullName(fmi3GetOutputDerivatives) +#define fmi3DoStep fmi3FullName(fmi3DoStep) +#define fmi3ActivateModelPartition fmi3FullName(fmi3ActivateModelPartition) + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and set debug logging */ +FMI3_Export fmi3GetVersionTYPE fmi3GetVersion; +FMI3_Export fmi3SetDebugLoggingTYPE fmi3SetDebugLogging; + +/* Creation and destruction of FMU instances */ +FMI3_Export fmi3InstantiateModelExchangeTYPE fmi3InstantiateModelExchange; +FMI3_Export fmi3InstantiateCoSimulationTYPE fmi3InstantiateCoSimulation; +FMI3_Export fmi3InstantiateScheduledExecutionTYPE fmi3InstantiateScheduledExecution; +FMI3_Export fmi3FreeInstanceTYPE fmi3FreeInstance; + +/* Enter and exit initialization mode, terminate and reset */ +FMI3_Export fmi3EnterInitializationModeTYPE fmi3EnterInitializationMode; +FMI3_Export fmi3ExitInitializationModeTYPE fmi3ExitInitializationMode; +FMI3_Export fmi3EnterEventModeTYPE fmi3EnterEventMode; +FMI3_Export fmi3TerminateTYPE fmi3Terminate; +FMI3_Export fmi3ResetTYPE fmi3Reset; + +/* Getting and setting variables values */ +FMI3_Export fmi3GetFloat32TYPE fmi3GetFloat32; +FMI3_Export fmi3GetFloat64TYPE fmi3GetFloat64; +FMI3_Export fmi3GetInt8TYPE fmi3GetInt8; +FMI3_Export fmi3GetUInt8TYPE fmi3GetUInt8; +FMI3_Export fmi3GetInt16TYPE fmi3GetInt16; +FMI3_Export fmi3GetUInt16TYPE fmi3GetUInt16; +FMI3_Export fmi3GetInt32TYPE fmi3GetInt32; +FMI3_Export fmi3GetUInt32TYPE fmi3GetUInt32; +FMI3_Export fmi3GetInt64TYPE fmi3GetInt64; +FMI3_Export fmi3GetUInt64TYPE fmi3GetUInt64; +FMI3_Export fmi3GetBooleanTYPE fmi3GetBoolean; +FMI3_Export fmi3GetStringTYPE fmi3GetString; +FMI3_Export fmi3GetBinaryTYPE fmi3GetBinary; +FMI3_Export fmi3GetClockTYPE fmi3GetClock; +FMI3_Export fmi3SetFloat32TYPE fmi3SetFloat32; +FMI3_Export fmi3SetFloat64TYPE fmi3SetFloat64; +FMI3_Export fmi3SetInt8TYPE fmi3SetInt8; +FMI3_Export fmi3SetUInt8TYPE fmi3SetUInt8; +FMI3_Export fmi3SetInt16TYPE fmi3SetInt16; +FMI3_Export fmi3SetUInt16TYPE fmi3SetUInt16; +FMI3_Export fmi3SetInt32TYPE fmi3SetInt32; +FMI3_Export fmi3SetUInt32TYPE fmi3SetUInt32; +FMI3_Export fmi3SetInt64TYPE fmi3SetInt64; +FMI3_Export fmi3SetUInt64TYPE fmi3SetUInt64; +FMI3_Export fmi3SetBooleanTYPE fmi3SetBoolean; +FMI3_Export fmi3SetStringTYPE fmi3SetString; +FMI3_Export fmi3SetBinaryTYPE fmi3SetBinary; +FMI3_Export fmi3SetClockTYPE fmi3SetClock; + +/* Getting Variable Dependency Information */ +FMI3_Export fmi3GetNumberOfVariableDependenciesTYPE fmi3GetNumberOfVariableDependencies; +FMI3_Export fmi3GetVariableDependenciesTYPE fmi3GetVariableDependencies; + +/* Getting and setting the internal FMU state */ +FMI3_Export fmi3GetFMUStateTYPE fmi3GetFMUState; +FMI3_Export fmi3SetFMUStateTYPE fmi3SetFMUState; +FMI3_Export fmi3FreeFMUStateTYPE fmi3FreeFMUState; +FMI3_Export fmi3SerializedFMUStateSizeTYPE fmi3SerializedFMUStateSize; +FMI3_Export fmi3SerializeFMUStateTYPE fmi3SerializeFMUState; +FMI3_Export fmi3DeserializeFMUStateTYPE fmi3DeserializeFMUState; + +/* Getting partial derivatives */ +FMI3_Export fmi3GetDirectionalDerivativeTYPE fmi3GetDirectionalDerivative; +FMI3_Export fmi3GetAdjointDerivativeTYPE fmi3GetAdjointDerivative; + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMI3_Export fmi3EnterConfigurationModeTYPE fmi3EnterConfigurationMode; +FMI3_Export fmi3ExitConfigurationModeTYPE fmi3ExitConfigurationMode; + +/* Clock related functions */ +FMI3_Export fmi3GetIntervalDecimalTYPE fmi3GetIntervalDecimal; +FMI3_Export fmi3GetIntervalFractionTYPE fmi3GetIntervalFraction; +FMI3_Export fmi3GetShiftDecimalTYPE fmi3GetShiftDecimal; +FMI3_Export fmi3GetShiftFractionTYPE fmi3GetShiftFraction; +FMI3_Export fmi3SetIntervalDecimalTYPE fmi3SetIntervalDecimal; +FMI3_Export fmi3SetIntervalFractionTYPE fmi3SetIntervalFraction; +FMI3_Export fmi3SetShiftDecimalTYPE fmi3SetShiftDecimal; +FMI3_Export fmi3SetShiftFractionTYPE fmi3SetShiftFraction; +FMI3_Export fmi3EvaluateDiscreteStatesTYPE fmi3EvaluateDiscreteStates; +FMI3_Export fmi3UpdateDiscreteStatesTYPE fmi3UpdateDiscreteStates; + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +FMI3_Export fmi3EnterContinuousTimeModeTYPE fmi3EnterContinuousTimeMode; +FMI3_Export fmi3CompletedIntegratorStepTYPE fmi3CompletedIntegratorStep; + +/* Providing independent variables and re-initialization of caching */ +/* tag::SetTimeTYPE[] */ +FMI3_Export fmi3SetTimeTYPE fmi3SetTime; +/* end::SetTimeTYPE[] */ +FMI3_Export fmi3SetContinuousStatesTYPE fmi3SetContinuousStates; + +/* Evaluation of the model equations */ +FMI3_Export fmi3GetContinuousStateDerivativesTYPE fmi3GetContinuousStateDerivatives; +FMI3_Export fmi3GetEventIndicatorsTYPE fmi3GetEventIndicators; +FMI3_Export fmi3GetContinuousStatesTYPE fmi3GetContinuousStates; +FMI3_Export fmi3GetNominalsOfContinuousStatesTYPE fmi3GetNominalsOfContinuousStates; +FMI3_Export fmi3GetNumberOfEventIndicatorsTYPE fmi3GetNumberOfEventIndicators; +FMI3_Export fmi3GetNumberOfContinuousStatesTYPE fmi3GetNumberOfContinuousStates; + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ +FMI3_Export fmi3EnterStepModeTYPE fmi3EnterStepMode; +FMI3_Export fmi3GetOutputDerivativesTYPE fmi3GetOutputDerivatives; +FMI3_Export fmi3DoStepTYPE fmi3DoStep; + +/*************************************************** +Functions for Scheduled Execution +****************************************************/ + +FMI3_Export fmi3ActivateModelPartitionTYPE fmi3ActivateModelPartition; + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi3Functions_h */ diff --git a/oscillator/fmi/fmu/include/fmi3PlatformTypes.h b/oscillator/fmi/fmu/include/fmi3PlatformTypes.h new file mode 100644 index 000000000..d83f6340f --- /dev/null +++ b/oscillator/fmi/fmu/include/fmi3PlatformTypes.h @@ -0,0 +1,93 @@ +#ifndef fmi3PlatformTypes_h +#define fmi3PlatformTypes_h + +/* +This header file defines the data types of FMI 3.0. +It must be used by both FMU and FMI master. + +Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +/* Include the integer and boolean type definitions */ +#include +#include + +/* tag::Component[] */ +typedef void *fmi3Instance; /* Pointer to the FMU instance */ +/* end::Component[] */ + +/* tag::ComponentEnvironment[] */ +typedef void *fmi3InstanceEnvironment; /* Pointer to the FMU environment */ +/* end::ComponentEnvironment[] */ + +/* tag::FMUState[] */ +typedef void *fmi3FMUState; /* Pointer to the internal FMU state */ +/* end::FMUState[] */ + +/* tag::ValueReference[] */ +typedef uint32_t fmi3ValueReference; /* Handle to the value of a variable */ +/* end::ValueReference[] */ + +/* tag::VariableTypes[] */ +typedef float fmi3Float32; /* Single precision floating point (32-bit) */ +/* tag::fmi3Float64[] */ +typedef double fmi3Float64; /* Double precision floating point (64-bit) */ +/* end::fmi3Float64[] */ +typedef int8_t fmi3Int8; /* 8-bit signed integer */ +typedef uint8_t fmi3UInt8; /* 8-bit unsigned integer */ +typedef int16_t fmi3Int16; /* 16-bit signed integer */ +typedef uint16_t fmi3UInt16; /* 16-bit unsigned integer */ +typedef int32_t fmi3Int32; /* 32-bit signed integer */ +typedef uint32_t fmi3UInt32; /* 32-bit unsigned integer */ +typedef int64_t fmi3Int64; /* 64-bit signed integer */ +typedef uint64_t fmi3UInt64; /* 64-bit unsigned integer */ +typedef bool fmi3Boolean; /* Data type to be used with fmi3True and fmi3False */ +typedef char fmi3Char; /* Data type for one character */ +typedef const fmi3Char *fmi3String; /* Data type for character strings + ('\0' terminated, UTF-8 encoded) */ +typedef uint8_t fmi3Byte; /* Smallest addressable unit of the machine + (typically one byte) */ +typedef const fmi3Byte *fmi3Binary; /* Data type for binary data + (out-of-band length terminated) */ +typedef bool fmi3Clock; /* Data type to be used with fmi3ClockActive and + fmi3ClockInactive */ + +/* Values for fmi3Boolean */ +#define fmi3True true +#define fmi3False false + +/* Values for fmi3Clock */ +#define fmi3ClockActive true +#define fmi3ClockInactive false +/* end::VariableTypes[] */ + +#endif /* fmi3PlatformTypes_h */ diff --git a/oscillator/fmi/fmu/include/fmiFunctions.h b/oscillator/fmi/fmu/include/fmiFunctions.h new file mode 100644 index 000000000..635348509 --- /dev/null +++ b/oscillator/fmi/fmu/include/fmiFunctions.h @@ -0,0 +1,228 @@ +#ifndef fmiFunctions_h +#define fmiFunctions_h + +/* This header file must be utilized when compiling a FMU. + It defines all functions of Co-Simulation Interface. + In order to have unique function names even if several FMUs + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by + "MODEL_IDENTIFIER" + "_" where "MODEL_IDENTIFIER" is the short name + of the model used as the name of the zip-file where the model is stored. + Therefore, the typical usage is: + + #define MODEL_IDENTIFIER MyModel + #include "fmiFunctions.h" + + As a result, a function that is defined as "fmiGetDerivatives" in this header file, + is actually getting the name "MyModel_fmiGetDerivatives". + + Revisions: + - November 4, 2010: Adapted to specification text: + o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform + o fmiInstantiateSlave: Argument GUID replaced by fmuGUID + Argument mimetype replaced by mimeType + o tabs replaced by spaces + - October 16, 2010: First public Version + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#include +#include "fmiPlatformTypes.h" + +/* Export fmi functions on Windows */ +#ifdef _MSC_VER +#define DllExport __declspec(dllexport) +#else +#define DllExport +#endif + +/* Macros to construct the real function name + (prepend function name by MODEL_IDENTIFIER + "_") */ + +#define fmiPaste(a, b) a##b +#define fmiPasteB(a, b) fmiPaste(a, b) +#define fmiFullName(name) fmiPasteB(MODEL_IDENTIFIER, name) + +/*************************************************** +Common Functions +****************************************************/ +#define fmiGetTypesPlatform fmiFullName(_fmiGetTypesPlatform) +#define fmiGetVersion fmiFullName(_fmiGetVersion) +#define fmiSetDebugLogging fmiFullName(_fmiSetDebugLogging) + +/*Data Exchange*/ +#define fmiSetReal fmiFullName(_fmiSetReal) +#define fmiSetInteger fmiFullName(_fmiSetInteger) +#define fmiSetBoolean fmiFullName(_fmiSetBoolean) +#define fmiSetString fmiFullName(_fmiSetString) + +#define fmiGetReal fmiFullName(_fmiGetReal) +#define fmiGetInteger fmiFullName(_fmiGetInteger) +#define fmiGetBoolean fmiFullName(_fmiGetBoolean) +#define fmiGetString fmiFullName(_fmiGetString) + +/*************************************************** +Functions for FMI for Co-Simulation +****************************************************/ +#define fmiInstantiateSlave fmiFullName(_fmiInstantiateSlave) +#define fmiInitializeSlave fmiFullName(_fmiInitializeSlave) +#define fmiTerminateSlave fmiFullName(_fmiTerminateSlave) +#define fmiResetSlave fmiFullName(_fmiResetSlave) +#define fmiFreeSlaveInstance fmiFullName(_fmiFreeSlaveInstance) +#define fmiSetRealInputDerivatives fmiFullName(_fmiSetRealInputDerivatives) +#define fmiGetRealOutputDerivatives fmiFullName(_fmiGetRealOutputDerivatives) +#define fmiDoStep fmiFullName(_fmiDoStep) +#define fmiCancelStep fmiFullName(_fmiCancelStep) +#define fmiGetStatus fmiFullName(_fmiGetStatus) +#define fmiGetRealStatus fmiFullName(_fmiGetRealStatus) +#define fmiGetIntegerStatus fmiFullName(_fmiGetIntegerStatus) +#define fmiGetBooleanStatus fmiFullName(_fmiGetBooleanStatus) +#define fmiGetStringStatus fmiFullName(_fmiGetStringStatus) + +/* Version number */ +#define fmiVersion "1.0" + +/* make sure all compiler use the same alignment policies for structures */ +#ifdef WIN32 +#pragma pack(push, 8) +#endif + +/* Type definitions */ +typedef enum { fmiOK, + fmiWarning, + fmiDiscard, + fmiError, + fmiFatal, + fmiPending } fmiStatus; + +typedef void (*fmiCallbackLogger)(fmiComponent c, fmiString instanceName, fmiStatus status, + fmiString category, fmiString message, ...); +typedef void *(*fmiCallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmiCallbackFreeMemory)(void *obj); +typedef void (*fmiStepFinished)(fmiComponent c, fmiStatus status); + +typedef struct { + fmiCallbackLogger logger; + fmiCallbackAllocateMemory allocateMemory; + fmiCallbackFreeMemory freeMemory; + fmiStepFinished stepFinished; +} fmiCallbackFunctions; + +typedef struct { + fmiBoolean iterationConverged; + fmiBoolean stateValueReferencesChanged; + fmiBoolean stateValuesChanged; + fmiBoolean terminateSimulation; + fmiBoolean upcomingTimeEvent; + fmiReal nextEventTime; +} fmiEventInfo; + +/* reset alignment policy to the one set before reading this file */ +#ifdef WIN32 +#pragma pack(pop) +#endif + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files */ +DllExport const char *fmiGetTypesPlatform(); +DllExport const char *fmiGetVersion(); + +DllExport fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn); + +/* Data Exchange Functions*/ +DllExport fmiStatus fmiGetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]); +DllExport fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]); +DllExport fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]); +DllExport fmiStatus fmiGetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]); + +DllExport fmiStatus fmiSetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]); +DllExport fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]); +DllExport fmiStatus fmiSetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]); +DllExport fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]); + +/*************************************************** +Functions for FMI for Co-Simulation +****************************************************/ + +/* Creation and destruction of slave instances and setting debug status */ +DllExport fmiComponent fmiInstantiateSlave(fmiString instanceName, + fmiString fmuGUID, + fmiString fmuLocation, + fmiString mimeType, + fmiReal timeout, + fmiBoolean visible, + fmiBoolean interactive, + fmiCallbackFunctions functions, + fmiBoolean loggingOn); + +DllExport fmiStatus fmiInitializeSlave(fmiComponent c, + fmiReal tStart, + fmiBoolean StopTimeDefined, + fmiReal tStop); + +DllExport fmiStatus fmiTerminateSlave(fmiComponent c); +DllExport fmiStatus fmiResetSlave(fmiComponent c); +DllExport void fmiFreeSlaveInstance(fmiComponent c); + +DllExport fmiStatus fmiSetRealInputDerivatives(fmiComponent c, + const fmiValueReference vr[], + size_t nvr, + const fmiInteger order[], + const fmiReal value[]); + +DllExport fmiStatus fmiGetRealOutputDerivatives(fmiComponent c, + const fmiValueReference vr[], + size_t nvr, + const fmiInteger order[], + fmiReal value[]); + +DllExport fmiStatus fmiCancelStep(fmiComponent c); +DllExport fmiStatus fmiDoStep(fmiComponent c, + fmiReal currentCommunicationPoint, + fmiReal communicationStepSize, + fmiBoolean newStep); + +typedef enum { fmiDoStepStatus, + fmiPendingStatus, + fmiLastSuccessfulTime } fmiStatusKind; + +DllExport fmiStatus fmiGetStatus(fmiComponent c, const fmiStatusKind s, fmiStatus *value); +DllExport fmiStatus fmiGetRealStatus(fmiComponent c, const fmiStatusKind s, fmiReal *value); +DllExport fmiStatus fmiGetIntegerStatus(fmiComponent c, const fmiStatusKind s, fmiInteger *value); +DllExport fmiStatus fmiGetBooleanStatus(fmiComponent c, const fmiStatusKind s, fmiBoolean *value); +DllExport fmiStatus fmiGetStringStatus(fmiComponent c, const fmiStatusKind s, fmiString *value); + +#endif // fmiFunctions_h diff --git a/oscillator/fmi/fmu/include/fmiModelFunctions.h b/oscillator/fmi/fmu/include/fmiModelFunctions.h new file mode 100644 index 000000000..092495138 --- /dev/null +++ b/oscillator/fmi/fmu/include/fmiModelFunctions.h @@ -0,0 +1,207 @@ +#ifndef fmiModelFunctions_h +#define fmiModelFunctions_h + +/* This header file must be utilized when compiling a model. + It defines all functions of the Model Execution Interface. + In order to have unique function names even if several models + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by + "MODEL_IDENTIFIER" + "_" where "MODEL_IDENTIFIER" is the short name + of the model used as the name of the zip-file where the model is stored. + Therefore, the typical usage is: + + #define MODEL_IDENTIFIER MyModel + #include "fmiModelFunctions.h" + + As a result, a function that is defined as "fmiGetDerivatives" in this header file, + is actually getting the name "MyModel_fmiGetDerivatives". + + Revisions: + - Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27) + (by M. Otter, DLR) + Added WIN32 pragma to define the struct layout (ticket #34) + (by J. Mauss, QTronic) + - Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize + Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion + Renamed macro fmiModelFunctionsVersion to fmiVersion + Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel + (by J. Mauss, QTronic) + - Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR). + - Dez. 14, 2009: Added eventInfo to meInitialize and added + meGetNominalContinuousStates (by Martin Otter, DLR) + - Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion) + (by A. Junghanns, QTronic) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + meInquireModelTypesVersion -> meGetModelTypesPlatform + meInquireModelFunctionsVersion -> meGetModelFunctionsVersion + meSetStates -> meSetContinuousStates + meGetStates -> meGetContinuousStates + removal of meInitializeModelClass + removal of meGetTime + change of arguments of meInstantiateModel + change of arguments of meCompletedIntegratorStep + (by Martin Otter, DLR): + - July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR). + - March 2, 2009: Changed function definitions according to the last design + meeting with additional improvements (by Martin Otter, DLR). + - Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim). + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- + + with the extension: + + You may distribute or publicly perform any modification only under the + terms of this license. +*/ + +#include +#include "fmiModelTypes.h" + +/* Export fmi functions on Windows */ +#ifdef _MSC_VER +#define DllExport __declspec(dllexport) +#else +#define DllExport +#endif + +/* Macros to construct the real function name + (prepend function name by MODEL_IDENTIFIER + "_") */ + +#define fmiPaste(a, b) a##b +#define fmiPasteB(a, b) fmiPaste(a, b) +#define fmiFullName(name) fmiPasteB(MODEL_IDENTIFIER, name) + +#define fmiGetModelTypesPlatform fmiFullName(_fmiGetModelTypesPlatform) +#define fmiGetVersion fmiFullName(_fmiGetVersion) +#define fmiInstantiateModel fmiFullName(_fmiInstantiateModel) +#define fmiFreeModelInstance fmiFullName(_fmiFreeModelInstance) +#define fmiSetDebugLogging fmiFullName(_fmiSetDebugLogging) +#define fmiSetTime fmiFullName(_fmiSetTime) +#define fmiSetContinuousStates fmiFullName(_fmiSetContinuousStates) +#define fmiCompletedIntegratorStep fmiFullName(_fmiCompletedIntegratorStep) +#define fmiSetReal fmiFullName(_fmiSetReal) +#define fmiSetInteger fmiFullName(_fmiSetInteger) +#define fmiSetBoolean fmiFullName(_fmiSetBoolean) +#define fmiSetString fmiFullName(_fmiSetString) +#define fmiInitialize fmiFullName(_fmiInitialize) +#define fmiGetDerivatives fmiFullName(_fmiGetDerivatives) +#define fmiGetEventIndicators fmiFullName(_fmiGetEventIndicators) +#define fmiGetReal fmiFullName(_fmiGetReal) +#define fmiGetInteger fmiFullName(_fmiGetInteger) +#define fmiGetBoolean fmiFullName(_fmiGetBoolean) +#define fmiGetString fmiFullName(_fmiGetString) +#define fmiEventUpdate fmiFullName(_fmiEventUpdate) +#define fmiGetContinuousStates fmiFullName(_fmiGetContinuousStates) +#define fmiGetNominalContinuousStates fmiFullName(_fmiGetNominalContinuousStates) +#define fmiGetStateValueReferences fmiFullName(_fmiGetStateValueReferences) +#define fmiTerminate fmiFullName(_fmiTerminate) + +/* Version number */ +#define fmiVersion "1.0" + +/* Inquire version numbers of header files */ +DllExport const char *fmiGetModelTypesPlatform(); +DllExport const char *fmiGetVersion(); + +/* make sure all compiler use the same alignment policies for structures */ +#ifdef WIN32 +#pragma pack(push, 8) +#endif + +/* Type definitions */ +typedef enum { fmiOK, + fmiWarning, + fmiDiscard, + fmiError, + fmiFatal } fmiStatus; + +typedef void (*fmiCallbackLogger)(fmiComponent c, fmiString instanceName, fmiStatus status, + fmiString category, fmiString message, ...); +typedef void *(*fmiCallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmiCallbackFreeMemory)(void *obj); + +typedef struct { + fmiCallbackLogger logger; + fmiCallbackAllocateMemory allocateMemory; + fmiCallbackFreeMemory freeMemory; +} fmiCallbackFunctions; + +typedef struct { + fmiBoolean iterationConverged; + fmiBoolean stateValueReferencesChanged; + fmiBoolean stateValuesChanged; + fmiBoolean terminateSimulation; + fmiBoolean upcomingTimeEvent; + fmiReal nextEventTime; +} fmiEventInfo; + +/* reset alignment policy to the one set before reading this file */ +#ifdef WIN32 +#pragma pack(pop) +#endif + +/* Creation and destruction of model instances and setting debug status */ +DllExport fmiComponent fmiInstantiateModel(fmiString instanceName, + fmiString GUID, + fmiCallbackFunctions functions, + fmiBoolean loggingOn); +DllExport void fmiFreeModelInstance(fmiComponent c); +DllExport fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn); + +/* Providing independent variables and re-initialization of caching */ +DllExport fmiStatus fmiSetTime(fmiComponent c, fmiReal time); +DllExport fmiStatus fmiSetContinuousStates(fmiComponent c, const fmiReal x[], size_t nx); +DllExport fmiStatus fmiCompletedIntegratorStep(fmiComponent c, fmiBoolean *callEventUpdate); +DllExport fmiStatus fmiSetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]); +DllExport fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]); +DllExport fmiStatus fmiSetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]); +DllExport fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]); + +/* Evaluation of the model equations */ +DllExport fmiStatus fmiInitialize(fmiComponent c, fmiBoolean toleranceControlled, + fmiReal relativeTolerance, fmiEventInfo *eventInfo); + +DllExport fmiStatus fmiGetDerivatives(fmiComponent c, fmiReal derivatives[], size_t nx); +DllExport fmiStatus fmiGetEventIndicators(fmiComponent c, fmiReal eventIndicators[], size_t ni); + +DllExport fmiStatus fmiGetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]); +DllExport fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]); +DllExport fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]); +DllExport fmiStatus fmiGetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]); + +DllExport fmiStatus fmiEventUpdate(fmiComponent c, fmiBoolean intermediateResults, fmiEventInfo *eventInfo); +DllExport fmiStatus fmiGetContinuousStates(fmiComponent c, fmiReal states[], size_t nx); +DllExport fmiStatus fmiGetNominalContinuousStates(fmiComponent c, fmiReal x_nominal[], size_t nx); +DllExport fmiStatus fmiGetStateValueReferences(fmiComponent c, fmiValueReference vrx[], size_t nx); +DllExport fmiStatus fmiTerminate(fmiComponent c); + +#endif // fmiModelFunctions_h diff --git a/oscillator/fmi/fmu/include/fmiModelTypes.h b/oscillator/fmi/fmu/include/fmiModelTypes.h new file mode 100644 index 000000000..5adfcf919 --- /dev/null +++ b/oscillator/fmi/fmu/include/fmiModelTypes.h @@ -0,0 +1,91 @@ +#ifndef fmiModelTypes_h +#define fmiModelTypes_h + +/* Standard header file to define the argument types of the + functions of the Model Execution Interface. + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic) + - Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent" + according to meeting on Dec. 18 (by Martin Otter, DLR) + - Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + Changed "version" to "platform", "standard" to "standard32", + Added a precise definition of "standard32" as comment + (by Martin Otter, DLR) + - July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse, + and changed meValueReferenced from int to unsigned int + (by Martin Otter, DLR). + - March 2, 2009: Moved enums and function pointer definitions to + ModelFunctions.h (by Martin Otter, DLR). + - Dec. 3, 2008 : First version by Martin Otter (DLR) and + Hans Olsson (Dynasim). + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html) + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- + + with the extension: + + You may distribute or publicly perform any modification only under the + terms of this license. +*/ + +/* Platform (combination of machine, compiler, operating system) */ +#define fmiModelTypesPlatform "standard32" + +/* Type definitions of variables passed as arguments + Version "standard32" means: + + fmiComponent : 32 bit pointer + fmiValueReference: 32 bit + fmiReal : 64 bit + fmiInteger : 32 bit + fmiBoolean : 8 bit + fmiString : 32 bit pointer + +*/ +typedef void * fmiComponent; +typedef unsigned int fmiValueReference; +typedef double fmiReal; +typedef int fmiInteger; +typedef char fmiBoolean; +typedef const char * fmiString; + +/* Values for fmiBoolean */ +#define fmiTrue 1 +#define fmiFalse 0 + +/* Undefined value for fmiValueReference (largest unsigned int value) */ +#define fmiUndefinedValueReference (fmiValueReference)(-1) + +#endif diff --git a/oscillator/fmi/fmu/include/fmiPlatformTypes.h b/oscillator/fmi/fmu/include/fmiPlatformTypes.h new file mode 100644 index 000000000..2e36b9043 --- /dev/null +++ b/oscillator/fmi/fmu/include/fmiPlatformTypes.h @@ -0,0 +1,73 @@ +#ifndef fmiPlatformTypes_h +#define fmiPlatformTypes_h + +/* Standard header file to define the argument types of the + functions of the Model Execution Interface. + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - October 2010: First public Version + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +/* Platform (combination of machine, compiler, operating system) */ +#define fmiPlatform "standard32" + +/* Type definitions of variables passed as arguments + Version "standard32" means: + + fmiComponent : 32 bit pointer + fmiValueReference: 32 bit + fmiReal : 64 bit + fmiInteger : 32 bit + fmiBoolean : 8 bit + fmiString : 32 bit pointer + +*/ +typedef void * fmiComponent; +typedef unsigned int fmiValueReference; +typedef double fmiReal; +typedef int fmiInteger; +typedef char fmiBoolean; +typedef const char * fmiString; + +/* Values for fmiBoolean */ +#define fmiTrue 1 +#define fmiFalse 0 + +/* Undefined value for fmiValueReference (largest unsigned int value) */ +#define fmiUndefinedValueReference (fmiValueReference)(-1) + +#endif diff --git a/oscillator/fmi/fmu/include/model.h b/oscillator/fmi/fmu/include/model.h new file mode 100644 index 000000000..88c294854 --- /dev/null +++ b/oscillator/fmi/fmu/include/model.h @@ -0,0 +1,235 @@ +#pragma once + +#if FMI_VERSION != 1 && FMI_VERSION != 2 && FMI_VERSION != 3 +#error FMI_VERSION must be one of 1, 2 or 3 +#endif + +#define UNUSED(x) (void) (x) + +#include // for bool +#include // for size_t +#include + +#include "config.h" + +#if FMI_VERSION == 1 + +#define not_modelError (Instantiated | Initialized | Terminated) + +typedef enum { + Instantiated = 1 << 0, + Initialized = 1 << 1, + Terminated = 1 << 2, + modelError = 1 << 3 +} ModelState; + +#elif FMI_VERSION == 2 + +typedef enum { + StartAndEnd = 1 << 0, + Instantiated = 1 << 1, + InitializationMode = 1 << 2, + + // ME states + EventMode = 1 << 3, + ContinuousTimeMode = 1 << 4, + + // CS states + StepComplete = 1 << 5, + StepInProgress = 1 << 6, + StepFailed = 1 << 7, + StepCanceled = 1 << 8, + + Terminated = 1 << 9, + modelError = 1 << 10, + modelFatal = 1 << 11, +} ModelState; + +#else + +typedef enum { + StartAndEnd = 1 << 0, + ConfigurationMode = 1 << 1, + Instantiated = 1 << 2, + InitializationMode = 1 << 3, + EventMode = 1 << 4, + ContinuousTimeMode = 1 << 5, + StepMode = 1 << 6, + ClockActivationMode = 1 << 7, + StepDiscarded = 1 << 8, + ReconfigurationMode = 1 << 9, + IntermediateUpdateMode = 1 << 10, + Terminated = 1 << 11, + modelError = 1 << 12, + modelFatal = 1 << 13, +} ModelState; + +#endif + +typedef enum { + ModelExchange, + CoSimulation, + ScheduledExecution, +} InterfaceType; + +typedef enum { + OK, + Warning, + Discard, + Error, + Fatal, + Pending +} Status; + +#if FMI_VERSION < 3 +typedef void (*loggerType)(void *componentEnvironment, const char *instanceName, int status, const char *category, const char *message, ...); +#else +typedef void (*loggerType)(void *componentEnvironment, int status, const char *category, const char *message); +#endif + +typedef void (*lockPreemptionType)(); +typedef void (*unlockPreemptionType)(); + +typedef void (*intermediateUpdateType)(void * instanceEnvironment, + double intermediateUpdateTime, + bool intermediateVariableSetRequested, + bool intermediateVariableGetAllowed, + bool intermediateStepFinished, + bool canReturnEarly, + bool * earlyReturnRequested, + double *earlyReturnTime); + +typedef void (*clockUpdateType)(void *instanceEnvironment); + +typedef struct { + + double startTime; + double time; + double solverStepSize; + const char * instanceName; + InterfaceType type; + const char * resourceLocation; + + Status status; + + // callback functions + loggerType logger; + intermediateUpdateType intermediateUpdate; + clockUpdateType clockUpdate; + + lockPreemptionType lockPreemtion; + unlockPreemptionType unlockPreemtion; + + bool logEvents; + bool logErrors; + + void * componentEnvironment; + ModelState state; + + // event info + bool newDiscreteStatesNeeded; + bool terminateSimulation; + bool nominalsOfContinuousStatesChanged; + bool valuesOfContinuousStatesChanged; + bool nextEventTimeDefined; + double nextEventTime; + bool clocksTicked; + + bool isDirtyValues; + + ModelData modelData; + +#if NZ > 0 + // event indicators + double z[NZ]; +#endif + + // internal solver steps + uint64_t nSteps; + + // Co-Simulation + bool earlyReturnAllowed; + bool eventModeUsed; + +} ModelInstance; + +ModelInstance *createModelInstance( + loggerType logger, + intermediateUpdateType intermediateUpdate, + void * componentEnvironment, + const char * instanceName, + const char * instantiationToken, + const char * resourceLocation, + bool loggingOn, + InterfaceType interfaceType); + +void freeModelInstance(ModelInstance *comp); + +void reset(ModelInstance *comp); + +void setStartValues(ModelInstance *comp); + +Status calculateValues(ModelInstance *comp); + +Status getFloat32(ModelInstance *comp, ValueReference vr, float value[], size_t *index); +Status getFloat64(ModelInstance *comp, ValueReference vr, double value[], size_t *index); +Status getInt8(ModelInstance *comp, ValueReference vr, int8_t value[], size_t *index); +Status getUInt8(ModelInstance *comp, ValueReference vr, uint8_t value[], size_t *index); +Status getInt16(ModelInstance *comp, ValueReference vr, int16_t value[], size_t *index); +Status getUInt16(ModelInstance *comp, ValueReference vr, uint16_t value[], size_t *index); +Status getInt32(ModelInstance *comp, ValueReference vr, int32_t value[], size_t *index); +Status getUInt32(ModelInstance *comp, ValueReference vr, uint32_t value[], size_t *index); +Status getInt64(ModelInstance *comp, ValueReference vr, int64_t value[], size_t *index); +Status getUInt64(ModelInstance *comp, ValueReference vr, uint64_t value[], size_t *index); +Status getBoolean(ModelInstance *comp, ValueReference vr, bool value[], size_t *index); +Status getString(ModelInstance *comp, ValueReference vr, const char *value[], size_t *index); +Status getBinary(ModelInstance *comp, ValueReference vr, size_t size[], const char *value[], size_t *index); + +Status setFloat32(ModelInstance *comp, ValueReference vr, const float value[], size_t *index); +Status setFloat64(ModelInstance *comp, ValueReference vr, const double value[], size_t *index); +Status setInt8(ModelInstance *comp, ValueReference vr, const int8_t value[], size_t *index); +Status setUInt8(ModelInstance *comp, ValueReference vr, const uint8_t value[], size_t *index); +Status setInt16(ModelInstance *comp, ValueReference vr, const int16_t value[], size_t *index); +Status setUInt16(ModelInstance *comp, ValueReference vr, const uint16_t value[], size_t *index); +Status setInt32(ModelInstance *comp, ValueReference vr, const int32_t value[], size_t *index); +Status setUInt32(ModelInstance *comp, ValueReference vr, const uint32_t value[], size_t *index); +Status setInt64(ModelInstance *comp, ValueReference vr, const int64_t value[], size_t *index); +Status setUInt64(ModelInstance *comp, ValueReference vr, const uint64_t value[], size_t *index); +Status setBoolean(ModelInstance *comp, ValueReference vr, const bool value[], size_t *index); +Status setString(ModelInstance *comp, ValueReference vr, const char *const value[], size_t *index); +Status setBinary(ModelInstance *comp, ValueReference vr, const size_t size[], const char *const value[], size_t *index); + +Status activateClock(ModelInstance *comp, ValueReference vr); +Status getClock(ModelInstance *comp, ValueReference vr, bool *value); +Status setClock(ModelInstance *comp, ValueReference vr, const bool *value); + +Status getInterval(ModelInstance *comp, ValueReference vr, double *interval, int *qualifier); + +Status activateModelPartition(ModelInstance *comp, ValueReference vr, double activationTime); + +void getContinuousStates(ModelInstance *comp, double x[], size_t nx); +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx); +void getDerivatives(ModelInstance *comp, double dx[], size_t nx); +Status getOutputDerivative(ModelInstance *comp, ValueReference valueReference, int order, double *value); +Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative); +void getEventIndicators(ModelInstance *comp, double z[], size_t nz); +void eventUpdate(ModelInstance *comp); +//void updateEventTime(ModelInstance *comp); + +bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected); +bool invalidState(ModelInstance *comp, const char *f, int statesExpected); +bool nullPointer(ModelInstance *comp, const char *f, const char *arg, const void *p); +void logError(ModelInstance *comp, const char *message, ...); +Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char *const categories[]); +void logEvent(ModelInstance *comp, const char *message, ...); +void logError(ModelInstance *comp, const char *message, ...); + +void *getFMUState(ModelInstance *comp); +void setFMUState(ModelInstance *comp, void *FMUState); + +// shorthand to access the variables +#define M(u) (comp->modelData.u) + +// "stringification" macros +#define xstr(s) str(s) +#define str(s) #s diff --git a/oscillator/fmi/fmu/set_tool_version.py b/oscillator/fmi/fmu/set_tool_version.py new file mode 100644 index 000000000..ba855c9cc --- /dev/null +++ b/oscillator/fmi/fmu/set_tool_version.py @@ -0,0 +1,45 @@ +import os.path +import subprocess +import sys + + +def set_tool_version(filename, git_executable='git'): + """ Set the Git tag or hash in the generationTool attribute if the repo is clean """ + + cwd = os.path.dirname(__file__) + + changed_files = subprocess.check_output( + [git_executable, 'status', '--porcelain', '--untracked=no'], cwd=cwd).decode('ascii').strip() + + if changed_files: + return + + version = subprocess.check_output([git_executable, 'tag', '--contains'], cwd=cwd).decode('ascii').strip() + + if not version: + version = subprocess.check_output([git_executable, 'rev-parse', '--short', + 'HEAD'], cwd=cwd).decode('ascii').strip() + + if not version: + return + + with open(filename, 'r') as f: + lines = f.read() + + lines = lines.replace('"Reference FMUs (development build)"', f'"Reference FMUs ({version})"') + + with open(filename, 'w') as f: + f.write(lines) + + +if __name__ == '__main__': + + try: + if len(sys.argv) > 2: + set_tool_version(sys.argv[1], sys.argv[2]) + elif len(sys.argv) > 1: + set_tool_version(sys.argv[1]) + else: + raise RuntimeError('Not enough arguments') + except Exception as e: + print(e) diff --git a/oscillator/fmi/fmu/src/FMI.c b/oscillator/fmi/fmu/src/FMI.c new file mode 100644 index 000000000..579946515 --- /dev/null +++ b/oscillator/fmi/fmu/src/FMI.c @@ -0,0 +1,329 @@ +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#pragma comment(lib, "shlwapi.lib") +#else +#include +#include +#endif + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +#include "FMI.h" + +#define INITIAL_MESSAGE_BUFFER_SIZE 1024 + +FMIInstance *FMICreateInstance(const char *instanceName, const char *libraryPath, FMILogMessage *logMessage, FMILogFunctionCall *logFunctionCall) +{ + +#ifdef _WIN32 + TCHAR Buffer[1024]; + GetCurrentDirectory(1024, Buffer); + + WCHAR dllDirectory[MAX_PATH]; + + // convert path to unicode + mbstowcs(dllDirectory, libraryPath, MAX_PATH); + + // remove the file name + PathRemoveFileSpecW(dllDirectory); + + // add the binaries directory temporarily to the DLL path to allow discovery of dependencies + DLL_DIRECTORY_COOKIE dllDirectoryCookie = AddDllDirectory(dllDirectory); + + // TODO: log getLastSystemError() + + HMODULE libraryHandle = LoadLibraryExA(libraryPath, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + + // remove the binaries directory from the DLL path + if (dllDirectoryCookie) { + RemoveDllDirectory(dllDirectoryCookie); + } + + // TODO: log error + +#else + void *libraryHandle = dlopen(libraryPath, RTLD_LAZY); +#endif + + if (!libraryHandle) { + return NULL; + } + + FMIInstance *instance = (FMIInstance *) calloc(1, sizeof(FMIInstance)); + + instance->libraryHandle = libraryHandle; + + instance->logMessage = logMessage; + instance->logFunctionCall = logFunctionCall; + + instance->bufsize1 = INITIAL_MESSAGE_BUFFER_SIZE; + instance->bufsize2 = INITIAL_MESSAGE_BUFFER_SIZE; + + instance->buf1 = (char *) calloc(instance->bufsize1, sizeof(char)); + instance->buf2 = (char *) calloc(instance->bufsize1, sizeof(char)); + + instance->name = strdup(instanceName); + + instance->status = FMIOK; + + return instance; +} + +void FMIFreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return; + } + + // unload the shared library + if (instance->libraryHandle) { +#ifdef _WIN32 + FreeLibrary(instance->libraryHandle); +#else + dlclose(instance->libraryHandle); +#endif + instance->libraryHandle = NULL; + } + + free(instance->buf1); + free(instance->buf2); + free((void *) instance->name); + + free(instance->fmi2Functions); + free(instance->fmi3Functions); + + free(instance); +} + +const char *FMIValueReferencesToString(FMIInstance *instance, const FMIValueReference vr[], size_t nvr) +{ + + size_t pos = 0; + + do { + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, "{"); + + for (size_t i = 0; i < nvr; i++) { + + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, i < nvr - 1 ? "%u, " : "%u", vr[i]); + + if (pos > instance->bufsize1 - 2) { + pos = 0; + instance->bufsize1 *= 2; + instance->buf1 = (char *) realloc(instance->buf1, instance->bufsize1); + break; + } + } + } while (pos == 0); + + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, "}"); + + return instance->buf1; +} + +const char *FMIValuesToString(FMIInstance *instance, size_t vValues, const size_t sizes[], const void *values, FMIVariableType variableType) +{ + + size_t pos = 0; + + do { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "{"); + + for (size_t i = 0; i < vValues; i++) { + + char * s = &instance->buf2[pos]; + size_t n = instance->bufsize2 - pos; + + switch (variableType) { + case FMIFloat32Type: + case FMIDiscreteFloat32Type: + pos += snprintf(s, n, "%.7g", ((float *) values)[i]); + break; + case FMIFloat64Type: + case FMIDiscreteFloat64Type: + pos += snprintf(s, n, "%.16g", ((double *) values)[i]); + break; + case FMIInt8Type: + pos += snprintf(s, n, "%" PRId8, ((int8_t *) values)[i]); + break; + case FMIUInt8Type: + pos += snprintf(s, n, "%" PRIu8, ((uint8_t *) values)[i]); + break; + case FMIInt16Type: + pos += snprintf(s, n, "%" PRId16, ((int16_t *) values)[i]); + break; + case FMIUInt16Type: + pos += snprintf(s, n, "%" PRIu16, ((uint16_t *) values)[i]); + break; + case FMIInt32Type: + pos += snprintf(s, n, "%" PRId32, ((int32_t *) values)[i]); + break; + case FMIUInt32Type: + pos += snprintf(s, n, "%" PRIu32, ((uint32_t *) values)[i]); + break; + case FMIInt64Type: + pos += snprintf(s, n, "%" PRId64, ((int64_t *) values)[i]); + break; + case FMIUInt64Type: + pos += snprintf(s, n, "%" PRIu64, ((uint64_t *) values)[i]); + break; + case FMIBooleanType: + switch (instance->fmiVersion) { + case FMIVersion1: + pos += snprintf(s, n, "%d", ((char *) values)[i]); + break; + case FMIVersion2: + pos += snprintf(s, n, "%d", ((int *) values)[i]); + break; + case FMIVersion3: + pos += snprintf(s, n, "%d", ((bool *) values)[i]); + break; + } + break; + case FMIStringType: + pos += snprintf(s, n, "\"%s\"", ((const char **) values)[i]); + break; + case FMIBinaryType: { + const size_t size = sizes[i]; + const unsigned char *v = ((const unsigned char **) values)[i]; + for (size_t j = 0; j < size; j++) { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "%02hhx", v[j]); + } + break; + } + case FMIClockType: + pos += snprintf(s, n, "%d", ((bool *) values)[i]); + break; + } + + if (i < vValues - 1) { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, ", "); + } + + // resize the buffer if we ran out of space + if (pos > instance->bufsize2 - 2) { + pos = 0; + instance->bufsize2 *= 2; + instance->buf2 = (char *) realloc(instance->buf2, instance->bufsize2); + break; + } + } + + } while (pos == 0); // run again if the buffer has been resized + + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "}"); + + return instance->buf2; +} + +FMIStatus FMIURIToPath(const char *uri, char *path, const size_t pathLength) +{ + +#ifdef _WIN32 + DWORD pcchPath = (DWORD) pathLength; + + if (PathCreateFromUrlA(uri, path, &pcchPath, 0) != S_OK) { + return FMIError; + } +#else + const char *scheme1 = "file:///"; + const char *scheme2 = "file:/"; + + strncpy(path, uri, pathLength); + + if (strncmp(uri, scheme1, strlen(scheme1)) == 0) { + strncpy(path, &uri[strlen(scheme1)] - 1, pathLength); + } else if (strncmp(uri, scheme2, strlen(scheme2)) == 0) { + strncpy(path, &uri[strlen(scheme2) - 1], pathLength); + } else { + return FMIError; + } +#endif + +#ifdef _WIN32 + const char *sep = "\\"; +#else + const char *sep = "/"; +#endif + + if (path[strlen(path) - 1] != sep[0]) { + strncat(path, sep, pathLength); + } + + return FMIOK; +} + +FMIStatus FMIPathToURI(const char *path, char *uri, const size_t uriLength) +{ + +#ifdef _WIN32 + DWORD pcchUri = (DWORD) uriLength; + + if (UrlCreateFromPathA(path, uri, &pcchUri, 0) != S_OK) { + return FMIError; + } +#else + snprintf(uri, uriLength, "file://%s", path); + + if (path[strlen(path) - 1] != '/') { + strncat(uri, "/", uriLength); + } +#endif + + return FMIOK; +} + +FMIStatus FMIPlatformBinaryPath(const char *unzipdir, const char *modelIdentifier, FMIVersion fmiVersion, char *platformBinaryPath, size_t size) +{ + +#if defined(_WIN32) + const char *platform = "win"; + const char *system = "windows"; + const char sep = '\\'; + const char *ext = ".dll"; +#elif defined(__APPLE__) + const char *platform = "darwin"; + const char *system = "darwin"; + const char sep = '/'; + const char *ext = ".dylib"; +#else + const char *platform = "linux"; + const char *system = "linux"; + const char sep = '/'; + const char *ext = ".so"; +#endif + +#if defined(_WIN64) || defined(__x86_64__) + const char *bits = "64"; + const char *arch = "x86_64"; +#else + const char *bits = "32"; + const char *arch = "x86"; +#endif + const char *bin = "binaries"; + char optSep[2] = ""; + int rc; + + if (unzipdir[strlen(unzipdir) - 1] != sep) { + optSep[0] = sep; + } + if (fmiVersion == 3) { + rc = snprintf(platformBinaryPath, size, "%s%s%s%c%s-%s%c%s%s", unzipdir, optSep, bin, sep, arch, system, sep, modelIdentifier, ext); + } else { + rc = snprintf(platformBinaryPath, size, "%s%s%s%c%s%s%c%s%s", unzipdir, optSep, bin, sep, platform, bits, sep, modelIdentifier, ext); + } + + if (rc >= size) { + return FMIError; + } + + return FMIOK; +} diff --git a/oscillator/fmi/fmu/src/FMI2.c b/oscillator/fmi/fmu/src/FMI2.c new file mode 100644 index 000000000..106b530a6 --- /dev/null +++ b/oscillator/fmi/fmu/src/FMI2.c @@ -0,0 +1,569 @@ +#ifdef _WIN32 +#include +#include "Shlwapi.h" +#pragma comment(lib, "shlwapi.lib") +#define strdup _strdup +#define INTERNET_MAX_URL_LENGTH 2083 // from wininet.h +#else +#include +#include +#endif + +#include +#include +#include + +#include "FMI2.h" + +static void cb_logMessage2(fmi2ComponentEnvironment componentEnvironment, fmi2String instanceName, fmi2Status status, fmi2String category, fmi2String message, ...) +{ + + if (!componentEnvironment) + return; + + FMIInstance *instance = componentEnvironment; + + char buf[FMI_MAX_MESSAGE_LENGTH]; + + va_list args; + + va_start(args, message); + vsnprintf(buf, FMI_MAX_MESSAGE_LENGTH, message, args); + va_end(args); + + if (!instance->logMessage) + return; + + instance->logMessage(instance, (FMIStatus) status, category, buf); +} + +#if defined(FMI2_FUNCTION_PREFIX) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = fmi2##f; \ + } while (0) +#elif defined(_WIN32) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = (fmi2##f##TYPE *) GetProcAddress(instance->libraryHandle, "fmi2" #f); \ + if (!instance->fmi2Functions->fmi2##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi2" #f " is missing in shared library."); \ + return fmi2Fatal; \ + } \ + } while (0) +#else +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = (fmi2##f##TYPE *) dlsym(instance->libraryHandle, "fmi2" #f); \ + if (!instance->fmi2Functions->fmi2##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi2" #f " is missing in shared library."); \ + return FMIFatal; \ + } \ + } while (0) +#endif + +#define CALL(f) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##f(instance->component); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi2" #f "()"); \ + } \ + return status; \ + } while (0) + +#define CALL_ARGS(f, m, ...) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##f(instance->component, __VA_ARGS__); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi2" #f "(" m ")", __VA_ARGS__); \ + } \ + return status; \ + } while (0) + +#define CALL_ARRAY(s, t) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##s##t(instance->component, vr, nvr, value); \ + if (instance->logFunctionCall) { \ + FMIValueReferencesToString(instance, vr, nvr); \ + FMIValuesToString(instance, nvr, NULL, value, FMI##t##Type); \ + instance->logFunctionCall(instance, status, "fmi2" #s #t "(vr=%s, nvr=%zu, value=%s)", instance->buf1, nvr, instance->buf2); \ + } \ + return status; \ + } while (0) + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +const char *FMI2GetTypesPlatform(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2GetTypesPlatform()"); + } + return instance->fmi2Functions->fmi2GetTypesPlatform(); +} + +const char *FMI2GetVersion(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2GetVersion()"); + } + return instance->fmi2Functions->fmi2GetVersion(); +} + +FMIStatus FMI2SetDebugLogging(FMIInstance *instance, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SetDebugLogging(instance->component, loggingOn, nCategories, categories); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nCategories, NULL, categories, FMIStringType); + instance->logFunctionCall(instance, status, "fmi2SetDebugLogging(loggingOn=%d, nCategories=%zu, categories=%s)", + loggingOn, nCategories, instance->buf2); + } + return status; +} + +/* Creation and destruction of FMU instances and setting debug status */ +FMIStatus FMI2Instantiate(FMIInstance *instance, const char *fmuResourceLocation, fmi2Type fmuType, fmi2String fmuGUID, + fmi2Boolean visible, fmi2Boolean loggingOn) +{ + + instance->fmiVersion = FMIVersion2; + + instance->fmi2Functions = calloc(1, sizeof(FMI2Functions)); + + if (!instance->fmi2Functions) { + return FMIError; + } + + instance->fmi2Functions->eventInfo.newDiscreteStatesNeeded = fmi2False; + instance->fmi2Functions->eventInfo.terminateSimulation = fmi2False; + instance->fmi2Functions->eventInfo.nominalsOfContinuousStatesChanged = fmi2False; + instance->fmi2Functions->eventInfo.valuesOfContinuousStatesChanged = fmi2False; + instance->fmi2Functions->eventInfo.nextEventTimeDefined = fmi2False; + instance->fmi2Functions->eventInfo.nextEventTime = 0.0; + + instance->state = FMI2StartAndEndState; + +#if !defined(FMI_VERSION) || FMI_VERSION == 2 + + /*************************************************** + Common Functions + ****************************************************/ + + /* required functions */ + LOAD_SYMBOL(GetTypesPlatform); + LOAD_SYMBOL(GetVersion); + LOAD_SYMBOL(SetDebugLogging); + LOAD_SYMBOL(Instantiate); + LOAD_SYMBOL(FreeInstance); + LOAD_SYMBOL(SetupExperiment); + LOAD_SYMBOL(EnterInitializationMode); + LOAD_SYMBOL(ExitInitializationMode); + LOAD_SYMBOL(Terminate); + LOAD_SYMBOL(Reset); + LOAD_SYMBOL(GetReal); + LOAD_SYMBOL(GetInteger); + LOAD_SYMBOL(GetBoolean); + LOAD_SYMBOL(GetString); + LOAD_SYMBOL(SetReal); + LOAD_SYMBOL(SetInteger); + LOAD_SYMBOL(SetBoolean); + LOAD_SYMBOL(SetString); + + /* optional functions */ + LOAD_SYMBOL(GetFMUstate); + LOAD_SYMBOL(SetFMUstate); + LOAD_SYMBOL(FreeFMUstate); + LOAD_SYMBOL(SerializedFMUstateSize); + LOAD_SYMBOL(SerializeFMUstate); + LOAD_SYMBOL(DeSerializeFMUstate); + LOAD_SYMBOL(GetDirectionalDerivative); + + if (fmuType == fmi2ModelExchange) { +#ifndef CO_SIMULATION + /*************************************************** + Model Exchange + ****************************************************/ + + LOAD_SYMBOL(EnterEventMode); + LOAD_SYMBOL(NewDiscreteStates); + LOAD_SYMBOL(EnterContinuousTimeMode); + LOAD_SYMBOL(CompletedIntegratorStep); + LOAD_SYMBOL(SetTime); + LOAD_SYMBOL(SetContinuousStates); + LOAD_SYMBOL(GetDerivatives); + LOAD_SYMBOL(GetEventIndicators); + LOAD_SYMBOL(GetContinuousStates); + LOAD_SYMBOL(GetNominalsOfContinuousStates); +#endif + } else { +#ifndef MODEL_EXCHANGE + /*************************************************** + Co-Simulation + ****************************************************/ + + LOAD_SYMBOL(SetRealInputDerivatives); + LOAD_SYMBOL(GetRealOutputDerivatives); + LOAD_SYMBOL(DoStep); + LOAD_SYMBOL(CancelStep); + LOAD_SYMBOL(GetStatus); + LOAD_SYMBOL(GetRealStatus); + LOAD_SYMBOL(GetIntegerStatus); + LOAD_SYMBOL(GetBooleanStatus); + LOAD_SYMBOL(GetStringStatus); +#endif + } + +#endif + + instance->fmi2Functions->callbacks.logger = cb_logMessage2; + instance->fmi2Functions->callbacks.allocateMemory = calloc; + instance->fmi2Functions->callbacks.freeMemory = free; + instance->fmi2Functions->callbacks.stepFinished = NULL; + instance->fmi2Functions->callbacks.componentEnvironment = instance; + + instance->component = instance->fmi2Functions->fmi2Instantiate(instance->name, fmuType, fmuGUID, fmuResourceLocation, &instance->fmi2Functions->callbacks, visible, loggingOn); + + if (instance->logFunctionCall) { + fmi2CallbackFunctions *f = &instance->fmi2Functions->callbacks; + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi2Instantiate(instanceName=\"%s\", fmuType=%d, fmuGUID=\"%s\", fmuResourceLocation=\"%s\", functions={logger=0x%p, allocateMemory=0x%p, freeMemory=0x%p, stepFinished=0x%p, componentEnvironment=0x%p}, visible=%d, loggingOn=%d)", + instance->name, fmuType, fmuGUID, fmuResourceLocation, f->logger, f->allocateMemory, f->freeMemory, f->stepFinished, f->componentEnvironment, visible, loggingOn); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = (FMIInterfaceType) fmuType; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +void FMI2FreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return; + } + + instance->fmi2Functions->fmi2FreeInstance(instance->component); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2FreeInstance()"); + } +} + +/* Enter and exit initialization mode, terminate and reset */ +FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime) +{ + + instance->time = startTime; + + CALL_ARGS(SetupExperiment, "toleranceDefined=%d, tolerance=%.16g, startTime=%.16g, stopTimeDefined=%d, stopTime=%.16g", toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); +} + +FMIStatus FMI2EnterInitializationMode(FMIInstance *instance) +{ + instance->state = FMI2InitializationModeState; + CALL(EnterInitializationMode); +} + +FMIStatus FMI2ExitInitializationMode(FMIInstance *instance) +{ + instance->state = instance->interfaceType == FMIModelExchange ? FMI2EventModeState : FMI2StepCompleteState; + CALL(ExitInitializationMode); +} + +FMIStatus FMI2Terminate(FMIInstance *instance) +{ + instance->state = FMI2TerminatedState; + CALL(Terminate); +} + +FMIStatus FMI2Reset(FMIInstance *instance) +{ + instance->state = FMI2InstantiatedState; + CALL(Reset); +} + +/* Getting and setting variable values */ +FMIStatus FMI2GetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) +{ + CALL_ARRAY(Get, Real); +} + +FMIStatus FMI2GetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) +{ + CALL_ARRAY(Get, Integer); +} + +FMIStatus FMI2GetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) +{ + CALL_ARRAY(Get, Boolean); +} + +FMIStatus FMI2GetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) +{ + CALL_ARRAY(Get, String); +} + +FMIStatus FMI2SetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) +{ + CALL_ARRAY(Set, Real); +} + +FMIStatus FMI2SetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) +{ + CALL_ARRAY(Set, Integer); +} + +FMIStatus FMI2SetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) +{ + CALL_ARRAY(Set, Boolean); +} + +FMIStatus FMI2SetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) +{ + CALL_ARRAY(Set, String); +} + +/* Getting and setting the internal FMU state */ +FMIStatus FMI2GetFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(GetFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2SetFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate) +{ + CALL_ARGS(SetFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2FreeFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(FreeFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2SerializedFMUstateSize(FMIInstance *instance, fmi2FMUstate FMUstate, size_t *size) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SerializedFMUstateSize(instance->component, FMUstate, size); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2SerializedFMUstateSize(FMUstate=0x%p, size=%zu)", FMUstate, *size); + } + return status; +} + +FMIStatus FMI2SerializeFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) +{ + CALL_ARGS(SerializeFMUstate, "FMUstate=0x%p, serializedState=0x%p, size=%zu", FMUstate, serializedState, size); +} + +FMIStatus FMI2DeSerializeFMUstate(FMIInstance *instance, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(DeSerializeFMUstate, "serializedState=0x%p, size=%zu, FMUstate=0x%p", serializedState, size, FMUstate); +} + +/* Getting partial derivatives */ +FMIStatus FMI2GetDirectionalDerivative(FMIInstance * instance, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]) +{ + CALL_ARGS(GetDirectionalDerivative, "vUnknown_ref=0x%p, nUnknown=%zu, vKnown_ref=0x%p, nKnown=%zu, dvKnown=0x%p, dvUnknown=0x%p", + vUnknown_ref, nUnknown, vKnown_ref, nKnown, dvKnown, dvUnknown); +} + +/*************************************************** +Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMIStatus FMI2EnterEventMode(FMIInstance *instance) +{ + instance->state = FMI2EventModeState; + CALL(EnterEventMode); +} + +FMIStatus FMI2NewDiscreteStates(FMIInstance *instance, fmi2EventInfo *eventInfo) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2NewDiscreteStates(instance->component, eventInfo); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi2NewDiscreteStates(eventInfo={newDiscreteStatesNeeded=%d, terminateSimulation=%d, nominalsOfContinuousStatesChanged=%d, valuesOfContinuousStatesChanged=%d, nextEventTimeDefined=%d, nextEventTime=%.16g})", + eventInfo->newDiscreteStatesNeeded, eventInfo->terminateSimulation, eventInfo->nominalsOfContinuousStatesChanged, eventInfo->valuesOfContinuousStatesChanged, eventInfo->nextEventTimeDefined, eventInfo->nextEventTime); + } + return status; +} + +FMIStatus FMI2EnterContinuousTimeMode(FMIInstance *instance) +{ + instance->state = FMI2ContinuousTimeModeState; + CALL(EnterContinuousTimeMode); +} + +FMIStatus FMI2CompletedIntegratorStep(FMIInstance *instance, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2CompletedIntegratorStep(instance->component, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2CompletedIntegratorStep(noSetFMUStatePriorToCurrentPoint=%d, enterEventMode=%d, terminateSimulation=%d)", noSetFMUStatePriorToCurrentPoint, *enterEventMode, *terminateSimulation); + } + return status; +} + +/* Providing independent variables and re-initialization of caching */ +FMIStatus FMI2SetTime(FMIInstance *instance, fmi2Real time) +{ + instance->time = time; + CALL_ARGS(SetTime, "time=%.16g", time); +} + +FMIStatus FMI2SetContinuousStates(FMIInstance *instance, const fmi2Real x[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SetContinuousStates(instance->component, x, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2SetContinuousStates(x=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +/* Evaluation of the model equations */ +FMIStatus FMI2GetDerivatives(FMIInstance *instance, fmi2Real derivatives[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetDerivatives(instance->component, derivatives, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, derivatives, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetDerivatives(derivatives=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +FMIStatus FMI2GetEventIndicators(FMIInstance *instance, fmi2Real eventIndicators[], size_t ni) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetEventIndicators(instance->component, eventIndicators, ni); + if (instance->logFunctionCall) { + FMIValuesToString(instance, ni, NULL, eventIndicators, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetEventIndicators(eventIndicators=%s, ni=%zu)", instance->buf2, ni); + } + return status; +} + +FMIStatus FMI2GetContinuousStates(FMIInstance *instance, fmi2Real x[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetContinuousStates(instance->component, x, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetContinuousStates(x=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +FMIStatus FMI2GetNominalsOfContinuousStates(FMIInstance *instance, fmi2Real x_nominal[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetNominalsOfContinuousStates(instance->component, x_nominal, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x_nominal, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetNominalsOfContinuousStates(x_nominal=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +/*************************************************** +Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMIStatus FMI2SetRealInputDerivatives(FMIInstance * instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]) +{ + CALL_ARGS(SetRealInputDerivatives, "vr=0x%p, nvr=%zu, order=0x%p, value=0x%p", vr, nvr, order, value); +} + +FMIStatus FMI2GetRealOutputDerivatives(FMIInstance * instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]) +{ + CALL_ARGS(GetRealOutputDerivatives, "vr=0x%p, nvr=%zu, order=0x%p, value=0x%p", vr, nvr, order, value); +} + +FMIStatus FMI2DoStep(FMIInstance *instance, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint) +{ + + instance->time = currentCommunicationPoint + communicationStepSize; + + CALL_ARGS(DoStep, "currentCommunicationPoint=%.16g, communicationStepSize=%.16g, noSetFMUStatePriorToCurrentPoint=%d", + currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); +} + +FMIStatus FMI2CancelStep(FMIInstance *instance) +{ + CALL(CancelStep); +} + +/* Inquire slave status */ +FMIStatus FMI2GetStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Status *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetRealStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Real *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetRealStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetRealStatus(s=%d, value=%.16g)", s, *value); + } + return status; +} + +FMIStatus FMI2GetIntegerStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Integer *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetIntegerStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetIntegerStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetBooleanStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Boolean *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetBooleanStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetBooleanStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetStringStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2String *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetStringStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetStringStatus(s=%d, value=%s)", s, *value); + } + return status; +} + +#undef LOAD_SYMBOL +#undef CALL +#undef CALL_ARGS +#undef CALL_ARRAY diff --git a/oscillator/fmi/fmu/src/FMI3.c b/oscillator/fmi/fmu/src/FMI3.c new file mode 100644 index 000000000..4c3b20d7b --- /dev/null +++ b/oscillator/fmi/fmu/src/FMI3.c @@ -0,0 +1,1186 @@ +#ifdef _WIN32 +#include +#include "Shlwapi.h" +#pragma comment(lib, "shlwapi.lib") +#else +#include +#include +#endif + +#include +#include +#include + +#include "FMI3.h" + +static void cb_logMessage3(fmi3InstanceEnvironment instanceEnvironment, + fmi3Status status, + fmi3String category, + fmi3String message) +{ + + if (!instanceEnvironment) + return; + + FMIInstance *instance = instanceEnvironment; + + if (!instance->logMessage) + return; + + instance->logMessage(instance, (FMIStatus) status, category, message); +} + +#if defined(FMI2_FUNCTION_PREFIX) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = fmi3##f; \ + } while (0) +#elif defined(_WIN32) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = (fmi3##f##TYPE *) GetProcAddress(instance->libraryHandle, "fmi3" #f); \ + if (!instance->fmi3Functions->fmi3##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi3" #f " is missing in shared library."); \ + return fmi3Fatal; \ + } \ + } while (0) +#else +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = (fmi3##f##TYPE *) dlsym(instance->libraryHandle, "fmi3" #f); \ + if (!instance->fmi3Functions->fmi3##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi3" #f " is missing in shared library."); \ + return FMIFatal; \ + } \ + } while (0) +#endif + +#define CALL(f) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##f(instance->component); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi3" #f "()"); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +#define CALL_ARGS(f, m, ...) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##f(instance->component, __VA_ARGS__); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi3" #f "(" m ")", __VA_ARGS__); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +#define CALL_ARRAY(s, t) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##s##t(instance->component, valueReferences, nValueReferences, values, nValues); \ + if (instance->logFunctionCall) { \ + FMIValueReferencesToString(instance, valueReferences, nValueReferences); \ + FMIValuesToString(instance, nValues, NULL, values, FMI##t##Type); \ + instance->logFunctionCall(instance, status, "fmi3" #s #t "(valueReferences=%s, nValueReferences=%zu, values=%s, nValues=%zu)", instance->buf1, nValueReferences, instance->buf2, nValues); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +const char *FMI3GetVersion(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi3GetVersion()"); + } + return instance->fmi3Functions->fmi3GetVersion(); +} + +FMIStatus FMI3SetDebugLogging(FMIInstance * instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]) +{ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetDebugLogging(instance->component, loggingOn, nCategories, categories); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nCategories, NULL, categories, FMIStringType); + instance->logFunctionCall(instance, status, "fmi3SetDebugLogging(loggingOn=%d, nCategories=%zu, categories=%s)", + loggingOn, nCategories, instance->buf2); + } + return status; +} + +static FMIStatus loadSymbols3(FMIInstance *instance) +{ + +#if !defined(FMI_VERSION) || FMI_VERSION == 3 + + instance->fmi3Functions = calloc(1, sizeof(FMI3Functions)); + + if (!instance->fmi3Functions) { + return FMIError; + } + + instance->fmiVersion = FMIVersion3; + + /*************************************************** + Common Functions + ****************************************************/ + + /* Inquire version numbers and set debug logging */ + LOAD_SYMBOL(GetVersion); + LOAD_SYMBOL(SetDebugLogging); + + /* Creation and destruction of FMU instances */ + LOAD_SYMBOL(InstantiateModelExchange); + LOAD_SYMBOL(InstantiateCoSimulation); + LOAD_SYMBOL(InstantiateScheduledExecution); + LOAD_SYMBOL(FreeInstance); + + /* Enter and exit initialization mode, terminate and reset */ + LOAD_SYMBOL(EnterInitializationMode); + LOAD_SYMBOL(ExitInitializationMode); + LOAD_SYMBOL(EnterEventMode); + LOAD_SYMBOL(Terminate); + LOAD_SYMBOL(Reset); + + /* Getting and setting variable values */ + LOAD_SYMBOL(GetFloat32); + LOAD_SYMBOL(GetFloat64); + LOAD_SYMBOL(GetInt8); + LOAD_SYMBOL(GetUInt8); + LOAD_SYMBOL(GetInt16); + LOAD_SYMBOL(GetUInt16); + LOAD_SYMBOL(GetInt32); + LOAD_SYMBOL(GetUInt32); + LOAD_SYMBOL(GetInt64); + LOAD_SYMBOL(GetUInt64); + LOAD_SYMBOL(GetBoolean); + LOAD_SYMBOL(GetString); + LOAD_SYMBOL(GetBinary); + LOAD_SYMBOL(GetClock); + LOAD_SYMBOL(SetFloat32); + LOAD_SYMBOL(SetFloat64); + LOAD_SYMBOL(SetInt8); + LOAD_SYMBOL(SetUInt8); + LOAD_SYMBOL(SetInt16); + LOAD_SYMBOL(SetUInt16); + LOAD_SYMBOL(SetInt32); + LOAD_SYMBOL(SetUInt32); + LOAD_SYMBOL(SetInt64); + LOAD_SYMBOL(SetUInt64); + LOAD_SYMBOL(SetBoolean); + LOAD_SYMBOL(SetString); + LOAD_SYMBOL(SetBinary); + LOAD_SYMBOL(SetClock); + + /* Getting Variable Dependency Information */ + LOAD_SYMBOL(GetNumberOfVariableDependencies); + LOAD_SYMBOL(GetVariableDependencies); + + /* Getting and setting the internal FMU state */ + LOAD_SYMBOL(GetFMUState); + LOAD_SYMBOL(SetFMUState); + LOAD_SYMBOL(FreeFMUState); + LOAD_SYMBOL(SerializedFMUStateSize); + LOAD_SYMBOL(SerializeFMUState); + LOAD_SYMBOL(DeserializeFMUState); + + /* Getting partial derivatives */ + LOAD_SYMBOL(GetDirectionalDerivative); + LOAD_SYMBOL(GetAdjointDerivative); + + /* Entering and exiting the Configuration or Reconfiguration Mode */ + LOAD_SYMBOL(EnterConfigurationMode); + LOAD_SYMBOL(ExitConfigurationMode); + + /* Clock related functions */ + LOAD_SYMBOL(GetIntervalDecimal); + LOAD_SYMBOL(GetIntervalFraction); + LOAD_SYMBOL(GetShiftDecimal); + LOAD_SYMBOL(GetShiftFraction); + LOAD_SYMBOL(SetIntervalDecimal); + LOAD_SYMBOL(SetIntervalFraction); + LOAD_SYMBOL(EvaluateDiscreteStates); + LOAD_SYMBOL(UpdateDiscreteStates); + + /*************************************************** + Functions for Model Exchange + ****************************************************/ + + LOAD_SYMBOL(EnterContinuousTimeMode); + LOAD_SYMBOL(CompletedIntegratorStep); + + /* Providing independent variables and re-initialization of caching */ + LOAD_SYMBOL(SetTime); + LOAD_SYMBOL(SetContinuousStates); + + /* Evaluation of the model equations */ + LOAD_SYMBOL(GetContinuousStateDerivatives); + LOAD_SYMBOL(GetEventIndicators); + LOAD_SYMBOL(GetContinuousStates); + LOAD_SYMBOL(GetNominalsOfContinuousStates); + LOAD_SYMBOL(GetNumberOfEventIndicators); + LOAD_SYMBOL(GetNumberOfContinuousStates); + + /*************************************************** + Functions for Co-Simulation + ****************************************************/ + + /* Simulating the FMU */ + LOAD_SYMBOL(EnterStepMode); + LOAD_SYMBOL(GetOutputDerivatives); + LOAD_SYMBOL(DoStep); + LOAD_SYMBOL(ActivateModelPartition); + + instance->state = FMI2StartAndEndState; + + return FMIOK; + +#else + + return FMIError; + +#endif +} + +/* Creation and destruction of FMU instances and setting debug status */ +FMIStatus FMI3InstantiateModelExchange( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn) +{ + + FMIStatus status = loadSymbols3(instance); + + fmi3LogMessageCallback logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateModelExchange(instance->name, instantiationToken, resourcePath, visible, loggingOn, instance, logMessage); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateModelExchange(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + logMessage); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMIModelExchange; + instance->state = FMI2InstantiatedState; + + return status; +} + +FMIStatus FMI3InstantiateCoSimulation( + FMIInstance * instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3IntermediateUpdateCallback intermediateUpdate) +{ + + if (loadSymbols3(instance) != FMIOK) { + return FMIFatal; + } + + fmi3LogMessageCallback logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateCoSimulation( + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + eventModeUsed, + earlyReturnAllowed, + requiredIntermediateVariables, + nRequiredIntermediateVariables, + instance, + logMessage, + intermediateUpdate); + + instance->fmi3Functions->eventModeUsed = eventModeUsed; + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateCoSimulation(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "eventModeUsed=%d, " + "earlyReturnAllowed=%d, " + "requiredIntermediateVariables=0x%p, " + "nRequiredIntermediateVariables=%zu, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p, " + "intermediateUpdate=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + eventModeUsed, + earlyReturnAllowed, + requiredIntermediateVariables, + nRequiredIntermediateVariables, + instance, + logMessage, + intermediateUpdate); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMICoSimulation; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +FMIStatus FMI3InstantiateScheduledExecution( + FMIInstance * instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption) +{ + + if (loadSymbols3(instance) != FMIOK) { + return FMIError; + } + + fmi3LogMessageCallback _logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateScheduledExecution( + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + _logMessage, + clockUpdate, + lockPreemption, + unlockPreemption); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateScheduledExecution(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p, " + "clockUpdate=0x%p, " + "lockPreemption=0x%p, " + "unlockPreemption=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + _logMessage, + clockUpdate, + lockPreemption, + unlockPreemption); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMIScheduledExecution; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +FMIStatus FMI3FreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return FMIError; + } + + instance->fmi3Functions->fmi3FreeInstance(instance->component); + + instance->component = NULL; + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi3FreeInstance()"); + } + + return FMIOK; +} + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +FMIStatus FMI3EnterInitializationMode(FMIInstance *instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime) +{ + + instance->state = FMI2InitializationModeState; + + CALL_ARGS(EnterInitializationMode, + "fmi3EnterInitializationMode(toleranceDefined=%d, tolerance=%.16g, startTime=%.16g, stopTimeDefined=%d, stopTime=%.16g)", + toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); +} + +FMIStatus FMI3ExitInitializationMode(FMIInstance *instance) +{ + + if (instance->interfaceType == FMIModelExchange || (instance->fmiVersion == FMIVersion3 && instance->interfaceType == FMICoSimulation && instance->fmi3Functions->eventModeUsed)) { + instance->state = FMI2EventModeState; + } else { + instance->state = FMI2StepCompleteState; + } + + CALL(ExitInitializationMode); +} + +FMIStatus FMI3EnterEventMode(FMIInstance *instance) +{ + instance->state = FMI2EventModeState; + CALL(EnterEventMode); +} + +FMIStatus FMI3Terminate(FMIInstance *instance) +{ + instance->state = FMI2TerminatedState; + CALL(Terminate); +} + +FMIStatus FMI3Reset(FMIInstance *instance) +{ + instance->state = FMI2InstantiatedState; + CALL(Reset); +} + +/* Getting and setting variable values */ +FMIStatus FMI3GetFloat32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Float32); +} + +FMIStatus FMI3GetFloat64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Float64); +} + +FMIStatus FMI3GetInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int8); +} + +FMIStatus FMI3GetUInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt8); +} + +FMIStatus FMI3GetInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int16); +} + +FMIStatus FMI3GetUInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt16); +} + +FMIStatus FMI3GetInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int32); +} + +FMIStatus FMI3GetUInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt32); +} + +FMIStatus FMI3GetInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int64); +} + +FMIStatus FMI3GetUInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt64); +} + +FMIStatus FMI3GetBoolean(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues) +{ + CALL_ARRAY(Get, Boolean); +} + +FMIStatus FMI3GetString(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues) +{ + CALL_ARRAY(Get, String); +} + +FMIStatus FMI3GetBinary(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t sizes[], + fmi3Binary values[], + size_t nValues) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetBinary(instance->component, valueReferences, nValueReferences, sizes, values, nValues); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValues, sizes, values, FMIBinaryType); + instance->logFunctionCall(instance, status, "fmi3GetBinary(valueReferences=%s, nValueReferences=%zu, sizes=%p, values=%s, nValues=%zu)", instance->buf1, nValueReferences, sizes, instance->buf2, nValues); + } + + return status; +} + +FMIStatus FMI3GetClock(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetClock(instance->component, valueReferences, nValueReferences, values); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValueReferences, NULL, values, FMIClockType); + instance->logFunctionCall(instance, status, "fmi3GetClock(valueReferences=%s, nValueReferences=%zu, values=%s)", instance->buf1, nValueReferences, instance->buf2); + } + + return status; +} + +FMIStatus FMI3SetFloat32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Float32); +} + +FMIStatus FMI3SetFloat64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Float64); +} + +FMIStatus FMI3SetInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int8); +} + +FMIStatus FMI3SetUInt8(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt8); +} + +FMIStatus FMI3SetInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int16); +} + +FMIStatus FMI3SetUInt16(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt16); +} + +FMIStatus FMI3SetInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int32); +} + +FMIStatus FMI3SetUInt32(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt32); +} + +FMIStatus FMI3SetInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int64); +} + +FMIStatus FMI3SetUInt64(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt64); +} + +FMIStatus FMI3SetBoolean(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues) +{ + CALL_ARRAY(Set, Boolean); +} + +FMIStatus FMI3SetString(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues) +{ + CALL_ARRAY(Set, String); +} + +FMIStatus FMI3SetBinary(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t sizes[], + const fmi3Binary values[], + size_t nValues) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetBinary(instance->component, valueReferences, nValueReferences, sizes, values, nValues); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValues, sizes, values, FMIBinaryType); + instance->logFunctionCall(instance, status, "fmi3SetBinary(valueReferences=%s, nValueReferences=%zu, sizes=0x%p, values=%s, nValues=%zu", instance->buf1, nValueReferences, sizes, instance->buf2, nValues); + } + + return status; +} + +FMIStatus FMI3SetClock(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetClock(instance->component, valueReferences, nValueReferences, values); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValueReferences, NULL, values, FMIClockType); + instance->logFunctionCall(instance, status, "fmi3SetClock(valueReferences=%s, nValueReferences=%zu, values=%s)", instance->buf1, nValueReferences, instance->buf2); + } + + return status; +} + +/* Getting Variable Dependency Information */ +FMIStatus FMI3GetNumberOfVariableDependencies(FMIInstance * instance, + fmi3ValueReference valueReference, + size_t * nDependencies) +{ + CALL_ARGS(GetNumberOfVariableDependencies, "valueReference=%u, nDependencies=0x%p", valueReference, nDependencies); +} + +FMIStatus FMI3GetVariableDependencies(FMIInstance * instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies) +{ + CALL_ARGS(GetVariableDependencies, "dependent=%u, elementIndicesOfDependent=0x%p, independents=0x%p, elementIndicesOfIndependents=0x%p, dependencyKinds=0x%p, nDependencies=%zu", + dependent, elementIndicesOfDependent, independents, elementIndicesOfIndependents, dependencyKinds, nDependencies); +} + +/* Getting and setting the internal FMU state */ +FMIStatus FMI3GetFMUState(FMIInstance *instance, fmi3FMUState *FMUState) +{ + CALL_ARGS(GetFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3SetFMUState(FMIInstance *instance, fmi3FMUState FMUState) +{ + CALL_ARGS(SetFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3FreeFMUState(FMIInstance *instance, fmi3FMUState *FMUState) +{ + CALL_ARGS(FreeFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3SerializedFMUStateSize(FMIInstance *instance, + fmi3FMUState FMUState, + size_t * size) +{ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SerializedFMUStateSize(instance->component, FMUState, size); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi3SerializedFMUStateSize(FMUState=0x%p, size=%zu)", FMUState, *size); + } + return status; +} + +FMIStatus FMI3SerializeFMUState(FMIInstance *instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size) +{ + CALL_ARGS(SerializeFMUState, "FMUstate=0x%p, serializedState=0x%p, size=%zu", FMUState, serializedState, size); +} + +FMIStatus FMI3DeserializeFMUState(FMIInstance * instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState * FMUState) +{ + CALL_ARGS(DeserializeFMUState, "serializedState=0x%p, size=%zu, FMUState=0x%p", serializedState, size, FMUState); +} + +/* Getting partial derivatives */ +FMIStatus FMI3GetDirectionalDerivative(FMIInstance * instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + CALL_ARGS(GetDirectionalDerivative, + "unknowns=0x%p, nUnknowns=%zu, knowns=0x%p, nKnowns=%zu, seed=0x%p, nSeed=%zu, sensitivity=0x%p, nSensitivity=%zu", + unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity); +} + +FMIStatus FMI3GetAdjointDerivative(FMIInstance * instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + CALL_ARGS(GetAdjointDerivative, + "unknowns=0x%p, nUnknowns=%zu, knowns=0x%p, nKnowns=%zu, seed=0x%p, nSeed=%zu, sensitivity=0x%p, nSensitivity=%zu", + unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity); +} + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMIStatus FMI3EnterConfigurationMode(FMIInstance *instance) +{ + CALL(EnterConfigurationMode); +} + +FMIStatus FMI3ExitConfigurationMode(FMIInstance *instance) +{ + CALL(ExitConfigurationMode); +} + +/* Clock related functions */ + +FMI_STATIC FMIStatus FMI3GetIntervalDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]) +{ + CALL_ARGS(GetIntervalDecimal, + "valueReferences=0x%p, nValueReferences=%zu, intervals=0x%p, qualifiers=0x%p", + valueReferences, nValueReferences, intervals, qualifiers); +} + +FMIStatus FMI3GetIntervalFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]) +{ + CALL_ARGS(GetIntervalFraction, + "valueReferences=0x%p, nValueReferences=%zu, intervalCounters=0x%p, resolutions=0x%p, qualifiers=%d", + valueReferences, nValueReferences, intervalCounters, resolutions, qualifiers); +} + +FMIStatus FMI3GetShiftDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]) +{ + CALL_ARGS(GetShiftDecimal, + "valueReferences=0x%p, nValueReferences=%zu, shifts=0x%p", + valueReferences, nValueReferences, shifts); +} + +FMIStatus FMI3GetShiftFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]) +{ + CALL_ARGS(GetShiftFraction, + "valueReferences=0x%p, nValueReferences=%zu, shiftCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, shiftCounters, resolutions); +} + +FMIStatus FMI3SetIntervalDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]) +{ + CALL_ARGS(SetIntervalDecimal, + "valueReferences=0x%p, nValueReferences=%zu, intervals=0x%p", + valueReferences, nValueReferences, intervals); +} + +FMIStatus FMI3SetIntervalFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]) +{ + CALL_ARGS(SetIntervalFraction, + "valueReferences=0x%p, nValueReferences=%zu, intervalCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, intervalCounters, resolutions); +} + +FMIStatus FMI3SetShiftDecimal(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]) +{ + CALL_ARGS(SetShiftDecimal, + "valueReferences=0x%p, nValueReferences=%zu, shifts=0x%p", + valueReferences, nValueReferences, shifts); +} + +FMIStatus FMI3SetShiftFraction(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]) +{ + CALL_ARGS(SetShiftFraction, + "valueReferences=0x%p, nValueReferences=%zu, shiftCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, shiftCounters, resolutions); +} + +FMIStatus FMI3EvaluateDiscreteStates(FMIInstance *instance) +{ + CALL(EvaluateDiscreteStates); +} + +FMIStatus FMI3UpdateDiscreteStates(FMIInstance *instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3UpdateDiscreteStates(instance->component, discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3UpdateDiscreteStates(discreteStatesNeedUpdate=%d, terminateSimulation=%d, nominalsOfContinuousStatesChanged=%d, valuesOfContinuousStatesChanged=%d, nextEventTimeDefined=%d, nextEventTime=%.16g)", + *discreteStatesNeedUpdate, *terminateSimulation, *nominalsOfContinuousStatesChanged, *valuesOfContinuousStatesChanged, *nextEventTimeDefined, *nextEventTime); + } + + return status; +} + +/*************************************************** +Types for Functions for Model Exchange +****************************************************/ + +FMIStatus FMI3EnterContinuousTimeMode(FMIInstance *instance) +{ + instance->state = FMI2ContinuousTimeModeState; + CALL(EnterContinuousTimeMode); +} + +FMIStatus FMI3CompletedIntegratorStep(FMIInstance *instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3CompletedIntegratorStep(instance->component, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3CompletedIntegratorStep(noSetFMUStatePriorToCurrentPoint=%d, enterEventMode=%d, terminateSimulation=%d)", + noSetFMUStatePriorToCurrentPoint, *enterEventMode, *terminateSimulation); + } + + return status; +} + +/* Providing independent variables and re-initialization of caching */ +FMIStatus FMI3SetTime(FMIInstance *instance, fmi3Float64 time) +{ + instance->time = time; + CALL_ARGS(SetTime, "time=%.16g", time); +} + +FMIStatus FMI3SetContinuousStates(FMIInstance * instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetContinuousStates(instance->component, continuousStates, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, continuousStates, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3SetContinuousStates(continuousStates=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +/* Evaluation of the model equations */ +FMIStatus FMI3GetContinuousStateDerivatives(FMIInstance *instance, + fmi3Float64 derivatives[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetContinuousStateDerivatives(instance->component, derivatives, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, derivatives, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetDerivatives(derivatives=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +FMIStatus FMI3GetEventIndicators(FMIInstance *instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetEventIndicators(instance->component, eventIndicators, nEventIndicators); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nEventIndicators, NULL, eventIndicators, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetEventIndicators(eventIndicators=%s, nEventIndicators=%zu)", + instance->buf2, nEventIndicators); + } + + return status; +} + +FMIStatus FMI3GetContinuousStates(FMIInstance *instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetContinuousStates(instance->component, continuousStates, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, continuousStates, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetContinuousStates(continuousStates=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +FMIStatus FMI3GetNominalsOfContinuousStates(FMIInstance *instance, + fmi3Float64 nominals[], + size_t nContinuousStates) +{ + CALL_ARGS(GetNominalsOfContinuousStates, "nominals=0x%p, nContinuousStates=%zu", nominals, nContinuousStates); +} + +FMIStatus FMI3GetNumberOfEventIndicators(FMIInstance *instance, + size_t * nEventIndicators) +{ + CALL_ARGS(GetNumberOfEventIndicators, "nEventIndicators=0x%p", nEventIndicators); +} + +FMIStatus FMI3GetNumberOfContinuousStates(FMIInstance *instance, + size_t * nContinuousStates) +{ + CALL_ARGS(GetNumberOfContinuousStates, "nContinuousStates=0x%p", nContinuousStates); +} + +/*************************************************** +Types for Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +FMIStatus FMI3EnterStepMode(FMIInstance *instance) +{ + CALL(EnterStepMode); +} + +FMIStatus FMI3GetOutputDerivatives(FMIInstance * instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues) +{ + CALL_ARGS(GetOutputDerivatives, + "valueReferences=0x%p, nValueReferences=%zu, orders=0x%p, values=0x%p, nValues=%zu", + valueReferences, nValueReferences, orders, values, nValues); +} + +FMIStatus FMI3DoStep(FMIInstance *instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventEncountered, + fmi3Boolean *terminate, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3DoStep(instance->component, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint, eventEncountered, terminate, earlyReturn, lastSuccessfulTime); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3DoStep(currentCommunicationPoint=%.16g, communicationStepSize=%.16g, noSetFMUStatePriorToCurrentPoint=%d, eventEncountered=%d, terminate=%d, earlyReturn=%d, lastSuccessfulTime=%.16g)", + currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint, *eventEncountered, *terminate, *earlyReturn, *lastSuccessfulTime); + } + + instance->time = *lastSuccessfulTime; + + return status; +} + +FMIStatus FMI3ActivateModelPartition(FMIInstance * instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime) +{ + CALL_ARGS(ActivateModelPartition, + "clockReference=%u, activationTime=%.16g", + clockReference, activationTime); +} + +#undef LOAD_SYMBOL +#undef CALL +#undef CALL_ARGS +#undef CALL_ARRAY diff --git a/oscillator/fmi/fmu/src/cosimulation.c b/oscillator/fmi/fmu/src/cosimulation.c new file mode 100644 index 000000000..35fa3a8e4 --- /dev/null +++ b/oscillator/fmi/fmu/src/cosimulation.c @@ -0,0 +1,620 @@ +#include "cosimulation.h" +#include // for DBL_EPSILON +#include // for fabs() +#include +#include +#include // for calloc(), free() +#include +#include "config.h" + +#if FMI_VERSION == 3 +#include "fmi3Functions.h" +#endif + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +ModelInstance *createModelInstance( + loggerType cbLogger, + intermediateUpdateType intermediateUpdate, + void * componentEnvironment, + const char * instanceName, + const char * instantiationToken, + const char * resourceLocation, + bool loggingOn, + InterfaceType interfaceType) +{ + + ModelInstance *comp = NULL; + + if (!instanceName || strlen(instanceName) == 0) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, "?", Error, "error", "Missing instance name."); +#else + cbLogger(componentEnvironment, Error, "error", "Missing instance name."); +#endif + } + return NULL; + } + + if (!instantiationToken || strlen(instantiationToken) == 0) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, instanceName, Error, "error", "Missing GUID."); +#else + cbLogger(componentEnvironment, Error, "error", "Missing instantiationToken."); +#endif + } + return NULL; + } + + if (strcmp(instantiationToken, INSTANTIATION_TOKEN)) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, instanceName, Error, "error", "Wrong GUID."); +#else + cbLogger(componentEnvironment, Error, "error", "Wrong instantiationToken."); +#endif + } + return NULL; + } + + comp = (ModelInstance *) calloc(1, sizeof(ModelInstance)); + + if (comp) { + comp->componentEnvironment = componentEnvironment; + comp->logger = cbLogger; + comp->intermediateUpdate = intermediateUpdate; + comp->lockPreemtion = NULL; + comp->unlockPreemtion = NULL; + comp->instanceName = strdup(instanceName); + comp->resourceLocation = resourceLocation ? strdup(resourceLocation) : NULL; + comp->status = OK; + comp->logEvents = loggingOn; + comp->logErrors = true; // always log errors + comp->nSteps = 0; + comp->solverStepSize = 1e-3; + comp->earlyReturnAllowed = false; + comp->eventModeUsed = false; + } + + if (!comp || !comp->instanceName) { + logError(comp, "Out of memory."); + return NULL; + } + + comp->time = 0.0; // overwrite in fmi*SetupExperiment, fmi*SetTime + comp->type = interfaceType; + + comp->state = Instantiated; + + comp->newDiscreteStatesNeeded = false; + comp->terminateSimulation = false; + comp->nominalsOfContinuousStatesChanged = false; + comp->valuesOfContinuousStatesChanged = false; + comp->nextEventTimeDefined = false; + comp->nextEventTime = 0; + + setStartValues(comp); + + comp->isDirtyValues = true; + + return comp; +} + +void freeModelInstance(ModelInstance *comp) +{ + free((void *) comp->instanceName); + free(comp); +} + +void reset(ModelInstance *comp) +{ + comp->state = Instantiated; + comp->startTime = 0.0; + comp->time = 0.0; + comp->nSteps = 0; + comp->solverStepSize = 1e-3; + comp->status = OK; + setStartValues(comp); + comp->isDirtyValues = true; +} + +bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected) +{ + + if (actual != expected) { + comp->state = modelError; + logError(comp, "%s: Invalid argument %s = %d. Expected %d.", f, arg, actual, expected); + return true; + } + + return false; +} + +bool invalidState(ModelInstance *comp, const char *f, int statesExpected) +{ + + UNUSED(f); + UNUSED(statesExpected); + + if (!comp) { + return true; + } + + // TODO: add missing states and check state + return false; + + // if (!(comp->state & statesExpected)) { + // comp->state = modelError; + // logError(comp, "%s: Illegal call sequence.", f); + // return true; + // } + // + // return false; +} + +bool nullPointer(ModelInstance *comp, const char *f, const char *arg, const void *p) +{ + + if (!p) { + comp->state = modelError; + logError(comp, "%s: Invalid argument %s = NULL.", f, arg); + return true; + } + + return false; +} + +Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char *const categories[]) +{ + + if (loggingOn) { + for (size_t i = 0; i < nCategories; i++) { + if (categories[i] == NULL) { + logError(comp, "Log category[%d] must not be NULL", i); + return Error; + } else if (strcmp(categories[i], "logEvents") == 0) { + comp->logEvents = true; + } else if (strcmp(categories[i], "logStatusError") == 0) { + comp->logErrors = true; + } else { + logError(comp, "Log category[%d] must be one of logEvents or logStatusError but was %s", i, categories[i]); + return Error; + } + } + } else { + // disable logging + comp->logEvents = false; + comp->logErrors = false; + } + + return OK; +} + +static void logMessage(ModelInstance *comp, int status, const char *category, const char *message, va_list args) +{ + + if (!comp->logger) { + return; + } + + va_list args1; + size_t len = 0; + char * buf = ""; + + va_copy(args1, args); + len = vsnprintf(buf, len, message, args1); + va_end(args1); + + va_copy(args1, args); + buf = (char *) calloc(len + 1, sizeof(char)); + vsnprintf(buf, len + 1, message, args); + va_end(args1); + + // no need to distinguish between FMI versions since we're not using variadic arguments +#if FMI_VERSION < 3 + comp->logger(comp->componentEnvironment, comp->instanceName, status, category, buf); +#else + comp->logger(comp->componentEnvironment, status, category, buf); +#endif + + free(buf); +} + +void logEvent(ModelInstance *comp, const char *message, ...) +{ + + if (!comp || !comp->logEvents) + return; + + va_list args; + va_start(args, message); + logMessage(comp, OK, "logEvents", message, args); + va_end(args); +} + +void logError(ModelInstance *comp, const char *message, ...) +{ + + if (!comp || !comp->logErrors) + return; + + va_list args; + va_start(args, message); + logMessage(comp, Error, "logStatusError", message, args); + va_end(args); +} + +// default implementations +#if NZ < 1 +void getEventIndicators(ModelInstance *comp, double z[], size_t nz) +{ + UNUSED(comp); + UNUSED(z); + UNUSED(nz); + // do nothing +} +#endif + +#define GET_NOT_ALLOWED(t) \ + do { \ + UNUSED(vr); \ + UNUSED(value); \ + UNUSED(index); \ + logError(comp, "Getting " t " is not allowed."); \ + return Error; \ + } while (false) + +#ifndef GET_FLOAT32 +Status getFloat32(ModelInstance *comp, ValueReference vr, float value[], size_t *index) +{ + GET_NOT_ALLOWED("Float32"); +} +#endif + +#ifndef GET_INT8 +Status getInt8(ModelInstance *comp, ValueReference vr, int8_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int8"); +} +#endif + +#ifndef GET_UINT8 +Status getUInt8(ModelInstance *comp, ValueReference vr, uint8_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt8"); +} +#endif + +#ifndef GET_INT16 +Status getInt16(ModelInstance *comp, ValueReference vr, int16_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int16"); +} +#endif + +#ifndef GET_UINT16 +Status getUInt16(ModelInstance *comp, ValueReference vr, uint16_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt16"); +} +#endif + +#ifndef GET_INT32 +Status getInt32(ModelInstance *comp, ValueReference vr, int32_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int32"); +} +#endif + +#ifndef GET_UINT32 +Status getUInt32(ModelInstance *comp, ValueReference vr, uint32_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt32"); +} +#endif + +#ifndef GET_INT64 +Status getInt64(ModelInstance *comp, ValueReference vr, int64_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int64"); +} +#endif + +#ifndef GET_UINT64 +Status getUInt64(ModelInstance *comp, ValueReference vr, uint64_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt64"); +} +#endif + +#ifndef GET_BOOLEAN +Status getBoolean(ModelInstance *comp, ValueReference vr, bool value[], size_t *index) +{ + GET_NOT_ALLOWED("Boolean"); +} +#endif + +#ifndef GET_STRING +Status getString(ModelInstance *comp, ValueReference vr, const char *value[], size_t *index) +{ + GET_NOT_ALLOWED("String"); +} +#endif + +#ifndef GET_BINARY +Status getBinary(ModelInstance *comp, ValueReference vr, size_t size[], const char *value[], size_t *index) +{ + UNUSED(size); + GET_NOT_ALLOWED("Binary"); +} +#endif + +#define SET_NOT_ALLOWED(t) \ + do { \ + UNUSED(vr); \ + UNUSED(value); \ + UNUSED(index); \ + logError(comp, "Setting " t " is not allowed."); \ + return Error; \ + } while (false) + +#ifndef SET_FLOAT32 +Status setFloat32(ModelInstance *comp, ValueReference vr, const float value[], size_t *index) +{ + SET_NOT_ALLOWED("Float32"); +} +#endif + +#ifndef SET_FLOAT64 +Status setFloat64(ModelInstance *comp, ValueReference vr, const double value[], size_t *index) +{ + SET_NOT_ALLOWED("Float64"); +} +#endif + +#ifndef SET_INT8 +Status setInt8(ModelInstance *comp, ValueReference vr, const int8_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int8"); +} +#endif + +#ifndef SET_UINT8 +Status setUInt8(ModelInstance *comp, ValueReference vr, const uint8_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt8"); +} +#endif + +#ifndef SET_INT16 +Status setInt16(ModelInstance *comp, ValueReference vr, const int16_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int16"); +} +#endif + +#ifndef SET_UINT16 +Status setUInt16(ModelInstance *comp, ValueReference vr, const uint16_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt16"); +} +#endif + +#ifndef SET_INT32 +Status setInt32(ModelInstance *comp, ValueReference vr, const int32_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int32"); +} +#endif + +#ifndef SET_UINT32 +Status setUInt32(ModelInstance *comp, ValueReference vr, const uint32_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt32"); +} +#endif + +#ifndef SET_INT64 +Status setInt64(ModelInstance *comp, ValueReference vr, const int64_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int64"); +} +#endif + +#ifndef SET_UINT64 +Status setUInt64(ModelInstance *comp, ValueReference vr, const uint64_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt64"); +} +#endif + +#ifndef SET_BOOLEAN +Status setBoolean(ModelInstance *comp, ValueReference vr, const bool value[], size_t *index) +{ + SET_NOT_ALLOWED("Boolean"); +} +#endif + +#ifndef SET_STRING +Status setString(ModelInstance *comp, ValueReference vr, const char *const value[], size_t *index) +{ + SET_NOT_ALLOWED("String"); +} +#endif + +#ifndef SET_BINARY +Status setBinary(ModelInstance *comp, ValueReference vr, const size_t size[], const char *const value[], size_t *index) +{ + UNUSED(size); + SET_NOT_ALLOWED("Binary"); +} +#endif + +#ifndef ACTIVATE_CLOCK +Status activateClock(ModelInstance *comp, ValueReference vr) +{ + UNUSED(comp); + UNUSED(vr); + return Error; +} +#endif + +#ifndef GET_CLOCK +Status getClock(ModelInstance *comp, ValueReference vr, bool *value) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(value); + return Error; +} +#endif + +#ifndef GET_INTERVAL +Status getInterval(ModelInstance *comp, ValueReference vr, double *interval, int *qualifier) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(interval); + UNUSED(qualifier); + return Error; +} +#endif + +#ifndef ACTIVATE_MODEL_PARTITION +Status activateModelPartition(ModelInstance *comp, ValueReference vr, double activationTime) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(activationTime); + return Error; +} +#endif + +#if NX < 1 +void getContinuousStates(ModelInstance *comp, double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(x); + UNUSED(nx); +} + +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(x); + UNUSED(nx); +} + +void getDerivatives(ModelInstance *comp, double dx[], size_t nx) +{ + UNUSED(comp); + UNUSED(dx); + UNUSED(nx); +} +#endif + +#ifndef GET_PARTIAL_DERIVATIVE +Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative) +{ + UNUSED(comp); + UNUSED(unknown); + UNUSED(known); + UNUSED(partialDerivative); + return Error; +} +#endif + +void *getFMUState(ModelInstance *comp) +{ + + ModelInstance *fmuState = (ModelInstance *) calloc(1, sizeof(ModelInstance)); + + memcpy(fmuState, comp, sizeof(ModelInstance)); + + return fmuState; +} + +void setFMUState(ModelInstance *comp, void *FMUState) +{ + + ModelInstance *s = (ModelInstance *) FMUState; + + comp->startTime = s->startTime; + comp->time = s->time; + comp->solverStepSize = s->solverStepSize; + comp->status = s->status; + comp->state = s->state; + comp->newDiscreteStatesNeeded = s->newDiscreteStatesNeeded; + comp->terminateSimulation = s->terminateSimulation; + comp->nominalsOfContinuousStatesChanged = s->nominalsOfContinuousStatesChanged; + comp->valuesOfContinuousStatesChanged = s->valuesOfContinuousStatesChanged; + comp->nextEventTimeDefined = s->nextEventTimeDefined; + comp->nextEventTime = s->nextEventTime; + comp->clocksTicked = s->clocksTicked; + comp->isDirtyValues = s->isDirtyValues; + comp->modelData = s->modelData; +#if NZ > 0 + memcpy(comp->z, s->z, NZ * sizeof(double)); +#endif + comp->nSteps = s->nSteps; +} + +void doFixedStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent) +{ + + UNUSED(comp); + UNUSED(stateEvent); + UNUSED(timeEvent); + logError(comp, "Fixed step not yet implemented. Please use doAlphaStep or implement method."); +} + +void doAlphaStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent) +{ + + // get current time step size + double dt = comp->solverStepSize; + + // create local variables + double t = comp->time; + double m[3] = {0}; + double force_in = M(force_in); + double force_out = 0; + double gamma = 0.5 - M(alpha_m) + M(alpha_f); + double beta = 0.25 * (gamma + 0.5); + double u_new = 0; + double v_new = 0; + double a_new = 0; + double k_bar = 0; + double stiffness = M(spring_fixed_c) + M(spring_middle_c); + + // do generalized alpha step + m[0] = (1 - M(alpha_m)) / (beta * dt * dt); + m[1] = (1 - M(alpha_m)) / (beta * dt); + m[2] = (1 - M(alpha_m) - 2 * beta) / (2 * beta); + + k_bar = stiffness * (1 - M(alpha_f)) + m[0] * M(mass_m); + u_new = (force_in - M(alpha_f) * stiffness * M(mass_u) + M(mass_m) * (m[0] * M(mass_u) + m[1] * M(mass_v) + m[2] * M(mass_a))) / k_bar; + a_new = 1.0 / (beta * dt * dt) * (u_new - M(mass_u) - dt * M(mass_v)) - (1 - 2 * beta) / (2 * beta) * M(mass_a); + v_new = M(mass_v) + dt * ((1 - gamma) * M(mass_a) + gamma * a_new); + + // compute force + force_out = M(spring_middle_c) * u_new; + + // store new values + M(mass_u) = u_new; + M(mass_v) = v_new; + M(mass_a) = a_new; + M(force_out) = force_out; + + // advance time + comp->nSteps++; + comp->time = t + comp->solverStepSize; + + // state event + *stateEvent = false; + UNUSED(timeEvent); +} diff --git a/oscillator/fmi/fmu/src/fmi2Functions.c b/oscillator/fmi/fmu/src/fmi2Functions.c new file mode 100644 index 000000000..c493ef6fb --- /dev/null +++ b/oscillator/fmi/fmu/src/fmi2Functions.c @@ -0,0 +1,923 @@ +#if FMI_VERSION != 2 +#error FMI_VERSION must be 2 +#endif + +#include +#include +#include +#include + +#include "config.h" +#include "cosimulation.h" +#include "model.h" + +// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_. +// Define DISABLE_PREFIX to build a binary FMU. +#ifndef DISABLE_PREFIX +#define pasteA(a, b) a##b +#define pasteB(a, b) pasteA(a, b) +#define FMI2_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _) +#endif +#include "fmi2Functions.h" + +#define ASSERT_NOT_NULL(p) \ + do { \ + if (!p) { \ + logError(S, "Argument %s must not be NULL.", xstr(p)); \ + S->state = modelError; \ + return (fmi2Status) Error; \ + } \ + } while (0) + +#define GET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nvr == 0) \ + return (fmi2Status) status; \ + ASSERT_NOT_NULL(vr); \ + ASSERT_NOT_NULL(value); \ + size_t index = 0; \ + if (S->isDirtyValues) { \ + Status s = calculateValues(S); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + S->isDirtyValues = false; \ + } \ + for (size_t i = 0; i < nvr; i++) { \ + Status s = get##T(S, vr[i], value, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#define SET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nvr == 0) \ + return (fmi2Status) status; \ + ASSERT_NOT_NULL(vr); \ + ASSERT_NOT_NULL(value); \ + size_t index = 0; \ + for (size_t i = 0; i < nvr; i++) { \ + Status s = set##T(S, vr[i], value, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + if (nvr > 0) \ + S->isDirtyValues = true; \ + return (fmi2Status) status; \ + } while (0) + +#define GET_BOOLEAN_VARIABLES \ + do { \ + Status status = OK; \ + for (size_t i = 0; i < nvr; i++) { \ + bool v = false; \ + size_t index = 0; \ + Status s = getBoolean(S, vr[i], &v, &index); \ + value[i] = v; \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#define SET_BOOLEAN_VARIABLES \ + do { \ + Status status = OK; \ + for (size_t i = 0; i < nvr; i++) { \ + bool v = value[i]; \ + size_t index = 0; \ + Status s = setBoolean(S, vr[i], &v, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef DT_EVENT_DETECT +#define DT_EVENT_DETECT 1e-10 +#endif + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for both Model-exchange and Co-simulation +// --------------------------------------------------------------------------- +#define MASK_fmi2GetTypesPlatform (StartAndEnd | Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepInProgress | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2GetVersion MASK_fmi2GetTypesPlatform +#define MASK_fmi2SetDebugLogging (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepInProgress | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2Instantiate (StartAndEnd) +#define MASK_fmi2FreeInstance (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2SetupExperiment Instantiated +#define MASK_fmi2EnterInitializationMode Instantiated +#define MASK_fmi2ExitInitializationMode InitializationMode +#define MASK_fmi2Terminate (EventMode | ContinuousTimeMode | StepComplete | StepFailed) +#define MASK_fmi2Reset MASK_fmi2FreeInstance +#define MASK_fmi2GetReal (InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2GetInteger MASK_fmi2GetReal +#define MASK_fmi2GetBoolean MASK_fmi2GetReal +#define MASK_fmi2GetString MASK_fmi2GetReal +#define MASK_fmi2SetReal (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete) +#define MASK_fmi2SetInteger (Instantiated | InitializationMode | EventMode | StepComplete) +#define MASK_fmi2SetBoolean MASK_fmi2SetInteger +#define MASK_fmi2SetString MASK_fmi2SetInteger +#define MASK_fmi2GetFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2SetFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2FreeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2SerializedFMUstateSize MASK_fmi2FreeInstance +#define MASK_fmi2SerializeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2DeSerializeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2GetDirectionalDerivative (InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for Model-exchange +// --------------------------------------------------------------------------- +#define MASK_fmi2EnterEventMode (EventMode | ContinuousTimeMode) +#define MASK_fmi2NewDiscreteStates EventMode +#define MASK_fmi2EnterContinuousTimeMode EventMode +#define MASK_fmi2CompletedIntegratorStep ContinuousTimeMode +#define MASK_fmi2SetTime (EventMode | ContinuousTimeMode) +#define MASK_fmi2SetContinuousStates ContinuousTimeMode +#define MASK_fmi2GetEventIndicators (InitializationMode | EventMode | ContinuousTimeMode | Terminated | Error) +#define MASK_fmi2GetContinuousStates MASK_fmi2GetEventIndicators +#define MASK_fmi2GetDerivatives (EventMode | ContinuousTimeMode | Terminated | Error) +#define MASK_fmi2GetNominalsOfContinuousStates (Instantiated | EventMode | ContinuousTimeMode | Terminated | Error) + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for Co-simulation +// --------------------------------------------------------------------------- +#define MASK_fmi2SetRealInputDerivatives (Instantiated | InitializationMode | StepComplete) +#define MASK_fmi2GetRealOutputDerivatives (StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2DoStep StepComplete +#define MASK_fmi2CancelStep StepInProgress +#define MASK_fmi2GetStatus (StepComplete | StepInProgress | StepFailed | Terminated) +#define MASK_fmi2GetRealStatus MASK_fmi2GetStatus +#define MASK_fmi2GetIntegerStatus MASK_fmi2GetStatus +#define MASK_fmi2GetBooleanStatus MASK_fmi2GetStatus +#define MASK_fmi2GetStringStatus MASK_fmi2GetStatus + +// shorthand to access the instance +#define S ((ModelInstance *) c) + +#define ASSERT_STATE(S) \ + if (!allowedState(c, MASK_fmi2##S, #S)) \ + return fmi2Error; + +static bool allowedState(ModelInstance *instance, int statesExpected, char *name) +{ + + if (!instance) { + return false; + } + + if (!(instance->state & statesExpected)) { + logError(instance, "fmi2%s: Illegal call sequence.", name); + return false; + } + + return true; +} + +// --------------------------------------------------------------------------- +// FMI functions +// --------------------------------------------------------------------------- + +fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, + fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions, + fmi2Boolean visible, fmi2Boolean loggingOn) +{ + + UNUSED(visible); + + if (!functions || !functions->logger) { + return NULL; + } + + return createModelInstance( + (loggerType) functions->logger, + NULL, + functions->componentEnvironment, + instanceName, + fmuGUID, + fmuResourceLocation, + loggingOn, + (InterfaceType) fmuType); +} + +fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance, + fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) +{ + + UNUSED(toleranceDefined); + UNUSED(tolerance); + UNUSED(stopTimeDefined); + UNUSED(stopTime); + + ASSERT_STATE(SetupExperiment) + + S->startTime = startTime; + S->time = startTime; + + return fmi2OK; +} + +fmi2Status fmi2EnterInitializationMode(fmi2Component c) +{ + + ASSERT_STATE(EnterInitializationMode) + + S->state = InitializationMode; + + return fmi2OK; +} + +fmi2Status fmi2ExitInitializationMode(fmi2Component c) +{ + + ASSERT_STATE(ExitInitializationMode); + + fmi2Status status = fmi2OK; + + // if values were set and no fmi2GetXXX triggered update before, + // ensure calculated values are updated now + if (S->isDirtyValues) { + status = (fmi2Status) calculateValues(S); + S->isDirtyValues = false; + } + + if (S->type == ModelExchange) { + S->state = EventMode; + } else { + S->state = StepComplete; + } + + return status; +} + +fmi2Status fmi2Terminate(fmi2Component c) +{ + + ASSERT_STATE(Terminate) + + S->state = Terminated; + + return fmi2OK; +} + +fmi2Status fmi2Reset(fmi2Component c) +{ + + ASSERT_STATE(Reset); + + reset(S); + + return fmi2OK; +} + +void fmi2FreeInstance(fmi2Component c) +{ + + if (S) { + freeModelInstance(S); + } +} + +// --------------------------------------------------------------------------- +// FMI functions: class methods not depending of a specific model instance +// --------------------------------------------------------------------------- + +const char *fmi2GetVersion() +{ + return fmi2Version; +} + +const char *fmi2GetTypesPlatform() +{ + return fmi2TypesPlatform; +} + +// --------------------------------------------------------------------------- +// FMI functions: logging control, setters and getters for Real, Integer, +// Boolean, String +// --------------------------------------------------------------------------- + +fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) +{ + + ASSERT_STATE(SetDebugLogging) + + return (fmi2Status) setDebugLogging(S, loggingOn, nCategories, categories); +} + +fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) +{ + + ASSERT_STATE(GetReal) + + if (nvr > 0 && nullPointer(S, "fmi2GetReal", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetReal", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(Float64); +} + +fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) +{ + + ASSERT_STATE(GetInteger) + + if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(Int32); +} + +fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) +{ + + ASSERT_STATE(GetBoolean) + + if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_BOOLEAN_VARIABLES; +} + +fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) +{ + + ASSERT_STATE(GetString) + + if (nvr > 0 && nullPointer(S, "fmi2GetString", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetString", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(String); +} + +fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) +{ + + ASSERT_STATE(SetReal) + + if (invalidState(S, "fmi2SetReal", MASK_fmi2SetReal)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetReal", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetReal", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(Float64); +} + +fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) +{ + + ASSERT_STATE(SetInteger) + + if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(Int32); +} + +fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) +{ + + ASSERT_STATE(SetBoolean) + + if (nvr > 0 && nullPointer(S, "fmi2SetBoolean", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetBoolean", "value[]", value)) + return fmi2Error; + + SET_BOOLEAN_VARIABLES; +} + +fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) +{ + + ASSERT_STATE(SetString); + + if (nvr > 0 && nullPointer(S, "fmi2SetString", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetString", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(String); +} + +fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(GetFMUstate); + + *FMUstate = getFMUState(S); + + return fmi2OK; +} + +fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) +{ + + ASSERT_STATE(SetFMUstate); + + if (nullPointer(S, "fmi2SetFMUstate", "FMUstate", FMUstate)) { + return fmi2Error; + } + + setFMUState(S, FMUstate); + + return fmi2OK; +} + +fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(FreeFMUstate); + + free(*FMUstate); + + *FMUstate = NULL; + + return fmi2OK; +} + +fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) +{ + + UNUSED(c); + UNUSED(FMUstate); + + ASSERT_STATE(SerializedFMUstateSize); + + *size = sizeof(ModelInstance); + + return fmi2OK; +} + +fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) +{ + + ASSERT_STATE(SerializeFMUstate); + + if (nullPointer(S, "fmi2SerializeFMUstate", "FMUstate", FMUstate)) { + return fmi2Error; + } + + if (invalidNumber(S, "fmi2SerializeFMUstate", "size", size, sizeof(ModelInstance))) { + return fmi2Error; + } + + memcpy(serializedState, FMUstate, sizeof(ModelInstance)); + + return fmi2OK; +} + +fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(DeSerializeFMUstate); + + if (invalidNumber(S, "fmi2DeSerializeFMUstate", "size", size, sizeof(ModelInstance))) { + return fmi2Error; + } + + if (*FMUstate == NULL) { + *FMUstate = calloc(1, sizeof(ModelInstance)); + } + + memcpy(*FMUstate, serializedState, sizeof(ModelInstance)); + + return fmi2OK; +} + +fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], fmi2Real dvUnknown[]) +{ + + ASSERT_STATE(GetDirectionalDerivative); + + // TODO: check value references + // TODO: assert nUnknowns == nDeltaOfUnknowns + // TODO: assert nKnowns == nDeltaKnowns + + Status status = OK; + + for (size_t i = 0; i < nUnknown; i++) { + dvUnknown[i] = 0; + for (size_t j = 0; j < nKnown; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, vUnknown_ref[i], vKnown_ref[j], &partialDerivative); + status = max(status, s); + if (status > Warning) { + return (fmi2Status) status; + } + dvUnknown[i] += partialDerivative * dvKnown[j]; + } + } + + return fmi2OK; +} + +// --------------------------------------------------------------------------- +// Functions for FMI for Co-Simulation +// --------------------------------------------------------------------------- +/* Simulating the slave */ +fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], const fmi2Real value[]) +{ + + UNUSED(vr); + UNUSED(nvr); + UNUSED(order); + UNUSED(value); + + ASSERT_STATE(SetRealInputDerivatives); + + logError(S, "fmi2SetRealInputDerivatives: ignoring function call." + " This model cannot interpolate inputs: canInterpolateInputs=\"fmi2False\""); + + return fmi2Error; +} + +fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], fmi2Real value[]) +{ + + ASSERT_STATE(GetRealOutputDerivatives); + +#ifdef GET_OUTPUT_DERIVATIVE + Status status = OK; + + for (size_t i = 0; i < nvr; i++) { + const Status s = getOutputDerivative(S, vr[i], order[i], &value[i]); + status = max(status, s); + if (status > Warning) { + return (fmi2Status) status; + } + } + + return (fmi2Status) status; +#else + UNUSED(vr); + UNUSED(nvr); + UNUSED(order); + UNUSED(value); + + logError(S, "fmi2GetRealOutputDerivatives: ignoring function call." + " This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\""); + + return fmi2Error; +#endif +} + +fmi2Status fmi2CancelStep(fmi2Component c) +{ + + ASSERT_STATE(CancelStep); + + logError(S, "fmi2CancelStep: Can be called when fmi2DoStep returned fmi2Pending." + " This is not the case."); + + return fmi2Error; +} + +fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(DoStep); + + if (communicationStepSize <= 0) { + logError(S, "fmi2DoStep: communication step size must be > 0 but was %g.", communicationStepSize); + S->state = modelError; + return fmi2Error; + } + + const fmi2Real nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON; + + S->solverStepSize = communicationStepSize; + + fmi2Boolean nextCommunicationPointReached; + + while (true) { + + nextCommunicationPointReached = S->time + S->solverStepSize > nextCommunicationPoint; + + if (nextCommunicationPointReached) { + break; // next communcation point reached + } + + bool stateEvent, timeEvent; + + doAlphaStep(S, &stateEvent, &timeEvent); + +#ifdef EVENT_UPDATE + if (stateEvent || timeEvent) { + eventUpdate(S); + } +#endif + } + + return S->terminateSimulation ? fmi2Discard : fmi2OK; +} + +/* Inquire slave status */ +static fmi2Status getStatus(char *fname, fmi2Component c, const fmi2StatusKind s) +{ + + if (invalidState(S, fname, MASK_fmi2GetStatus)) // all get status have the same MASK_fmi2GetStatus + return fmi2Error; + + switch (s) { + case fmi2DoStepStatus: + logError(S, + "%s: Can be called with fmi2DoStepStatus when fmi2DoStep returned fmi2Pending." + " This is not the case.", + fname); + break; + case fmi2PendingStatus: + logError(S, + "%s: Can be called with fmi2PendingStatus when fmi2DoStep returned fmi2Pending." + " This is not the case.", + fname); + break; + case fmi2LastSuccessfulTime: + logError(S, + "%s: Can be called with fmi2LastSuccessfulTime when fmi2DoStep returned fmi2Discard." + " This is not the case.", + fname); + break; + case fmi2Terminated: + logError(S, + "%s: Can be called with fmi2Terminated when fmi2DoStep returned fmi2Discard." + " This is not the case.", + fname); + break; + } + + return fmi2Discard; +} + +fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value) +{ + + UNUSED(value); + + ASSERT_STATE(GetStatus); + + return getStatus("fmi2GetStatus", c, s); +} + +fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value) +{ + + ASSERT_STATE(GetRealStatus); + + if (s == fmi2LastSuccessfulTime) { + *value = S->time; + return fmi2OK; + } + + return getStatus("fmi2GetRealStatus", c, s); +} + +fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value) +{ + + UNUSED(value); + + ASSERT_STATE(GetIntegerStatus); + + return getStatus("fmi2GetIntegerStatus", c, s); +} + +fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value) +{ + + ASSERT_STATE(GetBooleanStatus); + + if (s == fmi2Terminated) { + *value = S->terminateSimulation; + return fmi2OK; + } + + return getStatus("fmi2GetBooleanStatus", c, s); +} + +fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value) +{ + UNUSED(value); + ASSERT_STATE(GetStringStatus); + return getStatus("fmi2GetStringStatus", c, s); +} + +// --------------------------------------------------------------------------- +// Functions for FMI2 for Model Exchange +// --------------------------------------------------------------------------- +/* Enter and exit the different modes */ +fmi2Status fmi2EnterEventMode(fmi2Component c) +{ + + ASSERT_STATE(EnterEventMode); + + S->state = EventMode; + + return fmi2OK; +} + +fmi2Status fmi2NewDiscreteStates(fmi2Component c, fmi2EventInfo *eventInfo) +{ + + ASSERT_STATE(NewDiscreteStates); + +#ifdef EVENT_UPDATE + eventUpdate(S); +#endif + + eventInfo->newDiscreteStatesNeeded = S->newDiscreteStatesNeeded; + eventInfo->terminateSimulation = S->terminateSimulation; + eventInfo->nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged; + eventInfo->valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged; + eventInfo->nextEventTimeDefined = S->nextEventTimeDefined; + eventInfo->nextEventTime = S->nextEventTime; + + return fmi2OK; +} + +fmi2Status fmi2EnterContinuousTimeMode(fmi2Component c) +{ + + ASSERT_STATE(EnterContinuousTimeMode); + + S->state = ContinuousTimeMode; + + return fmi2OK; +} + +fmi2Status fmi2CompletedIntegratorStep(fmi2Component c, fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, fmi2Boolean *terminateSimulation) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(CompletedIntegratorStep); + + if (nullPointer(S, "fmi2CompletedIntegratorStep", "enterEventMode", enterEventMode)) + return fmi2Error; + + if (nullPointer(S, "fmi2CompletedIntegratorStep", "terminateSimulation", terminateSimulation)) + return fmi2Error; + + *enterEventMode = fmi2False; + *terminateSimulation = fmi2False; + + return fmi2OK; +} + +/* Providing independent variables and re-initialization of caching */ +fmi2Status fmi2SetTime(fmi2Component c, fmi2Real time) +{ + + ASSERT_STATE(SetTime); + + S->time = time; + + return fmi2OK; +} + +fmi2Status fmi2SetContinuousStates(fmi2Component c, const fmi2Real x[], size_t nx) +{ + + ASSERT_STATE(SetContinuousStates); + + if (invalidNumber(S, "fmi2SetContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2SetContinuousStates", "x[]", x)) + return fmi2Error; + + setContinuousStates(S, x, nx); + + return fmi2OK; +} + +/* Evaluation of the model equations */ +fmi2Status fmi2GetDerivatives(fmi2Component c, fmi2Real derivatives[], size_t nx) +{ + + ASSERT_STATE(GetDerivatives); + + if (invalidNumber(S, "fmi2GetDerivatives", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetDerivatives", "derivatives[]", derivatives)) + return fmi2Error; + + getDerivatives(S, derivatives, nx); + + return fmi2OK; +} + +fmi2Status fmi2GetEventIndicators(fmi2Component c, fmi2Real eventIndicators[], size_t ni) +{ + + ASSERT_STATE(GetEventIndicators); + +#if NZ > 0 + + if (invalidNumber(S, "fmi2GetEventIndicators", "ni", ni, NZ)) + return fmi2Error; + + getEventIndicators(S, eventIndicators, ni); +#else + UNUSED(c); + UNUSED(eventIndicators); + if (ni > 0) + return fmi2Error; +#endif + return fmi2OK; +} + +fmi2Status fmi2GetContinuousStates(fmi2Component c, fmi2Real states[], size_t nx) +{ + + ASSERT_STATE(GetContinuousStates); + + if (invalidNumber(S, "fmi2GetContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetContinuousStates", "states[]", states)) + return fmi2Error; + + getContinuousStates(S, states, nx); + + return fmi2OK; +} + +fmi2Status fmi2GetNominalsOfContinuousStates(fmi2Component c, fmi2Real x_nominal[], size_t nx) +{ + + ASSERT_STATE(GetNominalsOfContinuousStates); + + if (invalidNumber(S, "fmi2GetNominalContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetNominalContinuousStates", "x_nominal[]", x_nominal)) + return fmi2Error; + + for (size_t i = 0; i < nx; i++) + x_nominal[i] = 1; + + return fmi2OK; +} diff --git a/oscillator/fmi/fmu/src/fmi3Functions.c b/oscillator/fmi/fmu/src/fmi3Functions.c new file mode 100644 index 000000000..f1cc504a2 --- /dev/null +++ b/oscillator/fmi/fmu/src/fmi3Functions.c @@ -0,0 +1,1544 @@ +#if FMI_VERSION != 3 +#error FMI_VERSION must be 3 +#endif + +#include +#include +#include +#include + +#include "config.h" +#include "cosimulation.h" +#include "model.h" + +// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_. +// Define DISABLE_PREFIX to build a binary FMU. +#if !defined(DISABLE_PREFIX) && !defined(FMI3_FUNCTION_PREFIX) +#define pasteA(a, b) a##b +#define pasteB(a, b) pasteA(a, b) +#define FMI3_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _) +#endif +#include "fmi3Functions.h" + +#define ASSERT_NOT_NULL(p) \ + do { \ + if (!p) { \ + logError(S, "Argument %s must not be NULL.", xstr(p)); \ + S->state = modelError; \ + return (fmi3Status) Error; \ + } \ + } while (0) + +#define GET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + ASSERT_NOT_NULL(valueReferences); \ + ASSERT_NOT_NULL(values); \ + size_t index = 0; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + if (S->isDirtyValues) { \ + Status s = calculateValues(S); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + S->isDirtyValues = false; \ + } \ + for (size_t i = 0; i < nValueReferences; i++) { \ + Status s = get##T(S, (ValueReference) valueReferences[i], values, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + } \ + return (fmi3Status) status; \ + } while (0) + +#define SET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + ASSERT_NOT_NULL(valueReferences); \ + ASSERT_NOT_NULL(values); \ + size_t index = 0; \ + for (size_t i = 0; i < nValueReferences; i++) { \ + Status s = set##T(S, (ValueReference) valueReferences[i], values, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + } \ + if (nValueReferences > 0) \ + S->isDirtyValues = true; \ + return (fmi3Status) status; \ + } while (0) + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef DT_EVENT_DETECT +#define DT_EVENT_DETECT 1e-10 +#endif + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for both Model-exchange and Co-simulation +// --------------------------------------------------------------------------- +#define MASK_AnyState (~0) + +/* Inquire version numbers and set debug logging */ +#define MASK_fmi3GetVersion MASK_AnyState +#define MASK_fmi3SetDebugLogging MASK_AnyState + +/* Creation and destruction of FMU instances */ +#define MASK_fmi3InstantiateInstantiateModelExchange MASK_AnyState +#define MASK_fmi3InstantiateCoSimulation MASK_AnyState +#define MASK_fmi3InstantiateScheduledExectuion MASK_AnyState +#define MASK_fmi3FreeInstance MASK_AnyState + +/* Enter and exit initialization mode, terminate and reset */ +#define MASK_fmi3EnterInitializationMode Instantiated +#define MASK_fmi3ExitInitializationMode InitializationMode +#define MASK_fmi3EnterEventMode (ContinuousTimeMode | StepMode) +#define MASK_fmi3Terminate (ContinuousTimeMode | StepMode | StepDiscarded | EventMode | ClockActivationMode | ReconfigurationMode) +#define MASK_fmi3Reset MASK_AnyState + +/* Common Functions */ + +/* Getting and setting variable values */ +#define MASK_fmi3GetFloat32 (InitializationMode | ConfigurationMode | ReconfigurationMode | EventMode | ContinuousTimeMode | StepMode | ClockActivationMode | IntermediateUpdateMode | Terminated) +#define MASK_fmi3GetFloat64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt8 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt8 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt16 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt16 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt32 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt32 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetBoolean MASK_fmi3GetFloat32 +#define MASK_fmi3GetString MASK_fmi3GetFloat32 +#define MASK_fmi3GetBinary MASK_fmi3GetFloat32 +#define MASK_fmi3GetClock MASK_AnyState + +#define MASK_fmi3SetFloat32 (Instantiated | InitializationMode | ConfigurationMode | ReconfigurationMode | EventMode | ContinuousTimeMode | StepMode | ClockActivationMode | IntermediateUpdateMode | Terminated) +#define MASK_fmi3SetFloat64 MASK_fmi3SetFloat32 +#define MASK_fmi3SetInt8 (Instantiated | ConfigurationMode | ReconfigurationMode | InitializationMode | EventMode | StepMode | ClockActivationMode | Terminated) +#define MASK_fmi3SetUInt8 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt16 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt16 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt32 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt32 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt64 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt64 MASK_fmi3SetInt8 +#define MASK_fmi3SetBoolean MASK_fmi3SetInt8 +#define MASK_fmi3SetString MASK_fmi3SetInt8 +#define MASK_fmi3SetBinary MASK_fmi3SetInt8 +#define MASK_fmi3SetClock MASK_AnyState + +/* Getting Variable Dependency Information */ +#define MASK_fmi3GetNumberOfVariableDependencies MASK_AnyState +#define MASK_fmi3GetVariableDependencies MASK_AnyState + +/* Getting and setting the internal FMU state */ +#define MASK_fmi3GetFMUState MASK_AnyState +#define MASK_fmi3SetFMUState MASK_AnyState +#define MASK_fmi3FreeFMUState MASK_AnyState +#define MASK_fmi3SerializedFMUStateSize MASK_AnyState +#define MASK_fmi3SerializeFMUState MASK_AnyState +#define MASK_fmi3DeserializeFMUState MASK_AnyState + +/* Getting partial derivatives */ +#define MASK_fmi3GetDirectionalDerivative (InitializationMode | StepMode | EventMode | ContinuousTimeMode | Terminated) +#define MASK_fmi3GetAdjointDerivative MASK_fmi3GetDirectionalDerivative + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +#define MASK_fmi3EnterConfigurationMode (Instantiated | StepMode | EventMode | ClockActivationMode) +#define MASK_fmi3ExitConfigurationMode (ConfigurationMode | ReconfigurationMode) + +/* Clock related functions */ +// TODO: fix masks +#define MASK_fmi3GetIntervalDecimal MASK_AnyState +#define MASK_fmi3GetIntervalFraction MASK_AnyState +#define MASK_fmi3SetIntervalDecimal MASK_AnyState +#define MASK_fmi3SetIntervalFraction MASK_AnyState +#define MASK_fmi3NewDiscreteStates MASK_AnyState + +/* Functions for Model Exchange */ + +#define MASK_fmi3EnterContinuousTimeMode EventMode +#define MASK_fmi3CompletedIntegratorStep ContinuousTimeMode + +/* Providing independent variables and re-initialization of caching */ +#define MASK_fmi3SetTime (EventMode | ContinuousTimeMode) +#define MASK_fmi3SetContinuousStates ContinuousTimeMode + +/* Evaluation of the model equations */ +#define MASK_fmi3GetContinuousStateDerivatives (InitializationMode | EventMode | ContinuousTimeMode | Terminated) +#define MASK_fmi3GetEventIndicators MASK_fmi3GetContinuousStateDerivatives +#define MASK_fmi3GetContinuousStates MASK_fmi3GetContinuousStateDerivatives +#define MASK_fmi3GetNominalsOfContinuousStates MASK_fmi3GetContinuousStateDerivatives + +#define MASK_fmi3GetNumberOfContinuousStates MASK_AnyState +#define MASK_fmi3GetNumberOfEventIndicators MASK_AnyState + +/* Functions for Co-Simulation */ + +#define MASK_fmi3EnterStepMode (InitializationMode | EventMode) +#define MASK_fmi3SetInputDerivatives (Instantiated | InitializationMode | StepMode) +#define MASK_fmi3GetOutputDerivatives (StepMode | StepDiscarded | Terminated | Error) +#define MASK_fmi3DoStep StepMode +#define MASK_fmi3ActivateModelPartition ClockActivationMode +#define MASK_fmi3DoEarlyReturn IntermediateUpdateMode +#define MASK_fmi3GetDoStepDiscardedStatus StepMode + +// --------------------------------------------------------------------------- +// Private helpers used below to validate function arguments +// --------------------------------------------------------------------------- + +#define NOT_IMPLEMENTED \ + do { \ + ModelInstance *comp = (ModelInstance *) instance; \ + logError(comp, "Function is not implemented."); \ + return fmi3Error; \ + } while (0) + +#define ASSERT_STATE(F) \ + if (!instance) \ + return fmi3Error; \ + ModelInstance *S = (ModelInstance *) instance; \ + if (!allowedState(S, MASK_fmi3##F, #F)) \ + return fmi3Error; + +static bool allowedState(ModelInstance *instance, int statesExpected, char *name) +{ + + if (!instance) { + return false; + } + + if (!(instance->state & statesExpected)) { + logError(instance, "fmi3%s: Illegal call sequence.", name); + return false; + } + + return true; +} + +/*************************************************** + Common Functions + ****************************************************/ + +const char *fmi3GetVersion() +{ + return fmi3Version; +} + +fmi3Status fmi3SetDebugLogging(fmi3Instance instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]) +{ + + ASSERT_STATE(SetDebugLogging) + + return (fmi3Status) setDebugLogging(S, loggingOn, nCategories, categories); +} + +fmi3Instance fmi3InstantiateModelExchange( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage) +{ + + UNUSED(visible); + +#ifndef MODEL_EXCHANGE + UNUSED(instanceName); + UNUSED(instantiationToken); + UNUSED(resourcePath); + UNUSED(loggingOn); + UNUSED(instanceEnvironment); + UNUSED(logMessage); + + return NULL; +#else + return createModelInstance( + (loggerType) logMessage, + NULL, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + ModelExchange); +#endif +} + +fmi3Instance fmi3InstantiateCoSimulation( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3IntermediateUpdateCallback intermediateUpdate) +{ + + UNUSED(visible); + UNUSED(requiredIntermediateVariables); + UNUSED(nRequiredIntermediateVariables); + +#ifndef EVENT_UPDATE + if (eventModeUsed) { + if (logMessage) { + logMessage(instanceEnvironment, fmi3Error, "error", "Event Mode is not supported."); + } + return NULL; + } +#endif + + ModelInstance *instance = createModelInstance( + (loggerType) logMessage, + (intermediateUpdateType) intermediateUpdate, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + CoSimulation); + + if (instance) { + instance->earlyReturnAllowed = earlyReturnAllowed; + instance->eventModeUsed = eventModeUsed; + instance->state = Instantiated; + } + + return instance; +} + +fmi3Instance fmi3InstantiateScheduledExecution( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption) +{ + + UNUSED(visible); + +#ifndef SCHEDULED_CO_SIMULATION + + UNUSED(instanceName); + UNUSED(instantiationToken); + UNUSED(resourcePath); + UNUSED(loggingOn); + UNUSED(instanceEnvironment); + UNUSED(logMessage); + UNUSED(clockUpdate); + UNUSED(lockPreemption); + UNUSED(unlockPreemption); + + return NULL; +#else + ModelInstance *instance = createModelInstance( + (loggerType) logMessage, + NULL, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + ScheduledExecution); + + if (instance) { + instance->state = Instantiated; + instance->clockUpdate = clockUpdate; + instance->lockPreemtion = lockPreemption; + instance->unlockPreemtion = unlockPreemption; + } + + return instance; +#endif +} + +void fmi3FreeInstance(fmi3Instance instance) +{ + + if (!instance) + return; + + freeModelInstance((ModelInstance *) instance); +} + +fmi3Status fmi3EnterInitializationMode(fmi3Instance instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime) +{ + + UNUSED(toleranceDefined); + UNUSED(tolerance); + UNUSED(stopTimeDefined); + UNUSED(stopTime); + + ASSERT_STATE(EnterInitializationMode); + + S->startTime = startTime; + S->time = startTime; + S->state = InitializationMode; + + return fmi3OK; +} + +fmi3Status fmi3ExitInitializationMode(fmi3Instance instance) +{ + + ASSERT_STATE(ExitInitializationMode); + + fmi3Status status = fmi3OK; + + // if values were set and no fmi3GetXXX triggered update before, + // ensure calculated values are updated now + if (S->isDirtyValues) { + + status = (fmi3Status) calculateValues(S); + + if (status > fmi3Warning) { + return status; + } + + S->isDirtyValues = false; + } + + switch (S->type) { + case ModelExchange: + S->state = EventMode; + break; + case CoSimulation: + S->state = S->eventModeUsed ? EventMode : StepMode; + break; + case ScheduledExecution: + S->state = ClockActivationMode; + break; + } + +#if NZ > 0 + // initialize event indicators + getEventIndicators(S, S->z, NZ); +#endif + + return status; +} + +fmi3Status fmi3EnterEventMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterEventMode); + + S->state = EventMode; + + return fmi3OK; +} + +fmi3Status fmi3Terminate(fmi3Instance instance) +{ + + ASSERT_STATE(Terminate); + + S->state = Terminated; + + return fmi3OK; +} + +fmi3Status fmi3Reset(fmi3Instance instance) +{ + + ASSERT_STATE(Reset); + + reset(S); + + return fmi3OK; +} + +fmi3Status fmi3GetFloat32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetFloat32); + GET_VARIABLES(Float32); +} + +fmi3Status fmi3GetFloat64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetFloat64); + GET_VARIABLES(Float64); +} + +fmi3Status fmi3GetInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt8); + GET_VARIABLES(Int8); +} + +fmi3Status fmi3GetUInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt8); + GET_VARIABLES(UInt8); +} + +fmi3Status fmi3GetInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt16); + GET_VARIABLES(Int16); +} + +fmi3Status fmi3GetUInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt16); + GET_VARIABLES(UInt16); +} + +fmi3Status fmi3GetInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt32); + GET_VARIABLES(Int32); +} + +fmi3Status fmi3GetUInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt32); + GET_VARIABLES(UInt32); +} + +fmi3Status fmi3GetInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt64); + GET_VARIABLES(Int64); +} + +fmi3Status fmi3GetUInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt64); + GET_VARIABLES(UInt64); +} + +fmi3Status fmi3GetBoolean(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetBoolean); + GET_VARIABLES(Boolean); +} + +fmi3Status fmi3GetString(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetString); + GET_VARIABLES(String); +} + +fmi3Status fmi3GetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t valueSizes[], + fmi3Binary values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(GetBinary); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + size_t index = 0; + Status s = getBinary(S, (ValueReference) valueReferences[i], valueSizes, (const char **) values, &index); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetClock(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]) +{ + + ASSERT_STATE(GetClock); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + Status s = getClock(instance, (ValueReference) valueReferences[i], &values[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3SetFloat32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetFloat32); + SET_VARIABLES(Float32); +} + +fmi3Status fmi3SetFloat64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetFloat64); + SET_VARIABLES(Float64); +} + +fmi3Status fmi3SetInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt8); + SET_VARIABLES(Int8); +} + +fmi3Status fmi3SetUInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt8); + SET_VARIABLES(UInt8); +} + +fmi3Status fmi3SetInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt16); + SET_VARIABLES(Int16); +} + +fmi3Status fmi3SetUInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt16); + SET_VARIABLES(UInt16); +} + +fmi3Status fmi3SetInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt32); + SET_VARIABLES(Int32); +} + +fmi3Status fmi3SetUInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt32); + SET_VARIABLES(UInt32); +} + +fmi3Status fmi3SetInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt64); + SET_VARIABLES(Int64); +} + +fmi3Status fmi3SetUInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt64); + SET_VARIABLES(UInt64); +} + +fmi3Status fmi3SetBoolean(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetBoolean); + SET_VARIABLES(Boolean); +} + +fmi3Status fmi3SetString(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetString); + SET_VARIABLES(String); +} + +fmi3Status fmi3SetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t valueSizes[], + const fmi3Binary values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(SetBinary); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + size_t index = 0; + Status s = setBinary(S, (ValueReference) valueReferences[i], valueSizes, (const char *const *) values, &index); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3SetClock(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]) +{ + + ASSERT_STATE(SetClock); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + if (values[i]) { + Status s = activateClock(instance, (ValueReference) valueReferences[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetNumberOfVariableDependencies(fmi3Instance instance, + fmi3ValueReference valueReference, + size_t * nDependencies) +{ + UNUSED(valueReference); + UNUSED(nDependencies); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetVariableDependencies(fmi3Instance instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies) +{ + + UNUSED(dependent); + UNUSED(elementIndicesOfDependent); + UNUSED(independents); + UNUSED(elementIndicesOfIndependents); + UNUSED(dependencyKinds); + UNUSED(nDependencies); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetFMUState(fmi3Instance instance, fmi3FMUState *FMUState) +{ + + ASSERT_STATE(GetFMUState); + + *FMUState = getFMUState(S); + + return fmi3OK; +} + +fmi3Status fmi3SetFMUState(fmi3Instance instance, fmi3FMUState FMUState) +{ + + ASSERT_STATE(SetFMUState); + + if (nullPointer(S, "fmi3SetFMUState", "FMUState", FMUState)) { + return fmi3Error; + } + + setFMUState(S, FMUState); + + return fmi3OK; +} + +fmi3Status fmi3FreeFMUState(fmi3Instance instance, fmi3FMUState *FMUState) +{ + + ASSERT_STATE(FreeFMUState); + + free(*FMUState); + + *FMUState = NULL; + + return fmi3OK; +} + +fmi3Status fmi3SerializedFMUStateSize(fmi3Instance instance, + fmi3FMUState FMUState, + size_t * size) +{ + + UNUSED(instance); + UNUSED(FMUState); + + ASSERT_STATE(SerializedFMUStateSize); + + *size = sizeof(ModelInstance); + + return fmi3OK; +} + +fmi3Status fmi3SerializeFMUState(fmi3Instance instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size) +{ + + ASSERT_STATE(SerializeFMUState); + + if (nullPointer(S, "fmi3SerializeFMUState", "FMUstate", FMUState)) { + return fmi3Error; + } + + if (invalidNumber(S, "fmi3SerializeFMUState", "size", size, sizeof(ModelInstance))) { + return fmi3Error; + } + + memcpy(serializedState, FMUState, sizeof(ModelInstance)); + + return fmi3OK; +} + +fmi3Status fmi3DeserializeFMUState(fmi3Instance instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState * FMUState) +{ + + ASSERT_STATE(DeserializeFMUState); + + if (invalidNumber(S, "fmi3DeserializeFMUState", "size", size, sizeof(ModelInstance))) { + return fmi3Error; + } + + if (*FMUState == NULL) { + *FMUState = calloc(1, sizeof(ModelInstance)); + } + + memcpy(*FMUState, serializedState, sizeof(ModelInstance)); + + return fmi3OK; +} + +fmi3Status fmi3GetDirectionalDerivative(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + + UNUSED(nSeed); + UNUSED(nSensitivity); + + ASSERT_STATE(GetDirectionalDerivative); + + // TODO: check value references + // TODO: assert nUnknowns == nDeltaOfUnknowns + // TODO: assert nKnowns == nDeltaKnowns + + Status status = OK; + + for (size_t i = 0; i < nUnknowns; i++) { + sensitivity[i] = 0; + for (size_t j = 0; j < nKnowns; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, (ValueReference) unknowns[i], (ValueReference) knowns[j], &partialDerivative); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + sensitivity[i] += partialDerivative * seed[j]; + } + } + + return fmi3OK; +} + +fmi3Status fmi3GetAdjointDerivative(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + + UNUSED(nSeed); + UNUSED(nSensitivity); + + ASSERT_STATE(GetAdjointDerivative); + + // TODO: check value references + + Status status = OK; + + for (size_t i = 0; i < nKnowns; i++) { + sensitivity[i] = 0; + for (size_t j = 0; j < nUnknowns; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, (ValueReference) unknowns[j], (ValueReference) knowns[i], &partialDerivative); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + sensitivity[i] += partialDerivative * seed[j]; + } + } + + return fmi3OK; +} + +fmi3Status fmi3EnterConfigurationMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterConfigurationMode); + + S->state = (S->state == Instantiated) ? ConfigurationMode : ReconfigurationMode; + + return fmi3OK; +} + +fmi3Status fmi3ExitConfigurationMode(fmi3Instance instance) +{ + + ASSERT_STATE(ExitConfigurationMode); + + if (S->state == ConfigurationMode) { + S->state = Instantiated; + } else { + switch (S->type) { + case ModelExchange: + S->state = EventMode; + break; + case CoSimulation: + S->state = StepMode; + break; + case ScheduledExecution: + S->state = ClockActivationMode; + break; + } + } + + return fmi3OK; +} + +fmi3Status fmi3GetIntervalDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]) +{ + + ASSERT_STATE(GetIntervalDecimal); + + // ? Check nValueReferences != nValues + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + Status s = getInterval(instance, (ValueReference) valueReferences[i], &intervals[i], (int *) &qualifiers[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetIntervalFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervalCounters); + UNUSED(resolutions); + UNUSED(qualifiers); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetShiftDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shifts); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetShiftFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shiftCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetIntervalDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervals); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetIntervalFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervalCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetShiftDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shifts); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetShiftFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shiftCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3EvaluateDiscreteStates(fmi3Instance instance) +{ + NOT_IMPLEMENTED; +} + +fmi3Status fmi3UpdateDiscreteStates(fmi3Instance instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime) +{ + + ASSERT_STATE(NewDiscreteStates); + +#ifdef EVENT_UPDATE + eventUpdate(S); +#endif + + // copy internal eventInfo of component to output arguments + if (discreteStatesNeedUpdate) + *discreteStatesNeedUpdate = S->newDiscreteStatesNeeded; + if (terminateSimulation) + *terminateSimulation = S->terminateSimulation; + if (nominalsOfContinuousStatesChanged) + *nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged; + if (valuesOfContinuousStatesChanged) + *valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged; + if (nextEventTimeDefined) + *nextEventTimeDefined = S->nextEventTimeDefined; + if (nextEventTime) + *nextEventTime = S->nextEventTime; + + return fmi3OK; +} + +/*************************************************** + Functions for Model Exchange + ****************************************************/ + +fmi3Status fmi3EnterContinuousTimeMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterContinuousTimeMode); + + S->state = ContinuousTimeMode; + + return fmi3OK; +} + +fmi3Status fmi3CompletedIntegratorStep(fmi3Instance instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(CompletedIntegratorStep); + + ASSERT_NOT_NULL(enterEventMode); + ASSERT_NOT_NULL(terminateSimulation); + + *enterEventMode = fmi3False; + *terminateSimulation = fmi3False; + + return fmi3OK; +} + +/* Providing independent variables and re-initialization of caching */ +fmi3Status fmi3SetTime(fmi3Instance instance, fmi3Float64 time) +{ + + ASSERT_STATE(SetTime); + + S->time = time; + + return fmi3OK; +} + +fmi3Status fmi3SetContinuousStates(fmi3Instance instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + ASSERT_STATE(SetContinuousStates); + + if (invalidNumber(S, "fmi3SetContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + ASSERT_NOT_NULL(continuousStates); + + setContinuousStates(S, continuousStates, nContinuousStates); + + return fmi3OK; +} + +/* Evaluation of the model equations */ +fmi3Status fmi3GetContinuousStateDerivatives(fmi3Instance instance, + fmi3Float64 derivatives[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetContinuousStateDerivatives); + + if (invalidNumber(S, "fmi3GetContinuousStateDerivatives", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetContinuousStateDerivatives", "derivatives[]", derivatives)) + return fmi3Error; + + getDerivatives(S, derivatives, nContinuousStates); + + return fmi3OK; +} + +fmi3Status fmi3GetEventIndicators(fmi3Instance instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators) +{ + + ASSERT_STATE(GetEventIndicators); + +#if NZ > 0 + if (invalidNumber(S, "fmi3GetEventIndicators", "nEventIndicators", nEventIndicators, NZ)) { + return fmi3Error; + } + + getEventIndicators(S, eventIndicators, nEventIndicators); +#else + + UNUSED(eventIndicators); + + if (nEventIndicators > 0) { + // TODO: log error + return fmi3Error; + } +#endif + + return fmi3OK; +} + +fmi3Status fmi3GetContinuousStates(fmi3Instance instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetContinuousStates); + + if (invalidNumber(S, "fmi3GetContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetContinuousStates", "continuousStates[]", continuousStates)) + return fmi3Error; + + getContinuousStates(S, continuousStates, nContinuousStates); + + return fmi3OK; +} + +fmi3Status fmi3GetNominalsOfContinuousStates(fmi3Instance instance, + fmi3Float64 nominals[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetNominalsOfContinuousStates); + + if (invalidNumber(S, "fmi3GetNominalContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetNominalContinuousStates", "nominals[]", nominals)) + return fmi3Error; + + for (size_t i = 0; i < nContinuousStates; i++) { + nominals[i] = 1; + } + + return fmi3OK; +} + +fmi3Status fmi3GetNumberOfEventIndicators(fmi3Instance instance, + size_t * nEventIndicators) +{ + + ASSERT_STATE(GetNumberOfEventIndicators); + + ASSERT_NOT_NULL(nEventIndicators); + + *nEventIndicators = NZ; + + return fmi3OK; +} + +fmi3Status fmi3GetNumberOfContinuousStates(fmi3Instance instance, + size_t * nContinuousStates) +{ + + ASSERT_STATE(GetNumberOfContinuousStates); + + ASSERT_NOT_NULL(nContinuousStates); + + *nContinuousStates = NX; + + return fmi3OK; +} + +/*************************************************** + Functions for Co-Simulation + ****************************************************/ + +fmi3Status fmi3EnterStepMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterStepMode); + + S->state = StepMode; + + return fmi3OK; +} + +fmi3Status fmi3GetOutputDerivatives(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(GetOutputDerivatives); + +#ifdef GET_OUTPUT_DERIVATIVE + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + const Status s = getOutputDerivative(S, (ValueReference) valueReferences[i], orders[i], &values[i]); + status = max(status, s); + if (status > Warning) { + return (fmi3Status) status; + } + } + + return (fmi3Status) status; + +#else + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(orders); + UNUSED(values); + + NOT_IMPLEMENTED; +#endif +} + +fmi3Status fmi3DoStep(fmi3Instance instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(DoStep); + + if (communicationStepSize <= 0) { + logError(S, "fmi3DoStep: communication step size must be > 0 but was %g.", communicationStepSize); + S->state = modelError; + return fmi3Error; + } + + const fmi3Float64 nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON; + + S->solverStepSize = communicationStepSize; + + fmi3Boolean nextCommunicationPointReached; + + *eventHandlingNeeded = fmi3False; + + while (true) { + + nextCommunicationPointReached = S->time + S->solverStepSize > nextCommunicationPoint; + + if (nextCommunicationPointReached) { + break; + } + + bool stateEvent, timeEvent; + + doAlphaStep(S, &stateEvent, &timeEvent); + +#ifdef EVENT_UPDATE + if (stateEvent || timeEvent) { + + *eventHandlingNeeded = fmi3True; + + if (S->eventModeUsed) { + break; + } + + eventUpdate(S); + + if (S->earlyReturnAllowed) { + break; + } + } +#endif + } + + *earlyReturn = !nextCommunicationPointReached; + + *terminateSimulation = fmi3False; + + *lastSuccessfulTime = S->time; + + return fmi3OK; +} + +fmi3Status fmi3ActivateModelPartition(fmi3Instance instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime) +{ + + ASSERT_STATE(ActivateModelPartition); + + return (fmi3Status) activateModelPartition(S, (ValueReference) clockReference, activationTime); +} diff --git a/oscillator/fmi/fmu/thirdparty/LICENSE.txt b/oscillator/fmi/fmu/thirdparty/LICENSE.txt new file mode 100644 index 000000000..d2ff5fb89 --- /dev/null +++ b/oscillator/fmi/fmu/thirdparty/LICENSE.txt @@ -0,0 +1,148 @@ +Copyright (c) 2022, Modelica Association Project "FMI". +All rights reserved. + +The Reference FMUs and FMUSim are released under the 2-Clause BSD license: + +-------------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDi +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- + +The Reference FMUs are a fork of the Test FMUs (https://github.com/CATIA-Systems/Test-FMUs) +by Dassault Systemes, which are a fork of the FMU SDK (https://github.com/qtronic/fmusdk) +by QTronic, both released under the 2-Clause BSD License. + +FMUSim uses the following third party libraries. + +================================================================================ + +Libxml2 (https://gitlab.gnome.org/GNOME/libxml2) released under the MIT license: + +Except where otherwise noted in the source code (e.g. the files hash.c, +list.c and the trio files, which are covered by a similar licence but +with different Copyright notices) all the files are: + + Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is fur- +nished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +================================================================================ + +Zlib (http://zlib.net/) release under the zlib license: + +Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + +================================================================================ + +CSV-fast-reader (https://github.com/jandoczy/csv-fast-reader) release under the +MIT license: + +Copyright (c) 2019 Jan Doczy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +================================================================================ + +SUNDIALS: SUite of Nonlinear and DIfferential/ALgebraic equation Solvers +(https://computing.llnl.gov/projects/sundials) release under the BSD 3-Clause license: + +Copyright (c) 2002-2022, Lawrence Livermore National Security and Southern Methodist University. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +The FMI header files are copyright (c) 2008-2011 MODELISAR consortium, 2012-2022 +the Modelica Association Project "FMI" and released under the 2-Clause BSD License. diff --git a/oscillator/fmi/run.sh b/oscillator/fmi/run.sh new file mode 100755 index 000000000..3cc384bb9 --- /dev/null +++ b/oscillator/fmi/run.sh @@ -0,0 +1,40 @@ +#!/bin/sh +set -e -u + +usage() { echo "Usage: cmd [-l] [-r]" 1>&2; exit 1; } + +# Check if no input argument was provided +if [ -z "$*" ] ; then + usage +fi + +if [ ! -f Oscillator.fmu ]; then + cd fmu + rm -rf build + mkdir build + cd build + # Both FMI_VERSION=3 and FMI_VERSION=2 are supported + cmake -DFMI_TYPE=CS -DFMI_VERSION=3 .. + make + cp ./Oscillator.fmu ../.. + cd ../../ +fi + +# Select appropriate case +while getopts ":lr" opt; do + case ${opt} in + l) + fmiprecice ./MassLeft/fmi-settings.json MassLeft/precice-settings.json + python3 calculate-error.py MassLeft/fmi-settings.json MassLeft/precice-settings.json MassRight/fmi-settings.json MassRight/precice-settings.json Mass-Left + + ;; + r) + fmiprecice MassRight/fmi-settings.json MassRight/precice-settings.json + python3 calculate-error.py MassLeft/fmi-settings.json MassLeft/precice-settings.json MassRight/fmi-settings.json MassRight/precice-settings.json Mass-Right + + ;; + *) + usage + ;; + esac +done diff --git a/oscillator/plot-trajectory.py b/oscillator/plot-trajectory.py index e5f2558ac..53d3a11db 100644 --- a/oscillator/plot-trajectory.py +++ b/oscillator/plot-trajectory.py @@ -16,20 +16,38 @@ class PlotType(Enum): args = parser.parse_args() filename = args.csvFile -df = pd.read_csv(filename, delimiter=';') +split_filename = filename.split('/') +solver = split_filename[0] -if args.plotType == PlotType.U_OVER_T.name: - plt.plot(df['time'].to_numpy(), df['position'].to_numpy()) - plt.title(PlotType.U_OVER_T.value) -elif args.plotType == PlotType.V_OVER_T.name: - plt.plot(df['time'].to_numpy(), df['velocity'].to_numpy()) - plt.title(PlotType.V_OVER_T.value) -elif args.plotType == PlotType.TRAJECTORY.name: - plt.plot(df['position'].to_numpy(), df['velocity'].to_numpy()) - plt.scatter([df['position'][0]], [df['velocity'][0]], label=f"(u,v) at t={df['time'][0]}") - plt.scatter([df['position'].iloc[-1]], [df['velocity'].iloc[-1]], - label=f"(u,v) at t={df['time'].iloc[-1]}", marker="*") - plt.title(PlotType.TRAJECTORY.value) - plt.legend() +if solver == 'python': + df = pd.read_csv(filename, delimiter=';') + if args.plotType == PlotType.U_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['position'].to_numpy()) + plt.title(PlotType.U_OVER_T.value) + elif args.plotType == PlotType.V_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['velocity'].to_numpy()) + plt.title(PlotType.V_OVER_T.value) + elif args.plotType == PlotType.TRAJECTORY.name: + plt.plot(df['position'].to_numpy(), df['velocity'].to_numpy()) + plt.scatter([df['position'][0]], [df['velocity'][0]], label=f"(u,v) at t={df['time'][0]}") + plt.scatter([df['position'].iloc[-1]], [df['velocity'].iloc[-1]], + label=f"(u,v) at t={df['time'].iloc[-1]}", marker="*") + plt.title(PlotType.TRAJECTORY.value) + plt.legend() +elif solver == 'fmi': + df = pd.read_csv(filename, delimiter=',') + if args.plotType == PlotType.U_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['mass.u'].to_numpy()) + plt.title(PlotType.U_OVER_T.value) + elif args.plotType == PlotType.V_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['mass.v'].to_numpy()) + plt.title(PlotType.V_OVER_T.value) + elif args.plotType == PlotType.TRAJECTORY.name: + plt.plot(df[('mass.u')].to_numpy(), df['mass.v'].to_numpy()) + plt.scatter([df['mass.u'][0]], [df['mass.v'][0]], label=f"(u,v) at t={df['time'][0]}") + plt.scatter([df['mass.u'].iloc[-1]], [df['mass.v'].iloc[-1]], + label=f"(u,v) at t={df['time'].iloc[-1]}", marker="*") + plt.title(PlotType.TRAJECTORY.value) + plt.legend() plt.show()