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:
ComponentClass for counter flow heat exchanger.
The component HeatExchanger is the parent class for the components:
tespy.components.heat_exchangers.desuperheater.Desuperheatertespy.components.heat_exchangers.movingboundary.MovingBoundaryHeatExchanger
Mandatory Equations
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_func()
Optional Equations
tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_char_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_u_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_l_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_min_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_cold_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_max_func()
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
- 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_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_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_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_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_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_plotting_data()[source]¶
Generate a dictionary containing FluProDia plotting information.
- Returns:
data (dict) – A nested dictionary containing the keywords required by the
calc_individual_isolinemethod of theFluidPropertyDiagramclass. First level keys are the connection index (‘in1’ -> ‘out1’, therefore1etc.).
- 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.
- 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_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}}}}\]
- 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}\]
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:
HeatExchangerA 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
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_func()condensate outlet state, function can be disabled by specifying
set_attr(subcooling=True)tespy.components.heat_exchangers.condenser.Condenser.subcooling_func()
Optional Equations
The
Condenserclass uses an individual definition for the calculation of the logarithmic temperature differencetespy.components.heat_exchangers.base.HeatExchanger.energy_balance_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_char_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_u_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_l_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_min_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_cold_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_max_func()
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
- 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
- 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.
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:
HeatExchangerThe Desuperheater cools a fluid to the saturated gas state.
Mandatory Equations
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_func()tespy.components.heat_exchangers.desuperheater.Desuperheater.saturated_gas_func()
Optional Equations
tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_char_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_u_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_l_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_min_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_cold_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_max_func()
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
- 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
- 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.
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:
SectionedHeatExchangerClass 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
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_func()
Optional Equations
tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_hot_func()tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger.UA_func()tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger.td_pinch_func()tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger.UA_cecchinato_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_u_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_l_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_min_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_cold_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_max_func()
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
- 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
HeatExchangerkA 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_cecchinatoas offdesign parameter and along with it, values forrefrigerant 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
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:
SimpleHeatExchangerThe ParabolicTrough calculates heat output from irradiance.
Mandatory Equations
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()
Optional Equations
tespy.components.heat_exchangers.simple.SimpleHeatExchanger.energy_balance_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.darcy_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.hazen_williams_func()tespy.components.heat_exchangers.parabolic_trough.ParabolicTrough.energy_group_func()
Inlets/Outlets
in1
out1
Image
- 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
- 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].
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:
HeatExchangerClass for parallel flow heat exchanger.
Mandatory Equations
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_func()
Optional Equations
tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_func()tespy.components.heat_exchangers.base.HeatExchanger.kA_char_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_u_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_l_func()
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
- 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
ParallelFlowHeatExchangerimplements 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_uof 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 coefficientkAas 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
kAvalue 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
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:
HeatExchangerClass 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
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_func()
Optional Equations
tespy.components.heat_exchangers.base.HeatExchanger.energy_balance_hot_func()tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger.UA_func()tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger.td_pinch_func()tespy.components.heat_exchangers.sectioned.SectionedHeatExchanger.UA_cecchinato_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_u_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_l_func()tespy.components.heat_exchangers.base.HeatExchanger.ttd_min_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_cold_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_hot_func()tespy.components.heat_exchangers.base.HeatExchanger.eff_max_func()
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
- 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
HeatExchangerkA 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_cecchinatoas offdesign parameter and along with it, values forrefrigerant 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_charparameter 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 theUA_charusage is thatkA_charuses a characteristic line lookup table to define the scaling relationship.UA_cecchinatorequires 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_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
ComponentPropertieswhosecalcattribute is set is called here in topological order (respectingcalc_depsdependencies).Note
Two patterns exist for
calcmethods, 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_uor_calc_td_logcall helpers such ascalc_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
calcmethod, choose Pattern A if the result depends solely on solver variables; choose Pattern B otherwise, and make sure no caller invokes it during iteration.
- 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:
ComponentA basic heat exchanger representing a heat source or heat sink.
The component SimpleHeatExchanger is the parent class for the components:
tespy.components.heat_exchangers.solar_collector.SolarCollectortespy.components.heat_exchangers.parabolic_trough.ParabolicTrough
Mandatory Equations
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()
Optional Equations
tespy.components.heat_exchangers.simple.SimpleHeatExchanger.energy_balance_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.darcy_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.hazen_williams_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.kA_group_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.kA_char_group_func()
Inlets/Outlets
in1
out1
Image
- 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
HeatConnectionas an outlet. We run a new design calculation, because the old design case did not include theHeatConnection. 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
- 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_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}\]
- 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_plotting_data()[source]¶
Generate a dictionary containing FluProDia plotting information.
- Returns:
data (dict) – A nested dictionary containing the keywords required by the
calc_individual_isolinemethod of theFluidPropertyDiagramclass. First level keys are the connection index (‘in1’ -> ‘out1’, therefore1etc.).
- 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}\]
- 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_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} \]
- 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:
SimpleHeatExchangerThe solar collector calculates heat output from irradiance.
Mandatory Equations
fluid:
tespy.components.component.Component.variable_equality_structure_matrix()mass flow:
tespy.components.component.Component.variable_equality_structure_matrix()
Optional Equations
tespy.components.heat_exchangers.simple.SimpleHeatExchanger.energy_balance_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.darcy_func()tespy.components.heat_exchangers.simple.SimpleHeatExchanger.hazen_williams_func()tespy.components.heat_exchangers.solar_collector.SolarCollector.energy_group_func()
Inlets/Outlets
in1
out1
Image
- 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
- 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].