Source code for idaes.models.unit_models.feed_flash

#################################################################################
# The Institute for the Design of Advanced Energy Systems Integrated Platform
# Framework (IDAES IP) was produced under the DOE Institute for the
# Design of Advanced Energy Systems (IDAES).
#
# Copyright (c) 2018-2024 by the software owners: The Regents of the
# University of California, through Lawrence Berkeley National Laboratory,
# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon
# University, West Virginia University Research Corporation, et al.
# All rights reserved.  Please see the files COPYRIGHT.md and LICENSE.md
# for full copyright and license information.
#################################################################################
"""
Standard IDAES Feed block with phase equilibrium.
"""
from enum import Enum

# Import Pyomo libraries
from pyomo.environ import Reference
from pyomo.common.config import ConfigBlock, ConfigValue, In

# Import IDAES cores
from idaes.core import (
    ControlVolume0DBlock,
    declare_process_block_class,
    MaterialBalanceType,
    MomentumBalanceType,
    UnitModelBlockData,
    useDefault,
)
from idaes.core.util.config import is_physical_parameter_block
from idaes.core.util.tables import create_stream_table_dataframe
from idaes.core.util.initialization import fix_state_vars

__author__ = "Andrew Lee"


# Enumerate options for material balances
class FlashType(Enum):
    """
    Enum of supported flash types.
    """

    isothermal = 1
    isenthalpic = 2


[docs] @declare_process_block_class("FeedFlash") class FeedFlashData(UnitModelBlockData): """ Standard Feed block with phase equilibrium """ CONFIG = ConfigBlock() CONFIG.declare( "dynamic", ConfigValue( domain=In([False]), default=False, description="Dynamic model flag - must be False", doc="""Feed units do not support dynamic behavior.""", ), ) CONFIG.declare( "has_holdup", ConfigValue( default=False, domain=In([False]), description="Holdup construction flag - must be False", doc="""Feed units do not have defined volume, thus this must be False.""", ), ) CONFIG.declare( "material_balance_type", ConfigValue( default=MaterialBalanceType.useDefault, domain=In(MaterialBalanceType), description="Material balance construction flag", doc="""Indicates what type of mass balance should be constructed, **default** - MaterialBalanceType.useDefault. **Valid values:** { **MaterialBalanceType.useDefault - refer to property package for default balance type **MaterialBalanceType.none** - exclude material balances, **MaterialBalanceType.componentPhase** - use phase component balances, **MaterialBalanceType.componentTotal** - use total component balances, **MaterialBalanceType.elementTotal** - use total element balances, **MaterialBalanceType.total** - use total material balance.}""", ), ) CONFIG.declare( "flash_type", ConfigValue( default=FlashType.isothermal, domain=In(FlashType), description="Type of flash to perform", doc="""Indicates what type of flash operation should be used. **default** - FlashType.isothermal. **Valid values:** { **FlashType.isothermal** - specify temperature, **FlashType.isenthalpic** - specify enthalpy.}""", ), ) CONFIG.declare( "property_package", ConfigValue( default=useDefault, domain=is_physical_parameter_block, description="Property package to use for control volume", doc="""Property parameter object used to define property calculations, **default** - useDefault. **Valid values:** { **useDefault** - use default package from parent model or flowsheet, **PhysicalParameterObject** - a PhysicalParameterBlock object.}""", ), ) CONFIG.declare( "property_package_args", ConfigBlock( implicit=True, description="Arguments to use for constructing property packages", doc="""A ConfigBlock with arguments to be passed to a property block(s) and used when constructing these, **default** - None. **Valid values:** { see property package for documentation.}""", ), )
[docs] def build(self): """ Begin building model. Args: None Returns: None """ # Call UnitModel.build to setup dynamics super(FeedFlashData, self).build() # Build Control Volume self.control_volume = ControlVolume0DBlock( dynamic=self.config.dynamic, has_holdup=self.config.has_holdup, property_package=self.config.property_package, property_package_args=self.config.property_package_args, ) # No need for control volume geometry self.control_volume.add_state_blocks(has_phase_equilibrium=True) self.control_volume.add_material_balances( balance_type=self.config.material_balance_type, has_phase_equilibrium=True ) # Add isothermal constraint if self.config.flash_type == FlashType.isothermal: @self.Constraint(self.flowsheet().time, doc="Isothermal constraint") def isothermal(b, t): return ( b.control_volume.properties_in[t].temperature == b.control_volume.properties_out[t].temperature ) elif self.config.flash_type == FlashType.isenthalpic: @self.Constraint(self.flowsheet().time, doc="Isothermal constraint") def isenthalpic(b, t): cv = b.control_volume return sum( cv.properties_in[t].get_enthalpy_flow_terms(p) for p in cv.properties_in[t].phase_list ) == sum( cv.properties_out[t].get_enthalpy_flow_terms(p) for p in cv.properties_in[t].phase_list ) self.control_volume.add_momentum_balances( balance_type=MomentumBalanceType.pressureTotal ) # Add references to all feed state vars s_vars = self.control_volume.properties_in[ self.flowsheet().time.first() ].define_state_vars() for s in s_vars: l_name = s_vars[s].local_name if s_vars[s].is_indexed(): slicer = self.control_volume.properties_in[:].component(l_name)[...] else: slicer = self.control_volume.properties_in[:].component(l_name) r = Reference(slicer) setattr(self, s, r) # Add Ports self.add_outlet_port()
def _get_stream_table_contents(self, time_point=0): return create_stream_table_dataframe( {"Outlet": self.outlet}, time_point=time_point )
[docs] def fix_initialization_states(self): """ Fix feed state variables Returns: None """ fix_state_vars(self.control_volume.properties_in)