tespy.components.heat_exchangers package

tespy.components.heat_exchangers.base module

Module of class HeatExchanger.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/base.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.base.HeatExchanger(label, **kwargs)[source]

Bases: Component

Class for counter flow heat exchanger.

The component HeatExchanger is the parent class for the components:

Mandatory Equations

Optional Equations

For hot and cold side individually:

Inlets/Outlets

  • in1, in2 (index 1: hot side, index 2: cold side)

  • out1, out2 (index 1: hot side, index 2: cold side)

Image

flowsheet of the heat exchanger flowsheet of the heat exchanger
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict) – Heat transfer, \(Q/\text{W}\).

  • pr1 (float, dict, "var") – Outlet to inlet pressure ratio at hot side, \(pr/1\).

  • pr2 (float, dict, "var") – Outlet to inlet pressure ratio at cold side, \(pr/1\).

  • dp1 (float, dict, "var") – Inlet to outlet pressure delta at hot side, unit is the network’s pressure unit!.

  • dp2 (float, dict, "var") – Inlet to outlet pressure delta at cold side, unit is the network’s pressure unit!.

  • zeta1 (float, dict, "var") – Geometry independent friction coefficient at hot side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • zeta2 (float, dict, "var") – Geometry independent friction coefficient at cold side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • ttd_l (float, dict) – Lower terminal temperature difference \(ttd_\text{l}/\text{K}\).

  • ttd_u (float, dict) – Upper terminal temperature difference \(ttd_\text{u}/\text{K}\).

  • ttd_min (float, dict) – Minimum terminal temperature difference \(ttd_\text{min}/\text{K}\).

  • eff_cold (float, dict) – Cold side heat exchanger effectiveness \(eff_\text{cold}/\text{1}\).

  • eff_hot (float, dict) – Hot side heat exchanger effectiveness \(eff_\text{hot}/\text{1}\).

  • eff_max (float, dict) – Max value of hot and cold side heat exchanger effectiveness values \(eff_\text{max}/\text{1}\).

  • kA (float, dict) – Area independent heat transfer coefficient, \(kA/\frac{\text{W}}{\text{K}}\).

  • kA_char (dict) – Area independent heat transfer coefficient characteristic.

  • kA_char1 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for hot side heat transfer coefficient.

  • kA_char2 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for cold side heat transfer coefficient.

Note

The HeatExchanger and subclasses ( tespy.components.heat_exchangers.condenser.Condenser, tespy.components.heat_exchangers.desuperheater.Desuperheater) are countercurrent heat exchangers. Equations (kA, ttd_u, ttd_l) do not work for directcurrent and crosscurrent or combinations of different types.

Example

A water cooling is installed to transfer heat from hot exhaust air. The heat exchanger is designed for a terminal temperature difference of 5 K. From this, it is possible to calculate the heat transfer coefficient and predict water and air outlet temperature in offdesign operation.

>>> from tespy.components import Sink, Source, HeatExchanger
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "enthalpy": "kJ/kg",
...     "heat_transfer_coefficient": "kW/K"
... })
>>> exhaust_hot = Source('Exhaust air outlet')
>>> exhaust_cold = Sink('Exhaust air inlet')
>>> cw_cold = Source('cooling water inlet')
>>> cw_hot = Sink('cooling water outlet')
>>> he = HeatExchanger('waste heat exchanger')
>>> ex_he = Connection(exhaust_hot, 'out1', he, 'in1')
>>> he_ex = Connection(he, 'out1', exhaust_cold, 'in1')
>>> cw_he = Connection(cw_cold, 'out1', he, 'in2')
>>> he_cw = Connection(he, 'out2', cw_hot, 'in1')
>>> nw.add_conns(ex_he, he_ex, cw_he, he_cw)

The volumetric flow of the air is at 100 l/s. After designing the component it is possible to predict the temperature at different flow rates or different inlet temperatures of the exhaust air.

>>> he.set_attr(
...     pr1=0.98, pr2=0.98, ttd_u=5,
...     design=['pr1', 'pr2', 'ttd_u'],
...     offdesign=['zeta1', 'zeta2', 'kA_char']
... )
>>> cw_he.set_attr(
...     fluid={'water': 1}, T=10, p=3, offdesign=['m']
... )
>>> ex_he.set_attr(fluid={'air': 1}, v=0.1, T=35)
>>> he_ex.set_attr(T=17.5, p=1, design=['T'])
>>> nw.solve('design')
>>> design_state = nw.save(as_dict=True)
>>> round(ex_he.T.val - he_cw.T.val, 0)
5.0
>>> ex_he.set_attr(v=0.075)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(he_cw.T.val, 1)
27.5
>>> round(he_ex.T.val, 1)
14.4
>>> ex_he.set_attr(v=0.1, T=40)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(he_cw.T.val, 1)
33.9
>>> round(he_ex.T.val, 1)
18.8
calc_dh_max_cold()[source]

Calculate the theoretical maximum enthalpy increase on the cold side

Returns:

float – Maximum cold side enthalpy increase.

\[h\left(p_{out,2}, T_{in,1}\right) - h_{in,2}\]

calc_dh_max_hot()[source]

Calculate the theoretical maximum enthalpy decrease on the hot side

Returns:

float – Maximum hot side enthalpy decrease.

\[h\left(p_{out,1}, T_{in,2}\right) - h_{in,1}\]

calc_sections(postprocess=True)[source]

Calculate the sections of the heat exchanger. For the base class, these are only points at the edges

Returns:

tuple – Cumulated heat transfer over sections, temperature at steps hot side, temperature at steps cold side, heat transfer per section, logarithmic temperature per section

calculate_td_log()[source]

Method to calculate logarithmic temperature difference during iteration. It returns the minimal temperature difference value instead of the logarithmic temperature difference if the minimal temperature difference is negative during iteration to progress in convergence

eff_cold_dependents()[source]
eff_cold_func()[source]

Equation for cold side heat exchanger effectiveness.

Returns:

residual (float) – Residual value of equation.

\[0 = \text{eff}_\text{cold} \cdot \left(h\left(p_{out,2}, T_{in,1} \right) - h_{in,2}\right) - \left( h_{out,2} - h_{in,2} \right)\]

eff_hot_dependents()[source]
eff_hot_func()[source]

Equation for hot side heat exchanger effectiveness.

Returns:

residual (float) – Residual value of equation.

\[0 = \text{eff}_\text{hot} \cdot \left(h\left(p_{out,1}, T_{in,2}\right) - h_{in,1}\right) - \left( h_{out,1} - h_{in,1}\right)\]

eff_max_dependents()[source]
eff_max_func()[source]

Equation for maximum heat exchanger effectiveness.

Note

This functions works on what is larger: hot side or cold side effectiveness. It may cause numerical issues, if applied, when one of both sides’ effectiveness is already predetermined, e.g. by temperature specifications.

Returns:

residual (float) – Residual value of equation.

\[0 = \text{eff}_\text{max} - \text{max} \left(\text{eff}_\text{hot},\text{eff}_\text{cold}\right)\]

energy_balance_dependents()[source]
energy_balance_func()[source]

Equation for heat exchanger energy balance.

Returns:

residual (float) – Residual value of equation.

\[0 = \dot{m}_{in,1} \cdot \left(h_{out,1} - h_{in,1} \right) + \dot{m}_{in,2} \cdot \left(h_{out,2} - h_{in,2} \right)\]

energy_balance_hot_dependents()[source]
energy_balance_hot_func()[source]

Equation for hot side heat exchanger energy balance.

Returns:

residual (float) – Residual value of equation.

\[0 =\dot{m}_{in,1} \cdot \left(h_{out,1}-h_{in,1}\right)-\dot{Q}\]

entropy_balance()[source]

Calculate entropy balance of a heat exchanger.

The allocation of the entropy streams due to heat exchanged and due to irreversibility is performed by solving for T on both sides of the heat exchanger:

\[h_\text{out} - h_\text{in} = \int_\text{in}^\text{out} v \cdot dp - \int_\text{in}^\text{out} T \cdot ds\]

As solving \(\int_\text{in}^\text{out} v \cdot dp\) for non isobaric processes would require perfect process knowledge (the path) on how specific volume and pressure change throughout the component, the heat transfer is split into three separate virtual processes for both sides:

  • in->in*: decrease pressure to \(p_\text{in*}=p_\text{in}\cdot\sqrt{\frac{p_\text{out}}{p_\text{in}}}\) without changing enthalpy.

  • in*->out* transfer heat without changing pressure. \(h_\text{out*}-h_\text{in*}=h_\text{out}-h_\text{in}\)

  • out*->out decrease pressure to outlet pressure \(p_\text{out}\) without changing enthalpy.

Note

The entropy balance makes the following parameter available:

\[\begin{split}\text{S\_Q1}=\dot{m} \cdot \left(s_\text{out*,1}-s_\text{in*,1} \right)\\ \text{S\_Q2}=\dot{m} \cdot \left(s_\text{out*,2}-s_\text{in*,2} \right)\\ \text{S\_Qirr}=\text{S\_Q2} - \text{S\_Q1}\\ \text{S\_irr1}=\dot{m} \cdot \left(s_\text{out,1}-s_\text{in,1} \right) - \text{S\_Q1}\\ \text{S\_irr2}=\dot{m} \cdot \left(s_\text{out,2}-s_\text{in,2} \right) - \text{S\_Q2}\\ \text{S\_irr}=\sum \dot{S}_\text{irr}\\ \text{T\_mQ1}=\frac{\dot{Q}}{\text{S\_Q1}}\\ \text{T\_mQ2}=\frac{\dot{Q}}{\text{S\_Q2}}\end{split}\]
get_bypass_constraints()[source]
get_mandatory_constraints()[source]
get_parameters()[source]
get_plotting_data()[source]

Generate a dictionary containing FluProDia plotting information.

Returns:

