@@ -1707,11 +1707,11 @@ def run_doe():
17071707 simargs={"override": {'stopTime': 1.0}},
17081708 )
17091709 doe_mod.prepare()
1710- doe_dict = doe_mod.get_doe ()
1710+ doe_def = doe_mod.get_doe_definition ()
17111711 doe_mod.simulate()
1712- doe_sol = doe_mod.get_solutions ()
1712+ doe_sol = doe_mod.get_doe_solutions ()
17131713
1714- # ... work with doe_df and doe_sol ...
1714+ # ... work with doe_def and doe_sol ...
17151715
17161716
17171717 if __name__ == "__main__":
@@ -1777,8 +1777,8 @@ def __init__(
17771777 else :
17781778 self ._parameters = {}
17791779
1780- self ._sim_dict : Optional [dict [str , dict [str , Any ]]] = None
1781- self ._sim_task_query : queue . Queue = queue . Queue ()
1780+ self ._doe_def : Optional [dict [str , dict [str , Any ]]] = None
1781+ self ._doe_cmd : Optional [ dict [ str , OMCSessionRunData ]] = None
17821782
17831783 def prepare (self ) -> int :
17841784 """
@@ -1788,6 +1788,9 @@ def prepare(self) -> int:
17881788 The return value is the number of simulation defined.
17891789 """
17901790
1791+ doe_sim = {}
1792+ doe_def = {}
1793+
17911794 param_structure = {}
17921795 param_simple = {}
17931796 for param_name in self ._parameters .keys ():
@@ -1802,18 +1805,11 @@ def prepare(self) -> int:
18021805 param_structure_combinations = list (itertools .product (* param_structure .values ()))
18031806 param_simple_combinations = list (itertools .product (* param_simple .values ()))
18041807
1805- self ._sim_dict = {}
18061808 for idx_pc_structure , pc_structure in enumerate (param_structure_combinations ):
1807- mod_structure = ModelicaSystem (
1808- fileName = self ._fileName ,
1809- modelName = self ._modelName ,
1810- lmodel = self ._lmodel ,
1811- commandLineOptions = self ._CommandLineOptions ,
1812- variableFilter = self ._variableFilter ,
1813- customBuildDirectory = self ._customBuildDirectory ,
1814- omhome = self ._omhome ,
1815- build = False ,
1816- )
1809+
1810+ build_dir = self ._resultpath / f"DOE_{ idx_pc_structure :09d} "
1811+ build_dir .mkdir ()
1812+ self ._mod .setWorkDirectory (customBuildDirectory = build_dir )
18171813
18181814 sim_param_structure = {}
18191815 for idx_structure , pk_structure in enumerate (param_structure .keys ()):
@@ -1832,7 +1828,7 @@ def prepare(self) -> int:
18321828 raise ModelicaSystemError (f"Cannot set structural parameter { self ._modelName } .{ pk_structure } "
18331829 f"to { pk_value } using { repr (expression )} " )
18341830
1835- mod_structure . buildModel (variableFilter = self . _variableFilter )
1831+ self . _mod . buildModel ()
18361832
18371833 for idx_pc_simple , pc_simple in enumerate (param_simple_combinations ):
18381834 sim_param_simple = {}
@@ -1859,23 +1855,26 @@ def prepare(self) -> int:
18591855 }
18601856 )
18611857
1862- self ._sim_dict [resfilename ] = df_data
1863-
1864- mscmd = mod_structure .simulate_cmd (
1865- result_file = resultfile .absolute ().resolve (),
1858+ self ._mod .setParameters (sim_param_simple )
1859+ mscmd = self ._mod .simulate_cmd (
1860+ result_file = resultfile ,
18661861 timeout = self ._timeout ,
18671862 )
18681863 if self ._simargs is not None :
18691864 mscmd .args_set (args = self ._simargs )
1870- mscmd .args_set (args = {"override" : sim_param_simple })
1865+ cmd_definition = mscmd .definition ()
1866+ del mscmd
18711867
1872- self ._sim_task_query .put (mscmd )
1868+ doe_sim [resfilename ] = cmd_definition
1869+ doe_def [resfilename ] = df_data
18731870
1874- logger .info (f"Prepared { self ._sim_task_query .qsize ()} simulation definitions for the defined DoE." )
1871+ logger .info (f"Prepared { len (doe_sim )} simulation definitions for the defined DoE." )
1872+ self ._doe_cmd = doe_sim
1873+ self ._doe_def = doe_def
18751874
1876- return self . _sim_task_query . qsize ( )
1875+ return len ( doe_sim )
18771876
1878- def get_doe (self ) -> Optional [dict [str , dict [str , Any ]]]:
1877+ def get_doe_definition (self ) -> Optional [dict [str , dict [str , Any ]]]:
18791878 """
18801879 Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
18811880 settings including structural and non-structural parameters.
@@ -1885,12 +1884,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
18851884 ```
18861885 import pandas as pd
18871886
1888- doe_dict = doe_mod.get_doe ()
1887+ doe_dict = doe_mod.get_doe_definition ()
18891888 doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
18901889 ```
18911890
18921891 """
1893- return self ._sim_dict
1892+ return self ._doe_def
1893+
1894+ def get_doe_command (self ) -> Optional [dict [str , OMCSessionRunData ]]:
1895+ """
1896+ Get the definitions of simulations commands to run for this DoE.
1897+ """
1898+ return self ._doe_cmd
18941899
18951900 def simulate (
18961901 self ,
@@ -1902,71 +1907,85 @@ def simulate(
19021907 Returns True if all simulations were done successfully, else False.
19031908 """
19041909
1905- sim_query_total = self ._sim_task_query .qsize ()
1906- if not isinstance (self ._sim_dict , dict ) or len (self ._sim_dict ) == 0 :
1910+ if self ._doe_cmd is None or self ._doe_def is None :
1911+ raise ModelicaSystemError ("DoE preparation missing - call prepare() first!" )
1912+
1913+ doe_cmd_total = len (self ._doe_cmd )
1914+ doe_def_total = len (self ._doe_def )
1915+
1916+ if doe_cmd_total != doe_def_total :
1917+ raise ModelicaSystemError (f"Mismatch between number simulation commands ({ doe_cmd_total } ) "
1918+ f"and simulation definitions ({ doe_def_total } )." )
1919+
1920+ doe_task_query : queue .Queue = queue .Queue ()
1921+ if self ._doe_cmd is not None :
1922+ for doe_cmd in self ._doe_cmd .values ():
1923+ doe_task_query .put (doe_cmd )
1924+
1925+ if not isinstance (self ._doe_def , dict ) or len (self ._doe_def ) == 0 :
19071926 raise ModelicaSystemError ("Missing Doe Summary!" )
1908- sim_dict_total = len (self ._sim_dict )
19091927
19101928 def worker (worker_id , task_queue ):
19111929 while True :
19121930 try :
19131931 # Get the next task from the queue
1914- mscmd = task_queue .get (block = False )
1932+ cmd_definition = task_queue .get (block = False )
19151933 except queue .Empty :
19161934 logger .info (f"[Worker { worker_id } ] No more simulations to run." )
19171935 break
19181936
1919- if mscmd is None :
1937+ if cmd_definition is None :
19201938 raise ModelicaSystemError ("Missing simulation definition!" )
19211939
1922- resultfile = mscmd . arg_get ( key = 'r' )
1923- resultpath = pathlib . Path (resultfile )
1940+ resultfile = cmd_definition . cmd_result_path
1941+ resultpath = self . _mod . _getconn . omcpath (resultfile )
19241942
19251943 logger .info (f"[Worker { worker_id } ] Performing task: { resultpath .name } " )
19261944
19271945 try :
1928- mscmd .run ()
1946+ returncode = self ._mod ._getconn .run_model_executable (cmd_run_data = cmd_definition )
1947+ logger .info (f"[Worker { worker_id } ] Simulation { resultpath .name } "
1948+ f"finished with return code: { returncode } " )
19291949 except ModelicaSystemError as ex :
19301950 logger .warning (f"Simulation error for { resultpath .name } : { ex } " )
19311951
19321952 # Mark the task as done
19331953 task_queue .task_done ()
19341954
1935- sim_query_done = sim_query_total - self . _sim_task_query .qsize ()
1955+ sim_query_done = doe_cmd_total - doe_task_query .qsize ()
19361956 logger .info (f"[Worker { worker_id } ] Task completed: { resultpath .name } "
1937- f"({ sim_query_total - sim_query_done } /{ sim_query_total } = "
1938- f"{ (sim_query_total - sim_query_done ) / sim_query_total * 100 :.2f} % of tasks left)" )
1939-
1940- logger .info (f"Start simulations for DoE with { sim_query_total } simulations "
1941- f"using { num_workers } workers ..." )
1957+ f"({ doe_cmd_total - sim_query_done } /{ doe_cmd_total } = "
1958+ f"{ (doe_cmd_total - sim_query_done ) / doe_cmd_total * 100 :.2f} % of tasks left)" )
19421959
19431960 # Create and start worker threads
1961+ logger .info (f"Start simulations for DoE with { doe_cmd_total } simulations "
1962+ f"using { num_workers } workers ..." )
19441963 threads = []
19451964 for i in range (num_workers ):
1946- thread = threading .Thread (target = worker , args = (i , self . _sim_task_query ))
1965+ thread = threading .Thread (target = worker , args = (i , doe_task_query ))
19471966 thread .start ()
19481967 threads .append (thread )
19491968
19501969 # Wait for all threads to complete
19511970 for thread in threads :
19521971 thread .join ()
19531972
1954- sim_dict_done = 0
1955- for resultfilename in self ._sim_dict :
1973+ doe_def_done = 0
1974+ for resultfilename in self ._doe_def :
19561975 resultfile = self ._resultpath / resultfilename
19571976
19581977 # include check for an empty (=> 0B) result file which indicates a crash of the model executable
19591978 # see: https://github.com/OpenModelica/OMPython/issues/261
19601979 # https://github.com/OpenModelica/OpenModelica/issues/13829
1961- if resultfile .is_file () and resultfile .stat (). st_size > 0 :
1962- self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
1963- sim_dict_done += 1
1980+ if resultfile .is_file () and resultfile .size () > 0 :
1981+ self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ] = True
1982+ doe_def_done += 1
19641983
1965- logger .info (f"All workers finished ({ sim_dict_done } of { sim_dict_total } simulations with a result file)." )
1984+ logger .info (f"All workers finished ({ doe_def_done } of { doe_def_total } simulations with a result file)." )
19661985
1967- return sim_dict_total == sim_dict_done
1986+ return doe_def_total == doe_def_done
19681987
1969- def get_solutions (
1988+ def get_doe_solutions (
19701989 self ,
19711990 var_list : Optional [list ] = None ,
19721991 ) -> Optional [tuple [str ] | dict [str , dict [str , np .ndarray ]]]:
@@ -1982,7 +2001,7 @@ def get_solutions(
19822001 ```
19832002 import pandas as pd
19842003
1985- doe_sol = doe_mod.get_solutions ()
2004+ doe_sol = doe_mod.get_doe_solutions ()
19862005 for key in doe_sol:
19872006 data = doe_sol[key]['data']
19882007 if data:
@@ -1992,20 +2011,22 @@ def get_solutions(
19922011 ```
19932012
19942013 """
1995- if not isinstance (self ._sim_dict , dict ):
2014+ if not isinstance (self ._doe_def , dict ):
19962015 return None
19972016
1998- if len (self ._sim_dict ) == 0 :
2017+ if len (self ._doe_def ) == 0 :
19992018 raise ModelicaSystemError ("No result files available - all simulations did fail?" )
20002019
20012020 sol_dict : dict [str , dict [str , Any ]] = {}
2002- for resultfilename in self ._sim_dict :
2021+ for resultfilename in self ._doe_def :
20032022 resultfile = self ._resultpath / resultfilename
20042023
20052024 sol_dict [resultfilename ] = {}
20062025
2007- if not self ._sim_dict [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2008- sol_dict [resultfilename ]['msg' ] = 'No result file available!'
2026+ if not self ._doe_def [resultfilename ][self .DICT_RESULT_AVAILABLE ]:
2027+ msg = f"No result file available for { resultfilename } "
2028+ logger .warning (msg )
2029+ sol_dict [resultfilename ]['msg' ] = msg
20092030 sol_dict [resultfilename ]['data' ] = {}
20102031 continue
20112032
0 commit comments