11import os
22import tempfile
3+ import warnings
34from pathlib import Path
45
56import pandas as pd
@@ -15,7 +16,6 @@ def __init__(
1516 self ,
1617 model_path : Path | str ,
1718 simulation_options : dict [str , float | str | int ] = None ,
18- x : pd .DataFrame = None ,
1919 output_list : list [str ] = None ,
2020 simulation_path : Path = None ,
2121 x_combitimetable_name : str = None ,
@@ -33,9 +33,6 @@ def __init__(
3333 - simulation_options (dict[str, float | str | int], optional):
3434 Options for the simulation. May include values for "startTime",
3535 "stopTime", "stepSize", "tolerance", "solver", "outputFormat".
36- - x (pd.DataFrame, optional): Input data for the simulation. Index shall
37- be a DatetimeIndex or integers. Columns must match the combi time table
38- used to specify boundary conditions in the Modelica System.
3936 - output_list (list[str], optional): List of output variables. Default
4037 will output all available variables.
4138 - simulation_path (Path, optional): Path to run the simulation and
@@ -57,7 +54,7 @@ def __init__(
5754 if not os .path .exists (self ._simulation_path ):
5855 os .mkdir (simulation_path )
5956
60- self ._x = x if x is not None else pd .DataFrame ()
57+ self ._x = pd .DataFrame ()
6158 self .output_list = output_list
6259 self .omc = OMCSessionZMQ ()
6360 self .omc .sendExpression (f'cd("{ self ._simulation_path .as_posix ()} ")' )
@@ -84,14 +81,16 @@ def simulate(
8481 ) -> pd .DataFrame :
8582 """
8683 Runs the simulation with the provided parameters, simulation options and
87- boundariy conditions.
84+ boundary conditions.
8885 - parameter_dict (dict, optional): Dictionary of parameters.
89- - simulation_options (dict, optional): Will update simulation options if it
90- had been given at the init phase. May include values for "startTime",
91- "stopTime", "stepSize", "tolerance", "solver", "outputFormat" .
86+ - simulation_options (dict, optional): May include values for "startTime",
87+ "stopTime", "stepSize", "tolerance", "solver", "outputFormat". Can
88+ also include 'x' with a DataFrame for boundary conditions .
9289 - x (pd.DataFrame, optional): Input data for the simulation. Index shall
93- be a DatetimeIndex or integers. Columns must match the combi time table
94- used to specify boundary conditions in the Modelica System.
90+ be a DatetimeIndex or integers. Columns must match the combitimetable
91+ used to specify boundary conditions in the Modelica System. If 'x' is
92+ provided both in simulation_options and as a direct parameter, the one
93+ provided as direct parameter will be used.
9594 - verbose (bool, optional): If True, prints simulation progress. Defaults to
9695 True.
9796 - simflags (str, optional): Additional simulation flags.
@@ -102,9 +101,17 @@ def simulate(
102101 """
103102
104103 if parameter_dict is not None :
105- self ._set_param_dict (parameter_dict )
104+ self .set_param_dict (parameter_dict )
106105
107106 if simulation_options is not None :
107+ if x is not None and "x" in simulation_options :
108+ warnings .warn (
109+ "Boundary file 'x' specified both in simulation_options and as a "
110+ "direct parameter. The 'x' provided in simulate() will be used." ,
111+ UserWarning ,
112+ stacklevel = 2 ,
113+ )
114+
108115 self ._set_simulation_options (simulation_options )
109116
110117 if x is not None :
@@ -172,28 +179,32 @@ def get_parameters(self):
172179 return self .model .getParameters ()
173180
174181 def _set_simulation_options (self , simulation_options ):
175- self .model .setSimulationOptions (
176- [
177- f'startTime={ simulation_options ["startTime" ]} ' ,
178- f'stopTime={ simulation_options ["stopTime" ]} ' ,
179- f'stepSize={ simulation_options ["stepSize" ]} ' ,
180- f'tolerance={ simulation_options ["tolerance" ]} ' ,
181- f'solver={ simulation_options ["solver" ]} ' ,
182- f'outputFormat={ simulation_options ["outputFormat" ]} ' ,
183- ]
184- )
182+ standard_options = {
183+ "startTime" : simulation_options .get ("startTime" ),
184+ "stopTime" : simulation_options .get ("stopTime" ),
185+ "stepSize" : simulation_options .get ("stepSize" ),
186+ "tolerance" : simulation_options .get ("tolerance" ),
187+ "solver" : simulation_options .get ("solver" ),
188+ "outputFormat" : simulation_options .get ("outputFormat" ),
189+ }
190+
191+ options = [f"{ k } ={ v } " for k , v in standard_options .items () if v is not None ]
192+ self .model .setSimulationOptions (options )
185193 self .simulation_options = simulation_options
186194
195+ if "x" in simulation_options :
196+ self ._set_x (simulation_options ["x" ])
197+
187198 def _set_x (self , df : pd .DataFrame ):
188199 """Sets the input data for the simulation and updates the corresponding file."""
189200 if not self ._x .equals (df ):
190201 new_bounds_path = self ._simulation_path / "boundaries.txt"
191202 df_to_combitimetable (df , new_bounds_path )
192203 full_path = (self ._simulation_path / "boundaries.txt" ).resolve ().as_posix ()
193- self ._set_param_dict ({f"{ self .x_combitimetable_name } .fileName" : full_path })
204+ self .set_param_dict ({f"{ self .x_combitimetable_name } .fileName" : full_path })
194205 self ._x = df
195206
196- def _set_param_dict (self , param_dict ):
207+ def set_param_dict (self , param_dict ):
197208 self .model .setParameters ([f"{ item } ={ val } " for item , val in param_dict .items ()])
198209
199210
0 commit comments