3939import numpy as np
4040import os
4141import pathlib
42- import platform
43- import re
44- import subprocess
4542import tempfile
4643import textwrap
4744from typing import Optional , Any
4845import warnings
4946import xml .etree .ElementTree as ET
5047
51- from OMPython .OMCSession import OMCSessionException , OMCSessionZMQ , OMCProcessLocal
48+ from OMPython .OMCSession import OMCSessionException , OMCSessionRunData , OMCSessionZMQ , OMCProcessLocal
5249
5350# define logger using the current module name as ID
5451logger = logging .getLogger (__name__ )
@@ -114,7 +111,14 @@ def __getitem__(self, index: int):
114111class ModelicaSystemCmd :
115112 """A compiled model executable."""
116113
117- def __init__ (self , runpath : pathlib .Path , modelname : str , timeout : Optional [float ] = None ) -> None :
114+ def __init__ (
115+ self ,
116+ session : OMCSessionZMQ ,
117+ runpath : pathlib .Path ,
118+ modelname : str ,
119+ timeout : Optional [float ] = None ,
120+ ) -> None :
121+ self ._session = session
118122 self ._runpath = pathlib .Path (runpath ).resolve ().absolute ()
119123 self ._model_name = modelname
120124 self ._timeout = timeout
@@ -229,27 +233,12 @@ def args_set(
229233 for arg in args :
230234 self .arg_set (key = arg , val = args [arg ])
231235
232- def get_exe (self ) -> pathlib .Path :
233- """Get the path to the compiled model executable."""
234- if platform .system () == "Windows" :
235- path_exe = self ._runpath / f"{ self ._model_name } .exe"
236- else :
237- path_exe = self ._runpath / self ._model_name
238-
239- if not path_exe .exists ():
240- raise ModelicaSystemError (f"Application file path not found: { path_exe } " )
241-
242- return path_exe
243-
244- def get_cmd (self ) -> list :
245- """Get a list with the path to the executable and all command line args.
246-
247- This can later be used as an argument for subprocess.run().
236+ def get_cmd_args (self ) -> list [str ]:
237+ """
238+ Get a list with the command arguments for the model executable.
248239 """
249240
250- path_exe = self .get_exe ()
251-
252- cmdl = [path_exe .as_posix ()]
241+ cmdl = []
253242 for key in sorted (self ._args ):
254243 if self ._args [key ] is None :
255244 cmdl .append (f"-{ key } " )
@@ -258,54 +247,26 @@ def get_cmd(self) -> list:
258247
259248 return cmdl
260249
261- def run (self ) -> int :
262- """Run the requested simulation.
263-
264- Returns
265- -------
266- Subprocess return code (0 on success).
250+ def definition (self ) -> OMCSessionRunData :
267251 """
252+ Define all needed data to run the model executable. The data is stored in an OMCSessionRunData object.
253+ """
254+ # ensure that a result filename is provided
255+ result_file = self .arg_get ('r' )
256+ if not isinstance (result_file , str ):
257+ result_file = (self ._runpath / f"{ self ._model_name } .mat" ).as_posix ()
258+
259+ omc_run_data = OMCSessionRunData (
260+ cmd_path = self ._runpath .as_posix (),
261+ cmd_model_name = self ._model_name ,
262+ cmd_args = self .get_cmd_args (),
263+ cmd_result_path = result_file ,
264+ cmd_timeout = self ._timeout ,
265+ )
268266
269- cmdl : list = self .get_cmd ()
270-
271- logger .debug ("Run OM command %s in %s" , repr (cmdl ), self ._runpath .as_posix ())
272-
273- if platform .system () == "Windows" :
274- path_dll = ""
275-
276- # set the process environment from the generated .bat file in windows which should have all the dependencies
277- path_bat = self ._runpath / f"{ self ._model_name } .bat"
278- if not path_bat .exists ():
279- raise ModelicaSystemError ("Batch file (*.bat) does not exist " + str (path_bat ))
280-
281- with open (file = path_bat , mode = 'r' , encoding = 'utf-8' ) as fh :
282- for line in fh :
283- match = re .match (r"^SET PATH=([^%]*)" , line , re .IGNORECASE )
284- if match :
285- path_dll = match .group (1 ).strip (';' ) # Remove any trailing semicolons
286- my_env = os .environ .copy ()
287- my_env ["PATH" ] = path_dll + os .pathsep + my_env ["PATH" ]
288- else :
289- # TODO: how to handle path to resources of external libraries for any system not Windows?
290- my_env = None
291-
292- try :
293- cmdres = subprocess .run (cmdl , capture_output = True , text = True , env = my_env , cwd = self ._runpath ,
294- timeout = self ._timeout , check = True )
295- stdout = cmdres .stdout .strip ()
296- stderr = cmdres .stderr .strip ()
297- returncode = cmdres .returncode
298-
299- logger .debug ("OM output for command %s:\n %s" , repr (cmdl ), stdout )
300-
301- if stderr :
302- raise ModelicaSystemError (f"Error running command { repr (cmdl )} : { stderr } " )
303- except subprocess .TimeoutExpired as ex :
304- raise ModelicaSystemError (f"Timeout running command { repr (cmdl )} " ) from ex
305- except subprocess .CalledProcessError as ex :
306- raise ModelicaSystemError (f"Error running command { repr (cmdl )} " ) from ex
267+ omc_run_data_updated = self ._session .omc_run_data_update (omc_run_data = omc_run_data )
307268
308- return returncode
269+ return omc_run_data_updated
309270
310271 @staticmethod
311272 def parse_simflags (simflags : str ) -> dict [str , Optional [str | dict [str , Any ] | numbers .Number ]]:
@@ -1026,6 +987,7 @@ def simulate_cmd(
1026987 """
1027988
1028989 om_cmd = ModelicaSystemCmd (
990+ session = self ._getconn ,
1029991 runpath = self .getWorkDirectory (),
1030992 modelname = self ._model_name ,
1031993 timeout = timeout ,
@@ -1118,7 +1080,8 @@ def simulate(
11181080 if self ._result_file .is_file ():
11191081 self ._result_file .unlink ()
11201082 # ... run simulation ...
1121- returncode = om_cmd .run ()
1083+ cmd_definition = om_cmd .definition ()
1084+ returncode = self ._getconn .run_model_executable (cmd_run_data = cmd_definition )
11221085 # and check returncode *AND* resultfile
11231086 if returncode != 0 and self ._result_file .is_file ():
11241087 # check for an empty (=> 0B) result file which indicates a crash of the model executable
@@ -1637,6 +1600,7 @@ def linearize(
16371600 )
16381601
16391602 om_cmd = ModelicaSystemCmd (
1603+ session = self ._getconn ,
16401604 runpath = self .getWorkDirectory (),
16411605 modelname = self ._model_name ,
16421606 timeout = timeout ,
@@ -1675,7 +1639,8 @@ def linearize(
16751639 linear_file = self .getWorkDirectory () / "linearized_model.py"
16761640 linear_file .unlink (missing_ok = True )
16771641
1678- returncode = om_cmd .run ()
1642+ cmd_definition = om_cmd .definition ()
1643+ returncode = self ._getconn .run_model_executable (cmd_run_data = cmd_definition )
16791644 if returncode != 0 :
16801645 raise ModelicaSystemError (f"Linearize failed with return code: { returncode } " )
16811646 if not linear_file .exists ():
0 commit comments