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_\mathrm{l}/\text{K}\).

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

  • ttd_min (float, dict) – Minumum terminal temperature difference \(ttd_\mathrm{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
>>> import os
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "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'])
>>> he_cw.set_attr(h0=1e2)
>>> 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')
>>> nw.save('tmp.json')
>>> round(ex_he.T.val - he_cw.T.val, 0)
5.0
>>> ex_he.set_attr(v=0.075)
>>> nw.solve('offdesign', design_path='tmp.json')
>>> 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='tmp.json')
>>> round(he_cw.T.val, 1)
33.9
>>> round(he_ex.T.val, 1)
18.8
>>> os.remove("tmp.json")
bus_deriv(bus)[source]

Calculate partial derivatives of the bus function.

Parameters:

bus (tespy.connections.bus.Bus) – TESPy bus object.

Returns:

deriv (ndarray) – Matrix of partial derivatives.

bus_func(bus)[source]

Calculate the value of the bus function.

Parameters:

bus (tespy.connections.bus.Bus) – TESPy bus object.

Returns:

val (float) – Value of energy transfer \(\dot{E}\). This value is passed to tespy.components.component.Component.calc_bus_value() for value manipulation according to the specified characteristic line of the bus.

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

calc_dh_max_cold()[source]

Calculate the theoretical maximum enthalpy increase on the cold side

Returns:

float – Maxmium 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 – Maxmium hot side enthalpy decrease.

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

calc_parameters()[source]

Postprocessing parameter calculation.

calculate_td_log()[source]
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_\mathrm{out} - h_\mathrm{in} = \int_\mathrm{in}^\mathrm{out} v \cdot dp - \int_\mathrm{in}^\mathrm{out} T \cdot ds\]

