Ejemplo n.º 1
0
class PhysicalParameterData(PhysicalParameterBlock):
    """
    Property Parameter Block Class.
    """

    # Config block for the _IdealStateBlock
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare(
        "valid_phase",
        ConfigValue(default=('Vap', 'Liq'),
                    domain=In(['Liq', 'Vap', ('Vap', 'Liq'), ('Liq', 'Vap')]),
                    description="Flag indicating the valid phase",
                    doc="""Flag indicating the valid phase for a given set of
    conditions, and thus corresponding constraints  should be included,
    **default** - ('Vap', 'Liq').
    **Valid values:** {
    **'Liq'** - Liquid only,
    **'Vap'** - Vapor only,
    **('Vap', 'Liq')** - Vapor-liquid equilibrium,
    **('Liq', 'Vap')** - Vapor-liquid equilibrium,}"""))

    CONFIG.declare(
        "Cp",
        ConfigValue(
            default=0.035,
            domain=float,
            description="Constant pressure heat capacity in MJ/(kgmol K)",
            doc="""Value for the constant pressure heat capacity,
        **default** = 0.035 MJ/(kgmol K)"""))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(PhysicalParameterData, self).build()

        self.state_block_class = IdealStateBlock

        # List of valid phases in property package
        # List of valid phases in property package
        if self.config.valid_phase == ('Liq', 'Vap') or \
                self.config.valid_phase == ('Vap', 'Liq'):
            self.phase_list = Set(initialize=['Liq', 'Vap'], ordered=True)
        elif self.config.valid_phase == 'Liq':
            self.phase_list = Set(initialize=['Liq'])
        else:
            self.phase_list = Set(initialize=['Vap'])

        self.component_list = Set(initialize=['CH4', 'CO', 'H2', 'CH3OH'])

        # List of components in each phase (optional)
        self.phase_comp = {
            "Liq": self.component_list,
            "Vap": self.component_list
        }

        self.phase_equilibrium_idx = Set(initialize=[1, 2, 3, 4])

        self.phase_equilibrium_list = \
            {1: ["CH4", ("Vap", "Liq")],
             2: ["CO", ("Vap", "Liq")],
             3: ["H2", ("Vap", "Liq")],
             4: ["CH3OH", ("Vap", "Liq")]}

        # Gas Constant
        self.gas_constant = Param(within=NonNegativeReals,
                                  mutable=False,
                                  default=0.008314,
                                  doc='Gas Constant [MJ/(kgmol.K)]')

        self.vapor_pressure_coeff = {
            ('CH4', 'A'): 15.2243,
            ('CH4', 'B'): 897.84,
            ('CH4', 'C'): -7.16,
            ('CO', 'A'): 14.3686,
            ('CO', 'B'): 530.22,
            ('CO', 'C'): -13.15,
            ('H2', 'A'): 13.6333,
            ('H2', 'B'): 164.9,
            ('H2', 'C'): 3.19,
            ('CH3OH', 'A'): 18.5875,
            ('CH3OH', 'B'): 3626.55,
            ('CH3OH', 'C'): -34.29
        }

        Cp = self.config.Cp
        Cv = Cp - self.gas_constant.value
        gamma = Cp / Cv

        self.gamma = Param(within=NonNegativeReals,
                           mutable=True,
                           default=gamma,
                           doc='Ratio of Cp to Cv')

        self.Cp = Param(within=NonNegativeReals,
                        mutable=True,
                        default=Cp,
                        doc='Constant pressure heat capacity [MJ/(kgmol K)]')

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mol': {
                'method': None,
                'units': 'kgmol/s'
            },
            'mole_frac': {
                'method': None,
                'units': 'no unit'
            },
            'temperature': {
                'method': None,
                'units': '100K'
            },
            'pressure': {
                'method': None,
                'units': 'MPa'
            },
            'flow_mol_phase': {
                'method': None,
                'units': 'kgmol/s'
            },
            'density_mol': {
                'method': '_density_mol',
                'units': 'kgmol/m^3'
            },
            'vapor_pressure': {
                'method': '_vapor_pressure',
                'units': 'MPa'
            },
            'mole_frac_phase': {
                'method': '_mole_frac_phase',
                'units': 'no unit'
            },
            'enthalpy_comp_liq': {
                'method': '_enthalpy_comp_liq',
                'units': 'MJ/kgmol'
            },
            'enthalpy_comp_vap': {
                'method': '_enthalpy_comp_vap',
                'units': 'MJ/kgmol'
            },
            'enthalpy_liq': {
                'method': '_enthalpy_liq',
                'units': 'MJ/kgmol'
            },
            'enthalpy_vap': {
                'method': '_enthalpy_vap',
                'units': 'MJ/kgmol'
            }
        })

        obj.add_default_units({
            'time': 's',
            'length': 'm',
            'mass': 'kg',
            'amount': 'kgmol',
            'temperature': '100K',
            'energy': 'MJ',
            'holdup': 'kgmol'
        })
Ejemplo n.º 2
0
class ETOHParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(ETOHParameterData, self).build()

        self._state_block_class = IdealStateBlock

        self.ethanol = Component()
        self.water = Component()
        self.CO2 = Component()
        #self.hydrogen = Component()

        self.Liq = LiquidPhase()
        self.Vap = VaporPhase()

        # List of components in each phase (optional)
        self.phase_comp = {
            "Liq": self.component_list,
            "Vap": self.component_list
        }

        # List of phase equilibrium index
        self.phase_equilibrium_idx = Set(initialize=[1, 2, 3])

        self.phase_equilibrium_list = \
            {1: ["ethanol", ("Vap", "Liq")], #
             2: ["water", ("Vap", "Liq")],
             3: ["CO2", ("Vap", "Liq")]}
        #4: ["methane", ("Vap", "Liq")],
        #5: ["diphenyl", ("Vap", "Liq")]}

        # Thermodynamic reference state
        self.pressure_ref = Param(mutable=True,
                                  default=101325,
                                  doc='Reference pressure [Pa]')
        self.temperature_ref = Param(mutable=True,
                                     default=298.15,
                                     doc='Reference temperature [K]')

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        pressure_crit_data = {'ethanol': 63e5, 'water': 220.5e5, 'CO2': 73.8e5}

        self.pressure_crit = Param(self.component_list,
                                   within=NonNegativeReals,
                                   mutable=False,
                                   initialize=extract_data(pressure_crit_data),
                                   doc='Critical pressure [Pa]')

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        temperature_crit_data = {
            'ethanol': 515.15,
            'water': 647.15,
            'CO2': 304.34
        }

        self.temperature_crit = Param(
            self.component_list,
            within=NonNegativeReals,
            mutable=False,
            initialize=extract_data(temperature_crit_data),
            doc='Critical temperature [K]')

        # Gas Constant
        self.gas_const = Param(within=NonNegativeReals,
                               mutable=False,
                               default=8.314,
                               doc='Gas Constant [J/mol.K]')

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        mw_comp_data = {
            'ethanol': 46.07E-3,
            'water': 18.02E-3,
            'CO2': 44.01e-3
        }

        self.mw_comp = Param(self.component_list,
                             mutable=False,
                             initialize=extract_data(mw_comp_data),
                             doc="molecular weight Kg/mol")

        # Constants for liquid densities
        # Source: Perry's Chemical Engineers Handbook
        #         - Robert H. Perry (Cp_liq)
        dens_liq_data = {
            ('ethanol', '1'): 1.048,  #todo    
            ('ethanol', '2'): 0.27627,
            ('ethanol', '3'): 513.92,
            ('ethanol', '4'): 0.2331,
            ('water', '1'): 5.459,
            ('water', '2'): 0.30542,
            ('water', '3'): 647.13,
            ('water', '4'): 0.081,
            ('CO2', '1'): 2.768,
            ('CO2', '2'): 0.26212,
            ('CO2', '3'): 304.21,
            ('CO2', '4'): 0.2908
        }

        self.dens_liq_params = Param(
            self.component_list, ['1', '2', '3', '4'],
            mutable=False,
            initialize=extract_data(dens_liq_data),
            doc="Parameters to compute liquid densities")

        # Boiling point at standard pressure
        # Source: Perry's Chemical Engineers Handbook
        #         - Robert H. Perry (Cp_liq)
        bp_data = {('ethanol'): 351.52, ('water'): 373.15, ('CO2'): 194.69}

        self.temperature_boil = Param(
            self.component_list,
            mutable=False,
            initialize=extract_data(bp_data),
            doc="Pure component boiling points at standard pressure [K]")

        # Constants for specific heat capacity, enthalpy
        # Sources: The Properties of Gases and Liquids (1987)
        #         4th edition, Chemical Engineering Series - Robert C. Reid
        #         Perry's Chemical Engineers Handbook
        #         - Robert H. Perry (Cp_liq)
        # Unit: J/kmol-K
        cp_ig_data = {
            ('Liq', 'ethanol', '1'): 1.2064E5,  #todo
            ('Liq', 'ethanol', '2'): -1.3963E2,
            ('Liq', 'ethanol', '3'): -3.0341E-2,
            ('Liq', 'ethanol', '4'): 2.0386E-3,
            ('Liq', 'ethanol', '5'): 0,
            ('Vap', 'ethanol', '1'): 36.548344E3,
            ('Vap', 'ethanol', '2'): 5.221192,
            ('Vap', 'ethanol', '3'): 0.46109444,
            ('Vap', 'ethanol', '4'): -0.000583975,
            ('Vap', 'ethanol', '5'): 2.20986E-07,
            ('Liq', 'water', '1'): 2.7637E5,  #reference: toluene 1.40e5
            ('Liq', 'water', '2'): -2.0901E3,
            ('Liq', 'water', '3'): 8.1250,
            ('Liq', 'water', '4'): -1.4116E-2,
            ('Liq', 'water', '5'): 9.3701E-6,
            ('Vap', 'water', '1'): 3.654E4,
            ('Vap', 'water', '2'): -34.802404,
            ('Vap', 'water', '3'): -0.1168117,
            ('Vap', 'water', '4'): -0.000130031,
            ('Vap', 'water', '5'): 5.25445E-08,
            ('Liq', 'CO2', '1'): -8.3043E6,  # 6.6653e1,
            ('Liq', 'CO2', '2'): 1.0437E5,  # 6.7659e3,
            ('Liq', 'CO2', '3'): -4.3333E2,  # -1.2363e2,
            ('Liq', 'CO2', '4'): 6.0042E-1,  # 4.7827e2, # Eqn 2
            ('Liq', 'CO2', '5'): 0,
            ('Vap', 'CO2', '1'): 27095.326,
            ('Vap', 'CO2', '2'): 11.273784,
            ('Vap', 'CO2', '3'): 0.12487628,
            ('Vap', 'CO2', '4'): -0.000197374,
            ('Vap', 'CO2', '5'): 8.77958E-08
        }

        self.cp_ig = Param(self.phase_list,
                           self.component_list, ['1', '2', '3', '4', '5'],
                           mutable=False,
                           initialize=extract_data(cp_ig_data),
                           doc="parameters to compute Cp_comp")

        # Source: NIST
        # fitted to Antoine form
        # Unit: Pvp [bar] -> unit conversion later
        pressure_sat_coeff_data = {
            ('ethanol', 'A'): 5.24677,
            ('ethanol', 'B'): 1598.673,
            ('ethanol', 'C'): -46.424,
            ('water', 'A'): 5.40221,
            ('water', 'B'): 1838.675,
            ('water', 'C'): -31.737,
            ('CO2', 'A'): 6.812,
            ('CO2', 'B'): 1302,
            ('CO2', 'C'): -3.494
        }

        self.pressure_sat_coeff = Param(
            self.component_list, ['A', 'B', 'C'],
            mutable=False,
            initialize=extract_data(pressure_sat_coeff_data),
            doc="parameters to compute Cp_comp")

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        dh_vap = {'ethanol': 42.4e3, 'water': 43.86e3, 'CO2': 16.5e3}

        self.dh_vap = Param(self.component_list,
                            mutable=False,
                            initialize=extract_data(dh_vap),
                            doc="heat of vaporization")

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mol': {
                'method': None,
                'units': 'mol/s'
            },
            'flow_mol_phase_comp': {
                'method': None,
                'units': 'mol/s'
            },
            'mole_frac_comp': {
                'method': None,
                'units': 'none'
            },
            'temperature': {
                'method': None,
                'units': 'K'
            },
            'pressure': {
                'method': None,
                'units': 'Pa'
            },
            'flow_mol_phase': {
                'method': None,
                'units': 'mol/s'
            },
            'dens_mol_phase': {
                'method': '_dens_mol_phase',
                'units': 'mol/m^3'
            },
            'pressure_sat': {
                'method': '_pressure_sat',
                'units': 'Pa'
            },
            'mole_frac_phase_comp': {
                'method': '_mole_frac_phase',
                'units': 'no unit'
            },
            'energy_internal_mol_phase_comp': {
                'method': '_energy_internal_mol_phase_comp',
                'units': 'J/mol'
            },
            'energy_internal_mol_phase': {
                'method': '_enenrgy_internal_mol_phase',
                'units': 'J/mol'
            },
            'enth_mol_phase_comp': {
                'method': '_enth_mol_phase_comp',
                'units': 'J/mol'
            },
            'enth_mol_phase': {
                'method': '_enth_mol_phase',
                'units': 'J/mol'
            },
            'entr_mol_phase_comp': {
                'method': '_entr_mol_phase_comp',
                'units': 'J/mol'
            },
            'entr_mol_phase': {
                'method': '_entr_mol_phase',
                'units': 'J/mol'
            },
            'temperature_bubble': {
                'method': '_temperature_bubble',
                'units': 'K'
            },
            'temperature_dew': {
                'method': '_temperature_dew',
                'units': 'K'
            },
            'pressure_bubble': {
                'method': '_pressure_bubble',
                'units': 'Pa'
            },
            'pressure_dew': {
                'method': '_pressure_dew',
                'units': 'Pa'
            },
            'fug_vap': {
                'method': '_fug_vap',
                'units': 'Pa'
            },
            'fug_liq': {
                'method': '_fug_liq',
                'units': 'Pa'
            },
            'dh_vap': {
                'method': '_dh_vap',
                'units': 'J/mol'
            },
            'ds_vap': {
                'method': '_ds_vap',
                'units': 'J/mol.K'
            }
        })

        obj.add_default_units({
            'time': pyunits.s,
            'length': pyunits.m,
            'mass': pyunits.g,
            'amount': pyunits.mol,
            'temperature': pyunits.K
        })
Ejemplo n.º 3
0
class Iapws95ParameterBlockData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare(
        "phase_presentation",
        ConfigValue(
            default=PhaseType.MIX,
            domain=In(PhaseType),
            description="Set the way phases are presented to models",
            doc="""Set the way phases are presented to models. The MIX option
appears to the framework to be a mixed phase containing liquid and/or vapor.
The mixed option can simplify calculations at the unit model level since it can
be treated as a single phase, but unit models such as flash vessels will not be
able to treate the phases indepedently. The LG option presents as two sperate
phases to the framework. The L or G options can be used if it is known for sure
that only one phase is present.
**default** - PhaseType.MIX
**Valid values:** {
**PhaseType.MIX** - Present a mixed phase with liquid and/or vapor,
**PhaseType.LG** - Present a liquid and vapor phase,
**PhaseType.L** - Assume only liquid can be present,
**PhaseType.G** - Assume only vapor can be present}"""))

    CONFIG.declare(
        "state_vars",
        ConfigValue(
            default=StateVars.PH,
            domain=In(StateVars),
            description="State variable set",
            doc=
            """The set of state variables to use. Depending on the use, one state
variable set or another may be better computationally. Usually pressure and
enthalpy are the best choice because they are well behaved during a phase change.
**default** - StateVars.PH
**Valid values:** {
**StateVars.PH** - Pressure-Enthalpy,
**StateVars.TPX** - Temperature-Pressure-Quality}"""))

    def build(self):
        super(Iapws95ParameterBlockData, self).build()
        self.state_block_class = Iapws95StateBlock
        # Location of the *.so or *.dll file for external functions
        self.plib = _so
        self.available = os.path.isfile(self.plib)
        # Phase list
        self.private_phase_list = Set(initialize=["Vap", "Liq"])
        if self.config.phase_presentation == PhaseType.MIX:
            self.phase_list = Set(initialize=["Mix"])
        elif self.config.phase_presentation == PhaseType.LG:
            self.phase_list = Set(initialize=["Vap", "Liq"])
        elif self.config.phase_presentation == PhaseType.L:
            self.phase_list = Set(initialize=["Liq"])
        elif self.config.phase_presentation == PhaseType.G:
            self.phase_list = Set(initialize=["Vap"])
        # State var set
        self.state_vars = self.config.state_vars

        # Component list - a list of component identifiers
        self.component_list = Set(initialize=['H2O'])

        # List of phase equilibrium
        self.phase_equilibrium_idx = Set(initialize=[1])
        self.phase_equilibrium_list = {1: ["H2O", ("Vap", "Liq")]}

        # Parameters, these should match what's in the C code
        self.temperature_crit = Param(initialize=647.096,
                                      doc='Critical temperature [K]')
        self.pressure_crit = Param(initialize=2.2064e7,
                                   doc='Critical pressure [Pa]')
        self.dens_mass_crit = Param(initialize=322,
                                    doc='Critical density [kg/m3]')
        self.gas_const = Param(initialize=8.3144598,
                               doc='Gas Constant [J/mol/K]')
        self.mw = Param(initialize=0.01801528, doc='Molecular weight [kg/mol]')
        #Thermal conductivity parameters.
        # "Release on the IAPWS Formulation 2011 for the Thermal Conductivity of
        # Ordinary Water Substance"
        self.tc_L0 = Param(RangeSet(0, 5),
                           initialize={
                               0: 2.443221e-3,
                               1: 1.323095e-2,
                               2: 6.770357e-3,
                               3: -3.454586e-3,
                               4: 4.096266e-4
                           },
                           doc="0th order themalcondutivity paramters")

        self.tc_L1 = Param(RangeSet(0, 5),
                           RangeSet(0, 6),
                           initialize={
                               (0, 0): 1.60397357,
                               (1, 0): 2.33771842,
                               (2, 0): 2.19650529,
                               (3, 0): -1.21051378,
                               (4, 0): -2.7203370,
                               (0, 1): -0.646013523,
                               (1, 1): -2.78843778,
                               (2, 1): -4.54580785,
                               (3, 1): 1.60812989,
                               (4, 1): 4.57586331,
                               (0, 2): 0.111443906,
                               (1, 2): 1.53616167,
                               (2, 2): 3.55777244,
                               (3, 2): -0.621178141,
                               (4, 2): -3.18369245,
                               (0, 3): 0.102997357,
                               (1, 3): -0.463045512,
                               (2, 3): -1.40944978,
                               (3, 3): 0.0716373224,
                               (4, 3): 1.1168348,
                               (0, 4): -0.0504123634,
                               (1, 4): 0.0832827019,
                               (2, 4): 0.275418278,
                               (3, 4): 0.0,
                               (4, 4): -0.19268305,
                               (0, 5): 0.00609859258,
                               (1, 5): -0.00719201245,
                               (2, 5): -0.0205938816,
                               (3, 5): 0.0,
                               (4, 5): 0.012913842
                           },
                           doc="1st order themalcondutivity paramters")
        #Viscosity paramters
        #"Release on the IAPWS Formulation 2008 for the Viscosity of
        # Ordinary Water Substance "
        self.visc_H0 = Param(RangeSet(0, 4),
                             initialize={
                                 0: 1.67752,
                                 1: 2.20462,
                                 2: 0.6366564,
                                 3: -0.241605
                             },
                             doc="0th order viscosity parameters")

        self.visc_H1 = Param(RangeSet(0, 6),
                             RangeSet(0, 7),
                             initialize={
                                 (0, 0): 5.20094e-1,
                                 (1, 0): 8.50895e-2,
                                 (2, 0): -1.08374,
                                 (3, 0): -2.89555e-1,
                                 (4, 0): 0.0,
                                 (5, 0): 0.0,
                                 (0, 1): 2.22531e-1,
                                 (1, 1): 9.99115e-1,
                                 (2, 1): 1.88797,
                                 (3, 1): 1.26613,
                                 (4, 1): 0.0,
                                 (5, 1): 1.20573e-1,
                                 (0, 2): -2.81378e-1,
                                 (1, 2): -9.06851e-1,
                                 (2, 2): -7.72479e-1,
                                 (3, 2): -4.89837e-1,
                                 (4, 2): -2.57040e-1,
                                 (5, 2): 0.0,
                                 (0, 3): 1.61913e-1,
                                 (1, 3): 2.57399e-1,
                                 (2, 3): 0.0,
                                 (3, 3): 0.0,
                                 (4, 3): 0.0,
                                 (5, 3): 0.0,
                                 (0, 4): -3.25372e-2,
                                 (1, 4): 0.0,
                                 (2, 4): 0.0,
                                 (3, 4): 6.98452e-2,
                                 (4, 4): 0.0,
                                 (5, 4): 0.0,
                                 (0, 5): 0.0,
                                 (1, 5): 0.0,
                                 (2, 5): 0.0,
                                 (3, 5): 0.0,
                                 (4, 5): 8.72102e-3,
                                 (5, 5): 0.0,
                                 (0, 6): 0.0,
                                 (1, 6): 0.0,
                                 (2, 6): 0.0,
                                 (3, 6): -4.35673e-3,
                                 (4, 6): 0.0,
                                 (5, 6): -5.93264e-4
                             },
                             doc="1st order viscosity parameters")

        self.smoothing_pressure_over = Param(
            mutable=True,
            initialize=1e-4,
            doc='Smooth max parameter (pressure over)')
        self.smoothing_pressure_under = Param(
            mutable=True,
            initialize=1e-4,
            doc='Smooth max parameter (pressure under)')

    @classmethod
    def define_metadata(cls, obj):
        obj.add_properties({
            'temperature_crit': {
                'method': None,
                'units': 'K'
            },
            'pressure_crit': {
                'method': None,
                'units': 'Pa'
            },
            'dens_mass_crit': {
                'method': None,
                'units': 'kg/m^3'
            },
            'gas_const': {
                'method': None,
                'units': 'J/mol.K'
            },
            'mw': {
                'method': None,
                'units': 'kg/mol'
            },
            'temperature_sat': {
                'method': 'None',
                'units': 'K'
            },
            'flow_mol': {
                'method': None,
                'units': 'mol/s'
            },
            'flow_mass': {
                'method': None,
                'units': 'kg/s'
            },
            'temperature': {
                'method': None,
                'units': 'K'
            },
            'pressure': {
                'method': None,
                'units': 'Pa'
            },
            'vapor_frac': {
                'method': None,
                'units': None
            },
            'dens_mass_phase': {
                'method': None,
                'units': 'kg/m^3'
            },
            'temperature_red': {
                'method': None,
                'units': None
            },
            'pressure_sat': {
                'method': None,
                'units': 'kPa'
            },
            'energy_internal_mol_phase': {
                'method': None,
                'units': 'J/mol'
            },
            'enth_mol_phase': {
                'method': None,
                'units': 'J/mol'
            },
            'entr_mol_phase': {
                'method': None,
                'units': 'J/mol.K'
            },
            'cp_mol_phase': {
                'method': None,
                'units': 'J/mol.K'
            },
            'cv_mol_phase': {
                'method': None,
                'units': 'J/mol.K'
            },
            'speed_sound_phase': {
                'method': None,
                'units': 'm/s'
            },
            'dens_mol_phase': {
                'method': None,
                'units': 'mol/m^3'
            },
            'therm_cond_phase': {
                'method': None,
                'units': 'W/m.K'
            },
            'visc_d_phase': {
                'method': None,
                'units': 'Pa.s'
            },
            'visc_k_phase': {
                'method': None,
                'units': 'm^2/s'
            },
            'phase_frac': {
                'method': None,
                'units': None
            },
            'flow_mol_comp': {
                'method': None,
                'units': 'mol/s'
            },
            'energy_internal_mol': {
                'method': None,
                'units': 'J/mol'
            },
            'enth_mol': {
                'method': None,
                'units': 'J/mol'
            },
            'entr_mol': {
                'method': None,
                'units': 'J/mol.K'
            },
            'cp_mol': {
                'method': None,
                'units': 'J/mol.K'
            },
            'cv_mol': {
                'method': None,
                'units': 'J/mol.K'
            },
            'heat_capacity_ratio': {
                'method': None,
                'units': None
            },
            'dens_mass': {
                'method': None,
                'units': 'kg/m^3'
            },
            'dens_mol': {
                'method': None,
                'units': 'mol/m^3'
            },
            'dh_vap_mol': {
                'method': None,
                'units': 'J/mol'
            }
        })

        obj.add_default_units({
            'time': 's',
            'length': 'm',
            'mass': 'kg',
            'amount': 'mol',
            'temperature': 'K',
            'energy': 'J',
            'holdup': 'mol'
        })
