@@ -1850,11 +1850,11 @@ def run_doe():
18501850 simargs={"override": {'stopTime': 1.0}},
18511851 )
18521852 doe_mod.prepare()
1853- doe_dict = doe_mod.get_doe ()
1853+ doe_def = doe_mod.get_doe_definition ()
18541854 doe_mod.simulate()
1855- doe_sol = doe_mod.get_solutions ()
1855+ doe_sol = doe_mod.get_doe_solutions ()
18561856
1857- # ... work with doe_df and doe_sol ...
1857+ # ... work with doe_def and doe_sol ...
18581858
18591859
18601860 if __name__ == "__main__":
@@ -1926,8 +1926,8 @@ def __init__(
19261926 else :
19271927 self ._parameters = {}
19281928
1929- self ._sim_dict : Optional [dict [str , dict [str , Any ]]] = None
1930- self ._sim_task_query : queue . Queue = queue . Queue ()
1929+ self ._doe_def : Optional [dict [str , dict [str , Any ]]] = None
1930+ self ._doe_cmd : Optional [ dict [ str , OMCSessionRunData ]] = None
19311931
19321932 def session (self ) -> OMCSessionZMQ :
19331933 """
@@ -1943,6 +1943,9 @@ def prepare(self) -> int:
19431943 The return value is the number of simulation defined.
19441944 """
19451945
1946+ doe_sim = {}
1947+ doe_def = {}
1948+
19461949 param_structure = {}
19471950 param_non_structure = {}
19481951 for param_name in self ._parameters .keys ():
@@ -1957,18 +1960,11 @@ def prepare(self) -> int:
19571960 param_structure_combinations = list (itertools .product (* param_structure .values ()))
19581961 param_simple_combinations = list (itertools .product (* param_non_structure .values ()))
19591962
1960- self ._sim_dict = {}
19611963 for idx_pc_structure , pc_structure in enumerate (param_structure_combinations ):
1962- mod_structure = ModelicaSystem (
1963- fileName = self ._fileName ,
1964- modelName = self ._modelName ,
1965- lmodel = self ._lmodel ,
1966- commandLineOptions = self ._CommandLineOptions ,
1967- variableFilter = self ._variableFilter ,
1968- customBuildDirectory = self ._customBuildDirectory ,
1969- omhome = self ._omhome ,
1970- build = False ,
1971- )
1964+
1965+ build_dir = self ._resultpath / f"DOE_{ idx_pc_structure :09d} "
1966+ build_dir .mkdir ()
1967+ self ._mod .setWorkDirectory (customBuildDirectory = build_dir )
19721968
19731969 sim_param_structure = {}
19741970 for idx_structure , pk_structure in enumerate (param_structure .keys ()):
@@ -1983,12 +1979,12 @@ def prepare(self) -> int:
19831979 expression = f"setParameterValue({ self ._modelName } , { pk_structure } , { pk_value_bool_str } );"
19841980 else :
19851981 expression = f"setParameterValue({ self ._modelName } , { pk_structure } , { pk_value } )"
1986- res = mod_structure .sendExpression (expression )
1982+ res = self . _mod .sendExpression (expression )
19871983 if not res :
19881984 raise ModelicaSystemError (f"Cannot set structural parameter { self ._modelName } .{ pk_structure } "
19891985 f"to { pk_value } using { repr (expression )} " )
19901986
1991- mod_structure . buildModel (variableFilter = self . _variableFilter )
1987+ self . _mod . buildModel ()
19921988
19931989 for idx_pc_simple , pc_simple in enumerate (param_simple_combinations ):
19941990 sim_param_simple = {}
@@ -2015,23 +2011,26 @@ def prepare(self) -> int:
20152011 }
20162012 )
20172013
2018- self ._sim_dict [resfilename ] = df_data
2019-
2020- mscmd = mod_structure .simulate_cmd (
2014+ self ._mod .setParameters (sim_param_simple )
2015+ mscmd = self ._mod .simulate_cmd (
20212016 result_file = resultfile ,
20222017 timeout = self ._timeout ,
20232018 )
20242019 if self ._simargs is not None :
20252020 mscmd .args_set (args = self ._simargs )
2026- mscmd .args_set (args = {"override" : sim_param_simple })
2021+ cmd_definition = mscmd .definition ()
2022+ del mscmd
20272023
2028- self ._sim_task_query .put (mscmd )
2024+ doe_sim [resfilename ] = cmd_definition
2025+ doe_def [resfilename ] = df_data
20292026
2030- logger .info (f"Prepared { self ._sim_task_query .qsize ()} simulation definitions for the defined DoE." )
2027+ logger .info (f"Prepared { len (doe_sim )} simulation definitions for the defined DoE." )
2028+ self ._doe_cmd = doe_sim
2029+ self ._doe_def = doe_def
20312030
2032- return self . _sim_task_query . qsize ( )
2031+ return len ( doe_sim )
20332032
2034- def get_doe (self ) -> Optional [dict [str , dict [str , Any ]]]:
2033+ def get_doe_definition (self ) -> Optional [dict [str , dict [str , Any ]]]:
20352034 """
20362035 Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
20372036 settings including structural and non-structural parameters.
@@ -2041,12 +2040,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
20412040 ```
20422041 import pandas as pd
20432042
2044- doe_dict = doe_mod.get_doe ()
2043+ doe_dict = doe_mod.get_doe_definition ()
20452044 doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
20462045 ```
20472046
20482047 """
2049- return self ._sim_dict
2048+ return self ._doe_def
2049+
2050+ def get_doe_command (self ) -> Optional [dict [str , OMCSessionRunData ]]:
2051+ """
2052+ Get the definitions of simulations commands to run for this DoE.
2053+ """
2054+ return self ._doe_cmd
20502055
20512056 def simulate (
20522057 self ,
@@ -2058,71 +2063,85 @@ def simulate(
20582063 Returns True if all simulations were done successfully, else False.
20592064 """
20602065
2061- sim_query_total = self ._sim_task_query .qsize ()
2062- if not isinstance (self ._sim_dict , dict ) or len (self ._sim_dict ) == 0 :
2066+ if self ._doe_cmd is None or self ._doe_def is None :
2067+ raise ModelicaSystemError ("DoE preparation missing - call prepare() first!" )
2068+
2069+ doe_cmd_total = len (self ._doe_cmd )
2070+ doe_def_total = len (self ._doe_def )
2071+
2072+ if doe_cmd_total != doe_def_total :
2073+ raise ModelicaSystemError (f"Mismatch between number simulation commands ({ doe_cmd_total } ) "
2074+ f"and simulation definitions ({ doe_def_total } )." )
2075+
2076+ doe_task_query : queue .Queue = queue .Queue ()
2077+ if self ._doe_cmd is not None :
2078+ for doe_cmd in self ._doe_cmd .values ():
2079+ doe_task_query .put (doe_cmd )
2080+
2081+ if not isinstance (self ._doe_def , dict ) or len (self ._doe_def ) == 0 :
20632082 raise ModelicaSystemError ("Missing Doe Summary!" )
2064- sim_dict_total = len (self ._sim_dict )
20652083
20662084 def worker (worker_id , task_queue ):
20672085 while True :
20682086 try :
20692087 # Get the next task from the queue
2070- mscmd = task_queue .get (block = False )
2088+ cmd_definition = task_queue .get (block = False )
20712089 except queue .Empty :
20722090 logger .info (f"[Worker { worker_id } ] No more simulations to run." )
20732091 break
20742092
2075- if mscmd is None :
2093+ if cmd_definition is None :
20762094 raise ModelicaSystemError ("Missing simulation definition!" )
20772095
2078- resultfile = mscmd . arg_get ( key = 'r' )
2096+ resultfile = cmd_definition . cmd_result_path
20792097 resultpath = self .session ().omcpath (resultfile )
20802098
20812099 logger .info (f"[Worker { worker_id } ] Performing task: { resultpath .name } " )
20822100
20832101 try :
2084- mscmd .run ()
2102+ returncode = self ._mod ._getconn .run_model_executable (cmd_run_data = cmd_definition )
2103+ logger .info (f"[Worker { worker_id } ] Simulation { resultpath .name } "
2104+ f"finished with return code: { returncode } " )
20852105 except ModelicaSystemError as ex :
20862106 logger .warning (f"Simulation error for { resultpath .name } : { ex } " )
20872107
20882108 # Mark the task as done
20892109 task_queue .task_done ()
20902110
2091- sim_query_done = sim_query_total - self . _sim_task_query .qsize ()
2111+ sim_query_done = doe_cmd_total - doe_task_query .qsize ()
20922112 logger .info (f"[Worker { worker_id } ] Task completed: { resultpath .name } "
2093- f"({ sim_query_total - sim_query_done } /{ sim_query_total } = "
2094- f"{ (sim_query_total - sim_query_done ) / sim_query_total * 100 :.2f} % of tasks left)" )
2095-
2096- logger .info (f"Start simulations for DoE with { sim_query_total } simulations "
2097- f"using { num_workers } workers ..." )
2113+ f"({ doe_cmd_total - sim_query_done } /{ doe_cmd_total } = "
2114+ f"{ (doe_cmd_total - sim_query_done ) / doe_cmd_total * 100 :.2f} % of tasks left)" )
20982115
20992116 # Create and start worker threads
2117+ logger .info (f"Start simulations for DoE with { doe_cmd_total } simulations "
2118+ f"using { num_workers } workers ..." )
21002119 threads = []
21012120 for i in range (num_workers ):
2102- thread = threading .Thread (target = worker , args = (i , self . _sim_task_query ))
2121+ thread = threading .Thread (target = worker , args = (i , doe_task_query ))
21032122 thread .start ()
21042123 threads .append (thread )
21052124
21062125 # Wait for all threads to complete
21072126 for thread in threads :
21082127 thread .join ()
21092128
2110- sim_dict_done = 0
2111- for resultfilename in self ._sim_dict :
2129+ doe_def_done = 0
2130+ for resultfilename in self ._doe_def :
21122131 resultfile = self ._resultpath / resultfilename
21132132
21142133 # include check for an empty (=> 0B) result file which indicates a crash of the model executable
21152134 # see: https://github.com/OpenModelica/OMPython/issues/261
21162135 # https://github.com/OpenModelica/OpenModelica/issues/13829
21172136 if resultfile .is_file () and resultfile .size () > 0 :
2118- self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2119- sim_dict_done += 1
2137+ self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2138+ doe_def_done += 1
21202139
2121- logger .info (f"All workers finished ({ sim_dict_done } of { sim_dict_total } simulations with a result file)." )
2140+ logger .info (f"All workers finished ({ doe_def_done } of { doe_def_total } simulations with a result file)." )
21222141
2123- return sim_dict_total == sim_dict_done
2142+ return doe_def_total == doe_def_done
21242143
2125- def get_solutions (
2144+ def get_doe_solutions (
21262145 self ,
21272146 var_list : Optional [list ] = None ,
21282147 ) -> Optional [tuple [str ] | dict [str , dict [str , np .ndarray ]]]:
@@ -2138,7 +2157,7 @@ def get_solutions(
21382157 ```
21392158 import pandas as pd
21402159
2141- doe_sol = doe_mod.get_solutions ()
2160+ doe_sol = doe_mod.get_doe_solutions ()
21422161 for key in doe_sol:
21432162 data = doe_sol[key]['data']
21442163 if data:
@@ -2148,20 +2167,22 @@ def get_solutions(
21482167 ```
21492168
21502169 """
2151- if not isinstance (self ._sim_dict , dict ):
2170+ if not isinstance (self ._doe_def , dict ):
21522171 return None
21532172
2154- if len (self ._sim_dict ) == 0 :
2173+ if len (self ._doe_def ) == 0 :
21552174 raise ModelicaSystemError ("No result files available - all simulations did fail?" )
21562175
21572176 sol_dict : dict [str , dict [str , Any ]] = {}
2158- for resultfilename in self ._sim_dict :
2177+ for resultfilename in self ._doe_def :
21592178 resultfile = self ._resultpath / resultfilename
21602179
21612180 sol_dict [resultfilename ] = {}
21622181
2163- if not self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2164- sol_dict [resultfilename ]['msg' ] = 'No result file available!'
2182+ if not self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2183+ msg = f"No result file available for { resultfilename } "
2184+ logger .warning (msg )
2185+ sol_dict [resultfilename ]['msg' ] = msg
21652186 sol_dict [resultfilename ]['data' ] = {}
21662187 continue
21672188
0 commit comments