diff --git a/idaes/models/properties/modular_properties/base/generic_property.py b/idaes/models/properties/modular_properties/base/generic_property.py index 43ffad3806..26a31b3d57 100644 --- a/idaes/models/properties/modular_properties/base/generic_property.py +++ b/idaes/models/properties/modular_properties/base/generic_property.py @@ -2105,6 +2105,15 @@ def build(self): pobj = self.params.get_phase(p) pobj.config.equation_of_state.common(self, pobj) + # Check to see if state definition uses enthalpy + if self.is_property_constructed("enth_mol"): + # State definition uses enthalpy, need to add constraint on phase enthalpies + @self.Constraint(doc="Total molar enthalpy mixing rule") + def enth_mol_eqn(b): + return b.enth_mol == sum( + b.enth_mol_phase[p] * b.phase_frac[p] for p in b.phase_list + ) + # Add phase equilibrium constraints if necessary if self.params.config.phases_in_equilibrium is not None and ( not self.config.defined_state or self.always_flash diff --git a/idaes/models/properties/modular_properties/base/tests/dummy_eos.py b/idaes/models/properties/modular_properties/base/tests/dummy_eos.py index 4da20f2500..8efb87a37d 100644 --- a/idaes/models/properties/modular_properties/base/tests/dummy_eos.py +++ b/idaes/models/properties/modular_properties/base/tests/dummy_eos.py @@ -103,7 +103,7 @@ def energy_internal_mol_phase_comp(b, p, j): @staticmethod def enth_mol_phase(b, p): - return 1e2 * b.temperature + return 1e2 * pyunits.J / pyunits.mol / pyunits.K * b.temperature @staticmethod def enth_mol_phase_comp(b, p, j): diff --git a/idaes/models/properties/modular_properties/state_definitions/FPhx.py b/idaes/models/properties/modular_properties/state_definitions/FPhx.py index 9922d80332..d683e850d0 100644 --- a/idaes/models/properties/modular_properties/state_definitions/FPhx.py +++ b/idaes/models/properties/modular_properties/state_definitions/FPhx.py @@ -176,15 +176,6 @@ def flow_mol_phase_comp_rule(b, p, j): expr=1 == sum(b.mole_frac_comp[i] for i in b.component_list) ) - def rule_enth_mol(b): - return b.enth_mol == sum( - b.enth_mol_phase[p] * b.phase_frac[p] for p in b.phase_list - ) - - b.enth_mol_eq = Constraint( - rule=rule_enth_mol, doc="Total molar enthalpy mixing rule" - ) - if len(b.phase_list) == 1: def rule_total_mass_balance(b): @@ -451,7 +442,7 @@ def calculate_scaling_factors(b): b.sum_mole_frac_out, min(sf_mf.values()), overwrite=False ) - iscale.constraint_scaling_transform(b.enth_mol_eq, sf_h, overwrite=False) + iscale.constraint_scaling_transform(b.enth_mol_eqn, sf_h, overwrite=False) if len(b.phase_list) == 1: iscale.constraint_scaling_transform( diff --git a/idaes/models/properties/modular_properties/state_definitions/FcPh.py b/idaes/models/properties/modular_properties/state_definitions/FcPh.py index d53b5ebb82..8d4de71610 100644 --- a/idaes/models/properties/modular_properties/state_definitions/FcPh.py +++ b/idaes/models/properties/modular_properties/state_definitions/FcPh.py @@ -182,15 +182,6 @@ def rule_mole_frac_comp(b, j): b.mole_frac_comp_eq = Constraint(b.component_list, rule=rule_mole_frac_comp) - def rule_enth_mol(b): - return b.enth_mol == sum( - b.enth_mol_phase[p] * b.phase_frac[p] for p in b.phase_list - ) - - b.enth_mol_eq = Constraint( - rule=rule_enth_mol, doc="Total molar enthalpy mixing rule" - ) - if len(b.phase_list) == 1: def rule_total_mass_balance(b): @@ -456,7 +447,7 @@ def calculate_scaling_factors(b): b.mole_frac_comp_eq[j], sf_j, overwrite=False ) - iscale.constraint_scaling_transform(b.enth_mol_eq, sf_h, overwrite=False) + iscale.constraint_scaling_transform(b.enth_mol_eqn, sf_h, overwrite=False) if len(b.phase_list) == 1: iscale.constraint_scaling_transform( diff --git a/idaes/models/properties/modular_properties/state_definitions/tests/test_FPhx.py b/idaes/models/properties/modular_properties/state_definitions/tests/test_FPhx.py index c3c4514411..0ded46518b 100644 --- a/idaes/models/properties/modular_properties/state_definitions/tests/test_FPhx.py +++ b/idaes/models/properties/modular_properties/state_definitions/tests/test_FPhx.py @@ -47,6 +47,7 @@ pytestmark = pytest.mark.unit +# Note: The state definition is set by importing functions for the relevant module above @declare_process_block_class("DummyParameterBlock") class DummyParameterData(GenericParameterData): pass @@ -137,7 +138,7 @@ def test_mole_frac(self, caplog): class Test1PhaseDefinedStateFalseNoBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -263,7 +264,7 @@ def test_constraints(self, frame): class Test1PhaseDefinedStateTrueWithBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -389,7 +390,7 @@ def test_constraints(self, frame): class Test2PhaseDefinedStateFalseNoBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -551,7 +552,7 @@ def test_constraints(self, frame): class Test2PhaseDefinedStateTrueWithBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -712,7 +713,7 @@ def test_constraints(self, frame): class Test3PhaseDefinedStateFalseNoBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -862,7 +863,7 @@ def test_constraints(self, frame): class Test3PhaseDefinedStateTrueWithBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -1020,7 +1021,7 @@ def test_constraints(self, frame): class TestCommon(object): - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() diff --git a/idaes/models/properties/modular_properties/state_definitions/tests/test_FTPx.py b/idaes/models/properties/modular_properties/state_definitions/tests/test_FTPx.py index 50e44b7a50..ad4540b74e 100644 --- a/idaes/models/properties/modular_properties/state_definitions/tests/test_FTPx.py +++ b/idaes/models/properties/modular_properties/state_definitions/tests/test_FTPx.py @@ -55,6 +55,7 @@ import idaes.logger as idaeslog +# Note: The state definition is set by importing functions for the relevant module above @declare_process_block_class("DummyParameterBlock") class DummyParameterData(GenericParameterData): pass diff --git a/idaes/models/properties/modular_properties/state_definitions/tests/test_FcPh.py b/idaes/models/properties/modular_properties/state_definitions/tests/test_FcPh.py index f991791d34..24a6a3131f 100644 --- a/idaes/models/properties/modular_properties/state_definitions/tests/test_FcPh.py +++ b/idaes/models/properties/modular_properties/state_definitions/tests/test_FcPh.py @@ -51,6 +51,7 @@ import idaes.logger as idaeslog +# Note: The state definition is set by importing functions for the relevant module above @declare_process_block_class("DummyParameterBlock") class DummyParameterData(GenericParameterData): pass @@ -141,7 +142,7 @@ def test_mole_frac(self, caplog): class Test1PhaseDefinedStateFalseNoBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -276,7 +277,7 @@ def test_constraints(self, frame): class Test1PhaseDefinedStateTrueWithBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -429,7 +430,7 @@ def test_constraints(self, frame): class Test2PhaseDefinedStateFalseNoBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -600,7 +601,7 @@ def test_constraints(self, frame): class Test2PhaseDefinedStateTrueWithBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -788,7 +789,7 @@ def test_constraints(self, frame): class Test3PhaseDefinedStateFalseNoBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -947,7 +948,7 @@ def test_constraints(self, frame): class Test3PhaseDefinedStateTrueWithBounds(object): # Test define_state method with no bounds and defined_State = False - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() @@ -1121,7 +1122,7 @@ def test_constraints(self, frame): class TestCommon(object): - @pytest.fixture(scope="class") + @pytest.fixture() def frame(self): m = ConcreteModel() diff --git a/idaes/models/properties/modular_properties/state_definitions/tests/test_FcTP.py b/idaes/models/properties/modular_properties/state_definitions/tests/test_FcTP.py index 1c1d754fbd..07307bfe92 100644 --- a/idaes/models/properties/modular_properties/state_definitions/tests/test_FcTP.py +++ b/idaes/models/properties/modular_properties/state_definitions/tests/test_FcTP.py @@ -50,6 +50,7 @@ import idaes.logger as idaeslog +# Note: The state definition is set by importing functions for the relevant module above @declare_process_block_class("DummyParameterBlock") class DummyParameterData(GenericParameterData): pass diff --git a/idaes/models/properties/modular_properties/state_definitions/tests/test_FpcTP.py b/idaes/models/properties/modular_properties/state_definitions/tests/test_FpcTP.py index 8c339ee86f..6e6fca7729 100644 --- a/idaes/models/properties/modular_properties/state_definitions/tests/test_FpcTP.py +++ b/idaes/models/properties/modular_properties/state_definitions/tests/test_FpcTP.py @@ -58,6 +58,7 @@ from idaes.core.util.model_statistics import degrees_of_freedom, large_residuals_set +# Note: The state definition is set by importing functions for the relevant module above @declare_process_block_class("DummyParameterBlock") class DummyParameterData(GenericParameterData): pass