@@ -1814,11 +1814,11 @@ def run_doe():
18141814 simargs={"override": {'stopTime': 1.0}},
18151815 )
18161816 doe_mod.prepare()
1817- doe_dict = doe_mod.get_doe ()
1817+ doe_def = doe_mod.get_doe_definition ()
18181818 doe_mod.simulate()
1819- doe_sol = doe_mod.get_solutions ()
1819+ doe_sol = doe_mod.get_doe_solutions ()
18201820
1821- # ... work with doe_df and doe_sol ...
1821+ # ... work with doe_def and doe_sol ...
18221822
18231823
18241824 if __name__ == "__main__":
@@ -1890,8 +1890,8 @@ def __init__(
18901890 else :
18911891 self ._parameters = {}
18921892
1893- self ._sim_dict : Optional [dict [str , dict [str , Any ]]] = None
1894- self ._sim_task_query : queue . Queue = queue . Queue ()
1893+ self ._doe_def : Optional [dict [str , dict [str , Any ]]] = None
1894+ self ._doe_cmd : Optional [ dict [ str , OMCSessionRunData ]] = None
18951895
18961896 def session (self ) -> OMCSessionZMQ :
18971897 """
@@ -1907,6 +1907,9 @@ def prepare(self) -> int:
19071907 The return value is the number of simulation defined.
19081908 """
19091909
1910+ doe_sim = {}
1911+ doe_def = {}
1912+
19101913 param_structure = {}
19111914 param_non_structure = {}
19121915 for param_name in self ._parameters .keys ():
@@ -1921,18 +1924,11 @@ def prepare(self) -> int:
19211924 param_structure_combinations = list (itertools .product (* param_structure .values ()))
19221925 param_simple_combinations = list (itertools .product (* param_non_structure .values ()))
19231926
1924- self ._sim_dict = {}
19251927 for idx_pc_structure , pc_structure in enumerate (param_structure_combinations ):
1926- mod_structure = ModelicaSystem (
1927- fileName = self ._fileName ,
1928- modelName = self ._modelName ,
1929- lmodel = self ._lmodel ,
1930- commandLineOptions = self ._CommandLineOptions ,
1931- variableFilter = self ._variableFilter ,
1932- customBuildDirectory = self ._customBuildDirectory ,
1933- omhome = self ._omhome ,
1934- build = False ,
1935- )
1928+
1929+ build_dir = self ._resultpath / f"DOE_{ idx_pc_structure :09d} "
1930+ build_dir .mkdir ()
1931+ self ._mod .setWorkDirectory (customBuildDirectory = build_dir )
19361932
19371933 sim_param_structure = {}
19381934 for idx_structure , pk_structure in enumerate (param_structure .keys ()):
@@ -1947,12 +1943,12 @@ def prepare(self) -> int:
19471943 expression = f"setParameterValue({ self ._modelName } , { pk_structure } , { pk_value_bool_str } );"
19481944 else :
19491945 expression = f"setParameterValue({ self ._modelName } , { pk_structure } , { pk_value } )"
1950- res = mod_structure .sendExpression (expression )
1946+ res = self . _mod .sendExpression (expression )
19511947 if not res :
19521948 raise ModelicaSystemError (f"Cannot set structural parameter { self ._modelName } .{ pk_structure } "
19531949 f"to { pk_value } using { repr (expression )} " )
19541950
1955- mod_structure . buildModel (variableFilter = self . _variableFilter )
1951+ self . _mod . buildModel ()
19561952
19571953 for idx_pc_simple , pc_simple in enumerate (param_simple_combinations ):
19581954 sim_param_simple = {}
@@ -1979,23 +1975,26 @@ def prepare(self) -> int:
19791975 }
19801976 )
19811977
1982- self ._sim_dict [resfilename ] = df_data
1983-
1984- mscmd = mod_structure .simulate_cmd (
1978+ self ._mod .setParameters (sim_param_simple )
1979+ mscmd = self ._mod .simulate_cmd (
19851980 result_file = resultfile ,
19861981 timeout = self ._timeout ,
19871982 )
19881983 if self ._simargs is not None :
19891984 mscmd .args_set (args = self ._simargs )
1990- mscmd .args_set (args = {"override" : sim_param_simple })
1985+ cmd_definition = mscmd .definition ()
1986+ del mscmd
19911987
1992- self ._sim_task_query .put (mscmd )
1988+ doe_sim [resfilename ] = cmd_definition
1989+ doe_def [resfilename ] = df_data
19931990
1994- logger .info (f"Prepared { self ._sim_task_query .qsize ()} simulation definitions for the defined DoE." )
1991+ logger .info (f"Prepared { len (doe_sim )} simulation definitions for the defined DoE." )
1992+ self ._doe_cmd = doe_sim
1993+ self ._doe_def = doe_def
19951994
1996- return self . _sim_task_query . qsize ( )
1995+ return len ( doe_sim )
19971996
1998- def get_doe (self ) -> Optional [dict [str , dict [str , Any ]]]:
1997+ def get_doe_definition (self ) -> Optional [dict [str , dict [str , Any ]]]:
19991998 """
20001999 Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
20012000 settings including structural and non-structural parameters.
@@ -2005,12 +2004,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
20052004 ```
20062005 import pandas as pd
20072006
2008- doe_dict = doe_mod.get_doe ()
2007+ doe_dict = doe_mod.get_doe_definition ()
20092008 doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
20102009 ```
20112010
20122011 """
2013- return self ._sim_dict
2012+ return self ._doe_def
2013+
2014+ def get_doe_command (self ) -> Optional [dict [str , OMCSessionRunData ]]:
2015+ """
2016+ Get the definitions of simulations commands to run for this DoE.
2017+ """
2018+ return self ._doe_cmd
20142019
20152020 def simulate (
20162021 self ,
@@ -2022,71 +2027,85 @@ def simulate(
20222027 Returns True if all simulations were done successfully, else False.
20232028 """
20242029
2025- sim_query_total = self ._sim_task_query .qsize ()
2026- if not isinstance (self ._sim_dict , dict ) or len (self ._sim_dict ) == 0 :
2030+ if self ._doe_cmd is None or self ._doe_def is None :
2031+ raise ModelicaSystemError ("DoE preparation missing - call prepare() first!" )
2032+
2033+ doe_cmd_total = len (self ._doe_cmd )
2034+ doe_def_total = len (self ._doe_def )
2035+
2036+ if doe_cmd_total != doe_def_total :
2037+ raise ModelicaSystemError (f"Mismatch between number simulation commands ({ doe_cmd_total } ) "
2038+ f"and simulation definitions ({ doe_def_total } )." )
2039+
2040+ doe_task_query : queue .Queue = queue .Queue ()
2041+ if self ._doe_cmd is not None :
2042+ for doe_cmd in self ._doe_cmd .values ():
2043+ doe_task_query .put (doe_cmd )
2044+
2045+ if not isinstance (self ._doe_def , dict ) or len (self ._doe_def ) == 0 :
20272046 raise ModelicaSystemError ("Missing Doe Summary!" )
2028- sim_dict_total = len (self ._sim_dict )
20292047
20302048 def worker (worker_id , task_queue ):
20312049 while True :
20322050 try :
20332051 # Get the next task from the queue
2034- mscmd = task_queue .get (block = False )
2052+ cmd_definition = task_queue .get (block = False )
20352053 except queue .Empty :
20362054 logger .info (f"[Worker { worker_id } ] No more simulations to run." )
20372055 break
20382056
2039- if mscmd is None :
2057+ if cmd_definition is None :
20402058 raise ModelicaSystemError ("Missing simulation definition!" )
20412059
2042- resultfile = mscmd . arg_get ( key = 'r' )
2060+ resultfile = cmd_definition . cmd_result_path
20432061 resultpath = self .session ().omcpath (resultfile )
20442062
20452063 logger .info (f"[Worker { worker_id } ] Performing task: { resultpath .name } " )
20462064
20472065 try :
2048- mscmd .run ()
2066+ returncode = self ._mod ._getconn .run_model_executable (cmd_run_data = cmd_definition )
2067+ logger .info (f"[Worker { worker_id } ] Simulation { resultpath .name } "
2068+ f"finished with return code: { returncode } " )
20492069 except ModelicaSystemError as ex :
20502070 logger .warning (f"Simulation error for { resultpath .name } : { ex } " )
20512071
20522072 # Mark the task as done
20532073 task_queue .task_done ()
20542074
2055- sim_query_done = sim_query_total - self . _sim_task_query .qsize ()
2075+ sim_query_done = doe_cmd_total - doe_task_query .qsize ()
20562076 logger .info (f"[Worker { worker_id } ] Task completed: { resultpath .name } "
2057- f"({ sim_query_total - sim_query_done } /{ sim_query_total } = "
2058- f"{ (sim_query_total - sim_query_done ) / sim_query_total * 100 :.2f} % of tasks left)" )
2059-
2060- logger .info (f"Start simulations for DoE with { sim_query_total } simulations "
2061- f"using { num_workers } workers ..." )
2077+ f"({ doe_cmd_total - sim_query_done } /{ doe_cmd_total } = "
2078+ f"{ (doe_cmd_total - sim_query_done ) / doe_cmd_total * 100 :.2f} % of tasks left)" )
20622079
20632080 # Create and start worker threads
2081+ logger .info (f"Start simulations for DoE with { doe_cmd_total } simulations "
2082+ f"using { num_workers } workers ..." )
20642083 threads = []
20652084 for i in range (num_workers ):
2066- thread = threading .Thread (target = worker , args = (i , self . _sim_task_query ))
2085+ thread = threading .Thread (target = worker , args = (i , doe_task_query ))
20672086 thread .start ()
20682087 threads .append (thread )
20692088
20702089 # Wait for all threads to complete
20712090 for thread in threads :
20722091 thread .join ()
20732092
2074- sim_dict_done = 0
2075- for resultfilename in self ._sim_dict :
2093+ doe_def_done = 0
2094+ for resultfilename in self ._doe_def :
20762095 resultfile = self ._resultpath / resultfilename
20772096
20782097 # include check for an empty (=> 0B) result file which indicates a crash of the model executable
20792098 # see: https://github.com/OpenModelica/OMPython/issues/261
20802099 # https://github.com/OpenModelica/OpenModelica/issues/13829
20812100 if resultfile .is_file () and resultfile .size () > 0 :
2082- self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2083- sim_dict_done += 1
2101+ self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2102+ doe_def_done += 1
20842103
2085- logger .info (f"All workers finished ({ sim_dict_done } of { sim_dict_total } simulations with a result file)." )
2104+ logger .info (f"All workers finished ({ doe_def_done } of { doe_def_total } simulations with a result file)." )
20862105
2087- return sim_dict_total == sim_dict_done
2106+ return doe_def_total == doe_def_done
20882107
2089- def get_solutions (
2108+ def get_doe_solutions (
20902109 self ,
20912110 var_list : Optional [list ] = None ,
20922111 ) -> Optional [tuple [str ] | dict [str , dict [str , np .ndarray ]]]:
@@ -2102,7 +2121,7 @@ def get_solutions(
21022121 ```
21032122 import pandas as pd
21042123
2105- doe_sol = doe_mod.get_solutions ()
2124+ doe_sol = doe_mod.get_doe_solutions ()
21062125 for key in doe_sol:
21072126 data = doe_sol[key]['data']
21082127 if data:
@@ -2112,20 +2131,22 @@ def get_solutions(
21122131 ```
21132132
21142133 """
2115- if not isinstance (self ._sim_dict , dict ):
2134+ if not isinstance (self ._doe_def , dict ):
21162135 return None
21172136
2118- if len (self ._sim_dict ) == 0 :
2137+ if len (self ._doe_def ) == 0 :
21192138 raise ModelicaSystemError ("No result files available - all simulations did fail?" )
21202139
21212140 sol_dict : dict [str , dict [str , Any ]] = {}
2122- for resultfilename in self ._sim_dict :
2141+ for resultfilename in self ._doe_def :
21232142 resultfile = self ._resultpath / resultfilename
21242143
21252144 sol_dict [resultfilename ] = {}
21262145
2127- if not self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2128- sol_dict [resultfilename ]['msg' ] = 'No result file available!'
2146+ if not self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2147+ msg = f"No result file available for { resultfilename } "
2148+ logger .warning (msg )
2149+ sol_dict [resultfilename ]['msg' ] = msg
21292150 sol_dict [resultfilename ]['data' ] = {}
21302151 continue
21312152
0 commit comments