Ejemplo n.º 4
0
class NaClParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        """
        Callable method for Block construction.
        """
        super(NaClParameterData, self).build()

        self._state_block_class = NaClStateBlock

        # components
        self.H2O = Solvent()
        self.NaCl = Solute()

        # phases
        self.Liq = LiquidPhase()

        # reference
        # this package is developed from Bartholomew & Mauter (2019) https://doi.org/10.1016/j.memsci.2018.11.067
        # the enthalpy calculations are from Sharqawy et al. (2010) http://dx.doi.org/10.5004/dwt.2010.1079

        # molecular weight
        mw_comp_data = {"H2O": 18.01528e-3, "NaCl": 58.44e-3}
        self.mw_comp = Param(
            self.component_list,
            mutable=False,
            initialize=extract_data(mw_comp_data),
            units=pyunits.kg / pyunits.mol,
            doc="Molecular weight kg/mol",
        )

        # mass density parameters, eq 4 in Bartholomew
        dens_mass_param_dict = {"0": 995, "1": 756}
        self.dens_mass_param = Var(
            dens_mass_param_dict.keys(),
            domain=Reals,
            initialize=dens_mass_param_dict,
            units=pyunits.kg / pyunits.m**3,
            doc="Mass density parameters",
        )

        # dynamic viscosity parameters, eq 5 in Bartholomew
        visc_d_param_dict = {"0": 9.80e-4, "1": 2.15e-3}
        self.visc_d_param = Var(
            visc_d_param_dict.keys(),
            domain=Reals,
            initialize=visc_d_param_dict,
            units=pyunits.Pa * pyunits.s,
            doc="Dynamic viscosity parameters",
        )

        # diffusivity parameters, eq 6 in Bartholomew
        diffus_param_dict = {
            "0": 1.51e-9,
            "1": -2.00e-9,
            "2": 3.01e-8,
            "3": -1.22e-7,
            "4": 1.53e-7,
        }
        self.diffus_param = Var(
            diffus_param_dict.keys(),
            domain=Reals,
            initialize=diffus_param_dict,
            units=pyunits.m**2 / pyunits.s,
            doc="Dynamic viscosity parameters",
        )

        # osmotic coefficient parameters, eq. 3b in Bartholomew
        osm_coeff_param_dict = {"0": 0.918, "1": 8.89e-2, "2": 4.92}
        self.osm_coeff_param = Var(
            osm_coeff_param_dict.keys(),
            domain=Reals,
            initialize=osm_coeff_param_dict,
            units=pyunits.dimensionless,
            doc="Osmotic coefficient parameters",
        )

        # TODO: update for NaCl solution, relationship from Sharqawy is for seawater
        # specific enthalpy parameters, eq. 55 and 43 in Sharqawy (2010)
        self.enth_mass_param_A1 = Var(
            within=Reals,
            initialize=124.790,
            units=pyunits.J / pyunits.kg,
            doc="Specific enthalpy parameter A1",
        )
        self.enth_mass_param_A2 = Var(
            within=Reals,
            initialize=4203.075,
            units=(pyunits.J / pyunits.kg) * pyunits.K**-1,
            doc="Specific enthalpy parameter A2",
        )
        self.enth_mass_param_A3 = Var(
            within=Reals,
            initialize=-0.552,
            units=(pyunits.J / pyunits.kg) * pyunits.K**-2,
            doc="Specific enthalpy parameter A3",
        )
        self.enth_mass_param_A4 = Var(
            within=Reals,
            initialize=0.004,
            units=(pyunits.J / pyunits.kg) * pyunits.K**-3,
            doc="Specific enthalpy parameter A4",
        )
        self.enth_mass_param_B1 = Var(
            within=Reals,
            initialize=27062.623,
            units=pyunits.dimensionless,
            doc="Specific enthalpy parameter B1",
        )
        self.enth_mass_param_B2 = Var(
            within=Reals,
            initialize=4835.675,
            units=pyunits.dimensionless,
            doc="Specific enthalpy parameter B2",
        )

        # traditional parameters are the only Vars currently on the block and should be fixed
        for v in self.component_objects(Var):
            v.fix()

        # ---default scaling---
        self.set_default_scaling("temperature", 1e-2)
        self.set_default_scaling("pressure", 1e-6)
        self.set_default_scaling("dens_mass_phase", 1e-3, index="Liq")
        self.set_default_scaling("visc_d_phase", 1e3, index="Liq")
        self.set_default_scaling("diffus_phase", 1e9, index="Liq")
        self.set_default_scaling("osm_coeff", 1e0)
        self.set_default_scaling("enth_mass_phase", 1e-4, index="Liq")

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties(
            {
                "flow_mass_phase_comp": {"method": None},
                "temperature": {"method": None},
                "pressure": {"method": None},
                "mass_frac_phase_comp": {"method": "_mass_frac_phase_comp"},
                "dens_mass_phase": {"method": "_dens_mass_phase"},
                "flow_vol_phase": {"method": "_flow_vol_phase"},
                "flow_vol": {"method": "_flow_vol"},
                "conc_mass_phase_comp": {"method": "_conc_mass_phase_comp"},
                "flow_mol_phase_comp": {"method": "_flow_mol_phase_comp"},
                "mole_frac_phase_comp": {"method": "_mole_frac_phase_comp"},
                "molality_comp": {"method": "_molality_comp"},
                "diffus_phase": {"method": "_diffus_phase"},
                "visc_d_phase": {"method": "_visc_d_phase"},
                "osm_coeff": {"method": "_osm_coeff"},
                "pressure_osm": {"method": "_pressure_osm"},
                "enth_mass_phase": {"method": "_enth_mass_phase"},
                "enth_flow": {"method": "_enth_flow"},
            }
        )

        obj.add_default_units(
            {
                "time": pyunits.s,
                "length": pyunits.m,
                "mass": pyunits.kg,
                "amount": pyunits.mol,
                "temperature": pyunits.K,
            }
        )
Ejemplo n.º 5
0
class PhysicalParameterData(PhysicalParameterBlock):
    """
    Property Parameter Block Class.
    """

    # Config block for the _IdealStateBlock
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare("valid_phase", ConfigValue(
        default=('Vap', 'Liq'),
        domain=In(['Liq', 'Vap', ('Vap', 'Liq'), ('Liq', 'Vap')]),
        description="Flag indicating the valid phase",
        doc="""Flag indicating the valid phase for a given set of
    conditions, and thus corresponding constraints  should be included,
    **default** - ('Vap', 'Liq').
    **Valid values:** {
    **'Liq'** - Liquid only,
    **'Vap'** - Vapor only,
    **('Vap', 'Liq')** - Vapor-liquid equilibrium,
    **('Liq', 'Vap')** - Vapor-liquid equilibrium,}"""))

    CONFIG.declare("Cp", ConfigValue(
        default=0.035,
        domain=float,
        description="Constant pressure heat capacity in MJ/(kmol K)",
        doc="""Value for the constant pressure heat capacity,
        **default** = 0.035 MJ/(kmol K)"""))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(PhysicalParameterData, self).build()

        self._state_block_class = IdealStateBlock

        # List of valid phases and components in property package

        if self.config.valid_phase == ('Liq', 'Vap') or \
                self.config.valid_phase == ('Vap', 'Liq'):
            self.Liq = LiquidPhase()
            self.Vap = VaporPhase()
        elif self.config.valid_phase == 'Liq':
            self.Liq = LiquidPhase()
        else:
            self.Vap = VaporPhase()

        self.CH4 = Component()
        self.CO = Component()
        self.H2 = Component()
        self.CH3OH = Component()

        self.phase_equilibrium_idx = Set(initialize=[1, 2, 3, 4])

        self.phase_equilibrium_list = \
            {1: ["CH4", ("Vap", "Liq")],
             2: ["CO", ("Vap", "Liq")],
             3: ["H2", ("Vap", "Liq")],
             4: ["CH3OH", ("Vap", "Liq")]}

        # Antoine coefficients assume pressure in mmHG and temperature in K
        self.vapor_pressure_coeff = {('CH4', 'A'): 15.2243,
                                     ('CH4', 'B'): 897.84,
                                     ('CH4', 'C'): -7.16,
                                     ('CO', 'A'): 14.3686,
                                     ('CO', 'B'): 530.22,
                                     ('CO', 'C'): -13.15,
                                     ('H2', 'A'): 13.6333,
                                     ('H2', 'B'): 164.9,
                                     ('H2', 'C'): 3.19,
                                     ('CH3OH', 'A'): 18.5875,
                                     ('CH3OH', 'B'): 3626.55,
                                     ('CH3OH', 'C'): -34.29}

        Cp = self.config.Cp
        Cv = value(Cp - pyunits.convert(Constants.gas_constant,
                                        pyunits.MJ/pyunits.kmol/pyunits.K))
        gamma = Cp / Cv

        self.gamma = Param(within=NonNegativeReals,
                           mutable=True,
                           default=gamma,
                           doc='Ratio of Cp to Cv')

        self.Cp = Param(within=NonNegativeReals,
                        mutable=True,
                        default=Cp,
                        units=pyunits.MJ/pyunits.kmol/pyunits.K,
                        doc='Constant pressure heat capacity')

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties(
            {'flow_mol': {'method': None},
             'mole_frac': {'method': None},
             'temperature': {'method': None},
             'pressure': {'method': None},
             'flow_mol_phase': {'method': None},
             'density_mol': {'method': '_density_mol'},
             'vapor_pressure': {'method': '_vapor_pressure'},
             'mole_frac_phase': {'method': '_mole_frac_phase'},
             'enthalpy_comp_liq': {'method': '_enthalpy_comp_liq'},
             'enthalpy_comp_vap': {'method': '_enthalpy_comp_vap'},
             'enthalpy_liq': {'method': '_enthalpy_liq'},
             'enthalpy_vap': {'method': '_enthalpy_vap'}})

        obj.add_default_units({'time': pyunits.s,
                               'length': pyunits.m,
                               'mass': pyunits.Gg,  # yields base units MJ, MPa
                               'amount': pyunits.kmol,
                               'temperature': pyunits.hK})
Ejemplo n.º 6
0
class MethaneParameterData(ActivityCoeffParameterData):
    # Methane combstion only considers and ideal vapor phase, so need to
    # overload the user-selection of activity coefficient model and valid
    # phases. Do this by creating our own Config block with limited choices.
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare(
        "activity_coeff_model",
        ConfigValue(default="Ideal",
                    domain=In(["Ideal"]),
                    description="Methane combustion supports ideal gas only"))

    CONFIG.declare(
        "state_vars",
        ConfigValue(
            default="FTPz",
            domain=In(["FTPz", "FcTP"]),
            description="Flag indicating the choice for state variables",
            doc="""Flag indicating the choice for state variables to be used
    for the state block, and thus corresponding constraints  should be
    included,
    **default** - FTPz
    **Valid values:** {
    **"FTPx"** - Total flow, Temperature, Pressure and Mole fraction,
    **"FcTP"** - Component flow, Temperature and Pressure}"""))

    CONFIG.declare(
        "valid_phase",
        ConfigValue(default="Vap",
                    domain=In(["Vap"]),
                    description="Methane combustion supports ideal gas only"))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(MethaneParameterData, self).build()

        # Component list - a list of component identifiers
        self.H2 = Component()
        self.N2 = Component()
        self.O2 = Component()
        self.CH4 = Component()
        self.CO = Component()
        self.CO2 = Component()
        self.H2O = Component()
        self.NH3 = Component()

        # List of all chemical elements that constitute the chemical species
        self.element_list = Set(initialize=['H', 'N', 'O', 'C'])

        # Elemental composition of all species
        self.element_comp = {
            'H2': {
                'H': 2,
                'N': 0,
                'O': 0,
                'C': 0
            },
            'N2': {
                'H': 0,
                'N': 2,
                'O': 0,
                'C': 0
            },
            'O2': {
                'H': 0,
                'N': 0,
                'O': 2,
                'C': 0
            },
            'CH4': {
                'H': 4,
                'N': 0,
                'O': 0,
                'C': 1
            },
            'CO': {
                'H': 0,
                'N': 0,
                'O': 1,
                'C': 1
            },
            'CO2': {
                'H': 0,
                'N': 0,
                'O': 2,
                'C': 1
            },
            'H2O': {
                'H': 2,
                'N': 0,
                'O': 1,
                'C': 0
            },
            'NH3': {
                'H': 3,
                'N': 1,
                'O': 0,
                'C': 0
            }
        }

        # Thermodynamic reference state
        self.pressure_reference = Param(mutable=True,
                                        default=101325,
                                        doc='Reference pressure [Pa]',
                                        units=pyunits.Pa)
        self.temperature_reference = Param(mutable=True,
                                           default=1500,
                                           doc='Reference temperature [K]',
                                           units=pyunits.K)

        # Constants for specific heat capacity, enthalpy
        # Sources: The Properties of Gases and Liquids (1987)
        #         4th edition, Chemical Engineering Series - Robert C. Reid
        Cp_Vap_A_data = {
            ('CH4'): 1.925e1,
            ('CO'): 3.087e1,
            ('CO2'): 1.980e1,
            ('H2'): 2.714e1,
            ('H2O'): 3.224e1,
            ('N2'): 3.115e1,
            ('NH3'): 2.731e1,
            ('O2'): 2.811e1
        }
        Cp_Vap_B_data = {
            ('CH4'): 5.213e-2,
            ('CO'): -1.285e-2,
            ('CO2'): 7.344e-2,
            ('H2'): 9.274e-3,
            ('H2O'): 1.924e-3,
            ('N2'): -1.357e-2,
            ('NH3'): 2.383e-2,
            ('O2'): -3.680e-6
        }
        Cp_Vap_C_data = {
            ('CH4'): 1.197e-5,
            ('CO'): 2.789e-5,
            ('CO2'): -5.602e-5,
            ('H2'): -1.381e-5,
            ('H2O'): 1.055e-5,
            ('N2'): 2.680e-5,
            ('NH3'): 1.707e-5,
            ('O2'): 1.746e-5
        }
        Cp_Vap_D_data = {
            ('CH4'): -1.132e-8,
            ('CO'): -1.272e-8,
            ('CO2'): 1.715e-8,
            ('H2'): 7.645e-9,
            ('H2O'): -3.596e-9,
            ('N2'): -1.168e-8,
            ('NH3'): -1.185e-8,
            ('O2'): -1.065e-8
        }
        Cp_Vap_E_data = {
            ('CH4'): 0,
            ('CO'): 0,
            ('CO2'): 0,
            ('H2'): 0,
            ('H2O'): 0,
            ('N2'): 0,
            ('NH3'): 0,
            ('O2'): 0
        }

        self.cp_mol_vap_comp_coeff_A = Param(
            self.component_list,
            units=pyunits.J / pyunits.mol / pyunits.K,
            doc="Vapor phase Cp parameter A",
            initialize=extract_data(Cp_Vap_A_data))

        self.cp_mol_vap_comp_coeff_B = Param(
            self.component_list,
            units=pyunits.J / pyunits.mol / pyunits.K**2,
            doc="Vapor phase Cp parameter B",
            initialize=extract_data(Cp_Vap_B_data))

        self.cp_mol_vap_comp_coeff_C = Param(
            self.component_list,
            units=pyunits.J / pyunits.mol / pyunits.K**3,
            doc="Vapor phase Cp parameter C",
            initialize=extract_data(Cp_Vap_C_data))

        self.cp_mol_vap_comp_coeff_D = Param(
            self.component_list,
            units=pyunits.J / pyunits.mol / pyunits.K**4,
            doc="Vapor phase Cp parameter D",
            initialize=extract_data(Cp_Vap_D_data))

        self.cp_mol_vap_comp_coeff_E = Param(
            self.component_list,
            units=pyunits.J / pyunits.mol / pyunits.K**5,
            doc="Vapor phase Cp parameter E",
            initialize=extract_data(Cp_Vap_E_data))

        # Source: NIST Webbook, 9th October 2019
        dh_form = {
            ("Vap", "CH4"): -74600,
            ("Vap", "CO"): -110530,
            ("Vap", "CO2"): -393520,
            ("Vap", "H2"): 0,
            ("Vap", "H2O"): -241830,
            ("Vap", "N2"): 0,
            ("Vap", "NH3"): -45900,
            ("Vap", "O2"): 0
        }

        self.dh_form = Param(self.phase_list,
                             self.component_list,
                             mutable=False,
                             initialize=extract_data(dh_form),
                             doc="Heats of formation (J/mol)",
                             units=pyunits.J / pyunits.mol)

        # Source: NIST Webbook, 9th October 2019
        ds_form = {
            ("Vap", "CH4"): 186.25,
            ("Vap", "CO"): 197.66,
            ("Vap", "CO2"): 213.79,
            ("Vap", "H2"): 130.68,
            ("Vap", "H2O"): 188.84,
            ("Vap", "N2"): 191.61,
            ("Vap", "NH3"): 192.77,
            ("Vap", "O2"): 205.15
        }

        self.ds_form = Param(self.phase_list,
                             self.component_list,
                             mutable=False,
                             initialize=extract_data(ds_form),
                             doc="Entropies of formation (J/mol.K)",
                             units=pyunits.J / pyunits.mol / pyunits.K)
