Пример #1
0
def model():
    m = ConcreteModel()

    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = DSPMDEParameterBlock(
        default={
            "solute_list": ["A", "B", "C", "D"],
            "diffusivity_data": {
                ("Liq", "A"): 1e-9,
                ("Liq", "B"): 1e-10,
                ("Liq", "C"): 1e-7,
                ("Liq", "D"): 1e-11,
            },
            "mw_data": {
                "H2O": 18e-3,
                "A": 10e-3,
                "B": 25e-3,
                "C": 100e-3,
                "D": 25e-3
            },
            "stokes_radius_data": {
                "A": 1e-9,
                "B": 1e-9,
                "C": 1e-9,
                "D": 1e-10
            },
            "charge": {
                "A": 1,
                "B": -2,
                "C": 2,
                "D": -1
            },
        })

    return m
Пример #2
0
 def electrodialysis_cell3(self):
     m = ConcreteModel()
     m.fs = FlowsheetBlock(default={"dynamic": False})
     ion_dict = {
         "solute_list": ["Na_+", "Cl_-", "N"],
         "mw_data": {
             "H2O": 18e-3,
             "Na_+": 23e-3,
             "Cl_-": 35.5e-3,
             "N": 61.8e-3
         },
         "electrical_mobility_data": {
             "Na_+": 5.19e-8,
             "Cl_-": 7.92e-8
         },
         "charge": {
             "Na_+": 1,
             "Cl_-": -1
         },
     }
     m.fs.properties = DSPMDEParameterBlock(default=ion_dict)
     m.fs.unit = Electrodialysis0D(
         default={"property_package": m.fs.properties})
     m.fs.unit.config.operation_mode = "Constant_Current"
     return m
Пример #3
0
def model2():
    m = ConcreteModel()

    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = DSPMDEParameterBlock(
        default={"solute_list": ["A", "B", "C", "D"]})

    return m
Пример #4
0
def model3():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})

    m.fs.properties = DSPMDEParameterBlock(
        default={"solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"]})

    m.fs.stream = m.fs.properties.build_state_block(
        [0], default={"defined_state": True})

    return m
Пример #5
0
def test_config():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    # NOTE: Not giving actual charges in order to test construction of
    #   both the ion_set and solute_set
    m.fs.properties = DSPMDEParameterBlock(
        default={"solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"]})
    m.fs.unit = NanofiltrationDSPMDE0D(
        default={"property_package": m.fs.properties})

    # check unit config arguments
    assert len(m.fs.unit.config) == 8

    assert not m.fs.unit.config.dynamic
    assert not m.fs.unit.config.has_holdup
    assert m.fs.unit.config.material_balance_type == MaterialBalanceType.useDefault
    assert m.fs.unit.config.momentum_balance_type == MomentumBalanceType.pressureTotal
    assert not m.fs.unit.config.has_pressure_change
    assert m.fs.unit.config.property_package is m.fs.properties
    assert (m.fs.unit.config.property_package.config.activity_coefficient_model
            == ActivityCoefficientModel.ideal)
    assert (m.fs.unit.config.property_package.config.density_calculation ==
            DensityCalculation.constant)
    assert m.fs.unit.config.mass_transfer_coefficient == MassTransferCoefficient.fixed
