pythonfmu3 0.1.10__py3-none-any.whl → 0.1.12__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.
pythonfmu3/__init__.py CHANGED
@@ -4,4 +4,5 @@ from .enums import Fmi3Causality, Fmi3Initial, Fmi3Variability
4
4
  from .fmi3slave import Fmi3Slave
5
5
  from .variables import Boolean, Enumeration, Int32, Int64, UInt64, Float64, String, Dimension
6
6
  from .default_experiment import DefaultExperiment
7
- from .type_definitions import TypeDefinitions, Item, EnumerationType
7
+ from .variable_types import Float64Type, EnumerationType
8
+ from .unit import BaseUnit, Unit
pythonfmu3/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.10"
1
+ __version__ = "0.1.12"
pythonfmu3/fmi3slave.py CHANGED
@@ -11,10 +11,11 @@ from xml.etree.ElementTree import Element, SubElement
11
11
 
12
12
  from .logmsg import LogMsg
13
13
  from .default_experiment import DefaultExperiment
14
- from .type_definitions import TypeDefinitions
15
14
  from ._version import __version__ as VERSION
16
15
  from .enums import Fmi3Type, Fmi3Status, Fmi3Causality, Fmi3Initial, Fmi3Variability
17
16
  from .variables import Boolean, Enumeration, Int32, Int64, UInt64, Float64, ModelVariable, String
17
+ from .variable_types import VariableType
18
+ from .unit import Unit
18
19
 
19
20
  ModelOptions = namedtuple("ModelOptions", ["name", "value", "cli"])
20
21
 
@@ -54,7 +55,9 @@ class Fmi3Slave(ABC):
54
55
  self.modelName: Optional[str] = self.__class__.__name__
55
56
  self.description: Optional[str] = None
56
57
  self.default_experiment: Optional[DefaultExperiment] = None
57
- self.type_definitions: Optional[TypeDefinitions] = None
58
+
59
+ self.type_definitions: Dict[str, VariableType] = {}
60
+ self.units: Dict[str, Unit] = {}
58
61
 
59
62
  def to_xml(self, model_options: Dict[str, str] = dict()) -> Element:
60
63
  """Build the XML representation of the model.
@@ -99,8 +102,15 @@ class Fmi3Slave(ABC):
99
102
 
100
103
  SubElement(root, "CoSimulation", attrib=options)
101
104
 
102
- if self.type_definitions is not None:
103
- root.append(self.type_definitions.to_xml())
105
+ if self.units:
106
+ unit_defs = SubElement(root, "UnitDefinitions")
107
+ for _, unit in self.units.items():
108
+ unit_defs.append(unit.to_xml())
109
+
110
+ if self.type_definitions:
111
+ type_defs = SubElement(root, "TypeDefinitions")
112
+ for _, val in self.type_definitions.items():
113
+ type_defs.append(val.to_xml())
104
114
 
105
115
  if len(self.log_categories) > 0:
106
116
  categories = SubElement(root, "LogCategories")
@@ -178,7 +188,7 @@ class Fmi3Slave(ABC):
178
188
  raise Exception(f"Unsupported type {type(var)}!")
179
189
  var.start = refs if len(getattr(var, "dimensions", [])) > 0 else refs[0]
180
190
 
181
- def register_variable(self, var: ModelVariable, nested: bool = True):
191
+ def register_variable(self, var: ModelVariable, nested: bool = True, units: str = "", var_type: Any = None):
182
192
  """Register a variable as FMU interface.
183
193
 
184
194
  Args:
@@ -206,10 +216,18 @@ class Fmi3Slave(ABC):
206
216
  var.setter = lambda v: setattr(owner, var.local_name, np.reshape(v, newshape=getattr(owner, var.local_name).shape))
207
217
  else:
208
218
  var.setter = lambda v: setattr(owner, var.local_name, v)
219
+
220
+ if var_type:
221
+ self.type_definitions[var_type.name] = var_type
222
+ var.declared_type = var_type.name
209
223
 
210
224
  def setup_experiment(self, start_time: float):
211
225
  pass
212
226
 
227
+ def register_units(self, units: List[Unit]):
228
+ for unit in units:
229
+ self.units[unit.name] = unit
230
+
213
231
  def enter_initialization_mode(self):
214
232
  pass
215
233
 
