Skip to content

Commit

Permalink
Merge branch 'feature/add-heat-exchanger-dp-attribute' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
fwitte committed Dec 4, 2024
2 parents 3d2b5db + 6632a14 commit 63893c9
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 68 deletions.
8 changes: 8 additions & 0 deletions docs/whats_new/v0-7-7.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Under development
+++++++++++++++++

New Features
############
- The `HeatExchanger` class now has three new attributes, :code:`dp1`,
:code:`dp2` (hot side and cold side pressure drop in network pressure unit)
as well as :code:`ttd_min` for the minimal value of the terminal temperature
diference values
(`PR #581 <https://github.com/oemof/tespy/pull/581>`__).

Bug Fixes
#########
- Only :code:`.json` format files are loaded by the `load_network` method.
Expand Down
58 changes: 58 additions & 0 deletions src/tespy/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,3 +1230,61 @@ def zeta_deriv(self, increment_filter, k, zeta='', inconn=0, outconn=0):
# custom variable zeta
if data.is_var:
self.jacobian[k, data.J_col] = self.numeric_deriv(f, zeta, None, **kwargs)

def dp_func(self, dp=None, inconn=None, outconn=None):
"""Calculate residual value of pressure difference function.
Parameters
----------
dp : str
Component parameter to evaluate the dp_func on, e.g.
:code:`dp1`.
inconn : int
Connection index of inlet.
outconn : int
Connection index of outlet.
Returns
-------
residual : float
Residual value of function.
.. math::
0 = p_{in} - p_{out} - dp
"""
inlet_conn = self.inl[inconn]
outlet_conn = self.outl[outconn]
dp_value = self.get_attr(dp).val_SI
return inlet_conn.p.val_SI - outlet_conn.p.val_SI - dp_value

def dp_deriv(self, increment_filter, k, dp=None, inconn=None, outconn=None):
r"""
Calculate residual value of pressure difference function.
Parameters
----------
increment_filter : ndarray
Matrix for filtering non-changing variables.
k : int
Position of equation in Jacobian matrix.
dp : str
Component parameter to evaluate the dp_func on, e.g.
:code:`dp1`.
inconn : int
Connection index of inlet.
outconn : int
Connection index of outlet.
"""
inlet_conn = self.inl[inconn]
outlet_conn = self.outl[outconn]
if inlet_conn.p.is_var:
self.jacobian[k, inlet_conn.p.J_col] = 1
if outlet_conn.p.is_var:
self.jacobian[k, outlet_conn.p.J_col] = -1
98 changes: 94 additions & 4 deletions src/tespy/components/heat_exchangers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from tespy.tools.document_models import generate_latex_eq
from tespy.tools.fluid_properties import h_mix_pT
from tespy.tools.fluid_properties import s_mix_ph
from tespy.tools.helpers import convert_from_SI
from tespy.tools.helpers import convert_to_SI