Пример #6
0
    def NF_frame(self):
        m = ConcreteModel()
        m.fs = FlowsheetBlock(default={"dynamic": False})
        m.fs.properties = DSPMDEParameterBlock(
            default={
                "solute_list": [
                    "Ca_2+",
                    "SO4_2-",
                    "Mg_2+",
                    "Na_+",
                    "Cl_-",
                ],
                "diffusivity_data": {
                    ("Liq", "Ca_2+"): 9.2e-10,
                    ("Liq", "SO4_2-"): 1.06e-9,
                    ("Liq", "Mg_2+"): 0.706e-9,
                    ("Liq", "Na_+"): 1.33e-9,
                    ("Liq", "Cl_-"): 2.03e-9,
                },
                "mw_data": {
                    "H2O": 18e-3,
                    "Ca_2+": 40e-3,
                    "Mg_2+": 24e-3,
                    "SO4_2-": 96e-3,
                    "Na_+": 23e-3,
                    "Cl_-": 35e-3,
                },
                "stokes_radius_data": {
                    "Ca_2+": 0.309e-9,
                    "Mg_2+": 0.347e-9,
                    "SO4_2-": 0.230e-9,
                    "Cl_-": 0.121e-9,
                    "Na_+": 0.184e-9,
                },
                "charge": {
                    "Ca_2+": 2,
                    "Mg_2+": 2,
                    "SO4_2-": -2,
                    "Na_+": 1,
                    "Cl_-": -1,
                },
                "activity_coefficient_model": ActivityCoefficientModel.davies,
                "density_calculation": DensityCalculation.constant,
            })

        m.fs.unit = NanofiltrationDSPMDE0D(
            default={
                "property_package": m.fs.properties,
                "mass_transfer_coefficient":
                MassTransferCoefficient.spiral_wound,
            })
        b = m.fs.unit
        mass_flow_in = 1 * pyunits.kg / pyunits.s
        feed_mass_frac = {
            "Ca_2+": 382e-6,
            "Mg_2+": 1394e-6,
            "SO4_2-": 2136e-6,
            "Cl_-": 20101.6e-6,
            "Na_+": 11122e-6,
        }

        # Fix mole flow rates of each ion and water
        for ion, x in feed_mass_frac.items():
            mol_comp_flow = (x * pyunits.kg / pyunits.kg * mass_flow_in /
                             m.fs.unit.feed_side.properties_in[0].mw_comp[ion])
            m.fs.unit.inlet.flow_mol_phase_comp[0, "Liq",
                                                ion].fix(mol_comp_flow)
        H2O_mass_frac = 1 - sum(x for x in feed_mass_frac.values())
        H2O_mol_comp_flow = (
            H2O_mass_frac * pyunits.kg / pyunits.kg * mass_flow_in /
            m.fs.unit.feed_side.properties_in[0].mw_comp["H2O"])
        m.fs.unit.inlet.flow_mol_phase_comp[0, "Liq",
                                            "H2O"].fix(H2O_mol_comp_flow)

        # Use assert electroneutrality method from property model to ensure the ion concentrations provided
        # obey electroneutrality condition
        m.fs.unit.feed_side.properties_in[0].assert_electroneutrality(
            defined_state=True,
            adjust_by_ion="Cl_-",
            get_property="mass_frac_phase_comp",
        )

        # Fix other inlet state variables
        m.fs.unit.inlet.temperature[0].fix(298.15)
        m.fs.unit.inlet.pressure[0].fix(4e5)

        # Fix the membrane variables that are usually fixed for the DSPM-DE model
        m.fs.unit.radius_pore.fix(0.5e-9)
        m.fs.unit.membrane_thickness_effective.fix(1.33e-6)
        m.fs.unit.membrane_charge_density.fix(-27)
        m.fs.unit.dielectric_constant_pore.fix(41.3)

        # Fix final permeate pressure to be ~atmospheric
        m.fs.unit.mixed_permeate[0].pressure.fix(101325)

        # Fix additional variables for calculating mass transfer coefficient with spiral wound correlation
        m.fs.unit.spacer_porosity.fix(0.85)
        m.fs.unit.spacer_mixing_efficiency.fix()
        m.fs.unit.spacer_mixing_length.fix()
        m.fs.unit.channel_height.fix(5e-4)
        m.fs.unit.recovery_vol_phase[0, "Liq"].fix(0.5)

        return m
