@@ -1783,11 +1783,11 @@ def run_doe():
17831783 simargs={"override": {'stopTime': 1.0}},
17841784 )
17851785 doe_mod.prepare()
1786- doe_dict = doe_mod.get_doe ()
1786+ doe_def = doe_mod.get_doe_definition ()
17871787 doe_mod.simulate()
1788- doe_sol = doe_mod.get_solutions ()
1788+ doe_sol = doe_mod.get_doe_solutions ()
17891789
1790- # ... work with doe_df and doe_sol ...
1790+ # ... work with doe_def and doe_sol ...
17911791
17921792
17931793 if __name__ == "__main__":
@@ -1853,8 +1853,8 @@ def __init__(
18531853 else :
18541854 self ._parameters = {}
18551855
1856- self ._sim_dict : Optional [dict [str , dict [str , Any ]]] = None
1857- self ._sim_task_query : queue . Queue = queue . Queue ()
1856+ self ._doe_def : Optional [dict [str , dict [str , Any ]]] = None
1857+ self ._doe_cmd : Optional [ dict [ str , OMCSessionRunData ]] = None
18581858
18591859 def prepare (self ) -> int :
18601860 """
@@ -1864,6 +1864,9 @@ def prepare(self) -> int:
18641864 The return value is the number of simulation defined.
18651865 """
18661866
1867+ doe_sim = {}
1868+ doe_def = {}
1869+
18671870 param_structure = {}
18681871 param_simple = {}
18691872 for param_name in self ._parameters .keys ():
@@ -1878,18 +1881,11 @@ def prepare(self) -> int:
18781881 param_structure_combinations = list (itertools .product (* param_structure .values ()))
18791882 param_simple_combinations = list (itertools .product (* param_simple .values ()))
18801883
1881- self ._sim_dict = {}
18821884 for idx_pc_structure , pc_structure in enumerate (param_structure_combinations ):
1883- mod_structure = ModelicaSystem (
1884- fileName = self ._fileName ,
1885- modelName = self ._modelName ,
1886- lmodel = self ._lmodel ,
1887- commandLineOptions = self ._CommandLineOptions ,
1888- variableFilter = self ._variableFilter ,
1889- customBuildDirectory = self ._customBuildDirectory ,
1890- omhome = self ._omhome ,
1891- build = False ,
1892- )
1885+
1886+ build_dir = self ._resultpath / f"DOE_{ idx_pc_structure :09d} "
1887+ build_dir .mkdir ()
1888+ self ._mod .setWorkDirectory (customBuildDirectory = build_dir )
18931889
18941890 sim_param_structure = {}
18951891 for idx_structure , pk_structure in enumerate (param_structure .keys ()):
@@ -1908,7 +1904,7 @@ def prepare(self) -> int:
19081904 raise ModelicaSystemError (f"Cannot set structural parameter { self ._modelName } .{ pk_structure } "
19091905 f"to { pk_value } using { repr (expression )} " )
19101906
1911- mod_structure . buildModel (variableFilter = self . _variableFilter )
1907+ self . _mod . buildModel ()
19121908
19131909 for idx_pc_simple , pc_simple in enumerate (param_simple_combinations ):
19141910 sim_param_simple = {}
@@ -1935,23 +1931,26 @@ def prepare(self) -> int:
19351931 }
19361932 )
19371933
1938- self ._sim_dict [resfilename ] = df_data
1939-
1940- mscmd = mod_structure .simulate_cmd (
1941- result_file = resultfile .absolute ().resolve (),
1934+ self ._mod .setParameters (sim_param_simple )
1935+ mscmd = self ._mod .simulate_cmd (
1936+ result_file = resultfile ,
19421937 timeout = self ._timeout ,
19431938 )
19441939 if self ._simargs is not None :
19451940 mscmd .args_set (args = self ._simargs )
1946- mscmd .args_set (args = {"override" : sim_param_simple })
1941+ cmd_definition = mscmd .definition ()
1942+ del mscmd
19471943
1948- self ._sim_task_query .put (mscmd )
1944+ doe_sim [resfilename ] = cmd_definition
1945+ doe_def [resfilename ] = df_data
19491946
1950- logger .info (f"Prepared { self ._sim_task_query .qsize ()} simulation definitions for the defined DoE." )
1947+ logger .info (f"Prepared { len (doe_sim )} simulation definitions for the defined DoE." )
1948+ self ._doe_cmd = doe_sim
1949+ self ._doe_def = doe_def
19511950
1952- return self . _sim_task_query . qsize ( )
1951+ return len ( doe_sim )
19531952
1954- def get_doe (self ) -> Optional [dict [str , dict [str , Any ]]]:
1953+ def get_doe_definition (self ) -> Optional [dict [str , dict [str , Any ]]]:
19551954 """
19561955 Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
19571956 settings including structural and non-structural parameters.
@@ -1961,12 +1960,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
19611960 ```
19621961 import pandas as pd
19631962
1964- doe_dict = doe_mod.get_doe ()
1963+ doe_dict = doe_mod.get_doe_definition ()
19651964 doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
19661965 ```
19671966
19681967 """
1969- return self ._sim_dict
1968+ return self ._doe_def
1969+
1970+ def get_doe_command (self ) -> Optional [dict [str , OMCSessionRunData ]]:
1971+ """
1972+ Get the definitions of simulations commands to run for this DoE.
1973+ """
1974+ return self ._doe_cmd
19701975
19711976 def simulate (
19721977 self ,
@@ -1978,71 +1983,85 @@ def simulate(
19781983 Returns True if all simulations were done successfully, else False.
19791984 """
19801985
1981- sim_query_total = self ._sim_task_query .qsize ()
1982- if not isinstance (self ._sim_dict , dict ) or len (self ._sim_dict ) == 0 :
1986+ if self ._doe_cmd is None or self ._doe_def is None :
1987+ raise ModelicaSystemError ("DoE preparation missing - call prepare() first!" )
1988+
1989+ doe_cmd_total = len (self ._doe_cmd )
1990+ doe_def_total = len (self ._doe_def )
1991+
1992+ if doe_cmd_total != doe_def_total :
1993+ raise ModelicaSystemError (f"Mismatch between number simulation commands ({ doe_cmd_total } ) "
1994+ f"and simulation definitions ({ doe_def_total } )." )
1995+
1996+ doe_task_query : queue .Queue = queue .Queue ()
1997+ if self ._doe_cmd is not None :
1998+ for doe_cmd in self ._doe_cmd .values ():
1999+ doe_task_query .put (doe_cmd )
2000+
2001+ if not isinstance (self ._doe_def , dict ) or len (self ._doe_def ) == 0 :
19832002 raise ModelicaSystemError ("Missing Doe Summary!" )
1984- sim_dict_total = len (self ._sim_dict )
19852003
19862004 def worker (worker_id , task_queue ):
19872005 while True :
19882006 try :
19892007 # Get the next task from the queue
1990- mscmd = task_queue .get (block = False )
2008+ cmd_definition = task_queue .get (block = False )
19912009 except queue .Empty :
19922010 logger .info (f"[Worker { worker_id } ] No more simulations to run." )
19932011 break
19942012
1995- if mscmd is None :
2013+ if cmd_definition is None :
19962014 raise ModelicaSystemError ("Missing simulation definition!" )
19972015
1998- resultfile = mscmd . arg_get ( key = 'r' )
1999- resultpath = pathlib . Path (resultfile )
2016+ resultfile = cmd_definition . cmd_result_path
2017+ resultpath = self . _mod . _getconn . omcpath (resultfile )
20002018
20012019 logger .info (f"[Worker { worker_id } ] Performing task: { resultpath .name } " )
20022020
20032021 try :
2004- mscmd .run ()
2022+ returncode = self ._mod ._getconn .run_model_executable (cmd_run_data = cmd_definition )
2023+ logger .info (f"[Worker { worker_id } ] Simulation { resultpath .name } "
2024+ f"finished with return code: { returncode } " )
20052025 except ModelicaSystemError as ex :
20062026 logger .warning (f"Simulation error for { resultpath .name } : { ex } " )
20072027
20082028 # Mark the task as done
20092029 task_queue .task_done ()
20102030
2011- sim_query_done = sim_query_total - self . _sim_task_query .qsize ()
2031+ sim_query_done = doe_cmd_total - doe_task_query .qsize ()
20122032 logger .info (f"[Worker { worker_id } ] Task completed: { resultpath .name } "
2013- f"({ sim_query_total - sim_query_done } /{ sim_query_total } = "
2014- f"{ (sim_query_total - sim_query_done ) / sim_query_total * 100 :.2f} % of tasks left)" )
2015-
2016- logger .info (f"Start simulations for DoE with { sim_query_total } simulations "
2017- f"using { num_workers } workers ..." )
2033+ f"({ doe_cmd_total - sim_query_done } /{ doe_cmd_total } = "
2034+ f"{ (doe_cmd_total - sim_query_done ) / doe_cmd_total * 100 :.2f} % of tasks left)" )
20182035
20192036 # Create and start worker threads
2037+ logger .info (f"Start simulations for DoE with { doe_cmd_total } simulations "
2038+ f"using { num_workers } workers ..." )
20202039 threads = []
20212040 for i in range (num_workers ):
2022- thread = threading .Thread (target = worker , args = (i , self . _sim_task_query ))
2041+ thread = threading .Thread (target = worker , args = (i , doe_task_query ))
20232042 thread .start ()
20242043 threads .append (thread )
20252044
20262045 # Wait for all threads to complete
20272046 for thread in threads :
20282047 thread .join ()
20292048
2030- sim_dict_done = 0
2031- for resultfilename in self ._sim_dict :
2049+ doe_def_done = 0
2050+ for resultfilename in self ._doe_def :
20322051 resultfile = self ._resultpath / resultfilename
20332052
20342053 # include check for an empty (=> 0B) result file which indicates a crash of the model executable
20352054 # see: https://github.com/OpenModelica/OMPython/issues/261
20362055 # https://github.com/OpenModelica/OpenModelica/issues/13829
2037- if resultfile .is_file () and resultfile .stat (). st_size > 0 :
2038- self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2039- sim_dict_done += 1
2056+ if resultfile .is_file () and resultfile .size () > 0 :
2057+ self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2058+ doe_def_done += 1
20402059
2041- logger .info (f"All workers finished ({ sim_dict_done } of { sim_dict_total } simulations with a result file)." )
2060+ logger .info (f"All workers finished ({ doe_def_done } of { doe_def_total } simulations with a result file)." )
20422061
2043- return sim_dict_total == sim_dict_done
2062+ return doe_def_total == doe_def_done
20442063
2045- def get_solutions (
2064+ def get_doe_solutions (
20462065 self ,
20472066 var_list : Optional [list ] = None ,
20482067 ) -> Optional [tuple [str ] | dict [str , dict [str , np .ndarray ]]]:
@@ -2058,7 +2077,7 @@ def get_solutions(
20582077 ```
20592078 import pandas as pd
20602079
2061- doe_sol = doe_mod.get_solutions ()
2080+ doe_sol = doe_mod.get_doe_solutions ()
20622081 for key in doe_sol:
20632082 data = doe_sol[key]['data']
20642083 if data:
@@ -2068,20 +2087,22 @@ def get_solutions(
20682087 ```
20692088
20702089 """
2071- if not isinstance (self ._sim_dict , dict ):
2090+ if not isinstance (self ._doe_def , dict ):
20722091 return None
20732092
2074- if len (self ._sim_dict ) == 0 :
2093+ if len (self ._doe_def ) == 0 :
20752094 raise ModelicaSystemError ("No result files available - all simulations did fail?" )
20762095
20772096 sol_dict : dict [str , dict [str , Any ]] = {}
2078- for resultfilename in self ._sim_dict :
2097+ for resultfilename in self ._doe_def :
20792098 resultfile = self ._resultpath / resultfilename
20802099
20812100 sol_dict [resultfilename ] = {}
20822101
2083- if not self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2084- sol_dict [resultfilename ]['msg' ] = 'No result file available!'
2102+ if not self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2103+ msg = f"No result file available for { resultfilename } "
2104+ logger .warning (msg )
2105+ sol_dict [resultfilename ]['msg' ] = msg
20852106 sol_dict [resultfilename ]['data' ] = {}
20862107 continue
20872108
0 commit comments