@@ -124,9 +124,12 @@ def __init__(
124124 self ,
125125 session : OMCSessionZMQ ,
126126 runpath : OMCPath ,
127- modelname : str ,
127+ modelname : Optional [ str ] = None ,
128128 timeout : Optional [float ] = None ,
129129 ) -> None :
130+ if modelname is None :
131+ raise ModelicaSystemError ("Missing model name!" )
132+
130133 self ._session = session
131134 self ._runpath = runpath
132135 self ._model_name = modelname
@@ -319,60 +322,25 @@ def parse_simflags(simflags: str) -> dict[str, Optional[str | dict[str, Any] | n
319322class ModelicaSystem :
320323 def __init__ (
321324 self ,
322- fileName : Optional [str | os .PathLike ] = None ,
323- modelName : Optional [str ] = None ,
324- lmodel : Optional [list [str | tuple [str , str ]]] = None ,
325325 commandLineOptions : Optional [list [str ]] = None ,
326- variableFilter : Optional [str ] = None ,
327326 customBuildDirectory : Optional [str | os .PathLike ] = None ,
328327 omhome : Optional [str ] = None ,
329328 omc_process : Optional [OMCProcess ] = None ,
330- build : bool = True ,
331329 ) -> None :
332- """Initialize, load and build a model.
333-
334- The constructor loads the model file and builds it, generating exe and
335- xml files, etc.
330+ """Create a ModelicaSystem instance. To define the model use model() or convertFmu2Mo().
336331
337332 Args:
338- fileName: Path to the model file. Either absolute or relative to
339- the current working directory.
340- modelName: The name of the model class. If it is contained within
341- a package, "PackageName.ModelName" should be used.
342- lmodel: List of libraries to be loaded before the model itself is
343- loaded. Two formats are supported for the list elements:
344- lmodel=["Modelica"] for just the library name
345- and lmodel=[("Modelica","3.2.3")] for specifying both the name
346- and the version.
347333 commandLineOptions: List with extra command line options as elements. The list elements are
348334 provided to omc via setCommandLineOptions(). If set, the default values will be overridden.
349335 To disable any command line options, use an empty list.
350- variableFilter: A regular expression. Only variables fully
351- matching the regexp will be stored in the result file.
352- Leaving it unspecified is equivalent to ".*".
353336 customBuildDirectory: Path to a directory to be used for temporary
354337 files like the model executable. If left unspecified, a tmp
355338 directory will be created.
356- omhome: OPENMODELICAHOME value to be used when creating the OMC
357- session.
339+ omhome: path to OMC to be used when creating the OMC session (see OMCSessionZMQ).
358340 omc_process: definition of a (local) OMC process to be used. If
359341 unspecified, a new local session will be created.
360- build: Boolean controlling whether or not the model should be
361- built when constructor is called. If False, the constructor
362- simply loads the model without compiling.
363-
364- Examples:
365- mod = ModelicaSystem("ModelicaModel.mo", "modelName")
366- mod = ModelicaSystem("ModelicaModel.mo", "modelName", ["Modelica"])
367- mod = ModelicaSystem("ModelicaModel.mo", "modelName", [("Modelica","3.2.3"), "PowerSystems"])
368342 """
369343
370- if fileName is None and modelName is None and not lmodel : # all None
371- raise ModelicaSystemError ("Cannot create ModelicaSystem object without any arguments" )
372-
373- if modelName is None :
374- raise ModelicaSystemError ("A modelname must be provided (argument modelName)!" )
375-
376344 self ._quantities : list [dict [str , Any ]] = []
377345 self ._params : dict [str , str ] = {} # even numerical values are stored as str
378346 self ._inputs : dict [str , list | None ] = {}
@@ -406,44 +374,82 @@ def __init__(
406374 for opt in commandLineOptions :
407375 self .setCommandLineOptions (commandLineOptions = opt )
408376
409- if lmodel is None :
410- lmodel = []
411-
412- if not isinstance (lmodel , list ):
413- raise ModelicaSystemError (f"Invalid input type for lmodel: { type (lmodel )} - list expected!" )
414-
415- self ._lmodel = lmodel # may be needed if model is derived from other model
416- self ._model_name = modelName # Model class name
417- if fileName is not None :
418- file_name = self ._session .omcpath (fileName ).resolve ()
419- else :
420- file_name = None
421- self ._file_name : Optional [OMCPath ] = file_name # Model file/package name
422377 self ._simulated = False # True if the model has already been simulated
423378 self ._result_file : Optional [OMCPath ] = None # for storing result file
424- self ._variable_filter = variableFilter
425379
426- if self ._file_name is not None and not self ._file_name .is_file (): # if file does not exist
427- raise IOError (f"{ self ._file_name } does not exist!" )
380+ self ._work_dir : OMCPath = self .setWorkDirectory (customBuildDirectory )
428381
429- # set default command Line Options for linearization as
430- # linearize() will use the simulation executable and runtime
431- # flag -l to perform linearization
432- self .setCommandLineOptions ("--linearizationDumpLanguage=python" )
433- self .setCommandLineOptions ("--generateSymbolicLinearization" )
382+ self ._model_name : Optional [str ] = None
383+ self ._libraries : Optional [list [str | tuple [str , str ]]] = None
384+ self ._file_name : Optional [os .PathLike ]
385+ self ._variable_filter : Optional [str ] = None
434386
435- self ._work_dir : OMCPath = self .setWorkDirectory (customBuildDirectory )
387+ def model (
388+ self ,
389+ name : str ,
390+ file : Optional [str | os .PathLike ] = None ,
391+ libraries : Optional [list [str | tuple [str , str ]]] = None ,
392+ variable_filter : Optional [str ] = None ,
393+ build : bool = True ,
394+ ) -> None :
395+ """Load and build a Modelica model.
396+
397+ This method loads the model file and builds it if requested (build == True).
398+
399+ Args:
400+ file: Path to the model file. Either absolute or relative to
401+ the current working directory.
402+ name: The name of the model class. If it is contained within
403+ a package, "PackageName.ModelName" should be used.
404+ libraries: List of libraries to be loaded before the model itself is
405+ loaded. Two formats are supported for the list elements:
406+ lmodel=["Modelica"] for just the library name
407+ and lmodel=[("Modelica","3.2.3")] for specifying both the name
408+ and the version.
409+ variable_filter: A regular expression. Only variables fully
410+ matching the regexp will be stored in the result file.
411+ Leaving it unspecified is equivalent to ".*".
412+ build: Boolean controlling whether the model should be
413+ built when constructor is called. If False, the constructor
414+ simply loads the model without compiling.
436415
416+ Examples:
417+ mod = ModelicaSystem()
418+ # and then one of the lines below
419+ mod.model(name="modelName", file="ModelicaModel.mo", )
420+ mod.model(name="modelName", file="ModelicaModel.mo", libraries=["Modelica"])
421+ mod.model(name="modelName", file="ModelicaModel.mo", libraries=[("Modelica","3.2.3"), "PowerSystems"])
422+ """
423+
424+ if self ._model_name is not None :
425+ raise ModelicaSystemError ("Can not reuse this instance of ModelicaSystem "
426+ f"defined for { repr (self ._model_name )} !" )
427+
428+ if not isinstance (name , str ):
429+ raise ModelicaSystemError ("A model name must be provided (argument name)!" )
430+
431+ if libraries is None :
432+ libraries = []
433+
434+ if not isinstance (libraries , list ):
435+ raise ModelicaSystemError (f"Invalid input type for libraries: { type (libraries )} - list expected!" )
436+
437+ # set variables
438+ self ._model_name = name # Model class name
439+ self ._libraries = libraries # may be needed if model is derived from other model
440+ self ._file_name = self .get_session ().omcpath (file ).resolve () if file is not None else None # Model file/package name
441+ self ._variable_filter = variable_filter
442+
443+ if self ._file_name is not None and not self ._file_name .is_file (): # if file does not exist
444+ raise IOError (f"{ self ._file_name } does not exist!" )
445+
446+ if self ._libraries :
447+ self ._loadLibrary (libraries = self ._libraries )
437448 if self ._file_name is not None :
438- self ._loadLibrary (lmodel = self ._lmodel )
439449 self ._loadFile (fileName = self ._file_name )
440450
441- # allow directly loading models from MSL without fileName
442- elif fileName is None and modelName is not None :
443- self ._loadLibrary (lmodel = self ._lmodel )
444-
445451 if build :
446- self .buildModel (variableFilter )
452+ self .buildModel (variable_filter )
447453
448454 def get_session (self ) -> OMCSessionZMQ :
449455 return self ._session
@@ -460,9 +466,9 @@ def _loadFile(self, fileName: OMCPath):
460466 self .sendExpression (f'loadFile("{ fileName .as_posix ()} ")' )
461467
462468 # for loading file/package, loading model and building model
463- def _loadLibrary (self , lmodel : list ):
469+ def _loadLibrary (self , libraries : list ):
464470 # load Modelica standard libraries or Modelica files if needed
465- for element in lmodel :
471+ for element in libraries :
466472 if element is not None :
467473 if isinstance (element , str ):
468474 if element .endswith (".mo" ):
@@ -1580,9 +1586,13 @@ def _createCSVData(self, csvfile: Optional[OMCPath] = None) -> OMCPath:
15801586
15811587 return csvfile
15821588
1583- def convertMo2Fmu (self , version : str = "2.0" , fmuType : str = "me_cs" ,
1584- fileNamePrefix : str = "<default>" ,
1585- includeResources : bool = True ) -> str :
1589+ def convertMo2Fmu (
1590+ self ,
1591+ version : str = "2.0" ,
1592+ fmuType : str = "me_cs" ,
1593+ fileNamePrefix : Optional [str ] = None ,
1594+ includeResources : bool = True ,
1595+ ) -> str :
15861596 """Translate the model into a Functional Mockup Unit.
15871597
15881598 Args:
@@ -1598,12 +1608,12 @@ def convertMo2Fmu(self, version: str = "2.0", fmuType: str = "me_cs",
15981608 '/tmp/tmpmhfx9umo/CauerLowPassAnalog.fmu'
15991609 """
16001610
1601- if fileNamePrefix == "<default>" :
1611+ if fileNamePrefix is None :
1612+ if self ._model_name is None :
1613+ raise ModelicaSystemError ("Missing model name!" )
16021614 fileNamePrefix = self ._model_name
1603- if includeResources :
1604- includeResourcesStr = "true"
1605- else :
1606- includeResourcesStr = "false"
1615+ includeResourcesStr = "true" if includeResources else "false"
1616+
16071617 properties = (f'version="{ version } ", fmuType="{ fmuType } ", '
16081618 f'fileNamePrefix="{ fileNamePrefix } ", includeResources={ includeResourcesStr } ' )
16091619 fmu = self ._requestApi (apiName = 'buildModelFMU' , entity = self ._model_name , properties = properties )
0 commit comments