Пример #7
0
def model4():
    m4 = ConcreteModel()

    m4.fs = FlowsheetBlock(default={"dynamic": False})
    m4.fs.properties = DSPMDEParameterBlock(
        default={
            "solute_list": ["A", "B", "C", "D", "E"],
            "diffusivity_data": {
                ("Liq", "A"): 1e-9,
                ("Liq", "B"): 1e-10,
                ("Liq", "C"): 1e-7,
                ("Liq", "D"): 1e-11,
                ("Liq", "E"): 1e-11,
            },
            "mw_data": {
                "H2O": 18e-3,
                "A": 10e-3,
                "B": 25e-3,
                "C": 100e-3,
                "D": 25e-3,
                "E": 25e-3,
            },
            "electrical_mobility_data": {
                "A": 5.19e-8,
                "B": 8.29e-8,
                "C": 6.17e-8,
                "D": 7.92e-8,
            },
            "stokes_radius_data": {
                "A": 1e-9,
                "B": 1e-9,
                "C": 1e-9,
                "D": 1e-10,
                "E": 1e-10,
            },
            "charge": {
                "A": 1,
                "B": -2,
                "C": 2,
                "D": -1,
                "E": 0
            },
        })

    # config
    thermo_config = {
        "components": {
            "H2O": {
                "type": Solvent,
                "valid_phase_types": PT.aqueousPhase,
                "dens_mol_liq_comp": Constant,
                "enth_mol_liq_comp": Constant,
                "cp_mol_liq_comp": Constant,
                "entr_mol_liq_comp": Constant,
                # Parameter data is always associated with the methods defined above
                "parameter_data": {
                    "mw": (18.0153, pyunits.g / pyunits.mol),
                    "dens_mol_liq_comp_coeff":
                    (55.2, pyunits.kmol * pyunits.m**-3),
                    "cp_mol_liq_comp_coeff": (
                        75.312,
                        pyunits.J / pyunits.mol / pyunits.K,
                    ),
                    "enth_mol_form_liq_comp_ref":
                    (0, pyunits.kJ / pyunits.mol),
                    "entr_mol_form_liq_comp_ref": (
                        0,
                        pyunits.J / pyunits.K / pyunits.mol,
                    ),
                },
                # End parameter_data
            },
            "A": {
                "type": Cation,
                "charge": 1,
                "dens_mol_liq_comp": Constant,
                "enth_mol_liq_comp": Constant,
                "cp_mol_liq_comp": Constant,
                "entr_mol_liq_comp": Constant,
                "parameter_data": {
                    "mw": (10, pyunits.g / pyunits.mol),
                    "electrical_mobility_comp": (
                        5.19e-8,
                        pyunits.meter**2 * pyunits.volt**-1 *
                        pyunits.second**-1,
                    ),
                    "dens_mol_liq_comp_coeff":
                    (55.2, pyunits.kmol * pyunits.m**-3),
                    "cp_mol_liq_comp_coeff": (
                        75.312,
                        pyunits.J / pyunits.mol / pyunits.K,
                    ),
                    "enth_mol_form_liq_comp_ref":
                    (0, pyunits.kJ / pyunits.mol),
                    "entr_mol_form_liq_comp_ref": (
                        0,
                        pyunits.J / pyunits.K / pyunits.mol,
                    ),
                },
            },
            "B": {
                "type": Anion,
                "charge": -2,
                "dens_mol_liq_comp": Constant,
                "enth_mol_liq_comp": Constant,
                "cp_mol_liq_comp": Constant,
                "entr_mol_liq_comp": Constant,
                "parameter_data": {
                    "mw": (25, pyunits.g / pyunits.mol),
                    "electrical_mobility_comp": (
                        8.29e-8,
                        pyunits.meter**2 * pyunits.volt**-1 *
                        pyunits.second**-1,
                    ),
                    "dens_mol_liq_comp_coeff":
                    (55.2, pyunits.kmol * pyunits.m**-3),
                    "cp_mol_liq_comp_coeff": (
                        75.312,
                        pyunits.J / pyunits.mol / pyunits.K,
                    ),
                    "enth_mol_form_liq_comp_ref":
                    (0, pyunits.kJ / pyunits.mol),
                    "entr_mol_form_liq_comp_ref": (
                        0,
                        pyunits.J / pyunits.K / pyunits.mol,
                    ),
                },
            },
            "C": {
                "type": Cation,
                "charge": 2,
                "dens_mol_liq_comp": Constant,
                "enth_mol_liq_comp": Constant,
                "cp_mol_liq_comp": Constant,
                "entr_mol_liq_comp": Constant,
                "parameter_data": {
                    "mw": (100, pyunits.g / pyunits.mol),
                    "electrical_mobility_comp": (
                        6.17e-8,
                        pyunits.meter**2 * pyunits.volt**-1 *
                        pyunits.second**-1,
                    ),
                    "dens_mol_liq_comp_coeff":
                    (55.2, pyunits.kmol * pyunits.m**-3),
                    "cp_mol_liq_comp_coeff": (
                        75.312,
                        pyunits.J / pyunits.mol / pyunits.K,
                    ),
                    "enth_mol_form_liq_comp_ref":
                    (0, pyunits.kJ / pyunits.mol),
                    "entr_mol_form_liq_comp_ref": (
                        0,
                        pyunits.J / pyunits.K / pyunits.mol,
                    ),
                },
            },
            "D": {
                "type": Anion,
                "charge": -1,
                "dens_mol_liq_comp": Constant,
                "enth_mol_liq_comp": Constant,
                "cp_mol_liq_comp": Constant,
                "entr_mol_liq_comp": Constant,
                "parameter_data": {
                    "mw": (25, pyunits.g / pyunits.mol),
                    "electrical_mobility_comp": (
                        7.92e-8,
                        pyunits.meter**2 * pyunits.volt**-1 *
                        pyunits.second**-1,
                    ),
                    "dens_mol_liq_comp_coeff":
                    (55.2, pyunits.kmol * pyunits.m**-3),
                    "cp_mol_liq_comp_coeff": (
                        75.312,
                        pyunits.J / pyunits.mol / pyunits.K,
                    ),
                    "enth_mol_form_liq_comp_ref":
                    (0, pyunits.kJ / pyunits.mol),
                    "entr_mol_form_liq_comp_ref": (
                        0,
                        pyunits.J / pyunits.K / pyunits.mol,
                    ),
                },
            },
            "E": {
                "type": Solute,
                "valid_phase_types": PT.aqueousPhase,
                "dens_mol_liq_comp": Constant,
                "enth_mol_liq_comp": Constant,
                "cp_mol_liq_comp": Constant,
                "entr_mol_liq_comp": Constant,
                "parameter_data": {
                    "mw": (25, pyunits.g / pyunits.mol),
                    "dens_mol_liq_comp_coeff":
                    (55.2, pyunits.kmol * pyunits.m**-3),
                    "cp_mol_liq_comp_coeff": (
                        75.312,
                        pyunits.J / pyunits.mol / pyunits.K,
                    ),
                    "enth_mol_form_liq_comp_ref":
                    (0, pyunits.kJ / pyunits.mol),
                    "entr_mol_form_liq_comp_ref": (
                        0,
                        pyunits.J / pyunits.K / pyunits.mol,
                    ),
                },
            },
        },
        # End Component list
        "phases": {
            "Liq": {
                "type": AqueousPhase,
                "equation_of_state": Ideal
            },
        },
        "state_definition": FpcTP,
        "state_bounds": {
            "temperature": (273.15, 300, 650),
            "pressure": (5e4, 1e5, 1e6),
        },
        "pressure_ref": 1e5,
        "temperature_ref": 300,
        "base_units": {
            "time": pyunits.s,
            "length": pyunits.m,
            "mass": pyunits.kg,
            "amount": pyunits.mol,
            "temperature": pyunits.K,
        },
    }
    # End thermo_config definition

    m5 = ConcreteModel()
    m5.fs = FlowsheetBlock(default={"dynamic": False})
    m5.fs.properties = GenericParameterBlock(default=thermo_config)

    return (m4, m5)
