22import shutil
33import tempfile
44import warnings
5- from pathlib import Path
65from contextlib import contextmanager
6+ from pathlib import Path
77
88import fmpy
9- from fmpy import simulate_fmu
109import pandas as pd
10+ from fmpy import simulate_fmu
1111from sklearn .pipeline import Pipeline
1212
1313from 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+
1536DEFAULT_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 ,
0 commit comments