data (dict) – A nested dictionary containing the keywords required by the calc_individual_isoline method of the FluidPropertyDiagram class. First level keys are the connection index (‘in1’ -> ‘out1’, therefore 1 etc.).

initialise_source(c, key)[source]

Return a starting value for pressure and enthalpy at outlet.

Parameters:
  • c (tespy.connections.connection.Connection) – Connection to perform initialisation on.

  • key (str) – Fluid property to retrieve.

Returns:

val (float) – Starting value for pressure/enthalpy in SI units.

initialise_target(c, key)[source]

Return a starting value for pressure and enthalpy at inlet.

Parameters:
  • c (tespy.connections.connection.Connection) – Connection to perform initialisation on.

  • key (str) – Fluid property to retrieve.

Returns:

val (float) – Starting value for pressure/enthalpy in SI units.

static inlets()[source]
kA_char_dependents()[source]
kA_char_func()[source]

Calculate heat transfer from heat transfer coefficient characteristic.

Returns:

residual (float) – Residual value of equation.

\[ \begin{align}\begin{aligned}0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + kA_{design} \cdot f_{kA} \cdot \frac{T_{out,1} - T_{in,2} - T_{in,1} + T_{out,2}} {\ln{\frac{T_{out,1} - T_{in,2}}{T_{in,1} - T_{out,2}}}}\\f_{kA} = \frac{2}{\frac{1}{f_1\left( expr_1\right)} + \frac{1}{f_2\left( expr_2\right)}}\end{aligned}\end{align} \]

Note

For standard functions f1 and f2 see module tespy.data.

kA_dependents()[source]
kA_deriv(increment_filter, k, dependents=None)[source]

Partial derivatives of heat transfer coefficient function.

Parameters:
  • increment_filter (ndarray) – Matrix for filtering non-changing variables.

  • k (int) – Position of derivatives in Jacobian matrix (k-th equation).

kA_func()[source]

Calculate heat transfer from heat transfer coefficient.

Returns:

residual (float) – Residual value of equation.

\[0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + kA \cdot \frac{T_{out,1} - T_{in,2} - T_{in,1} + T_{out,2}} {\ln{\frac{T_{out,1} - T_{in,2}}{T_{in,1} - T_{out,2}}}}\]

static outlets()[source]
ttd_l_dependents()[source]
ttd_l_func()[source]

Equation for lower terminal temperature difference.

Returns:

residual (float) – Residual value of equation.

\[0 = ttd_{l} - T_{out,1} + T_{in,2}\]

ttd_min_dependents()[source]
ttd_min_func()[source]

Equation for minimum terminal temperature difference.

Returns:

residual (float) – Residual value of equation.

\[ttd_{l} = T_{out,1} - T_{in,2} ttd_{u} = T_{in,1} - T_{out,2} 0 = \text{min}\left(ttd_{u}, ttd_{l}\right)\]

ttd_u_dependents()[source]
ttd_u_func()[source]

Equation for upper terminal temperature difference.

Returns:

residual (float) – Residual value of equation.

\[0 = ttd_{u} - T_{in,1} + T_{out,2}\]

tespy.components.heat_exchangers.condenser module

Module of class Condenser.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/condenser.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.condenser.Condenser(label, **kwargs)[source]

Bases: HeatExchanger

A Condenser cools a fluid until it is in liquid state.

The condensing fluid is cooled by the cold side fluid. The fluid on the hot side of the condenser must be pure. Subcooling is available.

Mandatory Equations

Optional Equations

The Condenser class uses an individual definition for the calculation of the logarithmic temperature difference

For hot and cold side individually:

Inlets/Outlets

  • in1, in2 (index 1: hot side, index 2: cold side)

  • out1, out2 (index 1: hot side, index 2: cold side)

Image

flowsheet of the condenser flowsheet of the condenser
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict) – Heat transfer, \(Q/\text{W}\).

  • pr1 (float, dict, "var") – Outlet to inlet pressure ratio at hot side, \(pr/1\).

  • pr2 (float, dict, "var") – Outlet to inlet pressure ratio at cold side, \(pr/1\).

  • dp1 (float, dict, "var") – Inlet to outlet pressure delta at hot side, unit is the network’s pressure unit!.

  • dp2 (float, dict, "var") – Inlet to outlet pressure delta at cold side, unit is the network’s pressure unit!.

  • zeta1 (float, dict, "var") – Geometry independent friction coefficient at hot side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • zeta2 (float, dict, "var") – Geometry independent friction coefficient at cold side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • ttd_l (float, dict) – Lower terminal temperature difference \(ttd_\text{l}/\text{K}\).

  • ttd_u (float, dict) – Upper terminal temperature difference (referring to saturation temperature of condensing fluid) \(ttd_\text{u}/\text{K}\).

  • ttd_min (float, dict) – Minimum terminal temperature difference \(ttd_\text{min}/\text{K}\).

  • eff_cold (float, dict) – Cold side heat exchanger effectiveness \(eff_\text{cold}/\text{1}\).

  • eff_hot (float, dict) – Hot side heat exchanger effectiveness \(eff_\text{hot}/\text{1}\).

  • eff_max (float, dict) – Max value of hot and cold side heat exchanger effectiveness values \(eff_\text{max}/\text{1}\).

  • kA (float, dict) – Area independent heat transfer coefficient, \(kA/\frac{\text{W}}{\text{K}}\).

  • kA_char (tespy.tools.data_containers.SimpleDataContainer) – Area independent heat transfer coefficient characteristic.

  • kA_char1 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for hot side heat transfer coefficient.

  • kA_char2 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for cold side heat transfer coefficient.

  • subcooling (boolean) – Enable/disable subcooling, default value: disabled.

Note

The condenser has an additional equation for enthalpy at hot side outlet: The fluid leaves the component in saturated liquid state. If subcooling is activated, it possible to specify the enthalpy at the outgoing connection manually.

It has different calculation method for given heat transfer coefficient and upper terminal temperature dierence: These parameters refer to the condensing temperature, even if the fluid on the hot side enters the component in superheated state.

Example

Air is used to condensate water in a condenser. 1 kg/s waste steam is chilled with a terminal temperature difference of 15 K.

>>> from tespy.components import Sink, Source, Condenser
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> from tespy.tools.fluid_properties import T_sat_p
>>> nw = Network(m_range=[0.01, 1000], iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "enthalpy": "kJ/kg"
... })
>>> amb_in = Source('ambient air inlet')
>>> amb_out = Sink('air outlet')
>>> waste_steam = Source('waste steam')
>>> c = Sink('condensate sink')
>>> cond = Condenser('condenser')
>>> amb_he = Connection(amb_in, 'out1', cond, 'in2')
>>> he_amb = Connection(cond, 'out2', amb_out, 'in1')
>>> ws_he = Connection(waste_steam, 'out1', cond, 'in1')
>>> he_c = Connection(cond, 'out1', c, 'in1')
>>> nw.add_conns(amb_he, he_amb, ws_he, he_c)

The air flow can not be controlled, thus is constant in offdesign operation. If the waste steam mass flow or the ambient air temperature change, the outlet temperature of the air will change, too.

>>> cond.set_attr(pr1=0.98, pr2=0.999, ttd_u=15, design=['pr2', 'ttd_u'],
... offdesign=['zeta2', 'kA_char'])
>>> ws_he.set_attr(fluid={'water': 1}, h=2700, m=1)
>>> amb_he.set_attr(fluid={'air': 1}, T=20, offdesign=['v'])
>>> he_amb.set_attr(p=1, T=40, design=['T'])
>>> nw.solve('design')
>>> design_state = nw.save(as_dict=True)
>>> round(amb_he.v.val, 2)
103.17
>>> round(ws_he.T.val - he_amb.T.val, 1)
66.9
>>> round(ws_he.calc_T_sat() - 273.15 - he_amb.T.val, 1)
15.0
>>> ws_he.set_attr(m=0.7)
>>> amb_he.set_attr(T=30)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(ws_he.T.val - he_amb.T.val, 1)
62.5
>>> round(ws_he.calc_T_sat() - 273.15 - he_amb.T.val, 1)
11.3

It is possible to activate subcooling. The difference to boiling point temperature is specified to 5 K.

>>> cond.set_attr(subcooling=True)
>>> he_c.set_attr(td_bubble=5)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(ws_he.T.val - he_amb.T.val, 1)
62.5
>>> round(ws_he.calc_T_sat() - 273.15 - he_amb.T.val, 1)
13.4
calculate_td_log()[source]

Method to calculate logarithmic temperature difference during iteration. It returns the minimal temperature difference value instead of the logarithmic temperature difference if the minimal temperature difference is negative during iteration to progress in convergence

convergence_check()[source]
get_parameters()[source]
initialise_source(c, key)[source]

Return a starting value for pressure and enthalpy at outlet.

Parameters:
  • c (tespy.connections.connection.Connection) – Connection to perform initialisation on.

  • key (str) – Fluid property to retrieve.

Returns:

val (float) – Starting value for pressure/enthalpy in SI units.

kA_char_func()[source]

Calculate heat transfer from heat transfer coefficient characteristic.

Returns:

residual (float) – Residual value of equation.

\[ \begin{align}\begin{aligned}0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + kA_{design} \cdot f_{kA} \cdot \frac{T_{out,1} - T_{in,2} - T_{sat} \left(p_{in,1}\right) + T_{out,2}} {\ln{\frac{T_{out,1} - T_{in,2}} {T_{sat} \left(p_{in,1}\right) - T_{out,2}}}}\\f_{kA} = \frac{2}{\frac{1}{f_1 \left( expr_1\right)} + \frac{1}{f_2 \left( expr_2\right)}}\end{aligned}\end{align} \]

Note

For standard functions f1 and f2 see module tespy.data.

subcooling_dependents()[source]
subcooling_func()[source]

Equation for hot side outlet state.

Returns:

residual (float) – Residual value of equation.

