Skip to content

Commit c9ebd94

Browse files
committed
[ModelicaSystemDoE] rename variables & cleanup
1 parent c960064 commit c9ebd94

1 file changed

Lines changed: 76 additions & 55 deletions

File tree

OMPython/ModelicaSystem.py

Lines changed: 76 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,11 +1814,11 @@ def run_doe():
18141814
simargs={"override": {'stopTime': 1.0}},
18151815
)
18161816
doe_mod.prepare()
1817-
doe_dict = doe_mod.get_doe()
1817+
doe_def = doe_mod.get_doe_definition()
18181818
doe_mod.simulate()
1819-
doe_sol = doe_mod.get_solutions()
1819+
doe_sol = doe_mod.get_doe_solutions()
18201820
1821-
# ... work with doe_df and doe_sol ...
1821+
# ... work with doe_def and doe_sol ...
18221822
18231823
18241824
if __name__ == "__main__":
@@ -1890,8 +1890,8 @@ def __init__(
18901890
else:
18911891
self._parameters = {}
18921892

1893-
self._sim_dict: Optional[dict[str, dict[str, Any]]] = None
1894-
self._sim_task_query: queue.Queue = queue.Queue()
1893+
self._doe_def: Optional[dict[str, dict[str, Any]]] = None
1894+
self._doe_cmd: Optional[dict[str, OMCSessionRunData]] = None
18951895

18961896
def session(self) -> OMCSessionZMQ:
18971897
"""
@@ -1907,6 +1907,9 @@ def prepare(self) -> int:
19071907
The return value is the number of simulation defined.
19081908
"""
19091909

1910+
doe_sim = {}
1911+
doe_def = {}
1912+
19101913
param_structure = {}
19111914
param_non_structure = {}
19121915
for param_name in self._parameters.keys():
@@ -1921,18 +1924,11 @@ def prepare(self) -> int:
19211924
param_structure_combinations = list(itertools.product(*param_structure.values()))
19221925
param_simple_combinations = list(itertools.product(*param_non_structure.values()))
19231926

1924-
self._sim_dict = {}
19251927
for idx_pc_structure, pc_structure in enumerate(param_structure_combinations):
1926-
mod_structure = ModelicaSystem(
1927-
fileName=self._fileName,
1928-
modelName=self._modelName,
1929-
lmodel=self._lmodel,
1930-
commandLineOptions=self._CommandLineOptions,
1931-
variableFilter=self._variableFilter,
1932-
customBuildDirectory=self._customBuildDirectory,
1933-
omhome=self._omhome,
1934-
build=False,
1935-
)
1928+
1929+
build_dir = self._resultpath / f"DOE_{idx_pc_structure:09d}"
1930+
build_dir.mkdir()
1931+
self._mod.setWorkDirectory(customBuildDirectory=build_dir)
19361932

19371933
sim_param_structure = {}
19381934
for idx_structure, pk_structure in enumerate(param_structure.keys()):
@@ -1947,12 +1943,12 @@ def prepare(self) -> int:
19471943
expression = f"setParameterValue({self._modelName}, {pk_structure}, {pk_value_bool_str});"
19481944
else:
19491945
expression = f"setParameterValue({self._modelName}, {pk_structure}, {pk_value})"
1950-
res = mod_structure.sendExpression(expression)
1946+
res = self._mod.sendExpression(expression)
19511947
if not res:
19521948
raise ModelicaSystemError(f"Cannot set structural parameter {self._modelName}.{pk_structure} "
19531949
f"to {pk_value} using {repr(expression)}")
19541950

1955-
mod_structure.buildModel(variableFilter=self._variableFilter)
1951+
self._mod.buildModel()
19561952

19571953
for idx_pc_simple, pc_simple in enumerate(param_simple_combinations):
19581954
sim_param_simple = {}
@@ -1979,23 +1975,26 @@ def prepare(self) -> int:
19791975
}
19801976
)
19811977