As solving \(\int_\mathrm{in}^\mathrm{out} 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 splitted into three separate virtual processes for both sides:

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

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

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

Note

The entropy balance makes the follwing parameter available:

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

Calculate exergy balance of a heat exchanger.

Parameters:

T0 (float) – Ambient temperature T0 / K.

Note

\[ \begin{align}\begin{aligned}\begin{split}\dot{E}_\mathrm{P} = \begin{cases} \dot{E}_\mathrm{out,2}^\mathrm{T} - \dot{E}_\mathrm{in,2}^\mathrm{T} & T_\mathrm{in,1}, T_\mathrm{in,2}, T_\mathrm{out,1}, T_\mathrm{out,2} > T_0\\ \dot{E}_\mathrm{out,1}^\mathrm{T} - \dot{E}_\mathrm{in,1}^\mathrm{T} & T_0 \geq T_\mathrm{in,1}, T_\mathrm{in,2}, T_\mathrm{out,1}, T_\mathrm{out,2}\\ \dot{E}_\mathrm{out,1}^\mathrm{T} + \dot{E}_\mathrm{out,2}^\mathrm{T} & T_\mathrm{in,1}, T_\mathrm{out,2} > T_0 \geq T_\mathrm{in,2}, T_\mathrm{out,1}\\ \dot{E}_\mathrm{out,1}^\mathrm{T} & T_\mathrm{in,1} > T_0 \geq T_\mathrm{in,2}, T_\mathrm{out,1}, T_\mathrm{out,2}\\ \text{not defined (nan)} & T_\mathrm{in,1}, T_\mathrm{out,1} > T_0 \geq T_\mathrm{in,2}, T_\mathrm{out,2}\\ \dot{E}_\mathrm{out,2}^\mathrm{T} & T_\mathrm{in,1}, T_\mathrm{out,1}, T_\mathrm{out,2} \geq T_0 > T_\mathrm{in,2}\\ \end{cases}\end{split}\\\begin{split}\dot{E}_\mathrm{F} = \begin{cases} \dot{E}_\mathrm{in,1}^\mathrm{PH} - \dot{E}_\mathrm{out,1}^\mathrm{PH} + \dot{E}_\mathrm{in,2}^\mathrm{M} - \dot{E}_\mathrm{out,2}^\mathrm{M} & T_\mathrm{in,1}, T_\mathrm{in,2}, T_\mathrm{out,1}, T_\mathrm{out,2} > T_0\\ \dot{E}_\mathrm{in,2}^\mathrm{PH} - \dot{E}_\mathrm{out,2}^\mathrm{PH} + \dot{E}_\mathrm{in,1}^\mathrm{M} - \dot{E}_\mathrm{out,1}^\mathrm{M} & T_0 \geq T_\mathrm{in,1}, T_\mathrm{in,2}, T_\mathrm{out,1}, T_\mathrm{out,2}\\ \dot{E}_\mathrm{in,1}^\mathrm{PH} + \dot{E}_\mathrm{in,2}^\mathrm{PH} - \dot{E}_\mathrm{out,1}^\mathrm{M} - \dot{E}_\mathrm{out,2}^\mathrm{M} & T_\mathrm{in,1}, T_\mathrm{out,2} > T_0 \geq T_\mathrm{in,2}, T_\mathrm{out,1}\\ \dot{E}_\mathrm{in,1}^\mathrm{PH} + \dot{E}_\mathrm{in,2}^\mathrm{PH} - \dot{E}_\mathrm{out,2}^\mathrm{PH} - \dot{E}_\mathrm{out,1}^\mathrm{M} & T_\mathrm{in,1} > T_0 \geq T_\mathrm{in,2}, T_\mathrm{out,1}, T_\mathrm{out,2}\\ \dot{E}_\mathrm{in,1}^\mathrm{PH} - \dot{E}_\mathrm{out,1}^\mathrm{PH} + \dot{E}_\mathrm{in,2}^\mathrm{PH} - \dot{E}_\mathrm{out,2}^\mathrm{PH} & T_\mathrm{in,1}, T_\mathrm{out,1} > T_0 \geq T_\mathrm{in,2}, T_\mathrm{out,2}\\ \dot{E}_\mathrm{in,1}^\mathrm{PH} - \dot{E}_\mathrm{out,1}^\mathrm{PH} + \dot{E}_\mathrm{in,2}^\mathrm{PH} - \dot{E}_\mathrm{out,2}^\mathrm{M} & T_\mathrm{in,1}, T_\mathrm{out,1}, T_\mathrm{out,2} \geq T_0 > T_\mathrm{in,2}\\ \end{cases}\end{split}\end{aligned}\end{align} \]
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_\mathrm{l}/\text{K}\).

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

  • ttd_min (float, dict) – Minumum terminal temperature difference \(ttd_\mathrm{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
>>> import os
>>> nw = Network(m_range=[0.01, 1000], iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "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')
>>> nw.save('tmp.json')
>>> 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='tmp.json')
>>> 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='tmp.json')
>>> 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
>>> os.remove('tmp.json')
calc_parameters()[source]

Postprocessing parameter calculation.

calculate_td_log()[source]
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_\mathrm{l}/\text{K}\).

  • ttd_u (float, dict) – Upper terminal temperature difference \(ttd_\mathrm{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
>>> import os
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "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')
>>> nw.save('tmp.json')
>>> 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='tmp.json')
>>> round(cw_de.v.val, 2)
1.94
>>> et_de.set_attr(v=7)
>>> nw.solve('offdesign', init_path='tmp.json', design_path='tmp.json')
>>> round(cw_de.v.val, 2)
0.41
>>> os.remove('tmp.json')
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 [26].

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 [24], 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", "temperature": "degC"
... })
>>> nw.set_attr(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 [24]. 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)