\[0=h_{out,1} -h\left(p_{out,1}, x=0 \right)\]

Note

This equation is applied in case subcooling is False!

ttd_u_dependents()[source]
ttd_u_func()[source]

Equation for upper terminal temperature difference.

Returns:

residual (float) – Residual value of equation.

\[0 = ttd_{u} - T_{sat} \left(p_{in,1}\right) + T_{out,2}\]

Note

The upper terminal temperature difference ttd_u refers to boiling temperature at hot side inlet.

tespy.components.heat_exchangers.desuperheater module

Module of class Desuperheater.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/desuperheater.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.desuperheater.Desuperheater(label, **kwargs)[source]

Bases: HeatExchanger

The Desuperheater cools a fluid to the saturated gas state.

Mandatory Equations

Optional Equations

For hot and cold side individually:

Inlets/Outlets

  • in1, in2 (index 1: hot side, index 2: cold side)

  • out1, out2 (index 1: hot side, index 2: cold side)

Image

flowsheet of the desuperheater flowsheet of the desuperheater
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict) – Heat transfer, \(Q/\text{W}\).

  • pr1 (float, dict, "var") – Outlet to inlet pressure ratio at hot side, \(pr/1\).

  • pr2 (float, dict, "var") – Outlet to inlet pressure ratio at cold side, \(pr/1\).

  • zeta1 (float, dict, "var") – Geometry independent friction coefficient at hot side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • zeta2 (float, dict, "var") – Geometry independent friction coefficient at cold side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • ttd_l (float, dict) – Lower terminal temperature difference \(ttd_\text{l}/\text{K}\).

  • ttd_u (float, dict) – Upper terminal temperature difference \(ttd_\text{u}/\text{K}\).

  • kA (float, dict) – Area independent heat transfer coefficient, \(kA/\frac{\text{W}}{\text{K}}\).

  • kA_char1 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for hot side heat transfer coefficient.

  • kA_char2 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for cold side heat transfer coefficient.

Note

The desuperheater has an additional equation for enthalpy at hot side outlet: The fluid leaves the component in saturated gas state.

Example

Overheated enthanol is cooled with water in a heat exchanger until it reaches the state of saturated gas.

>>> from tespy.components import Sink, Source, Desuperheater
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "enthalpy": "kJ/kg", "volumetric_flow": "l/s"
... })
>>> et_in = Source('ethanol inlet')
>>> et_out = Sink('ethanol outlet')
>>> cw_in = Source('cooling water inlet')
>>> cw_out = Sink('cooling water outlet')
>>> desu = Desuperheater('desuperheater')
>>> et_de = Connection(et_in, 'out1', desu, 'in1')
>>> de_et = Connection(desu, 'out1', et_out, 'in1')
>>> cw_de = Connection(cw_in, 'out1', desu, 'in2')
>>> de_cw = Connection(desu, 'out2', cw_out, 'in1')
>>> nw.add_conns(et_de, de_et, cw_de, de_cw)

The cooling water enters the component at 15 °C. 10 l/s of ethanol is cooled from 100 K above boiling point. The water flow rate is at 1 l/s. Knowing the component’s design parameters it is possible to predict behavior at different inlet temperatures or different volumetric flow of ethanol. Controlling the ethanol’s state at the outlet is only possible, if the cooling water flow rate is adjusted accordingly.

>>> desu.set_attr(
...     pr1=0.99, pr2=0.98, design=['pr1', 'pr2'],
...     offdesign=['zeta1', 'zeta2', 'kA_char']
... )
>>> cw_de.set_attr(fluid={'water': 1}, T=15, v=1, design=['v'])
>>> de_cw.set_attr(p=1)
>>> et_de.set_attr(fluid={'ethanol': 1}, td_dew=100, v=10)
>>> de_et.set_attr(p=1)
>>> nw.solve('design')
>>> design_state = nw.save(as_dict=True)
>>> round(de_cw.T.val, 1)
15.5
>>> round(de_et.x.val, 1)
1.0
>>> et_de.set_attr(v=12)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(cw_de.v.val, 2)
1.94
>>> et_de.set_attr(v=7)
>>> nw.solve('offdesign', init_path=design_state, design_path=design_state)
>>> round(cw_de.v.val, 2)
0.41
get_mandatory_constraints()[source]
initialise_source(c, key)[source]

Return a starting value for pressure and enthalpy at outlet.

Parameters:
  • c (tespy.connections.connection.Connection) – Connection to perform initialisation on.

  • key (str) – Fluid property to retrieve.

Returns:

val (float) – Starting value for pressure/enthalpy in SI units.

saturated_gas_dependents()[source]
saturated_gas_deriv(increment_filter, k, dependents=None)[source]

Partial derivatives of saturated gas at hot side outlet function.

Parameters:
  • increment_filter (ndarray) – Matrix for filtering non-changing variables.

  • k (int) – Position of derivatives in Jacobian matrix (k-th equation).

saturated_gas_func()[source]

Calculate hot side outlet state.

Returns:

residual (float) – Residual value of equation

\[0 = h_{out,1} - h\left(p_{out,1}, x=1 \right)\]

tespy.components.heat_exchangers.movingboundary module

Module of class MovingBoundaryHeatExchanger.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/movingboundary.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.movingboundary.MovingBoundaryHeatExchanger(label, **kwargs)[source]

Bases: SectionedHeatExchanger

Class for counter flow heat exchanger with UA sections.

The heat exchanger is internally discretized into multiple sections, which are defined by phase changes. The component assumes, that a pressure drop is linear to the change in enthalpy, meaning the phase boundary identification is done iteratively. In principle the implementations follows [34].

Mandatory Equations

Optional Equations

For hot and cold side individually:

Inlets/Outlets

  • in1, in2 (index 1: hot side, index 2: cold side)

  • out1, out2 (index 1: hot side, index 2: cold side)

Image

flowsheet of the heat exchanger flowsheet of the heat exchanger
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict) – Heat transfer, \(Q/\text{W}\).

  • pr1 (float, dict, "var") – Outlet to inlet pressure ratio at hot side, \(pr/1\).

  • pr2 (float, dict, "var") – Outlet to inlet pressure ratio at cold side, \(pr/1\).

  • dp1 (float, dict, "var") – Inlet to outlet pressure delta at hot side, unit is the network’s pressure unit!.

  • dp2 (float, dict, "var") – Inlet to outlet pressure delta at cold side, unit is the network’s pressure unit!.

  • zeta1 (float, dict, "var") – Geometry independent friction coefficient at hot side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • zeta2 (float, dict, "var") – Geometry independent friction coefficient at cold side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • ttd_l (float, dict) – Lower terminal temperature difference \(ttd_\text{l}/\text{K}\).

  • ttd_u (float, dict) – Upper terminal temperature difference \(ttd_\text{u}/\text{K}\).

  • ttd_min (float, dict) – Minimum terminal temperature difference \(ttd_\text{min}/\text{K}\).

  • eff_cold (float, dict) – Cold side heat exchanger effectiveness \(eff_\text{cold}/\text{1}\).

  • eff_hot (float, dict) – Hot side heat exchanger effectiveness \(eff_\text{hot}/\text{1}\).

  • eff_max (float, dict) – Max value of hot and cold side heat exchanger effectiveness values \(eff_\text{max}/\text{1}\).

  • UA (float, dict) – Sum of UA in all sections of the heat exchanger.

  • td_pinch (float, dict) – Value of the lowest delta T between hot side and cold side at the different sections.

  • UA_cecchinato (dict) – Group specification for partload UA modification according to [21], for usage see details in the tespy.components.heat_exchangers.movingboundary.MovingBoundaryHeatExchanger.UA_cecchinato_func(). This method can only be used in offdesign simulations!

  • alpha_ration (float) – Secondary fluid to refrigerant heat transfer coefficient ratio.

  • area_ration (float) – Secondary fluid to refrigerant heat transfer area ratio.

  • re_exp_r (float) – Reynolds exponent for refrigerant side.

  • re_exp_sf (float) – Reynolds exponent for secondary fluid side.

  • refrigerant_index (int) – Connection index for the refrigerant side, 0 if refrigerant is on hot side, 1 if refrigerant is on cold side.

Note

The equations only apply to counter-current heat exchangers.

Example

Water vapor should be cooled down, condensed and then further subcooled. For this air is heated up from 15 °C to 25 °C.

>>> from tespy.components import Source, Sink, MovingBoundaryHeatExchanger
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> import numpy as np
>>> nw = Network()
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC"
... })
>>> nw.iterinfo = False
>>> so1 = Source("vapor source")
>>> so2 = Source("air source")
>>> cd = MovingBoundaryHeatExchanger("condenser")
>>> si1 = Sink("water sink")
>>> si2 = Sink("air sink")
>>> c1 = Connection(so1, "out1", cd, "in1", label="1")
>>> c2 = Connection(cd, "out1", si1, "in1", label="2")
>>> c11 = Connection(so2, "out1", cd, "in2", label="11")
>>> c12 = Connection(cd, "out2", si2, "in1", label="12")
>>> nw.add_conns(c1, c2, c11, c12)

To generate good guess values, first we run the simulation with fixed pressure on the water side. The water enters at superheated vapor state with 15 °C superheating and leaves it with 10 °C subcooling.

>>> c1.set_attr(fluid={"Water": 1}, p=1, td_dew=15, m=1)
>>> c2.set_attr(td_bubble=15)
>>> c11.set_attr(fluid={"Air": 1}, p=1, T=15)
>>> c12.set_attr(T=25)
>>> cd.set_attr(pr1=1, pr2=1)
>>> nw.solve("design")

Now we can remove the pressure specifications on the air side and impose the minimum pinch instead, which will determine the actual water condensation pressure.

>>> c1.set_attr(p=None)
>>> cd.set_attr(td_pinch=5)
>>> nw.solve("design")
>>> round(c1.p.val, 3)
0.056
>>> round(c1.T.val, 1)
50.0