1982-
self._sim_dict[resfilename] = df_data
1983-
1984-
mscmd = mod_structure.simulate_cmd(
1978+
self._mod.setParameters(sim_param_simple)
1979+
mscmd = self._mod.simulate_cmd(
19851980
result_file=resultfile,
19861981
timeout=self._timeout,
19871982
)
19881983
if self._simargs is not None:
19891984
mscmd.args_set(args=self._simargs)
1990-
mscmd.args_set(args={"override": sim_param_simple})
1985+
cmd_definition = mscmd.definition()
1986+
del mscmd
19911987

1992-
self._sim_task_query.put(mscmd)
1988+
doe_sim[resfilename] = cmd_definition
1989+
doe_def[resfilename] = df_data
19931990

1994-
logger.info(f"Prepared {self._sim_task_query.qsize()} simulation definitions for the defined DoE.")
1991+
logger.info(f"Prepared {len(doe_sim)} simulation definitions for the defined DoE.")
1992+
self._doe_cmd = doe_sim
1993+
self._doe_def = doe_def
19951994

1996-
return self._sim_task_query.qsize()
1995+
return len(doe_sim)
19971996

1998-
def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
1997+
def get_doe_definition(self) -> Optional[dict[str, dict[str, Any]]]:
19991998
"""
20001999
Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation
20012000
settings including structural and non-structural parameters.
@@ -2005,12 +2004,18 @@ def get_doe(self) -> Optional[dict[str, dict[str, Any]]]:
20052004
```
20062005
import pandas as pd
20072006
2008-
doe_dict = doe_mod.get_doe()
2007+
doe_dict = doe_mod.get_doe_definition()
20092008
doe_df = pd.DataFrame.from_dict(data=doe_dict, orient='index')
20102009
```
20112010
20122011
"""
2013-
return self._sim_dict
2012+
return self._doe_def
2013+
2014+
def get_doe_command(self) -> Optional[dict[str, OMCSessionRunData]]:
2015+
"""
2016+
Get the definitions of simulations commands to run for this DoE.
2017+
"""
2018+
return self._doe_cmd
20142019

20152020
def simulate(
20162021
self,
@@ -2022,71 +2027,85 @@ def simulate(
20222027
Returns True if all simulations were done successfully, else False.
20232028
"""
20242029

2025-
sim_query_total = self._sim_task_query.qsize()
2026-
if not isinstance(self._sim_dict, dict) or len(self._sim_dict) == 0:
2030+
if self._doe_cmd is None or self._doe_def is None:
2031+
raise ModelicaSystemError("DoE preparation missing - call prepare() first!")
2032+
2033+
doe_cmd_total = len(self._doe_cmd)
2034+
doe_def_total = len(self._doe_def)
2035+
2036+
if doe_cmd_total != doe_def_total:
2037+
raise ModelicaSystemError(f"Mismatch between number simulation commands ({doe_cmd_total}) "
2038+
f"and simulation definitions ({doe_def_total}).")
2039+
2040+
doe_task_query: queue.Queue = queue.Queue()
2041+
if self._doe_cmd is not None:
2042+
for doe_cmd in self._doe_cmd.values():
2043+
doe_task_query.put(doe_cmd)
2044+
2045+
if not isinstance(self._doe_def, dict) or len(self._doe_def) == 0:
20272046
raise ModelicaSystemError("Missing Doe Summary!")
2028-
sim_dict_total = len(self._sim_dict)
20292047

20302048
def worker(worker_id, task_queue):
20312049
while True:
20322050
try:
20332051
# Get the next task from the queue
2034-
mscmd = task_queue.get(block=False)
2052+
cmd_definition = task_queue.get(block=False)
20352053
except queue.Empty:
20362054
logger.info(f"[Worker {worker_id}] No more simulations to run.")
20372055
break
20382056

2039-
if mscmd is None:
2057+
if cmd_definition is None:
20402058
raise ModelicaSystemError("Missing simulation definition!")
20412059

2042-
resultfile = mscmd.arg_get(key='r')
2060+
resultfile = cmd_definition.cmd_result_path
20432061
resultpath = self.session().omcpath(resultfile)
20442062

20452063
logger.info(f"[Worker {worker_id}] Performing task: {resultpath.name}")
20462064

20472065
try:
2048-
mscmd.run()
2066+
returncode = self._mod._getconn.run_model_executable(cmd_run_data=cmd_definition)
2067+
logger.info(f"[Worker {worker_id}] Simulation {resultpath.name} "
2068+
f"finished with return code: {returncode}")
20492069
except ModelicaSystemError as ex:
20502070
logger.warning(f"Simulation error for {resultpath.name}: {ex}")
20512071

20522072
# Mark the task as done
20532073
task_queue.task_done()
20542074

2055-
sim_query_done = sim_query_total - self._sim_task_query.qsize()
2075+
sim_query_done = doe_cmd_total - doe_task_query.qsize()
20562076
logger.info(f"[Worker {worker_id}] Task completed: {resultpath.name} "
2057-
f"({sim_query_total - sim_query_done}/{sim_query_total} = "
2058-
f"{(sim_query_total - sim_query_done) / sim_query_total * 100:.2f}% of tasks left)")
2059-
2060-
logger.info(f"Start simulations for DoE with {sim_query_total} simulations "
2061-
f"using {num_workers} workers ...")
2077+
f"({doe_cmd_total - sim_query_done}/{doe_cmd_total} = "
2078+
f"{(doe_cmd_total - sim_query_done) / doe_cmd_total * 100:.2f}% of tasks left)")
20622079

20632080
# Create and start worker threads
2081+
logger.info(f"Start simulations for DoE with {doe_cmd_total} simulations "
2082+
f"using {num_workers} workers ...")
20642083
threads = []
20652084
for i in range(num_workers):
2066-
thread = threading.Thread(target=worker, args=(i, self._sim_task_query))
2085+
thread = threading.Thread(target=worker, args=(i, doe_task_query))
20672086
thread.start()
20682087
threads.append(thread)
20692088

20702089
# Wait for all threads to complete
20712090
for thread in threads:
20722091
thread.join()
20732092

2074-
sim_dict_done = 0
2075-
for resultfilename in self._sim_dict:
2093+
doe_def_done = 0
2094+
for resultfilename in self._doe_def:
20762095
resultfile = self._resultpath / resultfilename
20772096

20782097
# include check for an empty (=> 0B) result file which indicates a crash of the model executable
20792098
# see: https://github.com/OpenModelica/OMPython/issues/261
20802099
# https://github.com/OpenModelica/OpenModelica/issues/13829
20812100
if resultfile.is_file() and resultfile.size() > 0:
2082-
self._sim_dict[resultfilename][self.DICT_RESULT_AVAILABLE] = True
2083-
sim_dict_done += 1
2101+
self._doe_def[resultfilename][self.DICT_RESULT_AVAILABLE] = True
2102+
doe_def_done += 1
20842103

2085-
logger.info(f"All workers finished ({sim_dict_done} of {sim_dict_total} simulations with a result file).")
2104+
logger.info(f"All workers finished ({doe_def_done} of {doe_def_total} simulations with a result file).")
20862105

2087-
return sim_dict_total == sim_dict_done
2106+
return doe_def_total == doe_def_done
20882107

2089-
def get_solutions(
2108+
def get_doe_solutions(
20902109
self,
20912110
var_list: Optional[list] = None,
20922111
) -> Optional[tuple[str] | dict[str, dict[str, np.ndarray]]]:
@@ -2102,7 +2121,7 @@ def get_solutions(
21022121
```
21032122
import pandas as pd
21042123
2105-
doe_sol = doe_mod.get_solutions()
2124+
doe_sol = doe_mod.get_doe_solutions()
21062125
for key in doe_sol:
21072126
data = doe_sol[key]['data']
21082127
if data:
@@ -2112,20 +2131,22 @@ def get_solutions(
21122131
```
21132132
21142133
"""
2115-
if not isinstance(self._sim_dict, dict):
2134+
if not isinstance(self._doe_def, dict):
21162135
return None
21172136

2118-
if len(self._sim_dict) == 0:
2137+
if len(self._doe_def) == 0:
21192138
raise ModelicaSystemError("No result files available - all simulations did fail?")
21202139

21212140
sol_dict: dict[str, dict[str, Any]] = {}
2122-
for resultfilename in self._sim_dict:
2141+
for resultfilename in self._doe_def:
21232142
resultfile = self._resultpath / resultfilename
21242143

21252144
sol_dict[resultfilename] = {}
21262145

2127-
if not self._sim_dict[resultfilename][self.DICT_RESULT_AVAILABLE]:
2128-
sol_dict[resultfilename]['msg'] = 'No result file available!'
2146+
if not self._doe_def[resultfilename][self.DICT_RESULT_AVAILABLE]:
2147+
msg = f"No result file available for {resultfilename}"
2148+
logger.warning(msg)
2149+
sol_dict[resultfilename]['msg'] = msg
21292150
sol_dict[resultfilename]['data'] = {}
21302151
continue
21312152

0 commit comments

Comments
 (0)