pythonfmu3/unit.py ADDED
@@ -0,0 +1,62 @@
1
+ from xml.etree.ElementTree import Element
2
+
3
+ class BaseUnit(object):
4
+ tag = "BaseUnit"
5
+ base_units = {
6
+ "kg": 0,
7
+ "m": 0,
8
+ "s": 0,
9
+ "A": 0,
10
+ "K": 0,
11
+ "mol": 0,
12
+ "cd": 0,
13
+ "rad": 0,
14
+ }
15
+
16
+ def __init__(self, factor=1.0, offset=0.0, **kwargs) -> None:
17
+ self._factor = factor
18
+ self._offset = offset
19
+ self._units = {**BaseUnit.base_units, **kwargs}
20
+
21
+ @property
22
+ def units(self):
23
+ return {key: str(value) for key, value in self._units.items() if value != 0}
24
+
25
+ def to_xml(self):
26
+ """Convert the variable to XML node.
27
+
28
+ Returns
29
+ xml.etree.ElementTree.Element: XML node
30
+ """
31
+ attrib = dict()
32
+ if self._factor != 1.0:
33
+ attrib["factor"] = str(self._factor)
34
+ if self._offset != 0.0:
35
+ attrib["offset"] = str(self._offset)
36
+ attrib.update(self.units)
37
+ ele = Element(self.tag, attrib)
38
+ return ele
39
+
40
+
41
+ class Unit(object):
42
+ tag = "Unit"
43
+
44
+ def __init__(self, name, **kwargs):
45
+ self._name = name
46
+ self._base_unit = BaseUnit(**kwargs)
47
+
48
+ @property
49
+ def name(self) -> str:
50
+ return self._name
51
+
52
+ def to_xml(self) -> Element:
53
+ """Convert the variable to XML node.
54
+
55
+ Returns
56
+ xml.etree.ElementTree.Element: XML node
57
+ """
58
+ attrib = dict()
59
+ attrib["name"] = self._name
60
+ ele = Element(self.tag, attrib)
61
+ ele.append(self._base_unit.to_xml())
62
+ return ele
@@ -1,13 +1,20 @@
1
1
  from enum import Enum
2
- from typing import Any, Optional, List
2
+ from typing import Optional
3
3
  from xml.etree.ElementTree import Element
4
4
 
5
+ class VariableType(object):
5
6
 
6
- class TypeDefinitions(object):
7
- tag = "TypeDefinitions"
8
-
9
- def __init__(self, types: List[Any]):
10
- self.types = types
7
+ def __init__(self, tag, name, **kwargs):
8
+ self._tag = tag
9
+ self._attrs = {
10
+ "name": name,
11
+ }
12
+ self._attrs.update(**kwargs)
13
+
14
+ @property
15
+ def name(self) -> str:
16
+ """str: Variable name"""
17
+ return self._attrs["name"]
11
18
 
12
19
  def to_xml(self) -> Element:
13
20
  """Convert the variable to XML node.
@@ -16,19 +23,25 @@ class TypeDefinitions(object):
16
23
  xml.etree.ElementTree.Element: XML node
17
24
  """
18
25
  attrib = dict()
19
- ele = Element(self.tag, attrib)
20
- for definition in self.types:
21
- ele.append(definition.to_xml())
22
- return ele
26
+ for key, value in self._attrs.items():
27
+ if value is not None:
28
+ attrib[key] = str(value.name if isinstance(value, Enum) else value)
29
+ return Element(self._tag, attrib)
30
+
31
+ class Float64Type(VariableType):
32
+ tag = "Float64Type"
33
+
34
+ def __init__(self, name, **kwargs):
35
+ super().__init__(self.tag, name, **kwargs)
23
36
 
24
37
 
25
38
  class Item(object):
26
39
  tag = "Item"
27
40
 
28
- def __init__(self, name: str, value: str, description: str = ""):
41
+ def __init__(self, name: str, value: int, description: str = "", **kwargs):
29
42
  self.__attrs = {
30
43
  "name": name,
31
- "value": value,
44
+ "value": str(value),
32
45
  "description": description
33
46
  }
34
47
 
@@ -61,18 +74,21 @@ class Item(object):
61
74
  f"value={self.value}, " \
62
75
  f"description={self.description})"
63
76
 
64
-
65
- class EnumerationType(object):
77
+ class EnumerationType(VariableType):
66
78
  tag = "EnumerationType"
67
79
 
68
- def __init__(self, name: str, items = List[Item]):
69
- self.__attrs = {
70
- "name": name
71
- }
72
- self._items = items
80
+ def __init__(self, name: str, values: Optional[Enum] = None, **kwargs):
81
+ super().__init__(self.tag, name, **kwargs)
82
+ self._items = {}
83
+
84
+ for val in values:
85
+ self.add_value(name = val.name, value = val.value)
73
86
 
