3333"""
3434
3535import ast
36- import csv
3736from dataclasses import dataclass
3837import logging
3938import numbers
@@ -361,8 +360,7 @@ def __init__(
361360 self ._override_variables : dict [str , str ] = {}
362361 self ._simulate_options_override : dict [str , str ] = {}
363362 self ._linearization_options = {'startTime' : 0.0 , 'stopTime' : 1.0 , 'stepSize' : 0.002 , 'tolerance' : 1e-8 }
364- self ._optimization_options = {'startTime' : 0.0 , 'stopTime' : 1.0 , 'numberOfIntervals' : 500 , 'stepSize' : 0.002 ,
365- 'tolerance' : 1e-8 }
363+ self ._optimization_options = self ._linearization_options | {'numberOfIntervals' : 500 }
366364 self ._linearized_inputs : list [str ] = [] # linearization input list
367365 self ._linearized_outputs : list [str ] = [] # linearization output list
368366 self ._linearized_states : list [str ] = [] # linearization states list
@@ -383,7 +381,6 @@ def __init__(
383381 if not isinstance (lmodel , list ):
384382 raise ModelicaSystemError (f"Invalid input type for lmodel: { type (lmodel )} - list expected!" )
385383
386- self ._xml_file = None
387384 self ._lmodel = lmodel # may be needed if model is derived from other model
388385 self ._model_name = modelName # Model class name
389386 self ._file_name = pathlib .Path (fileName ).resolve () if fileName is not None else None # Model file/package name
@@ -480,8 +477,8 @@ def buildModel(self, variableFilter: Optional[str] = None):
480477 buildModelResult = self ._requestApi ("buildModel" , self ._model_name , properties = varFilter )
481478 logger .debug ("OM model build result: %s" , buildModelResult )
482479
483- self . _xml_file = pathlib .Path (buildModelResult [0 ]).parent / buildModelResult [1 ]
484- self ._xmlparse ()
480+ xml_file = pathlib .Path (buildModelResult [0 ]).parent / buildModelResult [1 ]
481+ self ._xmlparse (xml_file = xml_file )
485482
486483 def sendExpression (self , expr : str , parsed : bool = True ):
487484 try :
@@ -507,30 +504,42 @@ def _requestApi(self, apiName, entity=None, properties=None): # 2
507504
508505 return self .sendExpression (exp )
509506
510- def _xmlparse (self ):
511- if not self . _xml_file .is_file ():
512- raise ModelicaSystemError (f"XML file not generated: { self . _xml_file } " )
507+ def _xmlparse (self , xml_file : pathlib . Path ):
508+ if not xml_file .is_file ():
509+ raise ModelicaSystemError (f"XML file not generated: { xml_file } " )
513510
514- tree = ET .parse (self ._xml_file )
511+ xml_content = xml_file .read_text ()
512+ tree = ET .ElementTree (ET .fromstring (xml_content ))
515513 rootCQ = tree .getroot ()
516514 for attr in rootCQ .iter ('DefaultExperiment' ):
517515 for key in ("startTime" , "stopTime" , "stepSize" , "tolerance" ,
518516 "solver" , "outputFormat" ):
519- self ._simulate_options [key ] = attr .get (key )
517+ self ._simulate_options [key ] = str ( attr .get (key ) )
520518
521519 for sv in rootCQ .iter ('ScalarVariable' ):
522- scalar = {}
523- for key in ("name" , "description" , "variability" , "causality" , "alias" ):
524- scalar [key ] = sv .get (key )
525- scalar ["changeable" ] = sv .get ('isValueChangeable' )
526- scalar ["aliasvariable" ] = sv .get ('aliasVariable' )
520+ translations = {
521+ "alias" : "alias" ,
522+ "aliasvariable" : "aliasVariable" ,
523+ "causality" : "causality" ,
524+ "changeable" : "isValueChangeable" ,
525+ "description" : "description" ,
526+ "name" : "name" ,
527+ "variability" : "variability" ,
528+ }
529+
530+ scalar : dict [str , Any ] = {}
531+ for key_dst , key_src in translations .items ():
532+ val = sv .get (key_src )
533+ scalar [key_dst ] = None if val is None else str (val )
534+
527535 ch = list (sv )
528536 for att in ch :
529537 scalar ["start" ] = att .get ('start' )
530538 scalar ["min" ] = att .get ('min' )
531539 scalar ["max" ] = att .get ('max' )
532540 scalar ["unit" ] = att .get ('unit' )
533541
542+ # save parameters in the corresponding class variables
534543 if scalar ["variability" ] == "parameter" :
535544 if scalar ["name" ] in self ._override_variables :
536545 self ._params [scalar ["name" ]] = self ._override_variables [scalar ["name" ]]
@@ -954,16 +963,17 @@ def simulate_cmd(
954963 if simargs :
955964 om_cmd .args_set (args = simargs )
956965
957- overrideFile = self ._tempdir / f"{ self ._model_name } _override.txt"
958966 if self ._override_variables or self ._simulate_options_override :
959- tmpdict = self ._override_variables .copy ()
960- tmpdict .update (self ._simulate_options_override )
961- # write to override file
962- with open (file = overrideFile , mode = "w" , encoding = "utf-8" ) as fh :
963- for key , value in tmpdict .items ():
964- fh .write (f"{ key } ={ value } \n " )
967+ override_file = result_file .parent / f"{ result_file .stem } _override.txt"
968+
969+ override_content = (
970+ "\n " .join ([f"{ key } ={ value } " for key , value in self ._override_variables .items ()])
971+ + "\n " .join ([f"{ key } ={ value } " for key , value in self ._simulate_options_override .items ()])
972+ + "\n "
973+ )
965974
966- om_cmd .arg_set (key = "overrideFile" , val = overrideFile .as_posix ())
975+ override_file .write_text (override_content )
976+ om_cmd .arg_set (key = "overrideFile" , val = override_file .as_posix ())
967977
968978 if self ._inputs : # if model has input quantities
969979 for key in self ._inputs :
@@ -1083,9 +1093,9 @@ def getSolutions(self, varList: Optional[str | list[str]] = None, resultfile: Op
10831093 else :
10841094 result_file = pathlib .Path (resultfile )
10851095
1086- # check for result file exits
1096+ # check if the result file exits
10871097 if not result_file .is_file ():
1088- raise ModelicaSystemError (f"Result file does not exist { result_file } " )
1098+ raise ModelicaSystemError (f"Result file does not exist { result_file . as_posix () } " )
10891099
10901100 # get absolute path
10911101 result_file = result_file .absolute ()
@@ -1402,7 +1412,7 @@ def _createCSVData(self, csvfile: Optional[pathlib.Path] = None) -> pathlib.Path
14021412 interpolated_inputs [signal_name ] = np .interp (
14031413 all_times ,
14041414 signal [:, 0 ], # times
1405- signal [:, 1 ] # values
1415+ signal [:, 1 ], # values
14061416 )
14071417
14081418 # Write CSV file
@@ -1414,16 +1424,17 @@ def _createCSVData(self, csvfile: Optional[pathlib.Path] = None) -> pathlib.Path
14141424 row = [
14151425 t , # time
14161426 * (interpolated_inputs [name ][i ] for name in input_names ), # input values
1417- 0 # trailing 'end' column
1427+ 0 , # trailing 'end' column
14181428 ]
14191429 csv_rows .append (row )
14201430
14211431 if csvfile is None :
14221432 csvfile = self ._tempdir / f'{ self ._model_name } .csv'
14231433
1424- with open (file = csvfile , mode = "w" , encoding = "utf-8" , newline = "" ) as fh :
1425- writer = csv .writer (fh )
1426- writer .writerows (csv_rows )
1434+ # basic definition of a CSV file using csv_rows as input
1435+ csv_content = "\n " .join (["," .join (map (str , row )) for row in csv_rows ]) + "\n "
1436+
1437+ csvfile .write_text (csv_content )
14271438
14281439 return csvfile
14291440
@@ -1535,7 +1546,8 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
15351546 compatibility, because linearize() used to return `[A, B, C, D]`.
15361547 """
15371548
1538- if self ._xml_file is None :
1549+ if len (self ._quantities ) == 0 :
1550+ # if self._quantities has no content, the xml file was not parsed; see self._xmlparse()
15391551 raise ModelicaSystemError (
15401552 "Linearization cannot be performed as the model is not build, "
15411553 "use ModelicaSystem() to build the model first"
@@ -1546,10 +1558,10 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
15461558 overrideLinearFile = self ._tempdir / f'{ self ._model_name } _override_linear.txt'
15471559
15481560 with open (file = overrideLinearFile , mode = "w" , encoding = "utf-8" ) as fh :
1549- for key , value in self ._override_variables .items ():
1550- fh .write (f"{ key } ={ value } \n " )
1551- for key , value in self ._linearization_options .items ():
1552- fh .write (f"{ key } ={ value } \n " )
1561+ for key1 , value1 in self ._override_variables .items ():
1562+ fh .write (f"{ key1 } ={ value1 } \n " )
1563+ for key2 , value2 in self ._linearization_options .items ():
1564+ fh .write (f"{ key2 } ={ value2 } \n " )
15531565
15541566 om_cmd .arg_set (key = "overrideFile" , val = overrideLinearFile .as_posix ())
15551567
0 commit comments