exerpy 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,19 +9,11 @@ from exerpy.components.component import component_registry
9
9
  @component_registry
10
10
  class SimpleHeatExchanger(Component):
11
11
  r"""
12
- Class for exergy analysis of simple heat exchangers.
12
+ Class for exergy and exergoeconomic analysis of simple heat exchangers.
13
13
 
14
- This class performs exergy analysis calculations for simple heat exchangers with
15
- one primary flow stream and heat transfer. The exergy product and fuel definitions
16
- vary based on the direction of heat transfer and temperature levels relative to
17
- ambient temperature.
18
-
19
- Parameters
20
- ----------
21
- **kwargs : dict
22
- Arbitrary keyword arguments passed to parent class.
23
- Optional parameter 'dissipative' (bool) to indicate if the component
24
- is considered fully dissipative.
14
+ This class performs exergy and exergoeconomic analysis calculations for heat exchanger components,
15
+ accounting for one inlet and one outlet stream across various temperature regimes, including
16
+ above and below ambient temperature, and optional dissipative behavior.
25
17
 
26
18
  Attributes
27
19
  ----------
@@ -34,117 +26,261 @@ class SimpleHeatExchanger(Component):
34
26
  epsilon : float
35
27
  Exergetic efficiency of the component :math:`\varepsilon` in :math:`-`.
36
28
  inl : dict
37
- Dictionary containing inlet stream data with temperature, mass flows,
38
- enthalpies, and specific exergies.
29
+ Dictionary containing inlet stream data with mass flows and specific exergies.
39
30
  outl : dict
40
- Dictionary containing outlet stream data with temperature, mass flows,
41
- enthalpies, and specific exergies.
31
+ Dictionary containing outlet stream data with mass flows and specific exergies.
32
+ Z_costs : float
33
+ Investment cost rate of the component in currency/h.
34
+ C_P : float
35
+ Cost of product stream :math:`\dot{C}_P` in currency/h.
36
+ C_F : float
37
+ Cost of fuel stream :math:`\dot{C}_F` in currency/h.
38
+ C_D : float
39
+ Cost of exergy destruction :math:`\dot{C}_D` in currency/h.
40
+ c_P : float
41
+ Specific cost of product stream (currency per unit exergy).
42
+ c_F : float
43
+ Specific cost of fuel stream (currency per unit exergy).
44
+ r : float
45
+ Relative cost difference, :math:`(c_P - c_F)/c_F`.
46
+ f : float
47
+ Exergoeconomic factor, :math:`\dot{Z}/(\dot{Z} + \dot{C}_D)`.
48
+ Ex_C_col : dict
49
+ Custom cost coefficients collection passed via `kwargs`.
50
+ """
42
51
 
43
- Notes
44
- -----
45
- The exergy analysis considers three main cases based on heat transfer direction
46
- and temperatures relative to ambient temperature :math:`T_0`:
52
+ def __init__(self, **kwargs):
53
+ r"""
54
+ Initialize the heat exchanger component.
47
55
 
48
- Case 1 - **Heat Release** (:math:`\dot{Q} < 0`):
56
+ Parameters
57
+ ----------
58
+ **kwargs : dict
59
+ Arbitrary keyword arguments. Recognized keys:
60
+ - dissipative (bool): whether component has dissipative behavior, default False
61
+ - Ex_C_col (dict): custom cost coefficients, default {}
62
+ - Z_costs (float): investment cost rate in currency/h, default 0.0
63
+ """
64
+ super().__init__(**kwargs)
49
65
 
