BoilerHeatExchanger2D#

The BoilerHeatExchanger2D model can be used to represent boiler heat exchangers in sub-critical and super critical power plant flowsheets (i.e. econmizer, primary superheater, secondary superheater, finishing superheater, reheater, etc.). The model consists of a shell and tube crossflow heat exchanger, in which the shell is used as the gas side and the tube is used as the water or steam side. Due to the fluid temperature changes along the flow paths inside and outside of the tubes, the velocities of the fluids also change from the inlet to the outlet, causing the changes of heat transfer coefficients and friction factors on both sides along the flow paths. If the flows on both sides can be discretized along the flow paths, local temperature difference between the hot and cold streams (the driving force for heat transfer), local heat transfer coefficients and local friction factors can be used and a more accurate model can be constructed. Figure 1 shows a schematic of the shell and tube cross-flow heat exchanger. In this figure, the hot fluid on the shell side flows from left to right while the cold fluid flows through the tubes up and down. Notice that the cold fluid may enter the tube bundle in multiple rows (2 rows shown in the figure) and flow in parallel. The dash lines show the discretization along the flow path of the hot shell-side flow. The dash lines also cut the tube side flow to multiple segments with the direction of the flow inside the tube switching in two neighboring segments. The flow properties such as heat transfer coefficients and friction factors are calculated in individual discretized elements. Meanwhile the overall flow configuration is either a co-current or counter-current. Counter-current configuration are shown in Figure 1. Since the tube-side flow switches direction from one discretized section to another, pressure drop due the U-turn is also modeled based on the loss coefficient of the U-turn. If the elevation changes between the tube inlet and outlet, the pressure change due to gravity for the tube side fluid is also modeled in each element. Rigorous heat transfer calculations (convective heat transfer for shell side, and convective heat transfer for tube side) and shell and tube pressure drop calculations have been included.

../../../../_images/boiler2D_1.png

Cross-flow heat exchanger#

In a transient heat transfer process such as in a load ramping operating condition, tube metal wall contains internal energy and its change with time represents the accumulation term (source or sink) in the energy conservation equation. Due to the high density and high heat capacity of the tube metal, its energy holdup should not be ignored. In other words, the transient tube wall temperatures and its distribution along the wall thickness and along the flow path need to be solved. In addition to the discretization along the flow path direction, the discretization along the tube wall thickness at each discretized flow path section is required, which make the heat exchanger model a 2-D model. Besides, the temperature gradient along the tube thickness is also required to calculate the thermal stress and other equipment health related properties. Figure 2 shows the discretization of tube wall temperature along the tube radius direction. The transient tube wall temperature T_(w,r) at each discretized radius r is calculated based on transient heat conduction equation(Eqn. 1), and in the cylindrical coordinate system the heat conduction equation is shown in equation 2.

../../../../_images/boiler2D_2.png

Cross-flow heat exchanger#

where, T_(w,r) is the tube metal temperature, t is time, alfa is termal diffusivity of the tube metal, typically steel, and r is the radius. This partial differential equation can be discretized by Pyomo-DAE in the radius direction. The heat accumulation in the tube metal is represented by the solution of the transient temperatures along the radius direction.

The HeatExchangerCrossFlow2D_Header model can be imported from idaes.models_extra.power_generation.unit_models, while additional rules and utility functions can be imported from idaes.models_extra.power_generation.unit_models.boiler_heat_exchanger2D.

Degrees of Freedom#

