IDAES / idaes-pse

The IDAES Process Systems Engineering Framework
https://idaes-pse.readthedocs.io/
Other
217 stars 235 forks source link

Enthalpy as state variable doesn't work for generic property package #516

Closed dallan-keylogic closed 2 weeks ago

dallan-keylogic commented 3 years ago

The generic_property package does not support enthalpy as a state variable, at least for cubic equations of state.

from pyomo.environ import ConcreteModel
from pyomo.environ import units as pyunits                            

from idaes.core import FlowsheetBlock

from idaes.generic_models.properties.core.generic.generic_property import (
    GenericParameterBlock)
from idaes.generic_models.unit_models import Feed

from idaes.core import VaporPhase, LiquidPhase, Component, PhaseType

from idaes.generic_models.properties.core.state_definitions import FcPh
from idaes.generic_models.properties.core.eos.ceos import Cubic, CubicType
from idaes.generic_models.properties.core.phase_equil.forms import log_fugacity
from idaes.generic_models.properties.core.phase_equil import SmoothVLE

from idaes.generic_models.properties.core.pure import NIST
m = ConcreteModel()
m.fs = FlowsheetBlock(default={"dynamic": False})
components = {
    'H2O': {
        'type': Component,
        'valid_phase_types': [PhaseType.vaporPhase, PhaseType.liquidPhase],
        "phase_equilibrium_form": {("Vap", "Liq"): log_fugacity},
        'elemental_composition': {'H': 2, 'O': 1},
        'enth_mol_ig_comp': NIST,
        'entr_mol_ig_comp': NIST,
        'pressure_sat_comp': NIST,
        'parameter_data': {
            'mw': (0.01801528, pyunits.kg/pyunits.mol),
            'pressure_crit': (221.2e5, pyunits.Pa),
            'temperature_crit': (647.3, pyunits.K),
            'omega': 0.344,
            'cp_mol_ig_comp_coeff': {
                'A': 30.092,
                'B': 6.832514,
                'C': 6.793435,
                'D': -2.53448,
                'E': 0.082139,
                'F': -250.881,
                'G': 223.3967,
                'H': -241.8264},
            'pressure_sat_comp_coeff': { # NIST <- Stull 1947
                'A': 4.6543,
                'B': 1435.264,
                'C': -64.848},
        }
    }
}
phase_dicts = {
    "Vap": {
        "type": VaporPhase,
        "equation_of_state": Cubic,
        "equation_of_state_options": {"type": CubicType.PR}
    },
    "Liq": {
        "type": LiquidPhase,
        "equation_of_state": Cubic,
        "equation_of_state_options": {"type": CubicType.PR}
    },
}

configuration = {
    "components": components,
    "parameter_data": {"PR_kappa" : {("H2O","H2O") : 0}},
    "phases": phase_dicts,
    # Set base units of measurement
    "base_units": {"time": pyunits.s,
                   "length": pyunits.m,
                   "mass": pyunits.kg,
                   "amount": pyunits.mol,
                   "temperature": pyunits.K},

    # Specifying state definition
    "state_definition": FcPh,
    "pressure_ref": (101325, pyunits.Pa),
    "temperature_ref": (298.15, pyunits.K),
    "phases_in_equilibrium" : [("Liq","Vap")],
    "phase_equilibrium_state" : {("Liq","Vap") : SmoothVLE},
    "state_bounds" : {"flow_mol_comp": (0, 8000, 50000, pyunits.mol/pyunits.s),
            "enth_mol": (-1E6, 1000, 1E6, pyunits.kJ/pyunits.mol),
            "pressure": (5e2, 1.3e5, 1e7, pyunits.Pa)
            }
}

m.fs.properties = GenericParameterBlock(default=configuration)

m.fs.feed = Feed(default={"property_package": m.fs.properties})

PropertyNotSupportedError: fs.feed.properties[0.0] package property metadata method does not contain a method for PR_am. Please select a package which supports the necessary properties for your process.

This appears to be because, in order to define the enthalpy, FcPh.py tries to access methods for the cubic equation of state before it is defined in the parameter block:

class GenericStateBlockData(StateBlockData):
    CONFIG = StateBlockData.CONFIG()

    def build(self):
        super(GenericStateBlockData, self).build()

        # Add state variables and associated methods
        self.params.config.state_definition.define_state(self)

        # Add equilibrium temperature variable if required
        if (self.params.config.phases_in_equilibrium is not None and
                (not self.config.defined_state or self.always_flash)):

            t_units = self.params.get_metadata().default_units["temperature"]
            self._teq = Var(
                self.params._pe_pairs,
                initialize=value(self.temperature),
                doc='Temperature for calculating phase equilibrium',
                units=t_units)

        # Create common components for each property package
        for p in self.phase_list:
            pobj = self.params.get_phase(p)
            pobj.config.equation_of_state.common(self, pobj)
andrewlee94 commented 2 weeks ago

This was fixed in #1505