pythonfmu3 0.2.2__py3-none-any.whl → 0.2.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pythonfmu3 might be problematic. Click here for more details.

Files changed (199) hide show
  1. pythonfmu3/__init__.py +8 -8
  2. pythonfmu3/__main__.py +52 -52
  3. pythonfmu3/_version.py +1 -1
  4. pythonfmu3/builder.py +260 -260
  5. pythonfmu3/default_experiment.py +7 -7
  6. pythonfmu3/deploy.py +118 -118
  7. pythonfmu3/enums.py +48 -48
  8. pythonfmu3/fmi3slave.py +438 -438
  9. pythonfmu3/logmsg.py +14 -14
  10. pythonfmu3/osutil.py +22 -22
  11. pythonfmu3/pythonfmu-export/.clang-format +35 -35
  12. pythonfmu3/pythonfmu-export/CMakeLists.txt +59 -59
  13. pythonfmu3/pythonfmu-export/build/ALL_BUILD.vcxproj +184 -0
  14. pythonfmu3/pythonfmu-export/build/ALL_BUILD.vcxproj.filters +8 -0
  15. pythonfmu3/pythonfmu-export/build/CMakeCache.txt +369 -0
  16. pythonfmu3/pythonfmu-export/build/CMakeFiles/0ee4db0675778dfba98c7160896d5a45/generate.stamp.rule +1 -0
  17. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CMakeCCompiler.cmake +72 -0
  18. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CMakeCXXCompiler.cmake +83 -0
  19. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CMakeDetermineCompilerABI_C.bin +0 -0
  20. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CMakeDetermineCompilerABI_CXX.bin +0 -0
  21. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CMakeRCCompiler.cmake +6 -0
  22. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CMakeSystem.cmake +15 -0
  23. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/CMakeCCompilerId.c +838 -0
  24. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/CompilerIdC.exe +0 -0
  25. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/CompilerIdC.vcxproj +71 -0
  26. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CMakeCCompilerId.obj +0 -0
  27. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.exe.recipe +11 -0
  28. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.tlog/CL.command.1.tlog +0 -0
  29. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.tlog/CL.read.1.tlog +0 -0
  30. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.tlog/CL.write.1.tlog +0 -0
  31. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.tlog/CompilerIdC.lastbuildstate +2 -0
  32. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.tlog/link.command.1.tlog +0 -0
  33. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.tlog/link.read.1.tlog +0 -0
  34. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdC/Debug/CompilerIdC.tlog/link.write.1.tlog +0 -0
  35. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/CMakeCXXCompilerId.cpp +826 -0
  36. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/CompilerIdCXX.exe +0 -0
  37. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/CompilerIdCXX.vcxproj +71 -0
  38. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj +0 -0
  39. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.exe.recipe +11 -0
  40. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.command.1.tlog +0 -0
  41. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.read.1.tlog +0 -0
  42. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.write.1.tlog +0 -0
  43. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CompilerIdCXX.lastbuildstate +2 -0
  44. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.command.1.tlog +0 -0
  45. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.read.1.tlog +0 -0
  46. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.write.1.tlog +0 -0
  47. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/VCTargetsPath.txt +1 -0
  48. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/VCTargetsPath.vcxproj +31 -0
  49. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/x64/Debug/VCTargetsPath.recipe +11 -0
  50. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.24.0/x64/Debug/VCTargetsPath.tlog/VCTargetsPath.lastbuildstate +2 -0
  51. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CMakeCCompiler.cmake +81 -0
  52. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CMakeCXXCompiler.cmake +101 -0
  53. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CMakeDetermineCompilerABI_C.bin +0 -0
  54. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  55. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CMakeRCCompiler.cmake +6 -0
  56. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CMakeSystem.cmake +15 -0
  57. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/CMakeCCompilerId.c +904 -0
  58. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/CompilerIdC.exe +0 -0
  59. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/CompilerIdC.vcxproj +72 -0
  60. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CMakeCCompilerId.obj +0 -0
  61. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.exe.recipe +11 -0
  62. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.tlog/CL.command.1.tlog +0 -0
  63. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.tlog/CL.read.1.tlog +0 -0
  64. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.tlog/CL.write.1.tlog +0 -0
  65. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.tlog/CompilerIdC.lastbuildstate +2 -0
  66. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.tlog/link.command.1.tlog +0 -0
  67. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.tlog/link.read.1.tlog +0 -0
  68. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdC/Debug/CompilerIdC.tlog/link.write.1.tlog +0 -0
  69. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +919 -0
  70. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/CompilerIdCXX.exe +0 -0
  71. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/CompilerIdCXX.vcxproj +72 -0
  72. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj +0 -0
  73. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.exe.recipe +11 -0
  74. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.command.1.tlog +0 -0
  75. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.read.1.tlog +0 -0
  76. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.write.1.tlog +0 -0
  77. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CompilerIdCXX.lastbuildstate +2 -0
  78. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.command.1.tlog +0 -0
  79. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.read.1.tlog +0 -0
  80. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.write.1.tlog +0 -0
  81. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/VCTargetsPath.txt +1 -0
  82. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/VCTargetsPath.vcxproj +31 -0
  83. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/x64/Debug/VCTargetsPath.recipe +11 -0
  84. pythonfmu3/pythonfmu-export/build/CMakeFiles/3.30.2/x64/Debug/VCTargetsPath.tlog/VCTargetsPath.lastbuildstate +2 -0
  85. pythonfmu3/pythonfmu-export/build/CMakeFiles/CMakeConfigureLog.yaml +568 -0
  86. pythonfmu3/pythonfmu-export/build/CMakeFiles/CMakeOutput.log +357 -0
  87. pythonfmu3/pythonfmu-export/build/CMakeFiles/TargetDirectories.txt +3 -0
  88. pythonfmu3/pythonfmu-export/build/CMakeFiles/cmake.check_cache +1 -0
  89. pythonfmu3/pythonfmu-export/build/CMakeFiles/generate.stamp +1 -0
  90. pythonfmu3/pythonfmu-export/build/CMakeFiles/generate.stamp.depend +28 -0
  91. pythonfmu3/pythonfmu-export/build/CMakeFiles/generate.stamp.list +2 -0
  92. pythonfmu3/pythonfmu-export/build/ZERO_CHECK.vcxproj +174 -0
  93. pythonfmu3/pythonfmu-export/build/ZERO_CHECK.vcxproj.filters +13 -0
  94. pythonfmu3/pythonfmu-export/build/cmake_install.cmake +50 -0
  95. pythonfmu3/pythonfmu-export/build/install_manifest.txt +0 -0
  96. pythonfmu3/pythonfmu-export/build/pythonfmu-export.sln +53 -0
  97. pythonfmu3/pythonfmu-export/build/src/CMakeFiles/generate.stamp +1 -0
  98. pythonfmu3/pythonfmu-export/build/src/CMakeFiles/generate.stamp.depend +2 -0
  99. pythonfmu3/pythonfmu-export/build/src/Debug/pythonfmu-export.pdb +0 -0
  100. pythonfmu3/pythonfmu-export/build/src/Release/pythonfmu-export.exp +0 -0
  101. pythonfmu3/pythonfmu-export/build/src/Release/pythonfmu-export.lib +0 -0
  102. pythonfmu3/pythonfmu-export/build/src/cmake_install.cmake +34 -0
  103. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/PySlaveInstance.obj +0 -0
  104. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/cppfmu_cs.obj +0 -0
  105. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/exports.def +1885 -0
  106. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/fmi_functions.obj +0 -0
  107. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/objects.txt +3 -0
  108. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/CL.command.1.tlog +0 -0
  109. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/CL.read.1.tlog +0 -0
  110. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/CL.write.1.tlog +0 -0
  111. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/CustomBuild.command.1.tlog +10 -0
  112. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/CustomBuild.read.1.tlog +1 -0
  113. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/CustomBuild.write.1.tlog +2 -0
  114. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/link.command.1.tlog +1 -0
  115. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/link.read.1.tlog +1 -0
  116. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/link.read.3.tlog +1 -0
  117. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/link.write.1.tlog +1 -0
  118. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/pythonfmu-export.lastbuildstate +2 -0
  119. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/pythonfmu-export.tlog/unsuccessfulbuild +0 -0
  120. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Debug/vc142.pdb +0 -0
  121. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/MinSizeRel/objects.txt +3 -0
  122. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/RelWithDebInfo/objects.txt +3 -0
  123. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/PySlaveInstance.obj +0 -0
  124. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/cppfmu_cs.obj +0 -0
  125. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/exports.def +538 -0
  126. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/fmi_functions.obj +0 -0
  127. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/objects.txt +3 -0
  128. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.dll.recipe +14 -0
  129. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/CL.command.1.tlog +0 -0
  130. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/CL.read.1.tlog +0 -0
  131. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/CL.write.1.tlog +0 -0
  132. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/CustomBuild.command.1.tlog +10 -0
  133. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/CustomBuild.read.1.tlog +1 -0
  134. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/CustomBuild.write.1.tlog +2 -0
  135. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/link.command.1.tlog +0 -0
  136. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/link.delete.1.tlog +0 -0
  137. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/link.read.1.tlog +0 -0
  138. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/link.write.1.tlog +0 -0
  139. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/pythonfmu-export.lastbuildstate +2 -0
  140. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.dir/Release/pythonfmu-export.tlog/pythonfmu-export.write.1u.tlog +0 -0
  141. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.vcxproj +414 -0
  142. pythonfmu3/pythonfmu-export/build/src/pythonfmu-export.vcxproj.filters +48 -0
  143. pythonfmu3/pythonfmu-export/build/x64/Debug/ZERO_CHECK/ZERO_CHECK.recipe +11 -0
  144. pythonfmu3/pythonfmu-export/build/x64/Debug/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.command.1.tlog +10 -0
  145. pythonfmu3/pythonfmu-export/build/x64/Debug/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.read.1.tlog +29 -0
  146. pythonfmu3/pythonfmu-export/build/x64/Debug/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.write.1.tlog +3 -0
  147. pythonfmu3/pythonfmu-export/build/x64/Debug/ZERO_CHECK/ZERO_CHECK.tlog/ZERO_CHECK.lastbuildstate +2 -0
  148. pythonfmu3/pythonfmu-export/build/x64/Release/ALL_BUILD/ALL_BUILD.recipe +17 -0
  149. pythonfmu3/pythonfmu-export/build/x64/Release/ALL_BUILD/ALL_BUILD.tlog/ALL_BUILD.lastbuildstate +2 -0
  150. pythonfmu3/pythonfmu-export/build/x64/Release/ALL_BUILD/ALL_BUILD.tlog/CustomBuild.command.1.tlog +10 -0
  151. pythonfmu3/pythonfmu-export/build/x64/Release/ALL_BUILD/ALL_BUILD.tlog/CustomBuild.read.1.tlog +27 -0
  152. pythonfmu3/pythonfmu-export/build/x64/Release/ALL_BUILD/ALL_BUILD.tlog/CustomBuild.write.1.tlog +2 -0
  153. pythonfmu3/pythonfmu-export/build/x64/Release/ZERO_CHECK/ZERO_CHECK.recipe +11 -0
  154. pythonfmu3/pythonfmu-export/build/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.command.1.tlog +10 -0
  155. pythonfmu3/pythonfmu-export/build/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.read.1.tlog +29 -0
  156. pythonfmu3/pythonfmu-export/build/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.write.1.tlog +3 -0
  157. pythonfmu3/pythonfmu-export/build/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/ZERO_CHECK.lastbuildstate +2 -0
  158. pythonfmu3/pythonfmu-export/build_unix.sh +4 -4
  159. pythonfmu3/pythonfmu-export/build_win.sh +4 -4
  160. pythonfmu3/pythonfmu-export/src/CMakeLists.txt +45 -45
  161. pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_common.hpp +161 -161
  162. pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.cpp +192 -192
  163. pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.hpp +185 -185
  164. pythonfmu3/pythonfmu-export/src/cppfmu/fmi_functions.cpp +937 -937
  165. pythonfmu3/pythonfmu-export/src/fmi/fmi3FunctionTypes.h +638 -638
  166. pythonfmu3/pythonfmu-export/src/fmi/fmi3Functions.h +343 -343
  167. pythonfmu3/pythonfmu-export/src/fmi/fmi3PlatformTypes.h +94 -94
  168. pythonfmu3/pythonfmu-export/src/pythonfmu/IPyState.hpp +17 -17
  169. pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp +744 -744
  170. pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp +111 -111
  171. pythonfmu3/pythonfmu-export/src/pythonfmu/PyState.hpp +84 -84
  172. pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so +0 -0
  173. pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll +0 -0
  174. pythonfmu3/resources/binaries/x86_64-windows1/pythonfmu-export.dll +0 -0
  175. pythonfmu3/tests/conftest.py +5 -5
  176. pythonfmu3/tests/data/csvdemo.csv +7 -7
  177. pythonfmu3/tests/slaves/PythonSlaveWithException.py +18 -18
  178. pythonfmu3/tests/slaves/localmodule.py +8 -8
  179. pythonfmu3/tests/slaves/pythonslave.py +52 -52
  180. pythonfmu3/tests/slaves/pythonslave_read_file.py +23 -23
  181. pythonfmu3/tests/slaves/slavewithdep.py +21 -21
  182. pythonfmu3/tests/test_builder.py +195 -195
  183. pythonfmu3/tests/test_deploy.py +48 -48
  184. pythonfmu3/tests/test_fmi3slave.py +152 -152
  185. pythonfmu3/tests/test_integration.py +350 -350
  186. pythonfmu3/tests/test_logger.py +180 -180
  187. pythonfmu3/tests/test_multiple_fmus.py +141 -141
  188. pythonfmu3/tests/test_variables.py +334 -334
  189. pythonfmu3/tests/utils.py +13 -13
  190. pythonfmu3/unit.py +62 -62
  191. pythonfmu3/variable_types.py +101 -101
  192. pythonfmu3/variables.py +400 -400
  193. pythonfmu3-0.2.2.dist-info/LICENSE → pythonfmu3-0.2.2.2.dist-info/LICENSE.txt +23 -23
  194. {pythonfmu3-0.2.2.dist-info → pythonfmu3-0.2.2.2.dist-info}/METADATA +9 -6
  195. pythonfmu3-0.2.2.2.dist-info/RECORD +200 -0
  196. {pythonfmu3-0.2.2.dist-info → pythonfmu3-0.2.2.2.dist-info}/WHEEL +1 -1
  197. {pythonfmu3-0.2.2.dist-info → pythonfmu3-0.2.2.2.dist-info}/entry_points.txt +1 -0
  198. pythonfmu3-0.2.2.dist-info/RECORD +0 -54
  199. {pythonfmu3-0.2.2.dist-info → pythonfmu3-0.2.2.2.dist-info}/top_level.txt +0 -0
