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.
@@ -6,94 +6,91 @@ from exerpy.components.component import component_registry
6
6
 
7
7
  @component_registry
8
8
  class Condenser(Component):
9
- """
10
- Condenser component class.
9
+ r"""
10
+ Class for exergy and exergoeconomic analysis of condensers (only dissipative).
11
11
 
12
- This class represents a condenser within the system, responsible for
13
- calculating the exergy balance specific to condensation processes.
14
- It evaluates the exergy interactions between multiple inlet and outlet
15
- streams to determine exergy loss and exergy destruction.
12
+ This class performs exergy and exergoeconomic analysis calculations for condenser components,
13
+ accounting for two inlet and two outlet streams. This class should be used only for dissipative
14
+ condensers. For non-dissipative condensers, use components that are modeled in ExerPy using the
15
+ `HeatExchanger` class.
16
16
 
17
17
  Attributes
18
18
  ----------
19
- E_L : float
20
- Exergy loss associated with heat transfer (difference in physical exergy
21
- between specific outlet and inlet streams).
19
+ E_F : float
20
+ Exergy fuel of the component :math:`\dot{E}_\mathrm{F}` in :math:`\mathrm{W}`.
22
21
  E_D : float
23
- Exergy destruction, calculated as the difference between the primary
24
- inlet and outlet streams minus exergy loss (E_L), representing
25
- irreversibilities in the condensation process.
26
- E_P : None
27
- Exergy product, not defined for a condenser as there is no exergy output
28
- intended for productive use.
29
- E_F : None
30
- Exergy fuel, typically undefined for a condenser as it does not involve
31
- an external exergy input for production purposes.
32
- epsilon : None
33
- Exergy efficiency, not applicable to a condenser due to the nature of
34
- exergy interactions focused on loss and destruction.
35
-
36
- Methods
37
- -------
38
- __init__(**kwargs)
39
- Initializes the Condenser component with given parameters.
40
- calc_exergy_balance(T0, p0)
41
- Calculates the exergy balance of the condenser.
22
+ Exergy destruction of the component :math:`\dot{E}_\mathrm{D}` in :math:`\mathrm{W}`.
23
+ E_L : float
24
+ Exergy loss of the component :math:`\dot{E}_\mathrm{L}` in :math:`\mathrm{W}`.
25
+ inl : dict
26
+ Dictionary containing inlet stream data with mass flows and specific exergies.
27
+ outl : dict
28
+ Dictionary containing outlet stream data with mass flows and specific exergies.
29
+ Z_costs : float
30
+ Investment cost rate of the component in currency/h.
31
+ C_F : float
32
+ Cost of fuel stream :math:`\dot{C}_F` in currency/h.
33
+ C_D : float
34
+ Cost of exergy destruction :math:`\dot{C}_D` in currency/h.
35
+ c_F : float
36
+ Specific cost of fuel stream (currency per unit exergy).
37
+ f : float
38
+ Exergoeconomic factor, :math:`\dot{Z}/(\dot{Z} + \dot{C}_D)`.
39
+ Ex_C_col : dict
40
+ Custom cost coefficients collection passed via `kwargs`.
42
41
  """
43
42
 
44
43
  def __init__(self, **kwargs):
45
- """
46
- Initialize the Condenser component.
44
+ r"""
45
+ Initialize the condenser component.
47
46
 
48
47
  Parameters
49
48
  ----------
50
49
  **kwargs : dict
51
- Arbitrary keyword arguments passed to the base class initializer.
50
+ Arbitrary keyword arguments. Recognized keys:
51
+ - Ex_C_col (dict): custom cost coefficients, default {}
52
+ - Z_costs (float): investment cost rate in currency/h, default 0.0
52
53
  """
53
54
  super().__init__(**kwargs)
54
55
 
55
56
  def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy) -> None:
