@@ -1851,11 +1851,11 @@ def run_doe():
18511851 simargs={"override": {'stopTime': 1.0}},
18521852 )
18531853 doe_mod.prepare()
1854- doe_dict = doe_mod.get_doe ()
1854+ doe_def = doe_mod.get_doe_definition ()
18551855 doe_mod.simulate()
1856- doe_sol = doe_mod.get_solutions ()
1856+ doe_sol = doe_mod.get_doe_solutions ()
18571857
1858- # ... work with doe_df and doe_sol ...
1858+ # ... work with doe_def and doe_sol ...
18591859
18601860
18611861 if __name__ == "__main__":
@@ -1927,8 +1927,8 @@ def __init__(
19271927 else :
19281928 self ._parameters = {}
19291929
1930- self ._sim_dict : Optional [dict [str , dict [str , Any ]]] = None
1931- self ._sim_task_query : queue . Queue = queue . Queue ()
1930+ self ._doe_def : Optional [dict [str , dict [str , Any ]]] = None
1931+ self ._doe_cmd : Optional [ dict [ str , OMCSessionRunData ]] = None
19321932
19331933 def session (self ) -> OMCSessionZMQ :
19341934 """
@@ -1944,6 +1944,9 @@ def prepare(self) -> int:
19441944 The return value is the number of simulation defined.
19451945 """
19461946
1947+ doe_sim = {}
1948+ doe_def = {}
1949+
19471950 param_structure = {}
19481951 param_non_structure = {}
19491952 for param_name in self ._parameters .keys ():
@@ -1958,18 +1961,11 @@ def prepare(self) -> int:
19581961 param_structure_combinations = list (itertools .product (* param_structure .values ()))
19591962 param_simple_combinations = list (itertools .product (* param_non_structure .values ()))
19601963
1961- self ._sim_dict = {}
19621964 for idx_pc_structure , pc_structure in enumerate (param_structure_combinations ):
1963- mod_structure = ModelicaSystem (
1964- fileName = self ._fileName ,
1965- modelName = self ._modelName ,
1966- lmodel = self ._lmodel ,
1967- commandLineOptions = self ._CommandLineOptions ,
1968- variableFilter = self ._variableFilter ,
1969- customBuildDirectory = self ._customBuildDirectory ,
1970- omhome = self ._omhome ,
1971- build = False ,
1972- )
1965+
1966+ build_dir = self ._resultpath / f"DOE_{ idx_pc_structure :09d} "
1967+ build_dir .mkdir ()
1968+ self ._mod .setWorkDirectory (customBuildDirectory = build_dir )
19731969
19741970 sim_param_structure = {}
19751971 for idx_structure , pk_structure in enumerate (param_structure .keys ()):
@@ -1984,12 +1980,12 @@ def prepare(self) -> int:
19841980 expression = f"setParameterValue({ self ._modelName } , { pk_structure } , { pk_value_bool_str } );"
19851981 else :
19861982 expression = f"setParameterValue({ self ._modelName } , { pk_structure } , { pk_value } )"
1987- res = mod_structure .sendExpression (expression )
1983+ res = self . _mod .sendExpression (expression )
19881984 if not res :
19891985 raise ModelicaSystemError (f"Cannot set structural parameter { self ._modelName } .{ pk_structure } "
19901986 f"to { pk_value } using { repr (expression )} " )
19911987
1992- mod_structure . buildModel (variableFilter = self . _variableFilter )
1988+ self . _mod . buildModel ()
19931989
19941990 for idx_pc_simple , pc_simple in enumerate (param_simple_combinations ):
19951991 sim_param_simple = {}
@@ -2016,23 +2012,26 @@ def prepare(self) -> int:
20162012 }
20172013 )
20182014
2019- self ._sim_dict [resfilename ] = df_data
2020-
2021- mscmd = mod_structure .simulate_cmd (
2015+ self ._mod .setParameters (sim_param_simple )
2016+ mscmd = self ._mod .simulate_cmd (
20222017 result_file = resultfile ,
20232018 timeout = self ._timeout ,
20242019 )
20252020 if self ._simargs is not None :
20262021 mscmd .args_set (args = self ._simargs )
2027- mscmd .args_set (args = {"override" : sim_param_simple })
2022+ cmd_definition = mscmd .definition ()
2023+ del mscmd
20282024
2029- self ._sim_task_query .put (mscmd )
2025+ doe_sim [resfilename ] = cmd_definition
2026+ doe_def [resfilename ] = df_data
20302027
2031- logger .info (f"Prepared { self ._sim_task_query .qsize ()} simulation definitions for the defined DoE." )
2028+ logger .info (f"Prepared { len (doe_sim )} simulation definitions for the defined DoE." )
2029+ self ._doe_cmd = doe_sim
2030+ self ._doe_def = doe_def
20322031
2033- return self . _sim_task_query . qsize ( )
2032+ return len ( doe_sim )
20342033
2035- def get_doe (self ) -> Optional [dict [str , dict [str , Any ]]]:
2034+ def get_doe_definition (self ) -> Optional [dict [str , dict [str , Any ]]]:
20362035 """
20372036 Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
20382037 settings including structural and non-structural parameters.
@@ -2042,12 +2041,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
20422041 ```
20432042 import pandas as pd
20442043
2045- doe_dict = doe_mod.get_doe ()
2044+ doe_dict = doe_mod.get_doe_definition ()
20462045 doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
20472046 ```
20482047
20492048 """
2050- return self ._sim_dict
2049+ return self ._doe_def
2050+
2051+ def get_doe_command (self ) -> Optional [dict [str , OMCSessionRunData ]]:
2052+ """
2053+ Get the definitions of simulations commands to run for this DoE.
2054+ """
2055+ return self ._doe_cmd
20512056
20522057 def simulate (
20532058 self ,
@@ -2059,71 +2064,85 @@ def simulate(
20592064 Returns True if all simulations were done successfully, else False.
20602065 """
20612066
2062- sim_query_total = self ._sim_task_query .qsize ()
2063- if not isinstance (self ._sim_dict , dict ) or len (self ._sim_dict ) == 0 :
2067+ if self ._doe_cmd is None or self ._doe_def is None :
2068+ raise ModelicaSystemError ("DoE preparation missing - call prepare() first!" )
2069+
2070+ doe_cmd_total = len (self ._doe_cmd )
2071+ doe_def_total = len (self ._doe_def )
2072+
2073+ if doe_cmd_total != doe_def_total :
2074+ raise ModelicaSystemError (f"Mismatch between number simulation commands ({ doe_cmd_total } ) "
2075+ f"and simulation definitions ({ doe_def_total } )." )
2076+
2077+ doe_task_query : queue .Queue = queue .Queue ()
2078+ if self ._doe_cmd is not None :
2079+ for doe_cmd in self ._doe_cmd .values ():
2080+ doe_task_query .put (doe_cmd )
2081+
2082+ if not isinstance (self ._doe_def , dict ) or len (self ._doe_def ) == 0 :
20642083 raise ModelicaSystemError ("Missing Doe Summary!" )
2065- sim_dict_total = len (self ._sim_dict )
20662084
20672085 def worker (worker_id , task_queue ):
20682086 while True :
20692087 try :
20702088 # Get the next task from the queue
2071- mscmd = task_queue .get (block = False )
2089+ cmd_definition = task_queue .get (block = False )
20722090 except queue .Empty :
20732091 logger .info (f"[Worker { worker_id } ] No more simulations to run." )
20742092 break
20752093
2076- if mscmd is None :
2094+ if cmd_definition is None :
20772095 raise ModelicaSystemError ("Missing simulation definition!" )
20782096
2079- resultfile = mscmd . arg_get ( key = 'r' )
2097+ resultfile = cmd_definition . cmd_result_path
20802098 resultpath = self .session ().omcpath (resultfile )
20812099
20822100 logger .info (f"[Worker { worker_id } ] Performing task: { resultpath .name } " )
20832101
20842102 try :
2085- mscmd .run ()
2103+ returncode = self ._mod ._getconn .run_model_executable (cmd_run_data = cmd_definition )
2104+ logger .info (f"[Worker { worker_id } ] Simulation { resultpath .name } "
2105+ f"finished with return code: { returncode } " )
20862106 except ModelicaSystemError as ex :
20872107 logger .warning (f"Simulation error for { resultpath .name } : { ex } " )
20882108
20892109 # Mark the task as done
20902110 task_queue .task_done ()
20912111
2092- sim_query_done = sim_query_total - self . _sim_task_query .qsize ()
2112+ sim_query_done = doe_cmd_total - doe_task_query .qsize ()
20932113 logger .info (f"[Worker { worker_id } ] Task completed: { resultpath .name } "
2094- f"({ sim_query_total - sim_query_done } /{ sim_query_total } = "
2095- f"{ (sim_query_total - sim_query_done ) / sim_query_total * 100 :.2f} % of tasks left)" )
2096-
2097- logger .info (f"Start simulations for DoE with { sim_query_total } simulations "
2098- f"using { num_workers } workers ..." )
2114+ f"({ doe_cmd_total - sim_query_done } /{ doe_cmd_total } = "
2115+ f"{ (doe_cmd_total - sim_query_done ) / doe_cmd_total * 100 :.2f} % of tasks left)" )
20992116
21002117 # Create and start worker threads
2118+ logger .info (f"Start simulations for DoE with { doe_cmd_total } simulations "
2119+ f"using { num_workers } workers ..." )
21012120 threads = []
21022121 for i in range (num_workers ):
2103- thread = threading .Thread (target = worker , args = (i , self . _sim_task_query ))
2122+ thread = threading .Thread (target = worker , args = (i , doe_task_query ))
21042123 thread .start ()
21052124 threads .append (thread )
21062125
21072126 # Wait for all threads to complete
21082127 for thread in threads :
21092128 thread .join ()
21102129
2111- sim_dict_done = 0
2112- for resultfilename in self ._sim_dict :
2130+ doe_def_done = 0
2131+ for resultfilename in self ._doe_def :
21132132 resultfile = self ._resultpath / resultfilename
21142133
21152134 # include check for an empty (=> 0B) result file which indicates a crash of the model executable
21162135 # see: https://github.com/OpenModelica/OMPython/issues/261
21172136 # https://github.com/OpenModelica/OpenModelica/issues/13829
21182137 if resultfile .is_file () and resultfile .size () > 0 :
2119- self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2120- sim_dict_done += 1
2138+ self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2139+ doe_def_done += 1
21212140
2122- logger .info (f"All workers finished ({ sim_dict_done } of { sim_dict_total } simulations with a result file)." )
2141+ logger .info (f"All workers finished ({ doe_def_done } of { doe_def_total } simulations with a result file)." )
21232142
2124- return sim_dict_total == sim_dict_done
2143+ return doe_def_total == doe_def_done
21252144
2126- def get_solutions (
2145+ def get_doe_solutions (
21272146 self ,
21282147 var_list : Optional [list ] = None ,
21292148 ) -> Optional [tuple [str ] | dict [str , dict [str , np .ndarray ]]]:
@@ -2139,7 +2158,7 @@ def get_solutions(
21392158 ```
21402159 import pandas as pd
21412160
2142- doe_sol = doe_mod.get_solutions ()
2161+ doe_sol = doe_mod.get_doe_solutions ()
21432162 for key in doe_sol:
21442163 data = doe_sol[key]['data']
21452164 if data:
@@ -2149,20 +2168,22 @@ def get_solutions(
21492168 ```
21502169
21512170 """
2152- if not isinstance (self ._sim_dict , dict ):
2171+ if not isinstance (self ._doe_def , dict ):
21532172 return None
21542173
2155- if len (self ._sim_dict ) == 0 :
2174+ if len (self ._doe_def ) == 0 :
21562175 raise ModelicaSystemError ("No result files available - all simulations did fail?" )
21572176
21582177 sol_dict : dict [str , dict [str , Any ]] = {}
2159- for resultfilename in self ._sim_dict :
2178+ for resultfilename in self ._doe_def :
21602179 resultfile = self ._resultpath / resultfilename
21612180
21622181 sol_dict [resultfilename ] = {}
21632182
2164- if not self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2165- sol_dict [resultfilename ]['msg' ] = 'No result file available!'
2183+ if not self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2184+ msg = f"No result file available for { resultfilename } "
2185+ logger .warning (msg )
2186+ sol_dict [resultfilename ]['msg' ] = msg
21662187 sol_dict [resultfilename ]['data' ] = {}
21672188 continue
21682189
0 commit comments