|
15 | 15 | import re |
16 | 16 | import textwrap |
17 | 17 | import threading |
18 | | -from typing import Any, cast, Optional |
| 18 | +from typing import Any, cast, Optional, Tuple |
19 | 19 | import warnings |
20 | 20 | import xml.etree.ElementTree as ET |
21 | 21 |
|
@@ -2099,9 +2099,9 @@ class ModelicaSystem(ModelicaSystemOMC): |
2099 | 2099 | """ |
2100 | 2100 |
|
2101 | 2101 |
|
2102 | | -class ModelicaSystemDoE: |
| 2102 | +class ModelicaDoEABC(metaclass=abc.ABCMeta): |
2103 | 2103 | """ |
2104 | | - Class to run DoEs based on a (Open)Modelica model using ModelicaSystem |
| 2104 | + Base class to run DoEs based on a (Open)Modelica model using ModelicaSystem |
2105 | 2105 |
|
2106 | 2106 | Example |
2107 | 2107 | ------- |
@@ -2243,30 +2243,11 @@ def prepare(self) -> int: |
2243 | 2243 | param_non_structural_combinations = list(itertools.product(*param_non_structure.values())) |
2244 | 2244 |
|
2245 | 2245 | for idx_pc_structure, pc_structure in enumerate(param_structure_combinations): |
2246 | | - |
2247 | | - build_dir = self._resultpath / f"DOE_{idx_pc_structure:09d}" |
2248 | | - build_dir.mkdir() |
2249 | | - self._mod.setWorkDirectory(work_directory=build_dir) |
2250 | | - |
2251 | | - sim_param_structure = {} |
2252 | | - for idx_structure, pk_structure in enumerate(param_structure.keys()): |
2253 | | - sim_param_structure[pk_structure] = pc_structure[idx_structure] |
2254 | | - |
2255 | | - pk_value = pc_structure[idx_structure] |
2256 | | - if isinstance(pk_value, str): |
2257 | | - pk_value_str = self.get_session().escape_str(pk_value) |
2258 | | - expression = f"setParameterValue({self._model_name}, {pk_structure}, \"{pk_value_str}\")" |
2259 | | - elif isinstance(pk_value, bool): |
2260 | | - pk_value_bool_str = "true" if pk_value else "false" |
2261 | | - expression = f"setParameterValue({self._model_name}, {pk_structure}, {pk_value_bool_str});" |
2262 | | - else: |
2263 | | - expression = f"setParameterValue({self._model_name}, {pk_structure}, {pk_value})" |
2264 | | - res = self._mod.sendExpression(expression) |
2265 | | - if not res: |
2266 | | - raise ModelicaSystemError(f"Cannot set structural parameter {self._model_name}.{pk_structure} " |
2267 | | - f"to {pk_value} using {repr(expression)}") |
2268 | | - |
2269 | | - self._mod.buildModel() |
| 2246 | + sim_param_structure = self._prepare_structure_parameters( |
| 2247 | + idx_pc_structure=idx_pc_structure, |
| 2248 | + pc_structure=pc_structure, |
| 2249 | + param_structure=param_structure, |
| 2250 | + ) |
2270 | 2251 |
|
2271 | 2252 | for idx_non_structural, pk_non_structural in enumerate(param_non_structural_combinations): |
2272 | 2253 | sim_param_non_structural = {} |
@@ -2311,6 +2292,17 @@ def prepare(self) -> int: |
2311 | 2292 |
|
2312 | 2293 | return len(doe_sim) |
2313 | 2294 |
|
| 2295 | + @abc.abstractmethod |
| 2296 | + def _prepare_structure_parameters( |
| 2297 | + self, |
| 2298 | + idx_pc_structure: int, |
| 2299 | + pc_structure: Tuple, |
| 2300 | + param_structure: dict[str, list[str] | list[int] | list[float]], |
| 2301 | + ) -> dict[str, str | int | float]: |
| 2302 | + """ |
| 2303 | + Handle structural parameters. This should be implemented by the derived class |
| 2304 | + """ |
| 2305 | + |
2314 | 2306 | def get_doe_definition(self) -> Optional[dict[str, dict[str, Any]]]: |
2315 | 2307 | """ |
2316 | 2308 | Get the defined DoE as a dict, where each key is the result filename and the value is a dict of simulation |
@@ -2422,6 +2414,64 @@ def worker(worker_id, task_queue): |
2422 | 2414 |
|
2423 | 2415 | return doe_def_total == doe_def_done |
2424 | 2416 |
|
| 2417 | + |
| 2418 | +class ModelicaSystemDoE(ModelicaDoEABC): |
| 2419 | + """ |
| 2420 | + Class to run DoEs based on a (Open)Modelica model using ModelicaSystemOMC |
| 2421 | +
|
| 2422 | + The example is the same as defined for ModelicaDoEABC |
| 2423 | + """ |
| 2424 | + |
| 2425 | + def __init__( |
| 2426 | + self, |
| 2427 | + # ModelicaSystem definition to use |
| 2428 | + mod: ModelicaSystemOMC, |
| 2429 | + # simulation specific input |
| 2430 | + # TODO: add more settings (simulation options, input options, ...) |
| 2431 | + simargs: Optional[dict[str, Optional[str | dict[str, str] | numbers.Number]]] = None, |
| 2432 | + # DoE specific inputs |
| 2433 | + resultpath: Optional[str | os.PathLike] = None, |
| 2434 | + parameters: Optional[dict[str, list[str] | list[int] | list[float]]] = None, |
| 2435 | + ) -> None: |
| 2436 | + super().__init__( |
| 2437 | + mod=mod, |
| 2438 | + simargs=simargs, |
| 2439 | + resultpath=resultpath, |
| 2440 | + parameters=parameters, |
| 2441 | + ) |
| 2442 | + |
| 2443 | + def _prepare_structure_parameters( |
| 2444 | + self, |
| 2445 | + idx_pc_structure: int, |
| 2446 | + pc_structure: Tuple, |
| 2447 | + param_structure: dict[str, list[str] | list[int] | list[float]], |
| 2448 | + ) -> dict[str, str | int | float]: |
| 2449 | + build_dir = self._resultpath / f"DOE_{idx_pc_structure:09d}" |
| 2450 | + build_dir.mkdir() |
| 2451 | + self._mod.setWorkDirectory(work_directory=build_dir) |
| 2452 | + |
| 2453 | + sim_param_structure = {} |
| 2454 | + for idx_structure, pk_structure in enumerate(param_structure.keys()): |
| 2455 | + sim_param_structure[pk_structure] = pc_structure[idx_structure] |
| 2456 | + |
| 2457 | + pk_value = pc_structure[idx_structure] |
| 2458 | + if isinstance(pk_value, str): |
| 2459 | + pk_value_str = self.get_session().escape_str(pk_value) |
| 2460 | + expression = f"setParameterValue({self._model_name}, {pk_structure}, \"{pk_value_str}\")" |
| 2461 | + elif isinstance(pk_value, bool): |
| 2462 | + pk_value_bool_str = "true" if pk_value else "false" |
| 2463 | + expression = f"setParameterValue({self._model_name}, {pk_structure}, {pk_value_bool_str});" |
| 2464 | + else: |
| 2465 | + expression = f"setParameterValue({self._model_name}, {pk_structure}, {pk_value})" |
| 2466 | + res = self._mod.sendExpression(expression) |
| 2467 | + if not res: |
| 2468 | + raise ModelicaSystemError(f"Cannot set structural parameter {self._model_name}.{pk_structure} " |
| 2469 | + f"to {pk_value} using {repr(expression)}") |
| 2470 | + |
| 2471 | + self._mod.buildModel() |
| 2472 | + |
| 2473 | + return sim_param_structure |
| 2474 | + |
2425 | 2475 | def get_doe_solutions( |
2426 | 2476 | self, |
2427 | 2477 | var_list: Optional[list] = None, |
|
0 commit comments