56
- """
57
- Calculate the exergy balance of the condenser.
57
+ r"""
58
+ Compute the exergy balance of the condenser.
59
+
60
+ In order to distinguish between the exergetic destruction because of heat transfer
61
+ and the exergetic loss (coldf stream leaving the system) the exergetic losses and
62
+ destruction are calculated as follows:
63
+
64
+ .. math::
65
+
66
+ \dot{E}_{\mathrm{L}}
67
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{out},2}
68
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{in},2}
69
+
70
+ .. math::
58
71
 
59
- This method computes exergy loss and exergy destruction based on the inlet
60
- and outlet streams involved in the condensation process.
72
+ \dot{E}_{\mathrm{D}}
73
+ = \dot{E}^{\mathrm{PH}}_{\mathrm{in},1}
74
+ - \dot{E}^{\mathrm{PH}}_{\mathrm{out},1}
75
+ - \dot{E}_{\mathrm{L}}
76
+
77
+ However, these value can only be accessed via the attributes `E_L` and `E_D` of the component.
78
+ In the table of final results of the exergy analysis of the system, the exergy destruction of
79
+ the condenser is counted as the exergy loss and the exergetic destruction due to heat transfer.
61
80
 
62
81
  Parameters
63
82
  ----------
64
83
  T0 : float
65
- Reference temperature in Kelvin.
84
+ Ambient temperature (K).
66
85
  p0 : float
67
- Reference pressure in Pascals.
86
+ Ambient pressure (Pa).
68
87
  split_physical_exergy : bool
69
- Flag indicating whether physical exergy is split into thermal and mechanical components.
88
+ Whether to split thermal and mechanical exergy.
70
89
 
71
90
  Raises
72
91
  ------
73
92
  ValueError
