3939import numpy as np
4040import os
4141import pathlib
42- import platform
43- import re
4442import subprocess
4543import textwrap
4644from typing import Optional , Any
4745import warnings
4846import 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
5351logger = logging .getLogger (__name__ )
@@ -113,7 +111,14 @@ def __getitem__(self, index: int):
113111class 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