pythonfmu3 0.3.1__tar.gz → 0.3.2__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.2}/PKG-INFO +1 -10
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/README.md +0 -9
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/__init__.py +1 -1
- pythonfmu3-0.3.2/pythonfmu3/_version.py +1 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/fmi3slave.py +13 -2
- pythonfmu3-0.3.2/pythonfmu3/modelexchange.py +52 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.hpp +1 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/cppfmu/fmi_functions.cpp +11 -1
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp +85 -10
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp +1 -0
- pythonfmu3-0.3.2/pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so +0 -0
- pythonfmu3-0.3.2/pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2/pythonfmu3.egg-info}/PKG-INFO +1 -10
- 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.2}/LICENSE +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/MANIFEST.in +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/__main__.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/builder.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/cosimulation.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/default_experiment.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/deploy.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/enums.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/logmsg.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/osutil.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/.clang-format +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/CMakeLists.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/build_unix.sh +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/build_win.sh +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/CMakeLists.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_common.hpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.cpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/fmi/fmi3FunctionTypes.h +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/fmi/fmi3Functions.h +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/fmi/fmi3PlatformTypes.h +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/pythonfmu/IPyState.hpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/pythonfmu/PyState.hpp +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/__init__.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/conftest.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/data/csvdemo.csv +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/data/hello.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/slaves/PythonSlaveWithException.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/slaves/localmodule.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/slaves/pythonslave.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/slaves/pythonslaveMX.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/slaves/pythonslaveMXCS.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/slaves/pythonslave_read_file.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/slaves/slavewithdep.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/test_builder.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/test_deploy.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/test_fmi3slave.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/test_integration.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/test_logger.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/test_multiple_fmus.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/test_variables.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/tests/utils.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/unit.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/variable_types.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/variables.py +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3.egg-info/SOURCES.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3.egg-info/dependency_links.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3.egg-info/entry_points.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3.egg-info/not-zip-safe +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3.egg-info/requires.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3.egg-info/top_level.txt +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/setup.cfg +0 -0
- {pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/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.2
|
|
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:
|
|
@@ -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:
|
|
@@ -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.2"
|
|
@@ -50,6 +50,7 @@ class Fmi3SlaveBase(object):
|
|
|
50
50
|
|
|
51
51
|
def __init__(self, **kwargs):
|
|
52
52
|
self.vars = OrderedDict()
|
|
53
|
+
self.event_indicators: List[int] = []
|
|
53
54
|
self.instance_name = kwargs["instance_name"]
|
|
54
55
|
self.resources = kwargs.get("resources", None)
|
|
55
56
|
self.visible = kwargs.get("visible", False)
|
|
@@ -184,7 +185,8 @@ class Fmi3SlaveBase(object):
|
|
|
184
185
|
for v in initial_unknown:
|
|
185
186
|
SubElement(structure, "InitialUnknown", attrib=dict(valueReference=str(v.value_reference)))
|
|
186
187
|
|
|
187
|
-
|
|
188
|
+
for v in self.event_indicators:
|
|
189
|
+
SubElement(structure, "EventIndicator", attrib=dict(valueReference=str(v)))
|
|
188
190
|
|
|
189
191
|
return root
|
|
190
192
|
|
|
@@ -206,7 +208,7 @@ class Fmi3SlaveBase(object):
|
|
|
206
208
|
raise Exception(f"Unsupported type {type(var)}!")
|
|
207
209
|
var.start = refs if len(getattr(var, "dimensions", [])) > 0 else refs[0]
|
|
208
210
|
|
|
209
|
-
def register_variable(self, var: ModelVariable, nested: bool = True, var_type: Any = None):
|
|
211
|
+
def register_variable(self, var: ModelVariable, nested: bool = True, var_type: Any = None, has_event_indicator: bool = False):
|
|
210
212
|
"""Register a variable as FMU interface.
|
|
211
213
|
|
|
212
214
|
Args:
|
|
@@ -238,6 +240,12 @@ class Fmi3SlaveBase(object):
|
|
|
238
240
|
if var_type:
|
|
239
241
|
self.type_definitions[var_type.name] = var_type
|
|
240
242
|
var.declared_type = var_type.name
|
|
243
|
+
|
|
244
|
+
if has_event_indicator:
|
|
245
|
+
self.register_event_indicator(var.value_reference)
|
|
246
|
+
|
|
247
|
+
def register_event_indicator(self, vr):
|
|
248
|
+
self.event_indicators.append(vr)
|
|
241
249
|
|
|
242
250
|
def setup_experiment(self, start_time: float):
|
|
243
251
|
pass
|
|
@@ -416,6 +424,9 @@ class Fmi3SlaveBase(object):
|
|
|
416
424
|
if v.setter is not None:
|
|
417
425
|
v.setter(value)
|
|
418
426
|
|
|
427
|
+
def get_number_of_event_indicators(self) -> int:
|
|
428
|
+
return len(self.event_indicators)
|
|
429
|
+
|
|
419
430
|
def set_continuous_states(self, values: List[float]):
|
|
420
431
|
offset = 0
|
|
421
432
|
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.2}/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.2}/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.2}/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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonfmu3
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
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:
|
|
@@ -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
|
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_common.hpp
RENAMED
|
File without changes
|
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/fmi/fmi3FunctionTypes.h
RENAMED
|
File without changes
|
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/pythonfmu3/pythonfmu-export/src/fmi/fmi3PlatformTypes.h
RENAMED
|
File without changes
|
{pythonfmu3-0.3.1 → pythonfmu3-0.3.2}/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
|
|
File without changes
|
|
File without changes
|