74
- If the condenser does not have exactly two inlets and two outlets.
75
-
76
- Calculation Details
77
- -------------------
78
- The exergy balance is determined based on exergy transfer due to heat loss (`E_L`)
79
- and the exergy destruction within the system:
80
-
81
- - **Exergy Loss (E_L)**:
82
- \[
83
- E_L = \dot{m}_{\mathrm{out,1}} \cdot (e_{\mathrm{PH,out,1}} - e_{\mathrm{PH,in,1}})
84
- \]
85
- Represents the exergy loss due to heat transfer from the process.
86
-
87
- - **Exergy Destruction (E_D)**:
88
- \[
89
- E_D = \dot{m}_{\mathrm{out,0}} \cdot (e_{\mathrm{PH,in,0}} - e_{\mathrm{PH,out,0}}) - E_L
90
- \]
91
- Accounts for the irreversibilities and losses in the condenser.
92
-
93
- Note
94
- ----
95
- Exergy product (E_P) and exergy fuel (E_F) are generally undefined in a
96
- condenser due to the focus on exergy loss rather than productive exergy usage.
93
+ If required inlets or outlets are missing.
97
94
  """
98
95
  # Ensure that the component has both inlet and outlet streams
99
96
  if len(self.inl) < 2 or len(self.outl) < 2:
@@ -115,54 +112,106 @@ class Condenser(Component):
115
112
 
116
113
 
117
114
  def aux_eqs(self, A, b, counter, T0, equations, chemical_exergy_enabled):
118
- """
119
- Auxiliary equations for the condenser.
120
-
121
- This function adds rows to the cost matrix A and the right-hand-side vector b to enforce
122
- the following auxiliary cost relations:
123
-
124
- (1) Thermal auxiliary equation based on temperature cases:
125
- - Case 1 (T > T0): c_T(hot_inlet)/E_T(hot_in) = c_T(hot_outlet)/E_T(hot_out)
126
- F-principle: specific thermal exergy costs equalized in hot stream
127
- - Case 2 (T <= T0): c_T(cold_inlet)/E_T(cold_in) = c_T(cold_outlet)/E_T(cold_out)
128
- F-principle: specific thermal exergy costs equalized in cold stream
129
- - Case 3 (mixed temperatures): c_T(hot_outlet)/E_T(hot_out) = c_T(cold_outlet)/E_T(cold_out)
130
- P-principle: equal specific costs of thermal exergy in outlets
131
-
132
- (2) c_M(hot_inlet)/E_M(hot_in) = c_M(hot_outlet)/E_M(hot_out)
133
- - F-principle: specific mechanical exergy costs equalized in hot stream
134
-
135
- (3) c_M(cold_inlet)/E_M(cold_in) = c_M(cold_outlet)/E_M(cold_out)
136
- - F-principle: specific mechanical exergy costs equalized in cold stream
137
-
138
- (4-5) Chemical exergy cost equations (if enabled) for hot and cold streams
139
- - F-principle: specific chemical exergy costs equalized between inlets/outlets
140
-
115
+ r"""
116
+ Add auxiliary cost equations for the condenser.
117
+
118
+ This method appends rows to the cost matrix to enforce:
119
+
120
+ Case 1: All streams above ambient temperature
121
+
122
+ F rule for thermal exergy of the hot stream:
123
+
124
+ .. math::
125
+ -\frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{out},1}}\,\dot{C}^{\mathrm{T}}_{\mathrm{out},1}
126
+ + \frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{in},1}}\,\dot{C}^{\mathrm{T}}_{\mathrm{in},1}
127
+ = 0
128
+
129
+ Case 2: All streams below or equal to ambient temperature
130
+
131
+ F rule for thermal exergy of the cold stream:
132
+
133
+ .. math::
134
+ -\frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{out},2}}\,\dot{C}^{\mathrm{T}}_{\mathrm{out},2}
135
+ + \frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{in},2}}\,\dot{C}^{\mathrm{T}}_{\mathrm{in},2}
136
+ = 0
137
+
138
+ Case 3: Both stream crossing ambient temperature
139
+
140
+ P rule for thermal exergy of both outlets:
141
+
142
+ .. math::
143
+ -\frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{out},1}}\,\dot{C}^{\mathrm{T}}_{\mathrm{out},1}
144
+ + \frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{out},2}}\,\dot{C}^{\mathrm{T}}_{\mathrm{out},2}
145
+ = 0
146
+
147
+ Case 4: Only the hot inlet above ambient temperature
148
+
149
+ F rule for thermal exergy of the cold stream:
150
+
151
+ .. math::
152
+ -\frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{out},2}}\,\dot{C}^{\mathrm{T}}_{\mathrm{out},2}
153
+ + \frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{in},2}}\,\dot{C}^{\mathrm{T}}_{\mathrm{in},2}
154
+ = 0
155
+
156
+ Case 5: Only the cold inlet below ambient temperature
157
+
158
+ F rule for thermal exergy of the hot stream:
159
+
160
+ .. math::
161
+ -\frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{out},1}}\,\dot{C}^{\mathrm{T}}_{\mathrm{out},1}
162
+ + \frac{1}{\dot{E}^{\mathrm{T}}_{\mathrm{in},1}}\,\dot{C}^{\mathrm{T}}_{\mathrm{in},1}
163
+ = 0
164
+
165
+ Case 6: Hot stream always above and cold stream always below ambiente temperature (dissipative case):
166
+
167
+ The dissipative is not handeld here!
168
+
169
+ For all cases, the mechanical and chemical exergy costs are handled as follows:
170
+
171
+ F rule for mechanical exergy of the hot stream:
172
+
173
+ .. math::
174
+ -\frac{1}{\dot{E}^{\mathrm{M}}_{\mathrm{out},i}}\,\dot{C}^{\mathrm{M}}_{\mathrm{out},i}
175
+ + \frac{1}{\dot{E}^{\mathrm{M}}_{\mathrm{in},i}}\,\dot{C}^{\mathrm{M}}_{\mathrm{in},i}
176
+ = 0
177
+
178
+ F rule for chemical exergy on hot branch:
179
+
180
+ .. math::
181
+ -\frac{1}{\dot{E}^{\mathrm{CH}}_{\mathrm{out},i}}\,\dot{C}^{\mathrm{CH}}_{\mathrm{out},i}
182
+ + \frac{1}{\dot{E}^{\mathrm{CH}}_{\mathrm{in},i}}\,\dot{C}^{\mathrm{CH}}_{\mathrm{in},i}
183
+ = 0
184
+
141
185
  Parameters
142
186
  ----------
143
187
  A : numpy.ndarray
144
- The current cost matrix.
188
+ Current cost matrix.
145
189
  b : numpy.ndarray
146
- The current right-hand-side vector.
190
+ Current RHS vector.
147
191
  counter : int
148
- The current row index in the matrix.
192
+ Starting row index for auxiliary equations.
149
193
  T0 : float
150
- Ambient temperature.
151
- equations : dict
152
- Dictionary for storing equation labels.
194
+ Ambient temperature (K).
195
+ equations : dict or list
196
+ Structure for equation labels.
153
197
  chemical_exergy_enabled : bool
154
- Flag indicating whether chemical exergy auxiliary equations should be added.
155
-
198
+ Must be True to include chemical exergy mixing.
199
+
156
200
  Returns
157
201
  -------
158
202
  A : numpy.ndarray
159
- The updated cost matrix.
203
+ Updated cost matrix.
160
204
  b : numpy.ndarray
161
- The updated right-hand-side vector.
205
+ Updated RHS vector.
162
206
  counter : int
163
- The updated row index.
164
- equations : dict
165
- Updated dictionary with equation labels.
207
+ Updated row index after adding equations.
208
+ equations : dict or list
209
+ Updated labels.
210
+
211
+ Raises
212
+ ------
213
+ ValueError
214
+ If required cost variable indices are missing.
166
215
  """
