@@ -1784,11 +1784,11 @@ def run_doe():
17841784 simargs={"override": {'stopTime': 1.0}},
17851785 )
17861786 doe_mod.prepare()
1787- doe_dict = doe_mod.get_doe ()
1787+ doe_def = doe_mod.get_doe_definition ()
17881788 doe_mod.simulate()
1789- doe_sol = doe_mod.get_solutions ()
1789+ doe_sol = doe_mod.get_doe_solutions ()
17901790
1791- # ... work with doe_df and doe_sol ...
1791+ # ... work with doe_def and doe_sol ...
17921792
17931793
17941794 if __name__ == "__main__":
@@ -1854,8 +1854,8 @@ def __init__(
18541854 else :
18551855 self ._parameters = {}
18561856
1857- self ._sim_dict : Optional [dict [str , dict [str , Any ]]] = None
1858- self ._sim_task_query : queue . Queue = queue . Queue ()
1857+ self ._doe_def : Optional [dict [str , dict [str , Any ]]] = None
1858+ self ._doe_cmd : Optional [ dict [ str , OMCSessionRunData ]] = None
18591859
18601860 def prepare (self ) -> int :
18611861 """
@@ -1865,6 +1865,9 @@ def prepare(self) -> int:
18651865 The return value is the number of simulation defined.
18661866 """
18671867
1868+ doe_sim = {}
1869+ doe_def = {}
1870+
18681871 param_structure = {}
18691872 param_simple = {}
18701873 for param_name in self ._parameters .keys ():
@@ -1879,18 +1882,11 @@ def prepare(self) -> int:
18791882 param_structure_combinations = list (itertools .product (* param_structure .values ()))
18801883 param_simple_combinations = list (itertools .product (* param_simple .values ()))
18811884
1882- self ._sim_dict = {}
18831885 for idx_pc_structure , pc_structure in enumerate (param_structure_combinations ):
1884- mod_structure = ModelicaSystem (
1885- fileName = self ._fileName ,
1886- modelName = self ._modelName ,
1887- lmodel = self ._lmodel ,
1888- commandLineOptions = self ._CommandLineOptions ,
1889- variableFilter = self ._variableFilter ,
1890- customBuildDirectory = self ._customBuildDirectory ,
1891- omhome = self ._omhome ,
1892- build = False ,
1893- )
1886+
1887+ build_dir = self ._resultpath / f"DOE_{ idx_pc_structure :09d} "
1888+ build_dir .mkdir ()
1889+ self ._mod .setWorkDirectory (customBuildDirectory = build_dir )
18941890
18951891 sim_param_structure = {}
18961892 for idx_structure , pk_structure in enumerate (param_structure .keys ()):
@@ -1909,7 +1905,7 @@ def prepare(self) -> int:
19091905 raise ModelicaSystemError (f"Cannot set structural parameter { self ._modelName } .{ pk_structure } "
19101906 f"to { pk_value } using { repr (expression )} " )
19111907
1912- mod_structure . buildModel (variableFilter = self . _variableFilter )
1908+ self . _mod . buildModel ()
19131909
19141910 for idx_pc_simple , pc_simple in enumerate (param_simple_combinations ):
19151911 sim_param_simple = {}
@@ -1936,23 +1932,26 @@ def prepare(self) -> int:
19361932 }
19371933 )
19381934
1939- self ._sim_dict [resfilename ] = df_data
1940-
1941- mscmd = mod_structure .simulate_cmd (
1942- result_file = resultfile .absolute ().resolve (),
1935+ self ._mod .setParameters (sim_param_simple )
1936+ mscmd = self ._mod .simulate_cmd (
1937+ result_file = resultfile ,
19431938 timeout = self ._timeout ,
19441939 )
19451940 if self ._simargs is not None :
19461941 mscmd .args_set (args = self ._simargs )
1947- mscmd .args_set (args = {"override" : sim_param_simple })
1942+ cmd_definition = mscmd .definition ()
1943+ del mscmd
19481944
1949- self ._sim_task_query .put (mscmd )
1945+ doe_sim [resfilename ] = cmd_definition
1946+ doe_def [resfilename ] = df_data
19501947
1951- logger .info (f"Prepared { self ._sim_task_query .qsize ()} simulation definitions for the defined DoE." )
1948+ logger .info (f"Prepared { len (doe_sim )} simulation definitions for the defined DoE." )
1949+ self ._doe_cmd = doe_sim
1950+ self ._doe_def = doe_def
19521951
1953- return self . _sim_task_query . qsize ( )
1952+ return len ( doe_sim )
19541953
1955- def get_doe (self ) -> Optional [dict [str , dict [str , Any ]]]:
1954+ def get_doe_definition (self ) -> Optional [dict [str , dict [str , Any ]]]:
19561955 """
19571956 Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
19581957 settings including structural and non-structural parameters.
@@ -1962,12 +1961,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
19621961 ```
19631962 import pandas as pd
19641963
1965- doe_dict = doe_mod.get_doe ()
1964+ doe_dict = doe_mod.get_doe_definition ()
19661965 doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
19671966 ```
19681967
19691968 """
1970- return self ._sim_dict
1969+ return self ._doe_def
1970+
1971+ def get_doe_command (self ) -> Optional [dict [str , OMCSessionRunData ]]:
1972+ """
1973+ Get the definitions of simulations commands to run for this DoE.
1974+ """
1975+ return self ._doe_cmd
19711976
19721977 def simulate (
19731978 self ,
@@ -1979,71 +1984,85 @@ def simulate(
19791984 Returns True if all simulations were done successfully, else False.
19801985 """
19811986
1982- sim_query_total = self ._sim_task_query .qsize ()
1983- if not isinstance (self ._sim_dict , dict ) or len (self ._sim_dict ) == 0 :
1987+ if self ._doe_cmd is None or self ._doe_def is None :
1988+ raise ModelicaSystemError ("DoE preparation missing - call prepare() first!" )
1989+
1990+ doe_cmd_total = len (self ._doe_cmd )
1991+ doe_def_total = len (self ._doe_def )
1992+
1993+ if doe_cmd_total != doe_def_total :
1994+ raise ModelicaSystemError (f"Mismatch between number simulation commands ({ doe_cmd_total } ) "
1995+ f"and simulation definitions ({ doe_def_total } )." )
1996+
1997+ doe_task_query : queue .Queue = queue .Queue ()
1998+ if self ._doe_cmd is not None :
1999+ for doe_cmd in self ._doe_cmd .values ():
2000+ doe_task_query .put (doe_cmd )
2001+
2002+ if not isinstance (self ._doe_def , dict ) or len (self ._doe_def ) == 0 :
19842003 raise ModelicaSystemError ("Missing Doe Summary!" )
1985- sim_dict_total = len (self ._sim_dict )
19862004
19872005 def worker (worker_id , task_queue ):
19882006 while True :
19892007 try :
19902008 # Get the next task from the queue
1991- mscmd = task_queue .get (block = False )
2009+ cmd_definition = task_queue .get (block = False )
19922010 except queue .Empty :
19932011 logger .info (f"[Worker { worker_id } ] No more simulations to run." )
19942012 break
19952013
1996- if mscmd is None :
2014+ if cmd_definition is None :
19972015 raise ModelicaSystemError ("Missing simulation definition!" )
19982016
1999- resultfile = mscmd . arg_get ( key = 'r' )
2000- resultpath = pathlib . Path (resultfile )
2017+ resultfile = cmd_definition . cmd_result_path
2018+ resultpath = self . _mod . _getconn . omcpath (resultfile )
20012019
20022020 logger .info (f"[Worker { worker_id } ] Performing task: { resultpath .name } " )
20032021
20042022 try :
2005- mscmd .run ()
2023+ returncode = self ._mod ._getconn .run_model_executable (cmd_run_data = cmd_definition )
2024+ logger .info (f"[Worker { worker_id } ] Simulation { resultpath .name } "
2025+ f"finished with return code: { returncode } " )
20062026 except ModelicaSystemError as ex :
20072027 logger .warning (f"Simulation error for { resultpath .name } : { ex } " )
20082028
20092029 # Mark the task as done
20102030 task_queue .task_done ()
20112031
2012- sim_query_done = sim_query_total - self . _sim_task_query .qsize ()
2032+ sim_query_done = doe_cmd_total - doe_task_query .qsize ()
20132033 logger .info (f"[Worker { worker_id } ] Task completed: { resultpath .name } "
2014- f"({ sim_query_total - sim_query_done } /{ sim_query_total } = "
2015- f"{ (sim_query_total - sim_query_done ) / sim_query_total * 100 :.2f} % of tasks left)" )
2016-
2017- logger .info (f"Start simulations for DoE with { sim_query_total } simulations "
2018- f"using { num_workers } workers ..." )
2034+ f"({ doe_cmd_total - sim_query_done } /{ doe_cmd_total } = "
2035+ f"{ (doe_cmd_total - sim_query_done ) / doe_cmd_total * 100 :.2f} % of tasks left)" )
20192036
20202037 # Create and start worker threads
2038+ logger .info (f"Start simulations for DoE with { doe_cmd_total } simulations "
2039+ f"using { num_workers } workers ..." )
20212040 threads = []
20222041 for i in range (num_workers ):
2023- thread = threading .Thread (target = worker , args = (i , self . _sim_task_query ))
2042+ thread = threading .Thread (target = worker , args = (i , doe_task_query ))
20242043 thread .start ()
20252044 threads .append (thread )
20262045
20272046 # Wait for all threads to complete
20282047 for thread in threads :
20292048 thread .join ()
20302049
2031- sim_dict_done = 0
2032- for resultfilename in self ._sim_dict :
2050+ doe_def_done = 0
2051+ for resultfilename in self ._doe_def :
20332052 resultfile = self ._resultpath / resultfilename
20342053
20352054 # include check for an empty (=> 0B) result file which indicates a crash of the model executable
20362055 # see: https://github.com/OpenModelica/OMPython/issues/261
20372056 # https://github.com/OpenModelica/OpenModelica/issues/13829
2038- if resultfile .is_file () and resultfile .stat (). st_size > 0 :
2039- self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2040- sim_dict_done += 1
2057+ if resultfile .is_file () and resultfile .size () > 0 :
2058+ self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
2059+ doe_def_done += 1
20412060
2042- logger .info (f"All workers finished ({ sim_dict_done } of { sim_dict_total } simulations with a result file)." )
2061+ logger .info (f"All workers finished ({ doe_def_done } of { doe_def_total } simulations with a result file)." )
20432062
2044- return sim_dict_total == sim_dict_done
2063+ return doe_def_total == doe_def_done
20452064
2046- def get_solutions (
2065+ def get_doe_solutions (
20472066 self ,
20482067 var_list : Optional [list ] = None ,
20492068 ) -> Optional [tuple [str ] | dict [str , dict [str , np .ndarray ]]]:
@@ -2059,7 +2078,7 @@ def get_solutions(
20592078 ```
20602079 import pandas as pd
20612080
2062- doe_sol = doe_mod.get_solutions ()
2081+ doe_sol = doe_mod.get_doe_solutions ()
20632082 for key in doe_sol:
20642083 data = doe_sol[key]['data']
20652084 if data:
@@ -2069,20 +2088,22 @@ def get_solutions(
20692088 ```
20702089
20712090 """
2072- if not isinstance (self ._sim_dict , dict ):
2091+ if not isinstance (self ._doe_def , dict ):
20732092 return None
20742093
2075- if len (self ._sim_dict ) == 0 :
2094+ if len (self ._doe_def ) == 0 :
20762095 raise ModelicaSystemError ("No result files available - all simulations did fail?" )
20772096
20782097 sol_dict : dict [str , dict [str , Any ]] = {}
2079- for resultfilename in self ._sim_dict :
2098+ for resultfilename in self ._doe_def :
20802099 resultfile = self ._resultpath / resultfilename
20812100
20822101 sol_dict [resultfilename ] = {}
20832102
2084- if not self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2085- sol_dict [resultfilename ]['msg' ] = 'No result file available!'
2103+ if not self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2104+ msg = f"No result file available for { resultfilename } "
2105+ logger .warning (msg )
2106+ sol_dict [resultfilename ]['msg' ] = msg
20862107 sol_dict [resultfilename ]['data' ] = {}
20872108 continue
20882109
0 commit comments