74
- def name(self) -> str:
75
- return self.__attrs["name"]
87
+ def add_value(self, name: str, value: int, description: str = "", **kwargs):
88
+ self._items[name] = Item(name, value, description, **kwargs)
89
+
90
+ def get_value(self, name):
91
+ return self._items[name]
76
92
 
77
93
  def to_xml(self) -> Element:
78
94
  """Convert the variable to XML node.
@@ -80,7 +96,7 @@ class EnumerationType(object):
80
96
  Returns
81
97
  xml.etree.ElementTree.Element: XML node
82
98
  """
83
- element = Element(self.tag, self.__attrs)
84
- for item in self._items:
85
- element.append(item.to_xml())
86
- return element
99
+ parent = super().to_xml()
100
+ for _, item in self._items.items():
101
+ parent.append(item.to_xml())
102
+ return parent
pythonfmu3/variables.py CHANGED
@@ -32,6 +32,7 @@ class ModelVariable(ABC):
32
32
  description: Optional[str] = None,
33
33
  initial: Optional[Fmi3Initial] = None,
34
34
  variability: Optional[Fmi3Variability] = None,
35
+ declared_type: Optional[str] = None,
35
36
  getter: Any = None,
36
37
  setter: Any = None
37
38
  ):
@@ -46,6 +47,7 @@ class ModelVariable(ABC):
46
47
  "causality": causality,
47
48
  "variability": variability,
48
49
  "initial": initial,
50
+ "declaredType": declared_type,
49
51
  # 'canHandleMultipleSetPerTimeInstant': # Only for ME
50
52
  }
51
53
  self._extras = {}
@@ -81,6 +83,17 @@ class ModelVariable(ABC):
81
83
  raise RuntimeError("Value reference already set.")
82
84
  self.__attrs["valueReference"] = value
83
85
 
86
+ @property
87
+ def declared_type(self) -> str:
88
+ """str: declared type"""
89
+ return self.__attrs["declaredType"]
90
+
91
+ @declared_type.setter
92
+ def declared_type(self, value: str):
93
+ if self.__attrs["declaredType"] is not None:
94
+ raise RuntimeError("Declared type already set.")
95
+ self.__attrs["declaredType"] = value
96
+
84
97
  @property
85
98
  def variability(self) -> Optional[Fmi3Variability]:
86
99
  """:obj:`Fmi3Variability` or None: Variable variability - None if not set"""
@@ -145,10 +158,11 @@ class Dimension(object):
145
158
  return ele
146
159
 
147
160
  class Float64(ModelVariable):
148
- def __init__(self, name: str, start: Optional[Any] = None, derivative: Optional[Any] = None, dimensions: List[Dimension] = [], **kwargs):
161
+ def __init__(self, name: str, start: Optional[Any] = None, derivative: Optional[Any] = None, dimensions: List[Dimension] = [], unit: Optional[str] = None, **kwargs):
149
162
  super().__init__(name, **kwargs)
150
163
  self.__attrs = {"start": start, "derivative": derivative}
151
164
  self._type = "Float64"
165
+ self._unit = unit
152
166
  if dimensions:
153
167
  check_numpy()
154
168
  self.__dimensions = dimensions
@@ -160,6 +174,14 @@ class Float64(ModelVariable):
160
174
  @start.setter
161
175
  def start(self, value: float):
162
176
  self.__attrs["start"] = value
177
+
178
+ @property
179
+ def unit(self) -> Optional[Any]:
180
+ return self._unit
181
+
182
+ @unit.setter
183
+ def unit(self, value: str):
184
+ self._unit = value
163
185
 
164
186
  @property
165
187
  def derivative(self):
@@ -169,6 +191,7 @@ class Float64(ModelVariable):
169
191
  def dimensions(self) -> List[Dimension]:
170
192
  return self.__dimensions
171
193
 
194
+
172
195
  def to_xml(self) -> Element:
173
196
  attrib = dict()
174
197
  for key, value in self.__attrs.items():
@@ -181,6 +204,10 @@ class Float64(ModelVariable):
181
204
  else:
182
205
  output = f"{value:.16g}"
183
206
  attrib[key] = output
207
+
208
+ if self.unit:
209
+ attrib["unit"] = self.unit
210
+
184
211
  self._extras = attrib
185
212
  parent = super().to_xml()
186
213
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pythonfmu3
3
- Version: 0.1.10
3
+ Version: 0.1.12
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
@@ -21,8 +21,8 @@ Classifier: Topic :: Scientific/Engineering
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
23
  Provides-Extra: tests