Пример #8
0
def test_assert_electroneutrality_get_property():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = DSPMDEParameterBlock(
        default={
            "solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"],
            "mw_data": {
                "H2O": 18e-3,
                "Na_+": 23e-3,
                "Ca_2+": 40e-3,
                "Mg_2+": 24e-3,
                "Cl_-": 35e-3,
                "SO4_2-": 96e-3,
            },
            "charge": {
                "Na_+": 1,
                "Ca_2+": 2,
                "Mg_2+": 2,
                "Cl_-": -1,
                "SO4_2-": -2
            },
            "density_calculation": DensityCalculation.seawater,
            "activity_coefficient_model": ActivityCoefficientModel.davies,
        })
    m.fs.stream = stream = m.fs.properties.build_state_block(
        [0], default={"defined_state": True})

    mass_flow_in = 1 * pyunits.kg / pyunits.s
    feed_mass_frac = {
        "Na_+": 11122e-6,
        "Ca_2+": 382e-6,
        "Mg_2+": 1394e-6,
        "SO4_2-": 2136e-6,
        "Cl_-": 20300e-6,
    }
    for ion, x in feed_mass_frac.items():
        mol_comp_flow = (x * pyunits.kg / pyunits.kg * mass_flow_in /
                         stream[0].mw_comp[ion])

        stream[0].flow_mol_phase_comp["Liq", ion].fix(mol_comp_flow)

    H2O_mass_frac = 1 - sum(x for x in feed_mass_frac.values())
    H2O_mol_comp_flow = (H2O_mass_frac * pyunits.kg / pyunits.kg *
                         mass_flow_in / stream[0].mw_comp["H2O"])

    stream[0].flow_mol_phase_comp["Liq", "H2O"].fix(H2O_mol_comp_flow)
    stream[0].temperature.fix(298.15)
    stream[0].pressure.fix(101325)

    # check get_property works with tuple
    stream[0].assert_electroneutrality(
        defined_state=True,
        adjust_by_ion="Cl_-",
        get_property=("mass_frac_phase_comp", "pressure_osm_phase"),
    )
    # check error when adjust_by_ion is not in solute list
    with pytest.raises(
            ValueError,
            match="adjust_by_ion must be set to the name of an "
            "ion in the list of solutes.",
    ):
        stream[0].assert_electroneutrality(defined_state=True,
                                           adjust_by_ion="foo")

    # check error when get_property is not None and defined_state is NOT true
    with pytest.raises(
            ValueError,
            match="Set defined_state to true if get_property"
            " = flow_mass_phase_comp",
    ):
        stream[0].assert_electroneutrality(defined_state=False,
                                           get_property="flow_mass_phase_comp")

    # check error when state vars are fixed but defined_state is set to False
    with pytest.raises(
            AssertionError,
            match=re.escape(
                "fs.stream[0].flow_mol_phase_comp[Liq,Ca_2+] was fixed. "
                "Either set defined_state=True or unfix flow_mol_phase_comp "
                "for each solute to check that electroneutrality is satisfied."
            ),
    ):
        stream[0].assert_electroneutrality(defined_state=False)

    # check error when get_property receives anything other than str, list, or tuple of strings
    with pytest.raises(
            TypeError,
            match=re.escape(
                "get_property must be a string or list/tuple of strings."),
    ):
        stream[0].assert_electroneutrality(defined_state=True,
                                           adjust_by_ion="Cl_-",
                                           get_property=1)

    # check error when electroneutralit condition violated for stringent tolerance
    #   Changed the error message to look for the correct pattern instead of
    #   exact match of the numeric value in the string
    stream[0].flow_mol_phase_comp.unfix()
    with pytest.raises(
            AssertionError,
            match=re.escape(
                "Electroneutrality condition violated in fs.stream[0]. "),
    ):
        stream[0].assert_electroneutrality(defined_state=False,
                                           adjust_by_ion="Cl_-",
                                           tol=1e-18)
