From 758c85403315394f22024695d1160ad1078e3355 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 3 Dec 2023 12:45:49 +0100 Subject: [PATCH 01/27] Bump up CoolProp dependency and remove incompressible fluid handling quickfix --- pyproject.toml | 2 +- src/tespy/tools/fluid_properties/wrappers.py | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index eb184e992..7f9b42cea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ classifiers = [ ] requires-python = ">=3.9" dependencies = [ - "CoolProp>=6.4,<7", + "CoolProp>=6.6,<7", "jinja2", "matplotlib>=3.2.1,<4", "numpy>=1.13.3,<2", diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index bc2f84df7..565c98bf4 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -191,15 +191,6 @@ def h_ps(self, p, s): return self.AS.hmass() def h_pT(self, p, T): - if self.back_end == "INCOMP": - if T == (self._T_max + self._T_min) / 2: - T += ERR - self.AS.update(CP.PT_INPUTS, p, T) - h = self.AS.hmass() * 0.5 - T -= 2 * ERR - self.AS.update(CP.PT_INPUTS, p, T) - h += self.AS.hmass() * 0.5 - return h self.AS.update(CP.PT_INPUTS, p, T) return self.AS.hmass() From 3dff30a013d3422c48df776f14bbf3aa6a5e811f Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 3 Dec 2023 12:51:46 +0100 Subject: [PATCH 02/27] Force absolute difference mode for target values equal to zero --- src/tespy/tools/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tespy/tools/helpers.py b/src/tespy/tools/helpers.py index e177474ec..d92ebf04e 100644 --- a/src/tespy/tools/helpers.py +++ b/src/tespy/tools/helpers.py @@ -628,7 +628,7 @@ def newton(func, deriv, params, y, **kwargs): logger.debug(msg) break - if tol_mode == 'abs': + if tol_mode == 'abs' or y == 0: expr = abs(res) >= tol_abs elif tol_mode == 'rel': expr = abs(res / y) >= tol_rel @@ -680,7 +680,7 @@ def newton_with_kwargs( logger.debug(msg) break - if tol_mode == 'abs': + if tol_mode == 'abs' or target_value == 0: expr = abs(residual) >= tol_abs elif tol_mode == 'rel': expr = abs(residual / target_value) >= tol_rel From 9739a9f08e5e03695723478f3f3c78ce06da8eed Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Thu, 7 Dec 2023 18:55:03 +0100 Subject: [PATCH 03/27] Switched sign for value referencing of delta to match docs --- src/tespy/connections/connection.py | 6 +++--- tests/test_connections.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index ceb64a66f..459bcd14b 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -726,7 +726,7 @@ def primary_ref_func(self, k, **kwargs): ref = self.get_attr(f"{variable}_ref").ref self.residual[k] = ( self.get_attr(variable).val_SI - - ref.obj.get_attr(variable).val_SI * ref.factor + ref.delta_SI + - (ref.obj.get_attr(variable).val_SI * ref.factor + ref.delta_SI) ) def primary_ref_deriv(self, k, **kwargs): @@ -761,7 +761,7 @@ def T_deriv(self, k, **kwargs): def T_ref_func(self, k, **kwargs): ref = self.T_ref.ref self.residual[k] = ( - self.calc_T() - ref.obj.calc_T() * ref.factor + ref.delta_SI + self.calc_T() - (ref.obj.calc_T() * ref.factor + ref.delta_SI) ) def T_ref_deriv(self, k, **kwargs): @@ -810,7 +810,7 @@ def v_ref_func(self, k, **kwargs): ref = self.v_ref.ref self.residual[k] = ( self.calc_vol(T0=self.T.val_SI) * self.m.val_SI - - ref.obj.calc_vol(T0=ref.obj.T.val_SI) * ref.obj.m.val_SI * ref.factor + ref.delta_SI + - (ref.obj.calc_vol(T0=ref.obj.T.val_SI) * ref.obj.m.val_SI * ref.factor + ref.delta_SI) ) def v_ref_deriv(self, k, **kwargs): diff --git a/tests/test_connections.py b/tests/test_connections.py index acc620a20..6d35bdf80 100644 --- a/tests/test_connections.py +++ b/tests/test_connections.py @@ -58,7 +58,7 @@ def test_volumetric_flow_reference(self): c2.set_attr(v=Ref(c1, 2, 10)) self.nw.solve('design') - v_expected = round(c1.v.val * 2 - 10, 4) + v_expected = round(c1.v.val * 2 + 10, 4) v_is = round(c2.v.val, 4) msg = ( 'The mass flow of the connection 2 should be equal to ' @@ -87,7 +87,7 @@ def test_temperature_reference(self): c2.set_attr(T=Ref(c1, 1.5, -75)) self.nw.solve('design') - T_expected = round(convert_from_SI("T", c1.T.val_SI * 1.5, c1.T.unit) + 75, 4) + T_expected = round(convert_from_SI("T", c1.T.val_SI * 1.5, c1.T.unit) - 75, 4) T_is = round(c2.T.val, 4) msg = ( 'The temperature of the connection 2 should be equal to ' @@ -116,7 +116,7 @@ def test_primary_reference(self): c2.set_attr(m=Ref(c1, 2, -0.5)) self.nw.solve('design') - m_expected = round(convert_from_SI("m", c1.m.val_SI * 2, c1.m.unit) + 0.5, 4) + m_expected = round(convert_from_SI("m", c1.m.val_SI * 2, c1.m.unit) - 0.5, 4) m_is = round(c2.m.val, 4) msg = ( 'The mass flow of the connection 2 should be equal to ' From 1df16ff7f765450996ed2b3ea0945552890ee893 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Thu, 7 Dec 2023 19:24:14 +0100 Subject: [PATCH 04/27] Update What's New --- docs/whats_new.rst | 1 + docs/whats_new/v0-7-2.rst | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 docs/whats_new/v0-7-2.rst diff --git a/docs/whats_new.rst b/docs/whats_new.rst index f03b829f0..7f5718e07 100644 --- a/docs/whats_new.rst +++ b/docs/whats_new.rst @@ -3,6 +3,7 @@ What's New Discover noteable new features and improvements in each release +.. include:: whats_new/v0-7-2.rst .. include:: whats_new/v0-7-1.rst .. include:: whats_new/v0-7-0.rst .. include:: whats_new/v0-6-3.rst diff --git a/docs/whats_new/v0-7-2.rst b/docs/whats_new/v0-7-2.rst new file mode 100644 index 000000000..ca1c1c59b --- /dev/null +++ b/docs/whats_new/v0-7-2.rst @@ -0,0 +1,12 @@ +v0.7.2 - Under development +++++++++++++++++++++++++++ + +Bug Fixes +######### +- The `delta` value of the :py:class:`tespy.connections.connection.Ref` class + was oriented with the wrong sign. A positive delta lead to a negative value. + Fixed in (`PR #459 `__). + +Contributors +############ +- Francesco Witte (`@fwitte `__) From ef36007020f23a4098e3fa3348dcc9182067b0a3 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Fri, 8 Dec 2023 17:44:08 +0100 Subject: [PATCH 05/27] Fix some typos --- docs/modules/ude.rst | 2 +- src/tespy/networks/network.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/modules/ude.rst b/docs/modules/ude.rst index ee1488f4f..716c938a0 100644 --- a/docs/modules/ude.rst +++ b/docs/modules/ude.rst @@ -118,7 +118,7 @@ derivatives to mass flow are not zero. ... c0 = self.conns[0] ... c1 = self.conns[1] ... if c0.m.is_var: - ... ude.jacobian[c0.m.J_col] = 1 + ... self.jacobian[c0.m.J_col] = 1 ... if c1.m.is_var: ... self.jacobian[c1.m.J_col] = -2 * self.conns[1].m.val_SI diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 9f699dd08..48a4755d3 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1501,9 +1501,9 @@ def init_conn_design_params(self, c, df): if c.label not in df.index: # no matches in the connections of the network and the design files msg = ( - f"Could not find connection {c.label} in design case. Please " + f"Could not find connection '{c.label}' in design case. Please " "make sure no connections have been modified or components " - "havebeen relabeled for your offdesign calculation." + "have been relabeled for your offdesign calculation." ) logger.exception(msg) raise hlp.TESPyNetworkError(msg) From 25dc5ab59f35e97e41d2fb0b4b93665908971e5c Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 7 Jan 2024 13:38:14 +0100 Subject: [PATCH 06/27] Remove ordereddicts and implement zeta calculation method --- src/tespy/components/combustion/engine.py | 8 ++-- src/tespy/components/component.py | 39 +++++++++++-------- src/tespy/components/heat_exchangers/base.py | 14 +++---- .../components/heat_exchangers/condenser.py | 2 - .../heat_exchangers/parabolic_trough.py | 6 +-- .../components/heat_exchangers/simple.py | 5 +-- .../heat_exchangers/solar_collector.py | 6 +-- src/tespy/components/piping/valve.py | 5 +-- src/tespy/components/reactors/fuel_cell.py | 10 ++--- .../components/reactors/water_electrolyzer.py | 10 ++--- src/tespy/connections/connection.py | 6 +-- src/tespy/networks/network.py | 5 +-- src/tespy/tools/data_containers.py | 14 +++---- src/tespy/tools/global_vars.py | 5 +-- src/tespy/tools/helpers.py | 22 ----------- src/tespy/tools/optimization.py | 13 ++----- 16 files changed, 64 insertions(+), 106 deletions(-) diff --git a/src/tespy/components/combustion/engine.py b/src/tespy/components/combustion/engine.py index 6f47613a3..aa4661371 100644 --- a/src/tespy/components/combustion/engine.py +++ b/src/tespy/components/combustion/engine.py @@ -1302,11 +1302,9 @@ def calc_parameters(self): self.outl[i].h.val_SI - self.inl[i].h.val_SI) 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.inl[i].p.val_SI - self.outl[i].p.val_SI) * np.pi ** 2 / ( - 4 * self.inl[i].m.val_SI ** 2 * - (self.inl[i].vol.val_SI + self.outl[i].vol.val_SI) - )) + self.get_attr('zeta' + str(i + 1)).val = self.calc_zeta( + self.inl[i], self.outl[i] + ) self.P.val = self.calc_P() self.Qloss.val = self.calc_Qloss() diff --git a/src/tespy/components/component.py b/src/tespy/components/component.py index 8c8dec496..3d9e0f24c 100644 --- a/src/tespy/components/component.py +++ b/src/tespy/components/component.py @@ -12,8 +12,6 @@ SPDX-License-Identifier: MIT """ -from collections import OrderedDict - import numpy as np from tespy.tools import logger @@ -122,7 +120,7 @@ def __init__(self, label, **kwargs): self.fkt_group = self.label # add container for components attributes - self.parameters = OrderedDict(self.get_parameters().copy()) + self.parameters = self.get_parameters().copy() self.__dict__.update(self.parameters) self.set_attr(**kwargs) @@ -342,7 +340,7 @@ def preprocess(self, num_nw_vars): self.num_eq = 0 self.vars = {} self.num_vars = 0 - self.constraints = OrderedDict(self.get_mandatory_constraints().copy()) + self.constraints = self.get_mandatory_constraints().copy() self.prop_specifications = {} self.var_specifications = {} self.group_specifications = {} @@ -415,7 +413,7 @@ def preprocess(self, num_nw_vars): if data.is_set and data.func is not None: self.num_eq += data.num_eq - self.jacobian = OrderedDict() + self.jacobian = {} self.residual = np.zeros(self.num_eq) sum_eq = 0 @@ -813,18 +811,18 @@ def check_parameter_bounds(self): if isinstance(data, dc_cp): if data.val > data.max_val + ERR : msg = ( - 'Invalid value for ' + p + ': ' + p + ' = ' + - str(data.val) + ' above maximum value (' + - str(data.max_val) + ') at component ' + self.label + - '.') + f"Invalid value for {p}: {p} = {data.val} above " + f"maximum value ({data.max_val}) at component " + f"{self.label}." + ) logger.warning(msg) elif data.val < data.min_val - ERR : msg = ( - 'Invalid value for ' + p + ': ' + p + ' = ' + - str(data.val) + ' below minimum value (' + - str(data.min_val) + ') at component ' + self.label + - '.') + f"Invalid value for {p}: {p} = {data.val} below " + f"minimum value ({data.max_val}) at component " + f"{self.label}." + ) logger.warning(msg) elif isinstance(data, dc_cc) and data.is_set: @@ -968,7 +966,8 @@ def enthalpy_equality_func_doc(self, label): indices = str(indices[0]) latex = ( r'0=h_{\mathrm{in,}i}-h_{\mathrm{out,}i}' - r'\; \forall i \in [' + indices + r']') + r'\; \forall i \in [' + indices + r']' + ) return generate_latex_eq(self, latex, label) def enthalpy_equality_deriv(self, k): @@ -1021,8 +1020,7 @@ def pr_func(self, pr='', inconn=0, outconn=0): 0 = p_{in} \cdot pr - p_{out} """ pr = self.get_attr(pr) - return (self.inl[inconn].p.val_SI * pr.val - - self.outl[outconn].p.val_SI) + return self.inl[inconn].p.val_SI * pr.val - self.outl[outconn].p.val_SI def pr_func_doc(self, label, pr='', inconn=0, outconn=0): r""" @@ -1083,6 +1081,15 @@ def pr_deriv(self, increment_filter, k, pr='', inconn=0, outconn=0): if pr.is_var: self.jacobian[k, self.pr.J_col] = i.p.val_SI + def calc_zeta(self, i, o): + if abs(i.m.val_SI) <= 1e-4: + return 0 + else: + return ( + (i.p.val_SI - o.p.val_SI) * np.pi ** 2 + / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) + ) + def zeta_func(self, zeta='', inconn=0, outconn=0): r""" Calculate residual value of :math:`\zeta`-function. diff --git a/src/tespy/components/heat_exchangers/base.py b/src/tespy/components/heat_exchangers/base.py index 82830fac8..f1685f639 100644 --- a/src/tespy/components/heat_exchangers/base.py +++ b/src/tespy/components/heat_exchangers/base.py @@ -830,11 +830,9 @@ def calc_parameters(self): 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.inl[i].p.val_SI - self.outl[i].p.val_SI) * np.pi ** 2 / ( - 4 * self.inl[i].m.val_SI ** 2 * - (self.inl[i].vol.val_SI + self.outl[i].vol.val_SI) - )) + self.get_attr('zeta' + str(i + 1)).val = self.calc_zeta( + self.inl[i], self.outl[i] + ) # kA and logarithmic temperature difference if self.ttd_u.val < 0 or self.ttd_l.val < 0: @@ -842,8 +840,10 @@ def calc_parameters(self): elif self.ttd_l.val == self.ttd_u.val: self.td_log.val = self.ttd_l.val else: - self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / - np.log(self.ttd_l.val / self.ttd_u.val)) + self.td_log.val = ( + (self.ttd_l.val - self.ttd_u.val) + / np.log(self.ttd_l.val / self.ttd_u.val) + ) self.kA.val = -self.Q.val / self.td_log.val def entropy_balance(self): diff --git a/src/tespy/components/heat_exchangers/condenser.py b/src/tespy/components/heat_exchangers/condenser.py index 241a9c01b..a87316095 100644 --- a/src/tespy/components/heat_exchangers/condenser.py +++ b/src/tespy/components/heat_exchangers/condenser.py @@ -19,8 +19,6 @@ from tespy.tools.data_containers import GroupedComponentCharacteristics as dc_gcc from tespy.tools.data_containers import SimpleDataContainer as dc_simple from tespy.tools.document_models import generate_latex_eq -from tespy.tools.fluid_properties import T_mix_ph -from tespy.tools.fluid_properties import T_sat_p from tespy.tools.fluid_properties import dh_mix_dpQ from tespy.tools.fluid_properties import h_mix_pQ diff --git a/src/tespy/components/heat_exchangers/parabolic_trough.py b/src/tespy/components/heat_exchangers/parabolic_trough.py index 5a41e98d1..169d164fd 100644 --- a/src/tespy/components/heat_exchangers/parabolic_trough.py +++ b/src/tespy/components/heat_exchangers/parabolic_trough.py @@ -361,10 +361,8 @@ def calc_parameters(self): self.Q.val = i.m.val_SI * (o.h.val_SI - i.h.val_SI) self.pr.val = o.p.val_SI / i.p.val_SI - self.zeta.val = ( - (i.p.val_SI - o.p.val_SI) * np.pi ** 2 - / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) - ) + self.zeta.val = self.calc_zeta(i, o) + if self.energy_group.is_set: self.Q_loss.val = - self.E.val * self.A.val + self.Q.val self.Q_loss.is_result = True diff --git a/src/tespy/components/heat_exchangers/simple.py b/src/tespy/components/heat_exchangers/simple.py index 29d141ea9..57623e758 100644 --- a/src/tespy/components/heat_exchangers/simple.py +++ b/src/tespy/components/heat_exchangers/simple.py @@ -884,10 +884,7 @@ def calc_parameters(self): self.Q.val = i.m.val_SI * (o.h.val_SI - i.h.val_SI) self.pr.val = o.p.val_SI / i.p.val_SI - self.zeta.val = ( - (i.p.val_SI - o.p.val_SI) * np.pi ** 2 - / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) - ) + self.zeta.val = self.calc_zeta(i, o) if self.Tamb.is_set: ttd_1 = i.T.val_SI - self.Tamb.val_SI diff --git a/src/tespy/components/heat_exchangers/solar_collector.py b/src/tespy/components/heat_exchangers/solar_collector.py index bce3198ce..9a940e12c 100644 --- a/src/tespy/components/heat_exchangers/solar_collector.py +++ b/src/tespy/components/heat_exchangers/solar_collector.py @@ -311,10 +311,8 @@ def calc_parameters(self): self.Q.val = i.m.val_SI * (o.h.val_SI - i.h.val_SI) self.pr.val = o.p.val_SI / i.p.val_SI - self.zeta.val = ( - (i.p.val_SI - o.p.val_SI) * np.pi ** 2 - / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) - ) + self.zeta.val = self.calc_zeta(i, o) + if self.energy_group.is_set: self.Q_loss.val = -(self.E.val * self.A.val - self.Q.val) self.Q_loss.is_result = True diff --git a/src/tespy/components/piping/valve.py b/src/tespy/components/piping/valve.py index 3b23aadcb..723e1d829 100644 --- a/src/tespy/components/piping/valve.py +++ b/src/tespy/components/piping/valve.py @@ -316,10 +316,7 @@ def calc_parameters(self): i = self.inl[0] o = self.outl[0] self.pr.val = o.p.val_SI / i.p.val_SI - self.zeta.val = ( - (i.p.val_SI - o.p.val_SI) * np.pi ** 2 - / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) - ) + self.zeta.val = self.calc_zeta(i, o) def entropy_balance(self): r""" diff --git a/src/tespy/components/reactors/fuel_cell.py b/src/tespy/components/reactors/fuel_cell.py index 088d09757..fe0198bcc 100644 --- a/src/tespy/components/reactors/fuel_cell.py +++ b/src/tespy/components/reactors/fuel_cell.py @@ -828,15 +828,13 @@ def initialise_target(self, c, key): def calc_parameters(self): r"""Postprocessing parameter calculation.""" - self.Q.val = - self.inl[0].m.val_SI * ( - self.outl[0].h.val_SI - self.inl[0].h.val_SI) + self.Q.val = -self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI + ) self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI self.e.val = self.P.val / self.inl[2].m.val_SI self.eta.val = self.e.val / self.e0 i = self.inl[0] o = self.outl[0] - self.zeta.val = ( - (i.p.val_SI - o.p.val_SI) * np.pi ** 2 - / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) - ) + self.zeta.val = self.calc_zeta(i, o) diff --git a/src/tespy/components/reactors/water_electrolyzer.py b/src/tespy/components/reactors/water_electrolyzer.py index 9e8e959d8..e93d87a9a 100644 --- a/src/tespy/components/reactors/water_electrolyzer.py +++ b/src/tespy/components/reactors/water_electrolyzer.py @@ -1157,18 +1157,16 @@ def initialise_target(self, c, key): def calc_parameters(self): r"""Postprocessing parameter calculation.""" - self.Q.val = - self.inl[0].m.val_SI * ( - self.outl[0].h.val_SI - self.inl[0].h.val_SI) + self.Q.val = -self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI + ) self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI self.e.val = self.P.val / self.outl[2].m.val_SI self.eta.val = self.e0 / self.e.val i = self.inl[0] o = self.outl[0] - self.zeta.val = ( - (i.p.val_SI - o.p.val_SI) * np.pi ** 2 - / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) - ) + self.zeta.val = self.calc_zeta(i, o) def exergy_balance(self, T0): self.E_P = ( diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 459bcd14b..3c58eeafe 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -9,8 +9,6 @@ SPDX-License-Identifier: MIT """ -from collections import OrderedDict - import numpy as np from tespy.components.component import Component @@ -303,7 +301,7 @@ def _check_connector_id(self, component, connector_id, connecter_locations): if connector_id not in connecter_locations: msg = ( "Error creating connection. Specified connector for " - f"{component.label} ({connector_id} is not available. Choose " + f"{component.label} ({connector_id}) is not available. Choose " f"from " + ", ".join(connecter_locations) + "." ) logger.error(msg) @@ -626,7 +624,7 @@ def preprocess(self): container._solved = False self.residual = np.zeros(self.num_eq) - self.jacobian = OrderedDict() + self.jacobian = {} def simplify_specifications(self): systemvar_specs = [] diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 48a4755d3..d7a11fa2c 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -15,7 +15,6 @@ """ import json import os -from collections import OrderedDict from time import time import numpy as np @@ -189,7 +188,7 @@ def set_defaults(self): # user defined function dictionary for fast access self.user_defined_eq = {} # bus dictionary - self.busses = OrderedDict() + self.busses = {} # results and specification dictionary self.results = {} self.specifications = {} @@ -1262,7 +1261,7 @@ def init_design(self): c.m.design = np.nan c.p.design = np.nan c.h.design = np.nan - c.fluid.design = OrderedDict() + c.fluid.design = {} c.new_design = True diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index f55447d32..a9e559626 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -354,15 +354,15 @@ def attr(): values. """ return { - 'val': collections.OrderedDict(), - 'val0': collections.OrderedDict(), + 'val': dict(), + 'val0': dict(), 'is_set': set(), - 'design': collections.OrderedDict(), - 'wrapper': collections.OrderedDict(), - 'back_end': collections.OrderedDict(), - 'engine': collections.OrderedDict(), + 'design': dict(), + 'wrapper': dict(), + 'back_end': dict(), + 'engine': dict(), "is_var": set(), - "J_col": collections.OrderedDict(), + "J_col": dict(), } def serialize(self): diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index 37a9273e5..8cd773f1a 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -8,14 +8,13 @@ SPDX-License-Identifier: MIT """ -from collections import OrderedDict ERR = 1e-6 molar_masses = {} gas_constants = {} gas_constants['uni'] = 8.314462618 -fluid_property_data = OrderedDict({ +fluid_property_data = { 'm': { 'text': 'mass flow', 'SI_unit': 'kg / s', @@ -99,6 +98,6 @@ 'latex_eq': r'0 = s_\mathrm{spec} - s\left(p, h \right)', 'documentation': {'float_fmt': '{:,.2f}'} } -}) +} combustion_gases = ['methane', 'ethane', 'propane', 'butane', 'hydrogen', 'nDodecane'] diff --git a/src/tespy/tools/helpers.py b/src/tespy/tools/helpers.py index d92ebf04e..efd5b7720 100644 --- a/src/tespy/tools/helpers.py +++ b/src/tespy/tools/helpers.py @@ -11,7 +11,6 @@ import json import os -from collections import OrderedDict from collections.abc import Mapping from copy import deepcopy @@ -65,27 +64,6 @@ def merge_dicts(dict1, dict2): return result -def nested_OrderedDict(dictionary): - """Create a nested OrderedDict from a nested dict. - - Parameters - ---------- - dictionary : dict - Nested dict. - - Returns - ------- - dictionary : collections.OrderedDict - Nested OrderedDict. - """ - dictionary = OrderedDict(dictionary) - for key, value in dictionary.items(): - if isinstance(value, dict): - dictionary[key] = nested_OrderedDict(value) - - return dictionary - - class TESPyNetworkError(Exception): """Custom message for network related errors.""" diff --git a/src/tespy/tools/optimization.py b/src/tespy/tools/optimization.py index b7a513878..4154d1a95 100644 --- a/src/tespy/tools/optimization.py +++ b/src/tespy/tools/optimization.py @@ -6,7 +6,6 @@ import pandas as pd from tespy.tools.helpers import merge_dicts -from tespy.tools.helpers import nested_OrderedDict class OptimizationProblem: @@ -70,14 +69,8 @@ def __init__(self, model, variables={}, constraints={}, objective="objective"): "upper limits": {"Connections": {}, "Components": {}} } # merge the passed values into the default dictionary structure - variables = merge_dicts(variables, default_variables) - constraints = merge_dicts(constraints, default_constraints) - - # pygmo creates a vector for the variables and constraints, which has - # to be in consistent order. Therefore use OrderedDicts instead of - # dictionaries - self.variables = nested_OrderedDict(variables) - self.constraints = nested_OrderedDict(constraints) + self.variables = merge_dicts(variables, default_variables) + self.constraints = merge_dicts(constraints, default_constraints) self.objective = objective self.variable_list = [] self.constraint_list = [] @@ -307,3 +300,5 @@ def run(self, algo, pop, num_ind, num_gen): round(pop.champion_x[i], 4) ) ) + + return pop From 42adacd0e56cd124e0ebc6d7e604b951da6cba9e Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Mon, 8 Jan 2024 21:18:14 +0100 Subject: [PATCH 07/27] Fix DropletSeparator image --- docs/api/_images/DropletSeparator.svg | 6 +++--- docs/api/_images/DropletSeparator_darkmode.svg | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/api/_images/DropletSeparator.svg b/docs/api/_images/DropletSeparator.svg index b41a4eceb..6f80e1828 100644 --- a/docs/api/_images/DropletSeparator.svg +++ b/docs/api/_images/DropletSeparator.svg @@ -3,7 +3,7 @@ inkscape:export-ydpi="1012" inkscape:export-xdpi="1012" sodipodi:docname="DropletSeparator.svg" - inkscape:version="1.1.2 (1:1.1+202202050950+0a00cf5339)" + inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" id="svg8" version="1.1" viewBox="0 0 69.223438 95.000002" @@ -160,7 +160,7 @@ y="83.53054" style="fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round">out1 + id="tspan9360">2 out2 + id="tspan7156">1 out1 + style="font-size:6.42057px;baseline-shift:sub;fill:#ffffff;fill-opacity:1;stroke-width:0.529166" + id="tspan9360">2 out2 + style="font-size:6.42057px;baseline-shift:sub;fill:#ffffff;fill-opacity:1;stroke-width:0.529166" + id="tspan7156">1 Date: Mon, 8 Jan 2024 21:21:10 +0100 Subject: [PATCH 08/27] Fix link ignore --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index a8cf752fb..5d75eb094 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -148,5 +148,5 @@ r'https://doi.org/20.500.12738/6561', # 08.01.2023: does not resolve anymore r'https://doi.org/10.1021/ie4033999', # 28.02.2023: does not resolve anymore for some reason r'https://doi.org/10.1002/bbpc.19900940121', # 13.03.2023 ...? - r' http://www.coolprop.org/fluid_properties/Incompressibles.html', # 02.12.2023 ...? + r'http://www.coolprop.org/fluid_properties/Incompressibles.html', # 02.12.2023 ...? ] From 2c8541a84bb795160dd1f021e9dd3c4b3e1eca2b Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Mon, 8 Jan 2024 21:32:07 +0100 Subject: [PATCH 09/27] Try to ignore linkchecks to coolprop.org --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 5d75eb094..2441a7b50 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -148,5 +148,5 @@ r'https://doi.org/20.500.12738/6561', # 08.01.2023: does not resolve anymore r'https://doi.org/10.1021/ie4033999', # 28.02.2023: does not resolve anymore for some reason r'https://doi.org/10.1002/bbpc.19900940121', # 13.03.2023 ...? - r'http://www.coolprop.org/fluid_properties/Incompressibles.html', # 02.12.2023 ...? + r'http://www.coolprop.org\d+/', # 02.12.2023 ...? ] From c361f90bbb761c66f93f34c928f1e4b2bbca9b42 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Mon, 8 Jan 2024 21:41:20 +0100 Subject: [PATCH 10/27] Twice is the charm --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 2441a7b50..ea81ff341 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -148,5 +148,5 @@ r'https://doi.org/20.500.12738/6561', # 08.01.2023: does not resolve anymore r'https://doi.org/10.1021/ie4033999', # 28.02.2023: does not resolve anymore for some reason r'https://doi.org/10.1002/bbpc.19900940121', # 13.03.2023 ...? - r'http://www.coolprop.org\d+/', # 02.12.2023 ...? + r'http://www\.coolprop\.org/.*', # 02.12.2023 ...? ] From 827c753b41d5496bc4f90fb1e0f3d147dea6082a Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Mon, 8 Jan 2024 21:48:09 +0100 Subject: [PATCH 11/27] Ignore random git commit link --- docs/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/conf.py b/docs/conf.py index ea81ff341..aac7ce1b4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -149,4 +149,5 @@ r'https://doi.org/10.1021/ie4033999', # 28.02.2023: does not resolve anymore for some reason r'https://doi.org/10.1002/bbpc.19900940121', # 13.03.2023 ...? r'http://www\.coolprop\.org/.*', # 02.12.2023 ...? + r'https://github.com/oemof/tespy/commit/bf0b8650b0965c916727ebe10f39f0cefabb71e0', # 08.01.2024 ...? ] From 49765f03ca419029301a888c61bb1038182470b4 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Jan 2024 16:28:02 +0100 Subject: [PATCH 12/27] Apply condensation check only for water component --- src/tespy/tools/fluid_properties/mixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tespy/tools/fluid_properties/mixtures.py b/src/tespy/tools/fluid_properties/mixtures.py index b156a133f..645537783 100644 --- a/src/tespy/tools/fluid_properties/mixtures.py +++ b/src/tespy/tools/fluid_properties/mixtures.py @@ -253,7 +253,7 @@ def exergy_chemical_ideal_cond(pamb, Tamb, fluid_data, Chem_Ex): fluid_aliases = fluid_data[fluid]["wrapper"]._aliases - if molar_liquid > 0: + if molar_liquid > 0 and "water" in fluid_aliases: y = [ Chem_Ex[k][2] for k in fluid_aliases if k in Chem_Ex ] From 0c6ed01b9204d1acf75cf0bbea54c7e0c21a893a Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Jan 2024 16:28:44 +0100 Subject: [PATCH 13/27] Adhere to latest fluprodia API --- tutorial/heat_pump_exergy/NH3_calculations.py | 13 ++++++++----- tutorial/heat_pump_exergy/R410A_calculations.py | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/tutorial/heat_pump_exergy/NH3_calculations.py b/tutorial/heat_pump_exergy/NH3_calculations.py index a602ae0dc..af56e171f 100644 --- a/tutorial/heat_pump_exergy/NH3_calculations.py +++ b/tutorial/heat_pump_exergy/NH3_calculations.py @@ -19,6 +19,7 @@ import plotly.graph_objects as go from fluprodia import FluidPropertyDiagram import pandas as pd +import matplotlib.pyplot as plt # %% network pamb = 1.013 # ambient pressure @@ -166,16 +167,18 @@ for key, data in result_dict.items(): result_dict[key]['datapoints'] = diagram.calc_individual_isoline(**data) -diagram.set_limits(x_min=0, x_max=2100, y_min=1e0, y_max=2e2) diagram.calc_isolines() -diagram.draw_isolines('logph') + +fig, ax = plt.subplots(1, figsize=(16, 10)) +diagram.draw_isolines(fig, ax, 'logph', x_min=0, x_max=2100, y_min=1e0, y_max=2e2) for key in result_dict.keys(): datapoints = result_dict[key]['datapoints'] - diagram.ax.plot(datapoints['h'], datapoints['p'], color='#ff0000') - diagram.ax.scatter(datapoints['h'][0], datapoints['p'][0], color='#ff0000') + ax.plot(datapoints['h'], datapoints['p'], color='#ff0000') + ax.scatter(datapoints['h'][0], datapoints['p'][0], color='#ff0000') -diagram.save('NH3_logph.svg') +plt.tight_layout() +fig.savefig('NH3_logph.svg') # %% exergy analysis diff --git a/tutorial/heat_pump_exergy/R410A_calculations.py b/tutorial/heat_pump_exergy/R410A_calculations.py index 457a10472..5cb3e6a01 100644 --- a/tutorial/heat_pump_exergy/R410A_calculations.py +++ b/tutorial/heat_pump_exergy/R410A_calculations.py @@ -19,6 +19,7 @@ import plotly.graph_objects as go from fluprodia import FluidPropertyDiagram import pandas as pd +import matplotlib.pyplot as plt # %% network pamb = 1.013 # ambient pressure @@ -165,16 +166,18 @@ for key, data in result_dict.items(): result_dict[key]['datapoints'] = diagram.calc_individual_isoline(**data) -diagram.set_limits(x_min=200, x_max=500, y_min=0.8e1, y_max=0.8e2) diagram.calc_isolines() -diagram.draw_isolines('logph') + +fig, ax = plt.subplots(1, figsize=(16, 10)) +diagram.draw_isolines(fig, ax, 'logph', x_min=200, x_max=500, y_min=0.8e1, y_max=0.8e2) for key in result_dict.keys(): datapoints = result_dict[key]['datapoints'] - diagram.ax.plot(datapoints['h'], datapoints['p'], color='#ff0000') - diagram.ax.scatter(datapoints['h'][0], datapoints['p'][0], color='#ff0000') + ax.plot(datapoints['h'], datapoints['p'], color='#ff0000') + ax.scatter(datapoints['h'][0], datapoints['p'][0], color='#ff0000') -diagram.save('R410A_logph.svg') +plt.tight_layout() +fig.savefig('R410A_logph.svg') # %% exergy analysis From 23148e87136631b38be7f9a4ac57e2bd8293daa1 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Jan 2024 16:30:10 +0100 Subject: [PATCH 14/27] Increase upper limit for mixture temperature root finding --- src/tespy/tools/fluid_properties/helpers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tespy/tools/fluid_properties/helpers.py b/src/tespy/tools/fluid_properties/helpers.py index 27740208a..155c5cfa6 100644 --- a/src/tespy/tools/fluid_properties/helpers.py +++ b/src/tespy/tools/fluid_properties/helpers.py @@ -70,6 +70,8 @@ def inverse_temperature_mixture(p=None, target_value=None, fluid_data=None, T0=N if T0 is None: T0 = (valmin + valmax) / 2.0 + valmax *= 2 + function_kwargs = { "p": p, "fluid_data": fluid_data, "T": T0, "function": f, "parameter": "T" , "delta": 0.01 From fef2f80d9398b675978b663007241b86580362e8 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Jan 2024 16:31:02 +0100 Subject: [PATCH 15/27] Set the default value for fluid property data to nan --- src/tespy/tools/data_containers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index a9e559626..4dd647fd4 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -12,8 +12,6 @@ SPDX-License-Identifier: MIT """ -import collections - import numpy as np from tespy.tools import logger @@ -487,7 +485,7 @@ def attr(): 'design': np.nan, 'val': np.nan, 'val0': np.nan, - 'val_SI': 0, + 'val_SI': np.nan, 'unit': None, 'is_set': False, "is_var": False, From 4b4ccf1220d5aaf199f46db6eca99036f08a853b Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 12:27:42 +0100 Subject: [PATCH 16/27] Add a warning message for out of bound mixture tempertures --- src/tespy/connections/connection.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 3c58eeafe..47466b01e 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -37,6 +37,7 @@ from tespy.tools.fluid_properties.functions import dT_mix_ph_dfluid from tespy.tools.fluid_properties.functions import p_sat_T from tespy.tools.fluid_properties.helpers import get_number_of_fluids +from tespy.tools.fluid_properties.helpers import get_mixture_temperature_range from tespy.tools.global_vars import ERR from tespy.tools.global_vars import fluid_property_data as fpd from tespy.tools.helpers import TESPyConnectionError @@ -917,7 +918,14 @@ def calc_results(self): ) logger.error(msg) _converged = False - + else: + _, Tmax = get_mixture_temperature_range(self.fluid_data) + if self.T.val_SI > Tmax: + msg = ( + "The temperature value of the mixture is above the " + "upper temperature limit of a mixture component. " + "The resulting temperature might not be erroneous." + ) else: try: if not self.x.is_set: From c066179ff13e7409b83aceab5504d559a83c9d95 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 12:37:22 +0100 Subject: [PATCH 17/27] Add a test with higher temperature combustion product that water fluid properties allow --- src/tespy/connections/connection.py | 1 + tests/test_components/test_combustion.py | 16 +++++++++++++++- .../test_networks/test_binary_incompressible.py | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 47466b01e..9bcc80260 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -926,6 +926,7 @@ def calc_results(self): "upper temperature limit of a mixture component. " "The resulting temperature might not be erroneous." ) + logger.warning(msg) else: try: if not self.x.is_set: diff --git a/tests/test_components/test_combustion.py b/tests/test_components/test_combustion.py index 7912781fb..298601099 100644 --- a/tests/test_components/test_combustion.py +++ b/tests/test_components/test_combustion.py @@ -9,7 +9,7 @@ SPDX-License-Identifier: MIT """ - +import pytest import shutil from tespy.components import CombustionChamber @@ -103,6 +103,20 @@ def test_CombustionChamber(self): str(round(self.c3.fluid.val['O2'], 4)) + '.') assert 0.0 == round(self.c3.fluid.val['O2'], 4), msg + def test_CombustionChamberHighTemperature(self): + instance = CombustionChamber('combustion chamber') + self.setup_CombustionChamber_network(instance) + + # connection parameter specification + air = {'N2': 0.8, 'O2': 0.2} + fuel = {'CH4': 1} + self.c1.set_attr(fluid=air, p=1, T=30, m=1) + self.c2.set_attr(fluid=fuel, T=30) + instance.set_attr(lamb=1) + self.nw.solve('design') + self.nw._convergence_check() + assert self.c3.T.val_SI == pytest.approx(2110, abs=0.1) + def test_DiabaticCombustionChamber(self): """ Test component properties of diabatic combustion chamber. diff --git a/tests/test_networks/test_binary_incompressible.py b/tests/test_networks/test_binary_incompressible.py index c5aa7be94..9683e71cd 100644 --- a/tests/test_networks/test_binary_incompressible.py +++ b/tests/test_networks/test_binary_incompressible.py @@ -51,4 +51,4 @@ def setup_method(self): self.nw.solve("design") def test_binaries(self): - self.nw._convergence_check() \ No newline at end of file + self.nw._convergence_check() From 88e4002c7cecd3292e91a2786ba66a17fbd2feb3 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 12:46:14 +0100 Subject: [PATCH 18/27] Run isort --- src/tespy/connections/connection.py | 2 +- tests/test_components/test_combustion.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 9bcc80260..7e1f8b09c 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -36,8 +36,8 @@ from tespy.tools.fluid_properties import viscosity_mix_ph from tespy.tools.fluid_properties.functions import dT_mix_ph_dfluid from tespy.tools.fluid_properties.functions import p_sat_T -from tespy.tools.fluid_properties.helpers import get_number_of_fluids from tespy.tools.fluid_properties.helpers import get_mixture_temperature_range +from tespy.tools.fluid_properties.helpers import get_number_of_fluids from tespy.tools.global_vars import ERR from tespy.tools.global_vars import fluid_property_data as fpd from tespy.tools.helpers import TESPyConnectionError diff --git a/tests/test_components/test_combustion.py b/tests/test_components/test_combustion.py index 298601099..b8290babd 100644 --- a/tests/test_components/test_combustion.py +++ b/tests/test_components/test_combustion.py @@ -9,9 +9,10 @@ SPDX-License-Identifier: MIT """ -import pytest import shutil +import pytest + from tespy.components import CombustionChamber from tespy.components import CombustionEngine from tespy.components import DiabaticCombustionChamber From 03ddc6db021f9633df4a6c05e09d498c53eb22a1 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 13:01:19 +0100 Subject: [PATCH 19/27] Delegate T0 value passing to connection object where possible and check for 0 or nan T0 values --- src/tespy/components/heat_exchangers/base.py | 16 ++++++++-------- .../components/heat_exchangers/condenser.py | 8 ++++---- .../heat_exchangers/parabolic_trough.py | 2 +- src/tespy/components/heat_exchangers/simple.py | 8 ++++---- .../heat_exchangers/solar_collector.py | 2 +- src/tespy/components/nodes/separator.py | 4 ++-- .../components/turbomachinery/compressor.py | 4 ++-- src/tespy/connections/connection.py | 2 ++ src/tespy/tools/data_containers.py | 2 +- src/tespy/tools/fluid_properties/helpers.py | 2 +- 10 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/tespy/components/heat_exchangers/base.py b/src/tespy/components/heat_exchangers/base.py index f1685f639..5ad36b254 100644 --- a/src/tespy/components/heat_exchangers/base.py +++ b/src/tespy/components/heat_exchangers/base.py @@ -381,10 +381,10 @@ def calculate_td_log(self): o2 = self.outl[1] # temperature value manipulation for convergence stability - T_i1 = i1.calc_T(T0=i1.T.val_SI) - T_i2 = i2.calc_T(T0=i2.T.val_SI) - T_o1 = o1.calc_T(T0=o1.T.val_SI) - T_o2 = o2.calc_T(T0=o2.T.val_SI) + T_i1 = i1.calc_T() + T_i2 = i2.calc_T() + T_o1 = o1.calc_T() + T_o2 = o2.calc_T() if T_i1 <= T_o2: T_i1 = T_o2 + 0.01 @@ -581,8 +581,8 @@ def ttd_u_func(self): """ i = self.inl[0] o = self.outl[1] - T_i1 = i.calc_T(T0=i.T.val_SI) - T_o2 = o.calc_T(T0=o.T.val_SI) + T_i1 = i.calc_T() + T_o2 = o.calc_T() return self.ttd_u.val - T_i1 + T_o2 def ttd_u_func_doc(self, label): @@ -636,8 +636,8 @@ def ttd_l_func(self): """ i = self.inl[1] o = self.outl[0] - T_i2 = i.calc_T(T0=i.T.val_SI) - T_o1 = o.calc_T(T0=o.T.val_SI) + T_i2 = i.calc_T() + T_o1 = o.calc_T() return self.ttd_l.val - T_o1 + T_i2 def ttd_l_func_doc(self, label): diff --git a/src/tespy/components/heat_exchangers/condenser.py b/src/tespy/components/heat_exchangers/condenser.py index a87316095..377660332 100644 --- a/src/tespy/components/heat_exchangers/condenser.py +++ b/src/tespy/components/heat_exchangers/condenser.py @@ -327,9 +327,9 @@ def calculate_td_log(self): o2 = self.outl[1] T_i1 = i1.calc_T_sat() - T_i2 = i2.calc_T(T0=i2.T.val_SI) - T_o1 = o1.calc_T(T0=o1.T.val_SI) - T_o2 = o2.calc_T(T0=o2.T.val_SI) + T_i2 = i2.calc_T() + T_o1 = o1.calc_T() + T_o2 = o2.calc_T() if T_i1 <= T_o2 and not i1.T.is_set: T_i1 = T_o2 + 0.5 @@ -452,7 +452,7 @@ def ttd_u_func(self): i = self.inl[0] o = self.outl[1] T_i1 = i.calc_T_sat() - T_o2 = o.calc_T(T0=self.outl[1].T.val_SI) + T_o2 = o.calc_T() return self.ttd_u.val - T_i1 + T_o2 def ttd_u_func_doc(self, label): diff --git a/src/tespy/components/heat_exchangers/parabolic_trough.py b/src/tespy/components/heat_exchangers/parabolic_trough.py index 169d164fd..1b948ae7e 100644 --- a/src/tespy/components/heat_exchangers/parabolic_trough.py +++ b/src/tespy/components/heat_exchangers/parabolic_trough.py @@ -274,7 +274,7 @@ def energy_group_func(self): i = self.inl[0] o = self.outl[0] - T_m = 0.5 * (i.calc_T(T0=i.T.val_SI) + o.calc_T(T0=o.T.val_SI)) + T_m = 0.5 * (i.calc_T() + o.calc_T()) iam = ( 1 - self.iam_1.val * abs(self.aoi.val) diff --git a/src/tespy/components/heat_exchangers/simple.py b/src/tespy/components/heat_exchangers/simple.py index 57623e758..a9e555079 100644 --- a/src/tespy/components/heat_exchangers/simple.py +++ b/src/tespy/components/heat_exchangers/simple.py @@ -535,8 +535,8 @@ def kA_group_func(self): i = self.inl[0] o = self.outl[0] - ttd_1 = i.calc_T(T0=i.T.val_SI) - self.Tamb.val_SI - ttd_2 = o.calc_T(T0=o.T.val_SI) - self.Tamb.val_SI + ttd_1 = i.calc_T() - self.Tamb.val_SI + ttd_2 = o.calc_T() - self.Tamb.val_SI # For numerical stability: If temperature differences have # different sign use mean difference to avoid negative logarithm. @@ -651,8 +651,8 @@ def kA_char_group_func(self): # For numerical stability: If temperature differences have # different sign use mean difference to avoid negative logarithm. - ttd_1 = i.calc_T(T0=i.T.val_SI) - self.Tamb.val_SI - ttd_2 = o.calc_T(T0=o.T.val_SI) - self.Tamb.val_SI + ttd_1 = i.calc_T() - self.Tamb.val_SI + ttd_2 = o.calc_T() - self.Tamb.val_SI if (ttd_1 / ttd_2) < 0: td_log = (ttd_2 + ttd_1) / 2 diff --git a/src/tespy/components/heat_exchangers/solar_collector.py b/src/tespy/components/heat_exchangers/solar_collector.py index 9a940e12c..7129bd5c6 100644 --- a/src/tespy/components/heat_exchangers/solar_collector.py +++ b/src/tespy/components/heat_exchangers/solar_collector.py @@ -231,7 +231,7 @@ def energy_group_func(self): i = self.inl[0] o = self.outl[0] - T_m = 0.5 * (i.calc_T(T0=i.T.val_SI) + o.calc_T(T0=o.T.val_SI)) + T_m = 0.5 * (i.calc_T() + o.calc_T()) return ( i.m.val_SI * (o.h.val_SI - i.h.val_SI) diff --git a/src/tespy/components/nodes/separator.py b/src/tespy/components/nodes/separator.py index c826f022c..bf8a7be85 100644 --- a/src/tespy/components/nodes/separator.py +++ b/src/tespy/components/nodes/separator.py @@ -299,9 +299,9 @@ def energy_balance_func(self): \forall j \in \text{outlets} """ residual = [] - T_in = self.inl[0].calc_T(T0=300) + T_in = self.inl[0].calc_T() for o in self.outl: - residual += [T_in - o.calc_T(T0=300)] + residual += [T_in - o.calc_T()] return residual def energy_balance_func_doc(self, label): diff --git a/src/tespy/components/turbomachinery/compressor.py b/src/tespy/components/turbomachinery/compressor.py index a28d0d344..5c7668d92 100644 --- a/src/tespy/components/turbomachinery/compressor.py +++ b/src/tespy/components/turbomachinery/compressor.py @@ -374,7 +374,7 @@ def char_map_pr_func(self): i = self.inl[0] o = self.outl[0] - x = np.sqrt(i.T.design / i.calc_T(T0=i.T.val_SI)) + x = np.sqrt(i.T.design / i.calc_T()) y = (i.m.val_SI * i.p.design) / (i.m.design * i.p.val_SI * x) yarr, zarr = self.char_map_pr.char_func.evaluate_x(x) @@ -477,7 +477,7 @@ def char_map_eta_s_func(self): i = self.inl[0] o = self.outl[0] - x = np.sqrt(i.T.design / i.calc_T(T0=i.T.val_SI)) + x = np.sqrt(i.T.design / i.calc_T()) y = (i.m.val_SI * i.p.design) / (i.m.design * i.p.val_SI * x) yarr, zarr = self.char_map_eta_s.char_func.evaluate_x(x) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 3c58eeafe..bd788fc6a 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -737,6 +737,8 @@ def primary_ref_deriv(self, k, **kwargs): self.jacobian[k, ref.obj.get_attr(variable).J_col] = -ref.factor def calc_T(self, T0=None): + if T0 is None: + T0 = self.T.val_SI return T_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=T0) def T_func(self, k, **kwargs): diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index 4dd647fd4..61375b466 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -485,7 +485,7 @@ def attr(): 'design': np.nan, 'val': np.nan, 'val0': np.nan, - 'val_SI': np.nan, + 'val_SI': 0, 'unit': None, 'is_set': False, "is_var": False, diff --git a/src/tespy/tools/fluid_properties/helpers.py b/src/tespy/tools/fluid_properties/helpers.py index 27740208a..ff36cfa00 100644 --- a/src/tespy/tools/fluid_properties/helpers.py +++ b/src/tespy/tools/fluid_properties/helpers.py @@ -67,7 +67,7 @@ def get_molar_fractions(fluid_data): def inverse_temperature_mixture(p=None, target_value=None, fluid_data=None, T0=None, f=None): # calculate the fluid properties for fluid mixtures valmin, valmax = get_mixture_temperature_range(fluid_data) - if T0 is None: + if T0 is None or T0 == 0 or np.isnan(T0): T0 = (valmin + valmax) / 2.0 function_kwargs = { From f3a9d880c9892186ffe05f86a9500fcb377a7019 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 13:07:28 +0100 Subject: [PATCH 20/27] Update whats new --- docs/whats_new/v0-7-2.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/whats_new/v0-7-2.rst b/docs/whats_new/v0-7-2.rst index ca1c1c59b..fcb2a6dfb 100644 --- a/docs/whats_new/v0-7-2.rst +++ b/docs/whats_new/v0-7-2.rst @@ -6,6 +6,12 @@ Bug Fixes - The `delta` value of the :py:class:`tespy.connections.connection.Ref` class was oriented with the wrong sign. A positive delta lead to a negative value. Fixed in (`PR #459 `__). +- In initial simulations the temperature value of mixtures is 0 by default. + For calculating temperatures of the mixtures during that initial simulation, + that value was used as starting value causing CoolProp to raise an error and + the calculation to crash. This is now prevented by checking if the starting + value is reasonable or not + (`PR #477 `__). Contributors ############ From 676be3209e3a498f22f721e0582a451a5df28efe Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 16:38:38 +0100 Subject: [PATCH 21/27] Ignore github links in linkchecker --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index aac7ce1b4..ad8982f2e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -149,5 +149,5 @@ r'https://doi.org/10.1021/ie4033999', # 28.02.2023: does not resolve anymore for some reason r'https://doi.org/10.1002/bbpc.19900940121', # 13.03.2023 ...? r'http://www\.coolprop\.org/.*', # 02.12.2023 ...? - r'https://github.com/oemof/tespy/commit/bf0b8650b0965c916727ebe10f39f0cefabb71e0', # 08.01.2024 ...? + r'https://github\.com/oemof/tespy/.*', # 08.01.2024 ...? ] From dfa39959b20f35d24510e5bb475858b7b1d4ae24 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 16:43:52 +0100 Subject: [PATCH 22/27] Add a couple of sentences towards different mixture types --- docs/modules/fluid_properties.rst | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/modules/fluid_properties.rst b/docs/modules/fluid_properties.rst index 24d2a5958..e667b795a 100644 --- a/docs/modules/fluid_properties.rst +++ b/docs/modules/fluid_properties.rst @@ -60,14 +60,21 @@ Incompressible fluids If you are looking for heat transfer fluids, the list of incompressible `fluids `__ might be interesting for you. In contrast to the pure fluids, the properties -cover liquid state only. TESPy supports using pure incompressibles as well as -the predefined mixtures. +cover liquid state only. Fluid mixtures ++++++++++++++ -CoolProp provides a back end for predefined mixtures, which is rather instable -using HEOS. If you want to use the mixture feature of CoolProp we recommend -using the REFPROP back end instead. +TESPy provides suppport for three types of mixtures: + +- ideal: Mixtures for gases only. +- ideal-cond: Mixture for gases with condensation calculation for water share. +- incompressible: Mixtures for incompressible fluids. + +Furthermore, CoolProp provides a back end for predefined mixtures, which is +rather instable using HEOS. Using the CoolProp mixture back-end is not tested, +reach out if you would like to support us in adopting the TESPy implementation. +In general, to use the mixture feature of CoolProp we recommend using the +REFPROP back end instead of HEOS. Using other engines ------------------- From bd58717fffd375e9109759cb086f3330e6ca2a8c Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 16:44:32 +0100 Subject: [PATCH 23/27] Fix typo --- docs/modules/fluid_properties.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/fluid_properties.rst b/docs/modules/fluid_properties.rst index e667b795a..eb1366578 100644 --- a/docs/modules/fluid_properties.rst +++ b/docs/modules/fluid_properties.rst @@ -64,7 +64,7 @@ cover liquid state only. Fluid mixtures ++++++++++++++ -TESPy provides suppport for three types of mixtures: +TESPy provides support for three types of mixtures: - ideal: Mixtures for gases only. - ideal-cond: Mixture for gases with condensation calculation for water share. From d67e72eda2403346c3ff71aee899070c5e0f4940 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 17:57:13 +0100 Subject: [PATCH 24/27] Remove components and connections from removed parts and fix branch merging --- src/tespy/networks/network.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index d7a11fa2c..ee195af54 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -454,6 +454,7 @@ def del_conns(self, *args): comps = list({cp for c in args for cp in [c.source, c.target]}) for c in args: self.conns.drop(c.label, inplace=True) + self.results["Connection"].drop(c.label, inplace=True) msg = ('Deleted connection ' + c.label + ' from network.') logger.debug(msg) @@ -554,6 +555,9 @@ def _del_comps(self, comps): comp not in self.conns["target"].values ): self.comps.drop(comp.label, inplace=True) + self.results[comp.__class__.__name__].drop( + comp.label, inplace=True, errors="ignore" + ) msg = f"Deleted component {comp.label} from network." logger.debug(msg) @@ -741,7 +745,7 @@ def create_fluid_wrapper_branches(self): set(branch_data["connections"]) & set(ob_data["connections"]) ) - if len(common_connections) > 0: + if len(common_connections) > 0 and ob_name in merged: merged[branch_name]["connections"] = list( set(branch_data["connections"] + ob_data["connections"]) ) From 5934316f40d2eca5a5c4b47065e738c243348e17 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 18:19:13 +0100 Subject: [PATCH 25/27] Fix unsetting referenced connection properties --- src/tespy/connections/connection.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index e2ca573f0..e37049f05 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -522,8 +522,9 @@ def _parameter_specification(self, key, value): if value is None: self.get_attr(key).set_attr(is_set=False) + if f"{key}_ref" in self.property_data: - self.get_attr(key).set_attr(is_set=False) + self.get_attr(f"{key}_ref").set_attr(is_set=False) if key in ["m", "p", "h"]: self.get_attr(key).is_var = True From 3d9ff3bb913e5701080c3acb2582843cf6f00056 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 18:25:24 +0100 Subject: [PATCH 26/27] Fix dropping of data on connection deletion --- src/tespy/networks/network.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index ee195af54..1fcf09011 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -454,7 +454,10 @@ def del_conns(self, *args): comps = list({cp for c in args for cp in [c.source, c.target]}) for c in args: self.conns.drop(c.label, inplace=True) - self.results["Connection"].drop(c.label, inplace=True) + if "Connection" in self.results: + self.results["Connection"].drop( + c.label, inplace=True, errors="ignore" + ) msg = ('Deleted connection ' + c.label + ' from network.') logger.debug(msg) From 70654a87c8cbf23d5463db548b3cb34e7f522e92 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Sun, 21 Jan 2024 18:36:32 +0100 Subject: [PATCH 27/27] Bump versino --- docs/whats_new/v0-7-2.rst | 4 ++-- pyproject.toml | 2 +- src/tespy/__init__.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/whats_new/v0-7-2.rst b/docs/whats_new/v0-7-2.rst index fcb2a6dfb..430690e81 100644 --- a/docs/whats_new/v0-7-2.rst +++ b/docs/whats_new/v0-7-2.rst @@ -1,5 +1,5 @@ -v0.7.2 - Under development -++++++++++++++++++++++++++ +v0.7.1 - Newton's Nature (January, 21, 2024) +++++++++++++++++++++++++++++++++++++++++++++ Bug Fixes ######### diff --git a/pyproject.toml b/pyproject.toml index 7f9b42cea..648caec25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ exclude = ["docs/_build"] [project] name = "tespy" -version = "0.7.1.post1" +version = "0.7.2" description = "Thermal Engineering Systems in Python (TESPy)" readme = "README.rst" authors = [ diff --git a/src/tespy/__init__.py b/src/tespy/__init__.py index fde368697..9a79a2196 100644 --- a/src/tespy/__init__.py +++ b/src/tespy/__init__.py @@ -3,7 +3,7 @@ import os __datapath__ = os.path.join(importlib.resources.files("tespy"), "data") -__version__ = '0.7.1.post1 - Newton\'s Nature' +__version__ = '0.7.2 - Newton\'s Nature' # tespy data and connections import from . import connections # noqa: F401