24
- Requires-Dist: pytest ; extra == 'tests'
25
- Requires-Dist: fmpy ; extra == 'tests'
24
+ Requires-Dist: pytest; extra == "tests"
25
+ Requires-Dist: fmpy; extra == "tests"
26
26
 
27
27
  # PythonFMU3
28
28
 
@@ -40,13 +40,7 @@ This project is a fork of the original PythonFMU repository available at https:/
40
40
 
41
41
  ### Support:
42
42
 
43
- We currently support a basic FMU which follows the FMI3 standard. This includes support for:
44
-
45
- - Float64, Int32, UInt64, String, Boolean variables
46
- - Step Mode
47
- - Arrays, which requires the numpy package
48
-
49
- Please take a look at the examples bouncingBall.py and linearTransform.py for a demonstration of these features.
43
+ Please take a look at the examples to see the supported features.
50
44
 
51
45
  ### Future
52
46
 
@@ -55,7 +49,6 @@ In no particular order, we plan to add support for:
55
49
  - Support more variable types from FMI3
56
50
  - Improve array support
57
51
  - Add event mode
58
- - Include FMI3 related testing
59
52
 
60
53
  ### How do I build an FMU from python code?
61
54
 
@@ -1,15 +1,16 @@
1
- pythonfmu3/__init__.py,sha256=aTB9p2E_p6D6-KeUa1HGfzH88i_8Oin3JNApVD2D5HQ,375
1
+ pythonfmu3/__init__.py,sha256=PT1R0LpSInyVdXGJbkWMTQym6_SEU7CqUkG7OH5j1f0,396
2
2
  pythonfmu3/__main__.py,sha256=gC1T8x2d02hhqshyNQGSS70SyCk-3I3t8zPqoRo2Xd8,1543
3
- pythonfmu3/_version.py,sha256=z0zCHFTcKSR0tJ6h5qrpNmRVP21QIPP8N0p7quCnnm0,23
3
+ pythonfmu3/_version.py,sha256=LcIlFjHZFfiF9Rd4UHoakmombOFkxIYk00I181frGBM,23
4
4
  pythonfmu3/builder.py,sha256=YLTeLLpiFOkoDYwnJ55GEhb3ham0xxROMjMN6bvaw5Y,8784
5
5
  pythonfmu3/default_experiment.py,sha256=FJ0l0FpU7pT4Pox2RiA2y-Cb_e7DE2XlbWKySRYQaVk,293
6
6
  pythonfmu3/deploy.py,sha256=eqFWVxZUkJCLvmq1-GuMNjn2j0VCGoaXPhRWrCk2Vxg,3741
7
7
  pythonfmu3/enums.py,sha256=ZmC6vGeBTGt7HarPQ4uYV10ezPsvIxAHH1ypjNq7G3E,729
8
- pythonfmu3/fmi3slave.py,sha256=sJvODS7_adGYR4Ki4cBlmX-1LMxiK2iHrBKL0WqzDmI,15962
8
+ pythonfmu3/fmi3slave.py,sha256=KoKVXNsuDiKjJT_vPxi0WOtFGriQjgmj6qtWj1GclZw,16586
9
9
  pythonfmu3/logmsg.py,sha256=0wn11GLwq0LLWqyC2ktLRjQFWlpj07wWliZ8rUHx1gg,359
10
10
  pythonfmu3/osutil.py,sha256=KMAoMf_BpqFQQUy3WzHnt9jiklkS1xy0syIbj7kNH6A,656
11
- pythonfmu3/type_definitions.py,sha256=gcwe5HueMBfOuHk6pkf6TNJHKfUtqga_DNbj0o13XKk,2219
12
- pythonfmu3/variables.py,sha256=sKVOnITuirzHIMAC2f9CrKlGX8-R-dGoteKS-QCv2nk,10838
11
+ pythonfmu3/unit.py,sha256=SjOaywb5lVQbAO_iLjc_7Ly3nYrmAvIW2_hAGt12UFU,1475
12
+ pythonfmu3/variable_types.py,sha256=Q0D4wlGi3i3zE5UsmGJEpNh7SV_W8mn_8p_WIkwrLQA,2881
13
+ pythonfmu3/variables.py,sha256=mCu0nY09Snt8tGuAjlKmbtX5J4Cp0TwaaLYjmnjrmF8,11562
13
14
  pythonfmu3/pythonfmu-export/.clang-format,sha256=ApbsHWYwilCXJ1iBux4nqOjLkaqgbGLsVrc_U3hX7WI,944