167
216
  # Equality equation for mechanical and chemical exergy costs.
168
217
  def set_equal(A, row, in_item, out_item, var):
@@ -222,25 +271,42 @@ class Condenser(Component):
222
271
  set_thermal_f_hot(A, counter + 0)
223
272
  equations[counter] = f"aux_f_rule_hot_{self.name}"
224
273
  # Case 2: All temperatures <= T0.
225
- elif all([c["T"] <= T0 for c in self.inl + self.outl]):
274
+ elif all([c["T"] <= T0 for c in list(self.inl.values()) + list(self.outl.values())]):
226
275
  set_thermal_f_cold(A, counter + 0)
227
276
  equations[counter] = f"aux_f_rule_cold_{self.name}"
228
- # Case 3: Mixed temperatures: inl[0]["T"] > T0 and outl[1]["T"] > T0, while outl[0]["T"] <= T0 and inl[1]["T"] <= T0.
277
+ logging.warning(
278
+ f"All temperatures in {self.name} are below ambient temperature. " \
279
+ "This is not a typical case for a dissipative condenser."
280
+ )
281
+ # Case 3: Both stream crossing T0 (hot inlet and cold outlet > T0, hot outlet and cold inlet <= T0)
229
282
  elif (self.inl[0]["T"] > T0 and self.outl[1]["T"] > T0 and
230
283
  self.outl[0]["T"] <= T0 and self.inl[1]["T"] <= T0):
231
284
  set_thermal_p_rule(A, counter + 0)
232
285
  equations[counter] = f"aux_p_rule_{self.name}"
233
- # Case 4: Mixed temperatures: inl[0]["T"] > T0, inl[1]["T"] <= T0, and both outl[0]["T"] and outl[1]["T"] <= T0.
286
+ logging.warning(
287
+ f"Hot inlet and cold outlet in {self.name} are above ambient temperature, " \
288
+ "while hot outlet and cold inlet are below. This is not a typical case for a dissipative condenser." \
289
+ "The exergoeconomic analysis is counting the outlets as products."
290
+ )
291
+ # Case 4: Only hot inlet > T0
234
292
  elif (self.inl[0]["T"] > T0 and self.inl[1]["T"] <= T0 and
235
293
  self.outl[0]["T"] <= T0 and self.outl[1]["T"] <= T0):
236
294
  set_thermal_f_cold(A, counter + 0)
237
295
  equations[counter] = f"aux_f_rule_cold_{self.name}"
