Skip to content

Commit 74fa5c2

Browse files
committed
Merge branch 'OMCSession_executable' into MERGE@all
2 parents d37e6f7 + 9674e5f commit 74fa5c2

3 files changed

Lines changed: 203 additions & 73 deletions

File tree

OMPython/ModelicaSystem.py

Lines changed: 36 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,15 @@
4141
import numpy as np
4242
import os
4343
import pathlib
44-
import platform
4544
import queue
46-
import re
47-
import subprocess
4845
import tempfile
4946
import textwrap
5047
import threading
5148
from typing import Any, Optional
5249
import warnings
5350
import xml.etree.ElementTree as ET
5451

55-
from OMPython.OMCSession import OMCSessionException, OMCSessionZMQ, OMCProcessLocal
52+
from OMPython.OMCSession import OMCSessionException, OMCSessionRunData, OMCSessionZMQ, OMCProcessLocal
5653

5754
# define logger using the current module name as ID
5855
logger = logging.getLogger(__name__)
@@ -118,7 +115,14 @@ def __getitem__(self, index: int):
118115
class ModelicaSystemCmd:
119116
"""A compiled model executable."""
120117

121-
def __init__(self, runpath: pathlib.Path, modelname: str, timeout: Optional[float] = None) -> None:
118+
def __init__(
119+
self,
120+
session: OMCSessionZMQ,
121+
runpath: pathlib.Path,
122+
modelname: str,
123+
timeout: Optional[float] = None,
124+
) -> None:
125+
self._session = session
122126
self._runpath = pathlib.Path(runpath).resolve().absolute()
123127
self._model_name = modelname
124128
self._timeout = timeout
@@ -192,27 +196,12 @@ def args_set(self, args: dict[str, Optional[str | dict[str, Any]]]) -> None:
192196
for arg in args:
193197
self.arg_set(key=arg, val=args[arg])
194198

195-
def get_exe(self) -> pathlib.Path:
196-
"""Get the path to the compiled model executable."""
197-
if platform.system() == "Windows":
198-
path_exe = self._runpath / f"{self._model_name}.exe"
199-
else:
200-
path_exe = self._runpath / self._model_name
201-
202-
if not path_exe.exists():
203-
raise ModelicaSystemError(f"Application file path not found: {path_exe}")
204-
205-
return path_exe
206-
207-
def get_cmd(self) -> list:
208-
"""Get a list with the path to the executable and all command line args.
209-
210-
This can later be used as an argument for subprocess.run().
199+
def get_cmd_args(self) -> list[str]:
200+
"""
201+
Get a list with the command arguments for the model executable.
211202
"""
212203

213-
path_exe = self.get_exe()
214-
215-
cmdl = [path_exe.as_posix()]
204+
cmdl = []
216205
for key in self._args:
217206
if self._args[key] is None:
218207
cmdl.append(f"-{key}")
@@ -221,54 +210,26 @@ def get_cmd(self) -> list:
221210

222211
return cmdl
223212

224-
def run(self) -> int:
225-
"""Run the requested simulation.
226-
227-
Returns
228-
-------
229-
Subprocess return code (0 on success).
213+
def definition(self) -> OMCSessionRunData:
230214
"""
215+
Define all needed data to run the model executable. The data is stored in an OMCSessionRunData object.
216+
"""
217+
# ensure that a result filename is provided
218+
result_file = self.arg_get('r')
219+
if not isinstance(result_file, str):
220+
result_file = (self._runpath / f"{self._model_name}.mat").as_posix()
221+
222+
omc_run_data = OMCSessionRunData(
223+
cmd_path=self._runpath.as_posix(),
224+
cmd_model_name=self._model_name,
225+
cmd_args=self.get_cmd_args(),
226+
cmd_result_path=result_file,
227+
cmd_timeout=self._timeout,
228+
)
231229

232-
cmdl: list = self.get_cmd()
233-
234-
logger.debug("Run OM command %s in %s", repr(cmdl), self._runpath.as_posix())
235-
236-
if platform.system() == "Windows":
237-
path_dll = ""
238-
239-
# set the process environment from the generated .bat file in windows which should have all the dependencies
240-
path_bat = self._runpath / f"{self._model_name}.bat"
241-
if not path_bat.exists():
242-
raise ModelicaSystemError("Batch file (*.bat) does not exist " + str(path_bat))
243-
244-
with open(file=path_bat, mode='r', encoding='utf-8') as fh:
245-
for line in fh:
246-
match = re.match(r"^SET PATH=([^%]*)", line, re.IGNORECASE)
247-
if match:
248-
path_dll = match.group(1).strip(';') # Remove any trailing semicolons
249-
my_env = os.environ.copy()
250-
my_env["PATH"] = path_dll + os.pathsep + my_env["PATH"]
251-
else:
252-
# TODO: how to handle path to resources of external libraries for any system not Windows?
253-
my_env = None
254-
255-
try:
256-
cmdres = subprocess.run(cmdl, capture_output=True, text=True, env=my_env, cwd=self._runpath,
257-
timeout=self._timeout, check=True)
258-
stdout = cmdres.stdout.strip()
259-
stderr = cmdres.stderr.strip()
260-
returncode = cmdres.returncode
261-
262-
logger.debug("OM output for command %s:\n%s", repr(cmdl), stdout)
263-
264-
if stderr:
265-
raise ModelicaSystemError(f"Error running command {repr(cmdl)}: {stderr}")
266-
except subprocess.TimeoutExpired as ex:
267-
raise ModelicaSystemError(f"Timeout running command {repr(cmdl)}") from ex
268-
except subprocess.CalledProcessError as ex:
269-
raise ModelicaSystemError(f"Error running command {repr(cmdl)}") from ex
230+
omc_run_data_updated = self._session.omc_run_data_update(omc_run_data)
270231

271-
return returncode
232+
return omc_run_data_updated
272233

273234
@staticmethod
274235
def parse_simflags(simflags: str) -> dict[str, Optional[str | dict[str, str]]]:
@@ -983,6 +944,7 @@ def simulate_cmd(
983944
"""
984945

985946
om_cmd = ModelicaSystemCmd(
947+
session=self._getconn,
986948
runpath=self.getWorkDirectory(),
987949
modelname=self._model_name,
988950
timeout=timeout,
@@ -1074,7 +1036,8 @@ def simulate(
10741036
if self._result_file.is_file():
10751037
self._result_file.unlink()
10761038
# ... run simulation ...
1077-
returncode = om_cmd.run()
1039+
cmd_definition = om_cmd.definition()
1040+
returncode = self._getconn.run_model_executable(cmd_run_data=cmd_definition)
10781041
# and check returncode *AND* resultfile
10791042
if returncode != 0 and self._result_file.is_file():
10801043
# check for an empty (=> 0B) result file which indicates a crash of the model executable
@@ -1592,6 +1555,7 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
15921555
)
15931556

15941557
om_cmd = ModelicaSystemCmd(
1558+
session=self._getconn,
15951559
runpath=self.getWorkDirectory(),
15961560
modelname=self._model_name,
15971561
timeout=timeout,
@@ -1631,7 +1595,8 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
16311595

16321596
linear_file.unlink(missing_ok=True)
16331597

1634-
returncode = om_cmd.run()
1598+
cmd_definition = om_cmd.definition()
1599+
returncode = self._getconn.run_model_executable(cmd_run_data=cmd_definition)
16351600
if returncode != 0:
16361601
raise ModelicaSystemError(f"Linearize failed with return code: {returncode}")
16371602
if not linear_file.exists():

0 commit comments

Comments
 (0)