The configuration variables for the 2-D heat exchanger model include the inside diameter of the tube and thickness of the tube. They are used as parameters of the model and have to be declared for discretization in the radius direction. Once declared as configuration arguments, they are not allowed to change (immutable). Other configuration variables include “finite_elements” (the number of elements) in the flow path direction, “radial_elements” (the number of elements in radius direction, “tube_arrangement” for either staggered or in-line arrangement, “has_radiation” if shell-side radiation heat transfer is considered, and “flow_type” for either co-current or counter-current configuration. Additionally, has_header has been added as a configuration argument, when it is True, the health of the water/steam headers is calculated (see header section). The main input variables for the 2-D cross-flow heat exchanger model include design variables such as number of tube segments, number of tube columns, number of tube inlet rows, length of the tube in each segment (each pass), pitches in directions parallel and perpendicular to the shell fluid flow, and elevation change from tube inlet to tube outlet. The thermal and transport properties are also required as well as the mechanical properties if the equipment health model is used. Other required operating variables include fouling resistances on both tube and shell sides, tube wall emissivity if radiation model is turned on, and correction factors for heat transfer and pressure drops on both sides. Given the inlet conditions such as pressures, temperatures and flow rates on both sides, the outlet conditions will be predicted by the model. Meanwhile the temperature and pressure distributions along the flow path direction will be solved on both sides. The 2-D tube wall temperature distribution will also be solved.

In order to capture off design conditions and heat transfer coefficients at ramp up/down or load following conditions, the BoilerHeatExchanger2D model includes rigorous heat transfer calculations. Therefore, additional degrees of freedom are required to calculate Nusselt, Prandtl, Reynolds numbers, such as:

  • tube_di (inner diameter)

  • tube length

  • tube number of rows (tube_nrow), columns (tube_ncol), and inlet flow (nrow_inlet)

  • pitch in x and y axis (pitch_x and pitch_y, respectively)

If pressure drop calculation is enabled, additional degrees of freedom are required:

  • elevation with respect to ground level (delta_elevation)

  • tube fouling resistance (tube_r_fouling)

  • shell fouling resistance (shell_r_fouling)

Model Structure#

The HeatExchangerCrossFlow2D_Header model contains two ControlVolume1DBlock blocks. By default the gas side is named shell and the water/steam side is named tube. These names are configurable. The sign convention is that duty is positive for heat flowing from the hot side to the cold side.

The control volumes are configured the same as the ControlVolume1DBlock in the Heater model. The HeatExchangerCrossFlow2D_Header model contains additional constraints that calculate the amount of heat transferred from the hot side to the cold side.

The HeatExchangerCrossFlow2D_Header has two inlet ports and two outlet ports. By default these are shell_inlet, tube_inlet, shell_outlet, and tube_outlet. If the user supplies different hot and cold side names the inlet and outlets are named accordingly.

Variables#

Variable

Symbol

Index Sets

Doc

heat_duty

\(Q\)

time

Heat transferred from hot side to the cold side

area

\(A\)

None

Heat transfer area

U

\(U\)

time

Heat transfer coefficient

delta_temperature

\(\Delta T\)

time

Temperature difference, defaults to LMTD

Note: delta_temperature may be either a variable or expression depending on the callback used. If the specified cold side is hotter than the specified hot side this value will be negative.

Constraints#

The default constraints can be overridden by providing alternative rules for the heat transfer equation, temperature difference, heat transfer coefficient, shell and tube pressure drop. This section describes the default constraints.

Heat transfer from shell to tube:

\[Q = UA\Delta T\]

Temperature difference is:

\[\Delta T = \frac{\Delta T_1 - \Delta T_2}{\log_e\left(\frac{\Delta T_1}{\Delta T_2}\right)}\]

The overall heat transfer coefficient is calculated as a function of convective heat transfer shell and tube, and wall conduction heat transfer resistance.

Convective heat transfer equations:

\[\frac{1}{U}*fcorrection_{htc} = [\frac{1}{hconv_{tube}} + \frac{1}{hconv_{shell}} + r + tube_{r fouling} + shell_{r fouling}]\]

Tube convective heat transfer (for all elements in tube discretization approach):

\[hconv_{tube} = \frac{Nu_{tube} k}{2tube_{ri}}\]
\[Nu_{tube} = 0.023 Re_{tube}^{0.8} Pr_{tube}^{0.4}\]
\[Pr_{tube} = \frac{Cp \mu}{ k Mw}\]
\[Re_{tube} = \frac{tube_{ri}2 V \rho}{\mu}\]

Shell convective heat transfer:

\[hconv_{shell} = \frac{Nu_{shell} k_{flue gas}}{tube_{do}}\]
\[Nu_{shell} = f_{arrangement} 0.33 Re_{tube}^{0.6} Pr_{tube}^{0.3333}\]
\[Pr_{shell} = \frac{Cp \mu}{ k Mw}\]
\[Re_{shell} = \frac{tube_{do} V \rho}{\mu}\]
\[tube_{do} = 2*tube_{thickness} + tube_{di}\]

Wall heat conduction resistance equation:

\[r = 0.5 * tube_{do} * \log{(\frac{tube_{do}}{tube_{di}})}*k\]

where:

  • hconv_tube : convective heat transfer resistance tube side (fluid water/steam) (W / m2 / K)

  • hconv_shell : convective heat transfer resistance shell side (fluid Flue Gas) (W / m2 / K )

  • Nu : Nusselt number

  • Pr : Prandtl number

  • Re : Reynolds number

  • V: velocity (m/s)

  • tube_di : inner diameter of the tube (m)

  • tube_do : outer diameter of the tube (m) (expression calculated by the model)

  • tube_thickness : tube thickness (m)

  • r = wall heat conduction resistance (K m^2 / W)

  • k : thermal conductivity of the tube wall (W / m / K)

  • \(\rho\) : density (kg/m^3)

  • \(\mu\) : viscocity (kg/m/s)

  • tube_r_fouling : tube side fouling resistance (K m^2 / W)

  • shell_r_fouling : shell side fouling resistance (K m^2 / W)

  • fcorrection_htc: correction factor for overall heat transfer

  • f_arrangement: tube arrangement factor

Note: by default fcorrection_htc is set to 1, however, this variable can be used to match unit performance (i.e. as a parameter estimation problem using real plant data).

Tube arrangement factor is a config argument with two different type of arrangements supported at the moment: 1.- In-line tube arrangement factor (f_arrangement = 0.788), and 2.- Staggered tube arrangement factor (f_arrangement = 1). f_arrangement is a parameter that can be adjusted by the user.

The HeatExchangerCrossFlow2D_Header model includes an argument to compute heat transfer due to radiation of the flue gases. If has_radiation = True the model builds additional heat transfer calculations that will be added to the hconv_shell resistances. Radiation effects are calculated based on the gas gray fraction and gas-surface radiation (between gas and shell).

\[Gas_{gray frac} = f (gas_{emissivity})\]
\[frad_{gas gray frac} = f (wall_{emissivity}, gas_{emissivity})\]
\[hconv_{shell_rad} = f (k_{boltzmann}, frad_{gas gray frac}, T_{gas in}, T_{gas out}, T_{fluid in}, T_{fluid out})\]

Note: Gas emissivity is calculated with surrogate models (see more details in boiler_heat_exchanger.py). Radiation = True when flue gas temperatures are higher than 700 K (for example, when the model is used for units like Primary superheater, Reheater, or Finishing Superheater; while Radiation = False when the model is used to represent the economizer in a power plant flowsheet).

If pressure change is set to True, \(deltaP_{uturn} and friction_{factor}\) are calculated

Tube side:

\[\Delta P_{tube} = \Delta P_{tube friction} + \Delta P_{tube uturn} - elevation * g *\frac{\rho_{in} + \rho_{out}}{2}\]
\[\Delta P_{tube friction} = f( tube_{di} \rho, V_{tube}, number of tubes, tube_{length})\]
\[\Delta P_{tube uturn} = f(\rho, v_{tube}, k_{loss uturn})\]

where:

  • \(k_{loss uturn}\) : pressure loss coefficient of a tube u-turn

  • g : is the acceleration of gravity 9.807 (m/s^2)

Shell side:

\[\Delta P_{shell} = 1.4 \Delta P_{shell friction} \rho V_{shell}^2\]

\(\Delta P_{shell friction}\) is calculated based on the tube arrangement type:

In-line: \(\Delta P_{shell friction} = \frac{ 0.044 + \frac{0.08 ( \frac{P_x}{tube_{do}} ) } {(\frac{P_y}{tube_{do}}-1)^{0.43+\frac{1.13}{(\frac{P_x}{tube_{do}})}}}}{Re^{0.15}}\)

Staggered: \(\Delta P_{shell friction} = \frac{ 0.25 + \frac{0.118}{(\frac{P_y}{tube_{do}} -1)^{1.08}} }{Re^{0.16}}\)

Figure. Tube Arrangement

../../../../_images/tube_arrangement.png

Tube Arrangement#

Header Health Model#

The heat exchanger 2D model allows the user to calculate the thermal and mechanical stresses of the water/steam headers connected to the outlet of the tube side. Additionally, the rupture time and fatigue calculation of allowable cycles are computed by the model. A simplified 1D PDE problem is developed to represent the heat conduction transient through the radius of the superheater/reheater headers. Regarding to the flow path configuration (counter-current or co-current) of the 2D heat exchanger, the first or the last discretization point will be used to define the boundary of the headers. For this example, the last discretization point will be used for the outlet superheater header due to the counter-current flow configuration. Under the assumptions of constant conductivity and no heat generation, the Fourier’s equation is converted to the Eq. (h1) for the cylindrical header. The Pyomo.DAE framework is applied to solve the PDE problem. The thermal and mechanical stresses are calculated based on the pressure and temperature difference between both sides of the header which can be used to evaluate the allowable number of cycles of the main body and the critical point of the edge of the hole.

\[\frac{1}{a} \frac{\partial T}{\partial t} = \frac{{\partial}^2 T}{\partial r^2} + \frac{1}{r} \frac{\partial T}{\partial r}\]

where T is wall temperature (K), r is radius (m), and a is the material thermal difussivity (m2/s). The material thermal difussivity is a function of (material thermal conductivity, specific heat, and density)

Detailed description of the mechanical stress calculations and thermal stress calculations can be found in S. Bracco, 2012 and Taler & Duda, 2006, respectively.

Rupture time calculation: The creep phenomenon is an important design consideration in the analysis of structures. At the high temperature operation, the creep is coupled with fatigue due to cycling, the damage will be much higher than that occurring if the same fatigue or creep is working alone. For example, a long-time creep rupture strength values can be derived by using the Manson-Haferd model. However, depending on the investigated material, users can find another correlation to calculate the rupture strength in the open literature.

Fatigue calculation of allowable cycles: For general ferritic and austenitic materials, the calculation of the allowable number of cycles are expressed in the following equation. However, the users can be recommended to find a specific fatigue equation for their own material to obtain a better result. Using the calculated stresses above, the number of allowable cycles of the component can be evaluated based on fatigue assessment standard, such as EN 13445. The detail of the developed approach can be found in Bracco’s report (S. Bracco, 2012). This model can be applied for both drum and thick-walled components such as header. According to the EN 13445 standard, for a single cycle, the allowable number of fatigue cycles N can be computed as:

\[N = \frac{46000}{\Delta\Sigma R_i - 0.63 R_m + 11.5}\]

where Rm is the material tensile strength at room temperature while the reference stress range \(\Delta\SigmaR_i\) depends on the stress range \(\Delta\Sigma_i\)

Bracco, S. (2012). Dynamic simulation of combined cycles operating in transient conditions: An innovative approach to determine the steam drums life consumption. In Proceedings of the 25th International Conference on Efficiency, Cost, Optimization and Simulation of Energy Conversion Systems and Processes, ECOS 2012. Taler, J., & Duda, P. (2006). Solving direct and inverse heat conduction problems. Solving Direct and Inverse Heat Conduction Problems. Springer Berlin Heidelberg. https://doi.org/10.1007/978-3-540-33471-2

Class Documentation#

class idaes.models_extra.power_generation.unit_models.boiler_heat_exchanger_2D.HeatExchangerCrossFlow2D_Header(*args, **kwds)#
Parameters:
  • rule (function) – A rule function or None. Default rule calls build().

  • concrete (bool) – If True, make this a toplevel model. Default - False.

  • ctype (class) –

    Pyomo ctype of the block. Default - pyomo.environ.Block

    Config args

    dynamic

    Indicates whether this model will be dynamic or not, default = useDefault. Valid values: { useDefault - get flag from parent (default = False), True - set as a dynamic model, False - set as a steady-state model.}

    has_holdup

    Indicates whether holdup terms should be constructed or not. Must be True if dynamic = True, default - False. Valid values: { useDefault - get flag from parent (default = False), True - construct holdup terms, False - do not construct holdup terms}

    shell_side

    shell side config arguments

    shell_side
    material_balance_type

    Indicates what type of mass balance should be constructed, default - MaterialBalanceType.componentTotal. Valid values: { 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.}

    energy_balance_type

    Indicates what type of energy balance should be constructed, default - EnergyBalanceType.enthalpyTotal. Valid values: { EnergyBalanceType.none - exclude energy balances, EnergyBalanceType.enthalpyTotal - single ethalpy balance for material, EnergyBalanceType.enthalpyPhase - ethalpy balances for each phase, EnergyBalanceType.energyTotal - single energy balance for material, EnergyBalanceType.energyPhase - energy balances for each phase.}

    momentum_balance_type

    Indicates what type of momentum balance should be constructed, default - MomentumBalanceType.pressureTotal. Valid values: { MomentumBalanceType.none - exclude momentum balances, MomentumBalanceType.pressureTotal - single pressure balance for material, MomentumBalanceType.pressurePhase - pressure balances for each phase, MomentumBalanceType.momentumTotal - single momentum balance for material, MomentumBalanceType.momentumPhase - momentum balances for each phase.}

    has_pressure_change

    Indicates whether terms for pressure change should be constructed, default - False. Valid values: { True - include pressure change terms, False - exclude pressure change terms.}

    property_package

    Property parameter object used to define property calculations (default = ‘use_parent_value’) - ‘use_parent_value’ - get package from parent (default = None) - a ParameterBlock object

    property_package_args

    A dict of arguments to be passed to the PropertyBlockData and used when constructing these (default = ‘use_parent_value’) - ‘use_parent_value’ - get package from parent (default = None) - a dict (see property package for documentation)

    tube_side

    tube side config arguments

    tube_side
    material_balance_type

    Indicates what type of mass balance should be constructed, default - MaterialBalanceType.componentTotal. Valid values: { 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.}

    energy_balance_type

    Indicates what type of energy balance should be constructed, default - EnergyBalanceType.enthalpyTotal. Valid values: { EnergyBalanceType.none - exclude energy balances, EnergyBalanceType.enthalpyTotal - single ethalpy balance for material, EnergyBalanceType.enthalpyPhase - ethalpy balances for each phase, EnergyBalanceType.energyTotal - single energy balance for material, EnergyBalanceType.energyPhase - energy balances for each phase.}

    momentum_balance_type

    Indicates what type of momentum balance should be constructed, default - MomentumBalanceType.pressureTotal. Valid values: { MomentumBalanceType.none - exclude momentum balances, MomentumBalanceType.pressureTotal - single pressure balance for material, MomentumBalanceType.pressurePhase - pressure balances for each phase, MomentumBalanceType.momentumTotal - single momentum balance for material, MomentumBalanceType.momentumPhase - momentum balances for each phase.}

    has_pressure_change

    Indicates whether terms for pressure change should be constructed, default - False. Valid values: { True - include pressure change terms, False - exclude pressure change terms.}

    property_package

    Property parameter object used to define property calculations (default = ‘use_parent_value’) - ‘use_parent_value’ - get package from parent (default = None) - a ParameterBlock object

    property_package_args

    A dict of arguments to be passed to the PropertyBlockData and used when constructing these (default = ‘use_parent_value’) - ‘use_parent_value’ - get package from parent (default = None) - a dict (see property package for documentation)

    transformation_method

    Discretization method to use for DAE transformation. See Pyomo documentation for supported transformations.

    transformation_scheme

    Discretization scheme to use when transformating domain. See Pyomo documentation for supported schemes.

    finite_elements

    Number of finite elements to use when discretizing length domain (default=5). Should set to the number of tube rows

    collocation_points

    Number of collocation points to use per finite element when discretizing length domain (default=3)

    flow_type

    Flow configuration of heat exchanger co_current: shell and tube flows from 0 to 1 counter_current: shell side flows from 0 to 1 tube side flows from 1 to 0

    tube_arrangement

    Tube arrangement could be in-line or staggered

    tube_side_water_phase

    Define water phase for property calls

    has_radiation

    Define if shell side gas radiation is to be considered

    tube_inner_diameter

    User must define inner diameter of tube

    tube_thickness

    User must define tube wall thickness

    radial_elements

    Number of finite elements to use when discretizing radius domain (default=5).

    header_inner_diameter

    User must define inner diameter of header

    header_wall_thickness

    User must define header wall thickness

    header_radial_elements

    Number of finite elements to use when discretizing radius domain (default=5).

    has_header

    If has_header is True, user must provide header thickness and inner diameter.

  • initialize (dict) – ProcessBlockData config for individual elements. Keys are BlockData indexes and values are dictionaries with config arguments as keys.

  • idx_map (function) – Function to take the index of a BlockData element and return the index in the initialize dict from which to read arguments. This can be provided to override the default behavior of matching the BlockData index exactly to the index in initialize.

Returns:

(HeatExchangerCrossFlow2D_Header) New instance

class idaes.models_extra.power_generation.unit_models.boiler_heat_exchanger_2D.HeatExchangerCrossFlow2D_HeaderData(component)[source]#

Standard Heat Exchanger Cross Flow Unit Model Class.

build()[source]#

Begin building model.

Parameters:

None

Returns:

None

initialize_build(shell_state_args=None, tube_state_args=None, outlvl=0, solver=None, optarg=None)[source]#

HeatExchangerCrossFlow1D initialisation routine

Keyword Arguments:
  • state_args – a dict of arguments to be passed to the property package(s) to provide an initial state for initialization (see documentation of the specific property package) (default = None).

  • outlvl

    sets output level of initialisation routine

    • 0 = no output (default)

    • 1 = return solver state for each step in routine

    • 2 = return solver state for each step in subroutines

    • 3 = include solver output information (tee=True)

  • optarg – solver options dictionary object (default=None, use default solver options)

  • solver – str indicating which solver to use during initialization (default = None, use default solver)

Returns:

None