Ejemplo n.º 7
0
class FlueGasParameterData(PhysicalParameterBlock):
    """
    Property Parameter Block Class

    Contains parameters and indexing sets associated with properties for flue
    gas. The ideal gas assumption is applied.

    """

    CONFIG = PhysicalParameterBlock.CONFIG()
    CONFIG.declare(
        "components",
        ConfigValue(
            default=["N2", "O2", "NO", "CO2", "H2O", "SO2"],
            domain=list,
            description="Components to include",
        ),
    )

    def build(self):
        """Add contents to the block."""
        super().build()
        self._state_block_class = FlueGasStateBlock
        _valid_comps = ["N2", "O2", "NO", "CO2", "H2O", "SO2"]

        for j in self.config.components:
            if j not in _valid_comps:
                raise ConfigurationError(f"Component '{j}' is not supported")
            self.add_component(j, Component())

        # Create Phase object
        self.Vap = VaporPhase()

        # Molecular weight
        self.mw_comp = Param(
            self.component_list,
            initialize={
                k: v
                for k, v in {
                    "O2": 0.0319988,
                    "N2": 0.0280134,
                    "NO": 0.0300061,
                    "CO2": 0.0440095,
                    "H2O": 0.0180153,
                    "SO2": 0.064064,
                }.items() if k in self.component_list
            },
            doc="Molecular Weight [kg/mol]",
            units=pyunits.kg / pyunits.mol,
        )

        # Thermodynamic reference state
        self.pressure_ref = Param(
            within=PositiveReals,
            default=1.01325e5,
            doc="Reference pressure [Pa]",
            units=pyunits.Pa,
        )

        self.temperature_ref = Param(
            within=PositiveReals,
            default=298.15,
            doc="Reference temperature [K]",
            units=pyunits.K,
        )

        # Critical Properties
        self.pressure_crit = Param(
            self.component_list,
            within=PositiveReals,
            initialize={
                k: v
                for k, v in {
                    "O2": 50.45985e5,
                    "N2": 33.943875e5,
                    "NO": 64.85e5,
                    "CO2": 73.8e5,
                    "H2O": 220.64e5,
                    "SO2": 7.883e6,
                }.items() if k in self.component_list
            },
            doc="Critical pressure [Pa]",
            units=pyunits.Pa,
        )

        self.temperature_crit = Param(
            self.component_list,
            within=PositiveReals,
            initialize={
                k: v
                for k, v in {
                    "O2": 154.58,
                    "N2": 126.19,
                    "NO": 180.0,
                    "CO2": 304.18,
                    "H2O": 647,
                    "SO2": 430.8,
                }.items() if k in self.component_list
            },
            doc="Critical temperature [K]",
            units=pyunits.K,
        )

        # Constants for specific heat capacity, enthalpy, and entropy
        # calculations for ideal gas (from NIST 01/08/2020
        # https://webbook.nist.gov/cgi/cbook.cgi?ID=C7727379&Units=SI&Mask=1#Thermo-Gas)
        cp_mol_ig_comp_coeff_parameter_A = {
            k: v
            for k, v in {
                "N2": 19.50583,
                "O2": 30.03235,
                "CO2": 24.99735,
                "H2O": 30.092,
                "NO": 23.83491,
                "SO2": 21.43049,
            }.items() if k in self.component_list
        }
        cp_mol_ig_comp_coeff_parameter_B = {
            k: v
            for k, v in {
                "N2": 19.88705,
                "O2": 8.772972,
                "CO2": 55.18696,
                "H2O": 6.832514,
                "NO": 12.58878,
                "SO2": 74.35094,
            }.items() if k in self.component_list
        }
        cp_mol_ig_comp_coeff_parameter_C = {
            k: v
            for k, v in {
                "N2": -8.598535,
                "O2": -3.98813,
                "CO2": -33.69137,
                "H2O": 6.793435,
                "NO": -1.139011,
                "SO2": -57.75217,
            }.items() if k in self.component_list
        }
        cp_mol_ig_comp_coeff_parameter_D = {
            k: v
            for k, v in {
                "N2": 1.369784,
                "O2": 0.788313,
                "CO2": 7.948387,
                "H2O": -2.53448,
                "NO": -1.497459,
                "SO2": 16.35534,
            }.items() if k in self.component_list
        }
        cp_mol_ig_comp_coeff_parameter_E = {
            k: v
            for k, v in {
                "N2": 0.527601,
                "O2": -0.7416,
                "CO2": -0.136638,
                "H2O": 0.082139,
                "NO": 0.214194,
                "SO2": 0.086731,
            }.items() if k in self.component_list
        }
        cp_mol_ig_comp_coeff_parameter_F = {
            k: v
            for k, v in {
                "N2": -4.935202,
                "O2": -11.3247,
                "CO2": -403.6075,
                "H2O": -250.881,
                "NO": 83.35783,
                "SO2": -305.7688,
            }.items() if k in self.component_list
        }
        cp_mol_ig_comp_coeff_parameter_G = {
            k: v
            for k, v in {
                "N2": 212.39,
                "O2": 236.1663,
                "CO2": 228.2431,
                "H2O": 223.3967,
                "NO": 237.1219,
                "SO2": 254.8872,
            }.items() if k in self.component_list
        }
        cp_mol_ig_comp_coeff_parameter_H = {
            k: v
            for k, v in {
                "N2": 0,
                "O2": 0,
                "CO2": -393.5224,
                "H2O": -241.8264,
                "NO": 90.29114,
                "SO2": -296.8422,
            }.items() if k in self.component_list
        }

        self.cp_mol_ig_comp_coeff_A = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_A,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.J / pyunits.mol / pyunits.K,
        )
        self.cp_mol_ig_comp_coeff_B = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_B,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.J / pyunits.mol / pyunits.K / pyunits.kK,
        )
        self.cp_mol_ig_comp_coeff_C = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_C,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.J / pyunits.mol / pyunits.K / pyunits.kK**2,
        )
        self.cp_mol_ig_comp_coeff_D = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_D,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.J / pyunits.mol / pyunits.K / pyunits.kK**3,
        )
        self.cp_mol_ig_comp_coeff_E = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_E,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.J / pyunits.mol / pyunits.K * pyunits.kK**2,
        )
        self.cp_mol_ig_comp_coeff_F = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_F,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.kJ / pyunits.mol,
        )
        self.cp_mol_ig_comp_coeff_G = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_G,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.J / pyunits.mol / pyunits.K,
        )
        self.cp_mol_ig_comp_coeff_H = Param(
            self.component_list,
            initialize=cp_mol_ig_comp_coeff_parameter_H,
            doc="Constants for spec. heat capacity for ideal gas",
            units=pyunits.kJ / pyunits.mol,
        )

        # Viscosity and thermal conductivity parameters
        self.ce_param = Param(
            initialize=2.6693e-5,
            units=(pyunits.g**0.5 * pyunits.mol**0.5 * pyunits.angstrom**2 *
                   pyunits.K**-0.5 * pyunits.cm**-1 * pyunits.s**-1),
            doc="Parameter for the Chapman-Enskog viscosity correlation",
        )

        self.sigma = Param(
            self.component_list,
            initialize={
                k: v
                for k, v in {
                    "O2": 3.458,
                    "N2": 3.621,
                    "NO": 3.47,
                    "CO2": 3.763,
                    "H2O": 2.605,
                    "SO2": 4.29,
                }.items() if k in self.component_list
            },
            doc="collision diameter",
            units=pyunits.angstrom,
        )
        self.ep_Kappa = Param(
            self.component_list,
            initialize={
                k: v
                for k, v in {
                    "O2": 107.4,
                    "N2": 97.53,
                    "NO": 119.0,
                    "CO2": 244.0,
                    "H2O": 572.4,
                    "SO2": 252.0,
                }.items() if k in self.component_list
            },
            doc=
            "Boltzmann constant divided by characteristic Lennard-Jones energy",
            units=pyunits.K,
        )

        self.set_default_scaling("flow_mol", 1e-4)
        self.set_default_scaling("flow_mass", 1e-3)
        self.set_default_scaling("flow_vol", 1e-3)
        # anything not explicitly listed
        self.set_default_scaling("mole_frac_comp", 1)
        self.set_default_scaling("mole_frac_comp", 1e3, index="NO")
        self.set_default_scaling("mole_frac_comp", 1e3, index="SO2")
        self.set_default_scaling("mole_frac_comp", 1e2, index="H2O")
        self.set_default_scaling("mole_frac_comp", 1e2, index="CO2")
        self.set_default_scaling("flow_vol", 1)

        # For flow_mol_comp, will calculate from flow_mol and mole_frac_comp
        # user should set a scale for both, and for each compoent of
        # mole_frac_comp
        self.set_default_scaling("pressure", 1e-5)
        self.set_default_scaling("temperature", 1e-1)
        self.set_default_scaling("pressure_red", 1e-3)
        self.set_default_scaling("temperature_red", 1)
        self.set_default_scaling("enth_mol_phase", 1e-3)
        self.set_default_scaling("enth_mol", 1e-3)
        self.set_default_scaling("entr_mol", 1e-2)
        self.set_default_scaling("entr_mol_phase", 1e-2)
        self.set_default_scaling("cp_mol", 0.1)
        self.set_default_scaling("cp_mol_phase", 0.1)
        self.set_default_scaling("compress_fact", 1)
        self.set_default_scaling("dens_mol_phase", 1)
        self.set_default_scaling("pressure_sat", 1e-4)
        self.set_default_scaling("visc_d_comp", 1e4)
        self.set_default_scaling("therm_cond_comp", 1e2)
        self.set_default_scaling("visc_d", 1e4)
        self.set_default_scaling("therm_cond", 1e2)
        self.set_default_scaling("mw", 1)
        self.set_default_scaling("mw_comp", 1)

    @classmethod
    def define_metadata(cls, obj):
        obj.add_properties({
            "flow_mol_comp": {
                "method": None,
                "units": "mol/s"
            },
            "pressure": {
                "method": None,
                "units": "Pa"
            },
            "temperature": {
                "method": None,
                "units": "K"
            },
            "pressure_crit": {
                "method": None,
                "units": "Pa"
            },
            "temperature_crit": {
                "method": None,
                "units": "K"
            },
            "pressure_red": {
                "method": None,
                "units": None
            },
            "temperature_red": {
                "method": None,
                "units": None
            },
            "enth_mol_phase": {
                "method": "_enthalpy_calc",
                "units": "J/mol"
            },
            "entr_mol_phase": {
                "method": "_entropy_calc",
                "units": "J/mol/K"
            },
            "enth_mol": {
                "method": "_enthalpy_calc",
                "units": "J/mol"
            },
            "entr_mol": {
                "method": "_entropy_calc",
                "units": "J/mol.K"
            },
            "cp_mol": {
                "method": "_heat_cap_calc",
                "units": "J/mol.K"
            },
            "cp_mol_phase": {
                "method": "_heat_cap_calc",
                "units": "J/mol/K"
            },
            "compress_fact": {
                "method": "_compress_fact",
                "units": None
            },
            "dens_mol_phase": {
                "method": "_dens_mol_phase",
                "units": "mol/m^3"
            },
            "pressure_sat": {
                "method": "_vapor_pressure",
                "units": "Pa"
            },
            "flow_vol": {
                "method": "_flow_volume",
                "units": "m^3/s"
            },
            "visc_d": {
                "method": "_therm_cond",
                "units": "kg/m-s"
            },
            "therm_cond": {
                "method": "_therm_cond",
                "units": "W/m-K"
            },
            "mw_comp": {
                "method": None,
                "units": "kg/mol"
            },
            "mw": {
                "method": None,
                "units": "kg/mol"
            },
        })

        obj.add_default_units({
            "time": pyunits.s,
            "length": pyunits.m,
            "mass": pyunits.kg,
            "amount": pyunits.mol,
            "temperature": pyunits.K,
        })
Ejemplo n.º 8
0
class HDAParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def _get_param(self, name: str):
        """Helper method to convert data stored in a DMF resource into a Pyomo rule.

        The intermediate form, :class:`TidyUnitData`, is constructed from the data
        stored in the JSON of the DMF resource.

        Args:
            name: Primary alias of DMF resource with stored data.

        Returns:
            function for `initialize` keyword of `Param` class constructor.

        Raises:
            KeyError: Resource not found
            ValueError: Data in resource is missing or malformed

        Side-effects:
            For future reference, the resource itself is stored in an instance dict
            called `self._property_data` where the keys are the parameter names and
            the values are instances of :class:`idaes.dmf.resource.Resource`.
        """
        r = _dmf.find_one(name=name)
        if not hasattr(r, "data"):
            raise KeyError(f"No resource named {name} was found")
        try:
            dframe = TidyUnitData(r.data)
        except ValueError as err:
            raise ValueError(f"While extracting data for {name}: {err}")
        self._property_resources[name] = r
        return extract_data(dframe.param_data)

    def get_property_resource(self, name: str) -> Resource:
        return self._property_resources[name]

    def build(self):
        """
        Callable method for Block construction.
        """
        super(HDAParameterData, self).build()

        self._property_resources = {
        }  # see _get_param(), get_property_resource()

        self.state_block_class = IdealStateBlock

        self.component_list = Set(
            initialize=["benzene", "toluene", "hydrogen", "methane"])

        self.phase_list = Set(initialize=["Liq", "Vap"], ordered=True)

        # List of components in each phase (optional)
        self.phase_comp = {
            "Liq": self.component_list,
            "Vap": self.component_list
        }

        # List of phase equilibrium index
        self.phase_equilibrium_idx = Set(initialize=[1, 2, 3, 4, 5])

        self.phase_equilibrium_list = {
            1: ["benzene", ("Vap", "Liq")],
            2: ["toluene", ("Vap", "Liq")],
            3: ["hydrogen", ("Vap", "Liq")],
            4: ["methane", ("Vap", "Liq")],
            5: ["diphenyl", ("Vap", "Liq")],
        }

        # Thermodynamic reference state
        self.pressure_ref = Param(mutable=True,
                                  default=101325,
                                  doc="Reference pressure [Pa]")
        self.temperature_ref = Param(mutable=True,
                                     default=298.15,
                                     doc="Reference temperature [K]")

        self.pressure_crit = Param(
            self.component_list,
            within=NonNegativeReals,
            mutable=False,
            initialize=self._get_param("pressure_crit"),
            doc="Critical pressure [Pa]",
        )

        self.temperature_crit = Param(
            self.component_list,
            within=NonNegativeReals,
            mutable=False,
            initialize=self._get_param("temperature_crit"),
            doc="Critical temperature [K]",
        )

        # Gas Constant
        self.gas_const = Param(
            within=NonNegativeReals,
            mutable=False,
            default=8.314,
            doc="Gas Constant [J/mol.K]",
        )

        self.mw_comp = Param(
            self.component_list,
            mutable=False,
            initialize=self._get_param("mw"),
            doc="molecular weight Kg/mol",
        )

        self.dens_liq_params = Param(
            self.component_list,
            ["1", "2", "3", "4"],
            mutable=False,
            initialize=self._get_param("cp_liq"),
            doc="Parameters to compute liquid densities",
        )

        self.temperature_boil = Param(
            self.component_list,
            mutable=False,
            initialize=self._get_param("bp"),
            doc="Pure component boiling points at standard pressure [K]",
        )

        self.cp_ig = Param(
            self.phase_list,
            self.component_list,
            ["1", "2", "3", "4", "5"],
            mutable=False,
            initialize=self._get_param("cp_ig"),
            doc="parameters to compute Cp_comp",
        )

        self.pressure_sat_coeff = Param(
            self.component_list,
            ["A", "B", "C"],
            mutable=False,
            initialize=self._get_param("pressure_sat_coeff"),
            doc="parameters to compute Cp_comp",
        )

        self.dh_vap = Param(
            self.component_list,
            mutable=False,
            initialize=self._get_param("dh_vap"),
            doc="heat of vaporization",
        )

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            "flow_mol": {
                "method": None,
                "units": "mol/s"
            },
            "flow_mol_phase_comp": {
                "method": None,
                "units": "mol/s"
            },
            "mole_frac": {
                "method": None,
                "units": "none"
            },
            "temperature": {
                "method": None,
                "units": "K"
            },
            "pressure": {
                "method": None,
                "units": "Pa"
            },
            "flow_mol_phase": {
                "method": None,
                "units": "mol/s"
            },
            "dens_mol_phase": {
                "method": "_dens_mol_phase",
                "units": "mol/m^3"
            },
            "pressure_sat": {
                "method": "_pressure_sat",
                "units": "Pa"
            },
            "mole_frac_phase": {
                "method": "_mole_frac_phase",
                "units": "no unit"
            },
            "enth_mol_phase_comp": {
                "method": "_enth_mol_phase_comp",
                "units": "J/mol",
            },
            "enth_mol_phase": {
                "method": "_enth_mol_phase",
                "units": "J/mol"
            },
            "entr_mol_phase_comp": {
                "method": "_entr_mol_phase_comp",
                "units": "J/mol",
            },
            "entr_mol_phase": {
                "method": "_entr_mol_phase",
                "units": "J/mol"
            },
            "temperature_bubble": {
                "method": "_temperature_bubble",
                "units": "K"
            },
            "temperature_dew": {
                "method": "_temperature_dew",
                "units": "K"
            },
            "pressure_bubble": {
                "method": "_pressure_bubble",
                "units": "Pa"
            },
            "pressure_dew": {
                "method": "_pressure_dew",
                "units": "Pa"
            },
            "fug_vap": {
                "method": "_fug_vap",
                "units": "Pa"
            },
            "fug_liq": {
                "method": "_fug_liq",
                "units": "Pa"
            },
            "dh_vap": {
                "method": "_dh_vap",
                "units": "J/mol"
            },
            "ds_vap": {
                "method": "_ds_vap",
                "units": "J/mol.K"
            },
        })

        obj.add_default_units({
            "time": "s",
            "length": "m",
            "mass": "g",
            "amount": "mol",
            "temperature": "K",
            "energy": "J",
            "holdup": "mol",
        })