>>> import os
>>> nw.save("design.json")
>>> 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.json")

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.json")
>>> 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
>>> os.remove("design.json")
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 [27] are reproduced. Therefore, the direct normal irradiance \(\dot{E}_\mathrm{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", "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: [27].

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_\mathrm{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_\mathrm{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
>>> import os
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "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"])
>>> nw.save("design.json")
>>> nw.solve("offdesign", design_path="design.json")
>>> 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.json")
>>> round(c2.T.val, 2)
38.69
>>> c3.set_attr(v=2500, T=8)
>>> nw.solve("offdesign", design_path="design.json")
>>> round(c2.T.val, 2)
44.0
>>> os.remove("design.json")
calc_parameters()[source]

Postprocessing parameter calculation.

calculate_td_log()[source]
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 [28].

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_\mathrm{l}/\text{K}\).

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

  • ttd_min (float, dict) – Minimum terminal temperature difference \(ttd_\mathrm{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 [24], 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", "temperature": "degC"
... })
>>> nw.set_attr(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 [24]. 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)

>>> import os
>>> nw.save("design.json")
>>> 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.json")

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.json")
>>> 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
>>> os.remove("design.json")
UA_cecchinato_func()[source]

Method to calculate heat transfer via UA design with modification for part load according to [24]. 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_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_\text{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.

calc_sections(postprocess=True)[source]

Calculate the sections of the heat exchanger.

Returns:

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

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 coeffiecient, it is possible to predict heat transfer.

>>> from tespy.components import Sink, Source, SimpleHeatExchanger
>>> from tespy.connections import Connection
>>> from tespy.networks import Network
>>> import os
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "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')
>>> nw.save('tmp.json')
>>> 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='tmp.json')
>>> 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='tmp.json')
>>> round(heat_sink.Q.val, 1)
-47275.8
>>> round(outg.T.val, 1)
140.0
>>> os.remove('tmp.json')

Use of the PowerConnection

Single sided heat exchangers can also connect to a PowerConnection. In this case the heat exchanger represents a heat source from the perspective of the PowerConnection, meaning, we need a PowerSink component as target of that connection. To utilize the component in this connects, it is required to set the power_connector_location, in this case it should be the 'outlet'.

>>> from tespy.connections import PowerConnection
>>> from tespy.components import PowerSink
>>> ambient = PowerSink('ambient heat dissipation')
>>> heat_sink.set_attr(power_connector_location='outlet')

Then we can create and add the PowerConnection. We run a new design calculation, because the old design case did not inlcude the PowerConnection. The energy value will be identical to the heat transfer of the pipe.

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

Calculate partial derivatives of the bus function.

Parameters:

bus (tespy.connections.bus.Bus) – TESPy bus object.

Returns:

deriv (ndarray) – Matrix of partial derivatives.

bus_func(bus)[source]

Calculate the value of the bus function.

Parameters:

bus (tespy.connections.bus.Bus) – TESPy bus object.

Returns:

val (float) – Value of energy transfer \(\dot{E}\). This value is passed to tespy.components.component.Component.calc_bus_value() for value manipulation according to the specified characteristic line of the bus.

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

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_\mathrm{out} - h_\mathrm{in} = \int_\mathrm{out}^\mathrm{in} v \cdot dp - \int_\mathrm{out}^\mathrm{in} T \cdot ds\]