Пример #9
0
def test_assert_electroneutrality_get_property():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = DSPMDEParameterBlock(
        default={
            "solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"],
            "diffusivity_data": {
                ("Liq", "Ca_2+"): 0.792e-9,
                ("Liq", "SO4_2-"): 1.06e-9,
                ("Liq", "Na_+"): 1.33e-9,
                ("Liq", "Cl_-"): 2.03e-9,
                ("Liq", "Mg_2+"): 0.706e-9,
            },
            "mw_data": {
                "H2O": 18e-3,
                "Na_+": 23e-3,
                "Ca_2+": 40e-3,
                "Mg_2+": 24e-3,
                "Cl_-": 35e-3,
                "SO4_2-": 96e-3,
            },
            "electrical_mobility_data": {
                "Na_+": 5.19e-8,
                "Ca_2+": 6.17e-8,
                "Mg_2+": 5.50e-8,
                "Cl_-": 7.92e-8,
                "SO4_2-": 8.29e-8,
            },
            "stokes_radius_data": {
                "Na_+": 0.184e-9,
                "Ca_2+": 0.309e-9,
                "Mg_2+": 0.347e-9,
                "Cl_-": 0.121e-9,
                "SO4_2-": 0.230e-9,
            },
            "charge": {
                "Na_+": 1,
                "Ca_2+": 2,
                "Mg_2+": 2,
                "Cl_-": -1,
                "SO4_2-": -2
            },
            "density_calculation": DensityCalculation.seawater,
            "activity_coefficient_model": ActivityCoefficientModel.davies,
        })

    m.fs.stream = stream = m.fs.properties.build_state_block(
        [0], default={"defined_state": True})

    mass_flow_in = 1 * pyunits.kg / pyunits.s
    feed_mass_frac = {
        "Na_+": 11122e-6,
        "Ca_2+": 382e-6,
        "Mg_2+": 1394e-6,
        "SO4_2-": 2136e-6,
        "Cl_-": 20300e-6,
    }
    for ion, x in feed_mass_frac.items():
        mol_comp_flow = (x * pyunits.kg / pyunits.kg * mass_flow_in /
                         stream[0].mw_comp[ion])

        stream[0].flow_mol_phase_comp["Liq", ion].fix(mol_comp_flow)

    H2O_mass_frac = 1 - sum(x for x in feed_mass_frac.values())
    H2O_mol_comp_flow = (H2O_mass_frac * pyunits.kg / pyunits.kg *
                         mass_flow_in / stream[0].mw_comp["H2O"])

    stream[0].flow_mol_phase_comp["Liq", "H2O"].fix(H2O_mol_comp_flow)
    stream[0].temperature.fix(298.15)
    stream[0].pressure.fix(101325)

    assert not stream[0].is_property_constructed("pressure_osm_phase")
    assert not stream[0].is_property_constructed("mass_frac_phase_comp")

    stream[0].assert_electroneutrality(
        defined_state=True,
        adjust_by_ion="Cl_-",
        get_property=["mass_frac_phase_comp", "pressure_osm_phase"],
    )
    assert stream[0].is_property_constructed("mass_frac_phase_comp")
    assert stream[0].is_property_constructed("pressure_osm_phase")
    assert not hasattr(stream, "charge_balance")

    assert not stream[0].is_property_constructed("flow_vol")
    stream[0].assert_electroneutrality(defined_state=True,
                                       adjust_by_ion="Cl_-",
                                       get_property="flow_vol")
    assert stream[0].is_property_constructed("flow_vol")
    assert not hasattr(stream, "charge_balance")

    # check that charge_balance constraint is deleted after failed solve
    stream[0].flow_vol_phase.fix(1e5)
    with pytest.raises(
            ValueError,
            match="The stateblock failed to solve while computing "
            "concentrations to check the charge balance.",
    ):
        stream[0].assert_electroneutrality(defined_state=True,
                                           adjust_by_ion="Cl_-")
    assert not hasattr(stream, "charge_balance")