We can also see the temperature differences in all sections of the heat exchanger. Since the water vapor is cooled, condensed and then subcooled, while the air does not change phase, three sections will form:

>>> Q_sections, T_steps_hot, T_steps_cold, Q_per_section, td_log_per_section = cd.calc_sections()
>>> delta_T_between_sections = T_steps_hot - T_steps_cold
>>> [round(float(dT), 2) for dT in delta_T_between_sections]
[5.0, 19.75, 10.11, 25.0]

We can see that the lowest delta T is the first one. This is the delta T between the hot side outlet and the cold side inlet, which can also be seen if we have a look at the network’s results.

>>> ();nw.print_results();()
(...)

If we change the subcooling degree at the water outlet, the condensation pressure and pinch will move.

>>> c2.set_attr(td_bubble=5)
>>> nw.solve("design")
>>> round(c1.p.val, 3)
0.042
>>> Q_sections, T_steps_hot, T_steps_cold, Q_per_section, td_log_per_section = cd.calc_sections()
>>> delta_T_between_sections = T_steps_hot - T_steps_cold
>>> [round(float(dT), 2) for dT in delta_T_between_sections]
[9.88, 14.8, 5.0, 19.88]

Finally, in contrast to the baseclass HeatExchanger kA value, the UA value takes into account the heat transfer per section and calculates the heat transfer coefficient as the sum of all sections, while the kA value only takes into account the inlet and outlet temperatures and the total heat transfer.

>>> round(cd.kA.val)
173307
>>> round(cd.UA.val)
273449

It is also possible to apply a partload modification to UA following the implementation of [21]. For this you have to specify UA_cecchinato as offdesign parameter and along with it, values for

  • refrigerant side Reynolds exponent

  • secondary fluid side Reynolds exponent

  • secondary fluid to refrigerant area ratio

  • secondary fluid to refrigerant alpha (heat transfer coefficient) ratio

  • the refrigerant index (which side of the heat exchanger is passed by the refrigerant)

>>> design_state = nw.save(as_dict=True)
>>> cd.set_attr(
...     area_ratio=20,        # typical for a finned heat exchanger
...     alpha_ratio=1e-2,     # alpha for water side is higher
...     re_exp_r=0.8,
...     re_exp_sf=0.55,
...     refrigerant_index=0,  # water is refrigerant in this case
...     design=["td_pinch"],
...     offdesign=["UA_cecchinato"]
... )
>>> nw.solve("offdesign", design_path=design_state)

Without modifying any parameter, pinch and UA should be identical to design conditions.

>>> round(cd.td_pinch.val, 2)
5.0
>>> round(cd.UA.val)
273449

With change in operating conditions, e.g. reduction of heat transfer we’d typically observe lower pinch, if the heat transfer reduces faster than the UA value does.

>>> c1.set_attr(m=0.8)
>>> nw.solve("offdesign", design_path=design_state)
>>> round(cd.Q.val_SI / cd.Q.design, 2)
0.8
>>> round(cd.UA.val_SI / cd.UA.design, 2)
0.88
>>> round(cd.td_pinch.val, 2)
4.3
get_parameters()[source]

tespy.components.heat_exchangers.parabolic_trough module

Module of class ParabolicTrough.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/parabolic_trough.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.parabolic_trough.ParabolicTrough(label, **kwargs)[source]

Bases: SimpleHeatExchanger

The ParabolicTrough calculates heat output from irradiance.

Mandatory Equations

Optional Equations

Inlets/Outlets

  • in1

  • out1

Image

flowsheet of the parabolic trough flowsheet of the parabolic trough
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict, "var") – Heat transfer, \(Q/\text{W}\).

  • pr (float, dict, "var") – Outlet to inlet pressure ratio, \(pr/1\).

  • zeta (float, dict, "var") – Geometry independent friction coefficient, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • D (float, dict, "var") – Diameter of the absorber tube, \(D/\text{m}\).

  • L (float, dict, "var") – Length of the absorber tube, \(L/\text{m}\).

  • ks (float, dict, "var") – Pipe’s roughness, \(ks/\text{m}\).

  • darcy_group (str, dict) – Parametergroup for pressure drop calculation based on pipes dimensions using darcy weissbach equation.

  • ks_HW (float, dict, "var") – Pipe’s roughness, \(ks/\text{1}\).

  • hw_group (str, dict) – Parametergroup for pressure drop calculation based on pipes dimensions using hazen williams equation.

  • E (float, dict, "var") – Direct irradiance to tilted collector, \(E/\frac{\text{W}}{\text{m}^2}\).

  • aoi (float, dict, "var") – Angle of incidience, \(aoi/^\circ\).

  • doc (float, dict, "var") – Degree of cleanliness (1: full absorption, 0: no absorption), \(X\).

  • eta_opt (float, dict, "var") – (constant) optical losses due to surface reflection, \(\eta_{opt}\).

  • c_1 (float, dict, "var") – Linear thermal loss key figure, \(c_1/\frac{\text{W}}{\text{K} \cdot \text{m}^2}\).

  • c_2 (float, dict, "var") – Quadratic thermal loss key figure, \(c_2/\frac{\text{W}}{\text{K}^2 \cdot \text{m}^2}\).

  • iam_1 (float, dict, "var") – Linear incidence angle modifier, \(iam_1/\frac{1}{^\circ}\).

  • iam_2 (float, dict, "var") – Quadratic incidence angle modifier, \(iam_2/\left(\frac{1}{^\circ}\right)^2\).

  • A (float, dict, "var") – Collector aperture surface area \(A/\text{m}^2\).

  • Tamb (float, dict) – Ambient temperature, provide parameter in network’s temperature unit.

  • energy_group (str, dict) – Parametergroup for energy balance of solarthermal collector.

Example

A parabolic trough is installed using S800 as thermo-fluid. First, the operation conditions from [35] are reproduced. Therefore, the direct normal irradiance \(\dot{E}_\text{DNI}\) is at 1000 \(\frac{\text{W}}{\text{m}^2}\) at an angle of incidence \(aoi\) at 20 °. This means, the direct irradiance to the parabolic trough \(E\) is at \(\dot{E}_{DNI} \cdot cos\left(20^\circ\right)\).

>>> from tespy.components import Sink, Source, ParabolicTrough
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> import math
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "enthalpy": "kJ/kg"
... })
>>> so = Source('source')
>>> si = Sink('sink')
>>> pt = ParabolicTrough('parabolic trough collector')
>>> inc = Connection(so, 'out1', pt, 'in1')
>>> outg = Connection(pt, 'out1', si, 'in1')
>>> nw.add_conns(inc, outg)

The pressure ratio is at a constant level of 1. However, it is possible to specify the pressure losses from the absorber tube length, roughness and diameter, too. The aperture surface \(A\) is specified to 1 \(\text{m}^2\) for simplicity reasons.

>>> aoi = 20
>>> E = 1000 * math.cos(aoi / 180 * math.pi)
>>> pt.set_attr(
...     pr=1, aoi=aoi, doc=1,
...     Tamb=20, A=1, eta_opt=0.816, c_1=0.0622, c_2=0.00023, E=E,
...     iam_1=-1.59e-3, iam_2=9.77e-5
... )
>>> inc.set_attr(fluid={'INCOMP::S800': 1}, T=220, p=10)
>>> outg.set_attr(T=260)
>>> nw.solve('design')
>>> round(pt.Q.val, 0)
736.0

For example, it is possible to calculate the aperture area of the parabolic trough given the total heat production, outflow temperature and mass flow.

>>> pt.set_attr(A='var', Q=5e6, Tamb=25)
>>> inc.set_attr(T=None)
>>> outg.set_attr(T=350, m=20)
>>> nw.solve('design')
>>> round(inc.T.val, 0)
229.0
>>> round(pt.A.val, 0)
6862.0

Given this design, it is possible to calculate the outlet temperature as well as the heat transfer at different operating points.

>>> aoi = 30
>>> E = 800 * math.cos(aoi / 180 * math.pi)
>>> pt.set_attr(A=pt.A.val, aoi=aoi, Q=None, E=E)
>>> inc.set_attr(T=150)
>>> outg.set_attr(T=None)
>>> nw.solve('design')
>>> round(outg.T.val, 0)
244.0
>>> round(pt.Q.val, 0)
3602817.0
calc_parameters()[source]

Postprocessing parameter calculation.

convergence_check()[source]
energy_group_dependents()[source]
energy_group_func()[source]

Equation for solar collector energy balance.

Returns:

residual (float) – Residual value of equation.

\[\begin{split}\begin{split} T_m = & \frac{T_{out} + T_{in}}{2}\\ iam = & 1 - iam_1 \cdot |aoi| - iam_2 \cdot aoi^2\\ 0 = & \dot{m} \cdot \left( h_{out} - h_{in} \right)\\ & - A \cdot \left[E \cdot \eta_{opt} \cdot doc^{1.5} \cdot iam \right. \\ & \left. - c_1 \cdot \left(T_m - T_{amb} \right) - c_2 \cdot \left(T_m - T_{amb}\right)^2 \vphantom{ \eta_{opt} \cdot doc^{1.5}} \right] \end{split}\end{split}\]

Reference: [35].

get_parameters()[source]

tespy.components.heat_exchangers.parallel module

Module of class ParallelFlowHeatExchanger.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/parallel.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.parallel.ParallelFlowHeatExchanger(label, **kwargs)[source]

Bases: HeatExchanger

Class for parallel flow heat exchanger.

Mandatory Equations

Optional Equations

For hot and cold side individually:

Inlets/Outlets

  • in1, in2 (index 1: hot side, index 2: cold side)

  • out1, out2 (index 1: hot side, index 2: cold side)

Image

