pythonfmu3 0.3.1__tar.gz → 0.3.3__tar.gz
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.
- {pythonfmu3-0.3.1/pythonfmu3.egg-info → pythonfmu3-0.3.3}/PKG-INFO +2 -10
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/README.md +1 -9
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/__init__.py +1 -1
- pythonfmu3-0.3.3/pythonfmu3/_version.py +1 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/builder.py +29 -7
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/fmi3slave.py +33 -11
- pythonfmu3-0.3.3/pythonfmu3/modelexchange.py +52 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.hpp +1 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/cppfmu/fmi_functions.cpp +11 -1
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp +85 -10
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp +1 -0
- pythonfmu3-0.3.3/pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so +0 -0
- pythonfmu3-0.3.3/pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll +0 -0
- pythonfmu3-0.3.3/pythonfmu3/tests/test_docs.py +98 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3/pythonfmu3.egg-info}/PKG-INFO +2 -10
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3.egg-info/SOURCES.txt +1 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/setup.cfg +1 -0
- pythonfmu3-0.3.1/pythonfmu3/_version.py +0 -1
- pythonfmu3-0.3.1/pythonfmu3/modelexchange.py +0 -23
- pythonfmu3-0.3.1/pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so +0 -0
- pythonfmu3-0.3.1/pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/LICENSE +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/MANIFEST.in +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/__main__.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/cosimulation.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/default_experiment.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/deploy.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/enums.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/logmsg.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/osutil.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/.clang-format +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/CMakeLists.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/build_unix.sh +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/build_win.sh +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/CMakeLists.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_common.hpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.cpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/fmi/fmi3FunctionTypes.h +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/fmi/fmi3Functions.h +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/fmi/fmi3PlatformTypes.h +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/pythonfmu/IPyState.hpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/pythonfmu/PyState.hpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/__init__.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/conftest.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/data/csvdemo.csv +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/data/hello.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/slaves/PythonSlaveWithException.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/slaves/localmodule.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/slaves/pythonslave.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/slaves/pythonslaveMX.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/slaves/pythonslaveMXCS.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/slaves/pythonslave_read_file.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/slaves/slavewithdep.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/test_builder.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/test_deploy.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/test_fmi3slave.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/test_integration.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/test_logger.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/test_multiple_fmus.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/test_variables.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/tests/utils.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/unit.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/variable_types.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/variables.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3.egg-info/dependency_links.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3.egg-info/entry_points.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3.egg-info/not-zip-safe +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3.egg-info/requires.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3.egg-info/top_level.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonfmu3
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: A lightweight framework that enables the packaging of Python3.x code as co-simulation FMUs.
|
|
5
5
|
Home-page: https://github.com/stephensmith25/PythonFMU3
|
|
6
6
|
Author: Stephen Smith
|
|
@@ -44,15 +44,6 @@ This project is a fork of the original PythonFMU repository available at https:/
|
|
|
44
44
|
Please take a look at the examples to see the supported features.
|
|
45
45
|
We currently support both the Model exchange and Cosimulation Interfaces.
|
|
46
46
|
|
|
47
|
-
For both interfaces event mode is not supported.
|
|
48
|
-
|
|
49
|
-
We currently do not support the following methods (beyond a default, trivial implementation)
|
|
50
|
-
|
|
51
|
-
- fmi3UpdateDiscreteStates
|
|
52
|
-
- fmi3GetNumberOfEventindicators
|
|
53
|
-
- fmi3GetNominalsOfContinuousStates
|
|
54
|
-
- fmi3EvaluateDiscreteStates
|
|
55
|
-
|
|
56
47
|
### How do I build an FMU from python code?
|
|
57
48
|
|
|
58
49
|
1. Install `pythonfmu3` package:
|
|
@@ -182,6 +173,7 @@ To create a model exchange FMU you must inherit from `Fmi3SlaveBase` and one of
|
|
|
182
173
|
```python
|
|
183
174
|
|
|
184
175
|
from pythonfmu3 import Fmi3Causality, Fmi3SlaveBase, Float64, ModelExchange
|
|
176
|
+
from typing import List
|
|
185
177
|
|
|
186
178
|
|
|
187
179
|
class PythonSlaveMX(Fmi3SlaveBase, ModelExchange):
|
|
@@ -17,15 +17,6 @@ This project is a fork of the original PythonFMU repository available at https:/
|
|
|
17
17
|
Please take a look at the examples to see the supported features.
|
|
18
18
|
We currently support both the Model exchange and Cosimulation Interfaces.
|
|
19
19
|
|
|
20
|
-
For both interfaces event mode is not supported.
|
|
21
|
-
|
|
22
|
-
We currently do not support the following methods (beyond a default, trivial implementation)
|
|
23
|
-
|
|
24
|
-
- fmi3UpdateDiscreteStates
|
|
25
|
-
- fmi3GetNumberOfEventindicators
|
|
26
|
-
- fmi3GetNominalsOfContinuousStates
|
|
27
|
-
- fmi3EvaluateDiscreteStates
|
|
28
|
-
|
|
29
20
|
### How do I build an FMU from python code?
|
|
30
21
|
|
|
31
22
|
1. Install `pythonfmu3` package:
|
|
@@ -155,6 +146,7 @@ To create a model exchange FMU you must inherit from `Fmi3SlaveBase` and one of
|
|
|
155
146
|
```python
|
|
156
147
|
|
|
157
148
|
from pythonfmu3 import Fmi3Causality, Fmi3SlaveBase, Float64, ModelExchange
|
|
149
|
+
from typing import List
|
|
158
150
|
|
|
159
151
|
|
|
160
152
|
class PythonSlaveMX(Fmi3SlaveBase, ModelExchange):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from ._version import __version__
|
|
2
2
|
from .builder import FmuBuilder
|
|
3
3
|
from .cosimulation import CoSimulation
|
|
4
|
-
from .modelexchange import ModelExchange
|
|
4
|
+
from .modelexchange import ModelExchange, Fmi3UpdateDiscreteStatesResult
|
|
5
5
|
from .enums import Fmi3Causality, Fmi3Initial, Fmi3Status, Fmi3Variability
|
|
6
6
|
from .fmi3slave import Fmi3Slave, Fmi3SlaveBase, Fmi3StepResult
|
|
7
7
|
from .variables import Boolean, Enumeration, Int32, Int64, UInt64, Float64, String, Dimension
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.3"
|
|
@@ -13,7 +13,7 @@ from typing import Iterable, Optional, Tuple, Union
|
|
|
13
13
|
from xml.dom.minidom import parseString
|
|
14
14
|
from xml.etree.ElementTree import Element, SubElement, tostring
|
|
15
15
|
from .osutil import get_lib_extension, get_platform
|
|
16
|
-
from .fmi3slave import
|
|
16
|
+
from .fmi3slave import FMI3_MODEL_OPTIONS_COMMON, FMI3_MODEL_OPTIONS_COSIM, FMI3_MODEL_OPTIONS_MX, Fmi3Slave, Fmi3SlaveBase
|
|
17
17
|
|
|
18
18
|
FilePath = Union[str, Path]
|
|
19
19
|
HERE = Path(__file__).parent
|
|
@@ -137,16 +137,20 @@ class FmuBuilder:
|
|
|
137
137
|
dest_file = dest / f"{model_identifier}.fmu"
|
|
138
138
|
|
|
139
139
|
type_node = xml.find("CoSimulation")
|
|
140
|
-
option_names = [opt.name for opt in
|
|
141
|
-
|
|
140
|
+
option_names = [opt.name for opt in FMI3_MODEL_OPTIONS_COMMON]
|
|
141
|
+
cosim_option_names = option_names.copy()
|
|
142
|
+
cosim_option_names.extend(opt.name for opt in FMI3_MODEL_OPTIONS_COSIM)
|
|
143
|
+
if type_node is not None:
|
|
142
144
|
for option, value in options.items():
|
|
143
|
-
if option in
|
|
145
|
+
if option in cosim_option_names:
|
|
144
146
|
type_node.set(option, str(value).lower())
|
|
145
147
|
|
|
146
148
|
type_node = xml.find("ModelExchange")
|
|
147
|
-
|
|
149
|
+
mx_option_names = option_names.copy()
|
|
150
|
+
mx_option_names.extend(opt.name for opt in FMI3_MODEL_OPTIONS_MX)
|
|
151
|
+
if type_node is not None:
|
|
148
152
|
for option, value in options.items():
|
|
149
|
-
if option in
|
|
153
|
+
if option in mx_option_names:
|
|
150
154
|
type_node.set(option, str(value).lower())
|
|
151
155
|
|
|
152
156
|
with zipfile.ZipFile(dest_file, "w") as zip_fmu:
|
|
@@ -247,7 +251,25 @@ def create_command_parser(parser: argparse.ArgumentParser):
|
|
|
247
251
|
default=None
|
|
248
252
|
)
|
|
249
253
|
|
|
250
|
-
for option in
|
|
254
|
+
for option in FMI3_MODEL_OPTIONS_COMMON:
|
|
255
|
+
action = "store_false" if option.value else "store_true"
|
|
256
|
+
parser.add_argument(
|
|
257
|
+
f"--{option.cli}",
|
|
258
|
+
dest=option.name,
|
|
259
|
+
help=f"If given, {option.name}={action[6:]}",
|
|
260
|
+
action=action
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
for option in FMI3_MODEL_OPTIONS_COSIM:
|
|
264
|
+
action = "store_false" if option.value else "store_true"
|
|
265
|
+
parser.add_argument(
|
|
266
|
+
f"--{option.cli}",
|
|
267
|
+
dest=option.name,
|
|
268
|
+
help=f"If given, {option.name}={action[6:]}",
|
|
269
|
+
action=action
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
for option in FMI3_MODEL_OPTIONS_MX:
|
|
251
273
|
action = "store_false" if option.value else "store_true"
|
|
252
274
|
parser.add_argument(
|
|
253
275
|
f"--{option.cli}",
|
|
@@ -21,14 +21,22 @@ from .unit import Unit
|
|
|
21
21
|
|
|
22
22
|
ModelOptions = namedtuple("ModelOptions", ["name", "value", "cli"])
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
FMI3_MODEL_OPTIONS_COMMON: List[ModelOptions] = [
|
|
25
25
|
ModelOptions("needsExecutionTool", True, "no-external-tool"),
|
|
26
|
-
ModelOptions("canHandleVariableCommunicationStepSize", True, "no-variable-step"),
|
|
27
26
|
ModelOptions("canBeInstantiatedOnlyOncePerProcess", False, "only-one-per-process"),
|
|
28
27
|
ModelOptions("canGetAndSetFMUState", False, "handle-state"),
|
|
29
28
|
ModelOptions("canSerializeFMUState", False, "serialize-state")
|
|
30
29
|
]
|
|
31
30
|
|
|
31
|
+
FMI3_MODEL_OPTIONS_COSIM: List[ModelOptions] = [
|
|
32
|
+
ModelOptions("canHandleVariableCommunicationStepSize", True, "no-variable-step"),
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
FMI3_MODEL_OPTIONS_MX: List[ModelOptions] = [
|
|
36
|
+
ModelOptions("needsCompletedIntegratorStep", False, "needs-completed-step"),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
32
40
|
class Fmi3StepResult(NamedTuple):
|
|
33
41
|
status: Fmi3Status = Fmi3Status.ok
|
|
34
42
|
eventHandlingNeeded: bool = False
|
|
@@ -50,6 +58,7 @@ class Fmi3SlaveBase(object):
|
|
|
50
58
|
|
|
51
59
|
def __init__(self, **kwargs):
|
|
52
60
|
self.vars = OrderedDict()
|
|
61
|
+
self.event_indicators: List[int] = []
|
|
53
62
|
self.instance_name = kwargs["instance_name"]
|
|
54
63
|
self.resources = kwargs.get("resources", None)
|
|
55
64
|
self.visible = kwargs.get("visible", False)
|
|
@@ -102,23 +111,26 @@ class Fmi3SlaveBase(object):
|
|
|
102
111
|
root = Element("fmiModelDescription", attrib)
|
|
103
112
|
|
|
104
113
|
options = dict()
|
|
105
|
-
for option in
|
|
114
|
+
for option in FMI3_MODEL_OPTIONS_COMMON:
|
|
106
115
|
value = model_options.get(option.name, option.value)
|
|
107
116
|
options[option.name] = str(value).lower()
|
|
117
|
+
|
|
108
118
|
options["modelIdentifier"] = self.modelName
|
|
109
|
-
|
|
119
|
+
|
|
120
|
+
options_cs = options.copy()
|
|
121
|
+
for option in FMI3_MODEL_OPTIONS_COSIM:
|
|
122
|
+
options_cs[option.name] = str(value).lower()
|
|
110
123
|
|
|
111
|
-
options_me =
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
options_me["needsCompletedIntegratorStep"] = "false"
|
|
124
|
+
options_me = options.copy()
|
|
125
|
+
for option in FMI3_MODEL_OPTIONS_MX:
|
|
126
|
+
options_me[option.name] = str(value).lower()
|
|
115
127
|
|
|
116
128
|
# check if we have cosim mixin or model exchange mixin
|
|
117
129
|
if isinstance(self, ModelExchange):
|
|
118
130
|
SubElement(root, "ModelExchange", attrib=options_me)
|
|
119
131
|
|
|
120
132
|
if isinstance(self, CoSimulation):
|
|
121
|
-
SubElement(root, "CoSimulation", attrib=
|
|
133
|
+
SubElement(root, "CoSimulation", attrib=options_cs)
|
|
122
134
|
|
|
123
135
|
if self.units:
|
|
124
136
|
unit_defs = SubElement(root, "UnitDefinitions")
|
|
@@ -184,7 +196,8 @@ class Fmi3SlaveBase(object):
|
|
|
184
196
|
for v in initial_unknown:
|
|
185
197
|
SubElement(structure, "InitialUnknown", attrib=dict(valueReference=str(v.value_reference)))
|
|
186
198
|
|
|
187
|
-
|
|
199
|
+
for v in self.event_indicators:
|
|
200
|
+
SubElement(structure, "EventIndicator", attrib=dict(valueReference=str(v)))
|
|
188
201
|
|
|
189
202
|
return root
|
|
190
203
|
|
|
@@ -206,7 +219,7 @@ class Fmi3SlaveBase(object):
|
|
|
206
219
|
raise Exception(f"Unsupported type {type(var)}!")
|
|
207
220
|
var.start = refs if len(getattr(var, "dimensions", [])) > 0 else refs[0]
|
|
208
221
|
|
|
209
|
-
def register_variable(self, var: ModelVariable, nested: bool = True, var_type: Any = None):
|
|
222
|
+
def register_variable(self, var: ModelVariable, nested: bool = True, var_type: Any = None, has_event_indicator: bool = False):
|
|
210
223
|
"""Register a variable as FMU interface.
|
|
211
224
|
|
|
212
225
|
Args:
|
|
@@ -238,6 +251,12 @@ class Fmi3SlaveBase(object):
|
|
|
238
251
|
if var_type:
|
|
239
252
|
self.type_definitions[var_type.name] = var_type
|
|
240
253
|
var.declared_type = var_type.name
|
|
254
|
+
|
|
255
|
+
if has_event_indicator:
|
|
256
|
+
self.register_event_indicator(var.value_reference)
|
|
257
|
+
|
|
258
|
+
def register_event_indicator(self, vr):
|
|
259
|
+
self.event_indicators.append(vr)
|
|
241
260
|
|
|
242
261
|
def setup_experiment(self, start_time: float):
|
|
243
262
|
pass
|
|
@@ -416,6 +435,9 @@ class Fmi3SlaveBase(object):
|
|
|
416
435
|
if v.setter is not None:
|
|
417
436
|
v.setter(value)
|
|
418
437
|
|
|
438
|
+
def get_number_of_event_indicators(self) -> int:
|
|
439
|
+
return len(self.event_indicators)
|
|
440
|
+
|
|
419
441
|
def set_continuous_states(self, values: List[float]):
|
|
420
442
|
offset = 0
|
|
421
443
|
continuous_state_derivatives = list(
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from abc import ABC, ABCMeta, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
@dataclass
|
|
5
|
+
class Fmi3UpdateDiscreteStatesResult:
|
|
6
|
+
discreteStateNeedsUpdate: bool = False
|
|
7
|
+
terminateSimulation: bool = False
|
|
8
|
+
nominalsOfContinuousStatesChanged: bool = False
|
|
9
|
+
valuesOfContinuousStatesChanged: bool = False
|
|
10
|
+
nextEventTimeDefined: bool = False
|
|
11
|
+
nextEventTime: float = 0.0
|
|
12
|
+
|
|
13
|
+
class RequireTimeMeta(ABCMeta):
|
|
14
|
+
def __init__(cls, name, bases, namespace):
|
|
15
|
+
super().__init__(name, bases, namespace)
|
|
16
|
+
orig_init = cls.__init__
|
|
17
|
+
def new_init(self, *args, **kwargs):
|
|
18
|
+
orig_init(self, *args, **kwargs)
|
|
19
|
+
if not hasattr(self, 'time'):
|
|
20
|
+
raise AttributeError(f"{cls.__name__} must define 'self.time' in __init__")
|
|
21
|
+
cls.__init__ = new_init
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# model exchange mixin
|
|
25
|
+
class ModelExchange(ABC, metaclass=RequireTimeMeta):
|
|
26
|
+
"""
|
|
27
|
+
Classes derived from ModelExchange must define a 'self.time' member variable.
|
|
28
|
+
|
|
29
|
+
Required methods to override:
|
|
30
|
+
- `get_continuous_state_derivatives`: Must return a list of continuous state derivatives.
|
|
31
|
+
|
|
32
|
+
Optional methods:
|
|
33
|
+
- `get_event_indicators`: Should return a list of event indicators.
|
|
34
|
+
- `update_discrete_states`: Signify converged solution at current super-dense time instant.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def get_continuous_state_derivatives(self):
|
|
39
|
+
"""Return the continuous state derivatives of the model."""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
def get_event_indicators(self):
|
|
43
|
+
"""Return the event indicators of the model."""
|
|
44
|
+
return []
|
|
45
|
+
|
|
46
|
+
def update_discrete_states(self):
|
|
47
|
+
"""Update the discrete states of the model."""
|
|
48
|
+
return Fmi3UpdateDiscreteStatesResult()
|
|
49
|
+
|
|
50
|
+
def get_nominals_of_continuous_states(self, size: int) -> list[float]:
|
|
51
|
+
"""Return the nominal values of the continuous states."""
|
|
52
|
+
return [1.0] * size
|
|
@@ -141,6 +141,7 @@ public:
|
|
|
141
141
|
virtual void SetTime(cppfmu::FMIFloat64 time) = 0;
|
|
142
142
|
virtual void GetNumberOfContinuousStates(std::size_t& nStates) const = 0;
|
|
143
143
|
virtual void GetNumberOfEventIndicators(std::size_t& nEventIndicators) const = 0;
|
|
144
|
+
virtual void GetEventIndicators(cppfmu::FMIFloat64* eventIndicators, std::size_t nEventIndicators) const = 0;
|
|
144
145
|
virtual void UpdateDiscreteStates(
|
|
145
146
|
cppfmu::FMIBoolean* discreteStatesNeedUpdate,
|
|
146
147
|
cppfmu::FMIBoolean* terminateSimulation,
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/cppfmu/fmi_functions.cpp
RENAMED
|
@@ -622,7 +622,17 @@ fmi3Status fmi3GetEventIndicators(
|
|
|
622
622
|
fmi3Float64 eventIndicators[],
|
|
623
623
|
size_t nEventIndicators)
|
|
624
624
|
{
|
|
625
|
-
|
|
625
|
+
const auto component = reinterpret_cast<Component*>(c);
|
|
626
|
+
try {
|
|
627
|
+
component->slave->GetEventIndicators(eventIndicators, nEventIndicators);
|
|
628
|
+
return fmi3OK;
|
|
629
|
+
} catch (const cppfmu::FatalError& e) {
|
|
630
|
+
component->logger.Log(fmi3Fatal, "", e.what());
|
|
631
|
+
return fmi3Fatal;
|
|
632
|
+
} catch (const std::exception& e) {
|
|
633
|
+
component->logger.Log(fmi3Error, "", e.what());
|
|
634
|
+
return fmi3Error;
|
|
635
|
+
}
|
|
626
636
|
}
|
|
627
637
|
|
|
628
638
|
fmi3Status fmi3GetNominalsOfContinuousStates(
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp
RENAMED
|
@@ -542,6 +542,7 @@ void PySlaveInstance::GetContinuousStates(cppfmu::FMIFloat64* continuousStates,
|
|
|
542
542
|
PyObject* item = PyList_GetItem(f, i);
|
|
543
543
|
continuousStates[i] = static_cast<cppfmu::FMIFloat64>(PyFloat_AsDouble(item));
|
|
544
544
|
}
|
|
545
|
+
Py_DECREF(f);
|
|
545
546
|
clearLogBuffer();
|
|
546
547
|
});
|
|
547
548
|
}
|
|
@@ -551,6 +552,7 @@ void PySlaveInstance::GetContinuousStateDerivatives(cppfmu::FMIFloat64* continuo
|
|
|
551
552
|
py_safe_run([this, &continuousStateDerivatives, nStates](PyGILState_STATE gilState) {
|
|
552
553
|
auto f = PyObject_CallMethod(pInstance_, "get_continuous_state_derivatives", nullptr);
|
|
553
554
|
if (f == nullptr) {
|
|
555
|
+
PyErr_Print();
|
|
554
556
|
handle_py_exception("[get_continuous_state_derivatives] PyObject_CallMethod", gilState);
|
|
555
557
|
}
|
|
556
558
|
// Assuming f is a list of floats
|
|
@@ -558,15 +560,27 @@ void PySlaveInstance::GetContinuousStateDerivatives(cppfmu::FMIFloat64* continuo
|
|
|
558
560
|
PyObject* item = PyList_GetItem(f, i);
|
|
559
561
|
continuousStateDerivatives[i] = static_cast<cppfmu::FMIFloat64>(PyFloat_AsDouble(item));
|
|
560
562
|
}
|
|
563
|
+
Py_DECREF(f);
|
|
561
564
|
clearLogBuffer();
|
|
562
565
|
});
|
|
563
566
|
}
|
|
564
567
|
|
|
565
568
|
void PySlaveInstance::GetNominalsOfContinuousStates(cppfmu::FMIFloat64* nominalsOfContinuousStates, std::size_t nStates) const
|
|
566
569
|
{
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
+
py_safe_run([this, &nominalsOfContinuousStates, nStates](PyGILState_STATE gilState) {
|
|
571
|
+
auto f = PyObject_CallMethod(pInstance_, "get_nominals_of_continuous_states", "(i)", static_cast<int>(nStates));
|
|
572
|
+
// Check if f is a valid object
|
|
573
|
+
if (f == nullptr) {
|
|
574
|
+
handle_py_exception("[getNominalContinuousStates] PyObject_CallMethod", gilState);
|
|
575
|
+
}
|
|
576
|
+
// Assuming f is a list of floats
|
|
577
|
+
for (std::size_t i = 0; i < nStates; i++) {
|
|
578
|
+
PyObject* item = PyList_GetItem(f, i);
|
|
579
|
+
nominalsOfContinuousStates[i] = static_cast<cppfmu::FMIFloat64>(PyFloat_AsDouble(item));
|
|
580
|
+
}
|
|
581
|
+
Py_DECREF(f);
|
|
582
|
+
clearLogBuffer();
|
|
583
|
+
});
|
|
570
584
|
}
|
|
571
585
|
|
|
572
586
|
void PySlaveInstance::SetContinuousStates(const cppfmu::FMIFloat64* continuousStates, std::size_t nStates)
|
|
@@ -602,9 +616,36 @@ void PySlaveInstance::GetNumberOfContinuousStates(std::size_t& nStates) const
|
|
|
602
616
|
|
|
603
617
|
void PySlaveInstance::GetNumberOfEventIndicators(std::size_t& nIndicators) const
|
|
604
618
|
{
|
|
605
|
-
|
|
619
|
+
py_safe_run([this, &nIndicators](PyGILState_STATE gilState) {
|
|
620
|
+
auto f = PyObject_CallMethod(pInstance_, "get_number_of_event_indicators", nullptr);
|
|
621
|
+
if (f == nullptr) {
|
|
622
|
+
handle_py_exception("[getNumberOfEventIndicators] PyObject_CallMethod", gilState);
|
|
623
|
+
}
|
|
624
|
+
nIndicators = static_cast<std::size_t>(PyLong_AsLong(f));
|
|
625
|
+
Py_DECREF(f);
|
|
626
|
+
clearLogBuffer();
|
|
627
|
+
});
|
|
606
628
|
}
|
|
607
629
|
|
|
630
|
+
void PySlaveInstance::GetEventIndicators(cppfmu::FMIFloat64* eventIndicators, std::size_t nIndicators) const
|
|
631
|
+
{
|
|
632
|
+
py_safe_run([this, &eventIndicators, nIndicators](PyGILState_STATE gilState) {
|
|
633
|
+
auto f = PyObject_CallMethod(pInstance_, "get_event_indicators", nullptr);
|
|
634
|
+
if (f == nullptr) {
|
|
635
|
+
handle_py_exception("[getEventIndicators] PyObject_CallMethod", gilState);
|
|
636
|
+
}
|
|
637
|
+
// Assuming f is a list of floats
|
|
638
|
+
for (std::size_t i = 0; i < nIndicators; i++) {
|
|
639
|
+
PyObject* item = PyList_GetItem(f, i);
|
|
640
|
+
eventIndicators[i] = static_cast<cppfmu::FMIFloat64>(PyFloat_AsDouble(item));
|
|
641
|
+
}
|
|
642
|
+
Py_DECREF(f);
|
|
643
|
+
clearLogBuffer();
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
|
|
608
649
|
void PySlaveInstance::SetTime(cppfmu::FMIFloat64 time)
|
|
609
650
|
{
|
|
610
651
|
py_safe_run([this, time](PyGILState_STATE gilState) {
|
|
@@ -625,12 +666,46 @@ void PySlaveInstance::UpdateDiscreteStates(
|
|
|
625
666
|
cppfmu::FMIBoolean* nextEventTimeDefined,
|
|
626
667
|
cppfmu::FMIFloat64* nextEventTime)
|
|
627
668
|
{
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
669
|
+
py_safe_run([this, discreteStatesNeedUpdate, terminateSimulation, nominalContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime](PyGILState_STATE gilState) {
|
|
670
|
+
auto f = PyObject_CallMethod(pInstance_, "update_discrete_states", nullptr);
|
|
671
|
+
if (f == nullptr) {
|
|
672
|
+
handle_py_exception("[updateDiscreteStates] PyObject_CallMethod", gilState);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (PyObject_HasAttrString(f, "discreteStatesNeedUpdate")) {
|
|
676
|
+
PyObject * pyDiscreteStatesNeedUpdate = PyObject_GetAttrString(f, "discreteStatesNeedUpdate");
|
|
677
|
+
*discreteStatesNeedUpdate = static_cast<bool>(PyObject_IsTrue(pyDiscreteStatesNeedUpdate));
|
|
678
|
+
Py_DECREF(pyDiscreteStatesNeedUpdate);
|
|
679
|
+
}
|
|
680
|
+
if (PyObject_HasAttrString(f, "terminateSimulation")) {
|
|
681
|
+
PyObject* pyTerminateSimulation = PyObject_GetAttrString(f, "terminateSimulation");
|
|
682
|
+
*terminateSimulation = static_cast<bool>(PyObject_IsTrue(pyTerminateSimulation));
|
|
683
|
+
Py_DECREF(pyTerminateSimulation);
|
|
684
|
+
}
|
|
685
|
+
if (PyObject_HasAttrString(f, "nominalContinuousStatesChanged")) {
|
|
686
|
+
PyObject* pyNominalContinuousStatesChanged = PyObject_GetAttrString(f, "nominalContinuousStatesChanged");
|
|
687
|
+
*nominalContinuousStatesChanged = static_cast<bool>(PyObject_IsTrue(pyNominalContinuousStatesChanged));
|
|
688
|
+
Py_DECREF(pyNominalContinuousStatesChanged);
|
|
689
|
+
}
|
|
690
|
+
if (PyObject_HasAttrString(f, "valuesOfContinuousStatesChanged")) {
|
|
691
|
+
PyObject* pyValuesOfContinuousStatesChanged = PyObject_GetAttrString(f, "valuesOfContinuousStatesChanged");
|
|
692
|
+
*valuesOfContinuousStatesChanged = static_cast<bool>(PyObject_IsTrue(pyValuesOfContinuousStatesChanged));
|
|
693
|
+
Py_DECREF(pyValuesOfContinuousStatesChanged);
|
|
694
|
+
}
|
|
695
|
+
if (PyObject_HasAttrString(f, "nextEventTimeDefined")) {
|
|
696
|
+
PyObject* pyNextEventTimeDefined = PyObject_GetAttrString(f, "nextEventTimeDefined");
|
|
697
|
+
*nextEventTimeDefined = static_cast<bool>(PyObject_IsTrue(pyNextEventTimeDefined));
|
|
698
|
+
Py_DECREF(pyNextEventTimeDefined);
|
|
699
|
+
}
|
|
700
|
+
if (nextEventTimeDefined && *nextEventTimeDefined) {
|
|
701
|
+
PyObject* pyNextEventTime = PyObject_GetAttrString(f, "nextEventTime");
|
|
702
|
+
*nextEventTime = PyFloat_AsDouble(pyNextEventTime);
|
|
703
|
+
Py_DECREF(pyNextEventTime);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
Py_DECREF(f);
|
|
707
|
+
clearLogBuffer();
|
|
708
|
+
});
|
|
634
709
|
}
|
|
635
710
|
|
|
636
711
|
void PySlaveInstance::GetFMUstate(fmi3FMUState& state)
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp
RENAMED
|
@@ -57,6 +57,7 @@ public:
|
|
|
57
57
|
void GetNumberOfEventIndicators(std::size_t& nEventIndicators) const override;
|
|
58
58
|
void GetContinuousStateDerivatives(cppfmu::FMIFloat64* derivatives, std::size_t nStates) const override;
|
|
59
59
|
void GetNominalsOfContinuousStates(cppfmu::FMIFloat64* nominalContinuousStates, std::size_t nStates) const override;
|
|
60
|
+
void GetEventIndicators(cppfmu::FMIFloat64* eventIndicators, std::size_t nEventIndicators) const override;
|
|
60
61
|
void SetContinuousStates(const cppfmu::FMIFloat64* continuousStates, std::size_t nStates) override;
|
|
61
62
|
void SetTime(cppfmu::FMIFloat64 time) override;
|
|
62
63
|
void UpdateDiscreteStates(
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import pathlib
|
|
3
|
+
import re
|
|
4
|
+
import tempfile
|
|
5
|
+
|
|
6
|
+
def extract_python_code_from_md(md_file):
|
|
7
|
+
"""Extract Python code blocks from markdown, excluding skip blocks"""
|
|
8
|
+
content = pathlib.Path(md_file).read_text()
|
|
9
|
+
|
|
10
|
+
# Find all python code blocks that aren't marked as skip
|
|
11
|
+
python_blocks = []
|
|
12
|
+
|
|
13
|
+
# Pattern to match python blocks but not python skip
|
|
14
|
+
pattern = r'```python(?!\s+skip)(?:[^\n]*)\n(.*?)\n```'
|
|
15
|
+
matches = re.findall(pattern, content, re.DOTALL)
|
|
16
|
+
|
|
17
|
+
for match in matches:
|
|
18
|
+
# Skip blocks that are wrapped in skip-test comments
|
|
19
|
+
if '<!-- skip-test -->' not in content.split(match)[0][-100:]:
|
|
20
|
+
python_blocks.append(match)
|
|
21
|
+
|
|
22
|
+
return python_blocks
|
|
23
|
+
|
|
24
|
+
@pytest.mark.doc
|
|
25
|
+
def test_readme():
|
|
26
|
+
test_dir = pathlib.Path(__file__).parent
|
|
27
|
+
fpath = test_dir.parent.parent / "README.md"
|
|
28
|
+
|
|
29
|
+
# extract Python code
|
|
30
|
+
code_blocks = extract_python_code_from_md(fpath)
|
|
31
|
+
|
|
32
|
+
namespace = {}
|
|
33
|
+
exec("from pythonfmu3 import *", namespace)
|
|
34
|
+
|
|
35
|
+
for i, code in enumerate(code_blocks):
|
|
36
|
+
try:
|
|
37
|
+
exec(code, namespace)
|
|
38
|
+
print(f"✅ Code block {i+1} executed successfully")
|
|
39
|
+
except Exception as e:
|
|
40
|
+
pytest.fail(f"Code block {i+1} failed: {e}\nCode:\n{code}")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.mark.doc
|
|
46
|
+
def test_cosimulation_examples():
|
|
47
|
+
"""Test that all Python examples in usage.md actually work"""
|
|
48
|
+
test_dir = pathlib.Path(__file__).parent
|
|
49
|
+
usage_file = test_dir.parent.parent / "docs" / "usage.md"
|
|
50
|
+
|
|
51
|
+
# Extract Python code
|
|
52
|
+
code_blocks = extract_python_code_from_md(usage_file)
|
|
53
|
+
|
|
54
|
+
# Create a test namespace
|
|
55
|
+
namespace = {}
|
|
56
|
+
exec("from pythonfmu3 import *", namespace)
|
|
57
|
+
|
|
58
|
+
# Execute each code block
|
|
59
|
+
for i, code in enumerate(code_blocks):
|
|
60
|
+
try:
|
|
61
|
+
exec(code, namespace)
|
|
62
|
+
print(f"✅ Code block {i+1} executed successfully")
|
|
63
|
+
except Exception as e:
|
|
64
|
+
pytest.fail(f"Code block {i+1} failed: {e}\nCode:\n{code}")
|
|
65
|
+
|
|
66
|
+
assert 'LinearTransform' in namespace, "LinearTransform class not found"
|
|
67
|
+
assert 'PIDController' in namespace, "PIDController class not found"
|
|
68
|
+
|
|
69
|
+
# Test instantiation
|
|
70
|
+
lt = namespace['LinearTransform'](instance_name="test")
|
|
71
|
+
pc = namespace['PIDController'](instance_name="test")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.mark.doc
|
|
75
|
+
def test_model_exchange_examples():
|
|
76
|
+
"""Test Model Exchange examples"""
|
|
77
|
+
test_dir = pathlib.Path(__file__).parent
|
|
78
|
+
mx_file = test_dir.parent.parent / "docs" / "usageMX.md"
|
|
79
|
+
|
|
80
|
+
code_blocks = extract_python_code_from_md(mx_file)
|
|
81
|
+
|
|
82
|
+
namespace = {}
|
|
83
|
+
exec("from pythonfmu3 import *", namespace)
|
|
84
|
+
|
|
85
|
+
for i, code in enumerate(code_blocks):
|
|
86
|
+
try:
|
|
87
|
+
exec(code, namespace)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
pytest.fail(f"MX Code block {i+1} failed: {e}")
|
|
90
|
+
|
|
91
|
+
# Test that classes were actually created
|
|
92
|
+
assert 'VanDerPol' in namespace, "VanDerPol class not found"
|
|
93
|
+
assert 'BouncingBall' in namespace, "BouncingBall class not found"
|
|
94
|
+
|
|
95
|
+
# Test instantiation
|
|
96
|
+
vdp = namespace['VanDerPol'](instance_name="test")
|
|
97
|
+
|
|
98
|
+
bb = namespace['BouncingBall'](instance_name="test")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonfmu3
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: A lightweight framework that enables the packaging of Python3.x code as co-simulation FMUs.
|
|
5
5
|
Home-page: https://github.com/stephensmith25/PythonFMU3
|
|
6
6
|
Author: Stephen Smith
|
|
@@ -44,15 +44,6 @@ This project is a fork of the original PythonFMU repository available at https:/
|
|
|
44
44
|
Please take a look at the examples to see the supported features.
|
|
45
45
|
We currently support both the Model exchange and Cosimulation Interfaces.
|
|
46
46
|
|
|
47
|
-
For both interfaces event mode is not supported.
|
|
48
|
-
|
|
49
|
-
We currently do not support the following methods (beyond a default, trivial implementation)
|
|
50
|
-
|
|
51
|
-
- fmi3UpdateDiscreteStates
|
|
52
|
-
- fmi3GetNumberOfEventindicators
|
|
53
|
-
- fmi3GetNominalsOfContinuousStates
|
|
54
|
-
- fmi3EvaluateDiscreteStates
|
|
55
|
-
|
|
56
47
|
### How do I build an FMU from python code?
|
|
57
48
|
|
|
58
49
|
1. Install `pythonfmu3` package:
|
|
@@ -182,6 +173,7 @@ To create a model exchange FMU you must inherit from `Fmi3SlaveBase` and one of
|
|
|
182
173
|
```python
|
|
183
174
|
|
|
184
175
|
from pythonfmu3 import Fmi3Causality, Fmi3SlaveBase, Float64, ModelExchange
|
|
176
|
+
from typing import List
|
|
185
177
|
|
|
186
178
|
|
|
187
179
|
class PythonSlaveMX(Fmi3SlaveBase, ModelExchange):
|
|
@@ -47,6 +47,7 @@ pythonfmu3/tests/__init__.py
|
|
|
47
47
|
pythonfmu3/tests/conftest.py
|
|
48
48
|
pythonfmu3/tests/test_builder.py
|
|
49
49
|
pythonfmu3/tests/test_deploy.py
|
|
50
|
+
pythonfmu3/tests/test_docs.py
|
|
50
51
|
pythonfmu3/tests/test_fmi3slave.py
|
|
51
52
|
pythonfmu3/tests/test_integration.py
|
|
52
53
|
pythonfmu3/tests/test_logger.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.1"
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
from abc import ABC, ABCMeta, abstractmethod
|
|
2
|
-
|
|
3
|
-
class RequireTimeMeta(ABCMeta):
|
|
4
|
-
def __init__(cls, name, bases, namespace):
|
|
5
|
-
super().__init__(name, bases, namespace)
|
|
6
|
-
orig_init = cls.__init__
|
|
7
|
-
def new_init(self, *args, **kwargs):
|
|
8
|
-
orig_init(self, *args, **kwargs)
|
|
9
|
-
if not hasattr(self, 'time'):
|
|
10
|
-
raise AttributeError(f"{cls.__name__} must define 'self.time' in __init__")
|
|
11
|
-
cls.__init__ = new_init
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# model exchange mixin
|
|
15
|
-
class ModelExchange(ABC, metaclass=RequireTimeMeta):
|
|
16
|
-
"""
|
|
17
|
-
Classes derived from ModelExchange must define a 'self.time' member variable.
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
@abstractmethod
|
|
21
|
-
def get_continuous_state_derivatives(self):
|
|
22
|
-
"""Return the continuous state derivatives of the model."""
|
|
23
|
-
pass
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_common.hpp
RENAMED
|
File without changes
|
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/fmi/fmi3FunctionTypes.h
RENAMED
|
File without changes
|
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/fmi/fmi3PlatformTypes.h
RENAMED
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.3}/pythonfmu3/pythonfmu-export/src/pythonfmu/IPyState.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|