exerpy 0.0.2__py3-none-any.whl → 0.0.4__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 +849 -304
- 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 +188 -121
- exerpy/components/heat_exchanger/condenser.py +98 -62
- 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 +214 -68
- exerpy/components/turbomachinery/pump.py +215 -68
- exerpy/components/turbomachinery/turbine.py +182 -74
- exerpy/cost_estimation/__init__.py +65 -0
- exerpy/cost_estimation/turton.py +1260 -0
- exerpy/data/cost_correlations/cepci_index.json +135 -0
- exerpy/data/cost_correlations/component_mapping.json +450 -0
- exerpy/data/cost_correlations/material_factors.json +428 -0
- exerpy/data/cost_correlations/pressure_factors.json +206 -0
- exerpy/data/cost_correlations/turton2008.json +726 -0
- exerpy/data/cost_correlations/turton2008_design_analysis_synthesis_components_tables.pdf +0 -0
- exerpy/data/cost_correlations/turton2008_design_analysis_synthesis_components_theory.pdf +0 -0
- exerpy/functions.py +389 -264
- 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 +33 -1
- exerpy/parser/from_tespy/tespy_parser.py +151 -0
- {exerpy-0.0.2.dist-info → exerpy-0.0.4.dist-info}/METADATA +43 -2
- exerpy-0.0.4.dist-info/RECORD +57 -0
- exerpy-0.0.2.dist-info/RECORD +0 -44
- {exerpy-0.0.2.dist-info → exerpy-0.0.4.dist-info}/WHEEL +0 -0
- {exerpy-0.0.2.dist-info → exerpy-0.0.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,58 +1,67 @@
|
|
|
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
|
|
10
7
|
class FlashTank(Component):
|
|
11
8
|
r"""
|
|
12
|
-
Class for exergy analysis of flash
|
|
13
|
-
|
|
14
|
-
This class performs exergy analysis calculations for flash tanks where a feed
|
|
15
|
-
stream is partially flashed into two different outlet streams (e.g., vapor and liquid).
|
|
16
|
-
The exergy fuel is calculated using the physical/thermal exergy of the inlet streams,
|
|
17
|
-
while the exergy product is computed as the sum of the physical exergy of the outlet streams.
|
|
18
|
-
Exergy destruction is the difference between the fuel and product, and the efficiency is defined
|
|
19
|
-
as ε = E_P / E_F.
|
|
9
|
+
Class for exergy and exergoeconomic analysis of flash tank.
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
**kwargs : dict
|
|
24
|
-
Arbitrary keyword arguments passed to the parent class.
|
|
11
|
+
This class performs exergy and exergoeconomic analysis calculations for flash tank components,
|
|
12
|
+
accounting for two inlet and two outlet streams.
|
|
25
13
|
|
|
26
14
|
Attributes
|
|
27
15
|
----------
|
|
28
16
|
E_F : float
|
|
29
|
-
Exergy fuel of the component
|
|
17
|
+
Exergy fuel of the component :math:`\dot{E}_\mathrm{F}` in :math:`\mathrm{W}`.
|
|
30
18
|
E_P : float
|
|
31
|
-
Exergy product of the component
|
|
19
|
+
Exergy product of the component :math:`\dot{E}_\mathrm{P}` in :math:`\mathrm{W}`.
|
|
32
20
|
E_D : float
|
|
33
|
-
Exergy destruction
|
|
21
|
+
Exergy destruction of the component :math:`\dot{E}_\mathrm{D}` in :math:`\mathrm{W}`.
|
|
34
22
|
epsilon : float
|
|
35
|
-
Exergetic efficiency
|
|
23
|
+
Exergetic efficiency of the component :math:`\varepsilon` in :math:`-`.
|
|
36
24
|
inl : dict
|
|
37
|
-
Dictionary containing inlet
|
|
25
|
+
Dictionary containing inlet stream data with mass flows and specific exergies.
|
|
38
26
|
outl : dict
|
|
39
|
-
Dictionary containing outlet
|
|
27
|
+
Dictionary containing outlet stream data with mass flows and specific exergies.
|
|
28
|
+
Z_costs : float
|
|
29
|
+
Investment cost rate of the component in currency/h.
|
|
30
|
+
C_P : float
|
|
31
|
+
Cost of product stream :math:`\dot{C}_P` in currency/h.
|
|
32
|
+
C_F : float
|
|
33
|
+
Cost of fuel stream :math:`\dot{C}_F` in currency/h.
|
|
34
|
+
C_D : float
|
|
35
|
+
Cost of exergy destruction :math:`\dot{C}_D` in currency/h.
|
|
36
|
+
c_P : float
|
|
37
|
+
Specific cost of product stream (currency per unit exergy).
|
|
38
|
+
c_F : float
|
|
39
|
+
Specific cost of fuel stream (currency per unit exergy).
|
|
40
|
+
r : float
|
|
41
|
+
Relative cost difference, :math:`(c_P - c_F)/c_F`.
|
|
42
|
+
f : float
|
|
43
|
+
Exergoeconomic factor, :math:`\dot{Z}/(\dot{Z} + \dot{C}_D)`.
|
|
44
|
+
Ex_C_col : dict
|
|
45
|
+
Custom cost coefficients collection passed via `kwargs`.
|
|
40
46
|
"""
|
|
41
47
|
|
|
42
48
|
def __init__(self, **kwargs):
|
|
43
|
-
r"""
|
|
49
|
+
r"""
|
|
50
|
+
Initialize the flash tank component.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
**kwargs : dict
|
|
55
|
+
Arbitrary keyword arguments. Recognized keys:
|
|
56
|
+
- Ex_C_col (dict): custom cost coefficients, default {}
|
|
57
|
+
- Z_costs (float): investment cost rate in currency/h, default 0.0
|
|
58
|
+
"""
|
|
59
|
+
self.dissipative = False
|
|
44
60
|
super().__init__(**kwargs)
|
|
45
61
|
|
|
46
|
-
def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy
|
|
62
|
+
def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy) -> None:
|
|
47
63
|
r"""
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
The exergy fuel (E_F) is computed as the sum of the inlet streams' exergy.
|
|
51
|
-
If split_physical_exergy is True, the thermal exergy (e_T) is used;
|
|
52
|
-
otherwise, the physical exergy (e_PH) is used.
|
|
53
|
-
The exergy product (E_P) is calculated as the sum of the physical exergy of the
|
|
54
|
-
outlet streams. Exergy destruction (E_D) is the difference E_F - E_P, and
|
|
55
|
-
exergetic efficiency is ε = E_P / E_F.
|
|
64
|
+
Compute the exergy balance of the flash tank.
|
|
56
65
|
|
|
57
66
|
Parameters
|
|
58
67
|
----------
|
|
@@ -62,20 +71,36 @@ class FlashTank(Component):
|
|
|
62
71
|
Ambient pressure in Pascal.
|
|
63
72
|
split_physical_exergy : bool
|
|
64
73
|
Flag indicating whether physical exergy is split into thermal and mechanical components.
|
|
74
|
+
|
|
75
|
+
Raises
|
|
76
|
+
------
|
|
77
|
+
ValueError
|
|
78
|
+
If the number of inlet or outlet streams is less than two.
|
|
79
|
+
|
|
80
|
+
Notes
|
|
81
|
+
-----
|
|
82
|
+
The definition of exergy fuel and product for this component has not been validated yet. For now, the
|
|
83
|
+
exergy fuel is defined as the inlet streams exergy, and the exergy product is defined as the
|
|
84
|
+
sum of the outlet streams' exergies (i). The exergy destruction is calculated as the difference between the exergy fuel and product.
|
|
85
|
+
.. math::
|
|
86
|
+
|
|
87
|
+
\dot{E}_\mathrm{F} = \dot{E}_{in}^\mathrm{PH}
|
|
88
|
+
|
|
89
|
+
.. math::
|
|
90
|
+
|
|
91
|
+
\dot{E}_\mathrm{P} = \sum_{i=1}^{m} \dot{E}_i^\mathrm{PH}
|
|
92
|
+
|
|
65
93
|
"""
|
|
66
|
-
# Ensure that at least two
|
|
67
|
-
if len(self.inl) <
|
|
68
|
-
raise ValueError("
|
|
69
|
-
|
|
70
|
-
if split_physical_exergy
|
|
71
|
-
exergy_type = 'e_T'
|
|
72
|
-
else:
|
|
73
|
-
exergy_type = 'e_PH'
|
|
94
|
+
# Ensure that the component has at least two outlets and one inlet.
|
|
95
|
+
if len(self.inl) < 1 or len(self.outl) < 2:
|
|
96
|
+
raise ValueError("Flash tank requires one inlet and two outlets.")
|
|
97
|
+
|
|
98
|
+
exergy_type = "e_T" if split_physical_exergy else "e_PH"
|
|
74
99
|
|
|
75
100
|
# Calculate exergy fuel (E_F) from inlet streams.
|
|
76
|
-
self.E_F = sum(inlet[
|
|
101
|
+
self.E_F = sum(inlet["m"] * inlet[exergy_type] for inlet in self.inl.values())
|
|
77
102
|
# Calculate exergy product (E_P) from outlet streams.
|
|
78
|
-
self.E_P = sum(outlet[
|
|
103
|
+
self.E_P = sum(outlet["m"] * outlet[exergy_type] for outlet in self.outl.values())
|
|
79
104
|
|
|
80
105
|
# Exergy destruction and efficiency.
|
|
81
106
|
self.E_D = self.E_F - self.E_P
|
|
@@ -83,7 +108,157 @@ class FlashTank(Component):
|
|
|
83
108
|
|
|
84
109
|
# Log the results.
|
|
85
110
|
logging.info(
|
|
86
|
-
f"FlashTank
|
|
111
|
+
f"Exergy balance of FlashTank {self.name} calculated: "
|
|
87
112
|
f"E_F = {self.E_F:.2f} W, E_P = {self.E_P:.2f} W, E_D = {self.E_D:.2f} W, "
|
|
88
113
|
f"Efficiency = {self.epsilon:.2%}"
|
|
89
114
|
)
|
|
115
|
+
|
|
116
|
+
def aux_eqs(self, A, b, counter, T0, equations, chemical_exergy_enabled):
|
|
117
|
+
"""
|
|
118
|
+
Auxiliary equations for the flash tank.
|
|
119
|
+
|
|
120
|
+
This function adds rows to the cost matrix A and the right-hand-side vector b to enforce
|
|
121
|
+
equality of specific exergy costs between the single inlet stream and each outlet stream.
|
|
122
|
+
Thermal and mechanical costs are always equated; chemical costs are equated only if enabled.
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
A : numpy.ndarray
|
|
127
|
+
The current cost matrix.
|
|
128
|
+
b : numpy.ndarray
|
|
129
|
+
The current right-hand-side vector.
|
|
130
|
+
counter : int
|
|
131
|
+
The current row index in the matrix.
|
|
132
|
+
T0 : float
|
|
133
|
+
Ambient temperature (not used).
|
|
134
|
+
equations : list or dict
|
|
135
|
+
Data structure for storing equation labels.
|
|
136
|
+
chemical_exergy_enabled : bool
|
|
137
|
+
Flag indicating whether chemical exergy auxiliary equations should be added.
|
|
138
|
+
|
|
139
|
+
Returns
|
|
140
|
+
-------
|
|
141
|
+
A : numpy.ndarray
|
|
142
|
+
The updated cost matrix.
|
|
143
|
+
b : numpy.ndarray
|
|
144
|
+
The updated right-hand-side vector.
|
|
145
|
+
counter : int
|
|
146
|
+
The updated row index after adding equations.
|
|
147
|
+
equations : list or dict
|
|
148
|
+
Updated structure with equation labels.
|
|
149
|
+
"""
|
|
150
|
+
# single inlet
|
|
151
|
+
inlet = self.inl[0]
|
|
152
|
+
# two outlets (assumed indices 0 and 1)
|
|
153
|
+
out0 = self.outl[0]
|
|
154
|
+
out1 = self.outl[1]
|
|
155
|
+
|
|
156
|
+
# --- Thermal product‐rule: c_T,out0 = c_T,out1 ---
|
|
157
|
+
# 1/e_T,out0 · C_T,out0 − 1/e_T,out1 · C_T,out1 = 0
|
|
158
|
+
if out0["e_T"] != 0 and out1["e_T"] != 0:
|
|
159
|
+
A[counter, out0["CostVar_index"]["T"]] = 1.0 / out0["e_T"]
|
|
160
|
+
A[counter, out1["CostVar_index"]["T"]] = -1.0 / out1["e_T"]
|
|
161
|
+
elif out0["e_T"] == 0 and out1["e_T"] != 0:
|
|
162
|
+
A[counter, out0["CostVar_index"]["T"]] = 1.0
|
|
163
|
+
elif out0["e_T"] != 0 and out1["e_T"] == 0:
|
|
164
|
+
A[counter, out1["CostVar_index"]["T"]] = 1.0
|
|
165
|
+
else:
|
|
166
|
+
A[counter, out0["CostVar_index"]["T"]] = 1.0
|
|
167
|
+
A[counter, out1["CostVar_index"]["T"]] = -1.0
|
|
168
|
+
|
|
169
|
+
equations[counter] = {
|
|
170
|
+
"kind": "aux_p_rule",
|
|
171
|
+
"objects": [self.name, out0["name"], out1["name"]],
|
|
172
|
+
"property": "c_T",
|
|
173
|
+
}
|
|
174
|
+
b[counter] = 0.0
|
|
175
|
+
counter += 1
|
|
176
|
+
|
|
177
|
+
# --- Mechanical equality: c_M,inlet = c_M,outlet_i for each outlet ---
|
|
178
|
+
for out in (out0, out1):
|
|
179
|
+
if inlet["e_M"] != 0 and out["e_M"] != 0:
|
|
180
|
+
A[counter, inlet["CostVar_index"]["M"]] = 1.0 / inlet["e_M"]
|
|
181
|
+
A[counter, out["CostVar_index"]["M"]] = -1.0 / out["e_M"]
|
|
182
|
+
elif inlet["e_M"] == 0 and out["e_M"] != 0:
|
|
183
|
+
A[counter, inlet["CostVar_index"]["M"]] = 1.0
|
|
184
|
+
elif inlet["e_M"] != 0 and out["e_M"] == 0:
|
|
185
|
+
A[counter, out["CostVar_index"]["M"]] = 1.0
|
|
186
|
+
else:
|
|
187
|
+
A[counter, inlet["CostVar_index"]["M"]] = 1.0
|
|
188
|
+
A[counter, out["CostVar_index"]["M"]] = -1.0
|
|
189
|
+
|
|
190
|
+
equations[counter] = {
|
|
191
|
+
"kind": "aux_equality",
|
|
192
|
+
"objects": [self.name, inlet["name"], out["name"]],
|
|
193
|
+
"property": "c_M",
|
|
194
|
+
}
|
|
195
|
+
b[counter] = 0.0
|
|
196
|
+
counter += 1
|
|
197
|
+
|
|
198
|
+
# --- Chemical equality, if enabled: c_CH,inlet = c_CH,outlet_i ---
|
|
199
|
+
if chemical_exergy_enabled:
|
|
200
|
+
for out in (out0, out1):
|
|
201
|
+
if inlet["e_CH"] != 0 and out["e_CH"] != 0:
|
|
202
|
+
A[counter, inlet["CostVar_index"]["CH"]] = 1.0 / inlet["e_CH"]
|
|
203
|
+
A[counter, out["CostVar_index"]["CH"]] = -1.0 / out["e_CH"]
|
|
204
|
+
elif inlet["e_CH"] == 0 and out["e_CH"] != 0:
|
|
205
|
+
A[counter, inlet["CostVar_index"]["CH"]] = 1.0
|
|
206
|
+
elif inlet["e_CH"] != 0 and out["e_CH"] == 0:
|
|
207
|
+
A[counter, out["CostVar_index"]["CH"]] = 1.0
|
|
208
|
+
else:
|
|
209
|
+
A[counter, inlet["CostVar_index"]["CH"]] = 1.0
|
|
210
|
+
A[counter, out["CostVar_index"]["CH"]] = -1.0
|
|
211
|
+
|
|
212
|
+
equations[counter] = {
|
|
213
|
+
"kind": "aux_equality",
|
|
214
|
+
"objects": [self.name, inlet["name"], out["name"]],
|
|
215
|
+
"property": "c_CH",
|
|
216
|
+
}
|
|
217
|
+
b[counter] = 0.0
|
|
218
|
+
counter += 1
|
|
219
|
+
|
|
220
|
+
return A, b, counter, equations
|
|
221
|
+
|
|
222
|
+
def exergoeconomic_balance(self, T0, chemical_exergy_enabled=False):
|
|
223
|
+
r"""
|
|
224
|
+
Perform exergoeconomic cost balance for the flash tank.
|
|
225
|
+
|
|
226
|
+
The general cost balance is:
|
|
227
|
+
|
|
228
|
+
.. math::
|
|
229
|
+
\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
230
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
231
|
+
- \sum_{i=1}^{n} \dot{C}^{\mathrm{T}}_{\mathrm{out},i}
|
|
232
|
+
- \sum_{i=1}^{n} \dot{C}^{\mathrm{M}}_{\mathrm{out},i}
|
|
233
|
+
+ \dot{Z}
|
|
234
|
+
= 0
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
T0 : float
|
|
239
|
+
Ambient temperature
|
|
240
|
+
chemical_exergy_enabled : bool, optional
|
|
241
|
+
If True, chemical exergy is considered in the calculations.
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
# Calculate total cost of inlet streams (thermal + mechanical [+ chemical if enabled])
|
|
245
|
+
C_F = 0.0
|
|
246
|
+
for inlet in self.inl.values():
|
|
247
|
+
C_F += inlet["m"] * (inlet["c_T"] + inlet["c_M"])
|
|
248
|
+
if chemical_exergy_enabled:
|
|
249
|
+
C_F += inlet["m"] * inlet["c_CH"]
|
|
250
|
+
self.C_F = C_F
|
|
251
|
+
|
|
252
|
+
# Calculate total cost of outlet streams (thermal + mechanical [+ chemical if enabled])
|
|
253
|
+
C_P = 0.0
|
|
254
|
+
for outlet in self.outl.values():
|
|
255
|
+
C_P += outlet["m"] * (outlet["c_T"] + outlet["c_M"])
|
|
256
|
+
if chemical_exergy_enabled:
|
|
257
|
+
C_P += outlet["m"] * outlet["c_CH"]
|
|
258
|
+
self.C_P = C_P
|
|
259
|
+
|
|
260
|
+
self.c_F = self.C_F / self.E_F
|
|
261
|
+
self.c_P = self.C_P / self.E_P
|
|
262
|
+
self.C_D = self.c_F * self.E_D
|
|
263
|
+
self.r = (self.c_P - self.c_F) / self.c_F
|
|
264
|
+
self.f = self.Z_costs / (self.Z_costs + self.C_D)
|