flowsheet of the heat exchanger flowsheet of the heat exchanger
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict) – Heat transfer, \(Q/\text{W}\).

  • pr1 (float, dict) – Outlet to inlet pressure ratio at hot side, \(pr/1\).

  • pr2 (float, dict) – Outlet to inlet pressure ratio at cold side, \(pr/1\).

  • dp1 (float, dict,) – Inlet to outlet pressure delta at hot side, \(dp/\text{Pa}\)

  • dp2 (float, dict) – Inlet to outlet pressure delta at cold side, \(dp\text{Pa}\).

  • zeta1 (float, dict) – Geometry independent friction coefficient at hot side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • zeta2 (float, dict) – Geometry independent friction coefficient at cold side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • ttd_l (float, dict) – Initial terminal temperature difference, referring to the temperature difference between the two inlets of the heat exchanger, \(ttd_\text{l}/\text{K}\).

  • ttd_u (float, dict) – Final terminal temperature difference, referring to the temperature difference between the two outlets of the heat exchanger, \(ttd_\text{u}/\text{K}\).

  • kA (float, dict) – Area independent heat transfer coefficient, \(kA/\frac{\text{W}}{\text{K}}\).

  • kA_char (dict) – Area independent heat transfer coefficient characteristic.

  • kA_char1 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for hot side heat transfer coefficient.

  • kA_char2 (tespy.tools.characteristics.CharLine, dict) – Characteristic line for cold side heat transfer coefficient.

Note

The ParallelFlowHeatExchanger implements parallel flow of both streams, meaning the streams enter with a high temperature difference and then gradually reduce their temperature difference to each other. The initial temperature difference is the maximum temperature difference, the final temperature difference is the minimum temperature difference.

Example

Water at 75 °C is used to heat up an air stream 2500 l/s from 10 °C to 35 °C.

>>> from tespy.components import Sink, Source, ParallelFlowHeatExchanger
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "enthalpy": "kJ/kg",
...     "volumetric_flow": "l/s", "heat_transfer_coefficient": "kW/K"
... })
>>> feed_water = Source("Feed water inlet")
>>> return_water = Sink("Water outlet")
>>> air_inlet = Source("Fresh air inlet")
>>> air_warm = Sink("Air outlet")
>>> he = ParallelFlowHeatExchanger("heat exchanger")
>>> c1 = Connection(feed_water, 'out1', he, 'in1')
>>> c2 = Connection(he, 'out1', return_water, 'in1')
>>> c3 = Connection(air_inlet, 'out1', he, 'in2')
>>> c4 = Connection(he, 'out2', air_warm, 'in1')
>>> nw.add_conns(c1, c2, c3, c4)

We assume pressure losses of 10 mbar on the air side, and 100 mbar on the water side. Depending on our specifications we can calculate:

  • What is the temperature of the water leaving the heat exchanger, or

  • What is the required mass flow of water to heat up the air

Let’s first assume, that a final pinch ttd_u of 7.5 K is desired, meaning, the water should leave the heat exchanger with a temperature higher than the air by 7.5 K. With that, we will get the water flow, and also the heat transfer coefficient kA as a result.

Note

Note, that for specification of initial or final pinch temperature differences, it is often important to start the calculation with a good initial guess. In this case, we know that the water will be in liquid state, therefore we can

  • either specify the outlet enthalpy initial guess to be liquid,

  • the state at the water outlet to be "l",

  • or use "INCOMP::Water" as fluid, since this uses liquid phase only.

>>> he.set_attr(dp1=0.1, dp2=0.01, ttd_u=7.5)
>>> c1.set_attr(fluid={"INCOMP::Water": 1}, T=70, p=1.3)
>>> c3.set_attr(fluid={"air": 1}, T=10, p=1.02, v=2500)
>>> c4.set_attr(T=35)
>>> nw.solve("design")
>>> round(c1.v.val, 2)
0.7
>>> round(he.kA.val, 2)
3.13

Now, it might be interesting to see what happens under different operation conditions after we have designed the system. For that, we can assume that the heat transfer coefficient is constant. First we just fix the kA value instead of the final pinch and then resolve again.

>>> he.set_attr(design=["ttd_u"], offdesign=["kA"])
>>> design_state = nw.save(as_dict=True)
>>> nw.solve("offdesign", design_path=design_state)
>>> round(he.kA.val_SI / he.kA.design, 1)
1.0

Now, let’s see what happens under different operating conditions. First we change the air volumetric flow, then we change the air temperature to check what happens to the outflow temperature of the water.

>>> c3.set_attr(v=2000)
>>> nw.solve("offdesign", design_path=design_state)
>>> round(c2.T.val, 2)
38.69
>>> c3.set_attr(v=2500, T=8)
>>> nw.solve("offdesign", design_path=design_state)
>>> round(c2.T.val, 2)
44.0
calculate_td_log()[source]

Method to calculate logarithmic temperature difference during iteration. It returns the minimal temperature difference value instead of the logarithmic temperature difference if the minimal temperature difference is negative during iteration to progress in convergence

get_parameters()[source]
ttd_l_dependents()[source]
ttd_l_func()[source]

Equation for lower terminal temperature difference.

Returns:

residual (float) – Residual value of equation.

\[0 = ttd_{l} - T_{out,1} + T_{in,2}\]

ttd_u_dependents()[source]
ttd_u_func()[source]

Equation for upper terminal temperature difference.

Returns:

residual (float) – Residual value of equation.

\[0 = ttd_{u} - T_{in,1} + T_{out,2}\]

tespy.components.heat_exchangers.sectioned module

Module of class SectionedHeatExchanger.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/sectioned.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger(label, **kwargs)[source]

Bases: HeatExchanger

Class for counter flow heat exchanger with UA sections.

The heat exchanger is internally discretized into 51 sections of equal heat transfer. The number of section can be adjusted by the user. It is based on the model implemented by [36].

Mandatory Equations

Optional Equations

For hot and cold side individually:

Inlets/Outlets

  • in1, in2 (index 1: hot side, index 2: cold side)

  • out1, out2 (index 1: hot side, index 2: cold side)

Image

flowsheet of the heat exchanger flowsheet of the heat exchanger
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict) – Heat transfer, \(Q/\text{W}\).

  • pr1 (float, dict, "var") – Outlet to inlet pressure ratio at hot side, \(pr/1\).

  • pr2 (float, dict, "var") – Outlet to inlet pressure ratio at cold side, \(pr/1\).

  • dp1 (float, dict, "var") – Inlet to outlet pressure delta at hot side, unit is the network’s pressure unit!.

  • dp2 (float, dict, "var") – Inlet to outlet pressure delta at cold side, unit is the network’s pressure unit!.

  • zeta1 (float, dict, "var") – Geometry independent friction coefficient at hot side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • zeta2 (float, dict, "var") – Geometry independent friction coefficient at cold side, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • ttd_l (float, dict) – Lower terminal temperature difference \(ttd_\text{l}/\text{K}\).

  • ttd_u (float, dict) – Upper terminal temperature difference \(ttd_\text{u}/\text{K}\).

  • ttd_min (float, dict) – Minimum terminal temperature difference \(ttd_\text{min}/\text{K}\).

  • eff_cold (float, dict) – Cold side heat exchanger effectiveness \(eff_\text{cold}/\text{1}\).

  • eff_hot (float, dict) – Hot side heat exchanger effectiveness \(eff_\text{hot}/\text{1}\).

  • eff_max (float, dict) – Max value of hot and cold side heat exchanger effectiveness values \(eff_\text{max}/\text{1}\).

  • UA (float, dict) – Sum of UA in all sections of the heat exchanger.

  • td_pinch (float, dict) – Value of the lowest delta T between hot side and cold side at the different sections.

  • num_sections (int) – Number of sections.

  • UA_cecchinato (dict) – Group specification for partload UA modification according to [21], for usage see details in the tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger.UA_cecchinato_func(). This method can only be used in offdesign simulations!

  • alpha_ration (float) – Secondary fluid to refrigerant heat transfer coefficient ratio.

  • area_ration (float) – Secondary fluid to refrigerant heat transfer area ratio.

  • re_exp_r (float) – Reynolds exponent for refrigerant side.

  • re_exp_sf (float) – Reynolds exponent for secondary fluid side.

  • refrigerant_index (int) – Connection index for the refrigerant side, 0 if refrigerant is on hot side, 1 if refrigerant is on cold side.

Note

The equations only apply to counter-current heat exchangers.

Example

Water vapor should be cooled down, condensed and then further subcooled. For his air is heated up from 15 °C to 25 °C.

>>> from tespy.components import Source, Sink, SectionedHeatExchanger
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> import numpy as np
>>> nw = Network()
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC"
... })
>>> nw.iterinfo = False
>>> so1 = Source("vapor source")
>>> so2 = Source("air source")
>>> cd = SectionedHeatExchanger("condenser")
>>> si1 = Sink("water sink")
>>> si2 = Sink("air sink")
>>> c1 = Connection(so1, "out1", cd, "in1", label="1")
>>> c2 = Connection(cd, "out1", si1, "in1", label="2")
>>> c11 = Connection(so2, "out1", cd, "in2", label="11")
>>> c12 = Connection(cd, "out2", si2, "in1", label="12")
>>> nw.add_conns(c1, c2, c11, c12)

To generate good guess values, first we run the simulation with fixed pressure on the water side. The water enters at superheated vapor state with 15 °C superheating and leaves it with 10 °C subcooling.

>>> c1.set_attr(fluid={"Water": 1}, td_dew=15, m=1)
>>> c2.set_attr(td_bubble=15, p=1)
>>> c11.set_attr(fluid={"Air": 1}, T=15)
>>> c12.set_attr(T=25, p=1)
>>> cd.set_attr(dp1=0.0, dp2=0.0)
>>> nw.solve("design")

Now we can remove the pressure specifications on the air side and impose the minimum pinch instead, which will determine the actual water condensation pressure.

>>> c2.set_attr(p=None)
>>> cd.set_attr(td_pinch=5)
>>> nw.solve("design")
>>> round(c1.p.val, 3)
0.056
>>> round(c1.T.val, 1)
50.0

