exerpy 0.0.2__py3-none-any.whl → 0.0.3__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.
- exerpy/__init__.py +2 -4
- exerpy/analyses.py +597 -297
- exerpy/components/__init__.py +3 -0
- exerpy/components/combustion/base.py +53 -35
- exerpy/components/component.py +8 -8
- exerpy/components/heat_exchanger/base.py +186 -119
- exerpy/components/heat_exchanger/condenser.py +96 -60
- exerpy/components/heat_exchanger/simple.py +237 -137
- exerpy/components/heat_exchanger/steam_generator.py +46 -41
- exerpy/components/helpers/cycle_closer.py +61 -34
- exerpy/components/helpers/power_bus.py +117 -0
- exerpy/components/nodes/deaerator.py +176 -58
- exerpy/components/nodes/drum.py +50 -39
- exerpy/components/nodes/flash_tank.py +218 -43
- exerpy/components/nodes/mixer.py +249 -69
- exerpy/components/nodes/splitter.py +173 -0
- exerpy/components/nodes/storage.py +130 -0
- exerpy/components/piping/valve.py +311 -115
- exerpy/components/power_machines/generator.py +105 -38
- exerpy/components/power_machines/motor.py +111 -39
- exerpy/components/turbomachinery/compressor.py +181 -63
- exerpy/components/turbomachinery/pump.py +182 -63
- exerpy/components/turbomachinery/turbine.py +182 -74
- exerpy/functions.py +388 -263
- exerpy/parser/from_aspen/aspen_config.py +57 -48
- exerpy/parser/from_aspen/aspen_parser.py +373 -280
- exerpy/parser/from_ebsilon/__init__.py +2 -2
- exerpy/parser/from_ebsilon/check_ebs_path.py +15 -19
- exerpy/parser/from_ebsilon/ebsilon_config.py +328 -226
- exerpy/parser/from_ebsilon/ebsilon_functions.py +205 -38
- exerpy/parser/from_ebsilon/ebsilon_parser.py +392 -255
- exerpy/parser/from_ebsilon/utils.py +16 -11
- exerpy/parser/from_tespy/tespy_config.py +32 -1
- exerpy/parser/from_tespy/tespy_parser.py +151 -0
- {exerpy-0.0.2.dist-info → exerpy-0.0.3.dist-info}/METADATA +43 -2
- exerpy-0.0.3.dist-info/RECORD +48 -0
- exerpy-0.0.2.dist-info/RECORD +0 -44
- {exerpy-0.0.2.dist-info → exerpy-0.0.3.dist-info}/WHEEL +0 -0
- {exerpy-0.0.2.dist-info → exerpy-0.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,8 +2,7 @@ import logging
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
|
-
from exerpy.components.component import Component
|
|
6
|
-
from exerpy.components.component import component_registry
|
|
5
|
+
from exerpy.components.component import Component, component_registry
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
@component_registry
|
|
@@ -11,9 +10,9 @@ class Deaerator(Component):
|
|
|
11
10
|
r"""
|
|
12
11
|
Class for exergy analysis of deaerators.
|
|
13
12
|
|
|
14
|
-
This class performs exergy analysis calculations for deaerators with multiple
|
|
15
|
-
inlet streams and one outlet stream. The exergy product and fuel definitions
|
|
16
|
-
vary based on the temperature relationships between inlet streams, outlet
|
|
13
|
+
This class performs exergy analysis calculations for deaerators with multiple
|
|
14
|
+
inlet streams and one outlet stream. The exergy product and fuel definitions
|
|
15
|
+
vary based on the temperature relationships between inlet streams, outlet
|
|
17
16
|
stream, and ambient conditions.
|
|
18
17
|
|
|
19
18
|
Parameters
|
|
@@ -116,7 +115,7 @@ class Deaerator(Component):
|
|
|
116
115
|
------
|
|
117
116
|
ValueError
|
|
118
117
|
If the required inlet and outlet streams are not properly defined.
|
|
119
|
-
"""
|
|
118
|
+
"""
|
|
120
119
|
# Ensure that the component has both inlet and outlet streams
|
|
121
120
|
if len(self.inl) < 2 or len(self.outl) < 1:
|
|
122
121
|
raise ValueError("Deaerator requires at least two inlets and one outlet.")
|
|
@@ -125,34 +124,34 @@ class Deaerator(Component):
|
|
|
125
124
|
self.E_F = 0
|
|
126
125
|
|
|
127
126
|
# Case 1: Outlet temperature is greater than T0
|
|
128
|
-
if self.outl[0][
|
|
127
|
+
if self.outl[0]["T"] > T0:
|
|
129
128
|
for _, inlet in self.inl.items():
|
|
130
|
-
if inlet[
|
|
131
|
-
if inlet[
|
|
132
|
-
self.E_P += inlet[
|
|
129
|
+
if inlet["T"] < self.outl[0]["T"]: # Tin < Tout
|
|
130
|
+
if inlet["T"] >= T0: # and Tin >= T0
|
|
131
|
+
self.E_P += inlet["m"] * (self.outl[0]["e_PH"] - inlet["e_PH"])
|
|
133
132
|
else: # and Tin < T0
|
|
134
|
-
self.E_P += inlet[
|
|
135
|
-
self.E_F += inlet[
|
|
133
|
+
self.E_P += inlet["m"] * self.outl[0]["e_PH"]
|
|
134
|
+
self.E_F += inlet["m"] * inlet["e_PH"]
|
|
136
135
|
else: # Tin > Tout
|
|
137
|
-
self.E_F += inlet[
|
|
136
|
+
self.E_F += inlet["m"] * (inlet["e_PH"] - self.outl[0]["e_PH"])
|
|
138
137
|
|
|
139
138
|
# Case 2: Outlet temperature is equal to T0
|
|
140
|
-
elif self.outl[0][
|
|
139
|
+
elif self.outl[0]["T"] == T0:
|
|
141
140
|
self.E_P = np.nan
|
|
142
141
|
for _, inlet in self.inl.items():
|
|
143
|
-
self.E_F += inlet[
|
|
142
|
+
self.E_F += inlet["m"] * inlet["e_PH"]
|
|
144
143
|
|
|
145
144
|
# Case 3: Outlet temperature is less than T0
|
|
146
145
|
else:
|
|
147
146
|
for _, inlet in self.inl.items():
|
|
148
|
-
if inlet[
|
|
149
|
-
if inlet[
|
|
150
|
-
self.E_P += inlet[
|
|
151
|
-
self.E_F += inlet[
|
|
147
|
+
if inlet["T"] > self.outl[0]["T"]: # Tin > Tout
|
|
148
|
+
if inlet["T"] >= T0: # and Tin >= T0
|
|
149
|
+
self.E_P += inlet["m"] * self.outl[0]["e_PH"]
|
|
150
|
+
self.E_F += inlet["m"] * inlet["e_PH"]
|
|
152
151
|
else: # and Tin < T0
|
|
153
|
-
self.E_P += inlet[
|
|
152
|
+
self.E_P += inlet["m"] * (self.outl[0]["e_PH"] - inlet["e_PH"])
|
|
154
153
|
else: # Tin < Tout
|
|
155
|
-
self.E_F += inlet[
|
|
154
|
+
self.E_F += inlet["m"] * (inlet["e_PH"] - self.outl[0]["e_PH"])
|
|
156
155
|
|
|
157
156
|
# Calculate exergy destruction and efficiency
|
|
158
157
|
if np.isnan(self.E_P):
|
|
@@ -163,7 +162,7 @@ class Deaerator(Component):
|
|
|
163
162
|
|
|
164
163
|
# Log the results
|
|
165
164
|
logging.info(
|
|
166
|
-
f"Deaerator
|
|
165
|
+
f"Exergy balance of Deaerator {self.name} calculated: "
|
|
167
166
|
f"E_P={self.E_P:.2f}, E_F={self.E_F:.2f}, E_D={self.E_D:.2f}, "
|
|
168
167
|
f"Efficiency={self.epsilon:.2%}"
|
|
169
168
|
)
|
|
@@ -171,25 +170,25 @@ class Deaerator(Component):
|
|
|
171
170
|
def aux_eqs(self, A, b, counter, T0, equations, chemical_exergy_enabled):
|
|
172
171
|
"""
|
|
173
172
|
Auxiliary equations for the deaerator.
|
|
174
|
-
|
|
173
|
+
|
|
175
174
|
This function adds rows to the cost matrix A and the right-hand-side vector b to enforce
|
|
176
175
|
the following auxiliary cost relations:
|
|
177
|
-
|
|
176
|
+
|
|
178
177
|
(1) Mixing equation for chemical exergy costs (if enabled):
|
|
179
178
|
|
|
180
179
|
- The outlet's specific chemical exergy cost is calculated as a mass-weighted average of the inlet streams' specific chemical exergy costs
|
|
181
|
-
|
|
180
|
+
|
|
182
181
|
- This enforces proper chemical exergy cost distribution through the deaerator
|
|
183
|
-
|
|
182
|
+
|
|
184
183
|
(2) Mixing equation for mechanical exergy costs:
|
|
185
|
-
|
|
184
|
+
|
|
186
185
|
- The outlet's specific mechanical exergy cost is calculated as a mass-weighted average of the inlet streams' specific mechanical exergy costs
|
|
187
|
-
|
|
186
|
+
|
|
188
187
|
- This ensures mechanical exergy costs are properly conserved in the mixing process
|
|
189
|
-
|
|
188
|
+
|
|
190
189
|
Both equations implement the proportionality rule for mixing processes where
|
|
191
190
|
the outlet's specific costs should reflect the contribution of each inlet stream.
|
|
192
|
-
|
|
191
|
+
|
|
193
192
|
Parameters
|
|
194
193
|
----------
|
|
195
194
|
A : numpy.ndarray
|
|
@@ -204,7 +203,7 @@ class Deaerator(Component):
|
|
|
204
203
|
Dictionary for storing equation labels.
|
|
205
204
|
chemical_exergy_enabled : bool
|
|
206
205
|
Flag indicating whether chemical exergy auxiliary equations should be added.
|
|
207
|
-
|
|
206
|
+
|
|
208
207
|
Returns
|
|
209
208
|
-------
|
|
210
209
|
A : numpy.ndarray
|
|
@@ -230,13 +229,16 @@ class Deaerator(Component):
|
|
|
230
229
|
# Outlet chemical exergy is zero: assign fallback for all inlets.
|
|
231
230
|
for inlet in self.inl.values():
|
|
232
231
|
A[counter, inlet["CostVar_index"]["CH"]] = 1
|
|
233
|
-
equations[counter] =
|
|
232
|
+
equations[counter] = {
|
|
233
|
+
"kind": "aux_mixing",
|
|
234
|
+
"objects": [self.name, self.inl[0]["name"], self.inl[1]["name"], self.outl[0]["name"]],
|
|
235
|
+
"property": "c_CH",
|
|
236
|
+
}
|
|
234
237
|
chem_row = 1 # One row added for chemical equation.
|
|
235
238
|
else:
|
|
236
239
|
chem_row = 0 # No row added.
|
|
237
240
|
|
|
238
241
|
# --- Mechanical cost auxiliary equation ---
|
|
239
|
-
mech_row = 0 # This row will always be added.
|
|
240
242
|
if self.outl[0]["e_M"] != 0:
|
|
241
243
|
A[counter + chem_row, self.outl[0]["CostVar_index"]["M"]] = -1 / self.outl[0]["E_M"]
|
|
242
244
|
# Iterate over inlet streams for mechanical mixing.
|
|
@@ -248,7 +250,11 @@ class Deaerator(Component):
|
|
|
248
250
|
else:
|
|
249
251
|
for inlet in self.inl.values():
|
|
250
252
|
A[counter + chem_row, inlet["CostVar_index"]["M"]] = 1
|
|
251
|
-
equations[counter + chem_row] =
|
|
253
|
+
equations[counter + chem_row] = {
|
|
254
|
+
"kind": "aux_mixing",
|
|
255
|
+
"objects": [self.name, self.inl[0]["name"], self.inl[1]["name"], self.outl[0]["name"]],
|
|
256
|
+
"property": "c_M",
|
|
257
|
+
}
|
|
252
258
|
|
|
253
259
|
# Set the right-hand side entries to zero for the added rows.
|
|
254
260
|
if chemical_exergy_enabled:
|
|
@@ -261,26 +267,141 @@ class Deaerator(Component):
|
|
|
261
267
|
|
|
262
268
|
return A, b, counter, equations
|
|
263
269
|
|
|
264
|
-
def exergoeconomic_balance(self, T0):
|
|
265
|
-
"""
|
|
266
|
-
Perform exergoeconomic balance
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
270
|
+
def exergoeconomic_balance(self, T0, chemical_exergy_enabled=False):
|
|
271
|
+
r"""
|
|
272
|
+
Perform exergoeconomic cost balance for the deaerator (mixing component).
|
|
273
|
+
|
|
274
|
+
The deaerator is a mixing component where multiple streams combine. The general
|
|
275
|
+
exergoeconomic balance equation is:
|
|
276
|
+
|
|
277
|
+
.. math::
|
|
278
|
+
\sum_{\mathrm{in}} \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
279
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
280
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}\right)
|
|
281
|
+
- \sum_{\mathrm{out}} \left(\dot{C}^{\mathrm{T}}_{\mathrm{out}}
|
|
282
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
283
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{out}}\right)
|
|
284
|
+
+ \dot{Z}
|
|
285
|
+
= 0
|
|
286
|
+
|
|
287
|
+
The product is defined as the outlet stream. The fuel consists of all inlet
|
|
288
|
+
streams, with specific treatment depending on temperature levels. The cost
|
|
289
|
+
balance is closed using:
|
|
290
|
+
|
|
291
|
+
.. math::
|
|
292
|
+
\dot{C}_{\mathrm{P}} = \dot{C}_{\mathrm{F}} + \dot{Z}
|
|
293
|
+
|
|
294
|
+
**Case 1: Outlet above ambient temperature**
|
|
295
|
+
|
|
296
|
+
When :math:`T_{\mathrm{out}} > T_0`:
|
|
297
|
+
|
|
298
|
+
For cold inlets (:math:`T_{\mathrm{in}} < T_{\mathrm{out}}`):
|
|
299
|
+
|
|
300
|
+
.. math::
|
|
301
|
+
\dot{C}_{\mathrm{F,cold}} = \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
302
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}
|
|
303
|
+
|
|
304
|
+
For hot inlets (:math:`T_{\mathrm{in}} \geq T_{\mathrm{out}}`):
|
|
305
|
+
|
|
306
|
+
.. math::
|
|
307
|
+
\dot{C}_{\mathrm{F,hot}} = -\dot{m}_{\mathrm{in}} \cdot c^{\mathrm{T}}_{\mathrm{in}}
|
|
308
|
+
\cdot e^{\mathrm{T}}_{\mathrm{in}}
|
|
309
|
+
+ \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
310
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
311
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}\right)
|
|
312
|
+
|
|
313
|
+
Total fuel cost:
|
|
314
|
+
|
|
315
|
+
.. math::
|
|
316
|
+
\dot{C}_{\mathrm{F}} = \sum \dot{C}_{\mathrm{F,cold}}
|
|
317
|
+
+ \sum \dot{C}_{\mathrm{F,hot}}
|
|
318
|
+
- \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
319
|
+
- \dot{C}^{\mathrm{CH}}_{\mathrm{out}}
|
|
320
|
+
|
|
321
|
+
**Case 2: Outlet at ambient temperature (dissipative)**
|
|
322
|
+
|
|
323
|
+
When :math:`|T_{\mathrm{out}} - T_0| < 10^{-6}`:
|
|
324
|
+
|
|
325
|
+
.. math::
|
|
326
|
+
\dot{C}_{\mathrm{F}} = \sum_{\mathrm{in}} \dot{C}^{\mathrm{TOT}}_{\mathrm{in}}
|
|
327
|
+
|
|
328
|
+
**Case 3: Outlet below ambient temperature**
|
|
329
|
+
|
|
330
|
+
When :math:`T_{\mathrm{out}} < T_0`:
|
|
331
|
+
|
|
332
|
+
For hot inlets (:math:`T_{\mathrm{in}} > T_{\mathrm{out}}`):
|
|
333
|
+
|
|
334
|
+
.. math::
|
|
335
|
+
\dot{C}_{\mathrm{F,hot}} = \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
336
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}
|
|
337
|
+
|
|
338
|
+
For cold inlets (:math:`T_{\mathrm{in}} \leq T_{\mathrm{out}}`):
|
|
339
|
+
|
|
340
|
+
.. math::
|
|
341
|
+
\dot{C}_{\mathrm{F,cold}} = -\dot{m}_{\mathrm{in}} \cdot c^{\mathrm{T}}_{\mathrm{in}}
|
|
342
|
+
\cdot e^{\mathrm{T}}_{\mathrm{in}}
|
|
343
|
+
+ \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
344
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
345
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}\right)
|
|
346
|
+
|
|
347
|
+
Total fuel cost:
|
|
348
|
+
|
|
349
|
+
.. math::
|
|
350
|
+
\dot{C}_{\mathrm{F}} = \sum \dot{C}_{\mathrm{F,hot}}
|
|
351
|
+
+ \sum \dot{C}_{\mathrm{F,cold}}
|
|
352
|
+
- \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
353
|
+
- \dot{C}^{\mathrm{CH}}_{\mathrm{out}}
|
|
354
|
+
|
|
355
|
+
**Calculated exergoeconomic indicators:**
|
|
356
|
+
|
|
357
|
+
.. math::
|
|
358
|
+
c_{\mathrm{F}} = \frac{\dot{C}_{\mathrm{F}}}{\dot{E}_{\mathrm{F}}}
|
|
359
|
+
|
|
360
|
+
.. math::
|
|
361
|
+
c_{\mathrm{P}} = \frac{\dot{C}_{\mathrm{P}}}{\dot{E}_{\mathrm{P}}}
|
|
362
|
+
|
|
363
|
+
.. math::
|
|
364
|
+
\dot{C}_{\mathrm{D}} = c_{\mathrm{F}} \cdot \dot{E}_{\mathrm{D}}
|
|
365
|
+
|
|
366
|
+
.. math::
|
|
367
|
+
r = \frac{c_{\mathrm{P}} - c_{\mathrm{F}}}{c_{\mathrm{F}}}
|
|
368
|
+
|
|
369
|
+
.. math::
|
|
370
|
+
f = \frac{\dot{Z}}{\dot{Z} + \dot{C}_{\mathrm{D}}}
|
|
371
|
+
|
|
275
372
|
Parameters
|
|
276
373
|
----------
|
|
277
374
|
T0 : float
|
|
278
|
-
Ambient temperature
|
|
279
|
-
|
|
375
|
+
Ambient temperature (K).
|
|
376
|
+
chemical_exergy_enabled : bool, optional
|
|
377
|
+
If True, chemical exergy is considered in the calculations.
|
|
378
|
+
Default is False.
|
|
379
|
+
|
|
380
|
+
Attributes Set
|
|
381
|
+
--------------
|
|
382
|
+
C_P : float
|
|
383
|
+
Cost rate of product (currency/time).
|
|
384
|
+
C_F : float
|
|
385
|
+
Cost rate of fuel (currency/time).
|
|
386
|
+
c_P : float
|
|
387
|
+
Specific cost of product (currency/energy).
|
|
388
|
+
c_F : float
|
|
389
|
+
Specific cost of fuel (currency/energy).
|
|
390
|
+
C_D : float
|
|
391
|
+
Cost rate of exergy destruction (currency/time).
|
|
392
|
+
r : float
|
|
393
|
+
Relative cost difference (dimensionless).
|
|
394
|
+
f : float
|
|
395
|
+
Exergoeconomic factor (dimensionless).
|
|
396
|
+
|
|
280
397
|
Notes
|
|
281
398
|
-----
|
|
282
|
-
The
|
|
283
|
-
|
|
399
|
+
The deaerator treats thermal, mechanical, and chemical exergy components
|
|
400
|
+
differently depending on whether inlets are "hot" or "cold" relative to
|
|
401
|
+
the outlet temperature. The distinction ensures proper cost allocation
|
|
402
|
+
for streams that provide heating versus those being heated.
|
|
403
|
+
|
|
404
|
+
Future development may include merging profits from dissipative components.
|
|
284
405
|
"""
|
|
285
406
|
self.C_P = 0
|
|
286
407
|
self.C_F = 0
|
|
@@ -291,9 +412,8 @@ class Deaerator(Component):
|
|
|
291
412
|
self.C_F += i["C_M"] + i["C_CH"]
|
|
292
413
|
else:
|
|
293
414
|
# hot inlets
|
|
294
|
-
self.C_F += -
|
|
295
|
-
|
|
296
|
-
self.C_F += (-self.outl[0]["C_M"] - self.outl[0]["C_CH"])
|
|
415
|
+
self.C_F += -i["M"] * i["C_T"] * i["e_T"] + (i["C_T"] + i["C_M"] + i["C_CH"])
|
|
416
|
+
self.C_F += -self.outl[0]["C_M"] - self.outl[0]["C_CH"]
|
|
297
417
|
elif self.outl[0]["T"] - 1e-6 < T0 and self.outl[0]["T"] + 1e-6 > T0:
|
|
298
418
|
# dissipative
|
|
299
419
|
for i in self.inl:
|
|
@@ -305,15 +425,13 @@ class Deaerator(Component):
|
|
|
305
425
|
self.C_F += i["C_M"] + i["C_CH"]
|
|
306
426
|
else:
|
|
307
427
|
# cold inlets
|
|
308
|
-
self.C_F += -
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
self.C_P = self.C_F + self.Z_costs # +1/num_serving_comps * C_diff
|
|
428
|
+
self.C_F += -i["M"] * i["C_T"] * i["e_T"] + (i["C_T"] + i["C_M"] + i["C_CH"])
|
|
429
|
+
self.C_F += -self.outl[0]["C_M"] - self.outl[0]["C_CH"]
|
|
430
|
+
self.C_P = self.C_F + self.Z_costs # +1/num_serving_comps * C_diff
|
|
312
431
|
# ToDo: add case that merge profits from dissipative component(s)
|
|
313
432
|
|
|
314
|
-
|
|
315
433
|
self.c_F = self.C_F / self.E_F
|
|
316
434
|
self.c_P = self.C_P / self.E_P
|
|
317
435
|
self.C_D = self.c_F * self.E_D
|
|
318
436
|
self.r = (self.c_P - self.c_F) / self.c_F
|
|
319
|
-
self.f = self.Z_costs / (self.Z_costs + self.C_D)
|
|
437
|
+
self.f = self.Z_costs / (self.Z_costs + self.C_D)
|
exerpy/components/nodes/drum.py
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
from exerpy.components.component import Component
|
|
6
|
-
from exerpy.components.component import component_registry
|
|
3
|
+
from exerpy.components.component import Component, component_registry
|
|
7
4
|
|
|
8
5
|
|
|
9
6
|
@component_registry
|
|
@@ -30,14 +27,8 @@ class Drum(Component):
|
|
|
30
27
|
\dot{E}_\mathrm{P} = \sum \dot{E}_{\mathrm{out,}j}^\mathrm{PH}\\
|
|
31
28
|
\dot{E}_\mathrm{F} = \sum \dot{E}_{\mathrm{in,}i}^\mathrm{PH}
|
|
32
29
|
"""
|
|
33
|
-
self.E_P =
|
|
34
|
-
|
|
35
|
-
+ self.outl[1]['e_PH'] * self.outl[1]['m']
|
|
36
|
-
)
|
|
37
|
-
self.E_F = (
|
|
38
|
-
self.inl[0]['e_PH'] * self.inl[0]['m']
|
|
39
|
-
+ self.inl[1]['e_PH'] * self.inl[1]['m']
|
|
40
|
-
)
|
|
30
|
+
self.E_P = self.outl[0]["e_PH"] * self.outl[0]["m"] + self.outl[1]["e_PH"] * self.outl[1]["m"]
|
|
31
|
+
self.E_F = self.inl[0]["e_PH"] * self.inl[0]["m"] + self.inl[1]["e_PH"] * self.inl[1]["m"]
|
|
41
32
|
|
|
42
33
|
# Calculate exergy destruction and efficiency
|
|
43
34
|
self.E_D = self.E_F - self.E_P
|
|
@@ -45,7 +36,7 @@ class Drum(Component):
|
|
|
45
36
|
|
|
46
37
|
# Log the results
|
|
47
38
|
logging.info(
|
|
48
|
-
f"Drum
|
|
39
|
+
f"Exergy balance of Drum {self.name} calculated: "
|
|
49
40
|
f"E_P={self.E_P:.2f}, E_F={self.E_F:.2f}, E_D={self.E_D:.2f}, "
|
|
50
41
|
f"Efficiency={self.epsilon:.2%}"
|
|
51
42
|
)
|
|
@@ -102,18 +93,26 @@ class Drum(Component):
|
|
|
102
93
|
A[counter, self.outl[0]["CostVar_index"]["CH"]] = -1 / self.outl[0]["E_CH"]
|
|
103
94
|
else:
|
|
104
95
|
A[counter, self.outl[0]["CostVar_index"]["CH"]] = -1
|
|
105
|
-
equations[counter] =
|
|
106
|
-
|
|
96
|
+
equations[counter] = {
|
|
97
|
+
"kind": "aux_equality",
|
|
98
|
+
"objects": [self.name, self.inl[0]["name"], self.outl[0]["name"]],
|
|
99
|
+
"property": "c_CH",
|
|
100
|
+
}
|
|
101
|
+
|
|
107
102
|
# Equation 2: Balance between inlet 0 and outlet 1 for chemical exergy
|
|
108
103
|
if self.inl[0]["e_CH"] != 0:
|
|
109
|
-
A[counter+1, self.inl[0]["CostVar_index"]["CH"]] = 1 / self.inl[0]["E_CH"]
|
|
104
|
+
A[counter + 1, self.inl[0]["CostVar_index"]["CH"]] = 1 / self.inl[0]["E_CH"]
|
|
110
105
|
else:
|
|
111
|
-
A[counter+1, self.inl[0]["CostVar_index"]["CH"]] = 1
|
|
106
|
+
A[counter + 1, self.inl[0]["CostVar_index"]["CH"]] = 1
|
|
112
107
|
if self.outl[1]["e_CH"] != 0:
|
|
113
|
-
A[counter+1, self.outl[1]["CostVar_index"]["CH"]] = -1 / self.outl[1]["E_CH"]
|
|
108
|
+
A[counter + 1, self.outl[1]["CostVar_index"]["CH"]] = -1 / self.outl[1]["E_CH"]
|
|
114
109
|
else:
|
|
115
|
-
A[counter+1, self.outl[1]["CostVar_index"]["CH"]] = -1
|
|
116
|
-
equations[counter+1] =
|
|
110
|
+
A[counter + 1, self.outl[1]["CostVar_index"]["CH"]] = -1
|
|
111
|
+
equations[counter + 1] = {
|
|
112
|
+
"kind": "aux_equality",
|
|
113
|
+
"objects": [self.name, self.inl[1]["name"], self.outl[1]["name"]],
|
|
114
|
+
"property": "c_CH",
|
|
115
|
+
}
|
|
117
116
|
chem_rows = 2
|
|
118
117
|
else:
|
|
119
118
|
chem_rows = 0
|
|
@@ -121,41 +120,53 @@ class Drum(Component):
|
|
|
121
120
|
# --- Thermal cost auxiliary equation ---
|
|
122
121
|
# For thermal exergy, we balance the two outlets.
|
|
123
122
|
if (self.outl[0]["e_T"] != 0) and (self.outl[1]["e_T"] != 0):
|
|
124
|
-
A[counter+chem_rows, self.outl[0]["CostVar_index"]["T"]] = 1 / self.outl[0]["E_T"]
|
|
125
|
-
A[counter+chem_rows, self.outl[1]["CostVar_index"]["T"]] = -1 / self.outl[1]["E_T"]
|
|
123
|
+
A[counter + chem_rows, self.outl[0]["CostVar_index"]["T"]] = 1 / self.outl[0]["E_T"]
|
|
124
|
+
A[counter + chem_rows, self.outl[1]["CostVar_index"]["T"]] = -1 / self.outl[1]["E_T"]
|
|
126
125
|
elif self.outl[0]["e_T"] == 0 and self.outl[1]["e_T"] != 0:
|
|
127
|
-
A[counter+chem_rows, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
126
|
+
A[counter + chem_rows, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
128
127
|
elif self.outl[0]["e_T"] != 0 and self.outl[1]["e_T"] == 0:
|
|
129
|
-
A[counter+chem_rows, self.outl[1]["CostVar_index"]["T"]] = -1
|
|
128
|
+
A[counter + chem_rows, self.outl[1]["CostVar_index"]["T"]] = -1
|
|
130
129
|
else:
|
|
131
|
-
A[counter+chem_rows, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
132
|
-
A[counter+chem_rows, self.outl[1]["CostVar_index"]["T"]] = -1
|
|
133
|
-
equations[counter+chem_rows] =
|
|
130
|
+
A[counter + chem_rows, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
131
|
+
A[counter + chem_rows, self.outl[1]["CostVar_index"]["T"]] = -1
|
|
132
|
+
equations[counter + chem_rows] = {
|
|
133
|
+
"kind": "aux_p_rule",
|
|
134
|
+
"objects": [self.name, self.outl[0]["name"], self.outl[1]["name"]],
|
|
135
|
+
"property": "c_T",
|
|
136
|
+
}
|
|
134
137
|
|
|
135
138
|
# --- Mechanical cost auxiliary equation ---
|
|
136
139
|
if self.outl[0]["e_M"] != 0:
|
|
137
|
-
A[counter+chem_rows+1, self.outl[0]["CostVar_index"]["M"]] = 1 / self.outl[0]["E_M"]
|
|
140
|
+
A[counter + chem_rows + 1, self.outl[0]["CostVar_index"]["M"]] = 1 / self.outl[0]["E_M"]
|
|
138
141
|
else:
|
|
139
|
-
A[counter+chem_rows+1, self.outl[0]["CostVar_index"]["M"]] = 1
|
|
142
|
+
A[counter + chem_rows + 1, self.outl[0]["CostVar_index"]["M"]] = 1
|
|
140
143
|
if self.outl[1]["e_M"] != 0:
|
|
141
|
-
A[counter+chem_rows+1, self.outl[1]["CostVar_index"]["M"]] = -1 / self.outl[1]["E_M"]
|
|
144
|
+
A[counter + chem_rows + 1, self.outl[1]["CostVar_index"]["M"]] = -1 / self.outl[1]["E_M"]
|
|
142
145
|
else:
|
|
143
|
-
A[counter+chem_rows+1, self.outl[1]["CostVar_index"]["M"]] = -1
|
|
144
|
-
equations[counter+chem_rows+1] =
|
|
146
|
+
A[counter + chem_rows + 1, self.outl[1]["CostVar_index"]["M"]] = -1
|
|
147
|
+
equations[counter + chem_rows + 1] = {
|
|
148
|
+
"kind": "aux_p_rule",
|
|
149
|
+
"objects": [self.name, self.outl[0]["name"], self.outl[1]["name"]],
|
|
150
|
+
"property": "c_M",
|
|
151
|
+
}
|
|
145
152
|
|
|
146
153
|
# --- Thermal-Mechanical coupling equation for outlet 0 ---
|
|
147
154
|
# This enforces that the thermal and mechanical cost components at outlet 0 are consistent.
|
|
148
155
|
if (self.outl[0]["e_T"] != 0) and (self.outl[0]["e_M"] != 0):
|
|
149
|
-
A[counter+chem_rows+2, self.outl[0]["CostVar_index"]["T"]] = 1 / self.outl[0]["E_T"]
|
|
150
|
-
A[counter+chem_rows+2, self.outl[0]["CostVar_index"]["M"]] = -1 / self.outl[0]["E_M"]
|
|
156
|
+
A[counter + chem_rows + 2, self.outl[0]["CostVar_index"]["T"]] = 1 / self.outl[0]["E_T"]
|
|
157
|
+
A[counter + chem_rows + 2, self.outl[0]["CostVar_index"]["M"]] = -1 / self.outl[0]["E_M"]
|
|
151
158
|
elif (self.outl[0]["e_T"] == 0) and (self.outl[0]["e_M"] == 0):
|
|
152
|
-
A[counter+chem_rows+2, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
153
|
-
A[counter+chem_rows+2, self.outl[0]["CostVar_index"]["M"]] = -1
|
|
159
|
+
A[counter + chem_rows + 2, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
160
|
+
A[counter + chem_rows + 2, self.outl[0]["CostVar_index"]["M"]] = -1
|
|
154
161
|
elif self.outl[0]["e_T"] == 0:
|
|
155
|
-
A[counter+chem_rows+2, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
162
|
+
A[counter + chem_rows + 2, self.outl[0]["CostVar_index"]["T"]] = 1
|
|
156
163
|
else:
|
|
157
|
-
A[counter+chem_rows+2, self.outl[0]["CostVar_index"]["M"]] = -1
|
|
158
|
-
equations[counter+chem_rows+2] =
|
|
164
|
+
A[counter + chem_rows + 2, self.outl[0]["CostVar_index"]["M"]] = -1
|
|
165
|
+
equations[counter + chem_rows + 2] = {
|
|
166
|
+
"kind": "aux_equality",
|
|
167
|
+
"objects": [self.name, self.outl[0]["name"]],
|
|
168
|
+
"property": "c_T, c_M",
|
|
169
|
+
}
|
|
159
170
|
|
|
160
171
|
# Set the right-hand side entries to zero for all added rows.
|
|
161
172
|
for i in range(chem_rows + 3):
|