Skip to content

Commit 2d94159

Browse files
committed
✨ get properties values et and set property values in ModelicaFmuModel
1 parent c658b72 commit 2d94159

2 files changed

Lines changed: 61 additions & 32 deletions

File tree

corrai/fmu.py

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,37 @@
22
import shutil
33
import tempfile
44
import warnings
5-
from pathlib import Path
65
from contextlib import contextmanager
6+
from pathlib import Path
77

88
import fmpy
9-
from fmpy import simulate_fmu
109
import pandas as pd
10+
from fmpy import simulate_fmu
1111
from sklearn.pipeline import Pipeline
1212

1313
from corrai.base.model import Model
1414

15+
MODEL_VARIABLES_TYPES_MAP = {
16+
"Real": float,
17+
"Float32": float,
18+
"Float64": float,
19+
"Integer": int,
20+
"Int8": int,
21+
"UInt8": int,
22+
"Int16": int,
23+
"UInt16": int,
24+
"Int32": int,
25+
"UInt32": int,
26+
"Int64": int,
27+
"UInt64": int,
28+
"Boolean": bool,
29+
"String": str,
30+
# Not yet implemented
31+
# ('Enumeration'),
32+
# ('Binary'),
33+
# ('Clock'),
34+
}
35+
1536
DEFAULT_SIMULATION_OPTIONS = {
1637
"startTime": 0,
1738
"stopTime": 24 * 3600,
@@ -271,7 +292,6 @@ def __init__(
271292
simulation_dir: Path = None,
272293
output_list: list[str] = None,
273294
boundary_table_name: str | None = None,
274-
default_properties: dict[str, float | int | str] = None,
275295
):
276296
super().__init__(is_dynamic=True)
277297
fmu_path = Path(fmu_path) if isinstance(fmu_path, str) else fmu_path
@@ -298,7 +318,26 @@ def __init__(
298318
UserWarning,
299319
stacklevel=2,
300320
)
301-
self.default_properties = default_properties or {}
321+
self.property_dict = self._get_init_property_dict()
322+
323+
def _get_init_property_dict(self):
324+
model_description = fmpy.read_model_description(self.fmu_path.as_posix())
325+
fmu_param_dict = {
326+
var.name: var
327+
for var in model_description.modelVariables
328+
if var.causality == "parameter"
329+
}
330+
prop_dict = {}
331+
for name, var in fmu_param_dict.items():
332+
try:
333+
prop_dict[name] = MODEL_VARIABLES_TYPES_MAP[var.type](var.start)
334+
except TypeError:
335+
prop_dict[name] = var.start
336+
337+
except KeyError:
338+
pass
339+
340+
return prop_dict
302341

303342
def get_property_values(
304343
self, property_list: str | tuple[str, ...] | list[str]
@@ -325,22 +364,13 @@ def get_property_values(
325364
>>> model.get_property_values(["x.k", "y.k"])
326365
['2.0', '2.0']
327366
"""
328-
if isinstance(property_list, str):
329-
property_list = (property_list,)
367+
property_list = (
368+
[property_list] if isinstance(property_list, str) else property_list
369+
)
370+
return [self.property_dict[prop] for prop in property_list]
330371

331-
model_description = fmpy.read_model_description(self.fmu_path.as_posix())
332-
variable_map = {var.name: var for var in model_description.modelVariables}
333-
values = []
334-
for prop in property_list:
335-
if prop in variable_map:
336-
try:
337-
val = float(variable_map[prop].start)
338-
except (ValueError, TypeError):
339-
val = variable_map[prop].start
340-
values.append(val)
341-
else:
342-
values.append(None)
343-
return values
372+
def set_property_values(self, property_dict: dict):
373+
self.property_dict.update(property_dict.items())
344374

345375
def simulate(
346376
self,
@@ -442,13 +472,12 @@ def simulate(
442472
2.0 3.0
443473
444474
"""
445-
property_dict = dict(property_dict or {})
446-
merged_properties = self.default_properties.copy()
447-
if property_dict:
448-
merged_properties.update(property_dict)
449-
property_dict = merged_properties
475+
476+
simu_property = self.property_dict.copy()
477+
simu_property.update(dict(property_dict or {}))
478+
450479
if property_dict and debug_param:
451-
print(property_dict)
480+
print(simu_property)
452481

453482
simulation_options = {
454483
**DEFAULT_SIMULATION_OPTIONS,
@@ -468,8 +497,8 @@ def simulate(
468497
)
469498

470499
boundary_df = None
471-
if property_dict:
472-
boundary_df = property_dict.pop("boundary", boundary_df)
500+
if simu_property:
501+
boundary_df = simu_property.pop("boundary", boundary_df)
473502

474503
if simulation_options:
475504
sim_boundary = simulation_options.pop("boundary", boundary_df)
@@ -505,7 +534,7 @@ def simulate(
505534
local_boundary,
506535
):
507536
if local_boundary is not None and self.boundary_table_name:
508-
property_dict[f"{self.boundary_table_name}.fileName"] = (
537+
simu_property[f"{self.boundary_table_name}.fileName"] = (
509538
local_boundary.as_posix()
510539
)
511540

@@ -515,7 +544,7 @@ def simulate(
515544
stop_time=stop_sec,
516545
step_size=step_sec,
517546
relative_tolerance=simulation_options["tolerance"],
518-
start_values=property_dict,
547+
start_values=simu_property,
519548
output=self.output_list,
520549
solver=simulation_options["solver"],
521550
output_interval=output_int_sec,

tests/test_fmu.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,6 @@ def test_get_property_values(self):
141141
fmu_path=PACKAGE_DIR / "rosen.fmu",
142142
output_list=["res.showNumber"],
143143
)
144-
values = simu.get_property_values(("res.showNumber",))
145-
assert isinstance(values, list)
146-
assert len(values) == 1
147144

148145
vals = simu.get_property_values("x.k")
149146
assert vals == [2.0]
@@ -154,6 +151,9 @@ def test_get_property_values(self):
154151
vals = simu.get_property_values(["x.k", "y.k"])
155152
assert vals == [2.0, 2.0]
156153

154+
simu.set_property_values({"x.k": 3.0})
155+
assert simu.get_property_values("x.k") == [3.0]
156+
157157
def test_simulate_parallel(self):
158158
simu = ModelicaFmuModel(
159159
fmu_path=PACKAGE_DIR / "rosen.fmu",

0 commit comments

Comments
 (0)