Coverage for backend/ahuora-builder/src/ahuora_builder/methods/property_map_manipulation.py: 65%
41 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-03-26 20:57 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-03-26 20:57 +0000
1from __future__ import annotations
2from pyomo.core.base.var import ScalarVar
3from pyomo.environ import units as pyunits
4from ahuora_builder.methods.adapter import fix_slice, fix_var
5from ahuora_builder.properties_manager import PropertyComponent
7from pyomo.core.base.expression import ScalarExpression, Expression
8from pyomo.core.base.var import ScalarVar, VarData, _GeneralVarData
9from pyomo.core.base.constraint import ScalarConstraint, ConstraintData, _GeneralConstraintData
10from pyomo.core.base.indexed_component import IndexedComponent
11from pyomo.environ import value
12from sympy import var
13from ahuora_builder.methods.adapter import fix_slice
14from .units_handler import ValueWithUnits
19def update_property(property_component: PropertyComponent, values: list[ValueWithUnits]):
20 """
21 This function is used to update what a property component is fixed to.
22 For example, in the online solving, we want to update properties to their new values from the OPC UA server, and then re-solve the model.
23 This saves us from having to re-create the model and re-fix all the properties every time.
24 Args:
25 - property_component (PropertyComponent): The property component to update. This can be retrieved from the PropertiesManager.
26 - values (list[ValueWithUnits]): The new values to set the property component to. These could be a list of values with the IDAES unit attached too.
28 """
29 constraints: list[ScalarVar | ScalarConstraint] = list(property_component.corresponding_constraint)
30 if len(values) != len(constraints):
31 raise ValueError(f"Number of values provided ({len(values)}) does not match the number of constraints ({len(constraints)}) for property {property_component.name} (id {property_component}). Please provide the correct number of values.")
33 free_property(property_component)
35 new_constraints = fix_slice(property_component.component, values)
36 property_component.corresponding_constraint = new_constraints
40def free_property(property_component: PropertyComponent):
41 components: list[ScalarVar | ScalarExpression] = list(property_component.component.values())
42 constraints: list[ScalarVar | ScalarConstraint] = list(property_component.corresponding_constraint)
44 if len(components) != len(constraints): 44 ↛ 45line 44 didn't jump to line 45 because the condition on line 44 was never true
45 raise ValueError(f"Number of components ({len(components)}) does not match the number of corresponding constraints ({len(constraints)}) for property {property_component.name} (id {property_component}). This is likely an issue with the model setup internal to ahuora-builder, please check how the property and its corresponding constraint are added to the model.")
49 for component, constraint in zip(components, constraints):
50 if not (isinstance(component, ScalarVar) or isinstance(component, ScalarExpression)): 50 ↛ 52line 50 didn't jump to line 52 because the condition on line 50 was never true
51 # If this gets raised we have a problem and need to look at the get_variable_from_property function
52 raise ValueError(f"Something is wrong, we should have either a scalar variable or expression for this property_component, got {type(component)} for {component.name}")
54 if isinstance(component, ScalarVar):
55 if not component.is_fixed(): 55 ↛ 56line 55 didn't jump to line 56 because the condition on line 55 was never true
56 raise ValueError(f"Variable {component.name} must be fixed before applying input value. It looks like this variable is not fixed in the flowsheet scenario. Please choose variables that are fixed, or update the scenario JSON")
57 component.unfix()
58 else: # ScalarExpression
59 if constraint is None: 59 ↛ 60line 59 didn't jump to line 60 because the condition on line 59 was never true
60 raise ValueError(f"Could not find corresponding constraint for expression property {property_component.name}. This means that the expression is not an input. please choose properties that are fixed/inputs, or update the scenario JSON so that {component.name} is an input.")
61 # Remove the constraint(s), so that we can add a new one for the OPC input value
62 try:
63 blk = constraint.parent_block()
64 print(f"[DEL] Removing constraint: {constraint.name}")
65 blk.del_component(constraint)
66 except Exception as e:
67 print(f"[ERR] Could not delete constraint {constraint} (for {property_component.name}): {e}")
68 raise e