@component_registry
Expand All @@ -46,13 +48,16 @@ class HeatExchanger(Component):
- :py:meth:`tespy.components.heat_exchangers.base.HeatExchanger.kA_char_func`
- :py:meth:`tespy.components.heat_exchangers.base.HeatExchanger.ttd_u_func`
- :py:meth:`tespy.components.heat_exchangers.base.HeatExchanger.ttd_l_func`
- :py:meth:`tespy.components.heat_exchangers.base.HeatExchanger.ttd_min_func`
- :py:meth:`tespy.components.heat_exchangers.base.HeatExchanger.eff_cold_func`
- :py:meth:`tespy.components.heat_exchangers.base.HeatExchanger.eff_hot_func`
- :py:meth:`tespy.components.heat_exchangers.base.HeatExchanger.eff_max_func`
- hot side :py:meth:`tespy.components.component.Component.pr_func`
- cold side :py:meth:`tespy.components.component.Component.pr_func`
- hot side :py:meth:`tespy.components.component.Component.zeta_func`
- cold side :py:meth:`tespy.components.component.Component.zeta_func`
- hot side :py:meth:`tespy.components.component.Component.dp_func`
- cold side :py:meth:`tespy.components.component.Component.dp_func`
Inlets/Outlets
Expand Down Expand Up @@ -106,6 +111,12 @@ class HeatExchanger(Component):
pr2 : float, dict, :code:`"var"`
Outlet to inlet pressure ratio at cold side, :math:`pr/1`.
dp1 : float, dict, :code:`"var"`
Inlet to outlet pressure delta at hot side, :math:`dp/\text{Pa}`.
dp2 : float, dict, :code:`"var"`
Inlet to outlet pressure delta at cold side, :math:`dp/\text{Pa}`.
zeta1 : float, dict, :code:`"var"`
Geometry independent friction coefficient at hot side,
:math:`\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}`.
Expand All @@ -120,6 +131,9 @@ class HeatExchanger(Component):
ttd_u : float, dict
Upper terminal temperature difference :math:`ttd_\mathrm{u}/\text{K}`.
ttd_min : float, dict
Minumum terminal temperature difference :math:`ttd_\mathrm{min}/\text{K}`.
eff_cold : float, dict
Cold side heat exchanger effectiveness :math:`eff_\text{cold}/\text{1}`.
Expand Down Expand Up @@ -229,6 +243,9 @@ def get_parameters(self):
'ttd_l': dc_cp(
min_val=0, num_eq=1, func=self.ttd_l_func,
deriv=self.ttd_l_deriv, latex=self.ttd_l_func_doc),
'ttd_min': dc_cp(
min_val=0, num_eq=1, func=self.ttd_min_func,
deriv=self.ttd_min_deriv),
'pr1': dc_cp(
min_val=1e-4, max_val=1, num_eq=1, deriv=self.pr_deriv,
latex=self.pr_func_doc,
Expand All @@ -237,6 +254,14 @@ def get_parameters(self):
min_val=1e-4, max_val=1, num_eq=1, latex=self.pr_func_doc,
deriv=self.pr_deriv, func=self.pr_func,
func_params={'pr': 'pr2', 'inconn': 1, 'outconn': 1}),
'dp1': dc_cp(
min_val=0, max_val=10000, num_eq=1,
deriv=self.dp_deriv, func=self.dp_func,
func_params={'dp': 'dp1', 'inconn': 0, 'outconn': 0}),
'dp2': dc_cp(
min_val=0, max_val=10000, num_eq=1,
deriv=self.dp_deriv, func=self.dp_func,
func_params={'dp': 'dp2', 'inconn': 1, 'outconn': 1}),
'zeta1': dc_cp(
min_val=0, max_val=1e15, num_eq=1, latex=self.zeta_func_doc,
deriv=self.zeta_deriv, func=self.zeta_func,
Expand Down Expand Up @@ -285,6 +310,15 @@ def inlets():
def outlets():
return ['out1', 'out2']

def preprocess(self, num_nw_vars):
super().preprocess(num_nw_vars)

if self.dp1.is_set:
self.dp1.val_SI = convert_to_SI('p', self.dp1.val, self.inl[0].p.unit)

if self.dp2.is_set:
self.dp2.val_SI = convert_to_SI('p', self.dp2.val, self.inl[1].p.unit)

def energy_balance_func(self):
r"""
Equation for heat exchanger energy balance.
Expand Down Expand Up @@ -706,6 +740,56 @@ def ttd_l_deriv(self, increment_filter, k):
if self.is_variable(c.h, increment_filter):
self.jacobian[k, c.h.J_col] = self.numeric_deriv(f, 'h', c)

def ttd_min_func(self):
r"""
Equation for upper terminal temperature difference.
Returns
-------
residual : float
Residual value of equation.
.. math::
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)
"""
i = self.inl[1]
o = self.outl[0]
T_i2 = i.calc_T()
T_o1 = o.calc_T()

i = self.inl[0]
o = self.outl[1]
T_i1 = i.calc_T()
T_o2 = o.calc_T()

ttd_l = T_o1 - T_i2
ttd_u = T_i1 - T_o2

return self.ttd_min.val - min(ttd_l, ttd_u)

def ttd_min_deriv(self, increment_filter, k):
"""
Calculate partial derivates of minimum terminal temperature function.
Parameters
----------
increment_filter : ndarray
Matrix for filtering non-changing variables.
k : int
Position of derivatives in Jacobian matrix (k-th equation).
"""
f = self.ttd_min_func
for c in self.inl + self.outl:
if self.is_variable(c.p, increment_filter):
self.jacobian[k, c.p.J_col] = self.numeric_deriv(f, 'p', c)
if self.is_variable(c.h, increment_filter):
self.jacobian[k, c.h.J_col] = self.numeric_deriv(f, 'h', c)

def calc_dh_max_cold(self):
r"""Calculate the theoretical maximum enthalpy increase on the cold side
Expand Down Expand Up @@ -1030,20 +1114,26 @@ def initialise_target(self, c, key):

def calc_parameters(self):
r"""Postprocessing parameter calculation."""
# component parameters
self.Q.val = self.inl[0].m.val_SI * (
self.outl[0].h.val_SI - self.inl[0].h.val_SI
)
self.ttd_u.val = self.inl[0].T.val_SI - self.outl[1].T.val_SI
self.ttd_l.val = self.outl[0].T.val_SI - self.inl[1].T.val_SI
self.ttd_min.val = min(self.ttd_u.val, self.ttd_min.val)

# pr and zeta
for i in range(2):
self.get_attr('pr' + str(i + 1)).val = (
self.outl[i].p.val_SI / self.inl[i].p.val_SI)
self.get_attr('zeta' + str(i + 1)).val = self.calc_zeta(
self.get_attr(f'pr{i + 1}').val = (
self.outl[i].p.val_SI / self.inl[i].p.val_SI
)
self.get_attr(f'zeta{i + 1}').val = self.calc_zeta(
self.inl[i], self.outl[i]
)
self.get_attr(f'dp{i + 1}').val_SI = (
self.inl[i].p.val_SI - self.outl[i].p.val_SI)
self.get_attr(f'dp{i + 1}').val = convert_from_SI(
'p', self.get_attr(f'dp{i + 1}').val_SI, self.inl[i].p.unit
)

# kA and logarithmic temperature difference
if self.ttd_u.val < 0 or self.ttd_l.val < 0:
Expand Down
Loading

0 comments on commit 63893c9

Please sign in to comment.