14
15
  pythonfmu3/pythonfmu-export/CMakeLists.txt,sha256=p0-4Xh_sAaOI9AVb8lsUsMxJPc6bg9b_6CF6NJt5FHE,1847
15
16
  pythonfmu3/pythonfmu-export/build_unix.sh,sha256=I5RrF2O6y0hRG_SN4ExKN_CCFYaa2l-ngKzqmBXnHmA,73
@@ -25,8 +26,8 @@ pythonfmu3/pythonfmu-export/src/fmi/fmi3PlatformTypes.h,sha256=ZCQLJgSbRGrMsBiQ4
25
26
  pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp,sha256=uVGq0QcTySLjgTd3_fe-csPenT89DukCPL4u_j4rDew,22610
26
27
  pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp,sha256=XvRaA0OvB9MRSxFUP64TvHsLEP4CSOn0WcfImegS2_8,3954
27
28
  pythonfmu3/pythonfmu-export/src/pythonfmu/PyState.hpp,sha256=PApY1VOpEJbzrnQjKB1-UoTKKCzaDbIGF-dZt6f3Uls,717
28
- pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so,sha256=-xeuSKeqjB5_96yRhInnWCPh6kBXmlOHNeRzZZfOG9M,353232
29
- pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll,sha256=itKDopGQbFf_7BJDOZSctnRsamjyx5sVslfrAWWnyFk,417280
29
+ pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so,sha256=xTe9Sa52kpQqL8HFZtx-0Wm502N5GgkAeguDepUhloY,353232
30
+ pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll,sha256=OVZxmPljRrP-TA3s1R0ZdxLJadX_l3ED88HCgwo72U8,417792
30
31
  pythonfmu3/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
32
  pythonfmu3/tests/conftest.py,sha256=B6XxTnBdeF_tEJ3w2DlfPKUfvlk-oULgIhQtXkgOJIc,171
32
33
  pythonfmu3/tests/test_builder.py,sha256=StR9oNmF6dtuxxKtPFlncLQN-O7n97nvHm6EFH4Qn14,6252
@@ -44,9 +45,9 @@ pythonfmu3/tests/slaves/localmodule.py,sha256=-q5Lmh2I88MG7nLTscms0n5xhHLkUDed1I
44
45
  pythonfmu3/tests/slaves/pythonslave.py,sha256=H75vLhqshSWWvMj2NQt6a_aQhA6BGSkBVJstjjVE0AU,2024
45
46
  pythonfmu3/tests/slaves/pythonslave_read_file.py,sha256=NIAmyZZGNAcnqf8R5jb1yFcQxj6iSMOAc13pY0GFtco,634
46
47
  pythonfmu3/tests/slaves/slavewithdep.py,sha256=4yqxa0vsOTLLvtaUQFkjfU9OcwjDUtuUe-qIjnD-jrw,647
47
- pythonfmu3-0.1.10.dist-info/LICENSE,sha256=24Cw_MPouLK-G_t8Hgjm59IS9BnPoL6SKkyuZ0xesXY,1155
48
- pythonfmu3-0.1.10.dist-info/METADATA,sha256=P0EXnuAfYYGxZMM0YIYUIX_SKWp5bNYXKrCPv0gkAz0,7597
49
- pythonfmu3-0.1.10.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
50
- pythonfmu3-0.1.10.dist-info/entry_points.txt,sha256=GgkWYs0DKGHLcijMEYZGkhkHOK2RVUpjGwvl1fwyDwQ,60
51
- pythonfmu3-0.1.10.dist-info/top_level.txt,sha256=6ne7bh_cME1hepxCx1BG8N5QVhVAufrp7LLok6vq7nE,11
52
- pythonfmu3-0.1.10.dist-info/RECORD,,
48
+ pythonfmu3-0.1.12.dist-info/LICENSE,sha256=24Cw_MPouLK-G_t8Hgjm59IS9BnPoL6SKkyuZ0xesXY,1155
49
+ pythonfmu3-0.1.12.dist-info/METADATA,sha256=N--5rVV8JGikRz4Y9nO2FaC_B7j6ACASPbUSRG4gXkU,7315
50
+ pythonfmu3-0.1.12.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
51
+ pythonfmu3-0.1.12.dist-info/entry_points.txt,sha256=GgkWYs0DKGHLcijMEYZGkhkHOK2RVUpjGwvl1fwyDwQ,60
52
+ pythonfmu3-0.1.12.dist-info/top_level.txt,sha256=6ne7bh_cME1hepxCx1BG8N5QVhVAufrp7LLok6vq7nE,11
53
+ pythonfmu3-0.1.12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.1)
2
+ Generator: setuptools (73.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5