We can also see the temperature differences in all sections of the heat exchanger. Since the water vapor is cooled, condensed and then subcooled, while the air does not change phase, three sections will form:

>>> Q_sections, T_steps_hot, T_steps_cold, Q_per_section, td_log_per_section = cd.calc_sections()
>>> delta_T_between_sections = T_steps_hot - T_steps_cold
>>> delta_T_list = [round(float(dT), 2) for dT in delta_T_between_sections]
>>> delta_T_list[:6]
[5.0, 16.8, 19.75, 19.6, 19.4, 19.2]

We can see that the lowest delta T is the first one. This is the delta T between the hot side outlet and the cold side inlet, which can also be seen if we have a look at the network’s results.

>>> ();nw.print_results();()
(...)

If we change the subcooling degree at the water outlet, the condensation pressure and pinch will move.

>>> c2.set_attr(td_bubble=5)
>>> nw.solve("design")
>>> round(c1.p.val, 3)
0.042
>>> Q_sections, T_steps_hot, T_steps_cold, Q_per_section, td_log_per_section = cd.calc_sections()
>>> delta_T_between_sections = T_steps_hot - T_steps_cold
>>> delta_T_list = [round(float(dT), 2) for dT in delta_T_between_sections]
>>> delta_T_list[:6]
[9.88, 14.8, 14.68, 14.48, 14.28, 14.08]

Finally, in contrast to the baseclass HeatExchanger kA value, the UA value takes into account the heat transfer per section and calculates the heat transfer coefficient as the sum of all sections, while the kA value only takes into account the inlet and outlet temperatures and the total heat transfer.

>>> round(cd.kA.val)
173307
>>> round(cd.UA.val)
273456

It is also possible to apply a part-load modification to UA following the implementation of [21]. For this you have to specify UA_cecchinato as offdesign parameter and along with it, values for

  • refrigerant side Reynolds exponent

  • secondary fluid side Reynolds exponent

  • secondary fluid to refrigerant area ratio

  • secondary fluid to refrigerant alpha (heat transfer coefficient) ratio

  • the refrigerant index (which side of the heat exchanger is passed by the refrigerant)

>>> design_state = nw.save(as_dict=True)
>>> cd.set_attr(
...     area_ratio=20,        # typical for a finned heat exchanger
...     alpha_ratio=1e-2,     # alpha for water side is higher
...     re_exp_r=0.8,
...     re_exp_sf=0.55,
...     refrigerant_index=0,  # water is refrigerant in this case
...     design=["td_pinch"],
...     offdesign=["UA_cecchinato"]
... )
>>> nw.solve("offdesign", design_path=design_state)

Without modifying any parameter, pinch and UA should be identical to design conditions.

>>> round(cd.td_pinch.val, 2)
5.0
>>> round(cd.UA.val)
273456

With change in operating conditions, e.g. reduction of heat transfer we’d typically observe lower pinch, if the heat transfer reduces faster than the UA value does.

>>> c1.set_attr(m=0.8)
>>> nw.solve("offdesign", design_path=design_state)
>>> round(cd.Q.val_SI / cd.Q.design, 2)
0.8
>>> round(cd.UA.val_SI / cd.UA.design, 2)
0.88
>>> round(cd.td_pinch.val, 2)
4.3

Example

A transcritical gas cooler designed to cool CO2 from 160°C to approximately 50°C while water is heated from 10°C to 60°C. The heat exchanger uses characteristic lines (kA_char1 and kA_char2) to scale the heat transfer coefficient in offdesign operation as mass flow varies.

This two-stage approach improves convergence:

  • Stage 1: Design with fixed pressures to establish initial guess values

  • Stage 2: Offdesign with characteristic line scaling for part-load analysis

>>> from tespy.components import Source, Sink, SectionedHeatExchanger
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> from tespy.tools.characteristics import CharLine, load_default_char

Set up the network with appropriate units:

>>> nw = Network()
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "mass_flow": "kg/s"
... })
>>> nw.iterinfo = False

Create network components: two sources (CO2 and water inlets), the heat exchanger, and two sinks (outlets):

>>> so_co2 = Source("CO2 source")
>>> so_water = Source("Water source")
>>> hx = SectionedHeatExchanger("transcritical gas cooler")
>>> si_co2 = Sink("CO2 sink")
>>> si_water = Sink("Water sink")

Create connections with counter-current arrangement (CO2 on side 1, water on side 2):

>>> c1 = Connection(so_co2, "out1", hx, "in1", label="CO2_in")
>>> c2 = Connection(hx, "out1", si_co2, "in1", label="CO2_out")
>>> c11 = Connection(so_water, "out1", hx, "in2", label="water_in")
>>> c12 = Connection(hx, "out2", si_water, "in1", label="water_out")
>>> nw.add_conns(c1, c2, c11, c12)

Stage 1: Design calculation with fixed pressures

First, we solve with fixed pressures on both sides to generate good initial guess values. This improves convergence for the complex transcritical cycle.

Set CO2 inlet at 165 bar and 160°C (transcritical supercritical state):

>>> c1.set_attr(
...     fluid={"CO2": 1},
...     p=165,
...     T=160,
...     m=3.5
... )

Set water inlet at 5 bar and 10°C (cold inlet for cooling):

>>> c11.set_attr(
...     fluid={"Water": 1},
...     p=5,
...     T=10
... )

Specify water outlet temperature target at 60°C:

>>> c12.set_attr(T=60)

Configure heat exchanger with fixed pressures and initial pinch point:

>>> hx.set_attr(
...     td_pinch=20,
...     pr1=1,
...     pr2=1,
...     num_sections=10
... )

Solve the design point and save results:

>>> nw.solve('design')
>>> design_state = nw.save(as_dict=True)

After design computation, the CO2 outlet state is:

>>> round(c2.p.val, 1)
165.0
>>> round(c2.T.val, 1)
30.0

Stage 2: Offdesign analysis with kA_char characteristic scaling

Now we activate characteristic line-based scaling. Load the default characteristic line for heat exchangers:

>>> kA_char = load_default_char(
...     "HeatExchanger", "kA_char1", "DEFAULT", CharLine
... )

Reconfigure heat exchanger to use characteristic lines for UA scaling in offdesign operation:

>>> hx.set_attr(
...     kA_char1=kA_char,
...     kA_char2=kA_char,
...     design=['td_pinch'],
...     offdesign=['UA_char']
... )

When offdesign is set to ['UA_char'], the solver automatically scales the UA value based on the characteristic curve during part-load operation. Verify offdesign setup by solving at design conditions. The design UA value is approximately 23.4 kW/K and pinch is 20.0 K:

>>> nw.solve('offdesign', design_path=design_state)
>>> round(hx.UA.val / 1e3, 2)
23.42
>>> round(hx.td_pinch.val, 1)
20.0

Characteristic line scaling at part-load conditions

With variable mass flow, the UA value scales according to the characteristic curve. At 80 % mass flow, heat transfer reduces to roughly 83 % while UA reduces by 9.5 % following the characteristic scaling:

>>> c1.set_attr(m=2.8)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(hx.Q.val_SI / hx.Q.design, 2)
0.83
>>> round(hx.UA.val_SI / hx.UA.design, 2)
0.91

The pinch point decreases to 15.3 K when heat transfer reduces faster than the characteristic-based UA scaling:

>>> round(hx.td_pinch.val, 1)
15.3

The kA_char parameter allows automatic part-load scaling of UA, following the same principle as the standard HeatExchanger component (tespy.components.heat_exchangers.base.HeatExchanger). The difference to the UA_char usage is that kA_char uses a characteristic line lookup table to define the scaling relationship. UA_cecchinato requires the specification of Reynolds number exponents, area ratio and alpha ratio of the involved fluids.

UA_cecchinato_func()[source]

Method to calculate heat transfer via UA design with modification for part load according to [21]. UA is determined over the UA values of the sections of the heat exchanger.

Note

You need to specify a couple of parameters to use this method. The values depend on the context, as they define relations between the refrigerant and the secondary fluid. For an evaporator the refrigerant is the cold side, for a condenser it is the hot side. You can check the linked publication for reference values.

  • alpha_ratio: Ratio of secondary fluid to refrigerant heat transfer coefficient

  • area_ratio: Ratio of secondary fluid to refrigerant area

  • re_exp_sf: Reynolds exponent for the secondary fluid mass flow

  • re_exp_r: Reynolds exponent for the refrigerant mass flow

The modification factor for UA is calculated as follows

\[f_\text{UA}=\frac{ 1 + \frac{\alpha_\text{sf}}{\alpha_\text{r}} \cdot\frac{A_\text{sf}}{A_\text{r}} }{ \frac{\dot m_\text{sf}}{\dot m_\text{sf,ref}}^{-Re_\text{sf}} + \frac{\alpha_\text{sf}}{\alpha_\text{r}} \cdot\frac{A_\text{sf}}{A_\text{r}} \cdot\frac{\dot m_\text{r}}{\dot m_\text{r,ref}}^{-Re_\text{r}} }\]
Returns:

float – residual value of equation

\[0 = UA_\text{ref} \cdot f_\text{UA} - \sum UA_\text{i}\]

UA_char_func()[source]

Calculate offdesign UA from characteristic lines analogous to standard heat exchanger kA_char, but for the sectioned heat exchanger.

Returns:

float – Residual value of equation:

\[0 = UA_\text{design} * f_\text{UA} - \sum\left(UA_{i}\right)\]

UA_dependents()[source]
UA_func(**kwargs)[source]

Residual method for fixed heat transfer coefficient UA.

Returns:

residual (float) – Residual value of equation.

\[0 = UA - \sum UA_{i}\]

calc_UA(sections)[source]

Calculate the sum of UA for all sections in the heat exchanger

Returns:

float – Sum of UA values of all heat exchanger sections.