pythonfmu3/fmi3slave.py CHANGED
@@ -1,438 +1,438 @@
1
- """Define the abstract facade class."""
2
- import json
3
- import ctypes
4
- import datetime
5
- from abc import ABC, abstractmethod
6
- from collections import OrderedDict, namedtuple
7
- from pathlib import Path
8
- from typing import Any, ClassVar, Dict, List, NamedTuple, Optional
9
- from uuid import uuid1
10
- from xml.etree.ElementTree import Element, SubElement
11
-
12
- from .logmsg import LogMsg
13
- from .default_experiment import DefaultExperiment
14
- from ._version import __version__ as VERSION
15
- from .enums import Fmi3Type, Fmi3Status, Fmi3Causality, Fmi3Initial, Fmi3Variability
16
- from .variables import Boolean, Enumeration, Int32, Int64, UInt64, Float64, ModelVariable, String
17
- from .variable_types import VariableType
18
- from .unit import Unit
19
-
20
- ModelOptions = namedtuple("ModelOptions", ["name", "value", "cli"])
21
-
22
- FMI3_MODEL_OPTIONS: List[ModelOptions] = [
23
- ModelOptions("needsExecutionTool", True, "no-external-tool"),
24
- ModelOptions("canHandleVariableCommunicationStepSize", True, "no-variable-step"),
25
- ModelOptions("canBeInstantiatedOnlyOncePerProcess", False, "only-one-per-process"),
26
- ModelOptions("canGetAndSetFMUState", False, "handle-state"),
27
- ModelOptions("canSerializeFMUState", False, "serialize-state")
28
- ]
29
-
30
- class Fmi3StepResult(NamedTuple):
31
- status: Fmi3Status = Fmi3Status.ok
32
- eventHandlingNeeded: bool = False
33
- terminateSimulation: bool = False
34
- earlyReturn: bool = False
35
-
36
- class Fmi3Slave(ABC):
37
- """Abstract facade class to execute Python through FMI standard."""
38
-
39
- # Dictionary of (category, description) entries
40
- log_categories: Dict[str, str] = {
41
- "logStatusWarning": "Log messages with fmi3Warning status.",
42
- "logStatusDiscard": "Log messages with fmi3Discard status.",
43
- "logStatusError": "Log messages with fmi3Error status.",
44
- "logStatusFatal": "Log messages with fmi3Fatal status.",
45
- "logAll": "Log all messages."
46
- }
47
-
48
- def __init__(self, **kwargs):
49
- self.vars = OrderedDict()
50
- self.instance_name = kwargs["instance_name"]
51
- self.resources = kwargs.get("resources", None)
52
- self.visible = kwargs.get("visible", False)
53
- self.log_queue = []
54
-
55
- self.guid = uuid1()
56
- self.author: Optional[str] = None
57
- self.license: Optional[str] = None
58
- self.version: Optional[str] = None
59
- self.copyright: Optional[str] = None
60
- self.modelName: Optional[str] = self.__class__.__name__
61
- self.description: Optional[str] = None
62
- self.default_experiment: Optional[DefaultExperiment] = None
63
-
64
- self.type_definitions: Dict[str, VariableType] = {}
65
- self.units: Dict[str, Unit] = {}
66
-
67
- def to_xml(self, model_options: Dict[str, str] = dict()) -> Element:
68
- """Build the XML representation of the model.
69
-
70
- Args:
71
- model_options (Dict[str, str]) : FMU model options
72
-
73
- Returns:
74
- (xml.etree.TreeElement.Element) XML description of the FMU
75
- """
76
-
77
- t = datetime.datetime.now(datetime.timezone.utc)
78
- date_str = t.isoformat(timespec="seconds")
79
-
80
- attrib = dict(
81
- fmiVersion="3.0",
82
- modelName=self.modelName,
83
- instantiationToken=f"{self.guid!s}",
84
- generationTool=f"PythonFMU3 {VERSION}",
85
- generationDateAndTime=date_str,
86
- variableNamingConvention="structured"
87
- )
88
- if self.description is not None:
89
- attrib["description"] = self.description
90
- if self.author is not None:
91
- attrib["author"] = self.author
92
- if self.license is not None:
93
- attrib["license"] = self.license
94
- if self.version is not None:
95
- attrib["version"] = self.version
96
- if self.copyright is not None:
97
- attrib["copyright"] = self.copyright
98
-
99
- root = Element("fmiModelDescription", attrib)
100
-
101
- options = dict()
102
- for option in FMI3_MODEL_OPTIONS:
103
- value = model_options.get(option.name, option.value)
104
- options[option.name] = str(value).lower()
105
- options["modelIdentifier"] = self.modelName
106
- options["canNotUseMemoryManagementFunctions"] = "true"
107
-
108
- SubElement(root, "CoSimulation", attrib=options)
109
-
110
- if self.units:
111
- unit_defs = SubElement(root, "UnitDefinitions")
112
- for _, unit in self.units.items():
113
- unit_defs.append(unit.to_xml())
114
-
115
- if self.type_definitions:
116
- type_defs = SubElement(root, "TypeDefinitions")
117
- for _, val in self.type_definitions.items():
118
- type_defs.append(val.to_xml())
119
-
120
- if len(self.log_categories) > 0:
121
- categories = SubElement(root, "LogCategories")
122
- for category, description in self.log_categories.items():
123
- categories.append(
124
- Element(
125
- "Category",
126
- attrib={"name": category, "description": description},
127
- )
128
- )
129
-
130
- if self.default_experiment is not None:
131
- attrib = dict()
132
- if self.default_experiment.start_time is not None:
133
- attrib["startTime"] = str(self.default_experiment.start_time)
134
- if self.default_experiment.stop_time is not None:
135
- attrib["stopTime"] = str(self.default_experiment.stop_time)
136
- if self.default_experiment.step_size is not None:
137
- attrib["stepSize"] = str(self.default_experiment.step_size)
138
- if self.default_experiment.tolerance is not None:
139
- attrib["tolerance"] = str(self.default_experiment.tolerance)
140
- SubElement(root, "DefaultExperiment", attrib)
141
-
142
- variables = SubElement(root, "ModelVariables")
143
- for v in self.vars.values():
144
- if ModelVariable.requires_start(v):
145
- self.__apply_start_value(v)
146
- variables.append(v.to_xml())
147
-
148
- structure = SubElement(root, "ModelStructure")
149
- outputs = list(
150
- filter(lambda v: v.causality == Fmi3Causality.output, self.vars.values())
151
- )
152
-
153
- continuous_state_derivatives = list(
154
- filter(lambda v: v.variability == Fmi3Variability.continuous and (isinstance(v, Float64) and v.derivative is not None), self.vars.values())
155
- )
156
-
157
- allowed_variability = [None, Fmi3Initial.approx, Fmi3Initial.calculated]
158
- initial_unknown = list(
159
- filter(lambda v: (v.causality == Fmi3Causality.output and (v.initial in allowed_variability))
160
- or v.causality == Fmi3Causality.calculatedParameter
161
- or v in continuous_state_derivatives and v.initial in allowed_variability
162
- or v.variability == Fmi3Variability.continuous and v.initial in allowed_variability and v.causality != Fmi3Causality.independent, self.vars.values())
163
- )
164
-
165
- for v in outputs:
166
- SubElement(structure, "Output", attrib=dict(valueReference=str(v.value_reference)))
167
-
168
- for v in continuous_state_derivatives:
169
- SubElement(structure, "ContinuousStateDerivative", attrib=dict(valueReference=str(v.value_reference)))
170
-
171
- for v in initial_unknown:
172
- SubElement(structure, "InitialUnknown", attrib=dict(valueReference=str(v.value_reference)))
173
-
174
-
175
-
176
- return root
177
-
178
- def __apply_start_value(self, var: ModelVariable):
179
- vrs = [var.value_reference]
180
- if isinstance(var, Int32):
181
- refs = self.get_int32(vrs)
182
- elif isinstance(var, (Enumeration, Int64)):
183
- refs = self.get_int64(vrs)
184
- elif isinstance(var, UInt64):
185
- refs = [val.value for val in self.get_uint64(vrs)]
186
- elif isinstance(var, Float64):
187
- refs = self.get_float64(vrs)
188
- elif isinstance(var, Boolean):
189
- refs = self.get_boolean(vrs)
190
- elif isinstance(var, String):
191
- refs = self.get_string(vrs)
192
- else:
193
- raise Exception(f"Unsupported type {type(var)}!")
194
- var.start = refs if len(getattr(var, "dimensions", [])) > 0 else refs[0]
195
-
196
- def register_variable(self, var: ModelVariable, nested: bool = True, var_type: Any = None):
197
- """Register a variable as FMU interface.
198
-
199
- Args:
200
- var (ModelVariable): The variable to be registered
201
- nested (bool): Optional, does the "." in the variable name reflect an object hierarchy to access it? Default True
202
- """
203
- variable_reference = len(self.vars)
204
- self.vars[variable_reference] = var
205
- # Set the unique value reference
206
- var.value_reference = variable_reference
207
- owner = self
208
- if var.getter is None and nested and "." in var.name:
209
- split = var.name.split(".")
210
- split.pop(-1)
211
- for s in split:
212
- owner = getattr(owner, s)
213
- if var.getter is None:
214
- if hasattr(var, "dimensions") and len(var.dimensions) > 0:
215
- var.getter = lambda: getattr(owner, var.local_name).flatten().tolist()
216
- else:
217
- var.getter = lambda: getattr(owner, var.local_name)
218
- if var.setter is None and hasattr(owner, var.local_name) and var.variability != Fmi3Variability.constant:
219
- if hasattr(var, "dimensions") and len(var.dimensions) > 0:
220
- import numpy as np
221
- var.setter = lambda v: setattr(owner, var.local_name, np.reshape(v, newshape=getattr(owner, var.local_name).shape))
222
- else:
223
- var.setter = lambda v: setattr(owner, var.local_name, v)
224
-
225
- if var_type:
226
- self.type_definitions[var_type.name] = var_type
227
- var.declared_type = var_type.name
228
-
229
- def setup_experiment(self, start_time: float):
230
- pass
231
-
232
- def register_units(self, units: List[Unit]):
233
- for unit in units:
234
- self.units[unit.name] = unit
235
-
236
- def enter_initialization_mode(self):
237
- pass
238
-
239
- def exit_initialization_mode(self):
240
- pass
241
-
242
- @abstractmethod
243
- def do_step(self, current_time: float, step_size: float) -> Fmi3StepResult:
244
- pass
245
-
246
- def terminate(self):
247
- pass
248
-
249
- def get_int32(self, vrs: List[int]) -> List[int]:
250
- refs = list()
251
- for vr in vrs:
252
- var = self.vars[vr]
253
- if isinstance(var, Int32):
254
- refs.append(int(var.getter()))
255
- else:
256
- raise TypeError(
257
- f"Variable with valueReference={vr} is not of type Integer!"
258
- )
259
- return refs
260
-
261
- def get_int64(self, vrs: List[int]) -> List[int]:
262
- refs = list()
263
- for vr in vrs:
264
- var = self.vars[vr]
265
- if isinstance(var, (Enumeration, Int64)):
266
- refs.append(int(var.getter()))
267
- else:
268
- raise TypeError(
269
- f"Variable with valueReference={vr} is not of type Int64!"
270
- )
271
- return refs
272
-
273
- def get_uint64(self, vrs: List[int]) -> List[ctypes.c_uint64]:
274
- refs = list()
275
- for vr in vrs:
276
- var = self.vars[vr]
277
- if isinstance(var, UInt64):
278
- val = var.getter()
279
- refs.append(val if isinstance(val, ctypes.c_uint64) else ctypes.c_uint64(val))
280
- else:
281
- raise TypeError(
282
- f"Variable with valueReference={vr} is not of type UInt64!"
283
- )
284
- return refs
285
-
286
- def get_float64(self, vrs: List[int]) -> List[float]:
287
- refs = list()
288
- for vr in vrs:
289
- var = self.vars[vr]
290
- if isinstance(var, Float64):
291
- if len(var.dimensions) == 0:
292
- refs.append(float(var.getter()))
293
- else:
294
- refs.extend(var.getter())
295
- else:
296
- raise TypeError(
297
- f"Variable with valueReference={vr} is not of type Real!"
298
- )
299
- return refs
300
-
301
- def get_boolean(self, vrs: List[int]) -> List[bool]:
302
- refs = list()
303
- for vr in vrs:
304
- var = self.vars[vr]
305
- if isinstance(var, Boolean):
306
- refs.append(bool(var.getter()))
307
- else:
308
- raise TypeError(
309
- f"Variable with valueReference={vr} is not of type Boolean!"
310
- )
311
- return refs
312
-
313
- def get_string(self, vrs: List[int]) -> List[str]:
314
- refs = list()
315
- for vr in vrs:
316
- var = self.vars[vr]
317
- if isinstance(var, String):
318
- refs.append(str(var.getter()))
319
- else:
320
- raise TypeError(
321
- f"Variable with valueReference={vr} is not of type String!"
322
- )
323
- return refs
324
-
325
- def set_int32(self, vrs: List[int], values: List[int]):
326
- for vr, value in zip(vrs, values):
327
- var = self.vars[vr]
328
- if isinstance(var, Int32):
329
- var.setter(value)
330
- else:
331
- raise TypeError(
332
- f"Variable with valueReference={vr} is not of type Integer!"
333
- )
334
-
335
- def set_int64(self, vrs: List[int], values: List[int]):
336
- for vr, value in zip(vrs, values):
337
- var = self.vars[vr]
338
- if isinstance(var, (Enumeration, Int64)):
339
- var.setter(value)
340
- else:
341
- raise TypeError(
342
- f"Variable with valueReference={vr} is not of type Integer!"
343
- )
344
-
345
- def set_uint64(self, vrs: List[int], values: List[int]):
346
- for vr, value in zip(vrs, values):
347
- var = self.vars[vr]
348
- if isinstance(var, UInt64):
349
- var.setter(value)
350
- else:
351
- raise TypeError(
352
- f"Variable with valueReference={vr} is not of type UInt64!"
353
- )
354
-
355
- def set_float64(self, vrs: List[int], values: List[float]):
356
- offset = 0
357
- for vr in vrs:
358
- var = self.vars[vr]
359
- if isinstance(var, Float64):
360
- size = var.size(self.vars)
361
- if size > 1:
362
- var.setter(values[offset:offset+size])
363
- else:
364
- var.setter(values[offset])
365
- offset += size
366
- else:
367
- raise TypeError(
368
- f"Variable with valueReference={vr} is not of type Real!"
369
- )
370
-
371
- def set_boolean(self, vrs: List[int], values: List[bool]):
372
- for vr, value in zip(vrs, values):
373
- var = self.vars[vr]
374
- if isinstance(var, Boolean):
375
- var.setter(value)
376
- else:
377
- raise TypeError(
378
- f"Variable with valueReference={vr} is not of type Boolean!"
379
- )
380
-
381
- def set_string(self, vrs: List[int], values: List[str]):
382
- for vr, value in zip(vrs, values):
383
- var = self.vars[vr]
384
- if isinstance(var, String):
385
- var.setter(value)
386
- else:
387
- raise TypeError(
388
- f"Variable with valueReference={vr} is not of type String!"
389
- )
390
-
391
- def _get_fmu_state(self) -> Dict[str, Any]:
392
- state = dict()
393
- for var in self.vars.values():
394
- state[var.name] = var.getter()
395
- return state
396
-
397
- def _set_fmu_state(self, state: Dict[str, Any]):
398
- vars_by_name = dict([(v.name, v) for v in self.vars.values()])
399
- for name, value in state.items():
400
- if name not in vars_by_name:
401
- setattr(self, name, value)
402
- else:
403
- v = vars_by_name[name]
404
- if v.setter is not None:
405
- v.setter(value)
406
-
407
- @staticmethod
408
- def _fmu_state_to_bytes(state: Dict[str, Any]) -> bytes:
409
- return json.dumps(state).encode("utf-8")
410
-
411
- @staticmethod
412
- def _fmu_state_from_bytes(state: bytes) -> Dict[str, Any]:
413
- return json.loads(state.decode("utf-8"))
414
-
415
- def _get_log_queue(self):
416
- return self.log_queue
417
-
418
- def log(
419
- self,
420
- msg: str,
421
- status: Fmi3Status = Fmi3Status.ok,
422
- category: Optional[str] = None,
423
- debug: bool = False
424
- ):
425
- """Log a message to the FMU logger.
426
-
427
- Args:
428
- msg (str) : Log message
429
- status (Fmi3Status) : Optional, message status (default ok)
430
- category (str or None) : Optional, message category (default derived from status)
431
- debug (bool) : Optional, is this a debug message (default False)
432
- """
433
- if category is None:
434
- category = f"logStatus{status.name.capitalize()}"
435
- if category not in self.log_categories:
436
- category = "logAll"
437
- log_msg = LogMsg(status, category, msg, debug)
438
- self.log_queue.append(log_msg)
1
+ """Define the abstract facade class."""
2
+ import json
3
+ import ctypes
4
+ import datetime
5
+ from abc import ABC, abstractmethod
6
+ from collections import OrderedDict, namedtuple
7
+ from pathlib import Path
8
+ from typing import Any, ClassVar, Dict, List, NamedTuple, Optional
9
+ from uuid import uuid1
10
+ from xml.etree.ElementTree import Element, SubElement
11
+
12
+ from .logmsg import LogMsg
13
+ from .default_experiment import DefaultExperiment
14
+ from ._version import __version__ as VERSION
15
+ from .enums import Fmi3Type, Fmi3Status, Fmi3Causality, Fmi3Initial, Fmi3Variability
16
+ from .variables import Boolean, Enumeration, Int32, Int64, UInt64, Float64, ModelVariable, String
17
+ from .variable_types import VariableType
18
+ from .unit import Unit
19
+
20
+ ModelOptions = namedtuple("ModelOptions", ["name", "value", "cli"])
21
+
22
+ FMI3_MODEL_OPTIONS: List[ModelOptions] = [
23
+ ModelOptions("needsExecutionTool", True, "no-external-tool"),
24
+ ModelOptions("canHandleVariableCommunicationStepSize", True, "no-variable-step"),
25
+ ModelOptions("canBeInstantiatedOnlyOncePerProcess", False, "only-one-per-process"),
26
+ ModelOptions("canGetAndSetFMUState", False, "handle-state"),
27
+ ModelOptions("canSerializeFMUState", False, "serialize-state")
28
+ ]
29
+
30
+ class Fmi3StepResult(NamedTuple):
31
+ status: Fmi3Status = Fmi3Status.ok
32
+ eventHandlingNeeded: bool = False
33
+ terminateSimulation: bool = False
34
+ earlyReturn: bool = False
35
+
36
+ class Fmi3Slave(ABC):
37
+ """Abstract facade class to execute Python through FMI standard."""
38
+
39
+ # Dictionary of (category, description) entries
40
+ log_categories: Dict[str, str] = {
41
+ "logStatusWarning": "Log messages with fmi3Warning status.",
42
+ "logStatusDiscard": "Log messages with fmi3Discard status.",
43
+ "logStatusError": "Log messages with fmi3Error status.",
44
+ "logStatusFatal": "Log messages with fmi3Fatal status.",
45
+ "logAll": "Log all messages."
46
+ }
47
+
48
+ def __init__(self, **kwargs):
49
+ self.vars = OrderedDict()
50
+ self.instance_name = kwargs["instance_name"]
51
+ self.resources = kwargs.get("resources", None)
52
+ self.visible = kwargs.get("visible", False)
53
+ self.log_queue = []
54
+
55
+ self.guid = uuid1()
56
+ self.author: Optional[str] = None
57
+ self.license: Optional[str] = None
58
+ self.version: Optional[str] = None
59
+ self.copyright: Optional[str] = None
60
+ self.modelName: Optional[str] = self.__class__.__name__
61
+ self.description: Optional[str] = None
62
+ self.default_experiment: Optional[DefaultExperiment] = None
63
+
64
+ self.type_definitions: Dict[str, VariableType] = {}
65
+ self.units: Dict[str, Unit] = {}
66
+
67
+ def to_xml(self, model_options: Dict[str, str] = dict()) -> Element:
68
+ """Build the XML representation of the model.
69
+
70
+ Args:
71
+ model_options (Dict[str, str]) : FMU model options
72
+
73
+ Returns:
74
+ (xml.etree.TreeElement.Element) XML description of the FMU
75
+ """
76
+
77
+ t = datetime.datetime.now(datetime.timezone.utc)
78
+ date_str = t.isoformat(timespec="seconds")
79
+
80
+ attrib = dict(
81
+ fmiVersion="3.0",
82
+ modelName=self.modelName,
83
+ instantiationToken=f"{self.guid!s}",
84
+ generationTool=f"PythonFMU3 {VERSION}",
85
+ generationDateAndTime=date_str,
86
+ variableNamingConvention="structured"
87
+ )
88
+ if self.description is not None:
89
+ attrib["description"] = self.description
90
+ if self.author is not None:
91
+ attrib["author"] = self.author
92
+ if self.license is not None:
93
+ attrib["license"] = self.license
94
+ if self.version is not None:
95
+ attrib["version"] = self.version
96
+ if self.copyright is not None:
97
+ attrib["copyright"] = self.copyright
98
+
99
+ root = Element("fmiModelDescription", attrib)
100
+
101
+ options = dict()
102
+ for option in FMI3_MODEL_OPTIONS:
103
+ value = model_options.get(option.name, option.value)
104
+ options[option.name] = str(value).lower()
105
+ options["modelIdentifier"] = self.modelName
106
+ options["canNotUseMemoryManagementFunctions"] = "true"
107
+
108
+ SubElement(root, "CoSimulation", attrib=options)
109
+
110
+ if self.units:
111
+ unit_defs = SubElement(root, "UnitDefinitions")
112
+ for _, unit in self.units.items():
113
+ unit_defs.append(unit.to_xml())
114
+
115
+ if self.type_definitions:
116
+ type_defs = SubElement(root, "TypeDefinitions")
117
+ for _, val in self.type_definitions.items():
118
+ type_defs.append(val.to_xml())
119
+
120
+ if len(self.log_categories) > 0:
121
+ categories = SubElement(root, "LogCategories")
122
+ for category, description in self.log_categories.items():
123
+ categories.append(
124
+ Element(
125
+ "Category",
126
+ attrib={"name": category, "description": description},
127
+ )
128
+ )
129
+
130
+ if self.default_experiment is not None:
131
+ attrib = dict()
132
+ if self.default_experiment.start_time is not None:
133
+ attrib["startTime"] = str(self.default_experiment.start_time)
134
+ if self.default_experiment.stop_time is not None:
135
+ attrib["stopTime"] = str(self.default_experiment.stop_time)
136
+ if self.default_experiment.step_size is not None:
137
+ attrib["stepSize"] = str(self.default_experiment.step_size)
138
+ if self.default_experiment.tolerance is not None:
139
+ attrib["tolerance"] = str(self.default_experiment.tolerance)
140
+ SubElement(root, "DefaultExperiment", attrib)
141
+
142
+ variables = SubElement(root, "ModelVariables")
143
+ for v in self.vars.values():
144
+ if ModelVariable.requires_start(v):
145
+ self.__apply_start_value(v)
146
+ variables.append(v.to_xml())
147
+
148
+ structure = SubElement(root, "ModelStructure")
149
+ outputs = list(
150
+ filter(lambda v: v.causality == Fmi3Causality.output, self.vars.values())
151
+ )
152
+
153
+ continuous_state_derivatives = list(
154
+ filter(lambda v: v.variability == Fmi3Variability.continuous and (isinstance(v, Float64) and v.derivative is not None), self.vars.values())
155
+ )
156
+
157
+ allowed_variability = [None, Fmi3Initial.approx, Fmi3Initial.calculated]
158
+ initial_unknown = list(
159
+ filter(lambda v: (v.causality == Fmi3Causality.output and (v.initial in allowed_variability))
160
+ or v.causality == Fmi3Causality.calculatedParameter
161
+ or v in continuous_state_derivatives and v.initial in allowed_variability
162
+ or v.variability == Fmi3Variability.continuous and v.initial in allowed_variability and v.causality != Fmi3Causality.independent, self.vars.values())
163
+ )
164
+
165
+ for v in outputs:
166
+ SubElement(structure, "Output", attrib=dict(valueReference=str(v.value_reference)))
167
+
168
+ for v in continuous_state_derivatives:
169
+ SubElement(structure, "ContinuousStateDerivative", attrib=dict(valueReference=str(v.value_reference)))
170
+
171
+ for v in initial_unknown:
172
+ SubElement(structure, "InitialUnknown", attrib=dict(valueReference=str(v.value_reference)))
173
+
174
+
175
+
176
+ return root
177
+
178
+ def __apply_start_value(self, var: ModelVariable):
179
+ vrs = [var.value_reference]
180
+ if isinstance(var, Int32):
181
+ refs = self.get_int32(vrs)
182
+ elif isinstance(var, (Enumeration, Int64)):
183
+ refs = self.get_int64(vrs)
184
+ elif isinstance(var, UInt64):
185
+ refs = [val.value for val in self.get_uint64(vrs)]
186
+ elif isinstance(var, Float64):
187
+ refs = self.get_float64(vrs)
188
+ elif isinstance(var, Boolean):
189
+ refs = self.get_boolean(vrs)
190
+ elif isinstance(var, String):
191
+ refs = self.get_string(vrs)
192
+ else:
193
+ raise Exception(f"Unsupported type {type(var)}!")
194
+ var.start = refs if len(getattr(var, "dimensions", [])) > 0 else refs[0]
195
+
196
+ def register_variable(self, var: ModelVariable, nested: bool = True, var_type: Any = None):
197
+ """Register a variable as FMU interface.
198
+
199
+ Args:
200
+ var (ModelVariable): The variable to be registered
201
+ nested (bool): Optional, does the "." in the variable name reflect an object hierarchy to access it? Default True
202
+ """
203
+ variable_reference = len(self.vars)
204
+ self.vars[variable_reference] = var
205
+ # Set the unique value reference
206
+ var.value_reference = variable_reference
207
+ owner = self
208
+ if var.getter is None and nested and "." in var.name:
209
+ split = var.name.split(".")
210
+ split.pop(-1)
211
+ for s in split:
212
+ owner = getattr(owner, s)
213
+ if var.getter is None:
214
+ if hasattr(var, "dimensions") and len(var.dimensions) > 0:
215
+ var.getter = lambda: getattr(owner, var.local_name).flatten().tolist()
216
+ else:
217
+ var.getter = lambda: getattr(owner, var.local_name)
218
+ if var.setter is None and hasattr(owner, var.local_name) and var.variability != Fmi3Variability.constant:
219
+ if hasattr(var, "dimensions") and len(var.dimensions) > 0:
220
+ import numpy as np
221
+ var.setter = lambda v: setattr(owner, var.local_name, np.reshape(v, newshape=getattr(owner, var.local_name).shape))
222
+ else:
223
+ var.setter = lambda v: setattr(owner, var.local_name, v)
224
+
225
+ if var_type:
226
+ self.type_definitions[var_type.name] = var_type
227
+ var.declared_type = var_type.name
228
+
229
+ def setup_experiment(self, start_time: float):
230
+ pass
231
+
232
+ def register_units(self, units: List[Unit]):
233
+ for unit in units:
234
+ self.units[unit.name] = unit
235
+
236
+ def enter_initialization_mode(self):
237
+ pass
238
+
239
+ def exit_initialization_mode(self):
240
+ pass
241
+
242
+ @abstractmethod
243
+ def do_step(self, current_time: float, step_size: float) -> Fmi3StepResult:
244
+ pass
245
+
246
+ def terminate(self):
247
+ pass
248
+
249
+ def get_int32(self, vrs: List[int]) -> List[int]:
250
+ refs = list()
251
+ for vr in vrs:
252
+ var = self.vars[vr]
253
+ if isinstance(var, Int32):
254
+ refs.append(int(var.getter()))
255
+ else:
256
+ raise TypeError(
257
+ f"Variable with valueReference={vr} is not of type Integer!"
258
+ )
259
+ return refs
260
+
261
+ def get_int64(self, vrs: List[int]) -> List[int]:
262
+ refs = list()
263
+ for vr in vrs:
264
+ var = self.vars[vr]
265
+ if isinstance(var, (Enumeration, Int64)):
266
+ refs.append(int(var.getter()))
267
+ else:
268
+ raise TypeError(
269
+ f"Variable with valueReference={vr} is not of type Int64!"
270
+ )
271
+ return refs
272
+
273
+ def get_uint64(self, vrs: List[int]) -> List[ctypes.c_uint64]:
274
+ refs = list()
275
+ for vr in vrs:
276
+ var = self.vars[vr]
277
+ if isinstance(var, UInt64):
278
+ val = var.getter()
279
+ refs.append(val if isinstance(val, ctypes.c_uint64) else ctypes.c_uint64(val))
280
+ else:
281
+ raise TypeError(
282
+ f"Variable with valueReference={vr} is not of type UInt64!"
283
+ )
284
+ return refs
285
+
286
+ def get_float64(self, vrs: List[int]) -> List[float]:
287
+ refs = list()
288
+ for vr in vrs:
289
+ var = self.vars[vr]
290
+ if isinstance(var, Float64):
291
+ if len(var.dimensions) == 0:
292
+ refs.append(float(var.getter()))
293
+ else:
294
+ refs.extend(var.getter())
295
+ else:
296
+ raise TypeError(
297
+ f"Variable with valueReference={vr} is not of type Real!"
298
+ )
299
+ return refs
300
+
301
+ def get_boolean(self, vrs: List[int]) -> List[bool]:
302
+ refs = list()
303
+ for vr in vrs:
304
+ var = self.vars[vr]
305
+ if isinstance(var, Boolean):
306
+ refs.append(bool(var.getter()))
307
+ else:
308
+ raise TypeError(
309
+ f"Variable with valueReference={vr} is not of type Boolean!"
310
+ )
311
+ return refs
312
+
313
+ def get_string(self, vrs: List[int]) -> List[str]:
314
+ refs = list()
315
+ for vr in vrs:
316
+ var = self.vars[vr]
317
+ if isinstance(var, String):
318
+ refs.append(str(var.getter()))
319
+ else:
320
+ raise TypeError(
321
+ f"Variable with valueReference={vr} is not of type String!"
322
+ )
323
+ return refs
324
+
325
+ def set_int32(self, vrs: List[int], values: List[int]):
326
+ for vr, value in zip(vrs, values):
327
+ var = self.vars[vr]
328
+ if isinstance(var, Int32):
329
+ var.setter(value)
330
+ else:
331
+ raise TypeError(
332
+ f"Variable with valueReference={vr} is not of type Integer!"
333
+ )
334
+
335
+ def set_int64(self, vrs: List[int], values: List[int]):
336
+ for vr, value in zip(vrs, values):
337
+ var = self.vars[vr]
338
+ if isinstance(var, (Enumeration, Int64)):
339
+ var.setter(value)
340
+ else:
341
+ raise TypeError(
342
+ f"Variable with valueReference={vr} is not of type Integer!"
343
+ )
344
+
345
+ def set_uint64(self, vrs: List[int], values: List[int]):
346
+ for vr, value in zip(vrs, values):
347
+ var = self.vars[vr]
348
+ if isinstance(var, UInt64):
349
+ var.setter(value)
350
+ else:
351
+ raise TypeError(
352
+ f"Variable with valueReference={vr} is not of type UInt64!"
353
+ )
354
+
355
+ def set_float64(self, vrs: List[int], values: List[float]):
356
+ offset = 0
357
+ for vr in vrs:
358
+ var = self.vars[vr]
359
+ if isinstance(var, Float64):
360
+ size = var.size(self.vars)
361
+ if size > 1:
362
+ var.setter(values[offset:offset+size])
363
+ else:
364
+ var.setter(values[offset])
365
+ offset += size
366
+ else:
367
+ raise TypeError(
368
+ f"Variable with valueReference={vr} is not of type Real!"
369
+ )
370
+
371
+ def set_boolean(self, vrs: List[int], values: List[bool]):
372
+ for vr, value in zip(vrs, values):
373
+ var = self.vars[vr]
374
+ if isinstance(var, Boolean):
375
+ var.setter(value)
376
+ else:
377
+ raise TypeError(
378
+ f"Variable with valueReference={vr} is not of type Boolean!"
379
+ )
380
+
381
+ def set_string(self, vrs: List[int], values: List[str]):
382
+ for vr, value in zip(vrs, values):
383
+ var = self.vars[vr]
384
+ if isinstance(var, String):
385
+ var.setter(value)
386
+ else:
387
+ raise TypeError(
388
+ f"Variable with valueReference={vr} is not of type String!"
389
+ )
390
+
391
+ def _get_fmu_state(self) -> Dict[str, Any]:
392
+ state = dict()
393
+ for var in self.vars.values():
394
+ state[var.name] = var.getter()
395
+ return state
396
+
397
+ def _set_fmu_state(self, state: Dict[str, Any]):
398
+ vars_by_name = dict([(v.name, v) for v in self.vars.values()])
399
+ for name, value in state.items():
400
+ if name not in vars_by_name:
401
+ setattr(self, name, value)
402
+ else:
403
+ v = vars_by_name[name]
404
+ if v.setter is not None:
405
+ v.setter(value)
406
+
407
+ @staticmethod
408
+ def _fmu_state_to_bytes(state: Dict[str, Any]) -> bytes:
409
+ return json.dumps(state).encode("utf-8")
410
+
411
+ @staticmethod
412
+ def _fmu_state_from_bytes(state: bytes) -> Dict[str, Any]:
413
+ return json.loads(state.decode("utf-8"))
414
+
415
+ def _get_log_queue(self):
416
+ return self.log_queue
417
+
418
+ def log(
419
+ self,
420
+ msg: str,
421
+ status: Fmi3Status = Fmi3Status.ok,
422
+ category: Optional[str] = None,
423
+ debug: bool = False
424
+ ):
425
+ """Log a message to the FMU logger.
426
+
427
+ Args:
428
+ msg (str) : Log message
429
+ status (Fmi3Status) : Optional, message status (default ok)
430
+ category (str or None) : Optional, message category (default derived from status)
431
+ debug (bool) : Optional, is this a debug message (default False)
432
+ """
433
+ if category is None:
434
+ category = f"logStatus{status.name.capitalize()}"
435
+ if category not in self.log_categories:
436
+ category = "logAll"
437
+ log_msg = LogMsg(status, category, msg, debug)
438
+ self.log_queue.append(log_msg)