Пример #10
0
def test_seawater_data():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = DSPMDEParameterBlock(
        default={
            "solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"],
            "diffusivity_data": {
                ("Liq", "Ca_2+"): 0.792e-9,
                ("Liq", "SO4_2-"): 1.06e-9,
                ("Liq", "Na_+"): 1.33e-9,
                ("Liq", "Cl_-"): 2.03e-9,
                ("Liq", "Mg_2+"): 0.706e-9,
            },
            "mw_data": {
                "H2O": 18e-3,
                "Na_+": 23e-3,
                "Ca_2+": 40e-3,
                "Mg_2+": 24e-3,
                "Cl_-": 35e-3,
                "SO4_2-": 96e-3,
            },
            "electrical_mobility_data": {
                "Na_+": 5.19e-8,
                "Ca_2+": 6.17e-8,
                "Mg_2+": 5.50e-8,
                "Cl_-": 7.92e-8,
                "SO4_2-": 8.29e-8,
            },
            "stokes_radius_data": {
                "Na_+": 0.184e-9,
                "Ca_2+": 0.309e-9,
                "Mg_2+": 0.347e-9,
                "Cl_-": 0.121e-9,
                "SO4_2-": 0.230e-9,
            },
            "charge": {
                "Na_+": 1,
                "Ca_2+": 2,
                "Mg_2+": 2,
                "Cl_-": -1,
                "SO4_2-": -2
            },
            "density_calculation": DensityCalculation.seawater,
            "activity_coefficient_model": ActivityCoefficientModel.davies,
        })

    m.fs.stream = stream = m.fs.properties.build_state_block(
        [0], default={"defined_state": True})

    mass_flow_in = 1 * pyunits.kg / pyunits.s
    feed_mass_frac = {
        "Na_+": 11122e-6,
        "Ca_2+": 382e-6,
        "Mg_2+": 1394e-6,
        "SO4_2-": 2136e-6,
        "Cl_-": 20300e-6,
    }
    for ion, x in feed_mass_frac.items():
        mol_comp_flow = (x * pyunits.kg / pyunits.kg * mass_flow_in /
                         stream[0].mw_comp[ion])

        stream[0].flow_mol_phase_comp["Liq", ion].fix(mol_comp_flow)

    H2O_mass_frac = 1 - sum(x for x in feed_mass_frac.values())
    H2O_mol_comp_flow = (H2O_mass_frac * pyunits.kg / pyunits.kg *
                         mass_flow_in / stream[0].mw_comp["H2O"])

    stream[0].flow_mol_phase_comp["Liq", "H2O"].fix(H2O_mol_comp_flow)
    stream[0].temperature.fix(298.15)
    stream[0].pressure.fix(101325)

    stream[0].assert_electroneutrality(defined_state=True,
                                       tol=1e-2,
                                       adjust_by_ion="Cl_-")

    metadata = m.fs.properties.get_metadata().properties
    for v_name in metadata:
        getattr(stream[0], v_name)
    assert stream[0].is_property_constructed("conc_mol_phase_comp")

    assert_units_consistent(m)

    check_dof(m, fail_flag=True)

    m.fs.properties.set_default_scaling("flow_mol_phase_comp",
                                        1e-1,
                                        index=("Liq", "H2O"))
    m.fs.properties.set_default_scaling("flow_mol_phase_comp",
                                        1e1,
                                        index=("Liq", "Na_+"))
    m.fs.properties.set_default_scaling("flow_mol_phase_comp",
                                        1e1,
                                        index=("Liq", "Cl_-"))
    m.fs.properties.set_default_scaling("flow_mol_phase_comp",
                                        1e2,
                                        index=("Liq", "Ca_2+"))
    m.fs.properties.set_default_scaling("flow_mol_phase_comp",
                                        1e2,
                                        index=("Liq", "SO4_2-"))
    m.fs.properties.set_default_scaling("flow_mol_phase_comp",
                                        1e2,
                                        index=("Liq", "Mg_2+"))

    calculate_scaling_factors(m)

    stream.initialize()

    # check if any variables are badly scaled
    badly_scaled_var_list = list(
        badly_scaled_var_generator(m, large=100, small=0.01, zero=1e-10))
    assert len(badly_scaled_var_list) == 0

    results = solver.solve(m)
    assert_optimal_termination(results)

    assert value(stream[0].flow_vol_phase["Liq"]) == pytest.approx(9.767e-4,
                                                                   rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp["Liq", "H2O"]) == pytest.approx(
        53.59256, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp["Liq",
                                               "Na_+"]) == pytest.approx(
                                                   0.4836, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp["Liq",
                                               "Ca_2+"]) == pytest.approx(
                                                   0.00955, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp["Liq",
                                               "Mg_2+"]) == pytest.approx(
                                                   0.05808, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp["Liq",
                                               "Cl_-"]) == pytest.approx(
                                                   0.57443, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp["Liq",
                                               "SO4_2-"]) == pytest.approx(
                                                   0.02225, rel=1e-3)

    assert value(stream[0].dens_mass_phase["Liq"]) == pytest.approx(1023.816,
                                                                    rel=1e-3)
    assert value(stream[0].pressure_osm_phase["Liq"]) == pytest.approx(
        29.132e5, rel=1e-3)
    assert value(
        stream[0].electrical_conductivity_phase["Liq"]) == pytest.approx(
            8.08, rel=1e-3)
    assert value(stream[0].flow_vol) == pytest.approx(9.767e-4, rel=1e-3)

    assert value(
        sum(stream[0].conc_mass_phase_comp["Liq", j]
            for j in m.fs.properties.ion_set
            | m.fs.properties.solute_set)) == pytest.approx(35.9744, rel=1e-3)
    assert value(
        sum(stream[0].mass_frac_phase_comp["Liq", j]
            for j in m.fs.properties.ion_set
            | m.fs.properties.solute_set)) == pytest.approx(0.035142, rel=1e-3)
    assert value(
        sum(stream[0].mass_frac_phase_comp["Liq", j]
            for j in m.fs.properties.component_list)) == pytest.approx(
                1, rel=1e-3)
    assert value(
        sum(stream[0].mole_frac_phase_comp["Liq", j]
            for j in m.fs.properties.component_list)) == pytest.approx(
                1, rel=1e-3)

    assert value(stream[0].conc_mol_phase_comp["Liq",
                                               "Na_+"]) == pytest.approx(
                                                   495.082, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp["Liq",
                                               "Cl_-"]) == pytest.approx(
                                                   588.0431, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp["Liq",
                                               "Ca_2+"]) == pytest.approx(
                                                   9.777, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp["Liq",
                                               "SO4_2-"]) == pytest.approx(
                                                   22.780, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp["Liq",
                                               "Mg_2+"]) == pytest.approx(
                                                   59.467, rel=1e-3)

    assert value(stream[0].conc_mass_phase_comp["Liq",
                                                "Na_+"]) == pytest.approx(
                                                    11.387, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp["Liq",
                                                "Cl_-"]) == pytest.approx(
                                                    20.5815, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp["Liq",
                                                "Ca_2+"]) == pytest.approx(
                                                    0.391, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp["Liq",
                                                "SO4_2-"]) == pytest.approx(
                                                    2.187, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp["Liq",
                                                "Mg_2+"]) == pytest.approx(
                                                    1.427, rel=1e-3)

    assert value(stream[0].mole_frac_phase_comp["Liq",
                                                "Na_+"]) == pytest.approx(
                                                    8.833e-3, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp["Liq",
                                                "Cl_-"]) == pytest.approx(
                                                    1.049e-2, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp["Liq",
                                                "Ca_2+"]) == pytest.approx(
                                                    1.744e-4, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp["Liq",
                                                "SO4_2-"]) == pytest.approx(
                                                    4.064e-4, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp["Liq",
                                                "Mg_2+"]) == pytest.approx(
                                                    1.061e-3, rel=1e-3)

    assert value(stream[0].mass_frac_phase_comp["Liq",
                                                "Na_+"]) == pytest.approx(
                                                    1.112e-2, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp["Liq",
                                                "Cl_-"]) == pytest.approx(
                                                    2.01e-2, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp["Liq",
                                                "Ca_2+"]) == pytest.approx(
                                                    3.82e-4, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp["Liq",
                                                "SO4_2-"]) == pytest.approx(
                                                    2.136e-3, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp["Liq",
                                                "Mg_2+"]) == pytest.approx(
                                                    1.394e-3, rel=1e-3)

    assert value(stream[0].debye_huckel_constant) == pytest.approx(0.01554,
                                                                   rel=1e-3)
    assert value(stream[0].ionic_strength) == pytest.approx(0.73467, rel=1e-3)
