diff --git a/docs/advanced_tutorials/heat_exchangers.ipynb b/docs/advanced_tutorials/heat_exchangers.ipynb index ddfb1ae1..6a0c2122 100644 --- a/docs/advanced_tutorials/heat_exchangers.ipynb +++ b/docs/advanced_tutorials/heat_exchangers.ipynb @@ -129,18 +129,17 @@ "```{math}\n", "\\Delta \\theta_\\text{log} = \\frac{\\Delta T_{i} - \\Delta T_{i+1}}{\\ln \\frac{\\Delta T_{i}}{\\Delta T_{i+1}}}\\\\\n", "\n", - "kA=\\frac{\\dot Q}{\\Delta \\theta_\\text{log}}\\\\\n", - "\n", "UA_{i}=\\frac{\\dot Q_{i}}{\\Delta \\theta_{\\text{log,}i}}\\\\\n", "\n", "UA=\\sum UA_{i}\n", "\n", "```\n", "\n", - "For the calculation of {math}`kA` the terminal temperature differences `ttd_u` and\n", - "`ttd_l` are considered as {math}`\\Delta T_0` and {math}`\\Delta T_1`. For the calculation\n", - "of {math}`UA`, the internal temperature differences {math}`\\Delta T_{i}` in each section\n", - "of the heat exchanger are employed." + "For the calculation of {math}`UA` in 0D variants the terminal temperature\n", + "differences `ttd_u` and `ttd_l` are considered as {math}`\\Delta T_0` and\n", + "{math}`\\Delta T_1`. For the calculation of {math}`UA` in 1D variants the\n", + "internal temperature differences {math}`\\Delta T_{i}` in each section of the\n", + "heat exchanger are employed." ] }, { @@ -165,8 +164,7 @@ "results.append({\n", " \"model\": \"HeatExchanger\",\n", " \"minimum pinch (K)\": f\"n/a ({hx_0d.ttd_min.val:.1f})\",\n", - " \"kA (kW/K)\": f\"{hx_0d.kA.val:.1f}\",\n", - " \"UA (kW/K)\": \"n/a\",\n", + " \"UA (kW/K)\": f\"{hx_0d.UA.val:.1f}\",\n", "})\n", "\n", "heat = [0, abs(hx_0d.Q.val)]\n", @@ -232,8 +230,7 @@ "results.append({\n", " \"model\": \"Condenser\",\n", " \"minimum pinch (K)\": f\"n/a ({hx_cond.ttd_min.val:.1f})\",\n", - " \"kA (kW/K)\": f\"{hx_cond.kA.val:.1f}\",\n", - " \"UA (kW/K)\": \"n/a\",\n", + " \"UA (kW/K)\": f\"{hx_cond.UA.val:.1f}\",\n", "})\n", "\n", "T_cond = c2.T.val_SI - c2.calc_td_dew()\n", @@ -303,7 +300,6 @@ "results.append({\n", " \"model\": \"MovingBoundaryHeatExchanger\",\n", " \"minimum pinch (K)\": f\"{hx_mb.td_pinch.val:.2f}\",\n", - " \"kA (kW/K)\": f\"{hx_mb.kA.val:.1f}\",\n", " \"UA (kW/K)\": f\"{hx_mb.UA.val:.1f}\",\n", "})\n", "\n", @@ -369,7 +365,6 @@ "results.append({\n", " \"model\": \"SectionedHeatExchanger (50 sections)\",\n", " \"minimum pinch (K)\": f\"{hx_sectioned.td_pinch.val:.2f}\",\n", - " \"kA (kW/K)\": f\"{hx_sectioned.kA.val:.1f}\",\n", " \"UA (kW/K)\": f\"{hx_sectioned.UA.val:.1f}\",\n", "})\n", "\n", @@ -420,7 +415,6 @@ "results.append({\n", " \"model\": \"SectionedHeatExchanger (6 sections)\",\n", " \"minimum pinch (K)\": f\"{hx_sectioned.td_pinch.val:.2f}\",\n", - " \"kA (kW/K)\": f\"{hx_sectioned.kA.val:.1f}\",\n", " \"UA (kW/K)\": f\"{hx_sectioned.UA.val:.1f}\",\n", "})" ] diff --git a/docs/advanced_tutorials/heat_pump_steps.rst b/docs/advanced_tutorials/heat_pump_steps.rst index 15877507..1f3e8d26 100644 --- a/docs/advanced_tutorials/heat_pump_steps.rst +++ b/docs/advanced_tutorials/heat_pump_steps.rst @@ -442,7 +442,7 @@ The changes we want to apply can be summarized as follows: - All heat exchangers should be calculated based on their heat transfer coefficient with a characteristic for correction of that value depending - on the change of mass flow (:code:`kA_char` and :code:`UA_cecchinato` for the + on the change of mass flow (:code:`UA_char` and :code:`UA_cecchinato` for the condenser). Therefore, pinch temperature difference and terminal temperature difference value specifications need to be design parameters. Also, the temperature at connection 14 cannot be specified anymore, since it will be a @@ -451,8 +451,8 @@ The changes we want to apply can be summarized as follows: isentropic efficiency instead of a constant value (:code:`eta_s_char`). - Pressure drops in components will be a result of the changing mass flow through that component given the diameter in the design. The pressure ratio - will therefore be replaced by :code:`zeta` for all heat exchangers. The zeta - value is a geometry independent value. + will therefore be replaced by :code:`zeta_d4` for all heat exchangers. The + zeta_d4 value is a geometry independent value (:math:`\zeta/D^4`). On top of that, for the evaporator the characteristic function of the heat transfer coefficient should follow different data than the default diff --git a/docs/basic_tutorials/district_heating.rst b/docs/basic_tutorials/district_heating.rst index de408190..93a8cb54 100644 --- a/docs/basic_tutorials/district_heating.rst +++ b/docs/basic_tutorials/district_heating.rst @@ -84,7 +84,7 @@ In the second step we can fix the diameter to its resulting value and therefore unset the desired pressure loss first. Then, we set the ambient temperature of the pipes (we assume the temperature of the ambient is not affected by the heat loss of the pipe). With the given heat loss, the -:code:`kA` value can be calculated. It is the area independent heat transfer +:code:`UA` value can be calculated. It is the area independent heat transfer coefficient. .. literalinclude:: /../tutorial/basics/district_heating.py @@ -107,7 +107,7 @@ Next, we want to investigate what happens, in case the - overall temperature level in the heating system is reduced. To do that, we will use similar setups as show in the Rankine cycle -introduction. The :code:`kA` value of both pipes is assumed to be fixed, the +introduction. The :code:`UA` value of both pipes is assumed to be fixed, the efficiency of the pump and pressure losses in consumer and heat source are constant as well. diff --git a/docs/basic_tutorials/rankine_cycle.rst b/docs/basic_tutorials/rankine_cycle.rst index 31c24ed2..3bf12c61 100644 --- a/docs/basic_tutorials/rankine_cycle.rst +++ b/docs/basic_tutorials/rankine_cycle.rst @@ -245,7 +245,7 @@ In order to apply these specifications, we can use the :code:`design` and data in the list in an offdesign calculation. The keyword :code:`offdesign` automatically sets the respective parameter for the offdesign calculation. In case the specification refers to a value, the value is taken from the design -mode calculation. In the example, the main condenser's kA value is calculated +mode calculation. In the example, the main condenser's UA value is calculated in the design simulation and its value will be kept constant through the offdesign simulations. diff --git a/docs/building_blocks/components.rst b/docs/building_blocks/components.rst index 5c168146..56483a18 100644 --- a/docs/building_blocks/components.rst +++ b/docs/building_blocks/components.rst @@ -54,15 +54,15 @@ at the example of the heat transfer coefficient of an evaporator. >>> he = HeatExchanger('evaporator') >>> # specify the value - >>> he.set_attr(kA=1e5) - >>> he.kA.val + >>> he.set_attr(UA=1e5) + >>> he.UA.val 100000.0 - >>> he.kA.is_set + >>> he.UA.is_set True >>> # possibilities to unset a value - >>> he.set_attr(kA=None) - >>> he.kA.is_set + >>> he.set_attr(UA=None) + >>> he.UA.is_set False Grouped parameters @@ -186,8 +186,8 @@ is possible to specify your own data for these characteristic functions. **There are two different characteristics specifications** The characteristic function can be an auxiliary parameter of a different - component property. This is the case for :code:`kA_char1` - and :code:`kA_char2` of heat exchangers as well as the characteristics of a + component property. This is the case for :code:`UA_char1` + and :code:`UA_char2` of heat exchangers as well as the characteristics of a combustion engine: :code:`tiP_char`, :code:`Q1_char`, :code:`Q2_char` and :code:`Qloss_char`. @@ -196,13 +196,13 @@ is possible to specify your own data for these characteristic functions. **What does this mean?** - For the auxiliary functionality the main parameter, e.g. :code:`kA_char` - of a heat exchanger must be set :code:`.kA_char.is_set=True`. + For the auxiliary functionality the main parameter, e.g. :code:`UA_char` + of a heat exchanger must be set :code:`.UA_char.is_set=True`. For the other functionality the characteristics parameter must be set e.g. :code:`.eta_s_char.is_set=True`. -For example, :code:`kA_char` specification for heat exchangers: +For example, :code:`UA_char` specification for heat exchangers: .. code-block:: python @@ -235,49 +235,49 @@ For example, :code:`kA_char` specification for heat exchangers: >>> nw.solve("design") >>> nw.save("design_case.json") - >>> round(he.kA.val) + >>> round(he.UA.val) 503013 >>> # the characteristic function is made for offdesign calculation. - >>> he.set_attr(offdesign=["kA_char"]) + >>> he.set_attr(offdesign=["UA_char"]) >>> c4.set_attr(design=["T"]) >>> nw.solve("offdesign", design_path="design_case.json") >>> # since we did not change any property, the offdesign case yields the - >>> # same value as the design kA value - >>> round(he.kA.val) + >>> # same value as the design UA value + >>> round(he.UA.val) 503013 >>> c1.set_attr(m=9) >>> # use a characteristic line from the defaults: specify the component, the >>> # parameter and the name of the characteristic function. Also, specify, >>> # what type of characteristic function you want to use. - >>> kA_char1 = ldc('HeatExchanger', 'kA_char1', 'DEFAULT', CharLine) - >>> kA_char2 = ldc('HeatExchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) - >>> he.set_attr(kA_char2=kA_char2) + >>> UA_char1 = ldc('HeatExchanger', 'UA_char1', 'DEFAULT', CharLine) + >>> UA_char2 = ldc('HeatExchanger', 'UA_char2', 'EVAPORATING FLUID', CharLine) + >>> he.set_attr(UA_char2=UA_char2) >>> nw.solve("offdesign", design_path="design_case.json") - >>> round(he.kA.val) + >>> round(he.UA.val) 481745 >>> # specification of a data container yields the same result. It is >>> # additionally possible to specify the characteristics parameter, e.g. - >>> # mass flow for kA_char1 (identical to default case) and volumetric - >>> # flow for kA_char2 + >>> # mass flow for UA_char1 (identical to default case) and volumetric + >>> # flow for UA_char2 >>> he.set_attr( - ... kA_char1={'char_func': kA_char1, 'param': 'm'}, - ... kA_char2={'char_func': kA_char2, 'param': 'v'} + ... UA_char1={'char_func': UA_char1, 'param': 'm'}, + ... UA_char2={'char_func': UA_char2, 'param': 'v'} ... ) >>> nw.solve("offdesign", design_path="design_case.json") - >>> round(he.kA.val) + >>> round(he.UA.val) 481745 - >>> # or use custom values for the characteristic line e.g. kA vs volumetric + >>> # or use custom values for the characteristic line e.g. UA vs volumetric >>> # flow >>> x = np.array([0, 0.5, 1, 2]) >>> y = np.array([0, 0.8, 1, 1.2]) - >>> kA_char2 = CharLine(x, y) - >>> he.set_attr(kA_char2={'char_func': kA_char2, 'param': 'v'}) + >>> UA_char2 = CharLine(x, y) + >>> he.set_attr(UA_char2={'char_func': UA_char2, 'param': 'v'}) >>> nw.solve("offdesign", design_path="design_case.json") - >>> round(he.kA.val) + >>> round(he.UA.val) 475107 Full working example for :code:`eta_s_char` specification of a turbine. @@ -347,13 +347,13 @@ extrapolation parameter to :code:`True`. # use custom specification parameters >>> x = np.array([0, 0.5, 1, 2]) >>> y = np.array([0, 0.8, 1, 1.2]) - >>> kA_char1 = CharLine(x, y, extrapolate=True) - >>> kA_char1.extrapolate + >>> UA_char1 = CharLine(x, y, extrapolate=True) + >>> UA_char1.extrapolate True >>> # set extrapolation to True for existing lines, e.g. - >>> he.kA_char1.char_func.extrapolate = True - >>> he.kA_char1.char_func.extrapolate + >>> he.UA_char1.char_func.extrapolate = True + >>> he.UA_char1.char_func.extrapolate True For more information on how the characteristic functions work diff --git a/docs/building_blocks/networks.rst b/docs/building_blocks/networks.rst index 10c50982..46c6ddbc 100644 --- a/docs/building_blocks/networks.rst +++ b/docs/building_blocks/networks.rst @@ -316,12 +316,12 @@ The heat transfer coefficient is calculated in the preprocessing of the offdesign case based on the results from the design-case. Of course, this applies to all other parameters in the same way. Also, the pressure drop is a result of the geometry for the offdesign case, thus we swap the pressure ratios -with zeta values. +with geometry independent zeta :math:`\frac{\zeta}{D^4}` values. .. code-block:: python mycomponent.set_attr( - design=['ttd_u', 'pr1', 'pr2'], offdesign=['kA', 'zeta1', 'zeta2'] + design=['ttd_u', 'pr1', 'pr2'], offdesign=['UA', 'zeta1_d4', 'zeta2_d4'] ) .. note:: diff --git a/docs/building_blocks/subsystems.rst b/docs/building_blocks/subsystems.rst index b71040b1..d7c9b95b 100644 --- a/docs/building_blocks/subsystems.rst +++ b/docs/building_blocks/subsystems.rst @@ -140,17 +140,17 @@ different tespy classes required. >>> # %% component parameters >>> sg.get_comp('economizer').set_attr( ... pr1=0.999, pr2=0.97, design=['pr1', 'pr2'], - ... offdesign=['zeta1', 'zeta2', 'kA_char'] + ... offdesign=['zeta1_d4', 'zeta2_d4', 'UA_char'] ... ) >>> sg.get_comp('evaporator').set_attr( ... pr1=0.999, ttd_l=20, design=['pr1', 'ttd_l'], - ... offdesign=['zeta1', 'kA_char'] + ... offdesign=['zeta1_d4', 'UA_char'] ... ) >>> sg.get_comp('superheater').set_attr( ... pr1=0.999, pr2=0.99, design=['pr1', 'pr2'], - ... offdesign=['zeta1', 'zeta2', 'kA_char'] + ... offdesign=['zeta1_d4', 'zeta2_d4', 'UA_char'] ... ) >>> sg.get_conn('2').set_attr(td_bubble=5, design=['td_bubble']) diff --git a/docs/knowledge_center/faq.rst b/docs/knowledge_center/faq.rst index cc87fc46..340271a5 100644 --- a/docs/knowledge_center/faq.rst +++ b/docs/knowledge_center/faq.rst @@ -30,8 +30,8 @@ Modeling best practices - discretized 1D models, which allow the specification of internal pinch. - We have created an :ref:`overview ` on the - different 0D and 1D types available and when to use which model. + We have created an :ref:`overview ` on + the different 0D and 1D types available and when to use which model. .. _faq_errors_label: diff --git a/docs/scripts/docstring_updater.py b/docs/scripts/docstring_updater.py index 11dadf2a..f356f834 100644 --- a/docs/scripts/docstring_updater.py +++ b/docs/scripts/docstring_updater.py @@ -185,18 +185,18 @@ def _ports_section(cls): if kind == "fixed": ports = entry.get("ports", []) if ports: - lines.append(f"{label}: {', '.join(ports)}") + lines.append(f"- {label}: {', '.join(ports)}") elif kind == "variable": param = entry["parameter"] pattern = entry["pattern"] lines.append( - f"{label}: {pattern.replace('{n}', '1')}, " + f"- {label}: {pattern.replace('{n}', '1')}, " f"{pattern.replace('{n}', '2')}, ... " f"(variable, count set by :code:`{param}`)" ) if not lines: return "" - return "Ports\n-----\n\n" + "\n\n".join(lines) + return "Ports\n-----\n\n" + "\n".join(lines) def _mandatory_section(instance): @@ -266,8 +266,8 @@ def _parameters_section(instance, base_params=None, param_filter=None): " " + " ".join(meta_parts) if meta_parts else "" ) body_line = textwrap.fill( - desc_body.strip(), width=76, initial_indent=" ", - subsequent_indent=" " + desc_body.strip() or "Description missing.", + width=76, initial_indent=" ", subsequent_indent=" " ) if ref: eq_line = f" Equation: {ref}." diff --git a/src/tespy/components/basics/cycle_closer.py b/src/tespy/components/basics/cycle_closer.py index 76591ec4..de42185a 100644 --- a/src/tespy/components/basics/cycle_closer.py +++ b/src/tespy/components/basics/cycle_closer.py @@ -26,9 +26,8 @@ class CycleCloser(Component): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 + - Fluid inlets: in1 + - Fluid outlets: out1 Mandatory Equations ------------------- diff --git a/src/tespy/components/basics/sink.py b/src/tespy/components/basics/sink.py index 2f450160..4d81a518 100644 --- a/src/tespy/components/basics/sink.py +++ b/src/tespy/components/basics/sink.py @@ -24,7 +24,7 @@ class Sink(Component): Ports ----- - Fluid inlets: in1 + - Fluid inlets: in1 Mandatory Equations ------------------- diff --git a/src/tespy/components/basics/source.py b/src/tespy/components/basics/source.py index 70ada47b..64a4c3d5 100644 --- a/src/tespy/components/basics/source.py +++ b/src/tespy/components/basics/source.py @@ -25,7 +25,7 @@ class Source(Component): Ports ----- - Fluid outlets: out1 + - Fluid outlets: out1 Mandatory Equations ------------------- diff --git a/src/tespy/components/basics/subsystem_interface.py b/src/tespy/components/basics/subsystem_interface.py index 1f007935..d1fb2d2a 100644 --- a/src/tespy/components/basics/subsystem_interface.py +++ b/src/tespy/components/basics/subsystem_interface.py @@ -35,9 +35,8 @@ class SubsystemInterface(Component): Ports ----- - Fluid inlets: in1, in2, ... (variable, count set by :code:`num_inter`) - - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_inter`) + - Fluid inlets: in1, in2, ... (variable, count set by :code:`num_inter`) + - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_inter`) Mandatory Equations ------------------- diff --git a/src/tespy/components/combustion/base.py b/src/tespy/components/combustion/base.py index 9a2ad727..707ce0a9 100644 --- a/src/tespy/components/combustion/base.py +++ b/src/tespy/components/combustion/base.py @@ -45,9 +45,8 @@ class CombustionChamber(Component): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1 + - Fluid inlets: in1, in2 + - Fluid outlets: out1 Mandatory Equations ------------------- diff --git a/src/tespy/components/combustion/diabatic.py b/src/tespy/components/combustion/diabatic.py index 095b7e56..f4c440be 100644 --- a/src/tespy/components/combustion/diabatic.py +++ b/src/tespy/components/combustion/diabatic.py @@ -38,9 +38,8 @@ class DiabaticCombustionChamber(CombustionChamber): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1 + - Fluid inlets: in1, in2 + - Fluid outlets: out1 Mandatory Equations ------------------- diff --git a/src/tespy/components/combustion/engine.py b/src/tespy/components/combustion/engine.py index b5038269..3f758db9 100644 --- a/src/tespy/components/combustion/engine.py +++ b/src/tespy/components/combustion/engine.py @@ -49,11 +49,9 @@ class CombustionEngine(CombustionChamber): Ports ----- - Fluid inlets: in1, in2, in3, in4 - - Fluid outlets: out1, out2, out3 - - Power outlets: power + - Fluid inlets: in1, in2, in3, in4 + - Fluid outlets: out1, out2, out3 + - Power outlets: power Mandatory Equations ------------------- @@ -96,7 +94,7 @@ class CombustionEngine(CombustionChamber): Equation: :py:meth:`dp_structure_matrix `. eta_mech : float - + Description missing. f_nox : float, dict Mass-based nitric oxide (NO) generation rate in flue gas in mass of @@ -157,7 +155,7 @@ class CombustionEngine(CombustionChamber): Thermal input to heat dissipation lookup table. T_v_inner : float - + Description missing. ti : float, dict Thermal input of fuel: lower heating value multiplied with mass flow. @@ -168,14 +166,20 @@ class CombustionEngine(CombustionChamber): Thermal input to power lookup table. zeta1 : float, dict - Heating port 1 non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta1_d4` instead. + + zeta1_d4 : float, dict + Heating port 1 geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. zeta2 : float, dict - Heating port 2 non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta2_d4` instead. + + zeta2_d4 : float, dict + Heating port 2 geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -242,7 +246,7 @@ class CombustionEngine(CombustionChamber): to be split in half. >>> chp.set_attr(pr1=0.99, P=-10e6, lamb=1.0, - ... design=['pr1'], offdesign=['zeta1']) + ... design=['pr1'], offdesign=['zeta1_d4']) >>> amb_comb.set_attr(p=5, T=30, fluid={'Ar': 0.0129, 'N2': 0.7553, ... 'CO2': 0.0004, 'O2': 0.2314}) >>> sf_comb.set_attr(T=30, fluid={'CH4': 1}) @@ -271,6 +275,8 @@ class CombustionEngine(CombustionChamber): 0.75 """ + _parameter_aliases = {'zeta1': 'zeta1_d4', 'zeta2': 'zeta2_d4'} + def get_parameters(self): params = super().get_parameters() params.update({ @@ -334,21 +340,31 @@ def get_parameters(self): description="heating port 2 inlet to outlet absolute pressure change", calc=self._calc_dp, calc_params={'inconn': 1, 'outconn': 1} ), + 'zeta1_d4': dc_cp( + min_val=0, max_val=1e15, num_eq_sets=1, + dependents=self.zeta_d4_dependents, + func=self.zeta_d4_func, + func_params={'zeta': 'zeta1_d4'}, + description="heating port 1 geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4 + ), 'zeta1': dc_cp( + min_val=0, is_result=True, + description="deprecated, use :code:`zeta1_d4` instead", + calc=self._calc_zeta_d4 + ), + 'zeta2_d4': dc_cp( min_val=0, max_val=1e15, num_eq_sets=1, - dependents=self.zeta_dependents, - func=self.zeta_func, - func_params={'zeta': 'zeta1'}, - description="heating port 1 non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta + dependents=self.zeta_d4_dependents, + func=self.zeta_d4_func, + func_params={'zeta': 'zeta2_d4', 'inconn': 1, 'outconn': 1}, + description="heating port 2 geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4, calc_params={'inconn': 1, 'outconn': 1} ), 'zeta2': dc_cp( - min_val=0, max_val=1e15, num_eq_sets=1, - dependents=self.zeta_dependents, - func=self.zeta_func, - func_params={'zeta': 'zeta2', 'inconn': 1, 'outconn': 1}, - description="heating port 2 non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta, calc_params={'inconn': 1, 'outconn': 1} + min_val=0, is_result=True, + description="deprecated, use :code:`zeta2_d4` instead", + calc=self._calc_zeta_d4, calc_params={'inconn': 1, 'outconn': 1} ), 'tiP_char': dc_cc( description="thermal input to power lookup table" diff --git a/src/tespy/components/component.py b/src/tespy/components/component.py index d818ec6c..cf4f28ff 100644 --- a/src/tespy/components/component.py +++ b/src/tespy/components/component.py @@ -13,6 +13,7 @@ """ import math +import warnings from collections import deque import numpy as np @@ -131,6 +132,8 @@ class Component: """ + _parameter_aliases = {} + def __init__(self, label, **kwargs): if not isinstance(label, str): @@ -191,6 +194,16 @@ def set_attr(self, **kwargs): components share the :py:meth:`tespy.components.component.Component.set_attr` method. """ + for old, new in self._parameter_aliases.items(): + if old in kwargs: + warnings.warn( + f"The parameter '{old}' of component {self.label!r} is " + f"deprecated. Use '{new}' instead.", + FutureWarning, stacklevel=2 + ) + kwargs[new] = kwargs[old] + if kwargs[old] == 'var': + del kwargs[old] for key, value in kwargs.items(): if key in self.parameters: self._set_parameter(key, value) @@ -369,6 +382,25 @@ def _preprocess(self, row_idx): sum_eq += constraint.num_eq_sets + for old, new in self._parameter_aliases.items(): + if old not in self.parameters or new not in self.parameters: + continue + for lst_name in ('design', 'offdesign'): + lst = getattr(self, lst_name) + if old in lst: + warnings.warn( + f"Parameter '{old}' of component {self.label!r} is " + f"deprecated. Use '{new}' instead.", + FutureWarning, stacklevel=2 + ) + lst[lst.index(old)] = new + old_p = self.get_attr(old) + new_p = self.get_attr(new) + if old_p.is_set and not new_p.is_set: + new_p.is_set = True + if hasattr(old_p, 'design') and old_p.design and not getattr(new_p, 'design', None): + new_p.design = old_p.design + if not self.bypass: sum_eq = self._setup_user_imposed_constraints(row_idx, sum_eq) @@ -1005,7 +1037,7 @@ def variable_equality_structure_matrix(self, k, **kwargs): self._structure_matrix[k + count, i.get_attr(variable).sm_col] = 1 self._structure_matrix[k + count, o.get_attr(variable).sm_col] = -1 - def _calc_zeta(self, inconn=0, outconn=0): + def _calc_zeta_d4(self, inconn=0, outconn=0): i, o = self.inl[inconn], self.outl[outconn] if abs(i.m.val_SI) <= 1e-4: @@ -1016,15 +1048,15 @@ def _calc_zeta(self, inconn=0, outconn=0): / (4 * i.m.val_SI ** 2 * (i.vol.val_SI + o.vol.val_SI)) ) - def zeta_func(self, zeta=None, inconn=0, outconn=0): + def zeta_d4_func(self, zeta=None, inconn=0, outconn=0): r""" - Calculate residual value of :math:`\zeta`-function. + Calculate residual value of the :math:`\zeta/D^4` pressure loss equation. Parameters ---------- zeta : str - Component parameter to evaluate the zeta_func on, e.g. - :code:`zeta1`. + Component parameter to evaluate the zeta_d4_func on, e.g. + :code:`zeta1_d4`. inconn : int Connection index of inlet. @@ -1049,9 +1081,10 @@ def zeta_func(self, zeta=None, inconn=0, outconn=0): Note ---- - The zeta value is calculated on the basis of a given pressure loss at - a given flow rate in the design case. As the cross sectional area A - will not change, it is possible to handle the equation in this way: + The :math:`\zeta/D^4` value is calculated on the basis of a given + pressure loss at a given flow rate in the design case. As the cross + sectional area A will not change, it is possible to handle the equation + in this way: .. math:: @@ -1073,7 +1106,7 @@ def zeta_func(self, zeta=None, inconn=0, outconn=0): / (8 * abs(i.m.val_SI) * i.m.val_SI * (v_i + v_o) / 2) ) - def zeta_dependents(self, zeta=None, inconn=0, outconn=0): + def zeta_d4_dependents(self, zeta=None, inconn=0, outconn=0): return [ self.inl[inconn].m, self.inl[inconn].p, diff --git a/src/tespy/components/displacementmachinery/base.py b/src/tespy/components/displacementmachinery/base.py index 7e33e158..5f3bad75 100644 --- a/src/tespy/components/displacementmachinery/base.py +++ b/src/tespy/components/displacementmachinery/base.py @@ -26,9 +26,8 @@ class DisplacementMachine(Component): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 + - Fluid inlets: in1 + - Fluid outlets: out1 Mandatory Equations ------------------- diff --git a/src/tespy/components/displacementmachinery/polynomial_compressor.py b/src/tespy/components/displacementmachinery/polynomial_compressor.py index 5eb8ccc2..e67204c1 100644 --- a/src/tespy/components/displacementmachinery/polynomial_compressor.py +++ b/src/tespy/components/displacementmachinery/polynomial_compressor.py @@ -47,11 +47,9 @@ class PolynomialCompressor(DisplacementMachine): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: power + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/displacementmachinery/polynomial_compressor_with_cooling.py b/src/tespy/components/displacementmachinery/polynomial_compressor_with_cooling.py index 3f15161c..21171053 100644 --- a/src/tespy/components/displacementmachinery/polynomial_compressor_with_cooling.py +++ b/src/tespy/components/displacementmachinery/polynomial_compressor_with_cooling.py @@ -40,11 +40,9 @@ class PolynomialCompressorWithCooling(PolynomialCompressor): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 - - Power inlets: power + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 + - Power inlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/heat/bus.py b/src/tespy/components/heat/bus.py index 72d26bf7..f172fb2a 100644 --- a/src/tespy/components/heat/bus.py +++ b/src/tespy/components/heat/bus.py @@ -28,9 +28,8 @@ class HeatBus(_EnergyBus): Ports ----- - Heat inlets: heat_in1, heat_in2, ... (variable, count set by :code:`num_in`) - - Heat outlets: heat_out1, heat_out2, ... (variable, count set by :code:`num_out`) + - Heat inlets: heat_in1, heat_in2, ... (variable, count set by :code:`num_in`) + - Heat outlets: heat_out1, heat_out2, ... (variable, count set by :code:`num_out`) Mandatory Equations ------------------- diff --git a/src/tespy/components/heat/sink.py b/src/tespy/components/heat/sink.py index 8cc0e8b2..ec9d38f5 100644 --- a/src/tespy/components/heat/sink.py +++ b/src/tespy/components/heat/sink.py @@ -22,7 +22,7 @@ class HeatSink(_EnergySink): Ports ----- - Heat inlets: heat + - Heat inlets: heat Mandatory Equations ------------------- diff --git a/src/tespy/components/heat/source.py b/src/tespy/components/heat/source.py index 98eb6a12..b12965a7 100644 --- a/src/tespy/components/heat/source.py +++ b/src/tespy/components/heat/source.py @@ -22,7 +22,7 @@ class HeatSource(_EnergySource): Ports ----- - Heat outlets: heat + - Heat outlets: heat Mandatory Equations ------------------- diff --git a/src/tespy/components/heat_exchangers/base.py b/src/tespy/components/heat_exchangers/base.py index f6a7e96f..264a0d1a 100644 --- a/src/tespy/components/heat_exchangers/base.py +++ b/src/tespy/components/heat_exchangers/base.py @@ -53,9 +53,8 @@ class HeatExchanger(Component): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- @@ -100,24 +99,26 @@ class HeatExchanger(Component): Equation: :py:meth:`eff_max_func `. kA : float, dict - Heat transfer coefficient considering terminal temperature differences. - Quantity: :code:`heat_transfer_coefficient`. - Equation: :py:meth:`kA_func `. + Deprecated, use :code:`UA` instead. Quantity: + :code:`heat_transfer_coefficient`. kA_char : GroupedComponentCharacteristics - Equation for heat transfer based on kA and modification factor. - Elements: :code:`kA_char1`, :code:`kA_char2`. - Equation: :py:meth:`kA_char_func `. + Deprecated, use :code:`UA_char` instead. Elements: :code:`kA_char1`, + :code:`kA_char2`. kA_char1 : tespy.tools.characteristics.CharLine, dict - Hot side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char1` instead. kA_char2 : tespy.tools.characteristics.CharLine, dict - Cold side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char2` instead. label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -143,7 +144,7 @@ class HeatExchanger(Component): Equation: :py:meth:`energy_balance_hot_func `. td_log : float, dict - Logarithmic temperature difference. Quantity: + Deprecated, use :code:`lmtd` instead. Quantity: :code:`temperature_difference`. ttd_l : float, dict @@ -161,15 +162,37 @@ class HeatExchanger(Component): Quantity: :code:`temperature_difference`. Equation: :py:meth:`ttd_u_func `. + UA : float, dict + Heat transfer coefficient considering terminal temperature differences. + Quantity: :code:`heat_transfer_coefficient`. + Equation: :py:meth:`UA_func `. + + UA_char : GroupedComponentCharacteristics + Equation for heat transfer based on UA and modification factor. + Elements: :code:`UA_char1`, :code:`UA_char2`. + Equation: :py:meth:`UA_char_func `. + + UA_char1 : tespy.tools.characteristics.CharLine, dict + Hot side UA modification lookup table for offdesign. + + UA_char2 : tespy.tools.characteristics.CharLine, dict + Cold side UA modification lookup table for offdesign. + zeta1 : float, dict - Hot side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta1_d4` instead. + + zeta1_d4 : float, dict + Hot side geometry-independent friction coefficient zeta/D^4 for pressure + loss calculation. + Equation: :py:meth:`zeta_d4_func `. zeta2 : float, dict - Cold side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta2_d4` instead. + + zeta2_d4 : float, dict + Cold side geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -217,7 +240,7 @@ class HeatExchanger(Component): >>> he.set_attr( ... pr1=0.98, pr2=0.98, ttd_u=5, ... design=['pr1', 'pr2', 'ttd_u'], - ... offdesign=['zeta1', 'zeta2', 'kA_char'] + ... offdesign=['zeta1_d4', 'zeta2_d4', 'UA_char'] ... ) >>> cw_he.set_attr( ... fluid={'water': 1}, T=10, p=3, offdesign=['m'] @@ -242,6 +265,16 @@ class HeatExchanger(Component): 18.8 """ + _parameter_aliases = { + 'kA': 'UA', + 'kA_char': 'UA_char', + 'kA_char1': 'UA_char1', + 'kA_char2': 'UA_char2', + 'zeta1': 'zeta1_d4', + 'zeta2': 'zeta2_d4', + 'td_log': 'lmtd', + } + def get_parameters(self): return { 'Q': dc_cp( @@ -252,19 +285,30 @@ def get_parameters(self): description="heat transfer from hot side", calc=self._calc_Q ), - 'kA': dc_cp( + 'UA': dc_cp( min_val=0, num_eq_sets=1, - func=self.kA_func, - dependents=self.kA_dependents, - deriv=self.kA_deriv, + func=self.UA_func, + dependents=self.UA_dependents, + deriv=self.UA_deriv, quantity="heat_transfer_coefficient", description="heat transfer coefficient considering terminal temperature differences", - calc=self._calc_kA, calc_deps=['Q', 'td_log'] + calc=self._calc_UA, calc_deps=['Q', 'ttd_u', 'ttd_l'] + ), + 'kA': dc_cp( + min_val=0, is_result=True, + quantity="heat_transfer_coefficient", + description="deprecated, use :code:`UA` instead", + calc=self._calc_UA, calc_deps=['Q', 'ttd_u', 'ttd_l'] ), 'td_log': dc_cp( min_val=0, is_result=True, quantity="temperature_difference", - description="logarithmic temperature difference", - calc=self._calc_td_log, calc_deps=['ttd_u', 'ttd_l'] + description="deprecated, use :code:`lmtd` instead", + calc=self._calc_lmtd, calc_deps=['lmtd'] + ), + 'lmtd': dc_cp( + min_val=0, is_result=True, quantity="temperature_difference", + description="effective logarithmic mean temperature difference |Q|/UA", + calc=self._calc_lmtd, calc_deps=['Q', 'UA'] ), 'ttd_u': dc_cp( min_val=0, num_eq_sets=1, @@ -322,37 +366,60 @@ def get_parameters(self): description="cold side inlet to outlet absolute pressure change", calc=self._calc_dp, calc_params={'inconn': 1, 'outconn': 1} ), + 'zeta1_d4': dc_cp( + min_val=0, max_val=1e15, num_eq_sets=1, + func=self.zeta_d4_func, + dependents=self.zeta_d4_dependents, + func_params={'zeta': 'zeta1_d4'}, + description="hot side geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4 + ), 'zeta1': dc_cp( + min_val=0, is_result=True, + description="deprecated, use :code:`zeta1_d4` instead", + calc=self._calc_zeta_d4 + ), + 'zeta2_d4': dc_cp( min_val=0, max_val=1e15, num_eq_sets=1, - func=self.zeta_func, - dependents=self.zeta_dependents, - func_params={'zeta': 'zeta1'}, - description="hot side non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta + func=self.zeta_d4_func, + dependents=self.zeta_d4_dependents, + func_params={'zeta': 'zeta2_d4', 'inconn': 1, 'outconn': 1}, + description="cold side geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4, calc_params={'inconn': 1, 'outconn': 1} ), 'zeta2': dc_cp( - min_val=0, max_val=1e15, num_eq_sets=1, - func=self.zeta_func, - dependents=self.zeta_dependents, - func_params={'zeta': 'zeta2', 'inconn': 1, 'outconn': 1}, - description="cold side non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta, calc_params={'inconn': 1, 'outconn': 1} + min_val=0, is_result=True, + description="deprecated, use :code:`zeta2_d4` instead", + calc=self._calc_zeta_d4, calc_params={'inconn': 1, 'outconn': 1} + ), + 'UA_char': dc_gcc( + elements=['UA_char1', 'UA_char2'], + num_eq_sets=1, + func=self.UA_char_func, + dependents=self.UA_char_dependents, + description="equation for heat transfer based on UA and modification factor" + ), + 'UA_char1': dc_cc( + param='m', + description="hot side UA modification lookup table for offdesign" + ), + 'UA_char2': dc_cc( + param='m', + char_params={'type': 'rel', 'inconn': 1, 'outconn': 1}, + description="cold side UA modification lookup table for offdesign" ), 'kA_char': dc_gcc( elements=['kA_char1', 'kA_char2'], - num_eq_sets=1, - func=self.kA_char_func, - dependents=self.kA_char_dependents, - description="equation for heat transfer based on kA and modification factor" + description="deprecated, use :code:`UA_char` instead" ), 'kA_char1': dc_cc( param='m', - description="hot side kA modification lookup table for offdesign" + description="deprecated, use :code:`UA_char1` instead" ), 'kA_char2': dc_cc( param='m', char_params={'type': 'rel', 'inconn': 1, 'outconn': 1}, - description="cold side kA modification lookup table for offdesign" + description="deprecated, use :code:`UA_char2` instead" ), 'eff_hot': dc_cp( min_val=0, max_val=1, num_eq_sets=1, @@ -501,8 +568,13 @@ def _calc_td_log(self): return np.nan return (ttd_l - ttd_u) / math.log(ttd_l / ttd_u) - def _calc_kA(self): - return -self.Q.val_SI / self.td_log.val_SI + def _calc_UA(self): + return -self.Q.val_SI / self._calc_td_log() + + def _calc_lmtd(self): + if self.UA.val_SI == 0: + return np.nan + return abs(self.Q.val_SI) / self.UA.val_SI def _calc_eff_hot(self): try: @@ -555,7 +627,7 @@ def calculate_td_log(self): return ttd_l return (ttd_l - ttd_u) / math.log(ttd_l / ttd_u) - def kA_func(self): + def UA_func(self): r""" Calculate heat transfer from heat transfer coefficient. @@ -567,14 +639,14 @@ def kA_func(self): .. math:: 0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + - kA \cdot \frac{T_{out,1} - + UA \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}}}} """ Q = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - return Q + self.kA.val_SI * self.calculate_td_log() + return Q + self.UA.val_SI * self.calculate_td_log() - def kA_deriv(self, increment_filter, k, dependents=None): + def UA_deriv(self, increment_filter, k, dependents=None): r""" Partial derivatives of heat transfer coefficient function. @@ -587,7 +659,7 @@ def kA_deriv(self, increment_filter, k, dependents=None): Position of derivatives in Jacobian matrix (k-th equation). """ dependents = dependents["scalars"][0] - f = self.kA_func + f = self.UA_func i = self.inl[0] o = self.outl[0] if i.m.is_var: @@ -596,7 +668,7 @@ def kA_deriv(self, increment_filter, k, dependents=None): for var in dependents.difference(_get_dependents([i.m])[0]): self._partial_derivative(var, k, f, increment_filter) - def kA_dependents(self): + def UA_dependents(self): return [ self.inl[0].m, self.inl[0].p, @@ -609,7 +681,7 @@ def kA_dependents(self): self.outl[1].h, ] - def kA_char_func(self): + def UA_char_func(self): r""" Calculate heat transfer from heat transfer coefficient characteristic. @@ -621,11 +693,11 @@ def kA_char_func(self): .. math:: 0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + - kA_{design} \cdot f_{kA} \cdot \frac{T_{out,1} - + UA_{design} \cdot f_{UA} \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)} + + f_{UA} = \frac{2}{\frac{1}{f_1\left( expr_1\right)} + \frac{1}{f_2\left( expr_2\right)}} Note @@ -633,8 +705,8 @@ def kA_char_func(self): For standard functions f\ :subscript:`1` \ and f\ :subscript:`2` \ see module :ref:`tespy.data `. """ - p1 = self.kA_char1.param - p2 = self.kA_char2.param + p1 = self.UA_char1.param + p2 = self.UA_char2.param if self.local_offdesign: design_value = self._connection_offdesign[self.inl[0].label][p1] actual_value = getattr(self.inl[0], p1).val_SI @@ -644,17 +716,17 @@ def kA_char_func(self): actual_value = getattr(self.inl[1], p2).val_SI f2 = actual_value / design_value else: - f1 = self.get_char_expr(p1, **self.kA_char1.char_params) - f2 = self.get_char_expr(p2, **self.kA_char2.char_params) + f1 = self.get_char_expr(p1, **self.UA_char1.char_params) + f2 = self.get_char_expr(p2, **self.UA_char2.char_params) - fkA1 = self.kA_char1.char_func.evaluate(f1) - fkA2 = self.kA_char2.char_func.evaluate(f2) - fkA = 2 / (1 / fkA1 + 1 / fkA2) + fUA1 = self.UA_char1.char_func.evaluate(f1) + fUA2 = self.UA_char2.char_func.evaluate(f2) + fUA = 2 / (1 / fUA1 + 1 / fUA2) Q = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - return Q + self.kA.design * fkA * self.calculate_td_log() + return Q + self.UA.design * fUA * self.calculate_td_log() - def kA_char_dependents(self): + def UA_char_dependents(self): return [ self.inl[0].m, self.inl[0].p, diff --git a/src/tespy/components/heat_exchangers/condenser.py b/src/tespy/components/heat_exchangers/condenser.py index 1ecd8eaf..9cfb351a 100644 --- a/src/tespy/components/heat_exchangers/condenser.py +++ b/src/tespy/components/heat_exchangers/condenser.py @@ -41,9 +41,8 @@ class Condenser(HeatExchanger): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- @@ -88,24 +87,26 @@ class Condenser(HeatExchanger): Equation: :py:meth:`eff_max_func `. kA : float, dict - Heat transfer coefficient considering terminal temperature differences. - Quantity: :code:`heat_transfer_coefficient`. - Equation: :py:meth:`kA_func `. + Deprecated, use :code:`UA` instead. Quantity: + :code:`heat_transfer_coefficient`. kA_char : GroupedComponentCharacteristics - Equation for heat transfer based on kA and modification factor. - Elements: :code:`kA_char1`, :code:`kA_char2`. - Equation: :py:meth:`kA_char_func `. + Deprecated, use :code:`UA_char` instead. Elements: :code:`kA_char1`, + :code:`kA_char2`. kA_char1 : tespy.tools.characteristics.CharLine, dict - Hot side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char1` instead. kA_char2 : tespy.tools.characteristics.CharLine, dict - Cold side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char2` instead. label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -135,7 +136,7 @@ class Condenser(HeatExchanger): Equation: :py:meth:`subcooling_func `. td_log : float, dict - Logarithmic temperature difference. Quantity: + Deprecated, use :code:`lmtd` instead. Quantity: :code:`temperature_difference`. ttd_l : float, dict @@ -153,15 +154,37 @@ class Condenser(HeatExchanger): Quantity: :code:`temperature_difference`. Equation: :py:meth:`ttd_u_func `. + UA : float, dict + Heat transfer coefficient considering terminal temperature differences. + Quantity: :code:`heat_transfer_coefficient`. + Equation: :py:meth:`UA_func `. + + UA_char : GroupedComponentCharacteristics + Equation for heat transfer based on UA and modification factor. + Elements: :code:`UA_char1`, :code:`UA_char2`. + Equation: :py:meth:`UA_char_func `. + + UA_char1 : tespy.tools.characteristics.CharLine, dict + Hot side UA modification lookup table for offdesign. + + UA_char2 : tespy.tools.characteristics.CharLine, dict + Cold side UA modification lookup table for offdesign. + zeta1 : float, dict - Hot side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta1_d4` instead. + + zeta1_d4 : float, dict + Hot side geometry-independent friction coefficient zeta/D^4 for pressure + loss calculation. + Equation: :py:meth:`zeta_d4_func `. zeta2 : float, dict - Cold side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta2_d4` instead. + + zeta2_d4 : float, dict + Cold side geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -208,7 +231,7 @@ class Condenser(HeatExchanger): 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']) + ... offdesign=['zeta2_d4', 'UA_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']) @@ -299,7 +322,7 @@ def calculate_td_log(self): return ttd_l return (ttd_l - ttd_u) / math.log(ttd_l / ttd_u) - def kA_char_func(self): + def UA_char_func(self): r""" Calculate heat transfer from heat transfer coefficient characteristic. @@ -311,12 +334,12 @@ def kA_char_func(self): .. math:: 0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + - kA_{design} \cdot f_{kA} \cdot \frac{T_{out,1} - + UA_{design} \cdot f_{UA} \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)} + + f_{UA} = \frac{2}{\frac{1}{f_1 \left( expr_1\right)} + \frac{1}{f_2 \left( expr_2\right)}} Note @@ -324,7 +347,7 @@ def kA_char_func(self): For standard functions f\ :subscript:`1` \ and f\ :subscript:`2` \ see module :ref:`tespy.data `. """ - return super().kA_char_func() + return super().UA_char_func() def ttd_u_func(self): r""" diff --git a/src/tespy/components/heat_exchangers/desuperheater.py b/src/tespy/components/heat_exchangers/desuperheater.py index b3779839..d061c27b 100644 --- a/src/tespy/components/heat_exchangers/desuperheater.py +++ b/src/tespy/components/heat_exchangers/desuperheater.py @@ -37,9 +37,8 @@ class Desuperheater(HeatExchanger): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- @@ -85,24 +84,26 @@ class Desuperheater(HeatExchanger): Equation: :py:meth:`eff_max_func `. kA : float, dict - Heat transfer coefficient considering terminal temperature differences. - Quantity: :code:`heat_transfer_coefficient`. - Equation: :py:meth:`kA_func `. + Deprecated, use :code:`UA` instead. Quantity: + :code:`heat_transfer_coefficient`. kA_char : GroupedComponentCharacteristics - Equation for heat transfer based on kA and modification factor. - Elements: :code:`kA_char1`, :code:`kA_char2`. - Equation: :py:meth:`kA_char_func `. + Deprecated, use :code:`UA_char` instead. Elements: :code:`kA_char1`, + :code:`kA_char2`. kA_char1 : tespy.tools.characteristics.CharLine, dict - Hot side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char1` instead. kA_char2 : tespy.tools.characteristics.CharLine, dict - Cold side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char2` instead. label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -128,7 +129,7 @@ class Desuperheater(HeatExchanger): Equation: :py:meth:`energy_balance_hot_func `. td_log : float, dict - Logarithmic temperature difference. Quantity: + Deprecated, use :code:`lmtd` instead. Quantity: :code:`temperature_difference`. ttd_l : float, dict @@ -146,15 +147,37 @@ class Desuperheater(HeatExchanger): Quantity: :code:`temperature_difference`. Equation: :py:meth:`ttd_u_func `. + UA : float, dict + Heat transfer coefficient considering terminal temperature differences. + Quantity: :code:`heat_transfer_coefficient`. + Equation: :py:meth:`UA_func `. + + UA_char : GroupedComponentCharacteristics + Equation for heat transfer based on UA and modification factor. + Elements: :code:`UA_char1`, :code:`UA_char2`. + Equation: :py:meth:`UA_char_func `. + + UA_char1 : tespy.tools.characteristics.CharLine, dict + Hot side UA modification lookup table for offdesign. + + UA_char2 : tespy.tools.characteristics.CharLine, dict + Cold side UA modification lookup table for offdesign. + zeta1 : float, dict - Hot side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta1_d4` instead. + + zeta1_d4 : float, dict + Hot side geometry-independent friction coefficient zeta/D^4 for pressure + loss calculation. + Equation: :py:meth:`zeta_d4_func `. zeta2 : float, dict - Cold side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta2_d4` instead. + + zeta2_d4 : float, dict + Cold side geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -197,7 +220,7 @@ class Desuperheater(HeatExchanger): >>> desu.set_attr( ... pr1=0.99, pr2=0.98, design=['pr1', 'pr2'], - ... offdesign=['zeta1', 'zeta2', 'kA_char'] + ... offdesign=['zeta1_d4', 'zeta2_d4', 'UA_char'] ... ) >>> cw_de.set_attr(fluid={'water': 1}, T=15, v=1, design=['v']) >>> de_cw.set_attr(p=1) diff --git a/src/tespy/components/heat_exchangers/movingboundary.py b/src/tespy/components/heat_exchangers/movingboundary.py index 01828e5d..0a4e0ce0 100644 --- a/src/tespy/components/heat_exchangers/movingboundary.py +++ b/src/tespy/components/heat_exchangers/movingboundary.py @@ -40,9 +40,8 @@ class MovingBoundaryHeatExchanger(SectionedHeatExchanger): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- @@ -95,24 +94,26 @@ class MovingBoundaryHeatExchanger(SectionedHeatExchanger): Equation: :py:meth:`eff_max_func `. kA : float, dict - Heat transfer coefficient considering terminal temperature differences. - Quantity: :code:`heat_transfer_coefficient`. - Equation: :py:meth:`kA_func `. + Deprecated, use :code:`UA` instead. Quantity: + :code:`heat_transfer_coefficient`. kA_char : GroupedComponentCharacteristics - Equation for heat transfer based on kA and modification factor. - Elements: :code:`kA_char1`, :code:`kA_char2`. - Equation: :py:meth:`kA_char_func `. + Deprecated, use :code:`UA_char` instead. Elements: :code:`kA_char1`, + :code:`kA_char2`. kA_char1 : tespy.tools.characteristics.CharLine, dict - Hot side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char1` instead. kA_char2 : tespy.tools.characteristics.CharLine, dict - Cold side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char2` instead. label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -149,7 +150,7 @@ class MovingBoundaryHeatExchanger(SectionedHeatExchanger): Side on which the refrigerant is flowing (0: hot, 1:cold). td_log : float, dict - Logarithmic temperature difference. Quantity: + Deprecated, use :code:`lmtd` instead. Quantity: :code:`temperature_difference`. td_pinch : float, dict @@ -183,18 +184,30 @@ class MovingBoundaryHeatExchanger(SectionedHeatExchanger): UA_char : GroupedComponentCharacteristics Equation for sectioned UA modification based on characteristic lines. - Elements: :code:`kA_char1`, :code:`kA_char2`. + Elements: :code:`UA_char1`, :code:`UA_char2`. Equation: :py:meth:`UA_char_func `. + UA_char1 : tespy.tools.characteristics.CharLine, dict + Hot side UA modification lookup table for offdesign. + + UA_char2 : tespy.tools.characteristics.CharLine, dict + Cold side UA modification lookup table for offdesign. + zeta1 : float, dict - Hot side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta1_d4` instead. + + zeta1_d4 : float, dict + Hot side geometry-independent friction coefficient zeta/D^4 for pressure + loss calculation. + Equation: :py:meth:`zeta_d4_func `. zeta2 : float, dict - Cold side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta2_d4` instead. + + zeta2_d4 : float, dict + Cold side geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- diff --git a/src/tespy/components/heat_exchangers/parabolic_trough.py b/src/tespy/components/heat_exchangers/parabolic_trough.py index b6122352..b3db1c06 100644 --- a/src/tespy/components/heat_exchangers/parabolic_trough.py +++ b/src/tespy/components/heat_exchangers/parabolic_trough.py @@ -35,17 +35,12 @@ class ParabolicTrough(SimpleHeatExchanger): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: heat - - Power outlets: heat - - Heat inlets: heat - - Heat outlets: heat + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: heat + - Power outlets: heat + - Heat inlets: heat + - Heat outlets: heat Mandatory Equations ------------------- @@ -92,7 +87,7 @@ class ParabolicTrough(SimpleHeatExchanger): Path to the components design case. dissipative : bool - + Description missing. doc : float, dict Degree of cleanliness. Quantity: :code:`ratio`. @@ -151,7 +146,7 @@ class ParabolicTrough(SimpleHeatExchanger): List containing offdesign parameters (stated as String). power_connector_location : str - + Description missing. pr : float, dict Outlet to inlet pressure ratio. Quantity: :code:`ratio`. @@ -171,8 +166,12 @@ class ParabolicTrough(SimpleHeatExchanger): Ambient temperature. Quantity: :code:`temperature`. zeta : float, dict - Non-dimensional friction coefficient for pressure loss calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta_d4` instead. + + zeta_d4 : float, dict + Geometry-independent friction coefficient zeta/D^4 for pressure loss + calculation. + Equation: :py:meth:`zeta_d4_func `. Example ------- @@ -247,8 +246,9 @@ class ParabolicTrough(SimpleHeatExchanger): def get_parameters(self): data = super().get_parameters() - for k in ["kA_group", "kA_char_group", "kA", "kA_char"]: - del data[k] + for k in ["UA_group", "UA_char_group", "UA", "UA_char", + "kA_group", "kA_char_group", "kA", "kA_char", "lmtd"]: + data.pop(k, None) data.update({ 'E': dc_cp( diff --git a/src/tespy/components/heat_exchangers/parallel.py b/src/tespy/components/heat_exchangers/parallel.py index 194a0664..ca8884f4 100644 --- a/src/tespy/components/heat_exchangers/parallel.py +++ b/src/tespy/components/heat_exchangers/parallel.py @@ -33,9 +33,8 @@ class ParallelFlowHeatExchanger(HeatExchanger): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- @@ -67,24 +66,26 @@ class ParallelFlowHeatExchanger(HeatExchanger): Equation: :py:meth:`dp_structure_matrix `. kA : float, dict - Heat transfer coefficient considering terminal temperature differences. - Quantity: :code:`heat_transfer_coefficient`. - Equation: :py:meth:`kA_func `. + Deprecated, use :code:`UA` instead. Quantity: + :code:`heat_transfer_coefficient`. kA_char : GroupedComponentCharacteristics - Equation for heat transfer based on kA and modification factor. - Elements: :code:`kA_char1`, :code:`kA_char2`. - Equation: :py:meth:`kA_char_func `. + Deprecated, use :code:`UA_char` instead. Elements: :code:`kA_char1`, + :code:`kA_char2`. kA_char1 : tespy.tools.characteristics.CharLine, dict - Hot side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char1` instead. kA_char2 : tespy.tools.characteristics.CharLine, dict - Cold side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char2` instead. label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -110,7 +111,7 @@ class ParallelFlowHeatExchanger(HeatExchanger): Equation: :py:meth:`energy_balance_hot_func `. td_log : float, dict - Logarithmic temperature difference. Quantity: + Deprecated, use :code:`lmtd` instead. Quantity: :code:`temperature_difference`. ttd_l : float, dict @@ -123,15 +124,37 @@ class ParallelFlowHeatExchanger(HeatExchanger): Quantity: :code:`temperature_difference`. Equation: :py:meth:`ttd_u_func `. + UA : float, dict + Heat transfer coefficient considering terminal temperature differences. + Quantity: :code:`heat_transfer_coefficient`. + Equation: :py:meth:`UA_func `. + + UA_char : GroupedComponentCharacteristics + Equation for heat transfer based on UA and modification factor. + Elements: :code:`UA_char1`, :code:`UA_char2`. + Equation: :py:meth:`UA_char_func `. + + UA_char1 : tespy.tools.characteristics.CharLine, dict + Hot side UA modification lookup table for offdesign. + + UA_char2 : tespy.tools.characteristics.CharLine, dict + Cold side UA modification lookup table for offdesign. + zeta1 : float, dict - Hot side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta1_d4` instead. + + zeta1_d4 : float, dict + Hot side geometry-independent friction coefficient zeta/D^4 for pressure + loss calculation. + Equation: :py:meth:`zeta_d4_func `. zeta2 : float, dict - Cold side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta2_d4` instead. + + zeta2_d4 : float, dict + Cold side geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -204,13 +227,13 @@ class ParallelFlowHeatExchanger(HeatExchanger): 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 :code:`kA` + the heat transfer coefficient is constant. First we just fix the :code:`UA` value instead of the final pinch and then resolve again. - >>> he.set_attr(design=["ttd_u"], offdesign=["kA"]) + >>> he.set_attr(design=["ttd_u"], offdesign=["UA"]) >>> design_state = nw.save(as_dict=True) >>> nw.solve("offdesign", design_path=design_state) - >>> round(he.kA.val_SI / he.kA.design, 1) + >>> round(he.UA.val_SI / he.UA.design, 1) 1.0 Now, let's see what happens under different operating conditions. First @@ -270,4 +293,3 @@ def calculate_td_log(self): if round(ttd_u, 6) == round(ttd_l, 6): return ttd_l return (ttd_l - ttd_u) / math.log(ttd_l / ttd_u) - diff --git a/src/tespy/components/heat_exchangers/sectioned.py b/src/tespy/components/heat_exchangers/sectioned.py index 2251dc65..b815086a 100644 --- a/src/tespy/components/heat_exchangers/sectioned.py +++ b/src/tespy/components/heat_exchangers/sectioned.py @@ -49,9 +49,8 @@ class SectionedHeatExchanger(HeatExchanger): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- @@ -104,24 +103,26 @@ class SectionedHeatExchanger(HeatExchanger): Equation: :py:meth:`eff_max_func `. kA : float, dict - Heat transfer coefficient considering terminal temperature differences. - Quantity: :code:`heat_transfer_coefficient`. - Equation: :py:meth:`kA_func `. + Deprecated, use :code:`UA` instead. Quantity: + :code:`heat_transfer_coefficient`. kA_char : GroupedComponentCharacteristics - Equation for heat transfer based on kA and modification factor. - Elements: :code:`kA_char1`, :code:`kA_char2`. - Equation: :py:meth:`kA_char_func `. + Deprecated, use :code:`UA_char` instead. Elements: :code:`kA_char1`, + :code:`kA_char2`. kA_char1 : tespy.tools.characteristics.CharLine, dict - Hot side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char1` instead. kA_char2 : tespy.tools.characteristics.CharLine, dict - Cold side kA modification lookup table for offdesign. + Deprecated, use :code:`UA_char2` instead. label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -161,7 +162,7 @@ class SectionedHeatExchanger(HeatExchanger): Side on which the refrigerant is flowing (0: hot, 1:cold). td_log : float, dict - Logarithmic temperature difference. Quantity: + Deprecated, use :code:`lmtd` instead. Quantity: :code:`temperature_difference`. td_pinch : float, dict @@ -195,18 +196,30 @@ class SectionedHeatExchanger(HeatExchanger): UA_char : GroupedComponentCharacteristics Equation for sectioned UA modification based on characteristic lines. - Elements: :code:`kA_char1`, :code:`kA_char2`. + Elements: :code:`UA_char1`, :code:`UA_char2`. Equation: :py:meth:`UA_char_func `. + UA_char1 : tespy.tools.characteristics.CharLine, dict + Hot side UA modification lookup table for offdesign. + + UA_char2 : tespy.tools.characteristics.CharLine, dict + Cold side UA modification lookup table for offdesign. + zeta1 : float, dict - Hot side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta1_d4` instead. + + zeta1_d4 : float, dict + Hot side geometry-independent friction coefficient zeta/D^4 for pressure + loss calculation. + Equation: :py:meth:`zeta_d4_func `. zeta2 : float, dict - Cold side non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta2_d4` instead. + + zeta2_d4 : float, dict + Cold side geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -443,21 +456,21 @@ class SectionedHeatExchanger(HeatExchanger): >>> round(c2.T.val, 1) 30.0 - **Stage 2: Offdesign analysis with kA_char characteristic scaling** + **Stage 2: Offdesign analysis with UA_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 + >>> UA_char = load_default_char( + ... "HeatExchanger", "UA_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, + ... UA_char1=UA_char, + ... UA_char2=UA_char, ... design=['td_pinch'], ... offdesign=['UA_char'] ... ) @@ -492,15 +505,21 @@ class SectionedHeatExchanger(HeatExchanger): >>> round(hx.td_pinch.val, 1) 15.3 - The :code:`kA_char` parameter allows automatic part-load scaling of UA, + The :code:`UA_char` parameter allows automatic part-load scaling of UA, following the same principle as the standard HeatExchanger component - (:py:class:`tespy.components.heat_exchangers.base.HeatExchanger`). The - difference to the :code:`UA_char` usage is that :code:`kA_char` uses a - characteristic line lookup table to define the scaling relationship. + (:py:class:`tespy.components.heat_exchangers.base.HeatExchanger`). :code:`UA_cecchinato` requires the specification of Reynolds number exponents, area ratio and alpha ratio of the involved fluids. """ + _parameter_aliases = { + 'kA_char': 'UA_char', + 'kA_char1': 'UA_char1', + 'kA_char2': 'UA_char2', + 'zeta1': 'zeta1_d4', + 'zeta2': 'zeta2_d4', + } + def get_parameters(self): params = super().get_parameters() params.update({ @@ -515,13 +534,13 @@ def get_parameters(self): quantity="heat_transfer_coefficient", description="sum of UA values of all sections of heat exchanger" ), - 'UA_char': dc_gcc( - elements=['kA_char1', 'kA_char2'], - num_eq_sets=1, - func=self.UA_char_func, - dependents=self.UA_dependents, - description="equation for sectioned UA modification based on characteristic lines" - ), + 'UA_char': dc_gcc( + elements=['UA_char1', 'UA_char2'], + num_eq_sets=1, + func=self.UA_char_func, + dependents=self.UA_dependents, + description="equation for sectioned UA modification based on characteristic lines" + ), 'refrigerant_index': dc_simple( val=0, dtype="int", description="side on which the refrigerant is flowing (0: hot, 1:cold)" @@ -783,7 +802,7 @@ def UA_func(self, **kwargs): def UA_char_func(self): r""" Calculate offdesign UA from characteristic lines analogous to standard - heat exchanger kA_char, but for the sectioned heat exchanger. + heat exchanger UA_char, but for the sectioned heat exchanger. Returns ------- @@ -795,14 +814,14 @@ def UA_char_func(self): 0 = UA_\text{design} * f_\text{UA} - \sum\left(UA_{i}\right) """ - p1 = self.kA_char1.param - p2 = self.kA_char2.param + p1 = self.UA_char1.param + p2 = self.UA_char2.param - f1 = self.get_char_expr(p1, **self.kA_char1.char_params) - f2 = self.get_char_expr(p2, **self.kA_char2.char_params) + f1 = self.get_char_expr(p1, **self.UA_char1.char_params) + f2 = self.get_char_expr(p2, **self.UA_char2.char_params) - fUA1 = self.kA_char1.char_func.evaluate(f1) - fUA2 = self.kA_char2.char_func.evaluate(f2) + fUA1 = self.UA_char1.char_func.evaluate(f1) + fUA2 = self.UA_char2.char_func.evaluate(f2) fUA = 2 / (1 / fUA1 + 1 / fUA2) @@ -949,6 +968,8 @@ def calc_parameters(self): sections = self.calc_sections() self.UA.val_SI = self.calc_UA(sections) self.td_pinch.val_SI = self.calc_td_pinch(sections[1], sections[2]) + self.lmtd.val_SI = abs(self.Q.val_SI) / self.UA.val_SI + self.td_log.val_SI = self.lmtd.val_SI def identify_step_at_saturation(x, p_in, h_in, delta_p, delta_h, Q, fluid_data): diff --git a/src/tespy/components/heat_exchangers/simple.py b/src/tespy/components/heat_exchangers/simple.py index 4c30a58e..21bf694b 100644 --- a/src/tespy/components/heat_exchangers/simple.py +++ b/src/tespy/components/heat_exchangers/simple.py @@ -45,17 +45,12 @@ class SimpleHeatExchanger(Component): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: heat - - Power outlets: heat - - Heat inlets: heat - - Heat outlets: heat + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: heat + - Power outlets: heat + - Heat inlets: heat + - Heat outlets: heat Mandatory Equations ------------------- @@ -89,7 +84,7 @@ class SimpleHeatExchanger(Component): Path to the components design case. dissipative : bool - + Description missing. dp : float, dict Inlet to outlet absolute pressure change. Quantity: @@ -102,22 +97,20 @@ class SimpleHeatExchanger(Component): Equation: :py:meth:`hazen_williams_func `. kA : float, dict, :code:`"var"` - Heat transfer coefficient considering ambient temperature. Quantity: + Deprecated, use :code:`UA` instead. Quantity: :code:`heat_transfer_coefficient`. Can be set as a system variable by passing :code:`"var"` as its value. kA_char : tespy.tools.characteristics.CharLine, dict - Heat transfer coefficient lookup table for offdesign. + Deprecated, use :code:`UA_char` instead. kA_char_group : GroupedComponentProperties - Heat transfer from design heat transfer coefficient, modifier lookup - table and ambient temperature. Elements: :code:`kA_char`, :code:`Tamb`. - Equation: :py:meth:`kA_char_group_func `. + Deprecated, use :code:`UA_char_group` instead. Elements: + :code:`kA_char`, :code:`Tamb`. kA_group : GroupedComponentProperties - Equation for heat transfer based on ambient temperature and heat - transfer coefficient. Elements: :code:`kA`, :code:`Tamb`. - Equation: :py:meth:`kA_group_func `. + Deprecated, use :code:`UA_group` instead. Elements: :code:`kA`, + :code:`Tamb`. ks : float, dict, :code:`"var"` Roughness of wall material. Quantity: :code:`length`. Can be set as a @@ -134,6 +127,10 @@ class SimpleHeatExchanger(Component): label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -144,7 +141,7 @@ class SimpleHeatExchanger(Component): List containing offdesign parameters (stated as String). power_connector_location : str - + Description missing. pr : float, dict Outlet to inlet pressure ratio. Quantity: :code:`ratio`. @@ -160,9 +157,31 @@ class SimpleHeatExchanger(Component): Tamb : float, dict Ambient temperature. Quantity: :code:`temperature`. + UA : float, dict, :code:`"var"` + Heat transfer coefficient considering ambient temperature. Quantity: + :code:`heat_transfer_coefficient`. Can be set as a system variable by + passing :code:`"var"` as its value. + + UA_char : tespy.tools.characteristics.CharLine, dict + Heat transfer coefficient lookup table for offdesign. + + UA_char_group : GroupedComponentProperties + Heat transfer from design heat transfer coefficient, modifier lookup + table and ambient temperature. Elements: :code:`UA_char`, :code:`Tamb`. + Equation: :py:meth:`UA_char_group_func `. + + UA_group : GroupedComponentProperties + Equation for heat transfer based on ambient temperature and heat + transfer coefficient. Elements: :code:`UA`, :code:`Tamb`. + Equation: :py:meth:`UA_group_func `. + zeta : float, dict - Non-dimensional friction coefficient for pressure loss calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta_d4` instead. + + zeta_d4 : float, dict + Geometry-independent friction coefficient zeta/D^4 for pressure loss + calculation. + Equation: :py:meth:`zeta_d4_func `. Example ------- @@ -185,7 +204,7 @@ class SimpleHeatExchanger(Component): >>> si1 = Sink('sink 1') >>> heat_sink = SimpleHeatExchanger('heat sink') >>> heat_sink.set_attr(Tamb=10, pr=0.95, design=['pr'], - ... offdesign=['zeta', 'kA_char']) + ... offdesign=['zeta_d4', 'UA_char']) >>> inc = Connection(so1, 'out1', heat_sink, 'in1') >>> outg = Connection(heat_sink, 'out1', si1, 'in1') >>> nw.add_conns(inc, outg) @@ -241,6 +260,14 @@ class SimpleHeatExchanger(Component): True """ + _parameter_aliases = { + 'kA': 'UA', + 'kA_char': 'UA_char', + 'kA_group': 'UA_group', + 'kA_char_group': 'UA_char_group', + 'zeta': 'zeta_d4', + } + def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() if self.power_inl + self.power_outl + self.heat_inl + self.heat_outl: @@ -266,7 +293,7 @@ def set_attr(self, **kwargs): def _calc_Q(self): return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - def _calc_kA(self): + def _calc_UA(self): if not self.Tamb.is_set: return np.nan ttd_1 = self.inl[0].T.val_SI - self.Tamb.val_SI @@ -275,6 +302,11 @@ def _calc_kA(self): return np.nan return abs(self.Q.val_SI / self._calculate_td_log()) + def _calc_lmtd(self): + if self.UA.val_SI == 0: + return np.nan + return abs(self.Q.val_SI) / self.UA.val_SI + def get_parameters(self): return { 'power_connector_location': dc_simple(dtype="str"), @@ -302,13 +334,18 @@ def get_parameters(self): description="inlet to outlet absolute pressure change", calc=self._calc_dp ), - 'zeta': dc_cp( + 'zeta_d4': dc_cp( min_val=0, max_val=1e15, num_eq_sets=1, - func=self.zeta_func, - dependents=self.zeta_dependents, - func_params={'zeta': 'zeta'}, - description="non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta + func=self.zeta_d4_func, + dependents=self.zeta_d4_dependents, + func_params={'zeta': 'zeta_d4'}, + description="geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4 + ), + 'zeta': dc_cp( + min_val=0, is_result=True, + description="deprecated, use :code:`zeta_d4` instead", + calc=self._calc_zeta_d4 ), 'D': dc_cp( min_val=1e-2, max_val=2, d=1e-5, quantity="length", @@ -330,15 +367,30 @@ def get_parameters(self): description="Hazen-Williams roughness", _allows_var=True ), - 'kA': dc_cp( + 'UA': dc_cp( min_val=0, quantity="heat_transfer_coefficient", description="heat transfer coefficient considering ambient temperature", _allows_var=True, - calc=self._calc_kA, calc_deps=['Q'] + calc=self._calc_UA, calc_deps=['Q'] + ), + 'kA': dc_cp( + min_val=0, quantity="heat_transfer_coefficient", + description="deprecated, use :code:`UA` instead", + _allows_var=True, + calc=self._calc_UA, calc_deps=['Q'] + ), + 'lmtd': dc_cp( + min_val=0, is_result=True, quantity="temperature_difference", + description="effective logarithmic mean temperature difference |Q|/UA", + calc=self._calc_lmtd, calc_deps=['Q', 'UA'] + ), + 'UA_char': dc_cc( + param='m', + description="heat transfer coefficient lookup table for offdesign", ), 'kA_char': dc_cc( param='m', - description="heat transfer coefficient lookup table for offdesign" + description="deprecated, use :code:`UA_char` instead" ), 'Tamb': dc_cp( quantity="temperature", @@ -357,17 +409,25 @@ def get_parameters(self): dependents=self.hazen_williams_dependents, description="Hazen-Williams equation for pressure loss" ), - 'kA_group': dc_gcp( - elements=['kA', 'Tamb'], num_eq_sets=1, - func=self.kA_group_func, - dependents=self.kA_group_dependents, + 'UA_group': dc_gcp( + elements=['UA', 'Tamb'], num_eq_sets=1, + func=self.UA_group_func, + dependents=self.UA_group_dependents, description="equation for heat transfer based on ambient temperature and heat transfer coefficient" ), - 'kA_char_group': dc_gcp( - elements=['kA_char', 'Tamb'], num_eq_sets=1, - func=self.kA_char_group_func, - dependents=self.kA_char_group_dependents, + 'kA_group': dc_gcp( + elements=['kA', 'Tamb'], + description="deprecated, use :code:`UA_group` instead" + ), + 'UA_char_group': dc_gcp( + elements=['UA_char', 'Tamb'], num_eq_sets=1, + func=self.UA_char_group_func, + dependents=self.UA_char_group_dependents, description="heat transfer from design heat transfer coefficient, modifier lookup table and ambient temperature" + ), + 'kA_char_group': dc_gcp( + elements=['kA_char', 'Tamb'], + description="deprecated, use :code:`UA_char_group` instead" ) } @@ -649,7 +709,7 @@ def _calculate_td_log(self): return td_log - def kA_group_func(self): + def UA_group_func(self): r""" Calculate heat transfer from heat transfer coefficient. @@ -661,17 +721,7 @@ def kA_group_func(self): .. math:: 0 = \dot{m}_{in} \cdot \left( h_{out} - h_{in}\right) + - kA \cdot \Delta T_{log} - - \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} - - T_{amb}: \text{ambient temperature} + UA \cdot \Delta T_{log} """ i = self.inl[0] o = self.outl[0] @@ -679,25 +729,20 @@ def kA_group_func(self): ttd_1 = i.calc_T() - self.Tamb.val_SI ttd_2 = o.calc_T() - self.Tamb.val_SI if ttd_1 * ttd_2 <= 0: - # Outlet has crossed ambient: td_log undefined (log of negative). - # Replace with ttd_2 directly: signs ensure the residual is never - # zero (Q and kA·ttd_2 have the same sign when invalid), and - # continuity holds because td_log -> 0 as ttd_2 -> 0 from the valid - # side, so both branches give Q at the boundary. - return Q + self.kA.val_SI * ttd_2 - return Q + self.kA.val_SI * self._calculate_td_log() - - def kA_group_dependents(self): + return Q + self.UA.val_SI * ttd_2 + return Q + self.UA.val_SI * self._calculate_td_log() + + def UA_group_dependents(self): return [ self.inl[0].m, self.inl[0].p, self.inl[0].h, self.outl[0].p, self.outl[0].h, - self.kA + self.UA ] - def kA_char_group_func(self): + def UA_char_group_func(self): r""" Calculate heat transfer from heat transfer coefficient characteristic. @@ -709,40 +754,23 @@ def kA_char_group_func(self): .. math:: 0 = \dot{m}_{in} \cdot \left( h_{out} - h_{in}\right) + - kA_{design} \cdot f_{kA} \cdot \Delta T_{log} - - \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} - - f_{kA} = \frac{2}{1 + \frac{1}{f\left( expr\right)}} - - T_{amb}: \text{ambient temperature} - - Note - ---- - For standard function of f\ :subscript:`kA` \ see module - :ref:`tespy.data `. + UA_{design} \cdot f_{UA} \cdot \Delta T_{log} """ i = self.inl[0] o = self.outl[0] - p = self.kA_char.param + p = self.UA_char.param - expr = self.get_char_expr(p, **self.kA_char.char_params) - fkA = 2 / (1 + 1 / self.kA_char.char_func.evaluate(expr)) + expr = self.get_char_expr(p, **self.UA_char.char_params) + fkA = 2 / (1 + 1 / self.UA_char.char_func.evaluate(expr)) Q = i.m.val_SI * (o.h.val_SI - i.h.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: - return Q + self.kA.design * fkA * ttd_2 - return Q + self.kA.design * fkA * self._calculate_td_log() + return Q + self.UA.design * fkA * ttd_2 + return Q + self.UA.design * fkA * self._calculate_td_log() - def kA_char_group_dependents(self): + def UA_char_group_dependents(self): return [ self.inl[0].m, self.inl[0].p, @@ -752,7 +780,7 @@ def kA_char_group_dependents(self): ] def convergence_check(self): - if self.kA_group.is_set: + if self.UA_group.is_set: i = self.inl[0] o = self.outl[0] T_in = i.calc_T() @@ -858,9 +886,11 @@ def initialise_target(self, c, key): def calc_parameters(self): r"""Postprocessing parameter calculation.""" super().calc_parameters() - if "kA" not in self.parameters: + if "UA" not in self.parameters: return + self.UA.is_result = self.Tamb.is_set self.kA.is_result = self.Tamb.is_set + self.lmtd.is_result = self.Tamb.is_set def entropy_balance(self): r""" diff --git a/src/tespy/components/heat_exchangers/solar_collector.py b/src/tespy/components/heat_exchangers/solar_collector.py index 57f4b46a..cdde3b3c 100644 --- a/src/tespy/components/heat_exchangers/solar_collector.py +++ b/src/tespy/components/heat_exchangers/solar_collector.py @@ -35,17 +35,12 @@ class SolarCollector(SimpleHeatExchanger): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: heat - - Power outlets: heat - - Heat inlets: heat - - Heat outlets: heat + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: heat + - Power outlets: heat + - Heat inlets: heat + - Heat outlets: heat Mandatory Equations ------------------- @@ -83,7 +78,7 @@ class SolarCollector(SimpleHeatExchanger): Path to the components design case. dissipative : bool - + Description missing. dp : float, dict Inlet to outlet absolute pressure change. Quantity: @@ -139,7 +134,7 @@ class SolarCollector(SimpleHeatExchanger): List containing offdesign parameters (stated as String). power_connector_location : str - + Description missing. pr : float, dict Outlet to inlet pressure ratio. Quantity: :code:`ratio`. @@ -159,8 +154,12 @@ class SolarCollector(SimpleHeatExchanger): Ambient air temperature. Quantity: :code:`temperature`. zeta : float, dict - Non-dimensional friction coefficient for pressure loss calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta_d4` instead. + + zeta_d4 : float, dict + Geometry-independent friction coefficient zeta/D^4 for pressure loss + calculation. + Equation: :py:meth:`zeta_d4_func `. Example ------- @@ -181,7 +180,7 @@ class SolarCollector(SimpleHeatExchanger): >>> so = Source('source') >>> si = Sink('sink') >>> sc = SolarCollector('solar collector') - >>> sc.set_attr(pr=0.95, Q=1e4, design=['pr', 'Q'], offdesign=['zeta'], + >>> sc.set_attr(pr=0.95, Q=1e4, design=['pr', 'Q'], offdesign=['zeta_d4'], ... 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') @@ -210,8 +209,9 @@ class SolarCollector(SimpleHeatExchanger): def get_parameters(self): data = super().get_parameters() - for k in ["kA_group", "kA_char_group", "kA", "kA_char"]: - del data[k] + for k in ["UA_group", "UA_char_group", "UA", "UA_char", + "kA_group", "kA_char_group", "kA", "kA_char", "lmtd"]: + data.pop(k, None) data.update({ 'E': dc_cp( diff --git a/src/tespy/components/nodes/droplet_separator.py b/src/tespy/components/nodes/droplet_separator.py index 3efec237..f35c50c0 100644 --- a/src/tespy/components/nodes/droplet_separator.py +++ b/src/tespy/components/nodes/droplet_separator.py @@ -39,9 +39,8 @@ class DropletSeparator(NodeBase): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1, out2 + - Fluid inlets: in1 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- diff --git a/src/tespy/components/nodes/drum.py b/src/tespy/components/nodes/drum.py index cc44dd57..b51c0a27 100644 --- a/src/tespy/components/nodes/drum.py +++ b/src/tespy/components/nodes/drum.py @@ -36,9 +36,8 @@ class Drum(DropletSeparator): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2 + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2 Mandatory Equations ------------------- @@ -132,11 +131,12 @@ class Drum(DropletSeparator): transferred. State of ammonia at the inlet is at -5 °C and 5 bar. From this design it is possible to calculate offdesign performance at 75 % part load. - >>> char1 = ldc('HeatExchanger', 'kA_char1', 'DEFAULT', CharLine) - >>> char2 = ldc('HeatExchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) - >>> ev.set_attr(pr1=0.999, pr2=0.99, ttd_l=5, kA_char1=char1, - ... kA_char2=char2, design=['pr1', 'ttd_l'], - ... offdesign=['zeta1', 'kA_char'] + >>> char1 = ldc('HeatExchanger', 'UA_char1', 'DEFAULT', CharLine) + >>> char2 = ldc('HeatExchanger', 'UA_char2', 'EVAPORATING FLUID', CharLine) + >>> ev.set_attr( + ... pr1=0.999, pr2=0.99, ttd_l=5, UA_char1=char1, + ... UA_char2=char2, design=['pr1', 'ttd_l'], + ... offdesign=['zeta1_d4', 'UA_char'] ... ) >>> ev.set_attr(Q=-1e6) >>> erp.set_attr(eta_s=0.8) diff --git a/src/tespy/components/nodes/merge.py b/src/tespy/components/nodes/merge.py index ebb35e18..c7ab8645 100644 --- a/src/tespy/components/nodes/merge.py +++ b/src/tespy/components/nodes/merge.py @@ -37,9 +37,8 @@ class Merge(NodeBase): Ports ----- - Fluid inlets: in1, in2, ... (variable, count set by :code:`num_in`) - - Fluid outlets: out1 + - Fluid inlets: in1, in2, ... (variable, count set by :code:`num_in`) + - Fluid outlets: out1 Mandatory Equations ------------------- diff --git a/src/tespy/components/nodes/node.py b/src/tespy/components/nodes/node.py index c34ba0e1..5abd16c7 100644 --- a/src/tespy/components/nodes/node.py +++ b/src/tespy/components/nodes/node.py @@ -36,9 +36,8 @@ class Node(Splitter, Merge): Ports ----- - Fluid inlets: in1, in2, ... (variable, count set by :code:`num_in`) - - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_out`) + - Fluid inlets: in1, in2, ... (variable, count set by :code:`num_in`) + - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_out`) Mandatory Equations ------------------- diff --git a/src/tespy/components/nodes/separator.py b/src/tespy/components/nodes/separator.py index 04082d8f..dbd4be7e 100644 --- a/src/tespy/components/nodes/separator.py +++ b/src/tespy/components/nodes/separator.py @@ -26,9 +26,8 @@ class Separator(NodeBase): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_out`) + - Fluid inlets: in1 + - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_out`) Mandatory Equations ------------------- diff --git a/src/tespy/components/nodes/splitter.py b/src/tespy/components/nodes/splitter.py index 07c8a2e2..c653840c 100644 --- a/src/tespy/components/nodes/splitter.py +++ b/src/tespy/components/nodes/splitter.py @@ -34,9 +34,8 @@ class Splitter(NodeBase): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_out`) + - Fluid inlets: in1 + - Fluid outlets: out1, out2, ... (variable, count set by :code:`num_out`) Mandatory Equations ------------------- diff --git a/src/tespy/components/piping/pipe.py b/src/tespy/components/piping/pipe.py index f5f2bf74..8f4808a0 100644 --- a/src/tespy/components/piping/pipe.py +++ b/src/tespy/components/piping/pipe.py @@ -43,17 +43,12 @@ class Pipe(SimpleHeatExchanger): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: heat - - Power outlets: heat - - Heat inlets: heat - - Heat outlets: heat + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: heat + - Power outlets: heat + - Heat inlets: heat + - Heat outlets: heat Mandatory Equations ------------------- @@ -87,7 +82,7 @@ class Pipe(SimpleHeatExchanger): Path to the components design case. dissipative : bool - + Description missing. dp : float, dict Inlet to outlet absolute pressure change. Quantity: @@ -95,7 +90,7 @@ class Pipe(SimpleHeatExchanger): Equation: :py:meth:`dp_structure_matrix `. environment_media : str - + Description missing. flow_speed : float, dict Flow speed at inlet of pipe. Quantity: :code:`speed`. @@ -118,22 +113,20 @@ class Pipe(SimpleHeatExchanger): Thickness of pipe insulation. Quantity: :code:`length`. kA : float, dict, :code:`"var"` - Heat transfer coefficient considering ambient temperature. Quantity: + Deprecated, use :code:`UA` instead. Quantity: :code:`heat_transfer_coefficient`. Can be set as a system variable by passing :code:`"var"` as its value. kA_char : tespy.tools.characteristics.CharLine, dict - Heat transfer coefficient lookup table for offdesign. + Deprecated, use :code:`UA_char` instead. kA_char_group : GroupedComponentProperties - Heat transfer from design heat transfer coefficient, modifier lookup - table and ambient temperature. Elements: :code:`kA_char`, :code:`Tamb`. - Equation: :py:meth:`kA_char_group_func `. + Deprecated, use :code:`UA_char_group` instead. Elements: + :code:`kA_char`, :code:`Tamb`. kA_group : GroupedComponentProperties - Equation for heat transfer based on ambient temperature and heat - transfer coefficient. Elements: :code:`kA`, :code:`Tamb`. - Equation: :py:meth:`kA_group_func `. + Deprecated, use :code:`UA_group` instead. Elements: :code:`kA`, + :code:`Tamb`. ks : float, dict, :code:`"var"` Roughness of wall material. Quantity: :code:`length`. Can be set as a @@ -150,6 +143,10 @@ class Pipe(SimpleHeatExchanger): label : str The label of the component. + lmtd : float, dict + Effective logarithmic mean temperature difference |Q|/UA. Quantity: + :code:`temperature_difference`. + local_design : bool Treat this component in design mode in an offdesign calculation. @@ -157,7 +154,7 @@ class Pipe(SimpleHeatExchanger): Treat this component in offdesign mode in a design calculation. material : str - + Description missing. offdesign : list List containing offdesign parameters (stated as String). @@ -169,7 +166,7 @@ class Pipe(SimpleHeatExchanger): Wall thickness of pipe. Quantity: :code:`length`. power_connector_location : str - + Description missing. pr : float, dict Outlet to inlet pressure ratio. Quantity: :code:`ratio`. @@ -199,12 +196,34 @@ class Pipe(SimpleHeatExchanger): Tamb : float, dict Ambient temperature. Quantity: :code:`temperature`. + UA : float, dict, :code:`"var"` + Heat transfer coefficient considering ambient temperature. Quantity: + :code:`heat_transfer_coefficient`. Can be set as a system variable by + passing :code:`"var"` as its value. + + UA_char : tespy.tools.characteristics.CharLine, dict + Heat transfer coefficient lookup table for offdesign. + + UA_char_group : GroupedComponentProperties + Heat transfer from design heat transfer coefficient, modifier lookup + table and ambient temperature. Elements: :code:`UA_char`, :code:`Tamb`. + Equation: :py:meth:`UA_char_group_func `. + + UA_group : GroupedComponentProperties + Equation for heat transfer based on ambient temperature and heat + transfer coefficient. Elements: :code:`UA`, :code:`Tamb`. + Equation: :py:meth:`UA_group_func `. + wind_velocity : float, dict Velocity of wind at insulation surface. Quantity: :code:`speed`. zeta : float, dict - Non-dimensional friction coefficient for pressure loss calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta_d4` instead. + + zeta_d4 : float, dict + Geometry-independent friction coefficient zeta/D^4 for pressure loss + calculation. + Equation: :py:meth:`zeta_d4_func `. Example ------- diff --git a/src/tespy/components/piping/valve.py b/src/tespy/components/piping/valve.py index 97a3bd09..eae9070e 100644 --- a/src/tespy/components/piping/valve.py +++ b/src/tespy/components/piping/valve.py @@ -41,9 +41,8 @@ class Valve(Component): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 + - Fluid inlets: in1 + - Fluid outlets: out1 Mandatory Equations ------------------- @@ -118,8 +117,12 @@ class Valve(Component): Include this component in the network's results printout. zeta : float, dict - Non-dimensional friction coefficient for pressure loss calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta_d4` instead. + + zeta_d4 : float, dict + Geometry-independent friction coefficient zeta/D^4 for pressure loss + calculation. + Equation: :py:meth:`zeta_d4_func `. Example ------- @@ -141,7 +144,7 @@ class Valve(Component): >>> so_v = Connection(so, 'out1', v, 'in1') >>> v_si = Connection(v, 'out1', si, 'in1') >>> nw.add_conns(so_v, v_si) - >>> v.set_attr(offdesign=['zeta']) + >>> v.set_attr(offdesign=['zeta_d4']) >>> so_v.set_attr(fluid={'CH4': 1}, m=1, T=50, p=80, design=['m']) >>> v_si.set_attr(p=15) >>> nw.solve('design') @@ -151,10 +154,10 @@ class Valve(Component): >>> round(v.pr.val, 3) 0.188 - The simulation determined the area independent zeta value - :math:`\frac{\zeta}{D^4}`. This zeta remains constant if the cross - sectional area of the valve opening does not change. Using the zeta value - we can determine the pressure ratio at a different feed pressure. + The simulation determined the area independent zeta_d4 value + :math:`\frac{\zeta}{D^4}`. This value remains constant if the cross + sectional area of the valve opening does not change. Using zeta_d4 we can + determine the pressure ratio at a different feed pressure. >>> so_v.set_attr(p=70) >>> nw.solve('offdesign', design_path=design_state) @@ -221,6 +224,9 @@ class Valve(Component): >>> round(v.Kv.val, 1) 5.2 """ + + _parameter_aliases = {'zeta': 'zeta_d4'} + def get_parameters(self): return { 'pr': dc_cp( @@ -240,13 +246,18 @@ def get_parameters(self): description="inlet to outlet absolute pressure change", calc=self._calc_dp ), - 'zeta': dc_cp( + 'zeta_d4': dc_cp( min_val=0, max_val=1e15, num_eq_sets=1, - func=self.zeta_func, - dependents=self.zeta_dependents, - func_params={'zeta': 'zeta'}, - description="non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta + func=self.zeta_d4_func, + dependents=self.zeta_d4_dependents, + func_params={'zeta': 'zeta_d4'}, + description="geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4 + ), + 'zeta': dc_cp( + min_val=0, is_result=True, + description="deprecated, use :code:`zeta_d4` instead", + calc=self._calc_zeta_d4 ), 'dp_char': dc_cc( param='m', num_eq_sets=1, diff --git a/src/tespy/components/power/bus.py b/src/tespy/components/power/bus.py index db0cde4e..ed5d5c35 100644 --- a/src/tespy/components/power/bus.py +++ b/src/tespy/components/power/bus.py @@ -35,9 +35,8 @@ class PowerBus(_EnergyBus): Ports ----- - Power inlets: power_in1, power_in2, ... (variable, count set by :code:`num_in`) - - Power outlets: power_out1, power_out2, ... (variable, count set by :code:`num_out`) + - Power inlets: power_in1, power_in2, ... (variable, count set by :code:`num_in`) + - Power outlets: power_out1, power_out2, ... (variable, count set by :code:`num_out`) Mandatory Equations ------------------- diff --git a/src/tespy/components/power/generator.py b/src/tespy/components/power/generator.py index f6aa65a2..df9d7e35 100644 --- a/src/tespy/components/power/generator.py +++ b/src/tespy/components/power/generator.py @@ -32,9 +32,8 @@ class Generator(_EnergyConverter): Ports ----- - Power inlets: power_in - - Power outlets: power_out + - Power inlets: power_in + - Power outlets: power_out Mandatory Equations ------------------- diff --git a/src/tespy/components/power/motor.py b/src/tespy/components/power/motor.py index 99bc25c1..d4d89a84 100644 --- a/src/tespy/components/power/motor.py +++ b/src/tespy/components/power/motor.py @@ -32,9 +32,8 @@ class Motor(_EnergyConverter): Ports ----- - Power inlets: power_in - - Power outlets: power_out + - Power inlets: power_in + - Power outlets: power_out Mandatory Equations ------------------- diff --git a/src/tespy/components/power/sink.py b/src/tespy/components/power/sink.py index cec3cdcb..c2f5e84f 100644 --- a/src/tespy/components/power/sink.py +++ b/src/tespy/components/power/sink.py @@ -22,7 +22,7 @@ class PowerSink(_EnergySink): Ports ----- - Power inlets: power + - Power inlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/power/source.py b/src/tespy/components/power/source.py index c04b8172..01b6f369 100644 --- a/src/tespy/components/power/source.py +++ b/src/tespy/components/power/source.py @@ -22,7 +22,7 @@ class PowerSource(_EnergySource): Ports ----- - Power outlets: power + - Power outlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/reactors/fuel_cell.py b/src/tespy/components/reactors/fuel_cell.py index db7c7224..6cc12498 100644 --- a/src/tespy/components/reactors/fuel_cell.py +++ b/src/tespy/components/reactors/fuel_cell.py @@ -37,11 +37,9 @@ class FuelCell(Component): Ports ----- - Fluid inlets: in1, in2, in3 - - Fluid outlets: out1, out2 - - Power outlets: power + - Fluid inlets: in1, in2, in3 + - Fluid outlets: out1, out2 + - Power outlets: power Mandatory Equations ------------------- @@ -111,9 +109,12 @@ class FuelCell(Component): Equation: :py:meth:`heat_func `. zeta : float, dict - Cooling port non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta_d4` instead. + + zeta_d4 : float, dict + Cooling port geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -180,6 +181,8 @@ def _calc_Q(self): def _calc_e(self): return self.P.val_SI / self.inl[2].m.val_SI + _parameter_aliases = {'zeta': 'zeta_d4'} + def _calc_eta(self): return self.e.val_SI / self.e0 @@ -214,14 +217,19 @@ def get_parameters(self): description="cooling inlet to outlet absolute pressure change", calc=self._calc_dp ), - 'zeta': dc_cp( + 'zeta_d4': dc_cp( min_val=0, num_eq_sets=1, - dependents=self.zeta_dependents, - func=self.zeta_func, - func_params={'zeta': 'zeta'}, - description="cooling port non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta + dependents=self.zeta_d4_dependents, + func=self.zeta_d4_func, + func_params={'zeta': 'zeta_d4'}, + description="cooling port geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4 + ), + 'zeta': dc_cp( + min_val=0, is_result=True, + description="deprecated, use :code:`zeta_d4` instead", + calc=self._calc_zeta_d4 ), 'e': dc_cp( max_val=0, num_eq_sets=1, @@ -713,4 +721,3 @@ def initialise_target(self, c, key): elif key == 'h': temp = 50 + 273.15 return h_mix_pT(c.p.val_SI, temp, c.fluid_data, c.mixing_rule) - diff --git a/src/tespy/components/reactors/water_electrolyzer.py b/src/tespy/components/reactors/water_electrolyzer.py index 559dcfaf..254b69c7 100644 --- a/src/tespy/components/reactors/water_electrolyzer.py +++ b/src/tespy/components/reactors/water_electrolyzer.py @@ -39,11 +39,9 @@ class WaterElectrolyzer(Component): Ports ----- - Fluid inlets: in1, in2 - - Fluid outlets: out1, out2, out3 - - Power inlets: power + - Fluid inlets: in1, in2 + - Fluid outlets: out1, out2, out3 + - Power inlets: power Mandatory Equations ------------------- @@ -118,9 +116,12 @@ class WaterElectrolyzer(Component): Equation: :py:meth:`heat_func `. zeta : float, dict - Cooling port non-dimensional friction coefficient for pressure loss - calculation. - Equation: :py:meth:`zeta_func `. + Deprecated, use :code:`zeta_d4` instead. + + zeta_d4 : float, dict + Cooling port geometry-independent friction coefficient zeta/D^4 for + pressure loss calculation. + Equation: :py:meth:`zeta_d4_func `. Notes ----- @@ -176,7 +177,7 @@ class WaterElectrolyzer(Component): >>> cmp_h.set_attr(p=25) >>> el_cmp.set_attr(v=100, T=50) >>> el.set_attr(eta=0.8, pr=0.99, design=['eta', 'pr'], - ... offdesign=['eta_char', 'zeta']) + ... offdesign=['eta_char', 'zeta_d4']) >>> comp.set_attr(eta_s=0.85) >>> nw.solve('design') >>> design_state = nw.save(as_dict=True) @@ -201,6 +202,8 @@ def _calc_Q(self): def _calc_e(self): return self.P.val_SI / self.outl[2].m.val_SI + _parameter_aliases = {'zeta': 'zeta_d4'} + def _calc_eta(self): return self.e0 / self.e.val_SI @@ -235,14 +238,19 @@ def get_parameters(self): description="cooling inlet to outlet absolute pressure change", calc=self._calc_dp ), - 'zeta': dc_cp( + 'zeta_d4': dc_cp( min_val=0, num_eq_sets=1, - dependents=self.zeta_dependents, - func=self.zeta_func, - func_params={'zeta': 'zeta'}, - description="cooling port non-dimensional friction coefficient for pressure loss calculation", - calc=self._calc_zeta + dependents=self.zeta_d4_dependents, + func=self.zeta_d4_func, + func_params={'zeta': 'zeta_d4'}, + description="cooling port geometry-independent friction coefficient zeta/D^4 for pressure loss calculation", + calc=self._calc_zeta_d4 + ), + 'zeta': dc_cp( + min_val=0, is_result=True, + description="deprecated, use :code:`zeta_d4` instead", + calc=self._calc_zeta_d4 ), 'e': dc_cp( min_val=0, num_eq_sets=1, @@ -828,4 +836,3 @@ def initialise_target(self, c, key): elif key == 'h': temp = 20 + 273.15 return h_mix_pT(c.p.val_SI, temp, c.fluid_data, c.mixing_rule) - diff --git a/src/tespy/components/turbomachinery/base.py b/src/tespy/components/turbomachinery/base.py index a3842d4f..0f2ad416 100644 --- a/src/tespy/components/turbomachinery/base.py +++ b/src/tespy/components/turbomachinery/base.py @@ -26,9 +26,8 @@ class Turbomachine(Component): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 + - Fluid inlets: in1 + - Fluid outlets: out1 Mandatory Equations ------------------- diff --git a/src/tespy/components/turbomachinery/compressor.py b/src/tespy/components/turbomachinery/compressor.py index e821ace2..feb6e166 100644 --- a/src/tespy/components/turbomachinery/compressor.py +++ b/src/tespy/components/turbomachinery/compressor.py @@ -48,11 +48,9 @@ class Compressor(Turbomachine): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: power + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/turbomachinery/pump.py b/src/tespy/components/turbomachinery/pump.py index 5d440d47..86f671b5 100644 --- a/src/tespy/components/turbomachinery/pump.py +++ b/src/tespy/components/turbomachinery/pump.py @@ -46,11 +46,9 @@ class Pump(Turbomachine): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: power + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/turbomachinery/steam_turbine.py b/src/tespy/components/turbomachinery/steam_turbine.py index 4927ec75..2ba173d4 100644 --- a/src/tespy/components/turbomachinery/steam_turbine.py +++ b/src/tespy/components/turbomachinery/steam_turbine.py @@ -42,11 +42,9 @@ class SteamTurbine(Turbine): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power outlets: power + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power outlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/turbomachinery/turbine.py b/src/tespy/components/turbomachinery/turbine.py index 547f7a03..2c36891a 100644 --- a/src/tespy/components/turbomachinery/turbine.py +++ b/src/tespy/components/turbomachinery/turbine.py @@ -44,11 +44,9 @@ class Turbine(Turbomachine): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power outlets: power + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power outlets: power Mandatory Equations ------------------- diff --git a/src/tespy/components/turbomachinery/turbocompressor.py b/src/tespy/components/turbomachinery/turbocompressor.py index 935e7a51..6b507b94 100644 --- a/src/tespy/components/turbomachinery/turbocompressor.py +++ b/src/tespy/components/turbomachinery/turbocompressor.py @@ -39,11 +39,9 @@ class TurboCompressor(Compressor): Ports ----- - Fluid inlets: in1 - - Fluid outlets: out1 - - Power inlets: power + - Fluid inlets: in1 + - Fluid outlets: out1 + - Power inlets: power Mandatory Equations ------------------- diff --git a/src/tespy/data/char_lines.json b/src/tespy/data/char_lines.json index e9216532..2798bacc 100644 --- a/src/tespy/data/char_lines.json +++ b/src/tespy/data/char_lines.json @@ -72,6 +72,54 @@ } }, "HeatExchanger": { + "UA_char1": { + "DEFAULT": { + "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, + 0.28796, 0.38458, 0.49337, 0.61364, 0.74473, 0.88595, + 1.0, 1.19613, 1.36374, 1.53879, 1.72061, 1.90854, + 2.10189, 2.29999, 2.50217, 2.70776, 2.91608, 3.0], + "y": [0.01, 0.09598, 0.18995, 0.28191, 0.37185, 0.45974, + 0.54557, 0.62932, 0.71098, 0.79053, 0.86796, 0.94324, + 1.0, 1.0873, 1.15605, 1.22259, 1.28691, 1.34898, + 1.40879, 1.46633, 1.52157, 1.5745, 1.62511, 1.645], + "ref": false + }, + "CONDENSING FLUID": { + "x": [0.0, 0.02476, 0.08114, 0.167, 0.28023, 0.41869, + 0.58027, 0.76284, 0.96428, 1.0, 1.18245, 1.41525, + 1.66053, 1.91619, 2.18009, 2.4501, 2.72412, 3.0], + "y": [0.01, 0.19836, 0.37181, 0.52217, 0.65124, 0.76085, + 0.8528, 0.92891, 0.99099, 1.0, 1.04084, 1.0803, + 1.11116, 1.13524, 1.15435, 1.1703, 1.18492, 1.2], + "ref": false + } + }, + "UA_char2": { + "DEFAULT": { + "x": [0.0, 0.10449, 0.23774, 0.40054, 0.59243, 0.81296, + 1.0, 1.0617, 1.33818, 1.64196, 1.97259, 2.32963, + 2.71261, 3.0012], + "y": [0.01, 0.21181, 0.40637, 0.58484, 0.74792, 0.89627, + 1.0, 1.03058, 1.15152, 1.25977, 1.35602, 1.44093, + 1.51519, 1.562], + "ref": false + }, + "EVAPORATING FLUID": { + "x": [0.0, 0.00412, 0.0076, 0.01101, 0.01488, 0.0211, + 0.02758, 0.0362, 0.04751, 0.06206, 0.08041, 0.10312, + 0.13073, 0.1638, 0.20288, 0.24854, 0.30132, 0.37528, + 0.45378, 0.54212, 0.64561, 0.76955, 0.91927, 1.0, + 1.10006, 1.31723, 1.57609, 1.88195, 2.24011, 2.65589, + 3.0], + "y": [0.01, 0.04969, 0.10554, 0.16642, 0.2312, 0.29888, + 0.36806, 0.43773, 0.50677, 0.57404, 0.6384, 0.69873, + 0.75388, 0.80274, 0.84415, 0.87699, 0.90012, 0.92187, + 0.94082, 0.95729, 0.97163, 0.98417, 0.99525, 1.0, + 1.00521, 1.01439, 1.02312, 1.03175, 1.0406, 1.05002, + 1.0575], + "ref": false + } + }, "kA_char1": { "DEFAULT": { "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, @@ -122,6 +170,28 @@ } }, "Condenser": { + "UA_char1": { + "DEFAULT": { + "x": [0.0, 0.02476, 0.08114, 0.167, 0.28023, 0.41869, + 0.58027, 0.76284, 0.96428, 1.0, 1.18245, 1.41525, + 1.66053, 1.91619, 2.18009, 2.4501, 2.72412, 3.0], + "y": [0.01, 0.19836, 0.37181, 0.52217, 0.65124, 0.76085, + 0.8528, 0.92891, 0.99099, 1.0, 1.04084, 1.0803, + 1.11116, 1.13524, 1.15435, 1.1703, 1.18492, 1.2], + "ref": false + } + }, + "UA_char2": { + "DEFAULT": { + "x": [0.0, 0.10449, 0.23774, 0.40054, 0.59243, 0.81296, + 1.0, 1.0617, 1.33818, 1.64196, 1.97259, 2.32963, + 2.71261, 3.0012], + "y": [0.01, 0.21181, 0.40637, 0.58484, 0.74792, 0.89627, + 1.0, 1.03058, 1.15152, 1.25977, 1.35602, 1.44093, + 1.51519, 1.562], + "ref": false + } + }, "kA_char1": { "DEFAULT": { "x": [0.0, 0.02476, 0.08114, 0.167, 0.28023, 0.41869, @@ -146,6 +216,30 @@ } }, "Desuperheater": { + "UA_char1": { + "DEFAULT": { + "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, + 0.28796, 0.38458, 0.49337, 0.61364, 0.74473, 0.88595, + 1.0, 1.19613, 1.36374, 1.53879, 1.72061, 1.90854, + 2.10189, 2.29999, 2.50217, 2.70776, 2.91608, 3.0], + "y": [0.01, 0.09598, 0.18995, 0.28191, 0.37185, 0.45974, + 0.54557, 0.62932, 0.71098, 0.79053, 0.86796, 0.94324, + 1.0, 1.0873, 1.15605, 1.22259, 1.28691, 1.34898, + 1.40879, 1.46633, 1.52157, 1.5745, 1.62511, 1.645], + "ref": false + } + }, + "UA_char2": { + "DEFAULT": { + "x": [0.0, 0.10449, 0.23774, 0.40054, 0.59243, 0.81296, + 1.0, 1.0617, 1.33818, 1.64196, 1.97259, 2.32963, + 2.71261, 3.0012], + "y": [0.01, 0.21181, 0.40637, 0.58484, 0.74792, 0.89627, + 1.0, 1.03058, 1.15152, 1.25977, 1.35602, 1.44093, + 1.51519, 1.562], + "ref": false + } + }, "kA_char1": { "DEFAULT": { "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, @@ -172,6 +266,19 @@ } }, "SimpleHeatExchanger": { + "UA_char": { + "DEFAULT": { + "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, + 0.28796, 0.38458, 0.49337, 0.61364, 0.74473, 0.88595, + 1.0, 1.19613, 1.36374, 1.53879, 1.72061, 1.90854, + 2.10189, 2.29999, 2.50217, 2.70776, 2.91608, 3.0], + "y": [0.01, 0.09598, 0.18995, 0.28191, 0.37185, 0.45974, + 0.54557, 0.62932, 0.71098, 0.79053, 0.86796, 0.94324, + 1.0, 1.0873, 1.15605, 1.22259, 1.28691, 1.34898, + 1.40879, 1.46633, 1.52157, 1.5745, 1.62511, 1.645], + "ref": false + } + }, "kA_char": { "DEFAULT": { "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, @@ -187,6 +294,19 @@ } }, "Pipe": { + "UA_char": { + "DEFAULT": { + "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, + 0.28796, 0.38458, 0.49337, 0.61364, 0.74473, 0.88595, + 1.0, 1.19613, 1.36374, 1.53879, 1.72061, 1.90854, + 2.10189, 2.29999, 2.50217, 2.70776, 2.91608, 3.0], + "y": [0.01, 0.09598, 0.18995, 0.28191, 0.37185, 0.45974, + 0.54557, 0.62932, 0.71098, 0.79053, 0.86796, 0.94324, + 1.0, 1.0873, 1.15605, 1.22259, 1.28691, 1.34898, + 1.40879, 1.46633, 1.52157, 1.5745, 1.62511, 1.645], + "ref": false + } + }, "kA_char": { "DEFAULT": { "x": [0.0, 0.01084, 0.03655, 0.07779, 0.13389, 0.20417, diff --git a/tests/test_components/test_combustion.py b/tests/test_components/test_combustion.py index a2abb39c..aef7e2a3 100644 --- a/tests/test_components/test_combustion.py +++ b/tests/test_components/test_combustion.py @@ -304,7 +304,7 @@ def test_CombustionEngine(self): # connection parametrisation instance.set_attr( pr1=0.99, pr2=0.99, lamb=1.0, - design=['pr1', 'pr2'], offdesign=['zeta1', 'zeta2'] + design=['pr1', 'pr2'], offdesign=['zeta1_d4', 'zeta2_d4'] ) self.c1.set_attr(p=5, T=30, fluid=air) self.c2.set_attr(T=30, fluid=fuel) diff --git a/tests/test_components/test_components.py b/tests/test_components/test_components.py index 3a328d69..556e776c 100644 --- a/tests/test_components/test_components.py +++ b/tests/test_components/test_components.py @@ -26,22 +26,22 @@ def test_all_classes_in_registry(obj): QUANTITY_EXEMPTIONS = { "CycleCloser": {"fluid_deviation"}, - "CombustionEngine": {"zeta1", "zeta2"}, + "CombustionEngine": {"zeta1", "zeta1_d4", "zeta2", "zeta2_d4"}, "PolynomialCompressor": {"rpm", "re_exp_r", "re_exp_sf"}, "PolynomialCompressorWithCooling": {"rpm", "re_exp_r", "re_exp_sf"}, - "HeatExchanger": {"zeta1", "zeta2"}, - "Condenser": {"zeta1", "zeta2"}, - "Desuperheater": {"zeta1", "zeta2"}, - "SectionedHeatExchanger": {"zeta1", "zeta2", "re_exp_r", "re_exp_sf"}, - "MovingBoundaryHeatExchanger": {"zeta1", "zeta2", "re_exp_r", "re_exp_sf"}, - "SimpleHeatExchanger": {"zeta", "ks_HW"}, - "ParabolicTrough": {"zeta", "c_1", "c_2", "iam_1", "iam_2", "ks_HW"}, - "ParallelFlowHeatExchanger": {"zeta1", "zeta2"}, - "SolarCollector": {"zeta", "lkf_lin", "lkf_quad", "ks_HW"}, - "Pipe": {"zeta", "ks_HW"}, - "Valve": {"zeta", "Kv"}, - "FuelCell": {"zeta"}, - "WaterElectrolyzer": {"zeta"}, + "HeatExchanger": {"zeta1", "zeta1_d4", "zeta2", "zeta2_d4"}, + "Condenser": {"zeta1", "zeta1_d4", "zeta2", "zeta2_d4"}, + "Desuperheater": {"zeta1", "zeta1_d4", "zeta2", "zeta2_d4"}, + "SectionedHeatExchanger": {"zeta1", "zeta1_d4", "zeta2", "zeta2_d4", "re_exp_r", "re_exp_sf"}, + "MovingBoundaryHeatExchanger": {"zeta1", "zeta1_d4", "zeta2", "zeta2_d4", "re_exp_r", "re_exp_sf"}, + "SimpleHeatExchanger": {"zeta", "zeta_d4", "ks_HW"}, + "ParabolicTrough": {"zeta", "zeta_d4", "c_1", "c_2", "iam_1", "iam_2", "ks_HW"}, + "ParallelFlowHeatExchanger": {"zeta1", "zeta1_d4", "zeta2", "zeta2_d4"}, + "SolarCollector": {"zeta", "zeta_d4", "lkf_lin", "lkf_quad", "ks_HW"}, + "Pipe": {"zeta", "zeta_d4", "ks_HW"}, + "Valve": {"zeta", "zeta_d4", "Kv"}, + "FuelCell": {"zeta", "zeta_d4"}, + "WaterElectrolyzer": {"zeta", "zeta_d4"}, } def properties_of(instance): diff --git a/tests/test_components/test_heat_exchangers.py b/tests/test_components/test_heat_exchangers.py index 67e23e78..d8f70645 100644 --- a/tests/test_components/test_heat_exchangers.py +++ b/tests/test_components/test_heat_exchangers.py @@ -12,6 +12,7 @@ import math import numpy as np +import pytest from CoolProp.CoolProp import PropsSI as PSI from CoolProp.CoolProp import get_global_param_string from pytest import approx @@ -71,7 +72,7 @@ def _calc_td_log(ttd_u, ttd_l): return (ttd_l - ttd_u) / math.log(ttd_l / ttd_u) -def _calc_kA(Q, td_log): +def _calc_UA(Q, td_log): return - Q / td_log @@ -172,7 +173,7 @@ def test_postprocessing(self, heatexchanger_converged_network): assert instance.ttd_min.val == min(instance.ttd_l.val, instance.ttd_u.val) assert approx(instance.td_log.val) == _calc_td_log(instance.ttd_u.val, instance.ttd_l.val) - assert approx(instance.kA.val) == _calc_kA(instance.Q.val, instance.td_log.val) + assert approx(instance.UA.val) == _calc_UA(instance.Q.val, instance.td_log.val) assert approx(instance.eff_hot.val) == _calc_eff_hot(c1, c2, c3) assert approx(instance.eff_cold.val) == _calc_eff_cold(c3, c4, c1) @@ -212,7 +213,7 @@ def test_zeta1(self, heatexchanger_converged_network): zeta = 100 c2.set_attr(p=None) - instance.set_attr(zeta1=zeta) + instance.set_attr(zeta1_d4=zeta) nw.solve('design') nw.assert_convergence() @@ -252,7 +253,7 @@ def test_zeta2(self, heatexchanger_converged_network): zeta = 100 c4.set_attr(p=None) - instance.set_attr(zeta2=zeta) + instance.set_attr(zeta2_d4=zeta) nw.solve('design') nw.assert_convergence() @@ -301,15 +302,15 @@ def test_SimpleHeatExchanger(self): # test grouped parameter settings with missing parameters instance.darcy_group.is_set = True - instance.kA_group.is_set = True - instance.kA_char_group.is_set = True + instance.UA_group.is_set = True + instance.UA_char_group.is_set = True self.nw.solve('design', init_only=True) msg = ('Darcy group must no be set, if one parameter is missing!') assert not instance.darcy_group.is_set, msg - msg = ('kA group must no be set, if one parameter is missing!') - assert not instance.kA_group.is_set, msg - msg = ('kA char group must no be set, if one parameter is missing!') - assert not instance.kA_char_group.is_set, msg + msg = ('UA group must no be set, if one parameter is missing!') + assert not instance.UA_group.is_set, msg + msg = ('UA char group must no be set, if one parameter is missing!') + assert not instance.UA_char_group.is_set, msg # test diameter calculation from specified dimensions (as pipe) # with Hazen-Williams method @@ -328,42 +329,42 @@ def test_SimpleHeatExchanger(self): # test heat transfer coefficient as variable of the system (ambient # temperature required) instance.set_attr(D=instance.D.val) - instance.set_attr(kA='var', pr=None) + instance.set_attr(UA='var', pr=None) h1.set_attr(E=5e4) self.nw.solve('design') self.nw.assert_convergence() - # due to heat output being half of reference (for Tamb) kA should be + # due to heat output being half of reference (for Tamb) UA should be # somewhere near to that (actual value is 677) msg = ( "Value of heat transfer coefficient must be 677, is " - f"{instance.kA.val}." + f"{instance.UA.val}." ) - assert 677 == round(instance.kA.val, 0), msg + assert 677 == round(instance.UA.val, 0), msg - # test kA as network results parameter - instance.set_attr(Q=-5e4, Tamb=None, kA=None) + # test UA as network results parameter + instance.set_attr(Q=-5e4, Tamb=None, UA=None) h1.set_attr(E=None) self.nw.solve('design') self.nw.assert_convergence() - kA_network = self.nw.results['SimpleHeatExchanger'].loc[ - instance.label, 'kA' + UA_network = self.nw.results['SimpleHeatExchanger'].loc[ + instance.label, 'UA' ] - msg = 'kA value must not be included in network results.' - expr = not instance.kA.is_result and np.isnan(kA_network) + msg = 'UA value must not be included in network results.' + expr = not instance.UA.is_result and np.isnan(UA_network) assert expr, msg - # test kA as network results parameter + # test UA as network results parameter instance.set_attr(Tamb=20) self.nw.solve('design') - kA_network = self.nw.results['SimpleHeatExchanger'].loc[ - instance.label, 'kA'] - kA_comp = instance.kA.val - msg = 'kA value needs to be identical on network and component level.' - assert kA_network == kA_comp, msg - - def test_SimpleHeatExchanger_kA_convergence_cooling(self): - """Test kA group equation convergence for near ambient temperature outflow.""" + UA_network = self.nw.results['SimpleHeatExchanger'].loc[ + instance.label, 'UA'] + UA_comp = instance.UA.val + msg = 'UA value needs to be identical on network and component level.' + assert UA_network == UA_comp, msg + + def test_SimpleHeatExchanger_UA_convergence_cooling(self): + """Test UA group equation convergence for near ambient temperature outflow.""" instance = SimpleHeatExchanger("heatexchanger") self.setup_SimpleHeatExchanger_network(instance) self.c1.set_attr(fluid={"H2O": 1}, x=0, p=28, m=0.005) @@ -371,7 +372,7 @@ def test_SimpleHeatExchanger_kA_convergence_cooling(self): instance.set_attr( pr=0.95, Tamb=20, - kA=200, + UA=200, L=1000, D='var', ks=4.57e-5 @@ -380,16 +381,29 @@ def test_SimpleHeatExchanger_kA_convergence_cooling(self): self.nw.assert_convergence() assert round(self.c2.T.val - instance.Tamb.val, 3) == 0.019 - def test_SimpleHeatExchanger_kA_convergence_heating(self): + def test_SimpleHeatExchanger_UA_convergence_heating(self): instance = SimpleHeatExchanger("heatexchanger") self.setup_SimpleHeatExchanger_network(instance) - instance.set_attr(Tamb=10, D=0.0215, L=50, ks=0.00001, kA=3000.0) + instance.set_attr(Tamb=10, D=0.0215, L=50, ks=0.00001, UA=3000.0) self.c1.set_attr(p=4, m=0.1, fluid={"Water": 1}, T=0) self.nw.solve("design") self.nw.assert_convergence() assert round(instance.Tamb.val - self.c2.T.val, 3) == 0.008 + def test_SimpleHeatExchanger_lmtd_zero_Q(self): + """lmtd must be nan when Q=0 (UA=0), not raise ZeroDivisionError.""" + instance = SimpleHeatExchanger("heatexchanger") + self.setup_SimpleHeatExchanger_network(instance) + + instance.set_attr(Q=0, Tamb=20, pr=1) + self.c1.set_attr(fluid={"water": 1}, T=100, m=1, p=10) + self.nw.solve("design") + self.nw.assert_convergence() + + assert instance.UA.val_SI == 0 + assert np.isnan(instance.lmtd.val_SI) + def test_ParabolicTrough(self): """Test component properties of parabolic trough.""" instance = ParabolicTrough('parabolic trough') @@ -497,7 +511,7 @@ def test_HeatExchanger(self): instance.set_attr( pr1=0.98, pr2=0.98, ttd_u=5, design=['pr1', 'pr2', 'ttd_u'], - offdesign=['zeta1', 'zeta2', 'kA_char'] + offdesign=['zeta1_d4', 'zeta2_d4', 'UA_char'] ) self.c1.set_attr(T=120, p=3, fluid={'H2O': 1}) self.c2.set_attr(T=70) @@ -509,8 +523,8 @@ def test_HeatExchanger(self): design_state = self.nw.save(as_dict=True) Q_design = instance.Q.val - # test specified kA value - instance.set_attr(kA=instance.kA.val * 2 / 3, Q=None) + # test specified UA value + instance.set_attr(UA=instance.UA.val * 2 / 3, Q=None) self.nw.solve('design') self.nw.assert_convergence() @@ -523,7 +537,7 @@ def test_HeatExchanger(self): assert round(Q, 1) == round(Q_design * 2 / 3, 1), msg # back to design case - instance.set_attr(kA=None, Q=Q_design) + instance.set_attr(UA=None, Q=Q_design) self.nw.solve('design') self.nw.assert_convergence() @@ -536,7 +550,7 @@ def test_HeatExchanger(self): / (self.c1.T.val - self.c4.T.val) ) ) - kA = round(-Q / td_log, 0) + UA = round(-Q / td_log, 0) msg = ( f"Value of heat transfer must be {round(Q, 0)}, is " f"{round(instance.Q.val, 0)}." @@ -566,7 +580,7 @@ def test_HeatExchanger(self): ttd_l = round(instance.ttd_l.val, 1) assert ttd_l_calc == ttd_l, msg - # check specified kA value (by offdesign parameter), reset temperatures + # check specified UA value (by offdesign parameter), reset temperatures # to design state self.c2.set_attr(T=70) instance.set_attr(ttd_l=None) @@ -575,10 +589,10 @@ def test_HeatExchanger(self): msg = f'Value of heat flow must be {instance.Q.val}, is {round(Q, 0)}.' assert round(Q, 0) == round(instance.Q.val, 0), msg msg = ( - f'Value of heat transfer coefficient must be {kA}, is ' - f'{round(instance.kA.val, 0)}.' + f'Value of heat transfer coefficient must be {UA}, is ' + f'{round(instance.UA.val, 0)}.' ) - assert kA == round(instance.kA.val, 0), msg + assert UA == round(instance.UA.val, 0), msg # trigger negative lower terminal temperature difference as result self.c4.set_attr(T=None) @@ -692,9 +706,9 @@ def test_HeatExchanger_ttd_zero(self): self.nw.assert_convergence() msg = ( 'Value of heat transfer coefficient must be nan but is ' - f'{round(instance.kA.val, 1)}.' + f'{round(instance.UA.val, 1)}.' ) - assert np.isnan(instance.kA.val), msg + assert np.isnan(instance.UA.val), msg def test_Condenser(self): """Test component properties of Condenser.""" @@ -703,7 +717,7 @@ def test_Condenser(self): # design specification instance.set_attr( - pr1=0.98, pr2=0.98, ttd_u=5, offdesign=['zeta2', 'kA_char'] + pr1=0.98, pr2=0.98, ttd_u=5, offdesign=['zeta2_d4', 'UA_char'] ) self.c1.set_attr(T=100, p0=0.5, fluid={'H2O': 1}) self.c2.set_attr(p0=0.5) @@ -716,8 +730,8 @@ def test_Condenser(self): design_state = self.nw.save(as_dict=True) Q_design = instance.Q.val - # test specified kA value - instance.set_attr(kA=instance.kA.val * 2 / 3, Q=None) + # test specified UA value + instance.set_attr(UA=instance.UA.val * 2 / 3, Q=None) self.nw.solve('design') self.nw.assert_convergence() @@ -730,7 +744,7 @@ def test_Condenser(self): assert round(Q, 1) == round(Q_design * 2 / 3, 1), msg # back to design case - instance.set_attr(kA=None, Q=Q_design) + instance.set_attr(UA=None, Q=Q_design) self.nw.solve('design') self.nw.assert_convergence() @@ -764,7 +778,7 @@ def test_Condenser(self): ttd_l = round(instance.ttd_l.val, 1) assert ttd_l_calc == ttd_l, msg - # check kA value with condensing pressure in offdesign mode: + # check UA value with condensing pressure in offdesign mode: # no changes to design point means: identical pressure self.nw.solve('offdesign', design_path=design_state) self.nw.assert_convergence() @@ -780,7 +794,7 @@ def test_CondenserWithEvaporation(self): self.setup_HeatExchanger_network(instance) # design specification - instance.set_attr(pr1=1, pr2=1, offdesign=["kA"]) + instance.set_attr(pr1=1, pr2=1, offdesign=["UA"]) self.c1.set_attr(x=1, p=1, fluid={'H2O': 1}, m=1) self.c3.set_attr(x=0, p=0.7, fluid={'H2O': 1}, m=2, design=["m"]) self.nw.solve('design') @@ -820,9 +834,9 @@ def test_Condenser_ttd_zero(self): self.nw.assert_convergence() msg = ( 'Value of heat transfer coefficient must be nan but is ' - f'{round(instance.kA.val, 1)}.' + f'{round(instance.UA.val, 1)}.' ) - assert np.isnan(instance.kA.val), msg + assert np.isnan(instance.UA.val), msg def test_ParallelFlowHeatExchanger(self): instance = ParallelFlowHeatExchanger("heat exchanger") @@ -847,7 +861,7 @@ def test_ParallelFlowHeatExchanger(self): assert approx(instance.pr2.val_SI) == _calc_pr(self.c3, self.c4) assert approx(instance.td_log.val_SI) == _calc_td_log(ttd_u, ttd_l) - assert approx(instance.kA.val) == _calc_kA( + assert approx(instance.UA.val) == _calc_UA( instance.Q.val, instance.td_log.val ) @@ -858,7 +872,7 @@ def test_ParallelFlowHeatExchanger_offdesign(self): self.c1.set_attr(fluid={"air": 1}, m=1, T=85, p=1) self.c3.set_attr(fluid={"water": 1}, m=3, T=25, p=1) instance.set_attr(dp1=0.1, dp2=0.1, ttd_u=15) - instance.set_attr(design=["ttd_u"], offdesign=["kA"]) + instance.set_attr(design=["ttd_u"], offdesign=["UA"]) self.nw.solve("design") design_state = self.nw.save(as_dict=True) @@ -866,11 +880,11 @@ def test_ParallelFlowHeatExchanger_offdesign(self): assert approx(instance.ttd_u.val) == 15 self.c1.set_attr(m=1.5) self.nw.solve("offdesign", design_path=design_state) - assert approx(instance.kA.val_SI) == instance.kA.design + assert approx(instance.UA.val_SI) == instance.UA.design assert approx(instance.ttd_u.val, abs=0.01) == 23.01 self.c1.set_attr(m=0.8) self.nw.solve("offdesign", design_path=design_state) - assert approx(instance.kA.val_SI) == instance.kA.design + assert approx(instance.UA.val_SI) == instance.UA.design assert approx(instance.ttd_u.val, abs=0.01) == 10.88 def test_MovingBoundaryHeatExchanger(self): @@ -896,6 +910,7 @@ def test_MovingBoundaryHeatExchanger(self): # the sum of heat transfer of all sections must be equal to Q assert approx(sum(heat_sections)) == -instance.Q.val_SI # UA calculated over sections must be larger than kA + # this tests stays! assert instance.UA.val > instance.kA.val # minimum temperature difference at section borders = pinch assert approx(min(T_hot - T_cold)) == instance.td_pinch.val_SI @@ -980,7 +995,7 @@ def test_MovingBoundaryHeatExchanger_boundary_at_hot_side_outlet(self): self.c2.set_attr(x=1.0) self.c3.set_attr(fluid={"water": 1}, p=1, T=10) self.c4.set_attr(T=20) - instance.set_attr(zeta1=2000, pr2=0.99, Q=-1e6) + instance.set_attr(zeta1_d4=2000, pr2=0.99, Q=-1e6) self.nw.solve("design") @@ -995,7 +1010,7 @@ def test_MovingBoundaryHeatExchanger_boundary_at_cold_side_inlet(self): self.c2.set_attr(T=10) self.c3.set_attr(fluid={"NH3": 1}, x=1.0) self.c4.set_attr(td_dew=5, T=-19.597989949748744) - instance.set_attr(pr1=0.99, zeta2=2000, Q=-1e6) + instance.set_attr(pr1=0.99, zeta2_d4=2000, Q=-1e6) self.nw.solve("design") @@ -1024,6 +1039,7 @@ def test_SectionedHeatExchanger(self): # the sum of heat transfer of all sections must be equal to Q assert approx(sum(heat_sections)) == -instance.Q.val_SI # UA calculated over sections must be larger than kA + # this tests stays! assert instance.UA.val > instance.kA.val # minimum temperature difference at section borders = pinch assert approx(min(T_hot - T_cold)) == instance.td_pinch.val_SI @@ -1133,8 +1149,8 @@ def test_SectionedHeatExchanger_offdesign_UA_char(self): expr2 = self.c3.m.val_SI / self.c3.m.design UA_mod = ( 2 / ( - (1 / instance.kA_char1.char_func.evaluate(expr1)) - + (1 / instance.kA_char2.char_func.evaluate(expr2)) + (1 / instance.UA_char1.char_func.evaluate(expr1)) + + (1 / instance.UA_char2.char_func.evaluate(expr2)) ) ) assert approx(UA_mod * instance.UA.val_SI) == instance.UA.design @@ -1244,3 +1260,99 @@ def test_MovingBoundaryHeatExchanger_offdesign_cecchinato_evaporator(self): ) ) assert approx(instance.UA.val_SI) == instance.UA.design * fUA + + +# --------------------------------------------------------------------------- +# Tests for _parameter_aliases / deprecation-renaming feature +# --------------------------------------------------------------------------- + +class TestParameterAliases: + """Unit tests for the _parameter_aliases deprecation/renaming feature. + + The HeatExchanger._parameter_aliases maps, among others: + 'zeta1' -> 'zeta1_d4' + 'zeta2' -> 'zeta2_d4' + 'kA' -> 'UA' + """ + + @pytest.fixture(autouse=True) + def _build_network(self): + nw = Network() + nw.units.set_defaults(**{ + "pressure": "bar", "pressure_difference": "bar", + "temperature": "degC", + }) + inl1 = Source('inlet 1') + outl1 = Sink('outlet 1') + inl2 = Source('inlet 2') + outl2 = Sink('outlet 2') + self.he = HeatExchanger('heat exchanger') + c1 = Connection(inl1, 'out1', self.he, 'in1', label='1') + c2 = Connection(self.he, 'out1', outl1, 'in1', label='2') + c3 = Connection(inl2, 'out1', self.he, 'in2', label='3') + c4 = Connection(self.he, 'out2', outl2, 'in1', label='4') + nw.add_conns(c1, c2, c3, c4) + self.nw = nw + self.c1, self.c2, self.c3, self.c4 = c1, c2, c3, c4 + + def _solve_design(self): + self.c1.set_attr(T=120, p=1, fluid={'H2O': 1}, m=1) + self.c2.set_attr(T=105, p=0.95) + self.c3.set_attr(T=40, p=5, fluid={'Ar': 1}) + self.c4.set_attr(T=90, p=4.9) + self.nw.solve('design') + self.nw.assert_convergence() + + def test_set_attr_old_name_raises_future_warning(self): + """set_attr with a deprecated name emits FutureWarning.""" + with pytest.warns(FutureWarning, match="zeta1"): + self.he.set_attr(zeta1=500) + + def test_set_attr_old_name_sets_new_parameter(self): + """set_attr with 'zeta1' marks 'zeta1_d4' as set with the given value.""" + with pytest.warns(FutureWarning): + self.he.set_attr(zeta1=500) + assert self.he.zeta1_d4.val == pytest.approx(500) + assert self.he.zeta1_d4.is_set + + def test_set_attr_new_name_does_not_warn(self): + """Setting the new canonical name directly does not emit a FutureWarning.""" + import warnings + with warnings.catch_warnings(): + warnings.simplefilter("error", FutureWarning) + self.he.set_attr(zeta1_d4=500) + assert self.he.zeta1_d4.val == pytest.approx(500) + assert self.he.zeta1_d4.is_set + + def test_offdesign_list_alias_replaced_during_preprocess(self): + """Old name in offdesign list is remapped to the new name during solve.""" + self._solve_design() + # set_attr itself does not warn – the alias check for list entries + # happens inside _preprocess (i.e. during nw.solve) + self.he.set_attr(offdesign=['zeta1']) + design_state = self.nw.save(as_dict=True) + self.c2.set_attr(p=None) + with pytest.warns(FutureWarning, match="zeta1"): + self.nw.solve('offdesign', design_path=design_state) + self.nw.assert_convergence() + assert 'zeta1_d4' in self.he.offdesign + + def test_design_list_alias_replaced_during_preprocess(self): + """Old name in design list is remapped to the new name during solve.""" + # set_attr itself does not warn for list entries + self.he.set_attr(design=['zeta1']) + with pytest.warns(FutureWarning, match="zeta1"): + self._solve_design() + assert 'zeta1_d4' in self.he.design + + def test_network_solves_with_old_zeta_name(self): + """Network converges when 'zeta1' is used instead of 'zeta1_d4'.""" + zeta = 500 + # Establish a baseline solve, then free c2's pressure + self._solve_design() + self.c2.set_attr(p=None) + with pytest.warns(FutureWarning): + self.he.set_attr(zeta1=zeta) + self.nw.solve('design') + self.nw.assert_convergence() + assert approx(zeta) == _calc_zeta(self.c1, self.c2) diff --git a/tests/test_components/test_reactors.py b/tests/test_components/test_reactors.py index fdd80040..7d586b68 100644 --- a/tests/test_components/test_reactors.py +++ b/tests/test_components/test_reactors.py @@ -157,7 +157,7 @@ def test_WaterElectrolyzer(self): # use zeta as offdesign parameter, at design point pressure # ratio must not change - self.instance.set_attr(design=['pr'], offdesign=['zeta']) + self.instance.set_attr(design=['pr'], offdesign=['zeta_d4']) self.nw.solve('offdesign', design_path=design_state) self.nw.assert_convergence() msg = ( @@ -270,7 +270,7 @@ def test_FuelCell(self): # use zeta as offdesign parameter, at design point pressure # ratio must not change - self.instance.set_attr(design=['pr'], offdesign=['zeta']) + self.instance.set_attr(design=['pr'], offdesign=['zeta_d4']) self.nw.solve('offdesign', design_path=design_state) self.nw.assert_convergence() msg = ( diff --git a/tests/test_connections.py b/tests/test_connections.py index 7e4b1563..396db0e1 100644 --- a/tests/test_connections.py +++ b/tests/test_connections.py @@ -218,7 +218,7 @@ def test_td_dew_convergence_helper(simple_test_network): c2.set_attr(td_bubble=0) # settings to prevent preprocessing of temperatures - heatexchanger.set_attr(Q=1e5, zeta=0) + heatexchanger.set_attr(Q=1e5, zeta_d4=0) nw.solve("design") nw.assert_convergence() @@ -237,7 +237,7 @@ def test_td_bubble_convergence_helper(simple_test_network): c2.set_attr(td_bubble=0) # settings to prevent preprocessing of temperatures - heatexchanger.set_attr(Q=1e5, zeta=0) + heatexchanger.set_attr(Q=1e5, zeta_d4=0) nw.solve("design") nw.assert_convergence() @@ -258,7 +258,7 @@ def test_td_bubble_and_td_dew_in_iterations(simple_test_network): c2.set_attr(td_bubble=delta_T) # settings to prevent preprocessing of temperatures - heatexchanger.set_attr(Q=1e5, zeta=0) + heatexchanger.set_attr(Q=1e5, zeta_d4=0) nw.solve("design") @@ -291,7 +291,7 @@ def test_td_bubble_larger_0(simple_test_network): c2.set_attr(td_bubble=delta_T) # settings to prevent preprocessing of temperatures - heatexchanger.set_attr(Q=1e5, zeta=0) + heatexchanger.set_attr(Q=1e5, zeta_d4=0) nw.solve("design") nw.assert_convergence() @@ -308,7 +308,7 @@ def test_td_bubble_equals_0(simple_test_network): c2.set_attr(td_bubble=delta_T) # settings to prevent preprocessing of temperatures - heatexchanger.set_attr(Q=1e5, zeta=0) + heatexchanger.set_attr(Q=1e5, zeta_d4=0) nw.solve("design") nw.assert_convergence() diff --git a/tests/test_models/test_heat_pump_model.py b/tests/test_models/test_heat_pump_model.py index 7b801cf8..d4664071 100644 --- a/tests/test_models/test_heat_pump_model.py +++ b/tests/test_models/test_heat_pump_model.py @@ -143,7 +143,7 @@ def setup_method(self): 0.921, 1.000, 1.078, 1.154, 1.228, 1.302, 1.374, 1.446, 1.516, 1.585, 1.654, 1.722, 1.789, 1.855, 1.921, 1.986, 2.051 ]) - kA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} x = np.array([ 0.0100, 0.0400, 0.0700, 0.1100, 0.1500, 0.2000, 0.2500, 0.3000, @@ -156,28 +156,28 @@ def setup_method(self): 0.7942, 0.9400, 0.9883, 0.9913, 0.9936, 0.9953, 0.9966, 0.9975, 0.9983, 0.9988, 0.9992, 0.9996, 0.9998, 1.0000, 1.0008, 1.0014 ]) - kA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} ev.set_attr( - pr1=1, pr2=.999, ttd_l=5, design=['ttd_l'], offdesign=['kA_char'], - kA_char1=kA_char1, kA_char2=kA_char2 + pr1=1, pr2=.999, ttd_l=5, design=['ttd_l'], offdesign=['UA_char'], + UA_char1=UA_char1, UA_char2=UA_char2 ) - # no kA modification for hot side! + # no UA modification for hot side! x = np.array([0, 1]) y = np.array([1, 1]) - kA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} - # characteristic line for superheater kA + # characteristic line for superheater UA x = np.array([ 0, 0.045, 0.136, 0.244, 0.43, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2 ]) y = np.array([ 0, 0.037, 0.112, 0.207, 0.5, 0.8, 0.85, 0.9, 0.95, 1, 1.04, 1.07 ]) - kA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} su.set_attr( - kA_char1=kA_char1, kA_char2=kA_char2, - offdesign=['zeta1', 'zeta2', 'kA_char'] + UA_char1=UA_char1, UA_char2=UA_char2, + offdesign=['zeta1_d4', 'zeta2_d4', 'UA_char'] ) x = np.array([ @@ -208,7 +208,7 @@ def setup_method(self): eta_s_char={'char_func': CharLine(x, y), 'param': 'm'} ) - # characteristic line for intercooler kA + # characteristic line for intercooler UA x = np.linspace(0, 2.5, 26) y = np.array([ 0.0000, 0.2455, 0.3747, 0.4798, 0.5718, 0.6552, 0.7323, 0.8045, @@ -216,7 +216,7 @@ def setup_method(self): 1.3320, 1.3822, 1.4313, 1.4792, 1.5263, 1.5724, 1.6176, 1.6621, 1.7058, 1.7488 ]) - kA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} x = np.linspace(0, 2.5, 26) y = np.array([ @@ -224,14 +224,14 @@ def setup_method(self): 0.921, 1.000, 1.078, 1.154, 1.228, 1.302, 1.374, 1.446, 1.516, 1.585, 1.654, 1.722, 1.789, 1.855, 1.921, 1.986, 2.051 ]) - kA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} he.set_attr( - kA_char1=kA_char1, kA_char2=kA_char2, - offdesign=['zeta1', 'zeta2', 'kA_char'] + UA_char1=UA_char1, UA_char2=UA_char2, + offdesign=['zeta1_d4', 'zeta2_d4', 'UA_char'] ) - # characteristic line for condenser kA + # characteristic line for condenser UA x = np.linspace(0, 2.5, 26) y = np.array([ 0.0000, 0.2455, 0.3747, 0.4798, 0.5718, 0.6552, 0.7323, 0.8045, @@ -239,7 +239,7 @@ def setup_method(self): 1.3320, 1.3822, 1.4313, 1.4792, 1.5263, 1.5724, 1.6176, 1.6621, 1.7058, 1.7488 ]) - kA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char1 = {'char_func': CharLine(x, y), 'param': 'm'} x = np.linspace(0, 2.5, 26) y = np.array([ @@ -247,11 +247,11 @@ def setup_method(self): 0.921, 1.000, 1.078, 1.154, 1.228, 1.302, 1.374, 1.446, 1.516, 1.585, 1.654, 1.722, 1.789, 1.855, 1.921, 1.986, 2.051 ]) - kA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} + UA_char2 = {'char_func': CharLine(x, y), 'param': 'm'} cd.set_attr( - kA_char1=kA_char1, kA_char2=kA_char2, pr2=0.9998, - design=['pr2'], offdesign=['zeta2', 'kA_char'] + UA_char1=UA_char1, UA_char2=UA_char2, pr2=0.9998, + design=['pr2'], offdesign=['zeta2_d4', 'UA_char'] ) # condenser system diff --git a/tests/test_networks/test_network.py b/tests/test_networks/test_network.py index 87efe7b7..69f2e13f 100644 --- a/tests/test_networks/test_network.py +++ b/tests/test_networks/test_network.py @@ -812,13 +812,13 @@ def test_nonconverged_simulation_does_not_overwrite_component_specification_1(): nw.add_conns(c1, c2) c1.set_attr(m=0.1, fluid={"N2": 0.7, "O2": 0.15, "Water": 0.15}) c2.set_attr(p=1, T=20) - instance.set_attr(Q=1e4, zeta=1e6) + instance.set_attr(Q=1e4, zeta_d4=1e6) nw.solve("design") assert nw.status == 2 assert np.isnan(c1.T.val_SI) - assert instance.zeta.val == 1e6 - assert np.isnan(instance.zeta.val_SI) + assert instance.zeta_d4.val == 1e6 + assert np.isnan(instance.zeta_d4.val_SI) def test_nonconverged_simulation_does_not_overwrite_component_specification_2(): @@ -843,16 +843,16 @@ def test_nonconverged_simulation_does_not_overwrite_component_specification_2(): c1.set_attr(fluid={"H2O": 1}, T=30, p=1) c2.set_attr(T=19.5) - instance.set_attr(Tamb=20, kA=500, pr=1) + instance.set_attr(Tamb=20, UA=500, pr=1) nw.solve("design") assert nw.residual < 1e-3 # residual shows convergence assert nw.status == 2 # status shows non-convergence - assert np.isnan(instance.kA.val_SI) # calculated SI value is not equal to inputted value - assert instance.kA.val == 500 # inputted value stays the same + assert np.isnan(instance.UA.val_SI) # calculated SI value is not equal to inputted value + assert instance.UA.val == 500 # inputted value stays the same - # recalculation works, because old kA input is correctly retained + # recalculation works, because old UA input is correctly retained c2.set_attr(T=20.2) nw.solve("design") assert nw.status == 0 diff --git a/tests/test_networks/test_offdesign.py b/tests/test_networks/test_offdesign.py index f00b1dc1..fee6922f 100644 --- a/tests/test_networks/test_offdesign.py +++ b/tests/test_networks/test_offdesign.py @@ -64,12 +64,12 @@ def _build_network_and_designs(): c1.set_attr(fluid={"R290": 1}, T_dew=50, m=1) c2.set_attr(x=0) c3.set_attr(fluid={"water": 1}, p=2, T=30) - kA_char = load_default_char( - "HeatExchanger", "kA_char1", "DEFAULT", CharLine + UA_char = load_default_char( + "HeatExchanger", "UA_char1", "DEFAULT", CharLine ) heatex.set_attr( dp1=2, dp2=10, td_pinch=5, design=["td_pinch"], offdesign=["UA_char"], - kA_char1=kA_char, kA_char2=kA_char + UA_char1=UA_char, UA_char2=UA_char ) # design case 1: m = 1 kg/s @@ -432,11 +432,11 @@ def test_UA_char_char_expr_offdesign_design_reference(): nw.solve("offdesign", design_path=design1) nw.assert_convergence() - f1 = heatex.get_char_expr("m", **heatex.kA_char1.char_params) - f2 = heatex.get_char_expr("m", **heatex.kA_char2.char_params) + f1 = heatex.get_char_expr("m", **heatex.UA_char1.char_params) + f2 = heatex.get_char_expr("m", **heatex.UA_char2.char_params) - fUA1 = heatex.kA_char1.char_func.evaluate(f1) - fUA2 = heatex.kA_char2.char_func.evaluate(f2) + fUA1 = heatex.UA_char1.char_func.evaluate(f1) + fUA2 = heatex.UA_char2.char_func.evaluate(f2) fUA_a = 2 / (1 / fUA1 + 1 / fUA2) @@ -447,11 +447,11 @@ def test_UA_char_char_expr_offdesign_design_reference(): nw.solve("offdesign", design_path=design1) nw.assert_convergence() - f1 = heatex.get_char_expr("m", **heatex.kA_char1.char_params) - f2 = heatex.get_char_expr("m", **heatex.kA_char2.char_params) + f1 = heatex.get_char_expr("m", **heatex.UA_char1.char_params) + f2 = heatex.get_char_expr("m", **heatex.UA_char2.char_params) - fUA1 = heatex.kA_char1.char_func.evaluate(f1) - fUA2 = heatex.kA_char2.char_func.evaluate(f2) + fUA1 = heatex.UA_char1.char_func.evaluate(f1) + fUA2 = heatex.UA_char2.char_func.evaluate(f2) fUA_b = 2 / (1 / fUA1 + 1 / fUA2) @@ -703,7 +703,7 @@ def test_individual_design_path_on_connections_and_components(self): self.nw.assert_convergence() design1 = self.nw.save(as_dict=True) v1_design = self.sc1_v1.v.val_SI - zeta_sc1_design = self.sc1.zeta.val + zeta_sc1_design = self.sc1.zeta_d4.val self.sc2_v2.set_attr(T=95, state='l', m=None) self.sc1_v1.set_attr(m=0.001, T=None) @@ -711,7 +711,7 @@ def test_individual_design_path_on_connections_and_components(self): self.nw.assert_convergence() design2 = self.nw.save(as_dict=True) v2_design = self.sc2_v2.v.val_SI - zeta_sc2_design = self.sc2.zeta.val + zeta_sc2_design = self.sc2.zeta_d4.val self.sc1_v1.set_attr(m=None) self.sc1_v1.set_attr(design=['T'], offdesign=['v'], state='l') @@ -751,14 +751,14 @@ def test_individual_design_path_on_connections_and_components(self): # zeta value of solar collector comparison msg = ( - f"Value of zeta must be {zeta_sc1_design}, is {self.sc1.zeta.val}." + f"Value of zeta must be {zeta_sc1_design}, is {self.sc1.zeta_d4.val}." ) - assert round(zeta_sc1_design, 0) == round(self.sc1.zeta.val, 0), msg + assert round(zeta_sc1_design, 0) == round(self.sc1.zeta_d4.val, 0), msg msg = ( - f"Value of zeta must be {zeta_sc2_design}, is {self.sc2.zeta.val}." + f"Value of zeta must be {zeta_sc2_design}, is {self.sc2.zeta_d4.val}." ) - assert round(zeta_sc2_design, 0) == round(self.sc2.zeta.val, 0), msg + assert round(zeta_sc2_design, 0) == round(self.sc2.zeta_d4.val, 0), msg def test_local_offdesign_on_connections_and_components(self): """Test local offdesign feature."""