Ejemplo n.º 9
0
class WaterParameterData(PhysicalParameterBlock):
    """Parameter block for a water property package."""

    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        """
        Callable method for Block construction.
        """
        super(WaterParameterData, self).build()

        self._state_block_class = WaterStateBlock

        # components
        self.H2O = Component()

        # phases
        self.Liq = LiquidPhase()
        self.Vap = VaporPhase()
        """ References
        This package was developed from the following references:

        - K.G.Nayar, M.H.Sharqawy, L.D.Banchik, and J.H.Lienhard V, "Thermophysical properties of seawater: A review and
        new correlations that include pressure dependence,"Desalination, Vol.390, pp.1 - 24, 2016.
        doi: 10.1016/j.desal.2016.02.024(preprint)

        - Mostafa H.Sharqawy, John H.Lienhard V, and Syed M.Zubair, "Thermophysical properties of seawater: A review of 
        existing correlations and data,"Desalination and Water Treatment, Vol.16, pp.354 - 380, April 2010.
        (2017 corrections provided at http://web.mit.edu/seawater)
        """

        # Parameters
        # molecular weight
        self.mw_comp = Param(
            self.component_list,
            mutable=False,
            initialize=18.01528e-3,
            units=pyunits.kg / pyunits.mol,
            doc="Molecular weight",
        )

        # Liq mass density parameters, eq. 8 in Sharqawy et al. (2010)
        dens_units = pyunits.kg / pyunits.m**3
        t_inv_units = pyunits.K**-1
        s_inv_units = pyunits.kg / pyunits.g

        self.dens_mass_param_A1 = Var(
            within=Reals,
            initialize=9.999e2,
            units=dens_units,
            doc="Mass density parameter A1",
        )
        self.dens_mass_param_A2 = Var(
            within=Reals,
            initialize=2.034e-2,
            units=dens_units * t_inv_units,
            doc="Mass density parameter A2",
        )
        self.dens_mass_param_A3 = Var(
            within=Reals,
            initialize=-6.162e-3,
            units=dens_units * t_inv_units**2,
            doc="Mass density parameter A3",
        )
        self.dens_mass_param_A4 = Var(
            within=Reals,
            initialize=2.261e-5,
            units=dens_units * t_inv_units**3,
            doc="Mass density parameter A4",
        )
        self.dens_mass_param_A5 = Var(
            within=Reals,
            initialize=-4.657e-8,
            units=dens_units * t_inv_units**4,
            doc="Mass density parameter A5",
        )

        # Vap mass density parameters (approximating using ideal gas)
        self.dens_mass_param_mw = Var(
            within=Reals,
            initialize=18.01528e-3,
            units=pyunits.kg / pyunits.mol,
            doc="Mass density parameter molecular weight",
        )
        self.dens_mass_param_R = Var(
            within=Reals,
            initialize=8.31462618,
            units=pyunits.J / pyunits.mol / pyunits.K,
            doc="Mass density parameter universal gas constant",
        )

        # vapor pressure parameters,  eq. 5 and 6 in Nayar et al.(2016)
        self.pressure_sat_param_psatw_A1 = Var(
            within=Reals,
            initialize=-5.8002206e3,
            units=pyunits.K,
            doc="Vapor pressure of pure water parameter A1",
        )
        self.pressure_sat_param_psatw_A2 = Var(
            within=Reals,
            initialize=1.3914993,
            units=pyunits.dimensionless,
            doc="Vapor pressure of pure water parameter A2",
        )
        self.pressure_sat_param_psatw_A3 = Var(
            within=Reals,
            initialize=-4.8640239e-2,
            units=t_inv_units,
            doc="Vapor pressure of pure water parameter A3",
        )
        self.pressure_sat_param_psatw_A4 = Var(
            within=Reals,
            initialize=4.1764768e-5,
            units=t_inv_units**2,
            doc="Vapor pressure of pure water parameter A4",
        )
        self.pressure_sat_param_psatw_A5 = Var(
            within=Reals,
            initialize=-1.4452093e-8,
            units=t_inv_units**3,
            doc="Vapor pressure of pure water parameter A5",
        )
        self.pressure_sat_param_psatw_A6 = Var(
            within=Reals,
            initialize=6.5459673,
            units=pyunits.dimensionless,
            doc="Vapor pressure of pure water parameter A6",
        )

        # specific enthalpy parameters, eq. 55 and 43 in Sharqawy et al. (2010)
        enth_mass_units = pyunits.J / pyunits.kg

        self.enth_mass_param_A1 = Var(
            within=Reals,
            initialize=141.355,
            units=enth_mass_units,
            doc="Specific enthalpy parameter A1",
        )
        self.enth_mass_param_A2 = Var(
            within=Reals,
            initialize=4202.07,
            units=enth_mass_units * t_inv_units,
            doc="Specific enthalpy parameter A2",
        )
        self.enth_mass_param_A3 = Var(
            within=Reals,
            initialize=-0.535,
            units=enth_mass_units * t_inv_units**2,
            doc="Specific enthalpy parameter A3",
        )
        self.enth_mass_param_A4 = Var(
            within=Reals,
            initialize=0.004,
            units=enth_mass_units * t_inv_units**3,
            doc="Specific enthalpy parameter A4",
        )
        # self.enth_mass_param_B1 = Var(
        #     within=Reals, initialize=-2.348e4, units=enth_mass_units,
        #     doc='Specific enthalpy parameter B1')
        # self.enth_mass_param_B2 = Var(
        #     within=Reals, initialize=3.152e5, units=enth_mass_units,
        #     doc='Specific enthalpy parameter B2')
        # self.enth_mass_param_B3 = Var(
        #     within=Reals, initialize=2.803e6, units=enth_mass_units,
        #     doc='Specific enthalpy parameter B3')
        # self.enth_mass_param_B4 = Var(
        #     within=Reals, initialize=-1.446e7, units=enth_mass_units,
        #     doc='Specific enthalpy parameter B4')
        # self.enth_mass_param_B5 = Var(
        #     within=Reals, initialize=7.826e3, units=enth_mass_units * t_inv_units,
        #     doc='Specific enthalpy parameter B5')
        # self.enth_mass_param_B6 = Var(
        #     within=Reals, initialize=-4.417e1, units=enth_mass_units * t_inv_units**2,
        #     doc='Specific enthalpy parameter B6')
        # self.enth_mass_param_B7 = Var(
        #     within=Reals, initialize=2.139e-1, units=enth_mass_units * t_inv_units**3,
        #     doc='Specific enthalpy parameter B7')
        # self.enth_mass_param_B8 = Var(
        #     within=Reals, initialize=-1.991e4, units=enth_mass_units * t_inv_units,
        #     doc='Specific enthalpy parameter B8')
        # self.enth_mass_param_B9 = Var(
        #     within=Reals, initialize=2.778e4, units=enth_mass_units * t_inv_units,
        #     doc='Specific enthalpy parameter B9')
        # self.enth_mass_param_B10 = Var(
        #     within=Reals, initialize=9.728e1, units=enth_mass_units * t_inv_units**2,
        #     doc='Specific enthalpy parameter B10')

        # specific heat parameters from eq (9) in Sharqawy et al. (2010)
        cp_units = pyunits.J / (pyunits.kg * pyunits.K)
        self.cp_phase_param_A1 = Var(
            within=Reals,
            initialize=5.328,
            units=cp_units,
            doc="Specific heat of seawater parameter A1",
        )
        # self.cp_phase_param_A2 = Var(
        #     within=Reals, initialize=-9.76e-2, units=cp_units * s_inv_units,
        #     doc='Specific heat of seawater parameter A2')
        # self.cp_phase_param_A3 = Var(
        #     within=Reals, initialize=4.04e-4, units=cp_units * s_inv_units**2,
        #     doc='Specific heat of seawater parameter A3')
        self.cp_phase_param_B1 = Var(
            within=Reals,
            initialize=-6.913e-3,
            units=cp_units * t_inv_units,
            doc="Specific heat of seawater parameter B1",
        )
        # self.cp_phase_param_B2 = Var(
        #     within=Reals, initialize=7.351e-4, units=cp_units * s_inv_units * t_inv_units,
        #     doc='Specific heat of seawater parameter B2')
        # self.cp_phase_param_B3 = Var(
        #     within=Reals, initialize=-3.15e-6, units=cp_units * s_inv_units**2 * t_inv_units,
        #     doc='Specific heat of seawater parameter B3')
        self.cp_phase_param_C1 = Var(
            within=Reals,
            initialize=9.6e-6,
            units=cp_units * t_inv_units**2,
            doc="Specific heat of seawater parameter C1",
        )
        # self.cp_phase_param_C2 = Var(
        #     within=Reals, initialize=-1.927e-6, units=cp_units * s_inv_units * t_inv_units**2,
        #     doc='Specific heat of seawater parameter C2')
        # self.cp_phase_param_C3 = Var(
        #     within=Reals, initialize=8.23e-9, units=cp_units * s_inv_units**2 * t_inv_units**2,
        #     doc='Specific heat of seawater parameter C3')
        self.cp_phase_param_D1 = Var(
            within=Reals,
            initialize=2.5e-9,
            units=cp_units * t_inv_units**3,
            doc="Specific heat of seawater parameter D1",
        )
        # self.cp_phase_param_D2 = Var(
        #     within=Reals, initialize=1.666e-9, units=cp_units * s_inv_units * t_inv_units**3,
        #     doc='Specific heat of seawater parameter D2')
        # self.cp_phase_param_D3 = Var(
        #     within=Reals, initialize=-7.125e-12, units=cp_units * s_inv_units**2 * t_inv_units**3,
        #     doc='Specific heat of seawater parameter D3')

        # Specific heat parameters for Cp vapor from NIST Webbook
        # Chase, M.W., Jr., NIST-JANAF Themochemical Tables, Fourth Edition, J. Phys. Chem. Ref. Data, Monograph 9, 1998, 1-1951
        self.cp_vap_param_A = Var(
            within=Reals,
            initialize=30.09200 / 18.01528e-3,
            units=cp_units,
            doc="Specific heat of water vapor parameter A",
        )
        self.cp_vap_param_B = Var(
            within=Reals,
            initialize=6.832514 / 18.01528e-3,
            units=cp_units * t_inv_units,
            doc="Specific heat of water vapor parameter B",
        )
        self.cp_vap_param_C = Var(
            within=Reals,
            initialize=6.793435 / 18.01528e-3,
            units=cp_units * t_inv_units**2,
            doc="Specific heat of water vapor parameter C",
        )
        self.cp_vap_param_D = Var(
            within=Reals,
            initialize=-2.534480 / 18.01528e-3,
            units=cp_units * t_inv_units**3,
            doc="Specific heat of water vapor parameter D",
        )
        self.cp_vap_param_E = Var(
            within=Reals,
            initialize=0.082139 / 18.01528e-3,
            units=cp_units * t_inv_units**-2,
            doc="Specific heat of water vapor parameter E",
        )

        # latent heat of pure water parameters from eq. 54 in Sharqawy et al. (2010)
        self.dh_vap_w_param_0 = Var(
            within=Reals,
            initialize=2.501e6,
            units=enth_mass_units,
            doc="Latent heat of pure water parameter 0",
        )
        self.dh_vap_w_param_1 = Var(
            within=Reals,
            initialize=-2.369e3,
            units=cp_units,
            doc="Latent heat of pure water parameter 1",
        )
        self.dh_vap_w_param_2 = Var(
            within=Reals,
            initialize=2.678e-1,
            units=enth_mass_units * t_inv_units**2,
            doc="Latent heat of pure water parameter 2",
        )
        self.dh_vap_w_param_3 = Var(
            within=Reals,
            initialize=-8.103e-3,
            units=enth_mass_units * t_inv_units**3,
            doc="Latent heat of pure water parameter 3",
        )
        self.dh_vap_w_param_4 = Var(
            within=Reals,
            initialize=-2.079e-5,
            units=enth_mass_units * t_inv_units**4,
            doc="Latent heat of pure water parameter 4",
        )

        # traditional parameters are the only Vars currently on the block and should be fixed
        for v in self.component_objects(Var):
            v.fix()

        # ---default scaling---
        self.set_default_scaling("temperature", 1e-2)
        self.set_default_scaling("pressure", 1e-5)
        self.set_default_scaling("dens_mass_phase", 1e-3, index="Liq")
        self.set_default_scaling("dens_mass_phase", 1, index="Vap")
        # self.set_default_scaling('dens_mass_solvent', 1e-3)
        self.set_default_scaling("enth_mass_phase", 1e-5, index="Liq")
        self.set_default_scaling("enth_mass_phase", 1e-6, index="Vap")
        self.set_default_scaling("pressure_sat", 1e-5)
        self.set_default_scaling("cp_phase", 1e-3, index="Liq")
        self.set_default_scaling("cp_phase", 1e-3, index="Vap")
        self.set_default_scaling("dh_vap", 1e-6)

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            "flow_mass_phase_comp": {
                "method": None
            },
            "temperature": {
                "method": None
            },
            "pressure": {
                "method": None
            },
            "dens_mass_phase": {
                "method": "_dens_mass_phase"
            },
            "flow_vol_phase": {
                "method": "_flow_vol_phase"
            },
            "flow_vol": {
                "method": "_flow_vol"
            },
            "flow_mol_phase_comp": {
                "method": "_flow_mol_phase_comp"
            },
            "mole_frac_phase_comp": {
                "method": "_mole_frac_phase_comp"
            },
            "pressure_sat": {
                "method": "_pressure_sat"
            },
            "enth_mass_phase": {
                "method": "_enth_mass_phase"
            },
            "enth_flow_phase": {
                "method": "_enth_flow_phase"
            },
            "cp_phase": {
                "method": "_cp_phase"
            },
            "dh_vap": {
                "method": "_dh_vap"
            },
        })

        obj.add_default_units({
            "time": pyunits.s,
            "length": pyunits.m,
            "mass": pyunits.kg,
            "amount": pyunits.mol,
            "temperature": pyunits.K,
        })
Ejemplo n.º 10
0
class WaterParameterBlockData(PhysicalParameterBlock):
    """
    Property Parameter Block Class

    Defines component and phase lists, along with base units and constant
    parameters.
    """
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare(
        'database',
        ConfigValue(
            description=
            'An instance of a WaterTAP Database to use for parameters.'))
    CONFIG.declare(
        'water_source',
        ConfigValue(
            description=
            'Water source to use when looking up parameters from database.'))
    CONFIG.declare(
        "solute_list",
        ConfigValue(
            domain=list,
            description="List of solute species of interest. If None, will use "
            "all species defined in the water_source provided."))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super().build()

        self._state_block_class = WaterStateBlock

        self.Liq = LiquidPhase()

        self.H2O = Solvent()

        # Get component set from database if provided
        comp_set = None
        if self.config.database is not None:
            comp_set = self.config.database.get_solute_set(
                self.config.water_source)

        # Check definition of solute list
        solute_list = self.config.solute_list
        if solute_list is None:
            # No user-provided solute list, look up list from database
            if comp_set is None:
                # No solute list in database and none provided.
                raise ConfigurationError(
                    f"{self.name} no solute_list or database was defined. "
                    f"Users must provide at least one of these arguments.")
            else:
                solute_list = comp_set
        elif self.config.database is not None:
            # User provided custom list and database - check that all
            # components are supported
            for j in solute_list:
                if j not in comp_set:
                    _log.info(f"{self.name} component {j} is not defined in "
                              f"the water_sources database file.")
        else:
            # User provided list but no database - assume they know what they
            # are doing
            pass

        for j in solute_list:
            self.add_component(str(j), Solute())

        # Define default value for mass density of solution
        self.dens_mass_default = 1000 * pyunits.kg / pyunits.m**3
        # Define default value for dynamic viscosity of solution
        self.visc_d_default = 0.001 * pyunits.kg / pyunits.m / pyunits.s

        # ---------------------------------------------------------------------
        # Set default scaling factors
        self.default_scaling_factor = {
            ("flow_vol"): 1e3,
            ("conc_mass_comp"): 1e2
        }

    @classmethod
    def define_metadata(cls, obj):
        obj.add_default_units({
            'time': pyunits.s,
            'length': pyunits.m,
            'mass': pyunits.kg,
            'amount': pyunits.mol,
            'temperature': pyunits.K,
        })

        obj.add_properties({
            'flow_mass_comp': {
                'method': None
            },
            'flow_vol': {
                'method': '_flow_vol'
            },
            'conc_mass_comp': {
                'method': '_conc_mass_comp'
            },
            'dens_mass': {
                'method': '_dens_mass'
            },
            'visc_d': {
                'method': '_visc_d'
            }
        })
Ejemplo n.º 11
0
class NaClParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(NaClParameterData, self).build()

        self.state_block_class = IdealStateBlock

        self.component_list = Set(initialize=['H2O', 'NaCl'])

        self.phase_list = Set(initialize=['Liq'], ordered=True)

        # List of components in each phase (optional)
        self.phase_comp = {"Liq": self.component_list}

        # Source: google
        mw_comp_data = {'H2O': 18.0E-3, 'NaCl': 58.4E-3}

        self.mw_comp = Param(self.component_list,
                             mutable=False,
                             initialize=extract_data(mw_comp_data),
                             doc="molecular weight Kg/mol")

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mass': {
                'method': None,
                'units': 'g/s'
            },
            'flow_mass_comp': {
                'method': None,
                'units': 'g/s'
            },
            'mass_frac': {
                'method': None,
                'units': 'none'
            },
            'temperature': {
                'method': None,
                'units': 'K'
            },
            'pressure': {
                'method': None,
                'units': 'Pa'
            },
            'dens_mass': {
                'method': '_dens_mass',
                'units': 'g/m3'
            },
            'dens_mass_comp': {
                'method': '_dens_mass_comp',
                'units': 'g/m3'
            },
            'pressure_osm': {
                'method': '_pressure_osm',
                'units': 'Pa'
            }
        })

        obj.add_default_units({
            'time': 's',
            'length': 'm',
            'mass': 'g',
            'amount': 'mol',
            'temperature': 'K',
            'energy': 'J',
            'holdup': 'g'
        })
