Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8d19d26
[ModelicaSystem] add type hints for set*() functions and rename argum…
syntron Jun 23, 2025
9ac6a0e
[ModelicaSystem] add _prepare_inputdata()
syntron Jun 23, 2025
980ac33
[ModelicaSystem] update _set_method_helper()
syntron Jun 23, 2025
7c24f10
[ModelicaSystem] improve definition of _prepare_inputdata()
syntron Jun 23, 2025
b864a6c
[ModelicaSystem] rename _prepare_inputdata() => _prepare_input_data()
syntron Jun 23, 2025
3f180a6
[ModelicaSystem] update setInput()
syntron Jun 23, 2025
55051d9
update tests - use new dict based input for set*() methods
syntron Jun 23, 2025
3d8b83a
[ModelicaSystem] add type hint for return value of isParameterChangea…
syntron Jun 23, 2025
1b5917c
[ModelicaSystem] fix type hint for _prepare_input_data() - use dict[s…
syntron Jun 23, 2025
b5766f4
[ModelicaSystem] setInput() - handly input data as list of tuples
syntron Jun 23, 2025
9ef9d69
update tests - use new dict based input for setInput() method
syntron Jun 23, 2025
2fc67b9
[test_linearization] fix setInput() call
syntron Jun 24, 2025
bbd8740
[ModelicaSystem] simplify _set_method_helper()
syntron Jun 26, 2025
675a648
[ModelicaSystem] improve setInputs() - reduce spaces / cleanup
syntron Jun 26, 2025
9fcd39a
[ModelicaSystem] fix rebase fallout
syntron Jul 7, 2025
92651c5
[ModelicaSystem] fix rebase fallout 2
syntron Jul 7, 2025
d695899
[ModelicaSystem] remove _has_inputs - is defined by _inputs empty or not
syntron Jul 7, 2025
4fa05f1
[test_ModelicaSystem] cleanup
syntron Jul 7, 2025
30cb70e
[ModelicaSystem] simplify handling of inputs
syntron Jul 11, 2025
0a89151
[ModelicaSystem._set_method_helper] fail if parameter is *NOT* change…
syntron Jul 15, 2025
9a92c19
[ModelicaSystem] rename overwritedata => overridedata
syntron Aug 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[ModelicaSystem] add type hints for set*() functions and rename argum…
…ents

* fix some type hint issues in setInput()
* prepare for definition via dictionary replacing 'a=b' and '[a=b, c=d]' style
  • Loading branch information
syntron committed Jul 11, 2025
commit 8d19d261d898e79405e2bcd507a46a91b099f2f1
186 changes: 125 additions & 61 deletions OMPython/ModelicaSystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1126,106 +1126,164 @@ def _strip_space(name):

raise ModelicaSystemError("Unhandled input for strip_space()")

def _setMethodHelper(self, args1, args2, args3, args4=None):
"""Helper function for setters.
def _setMethodHelper(
self,
inputdata: str | list[str] | dict[str, str | int | float],
classdata: dict[str, Any],
datatype: str,
overwritedata: Optional[dict[str, str]] = None,
) -> bool:
"""
Helper function for setters.

args1 - string or list of string given by user
args2 - dict() containing the values of different variables(eg:, parameter,continuous,simulation parameters)
args3 - function name (eg; continuous, parameter, simulation, linearization,optimization)
args4 - dict() which stores the new override variables list,
"""
def apply_single(args1):
args1 = self._strip_space(args1)
value = args1.split("=")
if value[0] in args2:
if args3 == "parameter" and self.isParameterChangeable(value[0], value[1]):
args2[value[0]] = value[1]
if args4 is not None:
args4[value[0]] = value[1]
elif args3 != "parameter":
args2[value[0]] = value[1]
if args4 is not None:
args4[value[0]] = value[1]

# TODO: cleanup / data handling / ...
# (1) args1: Optional[str | list[str]] -> convert to dict
# (2) work on dict! inputs: dict[str, str | int | float | ?numbers.number?]
# (3) handle function
# (4) use it also for other functions with such an input, i.e. 'key=value' | ['key=value']
# (5) include setInputs()

def apply_single(key_val: str):
key_val_list = key_val.split("=")
if len(key_val_list) != 2:
raise ModelicaSystemError(f"Invalid key = value pair: {key_val}")

name = self._strip_space(key_val_list[0])
value = self._strip_space(key_val_list[1])

if name in classdata:
if datatype == "parameter" and not self.isParameterChangeable(name):
logger.debug(f"It is not possible to set the parameter {repr(name)}. It seems to be "
"structural, final, protected, evaluated or has a non-constant binding. "
"Use sendExpression(...) and rebuild the model using buildModel() API; example: "
"sendExpression(\"setParameterValue("
f"{self.modelName}, {name}, {value if value is not None else '<?value?>'}"
")\") ")
return False

classdata[name] = value
if overwritedata is not None:
overwritedata[name] = value

return True

else:
raise ModelicaSystemError("Unhandled case in _setMethodHelper.apply_single() - "
f"{repr(value[0])} is not a {repr(args3)} variable")
raise ModelicaSystemError("Unhandled case in setMethodHelper.apply_single() - "
f"{repr(name)} is not a {repr(datatype)} variable")

result = []
if isinstance(args1, str):
result = [apply_single(args1)]
if isinstance(inputdata, str):
result = [apply_single(inputdata)]

elif isinstance(args1, list):
elif isinstance(inputdata, list):
result = []
args1 = self._strip_space(args1)
for var in args1:
inputdata = self._strip_space(inputdata)
for var in inputdata:
result.append(apply_single(var))

return all(result)

def setContinuous(self, cvals): # 13
def isParameterChangeable(
self,
name: str,
):
q = self.getQuantities(name)
if q[0]["changeable"] == "false":
return False
return True

def setContinuous(
self,
cvals: str | list[str] | dict[str, str | int | float],
) -> bool:
"""
This method is used to set continuous values. It can be called:
with a sequence of continuous name and assigning corresponding values as arguments as show in the example below:
usage
>>> setContinuous("Name=value")
>>> setContinuous(["Name1=value1","Name2=value2"])
"""
return self._setMethodHelper(cvals, self._continuous, "continuous", self._override_variables)
return self._setMethodHelper(
inputdata=cvals,
classdata=self.continuouslist,
datatype="continuous",
overwritedata=self.overridevariables)

def setParameters(self, pvals): # 14
def setParameters(
self,
pvals: str | list[str] | dict[str, str | int | float],
) -> bool:
"""
This method is used to set parameter values. It can be called:
with a sequence of parameter name and assigning corresponding value as arguments as show in the example below:
usage
>>> setParameters("Name=value")
>>> setParameters(["Name1=value1","Name2=value2"])
"""
return self._setMethodHelper(pvals, self._params, "parameter", self._override_variables)
return self._setMethodHelper(
inputdata=pvals,
classdata=self.paramlist,
datatype="parameter",
overwritedata=self.overridevariables)

def isParameterChangeable(self, name, value):
q = self.getQuantities(name)
if q[0]["changeable"] == "false":
logger.debug(f"setParameters() failed : It is not possible to set the following signal {repr(name)}. "
"It seems to be structural, final, protected or evaluated or has a non-constant binding, "
f"use sendExpression(\"setParameterValue({self._model_name}, {name}, {value})\") "
"and rebuild the model using buildModel() API")
return False
return True

def setSimulationOptions(self, simOptions): # 16
def setSimulationOptions(
self,
simOptions: str | list[str] | dict[str, str | int | float],
) -> bool:
"""
This method is used to set simulation options. It can be called:
with a sequence of simulation options name and assigning corresponding values as arguments as show in the example below:
usage
>>> setSimulationOptions("Name=value")
>>> setSimulationOptions(["Name1=value1","Name2=value2"])
"""
return self._setMethodHelper(simOptions, self._simulate_options, "simulation-option", self._simulate_options_override)
return _self.setMethodHelper(
inputdata=simOptions,
classdata=self.simulateOptions,
datatype="simulation-option",
overwritedata=self.simoptionsoverride)

def setLinearizationOptions(self, linearizationOptions): # 18
def setLinearizationOptions(
self,
linearizationOptions: str | list[str] | dict[str, str | int | float],
) -> bool:
"""
This method is used to set linearization options. It can be called:
with a sequence of linearization options name and assigning corresponding value as arguments as show in the example below
usage
>>> setLinearizationOptions("Name=value")
>>> setLinearizationOptions(["Name1=value1","Name2=value2"])
"""
return self._setMethodHelper(linearizationOptions, self._linearization_options, "Linearization-option", None)
return self._setMethodHelper(
inputdata=linearizationOptions,
classdata=self.linearOptions,
datatype="Linearization-option",
overwritedata=None)

def setOptimizationOptions(self, optimizationOptions): # 17
def setOptimizationOptions(self, optimizationOptions: str | list[str] | dict[str, str | int | float]) -> bool:
"""
This method is used to set optimization options. It can be called:
with a sequence of optimization options name and assigning corresponding values as arguments as show in the example below:
usage
>>> setOptimizationOptions("Name=value")
>>> setOptimizationOptions(["Name1=value1","Name2=value2"])
"""
return self._setMethodHelper(optimizationOptions, self._optimization_options, "optimization-option", None)
return self._setMethodHelper(
inputdata=optimizationOptions,
classdata=self.optimizeOptions,
datatype="optimization-option",
overwritedata=None)

def setInputs(self, name): # 15
def setInputs(
self,
name: str | list[str] | dict[str, str | int | float],
) -> bool:
"""
This method is used to set input values. It can be called:
with a sequence of input name and assigning corresponding values as arguments as show in the example below:
Expand All @@ -1234,34 +1292,40 @@ def setInputs(self, name): # 15
>>> setInputs(["Name1=value1","Name2=value2"])
"""
if isinstance(name, str):
name = self._strip_space(name)
value = name.split("=")
if value[0] in self._inputs:
tmpvalue = eval(value[1])
name1: str = name
name1 = name1.replace(" ", "")
value1 = name1.split("=")
if value1[0] in self.inputlist:
tmpvalue = eval(value1[1])
if isinstance(tmpvalue, (int, float)):
self._inputs[value[0]] = [(float(self._simulate_options["startTime"]), float(value[1])),
(float(self._simulate_options["stopTime"]), float(value[1]))]
self.inputlist[value1[0]] = [(float(self._simulateOptions["startTime"]), float(value1[1])),
(float(self._simulateOptions["stopTime"]), float(value1[1]))]
elif isinstance(tmpvalue, list):
self._checkValidInputs(tmpvalue)
self._inputs[value[0]] = tmpvalue
self._has_inputs = True
self._inputs[value1[0]] = tmpvalue
self._inputFlag = True
else:
raise ModelicaSystemError(f"{value[0]} is not an input")
raise ModelicaSystemError(f"{value1[0]} is not an input")
elif isinstance(name, list):
name = self._strip_space(name)
for var in name:
value = var.split("=")
if value[0] in self._inputs:
tmpvalue = eval(value[1])
name_list: list[str] = name
for name2 in name_list:
name2 = name2.replace(" ", "")
value2 = name2.split("=")
if value2[0] in self.inputlist:
tmpvalue = eval(value2[1])
if isinstance(tmpvalue, (int, float)):
self._inputs[value[0]] = [(float(self._simulate_options["startTime"]), float(value[1])),
(float(self._simulate_options["stopTime"]), float(value[1]))]
self.inputlist[value2[0]] = [(float(self._simulateOptions["startTime"]), float(value2[1])),
(float(self.:simulateOptions["stopTime"]), float(value2[1]))]
elif isinstance(tmpvalue, list):
self._checkValidInputs(tmpvalue)
self._inputs[value[0]] = tmpvalue
self._has_inputs = True
self._inputs[value2[0]] = tmpvalue
self._inputFlag = True
else:
raise ModelicaSystemError(f"{value[0]} is not an input!")
raise ModelicaSystemError(f"{value2[0]} is not an input!")
elif isinstance(name, dict):
raise NotImplementedError("Must be defined!")

return True

def _checkValidInputs(self, name):
if name != sorted(name, key=lambda x: x[0]):
Expand Down