calc_parameters()[source]

Postprocessing parameter calculation.

Each ComponentProperties whose calc attribute is set is called here in topological order (respecting calc_deps dependencies).

Note

Two patterns exist for calc methods, and it is important to keep them distinct:

Pattern A - solver variables only (p, h, m, fluid composition, connection energies E): methods like _calc_P() read only quantities that are unknowns of the solver, therefore these methods can also be used in the residual calculations during iterations.

Pattern B - derived properties (T, v, x, …): methods like _calc_ttd_u or _calc_td_log call helpers such as calc_T() which rely on values that are computed during connection postprocessing (e.g. connection.T.val_SI). These methods must only be called in postprocessing, never during iteration, because the derived values are not yet available.

When adding a new calc method, choose Pattern A if the result depends solely on solver variables; choose Pattern B otherwise, and make sure no caller invokes it during iteration.

calc_td_pinch(T_steps_hot, T_steps_cold)[source]

Calculate the pinch point temperature difference

Returns:

float – Value of the pinch point temperature difference

get_parameters()[source]
td_pinch_dependents()[source]
td_pinch_func()[source]

Equation for minimal pinch temperature difference of sections.

Returns:

residual (float) – Residual value of equation.

\[0 = td_\text{pinch} - min(td_\text{i})\]

tespy.components.heat_exchangers.sectioned.identify_step_at_saturation(x, p_in, h_in, delta_p, delta_h, Q, fluid_data)[source]

Method to identify the step corresponding to a saturation line assuming the change of pressure delta p is linear to the change of enthalpy delta h.

\[\Delta h \cdot \left(p_\text{sat} - p_\text{in}\right) = \Delta p \cdot \left(h_\left[p_\text{sat}, Q\right] - h_\text{in} \right)\]
Parameters:
  • x (float) – Step to solve for

  • p_in (float) – pressure at inlet

  • h_in (float) – enthalpy at inlet

  • delta_p (float) – overall pressure difference

  • delta_h (float) – overall enthalpy difference

  • Q (float) – vapor mass fraction (0 for bubble line, 1 for dew line)

  • fluid_data (dict) – fluid_data dictionary

Returns:

float – residual of equation

tespy.components.heat_exchangers.simple module

Module of class SimpleHeatExchanger.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/simple.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.simple.SimpleHeatExchanger(label, **kwargs)[source]

Bases: Component

A basic heat exchanger representing a heat source or heat sink.

The component SimpleHeatExchanger is the parent class for the components:

Mandatory Equations

Optional Equations

Inlets/Outlets

  • in1

  • out1

Image

flowsheet of the simple heat exchanger flowsheet of the simple heat exchanger
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict, "var") – Heat transfer, \(Q/\text{W}\).

  • pr (float, dict, "var") – Outlet to inlet pressure ratio, \(pr/1\).

  • zeta (float, dict, "var") – Geometry independent friction coefficient, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • D (float, dict, "var") – Diameter of the pipes, \(D/\text{m}\).

  • L (float, dict, "var") – Length of the pipes, \(L/\text{m}\).

  • ks (float, dict, "var") – Pipe’s roughness, \(ks/\text{m}\).

  • darcy_group (str, dict) – Parametergroup for pressure drop calculation based on pipes dimensions using darcy weissbach equation.

  • ks_HW (float, dict, "var") – Pipe’s roughness, \(ks/\text{1}\).

  • hw_group (str, dict) – Parametergroup for pressure drop calculation based on pipes dimensions using hazen williams equation.

  • kA (float, dict, "var") – Area independent heat transfer coefficient, \(kA/\frac{\text{W}}{\text{K}}\).

  • kA_char (tespy.tools.characteristics.CharLine, dict) – Characteristic line for heat transfer coefficient.

  • Tamb (float, dict) – Ambient temperature, provide parameter in network’s temperature unit.

  • kA_group (str, dict) – Parametergroup for heat transfer calculation from ambient temperature and area independent heat transfer coefficient kA.

Example

The SimpleHeatExchanger can be used as a sink or source of heat. This component does not simulate the secondary side of the heat exchanger. It is possible to calculate the pressure ratio with the Darcy-Weisbach equation or in case of liquid water use the Hazen-Williams equation. Also, given ambient temperature and the heat transfer coefficient, it is possible to predict heat transfer.

>>> from tespy.components import Sink, Source, SimpleHeatExchanger
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "enthalpy": "kJ/kg"
... })
>>> so1 = Source('source 1')
>>> si1 = Sink('sink 1')
>>> heat_sink = SimpleHeatExchanger('heat sink')
>>> heat_sink.set_attr(Tamb=10, pr=0.95, design=['pr'],
... offdesign=['zeta', 'kA_char'])
>>> inc = Connection(so1, 'out1', heat_sink, 'in1')
>>> outg = Connection(heat_sink, 'out1', si1, 'in1')
>>> nw.add_conns(inc, outg)

It is possible to determine the amount of heat transferred when the fluid enters the heat sink at a temperature of 200 °C and is cooled down to 150 °C. Given an ambient temperature of 10 °C this also determines the heat transfer coefficient to the ambient. Assuming a characteristic function for the heat transfer coefficient we can predict the heat transferred at variable flow rates.

>>> inc.set_attr(fluid={'N2': 1}, m=1, T=200, p=5)
>>> outg.set_attr(T=150, design=['T'])
>>> nw.solve('design')
>>> design_state = nw.save(as_dict=True)
>>> round(heat_sink.Q.val, 0)
-52581.0
>>> round(heat_sink.kA.val, 0)
321.0
>>> inc.set_attr(m=1.25)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(heat_sink.Q.val, 0)
-56599.0
>>> round(outg.T.val, 1)
156.9
>>> inc.set_attr(m=0.75)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(heat_sink.Q.val, 1)
-47275.8
>>> round(outg.T.val, 1)
140.0

Use of the HeatConnection

Single sided heat exchangers can also connect to a HeatConnection. The component auto-detects whether the connection is on the inlet or outlet side - no prior declaration is needed.

>>> from tespy.connections import HeatConnection
>>> from tespy.components import HeatSink
>>> ambient = HeatSink('ambient heat dissipation')

Create and add the HeatConnection as an outlet. We run a new design calculation, because the old design case did not include the HeatConnection. The energy value will be identical to the heat transfer of the component.

>>> h1 = HeatConnection(heat_sink, 'heat', ambient, 'heat', label='h1')
>>> nw.add_conns(h1)
>>> nw.solve('design')
>>> round(h1.E.val) == round(-heat_sink.Q.val)
True
calc_parameters()[source]

Postprocessing parameter calculation.

convergence_check()[source]
darcy_dependents()[source]
darcy_func()[source]

Equation for pressure drop calculation from darcy friction factor.

Returns:

residual (float) – Residual value of equation.

\[ \begin{align}\begin{aligned}\begin{split}0 = p_{in} - p_{out} - \frac{8 \cdot |\dot{m}_{in}| \cdot \dot{m}_{in} \cdot \frac{v_{in}+v_{out}}{2} \cdot L \cdot \lambda\left(Re, ks, D\right)}{\pi^2 \cdot D^5}\\\end{split}\\\begin{split}Re = \frac{4 \cdot |\dot{m}_{in}|}{\pi \cdot D \cdot \frac{\eta_{in}+\eta_{out}}{2}}\\ \eta: \text{dynamic viscosity}\\ v: \text{specific volume}\\ \lambda: \text{darcy friction factor}\end{split}\end{aligned}\end{align} \]

energy_balance_dependents()[source]
energy_balance_func()[source]

Equation for pressure drop calculation.

Returns:

residual (float) – Residual value of equation:

\[0 =\dot{m}_{in}\cdot\left( h_{out}-h_{in}\right) -\dot{Q}\]

energy_connector_balance_func()[source]
energy_connector_dependents()[source]
entropy_balance()[source]

Calculate entropy balance of a simple heat exchanger.

The allocation of the entropy streams due to heat exchanged and due to irreversibility is performed by solving for T:

\[h_\text{out} - h_\text{in} = \int_\text{out}^\text{in} v \cdot dp - \int_\text{out}^\text{in} T \cdot ds\]

As solving \(\int_\text{out}^\text{in} v \cdot dp\) for non isobaric processes would require perfect process knowledge (the path) on how specific volume and pressure change throught the component, the heat transfer is split into three separate virtual processes:

  • in->in*: decrease pressure to \(p_\text{in*}=p_\text{in}\cdot\sqrt{\frac{p_\text{out}}{p_\text{in}}}\) without changing enthalpy.

  • in*->out* transfer heat without changing pressure. \(h_\text{out*}-h_\text{in*}=h_\text{out}-h_\text{in}\)

  • out*->out decrease pressure to outlet pressure \(p_\text{out}\) without changing enthalpy.

Note

The entropy balance makes the following parameter available:

\[\begin{split}\text{S\_Q}=\dot{m} \cdot \left(s_\text{out*}-s_\text{in*} \right)\\ \text{S\_irr}=\dot{m} \cdot \left(s_\text{out}-s_\text{in} \right) - \text{S\_Q}\\ \text{T\_mQ}=\frac{\dot{Q}}{\text{S\_Q}}\end{split}\]
get_bypass_constraints()[source]
get_mandatory_constraints()[source]
get_parameters()[source]
get_plotting_data()[source]

Generate a dictionary containing FluProDia plotting information.

Returns:

data (dict) – A nested dictionary containing the keywords required by the calc_individual_isoline method of the FluidPropertyDiagram class. First level keys are the connection index (‘in1’ -> ‘out1’, therefore 1 etc.).

hazen_williams_dependents()[source]
hazen_williams_func()[source]

Equation for pressure drop calculation from Hazen-Williams equation.

Returns:

residual (float) – Residual value of equation.