Ejemplo n.º 12
0
class PropParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(PropParameterData, self).build()

        self._state_block_class = PropStateBlock

        # phases
        self.Liq = LiquidPhase()

        # components
        self.H2O = Solvent()
        self.Na = Solute()
        self.Ca = Solute()
        self.Mg = Solute()
        self.SO4 = Solute()
        self.Cl = Solute()

        # molecular weight
        mw_comp_data = {'H2O': 18.015e-3,
                        'Na': 22.990e-3,
                        'Ca': 40.078e-3,
                        'Mg': 24.305e-3,
                        'SO4': 96.06e-3,
                        'Cl': 35.453e-3}

        self.mw_comp = Param(self.component_list,
                             mutable=False,
                             initialize=extract_data(mw_comp_data),
                             units=pyunits.kg / pyunits.mol,
                             doc="Molecular weight")

        self.dens_mass = Param(mutable=False,
                               initialize=1000,
                               units=pyunits.kg / pyunits.m**3,
                               doc="Density")

        self.cp = Param(mutable=False,
                        initialize=4.2e3,
                        units=pyunits.J / (pyunits.kg * pyunits.K))


        # ---default scaling---
        self.set_default_scaling('temperature', 1e-2)
        self.set_default_scaling('pressure', 1e-6)

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties(
            {'flow_mass_phase_comp': {'method': None},
             'temperature': {'method': None},
             'pressure': {'method': None},
             'mass_frac_phase_comp': {'method': '_mass_frac_phase_comp'},
             'flow_vol': {'method': '_flow_vol'},
             'flow_mol_phase_comp': {'method': '_flow_mol_phase_comp'},
             'conc_mol_phase_comp': {'method': '_conc_mol_phase_comp'},
             'enth_flow': {'method': '_enth_flow'},
            })

        obj.add_default_units({'time': pyunits.s,
                               'length': pyunits.m,
                               'mass': pyunits.kg,
                               'amount': pyunits.mol,
                               'temperature': pyunits.K})
class HDAParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(HDAParameterData, self).build()

        self._state_block_class = HDAStateBlock

        self.benzene = Component()
        self.toluene = Component()
        self.methane = Component()
        self.hydrogen = Component()
        self.diphenyl = Component()

        self.Vap = VaporPhase()

        # Thermodynamic reference state
        self.pressure_ref = Param(mutable=True,
                                  default=101325,
                                  units=pyunits.Pa,
                                  doc='Reference pressure')
        self.temperature_ref = Param(mutable=True,
                                     default=298.15,
                                     units=pyunits.K,
                                     doc='Reference temperature')

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        self.mw_comp = Param(self.component_list,
                             mutable=False,
                             initialize={'benzene': 78.1136E-3,
                                         'toluene': 92.1405E-3,
                                         'hydrogen': 2.016e-3,
                                         'methane': 16.043e-3,
                                         'diphenyl': 154.212e-4},
                             units=pyunits.kg/pyunits.mol,
                             doc="Molecular weight")

        # Constants for specific heat capacity, enthalpy
        # Sources: The Properties of Gases and Liquids (1987)
        #         4th edition, Chemical Engineering Series - Robert C. Reid
        self.cp_mol_ig_comp_coeff_A = Var(
            self.component_list,
            initialize={"benzene": -3.392E1,
                        "toluene": -2.435E1,
                        "hydrogen": 2.714e1,
                        "methane": 1.925e1,
                        "diphenyl": -9.707e1},
            units=pyunits.J/pyunits.mol/pyunits.K,
            doc="Parameter A for ideal gas molar heat capacity")
        self.cp_mol_ig_comp_coeff_A.fix()

        self.cp_mol_ig_comp_coeff_B = Var(
            self.component_list,
            initialize={"benzene": 4.739E-1,
                        "toluene": 5.125E-1,
                        "hydrogen": 9.274e-3,
                        "methane": 5.213e-2,
                        "diphenyl": 1.106e0},
            units=pyunits.J/pyunits.mol/pyunits.K**2,
            doc="Parameter B for ideal gas molar heat capacity")
        self.cp_mol_ig_comp_coeff_B.fix()

        self.cp_mol_ig_comp_coeff_C = Var(
            self.component_list,
            initialize={"benzene": -3.017E-4,
                        "toluene": -2.765E-4,
                        "hydrogen": -1.381e-5,
                        "methane": -8.855e-4,
                        "diphenyl": -8.855e-4},
            units=pyunits.J/pyunits.mol/pyunits.K**3,
            doc="Parameter C for ideal gas molar heat capacity")
        self.cp_mol_ig_comp_coeff_C.fix()

        self.cp_mol_ig_comp_coeff_D = Var(
            self.component_list,
            initialize={"benzene": 7.130E-8,
                        "toluene": 4.911E-8,
                        "hydrogen": 7.645e-9,
                        "methane": -1.132e-8,
                        "diphenyl": 2.790e-7},
            units=pyunits.J/pyunits.mol/pyunits.K**4,
            doc="Parameter D for ideal gas molar heat capacity")
        self.cp_mol_ig_comp_coeff_D.fix()

        # Source: NIST Webook, https://webbook.nist.gov/, retrieved 11/3/2020
        self.enth_mol_form_vap_comp_ref = Var(
            self.component_list,
            initialize={"benzene": -82.9e3,
                        "toluene": -50.1e3,
                        "hydrogen": 0,
                        "methane": -75e3,
                        "diphenyl": -180e3},
            units=pyunits.J/pyunits.mol,
            doc="Standard heat of formation at reference state")
        self.enth_mol_form_vap_comp_ref.fix()

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties(
            {'flow_mol': {'method': None},
             'mole_frac_comp': {'method': None},
             'temperature': {'method': None},
             'pressure': {'method': None},
             'mw_comp': {'method': None},
             'dens_mol': {'method': None},
             'enth_mol': {'method': '_enth_mol'}})

        obj.add_default_units({'time': pyunits.s,
                               'length': pyunits.m,
                               'mass': pyunits.kg,
                               'amount': pyunits.mol,
                               'temperature': pyunits.K})
Ejemplo n.º 14
0
class CoagulationParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        """
        Callable method for Block construction.
        """
        super(CoagulationParameterData, self).build()

        self._state_block_class = CoagulationStateBlock

        # phases
        self.Liq = LiquidPhase()

        # components
        self.H2O = Component()
        self.TSS = Component()
        self.TDS = Component()
        self.Sludge = Component()

        #   heat capacity of liquid
        self.cp = Param(mutable=False,
                        initialize=4184,
                        units=pyunits.J / (pyunits.kg * pyunits.K))

        #   reference density of liquid
        self.ref_dens_liq = Param(
            domain=Reals,
            initialize=999.26,
            mutable=True,
            units=pyunits.kg / pyunits.m**3,
            doc='Reference water mass density parameter @ 0 oC and no salts')

        #   change in liquid density with increasing mass fraction of salts/solids
        self.dens_slope = Param(
            domain=Reals,
            initialize=879.04,
            mutable=True,
            units=pyunits.kg / pyunits.m**3,
            doc=
            'Relative increase in liquid density with mass fraction of salts')

        #   adjustment parameters for density change with temperature
        #   Density calculation as a function of temperature and pressure
        #   --------------------------------------------------------------
        #   Engineering Toolbox. Water - Density, Specific Weight, and
        #   Thermal Expansion Coefficients. (2003) https://www.engineeringtoolbox.com/
        #   water-density-specific-weight-d_595.html [Accessed 02-01-2022]
        self.dens_param_A = Param(
            domain=Reals,
            initialize=-2.9335E-6,
            mutable=True,
            units=pyunits.K**-2,
            doc='Density correction parameter A for temperature variation')

        self.dens_param_B = Param(
            domain=Reals,
            initialize=0.001529811,
            mutable=True,
            units=pyunits.K**-1,
            doc='Density correction parameter B for temperature variation')

        self.dens_param_C = Param(
            domain=Reals,
            initialize=0.787973,
            mutable=True,
            units=pyunits.dimensionless,
            doc='Density correction parameter C for temperature variation')

        #   Correction factors for changes in density with changes in pressure
        self.ref_pressure_correction = Param(
            domain=Reals,
            initialize=1.0135,
            mutable=True,
            units=pyunits.dimensionless,
            doc='Density reference correction parameter for changes in pressure'
        )

        self.ref_pressure_slope = Param(
            domain=Reals,
            initialize=4.9582E-10,
            mutable=True,
            units=pyunits.Pa**-1,
            doc='Slope of density change as a function of pressure')

        #   reference density of solids
        self.ref_dens_sol = Param(
            domain=Reals,
            initialize=2600,
            mutable=True,
            units=pyunits.kg / pyunits.m**3,
            doc='Reference dry solid mass density parameter')

        # ---default scaling---
        self.set_default_scaling('temperature', 1e-2)
        self.set_default_scaling('pressure', 1e-6)

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mass_phase_comp': {
                'method': None
            },
            'temperature': {
                'method': None
            },
            'pressure': {
                'method': None
            },
            'mass_frac_phase_comp': {
                'method': '_mass_frac_phase_comp'
            },
            'dens_mass_phase': {
                'method': '_dens_mass_phase'
            },
            'flow_vol_phase': {
                'method': '_flow_vol_phase'
            },
            'conc_mass_phase_comp': {
                'method': '_conc_mass_phase_comp'
            },
            'enth_flow': {
                'method': '_enth_flow'
            },
        })

        obj.add_default_units({
            'time': pyunits.s,
            'length': pyunits.m,
            'mass': pyunits.kg,
            'amount': pyunits.mol,
            'temperature': pyunits.K
        })
Ejemplo n.º 15
0
class NaClParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(NaClParameterData, self).build()

        self.state_block_class = IdealStateBlock

        self.component_list = Set(initialize=['H2O', 'NaCl'])

        self.phase_list = Set(initialize=['Liq'], ordered=True)

        # List of components in each phase (optional)
        self.phase_comp = {"Liq": self.component_list}

        # Source: google
        mw_comp_data = {'H2O': 18.0E-3, 'NaCl': 58.4E-3}

        self.mw_comp = Param(self.component_list,
                             mutable=False,
                             initialize=extract_data(mw_comp_data),
                             doc="molecular weight Kg/mol")

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mass': {
                'method': None,
                'units': 'g/s'
            },
            'mass_frac': {
                'method': None,
                'units': 'none'
            },
            'temperature': {
                'method': None,
                'units': 'K'
            },
            'pressure': {
                'method': None,
                'units': 'Pa'
            },
            'dens_mass': {
                'method': '_dens_mass',
                'units': 'kg/m3'
            },
            'viscosity': {
                'method': '_viscosity',
                'units': 'Pa-s'
            },
            'dens_mass_comp': {
                'method': '_dens_mass_comp',
                'units': 'kg/m3'
            },
            'osm_coeff': {
                'method': '_osm_coeff',
                'units': 'none'
            },
            'pressure_osm': {
                'method': '_pressure_osm',
                'units': 'Pa'
            },
            'enth_mass_liq': {
                'method': '_enth_mass_liq',
                'units': 'J/kg'
            }
        })

        obj.add_default_units({
            'time': 's',
            'length': 'm',
            'mass': 'kg',
            'amount': 'mol',
            'temperature': 'K',
            'energy': 'J',
            'holdup': 'g'
        })

    # parameters
    R = 8.314  # gas constant [J/mol-K]
    MW = 58.44  # molecular weight [g/mol]
    osm_coeff_data = {
        'a1': 8.9453e-1,
        'a2': 4.1561e-4,
        'a3': -4.6262e-6,
        'a4': 2.2211e-11,
        'a5': -1.1445e-1,
        'a6': -1.4783e-3,
        'a7': -1.3526e-8,
        'a8': 7.0132,
        'a9': 5.696e-2,
        'a10': -2.8624e-4
    }
Ejemplo n.º 16
0
class PhysicalParameterData(PhysicalParameterBlock):
    """
    Vapor Phase Property Parameter Block Class

    Contains parameters and indexing sets associated with
    vapor phase properties for amine-based scrubbing process.

    """
    # Remove zero flow components in the vapor phase
    # using config to set the vapor components according to process type

    CONFIG = PhysicalParameterBlock.CONFIG()
    CONFIG.declare("process_type", ConfigValue(
        default=ProcessType.absorber,
        domain=In(ProcessType),
        description="Flag indicating the type of  process",
        doc="""Flag indicating either absorption or stripping process.
            **default** - ProcessType.absorber.
            **Valid values:** {
            **ProcessType.absorber** - absorption process,
            **ProcessType.stripper** - stripping process.}"""))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        '''
            Create Component objects
            components created using the component class are added
            to the component_list object which is used by the framework
            '''

        super(PhysicalParameterData, self).build()

        if (self.config.process_type == ProcessType.stripper):
            self.CO2 = Component()
            self.H2O = Component()
        elif (self.config.process_type == ProcessType.absorber):
            self.CO2 = Component()
            self.H2O = Component()
            self.O2 = Component()
            self.N2 = Component()


        self._state_block_class = VaporStateBlock

        # Create Phase object
        self.Vap = VaporPhase()

        # Thermodynamic reference state
        self.pressure_ref = Param(within=PositiveReals,
                                  mutable=True,
                                  default=101325,
                                  units=pyunits.Pa,
                                  doc='Reference pressure ')
        self.temperature_ref = Param(default=298.15,
                                     units=pyunits.K,
                                     doc='Thermodynamic Reference Temperature [K]')

        # Mol. weights of vapor component - units = kg/mol.
        mw_comp_dict_all = {'CO2': 0.04401,
                            'H2O': 0.01802, 'O2': 0.032, 'N2': 0.02801}
        mw_comp_dict = {}
        for i in self.component_list:
            mw_comp_dict[i] = mw_comp_dict_all[i]

        self.mw_comp = Param(
            self.component_list,
            mutable=False,
            initialize=mw_comp_dict,
            units=pyunits.kg / pyunits.mol,
            doc="Molecular weights of vapor components")

        # from Van Ness, J. Smith (appendix C):  CO2,N2,O2,WATER
        # cpig/R = A + BT + CT^-2
        # unit depends on unit of gas constant(J/mol.K)
        cp_param_dict_all = {
            ('O2', 1): 3.639 * CONST.gas_constant,
            ('O2', 2): 0.506E-3 * CONST.gas_constant,
            ('O2', 3): -0.227E5 * CONST.gas_constant,
            ('CO2', 1): 5.457 * CONST.gas_constant,
            ('CO2', 2): 1.045E-3 * CONST.gas_constant,
            ('CO2', 3): -1.157E5 * CONST.gas_constant,
            ('H2O', 1): 3.47 * CONST.gas_constant,
            ('H2O', 2): 1.45E-3 * CONST.gas_constant,
            ('H2O', 3): 0.121E5 * CONST.gas_constant,
            ('N2', 1): 3.28 * CONST.gas_constant,
            ('N2', 2): 0.593E-3 * CONST.gas_constant,
            ('N2', 3): 0.04E5 * CONST.gas_constant
        }
        cp_param_dict = {}
        for i in self.component_list:
            for j in [1, 2, 3]:
                cp_param_dict[i, j] = cp_param_dict_all[i, j]

        self.cp_param = Param(self.component_list,
                              range(1, 4),
                              mutable=False,
                              initialize=cp_param_dict,
                              units=pyunits.J / (pyunits.mol * pyunits.K),
                              doc="Ideal gas heat capacity parameters")

        # Viscosity constants
        #CO2 & H2O
        # calculated from  :C1*T^(C2)/(1+C3/T)
        # Reference: Perry and Green Handbook; McGraw Hill,8th edition 2008
        #O2 & N2
        # calculated from Sutherland Formular
        # C1*(C2 + C3)/(T+C3)*(T/C2)^1.5:
        # constants C1,C2,C3 in sutherlands' formular are:
        #C1 = vis_d_ref
        #C2 = temperature_ref
        # C3 = sutherland constant
        visc_d_param_dict_all = {
            ('N2', 1): 0.01781e-3,
            ('N2', 2): 300.55,
            ('N2', 3): 111,
            ('O2', 1): 0.02018e-3,
            ('O2', 2): 292.25,
            ('O2', 3): 127,
            ('CO2', 1): 2.148e-6,
            ('CO2', 2): 0.46,
            ('CO2', 3): 290,
            ('H2O', 1): 1.7096e-8,
            ('H2O', 2): 1.1146,
            ('H2O', 3): 0.0
        }
        visc_d_param_dict = {}
        for i in self.component_list:
            for j in [1, 2, 3]:
                visc_d_param_dict[i, j] = visc_d_param_dict_all[i, j]
        self.visc_d_param = Param(self.component_list,
                                  range(1, 4),
                                  mutable=True,
                                  initialize=visc_d_param_dict,
                                  units=pyunits.Pa * pyunits.s,
                                  doc="Dynamic viscosity constants")

        # Thermal conductivity constants -
        # Reference: Perry and Green Handbook; McGraw Hill, 8th edition 2008
        therm_cond_param_dict_all = {('N2', 1): 0.000331,
                                     ('N2', 2): 0.7722,
                                     ('N2', 3): 16.323,
                                     ('N2', 4): 373.72,
                                     ('CO2', 1): 3.69,
                                     ('CO2', 2): -0.3838,
                                     ('CO2', 3): 964,
                                     ('CO2', 4): 1.86e6,
                                     ('H2O', 1): 6.204e-6,
                                     ('H2O', 2): 1.3973,
                                     ('H2O', 3): 0,
                                     ('H2O', 4): 0,
                                     ('O2', 1): 0.00045,
                                     ('O2', 2): 0.7456,
                                     ('O2', 3): 56.699,
                                     ('O2', 4): 0.0}
        therm_cond_param_dict = {}
        for i in self.component_list:
            for j in [1, 2, 3, 4]:
                therm_cond_param_dict[i, j] = therm_cond_param_dict_all[i, j]
        self.therm_cond_param = Param(self.component_list,
                                      range(1, 5),
                                      mutable=True,
                                      initialize=therm_cond_param_dict,
                                      units=pyunits.W / pyunits.m / pyunits.K,
                                      doc="Thermal conductivity constants")

        # Diffusion Coefficient(binary) constants -
        # Diffusion volumes in Fuller-Schettler-Giddings correlation
        # for estimating binary diffusivities of components in vapor phase
        # Reference: Table 3.1 pp 71 Seader Henley (2006)
        diffus_binary_param_dict_all = {
            'N2': 18.5,
            'CO2': 26.7,
            'H2O': 13.1,
            'O2': 16.3}
        diffus_binary_param_dict = {}
        for i in self.component_list:
            diffus_binary_param_dict[i] = diffus_binary_param_dict_all[i]

        self.diffus_binary_param = \
            Param(self.component_list,
                  initialize=diffus_binary_param_dict,
                  units=pyunits.m**2 / pyunits.s,
                  doc="Diffusion volume parameter for binary diffusivity")

    @classmethod
    def define_metadata(cls, obj):
        obj.add_properties({
            'flow_mol': {'method': None, 'units': 'mol/s'},
            'pressure': {'method': None, 'units': 'Pa'},
            'temperature': {'method': None, 'units': 'K'},
            'mole_frac_comp': {'method': None, 'units': None},
            'flow_mol_comp': {'method': '_flow_mol_comp', 'units': 'mol/s'},
            'mw': {'method': '_mw', 'units': 'kg/mol'},
            'conc_mol': {'method': '_conc_mol', 'units': 'mol/m^3'},
            'conc_mol_comp': {'method': '_conc_mol_comp', 'units': 'mol/m^3'},
            'dens_mass': {'method': '_dens_mass', 'units': 'kg/m^3'},
            'cp_mol': {'method': '_cp_mol', 'units': 'J/mol.K'},
            'cp_mol_mean': {'method': '_cp_mol_mean', 'units': 'J/mol.K'},
            'cp_mol_comp': {'method': '_cp_mol_comp', 'units': 'J/mol.K'},
            'cp_mol_comp_mean': {'method': '_cp_mol_comp_mean', 'units': 'J/mol.K'},
            'enth_mean': {'method': '_enth_mean', 'units': 'J/s'},
            'enth_vap_density': {'method': '_enth_vap_density', 'units': 'J/m^3'},
            'diffus': {'method': '_diffus', 'units': 'm^2/s'},
            'visc_d': {'method': '_visc_d', 'units': 'kg/m.s'},
            'visc_d_comp': {'method': '_visc_d_comp', 'units': 'kg/m.s'},
            'therm_cond': {'method': '_therm_cond', 'units': 'J/m.K.s'},
            'therm_cond_comp': {'method': '_therm_cond_comp', 'units': 'J/m.K.s'}})

        obj.add_default_units({'time': pyunits.s,
                               'length': pyunits.m,
                               'mass': pyunits.kg,
                               'amount': pyunits.mol,
                               'temperature': pyunits.K})