238
- # Case 5: Mixed temperatures: inl[0]["T"] > T0, inl[1]["T"] <= T0, and both outl[0]["T"] and outl[1]["T"] > T0.
296
+ logging.warning(
297
+ f"Cold inlet in {self.name} is below ambient temperature. " \
298
+ "This is not a typical case for a dissipative condenser."
299
+ )
300
+ # Case 5: Only cold inlet <= T0
239
301
  elif (self.inl[0]["T"] > T0 and self.inl[1]["T"] <= T0 and
240
302
  self.outl[0]["T"] > T0 and self.outl[1]["T"] > T0):
241
303
  set_thermal_f_hot(A, counter + 0)
242
304
  equations[counter] = f"aux_f_rule_hot_{self.name}"
243
- # Case 6: Mixed temperatures (dissipative case): inl[0]["T"] > T0, inl[1]["T"] <= T0, outl[0]["T"] > T0, and outl[1]["T"] <= T0.
305
+ logging.warning(
306
+ f"Cold inlet in {self.name} is below ambient temperature. " \
307
+ "This is not a typical case for a dissipative condenser."
308
+ )
309
+ # Case 6: hot stream always above T0, cold stream always below T0
244
310
  elif (self.inl[0]["T"] > T0 and self.inl[1]["T"] <= T0 and
245
311
  self.outl[0]["T"] > T0 and self.outl[1]["T"] <= T0):
246
312
  print("you shouldn't see this")
@@ -273,25 +339,110 @@ class Condenser(Component):
273
339
  return A, b, counter + num_aux_eqs, equations
274
340
 
275
341
  def exergoeconomic_balance(self, T0):
