@@ -1717,11 +1717,11 @@ def run_doe():
17171717 simargs={"override": {'stopTime': 1.0}},
17181718 )
17191719 doe_mod.prepare()
1720- doe_dict = doe_mod.get_doe ()
1720+ doe_def = doe_mod.get_doe_definition ()
17211721 doe_mod.simulate()
1722- doe_sol = doe_mod.get_solutions ()
1722+ doe_sol = doe_mod.get_doe_solutions ()
17231723
1724- # ... work with doe_df and doe_sol ...
1724+ # ... work with doe_def and doe_sol ...
17251725
17261726
17271727 if __name__ == "__main__":
@@ -1787,8 +1787,8 @@ def __init__(
17871787 else :
17881788 self ._parameters = {}
17891789
1790- self ._sim_dict : Optional [dict [str , dict [str , Any ]]] = None
1791- self ._sim_task_query : queue . Queue = queue . Queue ()
1790+ self ._doe_def : Optional [dict [str , dict [str , Any ]]] = None
1791+ self ._doe_cmd : Optional [ dict [ str , OMCSessionRunData ]] = None
17921792
17931793 def prepare (self ) -> int :
17941794 """
@@ -1798,6 +1798,9 @@ def prepare(self) -> int:
17981798 The return value is the number of simulation defined.
17991799 """
18001800
1801+ doe_sim = {}
1802+ doe_def = {}
1803+
18011804 param_structure = {}
18021805 param_simple = {}
18031806 for param_name in self ._parameters .keys ():
@@ -1812,18 +1815,11 @@ def prepare(self) -> int:
18121815 param_structure_combinations = list (itertools .product (* param_structure .values ()))
18131816 param_simple_combinations = list (itertools .product (* param_simple .values ()))
18141817
1815- self ._sim_dict = {}
18161818 for idx_pc_structure , pc_structure in enumerate (param_structure_combinations ):
1817- mod_structure = ModelicaSystem (
1818- fileName = self ._fileName ,
1819- modelName = self ._modelName ,
1820- lmodel = self ._lmodel ,
1821- commandLineOptions = self ._CommandLineOptions ,
1822- variableFilter = self ._variableFilter ,
1823- customBuildDirectory = self ._customBuildDirectory ,
1824- omhome = self ._omhome ,
1825- build = False ,
1826- )
1819+
1820+ build_dir = self ._resultpath / f"DOE_{ idx_pc_structure :09d} "
1821+ build_dir .mkdir ()
1822+ self ._mod .setWorkDirectory (customBuildDirectory = build_dir )
18271823
18281824 sim_param_structure = {}
18291825 for idx_structure , pk_structure in enumerate (param_structure .keys ()):
@@ -1842,7 +1838,7 @@ def prepare(self) -> int:
18421838 raise ModelicaSystemError (f"Cannot set structural parameter { self ._modelName } .{ pk_structure } "
18431839 f"to { pk_value } using { repr (expression )} " )
18441840
1845- mod_structure . buildModel (variableFilter = self . _variableFilter )
1841+ self . _mod . buildModel ()
18461842
18471843 for idx_pc_simple , pc_simple in enumerate (param_simple_combinations ):
18481844 sim_param_simple = {}
@@ -1869,23 +1865,26 @@ def prepare(self) -> int:
18691865 }
18701866 )
18711867
1872- self ._sim_dict [resfilename ] = df_data
1873-
1874- mscmd = mod_structure .simulate_cmd (
1875- result_file = resultfile .absolute ().resolve (),
1868+ self ._mod .setParameters (sim_param_simple )
1869+ mscmd = self ._mod .simulate_cmd (
1870+ result_file = resultfile ,
18761871 timeout = self ._timeout ,
18771872 )
18781873 if self ._simargs is not None :
18791874 mscmd .args_set (args = self ._simargs )
1880- mscmd .args_set (args = {"override" : sim_param_simple })
1875+ cmd_definition = mscmd .definition ()
1876+ del mscmd
18811877
1882- self ._sim_task_query .put (mscmd )
1878+ doe_sim [resfilename ] = cmd_definition
1879+ doe_def [resfilename ] = df_data
18831880
1884- logger .info (f"Prepared { self ._sim_task_query .qsize ()} simulation definitions for the defined DoE." )
1881+ logger .info (f"Prepared { len (doe_sim )} simulation definitions for the defined DoE." )
1882+ self ._doe_cmd = doe_sim
1883+ self ._doe_def = doe_def
18851884
1886- return self . _sim_task_query . qsize ( )
1885+ return len ( doe_sim )
18871886
1888- def get_doe (self ) -> Optional [dict [str , dict [str , Any ]]]:
1887+ def get_doe_definition (self ) -> Optional [dict [str , dict [str , Any ]]]:
18891888 """
18901889 Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
18911890 settings including structural and non-structural parameters.
@@ -1895,12 +1894,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
18951894 ```
18961895 import pandas as pd
18971896
1898- doe_dict = doe_mod.get_doe ()
1897+ doe_dict = doe_mod.get_doe_definition ()
18991898 doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
19001899 ```
19011900
19021901 """
1903- return self ._sim_dict
1902+ return self ._doe_def
1903+
1904+ def get_doe_command (self ) -> Optional [dict [str , OMCSessionRunData ]]:
1905+ """
1906+ Get the definitions of simulations commands to run for this DoE.
1907+ """
1908+ return self ._doe_cmd
19041909
19051910 def simulate (
19061911 self ,
@@ -1912,71 +1917,84 @@ def simulate(
19121917 Returns True if all simulations were done successfully, else False.
19131918 """
19141919
1915- sim_query_total = self ._sim_task_query .qsize ()
1916- if not isinstance (self ._sim_dict , dict ) or len (self ._sim_dict ) == 0 :
1920+ if self ._doe_cmd is None or self ._doe_def is None :
1921+ raise ModelicaSystemError ("DoE preparation missing - call prepare() first!" )
1922+
1923+ doe_cmd_total = len (self ._doe_cmd )
1924+ doe_def_total = len (self ._doe_def )
1925+
1926+ if doe_cmd_total != doe_def_total :
1927+ raise ModelicaSystemError (f"Mismatch between number simulation commands ({ doe_cmd_total } ) "
1928+ f"and simulation definitions ({ doe_def_total } )." )
1929+
1930+ doe_task_query : queue .Queue = queue .Queue ()
1931+ for doe_cmd in self ._doe_cmd .values ():
1932+ doe_task_query .put (doe_cmd )
1933+
1934+ if not isinstance (self ._doe_def , dict ) or len (self ._doe_def ) == 0 :
19171935 raise ModelicaSystemError ("Missing Doe Summary!" )
1918- sim_dict_total = len (self ._sim_dict )
19191936
19201937 def worker (worker_id , task_queue ):
19211938 while True :
19221939 try :
19231940 # Get the next task from the queue
1924- mscmd = task_queue .get (block = False )
1941+ cmd_definition = task_queue .get (block = False )
19251942 except queue .Empty :
19261943 logger .info (f"[Worker { worker_id } ] No more simulations to run." )
19271944 break
19281945
1929- if mscmd is None :
1946+ if cmd_definition is None :
19301947 raise ModelicaSystemError ("Missing simulation definition!" )
19311948
1932- resultfile = mscmd . arg_get ( key = 'r' )
1933- resultpath = pathlib . Path (resultfile )
1949+ resultfile = cmd_definition . cmd_result_path
1950+ resultpath = self . _mod . _getconn . omcpath (resultfile )
19341951
19351952 logger .info (f"[Worker { worker_id } ] Performing task: { resultpath .name } " )
19361953
19371954 try :
1938- mscmd .run ()
1955+ returncode = self ._mod ._getconn .run_model_executable (cmd_run_data = cmd_definition )
1956+ logger .info (f"[Worker { worker_id } ] Simulation { resultpath .name } "
1957+ f"finished with return code: { returncode } " )
19391958 except ModelicaSystemError as ex :
19401959 logger .warning (f"Simulation error for { resultpath .name } : { ex } " )
19411960
19421961 # Mark the task as done
19431962 task_queue .task_done ()
19441963
1945- sim_query_done = sim_query_total - self . _sim_task_query .qsize ()
1964+ sim_query_done = doe_cmd_total - doe_task_query .qsize ()
19461965 logger .info (f"[Worker { worker_id } ] Task completed: { resultpath .name } "
1947- f"({ sim_query_total - sim_query_done } /{ sim_query_total } = "
1948- f"{ (sim_query_total - sim_query_done ) / sim_query_total * 100 :.2f} % of tasks left)" )
1949-
1950- logger .info (f"Start simulations for DoE with { sim_query_total } simulations "
1951- f"using { num_workers } workers ..." )
1966+ f"({ doe_cmd_total - sim_query_done } /{ doe_cmd_total } = "
1967+ f"{ (doe_cmd_total - sim_query_done ) / doe_cmd_total * 100 :.2f} % of tasks left)" )
19521968
19531969 # Create and start worker threads
1970+ logger .info (f"Start simulations for DoE with { doe_cmd_total } simulations "
1971+ f"using { num_workers } workers ..." )
19541972 threads = []
19551973 for i in range (num_workers ):
1956- thread = threading .Thread (target = worker , args = (i , self . _sim_task_query ))
1974+ thread = threading .Thread (target = worker , args = (i , doe_task_query ))
19571975 thread .start ()
19581976 threads .append (thread )
19591977
19601978 # Wait for all threads to complete
19611979 for thread in threads :
19621980 thread .join ()
19631981
1964- sim_dict_done = 0
1965- for resultfilename in self ._sim_dict :
1982+ doe_def_done = 0
1983+ for resultfilename in self ._doe_def :
19661984 resultfile = self ._resultpath / resultfilename
19671985
19681986 # include check for an empty (=> 0B) result file which indicates a crash of the model executable
19691987 # see: https://github.com/OpenModelica/OMPython/issues/261
19701988 # https://github.com/OpenModelica/OpenModelica/issues/13829
1971- if resultfile .is_file () and resultfile .stat (). st_size > 0 :
1972- self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
1973- sim_dict_done += 1
1989+ if resultfile .is_file () and resultfile .size () > 0 :
1990+ self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
1991+ doe_def_done += 1
19741992
1975- logger .info (f"All workers finished ({ sim_dict_done } of { sim_dict_total } simulations with a result file)." )
1993+ logger .info (f"All workers finished ({ doe_def_done } of { doe_def_total } simulations with a result file)." )
19761994
1977- return sim_dict_total == sim_dict_done
1995+ return doe_def_total == doe_def_done
19781996
1979- def get_solutions (
1997+ def get_doe_solutions (
19801998 self ,
19811999 var_list : Optional [list ] = None ,
19822000 ) -> Optional [tuple [str ] | dict [str , dict [str , np .ndarray ]]]:
@@ -1992,7 +2010,7 @@ def get_solutions(
19922010 ```
19932011 import pandas as pd
19942012
1995- doe_sol = doe_mod.get_solutions ()
2013+ doe_sol = doe_mod.get_doe_solutions ()
19962014 for key in doe_sol:
19972015 data = doe_sol[key]['data']
19982016 if data:
@@ -2002,20 +2020,22 @@ def get_solutions(
20022020 ```
20032021
20042022 """
2005- if not isinstance (self ._sim_dict , dict ):
2023+ if not isinstance (self ._doe_def , dict ):
20062024 return None
20072025
2008- if len (self ._sim_dict ) == 0 :
2026+ if len (self ._doe_def ) == 0 :
20092027 raise ModelicaSystemError ("No result files available - all simulations did fail?" )
20102028
20112029 sol_dict : dict [str , dict [str , Any ]] = {}
2012- for resultfilename in self ._sim_dict :
2030+ for resultfilename in self ._doe_def :
20132031 resultfile = self ._resultpath / resultfilename
20142032
20152033 sol_dict [resultfilename ] = {}
20162034
2017- if not self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2018- sol_dict [resultfilename ]['msg' ] = 'No result file available!'
2035+ if not self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2036+ msg = f"No result file available for { resultfilename } "
2037+ logger .warning (msg )
2038+ sol_dict [resultfilename ]['msg' ] = msg
20192039 sol_dict [resultfilename ]['data' ] = {}
20202040 continue
20212041
0 commit comments