50
- a) Both temperatures above ambient:
66
+ def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy) -> None:
67
+ r"""
68
+ Compute the exergy balance of the simple heat exchanger.
51
69
 
52
- .. math::
53
- \dot{E}_\mathrm{P} &= \dot{m} \cdot (e^\mathrm{T}_\mathrm{in} -
54
- e^\mathrm{T}_\mathrm{out})\\
55
- \dot{E}_\mathrm{F} &= \dot{m} \cdot (e^\mathrm{PH}_\mathrm{in} -
56
- e^\mathrm{PH}_\mathrm{out})
70
+ **Heat release** :math:\dot{Q}<0
57
71
 
58
- b) Inlet above, outlet below ambient:
72
+ Case 1: Both streams above ambient temperature
59
73
 
60
- .. math::
61
- \dot{E}_\mathrm{P} &= \dot{m}_\mathrm{out} \cdot e^\mathrm{T}_\mathrm{out}\\
62
- \dot{E}_\mathrm{F} &= \dot{m}_\mathrm{in} \cdot e^\mathrm{T}_\mathrm{in} +
63
- \dot{m}_\mathrm{out} \cdot e^\mathrm{T}_\mathrm{out} +
64
- (\dot{m}_\mathrm{in} \cdot e^\mathrm{M}_\mathrm{in} -
65
- \dot{m}_\mathrm{out} \cdot e^\mathrm{M}_\mathrm{out})
74
+ If split_physical_exergy=True:
66
75
 
67
- c) Both temperatures below ambient:
76
+ .. math::
68
77
 
69
- .. math::
70
- \dot{E}_\mathrm{P} &= \dot{m}_\mathrm{out} \cdot
71
- (e^\mathrm{T}_\mathrm{out} - e^\mathrm{T}_\mathrm{in})\\
72
- \dot{E}_\mathrm{F} &= \dot{E}_\mathrm{P} + \dot{m}_\mathrm{in} \cdot
73
- (e^\mathrm{M}_\mathrm{in} - e^\mathrm{M}_\mathrm{out})
78
+ \dot{E}_{\mathrm{P}}
79
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
80
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}
74
81
 
75
- Case 2 - **Heat Addition** (:math:`\dot{Q} > 0`):
82
+ .. math::
76
83
 
77
- a) Both temperatures above ambient:
84
+ \dot{E}_{\mathrm{F}}
85
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
86
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
78
87
 
79
- .. math::
80
- \dot{E}_\mathrm{P} &= \dot{m}_\mathrm{out} \cdot
81
- (e^\mathrm{PH}_\mathrm{out} - e^\mathrm{PH}_\mathrm{in})\\
82
- \dot{E}_\mathrm{F} &= \dot{m}_\mathrm{out} \cdot
83
- (e^\mathrm{T}_\mathrm{out} - e^\mathrm{T}_\mathrm{in})
88
+ Else:
84
89
 
85
- b) Inlet below, outlet above ambient:
90
+ .. math::
86
91
 
87
- .. math::
88
- \dot{E}_\mathrm{P} &= \dot{m}_\mathrm{out} \cdot
89
- (e^\mathrm{T}_\mathrm{out} + e^\mathrm{T}_\mathrm{in})\\
90
- \dot{E}_\mathrm{F} &= \dot{m}_\mathrm{in} \cdot e^\mathrm{T}_\mathrm{in} +
91
- (\dot{m}_\mathrm{in} \cdot e^\mathrm{M}_\mathrm{in} -
92
- \dot{m}_\mathrm{out} \cdot e^\mathrm{M}_\mathrm{out})
92
+ \dot{E}_{\mathrm{P}}
93
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
94
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
93
95
 
94
- c) Both temperatures below ambient:
96
+ .. math::
95
97
 
96
- .. math::
97
- \dot{E}_\mathrm{P} &= \dot{m}_\mathrm{in} \cdot
98
- (e^\mathrm{T}_\mathrm{in} - e^\mathrm{T}_\mathrm{out}) +
99
- (\dot{m}_\mathrm{out} \cdot e^\mathrm{M}_\mathrm{out} -
100
- \dot{m}_\mathrm{in} \cdot e^\mathrm{M}_\mathrm{in})\\
101
- \dot{E}_\mathrm{F} &= \dot{m}_\mathrm{in} \cdot
102
- (e^\mathrm{T}_\mathrm{in} - e^\mathrm{T}_\mathrm{out})
98
+ \dot{E}_{\mathrm{F}}
99
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
100
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
103
101
 
104
- Case 3 - **Dissipative** (it is not possible to specify the exergy product :math:`\dot{E}_\mathrm{P}` for this component):
102
+ Case 2: Inlet above and outlet below ambient temperature
105
103
 
106
- .. math::
107
- \dot{E}_\mathrm{P} &= \mathrm{NaN}\\
108
- \dot{E}_\mathrm{F} &= \dot{m}_\mathrm{in} \cdot
109
- (e^\mathrm{PH}_\mathrm{in} - e^\mathrm{PH}_\mathrm{out})
104
+ If split_physical_exergy=True:
110
105
 
111
- For all cases, the exergy destruction is calculated as:
106
+ .. math::
112
107
 
113
- .. math::
114
- \dot{E}_\mathrm{D} = \dot{E}_\mathrm{F} - \dot{E}_\mathrm{P}
108
+ \dot{E}_{\mathrm{P}}
109
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
115
110
 
116
- Where:
117
- - :math:`e^\mathrm{T}`: Thermal exergy
118
- - :math:`e^\mathrm{PH}`: Physical exergy
119
- - :math:`e^\mathrm{M}`: Mechanical exergy
120
- """
111
+ .. math::
121
112
 
