From 6fdb6bebad73d5e09b1cce454167007ef04166cc Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Mon, 3 Jun 2024 15:06:01 -0400 Subject: [PATCH] Fix some bugs in the modular properties implementation (#1425) * Fixing bug in modular phase equilibrium list * Add regression tests * Fix unrelated typo (cherry picked from commit 2ac64179d7b61b353a6e7105c0f166f2bcc742dd) --- idaes/core/util/model_serializer.py | 2 +- .../base/generic_property.py | 2 +- .../base/tests/test_generic_property.py | 36 +++- .../base/tests/test_noncondense.py | 4 +- .../base/tests/test_noncondense_PR.py | 4 +- .../base/tests/test_nonvap.py | 4 +- .../base/tests/test_nonvap_PR.py | 4 +- .../modular_properties/base/tests/test_vle.py | 16 +- .../examples/tests/test_ASU_PR.py | 6 +- .../tests/test_ASU_PR_Dowling_2015.py | 6 +- .../examples/tests/test_BTIdeal.py | 4 +- .../examples/tests/test_BTIdeal_FPhx.py | 4 +- .../examples/tests/test_BTIdeal_FcPh.py | 4 +- .../examples/tests/test_BTIdeal_FcTP.py | 4 +- .../examples/tests/test_CO2_H2O_Ideal_VLE.py | 2 +- .../examples/tests/test_CO2_bmimPF6_PR.py | 2 +- .../examples/tests/test_HC_PR.py | 22 +- .../state_definitions/FTPx.py | 6 +- .../state_definitions/tests/test_FTPx.py | 200 +++++++++++++----- 19 files changed, 231 insertions(+), 101 deletions(-) diff --git a/idaes/core/util/model_serializer.py b/idaes/core/util/model_serializer.py index e3eff66db7..03528a45bf 100644 --- a/idaes/core/util/model_serializer.py +++ b/idaes/core/util/model_serializer.py @@ -819,7 +819,7 @@ def _read_component(sd, o, wts, lookup=None, suffixes=None, root_name=None): if isinstance(o, Suffix): if wts.suffix_filter is None or oname in wts.suffix_filter: suffixes[odict["__id__"]] = odict["data"] # is populated - else: # read non-sufix component data + else: # read non-suffix component data _read_component_data(odict["data"], o, wts, lookup=lookup, suffixes=suffixes) diff --git a/idaes/models/properties/modular_properties/base/generic_property.py b/idaes/models/properties/modular_properties/base/generic_property.py index 0c1c74a46b..0656e6a666 100644 --- a/idaes/models/properties/modular_properties/base/generic_property.py +++ b/idaes/models/properties/modular_properties/base/generic_property.py @@ -700,7 +700,7 @@ def build(self): j, ) in self._phase_component_set: # Component j is in both phases, in equilibrium - pe_dict["PE" + str(counter)] = {j: (pp[0], pp[1])} + pe_dict["PE" + str(counter)] = [j, (pp[0], pp[1])] pe_set.append("PE" + str(counter)) counter += 1 diff --git a/idaes/models/properties/modular_properties/base/tests/test_generic_property.py b/idaes/models/properties/modular_properties/base/tests/test_generic_property.py index 461cf08aa7..897b3250aa 100644 --- a/idaes/models/properties/modular_properties/base/tests/test_generic_property.py +++ b/idaes/models/properties/modular_properties/base/tests/test_generic_property.py @@ -25,6 +25,7 @@ from pyomo.util.check_units import assert_units_equivalent from idaes.models.properties.modular_properties.base.generic_property import ( + GenericParameterBlock, GenericParameterData, GenericStateBlock, _initialize_critical_props, @@ -34,18 +35,25 @@ from idaes.core import ( declare_process_block_class, Component, + FlowsheetBlock, Phase, LiquidPhase, VaporPhase, + MaterialBalanceType, MaterialFlowBasis, Solvent, PhaseType as PT, ) from idaes.core.util.exceptions import ConfigurationError, PropertyPackageError -from idaes.models.properties.modular_properties.phase_equil.henry import HenryType from idaes.core.base.property_meta import UnitSet from idaes.core.initialization import BlockTriangularizationInitializer +from idaes.models.properties.modular_properties.phase_equil.henry import HenryType +from idaes.models.properties.modular_properties.examples.BT_ideal import ( + configuration as BTconfig, +) +from idaes.models.unit_models.flash import Flash + import idaes.logger as idaeslog @@ -494,9 +502,9 @@ def test_phases_in_equilibrium(self): assert isinstance(m.params.phase_equilibrium_list, dict) assert m.params.phase_equilibrium_list == { - "PE1": {"a": ("p1", "p2")}, - "PE2": {"b": ("p1", "p2")}, - "PE3": {"c": ("p1", "p2")}, + "PE1": ["a", ("p1", "p2")], + "PE2": ["b", ("p1", "p2")], + "PE3": ["c", ("p1", "p2")], } @pytest.mark.unit @@ -1962,3 +1970,23 @@ def build_critical_properties(b, *args, **kwargs): "Component declarations.", ): _initialize_critical_props(m.props[1]) + + +@pytest.mark.integration +def test_phase_component_flash(): + # Regression test for issue #1423 + m = ConcreteModel() + m.fs = FlowsheetBlock(dynamic=False) + + m.fs.props = GenericParameterBlock(**BTconfig) + + m.fs.flash = Flash( + property_package=m.fs.props, + material_balance_type=MaterialBalanceType.componentPhase, + ) + + assert m.fs.props.phase_equilibrium_list == { + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], + } + assert isinstance(m.fs.flash, Flash) diff --git a/idaes/models/properties/modular_properties/base/tests/test_noncondense.py b/idaes/models/properties/modular_properties/base/tests/test_noncondense.py index 4c42db3b82..cf070aca51 100644 --- a/idaes/models/properties/modular_properties/base/tests/test_noncondense.py +++ b/idaes/models/properties/modular_properties/base/tests/test_noncondense.py @@ -243,8 +243,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/base/tests/test_noncondense_PR.py b/idaes/models/properties/modular_properties/base/tests/test_noncondense_PR.py index e929d11cf8..a467d7c977 100644 --- a/idaes/models/properties/modular_properties/base/tests/test_noncondense_PR.py +++ b/idaes/models/properties/modular_properties/base/tests/test_noncondense_PR.py @@ -233,8 +233,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/base/tests/test_nonvap.py b/idaes/models/properties/modular_properties/base/tests/test_nonvap.py index 2dfafb6658..35bea43a07 100644 --- a/idaes/models/properties/modular_properties/base/tests/test_nonvap.py +++ b/idaes/models/properties/modular_properties/base/tests/test_nonvap.py @@ -244,8 +244,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/base/tests/test_nonvap_PR.py b/idaes/models/properties/modular_properties/base/tests/test_nonvap_PR.py index af07f17b67..a0331113a6 100644 --- a/idaes/models/properties/modular_properties/base/tests/test_nonvap_PR.py +++ b/idaes/models/properties/modular_properties/base/tests/test_nonvap_PR.py @@ -233,8 +233,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/base/tests/test_vle.py b/idaes/models/properties/modular_properties/base/tests/test_vle.py index 79906693f5..03b3e24555 100644 --- a/idaes/models/properties/modular_properties/base/tests/test_vle.py +++ b/idaes/models/properties/modular_properties/base/tests/test_vle.py @@ -209,8 +209,8 @@ def test_build(self, model): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"A": ("Vap", "Liq")}, - "PE2": {"B": ("Vap", "Liq")}, + "PE1": ["A", ("Vap", "Liq")], + "PE2": ["B", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 @@ -513,9 +513,9 @@ def test_build(self, model): assert i in ["PE1", "PE2", "PE3"] assert model.params.phase_equilibrium_list == { - "PE1": {"A": ("Vap", "Liq")}, - "PE2": {"B": ("Vap", "Liq")}, - "PE3": {"C": ("Vap", "Liq")}, + "PE1": ["A", ("Vap", "Liq")], + "PE2": ["B", ("Vap", "Liq")], + "PE3": ["C", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 @@ -692,9 +692,9 @@ def test_build(self, model): assert i in ["PE1", "PE2", "PE3"] assert model.params.phase_equilibrium_list == { - "PE1": {"A": ("Vap", "Liq")}, - "PE2": {"B": ("Vap", "Liq")}, - "PE3": {"C": ("Vap", "Liq")}, + "PE1": ["A", ("Vap", "Liq")], + "PE2": ["B", ("Vap", "Liq")], + "PE3": ["C", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR.py b/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR.py index e1d973d93e..2e1411857d 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR.py @@ -121,9 +121,9 @@ def test_build(self): assert i in ["PE1", "PE2", "PE3"] assert model.params.phase_equilibrium_list == { - "PE1": {"nitrogen": ("Vap", "Liq")}, - "PE2": {"argon": ("Vap", "Liq")}, - "PE3": {"oxygen": ("Vap", "Liq")}, + "PE1": ["nitrogen", ("Vap", "Liq")], + "PE2": ["argon", ("Vap", "Liq")], + "PE3": ["oxygen", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 101325 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR_Dowling_2015.py b/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR_Dowling_2015.py index d56ab935f3..4704d59a0d 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR_Dowling_2015.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_ASU_PR_Dowling_2015.py @@ -126,9 +126,9 @@ def test_build(self): assert i in ["PE1", "PE2", "PE3"] assert model.params.phase_equilibrium_list == { - "PE1": {"nitrogen": ("Vap", "Liq")}, - "PE2": {"argon": ("Vap", "Liq")}, - "PE3": {"oxygen": ("Vap", "Liq")}, + "PE1": ["nitrogen", ("Vap", "Liq")], + "PE2": ["argon", ("Vap", "Liq")], + "PE3": ["oxygen", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 101325 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal.py b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal.py index f6f8903d80..899a5df975 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal.py @@ -116,8 +116,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FPhx.py b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FPhx.py index 192bad13c8..3d8e04d094 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FPhx.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FPhx.py @@ -236,8 +236,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcPh.py b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcPh.py index 99f1d350aa..effa1fc08a 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcPh.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcPh.py @@ -237,8 +237,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcTP.py b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcTP.py index d55412533a..e6ad6c55b3 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcTP.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_BTIdeal_FcTP.py @@ -234,8 +234,8 @@ def test_build(self): assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { - "PE1": {"benzene": ("Vap", "Liq")}, - "PE2": {"toluene": ("Vap", "Liq")}, + "PE1": ["benzene", ("Vap", "Liq")], + "PE2": ["toluene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 1e5 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_CO2_H2O_Ideal_VLE.py b/idaes/models/properties/modular_properties/examples/tests/test_CO2_H2O_Ideal_VLE.py index ff463a8f55..f8700bc211 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_CO2_H2O_Ideal_VLE.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_CO2_H2O_Ideal_VLE.py @@ -109,7 +109,7 @@ def test_build(self): for i in model.params.phase_equilibrium_idx: assert i in ["PE1"] - assert model.params.phase_equilibrium_list == {"PE1": {"H2O": ("Vap", "Liq")}} + assert model.params.phase_equilibrium_list == {"PE1": ["H2O", ("Vap", "Liq")]} assert model.params.pressure_ref.value == 101325 assert model.params.temperature_ref.value == 298.15 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_CO2_bmimPF6_PR.py b/idaes/models/properties/modular_properties/examples/tests/test_CO2_bmimPF6_PR.py index d74afe10d7..b4fc0154d4 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_CO2_bmimPF6_PR.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_CO2_bmimPF6_PR.py @@ -107,7 +107,7 @@ def test_build(self): assert i in ["PE1"] assert model.param.phase_equilibrium_list == { - "PE1": {"carbon_dioxide": ("Vap", "Liq")} + "PE1": ["carbon_dioxide", ("Vap", "Liq")] } assert model.param.pressure_ref.value == 101325 diff --git a/idaes/models/properties/modular_properties/examples/tests/test_HC_PR.py b/idaes/models/properties/modular_properties/examples/tests/test_HC_PR.py index aa0aaa11ef..19b78556db 100644 --- a/idaes/models/properties/modular_properties/examples/tests/test_HC_PR.py +++ b/idaes/models/properties/modular_properties/examples/tests/test_HC_PR.py @@ -197,17 +197,17 @@ def test_build(self): ] assert model.params.phase_equilibrium_list == { - "PE1": {"ethane": ("Vap", "Liq")}, - "PE2": {"propane": ("Vap", "Liq")}, - "PE3": {"nbutane": ("Vap", "Liq")}, - "PE4": {"ibutane": ("Vap", "Liq")}, - "PE5": {"ethylene": ("Vap", "Liq")}, - "PE6": {"propene": ("Vap", "Liq")}, - "PE7": {"butene": ("Vap", "Liq")}, - "PE8": {"pentene": ("Vap", "Liq")}, - "PE9": {"hexene": ("Vap", "Liq")}, - "PE10": {"heptene": ("Vap", "Liq")}, - "PE11": {"octene": ("Vap", "Liq")}, + "PE1": ["ethane", ("Vap", "Liq")], + "PE2": ["propane", ("Vap", "Liq")], + "PE3": ["nbutane", ("Vap", "Liq")], + "PE4": ["ibutane", ("Vap", "Liq")], + "PE5": ["ethylene", ("Vap", "Liq")], + "PE6": ["propene", ("Vap", "Liq")], + "PE7": ["butene", ("Vap", "Liq")], + "PE8": ["pentene", ("Vap", "Liq")], + "PE9": ["hexene", ("Vap", "Liq")], + "PE10": ["heptene", ("Vap", "Liq")], + "PE11": ["octene", ("Vap", "Liq")], } assert model.params.pressure_ref.value == 101325 diff --git a/idaes/models/properties/modular_properties/state_definitions/FTPx.py b/idaes/models/properties/modular_properties/state_definitions/FTPx.py index b89b9583af..f60e3c52b9 100644 --- a/idaes/models/properties/modular_properties/state_definitions/FTPx.py +++ b/idaes/models/properties/modular_properties/state_definitions/FTPx.py @@ -469,6 +469,8 @@ def state_initialization(b): K = None break + # Default is no initialization of VLE + vap_frac = None if init_VLE: raoult_init = False if tdew is not None and b.temperature.value > tdew: @@ -490,9 +492,7 @@ def state_initialization(b): l_only_comps, v_only_comps + henry_conc + henry_other, ) - else: - # No way to estimate phase fraction - vap_frac = None + # else: No way to estimate phase fraction, do nothing if vap_frac is not None: b.phase_frac[v_phase] = vap_frac 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 0e8c86143c..f3eeaca323 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 @@ -19,7 +19,6 @@ import pytest import re import numpy as np -from pytest import approx from sys import modules from pyomo.environ import ( @@ -45,6 +44,8 @@ MaterialBalanceType, EnergyBalanceType, declare_process_block_class, + LiquidPhase, + SolidPhase, ) from idaes.models.properties.modular_properties.base.generic_property import ( GenericParameterData, @@ -402,15 +403,78 @@ def test_initialization(self, frame): assert isinstance(frame.props[1].phase_frac, Var) assert isinstance(frame.props[1].mole_frac_phase_comp, Var) - assert frame.props[1].temperature.value == approx(345) - assert frame.props[1].pressure.value == approx(3e5) - assert frame.props[1].flow_mol.value == approx(100) - assert frame.props[1].phase_frac["p1"].value == approx(1) - assert frame.props[1].flow_mol_phase["p1"].value == approx(100) + assert frame.props[1].temperature.value == pytest.approx(345, rel=1e-5) + assert frame.props[1].pressure.value == pytest.approx(3e5, rel=1e-5) + assert frame.props[1].flow_mol.value == pytest.approx(100, rel=1e-5) + assert frame.props[1].phase_frac["p1"].value == pytest.approx(1, rel=1e-5) + assert frame.props[1].flow_mol_phase["p1"].value == pytest.approx(100, rel=1e-5) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_comp[j].value == approx(1 / 3) - assert frame.props[1].mole_frac_phase_comp["p1", j].value == approx(1 / 3) - assert approx(100 / 3) == value(frame.props[1].flow_mol_phase_comp["p1", j]) + assert frame.props[1].mole_frac_comp[j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert frame.props[1].mole_frac_phase_comp["p1", j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(100 / 3, rel=1e-5) == value( + frame.props[1].flow_mol_phase_comp["p1", j] + ) + + +@pytest.mark.unit +def test_state_initialization_no_vle(): + # Regression test for issue #1424 + m = ConcreteModel() + + # Create a dummy parameter block + m.params = DummyParameterBlock( + components={"c1": {}, "c2": {}, "c3": {}}, + phases={ + "p1": {"type": LiquidPhase, "equation_of_state": DummyEoS}, + "p2": {"type": SolidPhase, "equation_of_state": DummyEoS}, + }, + state_definition=modules[__name__], + pressure_ref=100000.0, + temperature_ref=300, + state_bounds={ + "flow_mol": (0, 100, 200), + "temperature": (290, 345, 400), + "pressure": (100000.0, 300000.0, 500000.0), + }, + base_units={ + "time": pyunits.s, + "length": pyunits.m, + "mass": pyunits.kg, + "amount": pyunits.mol, + "temperature": pyunits.K, + }, + ) + + # Create state block + m.props = m.params.build_state_block([1], defined_state=True) + + state_initialization(m.props[1]) + assert isinstance(m.props[1].temperature, Var) + assert isinstance(m.props[1].pressure, Var) + assert isinstance(m.props[1].flow_mol, Var) + + assert isinstance(m.props[1].mole_frac_comp, Var) + assert isinstance(m.props[1].flow_mol_phase, Var) + assert isinstance(m.props[1].flow_mol_phase_comp, Expression) + assert isinstance(m.props[1].phase_frac, Var) + assert isinstance(m.props[1].mole_frac_phase_comp, Var) + + assert m.props[1].temperature.value == pytest.approx(345, rel=1e-5) + assert m.props[1].pressure.value == pytest.approx(3e5, rel=1e-5) + assert m.props[1].flow_mol.value == pytest.approx(100, rel=1e-5) + + for p in m.props[1].phase_list: + assert value(m.props[1].phase_frac[p]) == pytest.approx(0.5, rel=1e-5) + assert value(m.props[1].flow_mol_phase[p]) == pytest.approx(50, rel=1e-5) + for j in m.props[1].component_list: + assert m.props[1].mole_frac_comp[j].value == pytest.approx(1 / 3, rel=1e-5) + assert m.props[1].mole_frac_phase_comp[p, j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) class Test2PhaseDefinedStateFalseNoBounds(object): @@ -745,33 +809,49 @@ def test_initialization(self, frame): assert isinstance(frame.props[1].phase_frac, Var) assert isinstance(frame.props[1].mole_frac_phase_comp, Var) - assert frame.props[1].temperature.value == approx(345) - assert frame.props[1].pressure.value == approx(3e5) - assert frame.props[1].flow_mol.value == approx(100) + assert frame.props[1].temperature.value == pytest.approx(345, rel=1e-5) + assert frame.props[1].pressure.value == pytest.approx(3e5, rel=1e-5) + assert frame.props[1].flow_mol.value == pytest.approx(100, rel=1e-5) for p in frame.props[1].phase_list: - assert frame.props[1].phase_frac[p].value == approx(0.5) - assert frame.props[1].flow_mol_phase[p].value == approx(50) + assert frame.props[1].phase_frac[p].value == pytest.approx(0.5, rel=1e-5) + assert frame.props[1].flow_mol_phase[p].value == pytest.approx(50, rel=1e-5) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_comp[j].value == approx(1 / 3) - assert frame.props[1].mole_frac_phase_comp[p, j].value == approx(1 / 3) - assert approx(50 / 3) == value(frame.props[1].flow_mol_phase_comp[p, j]) + assert frame.props[1].mole_frac_comp[j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert frame.props[1].mole_frac_phase_comp[p, j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(50 / 3, rel=1e-5) == value( + frame.props[1].flow_mol_phase_comp[p, j] + ) frame.props[1].phase_frac["p1"].value = 0.4 state_initialization(frame.props[1]) - assert frame.props[1].phase_frac["p1"].value == approx(0.4) - assert frame.props[1].flow_mol_phase["p1"].value == approx(40) + assert frame.props[1].phase_frac["p1"].value == pytest.approx(0.4, rel=1e-5) + assert frame.props[1].flow_mol_phase["p1"].value == pytest.approx(40, rel=1e-5) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_comp[j].value == approx(1 / 3) - assert frame.props[1].mole_frac_phase_comp["p1", j].value == approx(1 / 3) - assert approx(40 / 3) == value(frame.props[1].flow_mol_phase_comp["p1", j]) + assert frame.props[1].mole_frac_comp[j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert frame.props[1].mole_frac_phase_comp["p1", j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(40 / 3, rel=1e-5) == value( + frame.props[1].flow_mol_phase_comp["p1", j] + ) - assert frame.props[1].phase_frac["p2"].value == approx(0.5) - assert frame.props[1].flow_mol_phase["p2"].value == approx(50) + assert frame.props[1].phase_frac["p2"].value == pytest.approx(0.5, rel=1e-5) + assert frame.props[1].flow_mol_phase["p2"].value == pytest.approx(50, rel=1e-5) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_phase_comp["p2", j].value == approx(1 / 3) - assert approx(50 / 3) == value(frame.props[1].flow_mol_phase_comp["p2", j]) + assert frame.props[1].mole_frac_phase_comp["p2", j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(50 / 3, rel=1e-5) == value( + frame.props[1].flow_mol_phase_comp["p2", j] + ) # To avoid side effects frame.props[1].phase_frac["p1"].value = 0.5 state_initialization(frame.props[1]) @@ -1085,18 +1165,24 @@ def test_initialization(self, frame): assert isinstance(frame.props[1].phase_frac, Var) assert isinstance(frame.props[1].mole_frac_phase_comp, Var) - assert frame.props[1].temperature.value == approx(345) - assert frame.props[1].pressure.value == approx(3e5) - assert frame.props[1].flow_mol.value == approx(100) + assert frame.props[1].temperature.value == pytest.approx(345, rel=1e-5) + assert frame.props[1].pressure.value == pytest.approx(3e5, rel=1e-5) + assert frame.props[1].flow_mol.value == pytest.approx(100, rel=1e-5) for p in frame.props[1].phase_list: - assert frame.props[1].phase_frac[p].value == approx(1 / 3) - assert frame.props[1].flow_mol_phase[p].value == approx(100 / 3) + assert frame.props[1].phase_frac[p].value == pytest.approx(1 / 3, rel=1e-5) + assert frame.props[1].flow_mol_phase[p].value == pytest.approx( + 100 / 3, rel=1e-5 + ) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_comp[j].value == approx(1 / 3) - assert frame.props[1].mole_frac_phase_comp[p, j].value == approx(1 / 3) - assert approx(100 / 9) == value( + assert frame.props[1].mole_frac_comp[j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert frame.props[1].mole_frac_phase_comp[p, j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(100 / 9, rel=1e-5) == value( frame.props[1].flow_mol_phase_comp[p, j] ) @@ -1104,25 +1190,41 @@ def test_initialization(self, frame): frame.props[1].phase_frac["p2"].value = 0.5 frame.props[1].phase_frac["p3"].value = 0.3 state_initialization(frame.props[1]) - assert frame.props[1].phase_frac["p1"].value == approx(0.2) - assert frame.props[1].flow_mol_phase["p1"].value == approx(20) + assert frame.props[1].phase_frac["p1"].value == pytest.approx(0.2, rel=1e-5) + assert frame.props[1].flow_mol_phase["p1"].value == pytest.approx(20, rel=1e-5) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_comp[j].value == approx(1 / 3) - assert frame.props[1].mole_frac_phase_comp["p1", j].value == approx(1 / 3) - assert approx(20 / 3) == value(frame.props[1].flow_mol_phase_comp["p1", j]) + assert frame.props[1].mole_frac_comp[j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert frame.props[1].mole_frac_phase_comp["p1", j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(20 / 3, rel=1e-5) == value( + frame.props[1].flow_mol_phase_comp["p1", j] + ) - assert frame.props[1].phase_frac["p2"].value == approx(0.5) - assert frame.props[1].flow_mol_phase["p2"].value == approx(50) + assert frame.props[1].phase_frac["p2"].value == pytest.approx(0.5, rel=1e-5) + assert frame.props[1].flow_mol_phase["p2"].value == pytest.approx(50, rel=1e-5) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_phase_comp["p2", j].value == approx(1 / 3) - assert approx(50 / 3) == value(frame.props[1].flow_mol_phase_comp["p2", j]) + assert frame.props[1].mole_frac_phase_comp["p2", j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(50 / 3, rel=1e-5) == value( + frame.props[1].flow_mol_phase_comp["p2", j] + ) - assert frame.props[1].phase_frac["p3"].value == approx(0.3) - assert frame.props[1].flow_mol_phase["p3"].value == approx(30) + assert frame.props[1].phase_frac["p3"].value == pytest.approx(0.3, rel=1e-5) + assert frame.props[1].flow_mol_phase["p3"].value == pytest.approx(30, rel=1e-5) for j in frame.props[1].component_list: - assert frame.props[1].mole_frac_comp[j].value == approx(1 / 3) - assert frame.props[1].mole_frac_phase_comp["p3", j].value == approx(1 / 3) - assert approx(30 / 3) == value(frame.props[1].flow_mol_phase_comp["p3", j]) + assert frame.props[1].mole_frac_comp[j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert frame.props[1].mole_frac_phase_comp["p3", j].value == pytest.approx( + 1 / 3, rel=1e-5 + ) + assert pytest.approx(30 / 3, rel=1e-5) == value( + frame.props[1].flow_mol_phase_comp["p3", j] + ) # To avoid side effects for p in frame.props[1].phase_list: @@ -1475,7 +1577,7 @@ def test_flash(self, model): # Convergence criterion for Newton's method is 1e-6 (because # we expect to pass it of to IPOPT later). We cannot expect # machine precision here. - assert expected_output[j, i] == approx(vap_frac, rel=5e-5) + assert expected_output[j, i] == pytest.approx(vap_frac, rel=5e-5) @pytest.mark.unit def test_negative_K(self, model, caplog):