\[ \begin{align}\begin{aligned}0 = \left(p_{in} - p_{out} \right) \cdot \left(-1\right)^i - \frac{10.67 \cdot |\dot{m}_{in}| ^ {1.852} \cdot L}{ks^{1.852} \cdot D^{4.871}} \cdot g \cdot \left(\frac{v_{in} + v_{out}}{2}\right)^{0.852}\\\begin{split}i = \begin{cases} 0 & \dot{m}_{in} \geq 0\\ 1 & \dot{m}_{in} < 0 \end{cases}\end{split}\end{aligned}\end{align} \]

Note

Gravity \(g\) is set to \(9.81 \frac{m}{s^2}\)

static heatinlets()[source]
static heatoutlets()[source]
initialise_source(c, key)[source]

Return a starting value for pressure and enthalpy the outlets.

Parameters:
  • c (tespy.connections.connection.Connection) – Connection to perform initialisation on.

  • key (str) – Fluid property to retrieve.

Returns:

val (float) – Starting value for pressure/enthalpy in SI units.

\[\begin{split}val = \begin{cases} \begin{cases} 1 \cdot 10^5 \; \frac{\text{J}}{\text{kg}} & \dot{Q} < 0\\ 3 \cdot 10^5 \; \frac{\text{J}}{\text{kg}} & \dot{Q} = 0\\ 5 \cdot 10^5 \; \frac{\text{J}}{\text{kg}} & \dot{Q} > 0 \end{cases} & \text{key = 'h'}\\ \; \; \; \; 10^5 \text{Pa} & \text{key = 'p'} \end{cases}\end{split}\]

initialise_target(c, key)[source]

Return a starting value for pressure and enthalpy the inlets.

Parameters:
  • c (tespy.connections.connection.Connection) – Connection to perform initialisation on.

  • key (str) – Fluid property to retrieve.

Returns:

val (float) – Starting value for pressure/enthalpy in SI units.

\[\begin{split}val = \begin{cases} 1 \cdot 10^5 & \text{key = 'p'}\\ \begin{cases} 5 \cdot 10^5 & \dot{Q} < 0\\ 3 \cdot 10^5 & \dot{Q} = 0\\ 1 \cdot 10^5 & \dot{Q} > 0 \end{cases} & \text{key = 'h'}\\ \end{cases}\end{split}\]

static inlets()[source]
kA_char_group_dependents()[source]
kA_char_group_func()[source]

Calculate heat transfer from heat transfer coefficient characteristic.

Returns:

residual (float) – Residual value of equation.

\[ \begin{align}\begin{aligned}0 = \dot{m}_{in} \cdot \left( h_{out} - h_{in}\right) + kA_{design} \cdot f_{kA} \cdot \Delta T_{log}\\\begin{split}\Delta T_{log} = \begin{cases} \frac{T_{in}-T_{out}}{\ln{\frac{T_{in}-T_{amb}} {T_{out}-T_{amb}}}} & T_{in} > T_{out} \\ \frac{T_{out}-T_{in}}{\ln{\frac{T_{out}-T_{amb}} {T_{in}-T_{amb}}}} & T_{in} < T_{out}\\ 0 & T_{in} = T_{out} \end{cases}\end{split}\\f_{kA} = \frac{2}{1 + \frac{1}{f\left( expr\right)}}\\T_{amb}: \text{ambient temperature}\end{aligned}\end{align} \]

Note

For standard function of fkA see module tespy.data.

kA_group_dependents()[source]
kA_group_func()[source]

Calculate heat transfer from heat transfer coefficient.

Returns:

residual (float) – Residual value of equation.

\[ \begin{align}\begin{aligned}0 = \dot{m}_{in} \cdot \left( h_{out} - h_{in}\right) + kA \cdot \Delta T_{log}\\\begin{split}\Delta T_{log} = \begin{cases} \frac{T_{in}-T_{out}}{\ln{\frac{T_{in}-T_{amb}} {T_{out}-T_{amb}}}} & T_{in} > T_{out} \\ \frac{T_{out}-T_{in}}{\ln{\frac{T_{out}-T_{amb}} {T_{in}-T_{amb}}}} & T_{in} < T_{out}\\ 0 & T_{in} = T_{out} \end{cases}\end{split}\\T_{amb}: \text{ambient temperature}\end{aligned}\end{align} \]

static outlets()[source]
static powerinlets()[source]
static poweroutlets()[source]
set_attr(**kwargs)[source]

Set, reset or unset attributes of a component for provided arguments.

Parameters:
  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • **kwargs – See the class documentation of desired component for available keywords.

Note

Allowed keywords in kwargs are obtained from class documentation as all components share the tespy.components.component.Component.set_attr() method.

tespy.components.heat_exchangers.solar_collector module

Module of class SolarCollector.

This file is part of project TESPy (github.com/oemof/tespy). It’s copyrighted by the contributors recorded in the version control history of the file, available from its original location tespy/components/heat_exchangers/solar_collector.py

SPDX-License-Identifier: MIT

class tespy.components.heat_exchangers.solar_collector.SolarCollector(label, **kwargs)[source]

Bases: SimpleHeatExchanger

The solar collector calculates heat output from irradiance.

Mandatory Equations

Optional Equations

Inlets/Outlets

  • in1

  • out1

Image

flowsheet of the solar collector flowsheet of the solar collector
Parameters:
  • label (str) – The label of the component.

  • design (list) – List containing design parameters (stated as String).

  • offdesign (list) – List containing offdesign parameters (stated as String).

  • design_path (str) – Path to the components design case.

  • local_offdesign (boolean) – Treat this component in offdesign mode in a design calculation.

  • local_design (boolean) – Treat this component in design mode in an offdesign calculation.

  • char_warnings (boolean) – Ignore warnings on default characteristics usage for this component.

  • printout (boolean) – Include this component in the network’s results printout.

  • Q (float, dict, "var") – Heat transfer, \(Q/\text{W}\).

  • pr (float, dict, "var") – Outlet to inlet pressure ratio, \(pr/1\).

  • zeta (float, dict, "var") – Geometry independent friction coefficient, \(\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}\).

  • D (float, dict, "var") – Diameter of the pipes, \(D/\text{m}\).

  • L (float, dict, "var") – Length of the pipes, \(L/\text{m}\).

  • ks (float, dict, "var") – Pipe’s roughness, \(ks/\text{m}\).

  • darcy_group (str, dict) – Parametergroup for pressure drop calculation based on pipes dimensions using darcy weissbach equation.

  • ks_HW (float, dict, "var") – Pipe’s roughness, \(ks/\text{1}\).

  • hw_group (str, dict) – Parametergroup for pressure drop calculation based on pipes dimensions using hazen williams equation.

  • E (float, dict, "var") – irradiance at tilted collector surface area, \(E/\frac{\text{W}}{\text{m}^2}\).

  • eta_opt (float, dict, "var") – optical loss at surface cover, \(\eta_{opt}\).

  • lkf_lin (float, dict, "var") – Linear thermal loss key figure, \(\alpha_1/\frac{\text{W}}{\text{K} \cdot \text{m}^2}\).

  • lkf_quad (float, dict, "var") – Quadratic thermal loss key figure, \(\alpha_2/\frac{\text{W}}{\text{K}^2 \cdot \text{m}^2}\).

  • A (float, dict, "var") – Collector surface area \(A/\text{m}^2\).

  • Tamb (float, dict) – Ambient temperature, provide parameter in network’s temperature unit.

  • energy_group (str, dict) – Parametergroup for energy balance of solarthermal collector.

Example

The solar collector is used to calculate heat transferred to the heating system from irradiance on a tilted plane. For instance, it is possible to calculate the collector surface area required to transfer a specific amount of heat at a given irradiance. The collector parameters are the linear and the quadratic loss keyfigure as well as the optical effifiency.

>>> from tespy.components import Sink, Source, SolarCollector
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "bar", "pressure_difference": "bar",
...     "temperature": "degC", "enthalpy": "kJ/kg"
... })
>>> so = Source('source')
>>> si = Sink('sink')
>>> sc = SolarCollector('solar collector')
>>> sc.set_attr(pr=0.95, Q=1e4, design=['pr', 'Q'], offdesign=['zeta'],
...     Tamb=25, A='var', eta_opt=0.92, lkf_lin=1, lkf_quad=0.005, E=8e2)
>>> inc = Connection(so, 'out1', sc, 'in1')
>>> outg = Connection(sc, 'out1', si, 'in1')
>>> nw.add_conns(inc, outg)

The outlet temperature should be at 90 °C at a constant mass flow, which is determined in the design calculation. In offdesign operation (at a different irradiance) using the calculated surface area and mass flow, it is possible to predict the outlet temperature. It would instead be possible to calculate the change in mass flow required to hold the specified outlet temperature, too.

>>> inc.set_attr(fluid={'H2O': 1}, T=40, p=3, offdesign=['m'])
>>> outg.set_attr(T=90, design=['T'])
>>> nw.solve('design')
>>> design_state = nw.save(as_dict=True)
>>> round(sc.A.val, 1)
14.5
>>> sc.set_attr(A=sc.A.val, E=5e2, Tamb=20)
>>> nw.solve('offdesign', design_path=design_state)
>>> round(sc.Q.val, 1)
6083.8
>>> round(outg.T.val, 1)
70.5
calc_parameters()[source]

Postprocessing parameter calculation.

convergence_check()[source]
energy_group_dependents()[source]
energy_group_func()[source]

Equation for solar collector energy balance.

Returns:

residual (float) – Residual value of equation.

\[\begin{split}\begin{split} 0 = & \dot{m} \cdot \left( h_{out} - h_{in} \right)\\ & - A \cdot \left[E \cdot \eta_{opt} - \alpha_1 \cdot \left(T_m - T_{amb} \right) - \alpha_2 \cdot \left(T_m - T_{amb}\right)^2 \right]\\ T_m = & \frac{T_{out} + T_{in}}{2}\\ \end{split}\end{split}\]

Reference: [37].

get_parameters()[source]