122
- def __init__(self, **kwargs):
123
- r"""Initialize simple heat exchanger component with given parameters."""
124
- super().__init__(**kwargs)
113
+ \dot{E}_{\mathrm{F}}
114
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
115
+ + \dot{E}^{\mathrm{T}}_{\mathrm{out}}
116
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{in}}
117
+ - \dot{E}^{\mathrm{M}}_{\mathrm{out}}\bigr)
125
118
 
126
- def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy) -> None:
127
- r"""
128
- Calculate the exergy balance of the simple heat exchanger.
119
+ Else:
120
+
121
+ .. math::
122
+
123
+ \dot{E}_{\mathrm{P}}
124
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
125
+
126
+ .. math::
127
+
128
+ \dot{E}_{\mathrm{F}}
129
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
130
+
131
+ Case 3: Both streams below ambient temperature
132
+
133
+ If split_physical_exergy=True:
134
+
135
+ .. math::
136
+
137
+ \dot{E}_{\mathrm{P}}
138
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
139
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}
140
+
141
+ .. math::
142
+
143
+ \dot{E}_{\mathrm{F}}
144
+ = \bigl(\dot{E}^{\mathrm{T}}_{\mathrm{out}}
145
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}\bigr)
146
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{in}}
147
+ - \dot{E}^{\mathrm{M}}_{\mathrm{out}}\bigr)
148
+
149
+ Else:
150
+
151
+ .. math::
152
+
153
+ \dot{E}_{\mathrm{P}}
154
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
155
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
156
+
157
+ .. math::
158
+
159
+ \dot{E}_{\mathrm{F}}
160
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
161
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
162
+
163
+ **Heat injection** :math:\dot{Q}>0
164
+
165
+ Case 1: Both streams above ambient temperature
166
+
167
+ If split_physical_exergy=True:
168
+
169
+ .. math::
170
+
171
+ \dot{E}_{\mathrm{P}}
172
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
173
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
174
+
175
+ .. math::
129
176
 
130
- Performs exergy balance calculations considering both heat transfer direction
131
- and temperature levels relative to ambient temperature.
177
+ \dot{E}_{\mathrm{F}}
178
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
179
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}
180
+
181
+ Else:
182
+
183
+ .. math::
184
+
185
+ \dot{E}_{\mathrm{P}}
186
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
187
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
188
+
189
+ .. math::
190
+
191
+ \dot{E}_{\mathrm{F}}
192
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
193
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
194
+
195
+ Case 2: Inlet below and outlet above ambient temperature
196
+
197
+ If split_physical_exergy=True:
198
+
199
+ .. math::
200
+
201
+ \dot{E}_{\mathrm{P}}
202
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
203
+ + \dot{E}^{\mathrm{T}}_{\mathrm{in}}
204
+
205
+ .. math::
206
+
207
+ \dot{E}_{\mathrm{F}}
208
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
209
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{in}}
210
+ - \dot{E}^{\mathrm{M}}_{\mathrm{out}}\bigr)
211
+
212
+ Else:
213
+
214
+ .. math::
215
+
216
+ \dot{E}_{\mathrm{P}}
217
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
218
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
219
+
220
+ .. math::
221
+
222
+ \dot{E}_{\mathrm{F}}
223
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
224
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
225
+
226
+ Case 3: Both streams below ambient temperature
227
+
228
+ If split_physical_exergy=True:
229
+
230
+ .. math::
231
+
232
+ \dot{E}_{\mathrm{P}}
233
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
234
+ - \dot{E}^{\mathrm{T}}_{\mathrm{out}}
235
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{out}}
236
+ - \dot{E}^{\mathrm{M}}_{\mathrm{in}}\bigr)
237
+
238
+ .. math::
239
+
240
+ \dot{E}_{\mathrm{F}}
241
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
242
+ - \dot{E}^{\mathrm{T}}_{\mathrm{out}}
243
+
244
+ Else:
245
+
246
+ .. math::
247
+
248
+ \dot{E}_{\mathrm{P}}
249
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
250
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
251
+
252
+ .. math::
253
+
254
+ \dot{E}_{\mathrm{F}}
255
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
256
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
257
+
258
+ Fully dissipative or :math:\dot{Q}=0
259
+
260
+ .. math::
261
+
262
+ \dot{E}_{\mathrm{P}} = \mathrm{NaN}
263
+
264
+ .. math::
265
+
266
+ \dot{E}_{\mathrm{F}}
267
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
268
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
132
269
 
133
270
  Parameters
134
271
  ----------
135
272
  T0 : float
136
- Ambient temperature in :math:`\mathrm{K}`.
273
+ Ambient temperature (K).
137
274
  p0 : float
138
- Ambient pressure in :math:`\mathrm{Pa}`.
275
+ Ambient pressure (Pa).
139
276
  split_physical_exergy : bool
140
- Flag indicating whether physical exergy is split into thermal and mechanical components.
277
+ Whether to split thermal and mechanical exergy.
141
278
 
142
279
  Raises
143
280
  ------
144
281
  ValueError
145
- If the required inlet and outlet streams are not properly defined or
146
- exceed the maximum allowed number.
147
- """
282
+ If required inlet or outlet are missing.
283
+ """
148
284
  # Validate the number of inlets and outlets
149
285
  if not hasattr(self, 'inl') or not hasattr(self, 'outl') or len(self.inl) < 1 or len(self.outl) < 1:
150
286
  msg = "SimpleHeatExchanger requires at least one inlet and one outlet as well as one heat flow."
@@ -259,83 +395,51 @@ class SimpleHeatExchanger(Component):
259
395
 
260
396
 
261
397
  def aux_eqs(self, A, b, counter, T0, equations, chemical_exergy_enabled):
398
+ r"""
399
+ This function must be implemented in the future.
400
+
401
+ The exergoeconomic analysis of SimpleHeatExchanger is not implemented yet.
262
402
  """
263
- Auxiliary equations for the simple heat exchanger.
264
-
265
- This function adds rows to the cost matrix A and the right-hand-side vector b to enforce
266
- the following auxiliary cost relations:
267
403
 
268
- (1) Thermal exergy cost equation:
269
- - For heat release (T_in > T_out > T0): F-principle is applied
270
- 1/E_T_in * C_T_in - 1/E_T_out * C_T_out = 0
271
- - For heat addition (T_in < T_out > T0): P-principle is applied
272
- 1/ΔE_T * (C_T_out - C_T_in) = 1/ΔE_M * (C_M_out - C_M_in)
273
-
274
- (2) Mechanical exergy cost equation:
275
- 1/E_M_in * C_M_in - 1/E_M_out * C_M_out = 0
276
- - F-principle: specific mechanical exergy costs equalized between inlet/outlet
277
-
278
- (3) Chemical exergy cost equation (if enabled):
279
- 1/E_CH_in * C_CH_in - 1/E_CH_out * C_CH_out = 0
280
- - F-principle: specific chemical exergy costs equalized between inlet/outlet
281
-
282
- Parameters
283
- ----------
284
- A : numpy.ndarray
285
- The current cost matrix.
286
- b : numpy.ndarray
287
- The current right-hand-side vector.
288
- counter : int
289
- The current row index in the matrix.
290
- T0 : float
291
- Ambient temperature.
292
- equations : dict
293
- Dictionary for storing equation labels.
294
- chemical_exergy_enabled : bool
295
- Flag indicating whether chemical exergy auxiliary equations should be added.
296
-
297
- Returns
298
- -------
299
- A : numpy.ndarray
300
- The updated cost matrix.
301
- b : numpy.ndarray
302
- The updated right-hand-side vector.
303
- counter : int
304
- The updated row index.
305
- equations : dict
306
- Updated dictionary with equation labels.
307
- """
308
- # --- Thermal cost equation (row counter) ---
309
- if self.inl[0]["T"] > T0 and self.outl[0]["T"] > T0:
310
- if self.inl[0]["T"] > self.outl[0]["T"]:
311
- # Heat is released (turbine-like behavior, f‑rule).
312
- A[counter, self.inl[0]["CostVar_index"]["T"]] = (1 / self.inl[0]["e_T"]
313
- if self.inl[0]["e_T"] != 0 else 1)
314
- A[counter, self.outl[0]["CostVar_index"]["T"]] = (-1 / self.outl[0]["e_T"]
315
- if self.outl[0]["e_T"] != 0 else -1)
316
- equations[counter] = f"aux_f_rule_{self.name}"
317
- elif self.inl[0]["T"] < self.outl[0]["T"]:
318
- # Heat is injected (compressor-like behavior, p‑rule):
319
- dET = self.outl[0]["e_T"] - self.inl[0]["e_T"]
320
- dEM = self.outl[0]["e_M"] - self.inl[0]["e_M"]
321
- if dET != 0 and dEM != 0:
322
- A[counter, self.inl[0]["CostVar_index"]["T"]] = -1 / dET
323
- A[counter, self.outl[0]["CostVar_index"]["T"]] = 1 / dET
324
- A[counter, self.inl[0]["CostVar_index"]["M"]] = 1 / dEM
325
- A[counter, self.outl[0]["CostVar_index"]["M"]] = -1 / dEM
326
- equations[counter] = f"aux_p_rule_{self.name}"
327
- else:
328
- logging.warning("SimpleHeatExchanger: dET or dEM is zero; case not implemented.")
329
- equations[counter] = "aux_unimpl_HEX"
330
- else:
331
- logging.warning("SimpleHeatExchanger: Inlet and outlet temperatures are equal; case not implemented.")
332
- equations[counter] = "aux_unimpl_HEX"
333
- else:
334
- logging.warning("SimpleHeatExchanger: Cases with T_in or T_out below T0 are not implemented.")
335
- equations[counter] = "aux_unimpl_HEX"
404
+ logging.error(
405
+ "The exergoeconomic analysis of SimpleHeatExchanger is not implemented yet. "
406
+ "This method will be implemented in a future release."
407
+ )
408
+ r"""
409
+ Add auxiliary cost equations for the heat exchanger.
410
+
411
+ For all cases:
412
+
413
+ .. math::
414
+ -\frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{out}}}\,\dot{C}^{\mathrm{T}}_{\mathrm{out}}
415
+ + \frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{in}}}\,\dot{C}^{\mathrm{Tc}}_{\mathrm{in}}
416
+ = 0
417
+
418
+ F rule for mechanical exergy:
419
+
420
+ .. math::
421
+ -\frac{1}{\dot{E}^{\mathrm{M}}_{\mathrm{out}}\,\dot{C}^{\mathrm{M}}_{\mathrm{out}}
422
+ + \frac{1}{\dot{E}^{\mathrm{M}}_{\mathrm{in}}\,\dot{C}^{\mathrm{M}}_{\mathrm{in}}
423
+ = 0
424
+
425
+ F rule for chemical exergy:
426
+
427
+ .. math::
428
+ -\frac{1}{\dot{E}^{\mathrm{CH}}_{\mathrm{out}}}\,\dot{C}^{\mathrm{CH}}_{\mathrm{out}}
429
+ + \frac{1}{\dot{E}^{\mathrm{CH}}_{\mathrm{in}}}\,\dot{C}^{\mathrm{CH}}_{\mathrm{in}}
430
+ = 0
431
+
432
+ """
433
+ """# For all cases: c_Tin = c_Tout
434
+ A[counter, self.inl[0]["CostVar_index"]["T"]] = (1 / self.inl[0]["e_T"]
435
+ if self.inl[0]["e_T"] != 0 else 1)
436
+ A[counter, self.outl[0]["CostVar_index"]["T"]] = (-1 / self.outl[0]["e_T"]
437
+ if self.outl[0]["e_T"] != 0 else -1)
438
+ equations[counter] = f"aux_equality_therm_{self.outl[0]['name']}"
439
+
336
440
  b[counter] = 0
337
441
 
338
- # --- Mechanical cost equality (row counter+1) ---
442
+ # For alle cases: c_Min = c_Mout
339
443
  A[counter+1, self.inl[0]["CostVar_index"]["M"]] = (1 / self.inl[0]["e_M"]
340
444
  if self.inl[0]["e_M"] != 0 else 1)
341
445
  A[counter+1, self.outl[0]["CostVar_index"]["M"]] = (-1 / self.outl[0]["e_M"]
@@ -343,7 +447,7 @@ class SimpleHeatExchanger(Component):
343
447
  equations[counter+1] = f"aux_equality_mech_{self.outl[0]['name']}"
344
448
  b[counter+1] = 0
345
449
 
346
- # --- Chemical cost equality (conditionally added) ---
450
+ # For all cases: c_CHin = c_CHout
347
451
  if chemical_exergy_enabled:
348
452
  A[counter+2, self.inl[0]["CostVar_index"]["CH"]] = (1 / self.inl[0]["e_CH"]
349
453
  if self.inl[0]["e_CH"] != 0 else 1)
@@ -355,4 +459,150 @@ class SimpleHeatExchanger(Component):
355
459
  else:
356
460
  counter += 2
357
461
 
358
- return A, b, counter, equations
462
+ return A, b, counter, equations"""
463
+
464
+ def exergoeconomic_balance(self, T0):
465
+ r"""
466
+ This function must be implemented in the future.
467
+
468
+ The exergoeconomic analysis of SimpleHeatExchanger is not implemented yet.
469
+ """
470
+
471
+ logging.error(
472
+ "The exergoeconomic analysis of SimpleHeatExchanger is not implemented yet. "
473
+ "This method will be implemented in a future release."
474
+ )
475
+ r"""
476
+ Perform exergoeconomic cost balance for the simple heat exchanger.
477
+
478
+ .. math::
479
+ \dot{C}^{\mathrm{T}}_{\mathrm{in}}
480
+ + \dot{C}^{\mathrm{M}}_{\mathrm{in}}
481
+ - \dot{C}^{\mathrm{T}}_{\mathrm{out}}
482
+ - \dot{C}^{\mathrm{M}}_{\mathrm{out}}
483
+ + \dot{Z}
484
+ = 0
485
+
486
+ In case the chemical exergy of the streams is know:
487
+
488
+ .. math::
489
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in},1} =
490
+ \dot{C}^{\mathrm{CH}}_{\mathrm{out},1}
491
+
492
+ .. math::
493
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in},2} =
494
+ \dot{C}^{\mathrm{CH}}_{\mathrm{out},2}
495
+
496
+ This method computes cost coefficients and ratios:
497
+
498
+ **Heat release** :math:\dot{Q}<0
499
+
500
+ Case 1: Both streams above ambient temperature
501
+
502
+ .. math::
503
+
504
+ \dot{E}_{\mathrm{P}}
505
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
506
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}
507
+
508
+ .. math::
509
+
510
+ \dot{E}_{\mathrm{F}}
511
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
512
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
513
+
514
+ Case 2: Inlet above and outlet below ambient temperature
515
+
516
+ .. math::
517
+
518
+ \dot{E}_{\mathrm{P}}
519
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
520
+
521
+ .. math::
522
+
523
+ \dot{E}_{\mathrm{F}}
524
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
525
+ + \dot{E}^{\mathrm{T}}_{\mathrm{out}}
526
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{in}}
527
+ - \dot{E}^{\mathrm{M}}_{\mathrm{out}}\bigr)
528
+
529
+ Case 3: Both streams below ambient temperature
530
+
531
+ .. math::
532
+
533
+ \dot{E}_{\mathrm{P}}
534
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
535
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}
536
+
537
+ .. math::
538
+
539
+ \dot{E}_{\mathrm{F}}
540
+ = \bigl(\dot{E}^{\mathrm{T}}_{\mathrm{out}}
541
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}\bigr)
542
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{in}}
543
+ - \dot{E}^{\mathrm{M}}_{\mathrm{out}}\bigr)
544
+
545
+ **Heat injection** :math:\dot{Q}
546
+
547
+ Case 1: Both streams above ambient temperature
548
+
549
+ .. math::
550
+
551
+ \dot{E}_{\mathrm{P}}
552
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
553
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
554
+
555
+ .. math::
556
+
557
+ \dot{E}_{\mathrm{F}}
558
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
559
+ - \dot{E}^{\mathrm{T}}_{\mathrm{in}}
560
+
561
+ Case 2: Inlet below and outlet above ambient temperature
562
+
563
+ .. math::
564
+
565
+ \dot{E}_{\mathrm{P}}
566
+ = \dot{E}^{\mathrm{T}}_{\mathrm{out}}
567
+ + \dot{E}^{\mathrm{T}}_{\mathrm{in}}
568
+
569
+ .. math::
570
+
571
+ \dot{E}_{\mathrm{F}}
572
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
573
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{in}}
574
+ - \dot{E}^{\mathrm{M}}_{\mathrm{out}}\bigr)
575
+
576
+ Case 3: Both streams below ambient temperature
577
+
578
+ .. math::
579
+
580
+ \dot{E}_{\mathrm{P}}
581
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
582
+ - \dot{E}^{\mathrm{T}}_{\mathrm{out}}
583
+ + \bigl(\dot{E}^{\mathrm{M}}_{\mathrm{out}}
584
+ - \dot{E}^{\mathrm{M}}_{\mathrm{in}}\bigr)
585
+
586
+ .. math::
587
+
588
+ \dot{E}_{\mathrm{F}}
589
+ = \dot{E}^{\mathrm{T}}_{\mathrm{in}}
590
+ - \dot{E}^{\mathrm{T}}_{\mathrm{out}}
591
+
592
+ Fully dissipative or :math:\dot{Q}=0
593
+
594
+ .. math::
595
+
596
+ \dot{E}_{\mathrm{P}} = \mathrm{NaN}
597
+
598
+ .. math::
599
+
600
+ \dot{E}_{\mathrm{F}}
601
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in}}
602
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out}}
603
+
604
+ Parameters
605
+ ----------
606
+ T0 : float
607
+ Ambient temperature (K).
608
+ """