3838import numbers
3939import numpy as np
4040import os
41- import pathlib
4241import platform
4342import re
4443import subprocess
45- import tempfile
4644import textwrap
4745from typing import Optional , Any
4846import warnings
4947import xml .etree .ElementTree as ET
5048
51- from OMPython .OMCSession import OMCSessionException , OMCSessionZMQ , OMCProcessLocal
49+ from OMPython .OMCSession import OMCSessionException , OMCSessionZMQ , OMCProcessLocal , OMCPath
5250
5351# define logger using the current module name as ID
5452logger = logging .getLogger (__name__ )
@@ -114,8 +112,8 @@ def __getitem__(self, index: int):
114112class ModelicaSystemCmd :
115113 """A compiled model executable."""
116114
117- def __init__ (self , runpath : pathlib . Path , modelname : str , timeout : Optional [float ] = None ) -> None :
118- self ._runpath = pathlib . Path ( runpath ). resolve (). absolute ()
115+ def __init__ (self , runpath : OMCPath , modelname : str , timeout : Optional [float ] = None ) -> None :
116+ self ._runpath = runpath
119117 self ._model_name = modelname
120118 self ._timeout = timeout
121119 self ._args : dict [str , str | None ] = {}
@@ -175,7 +173,7 @@ def args_set(self, args: dict[str, Optional[str | dict[str, str]]]) -> None:
175173 for arg in args :
176174 self .arg_set (key = arg , val = args [arg ])
177175
178- def get_exe (self ) -> pathlib . Path :
176+ def get_exe (self ) -> OMCPath :
179177 """Get the path to the compiled model executable."""
180178 if platform .system () == "Windows" :
181179 path_exe = self ._runpath / f"{ self ._model_name } .exe"
@@ -295,7 +293,7 @@ def parse_simflags(simflags: str) -> dict[str, Optional[str | dict[str, str]]]:
295293class ModelicaSystem :
296294 def __init__ (
297295 self ,
298- fileName : Optional [str | os .PathLike | pathlib . Path ] = None ,
296+ fileName : Optional [str | os .PathLike ] = None ,
299297 modelName : Optional [str ] = None ,
300298 lmodel : Optional [list [str | tuple [str , str ]]] = None ,
301299 commandLineOptions : Optional [str ] = None ,
@@ -384,9 +382,13 @@ def __init__(
384382
385383 self ._lmodel = lmodel # may be needed if model is derived from other model
386384 self ._model_name = modelName # Model class name
387- self ._file_name = pathlib .Path (fileName ).resolve () if fileName is not None else None # Model file/package name
385+ if fileName is not None :
386+ file_name = self ._getconn .omcpath (fileName ).resolve ()
387+ else :
388+ file_name = None
389+ self ._file_name : Optional [OMCPath ] = file_name # Model file/package name
388390 self ._simulated = False # True if the model has already been simulated
389- self ._result_file : Optional [pathlib . Path ] = None # for storing result file
391+ self ._result_file : Optional [OMCPath ] = None # for storing result file
390392 self ._variable_filter = variableFilter
391393
392394 if self ._file_name is not None and not self ._file_name .is_file (): # if file does not exist
@@ -398,7 +400,7 @@ def __init__(
398400 self .setCommandLineOptions ("--linearizationDumpLanguage=python" )
399401 self .setCommandLineOptions ("--generateSymbolicLinearization" )
400402
401- self ._work_dir : pathlib . Path = self .setWorkDirectory (customBuildDirectory )
403+ self ._work_dir : OMCPath = self .setWorkDirectory (customBuildDirectory )
402404
403405 if self ._file_name is not None :
404406 self ._loadLibrary (lmodel = self ._lmodel )
@@ -418,7 +420,7 @@ def setCommandLineOptions(self, commandLineOptions: Optional[str] = None):
418420 exp = f'setCommandLineOptions("{ commandLineOptions } ")'
419421 self .sendExpression (exp )
420422
421- def _loadFile (self , fileName : pathlib . Path ):
423+ def _loadFile (self , fileName : OMCPath ):
422424 # load file
423425 self .sendExpression (f'loadFile("{ fileName .as_posix ()} ")' )
424426
@@ -446,17 +448,17 @@ def _loadLibrary(self, lmodel: list):
446448 '1)["Modelica"]\n '
447449 '2)[("Modelica","3.2.3"), "PowerSystems"]\n ' )
448450
449- def setWorkDirectory (self , customBuildDirectory : Optional [str | os .PathLike ] = None ) -> pathlib . Path :
451+ def setWorkDirectory (self , customBuildDirectory : Optional [str | os .PathLike ] = None ) -> OMCPath :
450452 """
451453 Define the work directory for the ModelicaSystem / OpenModelica session. The model is build within this
452454 directory. If no directory is defined a unique temporary directory is created.
453455 """
454456 if customBuildDirectory is not None :
455- workdir = pathlib . Path (customBuildDirectory ).absolute ()
457+ workdir = self . _getconn . omcpath (customBuildDirectory ).absolute ()
456458 if not workdir .is_dir ():
457459 raise IOError (f"Provided work directory does not exists: { customBuildDirectory } !" )
458460 else :
459- workdir = pathlib . Path ( tempfile . mkdtemp () ).absolute ()
461+ workdir = self . _getconn . omcpath_tempdir ( ).absolute ()
460462 if not workdir .is_dir ():
461463 raise IOError (f"{ workdir } could not be created" )
462464
@@ -469,7 +471,7 @@ def setWorkDirectory(self, customBuildDirectory: Optional[str | os.PathLike] = N
469471 # ... and also return the defined path
470472 return workdir
471473
472- def getWorkDirectory (self ) -> pathlib . Path :
474+ def getWorkDirectory (self ) -> OMCPath :
473475 """
474476 Return the defined working directory for this ModelicaSystem / OpenModelica session.
475477 """
@@ -487,7 +489,7 @@ def buildModel(self, variableFilter: Optional[str] = None):
487489 buildModelResult = self ._requestApi ("buildModel" , self ._model_name , properties = varFilter )
488490 logger .debug ("OM model build result: %s" , buildModelResult )
489491
490- xml_file = pathlib . Path (buildModelResult [0 ]).parent / buildModelResult [1 ]
492+ xml_file = self . _getconn . omcpath (buildModelResult [0 ]).parent / buildModelResult [1 ]
491493 self ._xmlparse (xml_file = xml_file )
492494
493495 def sendExpression (self , expr : str , parsed : bool = True ):
@@ -514,7 +516,7 @@ def _requestApi(self, apiName, entity=None, properties=None): # 2
514516
515517 return self .sendExpression (exp )
516518
517- def _xmlparse (self , xml_file : pathlib . Path ):
519+ def _xmlparse (self , xml_file : OMCPath ):
518520 if not xml_file .is_file ():
519521 raise ModelicaSystemError (f"XML file not generated: { xml_file } " )
520522
@@ -934,7 +936,7 @@ def getOptimizationOptions(self, names: Optional[str | list[str]] = None) -> dic
934936
935937 def simulate_cmd (
936938 self ,
937- result_file : pathlib . Path ,
939+ result_file : OMCPath ,
938940 simflags : Optional [str ] = None ,
939941 simargs : Optional [dict [str , Optional [str | dict [str , str ]]]] = None ,
940942 timeout : Optional [float ] = None ,
@@ -1039,10 +1041,13 @@ def simulate(
10391041 # default result file generated by OM
10401042 self ._result_file = self .getWorkDirectory () / f"{ self ._model_name } _res.mat"
10411043 elif os .path .exists (resultfile ):
1042- self ._result_file = pathlib . Path (resultfile )
1044+ self ._result_file = self . _getconn . omcpath (resultfile )
10431045 else :
10441046 self ._result_file = self .getWorkDirectory () / resultfile
10451047
1048+ if not isinstance (self ._result_file , OMCPath ):
1049+ raise ModelicaSystemError (f"Invalid result file path: { self ._result_file } - must be an OMCPath object!" )
1050+
10461051 om_cmd = self .simulate_cmd (
10471052 result_file = self ._result_file ,
10481053 simflags = simflags ,
@@ -1060,7 +1065,7 @@ def simulate(
10601065 # check for an empty (=> 0B) result file which indicates a crash of the model executable
10611066 # see: https://github.com/OpenModelica/OMPython/issues/261
10621067 # https://github.com/OpenModelica/OpenModelica/issues/13829
1063- if self ._result_file .stat (). st_size == 0 :
1068+ if self ._result_file .size () == 0 :
10641069 self ._result_file .unlink ()
10651070 raise ModelicaSystemError ("Empty result file - this indicates a crash of the model executable!" )
10661071
@@ -1109,7 +1114,7 @@ def getSolutions(
11091114 raise ModelicaSystemError ("No result file found. Run simulate() first." )
11101115 result_file = self ._result_file
11111116 else :
1112- result_file = pathlib . Path (resultfile )
1117+ result_file = self . _getconn . omcpath (resultfile )
11131118
11141119 # check for result file exits
11151120 if not result_file .is_file ():
@@ -1399,11 +1404,9 @@ def setInputs(
13991404 else :
14001405 raise ModelicaSystemError (f"Data cannot be evaluated for { repr (key )} : { repr (val )} " )
14011406
1402- self ._has_inputs = True
1403-
14041407 return True
14051408
1406- def _createCSVData (self , csvfile : Optional [pathlib . Path ] = None ) -> pathlib . Path :
1409+ def _createCSVData (self , csvfile : Optional [OMCPath ] = None ) -> OMCPath :
14071410 """
14081411 Create a csv file with inputs for the simulation/optimization of the model. If csvfile is provided as argument,
14091412 this file is used; else a generic file name is created.
@@ -1578,15 +1581,15 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
15781581 timeout = timeout ,
15791582 )
15801583
1581- overrideLinearFile = self . getWorkDirectory () / f' { self . _model_name } _override_linear.txt'
1582-
1583- with open ( file = overrideLinearFile , mode = "w" , encoding = "utf-8" ) as fh :
1584- for key1 , value1 in self . _override_variables . items ():
1585- fh . write ( f" { key1 } = { value1 } \n " )
1586- for key2 , value2 in self ._linearization_options . items ():
1587- fh . write ( f" { key2 } = { value2 } \n " )
1584+ override_content = (
1585+ " \n " . join ([ f" { key } = { value } " for key , value in self . _override_variables . items ()])
1586+ + " \n " . join ([ f" { key } = { value } " for key , value in self . _linearization_options . items ()])
1587+ + " \n "
1588+ )
1589+ override_file = self . getWorkDirectory () / f' { self ._model_name } _override_linear.txt'
1590+ override_file . write_text ( override_content )
15881591
1589- om_cmd .arg_set (key = "overrideFile" , val = overrideLinearFile .as_posix ())
1592+ om_cmd .arg_set (key = "overrideFile" , val = override_file .as_posix ())
15901593
15911594 if self ._inputs :
15921595 for key in self ._inputs :
@@ -1608,13 +1611,13 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
16081611 om_cmd .args_set (args = simargs )
16091612
16101613 # the file create by the model executable which contains the matrix and linear inputs, outputs and states
1611- linear_file = self ._tempdir / "linearized_model.py"
1614+ linear_file = self .getWorkDirectory () / "linearized_model.py"
16121615 linear_file .unlink (missing_ok = True )
16131616
16141617 returncode = om_cmd .run ()
16151618 if returncode != 0 :
16161619 raise ModelicaSystemError (f"Linearize failed with return code: { returncode } " )
1617- if not linear_file .exists ():
1620+ if not linear_file .is_file ():
16181621 raise ModelicaSystemError (f"Linearization failed: { linear_file } not found!" )
16191622
16201623 self ._simulated = True
0 commit comments