Coverage for backend/idaes_service/solver/build_state.py: 95%
36 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1from typing import Any
2from idaes.core import FlowsheetBlock
4from common.models.idaes.flowsheet_schema import PropertyPackageType
5from common.models.idaes.payloads import BuildStateRequestSchema
6from common.models.idaes.unit_model_schema import SolvedPropertyValueSchema
7from .property_package_manager import create_property_package
8from .methods.adapter import fix_block, serialize_properties_map, deactivate_fixed_guesses
9from .methods.BlockContext import BlockContext
10from pyomo.environ import ConcreteModel
11from .properties_manager import PropertiesManager
12from pyomo.environ import Block, assert_optimal_termination, SolverFactory
13from pyomo.core.base.constraint import ScalarConstraint
14from .flowsheet_manager import build_flowsheet
15from idaes.core.util.model_statistics import degrees_of_freedom, number_unused_variables, number_activated_equalities, number_unfixed_variables, number_unfixed_variables_in_activated_equalities
16from idaes.core.util.model_diagnostics import DiagnosticsToolbox
18def solve_state_block(schema: BuildStateRequestSchema) -> list[SolvedPropertyValueSchema]:
19 m, sb = build_state(schema.property_package)
20 # if there's only one compound in the property package, remove the mole_frac_comp (as it's over specified)
21 if len(schema.property_package.compounds) == 1:
22 del schema.properties["mole_frac_comp"]
24 block_ctx = BlockContext(m.fs)
25 fix_block(sb, schema.properties, m.fs, block_ctx)
27 # If the degrees of freedom are not zero, don't try solve.
28 # However, the degree of freedom logic ignores any variables that aren't actually used. So if temperature
29 # and pressure are both not specified, and there are no constraints for them either, it decides that
30 # they are not part of the solution, and says there's 0 degrees of freedom.
31 # so instead, we actually check there are unfixed variables that are not in activated equalities.
32 # TODO: Check why adding and degrees_of_freedom(sb) == 0 makes pr fail (python manage.py test core.auxiliary.tests.test_Compounds)
33 if number_unfixed_variables(sb) - number_unfixed_variables_in_activated_equalities(sb) != 0: 33 ↛ 34line 33 didn't jump to line 34 because the condition on line 33 was never true
34 return [] # This means no properties are returned, so the backend won't update anything.
35 block_ctx.apply_elimination()
37 # initialise the state block, which will perform a solve
38 sb.initialize(outlvl=1)
39 deactivate_fixed_guesses(m.fs.guess_vars)
41 return serialize_properties_map(m.fs)
44def build_state(schema: PropertyPackageType) -> Any: # PropertyPackageSchema
45 m = build_flowsheet(dynamic=False)
46 # create the property package and state block
47 property_package = create_property_package(schema, m)
48 state_block = property_package.build_state_block(m.fs.time, defined_state=True)
49 m.fs.add_component(f"PP_{schema.id}_state", state_block)
51 return m, state_block
54def get_state_vars(schema: PropertyPackageType) -> Any:
55 _, state_block = build_state(schema)
57 return state_block[0].define_state_vars()