276
- """
277
- Perform exergoeconomic balance calculations for the condenser.
278
-
279
- This method calculates various exergoeconomic parameters including:
280
- - Cost rates of product (C_P) and fuel (C_F)
281
- - Specific cost of product (c_P) and fuel (c_F)
282
- - Cost rate of exergy destruction (C_D)
283
- - Relative cost difference (r)
284
- - Exergoeconomic factor (f)
342
+ r"""
343
+ Perform exergoeconomic cost balance for the condenser.
344
+
345
+ Even though this class should only consider dissipative condensers, the exergoeconomic balance is
346
+ still performed to ensure consistency. Please note that same of the following cases cases are not
347
+ typical for dissipative condensers. This may change in a future version of ExerPy.
348
+
349
+ .. math::
350
+ \dot{C}^{\mathrm{T}}_{\mathrm{in},1}
351
+ + \dot{C}^{\mathrm{M}}_{\mathrm{in},1}
352
+ + \dot{C}^{\mathrm{T}}_{\mathrm{in},2}
353
+ + \dot{C}^{\mathrm{M}}_{\mathrm{in},2}
354
+ - \dot{C}^{\mathrm{T}}_{\mathrm{out},1}
355
+ - \dot{C}^{\mathrm{M}}_{\mathrm{out},1}
356
+ - \dot{C}^{\mathrm{T}}_{\mathrm{out},2}
357
+ - \dot{C}^{\mathrm{M}}_{\mathrm{out},2}
358
+ + \dot{Z}
359
+ = 0
360
+
361
+ In case the chemical exergy of the streams is know:
362
+
363
+ .. math::
364
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in},1} =
365
+ \dot{C}^{\mathrm{CH}}_{\mathrm{out},1}
366
+
367
+ .. math::
368
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in},2} =
369
+ \dot{C}^{\mathrm{CH}}_{\mathrm{out},2}
370
+
371
+ This method computes cost coefficients and ratios:
372
+
373
+ Case 1: All streams above ambient temperature
374
+
375
+ .. math::
376
+ \dot{C}_P = \dot{C}^{\mathrm{T}}_{\mathrm{out},2}
377
+ - \dot{C}^{\mathrm{T}}_{\mathrm{in},2}
378
+
379
+ .. math::
380
+ \dot{C}_F = \dot{C}^{\mathrm{PH}}_{\mathrm{in},1}
381
+ - \dot{C}^{\mathrm{PH}}_{\mathrm{out},1}
382
+ + \bigl(\dot{C}^{\mathrm{M}}_{\mathrm{in},2}
383
+ - \dot{C}^{\mathrm{M}}_{\mathrm{out},2}\bigr)
384
+
385
+ Case 2: All streams below or equal to ambient temperature
386
+
387
+ .. math::
388
+ \dot{C}_P = \dot{C}^{\mathrm{T}}_{\mathrm{out},1}
389
+ - \dot{C}^{\mathrm{T}}_{\mathrm{in},1}
390
+
391
+ .. math::
392
+ \dot{C}_F = \dot{C}^{\mathrm{PH}}_{\mathrm{in},2}
393
+ - \dot{C}^{\mathrm{PH}}_{\mathrm{out},2}
394
+ + \bigl(\dot{C}^{\mathrm{M}}_{\mathrm{in},1}
395
+ - \dot{C}^{\mathrm{M}}_{\mathrm{out},1}\bigr)
396
+
397
+ Case 3: Both stream crossing ambient temperature
398
+
399
+ .. math::
400
+ \dot{C}_P = \dot{C}^{\mathrm{T}}_{\mathrm{out},1}
401
+ + \dot{C}^{\mathrm{T}}_{\mathrm{out},2}
402
+
403
+ .. math::
404
+ \dot{C}_F = \dot{C}^{\mathrm{PH}}_{\mathrm{in},1}
405
+ + \dot{C}^{\mathrm{PH}}_{\mathrm{in},2}
406
+ - \bigl(\dot{C}^{\mathrm{M}}_{\mathrm{out},1}
407
+ + \dot{C}^{\mathrm{M}}_{\mathrm{out},2}\bigr)
408
+
409
+ Case 4: Only the hot inlet above ambient temperature
410
+
411
+ .. math::
412
+ \dot{C}_P = \dot{C}^{\mathrm{T}}_{\mathrm{out},1}
413
+
414
+ .. math::
415
+ \dot{C}_F = \bigl(\dot{C}^{\mathrm{PH}}_{\mathrm{in},1}
416
+ + \dot{C}^{\mathrm{PH}}_{\mathrm{in},2}\bigr)
417
+ - \bigl(\dot{C}^{\mathrm{PH}}_{\mathrm{out},2}
418
+ + \dot{C}^{\mathrm{M}}_{\mathrm{out},1}\bigr)
419
+
420
+ Case 5: Only the cold inlet below ambient temperature
421
+
422
+ .. math::
423
+ \dot{C}_P = \dot{C}^{\mathrm{T}}_{\mathrm{out},2}
424
+
425
+ .. math::
426
+ \dot{C}_F = \dot{C}^{\mathrm{PH}}_{\mathrm{in},1}
427
+ - \dot{C}^{\mathrm{PH}}_{\mathrm{out},1}
428
+ + \bigl(\dot{C}^{\mathrm{PH}}_{\mathrm{in},2}
429
+ - \dot{C}^{\mathrm{M}}_{\mathrm{out},2}\bigr)
430
+
431
+ Case 6: Hot stream always above and cold stream always below ambient temperature (dissipative case):
432
+
433
+ .. math::
434
+ \dot{C}_P = \mathrm{NaN}
435
+
436
+ .. math::
437
+ \dot{C}_F = \bigl(\dot{C}^{\mathrm{PH}}_{\mathrm{in},1}
438
+ - \dot{C}^{\mathrm{PH}}_{\mathrm{out},1}\bigr)
439
+ - \dot{C}^{\mathrm{PH}}_{\mathrm{out},2}
440
+ + \dot{C}^{\mathrm{PH}}_{\mathrm{in},2}
285
441
 
286
442
  Parameters
287
443
  ----------
288
444
  T0 : float
289
- Ambient temperature
290
-
291
- Notes
292
- -----
293
- The exergoeconomic balance considers thermal (T), chemical (CH),
294
- and mechanical (M) exergy components for the inlet and outlet streams.
445
+ Ambient temperature (K).
295
446
  """
296
447
  if all([c["T"] > T0 for c in list(self.inl.values()) + list(self.outl.values())]):
297
448
  self.C_P = self.outl[1]["C_T"] - self.inl[1]["C_T"]