Ejemplo n.º 17
0
class PropertyInterrogatorData(PhysicalParameterBlock):
    """
    Interrogator Parameter Block Class

    This class contains the methods and attributes for recording and displaying
    the properties requried by the flowsheet.
    """
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare(
        "phase_list",
        ConfigValue(
            domain=dict,
            description="User defined phase list. Dict with form {name: Type}")
    )
    CONFIG.declare(
        "component_list",
        ConfigValue(
            domain=dict,
            description=
            "User defined component list. Dict with form {name: Type}"))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(PropertyInterrogatorData, self).build()

        self._state_block_class = InterrogatorStateBlock

        # Phase objects
        if self.config.phase_list is None:
            self.Liq = LiquidPhase()
            self.Vap = VaporPhase()
        else:
            for p, t in self.config.phase_list.items():
                if t is None:
                    t = Phase
                elif not isclass(t) or not issubclass(t, Phase):
                    raise ConfigurationError(
                        f"{self.name} invalid phase type {t} (for phase {p})."
                        f" Type must be a subclass of Phase.")
                self.add_component(p, t())

        # Component objects
        if self.config.component_list is None:
            self.A = Component()
            self.B = Component()
        else:
            for j, t in self.config.component_list.items():
                if t is None:
                    t = Component
                elif not isclass(t) or not issubclass(t, Component):
                    raise ConfigurationError(
                        f"{self.name} invalid component type {t} (for "
                        f"component {j}). Type must be a subclass of "
                        f"Component.")
                self.add_component(j, t())

        # Set up dict to record property calls
        self.required_properties = {}

        # Dummy phase equilibrium definition so we can handle flash cases
        self.phase_equilibrium_idx = Set(initialize=[1])

        self.phase_equilibrium_list = \
            {1: ["A", ("Vap", "Liq")]}

    def list_required_properties(self):
        """
        Method to list all thermophysical properties required by the flowsheet.

        Args:
            None

        Returns:
            A list of properties required
        """
        return list(self.required_properties)

    def list_models_requiring_property(self, prop):
        """
        Method to list all models in the flowsheet requiring the given
        property.

        Args:
            prop : the property of interest

        Returns:
            A list of unit model names which require prop
        """
        try:
            return self.required_properties[prop]
        except KeyError:
            raise KeyError(
                "Property {} does not appear in required_properties. "
                "Please check the spelling of the property that you are "
                "interested in.".format(prop))

    def list_properties_required_by_model(self, model):
        """
        Method to list all thermophysical properties required by a given unit
        model.

        Args:
            model : the unit model of interest. Can be given as either a model
                    component or the unit name as a string

        Returns:
            A list of thermophysical properties required by model
        """
        prop_list = []
        if not isinstance(model, str):
            model = model.name

        for k, v in self.required_properties.items():
            if model in v:
                prop_list.append(k)

        if len(prop_list) < 1:
            raise ValueError(
                "Model {} does not appear in the flowsheet. Please check "
                "the spelling of the model provided.")
        else:
            return prop_list

    def print_required_properties(self, ostream=None):
        """
        Method to print a summary of the thermophysical properties required by
        the flowsheet.

        Args:
            ostream : output stream to print to. If not provided will print to
                      sys.stdout

        Returns:
            None
        """
        if ostream is None:
            ostream = sys.stdout

        # Write header
        max_str_length = 74
        tab = " " * 4
        ostream.write("\n" + "=" * max_str_length + "\n")
        ostream.write("Property Interrogator Summary" + "\n")
        ostream.write("\n" +
                      "The Flowsheet requires the following properties " +
                      "(times required):" + "\n" + "\n")
        for k, v in self.required_properties.items():
            lead_str = tab + k
            trail_str = str(len(v))
            mid_str = " " * (max_str_length - len(lead_str) - len(trail_str))
            ostream.write(lead_str + mid_str + trail_str + "\n")
        ostream.write(
            "\n" +
            "Note: User constraints may require additional properties " +
            "which are not" + "\n" + "reported here." + "\n")

    def print_models_requiring_property(self, prop, ostream=None):
        """
        Method to print a summary of the models in the flowsheet requiring a
        given property.

        Args:
            prop : the property of interest.
            ostream : output stream to print to. If not provided will print to
                      sys.stdout

        Returns:
            None
        """
        if ostream is None:
            ostream = sys.stdout

        tab = " " * 4

        ostream.write("\n")
        ostream.write(f"The following models in the Flowsheet "
                      f"require {prop}:" + "\n")

        for m in self.required_properties[prop]:
            ostream.write(tab + m + "\n")

    def print_properties_required_by_model(self, model, ostream=None):
        """
        Method to print a summary of the thermophysical properties required by
        a given unit model.

        Args:
            model : the unit model of interest.
            ostream : output stream to print to. If not provided will print to
                      sys.stdout

        Returns:
            None
        """
        if not isinstance(model, str):
            model = model.name

        if ostream is None:
            ostream = sys.stdout

        tab = " " * 4

        ostream.write("\n")
        ostream.write(f"The following properties are required by model "
                      f"{model}:" + "\n")

        for m in self.list_properties_required_by_model(model):
            ostream.write(tab + m + "\n")

    @classmethod
    def define_metadata(cls, obj):
        obj.add_default_units({
            'time': pyunits.s,
            'length': pyunits.m,
            'mass': pyunits.kg,
            'amount': pyunits.mol,
            'temperature': pyunits.K
        })
Ejemplo n.º 18
0
class NaClParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(NaClParameterData, self).build()

        self._state_block_class = NaClStateBlock

        # components
        self.H2O = Solvent()
        self.NaCl = Solute()

        # phases
        self.Liq = LiquidPhase()

        # reference
        # this package is developed from Bartholomew & Mauter (2019) https://doi.org/10.1016/j.memsci.2018.11.067
        # the enthalpy calculations are from Sharqawy et al. (2010) http://dx.doi.org/10.5004/dwt.2010.1079

        # molecular weight
        mw_comp_data = {'H2O': 18.01528E-3, 'NaCl': 58.44E-3}
        self.mw_comp = Param(self.component_list,
                             mutable=False,
                             initialize=extract_data(mw_comp_data),
                             units=pyunits.kg / pyunits.mol,
                             doc="Molecular weight kg/mol")

        # mass density parameters, eq 4 in Bartholomew
        dens_mass_param_dict = {'0': 995, '1': 756}
        self.dens_mass_param = Var(dens_mass_param_dict.keys(),
                                   domain=Reals,
                                   initialize=dens_mass_param_dict,
                                   units=pyunits.kg / pyunits.m**3,
                                   doc='Mass density parameters')

        # dynamic viscosity parameters, eq 5 in Bartholomew
        visc_d_param_dict = {'0': 9.80E-4, '1': 2.15E-3}
        self.visc_d_param = Var(visc_d_param_dict.keys(),
                                domain=Reals,
                                initialize=visc_d_param_dict,
                                units=pyunits.Pa * pyunits.s,
                                doc='Dynamic viscosity parameters')

        # diffusivity parameters, eq 6 in Bartholomew
        diffus_param_dict = {
            '0': 1.51e-9,
            '1': -2.00e-9,
            '2': 3.01e-8,
            '3': -1.22e-7,
            '4': 1.53e-7
        }
        self.diffus_param = Var(diffus_param_dict.keys(),
                                domain=Reals,
                                initialize=diffus_param_dict,
                                units=pyunits.m**2 / pyunits.s,
                                doc='Dynamic viscosity parameters')

        # osmotic coefficient parameters, eq. 3b in Bartholomew
        osm_coeff_param_dict = {'0': 0.918, '1': 8.89e-2, '2': 4.92}
        self.osm_coeff_param = Var(osm_coeff_param_dict.keys(),
                                   domain=Reals,
                                   initialize=osm_coeff_param_dict,
                                   units=pyunits.dimensionless,
                                   doc='Osmotic coefficient parameters')

        # TODO: update for NaCl solution, relationship from Sharqawy is for seawater
        # specific enthalpy parameters, eq. 55 and 43 in Sharqawy (2010)
        self.enth_mass_param_A1 = Var(within=Reals,
                                      initialize=124.790,
                                      units=pyunits.J / pyunits.kg,
                                      doc='Specific enthalpy parameter A1')
        self.enth_mass_param_A2 = Var(within=Reals,
                                      initialize=4203.075,
                                      units=(pyunits.J / pyunits.kg) *
                                      pyunits.K**-1,
                                      doc='Specific enthalpy parameter A2')
        self.enth_mass_param_A3 = Var(within=Reals,
                                      initialize=-0.552,
                                      units=(pyunits.J / pyunits.kg) *
                                      pyunits.K**-2,
                                      doc='Specific enthalpy parameter A3')
        self.enth_mass_param_A4 = Var(within=Reals,
                                      initialize=0.004,
                                      units=(pyunits.J / pyunits.kg) *
                                      pyunits.K**-3,
                                      doc='Specific enthalpy parameter A4')
        self.enth_mass_param_B1 = Var(within=Reals,
                                      initialize=27062.623,
                                      units=pyunits.dimensionless,
                                      doc='Specific enthalpy parameter B1')
        self.enth_mass_param_B2 = Var(within=Reals,
                                      initialize=4835.675,
                                      units=pyunits.dimensionless,
                                      doc='Specific enthalpy parameter B2')

        # traditional parameters are the only Vars currently on the block and should be fixed
        for v in self.component_objects(Var):
            v.fix()

        # ---default scaling---
        self.set_default_scaling('temperature', 1e-2)
        self.set_default_scaling('pressure', 1e-6)
        self.set_default_scaling('dens_mass_phase', 1e-3, index='Liq')
        self.set_default_scaling('visc_d_phase', 1e3, index='Liq')
        self.set_default_scaling('diffus_phase', 1e9, index='Liq')
        self.set_default_scaling('osm_coeff', 1e0)
        self.set_default_scaling('enth_mass_phase', 1e-5, index='Liq')

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mass_phase_comp': {
                'method': None
            },
            'temperature': {
                'method': None
            },
            'pressure': {
                'method': None
            },
            'mass_frac_phase_comp': {
                'method': '_mass_frac_phase_comp'
            },
            'dens_mass_phase': {
                'method': '_dens_mass_phase'
            },
            'flow_vol_phase': {
                'method': '_flow_vol_phase'
            },
            'flow_vol': {
                'method': '_flow_vol'
            },
            'conc_mass_phase_comp': {
                'method': '_conc_mass_phase_comp'
            },
            'flow_mol_phase_comp': {
                'method': '_flow_mol_phase_comp'
            },
            'mole_frac_phase_comp': {
                'method': '_mole_frac_phase_comp'
            },
            'molality_comp': {
                'method': '_molality_comp'
            },
            'diffus_phase': {
                'method': '_diffus_phase'
            },
            'visc_d_phase': {
                'method': '_visc_d_phase'
            },
            'osm_coeff': {
                'method': '_osm_coeff'
            },
            'pressure_osm': {
                'method': '_pressure_osm'
            },
            'enth_mass_phase': {
                'method': '_enth_mass_phase'
            },
            'enth_flow': {
                'method': '_enth_flow'
            }
        })

        obj.add_default_units({
            'time': pyunits.s,
            'length': pyunits.m,
            'mass': pyunits.kg,
            'amount': pyunits.mol,
            'temperature': pyunits.K
        })
Ejemplo n.º 19
0
class GenericParameterData(PhysicalParameterBlock):
    """
    General Property Parameter Block Class
    """
    CONFIG = PhysicalParameterBlock.CONFIG()

    # General options
    CONFIG.declare(
        "component_list",
        ConfigValue(
            description="List of components in material",
            doc="""A list of names for the components of interest in the mixture.
        """))
    CONFIG.declare(
        "phase_list",
        ConfigValue(
            description="List of phases of interest",
            doc="""A list of phases of interest in the mixture for the property
        package."""))
    CONFIG.declare(
        "phase_component_list",
        ConfigValue(
            description="List of components in each phase",
            doc=
            """A dict of component_lists for each phase. Keys should correspond
        to members of phase_list, and each value should be a list of component
        names."""))

    CONFIG.declare(
        "state_definition",
        ConfigValue(
            description="Choice of State Variable",
            doc="""Flag indicating the set of state variables to use for property
        package. Values should be a valid Python method which creates the
        required state variables. Default = state_methods.FPHx"""))
    CONFIG.declare(
        "state_bounds",
        ConfigValue(
            domain=dict,
            description="Bounds for state variables",
            doc="""A dict containing bounds to use for state variables."""))

    CONFIG.declare(
        "phase_equilibrium_formulation",
        ConfigValue(
            default=None,
            description="Phase equilibrium formulation to use",
            doc="""Flag indicating what formulation to use for calculating phase
        equilibrium. Value should be a valid Python method or None. Default =
        None, indicating no phase equilibrium will occur."""))
    CONFIG.declare(
        "phase_equilibrium_dict",
        ConfigValue(
            default=None,
            description="Phase equilibrium reactions to be modeled",
            doc="""Dict describing what phase equilibrium reactions should be
        included in the property package. Keys should be names from
        component_list, and values should be a 2-tuple of phases from
        phase_list which should be in equilibrium."""))

    CONFIG.declare(
        "temperature_bubble",
        ConfigValue(
            description="Method to use to calculate bubble temperature",
            doc="""Flag indicating what formulation to use for calculating bubble
        temperature. Value should be a valid Python method."""))
    CONFIG.declare(
        "temperature_dew",
        ConfigValue(
            description="Method to use to calculate dew temperature",
            doc="""Flag indicating what formulation to use for calculating dew
        temperature. Value should be a valid Python method."""))
    CONFIG.declare(
        "pressure_bubble",
        ConfigValue(
            description="Method to use to calculate bubble pressure",
            doc="""Flag indicating what formulation to use for calculating bubble
        pressure. Value should be a valid Python method."""))
    CONFIG.declare(
        "pressure_dew",
        ConfigValue(
            description="Method to use to calculate dew pressure",
            doc="""Flag indicating what formulation to use for calculating dew
        pressure. Value should be a valid Python method."""))

    # Equation of state options
    CONFIG.declare(
        "equation_of_state",
        ConfigValue(
            description="Equation of state for each phase",
            doc="""Flag containing a dict indicating the equation of state for
        each phase. Value should be a dict with keys for each valid phase and
        values being a valid Python module with the necessary methods for
        the desired equation of state."""))

    # Pure component property options
    CONFIG.declare(
        "dens_mol_liq_comp",
        ConfigValue(
            description="Method to use to calculate liquid phase molar density",
            doc=
            """Flag indicating what method to use when calculating liquid phase
        molar density."""))
    CONFIG.declare(
        "enth_mol_liq_comp",
        ConfigValue(
            description="Method to calculate liquid component molar enthalpies",
            doc=
            """Flag indicating what method to use when calculating liquid phase
        component molar enthalpies."""))
    CONFIG.declare(
        "enth_mol_ig_comp",
        ConfigValue(
            description=
            "Method to calculate ideal gas component molar enthalpies",
            doc="""Flag indicating what method to use when calculating ideal gas
        phase component molar enthalpies."""))
    CONFIG.declare(
        "entr_mol_liq_comp",
        ConfigValue(
            description="Method to calculate liquid component molar entropies",
            doc=
            """Flag indicating what method to use when calculating liquid phase
        component molar entropies."""))
    CONFIG.declare(
        "entr_mol_ig_comp",
        ConfigValue(
            description=
            "Method to calculate ideal gas component molar entropies",
            doc="""Flag indicating what method to use when calculating ideal gas
        phase component molar entropies."""))
    CONFIG.declare(
        "pressure_sat_comp",
        ConfigValue(
            description="Method to use to calculate saturation pressure",
            doc="""Flag indicating what method to use when calculating saturation
        pressure. Value should be a valid Python method which takes two
        arguments: temperature and a component name."""))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        # Call super.build() to initialize Block
        super(GenericParameterData, self).build()

        # Call configure method to set construction arguments
        self.configure()

        # Build core components
        self.state_block_class = GenericStateBlock

        if self.config.phase_component_list is not None:
            # Check if phase list provided and cross-validate
            if self.config.phase_list is not None:
                # Phase list provided, cross-validate
                for p in self.config.phase_component_list:
                    if p not in self.config.phase_list:
                        raise ConfigurationError(
                            "{} mismatch between phase_list and "
                            "phase_component_list. Phase {} appears in "
                            "phase_component_list but not phase_list.".format(
                                self.name, p))

                for p in self.config.phase_list:
                    if p not in self.config.phase_component_list:
                        raise ConfigurationError(
                            "{} mismatch between phase_list and "
                            "phase_component_list. Phase {} appears in "
                            "phase_list but not phase_component_list.".format(
                                self.name, p))

                # Build phase_list if cross-validation passes
                self.phase_list = Set(initialize=self.config.phase_list,
                                      ordered=True)
            else:
                # No phase_list provided, build from phase_component_list
                self.phase_list = Set(
                    initialize=[p for p in self.config.phase_component_list],
                    ordered=True)

            if self.config.component_list is not None:
                # Component list provided, cross-validate
                for p in self.config.phase_component_list:
                    for j in self.config.phase_component_list[p]:
                        if j not in self.config.component_list:
                            raise ConfigurationError(
                                "{} mismatch between component_list and "
                                "phase_component_list. Component {} appears in"
                                " phase_component_list but not component_list."
                                .format(self.name, j))
                for j in self.config.component_list:
                    xcheck = False
                    for p in self.config.phase_component_list:
                        if j in self.config.phase_component_list[p]:
                            xcheck = True
                            break
                    if not xcheck:
                        raise ConfigurationError(
                            "{} mismatch between component_list and "
                            "phase_component_list. Component {} appears in"
                            " component_list but not phase_component_list.".
                            format(self.name, j))

                # Build component_list if cross-validation passes
                self.component_list = Set(
                    initialize=self.config.component_list, ordered=True)
            else:
                # No component_list provided, build from phase_component_list
                c_list = []
                for p in self.config.phase_component_list:
                    for j in self.config.phase_component_list[p]:
                        if j not in c_list:
                            c_list.append(j)
                self.component_list = Set(initialize=c_list, ordered=True)

            # All validation passed, build phase_component_set
            pc_set = []
            for p in self.config.phase_component_list:
                for j in self.config.phase_component_list[p]:
                    pc_set.append((p, j))
            self._phase_component_set = Set(initialize=pc_set, ordered=True)

        elif (self.config.phase_list is not None
              and self.config.component_list is not None):
            # Have phase and component lists
            # Assume all components in all phases
            self.phase_list = Set(initialize=self.config.phase_list,
                                  ordered=True)
            self.component_list = Set(initialize=self.config.component_list,
                                      ordered=True)

            # Create phase-component set
            pc_set = []
            for p in self.phase_list:
                for j in self.component_list:
                    pc_set.append((p, j))
            self._phase_component_set = Set(initialize=pc_set, ordered=True)
        else:
            # User has not provided sufficient information.
            if self.config.component_list is None:
                raise ConfigurationError(
                    "{} Generic Property Package was not provided with a "
                    "component_list or a phase_component_list. Users must "
                    "provide either at least one of these arguments".format(
                        self.name))

            if self.config.phase_list is None:
                raise ConfigurationError(
                    "{} Generic Property Package was not provided with a "
                    "phase_list or a phase_component_list. Users must "
                    "provide either at least one of these arguments".format(
                        self.name))

        # Validate state definition
        if self.config.state_definition is None:
            raise ConfigurationError(
                "{} Generic Property Package was not provided with a "
                "state_definition configuration argument. Please fix "
                "your property parameter definition to include this "
                "configuration argument.".format(self.name))

        # Validate equation of state
        if self.config.equation_of_state is None:
            raise ConfigurationError(
                "{} Generic Property Package was not provided with an "
                "equation_of_state configuration argument. Please fix "
                "your property parameter definition to include this "
                "configuration argument.".format(self.name))
        if not isinstance(self.config.equation_of_state, dict):
            raise ConfigurationError(
                "{} Generic Property Package was provided with an invalid "
                "equation_of_state configuration argument. Argument must "
                "be a dict with phases as keys.".format(self.name))
        if len(self.config.equation_of_state) != len(self.phase_list):
            raise ConfigurationError(
                "{} Generic Property Package was provided with an invalid "
                "equation_of_state configuration argument. A value must "
                "be present for each phase.".format(self.name))
        for p in self.config.equation_of_state:
            if p not in self.phase_list:
                raise ConfigurationError(
                    "{} Generic Property Package unrecognised phase {} in "
                    "equation_of_state configuration argument. Keys must be "
                    "valid phases.".format(self.name, p))

        # Validate that user provided either both a phase equilibrium
        # formulation and a dict of phase equilibria or neither
        if ((self.config.phase_equilibrium_formulation is not None) ^
            (self.config.phase_equilibrium_dict is not None)):
            raise ConfigurationError(
                "{} Generic Property Package provided with only one of "
                "phase_equilibrium_formulation and phase_equilibrium_dict."
                " Either both of these arguments need to be provided or "
                "neither.".format(self.name))

        # Validate and build phase equilibrium list
        if self.config.phase_equilibrium_dict is not None:
            if not isinstance(self.config.phase_equilibrium_dict, dict):
                raise ConfigurationError(
                    "{} Generic Property Package provided with invalid "
                    "phase_equilibrium_dict - value must be a dict. "
                    "Please see the documentation for the correct form.".
                    format(self.name))
            # Validate phase_equilibrium_dict
            for v in self.config.phase_equilibrium_dict.values():
                if not (isinstance(v, list) and len(v) == 2):
                    raise ConfigurationError(
                        "{} Generic Property Package provided with invalid "
                        "phase_equilibrium_dict, {}. Values in dict must be "
                        "lists containing 2 values.".format(self.name, v))
                if v[0] not in self.component_list:
                    raise ConfigurationError(
                        "{} Generic Property Package provided with invalid "
                        "phase_equilibrium_dict. First value in each list "
                        "must be a valid component, received {}.".format(
                            self.name, v[0]))
                if not (isinstance(v[1], tuple) and len(v[1]) == 2):
                    raise ConfigurationError(
                        "{} Generic Property Package provided with invalid "
                        "phase_equilibrium_dict. Second value in each list "
                        "must be a 2-tuple containing 2 valid phases, "
                        "received {}.".format(self.name, v[1]))
                for p in v[1]:
                    if p not in self.phase_list:
                        raise ConfigurationError(
                            "{} Generic Property Package provided with invalid"
                            " phase_equilibrium_dict. Unrecognised phase {} "
                            "in tuple {}".format(self.name, p, v[1]))

            self.phase_equilibrium_list = self.config.phase_equilibrium_dict

            pe_set = []
            for k in self.config.phase_equilibrium_dict.keys():
                pe_set.append(k)
            self.phase_equilibrium_idx = Set(initialize=pe_set, ordered=True)
        self.parameters()

    def configure(self):
        raise PropertyPackageError(
            "{} User defined property package failed to define a "
            "configure method. Please contact the developer of the "
            "property package with this error.".format(self.name))

    def parameters(self):
        raise PropertyPackageError(
            "{} User defined property package failed to define a "
            "parameters method. Please contact the developer of the "
            "property package with this error.".format(self.name))

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        # TODO : Need to fix to have methods for things that may or may not be
        # created by state var methods
        obj.add_properties({
            'flow_mol': {
                'method': None,
                'units': 'mol/s'
            },
            'mole_frac_comp': {
                'method': None,
                'units': 'none'
            },
            'mole_frac_phase_comp': {
                'method': None,
                'units': 'none'
            },
            'phase_frac': {
                'method': None,
                'units': 'none'
            },
            'temperature': {
                'method': None,
                'units': 'K'
            },
            'pressure': {
                'method': None,
                'units': 'Pa'
            },
            'flow_mol_phase': {
                'method': None,
                'units': 'mol/s'
            },
            'dens_mass': {
                'method': '_dens_mass',
                'units': 'kg/m^3'
            },
            'dens_mass_phase': {
                'method': '_dens_mass_phase',
                'units': 'kg/m^3'
            },
            'dens_mol': {
                'method': '_dens_mol',
                'units': 'mol/m^3'
            },
            'dens_mol_phase': {
                'method': '_dens_mol_phase',
                'units': 'mol/m^3'
            },
            'enth_mol': {
                'method': '_enth_mol',
                'units': 'J/mol'
            },
            'enth_mol_phase': {
                'method': '_enth_mol_phase',
                'units': 'J/mol'
            },
            'enth_mol_phase_comp': {
                'method': '_enth_mol_phase_comp',
                'units': 'J/mol'
            },
            'entr_mol': {
                'method': '_entr_mol',
                'units': 'J/mol.K'
            },
            'entr_mol_phase': {
                'method': '_entr_mol_phase',
                'units': 'J/mol.K'
            },
            'entr_mol_phase_comp': {
                'method': '_entr_mol_phase_comp',
                'units': 'J/mol.K'
            },
            'fug_phase_comp': {
                'method': '_fug_phase_comp',
                'units': 'Pa'
            },
            'fug_coeff_phase_comp': {
                'method': '_fug_coeff_phase_comp',
                'units': '-'
            },
            'gibbs_mol': {
                'method': '_gibbs_mol',
                'units': 'J/mol'
            },
            'gibbs_mol_phase': {
                'method': '_gibbs_mol_phase',
                'units': 'J/mol'
            },
            'gibbs_mol_phase_comp': {
                'method': '_gibbs_mol_phase_comp',
                'units': 'J/mol'
            },
            'mw': {
                'method': '_mw',
                'units': 'kg/mol'
            },
            'mw_phase': {
                'method': '_mw_phase',
                'units': 'kg/mol'
            },
            'pressure_bubble': {
                'method': '_pressure_bubble',
                'units': 'Pa'
            },
            'pressure_dew': {
                'method': '_pressure_dew',
                'units': 'Pa'
            },
            'pressure_sat_comp': {
                'method': '_pressure_sat_comp',
                'units': 'Pa'
            },
            'temperature_bubble': {
                'method': '_temperature_bubble',
                'units': 'K'
            },
            'temperature_dew': {
                'method': '_temperature_dew',
                'units': 'K'
            }
        })

        obj.add_default_units({
            'time': 's',
            'length': 'm',
            'mass': 'g',
            'amount': 'mol',
            'temperature': 'K',
            'energy': 'J',
            'holdup': 'mol'
        })