Пример #11
0
def test_seawater_data():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={'dynamic': False})
    m.fs.properties = DSPMDEParameterBlock(
        default={
            "solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"],
            "diffusivity_data": {
                ("Liq", "Ca_2+"): 0.792e-9,
                ("Liq", "SO4_2-"): 1.06e-9,
                ("Liq", "Na_+"): 1.33e-9,
                ("Liq", "Cl_-"): 2.03e-9,
                ("Liq", "Mg_2+"): 0.706e-9
            },
            "mw_data": {
                "H2O": 18e-3,
                "Na_+": 23e-3,
                "Ca_2+": 40e-3,
                "Mg_2+": 24e-3,
                "Cl_-": 35e-3,
                "SO4_2-": 96e-3
            },
            "stokes_radius_data": {
                "Na_+": 0.184e-9,
                "Ca_2+": 0.309e-9,
                "Mg_2+": 0.347e-9,
                "Cl_-": 0.121e-9,
                "SO4_2-": 0.230e-9
            },
            "charge": {
                "Na_+": 1,
                "Ca_2+": 2,
                "Mg_2+": 2,
                "Cl_-": -1,
                "SO4_2-": -2
            },
        })

    m.fs.stream = stream = m.fs.properties.build_state_block(
        [0], default={'defined_state': True})

    mass_flow_in = 1 * pyunits.kg / pyunits.s
    feed_mass_frac = {
        'Na_+': 11122e-6,
        'Ca_2+': 382e-6,
        'Mg_2+': 1394e-6,
        'SO4_2-': 2136e-6,
        'Cl_-': 20300e-6
    }
    for ion, x in feed_mass_frac.items():
        mol_comp_flow = x * pyunits.kg / pyunits.kg * mass_flow_in / stream[
            0].mw_comp[ion]

        stream[0].flow_mol_phase_comp['Liq', ion].fix(mol_comp_flow)

    H2O_mass_frac = 1 - sum(x for x in feed_mass_frac.values())
    H2O_mol_comp_flow = H2O_mass_frac * pyunits.kg / pyunits.kg * mass_flow_in / stream[
        0].mw_comp['H2O']

    stream[0].flow_mol_phase_comp['Liq', 'H2O'].fix(H2O_mol_comp_flow)
    stream[0].temperature.fix(298.15)
    stream[0].pressure.fix(101325)

    stream[0].assert_electroneutrality(tol=1e-2)

    metadata = m.fs.properties.get_metadata().properties
    for v_name in metadata:
        getattr(stream[0], v_name)
    assert stream[0].is_property_constructed('conc_mol_phase_comp')

    assert_units_consistent(m)

    check_dof(m, fail_flag=True)

    m.fs.properties.set_default_scaling('flow_mol_phase_comp',
                                        1,
                                        index=('Liq', 'H2O'))
    m.fs.properties.set_default_scaling('flow_mol_phase_comp',
                                        1,
                                        index=('Liq', 'Na_+'))
    m.fs.properties.set_default_scaling('flow_mol_phase_comp',
                                        1,
                                        index=('Liq', 'Cl_-'))
    m.fs.properties.set_default_scaling('flow_mol_phase_comp',
                                        1e1,
                                        index=('Liq', 'Ca_2+'))
    m.fs.properties.set_default_scaling('flow_mol_phase_comp',
                                        1e1,
                                        index=('Liq', 'SO4_2-'))
    m.fs.properties.set_default_scaling('flow_mol_phase_comp',
                                        1,
                                        index=('Liq', 'Mg_2+'))
    calculate_scaling_factors(m)

    # check if any variables are badly scaled
    badly_scaled_var_list = list(badly_scaled_var_generator(m))
    assert len(badly_scaled_var_list) == 0

    stream.initialize()

    # check if any variables are badly scaled
    badly_scaled_var_list = list(badly_scaled_var_generator(m))
    assert len(badly_scaled_var_list) == 0

    results = solver.solve(m)
    assert_optimal_termination(results)

    assert value(stream[0].flow_vol_phase['Liq']) == pytest.approx(0.001,
                                                                   rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp['Liq', 'H2O']) == pytest.approx(
        53.59256, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp['Liq',
                                               'Na_+']) == pytest.approx(
                                                   0.4836, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp['Liq',
                                               'Ca_2+']) == pytest.approx(
                                                   0.00955, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp['Liq',
                                               'Mg_2+']) == pytest.approx(
                                                   0.05808, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp['Liq',
                                               'Cl_-']) == pytest.approx(
                                                   0.58, rel=1e-3)
    assert value(stream[0].flow_mol_phase_comp['Liq',
                                               'SO4_2-']) == pytest.approx(
                                                   0.02225, rel=1e-3)
    assert value(stream[0].dens_mass_phase['Liq']) == pytest.approx(1000,
                                                                    rel=1e-3)
    assert value(stream[0].pressure_osm) == pytest.approx(28.593e5, rel=1e-3)
    assert value(stream[0].flow_vol) == pytest.approx(0.001, rel=1e-3)

    assert value(
        sum(stream[0].conc_mass_phase_comp['Liq', j]
            for j in m.fs.properties.solute_set)) == pytest.approx(35.334,
                                                                   rel=1e-3)
    assert value(
        sum(stream[0].mass_frac_phase_comp['Liq', j]
            for j in m.fs.properties.solute_set)) == pytest.approx(35334e-6,
                                                                   rel=1e-3)
    assert value(
        sum(stream[0].mass_frac_phase_comp['Liq', j]
            for j in m.fs.properties.component_list)) == pytest.approx(
                1, rel=1e-3)
    assert value(
        sum(stream[0].mole_frac_phase_comp['Liq', j]
            for j in m.fs.properties.component_list)) == pytest.approx(
                1, rel=1e-3)

    assert value(stream[0].conc_mol_phase_comp['Liq',
                                               'Na_+']) == pytest.approx(
                                                   483.565, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp['Liq',
                                               'Cl_-']) == pytest.approx(
                                                   580, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp['Liq',
                                               'Ca_2+']) == pytest.approx(
                                                   9.55, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp['Liq',
                                               'SO4_2-']) == pytest.approx(
                                                   22.25, rel=1e-3)
    assert value(stream[0].conc_mol_phase_comp['Liq',
                                               'Mg_2+']) == pytest.approx(
                                                   58.08, rel=1e-3)

    assert value(stream[0].conc_mass_phase_comp['Liq',
                                                'Na_+']) == pytest.approx(
                                                    11.122, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp['Liq',
                                                'Cl_-']) == pytest.approx(
                                                    20.3, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp['Liq',
                                                'Ca_2+']) == pytest.approx(
                                                    0.382, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp['Liq',
                                                'SO4_2-']) == pytest.approx(
                                                    2.136, rel=1e-3)
    assert value(stream[0].conc_mass_phase_comp['Liq',
                                                'Mg_2+']) == pytest.approx(
                                                    1.394, rel=1e-3)

    assert value(stream[0].mole_frac_phase_comp['Liq',
                                                'Na_+']) == pytest.approx(
                                                    8.833e-3, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp['Liq',
                                                'Cl_-']) == pytest.approx(
                                                    1.059e-2, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp['Liq',
                                                'Ca_2+']) == pytest.approx(
                                                    1.744e-4, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp['Liq',
                                                'SO4_2-']) == pytest.approx(
                                                    4.064e-4, rel=1e-3)
    assert value(stream[0].mole_frac_phase_comp['Liq',
                                                'Mg_2+']) == pytest.approx(
                                                    1.061e-3, rel=1e-3)

    assert value(stream[0].mass_frac_phase_comp['Liq',
                                                'Na_+']) == pytest.approx(
                                                    1.112e-2, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp['Liq',
                                                'Cl_-']) == pytest.approx(
                                                    2.03e-2, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp['Liq',
                                                'Ca_2+']) == pytest.approx(
                                                    3.82e-4, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp['Liq',
                                                'SO4_2-']) == pytest.approx(
                                                    2.136e-3, rel=1e-3)
    assert value(stream[0].mass_frac_phase_comp['Liq',
                                                'Mg_2+']) == pytest.approx(
                                                    1.394e-3, rel=1e-3)