├── .clang-format ├── .github └── workflows │ └── config.yml ├── .gitignore ├── BUILDING.md ├── CITATION.cff ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── FindLIBZIP.cmake ├── FindPugiXML.cmake ├── conan.cmake └── fmi4cpp-config.cmake.in ├── examples ├── CMakeLists.txt ├── controlled_temperature.cpp ├── fmu_test.cpp ├── multiple_fmus.cpp ├── time_util.hpp └── torsionbar.cpp ├── include └── fmi4cpp │ ├── dll_handle.hpp │ ├── fmi2 │ ├── cs_fmu.hpp │ ├── cs_library.hpp │ ├── cs_slave.hpp │ ├── fmi2.hpp │ ├── fmi2FunctionTypes.h │ ├── fmi2Functions.h │ ├── fmi2TypesPlatform.h │ ├── fmi2_library.hpp │ ├── fmu.hpp │ ├── me_fmu.hpp │ ├── me_instance.hpp │ ├── me_library.hpp │ └── xml │ │ ├── cs_model_description.hpp │ │ ├── default_experiment.hpp │ │ ├── enums.hpp │ │ ├── fmu_attributes.hpp │ │ ├── me_model_description.hpp │ │ ├── model_description.hpp │ │ ├── model_description_parser.hpp │ │ ├── model_structure.hpp │ │ ├── model_variables.hpp │ │ ├── scalar_variable.hpp │ │ ├── source_files.hpp │ │ ├── specific_model_description.hpp │ │ ├── typed_scalar_variable.hpp │ │ └── unit_definitions.hpp │ ├── fmi4cpp.hpp │ ├── fmu_base.hpp │ ├── fmu_instance.hpp │ ├── fmu_instance_base.hpp │ ├── fmu_resource.hpp │ ├── fmu_slave.hpp │ ├── fmu_variable_accessor.hpp │ ├── status.hpp │ ├── tools │ └── unzipper.hpp │ └── types.hpp ├── resources └── fmus │ └── 2.0 │ ├── cs │ ├── 20sim │ │ └── 4.6.4.8004 │ │ │ ├── ControlledTemperature │ │ │ ├── ControlledTemperature.fmu │ │ │ └── modelDescription.xml │ │ │ └── TorsionBar │ │ │ ├── TorsionBar.fmu │ │ │ └── modelDescription.xml │ └── OpenModelica │ │ └── v1.11.0 │ │ └── FmuExportCrossCompile │ │ ├── FmuExportCrossCompile.fmu │ │ └── modelDescription.xml │ └── me │ ├── OpenModelica │ └── v1.11.0 │ │ └── FmuExportCrossCompile │ │ ├── FmuExportCrossCompile.fmu │ │ └── modelDescription.xml │ └── Test-FMUs │ └── 0.0.1 │ ├── BouncingBall │ └── BouncingBall.fmu │ ├── Dahlquist │ └── Dahlquist.fmu │ ├── Feedthrough │ └── Feedthrough.fmu │ ├── Resource │ └── Resource.fmu │ ├── Stair │ └── Stair.fmu │ └── VanDerPol │ └── VanDerPol.fmu ├── src ├── CMakeLists.txt └── fmi4cpp │ ├── fmi2 │ ├── cs_fmu.cpp │ ├── cs_library.cpp │ ├── cs_slave.cpp │ ├── fmi2_library.cpp │ ├── fmu.cpp │ ├── me_fmu.cpp │ ├── me_instance.cpp │ ├── me_library.cpp │ ├── status_converter.hpp │ └── xml │ │ ├── enums.cpp │ │ ├── model_description.cpp │ │ ├── model_description_parser.cpp │ │ ├── model_variables.cpp │ │ └── scalar_variable.cpp │ ├── fmu_resource.cpp │ ├── library_helper.hpp │ ├── mlog.hpp │ └── tools │ ├── os_util.hpp │ ├── simple_id.hpp │ └── unzipper.cpp ├── tests ├── CMakeLists.txt ├── test_controlled_temperature.cpp ├── test_modeldescription1.cpp └── test_modeldescription2.cpp ├── vcpkg.json └── version.txt /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | Standard: Cpp11 3 | BasedOnStyle: WebKit 4 | NamespaceIndentation: None 5 | IndentCaseLabels: true 6 | IndentPPDirectives: AfterHash 7 | FixNamespaceComments: true 8 | MaxEmptyLinesToKeep: 2 9 | SpaceAfterTemplateKeyword: false 10 | AllowShortCaseLabelsOnASingleLine: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortIfStatementsOnASingleLine: true 13 | AllowShortBlocksOnASingleLine: true 14 | AllowShortLoopsOnASingleLine: true 15 | BreakBeforeBinaryOperators: None 16 | Cpp11BracedListStyle: true 17 | SpaceBeforeCpp11BracedList: false 18 | BreakBeforeBraces: Custom 19 | BraceWrapping: 20 | AfterEnum: true 21 | AfterStruct: true 22 | AfterClass: true 23 | SplitEmptyFunction: false 24 | AfterFunction: true 25 | AfterNamespace : true 26 | AfterControlStatement: false 27 | IncludeBlocks: Regroup 28 | IncludeCategories: 29 | - Regex: '^[<"]fmi4cpp[/.]' 30 | Priority: 20 31 | - Regex: '^[<"](boost|zip|catch2)[/.]' 32 | Priority: 30 33 | - Regex: '^"' 34 | Priority: 10 35 | - Regex: '.*' 36 | Priority: 40 37 | -------------------------------------------------------------------------------- /.github/workflows/config.yml: -------------------------------------------------------------------------------- 1 | name: FMI4cpp CI 2 | 3 | on: [ push, workflow_dispatch ] 4 | 5 | jobs: 6 | 7 | cmake-on-linux: 8 | 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: [ubuntu-20.04] 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - name: Install prerequisites 19 | run: | 20 | sudo apt-get update && sudo apt-get install -y --no-install-recommends \ 21 | gcc g++ cmake libzip-dev libpugixml-dev 22 | 23 | - name: Configure and build 24 | run: | 25 | cmake . -B build -DFMI4CPP_BUILD_TESTS=ON -DFMI4CPP_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release 26 | cmake --build build 27 | 28 | - name: Test 29 | run: | 30 | cd build/tests && ctest 31 | 32 | 33 | vcpkg-on-linux: 34 | 35 | runs-on: ${{ matrix.os }} 36 | env: 37 | CC: gcc-${{ matrix.compiler_version }} 38 | CXX: g++-${{ matrix.compiler_version }} 39 | strategy: 40 | fail-fast: false 41 | matrix: 42 | os: [ubuntu-22.04] 43 | compiler_version: [11] 44 | 45 | steps: 46 | - uses: actions/checkout@v3 47 | 48 | - name: Restore artifacts, or run vcpkg, build (and cache artifacts as post step) 49 | uses: lukka/run-vcpkg@v10 50 | id: runvcpkg 51 | with: 52 | vcpkgDirectory: '${{ github.workspace }}/vcpkg' 53 | vcpkgGitCommitId: '4cac260c4b7331538d31886f57739fea0bffa27e' 54 | vcpkgJsonGlob: 'vcpkg.json' 55 | appendedCacheKey: vcpkginstall 56 | 57 | - name: Configure and build 58 | run: | 59 | cmake . -B build -DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake" -DFMI4CPP_BUILD_TESTS=ON -DFMI4CPP_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release 60 | cmake --build build 61 | 62 | - name: Test 63 | run: | 64 | cd build/tests && ctest 65 | 66 | 67 | vcpkg-on-windows: 68 | 69 | runs-on: ${{ matrix.os }} 70 | strategy: 71 | fail-fast: false 72 | matrix: 73 | os: [windows-2019, windows-2022] 74 | 75 | steps: 76 | - uses: actions/checkout@v3 77 | 78 | - name: Restore artifacts, or run vcpkg, build (and cache artifacts as post step) 79 | uses: lukka/run-vcpkg@v10 80 | id: runvcpkg 81 | with: 82 | vcpkgDirectory: '${{ github.workspace }}/vcpkg' 83 | vcpkgGitCommitId: '4cac260c4b7331538d31886f57739fea0bffa27e' 84 | vcpkgJsonGlob: 'vcpkg.json' 85 | appendedCacheKey: vcpkginstall 86 | 87 | - name: Configure and build 88 | run: | 89 | cmake . -B build -A x64 -DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake" -DFMI4CPP_BUILD_TESTS=ON -DFMI4CPP_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release 90 | cmake --build build --config Release 91 | shell: bash 92 | 93 | - name: Test 94 | run: | 95 | cd build/tests && ctest -C Release 96 | shell: bash 97 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | build 3 | cmake-build-* 4 | 5 | .idea 6 | .vscode 7 | .cache 8 | 9 | compile_commands.json 10 | 11 | /vcpkg 12 | -------------------------------------------------------------------------------- /BUILDING.md: -------------------------------------------------------------------------------- 1 | ### BUILDING 2 | 3 | For building FMI4cpp, you can use either `vcpkg` or `apt-get` for getting the required dependencies. 4 | 5 | ##### vcpkg 6 | 7 | Call CMake with `-DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake` 8 | 9 | ##### apt-get 10 | 11 | ```bash 12 | Linux:~/$ sudo apt-get install libzip-dev libpugixml-dev 13 | ``` 14 | 15 | ### Running examples/tests 16 | 17 | To build the examples pass `-DFMI4CPP_BUILD_EXAMPLES=ON` to CMake. 18 | To build the tests pass `-DFMI4CPP_BUILD_TESTS=ON` to CMake. 19 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: FMI4cpp 3 | message: >- 4 | If you use FMI4cpp in your research, please cite it using 5 | the following metadata. 6 | type: software 7 | authors: 8 | - family-names: Hatledal 9 | given-names: Lars Ivar 10 | orcid: 'https://orcid.org/0000-0001-6436-7213' 11 | email: larsivarhatledal@gmail.com 12 | affiliation: 'NTNU Aalesund, Norway' 13 | repository-code: 'https://github.com/NTNU-IHB/FMI4cpp' 14 | url: 'https://github.com/NTNU-IHB/FMI4cpp' 15 | abstract: >- 16 | FMI4cpp is a modern C++ library that provides support for 17 | the Functional Mock-up Interface (FMI) 2.0 standard. It 18 | enables the integration and simulation of Functional 19 | Mock-up Units (FMUs) within C++ applications, facilitating 20 | model exchange and co-simulation. 21 | keywords: 22 | - FMI 23 | - FMU 24 | - C++ 25 | - Simulation 26 | - Co-simulation 27 | - Model Exchange 28 | - Functional Mock-up Interface 29 | license: MIT 30 | commit: 1c6f77b 31 | version: 0.8.3 32 | date-released: '2022-06-29' 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/version.txt" projectVersion) 3 | project(fmi4cpp VERSION ${projectVersion}) 4 | message("Current fmi4cpp version: ${projectVersion}\n") 5 | 6 | 7 | # ============================================================================== 8 | # Build settings 9 | # ============================================================================== 10 | 11 | option(FMI4CPP_BUILD_TESTS "Build tests" OFF) 12 | option(FMI4CPP_BUILD_EXAMPLES "Build examples" OFF) 13 | option(BUILD_SHARED_LIBS "Build shared libraries instead of static libraries" ON) 14 | 15 | set(FMI4CPP_LOG_LEVEL "DEFAULT" CACHE STRING "FMI4cpp logging level") 16 | set(FMI4CPP_LOG_LEVEL_VALUES "DEFAULT;OFF;TRACE;DEBUG;INFO;WARN;ERROR;FATAL" CACHE STRING "List of possible log levels") 17 | set_property(CACHE FMI4CPP_LOG_LEVEL PROPERTY STRINGS ${FMI4CPP_LOG_LEVEL_VALUES}) 18 | 19 | 20 | # ============================================================================== 21 | # Global internal configuration 22 | # ============================================================================== 23 | 24 | set(CMAKE_CXX_STANDARD 17) 25 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 26 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 27 | 28 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) 29 | 30 | if (NOT CMAKE_BUILD_TYPE) 31 | set(CMAKE_BUILD_TYPE "Release") 32 | endif () 33 | 34 | if (MSVC) 35 | set(CMAKE_DEBUG_POSTFIX "d") 36 | add_definitions("-D_CRT_SECURE_NO_WARNINGS") 37 | endif () 38 | 39 | include(GNUInstallDirs) 40 | 41 | set(FMI4CPP_HEADER_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") 42 | set(FMI4CPP_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}") 43 | set(FMI4CPP_DOC_INSTALL_DIR "${CMAKE_INSTALL_DOCDIR}") 44 | 45 | set(FMI4CPP_INSTALL_DESTINATIONS 46 | ARCHIVE DESTINATION "lib" 47 | LIBRARY DESTINATION "lib" 48 | RUNTIME DESTINATION "bin" 49 | INCLUDES DESTINATION "${FMI4CPP_HEADER_INSTALL_DIR}") 50 | set(FMI4CPP_EXPORT_TARGET "${PROJECT_NAME}-targets") 51 | 52 | 53 | # ============================================================================== 54 | # Dependencies 55 | # ============================================================================== 56 | 57 | find_package(LIBZIP REQUIRED) 58 | find_package(PugiXML REQUIRED) 59 | 60 | if (FMI4CPP_BUILD_TESTS) 61 | 62 | Include(FetchContent) 63 | FetchContent_Declare( 64 | Catch2 65 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git 66 | GIT_TAG v2.13.8 67 | ) 68 | 69 | FetchContent_MakeAvailable(Catch2) 70 | endif() 71 | 72 | 73 | # ============================================================================== 74 | # Targets 75 | # ============================================================================== 76 | 77 | add_subdirectory(src) 78 | 79 | if (FMI4CPP_BUILD_TESTS) 80 | enable_testing() 81 | add_subdirectory(tests) 82 | endif () 83 | 84 | if (FMI4CPP_BUILD_EXAMPLES) 85 | add_subdirectory(examples) 86 | endif () 87 | 88 | if (FMI4CPP_BUILD_TESTS OR FMI4CPP_BUILD_EXAMPLES) 89 | file(COPY resources DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 90 | endif () 91 | 92 | 93 | # ============================================================================== 94 | # Exports and remaining installation 95 | # ============================================================================== 96 | 97 | install( 98 | EXPORT "${FMI4CPP_EXPORT_TARGET}" 99 | DESTINATION "${FMI4CPP_CMAKE_INSTALL_DIR}" 100 | NAMESPACE "${PROJECT_NAME}::" 101 | ) 102 | 103 | include(CMakePackageConfigHelpers) 104 | 105 | # Generate and install package-config file. 106 | set(configFile "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake") 107 | set(targetsFile "${FMI4CPP_CMAKE_INSTALL_DIR}/${FMI4CPP_EXPORT_TARGET}.cmake") 108 | configure_package_config_file( 109 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in" 110 | "${configFile}" 111 | INSTALL_DESTINATION "${FMI4CPP_CMAKE_INSTALL_DIR}" 112 | PATH_VARS targetsFile 113 | ) 114 | install(FILES "${configFile}" DESTINATION "${FMI4CPP_CMAKE_INSTALL_DIR}") 115 | 116 | # Generate and install package-version file 117 | set(versionFile "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake") 118 | write_basic_package_version_file( 119 | "${versionFile}" 120 | VERSION "${PROJECT_VERSION}" 121 | COMPATIBILITY "SameMajorVersion") 122 | install(FILES "${versionFile}" DESTINATION "${FMI4CPP_CMAKE_INSTALL_DIR}") 123 | 124 | 125 | # Install custom find modules 126 | install(FILES 127 | ${PROJECT_SOURCE_DIR}/cmake/FindLIBZIP.cmake 128 | ${PROJECT_SOURCE_DIR}/cmake/FindPugiXML.cmake 129 | DESTINATION 130 | ${FMI4CPP_CMAKE_INSTALL_DIR} 131 | ) 132 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2021 Norwegian University of Science and Technology 4 | Copyright (c) 2018-2021 fmi4cpp authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FMI4cpp (work in progress) 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/NTNU-IHB/FMU-proxy/issues) 5 | [![Join the chat at https://gitter.im/NTNU-IHB/FMI4cpp](https://badges.gitter.im/NTNU-IHB/FMI4cpp.svg)](https://gitter.im/NTNU-IHB/FMI4cpp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | [![GitHub Actions](https://github.com/NTNU-IHB/FMI4cpp/workflows/Conan/badge.svg)](https://github.com/NTNU-IHB/FMI4cpp/actions) 8 | 9 | FMI4cpp is a cross-platform [FMI](https://fmi-standard.org/) 2.0 implementation written in modern C++. 10 | 11 | Influenced by its spiritual brother [FMI4j](https://github.com/NTNU-IHB/FMI4j), it aims to be 12 | an easy to install, easy to use, object-oriented and fast FMI implementation for C++. 13 | 14 | FMI4cpp supports both **Co-simulation** and **Model Exchange**.
15 | 16 | 17 | ## Build instructions 18 | 19 | Refer to [BUILDING.md](BUILDING.md) 20 | 21 | #### API 22 | 23 | ```cpp 24 | #include 25 | #include 26 | 27 | using namespace fmi4cpp; 28 | 29 | const double stop = ...; 30 | const double stepSize = ...; 31 | 32 | int main() 33 | { 34 | fmi2::fmu fmu("path/to/fmu.fmu"); 35 | 36 | auto cs_fmu = fmu.as_cs_fmu(); 37 | auto me_fmu = fmu.as_me_fmu(); 38 | 39 | auto cs_md = cs_fmu->get_model_description(); //smart pointer to a cs_model_description instance 40 | std::cout << "model_identifier=" << cs_md->model_identifier << std::endl; 41 | 42 | auto me_md = me_fmu->get_model_description(); //smart pointer to a me_model_description instance 43 | std::cout << "model_identifier=" << me_md->model_identifier << std::endl; 44 | 45 | auto var = cs_md->get_variable_by_name("my_var").as_real(); 46 | std::cout << "Name=" << var.name() << ", start=" << var.start().value_or(0) << std::endl; 47 | 48 | auto slave = cs_fmu->new_instance(); 49 | 50 | slave->setup_experiment(); 51 | slave->enter_initialization_mode(); 52 | slave->exit_initialization_mode(); 53 | 54 | double t; 55 | double value; 56 | auto vr = var.valueReference(); 57 | while ( (t = slave->get_simulation_time()) <= stop) { 58 | 59 | if (!slave->step(stepSize)) { 60 | std::cerr << "Error! step() returned with status: " << to_string(slave->last_status()) << std::endl; 61 | break; 62 | } 63 | 64 | if (!slave->read_real(vr, value)) { 65 | std::cerr << "Error! step() returned with status: " << to_string(slave->last_status()) << std::endl; 66 | break; 67 | } 68 | std::cout << "t=" << t << ", " << var.name() << "=" << value << std::endl; 69 | 70 | } 71 | 72 | slave->terminate(); 73 | 74 | return 0; 75 | } 76 | ``` 77 | 78 | *** 79 | 80 | Would you rather simulate FMUs in Java? Check out [FMI4j](https://github.com/NTNU-IHB/FMI4j)!
81 | Would you like to build JVM based FMUs? Check out [FMU4j](https://github.com/https://github.com/Vico-platform/FMU4j)!
82 | Perhaps you want to build FMUs using plain Python? Check out [PythonFMU](https://github.com/NTNU-IHB/PythonFMU)!
83 | Need to distribute your FMUs? [FMU-proxy](https://github.com/NTNU-IHB/FMU-proxy) to the rescue! 84 | 85 | -------------------------------------------------------------------------------- /cmake/FindLIBZIP.cmake: -------------------------------------------------------------------------------- 1 | 2 | # - CMake script for locating libzip 3 | # 4 | # If the script succeeds, it will create an IMPORTED target named 5 | # "libzip::libzip", plus set the following variables: 6 | # 7 | # LIBZIP_FOUND - If the library was found 8 | # LIBZIP_INCLUDE_DIRS - The directory that contains the header files. 9 | # LIBZIP_LIBRARIES - Contains "libzip::libzip" 10 | # LIBZIP_LIBRARY - Path to static/import library file. 11 | # 12 | 13 | find_package(BZip2 QUIET) # optional package - used when building using conan 14 | find_package(OpenSSL COMPONENTS Crypto SSL QUIET) # optional package - used when building using conan on linux 15 | find_package(ZLIB QUIET) # optional package - used when building using conan 16 | find_package(LibLZMA QUIET) # optional package - used when building using conan 17 | 18 | # Find static library, and use its path prefix to provide a HINTS option to the 19 | # other find_*() commands. 20 | find_library (LIBZIP_LIBRARY "zip" 21 | PATHS ${LIBZIP_DIR} $ENV{LIBZIP_DIR} 22 | PATH_SUFFIXES "lib") 23 | mark_as_advanced (LIBZIP_LIBRARY) 24 | unset (_LIBZIP_hints) 25 | if (LIBZIP_LIBRARY) 26 | get_filename_component (_LIBZIP_prefix "${LIBZIP_LIBRARY}" PATH) 27 | get_filename_component (_LIBZIP_prefix "${_LIBZIP_prefix}" PATH) 28 | set (_LIBZIP_hints "HINTS" "${_LIBZIP_prefix}") 29 | unset (_LIBZIP_prefix) 30 | endif () 31 | 32 | # Find header files and, on Windows, the DLL 33 | find_path (LIBZIP_INCLUDE_DIR_zip "zip.h" 34 | ${_LIBZIP_hints} 35 | PATHS ${LIBZIP_DIR} $ENV{LIBZIP_DIR} 36 | PATH_SUFFIXES "include") 37 | find_path (LIBZIP_INCLUDE_DIR_zipconf "zipconf.h" 38 | ${_LIBZIP_hints} 39 | PATHS ${LIBZIP_DIR} $ENV{LIBZIP_DIR} 40 | PATH_SUFFIXES "include" "lib/libzip/include") 41 | set (LIBZIP_INCLUDE_DIRS 42 | "${LIBZIP_INCLUDE_DIR_zip}" "${LIBZIP_INCLUDE_DIR_zipconf}" 43 | ) 44 | 45 | mark_as_advanced (LIBZIP_INCLUDE_DIRS) 46 | 47 | if (WIN32) 48 | find_file (LIBZIP_DLL NAMES "zip.dll" "libzip.dll" 49 | ${_LIBZIP_hints} 50 | PATHS ${LIBZIP_DIR} $ENV{LIBZIP_DIR} 51 | PATH_SUFFIXES "bin" "lib" 52 | NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) 53 | mark_as_advanced (LIBZIP_DLL) 54 | endif () 55 | unset (_LIBZIP_hints) 56 | 57 | # Create the IMPORTED targets. 58 | if (LIBZIP_LIBRARY) 59 | add_library ("libzip::libzip" SHARED IMPORTED) 60 | set_target_properties ("libzip::libzip" PROPERTIES 61 | IMPORTED_LINK_INTERFACE_LANGUAGES "C" 62 | IMPORTED_LOCATION "${LIBZIP_LIBRARY}" 63 | INTERFACE_COMPILE_DEFINITIONS "LIBZIP_STATIC_LIB_ONLY" 64 | INTERFACE_INCLUDE_DIRECTORIES "${LIBZIP_INCLUDE_DIRS}") 65 | if (WIN32) 66 | set_target_properties ("libzip::libzip" PROPERTIES 67 | IMPORTED_IMPLIB "${LIBZIP_LIBRARY}" 68 | IMPORTED_LOCATION "${LIBZIP_DLL}") 69 | else () # not WIN32 70 | set_target_properties ("libzip::libzip" PROPERTIES 71 | IMPORTED_LOCATION "${LIBZIP_LIBRARY}") 72 | endif () 73 | 74 | set (LIBZIP_LIBRARIES "libzip::libzip") 75 | 76 | ##### required by conan when linking libzip statically #### 77 | set(LIBZIP_interfaceLinkLibraries) 78 | if (ZLIB_FOUND) 79 | list(APPEND LIBZIP_interfaceLinkLibraries ZLIB::ZLIB) 80 | endif() 81 | if (LIBLZMA_FOUND) 82 | list(APPEND LIBZIP_interfaceLinkLibraries LibLZMA::LibLZMA) 83 | endif() 84 | if (BZip2_FOUND) 85 | list(APPEND LIBZIP_interfaceLinkLibraries BZip2::BZip2) 86 | endif() 87 | if (OpenSSL_FOUND) 88 | list(APPEND LIBZIP_interfaceLinkLibraries OpenSSL::SSL OpenSSL::Crypto) 89 | endif() 90 | if (BZip2_FOUND OR OpenSSL_FOUND) 91 | set_property(TARGET libzip::libzip 92 | APPEND 93 | PROPERTY INTERFACE_LINK_LIBRARIES 94 | ${LIBZIP_interfaceLinkLibraries}) 95 | endif() 96 | ############################################################### 97 | endif () 98 | 99 | # Debug print-out. 100 | if (LIBZIP_PRINT_VARS) 101 | message ("LIBZIP find script variables:") 102 | message (" LIBZIP_INCLUDE_DIRS = ${LIBZIP_INCLUDE_DIRS}") 103 | message (" LIBZIP_LIBRARIES = ${LIBZIP_LIBRARIES}") 104 | message (" LIBZIP_DLL = ${LIBZIP_DLL}") 105 | message (" LIBZIP_LIBRARY = ${LIBZIP_LIBRARY}") 106 | endif () 107 | 108 | # Standard find_package stuff. 109 | include (FindPackageHandleStandardArgs) 110 | find_package_handle_standard_args (LIBZIP DEFAULT_MSG LIBZIP_LIBRARIES LIBZIP_INCLUDE_DIRS) -------------------------------------------------------------------------------- /cmake/FindPugiXML.cmake: -------------------------------------------------------------------------------- 1 | # Find the pugixml XML parsing library. 2 | # 3 | # Sets the usual variables expected for find_package scripts: 4 | # 5 | # PUGIXML_INCLUDE_DIR - header location 6 | # PUGIXML_LIBRARIES - library to link against 7 | # PUGIXML_FOUND - true if pugixml was found. 8 | find_path(PUGIXML_INCLUDE_DIR NAMES pugixml.hpp PATHS ${PUGIXML_HOME}/include) 9 | find_library(PUGIXML_LIBRARY NAMES pugixml PATHS ${PUGIXML_HOME}/lib) 10 | 11 | # Support the REQUIRED and QUIET arguments, and set PUGIXML_FOUND if found. 12 | include(FindPackageHandleStandardArgs) 13 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(PugiXML DEFAULT_MSG PUGIXML_LIBRARY 14 | PUGIXML_INCLUDE_DIR) 15 | 16 | if (PUGIXML_FOUND) 17 | set(PUGIXML_LIBRARIES ${PUGIXML_LIBRARY}) 18 | message(STATUS "PugiXML include = ${PUGIXML_INCLUDE_DIR}") 19 | message(STATUS "PugiXML library = ${PUGIXML_LIBRARY}") 20 | else () 21 | message(STATUS "No PugiXML found") 22 | endif () 23 | 24 | if (PUGIXML_FOUND AND NOT TARGET pugixml::pugixml) 25 | add_library(pugixml::pugixml INTERFACE IMPORTED) 26 | target_include_directories(pugixml::pugixml INTERFACE "${PUGIXML_INCLUDE_DIR}") 27 | target_link_libraries(pugixml::pugixml INTERFACE "${PUGIXML_LIBRARY}") 28 | endif () 29 | 30 | mark_as_advanced(PUGIXML_LIBRARY PUGIXML_INCLUDE_DIR) 31 | -------------------------------------------------------------------------------- /cmake/fmi4cpp-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | include ("@PACKAGE_targetsFile@") 3 | 4 | get_filename_component(FMI4CPP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 5 | include(CMakeFindDependencyMacro) 6 | 7 | list(APPEND CMAKE_MODULE_PATH ${FMI4CPP_CMAKE_DIR}) 8 | 9 | find_dependency(LIBZIP REQUIRED) 10 | find_dependency(PugiXML REQUIRED) 11 | 12 | list(REMOVE_AT CMAKE_MODULE_PATH -1) 13 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | link_libraries(fmi4cpp::fmi4cpp) 3 | include_directories(${fmi4cpp_SOURCE_DIR}/src/fmi4cpp/tools) 4 | 5 | add_executable(fmu_test fmu_test.cpp) 6 | add_executable(torsionbar torsionbar.cpp) 7 | add_executable(multiple_fmus multiple_fmus.cpp) 8 | add_executable(controlled_temperature controlled_temperature.cpp) 9 | -------------------------------------------------------------------------------- /examples/controlled_temperature.cpp: -------------------------------------------------------------------------------- 1 | #include "time_util.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | using namespace fmi4cpp; 8 | 9 | const double stop = 10.0; 10 | const double step_size = 1E-4; 11 | 12 | void run(std::unique_ptr& slave) 13 | { 14 | slave->setup_experiment(); 15 | slave->enter_initialization_mode(); 16 | slave->exit_initialization_mode(); 17 | 18 | auto elapsed = measure_time_sec([&slave] { 19 | double ref; 20 | const auto vr = slave->get_model_description()->get_variable_by_name("Temperature_Room").as_real().valueReference(); 21 | while ((slave->get_simulation_time()) <= (stop - step_size)) { 22 | if (!slave->step(step_size)) { 23 | std::cerr << "Error! step returned with status: " << to_string(slave->last_status()) << std::endl; 24 | break; 25 | } 26 | if (!slave->read_real(vr, ref)) { 27 | std::cerr << "Error! read_real returned with status: " << to_string(slave->last_status()) << std::endl; 28 | break; 29 | } 30 | } 31 | }); 32 | 33 | std::cout << "Time elapsed=" << elapsed << "s" << std::endl; 34 | 35 | slave->terminate(); 36 | } 37 | 38 | int main() 39 | { 40 | const std::string fmu_path = "../resources/fmus/2.0/cs/20sim/4.6.4.8004/" 41 | "ControlledTemperature/ControlledTemperature.fmu"; 42 | 43 | auto fmu = fmi2::fmu(fmu_path).as_cs_fmu()->new_instance(); 44 | run(fmu); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /examples/fmu_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | using namespace fmi4cpp; 7 | 8 | const double stop = 0.01; 9 | const double stepSize = 1E-3; 10 | 11 | int main() 12 | { 13 | const std::string fmuPath = "../resources/fmus/2.0/cs/20sim/4.6.4.8004/" 14 | "ControlledTemperature/ControlledTemperature.fmu"; 15 | 16 | fmi2::fmu fmu(fmuPath); 17 | auto cs_fmu = fmu.as_cs_fmu(); 18 | auto md = cs_fmu->get_model_description(); 19 | 20 | auto var = md->model_variables->getByValueReference(47).as_real(); 21 | std::cout << "Name=" << var.name() << ", start=" << var.start().value_or(0) << std::endl; 22 | 23 | auto slave1 = cs_fmu->new_instance(); 24 | auto slave2 = cs_fmu->new_instance(); 25 | 26 | std::cout << "model_identifier=" << slave1->get_model_description()->model_identifier << std::endl; 27 | 28 | slave1->setup_experiment(); 29 | slave1->enter_initialization_mode(); 30 | slave1->exit_initialization_mode(); 31 | 32 | slave2->setup_experiment(); 33 | slave2->enter_initialization_mode(); 34 | slave2->exit_initialization_mode(); 35 | 36 | std::vector ref(2); 37 | std::vector vr = {md->get_variable_by_name("Temperature_Reference").value_reference, 38 | md->get_variable_by_name("Temperature_Room").value_reference}; 39 | 40 | double t; 41 | while ((t = slave1->get_simulation_time()) <= stop) { 42 | 43 | if (!slave1->step(stepSize)) { break; } 44 | if (!slave1->read_real(vr, ref)) { break; } 45 | std::cout << "t=" << t << ", Temperature_Reference=" << ref[0] << ", Temperature_Room=" << ref[1] << std::endl; 46 | } 47 | 48 | std::cout << "FMU '" << fmu.model_name() << "' terminated with success: " << std::boolalpha << slave1->terminate() << std::endl; 49 | std::cout << "FMU '" << fmu.model_name() << "' terminated with success: " << std::boolalpha << slave2->terminate() << std::endl; 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /examples/multiple_fmus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | using namespace fmi4cpp; 7 | 8 | int main() 9 | { 10 | const std::string fmu_path1 = "../resources/fmus/2.0/cs/20sim/4.6.4.8004/" 11 | "TorsionBar/TorsionBar.fmu"; 12 | 13 | const std::string fmu_path2 = "../resources/fmus/2.0/cs/20sim/4.6.4.8004/" 14 | "ControlledTemperature/ControlledTemperature.fmu"; 15 | 16 | fmi2::fmu fmu1(fmu_path1); 17 | fmi2::fmu fmu2(fmu_path2); 18 | 19 | const auto slave1 = fmu1.as_cs_fmu()->new_instance(); 20 | const auto md1 = slave1->get_model_description(); 21 | 22 | slave1->setup_experiment(); 23 | slave1->enter_initialization_mode(); 24 | slave1->exit_initialization_mode(); 25 | 26 | const auto slave2 = fmu2.as_cs_fmu()->new_instance(); 27 | const auto md2 = slave2->get_model_description(); 28 | slave2->setup_experiment(); 29 | slave2->enter_initialization_mode(); 30 | slave2->exit_initialization_mode(); 31 | 32 | slave1->step(1E-5); 33 | slave2->step(1E-4); 34 | 35 | double ref; 36 | { 37 | auto vr = md1->get_variable_by_name("MotorDiskRev").value_reference; 38 | assert(vr == 105); 39 | slave1->read_real(vr, ref); 40 | std::cout << "MotorDiskRev=" << ref << std::endl; 41 | } 42 | 43 | { 44 | auto vr = md2->get_value_reference("Temperature_Room"); 45 | assert(vr == 47); 46 | slave2->read_real(vr, ref); 47 | std::cout << "Temperature_Room=" << ref << std::endl; 48 | } 49 | 50 | slave1->terminate(); 51 | slave2->terminate(); 52 | 53 | return 0; 54 | } -------------------------------------------------------------------------------- /examples/time_util.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_TIME_UTIL_HPP 3 | #define FMI4CPP_TIME_UTIL_HPP 4 | 5 | #include 6 | 7 | namespace 8 | { 9 | 10 | template 11 | inline float measure_time_sec(function&& fun) 12 | { 13 | auto t_start = std::chrono::high_resolution_clock::now(); 14 | fun(); 15 | auto t_stop = std::chrono::high_resolution_clock::now(); 16 | return std::chrono::duration(t_stop - t_start).count(); 17 | } 18 | 19 | } // namespace 20 | 21 | #endif //FMI4CPP_TIME_UTIL_HPP 22 | -------------------------------------------------------------------------------- /examples/torsionbar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include "time_util.hpp" 5 | 6 | using namespace fmi4cpp; 7 | 8 | const double stop = 12.0; 9 | const double step_size = 1E-5; 10 | const fmi2ValueReference vr = 2; 11 | 12 | int main() 13 | { 14 | const std::string fmu_path = "../resources/fmus/2.0/cs/20sim/4.6.4.8004/" 15 | "TorsionBar/TorsionBar.fmu"; 16 | 17 | fmi2::fmu fmu(fmu_path); 18 | 19 | const auto slave = fmu.as_cs_fmu()->new_instance(); 20 | slave->setup_experiment(); 21 | slave->enter_initialization_mode(); 22 | slave->exit_initialization_mode(); 23 | 24 | auto elapsed = measure_time_sec([&slave] { 25 | double ref; 26 | while ((slave->get_simulation_time()) <= (stop - step_size)) { 27 | if (!slave->step(step_size)) { 28 | std::cerr << "Error! step returned with status: " << to_string(slave->last_status()) << std::endl; 29 | break; 30 | } 31 | if (!slave->read_real(vr, ref)) { 32 | std::cerr << "Error! read_real returned with status: " << to_string(slave->last_status()) << std::endl; 33 | break; 34 | } 35 | } 36 | }); 37 | 38 | std::cout << "Time elapsed=" << elapsed << "s" << std::endl; 39 | 40 | slave->terminate(); 41 | 42 | return 0; 43 | } -------------------------------------------------------------------------------- /include/fmi4cpp/dll_handle.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_DLL_HANDLE_HPP 3 | #define FMI4CPP_DLL_HANDLE_HPP 4 | 5 | #if defined(_MSC_VER) || defined(WIN32) || defined(__MINGW32__) 6 | # define WIN32_LEAN_AND_MEAN 7 | # include 8 | # define DLL_HANDLE HMODULE 9 | #else 10 | # define DLL_HANDLE void* 11 | # include 12 | #endif 13 | 14 | #ifdef WIN32 15 | # define function_ptr FARPROC 16 | #else 17 | typedef void* function_ptr; 18 | #endif 19 | 20 | #endif //FMI4CPP_DLL_HANDLE_HPP 21 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/cs_fmu.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2COSIMULATIONFMU_H 3 | #define FMI4CPP_FMI2COSIMULATIONFMU_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | namespace fmi4cpp::fmi2 13 | { 14 | 15 | class cs_fmu : public cs_fmu_base 16 | { 17 | 18 | private: 19 | std::shared_ptr lib_; 20 | std::shared_ptr resource_; 21 | std::shared_ptr modelDescription_; 22 | 23 | public: 24 | cs_fmu(std::shared_ptr resource, 25 | std::shared_ptr md); 26 | 27 | [[nodiscard]] std::string get_model_description_xml() const; 28 | 29 | [[nodiscard]] std::shared_ptr get_model_description() const override; 30 | 31 | std::unique_ptr new_instance(bool visible = false, bool loggingOn = false) override; 32 | }; 33 | 34 | } // namespace fmi4cpp::fmi2 35 | 36 | #endif //FMI4CPP_FMI2COSIMULATIONFMU_H 37 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/cs_library.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2COSIMULATIONLIBRARY_HPP 3 | #define FMI4CPP_FMI2COSIMULATIONLIBRARY_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp::fmi2 8 | { 9 | 10 | class cs_library : public fmi2_library 11 | { 12 | 13 | private: 14 | fmi2SetRealInputDerivativesTYPE* fmi2SetRealInputDerivatives_; 15 | fmi2GetRealOutputDerivativesTYPE* fmi2GetRealOutputDerivatives_; 16 | 17 | fmi2DoStepTYPE* fmi2DoStep_; 18 | fmi2CancelStepTYPE* fmi2CancelStep_; 19 | 20 | fmi2GetStatusTYPE* fmi2GetStatus_; 21 | fmi2GetRealStatusTYPE* fmi2GetRealStatus_; 22 | fmi2GetIntegerStatusTYPE* fmi2GetIntegerStatus_; 23 | fmi2GetBooleanStatusTYPE* fmi2GetBooleanStatus_; 24 | fmi2GetStringStatusTYPE* fmi2GetStringStatus_; 25 | 26 | public: 27 | cs_library( 28 | const std::string& modelIdentifier, 29 | const std::shared_ptr& resource); 30 | 31 | bool step(fmi2Component c, fmi2Real currentCommunicationPoint, 32 | fmi2Real communicationStepSize, bool noSetFMUStatePriorToCurrentPoint); 33 | 34 | bool cancel_step(fmi2Component c); 35 | 36 | bool set_real_input_derivatives(fmi2Component c, 37 | const std::vector& vr, 38 | const std::vector& order, 39 | const std::vector& value); 40 | 41 | bool get_real_output_derivatives(fmi2Component c, 42 | const std::vector& vr, 43 | const std::vector& order, 44 | std::vector& value); 45 | 46 | bool get_status(fmi2Component c, fmi2StatusKind s, fmi2Status& value); 47 | bool get_real_status(fmi2Component c, fmi2StatusKind s, fmi2Real& value); 48 | bool get_integer_status(fmi2Component c, fmi2StatusKind s, fmi2Integer& value); 49 | bool get_boolean_status(fmi2Component c, fmi2StatusKind s, fmi2Boolean& value); 50 | bool get_string_status(fmi2Component c, fmi2StatusKind s, fmi2String& value); 51 | }; 52 | 53 | } // namespace fmi4cpp::fmi2 54 | 55 | #endif //FMI4CPP_FMI2COSIMULATIONLIBRARY_HPP 56 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/cs_slave.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2_CS_SLAVE_HPP 3 | #define FMI4CPP_FMI2_CS_SLAVE_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | 15 | namespace fmi4cpp::fmi2 16 | { 17 | 18 | class cs_slave : public virtual fmu_slave, 19 | public fmu_instance_base 20 | { 21 | 22 | public: 23 | cs_slave(fmi2Component c, 24 | const std::shared_ptr& resource, 25 | const std::shared_ptr& library, 26 | const std::shared_ptr& modelDescription); 27 | 28 | bool step(double stepSize) override; 29 | bool cancel_step() override; 30 | 31 | [[nodiscard]] std::shared_ptr get_model_description() const override; 32 | 33 | [[nodiscard]] DLL_HANDLE handle() const override; 34 | [[nodiscard]] status last_status() const override; 35 | 36 | bool setup_experiment(double start = 0, double stop = 0, double tolerance = 0) override; 37 | bool enter_initialization_mode() override; 38 | bool exit_initialization_mode() override; 39 | 40 | bool reset() override; 41 | bool terminate() override; 42 | 43 | bool read_integer(fmi2ValueReference vr, fmi2Integer& ref) override; 44 | bool read_integer(const std::vector& vr, std::vector& ref) override; 45 | 46 | bool read_real(fmi2ValueReference vr, fmi2Real& ref) override; 47 | bool read_real(const std::vector& vr, std::vector& ref) override; 48 | 49 | bool read_string(fmi2ValueReference vr, fmi2String& ref) override; 50 | bool read_string(const std::vector& vr, std::vector& ref) override; 51 | 52 | bool read_boolean(fmi2ValueReference vr, fmi2Boolean& ref) override; 53 | bool read_boolean(const std::vector& vr, std::vector& ref) override; 54 | 55 | bool write_integer(fmi2ValueReference vr, fmi2Integer value) override; 56 | bool write_integer(const std::vector& vr, const std::vector& values) override; 57 | 58 | bool write_real(fmi2ValueReference vr, fmi2Real value) override; 59 | bool write_real(const std::vector& vr, const std::vector& values) override; 60 | 61 | bool write_string(fmi2ValueReference vr, fmi2String value) override; 62 | bool write_string(const std::vector& vr, const std::vector& values) override; 63 | 64 | bool write_boolean(fmi2ValueReference vr, fmi2Boolean value) override; 65 | bool write_boolean(const std::vector& vr, const std::vector& values) override; 66 | 67 | 68 | bool get_fmu_state(fmi2FMUstate& state) override; 69 | bool set_fmu_state(fmi2FMUstate state) override; 70 | bool free_fmu_state(fmi2FMUstate& state) override; 71 | 72 | bool serialize_fmu_state(const fmi2FMUstate& state, std::vector& serializedState) override; 73 | bool de_serialize_fmu_state(fmi2FMUstate& state, const std::vector& serializedState) override; 74 | 75 | bool get_directional_derivative(const std::vector& vUnknownRef, 76 | const std::vector& vKnownRef, 77 | const std::vector& dvKnownRef, 78 | std::vector& dvUnknownRef) override; 79 | }; 80 | 81 | } // namespace fmi4cpp::fmi2 82 | 83 | 84 | #endif //FMI4CPP_FMI2_CS_SLAVE_HPP 85 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/fmi2.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2_HPP 3 | #define FMI4CPP_FMI2_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #endif //FMI4CPP_FMI2_HPP 16 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/fmi2FunctionTypes.h: -------------------------------------------------------------------------------- 1 | #ifndef fmi2FunctionTypes_h 2 | #define fmi2FunctionTypes_h 3 | 4 | #include "fmi2TypesPlatform.h" 5 | 6 | /* This header file must be utilized when compiling an FMU or an FMI master. 7 | It declares data and function types for FMI 2.0 8 | 9 | Revisions: 10 | - Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8) 11 | - Apr. 3, 2014: Added #include for size_t definition 12 | - Mar. 27, 2014: Added #include "fmiTypesPlatform.h" (#179) 13 | - Mar. 26, 2014: Introduced function argument "void" for the functions (#171) 14 | fmiGetTypesPlatformTYPE and fmiGetVersionTYPE 15 | - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: 16 | fmiInstantiateModelTYPE , fmiInstantiateSlaveTYPE -> fmiInstantiateTYPE 17 | fmiFreeModelInstanceTYPE, fmiFreeSlaveInstanceTYPE -> fmiFreeInstanceTYPE 18 | fmiEnterModelInitializationModeTYPE, fmiEnterSlaveInitializationModeTYPE -> fmiEnterInitializationModeTYPE 19 | fmiExitModelInitializationModeTYPE , fmiExitSlaveInitializationModeTYPE -> fmiExitInitializationModeTYPE 20 | fmiTerminateModelTYPE , fmiTerminateSlaveTYPE -> fmiTerminate 21 | fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) 22 | Functions renamed 23 | fmiUpdateDiscreteStatesTYPE -> fmiNewDiscreteStatesTYPE 24 | Renamed elements of the enumeration fmiEventInfo 25 | upcomingTimeEvent -> nextEventTimeDefined // due to generic naming scheme: varDefined + var 26 | newUpdateDiscreteStatesNeeded -> newDiscreteStatesNeeded; 27 | - June 13, 2013: Changed type fmiEventInfo 28 | Functions removed: 29 | fmiInitializeModelTYPE 30 | fmiEventUpdateTYPE 31 | fmiCompletedEventIterationTYPE 32 | fmiInitializeSlaveTYPE 33 | Functions added: 34 | fmiEnterModelInitializationModeTYPE 35 | fmiExitModelInitializationModeTYPE 36 | fmiEnterEventModeTYPE 37 | fmiUpdateDiscreteStatesTYPE 38 | fmiEnterContinuousTimeModeTYPE 39 | fmiEnterSlaveInitializationModeTYPE; 40 | fmiExitSlaveInitializationModeTYPE; 41 | - Feb. 17, 2013: Added third argument to fmiCompletedIntegratorStepTYPE 42 | Changed function name "fmiTerminateType" to "fmiTerminateModelType" (due to #113) 43 | Changed function name "fmiGetNominalContinuousStateTYPE" to 44 | "fmiGetNominalsOfContinuousStatesTYPE" 45 | Removed fmiGetStateValueReferencesTYPE. 46 | - Nov. 14, 2011: First public Version 47 | 48 | 49 | Copyright © 2011 MODELISAR consortium, 50 | 2012-2013 Modelica Association Project "FMI" 51 | All rights reserved. 52 | This file is licensed by the copyright holders under the BSD 2-Clause License 53 | (http://www.opensource.org/licenses/bsd-license.html): 54 | 55 | ---------------------------------------------------------------------------- 56 | Redistribution and use in source and binary forms, with or without 57 | modification, are permitted provided that the following conditions are met: 58 | 59 | - Redistributions of source code must retain the above copyright notice, 60 | this list of conditions and the following disclaimer. 61 | - Redistributions in binary form must reproduce the above copyright notice, 62 | this list of conditions and the following disclaimer in the documentation 63 | and/or other materials provided with the distribution. 64 | - Neither the name of the copyright holders nor the names of its 65 | contributors may be used to endorse or promote products derived 66 | from this software without specific prior written permission. 67 | 68 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 69 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 70 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 71 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 72 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 73 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 74 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 75 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 76 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 77 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 78 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 79 | ---------------------------------------------------------------------------- 80 | 81 | with the extension: 82 | 83 | You may distribute or publicly perform any modification only under the 84 | terms of this license. 85 | (Note, this means that if you distribute a modified file, 86 | the modified file must also be provided under this license). 87 | */ 88 | 89 | #ifdef __cplusplus 90 | extern "C" { 91 | #endif 92 | 93 | /* make sure all compiler use the same alignment policies for structures */ 94 | #if defined _MSC_VER || defined __GNUC__ 95 | #pragma pack(push, 8) 96 | #endif 97 | 98 | /* Include stddef.h, in order that size_t etc. is defined */ 99 | #include 100 | 101 | 102 | /* Type definitions */ 103 | typedef enum { 104 | fmi2OK, 105 | fmi2Warning, 106 | fmi2Discard, 107 | fmi2Error, 108 | fmi2Fatal, 109 | fmi2Pending 110 | } fmi2Status; 111 | 112 | typedef enum { 113 | fmi2ModelExchange, 114 | fmi2CoSimulation 115 | } fmi2Type; 116 | 117 | typedef enum { 118 | fmi2DoStepStatus, 119 | fmi2PendingStatus, 120 | fmi2LastSuccessfulTime, 121 | fmi2Terminated 122 | } fmi2StatusKind; 123 | 124 | typedef void (*fmi2CallbackLogger)(fmi2ComponentEnvironment, fmi2String, fmi2Status, fmi2String, fmi2String, ...); 125 | typedef void *(*fmi2CallbackAllocateMemory)(size_t, size_t); 126 | typedef void (*fmi2CallbackFreeMemory)(void *); 127 | typedef void (*fmi2StepFinished)(fmi2ComponentEnvironment, fmi2Status); 128 | 129 | typedef struct { 130 | const fmi2CallbackLogger logger; 131 | const fmi2CallbackAllocateMemory allocateMemory; 132 | const fmi2CallbackFreeMemory freeMemory; 133 | const fmi2StepFinished stepFinished; 134 | const fmi2ComponentEnvironment componentEnvironment; 135 | } fmi2CallbackFunctions; 136 | 137 | typedef struct { 138 | fmi2Boolean newDiscreteStatesNeeded; 139 | fmi2Boolean terminateSimulation; 140 | fmi2Boolean nominalsOfContinuousStatesChanged; 141 | fmi2Boolean valuesOfContinuousStatesChanged; 142 | fmi2Boolean nextEventTimeDefined; 143 | fmi2Real nextEventTime; 144 | } fmi2EventInfo; 145 | 146 | 147 | /* reset alignment policy to the one set before reading this file */ 148 | #if defined _MSC_VER || defined __GNUC__ 149 | #pragma pack(pop) 150 | #endif 151 | 152 | 153 | /* Define fmi2 function pointer types to simplify dynamic loading */ 154 | 155 | /*************************************************** 156 | Types for Common Functions 157 | ****************************************************/ 158 | 159 | /* Inquire version numbers of header files and setting logging status */ 160 | typedef const char *fmi2GetTypesPlatformTYPE(void); 161 | typedef const char *fmi2GetVersionTYPE(void); 162 | typedef fmi2Status fmi2SetDebugLoggingTYPE(fmi2Component, fmi2Boolean, size_t, const fmi2String[]); 163 | 164 | /* Creation and destruction of FMU instances and setting debug status */ 165 | typedef fmi2Component fmi2InstantiateTYPE(fmi2String, fmi2Type, fmi2String, fmi2String, const fmi2CallbackFunctions *, 166 | fmi2Boolean, fmi2Boolean); 167 | typedef void fmi2FreeInstanceTYPE(fmi2Component); 168 | 169 | /* Enter and exit initialization mode, terminate and reset */ 170 | typedef fmi2Status fmi2SetupExperimentTYPE(fmi2Component, fmi2Boolean, fmi2Real, fmi2Real, fmi2Boolean, fmi2Real); 171 | typedef fmi2Status fmi2EnterInitializationModeTYPE(fmi2Component); 172 | typedef fmi2Status fmi2ExitInitializationModeTYPE(fmi2Component); 173 | typedef fmi2Status fmi2TerminateTYPE(fmi2Component); 174 | typedef fmi2Status fmi2ResetTYPE(fmi2Component); 175 | 176 | /* Getting and setting variable values */ 177 | typedef fmi2Status fmi2GetRealTYPE(fmi2Component, const fmi2ValueReference[], size_t, fmi2Real []); 178 | typedef fmi2Status fmi2GetIntegerTYPE(fmi2Component, const fmi2ValueReference[], size_t, fmi2Integer[]); 179 | typedef fmi2Status fmi2GetBooleanTYPE(fmi2Component, const fmi2ValueReference[], size_t, fmi2Boolean[]); 180 | typedef fmi2Status fmi2GetStringTYPE(fmi2Component, const fmi2ValueReference[], size_t, fmi2String []); 181 | 182 | typedef fmi2Status fmi2SetRealTYPE(fmi2Component, const fmi2ValueReference[], size_t, const fmi2Real []); 183 | typedef fmi2Status fmi2SetIntegerTYPE(fmi2Component, const fmi2ValueReference[], size_t, const fmi2Integer[]); 184 | typedef fmi2Status fmi2SetBooleanTYPE(fmi2Component, const fmi2ValueReference[], size_t, const fmi2Boolean[]); 185 | typedef fmi2Status fmi2SetStringTYPE(fmi2Component, const fmi2ValueReference[], size_t, const fmi2String []); 186 | 187 | /* Getting and setting the internal FMU state */ 188 | typedef fmi2Status fmi2GetFMUstateTYPE(fmi2Component, fmi2FMUstate *); 189 | typedef fmi2Status fmi2SetFMUstateTYPE(fmi2Component, fmi2FMUstate); 190 | typedef fmi2Status fmi2FreeFMUstateTYPE(fmi2Component, fmi2FMUstate *); 191 | typedef fmi2Status fmi2SerializedFMUstateSizeTYPE(fmi2Component, fmi2FMUstate, size_t *); 192 | typedef fmi2Status fmi2SerializeFMUstateTYPE(fmi2Component, fmi2FMUstate, fmi2Byte[], size_t); 193 | typedef fmi2Status fmi2DeSerializeFMUstateTYPE(fmi2Component, const fmi2Byte[], size_t, fmi2FMUstate *); 194 | 195 | /* Getting partial derivatives */ 196 | typedef fmi2Status fmi2GetDirectionalDerivativeTYPE(fmi2Component, const fmi2ValueReference[], size_t, 197 | const fmi2ValueReference[], size_t, 198 | const fmi2Real[], fmi2Real[]); 199 | 200 | /*************************************************** 201 | Types for Functions for FMI2 for Model Exchange 202 | ****************************************************/ 203 | 204 | /* Enter and exit the different modes */ 205 | typedef fmi2Status fmi2EnterEventModeTYPE(fmi2Component); 206 | typedef fmi2Status fmi2NewDiscreteStatesTYPE(fmi2Component, fmi2EventInfo *); 207 | typedef fmi2Status fmi2EnterContinuousTimeModeTYPE(fmi2Component); 208 | typedef fmi2Status fmi2CompletedIntegratorStepTYPE(fmi2Component, fmi2Boolean, fmi2Boolean *, fmi2Boolean *); 209 | 210 | /* Providing independent variables and re-initialization of caching */ 211 | typedef fmi2Status fmi2SetTimeTYPE(fmi2Component, fmi2Real); 212 | typedef fmi2Status fmi2SetContinuousStatesTYPE(fmi2Component, const fmi2Real[], size_t); 213 | 214 | /* Evaluation of the model equations */ 215 | typedef fmi2Status fmi2GetDerivativesTYPE(fmi2Component, fmi2Real[], size_t); 216 | typedef fmi2Status fmi2GetEventIndicatorsTYPE(fmi2Component, fmi2Real[], size_t); 217 | typedef fmi2Status fmi2GetContinuousStatesTYPE(fmi2Component, fmi2Real[], size_t); 218 | typedef fmi2Status fmi2GetNominalsOfContinuousStatesTYPE(fmi2Component, fmi2Real[], size_t); 219 | 220 | 221 | /*************************************************** 222 | Types for Functions for FMI2 for Co-Simulation 223 | ****************************************************/ 224 | 225 | /* Simulating the slave */ 226 | typedef fmi2Status fmi2SetRealInputDerivativesTYPE(fmi2Component, const fmi2ValueReference [], size_t, 227 | const fmi2Integer [], const fmi2Real []); 228 | typedef fmi2Status fmi2GetRealOutputDerivativesTYPE(fmi2Component, const fmi2ValueReference [], size_t, 229 | const fmi2Integer [], fmi2Real []); 230 | 231 | typedef fmi2Status fmi2DoStepTYPE(fmi2Component, fmi2Real, fmi2Real, fmi2Boolean); 232 | typedef fmi2Status fmi2CancelStepTYPE(fmi2Component); 233 | 234 | /* Inquire slave status */ 235 | typedef fmi2Status fmi2GetStatusTYPE(fmi2Component, const fmi2StatusKind, fmi2Status *); 236 | typedef fmi2Status fmi2GetRealStatusTYPE(fmi2Component, const fmi2StatusKind, fmi2Real *); 237 | typedef fmi2Status fmi2GetIntegerStatusTYPE(fmi2Component, const fmi2StatusKind, fmi2Integer *); 238 | typedef fmi2Status fmi2GetBooleanStatusTYPE(fmi2Component, const fmi2StatusKind, fmi2Boolean *); 239 | typedef fmi2Status fmi2GetStringStatusTYPE(fmi2Component, const fmi2StatusKind, fmi2String *); 240 | 241 | 242 | #ifdef __cplusplus 243 | } /* end of extern "C" { */ 244 | #endif 245 | 246 | #endif /* fmi2FunctionTypes_h */ 247 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/fmi2Functions.h: -------------------------------------------------------------------------------- 1 | #ifndef fmi2Functions_h 2 | #define fmi2Functions_h 3 | 4 | /* This header file must be utilized when compiling a FMU. 5 | It defines all functions of the 6 | FMI 2.0 Model Exchange and Co-Simulation Interface. 7 | 8 | In order to have unique function names even if several FMUs 9 | are compiled together (e.g. for embedded systems), every "real" function name 10 | is constructed by prepending the function name by "FMI2_FUNCTION_PREFIX". 11 | Therefore, the typical usage is: 12 | 13 | #define FMI2_FUNCTION_PREFIX MyModel_ 14 | #include "fmi2Functions.h" 15 | 16 | As a result, a function that is defined as "fmi2GetDerivatives" in this header file, 17 | is actually getting the name "MyModel_fmi2GetDerivatives". 18 | 19 | This only holds if the FMU is shipped in C source code, or is compiled in a 20 | static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function 21 | names are used and "FMI2_FUNCTION_PREFIX" must not be defined. 22 | 23 | Revisions: 24 | - Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8) 25 | - Mar. 26, 2014: FMI_Export set to empty value if FMI_Export and FMI_FUNCTION_PREFIX 26 | are not defined (#173) 27 | - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: 28 | fmiInstantiateModel , fmiInstantiateSlave -> fmiInstantiate 29 | fmiFreeModelInstance, fmiFreeSlaveInstance -> fmiFreeInstance 30 | fmiEnterModelInitializationMode, fmiEnterSlaveInitializationMode -> fmiEnterInitializationMode 31 | fmiExitModelInitializationMode , fmiExitSlaveInitializationMode -> fmiExitInitializationMode 32 | fmiTerminateModel, fmiTerminateSlave -> fmiTerminate 33 | fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) 34 | Functions renamed: 35 | fmiUpdateDiscreteStates -> fmiNewDiscreteStates 36 | - June 13, 2013: Functions removed: 37 | fmiInitializeModel 38 | fmiEventUpdate 39 | fmiCompletedEventIteration 40 | fmiInitializeSlave 41 | Functions added: 42 | fmiEnterModelInitializationMode 43 | fmiExitModelInitializationMode 44 | fmiEnterEventMode 45 | fmiUpdateDiscreteStates 46 | fmiEnterContinuousTimeMode 47 | fmiEnterSlaveInitializationMode; 48 | fmiExitSlaveInitializationMode; 49 | - Feb. 17, 2013: Portability improvements: 50 | o DllExport changed to FMI_Export 51 | o FUNCTION_PREFIX changed to FMI_FUNCTION_PREFIX 52 | o Allow undefined FMI_FUNCTION_PREFIX (meaning no prefix is used) 53 | Changed function name "fmiTerminate" to "fmiTerminateModel" (due to #113) 54 | Changed function name "fmiGetNominalContinuousState" to 55 | "fmiGetNominalsOfContinuousStates" 56 | Removed fmiGetStateValueReferences. 57 | - Nov. 14, 2011: Adapted to FMI 2.0: 58 | o Split into two files (fmiFunctions.h, fmiTypes.h) in order 59 | that code that dynamically loads an FMU can directly 60 | utilize the header files). 61 | o Added C++ encapsulation of C-part, in order that the header 62 | file can be directly utilized in C++ code. 63 | o fmiCallbackFunctions is passed as pointer to fmiInstantiateXXX 64 | o stepFinished within fmiCallbackFunctions has as first 65 | argument "fmiComponentEnvironment" and not "fmiComponent". 66 | o New functions to get and set the complete FMU state 67 | and to compute partial derivatives. 68 | - Nov. 4, 2010: Adapted to specification text: 69 | o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform 70 | o fmiInstantiateSlave: Argument GUID replaced by fmuGUID 71 | Argument mimetype replaced by mimeType 72 | o tabs replaced by spaces 73 | - Oct. 16, 2010: Functions for FMI for Co-simulation added 74 | - Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27) 75 | (by M. Otter, DLR) 76 | Added WIN32 pragma to define the struct layout (ticket #34) 77 | (by J. Mauss, QTronic) 78 | - Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize 79 | Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion 80 | Renamed macro fmiModelFunctionsVersion to fmiVersion 81 | Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel 82 | (by J. Mauss, QTronic) 83 | - Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR). 84 | - Dez. 14, 2009: Added eventInfo to meInitialize and added 85 | meGetNominalContinuousStates (by Martin Otter, DLR) 86 | - Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion) 87 | (by A. Junghanns, QTronic) 88 | - Sept. 9, 2009: Changes according to FMI-meeting on July 21: 89 | meInquireModelTypesVersion -> meGetModelTypesPlatform 90 | meInquireModelFunctionsVersion -> meGetModelFunctionsVersion 91 | meSetStates -> meSetContinuousStates 92 | meGetStates -> meGetContinuousStates 93 | removal of meInitializeModelClass 94 | removal of meGetTime 95 | change of arguments of meInstantiateModel 96 | change of arguments of meCompletedIntegratorStep 97 | (by Martin Otter, DLR): 98 | - July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR). 99 | - March 2, 2009: Changed function definitions according to the last design 100 | meeting with additional improvements (by Martin Otter, DLR). 101 | - Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim). 102 | 103 | Copyright © 2008-2011 MODELISAR consortium, 104 | 2012-2013 Modelica Association Project "FMI" 105 | All rights reserved. 106 | This file is licensed by the copyright holders under the BSD 2-Clause License 107 | (http://www.opensource.org/licenses/bsd-license.html): 108 | 109 | ---------------------------------------------------------------------------- 110 | Redistribution and use in source and binary forms, with or without 111 | modification, are permitted provided that the following conditions are met: 112 | 113 | - Redistributions of source code must retain the above copyright notice, 114 | this list of conditions and the following disclaimer. 115 | - Redistributions in binary form must reproduce the above copyright notice, 116 | this list of conditions and the following disclaimer in the documentation 117 | and/or other materials provided with the distribution. 118 | - Neither the name of the copyright holders nor the names of its 119 | contributors may be used to endorse or promote products derived 120 | from this software without specific prior written permission. 121 | 122 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 123 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 124 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 125 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 126 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 127 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 128 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 129 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 130 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 131 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 132 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 133 | ---------------------------------------------------------------------------- 134 | 135 | with the extension: 136 | 137 | You may distribute or publicly perform any modification only under the 138 | terms of this license. 139 | (Note, this means that if you distribute a modified file, 140 | the modified file must also be provided under this license). 141 | */ 142 | 143 | #ifdef __cplusplus 144 | extern "C" { 145 | #endif 146 | 147 | #include "fmi2TypesPlatform.h" 148 | #include "fmi2FunctionTypes.h" 149 | #include 150 | 151 | 152 | /* 153 | Export FMI2 API functions on Windows and under GCC. 154 | If custom linking is desired then the FMI2_Export must be 155 | defined before including this file. For instance, 156 | it may be set to __declspec(dllimport). 157 | */ 158 | #if !defined(FMI2_Export) 159 | #if !defined(FMI2_FUNCTION_PREFIX) 160 | #if defined _WIN32 || defined __CYGWIN__ 161 | /* Note: both gcc & MSVC on Windows support this syntax. */ 162 | #define FMI2_Export __declspec(dllexport) 163 | #else 164 | #if __GNUC__ >= 4 165 | #define FMI2_Export __attribute__ ((visibility ("default"))) 166 | #else 167 | #define FMI2_Export 168 | #endif 169 | #endif 170 | #else 171 | #define FMI2_Export 172 | #endif 173 | #endif 174 | 175 | /* Macros to construct the real function name 176 | (prepend function name by FMI2_FUNCTION_PREFIX) */ 177 | #if defined(FMI2_FUNCTION_PREFIX) 178 | #define fmi2Paste(a,b) a ## b 179 | #define fmi2PasteB(a,b) fmi2Paste(a,b) 180 | #define fmi2FullName(name) fmi2PasteB(FMI2_FUNCTION_PREFIX, name) 181 | #else 182 | #define fmi2FullName(name) name 183 | #endif 184 | 185 | /*************************************************** 186 | Common Functions 187 | ****************************************************/ 188 | #define fmi2GetTypesPlatform fmi2FullName(fmi2GetTypesPlatform) 189 | #define fmi2GetVersion fmi2FullName(fmi2GetVersion) 190 | #define fmi2SetDebugLogging fmi2FullName(fmi2SetDebugLogging) 191 | #define fmi2Instantiate fmi2FullName(fmi2Instantiate) 192 | #define fmi2FreeInstance fmi2FullName(fmi2FreeInstance) 193 | #define fmi2SetupExperiment fmi2FullName(fmi2SetupExperiment) 194 | #define fmi2EnterInitializationMode fmi2FullName(fmi2EnterInitializationMode) 195 | #define fmi2ExitInitializationMode fmi2FullName(fmi2ExitInitializationMode) 196 | #define fmi2Terminate fmi2FullName(fmi2Terminate) 197 | #define fmi2Reset fmi2FullName(fmi2Reset) 198 | #define fmi2GetReal fmi2FullName(fmi2GetReal) 199 | #define fmi2GetInteger fmi2FullName(fmi2GetInteger) 200 | #define fmi2GetBoolean fmi2FullName(fmi2GetBoolean) 201 | #define fmi2GetString fmi2FullName(fmi2GetString) 202 | #define fmi2SetReal fmi2FullName(fmi2SetReal) 203 | #define fmi2SetInteger fmi2FullName(fmi2SetInteger) 204 | #define fmi2SetBoolean fmi2FullName(fmi2SetBoolean) 205 | #define fmi2SetString fmi2FullName(fmi2SetString) 206 | #define fmi2GetFMUstate fmi2FullName(fmi2GetFMUstate) 207 | #define fmi2SetFMUstate fmi2FullName(fmi2SetFMUstate) 208 | #define fmi2FreeFMUstate fmi2FullName(fmi2FreeFMUstate) 209 | #define fmi2SerializedFMUstateSize fmi2FullName(fmi2SerializedFMUstateSize) 210 | #define fmi2SerializeFMUstate fmi2FullName(fmi2SerializeFMUstate) 211 | #define fmi2DeSerializeFMUstate fmi2FullName(fmi2DeSerializeFMUstate) 212 | #define fmi2GetDirectionalDerivative fmi2FullName(fmi2GetDirectionalDerivative) 213 | 214 | 215 | /*************************************************** 216 | Functions for FMI2 for Model Exchange 217 | ****************************************************/ 218 | #define fmi2EnterEventMode fmi2FullName(fmi2EnterEventMode) 219 | #define fmi2NewDiscreteStates fmi2FullName(fmi2NewDiscreteStates) 220 | #define fmi2EnterContinuousTimeMode fmi2FullName(fmi2EnterContinuousTimeMode) 221 | #define fmi2CompletedIntegratorStep fmi2FullName(fmi2CompletedIntegratorStep) 222 | #define fmi2SetTime fmi2FullName(fmi2SetTime) 223 | #define fmi2SetContinuousStates fmi2FullName(fmi2SetContinuousStates) 224 | #define fmi2GetDerivatives fmi2FullName(fmi2GetDerivatives) 225 | #define fmi2GetEventIndicators fmi2FullName(fmi2GetEventIndicators) 226 | #define fmi2GetContinuousStates fmi2FullName(fmi2GetContinuousStates) 227 | #define fmi2GetNominalsOfContinuousStates fmi2FullName(fmi2GetNominalsOfContinuousStates) 228 | 229 | 230 | /*************************************************** 231 | Functions for FMI2 for Co-Simulation 232 | ****************************************************/ 233 | #define fmi2SetRealInputDerivatives fmi2FullName(fmi2SetRealInputDerivatives) 234 | #define fmi2GetRealOutputDerivatives fmi2FullName(fmi2GetRealOutputDerivatives) 235 | #define fmi2DoStep fmi2FullName(fmi2DoStep) 236 | #define fmi2CancelStep fmi2FullName(fmi2CancelStep) 237 | #define fmi2GetStatus fmi2FullName(fmi2GetStatus) 238 | #define fmi2GetRealStatus fmi2FullName(fmi2GetRealStatus) 239 | #define fmi2GetIntegerStatus fmi2FullName(fmi2GetIntegerStatus) 240 | #define fmi2GetBooleanStatus fmi2FullName(fmi2GetBooleanStatus) 241 | #define fmi2GetStringStatus fmi2FullName(fmi2GetStringStatus) 242 | 243 | /* Version number */ 244 | #define fmi2Version "2.0" 245 | 246 | 247 | /*************************************************** 248 | Common Functions 249 | ****************************************************/ 250 | 251 | /* Inquire version numbers of header files */ 252 | FMI2_Export fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform; 253 | FMI2_Export fmi2GetVersionTYPE fmi2GetVersion; 254 | FMI2_Export fmi2SetDebugLoggingTYPE fmi2SetDebugLogging; 255 | 256 | /* Creation and destruction of FMU instances */ 257 | FMI2_Export fmi2InstantiateTYPE fmi2Instantiate; 258 | FMI2_Export fmi2FreeInstanceTYPE fmi2FreeInstance; 259 | 260 | /* Enter and exit initialization mode, terminate and reset */ 261 | FMI2_Export fmi2SetupExperimentTYPE fmi2SetupExperiment; 262 | FMI2_Export fmi2EnterInitializationModeTYPE fmi2EnterInitializationMode; 263 | FMI2_Export fmi2ExitInitializationModeTYPE fmi2ExitInitializationMode; 264 | FMI2_Export fmi2TerminateTYPE fmi2Terminate; 265 | FMI2_Export fmi2ResetTYPE fmi2Reset; 266 | 267 | /* Getting and setting variables values */ 268 | FMI2_Export fmi2GetRealTYPE fmi2GetReal; 269 | FMI2_Export fmi2GetIntegerTYPE fmi2GetInteger; 270 | FMI2_Export fmi2GetBooleanTYPE fmi2GetBoolean; 271 | FMI2_Export fmi2GetStringTYPE fmi2GetString; 272 | 273 | FMI2_Export fmi2SetRealTYPE fmi2SetReal; 274 | FMI2_Export fmi2SetIntegerTYPE fmi2SetInteger; 275 | FMI2_Export fmi2SetBooleanTYPE fmi2SetBoolean; 276 | FMI2_Export fmi2SetStringTYPE fmi2SetString; 277 | 278 | /* Getting and setting the internal FMU state */ 279 | FMI2_Export fmi2GetFMUstateTYPE fmi2GetFMUstate; 280 | FMI2_Export fmi2SetFMUstateTYPE fmi2SetFMUstate; 281 | FMI2_Export fmi2FreeFMUstateTYPE fmi2FreeFMUstate; 282 | FMI2_Export fmi2SerializedFMUstateSizeTYPE fmi2SerializedFMUstateSize; 283 | FMI2_Export fmi2SerializeFMUstateTYPE fmi2SerializeFMUstate; 284 | FMI2_Export fmi2DeSerializeFMUstateTYPE fmi2DeSerializeFMUstate; 285 | 286 | /* Getting partial derivatives */ 287 | FMI2_Export fmi2GetDirectionalDerivativeTYPE fmi2GetDirectionalDerivative; 288 | 289 | 290 | /*************************************************** 291 | Functions for FMI2 for Model Exchange 292 | ****************************************************/ 293 | 294 | /* Enter and exit the different modes */ 295 | FMI2_Export fmi2EnterEventModeTYPE fmi2EnterEventMode; 296 | FMI2_Export fmi2NewDiscreteStatesTYPE fmi2NewDiscreteStates; 297 | FMI2_Export fmi2EnterContinuousTimeModeTYPE fmi2EnterContinuousTimeMode; 298 | FMI2_Export fmi2CompletedIntegratorStepTYPE fmi2CompletedIntegratorStep; 299 | 300 | /* Providing independent variables and re-initialization of caching */ 301 | FMI2_Export fmi2SetTimeTYPE fmi2SetTime; 302 | FMI2_Export fmi2SetContinuousStatesTYPE fmi2SetContinuousStates; 303 | 304 | /* Evaluation of the model equations */ 305 | FMI2_Export fmi2GetDerivativesTYPE fmi2GetDerivatives; 306 | FMI2_Export fmi2GetEventIndicatorsTYPE fmi2GetEventIndicators; 307 | FMI2_Export fmi2GetContinuousStatesTYPE fmi2GetContinuousStates; 308 | FMI2_Export fmi2GetNominalsOfContinuousStatesTYPE fmi2GetNominalsOfContinuousStates; 309 | 310 | 311 | /*************************************************** 312 | Functions for FMI2 for Co-Simulation 313 | ****************************************************/ 314 | 315 | /* Simulating the slave */ 316 | FMI2_Export fmi2SetRealInputDerivativesTYPE fmi2SetRealInputDerivatives; 317 | FMI2_Export fmi2GetRealOutputDerivativesTYPE fmi2GetRealOutputDerivatives; 318 | 319 | FMI2_Export fmi2DoStepTYPE fmi2DoStep; 320 | FMI2_Export fmi2CancelStepTYPE fmi2CancelStep; 321 | 322 | /* Inquire slave status */ 323 | FMI2_Export fmi2GetStatusTYPE fmi2GetStatus; 324 | FMI2_Export fmi2GetRealStatusTYPE fmi2GetRealStatus; 325 | FMI2_Export fmi2GetIntegerStatusTYPE fmi2GetIntegerStatus; 326 | FMI2_Export fmi2GetBooleanStatusTYPE fmi2GetBooleanStatus; 327 | FMI2_Export fmi2GetStringStatusTYPE fmi2GetStringStatus; 328 | 329 | #ifdef __cplusplus 330 | } /* end of extern "C" { */ 331 | #endif 332 | 333 | #endif /* fmi2Functions_h */ -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/fmi2TypesPlatform.h: -------------------------------------------------------------------------------- 1 | #ifndef fmi2TypesPlatform_h 2 | #define fmi2TypesPlatform_h 3 | 4 | /* Standard header file to define the argument types of the 5 | functions of the Functional Mock-up Interface 2.0. 6 | This header file must be utilized both by the model and 7 | by the simulation engine. 8 | 9 | Revisions: 10 | - Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8) 11 | - Mar 31, 2014: New datatype fmiChar introduced. 12 | - Feb. 17, 2013: Changed fmiTypesPlatform from "standard32" to "default". 13 | Removed fmiUndefinedValueReference since no longer needed 14 | (because every state is defined in ScalarVariables). 15 | - March 20, 2012: Renamed from fmiPlatformTypes.h to fmiTypesPlatform.h 16 | - Nov. 14, 2011: Use the header file "fmiPlatformTypes.h" for FMI 2.0 17 | both for "FMI for model exchange" and for "FMI for co-simulation" 18 | New types "fmiComponentEnvironment", "fmiState", and "fmiByte". 19 | The implementation of "fmiBoolean" is change from "char" to "int". 20 | The #define "fmiPlatform" changed to "fmiTypesPlatform" 21 | (in order that #define and function call are consistent) 22 | - Oct. 4, 2010: Renamed header file from "fmiModelTypes.h" to fmiPlatformTypes.h" 23 | for the co-simulation interface 24 | - Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic) 25 | - Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent" 26 | according to meeting on Dec. 18 (by Martin Otter, DLR) 27 | - Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR) 28 | - Sept. 9, 2009: Changes according to FMI-meeting on July 21: 29 | Changed "version" to "platform", "standard" to "standard32", 30 | Added a precise definition of "standard32" as comment 31 | (by Martin Otter, DLR) 32 | - July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse, 33 | and changed meValueReferenced from int to unsigned int 34 | (by Martin Otter, DLR). 35 | - March 2, 2009: Moved enums and function pointer definitions to 36 | ModelFunctions.h (by Martin Otter, DLR). 37 | - Dec. 3, 2008 : First version by Martin Otter (DLR) and 38 | Hans Olsson (Dynasim). 39 | 40 | 41 | Copyright © 2008-2011 MODELISAR consortium, 42 | 2012-2013 Modelica Association Project "FMI" 43 | All rights reserved. 44 | This file is licensed by the copyright holders under the BSD 2-Clause License 45 | (http://www.opensource.org/licenses/bsd-license.html): 46 | 47 | ---------------------------------------------------------------------------- 48 | Redistribution and use in source and binary forms, with or without 49 | modification, are permitted provided that the following conditions are met: 50 | 51 | - Redistributions of source code must retain the above copyright notice, 52 | this list of conditions and the following disclaimer. 53 | - Redistributions in binary form must reproduce the above copyright notice, 54 | this list of conditions and the following disclaimer in the documentation 55 | and/or other materials provided with the distribution. 56 | - Neither the name of the copyright holders nor the names of its 57 | contributors may be used to endorse or promote products derived 58 | from this software without specific prior written permission. 59 | 60 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 61 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 62 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 63 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 64 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 65 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 66 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 67 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 68 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 69 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 70 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 71 | ---------------------------------------------------------------------------- 72 | 73 | with the extension: 74 | 75 | You may distribute or publicly perform any modification only under the 76 | terms of this license. 77 | (Note, this means that if you distribute a modified file, 78 | the modified file must also be provided under this license). 79 | */ 80 | 81 | /* Platform (unique identification of this header file) */ 82 | #define fmi2TypesPlatform "default" 83 | 84 | /* Type definitions of variables passed as arguments 85 | Version "default" means: 86 | 87 | fmi2Component : an opaque object pointer 88 | fmi2ComponentEnvironment: an opaque object pointer 89 | fmi2FMUstate : an opaque object pointer 90 | fmi2ValueReference : handle to the value of a variable 91 | fmi2Real : double precision floating-point data type 92 | fmi2Integer : basic signed integer data type 93 | fmi2Boolean : basic signed integer data type 94 | fmi2Char : character data type 95 | fmi2String : a pointer to a vector of fmi2Char characters 96 | ('\0' terminated, UTF8 encoded) 97 | fmi2Byte : smallest addressable unit of the machine, typically one byte. 98 | */ 99 | typedef void *fmi2Component; /* Pointer to FMU instance */ 100 | typedef void *fmi2ComponentEnvironment; /* Pointer to FMU environment */ 101 | typedef void *fmi2FMUstate; /* Pointer to internal FMU state */ 102 | typedef unsigned int fmi2ValueReference; 103 | typedef double fmi2Real; 104 | typedef int fmi2Integer; 105 | typedef int fmi2Boolean; 106 | typedef char fmi2Char; 107 | typedef const fmi2Char *fmi2String; 108 | typedef char fmi2Byte; 109 | 110 | /* Values for fmi2Boolean */ 111 | #define fmi2True 1 112 | #define fmi2False 0 113 | 114 | 115 | #endif /* fmi2TypesPlatform_h */ 116 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/fmi2_library.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2LIBRARY_HPP 3 | #define FMI4CPP_FMI2LIBRARY_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace fmi4cpp::fmi2 15 | { 16 | 17 | class fmi2_library 18 | { 19 | 20 | private: 21 | std::shared_ptr resource_; 22 | 23 | fmi2GetVersionTYPE* fmi2GetVersion_; 24 | fmi2GetTypesPlatformTYPE* fmi2GetTypesPlatform_; 25 | 26 | fmi2SetDebugLoggingTYPE* fmi2SetDebugLogging_; 27 | 28 | fmi2InstantiateTYPE* fmi2Instantiate_; 29 | fmi2SetupExperimentTYPE* fmi2SetupExperiment_; 30 | fmi2EnterInitializationModeTYPE* fmi2EnterInitializationMode_; 31 | fmi2ExitInitializationModeTYPE* fmi2ExitInitializationMode_; 32 | 33 | fmi2ResetTYPE* fmi2Reset_; 34 | fmi2TerminateTYPE* fmi2Terminate_; 35 | 36 | fmi2GetIntegerTYPE* fmi2GetInteger_; 37 | fmi2GetRealTYPE* fmi2GetReal_; 38 | fmi2GetStringTYPE* fmi2GetString_; 39 | fmi2GetBooleanTYPE* fmi2GetBoolean_; 40 | 41 | fmi2SetIntegerTYPE* fmi2SetInteger_; 42 | fmi2SetRealTYPE* fmi2SetReal_; 43 | fmi2SetStringTYPE* fmi2SetString_; 44 | fmi2SetBooleanTYPE* fmi2SetBoolean_; 45 | 46 | fmi2GetFMUstateTYPE* fmi2GetFMUstate_; 47 | fmi2SetFMUstateTYPE* fmi2SetFMUstate_; 48 | fmi2FreeFMUstateTYPE* fmi2FreeFMUstate_; 49 | 50 | fmi2SerializedFMUstateSizeTYPE* fmi2SerializedFMUstateSize_; 51 | fmi2SerializeFMUstateTYPE* fmi2SerializeFMUstate_; 52 | fmi2DeSerializeFMUstateTYPE* fmi2DeSerializeFMUstate_; 53 | 54 | fmi2GetDirectionalDerivativeTYPE* fmi2GetDirectionalDerivative_; 55 | 56 | fmi2FreeInstanceTYPE* fmi2FreeInstance_; 57 | 58 | #ifdef _WIN32 59 | DLL_DIRECTORY_COOKIE dllDirectoryCookie_ = nullptr; 60 | #endif 61 | 62 | protected: 63 | fmi2Status lastStatus_; 64 | DLL_HANDLE handle_ = nullptr; 65 | bool update_status_and_return_true_if_ok(fmi2Status status); 66 | 67 | public: 68 | fmi2_library(const std::string& modelIdentifier, const std::shared_ptr& resource); 69 | 70 | [[nodiscard]] DLL_HANDLE handle() const; 71 | [[nodiscard]] fmi2Status last_status() const; 72 | [[nodiscard]] fmi2String get_version() const; 73 | [[nodiscard]] fmi2String get_types_platform() const; 74 | 75 | bool set_debug_logging(fmi2Component c, bool loggingOn, std::vector categories); 76 | 77 | fmi2Component instantiate(const std::string& instanceName, fmi2Type type, 78 | const std::string& guid, const std::string& resourceLocation, 79 | bool visible = false, bool loggingOn = false); 80 | 81 | bool setup_experiment(fmi2Component c, double tolerance, double startTime, double stopTime); 82 | bool enter_initialization_mode(fmi2Component c); 83 | bool exit_initialization_mode(fmi2Component c); 84 | 85 | bool reset(fmi2Component c); 86 | bool terminate(fmi2Component c); 87 | 88 | bool read_integer(fmi2Component c, fmi2ValueReference vr, fmi2Integer& ref); 89 | bool read_integer(fmi2Component c, const std::vector& vr, std::vector& ref); 90 | 91 | bool read_real(fmi2Component c, fmi2ValueReference vr, fmi2Real& ref); 92 | bool read_real(fmi2Component c, const std::vector& vr, std::vector& ref); 93 | 94 | bool read_string(fmi2Component c, fmi2ValueReference vr, fmi2String& ref); 95 | bool read_string(fmi2Component c, const std::vector& vr, std::vector& ref); 96 | 97 | bool read_boolean(fmi2Component c, fmi2ValueReference vr, fmi2Boolean& ref); 98 | bool read_boolean(fmi2Component c, const std::vector& vr, std::vector& ref); 99 | 100 | bool write_integer(fmi2Component c, fmi2ValueReference vr, const fmi2Integer& value); 101 | bool write_integer(fmi2Component c, const std::vector& vr, 102 | const std::vector& values); 103 | 104 | bool write_real(fmi2Component c, fmi2ValueReference vr, const fmi2Real& value); 105 | bool write_real(fmi2Component c, const std::vector& vr, const std::vector& values); 106 | 107 | bool write_string(fmi2Component c, fmi2ValueReference vr, fmi2String& value); 108 | bool write_string(fmi2Component c, const std::vector& vr, 109 | const std::vector& values); 110 | 111 | bool write_boolean(fmi2Component c, fmi2ValueReference vr, const fmi2Boolean& value); 112 | bool write_boolean(fmi2Component c, const std::vector& vr, 113 | const std::vector& values); 114 | 115 | bool get_fmu_state(fmi2Component c, fmi2FMUstate& state); 116 | bool set_fmu_state(fmi2Component c, fmi2FMUstate state); 117 | bool free_fmu_state(fmi2Component c, fmi2FMUstate& state); 118 | 119 | bool get_serialized_fmu_state_size(fmi2Component c, fmi2FMUstate state, size_t& size); 120 | bool serialize_fmu_state(fmi2Component c, const fmi2FMUstate& state, std::vector& serializedState); 121 | bool de_serialize_fmu_state(fmi2Component c, fmi2FMUstate& state, const std::vector& serializedState); 122 | 123 | bool get_directional_derivative(fmi2Component c, 124 | const std::vector& vUnknownRef, 125 | const std::vector& vKnownRef, 126 | const std::vector& dvKnownRef, std::vector& dvUnknownRef); 127 | 128 | void free_instance(fmi2Component c); 129 | 130 | ~fmi2_library(); 131 | }; 132 | 133 | } // namespace fmi4cpp::fmi2 134 | 135 | #endif //FMI4CPP_FMI2LIBRARY_HPP 136 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/fmu.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2FMU_HPP 3 | #define FMI4CPP_FMI2FMU_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace fmi4cpp::fmi2 15 | { 16 | 17 | class fmu : public virtual fmu_provider 18 | { 19 | 20 | friend class cs_fmu; 21 | friend class me_fmu; 22 | 23 | private: 24 | std::shared_ptr resource_; 25 | std::shared_ptr modelDescription_; 26 | 27 | public: 28 | explicit fmu(const std::filesystem::path& fmuPath); 29 | 30 | [[nodiscard]] std::string get_model_description_xml() const; 31 | [[nodiscard]] std::shared_ptr get_model_description() const override; 32 | 33 | [[nodiscard]] bool supports_me() const override; 34 | [[nodiscard]] bool supports_cs() const override; 35 | 36 | [[nodiscard]] std::unique_ptr as_cs_fmu() const override; 37 | [[nodiscard]] std::unique_ptr as_me_fmu() const override; 38 | }; 39 | 40 | } // namespace fmi4cpp::fmi2 41 | 42 | 43 | #endif // FMI4CPP_FMI2FMU_HPP 44 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/me_fmu.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2MODELEXCHANGEFMU_H 3 | #define FMI4CPP_FMI2MODELEXCHANGEFMU_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace fmi4cpp::fmi2 11 | { 12 | 13 | class me_fmu : public virtual me_fmu_base 14 | { 15 | 16 | private: 17 | std::shared_ptr resource_; 18 | std::shared_ptr lib_; 19 | std::shared_ptr modelDescription_; 20 | 21 | public: 22 | me_fmu(std::shared_ptr resource, 23 | std::shared_ptr md); 24 | 25 | [[nodiscard]] std::string get_model_description_xml() const; 26 | 27 | [[nodiscard]] std::shared_ptr get_model_description() const override; 28 | 29 | std::unique_ptr new_instance(bool visible = false, bool loggingOn = false) override; 30 | }; 31 | 32 | } // namespace fmi4cpp::fmi2 33 | 34 | #endif //FMI4CPP_FMI2MODELEXCHANGEFMU_H 35 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/me_instance.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2MODELEXCHANGEINSTANCE_HPP 3 | #define FMI4CPP_FMI2MODELEXCHANGEINSTANCE_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace fmi4cpp::fmi2 14 | { 15 | 16 | class me_instance : public fmu_instance_base 17 | { 18 | 19 | public: 20 | fmi2EventInfo eventInfo_; 21 | 22 | me_instance(fmi2Component c, 23 | const std::shared_ptr& resource, 24 | const std::shared_ptr& library, 25 | const std::shared_ptr& modelDescription); 26 | 27 | 28 | bool enter_event_mode(); 29 | 30 | bool enter_continuous_time_mode(); 31 | 32 | bool set_time(double time); 33 | 34 | bool set_continuous_states(const std::vector& x); 35 | 36 | bool get_derivatives(std::vector& derivatives); 37 | 38 | bool get_event_indicators(std::vector& eventIndicators); 39 | 40 | bool get_continuous_states(std::vector& x); 41 | 42 | bool get_nominals_of_continuous_states(std::vector& x_nominal); 43 | 44 | bool completed_integrator_step(fmi2Boolean noSetFMUStatePriorToCurrentPoint, 45 | fmi2Boolean& enterEventMode, fmi2Boolean& terminateSimulation); 46 | 47 | bool new_discrete_states(); 48 | 49 | [[nodiscard]] DLL_HANDLE handle() const override; 50 | 51 | [[nodiscard]] status last_status() const override; 52 | }; 53 | 54 | } // namespace fmi4cpp::fmi2 55 | 56 | #endif //FMI4CPP_FMI2MODELEXCHANGEINSTANCE_HPP 57 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/me_library.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2MODELEXCHANGELIBRARY_HPP 3 | #define FMI4CPP_FMI2MODELEXCHANGELIBRARY_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp::fmi2 8 | { 9 | 10 | class me_library : public fmi2_library 11 | { 12 | 13 | private: 14 | fmi2EnterEventModeTYPE* fmi2EnterEventMode_; 15 | fmi2EnterContinuousTimeModeTYPE* fmi2EnterContinuousTimeMode_; 16 | fmi2SetTimeTYPE* fmi2SetTime_; 17 | fmi2SetContinuousStatesTYPE* fmi2SetContinuousStates_; 18 | fmi2GetDerivativesTYPE* fmi2GetDerivatives_; 19 | fmi2GetEventIndicatorsTYPE* fmi2GetEventIndicators_; 20 | fmi2GetContinuousStatesTYPE* fmi2GetContinuousStates_; 21 | fmi2GetNominalsOfContinuousStatesTYPE* fmi2GetNominalsOfContinuousStates_; 22 | fmi2CompletedIntegratorStepTYPE* fmi2CompletedIntegratorStep_; 23 | fmi2NewDiscreteStatesTYPE* fmi2NewDiscreteStates_; 24 | 25 | public: 26 | explicit me_library( 27 | const std::string& modelIdentifier, 28 | const std::shared_ptr& resource); 29 | 30 | bool enter_event_mode(fmi2Component c); 31 | 32 | bool enter_continuous_time_mode(fmi2Component c); 33 | 34 | bool set_time(fmi2Component c, double time); 35 | 36 | bool set_continuous_states(fmi2Component c, const std::vector& x); 37 | 38 | bool get_derivatives(fmi2Component c, std::vector& derivatives); 39 | 40 | bool get_event_indicators(fmi2Component c, std::vector& eventIndicators); 41 | 42 | bool get_continuous_states(fmi2Component c, std::vector& x); 43 | 44 | bool get_nominals_of_continuous_states(fmi2Component c, std::vector& x_nominal); 45 | 46 | bool completed_integrator_step(fmi2Component c, 47 | fmi2Boolean noSetFMUStatePriorToCurrentPoint, 48 | fmi2Boolean& enterEventMode, 49 | fmi2Boolean& terminateSimulation); 50 | 51 | bool new_discrete_states(fmi2Component c, fmi2EventInfo& eventInfo); 52 | }; 53 | 54 | } // namespace fmi4cpp::fmi2 55 | 56 | #endif //FMI4CPP_FMI2MODELEXCHANGELIBRARY_HPP 57 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/cs_model_description.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2_CS_MODEL_DESCRIPTION_HPP 3 | #define FMI4CPP_FMI2_CS_MODEL_DESCRIPTION_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp::fmi2 8 | { 9 | 10 | struct cs_model_description : specific_model_description 11 | { 12 | cs_model_description(const model_description_base& base, const cs_attributes& attributes) 13 | : specific_model_description(base, attributes) 14 | {} 15 | }; 16 | 17 | } // namespace fmi4cpp::fmi2 18 | 19 | #endif //FMI4CPP_FMI2_CS_MODEL_DESCRIPTION_HPP 20 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/default_experiment.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_DEFAULTEXPERIMENT_HPP 3 | #define FMI4CPP_DEFAULTEXPERIMENT_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp::fmi2 8 | { 9 | 10 | struct default_experiment 11 | { 12 | std::optional startTime; 13 | std::optional stopTime; 14 | std::optional stepSize; 15 | std::optional tolerance; 16 | }; 17 | 18 | } // namespace fmi4cpp::fmi2 19 | 20 | #endif //FMI4CPP_DEFAULTEXPERIMENT_HPP 21 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/enums.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_ENUMS_HPP 3 | #define FMI4CPP_ENUMS_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp::fmi2 8 | { 9 | 10 | enum class causality 11 | { 12 | parameter, 13 | calculatedParameter, 14 | input, 15 | output, 16 | local, 17 | independent, 18 | unknown 19 | }; 20 | 21 | enum class variability 22 | { 23 | constant, 24 | fixed, 25 | tunable, 26 | discrete, 27 | continuous, 28 | unknown 29 | }; 30 | 31 | enum class initial 32 | { 33 | exact, 34 | approx, 35 | calculated, 36 | unknown 37 | }; 38 | 39 | causality parse_causality(const std::string& str); 40 | variability parse_variability(const std::string& str); 41 | initial parse_initial(const std::string& str); 42 | 43 | std::string to_string(causality causality); 44 | std::string to_string(variability variability); 45 | std::string to_string(initial initial); 46 | 47 | } // namespace fmi4cpp::fmi2 48 | 49 | #endif //FMI4CPP_ENUMS_HPP 50 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/fmu_attributes.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMUTYPESATTRIBUTE_HPP 3 | #define FMI4CPP_FMUTYPESATTRIBUTE_HPP 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace fmi4cpp::fmi2 10 | { 11 | 12 | struct fmu_attributes 13 | { 14 | source_files sourceFiles; 15 | std::string model_identifier; 16 | 17 | bool can_get_and_set_fmu_state; 18 | bool can_serialize_fmu_state; 19 | bool needs_execution_tool; 20 | bool can_not_use_memory_management_functions; 21 | bool can_be_instantiated_only_once_per_process; 22 | bool provides_directional_derivative; 23 | }; 24 | 25 | struct cs_attributes : fmu_attributes 26 | { 27 | bool can_interpolate_inputs = false; 28 | bool can_run_asynchronuously = false; 29 | bool can_handle_variable_communication_step_size = false; 30 | 31 | unsigned int max_output_derivative_order{}; 32 | 33 | cs_attributes() = default; 34 | 35 | explicit cs_attributes(const fmu_attributes& attributes) 36 | : fmu_attributes(attributes) 37 | {} 38 | }; 39 | 40 | struct me_attributes : fmu_attributes 41 | { 42 | 43 | bool completed_integrator_step_not_needed = false; 44 | 45 | me_attributes() = default; 46 | 47 | explicit me_attributes(const fmu_attributes& attributes) 48 | : fmu_attributes(attributes) 49 | {} 50 | }; 51 | 52 | } // namespace fmi4cpp::fmi2 53 | 54 | #endif //FMI4CPP_FMUTYPESATTRIBUTE_HPP 55 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/me_model_description.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2_ME_MODEL_DESCRIPTION_HPP 3 | #define FMI4CPP_FMI2_ME_MODEL_DESCRIPTION_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp::fmi2 8 | { 9 | 10 | struct me_model_description : public specific_model_description 11 | { 12 | me_model_description(const model_description_base& base, const me_attributes& attributes) 13 | : specific_model_description(base, attributes) 14 | {} 15 | }; 16 | 17 | } // namespace fmi4cpp::fmi2 18 | 19 | #endif //FMI4CPP_FMI2_ME_MODEL_DESCRIPTION_HPP 20 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/model_description.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_MODELDESCRIPTION_HPP 3 | #define FMI4CPP_MODELDESCRIPTION_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace fmi4cpp::fmi2 16 | { 17 | 18 | struct model_description_base 19 | { 20 | std::string guid; 21 | std::string model_name; 22 | std::string fmi_version; 23 | 24 | std::optional author; 25 | std::optional version; 26 | std::optional license; 27 | std::optional copyright; 28 | std::optional description; 29 | std::optional generation_tool; 30 | std::optional generation_date_and_time; 31 | std::optional variable_naming_convention; 32 | 33 | std::shared_ptr model_variables; 34 | std::shared_ptr model_structure; 35 | 36 | std::optional default_experiment; 37 | std::optional unit_definitions; 38 | 39 | size_t number_of_event_indicators; 40 | [[nodiscard]] size_t number_of_continuous_states() const; 41 | 42 | [[nodiscard]] unsigned int get_value_reference(const std::string& name) const; 43 | [[nodiscard]] const scalar_variable& get_variable_by_name(const std::string& name) const; 44 | }; 45 | 46 | struct cs_model_description; 47 | struct me_model_description; 48 | 49 | class model_description : public model_description_base 50 | { 51 | 52 | protected: 53 | std::optional coSimulation_; 54 | std::optional modelExchange_; 55 | 56 | public: 57 | model_description( 58 | const model_description_base& base, 59 | std::optional coSimulation, 60 | std::optional modelExchange); 61 | 62 | [[nodiscard]] bool supports_cs() const; 63 | [[nodiscard]] bool supports_me() const; 64 | 65 | [[nodiscard]] std::unique_ptr as_cs_description() const; 66 | [[nodiscard]] std::unique_ptr as_me_description() const; 67 | }; 68 | 69 | } // namespace fmi4cpp::fmi2 70 | 71 | #endif //FMI4CPP_MODELDESCRIPTION_HPP 72 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/model_description_parser.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_MODELDESCRIPTIONPARSER_HPP 3 | #define FMI4CPP_MODELDESCRIPTIONPARSER_HPP 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace fmi4cpp::fmi2 11 | { 12 | 13 | std::unique_ptr parse_model_description(const std::string& fileName); 14 | 15 | } 16 | 17 | #endif //FMI4CPP_MODELDESCRIPTIONPARSER_HPP 18 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/model_structure.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_MODELSTRUCTURE_HPP 3 | #define FMI4CPP_MODELSTRUCTURE_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace fmi4cpp::fmi2 10 | { 11 | 12 | struct unknown 13 | { 14 | unsigned int index; 15 | std::optional> dependencies; 16 | std::optional> dependencies_kind; 17 | }; 18 | 19 | struct model_structure 20 | { 21 | const std::vector outputs; 22 | const std::vector derivatives; 23 | const std::vector initialUnknowns; 24 | 25 | model_structure(std::vector outputs, std::vector derivatives, 26 | std::vector initialUnknowns) 27 | : outputs(std::move(outputs)) 28 | , derivatives(std::move(derivatives)) 29 | , initialUnknowns(std::move(initialUnknowns)) 30 | {} 31 | }; 32 | 33 | } // namespace fmi4cpp::fmi2 34 | 35 | #endif //FMI4CPP_MODELSTRUCTURE_HPP 36 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/model_variables.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_MODELVARIABLES_HPP 3 | #define FMI4CPP_MODELVARIABLES_HPP 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace fmi4cpp::fmi2 12 | { 13 | 14 | class model_variables 15 | { 16 | 17 | private: 18 | const std::vector variables_ = {}; 19 | 20 | public: 21 | model_variables(); 22 | 23 | explicit model_variables(std::vector variables); 24 | 25 | [[nodiscard]] size_t size() const; 26 | 27 | const scalar_variable& operator[](size_t index) const; 28 | [[nodiscard]] const scalar_variable& getByName(const std::string& name) const; 29 | [[nodiscard]] const scalar_variable& getByValueReference(fmi2ValueReference vr) const; 30 | 31 | void getByValueReference(fmi2ValueReference vr, std::vector& store) const; 32 | void getByCausality(causality causality, std::vector& store) const; 33 | 34 | [[nodiscard]] std::vector::const_iterator begin() const; 35 | [[nodiscard]] std::vector::const_iterator end() const; 36 | }; 37 | 38 | } // namespace fmi4cpp::fmi2 39 | 40 | #endif //FMI4CPP_MODELVARIABLES_HPP 41 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/scalar_variable.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_SCALARVARIABLE_HPP 3 | #define FMI4CPP_SCALARVARIABLE_HPP 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace fmi4cpp::fmi2 11 | { 12 | 13 | class integer_variable; 14 | class real_variable; 15 | class string_variable; 16 | class boolean_variable; 17 | class enumeration_variable; 18 | 19 | const std::string INTEGER_TYPE = "Integer"; 20 | const std::string REAL_TYPE = "Real"; 21 | const std::string STRING_TYPE = "String"; 22 | const std::string BOOLEAN_TYPE = "Boolean"; 23 | const std::string ENUMERATION_TYPE = "Enumeration"; 24 | const std::string UNKNOWN_TYPE = "Unknown"; 25 | 26 | struct scalar_variable_base 27 | { 28 | std::string name; 29 | std::string description; 30 | 31 | fmi2::initial initial; 32 | fmi2::causality causality; 33 | fmi2::variability variability; 34 | 35 | fmi2ValueReference value_reference; 36 | bool can_handle_multiple_set_per_time_instant; 37 | }; 38 | 39 | 40 | template 41 | struct scalar_variable_attribute 42 | { 43 | std::optional start; 44 | std::optional declared_type; 45 | }; 46 | 47 | 48 | template 49 | struct bounded_scalar_variable_attribute : scalar_variable_attribute 50 | { 51 | std::optional min; 52 | std::optional max; 53 | std::optional quantity; 54 | 55 | explicit bounded_scalar_variable_attribute(const scalar_variable_attribute& attributes) 56 | : scalar_variable_attribute(attributes) 57 | {} 58 | }; 59 | 60 | struct integer_attribute : bounded_scalar_variable_attribute 61 | { 62 | explicit integer_attribute(const bounded_scalar_variable_attribute& attributes); 63 | }; 64 | 65 | struct real_attribute : bounded_scalar_variable_attribute 66 | { 67 | bool reinit = false; 68 | bool unbounded = false; 69 | bool relative_quantity = false; 70 | 71 | std::optional nominal; 72 | std::optional derivative; 73 | 74 | std::optional unit; 75 | std::optional display_unit; 76 | 77 | explicit real_attribute(const bounded_scalar_variable_attribute& attributes); 78 | }; 79 | 80 | struct string_attribute : scalar_variable_attribute 81 | { 82 | explicit string_attribute(const scalar_variable_attribute& attributes); 83 | }; 84 | 85 | struct boolean_attribute : scalar_variable_attribute 86 | { 87 | explicit boolean_attribute(const scalar_variable_attribute& attributes); 88 | }; 89 | 90 | struct enumeration_attribute : bounded_scalar_variable_attribute 91 | { 92 | explicit enumeration_attribute(const bounded_scalar_variable_attribute& attributes); 93 | }; 94 | 95 | 96 | class scalar_variable : public scalar_variable_base 97 | { 98 | 99 | private: 100 | std::optional integer_; 101 | std::optional real_; 102 | std::optional string_; 103 | std::optional boolean_; 104 | std::optional enumeration_; 105 | 106 | public: 107 | scalar_variable(const scalar_variable_base& base, 108 | const integer_attribute& integer); 109 | 110 | scalar_variable(const scalar_variable_base& base, 111 | const real_attribute& real); 112 | 113 | scalar_variable(const scalar_variable_base& base, 114 | const string_attribute& string); 115 | 116 | scalar_variable(const scalar_variable_base& base, 117 | const boolean_attribute& enumeration); 118 | 119 | scalar_variable(const scalar_variable_base& base, 120 | const enumeration_attribute& enumeration); 121 | 122 | 123 | [[nodiscard]] bool is_integer() const; 124 | [[nodiscard]] bool is_real() const; 125 | [[nodiscard]] bool is_string() const; 126 | [[nodiscard]] bool is_boolean() const; 127 | [[nodiscard]] bool is_enumeration() const; 128 | 129 | [[nodiscard]] std::string type_name() const; 130 | 131 | [[nodiscard]] integer_variable as_integer() const; 132 | [[nodiscard]] real_variable as_real() const; 133 | [[nodiscard]] string_variable as_string() const; 134 | [[nodiscard]] boolean_variable as_boolean() const; 135 | [[nodiscard]] enumeration_variable as_enumeration() const; 136 | }; 137 | 138 | } // namespace fmi4cpp::fmi2 139 | 140 | #endif //FMI4CPP_SCALARVARIABLE_HPP 141 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/source_files.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_SOURCEFILES_HPP 3 | #define FMI4CPP_SOURCEFILES_HPP 4 | 5 | #include 6 | #include 7 | 8 | 9 | namespace fmi4cpp::fmi2 10 | { 11 | 12 | struct source_file 13 | { 14 | std::string name; 15 | }; 16 | 17 | typedef std::vector source_files; 18 | 19 | } // namespace fmi4cpp::fmi2 20 | 21 | #endif //FMI4CPP_SOURCEFILES_HPP 22 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/specific_model_description.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_SPECIFICMODELDESCRIPTION_HPP 3 | #define FMI4CPP_SPECIFICMODELDESCRIPTION_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp::fmi2 8 | { 9 | 10 | template 11 | struct specific_model_description : model_description_base, T 12 | { 13 | specific_model_description(const model_description_base& base, const T& attributes) 14 | : model_description_base(base) 15 | , T(attributes) 16 | {} 17 | }; 18 | 19 | } // namespace fmi4cpp::fmi2 20 | 21 | #endif //FMI4CPP_SPECIFICMODELDESCRIPTION_HPP 22 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/typed_scalar_variable.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_TYPEDSCALARVARIABLE_HPP 3 | #define FMI4CPP_TYPEDSCALARVARIABLE_HPP 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | 11 | namespace fmi4cpp::fmi2 12 | { 13 | 14 | template 15 | class typed_scalar_variable 16 | { 17 | 18 | protected: 19 | const U attribute_; 20 | 21 | private: 22 | const scalar_variable variable_; 23 | 24 | 25 | public: 26 | typed_scalar_variable( 27 | scalar_variable variable, 28 | const U& attribute) 29 | : variable_(std::move(variable)) 30 | , attribute_(attribute) 31 | { } 32 | 33 | [[nodiscard]] std::string name() const 34 | { 35 | return variable_.name; 36 | } 37 | 38 | [[nodiscard]] std::string description() const 39 | { 40 | return variable_.description; 41 | } 42 | 43 | [[nodiscard]] fmi2ValueReference valueReference() const 44 | { 45 | return variable_.value_reference; 46 | } 47 | 48 | [[nodiscard]] fmi2::causality causality() const 49 | { 50 | return variable_.causality; 51 | } 52 | 53 | [[nodiscard]] fmi2::variability variability() const 54 | { 55 | return variable_.variability; 56 | } 57 | 58 | [[nodiscard]] fmi2::initial initial() const 59 | { 60 | return variable_.initial; 61 | } 62 | 63 | [[nodiscard]] bool canHandleMultipleSetPerTimelnstant() const 64 | { 65 | return variable_.can_handle_multiple_set_per_time_instant; 66 | } 67 | 68 | [[nodiscard]] std::optional start() const 69 | { 70 | return attribute_.start; 71 | } 72 | 73 | [[nodiscard]] std::optional declaredType() const 74 | { 75 | return attribute_.declaredType; 76 | } 77 | 78 | [[nodiscard]] const U& attribute() const 79 | { 80 | return attribute_; 81 | } 82 | }; 83 | 84 | template 85 | class bounded_scalar_variable : public typed_scalar_variable 86 | { 87 | 88 | public: 89 | bounded_scalar_variable(const scalar_variable& variable, const U& attribute) 90 | : typed_scalar_variable(variable, attribute) 91 | { } 92 | 93 | #if !defined(_WIN32) || (defined(_WIN32) && defined(NOMINMAX)) 94 | [[deprecated("Use get_min() instead")]] [[nodiscard]] std::optional min() const 95 | { 96 | return this->attribute_.min; 97 | } 98 | 99 | [[deprecated("Use get_max() instead")]] [[nodiscard]] std::optional max() const 100 | { 101 | return this->attribute_.max; 102 | } 103 | #endif 104 | 105 | [[nodiscard]] std::optional get_min() const 106 | { 107 | return this->attribute_.min; 108 | } 109 | 110 | [[nodiscard]] std::optional get_max() const 111 | { 112 | return this->attribute_.max; 113 | } 114 | 115 | [[nodiscard]] std::optional quantity() const 116 | { 117 | return this->attribute_.quantity; 118 | } 119 | }; 120 | 121 | class integer_variable : public bounded_scalar_variable 122 | { 123 | 124 | public: 125 | integer_variable( 126 | const scalar_variable& variable, 127 | const integer_attribute& attribute); 128 | }; 129 | 130 | class real_variable : public bounded_scalar_variable 131 | { 132 | 133 | public: 134 | real_variable( 135 | const scalar_variable& variable, 136 | const real_attribute& attribute); 137 | 138 | [[nodiscard]] bool reinit() const; 139 | [[nodiscard]] bool unbounded() const; 140 | [[nodiscard]] bool relativeQuantity() const; 141 | 142 | [[nodiscard]] std::optional nominal() const; 143 | [[nodiscard]] std::optional derivative() const; 144 | [[nodiscard]] std::optional unit() const; 145 | [[nodiscard]] std::optional displayUnit() const; 146 | }; 147 | 148 | 149 | class string_variable : public typed_scalar_variable 150 | { 151 | 152 | public: 153 | string_variable( 154 | const scalar_variable& variable, 155 | const string_attribute& attribute); 156 | }; 157 | 158 | class boolean_variable : public typed_scalar_variable 159 | { 160 | 161 | public: 162 | boolean_variable( 163 | const scalar_variable& variable, 164 | const boolean_attribute& attribute); 165 | }; 166 | 167 | class enumeration_variable : public typed_scalar_variable 168 | { 169 | 170 | public: 171 | enumeration_variable( 172 | const scalar_variable& variable, 173 | const enumeration_attribute& attribute); 174 | }; 175 | 176 | 177 | } // namespace fmi4cpp::fmi2 178 | 179 | 180 | #endif // FMI4CPP_TYPEDSCALARVARIABLE_HPP 181 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi2/xml/unit_definitions.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File Name: unit_definitions.h 3 | * Description: Defines structures for handling physical units and their conversions, including base units, display units, and unit definitions. 4 | * Author: weilong.wen 5 | * Email: weilong.wen.mail@gmail.com 6 | * Created: 2025-02-03 7 | */ 8 | 9 | #ifndef FMI4CPP_UNITDEFINITIONS_HPP 10 | #define FMI4CPP_UNITDEFINITIONS_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace fmi4cpp::fmi2 17 | { 18 | 19 | struct base_unit 20 | { 21 | std::optional kg = 0; 22 | std::optional m = 0; 23 | std::optional s = 0; 24 | std::optional A = 0; 25 | std::optional K = 0; 26 | std::optional mol = 0; 27 | std::optional cd = 0; 28 | std::optional rad = 0; 29 | std::optional factor = 1.0; 30 | std::optional offset = 0.0; 31 | }; 32 | 33 | struct display_unit 34 | { 35 | std::string name; 36 | double factor = 1.0; 37 | double offset = 0.0; 38 | }; 39 | 40 | struct unit 41 | { 42 | std::string name; 43 | ::fmi4cpp::fmi2::base_unit base_unit; 44 | std::vector display_units; 45 | }; 46 | 47 | struct unit_definitions 48 | { 49 | std::vector units; 50 | }; 51 | 52 | } // namespace fmi4cpp::fmi2 53 | 54 | #endif // FMI4CPP_UNITDEFINITIONS_HPP 55 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmi4cpp.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI4CPP_HPP 3 | #define FMI4CPP_FMI4CPP_HPP 4 | 5 | #include 6 | 7 | #endif //FMI4CPP_FMI4CPP_HPP 8 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmu_base.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMU_HPP 3 | #define FMI4CPP_FMU_HPP 4 | 5 | #include 6 | #include 7 | 8 | namespace fmi4cpp 9 | { 10 | 11 | template 12 | class fmu_base 13 | { 14 | 15 | public: 16 | [[nodiscard]] std::string guid() const 17 | { 18 | return get_model_description()->guid; 19 | } 20 | 21 | [[nodiscard]] std::string model_name() const 22 | { 23 | return get_model_description()->model_name; 24 | } 25 | 26 | virtual std::shared_ptr get_model_description() const = 0; 27 | 28 | virtual ~fmu_base() = default; 29 | }; 30 | 31 | template 32 | class fmu_provider : public virtual fmu_base 33 | { 34 | 35 | public: 36 | [[nodiscard]] virtual bool supports_cs() const = 0; 37 | [[nodiscard]] virtual bool supports_me() const = 0; 38 | 39 | virtual std::unique_ptr as_cs_fmu() const = 0; 40 | virtual std::unique_ptr as_me_fmu() const = 0; 41 | }; 42 | 43 | template 44 | class cs_fmu_base : public fmu_base 45 | { 46 | 47 | public: 48 | virtual std::shared_ptr get_model_description() const = 0; 49 | 50 | virtual std::unique_ptr new_instance(bool visible, bool loggingOn) = 0; 51 | }; 52 | 53 | template 54 | class me_fmu_base : public fmu_base 55 | { 56 | 57 | public: 58 | virtual std::shared_ptr get_model_description() const = 0; 59 | 60 | virtual std::unique_ptr new_instance(bool visible, bool loggingOn) = 0; 61 | }; 62 | 63 | } // namespace fmi4cpp 64 | 65 | 66 | #endif //FMI4CPP_FMU_HPP 67 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmu_instance.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMUINSTANCE_HPP 3 | #define FMI4CPP_FMUINSTANCE_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace fmi4cpp 14 | { 15 | 16 | template 17 | class fmu_instance : public fmu_variable_accessor 18 | { 19 | 20 | protected: 21 | double simulationTime_ = 0.0; 22 | 23 | public: 24 | [[nodiscard]] virtual double get_simulation_time() const 25 | { 26 | return simulationTime_; 27 | } 28 | 29 | [[nodiscard]] virtual DLL_HANDLE handle() const = 0; 30 | 31 | [[nodiscard]] virtual status last_status() const = 0; 32 | 33 | virtual std::shared_ptr get_model_description() const = 0; 34 | 35 | virtual bool setup_experiment(double startTime = 0.0, double stopTime = 0.0, double tolerance = 0.0) = 0; 36 | virtual bool enter_initialization_mode() = 0; 37 | virtual bool exit_initialization_mode() = 0; 38 | 39 | virtual bool reset() = 0; 40 | virtual bool terminate() = 0; 41 | 42 | virtual bool get_fmu_state(fmi4cppFMUstate& state) = 0; 43 | virtual bool set_fmu_state(fmi4cppFMUstate state) = 0; 44 | virtual bool free_fmu_state(fmi4cppFMUstate& state) = 0; 45 | 46 | virtual bool serialize_fmu_state( 47 | const fmi4cppFMUstate& state, 48 | std::vector& serializedState) = 0; 49 | virtual bool de_serialize_fmu_state( 50 | fmi4cppFMUstate& state, 51 | const std::vector& serializedState) = 0; 52 | 53 | virtual bool get_directional_derivative( 54 | const std::vector& vUnknownRef, 55 | const std::vector& vKnownRef, 56 | const std::vector& dvKnownRef, 57 | std::vector& dvUnknownRef) = 0; 58 | 59 | ~fmu_instance() override = default; 60 | }; 61 | 62 | } // namespace fmi4cpp 63 | 64 | #endif //FMI4CPP_FMUINSTANCE_HPP 65 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmu_instance_base.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_ABSTRACTFMUINSTANCE_HPP 3 | #define FMI4CPP_ABSTRACTFMUINSTANCE_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace fmi4cpp 13 | { 14 | 15 | template 16 | class fmu_instance_base : public virtual fmu_instance 17 | { 18 | 19 | private: 20 | bool terminated_ = false; 21 | bool instanceFreed_ = false; 22 | std::shared_ptr resource_; 23 | 24 | protected: 25 | fmi4cppComponent c_; 26 | const std::shared_ptr library_; 27 | const std::shared_ptr modelDescription_; 28 | 29 | public: 30 | fmu_instance_base(fmi4cppComponent c, 31 | std::shared_ptr resource, 32 | const std::shared_ptr& library, 33 | const std::shared_ptr& modelDescription) 34 | : resource_(std::move(resource)) 35 | , c_(c) 36 | , library_(library) 37 | , modelDescription_(modelDescription) 38 | {} 39 | 40 | std::shared_ptr get_model_description() const override 41 | { 42 | return modelDescription_; 43 | } 44 | 45 | bool set_debug_logging( 46 | const bool loggingOn, 47 | const std::vector categories) const 48 | { 49 | return library_->set_debug_logging(c_, loggingOn, categories); 50 | } 51 | 52 | bool setup_experiment(double start = 0, double stop = 0, double tolerance = 0) override 53 | { 54 | this->simulationTime_ = start; 55 | return library_->setup_experiment(c_, tolerance, start, stop); 56 | } 57 | 58 | bool enter_initialization_mode() override 59 | { 60 | return library_->enter_initialization_mode(c_); 61 | } 62 | 63 | bool exit_initialization_mode() override 64 | { 65 | return library_->exit_initialization_mode(c_); 66 | } 67 | 68 | bool reset() override 69 | { 70 | return library_->reset(c_); 71 | } 72 | 73 | bool terminate() 74 | { 75 | if (!this->terminated_) { 76 | this->terminated_ = true; 77 | if (!library_->terminate(c_)) { 78 | return false; 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | void free_instance() 85 | { 86 | if (!instanceFreed_) { 87 | instanceFreed_ = true; 88 | library_->free_instance(c_); 89 | c_ = nullptr; 90 | } 91 | } 92 | 93 | bool get_fmu_state(fmi4cppFMUstate& state) override 94 | { 95 | return library_->get_fmu_state(c_, state); 96 | } 97 | 98 | bool set_fmu_state(fmi4cppFMUstate state) override 99 | { 100 | return library_->set_fmu_state(c_, state); 101 | } 102 | 103 | bool free_fmu_state(fmi4cppFMUstate& state) override 104 | { 105 | return library_->free_fmu_state(c_, state); 106 | } 107 | 108 | 109 | bool get_serialized_fmu_state_size( 110 | fmi4cppFMUstate state, 111 | size_t& size) const 112 | { 113 | return library_->get_serialized_fmu_state_size(c_, state, size); 114 | } 115 | 116 | bool serialize_fmu_state( 117 | const fmi4cppFMUstate& state, 118 | std::vector& serializedState) override 119 | { 120 | return library_->serialize_fmu_state(c_, state, serializedState); 121 | } 122 | 123 | bool de_serialize_fmu_state( 124 | fmi4cppFMUstate& state, 125 | const std::vector& serializedState) override 126 | { 127 | return library_->de_serialize_fmu_state(c_, state, serializedState); 128 | } 129 | 130 | bool get_directional_derivative( 131 | const std::vector& vUnknownRef, 132 | const std::vector& vKnownRef, 133 | const std::vector& dvKnownRef, 134 | std::vector& dvUnknownRef) override 135 | { 136 | return library_->get_directional_derivative(c_, vUnknownRef, vKnownRef, dvKnownRef, dvUnknownRef); 137 | } 138 | 139 | bool read_integer( 140 | const fmi4cppValueReference vr, 141 | fmi4cppInteger& ref) override 142 | { 143 | return library_->read_integer(c_, vr, ref); 144 | } 145 | 146 | bool read_integer( 147 | const std::vector& vr, 148 | std::vector& ref) override 149 | { 150 | return library_->read_integer(c_, vr, ref); 151 | } 152 | 153 | bool read_real( 154 | const fmi4cppValueReference vr, 155 | fmi4cppReal& ref) override 156 | { 157 | return library_->read_real(c_, vr, ref); 158 | } 159 | 160 | bool read_real( 161 | const std::vector& vr, 162 | std::vector& ref) override 163 | { 164 | return library_->read_real(c_, vr, ref); 165 | } 166 | 167 | bool read_string( 168 | const fmi4cppValueReference vr, 169 | fmi4cppString& ref) override 170 | { 171 | return library_->read_string(c_, vr, ref); 172 | } 173 | 174 | bool read_string( 175 | const std::vector& vr, 176 | std::vector& ref) override 177 | { 178 | return library_->read_string(c_, vr, ref); 179 | } 180 | 181 | bool read_boolean( 182 | const fmi4cppValueReference vr, 183 | fmi4cppBoolean& ref) override 184 | { 185 | return library_->read_boolean(c_, vr, ref); 186 | } 187 | 188 | bool read_boolean( 189 | const std::vector& vr, 190 | std::vector& ref) override 191 | { 192 | return library_->read_boolean(c_, vr, ref); 193 | } 194 | 195 | bool write_integer( 196 | const fmi4cppValueReference vr, 197 | const fmi4cppInteger value) override 198 | { 199 | return library_->write_integer(c_, vr, value); 200 | } 201 | 202 | bool write_integer( 203 | const std::vector& vr, 204 | const std::vector& values) override 205 | { 206 | return library_->write_integer(c_, vr, values); 207 | } 208 | 209 | bool write_real( 210 | const fmi4cppValueReference vr, 211 | const fmi4cppReal value) override 212 | { 213 | return library_->write_real(c_, vr, value); 214 | } 215 | 216 | bool write_real( 217 | const std::vector& vr, 218 | const std::vector& values) override 219 | { 220 | return library_->write_real(c_, vr, values); 221 | } 222 | 223 | bool write_string( 224 | const fmi4cppValueReference vr, 225 | fmi4cppString value) override 226 | { 227 | return library_->write_string(c_, vr, value); 228 | } 229 | 230 | bool write_string( 231 | const std::vector& vr, 232 | const std::vector& values) override 233 | { 234 | return library_->write_string(c_, vr, values); 235 | } 236 | 237 | bool write_boolean( 238 | const fmi4cppValueReference vr, 239 | const fmi4cppBoolean value) override 240 | { 241 | return library_->write_boolean(c_, vr, value); 242 | } 243 | 244 | bool write_boolean( 245 | const std::vector& vr, 246 | const std::vector& values) override 247 | { 248 | return library_->write_boolean(c_, vr, values); 249 | } 250 | 251 | ~fmu_instance_base() 252 | { 253 | terminate(); 254 | free_instance(); 255 | } 256 | }; 257 | 258 | } // namespace fmi4cpp 259 | 260 | #endif //FMI4CPP_ABSTRACTFMUINSTANCE_HPP 261 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmu_resource.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMURESOURCE_HPP 3 | #define FMI4CPP_FMURESOURCE_HPP 4 | 5 | #include 6 | #include 7 | 8 | namespace fmi4cpp 9 | { 10 | 11 | class fmu_resource 12 | { 13 | 14 | private: 15 | std::filesystem::path path_; 16 | 17 | public: 18 | explicit fmu_resource(std::filesystem::path path); 19 | 20 | [[nodiscard]] std::string resource_path() const; 21 | 22 | [[nodiscard]] std::string model_description_path() const; 23 | 24 | [[nodiscard]] std::string absolute_library_path(const std::string& modelIdentifier) const; 25 | 26 | [[nodiscard]] std::string get_model_description_xml() const; 27 | 28 | ~fmu_resource(); 29 | }; 30 | 31 | } // namespace fmi4cpp 32 | 33 | #endif //FMI4CPP_FMURESOURCE_HPP -------------------------------------------------------------------------------- /include/fmi4cpp/fmu_slave.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMUSLAVE_HPP 3 | #define FMI4CPP_FMUSLAVE_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp 8 | { 9 | 10 | template 11 | class fmu_slave : public virtual fmu_instance 12 | { 13 | 14 | public: 15 | virtual bool step(double stepSize) = 0; 16 | 17 | virtual bool cancel_step() = 0; 18 | }; 19 | 20 | } // namespace fmi4cpp 21 | 22 | #endif //FMI4CPP_FMUSLAVE_HPP 23 | -------------------------------------------------------------------------------- /include/fmi4cpp/fmu_variable_accessor.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMUVARIABLEACCESSOR_HPP 3 | #define FMI4CPP_FMUVARIABLEACCESSOR_HPP 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace fmi4cpp 10 | { 11 | 12 | class fmu_reader 13 | { 14 | 15 | public: 16 | virtual bool read_integer(fmi4cppValueReference vr, fmi4cppInteger& ref) = 0; 17 | virtual bool read_integer(const std::vector& vr, std::vector& ref) = 0; 18 | 19 | virtual bool read_real(fmi4cppValueReference vr, fmi4cppReal& ref) = 0; 20 | virtual bool read_real(const std::vector& vr, std::vector& ref) = 0; 21 | 22 | virtual bool read_string(fmi4cppValueReference vr, fmi4cppString& ref) = 0; 23 | virtual bool read_string(const std::vector& vr, std::vector& ref) = 0; 24 | 25 | virtual bool read_boolean(fmi4cppValueReference vr, fmi4cppBoolean& ref) = 0; 26 | virtual bool read_boolean(const std::vector& vr, std::vector& ref) = 0; 27 | 28 | virtual ~fmu_reader() = default; 29 | }; 30 | 31 | class fmu_writer 32 | { 33 | 34 | public: 35 | virtual bool write_integer(fmi4cppValueReference vr, fmi4cppInteger value) = 0; 36 | virtual bool write_integer( 37 | const std::vector& vr, 38 | const std::vector& values) = 0; 39 | 40 | virtual bool write_real(fmi4cppValueReference vr, fmi4cppReal value) = 0; 41 | virtual bool write_real( 42 | const std::vector& vr, 43 | const std::vector& values) = 0; 44 | 45 | virtual bool write_string(fmi4cppValueReference vr, fmi4cppString value) = 0; 46 | virtual bool write_string( 47 | const std::vector& vr, 48 | const std::vector& values) = 0; 49 | 50 | virtual bool write_boolean(fmi4cppValueReference vr, fmi4cppBoolean value) = 0; 51 | virtual bool write_boolean( 52 | const std::vector& vr, 53 | const std::vector& values) = 0; 54 | 55 | virtual ~fmu_writer() = default; 56 | }; 57 | 58 | class fmu_variable_accessor : public fmu_reader, public fmu_writer 59 | { 60 | }; 61 | 62 | } // namespace fmi4cpp 63 | 64 | #endif //FMI4CPP_FMUVARIABLEACCESSOR_HPP 65 | -------------------------------------------------------------------------------- /include/fmi4cpp/status.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_STATUS_HPP 3 | #define FMI4CPP_STATUS_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp 8 | { 9 | 10 | enum class status 11 | { 12 | OK, 13 | Warning, 14 | Discard, 15 | Error, 16 | Fatal, 17 | Pending, 18 | Unknown 19 | }; 20 | 21 | inline std::string to_string(fmi4cpp::status status) 22 | { 23 | switch (status) { 24 | case fmi4cpp::status::OK: 25 | return "OK"; 26 | case fmi4cpp::status::Warning: 27 | return "Warning"; 28 | case fmi4cpp::status::Discard: 29 | return "Discard"; 30 | case fmi4cpp::status::Error: 31 | return "Error"; 32 | case fmi4cpp::status::Fatal: 33 | return "Fatal"; 34 | case fmi4cpp::status::Pending: 35 | return "Pending"; 36 | default: 37 | return "Unknown"; 38 | } 39 | } 40 | 41 | } // namespace fmi4cpp 42 | 43 | #endif //FMI4CPP_STATUS_HPP 44 | -------------------------------------------------------------------------------- /include/fmi4cpp/tools/unzipper.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_UNZIPPER_HPP 3 | #define FMI4CPP_UNZIPPER_HPP 4 | 5 | #include 6 | 7 | namespace fmi4cpp 8 | { 9 | 10 | bool unzip(const std::filesystem::path& zip_file, const std::filesystem::path& tmp_path); 11 | 12 | } // namespace fmi4cpp 13 | 14 | #endif // FMI4CPP_UNZIPPER_HPP 15 | -------------------------------------------------------------------------------- /include/fmi4cpp/types.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_TYPES_HPP 3 | #define FMI4CPP_TYPES_HPP 4 | 5 | namespace fmi4cpp 6 | { 7 | 8 | typedef void* fmi4cppComponent; /* Pointer to FMU instance */ 9 | typedef void* fmi4cppFMUstate; /* Pointer to internal FMU state */ 10 | typedef unsigned int fmi4cppValueReference; 11 | typedef double fmi4cppReal; 12 | typedef int fmi4cppInteger; 13 | typedef int fmi4cppBoolean; 14 | typedef char fmi4cppChar; 15 | typedef const fmi4cppChar* fmi4cppString; 16 | typedef char fmi4cppByte; 17 | 18 | } // namespace fmi4cpp 19 | 20 | #endif //FMI4CPP_TYPES_HPP 21 | -------------------------------------------------------------------------------- /resources/fmus/2.0/cs/20sim/4.6.4.8004/ControlledTemperature/ControlledTemperature.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/cs/20sim/4.6.4.8004/ControlledTemperature/ControlledTemperature.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/cs/20sim/4.6.4.8004/TorsionBar/TorsionBar.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/cs/20sim/4.6.4.8004/TorsionBar/TorsionBar.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/cs/OpenModelica/v1.11.0/FmuExportCrossCompile/FmuExportCrossCompile.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/cs/OpenModelica/v1.11.0/FmuExportCrossCompile/FmuExportCrossCompile.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/cs/OpenModelica/v1.11.0/FmuExportCrossCompile/modelDescription.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 13 | 14 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 48 | 49 | 50 | 51 | 57 | 58 | 59 | 60 | 66 | 67 | 68 | 69 | 75 | 76 | 77 | 78 | 84 | 85 | 86 | 87 | 93 | 94 | 95 | 96 | 102 | 103 | 104 | 105 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /resources/fmus/2.0/me/OpenModelica/v1.11.0/FmuExportCrossCompile/FmuExportCrossCompile.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/me/OpenModelica/v1.11.0/FmuExportCrossCompile/FmuExportCrossCompile.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/me/OpenModelica/v1.11.0/FmuExportCrossCompile/modelDescription.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 13 | 14 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 48 | 49 | 50 | 51 | 57 | 58 | 59 | 60 | 66 | 67 | 68 | 69 | 75 | 76 | 77 | 78 | 84 | 85 | 86 | 87 | 93 | 94 | 95 | 96 | 102 | 103 | 104 | 105 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /resources/fmus/2.0/me/Test-FMUs/0.0.1/BouncingBall/BouncingBall.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/me/Test-FMUs/0.0.1/BouncingBall/BouncingBall.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/me/Test-FMUs/0.0.1/Dahlquist/Dahlquist.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/me/Test-FMUs/0.0.1/Dahlquist/Dahlquist.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/me/Test-FMUs/0.0.1/Feedthrough/Feedthrough.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/me/Test-FMUs/0.0.1/Feedthrough/Feedthrough.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/me/Test-FMUs/0.0.1/Resource/Resource.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/me/Test-FMUs/0.0.1/Resource/Resource.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/me/Test-FMUs/0.0.1/Stair/Stair.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/me/Test-FMUs/0.0.1/Stair/Stair.fmu -------------------------------------------------------------------------------- /resources/fmus/2.0/me/Test-FMUs/0.0.1/VanDerPol/VanDerPol.fmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NTNU-IHB/FMI4cpp/b29291588ff46a1a85cfd04bc2974078838ec8c6/resources/fmus/2.0/me/Test-FMUs/0.0.1/VanDerPol/VanDerPol.fmu -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(publicHeaderDir ${PROJECT_SOURCE_DIR}/include) 2 | 3 | set(publicHeaders 4 | 5 | "fmi4cpp/fmi4cpp.hpp" 6 | "fmi4cpp/status.hpp" 7 | "fmi4cpp/types.hpp" 8 | 9 | "fmi4cpp/fmu_base.hpp" 10 | "fmi4cpp/fmu_slave.hpp" 11 | "fmi4cpp/fmu_resource.hpp" 12 | "fmi4cpp/fmu_instance.hpp" 13 | "fmi4cpp/fmu_instance_base.hpp" 14 | "fmi4cpp/fmu_variable_accessor.hpp" 15 | 16 | "fmi4cpp/dll_handle.hpp" 17 | 18 | "fmi4cpp/fmi2/fmi2.hpp" 19 | "fmi4cpp/fmi2/fmu.hpp" 20 | "fmi4cpp/fmi2/fmi2_library.hpp" 21 | 22 | "fmi4cpp/fmi2/fmi2Functions.h" 23 | "fmi4cpp/fmi2/fmi2FunctionTypes.h" 24 | "fmi4cpp/fmi2/fmi2TypesPlatform.h" 25 | 26 | "fmi4cpp/fmi2/cs_fmu.hpp" 27 | "fmi4cpp/fmi2/cs_library.hpp" 28 | "fmi4cpp/fmi2/cs_slave.hpp" 29 | 30 | "fmi4cpp/fmi2/me_fmu.hpp" 31 | "fmi4cpp/fmi2/me_library.hpp" 32 | "fmi4cpp/fmi2/me_instance.hpp" 33 | 34 | "fmi4cpp/fmi2/xml/enums.hpp" 35 | "fmi4cpp/fmi2/xml/source_files.hpp" 36 | "fmi4cpp/fmi2/xml/unit_definitions.hpp" 37 | 38 | "fmi4cpp/fmi2/xml/default_experiment.hpp" 39 | "fmi4cpp/fmi2/xml/fmu_attributes.hpp" 40 | "fmi4cpp/fmi2/xml/model_structure.hpp" 41 | "fmi4cpp/fmi2/xml/model_description.hpp" 42 | "fmi4cpp/fmi2/xml/specific_model_description.hpp" 43 | "fmi4cpp/fmi2/xml/me_model_description.hpp" 44 | "fmi4cpp/fmi2/xml/cs_model_description.hpp" 45 | "fmi4cpp/fmi2/xml/model_description_parser.hpp" 46 | 47 | "fmi4cpp/fmi2/xml/model_variables.hpp" 48 | "fmi4cpp/fmi2/xml/scalar_variable.hpp" 49 | "fmi4cpp/fmi2/xml/typed_scalar_variable.hpp" 50 | 51 | "fmi4cpp/tools/unzipper.hpp" 52 | 53 | ) 54 | 55 | set(privateHeaders 56 | 57 | "fmi4cpp/mlog.hpp" 58 | "fmi4cpp/library_helper.hpp" 59 | 60 | "fmi4cpp/fmi2/status_converter.hpp" 61 | 62 | "fmi4cpp/tools/simple_id.hpp" 63 | "fmi4cpp/tools/os_util.hpp" 64 | 65 | ) 66 | 67 | set(sources 68 | 69 | "fmi4cpp/fmu_resource.cpp" 70 | 71 | "fmi4cpp/fmi2/fmu.cpp" 72 | "fmi4cpp/fmi2/fmi2_library.cpp" 73 | 74 | "fmi4cpp/fmi2/cs_fmu.cpp" 75 | "fmi4cpp/fmi2/me_fmu.cpp" 76 | "fmi4cpp/fmi2/cs_library.cpp" 77 | "fmi4cpp/fmi2/cs_slave.cpp" 78 | "fmi4cpp/fmi2/me_library.cpp" 79 | "fmi4cpp/fmi2/me_instance.cpp" 80 | 81 | "fmi4cpp/fmi2/xml/enums.cpp" 82 | "fmi4cpp/fmi2/xml/model_description.cpp" 83 | "fmi4cpp/fmi2/xml/model_description_parser.cpp" 84 | "fmi4cpp/fmi2/xml/model_variables.cpp" 85 | "fmi4cpp/fmi2/xml/scalar_variable.cpp" 86 | 87 | "fmi4cpp/tools/unzipper.cpp" 88 | 89 | ) 90 | 91 | set(publicHeadersFull) 92 | foreach(header IN LISTS publicHeaders) 93 | list(APPEND publicHeadersFull "${publicHeaderDir}/${header}") 94 | endforeach() 95 | 96 | add_library(fmi4cpp ${publicHeadersFull} ${privateHeaders} ${sources}) 97 | add_library(fmi4cpp::fmi4cpp ALIAS fmi4cpp) 98 | target_compile_features(fmi4cpp PUBLIC "cxx_std_17") 99 | 100 | target_include_directories(fmi4cpp 101 | PUBLIC 102 | $ 103 | $ 104 | PRIVATE 105 | ${CMAKE_CURRENT_SOURCE_DIR} 106 | ) 107 | 108 | target_link_libraries(fmi4cpp 109 | PRIVATE 110 | libzip::libzip 111 | pugixml::pugixml 112 | ) 113 | 114 | if(WIN32) 115 | target_link_libraries(fmi4cpp PRIVATE "Bcrypt") 116 | elseif(UNIX) 117 | target_link_libraries(fmi4cpp PRIVATE dl) 118 | endif() 119 | 120 | 121 | if (FMI4CPP_LOG_LEVEL STREQUAL "OFF") 122 | target_compile_definitions(fmi4cpp PRIVATE MLOG_LEVEL_OFF) 123 | elseif (FMI4CPP_LOG_LEVEL STREQUAL "TRACE") 124 | target_compile_definitions(fmi4cpp PRIVATE MLOG_LEVEL_TRACE) 125 | elseif (FMI4CPP_LOG_LEVEL STREQUAL "DEBUG") 126 | target_compile_definitions(fmi4cpp PRIVATE MLOG_LEVEL_DEBUG) 127 | elseif (FMI4CPP_LOG_LEVEL STREQUAL "INFO") 128 | target_compile_definitions(fmi4cpp PRIVATE MLOG_LEVEL_INFO) 129 | elseif (FMI4CPP_LOG_LEVEL STREQUAL "WARN") 130 | target_compile_definitions(fmi4cpp PRIVATE MLOG_LEVEL_WARN) 131 | elseif (FMI4CPP_LOG_LEVEL STREQUAL "ERROR") 132 | target_compile_definitions(fmi4cpp PRIVATE MLOG_LEVEL_ERROR) 133 | elseif (FMI4CPP_LOG_LEVEL STREQUAL "FATAL") 134 | target_compile_definitions(fmi4cpp PRIVATE MLOG_LEVEL_FATAL) 135 | else () 136 | target_compile_definitions(fmi4cpp PRIVATE $<$:MLOG_LEVEL_DEBUG>) 137 | endif () 138 | 139 | install( 140 | TARGETS fmi4cpp 141 | EXPORT "${FMI4CPP_EXPORT_TARGET}" 142 | ${FMI4CPP_INSTALL_DESTINATIONS} 143 | ) 144 | install( 145 | DIRECTORY "${publicHeaderDir}/fmi4cpp" 146 | DESTINATION "${FMI4CPP_HEADER_INSTALL_DIR}" 147 | ) 148 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/cs_fmu.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | using namespace fmi4cpp; 7 | using namespace fmi4cpp::fmi2; 8 | 9 | cs_fmu::cs_fmu(std::shared_ptr resource, 10 | std::shared_ptr md) 11 | : resource_(std::move(resource)) 12 | , modelDescription_(std::move(md)) 13 | {} 14 | 15 | std::string cs_fmu::get_model_description_xml() const 16 | { 17 | return resource_->get_model_description_xml(); 18 | } 19 | 20 | std::shared_ptr cs_fmu::get_model_description() const 21 | { 22 | return modelDescription_; 23 | } 24 | 25 | std::unique_ptr cs_fmu::new_instance(const bool visible, const bool loggingOn) 26 | { 27 | std::shared_ptr lib = nullptr; 28 | auto modelIdentifier = modelDescription_->model_identifier; 29 | if (lib_ == nullptr) { 30 | lib_ = std::make_shared(modelIdentifier, resource_); 31 | } 32 | lib = lib_; 33 | 34 | auto c = lib->instantiate(modelIdentifier, fmi2CoSimulation, guid(), 35 | resource_->resource_path(), visible, loggingOn); 36 | return std::make_unique(c, resource_, lib, modelDescription_); 37 | } 38 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/cs_library.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace fmi4cpp; 6 | using namespace fmi4cpp::fmi2; 7 | 8 | cs_library::cs_library(const std::string& modelIdentifier, 9 | const std::shared_ptr& resource) 10 | : fmi2_library(modelIdentifier, resource) 11 | { 12 | 13 | fmi2SetRealInputDerivatives_ = load_function(handle_, 14 | "fmi2SetRealInputDerivatives"); 15 | fmi2GetRealOutputDerivatives_ = load_function(handle_, 16 | "fmi2GetRealOutputDerivatives"); 17 | 18 | fmi2DoStep_ = load_function(handle_, "fmi2DoStep"); 19 | fmi2CancelStep_ = load_function(handle_, "fmi2CancelStep"); 20 | 21 | fmi2GetStatus_ = load_function(handle_, "fmi2GetStatusTYPE"); 22 | fmi2GetRealStatus_ = load_function(handle_, "fmi2GetRealStatusTYPE"); 23 | fmi2GetIntegerStatus_ = load_function(handle_, "fmi2GetIntegerStatusTYPE"); 24 | fmi2GetBooleanStatus_ = load_function(handle_, "fmi2GetBooleanStatusTYPE"); 25 | fmi2GetStringStatus_ = load_function(handle_, "fmi2GetStringStatusTYPE"); 26 | } 27 | 28 | bool cs_library::step( 29 | fmi2Component c, 30 | const fmi2Real currentCommunicationPoint, 31 | const fmi2Real communicationStepSize, 32 | const bool noSetFMUStatePriorToCurrentPoint) 33 | { 34 | return update_status_and_return_true_if_ok( 35 | fmi2DoStep_(c, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint)); 36 | } 37 | 38 | bool cs_library::cancel_step(fmi2Component c) 39 | { 40 | return update_status_and_return_true_if_ok(fmi2CancelStep_(c)); 41 | } 42 | 43 | bool cs_library::set_real_input_derivatives( 44 | fmi2Component c, 45 | const std::vector& vr, 46 | const std::vector& order, 47 | const std::vector& value) 48 | { 49 | return update_status_and_return_true_if_ok(fmi2SetRealInputDerivatives_(c, vr.data(), vr.size(), order.data(), value.data())); 50 | } 51 | 52 | bool cs_library::get_real_output_derivatives( 53 | fmi2Component c, 54 | const std::vector& vr, 55 | const std::vector& order, 56 | std::vector& value) 57 | { 58 | return update_status_and_return_true_if_ok( 59 | fmi2GetRealOutputDerivatives_(c, vr.data(), vr.size(), order.data(), value.data())); 60 | } 61 | 62 | bool cs_library::get_status( 63 | fmi2Component c, 64 | const fmi2StatusKind s, 65 | fmi2Status& value) 66 | { 67 | return update_status_and_return_true_if_ok( 68 | fmi2GetStatus_(c, s, &value)); 69 | } 70 | 71 | bool cs_library::get_real_status( 72 | fmi2Component c, 73 | const fmi2StatusKind s, 74 | fmi2Real& value) 75 | { 76 | return update_status_and_return_true_if_ok( 77 | fmi2GetRealStatus_(c, s, &value)); 78 | } 79 | 80 | bool cs_library::get_integer_status( 81 | fmi2Component c, 82 | const fmi2StatusKind s, 83 | fmi2Integer& value) 84 | { 85 | return update_status_and_return_true_if_ok( 86 | fmi2GetIntegerStatus_(c, s, &value)); 87 | } 88 | 89 | bool cs_library::get_boolean_status( 90 | fmi2Component c, 91 | const fmi2StatusKind s, 92 | fmi2Boolean& value) 93 | { 94 | return update_status_and_return_true_if_ok( 95 | fmi2GetBooleanStatus_(c, s, &value)); 96 | } 97 | 98 | bool cs_library::get_string_status( 99 | fmi2Component c, 100 | const fmi2StatusKind s, 101 | fmi2String& value) 102 | { 103 | return update_status_and_return_true_if_ok( 104 | fmi2GetStringStatus_(c, s, &value)); 105 | } 106 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/cs_slave.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace fmi4cpp::fmi2; 6 | 7 | cs_slave::cs_slave(fmi2Component c, 8 | const std::shared_ptr& resource, 9 | const std::shared_ptr& library, 10 | const std::shared_ptr& modelDescription) 11 | : fmu_instance_base(c, resource, library, modelDescription) 12 | {} 13 | 14 | DLL_HANDLE cs_slave::handle() const 15 | { 16 | return library_->handle(); 17 | } 18 | 19 | fmi4cpp::status cs_slave::last_status() const 20 | { 21 | return convert(library_->last_status()); 22 | } 23 | 24 | bool cs_slave::step(const double stepSize) 25 | { 26 | if (library_->step(c_, simulationTime_, stepSize, false)) { 27 | simulationTime_ += stepSize; 28 | return true; 29 | } 30 | return false; 31 | } 32 | 33 | bool cs_slave::cancel_step() 34 | { 35 | return library_->cancel_step(c_); 36 | } 37 | 38 | std::shared_ptr cs_slave::get_model_description() const 39 | { 40 | return fmu_instance_base::get_model_description(); 41 | } 42 | 43 | bool cs_slave::setup_experiment(double start, double stop, double tolerance) 44 | { 45 | return fmu_instance_base::setup_experiment(start, stop, tolerance); 46 | } 47 | 48 | bool cs_slave::enter_initialization_mode() 49 | { 50 | return fmu_instance_base::enter_initialization_mode(); 51 | } 52 | 53 | bool cs_slave::exit_initialization_mode() 54 | { 55 | return fmu_instance_base::exit_initialization_mode(); 56 | } 57 | 58 | bool cs_slave::reset() 59 | { 60 | return fmu_instance_base::reset(); 61 | } 62 | 63 | bool cs_slave::terminate() 64 | { 65 | return fmu_instance_base::terminate(); 66 | } 67 | 68 | bool cs_slave::read_integer(unsigned int vr, int& ref) 69 | { 70 | return fmu_instance_base::read_integer(vr, ref); 71 | } 72 | 73 | bool cs_slave::read_integer( 74 | const std::vector& vr, 75 | std::vector& ref) 76 | { 77 | return fmu_instance_base::read_integer(vr, ref); 78 | } 79 | 80 | bool cs_slave::read_real(unsigned int vr, double& ref) 81 | { 82 | return fmu_instance_base::read_real(vr, ref); 83 | } 84 | 85 | bool cs_slave::read_real( 86 | const std::vector& vr, 87 | std::vector& ref) 88 | { 89 | return fmu_instance_base::read_real(vr, ref); 90 | } 91 | 92 | bool cs_slave::read_string(unsigned int vr, const char*& ref) 93 | { 94 | return fmu_instance_base::read_string(vr, ref); 95 | } 96 | 97 | bool cs_slave::read_string( 98 | const std::vector& vr, 99 | std::vector& ref) 100 | { 101 | return fmu_instance_base::read_string(vr, ref); 102 | } 103 | 104 | bool cs_slave::read_boolean(unsigned int vr, int& ref) 105 | { 106 | return fmu_instance_base::read_boolean(vr, ref); 107 | } 108 | 109 | bool cs_slave::read_boolean( 110 | const std::vector& vr, 111 | std::vector& ref) 112 | { 113 | return fmu_instance_base::read_boolean(vr, ref); 114 | } 115 | 116 | bool cs_slave::write_integer(unsigned int vr, int value) 117 | { 118 | return fmu_instance_base::write_integer(vr, value); 119 | } 120 | 121 | bool cs_slave::write_integer( 122 | const std::vector& vr, 123 | const std::vector& values) 124 | { 125 | return fmu_instance_base::write_integer(vr, values); 126 | } 127 | 128 | bool cs_slave::write_real(unsigned int vr, double value) 129 | { 130 | return fmu_instance_base::write_real(vr, value); 131 | } 132 | 133 | bool cs_slave::write_real( 134 | const std::vector& vr, 135 | const std::vector& values) 136 | { 137 | return fmu_instance_base::write_real(vr, values); 138 | } 139 | 140 | bool cs_slave::write_string(unsigned int vr, const char* value) 141 | { 142 | return fmu_instance_base::write_string(vr, value); 143 | } 144 | 145 | bool cs_slave::write_string( 146 | const std::vector& vr, 147 | const std::vector& values) 148 | { 149 | return fmu_instance_base::write_string(vr, values); 150 | } 151 | 152 | bool cs_slave::write_boolean(unsigned int vr, int value) 153 | { 154 | return fmu_instance_base::write_boolean(vr, value); 155 | } 156 | 157 | bool cs_slave::write_boolean( 158 | const std::vector& vr, 159 | const std::vector& values) 160 | { 161 | return fmu_instance_base::write_boolean(vr, values); 162 | } 163 | 164 | 165 | bool cs_slave::get_fmu_state(void*& state) 166 | { 167 | return fmu_instance_base::get_fmu_state(state); 168 | } 169 | 170 | bool cs_slave::set_fmu_state(void* state) 171 | { 172 | return fmu_instance_base::set_fmu_state(state); 173 | } 174 | 175 | bool cs_slave::free_fmu_state(void*& state) 176 | { 177 | return fmu_instance_base::free_fmu_state(state); 178 | } 179 | 180 | bool cs_slave::serialize_fmu_state( 181 | const fmi2FMUstate& state, 182 | std::vector& serializedState) 183 | { 184 | return fmu_instance_base::serialize_fmu_state( 185 | state, serializedState); 186 | } 187 | 188 | bool cs_slave::de_serialize_fmu_state( 189 | fmi2FMUstate& state, 190 | const std::vector& serializedState) 191 | { 192 | return fmu_instance_base::de_serialize_fmu_state( 193 | state, serializedState); 194 | } 195 | 196 | bool cs_slave::get_directional_derivative( 197 | const std::vector& vUnknownRef, 198 | const std::vector& vKnownRef, 199 | const std::vector& dvKnownRef, 200 | std::vector& dvUnknownRef) 201 | { 202 | return fmu_instance_base::get_directional_derivative( 203 | vUnknownRef, vKnownRef, dvKnownRef, dvUnknownRef); 204 | } 205 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/fmi2_library.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using namespace fmi4cpp; 11 | using namespace fmi4cpp::fmi2; 12 | 13 | namespace 14 | { 15 | 16 | std::string to_string(fmi2Status status) 17 | { 18 | switch (status) { 19 | case fmi2OK: 20 | return "OK"; 21 | case fmi2Warning: 22 | return "Warning"; 23 | case fmi2Discard: 24 | return "Discard"; 25 | case fmi2Error: 26 | return "Error"; 27 | case fmi2Fatal: 28 | return "Fatal"; 29 | case fmi2Pending: 30 | return "Pending"; 31 | default: 32 | return "Unknown"; 33 | } 34 | } 35 | 36 | void logger(void* /*fmi2ComponentEnvironment*/, fmi2String instance_name, fmi2Status status, fmi2String category, 37 | fmi2String message, ...) 38 | { 39 | char msg[1000]; 40 | va_list argp; 41 | 42 | va_start(argp, message); 43 | vsprintf(msg, message, argp); 44 | va_end(argp); 45 | 46 | MLOG_INFO("[FMI callback logger] status=" + to_string(status) + ", instanceName=" + instance_name + 47 | ", category=" + category + ", message=" + msg); 48 | } 49 | 50 | const fmi2CallbackFunctions callback = { 51 | logger, calloc, free, nullptr, nullptr}; 52 | 53 | } // namespace 54 | 55 | 56 | fmi2_library::fmi2_library(const std::string& modelIdentifier, const std::shared_ptr& resource) 57 | : resource_(resource) 58 | { 59 | const std::string libName = resource->absolute_library_path(modelIdentifier); 60 | 61 | MLOG_DEBUG("Loading shared library '" + std::filesystem::path(libName).stem().string() + get_shared_library_extension() + "'"); 62 | 63 | #ifdef _WIN32 64 | std::string dllDirectory; 65 | std::filesystem::path path(libName); 66 | 67 | if (path.has_parent_path()) { 68 | dllDirectory = path.parent_path().string(); 69 | } 70 | 71 | if (!dllDirectory.empty()) { 72 | std::wstring wDllDirectory(dllDirectory.begin(), dllDirectory.end()); 73 | dllDirectoryCookie_ = AddDllDirectory(wDllDirectory.c_str()); 74 | } 75 | #endif 76 | 77 | handle_ = load_library(libName); 78 | 79 | if (!handle_) { 80 | const auto err = "Unable to load dynamic library '" + libName + "'! " + getLastError(); 81 | MLOG_ERROR(err); 82 | throw std::runtime_error(err); 83 | } 84 | 85 | fmi2GetVersion_ = load_function(handle_, "fmi2GetVersion"); 86 | fmi2GetTypesPlatform_ = load_function(handle_, "fmi2GetTypesPlatform"); 87 | 88 | fmi2SetDebugLogging_ = load_function(handle_, "fmi2SetDebugLogging"); 89 | 90 | fmi2Instantiate_ = load_function(handle_, "fmi2Instantiate"); 91 | fmi2SetupExperiment_ = load_function(handle_, "fmi2SetupExperiment"); 92 | fmi2EnterInitializationMode_ = load_function(handle_, 93 | "fmi2EnterInitializationMode"); 94 | fmi2ExitInitializationMode_ = load_function(handle_, 95 | "fmi2ExitInitializationMode"); 96 | 97 | fmi2Reset_ = load_function(handle_, "fmi2Reset"); 98 | fmi2Terminate_ = load_function(handle_, "fmi2Terminate"); 99 | 100 | fmi2GetInteger_ = load_function(handle_, "fmi2GetInteger"); 101 | fmi2GetReal_ = load_function(handle_, "fmi2GetReal"); 102 | fmi2GetString_ = load_function(handle_, "fmi2GetString"); 103 | fmi2GetBoolean_ = load_function(handle_, "fmi2GetBoolean"); 104 | 105 | fmi2SetInteger_ = load_function(handle_, "fmi2SetInteger"); 106 | fmi2SetReal_ = load_function(handle_, "fmi2SetReal"); 107 | fmi2SetString_ = load_function(handle_, "fmi2SetString"); 108 | fmi2SetBoolean_ = load_function(handle_, "fmi2SetBoolean"); 109 | 110 | fmi2GetFMUstate_ = load_function(handle_, "fmi2GetFMUstate"); 111 | fmi2SetFMUstate_ = load_function(handle_, "fmi2SetFMUstate"); 112 | fmi2FreeFMUstate_ = load_function(handle_, "fmi2FreeFMUstate"); 113 | fmi2SerializeFMUstate_ = load_function(handle_, "fmi2SerializeFMUstate"); 114 | fmi2DeSerializeFMUstate_ = load_function(handle_, "fmi2DeSerializeFMUstate"); 115 | 116 | fmi2GetDirectionalDerivative_ = load_function(handle_, 117 | "fmi2GetDirectionalDerivative"); 118 | 119 | fmi2FreeInstance_ = load_function(handle_, "fmi2FreeInstance"); 120 | } 121 | 122 | bool fmi2_library::update_status_and_return_true_if_ok(fmi2Status status) 123 | { 124 | lastStatus_ = status; 125 | return status == fmi2OK; 126 | } 127 | 128 | DLL_HANDLE fmi2_library::handle() const 129 | { 130 | return handle_; 131 | } 132 | 133 | fmi2Status fmi2_library::last_status() const 134 | { 135 | return lastStatus_; 136 | } 137 | 138 | fmi2String fmi2_library::get_version() const 139 | { 140 | return fmi2GetVersion_(); 141 | } 142 | 143 | fmi2String fmi2_library::get_types_platform() const 144 | { 145 | return fmi2GetTypesPlatform_(); 146 | } 147 | 148 | fmi2Component fmi2_library::instantiate(const std::string& instanceName, const fmi2Type type, 149 | const std::string& guid, const std::string& resourceLocation, 150 | bool visible, bool loggingOn) 151 | { 152 | fmi2Component c = fmi2Instantiate_(instanceName.c_str(), type, guid.c_str(), 153 | resourceLocation.c_str(), &callback, visible, loggingOn); 154 | 155 | if (c == nullptr) { 156 | const std::string msg = "Fatal: fmi2Instantiate returned nullptr, unable to instantiate FMU instance!"; 157 | MLOG_ERROR(msg); 158 | throw std::runtime_error(msg); 159 | } 160 | 161 | return c; 162 | } 163 | 164 | bool fmi2_library::set_debug_logging(fmi2Component c, bool loggingOn, 165 | std::vector categories) 166 | { 167 | return update_status_and_return_true_if_ok( 168 | fmi2SetDebugLogging_(c, loggingOn, categories.size(), categories.data())); 169 | } 170 | 171 | bool fmi2_library::setup_experiment(fmi2Component c, double tolerance, double startTime, double stopTime) 172 | { 173 | bool stopDefined = (stopTime > startTime); 174 | bool toleranceDefined = (tolerance > 0); 175 | MLOG_INFO("Calling fmi2SetupExperiment with toleranceDefined=" + 176 | std::string((toleranceDefined ? "true" : "false")) 177 | << ", tolerance=" << tolerance 178 | << ", startTime=" << startTime 179 | << ", stopTimeDefined=" << std::string((stopDefined ? "true" : "false")) << ", stop=" << stopTime) 180 | return update_status_and_return_true_if_ok( 181 | fmi2SetupExperiment_(c, toleranceDefined, tolerance, startTime, stopDefined, stopTime)); 182 | } 183 | 184 | bool fmi2_library::enter_initialization_mode(fmi2Component c) 185 | { 186 | return update_status_and_return_true_if_ok( 187 | fmi2EnterInitializationMode_(c)); 188 | } 189 | 190 | bool fmi2_library::exit_initialization_mode(fmi2Component c) 191 | { 192 | return update_status_and_return_true_if_ok( 193 | fmi2ExitInitializationMode_(c)); 194 | } 195 | 196 | bool fmi2_library::reset(fmi2Component c) 197 | { 198 | return update_status_and_return_true_if_ok( 199 | fmi2Reset_(c)); 200 | } 201 | 202 | bool fmi2_library::terminate(fmi2Component c) 203 | { 204 | return update_status_and_return_true_if_ok( 205 | fmi2Terminate_(c)); 206 | } 207 | 208 | bool fmi2_library::read_integer( 209 | fmi2Component c, 210 | fmi2ValueReference vr, 211 | fmi2Integer& ref) 212 | { 213 | return update_status_and_return_true_if_ok( 214 | fmi2GetInteger_(c, &vr, 1, &ref)); 215 | } 216 | 217 | bool fmi2_library::read_integer( 218 | fmi2Component c, 219 | const std::vector& vr, 220 | std::vector& ref) 221 | { 222 | return update_status_and_return_true_if_ok( 223 | fmi2GetInteger_(c, vr.data(), vr.size(), ref.data())); 224 | } 225 | 226 | bool fmi2_library::read_real( 227 | fmi2Component c, 228 | fmi2ValueReference vr, 229 | fmi2Real& ref) 230 | { 231 | return update_status_and_return_true_if_ok( 232 | fmi2GetReal_(c, &vr, 1, &ref)); 233 | } 234 | 235 | bool fmi2_library::read_real( 236 | fmi2Component c, 237 | const std::vector& vr, 238 | std::vector& ref) 239 | { 240 | return update_status_and_return_true_if_ok( 241 | fmi2GetReal_(c, vr.data(), vr.size(), ref.data())); 242 | } 243 | 244 | bool fmi2_library::read_string( 245 | fmi2Component c, 246 | fmi2ValueReference vr, 247 | fmi2String& ref) 248 | { 249 | return update_status_and_return_true_if_ok( 250 | fmi2GetString_(c, &vr, 1, &ref)); 251 | } 252 | 253 | bool fmi2_library::read_string( 254 | fmi2Component c, 255 | const std::vector& vr, 256 | std::vector& ref) 257 | { 258 | return update_status_and_return_true_if_ok( 259 | fmi2GetString_(c, vr.data(), vr.size(), ref.data())); 260 | } 261 | 262 | bool fmi2_library::read_boolean( 263 | fmi2Component c, 264 | fmi2ValueReference vr, 265 | fmi2Boolean& ref) 266 | { 267 | return update_status_and_return_true_if_ok( 268 | fmi2GetBoolean_(c, &vr, 1, &ref)); 269 | } 270 | 271 | bool fmi2_library::read_boolean( 272 | fmi2Component c, 273 | const std::vector& vr, 274 | std::vector& ref) 275 | { 276 | return update_status_and_return_true_if_ok( 277 | fmi2GetBoolean_(c, vr.data(), vr.size(), ref.data())); 278 | } 279 | 280 | bool fmi2_library::write_integer( 281 | fmi2Component c, 282 | fmi2ValueReference vr, 283 | const fmi2Integer& value) 284 | { 285 | return update_status_and_return_true_if_ok( 286 | fmi2SetInteger_(c, &vr, 1, &value)); 287 | } 288 | 289 | bool fmi2_library::write_integer( 290 | fmi2Component c, 291 | const std::vector& vr, 292 | const std::vector& values) 293 | { 294 | return update_status_and_return_true_if_ok( 295 | fmi2SetInteger_(c, vr.data(), vr.size(), values.data())); 296 | } 297 | 298 | bool fmi2_library::write_real( 299 | fmi2Component c, 300 | fmi2ValueReference vr, 301 | const fmi2Real& value) 302 | { 303 | return update_status_and_return_true_if_ok( 304 | fmi2SetReal_(c, &vr, 1, &value)); 305 | } 306 | 307 | bool fmi2_library::write_real( 308 | fmi2Component c, 309 | const std::vector& vr, 310 | const std::vector& values) 311 | { 312 | return update_status_and_return_true_if_ok( 313 | fmi2SetReal_(c, vr.data(), vr.size(), values.data())); 314 | } 315 | 316 | bool fmi2_library::write_string( 317 | fmi2Component c, 318 | fmi2ValueReference vr, 319 | fmi2String& value) 320 | { 321 | return update_status_and_return_true_if_ok( 322 | fmi2SetString_(c, &vr, 1, &value)); 323 | } 324 | 325 | bool fmi2_library::write_string( 326 | fmi2Component c, 327 | const std::vector& vr, 328 | const std::vector& values) 329 | { 330 | return update_status_and_return_true_if_ok( 331 | fmi2SetString_(c, vr.data(), vr.size(), values.data())); 332 | } 333 | 334 | bool fmi2_library::write_boolean( 335 | fmi2Component c, 336 | fmi2ValueReference vr, 337 | const fmi2Boolean& value) 338 | { 339 | return update_status_and_return_true_if_ok( 340 | fmi2SetBoolean_(c, &vr, 1, &value)); 341 | } 342 | 343 | bool fmi2_library::write_boolean( 344 | fmi2Component c, 345 | const std::vector& vr, 346 | const std::vector& values) 347 | { 348 | return update_status_and_return_true_if_ok( 349 | fmi2SetBoolean_(c, 350 | vr.data(), 351 | vr.size(), 352 | values.data())); 353 | } 354 | 355 | bool fmi2_library::get_fmu_state( 356 | fmi2Component c, 357 | fmi2FMUstate& state) 358 | { 359 | return update_status_and_return_true_if_ok( 360 | fmi2GetFMUstate_(c, &state)); 361 | } 362 | 363 | bool fmi2_library::set_fmu_state( 364 | fmi2Component c, 365 | fmi2FMUstate state) 366 | { 367 | return update_status_and_return_true_if_ok( 368 | fmi2SetFMUstate_(c, state)); 369 | } 370 | 371 | bool fmi2_library::free_fmu_state( 372 | fmi2Component c, 373 | fmi2FMUstate& state) 374 | { 375 | return update_status_and_return_true_if_ok( 376 | fmi2FreeFMUstate_(c, &state)); 377 | } 378 | 379 | bool fmi4cpp::fmi2::fmi2_library::get_serialized_fmu_state_size( 380 | fmi2Component c, 381 | fmi2FMUstate state, 382 | size_t& size) 383 | { 384 | return update_status_and_return_true_if_ok( 385 | fmi2SerializedFMUstateSize_(c, state, &size)); 386 | } 387 | 388 | bool fmi2_library::serialize_fmu_state( 389 | fmi2Component c, 390 | const fmi2FMUstate& state, 391 | std::vector& serializedState) 392 | { 393 | size_t size = 0; 394 | get_serialized_fmu_state_size(c, state, size); 395 | serializedState.reserve(size); 396 | return update_status_and_return_true_if_ok( 397 | fmi2SerializeFMUstate_(c, 398 | state, 399 | serializedState.data(), 400 | size)); 401 | } 402 | 403 | bool fmi2_library::de_serialize_fmu_state( 404 | fmi2Component c, 405 | fmi2FMUstate& state, 406 | const std::vector& serializedState) 407 | { 408 | return update_status_and_return_true_if_ok( 409 | fmi2DeSerializeFMUstate_(c, 410 | serializedState.data(), 411 | serializedState.size(), 412 | &state)); 413 | } 414 | 415 | bool fmi2_library::get_directional_derivative( 416 | fmi2Component c, 417 | const std::vector& vUnknownRef, 418 | const std::vector& vKnownRef, 419 | const std::vector& dvKnownRef, 420 | std::vector& dvUnknownRef) 421 | { 422 | return update_status_and_return_true_if_ok( 423 | fmi2GetDirectionalDerivative_(c, 424 | vUnknownRef.data(), vUnknownRef.size(), 425 | vKnownRef.data(), vKnownRef.size(), 426 | dvKnownRef.data(), dvUnknownRef.data())); 427 | } 428 | 429 | void fmi2_library::free_instance(fmi2Component c) 430 | { 431 | fmi2FreeInstance_(c); 432 | } 433 | 434 | fmi2_library::~fmi2_library() 435 | { 436 | #ifdef _WIN32 437 | if (dllDirectoryCookie_) { 438 | RemoveDllDirectory(dllDirectoryCookie_); 439 | dllDirectoryCookie_ = nullptr; 440 | } 441 | #endif 442 | 443 | if (handle_) { 444 | if (!free_library(handle_)) { 445 | MLOG_ERROR(getLastError()); 446 | } 447 | handle_ = nullptr; 448 | } 449 | } 450 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/fmu.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using namespace fmi4cpp; 12 | using namespace fmi4cpp::fmi2; 13 | 14 | fmu::fmu(const std::filesystem::path& fmuPath) 15 | { 16 | 17 | if (!exists(fmuPath)) { 18 | const auto err = "No such file '" + absolute(fmuPath).string() + "'!"; 19 | MLOG_FATAL(err); 20 | throw std::runtime_error(err); 21 | } 22 | 23 | const std::string fmuName = fmuPath.stem().string(); 24 | std::filesystem::path tmpPath(std::filesystem::temp_directory_path() /= std::filesystem::path("fmi4cpp_" + fmuName + "_" + generate_simple_id(8))); 25 | 26 | if (!create_directories(tmpPath)) { 27 | const auto err = "Failed to create temporary directory '" + tmpPath.string() + "' !"; 28 | MLOG_FATAL(err); 29 | throw std::runtime_error(err); 30 | } 31 | 32 | MLOG_DEBUG("Created temporary directory '" << tmpPath.string()); 33 | 34 | if (!unzip(fmuPath, tmpPath.string())) { 35 | const auto err = "Failed to extract FMU '" + absolute(fmuPath).string() + "'!"; 36 | MLOG_FATAL(err); 37 | throw std::runtime_error(err); 38 | } 39 | 40 | resource_ = std::make_shared(tmpPath); 41 | modelDescription_ = std::move(parse_model_description(resource_->model_description_path())); 42 | } 43 | 44 | std::string fmu::get_model_description_xml() const 45 | { 46 | return resource_->get_model_description_xml(); 47 | } 48 | 49 | std::shared_ptr fmu::get_model_description() const 50 | { 51 | return modelDescription_; 52 | } 53 | 54 | bool fmu::supports_me() const 55 | { 56 | return modelDescription_->supports_me(); 57 | } 58 | 59 | bool fmu::supports_cs() const 60 | { 61 | return modelDescription_->supports_cs(); 62 | } 63 | 64 | std::unique_ptr fmu::as_cs_fmu() const 65 | { 66 | std::shared_ptr cs = std::move(modelDescription_->as_cs_description()); 67 | return std::make_unique(resource_, cs); 68 | } 69 | 70 | std::unique_ptr fmu::as_me_fmu() const 71 | { 72 | std::shared_ptr me = std::move(modelDescription_->as_me_description()); 73 | return std::make_unique(resource_, me); 74 | } 75 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/me_fmu.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | using namespace fmi4cpp; 8 | using namespace fmi4cpp::fmi2; 9 | 10 | me_fmu::me_fmu(std::shared_ptr resource, 11 | std::shared_ptr md) 12 | : resource_(std::move(resource)) 13 | , modelDescription_(std::move(md)) 14 | {} 15 | 16 | std::string me_fmu::get_model_description_xml() const 17 | { 18 | return resource_->get_model_description_xml(); 19 | } 20 | 21 | std::shared_ptr me_fmu::get_model_description() const 22 | { 23 | return modelDescription_; 24 | } 25 | 26 | std::unique_ptr me_fmu::new_instance(const bool visible, const bool loggingOn) 27 | { 28 | std::shared_ptr lib = nullptr; 29 | auto modelIdentifier = modelDescription_->model_identifier; 30 | if (lib_ == nullptr) { 31 | lib_ = std::make_shared(modelIdentifier, resource_); 32 | } 33 | lib = lib_; 34 | 35 | fmi2Component c = lib->instantiate(modelIdentifier, fmi2ModelExchange, guid(), 36 | resource_->resource_path(), visible, loggingOn); 37 | return std::make_unique(c, resource_, lib, modelDescription_); 38 | } 39 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/me_instance.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace fmi4cpp::fmi2; 6 | 7 | me_instance::me_instance(fmi2Component c, 8 | const std::shared_ptr& resource, 9 | const std::shared_ptr& library, 10 | const std::shared_ptr& modelDescription) 11 | : fmu_instance_base(c, resource, library, modelDescription) 12 | {} 13 | 14 | DLL_HANDLE me_instance::handle() const 15 | { 16 | return library_->handle(); 17 | } 18 | 19 | fmi4cpp::status me_instance::last_status() const 20 | { 21 | return convert(library_->last_status()); 22 | } 23 | 24 | bool me_instance::enter_event_mode() 25 | { 26 | return library_->enter_event_mode(c_); 27 | } 28 | 29 | bool me_instance::enter_continuous_time_mode() 30 | { 31 | return library_->enter_continuous_time_mode(c_); 32 | } 33 | 34 | bool me_instance::set_time(const double time) 35 | { 36 | this->simulationTime_ = time; 37 | return library_->set_time(c_, time); 38 | } 39 | 40 | bool me_instance::set_continuous_states(const std::vector& x) 41 | { 42 | return library_->set_continuous_states(c_, x); 43 | } 44 | 45 | bool me_instance::get_derivatives(std::vector& derivatives) 46 | { 47 | return library_->get_derivatives(c_, derivatives); 48 | } 49 | 50 | bool me_instance::get_event_indicators(std::vector& eventIndicators) 51 | { 52 | return library_->get_event_indicators(c_, eventIndicators); 53 | } 54 | 55 | bool me_instance::get_continuous_states(std::vector& x) 56 | { 57 | return library_->get_continuous_states(c_, x); 58 | } 59 | 60 | bool me_instance::get_nominals_of_continuous_states(std::vector& x_nominal) 61 | { 62 | return library_->get_nominals_of_continuous_states(c_, x_nominal); 63 | } 64 | 65 | bool me_instance::completed_integrator_step( 66 | fmi2Boolean noSetFMUStatePriorToCurrentPoint, 67 | fmi2Boolean& enterEventMode, 68 | fmi2Boolean& terminateSimulation) 69 | { 70 | return library_->completed_integrator_step(c_, 71 | noSetFMUStatePriorToCurrentPoint, 72 | enterEventMode, 73 | terminateSimulation); 74 | } 75 | 76 | bool me_instance::new_discrete_states() 77 | { 78 | return library_->new_discrete_states(c_, eventInfo_); 79 | } 80 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/me_library.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace fmi4cpp; 6 | using namespace fmi4cpp::fmi2; 7 | 8 | me_library::me_library(const std::string& modelIdentifier, 9 | const std::shared_ptr& resource) 10 | : fmi2_library(modelIdentifier, resource) 11 | { 12 | 13 | fmi2EnterEventMode_ = load_function(handle_, "fmi2EnterEventMode"); 14 | fmi2EnterContinuousTimeMode_ = load_function( 15 | handle_, "fmi2EnterContinuousTimeMode"); 16 | fmi2SetTime_ = load_function(handle_, "fmi2SetTime"); 17 | fmi2SetContinuousStates_ = load_function(handle_, "fmi2SetContinuousStates"); 18 | fmi2GetDerivatives_ = load_function(handle_, "fmi2GetDerivatives"); 19 | fmi2GetEventIndicators_ = load_function(handle_, "fmi2GetEventIndicators"); 20 | fmi2GetContinuousStates_ = load_function(handle_, "fmi2GetContinuousStates"); 21 | fmi2GetNominalsOfContinuousStates_ = load_function( 22 | handle_, "fmi2GetNominalsOfContinuousStates"); 23 | fmi2CompletedIntegratorStep_ = load_function(handle_, 24 | "fmi2CompletedIntegratorStep"); 25 | fmi2NewDiscreteStates_ = load_function(handle_, "fmi2NewDiscreteStates"); 26 | } 27 | 28 | bool me_library::enter_event_mode(fmi2Component c) 29 | { 30 | return update_status_and_return_true_if_ok( 31 | fmi2EnterEventMode_(c)); 32 | } 33 | 34 | bool me_library::enter_continuous_time_mode(fmi2Component c) 35 | { 36 | return update_status_and_return_true_if_ok( 37 | fmi2EnterContinuousTimeMode_(c)); 38 | } 39 | 40 | bool me_library::set_time( 41 | fmi2Component c, 42 | double time) 43 | { 44 | return update_status_and_return_true_if_ok( 45 | fmi2SetTime_(c, time)); 46 | } 47 | 48 | bool me_library::set_continuous_states( 49 | fmi2Component c, 50 | const std::vector& x) 51 | { 52 | return update_status_and_return_true_if_ok( 53 | fmi2SetContinuousStates_(c, x.data(), x.size())); 54 | } 55 | 56 | bool me_library::get_derivatives( 57 | fmi2Component c, 58 | std::vector& derivatives) 59 | { 60 | return update_status_and_return_true_if_ok( 61 | fmi2GetDerivatives_(c, derivatives.data(), derivatives.size())); 62 | } 63 | 64 | bool me_library::get_event_indicators( 65 | fmi2Component c, 66 | std::vector& eventIndicators) 67 | { 68 | return update_status_and_return_true_if_ok( 69 | fmi2GetEventIndicators_(c, eventIndicators.data(), eventIndicators.size())); 70 | } 71 | 72 | bool me_library::get_continuous_states( 73 | fmi2Component c, 74 | std::vector& x) 75 | { 76 | return update_status_and_return_true_if_ok( 77 | fmi2GetContinuousStates_(c, x.data(), x.size())); 78 | } 79 | 80 | bool me_library::get_nominals_of_continuous_states( 81 | fmi2Component c, 82 | std::vector& x_nominal) 83 | { 84 | return update_status_and_return_true_if_ok( 85 | fmi2GetNominalsOfContinuousStates_(c, x_nominal.data(), x_nominal.size())); 86 | } 87 | 88 | bool me_library::completed_integrator_step( 89 | fmi2Component c, 90 | fmi2Boolean noSetFMUStatePriorToCurrentPoint, 91 | fmi2Boolean& enterEventMode, 92 | fmi2Boolean& terminateSimulation) 93 | { 94 | return update_status_and_return_true_if_ok( 95 | fmi2CompletedIntegratorStep_(c, noSetFMUStatePriorToCurrentPoint, &enterEventMode, &terminateSimulation)); 96 | } 97 | 98 | bool me_library::new_discrete_states( 99 | fmi2Component c, 100 | fmi2EventInfo& eventInfo) 101 | { 102 | return update_status_and_return_true_if_ok( 103 | fmi2NewDiscreteStates_(c, &eventInfo)); 104 | } 105 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/status_converter.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_FMI2STATUSCONVERTER_HPP 3 | #define FMI4CPP_FMI2STATUSCONVERTER_HPP 4 | 5 | #include 6 | #include 7 | 8 | namespace fmi4cpp::fmi2 9 | { 10 | 11 | inline status convert(fmi2Status status) 12 | { 13 | switch (status) { 14 | case fmi2OK: 15 | return status::OK; 16 | case fmi2Warning: 17 | return status::Warning; 18 | case fmi2Discard: 19 | return status::Discard; 20 | case fmi2Error: 21 | return status::Error; 22 | case fmi2Fatal: 23 | return status::Fatal; 24 | case fmi2Pending: 25 | return status::Pending; 26 | default: 27 | return status::Unknown; 28 | } 29 | } 30 | 31 | } // namespace fmi4cpp::fmi2 32 | 33 | #endif //FMI4CPP_FMI2STATUSCONVERTER_HPP 34 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/xml/enums.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using fmi4cpp::fmi2::causality; 5 | using fmi4cpp::fmi2::initial; 6 | using fmi4cpp::fmi2::variability; 7 | 8 | causality fmi4cpp::fmi2::parse_causality(const std::string& str) 9 | { 10 | if (str == "calculatedParameter") { 11 | return causality::calculatedParameter; 12 | } else if (str == "parameter") { 13 | return causality::parameter; 14 | } else if (str == "input") { 15 | return causality::input; 16 | } else if (str == "output") { 17 | return causality::output; 18 | } else if (str == "independent") { 19 | return causality::independent; 20 | } else { 21 | return causality::local; 22 | } 23 | } 24 | 25 | variability fmi4cpp::fmi2::parse_variability(const std::string& str) 26 | { 27 | if (str == "constant") { 28 | return variability::constant; 29 | } else if (str == "fixed") { 30 | return variability::fixed; 31 | } else if (str == "tunable") { 32 | return variability::tunable; 33 | } else if (str == "discrete") { 34 | return variability::discrete; 35 | } else { 36 | return variability::continuous; 37 | } 38 | } 39 | 40 | initial fmi4cpp::fmi2::parse_initial(const std::string& str) 41 | { 42 | if (str == "exact") { 43 | return initial::exact; 44 | } else if (str == "approx") { 45 | return initial::approx; 46 | } else if (str == "calculated") { 47 | return initial::calculated; 48 | } else { 49 | return initial::unknown; 50 | } 51 | } 52 | 53 | std::string fmi4cpp::fmi2::to_string(causality causality) 54 | { 55 | switch (causality) { 56 | case causality::calculatedParameter: 57 | return "calculatedParameter"; 58 | case causality::parameter: 59 | return "parameter"; 60 | case causality::input: 61 | return "input"; 62 | case causality::output: 63 | return "output"; 64 | case causality::local: 65 | return "local"; 66 | case causality::independent: 67 | return "independent"; 68 | case causality::unknown: 69 | default: 70 | return "unknown"; 71 | } 72 | } 73 | 74 | std::string fmi4cpp::fmi2::to_string(variability variability) 75 | { 76 | switch (variability) { 77 | case variability::constant: 78 | return "constant"; 79 | case variability::fixed: 80 | return "fixed"; 81 | case variability::tunable: 82 | return "tunable"; 83 | case variability::discrete: 84 | return "discrete"; 85 | case variability::continuous: 86 | return "continuous"; 87 | case variability::unknown: 88 | default: 89 | return "unknown"; 90 | } 91 | } 92 | 93 | std::string fmi4cpp::fmi2::to_string(initial initial) 94 | { 95 | switch (initial) { 96 | case initial::exact: 97 | return "exact"; 98 | case initial::approx: 99 | return "approx"; 100 | case initial::calculated: 101 | return "calculated"; 102 | case initial::unknown: 103 | default: 104 | return "unknown"; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/xml/model_description.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace fmi4cpp::fmi2; 9 | 10 | size_t model_description_base::number_of_continuous_states() const 11 | { 12 | return model_structure->derivatives.size(); 13 | } 14 | 15 | const scalar_variable& model_description_base::get_variable_by_name(const std::string& name) const 16 | { 17 | return model_variables->getByName(name); 18 | } 19 | 20 | fmi2ValueReference model_description_base::get_value_reference(const std::string& name) const 21 | { 22 | return model_variables->getByName(name).value_reference; 23 | } 24 | 25 | model_description::model_description( 26 | const model_description_base& base, 27 | std::optional coSimulation, 28 | std::optional modelExchange) 29 | : model_description_base(base) 30 | , coSimulation_(std::move(coSimulation)) 31 | , modelExchange_(std::move(modelExchange)) 32 | {} 33 | 34 | bool model_description::supports_cs() const 35 | { 36 | return coSimulation_.has_value(); 37 | } 38 | 39 | bool model_description::supports_me() const 40 | { 41 | return modelExchange_.has_value(); 42 | } 43 | 44 | std::unique_ptr model_description::as_cs_description() const 45 | { 46 | if (!supports_cs()) { 47 | throw std::runtime_error("CoSimulation not supported!"); 48 | } 49 | return std::make_unique(*this, *coSimulation_); 50 | } 51 | 52 | std::unique_ptr model_description::as_me_description() const 53 | { 54 | if (!supports_me()) { 55 | throw std::runtime_error("ModelExchange not supported!"); 56 | } 57 | return std::make_unique(*this, *modelExchange_); 58 | } 59 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/xml/model_description_parser.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace fmi4cpp::fmi2; 10 | 11 | namespace 12 | { 13 | 14 | void split(std::vector& store, const std::string& target, char c) 15 | { 16 | std::string temp; 17 | std::stringstream ss{target}; 18 | std::vector result; 19 | 20 | while (std::getline(ss, temp, c)) { 21 | store.push_back(temp); 22 | } 23 | } 24 | 25 | 26 | void parse_unknown_dependencies_kind(const std::string& str, std::vector& store) 27 | { 28 | split(store, str, ' '); 29 | } 30 | 31 | template 32 | T parse_attribute(const pugi::xml_node& node, const std::string& name) 33 | { 34 | if constexpr (std::is_same_v) { 35 | return node.attribute(name.c_str()).as_int(); 36 | } else if constexpr (std::is_same_v) { 37 | return node.attribute(name.c_str()).as_uint(); 38 | } else if constexpr (std::is_same_v) { 39 | return node.attribute(name.c_str()).as_double(); 40 | } else if constexpr (std::is_same_v) { 41 | return node.attribute(name.c_str()).as_bool(); 42 | } else if constexpr (std::is_same_v) { 43 | return node.attribute(name.c_str()).as_string(); 44 | } else { 45 | throw std::runtime_error("Unable to parse attribute: " + name); 46 | } 47 | } 48 | 49 | template 50 | std::optional parse_optional_attribute(const pugi::xml_node& node, const std::string& name) 51 | { 52 | if (node.attribute(name.c_str()).empty()) { 53 | return std::nullopt; 54 | } 55 | return parse_attribute(node, name); 56 | } 57 | 58 | 59 | default_experiment parse_default_experiment(const pugi::xml_node& node) 60 | { 61 | default_experiment ex; 62 | ex.startTime = parse_optional_attribute(node, "startTime"); 63 | ex.stopTime = parse_optional_attribute(node, "stopTime"); 64 | ex.stepSize = parse_optional_attribute(node, "stepSize"); 65 | ex.tolerance = parse_optional_attribute(node, "tolerance"); 66 | return ex; 67 | } 68 | 69 | source_file parse_file(const pugi::xml_node& node) 70 | { 71 | source_file file; 72 | file.name = node.attribute("name").as_string(); 73 | return file; 74 | } 75 | 76 | void parse_source_files(const pugi::xml_node& node, source_files& files) 77 | { 78 | for (const pugi::xml_node& v : node) { 79 | if (std::string("File") == v.name()) { 80 | auto file = parse_file(v); 81 | files.push_back(file); 82 | } 83 | } 84 | } 85 | 86 | void parse_unknown_dependencies(const std::string& str, std::vector& store) 87 | { 88 | unsigned int i; 89 | std::stringstream ss(str); 90 | while (ss >> i) { 91 | store.push_back(i); 92 | if (ss.peek() == ',' || ss.peek() == ' ') { 93 | ss.ignore(); 94 | } 95 | } 96 | } 97 | 98 | unknown parse_unknown(const pugi::xml_node& node) 99 | { 100 | 101 | unknown unknown; 102 | unknown.index = node.attribute("index").as_uint(); 103 | 104 | auto optDependencies = parse_optional_attribute(node, "dependencies"); 105 | if (optDependencies) { 106 | std::vector dependencies; 107 | parse_unknown_dependencies(*optDependencies, dependencies); 108 | unknown.dependencies = dependencies; 109 | } 110 | 111 | auto optDependenciesKind = parse_optional_attribute(node, "dependenciesKind"); 112 | if (optDependenciesKind) { 113 | std::vector dependenciesKind; 114 | parse_unknown_dependencies_kind(*optDependenciesKind, dependenciesKind); 115 | unknown.dependencies_kind = dependenciesKind; 116 | } 117 | 118 | return unknown; 119 | } 120 | 121 | void load_unknowns(const pugi::xml_node& node, std::vector& vector) 122 | { 123 | for (const pugi::xml_node& v : node) { 124 | if (std::string("Unknown") == v.name()) { 125 | auto unknown = parse_unknown(v); 126 | vector.push_back(unknown); 127 | } 128 | } 129 | } 130 | 131 | std::unique_ptr parse_model_structure(const pugi::xml_node& node) 132 | { 133 | 134 | std::vector outputs; 135 | std::vector derivatives; 136 | std::vector initial_unknowns; 137 | 138 | for (const pugi::xml_node& v : node) { 139 | if (std::string("Outputs") == v.name()) { 140 | load_unknowns(v, outputs); 141 | } else if (std::string("Derivatives") == v.name()) { 142 | load_unknowns(v, derivatives); 143 | } else if (std::string("InitialUnknowns") == v.name()) { 144 | load_unknowns(v, initial_unknowns); 145 | } 146 | } 147 | 148 | return std::make_unique(outputs, derivatives, initial_unknowns); 149 | } 150 | 151 | base_unit parse_base_unit(const pugi::xml_node& node) 152 | { 153 | base_unit baseUnit; 154 | baseUnit.kg = parse_attribute(node, "kg"); 155 | baseUnit.m = parse_attribute(node, "m"); 156 | baseUnit.s = parse_attribute(node, "s"); 157 | baseUnit.A = parse_attribute(node, "A"); 158 | baseUnit.K = parse_attribute(node, "K"); 159 | baseUnit.mol = parse_attribute(node, "mol"); 160 | baseUnit.cd = parse_attribute(node, "cd"); 161 | baseUnit.rad = parse_attribute(node, "rad"); 162 | baseUnit.factor = parse_attribute(node, "factor"); 163 | baseUnit.offset = parse_attribute(node, "offset"); 164 | 165 | return baseUnit; 166 | } 167 | 168 | display_unit parse_display_unit(const pugi::xml_node& node) 169 | { 170 | display_unit displayUnit; 171 | displayUnit.name = parse_attribute(node, "name"); 172 | displayUnit.factor = parse_attribute(node, "factor"); 173 | displayUnit.offset = parse_attribute(node, "offset"); 174 | 175 | return displayUnit; 176 | } 177 | 178 | unit parse_unit(const pugi::xml_node& node) 179 | { 180 | unit Unit; 181 | for (const pugi::xml_node& v : node) { 182 | if (std::string("BaseUnit") == v.name()) { 183 | Unit.base_unit = parse_base_unit(v); 184 | } else if (std::string("DisplayUnit") == v.name()) { 185 | Unit.display_units.push_back(parse_display_unit(v)); 186 | } 187 | } 188 | Unit.name = parse_attribute(node, "name"); 189 | 190 | return Unit; 191 | } 192 | 193 | unit_definitions parse_unit_definitions(const pugi::xml_node& node) 194 | { 195 | unit_definitions unitDefs; 196 | for (const pugi::xml_node& v : node) { 197 | if (std::string("Unit") == v.name()) { 198 | unitDefs.units.push_back(parse_unit(v)); 199 | } 200 | } 201 | return unitDefs; 202 | } 203 | 204 | fmu_attributes parse_fmu_attributes(const pugi::xml_node& node) 205 | { 206 | 207 | fmu_attributes attributes; 208 | 209 | attributes.model_identifier = node.attribute("modelIdentifier").as_string(); 210 | attributes.needs_execution_tool = node.attribute("needsExecutionTool").as_bool(); 211 | attributes.can_get_and_set_fmu_state = node.attribute("canGetAndSetFMUstate").as_bool(); 212 | attributes.can_serialize_fmu_state = node.attribute("canSerializeFMUstate").as_bool(); 213 | attributes.provides_directional_derivative = node.attribute("providesDirectionalDerivative").as_bool(); 214 | attributes.can_not_use_memory_management_functions = node.attribute("canNotUseMemoryManagementFunctions").as_bool(); 215 | attributes.can_be_instantiated_only_once_per_process = node.attribute("canBeInstantiatedOnlyOncePerProcess").as_bool(); 216 | 217 | for (const pugi::xml_node& v : node) { 218 | if (std::string("SourceFiles") == v.name()) { 219 | parse_source_files(v, attributes.sourceFiles); 220 | } 221 | } 222 | 223 | return attributes; 224 | } 225 | 226 | cs_attributes parse_cs_attributes(const pugi::xml_node& node) 227 | { 228 | cs_attributes attributes(parse_fmu_attributes(node)); 229 | attributes.max_output_derivative_order = node.attribute("maxOutputDerivativeOrder").as_uint(); 230 | attributes.can_interpolate_inputs = node.attribute("canInterpolateInputs").as_bool(); 231 | attributes.can_run_asynchronuously = node.attribute("canRunAsynchronuously").as_bool(); 232 | attributes.can_handle_variable_communication_step_size = node.attribute("canHandleVariableCommunicationStepSize").as_bool(); 233 | return attributes; 234 | } 235 | 236 | me_attributes parse_me_attributes(const pugi::xml_node& node) 237 | { 238 | me_attributes attributes(parse_fmu_attributes(node)); 239 | attributes.completed_integrator_step_not_needed = node.attribute("completedIntegratorStepNotNeeded").as_bool(); 240 | return attributes; 241 | } 242 | 243 | template 244 | scalar_variable_attribute parse_scalar_variable_attributes(const pugi::xml_node& node) 245 | { 246 | scalar_variable_attribute attributes; 247 | attributes.start = parse_attribute(node, "start"); 248 | attributes.declared_type = parse_optional_attribute(node, "declaredType"); 249 | return attributes; 250 | } 251 | 252 | template 253 | bounded_scalar_variable_attribute parse_bounded_scalar_variable_attributes(const pugi::xml_node& node) 254 | { 255 | bounded_scalar_variable_attribute attributes(parse_scalar_variable_attributes(node)); 256 | attributes.min = parse_optional_attribute(node, "min"); 257 | attributes.max = parse_optional_attribute(node, "max"); 258 | attributes.quantity = parse_optional_attribute(node, "quantity"); 259 | return attributes; 260 | } 261 | 262 | integer_attribute parse_integer_attribute(const pugi::xml_node& node) 263 | { 264 | return integer_attribute(parse_bounded_scalar_variable_attributes(node)); 265 | } 266 | 267 | real_attribute parse_real_attribute(const pugi::xml_node& node) 268 | { 269 | real_attribute attributes(parse_bounded_scalar_variable_attributes(node)); 270 | attributes.nominal = parse_optional_attribute(node, "nominal"); 271 | attributes.unit = parse_optional_attribute(node, "unit"); 272 | attributes.derivative = parse_optional_attribute(node, "derivative"); 273 | attributes.reinit = node.attribute("reinit").as_bool(); 274 | attributes.unbounded = node.attribute("(node)); 282 | } 283 | 284 | boolean_attribute parse_boolean_attribute(const pugi::xml_node& node) 285 | { 286 | return boolean_attribute(parse_scalar_variable_attributes(node)); 287 | } 288 | 289 | enumeration_attribute parseEnumerationAttribute(const pugi::xml_node& node) 290 | { 291 | return enumeration_attribute(parse_bounded_scalar_variable_attributes(node)); 292 | } 293 | 294 | 295 | scalar_variable parse_scalar_variable(const pugi::xml_node& node) 296 | { 297 | scalar_variable_base base; 298 | 299 | base.name = node.attribute("name").as_string(); 300 | base.description = node.attribute("description").as_string(); 301 | base.value_reference = node.attribute("valueReference").as_uint(); 302 | base.can_handle_multiple_set_per_time_instant = node.attribute("canHandleMultipleSetPerTimelnstant").as_bool(); 303 | 304 | base.causality = parse_causality(node.attribute("causality").as_string()); 305 | base.variability = parse_variability(node.attribute("variability").as_string()); 306 | base.initial = parse_initial(node.attribute("initial").as_string()); 307 | 308 | for (const pugi::xml_node& v : node) { 309 | if (INTEGER_TYPE == v.name()) { 310 | return {base, parse_integer_attribute(v)}; 311 | } else if (REAL_TYPE == v.name()) { 312 | return {base, parse_real_attribute(v)}; 313 | } else if (STRING_TYPE == v.name()) { 314 | return {base, parse_string_attribute(v)}; 315 | } else if (BOOLEAN_TYPE == v.name()) { 316 | return {base, parse_boolean_attribute(v)}; 317 | } else if (ENUMERATION_TYPE == v.name()) { 318 | return {base, parseEnumerationAttribute(v)}; 319 | } 320 | } 321 | 322 | throw std::runtime_error("FATAL: Failed to parse ScalarVariable!"); 323 | } 324 | 325 | std::unique_ptr parse_model_variables(const pugi::xml_node& node) 326 | { 327 | std::vector variables; 328 | for (const pugi::xml_node& v : node) { 329 | if (std::string("ScalarVariable") == v.name()) { 330 | auto var = parse_scalar_variable(v); 331 | variables.push_back(var); 332 | } 333 | } 334 | return std::make_unique(variables); 335 | } 336 | 337 | } // namespace 338 | 339 | std::unique_ptr fmi4cpp::fmi2::parse_model_description(const std::string& fileName) 340 | { 341 | 342 | pugi::xml_document doc; 343 | pugi::xml_parse_result result = doc.load_file(fileName.c_str()); 344 | if (!result) { 345 | throw std::runtime_error("Unable to parse modelDescription.xml"); 346 | } 347 | auto root = doc.child("fmiModelDescription"); 348 | 349 | model_description_base base; 350 | 351 | base.guid = root.attribute("guid").as_string(); 352 | base.fmi_version = root.attribute("fmiVersion").as_string(); 353 | base.model_name = root.attribute("modelName").as_string(); 354 | base.description = root.attribute("description").as_string(); 355 | base.author = root.attribute("author").as_string(); 356 | base.version = root.attribute("version").as_string(); 357 | base.license = root.attribute("license").as_string(); 358 | base.copyright = root.attribute("copyright").as_string(); 359 | base.generation_tool = root.attribute("generationTool").as_string(); 360 | base.generation_date_and_time = root.attribute("generationDateAndTime").as_string(); 361 | base.number_of_event_indicators = root.attribute("numberOfEventIndicators").as_ullong(); 362 | base.variable_naming_convention = root.attribute("variableNamingConvention").as_string("flat"); 363 | 364 | std::optional coSimulation; 365 | std::optional modelExchange; 366 | 367 | for (const auto& v : root) { 368 | if (std::string("CoSimulation") == v.name()) { 369 | coSimulation = parse_cs_attributes(v); 370 | } else if (std::string("ModelExchange") == v.name()) { 371 | modelExchange = parse_me_attributes(v); 372 | } else if (std::string("DefaultExperiment") == v.name()) { 373 | base.default_experiment = parse_default_experiment(v); 374 | } else if (std::string("ModelVariables") == v.name()) { 375 | base.model_variables = std::move(parse_model_variables(v)); 376 | } else if (std::string("ModelStructure") == v.name()) { 377 | base.model_structure = std::move(parse_model_structure(v)); 378 | } else if (std::string("UnitDefinitions") == v.name()) { 379 | base.unit_definitions = std::move(parse_unit_definitions(v)); 380 | } 381 | } 382 | 383 | return std::make_unique(base, coSimulation, modelExchange); 384 | } 385 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/xml/model_variables.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace fmi4cpp::fmi2; 9 | 10 | model_variables::model_variables() = default; 11 | 12 | model_variables::model_variables(std::vector variables) 13 | : variables_(std::move(variables)) 14 | {} 15 | 16 | const scalar_variable& model_variables::getByName(const std::string& name) const 17 | { 18 | for (auto& v : variables_) { 19 | if (v.name == name) { 20 | return v; 21 | } 22 | } 23 | throw std::runtime_error("No such variable with name '" + name + "'!"); 24 | } 25 | 26 | const scalar_variable& model_variables::getByValueReference(const fmi2ValueReference vr) const 27 | { 28 | for (const auto& var : variables_) { 29 | if (var.value_reference == vr) { 30 | return var; 31 | } 32 | } 33 | throw std::runtime_error("No such variable with valueReference '" + std::to_string(vr) + "'!"); 34 | } 35 | 36 | void model_variables::getByValueReference( 37 | const fmi2ValueReference vr, 38 | std::vector& store) const 39 | { 40 | for (const auto& var : variables_) { 41 | if (var.value_reference == vr) { 42 | store.push_back(var); 43 | } 44 | } 45 | } 46 | 47 | void model_variables::getByCausality( 48 | const causality causality, 49 | std::vector& store) const 50 | { 51 | for (const auto& var : variables_) { 52 | if (var.causality == causality) { 53 | store.push_back(var); 54 | } 55 | } 56 | } 57 | 58 | size_t model_variables::size() const 59 | { 60 | return variables_.size(); 61 | } 62 | 63 | const scalar_variable& model_variables::operator[](const size_t index) const 64 | { 65 | return variables_[index]; 66 | } 67 | 68 | std::vector::const_iterator model_variables::begin() const 69 | { 70 | return variables_.begin(); 71 | } 72 | 73 | std::vector::const_iterator model_variables::end() const 74 | { 75 | return variables_.end(); 76 | } 77 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmi2/xml/scalar_variable.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace fmi4cpp; 6 | using namespace fmi4cpp::fmi2; 7 | 8 | scalar_variable::scalar_variable( 9 | const scalar_variable_base& base, 10 | const integer_attribute& integer) 11 | : scalar_variable_base(base) 12 | , integer_(integer) 13 | {} 14 | 15 | scalar_variable::scalar_variable( 16 | const scalar_variable_base& base, 17 | const real_attribute& real) 18 | : scalar_variable_base(base) 19 | , real_(real) 20 | {} 21 | 22 | scalar_variable::scalar_variable( 23 | const scalar_variable_base& base, 24 | const string_attribute& string) 25 | : scalar_variable_base(base) 26 | , string_(string) 27 | {} 28 | 29 | scalar_variable::scalar_variable( 30 | const scalar_variable_base& base, 31 | const boolean_attribute& boolean) 32 | : scalar_variable_base(base) 33 | , boolean_(boolean) 34 | {} 35 | 36 | scalar_variable::scalar_variable( 37 | const scalar_variable_base& base, 38 | const enumeration_attribute& enumeration) 39 | : scalar_variable_base(base) 40 | , enumeration_(enumeration) 41 | {} 42 | 43 | 44 | bool scalar_variable::is_integer() const 45 | { 46 | return integer_.has_value(); 47 | } 48 | 49 | bool scalar_variable::is_real() const 50 | { 51 | return real_.has_value(); 52 | } 53 | 54 | bool scalar_variable::is_string() const 55 | { 56 | return string_.has_value(); 57 | } 58 | 59 | bool scalar_variable::is_boolean() const 60 | { 61 | return boolean_.has_value(); 62 | } 63 | 64 | bool scalar_variable::is_enumeration() const 65 | { 66 | return enumeration_.has_value(); 67 | } 68 | 69 | integer_variable scalar_variable::as_integer() const 70 | { 71 | return integer_variable(*this, *integer_); 72 | } 73 | 74 | real_variable scalar_variable::as_real() const 75 | { 76 | return real_variable(*this, *real_); 77 | } 78 | 79 | string_variable scalar_variable::as_string() const 80 | { 81 | return string_variable(*this, *string_); 82 | } 83 | 84 | boolean_variable scalar_variable::as_boolean() const 85 | { 86 | return boolean_variable(*this, *boolean_); 87 | } 88 | 89 | enumeration_variable scalar_variable::as_enumeration() const 90 | { 91 | return enumeration_variable(*this, *enumeration_); 92 | } 93 | 94 | std::string scalar_variable::type_name() const 95 | { 96 | if (integer_) { 97 | return INTEGER_TYPE; 98 | } else if (real_) { 99 | return REAL_TYPE; 100 | } else if (string_) { 101 | return STRING_TYPE; 102 | } else if (boolean_) { 103 | return BOOLEAN_TYPE; 104 | } else if (enumeration_) { 105 | return ENUMERATION_TYPE; 106 | } else { 107 | return UNKNOWN_TYPE; 108 | } 109 | } 110 | 111 | 112 | integer_variable::integer_variable( 113 | const scalar_variable& variable, 114 | const integer_attribute& attribute) 115 | : bounded_scalar_variable(variable, attribute) 116 | {} 117 | 118 | 119 | real_variable::real_variable( 120 | const scalar_variable& variable, 121 | const real_attribute& attribute) 122 | : bounded_scalar_variable(variable, attribute) 123 | {} 124 | 125 | std::optional real_variable::displayUnit() const 126 | { 127 | return attribute_.display_unit; 128 | } 129 | 130 | std::optional real_variable::unit() const 131 | { 132 | return attribute_.unit; 133 | } 134 | 135 | std::optional real_variable::derivative() const 136 | { 137 | return attribute_.derivative; 138 | } 139 | 140 | std::optional real_variable::nominal() const 141 | { 142 | return attribute_.nominal; 143 | } 144 | 145 | bool real_variable::relativeQuantity() const 146 | { 147 | return attribute_.relative_quantity; 148 | } 149 | 150 | bool real_variable::unbounded() const 151 | { 152 | return attribute_.unbounded; 153 | } 154 | 155 | bool real_variable::reinit() const 156 | { 157 | return attribute_.reinit; 158 | } 159 | 160 | 161 | string_variable::string_variable( 162 | const scalar_variable& variable, 163 | const string_attribute& attribute) 164 | : typed_scalar_variable(variable, attribute) 165 | {} 166 | 167 | 168 | boolean_variable::boolean_variable( 169 | const scalar_variable& variable, 170 | const boolean_attribute& attribute) 171 | : typed_scalar_variable(variable, attribute) 172 | {} 173 | 174 | 175 | enumeration_variable::enumeration_variable( 176 | const scalar_variable& variable, 177 | const enumeration_attribute& attribute) 178 | : typed_scalar_variable(variable, attribute) 179 | {} 180 | 181 | 182 | integer_attribute::integer_attribute(const bounded_scalar_variable_attribute& attributes) 183 | : bounded_scalar_variable_attribute(attributes) 184 | {} 185 | 186 | 187 | real_attribute::real_attribute(const bounded_scalar_variable_attribute& attributes) 188 | : bounded_scalar_variable_attribute(attributes) 189 | {} 190 | 191 | 192 | string_attribute::string_attribute(const scalar_variable_attribute& attributes) 193 | : scalar_variable_attribute(attributes) 194 | {} 195 | 196 | 197 | boolean_attribute::boolean_attribute(const scalar_variable_attribute& attributes) 198 | : scalar_variable_attribute(attributes) 199 | {} 200 | 201 | 202 | enumeration_attribute::enumeration_attribute(const bounded_scalar_variable_attribute& attributes) 203 | : bounded_scalar_variable_attribute(attributes) 204 | {} 205 | -------------------------------------------------------------------------------- /src/fmi4cpp/fmu_resource.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace fmi4cpp; 11 | 12 | fmu_resource::fmu_resource(std::filesystem::path path) 13 | : path_(std::move(path)) 14 | {} 15 | 16 | std::string fmu_resource::model_description_path() const 17 | { 18 | return path_.string() + "/modelDescription.xml"; 19 | } 20 | 21 | std::string fmu_resource::resource_path() const 22 | { 23 | return "file:///" + path_.string() + "/resources/"; 24 | } 25 | 26 | std::string fmu_resource::absolute_library_path(const std::string& modelIdentifier) const 27 | { 28 | return path_.string() + "/binaries/" + get_os() + "/" + modelIdentifier + get_shared_library_extension(); 29 | } 30 | 31 | std::string fmu_resource::get_model_description_xml() const 32 | { 33 | std::ifstream stream(model_description_path()); 34 | return std::string((std::istreambuf_iterator(stream)), std::istreambuf_iterator()); 35 | } 36 | 37 | fmu_resource::~fmu_resource() 38 | { 39 | std::error_code success; 40 | remove_all(path_, success); 41 | 42 | if (!success) { 43 | MLOG_DEBUG("Deleted temporal folder '" + path_.string() + "'"); 44 | } else { 45 | MLOG_DEBUG("Unable to delete temporal folder '" + path_.string() + "'"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/fmi4cpp/library_helper.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FMI4CPP_LIBRARYHELPER_HPP 2 | #define FMI4CPP_LIBRARYHELPER_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace fmi4cpp 8 | { 9 | 10 | inline DLL_HANDLE load_library(const std::string& libName) 11 | { 12 | #ifdef WIN32 13 | return LoadLibrary(libName.c_str()); 14 | #else 15 | return dlopen(libName.c_str(), RTLD_NOW | RTLD_LOCAL); 16 | #endif 17 | } 18 | 19 | template 20 | T load_function(DLL_HANDLE handle, const char* function_name) 21 | { 22 | #ifdef WIN32 23 | return (T)GetProcAddress(handle, function_name); 24 | #else 25 | return (T)dlsym(handle, function_name); 26 | #endif 27 | } 28 | 29 | inline bool free_library(DLL_HANDLE handle) 30 | { 31 | #ifdef WIN32 32 | return static_cast(FreeLibrary(handle)); 33 | #else 34 | return (dlclose(handle) == 0); 35 | #endif 36 | } 37 | 38 | inline std::string getLastError() 39 | { 40 | #ifdef WIN32 41 | std::ostringstream os; 42 | os << GetLastError(); 43 | return os.str(); 44 | #else 45 | return dlerror(); 46 | #endif 47 | } 48 | 49 | } // namespace 50 | 51 | #endif //FMI4CPP_LIBRARYHELPER_HPP 52 | -------------------------------------------------------------------------------- /src/fmi4cpp/mlog.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MLOG_HPP 3 | #define MLOG_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace 11 | { 12 | 13 | #ifndef LOG_LEVEL_OFF 14 | 15 | enum mlog_level 16 | { 17 | Trace = 0, 18 | Debug = 1, 19 | Info = 2, 20 | Warn = 3, 21 | Error = 4, 22 | Fatal = 5 23 | }; 24 | 25 | const char* to_string(mlog_level lvl) 26 | { 27 | switch (lvl) { 28 | case Trace: return "Trace"; 29 | case Debug: return "Debug"; 30 | case Info: return "Info"; 31 | case Warn: return "Warn"; 32 | case Error: return "Error"; 33 | case Fatal: return "Fatal"; 34 | default: return nullptr; 35 | } 36 | } 37 | 38 | # if MLOG_LEVEL_TRACE 39 | mlog_level M_LOG_LEVEL = Trace; 40 | # elif MLOG_LEVEL_DEBUG 41 | mlog_level M_LOG_LEVEL = Debug; 42 | # elif MLOG_LEVEL_INFO 43 | mlog_level M_LOG_LEVEL = Info; 44 | # elif MLOG_LEVEL_WARN 45 | mlog_level M_LOG_LEVEL = Warn; 46 | # elif MLOG_LEVEL_ERROR 47 | mlog_level M_LOG_LEVEL = Error; 48 | # elif MLOG_LEVEL_FATAL 49 | mlog_level M_LOG_LEVEL = Fatal; 50 | # else 51 | mlog_level M_LOG_LEVEL = Info; 52 | # endif 53 | 54 | # define MLOG_TRACE(msg) _MLOG_(msg, Trace) 55 | # define MLOG_DEBUG(msg) _MLOG_(msg, Debug) 56 | # define MLOG_INFO(msg) _MLOG_(msg, Info) 57 | # define MLOG_WARN(msg) _MLOG_(msg, Warn) 58 | # define MLOG_ERROR(msg) _MLOG_(msg, Error) 59 | # define MLOG_FATAL(msg) _MLOG_(msg, Fatal) 60 | 61 | # define _MLOG_(msg, level) \ 62 | { \ 63 | if (level >= M_LOG_LEVEL) { \ 64 | auto time_now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); \ 65 | __MLOG__("[" << to_string(level) << "] [" << std::ctime(&time_now) << "] " << __FILE__ << ":" << __LINE__ << ": " << msg, level); \ 66 | } \ 67 | } 68 | 69 | # define __MLOG__(msg, level) \ 70 | { \ 71 | if (level > Warn) { \ 72 | std::cerr << msg << std::endl; \ 73 | } else { \ 74 | std::cout << msg << std::endl; \ 75 | } \ 76 | } 77 | 78 | #else 79 | 80 | # define MLOG_TRACE(msg) 81 | # define MLOG_DEBUG(msg) 82 | # define MLOG_INFO(msg) 83 | # define MLOG_WARN(msg) 84 | # define MLOG_ERROR(msg) 85 | # define MLOG_FATAL(msg) 86 | 87 | #endif 88 | 89 | } // namespace 90 | 91 | #endif //MLOG_HPP 92 | -------------------------------------------------------------------------------- /src/fmi4cpp/tools/os_util.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_OS_UTIL_HPP 3 | #define FMI4CPP_OS_UTIL_HPP 4 | 5 | #include 6 | 7 | namespace 8 | { 9 | 10 | std::string get_os() 11 | { 12 | #if _WIN32 || _WIN64 13 | # if _WIN64 14 | return "win64"; 15 | # else 16 | return "win32"; 17 | # endif 18 | #elif __linux__ 19 | return "linux64"; 20 | #endif 21 | } 22 | 23 | std::string get_shared_library_extension() 24 | { 25 | #if _WIN32 26 | return ".dll"; 27 | #elif __linux__ 28 | return ".so"; 29 | #endif 30 | } 31 | } // namespace 32 | 33 | #endif //FMI4CPP_OS_UTIL_HPP 34 | -------------------------------------------------------------------------------- /src/fmi4cpp/tools/simple_id.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FMI4CPP_SIMPLE_ID_HPP 3 | #define FMI4CPP_SIMPLE_ID_HPP 4 | 5 | #include 6 | #include 7 | 8 | namespace 9 | { 10 | 11 | std::random_device rd; 12 | std::mt19937 mt(rd()); 13 | std::uniform_int_distribution dist(0, 9); 14 | 15 | std::string generate_simple_id(const unsigned int len) 16 | { 17 | std::string id; 18 | for (unsigned int i = 0; i < len; i++) { 19 | id += std::to_string(dist(mt)); 20 | } 21 | return id; 22 | } 23 | 24 | } // namespace 25 | 26 | #endif //FMI4CPP_SIMPLE_ID_HPP 27 | -------------------------------------------------------------------------------- /src/fmi4cpp/tools/unzipper.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "fmi4cpp/tools/unzipper.hpp" 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | bool fmi4cpp::unzip(const std::filesystem::path& zip_file, const std::filesystem::path& tmp_path) 11 | { 12 | int* err = nullptr; 13 | zip* za = zip_open(absolute(zip_file).string().c_str(), 0, err); 14 | if (za == nullptr) { 15 | return false; 16 | } 17 | 18 | struct zip_file* zf; 19 | // clang-format off 20 | struct zip_stat sb{}; 21 | // clang-format on 22 | 23 | constexpr int bufferSize = 1000; 24 | std::vector contents(bufferSize); 25 | for (int i = 0; i < zip_get_num_entries(za, 0); i++) { 26 | if (zip_stat_index(za, i, 0, &sb) == 0) { 27 | 28 | const std::filesystem::path newFile = tmp_path / sb.name; 29 | 30 | if (sb.size == 0) { 31 | create_directories(newFile); 32 | } else { 33 | const auto containingDirectory = newFile.parent_path(); 34 | if (!exists(containingDirectory) && !create_directories(containingDirectory)) { 35 | return false; 36 | } 37 | zf = zip_fopen_index(za, i, 0); 38 | 39 | std::ofstream file; 40 | file.open(newFile, std::ios::out | std::ios::binary); 41 | 42 | zip_int64_t sum = 0; 43 | while (sum != sb.size) { 44 | zip_int64_t len = zip_fread(zf, contents.data(), bufferSize); 45 | file.write(contents.data(), len); 46 | sum += len; 47 | } 48 | 49 | file.flush(); 50 | file.close(); 51 | 52 | zip_fclose(zf); 53 | } 54 | } 55 | } 56 | zip_close(za); 57 | 58 | return true; 59 | } 60 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(test_controlled_temperature test_controlled_temperature.cpp) 3 | target_link_libraries(test_controlled_temperature PRIVATE fmi4cpp::fmi4cpp Catch2::Catch2) 4 | add_test(NAME test_controlled_temperature COMMAND test_controlled_temperature) 5 | 6 | add_executable(test_model_description1 test_modeldescription1.cpp) 7 | target_link_libraries(test_model_description1 PRIVATE fmi4cpp::fmi4cpp Catch2::Catch2) 8 | add_test(NAME test_model_description1 COMMAND test_model_description1) 9 | 10 | add_executable(test_model_description2 test_modeldescription2.cpp) 11 | target_link_libraries(test_model_description2 PRIVATE fmi4cpp::fmi4cpp Catch2::Catch2) 12 | add_test(NAME test_model_description2 COMMAND test_model_description2) 13 | -------------------------------------------------------------------------------- /tests/test_controlled_temperature.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define CATCH_CONFIG_MAIN 5 | #include 6 | 7 | #include 8 | 9 | using namespace fmi4cpp; 10 | 11 | const double step_size = 1E-4; 12 | const fmi2ValueReference vr = 46; 13 | 14 | TEST_CASE("ControlledTemperature_test1") 15 | { 16 | const std::string fmu_path = "../resources/fmus/2.0/cs/20sim/4.6.4.8004/" 17 | "ControlledTemperature/ControlledTemperature.fmu"; 18 | 19 | auto fmu = fmi2::fmu(fmu_path).as_cs_fmu(); 20 | 21 | size_t numOutputs = 0; 22 | for (const auto& v : *fmu->get_model_description()->model_variables) { 23 | if (v.causality == fmi2::causality::output) { 24 | numOutputs++; 25 | } 26 | } 27 | CHECK(2 == numOutputs); 28 | 29 | auto slave = fmu->new_instance(); 30 | CHECK(slave->setup_experiment()); 31 | CHECK(slave->enter_initialization_mode()); 32 | CHECK(slave->exit_initialization_mode()); 33 | 34 | double ref; 35 | CHECK(slave->step(step_size)); 36 | CHECK(slave->read_real(vr, ref)); 37 | 38 | CHECK(298.15 == Approx(ref)); 39 | 40 | CHECK(slave->terminate()); 41 | } -------------------------------------------------------------------------------- /tests/test_modeldescription1.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define CATCH_CONFIG_MAIN 5 | #include 6 | 7 | #include 8 | 9 | using namespace fmi4cpp; 10 | 11 | 12 | TEST_CASE("ControlledTemperature_test1") 13 | { 14 | const std::string fmu_path = "../resources/fmus/2.0/cs/20sim/4.6.4.8004/" 15 | "ControlledTemperature/modelDescription.xml"; 16 | 17 | 18 | auto md = fmi2::parse_model_description(fmu_path); 19 | auto md_cs = md->as_cs_description(); 20 | 21 | CHECK("2.0" == md->fmi_version); 22 | CHECK("ControlledTemperature" == md->model_name); 23 | 24 | CHECK("{06c2700b-b39c-4895-9151-304ddde28443}" == md->guid); 25 | CHECK("{06c2700b-b39c-4895-9151-304ddde28443}" == md_cs->guid); 26 | CHECK("20-sim" == *md->generation_tool); 27 | CHECK("20-sim" == *md_cs->generation_tool); 28 | 29 | CHECK(md->supports_cs()); 30 | CHECK(!md->supports_me()); 31 | 32 | CHECK(120 == md->model_variables->size()); 33 | CHECK(120 == md_cs->model_variables->size()); 34 | 35 | const fmi2::real_variable& heatCapacity1 = md->get_variable_by_name("HeatCapacity1.T0").as_real(); 36 | CHECK(1 == heatCapacity1.valueReference()); 37 | CHECK(!heatCapacity1.get_min().has_value()); 38 | CHECK(!heatCapacity1.get_max().has_value()); 39 | CHECK(heatCapacity1.start().has_value()); 40 | CHECK(298.0 == Approx(heatCapacity1.start().value())); 41 | CHECK("starting temperature" == heatCapacity1.description()); 42 | CHECK(!heatCapacity1.quantity().has_value()); 43 | 44 | auto& thermalConductor = md->model_variables->getByValueReference(12); 45 | CHECK("TemperatureSource.T" == thermalConductor.name); 46 | CHECK(fmi2::variability::tunable == thermalConductor.variability); 47 | CHECK(fmi2::causality::parameter == thermalConductor.causality); 48 | 49 | fmi2::source_files sourceFiles = md_cs->sourceFiles; 50 | CHECK(10 == sourceFiles.size()); 51 | CHECK("EulerAngles.c" == sourceFiles[0].name); 52 | 53 | std::vector modelStructureOutputs = md->model_structure->outputs; 54 | CHECK(2 == modelStructureOutputs.size()); 55 | CHECK(115 == modelStructureOutputs[0].index); 56 | CHECK(116 == modelStructureOutputs[1].index); 57 | 58 | std::optional de = md->default_experiment; 59 | CHECK(de.has_value()); 60 | CHECK(0.0 == Approx(*de->startTime)); 61 | CHECK(20.0 == Approx(*de->stopTime)); 62 | CHECK(1E-4 == Approx(*de->stepSize)); 63 | CHECK(!de->tolerance.has_value()); 64 | 65 | size_t count = 0; 66 | auto mv = md->model_variables; 67 | for (const auto& v : *mv) { 68 | if (v.causality == fmi2::causality::output) { 69 | count++; 70 | } 71 | } 72 | CHECK(2 == count); 73 | 74 | std::vector outputs = {}; 75 | md->model_variables->getByCausality(fmi2::causality::output, outputs); 76 | 77 | CHECK(count == outputs.size()); 78 | } -------------------------------------------------------------------------------- /tests/test_modeldescription2.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define CATCH_CONFIG_MAIN 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using namespace fmi4cpp::fmi2; 11 | 12 | TEST_CASE("FmuExportCrossCompile_test1") 13 | { 14 | 15 | const std::string fmu_path = "../resources/fmus/2.0/cs/OpenModelica/v1.11.0/" 16 | "FmuExportCrossCompile/modelDescription.xml"; 17 | 18 | auto md = parse_model_description(fmu_path); 19 | 20 | CHECK("structured" == md->variable_naming_convention.value()); 21 | 22 | std::vector derivatives = md->model_structure->derivatives; 23 | CHECK(2 == derivatives.size()); 24 | 25 | CHECK(3 == derivatives[0].index); 26 | CHECK(4 == derivatives[1].index); 27 | 28 | CHECK(true == derivatives[0].dependencies.has_value()); 29 | CHECK(2 == derivatives[0].dependencies.value()[0]); 30 | REQUIRE(derivatives[0].dependencies_kind); 31 | REQUIRE(1 == derivatives[0].dependencies_kind.value().size()); 32 | CHECK("dependent" == derivatives[0].dependencies_kind.value()[0]); 33 | } 34 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", 3 | "name": "fmi4cpp", 4 | "dependencies": [ 5 | "pugixml", 6 | "libzip" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 0.8.4 --------------------------------------------------------------------------------