Ejemplo n.º 20
0
class IdealParameterData(PhysicalParameterBlock):
    """
    Property Parameter Block Class
    Contains parameters and indexing sets associated with properties for
    BTX system.
    """
    # Config block for the _IdealStateBlock
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare(
        "valid_phase",
        ConfigValue(default=('Vap', 'Liq'),
                    domain=In(['Liq', 'Vap', ('Vap', 'Liq'), ('Liq', 'Vap')]),
                    description="Flag indicating the valid phase",
                    doc="""Flag indicating the valid phase for a given set of
conditions, and thus corresponding constraints  should be included,
**default** - ('Vap', 'Liq').
**Valid values:** {
**'Liq'** - Liquid only,
**'Vap'** - Vapor only,
**('Vap', 'Liq')** - Vapor-liquid equilibrium,
**('Liq', 'Vap')** - Vapor-liquid equilibrium,}"""))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(IdealParameterData, self).build()

        self.state_block_class = IdealStateBlock

        # List of valid phases in property package
        if self.config.valid_phase == ('Liq', 'Vap') or \
                self.config.valid_phase == ('Vap', 'Liq'):
            self.phase_list = Set(initialize=['Liq', 'Vap'], ordered=True)
        elif self.config.valid_phase == 'Liq':
            self.phase_list = Set(initialize=['Liq'])
        else:
            self.phase_list = Set(initialize=['Vap'])

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mol': {
                'method': None,
                'units': 'mol/s'
            },
            'mole_frac_comp': {
                'method': None,
                'units': 'none'
            },
            'temperature': {
                'method': None,
                'units': 'K'
            },
            'pressure': {
                'method': None,
                'units': 'Pa'
            },
            'flow_mol_phase': {
                'method': None,
                'units': 'mol/s'
            },
            'dens_mol_phase': {
                'method': '_dens_mol_phase',
                'units': 'mol/m^3'
            },
            'pressure_sat': {
                'method': '_pressure_sat',
                'units': 'Pa'
            },
            'mole_frac_phase_comp': {
                'method': '_mole_frac_phase',
                'units': 'no unit'
            },
            'energy_internal_mol_phase_comp': {
                'method': '_energy_internal_mol_phase_comp',
                'units': 'J/mol'
            },
            'energy_internal_mol_phase': {
                'method': '_enenrgy_internal_mol_phase',
                'units': 'J/mol'
            },
            'enth_mol_phase_comp': {
                'method': '_enth_mol_phase_comp',
                'units': 'J/mol'
            },
            'enth_mol_phase': {
                'method': '_enth_mol_phase',
                'units': 'J/mol'
            },
            'entr_mol_phase_comp': {
                'method': '_entr_mol_phase_comp',
                'units': 'J/mol'
            },
            'entr_mol_phase': {
                'method': '_entr_mol_phase',
                'units': 'J/mol'
            },
            'temperature_bubble': {
                'method': '_temperature_bubble',
                'units': 'K'
            },
            'temperature_dew': {
                'method': '_temperature_dew',
                'units': 'K'
            },
            'pressure_bubble': {
                'method': '_pressure_bubble',
                'units': 'Pa'
            },
            'pressure_dew': {
                'method': '_pressure_dew',
                'units': 'Pa'
            },
            'fug_vap': {
                'method': '_fug_vap',
                'units': 'Pa'
            },
            'fug_liq': {
                'method': '_fug_liq',
                'units': 'Pa'
            },
            'dh_vap': {
                'method': '_dh_vap',
                'units': 'J/mol'
            },
            'ds_vap': {
                'method': '_ds_vap',
                'units': 'J/mol.K'
            }
        })

        obj.add_default_units({
            'time': 's',
            'length': 'm',
            'mass': 'g',
            'amount': 'mol',
            'temperature': 'K',
            'energy': 'J',
            'holdup': 'mol'
        })
Ejemplo n.º 21
0
class HelmholtzParameterBlockData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare(
        "phase_presentation",
        ConfigValue(
            default=PhaseType.MIX,
            domain=In(PhaseType),
            description="Set the way phases are presented to models",
            doc="""Set the way phases are presented to models. The MIX option
appears to the framework to be a mixed phase containing liquid and/or vapor.
The mixed option can simplify calculations at the unit model level since it can
be treated as a single phase, but unit models such as flash vessels will not be
able to treat the phases independently. The LG option presents as two separate
phases to the framework. The L or G options can be used if it is known for sure
that only one phase is present.
**default** - PhaseType.MIX
**Valid values:** {
**PhaseType.MIX** - Present a mixed phase with liquid and/or vapor,
**PhaseType.LG** - Present a liquid and vapor phase,
**PhaseType.L** - Assume only liquid can be present,
**PhaseType.G** - Assume only vapor can be present}""",
        ),
    )

    CONFIG.declare(
        "state_vars",
        ConfigValue(
            default=StateVars.PH,
            domain=In(StateVars),
            description="State variable set",
            doc="""The set of state variables to use. Depending on the use, one
state variable set or another may be better computationally. Usually pressure
and enthalpy are the best choice because they are well behaved during a phase
change.
**default** - StateVars.PH
**Valid values:** {
**StateVars.PH** - Pressure-Enthalpy,
**StateVars.TPX** - Temperature-Pressure-Quality}""",
        ),
    )
    def _set_parameters(
        self,
        library,
        state_block_class,
        component_list,
        phase_equilibrium_idx,
        phase_equilibrium_list,
        mw,
        temperature_crit,
        pressure_crit,
        dens_mass_crit,
        gas_const,
    ):
        """This function sets the parameters that are required for a Helmholtz
        equation of state parameter block, and ensures that all required parameters
        are set.

        """
        # Location of the *.so or *.dll file for external functions
        self.plib = library
        self.state_block_class = state_block_class
        self.component_list = component_list
        self.phase_equilibrium_idx = phase_equilibrium_idx
        self.phase_equilibrium_list = phase_equilibrium_list
        # Parameters, these should match what's in the C code
        self.temperature_crit = temperature_crit
        self.pressure_crit = pressure_crit
        self.dens_mass_crit = dens_mass_crit
        self.gas_const = gas_const
        self.mw = mw


    def build(self):
        super().build()
        # Location of the *.so or *.dll file for external functions
        # Phase list
        self.available = _available(self.plib)

        self.private_phase_list = Set(initialize=["Vap", "Liq"])
        if self.config.phase_presentation == PhaseType.MIX:
            self.phase_list = Set(initialize=["Mix"])
        elif self.config.phase_presentation == PhaseType.LG:
            self.phase_list = Set(initialize=["Vap", "Liq"])
        elif self.config.phase_presentation == PhaseType.L:
            self.phase_list = Set(initialize=["Liq"])
        elif self.config.phase_presentation == PhaseType.G:
            self.phase_list = Set(initialize=["Vap"])

        # State var set
        self.state_vars = self.config.state_vars

        self.smoothing_pressure_over = Param(
            mutable=True, initialize=1e-4, doc="Smooth max parameter (pressure over)"
        )
        self.smoothing_pressure_under = Param(
            mutable=True, initialize=1e-4, doc="Smooth max parameter (pressure under)"
        )

    @classmethod
    def define_metadata(cls, obj):
        obj.add_properties(
            {
                "temperature_crit": {"method": None, "units": "K"},
                "pressure_crit": {"method": None, "units": "Pa"},
                "dens_mass_crit": {"method": None, "units": "kg/m^3"},
                "gas_const": {"method": None, "units": "J/mol.K"},
                "mw": {"method": None, "units": "kg/mol"},
                "temperature_sat": {"method": "None", "units": "K"},
                "flow_mol": {"method": None, "units": "mol/s"},
                "flow_mass": {"method": None, "units": "kg/s"},
                "flow_vol": {"method": None, "units": "m^3/s"},
                "temperature": {"method": None, "units": "K"},
                "pressure": {"method": None, "units": "Pa"},
                "vapor_frac": {"method": None, "units": None},
                "dens_mass_phase": {"method": None, "units": "kg/m^3"},
                "temperature_red": {"method": None, "units": None},
                "pressure_sat": {"method": None, "units": "kPa"},
                "energy_internal_mol_phase": {"method": None, "units": "J/mol"},
                "enth_mol_phase": {"method": None, "units": "J/mol"},
                "entr_mol_phase": {"method": None, "units": "J/mol.K"},
                "cp_mol_phase": {"method": None, "units": "J/mol.K"},
                "cv_mol_phase": {"method": None, "units": "J/mol.K"},
                "speed_sound_phase": {"method": None, "units": "m/s"},
                "dens_mol_phase": {"method": None, "units": "mol/m^3"},
                "therm_cond_phase": {"method": None, "units": "W/m.K"},
                "visc_d_phase": {"method": None, "units": "Pa.s"},
                "visc_k_phase": {"method": None, "units": "m^2/s"},
                "phase_frac": {"method": None, "units": None},
                "flow_mol_comp": {"method": None, "units": "mol/s"},
                "energy_internal_mol": {"method": None, "units": "J/mol"},
                "enth_mol": {"method": None, "units": "J/mol"},
                "entr_mol": {"method": None, "units": "J/mol.K"},
                "cp_mol": {"method": None, "units": "J/mol.K"},
                "cv_mol": {"method": None, "units": "J/mol.K"},
                "heat_capacity_ratio": {"method": None, "units": None},
                "dens_mass": {"method": None, "units": "kg/m^3"},
                "dens_mol": {"method": None, "units": "mol/m^3"},
                "dh_vap_mol": {"method": None, "units": "J/mol"},
            }
        )

        obj.add_default_units(
            {
                "time": "s",
                "length": "m",
                "mass": "kg",
                "amount": "mol",
                "temperature": "K",
                "energy": "J",
                "holdup": "mol",
            }
        )
Ejemplo n.º 22
0
class PropParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        """
        Callable method for Block construction.
        """
        super(PropParameterData, self).build()

        self._state_block_class = PropStateBlock

        # phases
        self.Liq = LiquidPhase()

        # components
        self.H2O = Solvent()
        self.Na = Solute()
        self.Ca = Solute()
        self.Mg = Solute()
        self.SO4 = Solute()
        self.Cl = Solute()

        # molecular weight
        mw_comp_data = {
            "H2O": 18.015e-3,
            "Na": 22.990e-3,
            "Ca": 40.078e-3,
            "Mg": 24.305e-3,
            "SO4": 96.06e-3,
            "Cl": 35.453e-3,
        }

        self.mw_comp = Param(
            self.component_list,
            mutable=False,
            initialize=extract_data(mw_comp_data),
            units=pyunits.kg / pyunits.mol,
            doc="Molecular weight",
        )

        self.dens_mass = Param(
            mutable=False,
            initialize=1000,
            units=pyunits.kg / pyunits.m**3,
            doc="Density",
        )

        self.cp = Param(mutable=False,
                        initialize=4.2e3,
                        units=pyunits.J / (pyunits.kg * pyunits.K))

        # ---default scaling---
        self.set_default_scaling("temperature", 1e-2)
        self.set_default_scaling("pressure", 1e-6)

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            "flow_mass_phase_comp": {
                "method": None
            },
            "temperature": {
                "method": None
            },
            "pressure": {
                "method": None
            },
            "mass_frac_phase_comp": {
                "method": "_mass_frac_phase_comp"
            },
            "flow_vol": {
                "method": "_flow_vol"
            },
            "flow_mol_phase_comp": {
                "method": "_flow_mol_phase_comp"
            },
            "conc_mol_phase_comp": {
                "method": "_conc_mol_phase_comp"
            },
            "enth_flow": {
                "method": "_enth_flow"
            },
        })

        obj.add_default_units({
            "time": pyunits.s,
            "length": pyunits.m,
            "mass": pyunits.kg,
            "amount": pyunits.mol,
            "temperature": pyunits.K,
        })
