1111import os
1212import pathlib
1313import queue
14+ import re
1415import textwrap
1516import threading
1617from typing import Any , cast , Optional
1920
2021import numpy as np
2122
22- import re
23-
2423from OMPython .OMCSession import (
2524 OMCSessionException ,
2625 OMCSessionRunData ,
@@ -332,14 +331,14 @@ def __init__(
332331 self ._simulate_options : dict [str , str ] = {}
333332 self ._override_variables : dict [str , str ] = {}
334333 self ._simulate_options_override : dict [str , str ] = {}
335- self ._linearization_options : dict [str , str | float ] = {
336- 'startTime' : 0.0 ,
337- 'stopTime' : 1.0 ,
338- 'stepSize' : 0.002 ,
339- 'tolerance' : 1e-8 ,
334+ self ._linearization_options : dict [str , str ] = {
335+ 'startTime' : str ( 0.0 ) ,
336+ 'stopTime' : str ( 1.0 ) ,
337+ 'stepSize' : str ( 0.002 ) ,
338+ 'tolerance' : str ( 1e-8 ) ,
340339 }
341340 self ._optimization_options = self ._linearization_options | {
342- 'numberOfIntervals' : 500 ,
341+ 'numberOfIntervals' : str ( 500 ) ,
343342 }
344343 self ._linearized_inputs : list [str ] = [] # linearization input list
345344 self ._linearized_outputs : list [str ] = [] # linearization output list
@@ -351,7 +350,8 @@ def __init__(
351350 self ._session = OMCSessionLocal (omhome = omhome )
352351
353352 # get OpenModelica version
354- self ._version = self ._session .sendExpression ("getVersion()" , parsed = True )
353+ version_str = self .sendExpression (expr = "getVersion()" )
354+ self ._version = self ._parse_om_version (version = version_str )
355355 # set commandLineOptions using default values or the user defined list
356356 if command_line_options is None :
357357 # set default command line options to improve the performance of linearization and to avoid recompilation if
@@ -950,7 +950,7 @@ def getSimulationOptions(
950950 def getLinearizationOptions (
951951 self ,
952952 names : Optional [str | list [str ]] = None ,
953- ) -> dict [str , str | float ] | list [str | float ]:
953+ ) -> dict [str , str ] | list [str ]:
954954 """Get simulation options used for linearization.
955955
956956 Args:
@@ -964,17 +964,16 @@ def getLinearizationOptions(
964964 returned.
965965 If `names` is a list, a list with one value for each option name
966966 in names is returned: [option1_value, option2_value, ...].
967- Some option values are returned as float when first initialized,
968- but always as strings after setLinearizationOptions is used to
969- change them.
967+
968+ The option values are always returned as strings.
970969
971970 Examples:
972971 >>> mod.getLinearizationOptions()
973- {'startTime': 0.0, 'stopTime': 1.0, 'stepSize': 0.002, 'tolerance': 1e-08}
972+ {'startTime': ' 0.0' , 'stopTime': ' 1.0' , 'stepSize': ' 0.002' , 'tolerance': ' 1e-08' }
974973 >>> mod.getLinearizationOptions("stopTime")
975- [1.0]
974+ [' 1.0' ]
976975 >>> mod.getLinearizationOptions(["tolerance", "stopTime"])
977- [1e-08, 1.0]
976+ [' 1e-08', ' 1.0' ]
978977 """
979978 if names is None :
980979 return self ._linearization_options
@@ -988,7 +987,7 @@ def getLinearizationOptions(
988987 def getOptimizationOptions (
989988 self ,
990989 names : Optional [str | list [str ]] = None ,
991- ) -> dict [str , str | float ] | list [str | float ]:
990+ ) -> dict [str , str ] | list [str ]:
992991 """Get simulation options used for optimization.
993992
994993 Args:
@@ -1002,9 +1001,8 @@ def getOptimizationOptions(
10021001 returned.
10031002 If `names` is a list, a list with one value for each option name
10041003 in names is returned: [option1_value, option2_value, ...].
1005- Some option values are returned as float when first initialized,
1006- but always as strings after setOptimizationOptions is used to
1007- change them.
1004+
1005+ The option values are always returned as string.
10081006
10091007 Examples:
10101008 >>> mod.getOptimizationOptions()
@@ -1023,13 +1021,47 @@ def getOptimizationOptions(
10231021
10241022 raise ModelicaSystemError ("Unhandled input for getOptimizationOptions()" )
10251023
1026- def parse_om_version (self , version : str ) -> tuple [int , int , int ]:
1024+ def _parse_om_version (self , version : str ) -> tuple [int , int , int ]:
10271025 match = re .search (r"v?(\d+)\.(\d+)\.(\d+)" , version )
10281026 if not match :
10291027 raise ValueError (f"Version not found in: { version } " )
10301028 major , minor , patch = map (int , match .groups ())
1029+
10311030 return major , minor , patch
10321031
1032+ def _process_override_data (
1033+ self ,
1034+ om_cmd : ModelicaSystemCmd ,
1035+ override_file : OMCPath ,
1036+ override_var : dict [str , str ],
1037+ override_sim : dict [str , str ],
1038+ ) -> None :
1039+ """
1040+ Define the override parameters. As the definition of simulation specific override parameter changes with OM
1041+ 1.26.0, version specific code is needed. Please keep in mind, that this will fail if OMC is not used to run the
1042+ model executable.
1043+ """
1044+ if len (override_var ) == 0 and len (override_sim ) == 0 :
1045+ return
1046+
1047+ override_content = ""
1048+ if override_var :
1049+ override_content += "\n " .join ([f"{ key } ={ value } " for key , value in override_var .items ()]) + "\n "
1050+
1051+ # simulation options are not read from override file from version >= 1.26.0,
1052+ # pass them to simulation executable directly as individual arguments
1053+ # see https://github.com/OpenModelica/OpenModelica/pull/14813
1054+ if override_sim :
1055+ if self ._version >= (1 , 26 , 0 ):
1056+ for key , opt_value in override_sim .items ():
1057+ om_cmd .arg_set (key = key , val = str (opt_value ))
1058+ else :
1059+ override_content += "\n " .join ([f"{ key } ={ value } " for key , value in override_sim .items ()]) + "\n "
1060+
1061+ if override_content :
1062+ override_file .write_text (override_content )
1063+ om_cmd .arg_set (key = "overrideFile" , val = override_file .as_posix ())
1064+
10331065 def simulate_cmd (
10341066 self ,
10351067 result_file : OMCPath ,
@@ -1073,29 +1105,12 @@ def simulate_cmd(
10731105 if simargs :
10741106 om_cmd .args_set (args = simargs )
10751107
1076- if self ._override_variables or self ._simulate_options_override :
1077- override_file = result_file .parent / f"{ result_file .stem } _override.txt"
1078-
1079- # simulation options are not read from override file from version >= 1.26.0,
1080- # pass them to simulation executable directly as individual arguments
1081- # see https://github.com/OpenModelica/OpenModelica/pull/14813
1082- major , minor , patch = self .parse_om_version (self ._version )
1083- if (major , minor , patch ) >= (1 , 26 , 0 ):
1084- for key , opt_value in self ._simulate_options_override .items ():
1085- om_cmd .arg_set (key = key , val = str (opt_value ))
1086- override_content = (
1087- "\n " .join ([f"{ key } ={ value } " for key , value in self ._override_variables .items ()])
1088- + "\n "
1089- )
1090- else :
1091- override_content = (
1092- "\n " .join ([f"{ key } ={ value } " for key , value in self ._override_variables .items ()])
1093- + "\n " .join ([f"{ key } ={ value } " for key , value in self ._simulate_options_override .items ()])
1094- + "\n "
1095- )
1096-
1097- override_file .write_text (override_content )
1098- om_cmd .arg_set (key = "overrideFile" , val = override_file .as_posix ())
1108+ self ._process_override_data (
1109+ om_cmd = om_cmd ,
1110+ override_file = result_file .parent / f"{ result_file .stem } _override.txt" ,
1111+ override_var = self ._override_variables ,
1112+ override_sim = self ._simulate_options_override ,
1113+ )
10991114
11001115 if self ._inputs : # if model has input quantities
11011116 for key , val in self ._inputs .items ():
@@ -1775,26 +1790,12 @@ def linearize(
17751790 modelname = self ._model_name ,
17761791 )
17771792
1778- # See comment in simulate_cmd regarding override file and OM version
1779- major , minor , patch = self .parse_om_version (self ._version )
1780- if (major , minor , patch ) >= (1 , 26 , 0 ):
1781- for key , opt_value in self ._linearization_options .items ():
1782- om_cmd .arg_set (key = key , val = str (opt_value ))
1783- override_content = (
1784- "\n " .join ([f"{ key } ={ value } " for key , value in self ._override_variables .items ()])
1785- + "\n "
1786- )
1787- else :
1788- override_content = (
1789- "\n " .join ([f"{ key } ={ value } " for key , value in self ._override_variables .items ()])
1790- + "\n " .join ([f"{ key } ={ value } " for key , value in self ._linearization_options .items ()])
1791- + "\n "
1792- )
1793-
1794- override_file = self .getWorkDirectory () / f'{ self ._model_name } _override_linear.txt'
1795- override_file .write_text (override_content )
1796-
1797- om_cmd .arg_set (key = "overrideFile" , val = override_file .as_posix ())
1793+ self ._process_override_data (
1794+ om_cmd = om_cmd ,
1795+ override_file = self .getWorkDirectory () / f'{ self ._model_name } _override_linear.txt' ,
1796+ override_var = self ._override_variables ,
1797+ override_sim = self ._linearization_options ,
1798+ )
17981799
17991800 if self ._inputs :
18001801 for key , data in self ._inputs .items ():
0 commit comments