Skip to content

Commit 2031c53

Browse files
committed
Merge branch 'ModelicaSystemCmd_use_OMCPath' into MP_merge
2 parents 7d4a557 + 80f5c96 commit 2031c53

5 files changed

Lines changed: 274 additions & 73 deletions

File tree

OMPython/ModelicaSystem.py

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,13 @@
3939
import numpy as np
4040
import os
4141
import pathlib
42-
import platform
43-
import re
4442
import subprocess
4543
import textwrap
4644
from typing import Optional, Any
4745
import warnings
4846
import xml.etree.ElementTree as ET
4947

50-
from OMPython.OMCSession import OMCSessionException, OMCSessionZMQ, OMCProcessLocal, OMCPath
48+
from OMPython.OMCSession import OMCSessionException, OMCSessionZMQ, OMCProcessLocal, OMCPath, OMCSessionRunData
5149

5250
# define logger using the current module name as ID
5351
logger = logging.getLogger(__name__)
@@ -113,7 +111,14 @@ def __getitem__(self, index: int):
113111
class ModelicaSystemCmd:
114112
"""A compiled model executable."""
115113

116-
def __init__(self, runpath: pathlib.Path, modelname: str, timeout: Optional[float] = None) -> None:
114+
def __init__(
115+
self,
116+
session: OMCSessionZMQ,
117+
runpath: OMCPath,
118+
modelname: str,
119+
timeout: Optional[float] = None,
120+
) -> None:
121+
self._session = session
117122
self._runpath = pathlib.Path(runpath).resolve().absolute()
118123
self._model_name = modelname
119124
self._timeout = timeout
@@ -187,27 +192,12 @@ def args_set(self, args: dict[str, Optional[str | dict[str, str]]]) -> None:
187192
for arg in args:
188193
self.arg_set(key=arg, val=args[arg])
189194

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

208-
path_exe = self.get_exe()
209-
210-
cmdl = [path_exe.as_posix()]
200+
cmdl = []
211201
for key in self._args:
212202
if self._args[key] is None:
213203
cmdl.append(f"-{key}")
@@ -216,40 +206,51 @@ def get_cmd(self) -> list:
216206

217207
return cmdl
218208

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

227-
cmdl: list = self.get_cmd()
226+
omc_run_data_updated = self._session.omc_run_data_update(omc_run_data, session=self._session)
228227

229-
logger.debug("Run OM command %s in %s", repr(cmdl), self._runpath.as_posix())
228+
return omc_run_data_updated
230229

231-
if platform.system() == "Windows":
232-
path_dll = ""
230+
@staticmethod
231+
def run_cmd(cmd_run_data: OMCSessionRunData) -> int:
232+
"""
233+
Run the command defined in cmd_run_data. This class is defined as static method such that there is no need to
234+
keep instances of over classes around.
235+
"""
233236

234-
# set the process environment from the generated .bat file in windows which should have all the dependencies
235-
path_bat = self._runpath / f"{self._model_name}.bat"
236-
if not path_bat.exists():
237-
raise ModelicaSystemError("Batch file (*.bat) does not exist " + str(path_bat))
237+
my_env = os.environ.copy()
238+
if isinstance(cmd_run_data.cmd_library_path, str):
239+
my_env["PATH"] = cmd_run_data.cmd_library_path + os.pathsep + my_env["PATH"]
238240

239-
with open(file=path_bat, mode='r', encoding='utf-8') as fh:
240-
for line in fh:
241-
match = re.match(r"^SET PATH=([^%]*)", line, re.IGNORECASE)
242-
if match:
243-
path_dll = match.group(1).strip(';') # Remove any trailing semicolons
244-
my_env = os.environ.copy()
245-
my_env["PATH"] = path_dll + os.pathsep + my_env["PATH"]
246-
else:
247-
# TODO: how to handle path to resources of external libraries for any system not Windows?
248-
my_env = None
241+
cmdl = cmd_run_data.get_cmd()
249242

243+
logger.debug("Run OM command %s in %s", repr(cmdl), cmd_run_data.cmd_path)
250244
try:
251-
cmdres = subprocess.run(cmdl, capture_output=True, text=True, env=my_env, cwd=self._runpath,
252-
timeout=self._timeout, check=True)
245+
cmdres = subprocess.run(
246+
cmdl,
247+
capture_output=True,
248+
text=True,
249+
env=my_env,
250+
cwd=cmd_run_data.cmd_cwd_local,
251+
timeout=cmd_run_data.cmd_timeout,
252+
check=True,
253+
)
253254
stdout = cmdres.stdout.strip()
254255
stderr = cmdres.stderr.strip()
255256
returncode = cmdres.returncode
@@ -265,6 +266,16 @@ def run(self) -> int:
265266

266267
return returncode
267268

269+
def run(self) -> int:
270+
"""Run the requested simulation.
271+
272+
Returns
273+
-------
274+
Subprocess return code (0 on success).
275+
"""
276+
cmd_run_data = self.run_def()
277+
return self.run_cmd(cmd_run_data=cmd_run_data)
278+
268279
@staticmethod
269280
def parse_simflags(simflags: str) -> dict[str, Optional[str | dict[str, str]]]:
270281
"""
@@ -379,8 +390,6 @@ def __init__(
379390
self._linearized_states: list[str] = [] # linearization states list
380391

381392
if omc_process is not None:
382-
if not isinstance(omc_process, OMCProcessLocal):
383-
raise ModelicaSystemError("Invalid (local) omc process definition provided!")
384393
self._getconn = OMCSessionZMQ(omc_process=omc_process)
385394
else:
386395
self._getconn = OMCSessionZMQ(omhome=omhome)
@@ -970,7 +979,8 @@ def simulate_cmd(
970979
"""
971980

972981
om_cmd = ModelicaSystemCmd(
973-
runpath=pathlib.Path(self.getWorkDirectory()),
982+
session=self._getconn,
983+
runpath=self.getWorkDirectory(),
974984
modelname=self._model_name,
975985
timeout=timeout,
976986
)
@@ -1581,7 +1591,8 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
15811591
)
15821592

15831593
om_cmd = ModelicaSystemCmd(
1584-
runpath=pathlib.Path(self.getWorkDirectory()),
1594+
session=self._getconn,
1595+
runpath=self.getWorkDirectory(),
15851596
modelname=self._model_name,
15861597
timeout=timeout,
15871598
)

0 commit comments

Comments
 (0)