Ejemplo n.º 23
0
class DSPMDEParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    CONFIG.declare("solute_list", ConfigValue(
        domain=list,
        description="List of solute species names"))
    CONFIG.declare("stokes_radius_data", ConfigValue(
        default={},
        domain=dict,
        description="Dict of solute species names and Stokes radius data"))
    CONFIG.declare("diffusivity_data", ConfigValue(
        default={},
        domain=dict,
        description="Dict of solute species names and bulk ion diffusivity data"))
    CONFIG.declare("mw_data", ConfigValue(
        default={},
        domain=dict,
        description="Dict of component names and molecular weight data"))
    CONFIG.declare("charge", ConfigValue(
        default={},
        domain=dict,
        description="Ion charge"))
    CONFIG.declare("activity_coefficient_model", ConfigValue(
        default=ActivityCoefficientModel.ideal,
        domain=In(ActivityCoefficientModel),
        description="Activity coefficient model construction flag",
        doc="""
           Options to account for activity coefficient model.
    
           **default** - ``ActivityCoefficientModel.ideal``
    
       .. csv-table::
           :header: "Configuration Options", "Description"
    
           "``ActivityCoefficientModel.ideal``", "Activity coefficients equal to 1 assuming ideal solution"
           "``ActivityCoefficientModel.davies``", "Activity coefficients estimated via Davies model"
       """))

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(DSPMDEParameterData, self).build()

        self._state_block_class = DSPMDEStateBlock

        # components
        self.H2O = Solvent()

        for j in self.config.solute_list:
            self.add_component(str(j), Solute())

        # phases
        self.Liq = LiquidPhase()

        # reference
        # Todo: enter any relevant references

        # TODO: consider turning parameters into variables for future param estimation
        # molecular weight
        self.mw_comp = Param(
            self.component_list,
            mutable=True,
            default=18e-3,
            initialize=self.config.mw_data,
            units=pyunits.kg/pyunits.mol,
            doc="Molecular weight")
        # Stokes radius
        self.radius_stokes_comp = Param(
            self.solute_set,
            mutable=True,
            default=1e-10,
            initialize=self.config.stokes_radius_data,
            units=pyunits.m,
            doc="Stokes radius of solute")
        self.diffus_phase_comp = Param(
            self.phase_list,
            self.solute_set,
            mutable=True,
            default=1e-9,
            initialize=self.config.diffusivity_data,
            units=pyunits.m ** 2 * pyunits.s ** -1,
            doc="Bulk diffusivity of ion")
        self.visc_d_phase = Param(
            self.phase_list,
            mutable=True,
            default=1e-3,
            initialize=1e-3, #TODO:revisit- assuming ~ 1e-3 Pa*s for pure water
            units=pyunits.Pa * pyunits.s,
            doc="Fluid viscosity")
        # Ion charge
        self.charge_comp = Param(
            self.solute_set,
            mutable=True,
            default=1,
            initialize=self.config.charge,
            units=pyunits.dimensionless,
            doc="Ion charge")
        # Dielectric constant of water
        self.dielectric_constant = Param(
            mutable=True,
            default=80.4,
            initialize=80.4, #todo: make a variable with parameter values for coefficients in the function of temperature
            units=pyunits.dimensionless,
            doc="Dielectric constant of water")


        # ---default scaling---
        self.set_default_scaling('temperature', 1e-2)
        self.set_default_scaling('pressure', 1e-6)
        self.set_default_scaling('dens_mass_phase', 1e-3, index='Liq')
        self.set_default_scaling('visc_d_phase', 1e3, index='Liq')


    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties(
            {'flow_mol_phase_comp': {'method': None},
             'temperature': {'method': None},
             'pressure': {'method': None},
             'flow_mass_phase_comp': {'method': '_flow_mass_phase_comp'},
             'mass_frac_phase_comp': {'method': '_mass_frac_phase_comp'},
             'dens_mass_phase': {'method': '_dens_mass_phase'},
             'flow_vol_phase': {'method': '_flow_vol_phase'},
             'flow_vol': {'method': '_flow_vol'},
             'conc_mol_phase_comp': {'method': '_conc_mol_phase_comp'},
             'conc_mass_phase_comp': {'method': '_conc_mass_phase_comp'},
             'mole_frac_phase_comp': {'method': '_mole_frac_phase_comp'},
             'molality_comp': {'method': '_molality_comp'},
             'diffus_phase_comp': {'method': '_diffus_phase_comp'},
             'visc_d_phase': {'method': '_visc_d_phase'},
             'pressure_osm': {'method': '_pressure_osm'},
             'radius_stokes_comp': {'method': '_radius_stokes_comp'},
             'mw_comp': {'method': '_mw_comp'},
             'charge_comp': {'method': '_charge_comp'},
             'act_coeff_phase_comp': {'method': '_act_coeff_phase_comp'},
             'dielectric_constant': {'method': '_dielectric_constant'}
             })

        obj.add_default_units({'time': pyunits.s,
                               'length': pyunits.m,
                               'mass': pyunits.kg,
                               'amount': pyunits.mol,
                               'temperature': pyunits.K})
Ejemplo n.º 24
0
class HDAParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        '''
        Callable method for Block construction.
        '''
        super(HDAParameterData, self).build()

        self.state_block_class = IdealStateBlock

        self.component_list = Set(
            initialize=['benzene', 'toluene', 'hydrogen', 'methane'])

        self.phase_list = Set(initialize=['Liq', 'Vap'], ordered=True)

        # List of components in each phase (optional)
        self.phase_comp = {
            "Liq": self.component_list,
            "Vap": self.component_list
        }

        # List of phase equilibrium index
        self.phase_equilibrium_idx = Set(initialize=[1, 2, 3, 4, 5])

        self.phase_equilibrium_list = \
            {1: ["benzene", ("Vap", "Liq")],
             2: ["toluene", ("Vap", "Liq")],
             3: ["hydrogen", ("Vap", "Liq")],
             4: ["methane", ("Vap", "Liq")],
             5: ["diphenyl", ("Vap", "Liq")]}

        # Thermodynamic reference state
        self.pressure_ref = Param(mutable=True,
                                  default=101325,
                                  doc='Reference pressure [Pa]')
        self.temperature_ref = Param(mutable=True,
                                     default=298.15,
                                     doc='Reference temperature [K]')

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        pressure_crit_data = {
            'benzene': 48.9e5,
            'toluene': 41e5,
            'hydrogen': 12.9e5,
            'methane': 46e5,
            'diphenyl': 38.5e5
        }

        self.pressure_crit = Param(self.component_list,
                                   within=NonNegativeReals,
                                   mutable=False,
                                   initialize=extract_data(pressure_crit_data),
                                   doc='Critical pressure [Pa]')

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        temperature_crit_data = {
            'benzene': 562.2,
            'toluene': 591.8,
            'hydrogen': 33.0,
            'methane': 190.4,
            'diphenyl': 789
        }

        self.temperature_crit = Param(
            self.component_list,
            within=NonNegativeReals,
            mutable=False,
            initialize=extract_data(temperature_crit_data),
            doc='Critical temperature [K]')

        # Gas Constant
        self.gas_const = Param(within=NonNegativeReals,
                               mutable=False,
                               default=8.314,
                               doc='Gas Constant [J/mol.K]')

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        mw_comp_data = {
            'benzene': 78.1136E-3,
            'toluene': 92.1405E-3,
            'hydrogen': 2.016e-3,
            'methane': 16.043e-3,
            'diphenyl': 154.212e-4
        }

        self.mw_comp = Param(self.component_list,
                             mutable=False,
                             initialize=extract_data(mw_comp_data),
                             doc="molecular weight Kg/mol")

        # Constants for liquid densities
        # Source: Perry's Chemical Engineers Handbook
        #         - Robert H. Perry (Cp_liq)
        dens_liq_data = {
            ('benzene', '1'): 1.0162,
            ('benzene', '2'): 0.2655,
            ('benzene', '3'): 562.16,
            ('benzene', '4'): 0.28212,
            ('toluene', '1'): 0.8488,
            ('toluene', '2'): 0.26655,
            ('toluene', '3'): 591.8,
            ('toluene', '4'): 0.2878,
            ('hydrogen', '1'): 5.414,
            ('hydrogen', '2'): 0.34893,
            ('hydrogen', '3'): 33.19,
            ('hydrogen', '4'): 0.2706,
            ('methane', '1'): 2.9214,
            ('methane', '2'): 0.28976,
            ('methane', '3'): 190.56,
            ('methane', '4'): 0.28881,
            ('diphenyl', '1'): 0.5039,
            ('diphenyl', '2'): 0.25273,
            ('diphenyl', '3'): 789.26,
            ('diphenyl', '4'): 0.281
        }

        self.dens_liq_params = Param(
            self.component_list, ['1', '2', '3', '4'],
            mutable=False,
            initialize=extract_data(dens_liq_data),
            doc="Parameters to compute liquid densities")

        # Boiling point at standard pressure
        # Source: Perry's Chemical Engineers Handbook
        #         - Robert H. Perry (Cp_liq)
        bp_data = {
            ('benzene'): 353.25,
            ('toluene'): 383.95,
            ('hydrogen'): 20.45,
            ('methane'): 111.75,
            ('diphenyl'): 528.05
        }

        self.temperature_boil = Param(
            self.component_list,
            mutable=False,
            initialize=extract_data(bp_data),
            doc="Pure component boiling points at standard pressure [K]")

        # Constants for specific heat capacity, enthalpy
        # Sources: The Properties of Gases and Liquids (1987)
        #         4th edition, Chemical Engineering Series - Robert C. Reid
        #         Perry's Chemical Engineers Handbook
        #         - Robert H. Perry (Cp_liq)
        cp_ig_data = {
            ('Liq', 'benzene', '1'): 1.29E5,
            ('Liq', 'benzene', '2'): -1.7E2,
            ('Liq', 'benzene', '3'): 6.48E-1,
            ('Liq', 'benzene', '4'): 0,
            ('Liq', 'benzene', '5'): 0,
            ('Vap', 'benzene', '1'): -3.392E1,
            ('Vap', 'benzene', '2'): 4.739E-1,
            ('Vap', 'benzene', '3'): -3.017E-4,
            ('Vap', 'benzene', '4'): 7.130E-8,
            ('Vap', 'benzene', '5'): 0,
            ('Liq', 'toluene', '1'): 1.40E5,
            ('Liq', 'toluene', '2'): -1.52E2,
            ('Liq', 'toluene', '3'): 6.95E-1,
            ('Liq', 'toluene', '4'): 0,
            ('Liq', 'toluene', '5'): 0,
            ('Vap', 'toluene', '1'): -2.435E1,
            ('Vap', 'toluene', '2'): 5.125E-1,
            ('Vap', 'toluene', '3'): -2.765E-4,
            ('Vap', 'toluene', '4'): 4.911E-8,
            ('Vap', 'toluene', '5'): 0,
            ('Liq', 'hydrogen', '1'): 0,  # 6.6653e1,
            ('Liq', 'hydrogen', '2'): 0,  # 6.7659e3,
            ('Liq', 'hydrogen', '3'): 0,  # -1.2363e2,
            ('Liq', 'hydrogen', '4'): 0,  # 4.7827e2, # Eqn 2
            ('Liq', 'hydrogen', '5'): 0,
            ('Vap', 'hydrogen', '1'): 2.714e1,
            ('Vap', 'hydrogen', '2'): 9.274e-3,
            ('Vap', 'hydrogen', '3'): -1.381e-5,
            ('Vap', 'hydrogen', '4'): 7.645e-9,
            ('Vap', 'hydrogen', '5'): 0,
            ('Liq', 'methane', '1'): 0,  # 6.5708e1,
            ('Liq', 'methane', '2'): 0,  # 3.8883e4,
            ('Liq', 'methane', '3'): 0,  # -2.5795e2,
            ('Liq', 'methane', '4'): 0,  # 6.1407e2, # Eqn 2
            ('Liq', 'methane', '5'): 0,
            ('Vap', 'methane', '1'): 1.925e1,
            ('Vap', 'methane', '2'): 5.213e-2,
            ('Vap', 'methane', '3'): 1.197e-5,
            ('Vap', 'methane', '4'): -1.132e-8,
            ('Vap', 'methane', '5'): 0,
            ('Liq', 'diphenyl', '1'): 1.2177e5,
            ('Liq', 'diphenyl', '2'): 4.2930e2,
            ('Liq', 'diphenyl', '3'): 0,
            ('Liq', 'diphenyl', '4'): 0,
            ('Liq', 'diphenyl', '5'): 0,
            ('Vap', 'diphenyl', '1'): -9.707e1,
            ('Vap', 'diphenyl', '2'): 1.106e0,
            ('Vap', 'diphenyl', '3'): -8.855e-4,
            ('Vap', 'diphenyl', '4'): 2.790e-7,
            ('Vap', 'diphenyl', '5'): 0
        }

        self.cp_ig = Param(self.phase_list,
                           self.component_list, ['1', '2', '3', '4', '5'],
                           mutable=False,
                           initialize=extract_data(cp_ig_data),
                           doc="parameters to compute Cp_comp")

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        # fitted to Antoine form
        # H2, Methane from NIST webbook
        pressure_sat_coeff_data = {
            ('benzene', 'A'): 4.202,
            ('benzene', 'B'): 1322,
            ('benzene', 'C'): -38.56,
            ('toluene', 'A'): 4.216,
            ('toluene', 'B'): 1435,
            ('toluene', 'C'): -43.33,
            ('hydrogen', 'A'): 3.543,
            ('hydrogen', 'B'): 99.40,
            ('hydrogen', 'C'): 7.726,
            ('methane', 'A'): 3.990,
            ('methane', 'B'): 443.0,
            ('methane', 'C'): -0.49,
            ('diphenyl', 'A'): 4.345,
            ('diphenyl', 'B'): 1988,
            ('diphenyl', 'C'): -70.82
        }

        self.pressure_sat_coeff = Param(
            self.component_list, ['A', 'B', 'C'],
            mutable=False,
            initialize=extract_data(pressure_sat_coeff_data),
            doc="parameters to compute Cp_comp")

        # Source: The Properties of Gases and Liquids (1987)
        # 4th edition, Chemical Engineering Series - Robert C. Reid
        dh_vap = {
            'benzene': 3.387e4,
            'toluene': 3.8262e4,
            'hydrogen': 0,
            'methane': 0,
            "diphenyl": 6.271e4
        }

        self.dh_vap = Param(self.component_list,
                            mutable=False,
                            initialize=extract_data(dh_vap),
                            doc="heat of vaporization")

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            'flow_mol': {
                'method': None,
                'units': 'mol/s'
            },
            'flow_mol_phase_comp': {
                'method': None,
                'units': 'mol/s'
            },
            'mole_frac': {
                'method': None,
                'units': 'none'
            },
            'temperature': {
                'method': None,
                'units': 'K'
            },
            'pressure': {
                'method': None,
                'units': 'Pa'
            },
            'flow_mol_phase': {
                'method': None,
                'units': 'mol/s'
            },
            'dens_mol_phase': {
                'method': '_dens_mol_phase',
                'units': 'mol/m^3'
            },
            'pressure_sat': {
                'method': '_pressure_sat',
                'units': 'Pa'
            },
            'mole_frac_phase': {
                'method': '_mole_frac_phase',
                'units': 'no unit'
            },
            'enth_mol_phase_comp': {
                'method': '_enth_mol_phase_comp',
                'units': 'J/mol'
            },
            'enth_mol_phase': {
                'method': '_enth_mol_phase',
                'units': 'J/mol'
            },
            'entr_mol_phase_comp': {
                'method': '_entr_mol_phase_comp',
                'units': 'J/mol'
            },
            'entr_mol_phase': {
                'method': '_entr_mol_phase',
                'units': 'J/mol'
            },
            'temperature_bubble': {
                'method': '_temperature_bubble',
                'units': 'K'
            },
            'temperature_dew': {
                'method': '_temperature_dew',
                'units': 'K'
            },
            'pressure_bubble': {
                'method': '_pressure_bubble',
                'units': 'Pa'
            },
            'pressure_dew': {
                'method': '_pressure_dew',
                'units': 'Pa'
            },
            'fug_vap': {
                'method': '_fug_vap',
                'units': 'Pa'
            },
            'fug_liq': {
                'method': '_fug_liq',
                'units': 'Pa'
            },
            'dh_vap': {
                'method': '_dh_vap',
                'units': 'J/mol'
            },
            'ds_vap': {
                'method': '_ds_vap',
                'units': 'J/mol.K'
            }
        })

        obj.add_default_units({
            'time': 's',
            'length': 'm',
            'mass': 'g',
            'amount': 'mol',
            'temperature': 'K',
            'energy': 'J',
            'holdup': 'mol'
        })
Ejemplo n.º 25
0
class CoagulationParameterData(PhysicalParameterBlock):
    CONFIG = PhysicalParameterBlock.CONFIG()

    def build(self):
        """
        Callable method for Block construction.
        """
        super(CoagulationParameterData, self).build()

        self._state_block_class = CoagulationStateBlock

        # phases
        self.Liq = LiquidPhase()

        # components
        self.H2O = Component()
        self.TSS = Component()
        self.TDS = Component()
        self.Sludge = Component()

        #   heat capacity of liquid
        self.cp = Param(mutable=False,
                        initialize=4184,
                        units=pyunits.J / (pyunits.kg * pyunits.K))

        #   reference density of liquid
        self.ref_dens_liq = Param(
            domain=Reals,
            initialize=999.26,
            mutable=True,
            units=pyunits.kg / pyunits.m**3,
            doc="Reference water mass density parameter @ 0 oC and no salts",
        )

        #   change in liquid density with increasing mass fraction of salts/solids
        self.dens_slope = Param(
            domain=Reals,
            initialize=879.04,
            mutable=True,
            units=pyunits.kg / pyunits.m**3,
            doc=
            "Relative increase in liquid density with mass fraction of salts",
        )

        #   adjustment parameters for density change with temperature
        #   Density calculation as a function of temperature and pressure
        #   --------------------------------------------------------------
        #   Engineering Toolbox. Water - Density, Specific Weight, and
        #   Thermal Expansion Coefficients. (2003) https://www.engineeringtoolbox.com/
        #   water-density-specific-weight-d_595.html [Accessed 02-01-2022]
        self.dens_param_A = Param(
            domain=Reals,
            initialize=-2.9335e-6,
            mutable=True,
            units=pyunits.K**-2,
            doc="Density correction parameter A for temperature variation",
        )

        self.dens_param_B = Param(
            domain=Reals,
            initialize=0.001529811,
            mutable=True,
            units=pyunits.K**-1,
            doc="Density correction parameter B for temperature variation",
        )

        self.dens_param_C = Param(
            domain=Reals,
            initialize=0.787973,
            mutable=True,
            units=pyunits.dimensionless,
            doc="Density correction parameter C for temperature variation",
        )

        #   Correction factors for changes in density with changes in pressure
        self.ref_pressure_correction = Param(
            domain=Reals,
            initialize=1.0135,
            mutable=True,
            units=pyunits.dimensionless,
            doc=
            "Density reference correction parameter for changes in pressure",
        )

        self.ref_pressure_slope = Param(
            domain=Reals,
            initialize=4.9582e-10,
            mutable=True,
            units=pyunits.Pa**-1,
            doc="Slope of density change as a function of pressure",
        )

        #   Adjustment for dynamic viscosity as a function of temperature
        #   -------------------------------------------------------------
        #   D.S. Viswananth, G. Natarajan. Data Book on the Viscosity of
        #     Liquids. Hemisphere Publishing Corp. (1989)
        self.mu_A = Param(
            domain=Reals,
            initialize=2.939e-5,
            mutable=True,
            units=pyunits.kg / pyunits.m / pyunits.s,
            doc="Pre-exponential factor for viscosity calculation",
        )

        self.mu_B = Param(
            domain=Reals,
            initialize=507.88,
            mutable=True,
            units=pyunits.K,
            doc="Exponential numerator term for viscosity calculation",
        )

        self.mu_C = Param(
            domain=Reals,
            initialize=149.3,
            mutable=True,
            units=pyunits.K,
            doc="Exponential denominator term for viscosity calculation",
        )

        # ---default scaling---
        self.set_default_scaling("temperature", 1e-2)
        self.set_default_scaling("pressure", 1e-6)

    @classmethod
    def define_metadata(cls, obj):
        """Define properties supported and units."""
        obj.add_properties({
            "flow_mass_phase_comp": {
                "method": None
            },
            "temperature": {
                "method": None
            },
            "pressure": {
                "method": None
            },
            "mass_frac_phase_comp": {
                "method": "_mass_frac_phase_comp"
            },
            "dens_mass_phase": {
                "method": "_dens_mass_phase"
            },
            "flow_vol_phase": {
                "method": "_flow_vol_phase"
            },
            "conc_mass_phase_comp": {
                "method": "_conc_mass_phase_comp"
            },
            "visc_d": {
                "method": "_visc_d"
            },
            "enth_flow": {
                "method": "_enth_flow"
            },
        })

        obj.add_default_units({
            "time": pyunits.s,
            "length": pyunits.m,
            "mass": pyunits.kg,
            "amount": pyunits.mol,
            "temperature": pyunits.K,
        })