As solving \(\int_\mathrm{out}^\mathrm{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 splitted into three separate virtual processes:

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

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

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

Note

The entropy balance makes the follwing parameter available:

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

Calculate exergy balance of a simple heat exchanger.

The exergy of heat is calculated by allocation of thermal and mechanical share of exergy in the physical exergy. Depending on the temperature levels at the inlet and outlet of the heat exchanger as well as the direction of heat transfer (input or output) fuel and product exergy are calculated as follows.

Parameters:

T0 (float) – Ambient temperature T0 / K.

Note

If the fluid transfers heat to the ambient, you can specify mysimpleheatexchanger.set_attr(dissipative=False) if you do NOT want the exergy production nan (only applicable in case \(\dot{Q}<0\)).

\[ \begin{align}\begin{aligned}\begin{split}\dot{E}_\mathrm{P} = \begin{cases} \begin{cases} \begin{cases} \text{not defined (nan)} & \text{if dissipative}\\ \dot{E}_\mathrm{in}^\mathrm{T} - \dot{E}_\mathrm{out}^\mathrm{T} & \text{else}\\ \end{cases} & T_\mathrm{in}, T_\mathrm{out} \geq T_0\\ \dot{E}_\mathrm{out}^\mathrm{T} & T_\mathrm{in} \geq T_0 > T_\mathrm{out}\\ \dot{E}_\mathrm{out}^\mathrm{T} - \dot{E}_\mathrm{in}^\mathrm{T} & T_0 \geq T_\mathrm{in}, T_\mathrm{out}\\ \end{cases} & \dot{Q} < 0\\\end{split}\\\begin{split}\begin{cases} \dot{E}_\mathrm{out}^\mathrm{PH} - \dot{E}_\mathrm{in}^\mathrm{PH} & T_\mathrm{in}, T_\mathrm{out} \geq T_0\\ \dot{E}_\mathrm{in}^\mathrm{T} + \dot{E}_\mathrm{out}^\mathrm{T} & T_\mathrm{out} > T_0 \geq T_\mathrm{in}\\ \dot{E}_\mathrm{in}^\mathrm{T} - \dot{E}_\mathrm{out}^\mathrm{T} + \dot{E}_\mathrm{out}^\mathrm{M} - \dot{E}_\mathrm{in}^\mathrm{M} + & T_0 \geq T_\mathrm{in}, T_\mathrm{out}\\ \end{cases} & \dot{Q} > 0\\ \end{cases}\end{split}\\\begin{split}\dot{E}_\mathrm{F} = \begin{cases} \begin{cases} \dot{E}_\mathrm{in}^\mathrm{PH} - \dot{E}_\mathrm{out}^\mathrm{PH} & T_\mathrm{in}, T_\mathrm{out} \geq T_0\\ \dot{E}_\mathrm{in}^\mathrm{T} + \dot{E}_\mathrm{in}^\mathrm{M} + \dot{E}_\mathrm{out}^\mathrm{T} - \dot{E}_\mathrm{out}^\mathrm{M} & T_\mathrm{in} \geq T_0 > T_\mathrm{out}\\ \dot{E}_\mathrm{out}^\mathrm{T} - \dot{E}_\mathrm{in}^\mathrm{T} + \dot{E}_\mathrm{in}^\mathrm{M} - \dot{E}_\mathrm{out}^\mathrm{M} + & T_0 \geq T_\mathrm{in}, T_\mathrm{out}\\ \end{cases} & \dot{Q} < 0\\\end{split}\\\begin{split}\begin{cases} \dot{E}_\mathrm{out}^\mathrm{T} - \dot{E}_\mathrm{in}^\mathrm{T} & T_\mathrm{in}, T_\mathrm{out} \geq T_0\\ \dot{E}_\mathrm{in}^\mathrm{T} + \dot{E}_\mathrm{in}^\mathrm{M} - \dot{E}_\mathrm{out}^\mathrm{M} & T_\mathrm{out} > T_0 \geq T_\mathrm{in}\\ \dot{E}_\mathrm{in}^\mathrm{T}-\dot{E}_\mathrm{out}^\mathrm{T} & T_0 \geq T_\mathrm{in}, T_\mathrm{out}\\ \end{cases} & \dot{Q} > 0\\ \end{cases}\end{split}\\\begin{split}\dot{E}_\mathrm{bus} = \begin{cases} \begin{cases} \dot{E}_\mathrm{P} & \text{other cases}\\ \dot{E}_\mathrm{in}^\mathrm{T} & T_\mathrm{in} \geq T_0 > T_\mathrm{out}\\ \end{cases} & \dot{Q} < 0\\ \dot{E}_\mathrm{F} & \dot{Q} > 0\\ \end{cases}\end{split}\end{aligned}\end{align} \]
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}\)

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]
powerinlets()[source]
poweroutlets()[source]

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
>>> import os
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(**{
...     "pressure": "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 calulate 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')
>>> nw.save('tmp.json')
>>> round(sc.A.val, 1)
14.5
>>> sc.set_attr(A=sc.A.val, E=5e2, Tamb=20)
>>> nw.solve('offdesign', design_path='tmp.json')
>>> round(sc.Q.val, 1)
6083.8
>>> round(outg.T.val, 1)
70.5
>>> os.remove('tmp.json')
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: [29].

get_parameters()[source]