exerpy 0.0.1__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 +157 -114
- exerpy/components/component.py +8 -8
- exerpy/components/heat_exchanger/base.py +593 -256
- exerpy/components/heat_exchanger/condenser.py +353 -166
- exerpy/components/heat_exchanger/simple.py +575 -225
- exerpy/components/heat_exchanger/steam_generator.py +153 -123
- exerpy/components/helpers/cycle_closer.py +61 -34
- exerpy/components/helpers/power_bus.py +117 -0
- exerpy/components/nodes/deaerator.py +221 -102
- exerpy/components/nodes/drum.py +50 -39
- exerpy/components/nodes/flash_tank.py +218 -43
- exerpy/components/nodes/mixer.py +296 -115
- exerpy/components/nodes/splitter.py +173 -0
- exerpy/components/nodes/storage.py +130 -0
- exerpy/components/piping/valve.py +351 -139
- 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 +329 -227
- 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.1.dist-info → exerpy-0.0.3.dist-info}/METADATA +45 -4
- exerpy-0.0.3.dist-info/RECORD +48 -0
- exerpy-0.0.1.dist-info/RECORD +0 -44
- {exerpy-0.0.1.dist-info → exerpy-0.0.3.dist-info}/WHEEL +0 -0
- {exerpy-0.0.1.dist-info → exerpy-0.0.3.dist-info}/licenses/LICENSE +0 -0
exerpy/components/nodes/mixer.py
CHANGED
|
@@ -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
|
|
@@ -12,8 +11,8 @@ class Mixer(Component):
|
|
|
12
11
|
Class for exergy analysis of mixers.
|
|
13
12
|
|
|
14
13
|
This class performs exergy analysis calculations for mixers with multiple
|
|
15
|
-
inlet streams and generally one outlet stream (multiple outlets are possible).
|
|
16
|
-
The exergy product and fuel definitions vary based on the temperature
|
|
14
|
+
inlet streams and generally one outlet stream (multiple outlets are possible).
|
|
15
|
+
The exergy product and fuel definitions vary based on the temperature
|
|
17
16
|
relationships between inlet streams, outlet streams, and ambient conditions.
|
|
18
17
|
|
|
19
18
|
Parameters
|
|
@@ -44,53 +43,52 @@ class Mixer(Component):
|
|
|
44
43
|
product and fuel are defined based on temperature relationships:
|
|
45
44
|
|
|
46
45
|
.. math::
|
|
47
|
-
|
|
48
|
-
\dot{
|
|
49
|
-
\begin{cases}
|
|
50
|
-
\begin{cases}
|
|
51
|
-
\sum_i \dot{m}_i \cdot (e_\mathrm{out}^\mathrm{PH} -
|
|
52
|
-
e_{\mathrm{in,}i}^\mathrm{PH})
|
|
53
|
-
& T_{\mathrm{in,}i} < T_\mathrm{out} \mathrm{ & }
|
|
54
|
-
T_{\mathrm{in,}i} \geq T_0 \\
|
|
55
|
-
\sum_i \dot{m}_i \cdot e_\mathrm{out}^\mathrm{PH}
|
|
56
|
-
& T_{\mathrm{in,}i} < T_\mathrm{out} \mathrm{ & }
|
|
57
|
-
T_{\mathrm{in,}i} < T_0 \\
|
|
58
|
-
\end{cases} & T_\mathrm{out} > T_0\\
|
|
59
|
-
\mathrm{not defined (nan)} & T_\mathrm{out} = T_0\\
|
|
46
|
+
\displaystyle
|
|
47
|
+
\dot E_{P} =
|
|
60
48
|
\begin{cases}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
49
|
+
\displaystyle
|
|
50
|
+
\sum_{i}\dot m_{i}\,\bigl(e_{\mathrm{out}}^{\mathrm{PH}}
|
|
51
|
+
-e_{\mathrm{in},i}^{\mathrm{PH}}\bigr),
|
|
52
|
+
\quad \text{if }T_{\mathrm{in},i}<T_{\mathrm{out}}\text{ and }T_{\mathrm{in},i}\ge T_{0},\\[8pt]
|
|
53
|
+
\displaystyle
|
|
54
|
+
\sum_{i}\dot m_{i}\,e_{\mathrm{out}}^{\mathrm{PH}},
|
|
55
|
+
\quad \text{if }T_{\mathrm{in},i}<T_{\mathrm{out}}\text{ and }T_{\mathrm{in},i}<T_{0},\\[8pt]
|
|
56
|
+
\displaystyle
|
|
57
|
+
\text{not defined (nan)},
|
|
58
|
+
\quad \text{if }T_{\mathrm{out}}=T_{0},\\[8pt]
|
|
59
|
+
\displaystyle
|
|
60
|
+
\sum_{i}\dot m_{i}\,e_{\mathrm{out}}^{\mathrm{PH}},
|
|
61
|
+
\quad \text{if }T_{\mathrm{in},i}>T_{\mathrm{out}}\text{ and }T_{\mathrm{in},i}\ge T_{0},\\[8pt]
|
|
62
|
+
\displaystyle
|
|
63
|
+
\sum_{i}\dot m_{i}\,\bigl(e_{\mathrm{out}}^{\mathrm{PH}}
|
|
64
|
+
-e_{\mathrm{in},i}^{\mathrm{PH}}\bigr),
|
|
65
|
+
\quad \text{if }T_{\mathrm{in},i}>T_{\mathrm{out}}\text{ and }T_{\mathrm{in},i}<T_{0}.
|
|
69
66
|
\end{cases}
|
|
70
67
|
|
|
71
|
-
|
|
72
|
-
\
|
|
73
|
-
\
|
|
74
|
-
\sum_i \dot{m}_i \cdot (e_{\mathrm{in,}i}^\mathrm{PH} -
|
|
75
|
-
e_\mathrm{out}^\mathrm{PH})
|
|
76
|
-
& T_{\mathrm{in,}i} > T_\mathrm{out} \\
|
|
77
|
-
\sum_i \dot{m}_i \cdot e_{\mathrm{in,}i}^\mathrm{PH}
|
|
78
|
-
& T_{\mathrm{in,}i} < T_\mathrm{out} \mathrm{ & }
|
|
79
|
-
T_{\mathrm{in,}i} < T_0 \\
|
|
80
|
-
\end{cases} & T_\mathrm{out} > T_0\\
|
|
81
|
-
\sum_i \dot{m}_i \cdot e_{\mathrm{in,}i}^\mathrm{PH}
|
|
82
|
-
& T_\mathrm{out} = T_0\\
|
|
68
|
+
.. math::
|
|
69
|
+
\displaystyle
|
|
70
|
+
\dot E_{F} =
|
|
83
71
|
\begin{cases}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
72
|
+
\displaystyle
|
|
73
|
+
\sum_{i}\dot m_{i}\,\bigl(e_{\mathrm{in},i}^{\mathrm{PH}}
|
|
74
|
+
-e_{\mathrm{out}}^{\mathrm{PH}}\bigr),
|
|
75
|
+
\quad \text{if }T_{\mathrm{out}}>T_{0}\text{ and }T_{\mathrm{in},i}>T_{\mathrm{out}},\\[8pt]
|
|
76
|
+
\displaystyle
|
|
77
|
+
\sum_{i}\dot m_{i}\,e_{\mathrm{in},i}^{\mathrm{PH}},
|
|
78
|
+
\quad \text{if }T_{\mathrm{out}}>T_{0}\text{ and }T_{\mathrm{in},i}<T_{\mathrm{out}}
|
|
79
|
+
\text{ and }T_{\mathrm{in},i}<T_{0},\\[8pt]
|
|
80
|
+
\displaystyle
|
|
81
|
+
\sum_{i}\dot m_{i}\,e_{\mathrm{in},i}^{\mathrm{PH}},
|
|
82
|
+
\quad \text{if }T_{\mathrm{out}}=T_{0},\\[8pt]
|
|
83
|
+
\displaystyle
|
|
84
|
+
\sum_{i}\dot m_{i}\,e_{\mathrm{in},i}^{\mathrm{PH}},
|
|
85
|
+
\quad \text{if }T_{\mathrm{out}}<T_{0}\text{ and }T_{\mathrm{in},i}>T_{\mathrm{out}},\\[8pt]
|
|
86
|
+
\displaystyle
|
|
87
|
+
\sum_{i}\dot m_{i}\,\bigl(e_{\mathrm{in},i}^{\mathrm{PH}}
|
|
88
|
+
-e_{\mathrm{out}}^{\mathrm{PH}}\bigr),
|
|
89
|
+
\quad \text{if }T_{\mathrm{out}}<T_{0}\text{ and }T_{\mathrm{in},i}<T_{\mathrm{out}}.
|
|
91
90
|
\end{cases}
|
|
92
91
|
|
|
93
|
-
\forall i \in \mathrm{mixer inlets}
|
|
94
92
|
"""
|
|
95
93
|
|
|
96
94
|
def __init__(self, **kwargs):
|
|
@@ -121,22 +119,22 @@ class Mixer(Component):
|
|
|
121
119
|
# Ensure that the component has at least two inlets and one outlet.
|
|
122
120
|
if len(self.inl) < 2 or len(self.outl) < 1:
|
|
123
121
|
raise ValueError("Mixer requires at least two inlets and one outlet.")
|
|
124
|
-
|
|
122
|
+
|
|
125
123
|
# Compute effective outlet state by aggregating all outlet streams.
|
|
126
124
|
# Assume that all outlets share the same thermodynamic state.
|
|
127
125
|
outlet_list = list(self.outl.values())
|
|
128
126
|
first_outlet = outlet_list[0]
|
|
129
|
-
T_out = first_outlet[
|
|
130
|
-
e_out_PH = first_outlet[
|
|
127
|
+
T_out = first_outlet["T"]
|
|
128
|
+
e_out_PH = first_outlet["e_PH"]
|
|
131
129
|
# Verify that all outlets have the same thermodynamic state.
|
|
132
130
|
for outlet in outlet_list:
|
|
133
|
-
if outlet[
|
|
131
|
+
if outlet["T"] != T_out or outlet["e_PH"] != e_out_PH:
|
|
134
132
|
msg = "All outlets in Mixer must have the same thermodynamic state."
|
|
135
133
|
logging.error(msg)
|
|
136
134
|
raise ValueError(msg)
|
|
137
135
|
# Sum the mass of all outlet streams (if needed for further analysis)
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
sum(outlet.get("m", 0) for outlet in outlet_list)
|
|
137
|
+
|
|
140
138
|
# Initialize exergy product and fuel.
|
|
141
139
|
self.E_P = 0
|
|
142
140
|
self.E_F = 0
|
|
@@ -145,64 +143,64 @@ class Mixer(Component):
|
|
|
145
143
|
if T_out > T0:
|
|
146
144
|
for _, inlet in self.inl.items():
|
|
147
145
|
# Case when inlet temperature is lower than outlet temperature.
|
|
148
|
-
if inlet[
|
|
149
|
-
if inlet[
|
|
146
|
+
if inlet["T"] < T_out:
|
|
147
|
+
if inlet["T"] >= T0:
|
|
150
148
|
# Contribution to exergy product from inlets above ambient.
|
|
151
|
-
self.E_P += inlet[
|
|
149
|
+
self.E_P += inlet["m"] * (e_out_PH - inlet["e_PH"])
|
|
152
150
|
else: # inlet['T'] < T0
|
|
153
|
-
self.E_P += inlet[
|
|
154
|
-
self.E_F += inlet[
|
|
151
|
+
self.E_P += inlet["m"] * e_out_PH
|
|
152
|
+
self.E_F += inlet["m"] * inlet["e_PH"]
|
|
155
153
|
else: # inlet['T'] > T_out
|
|
156
|
-
self.E_F += inlet[
|
|
157
|
-
|
|
154
|
+
self.E_F += inlet["m"] * (inlet["e_PH"] - e_out_PH)
|
|
155
|
+
|
|
158
156
|
# Case 2: Outlet temperature equals ambient.
|
|
159
157
|
elif T_out == T0:
|
|
160
158
|
self.E_P = np.nan
|
|
161
159
|
for _, inlet in self.inl.items():
|
|
162
|
-
self.E_F += inlet[
|
|
163
|
-
|
|
160
|
+
self.E_F += inlet["m"] * inlet["e_PH"]
|
|
161
|
+
|
|
164
162
|
# Case 3: Outlet temperature is less than ambient.
|
|
165
163
|
else: # T_out < T0
|
|
166
164
|
for _, inlet in self.inl.items():
|
|
167
|
-
if inlet[
|
|
168
|
-
if inlet[
|
|
169
|
-
self.E_P += inlet[
|
|
170
|
-
self.E_F += inlet[
|
|
165
|
+
if inlet["T"] > T_out:
|
|
166
|
+
if inlet["T"] >= T0:
|
|
167
|
+
self.E_P += inlet["m"] * e_out_PH
|
|
168
|
+
self.E_F += inlet["m"] * inlet["e_PH"]
|
|
171
169
|
else: # inlet['T'] < T0
|
|
172
|
-
self.E_P += inlet[
|
|
170
|
+
self.E_P += inlet["m"] * (e_out_PH - inlet["e_PH"])
|
|
173
171
|
else: # inlet['T'] <= T_out
|
|
174
|
-
self.E_F += inlet[
|
|
175
|
-
|
|
172
|
+
self.E_F += inlet["m"] * (inlet["e_PH"] - e_out_PH)
|
|
173
|
+
|
|
176
174
|
# Calculate exergy destruction and efficiency.
|
|
177
175
|
self.E_D = self.E_F - self.E_P
|
|
178
176
|
self.epsilon = self.calc_epsilon()
|
|
179
|
-
|
|
177
|
+
|
|
180
178
|
# Log the results.
|
|
181
179
|
logging.info(
|
|
182
|
-
f"Mixer
|
|
180
|
+
f"Exergy balance of Mixer {self.name} calculated: "
|
|
183
181
|
f"E_P={self.E_P:.2f}, E_F={self.E_F:.2f}, E_D={self.E_D:.2f}, "
|
|
184
182
|
f"Efficiency={self.epsilon:.2%}"
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
183
|
+
)
|
|
188
184
|
|
|
189
185
|
def aux_eqs(self, A, b, counter, T0, equations, chemical_exergy_enabled):
|
|
190
186
|
"""
|
|
191
187
|
Auxiliary equations for the mixer.
|
|
192
|
-
|
|
188
|
+
|
|
193
189
|
This function adds rows to the cost matrix A and the right-hand-side vector b to enforce
|
|
194
190
|
the following auxiliary cost relations:
|
|
195
|
-
|
|
196
|
-
(1)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
191
|
+
|
|
192
|
+
(1) Mixing equation for chemical exergy costs (if enabled):
|
|
193
|
+
|
|
194
|
+
- The outlet's specific chemical exergy cost is calculated as a mass-weighted average of the inlet streams' specific chemical exergy costs
|
|
195
|
+
|
|
196
|
+
- This enforces proper chemical exergy cost distribution through the deaerator
|
|
197
|
+
|
|
198
|
+
(2) Mixing equation for mechanical exergy costs:
|
|
199
|
+
|
|
200
|
+
- The outlet's specific mechanical exergy cost is calculated as a mass-weighted average of the inlet streams' specific mechanical exergy costs
|
|
201
|
+
|
|
202
|
+
- This ensures mechanical exergy costs are properly conserved in the mixing process
|
|
203
|
+
|
|
206
204
|
Parameters
|
|
207
205
|
----------
|
|
208
206
|
A : numpy.ndarray
|
|
@@ -243,13 +241,16 @@ class Mixer(Component):
|
|
|
243
241
|
# Outlet chemical exergy is zero: assign fallback for all inlets.
|
|
244
242
|
for inlet in self.inl.values():
|
|
245
243
|
A[counter, inlet["CostVar_index"]["CH"]] = 1
|
|
246
|
-
equations[counter] =
|
|
244
|
+
equations[counter] = {
|
|
245
|
+
"kind": "aux_mixing",
|
|
246
|
+
"objects": [self.name, self.inl[0]["name"], self.inl[1]["name"], self.outl[0]["name"]],
|
|
247
|
+
"property": "c_CH",
|
|
248
|
+
}
|
|
247
249
|
chem_row = 1 # One row added for chemical equation.
|
|
248
250
|
else:
|
|
249
251
|
chem_row = 0 # No row added.
|
|
250
252
|
|
|
251
253
|
# --- Mechanical cost auxiliary equation ---
|
|
252
|
-
mech_row = 0 # This row will always be added.
|
|
253
254
|
if self.outl[0]["e_M"] != 0:
|
|
254
255
|
A[counter + chem_row, self.outl[0]["CostVar_index"]["M"]] = -1 / self.outl[0]["E_M"]
|
|
255
256
|
# Iterate over inlet streams for mechanical mixing.
|
|
@@ -261,7 +262,15 @@ class Mixer(Component):
|
|
|
261
262
|
else:
|
|
262
263
|
for inlet in self.inl.values():
|
|
263
264
|
A[counter + chem_row, inlet["CostVar_index"]["M"]] = 1
|
|
264
|
-
|
|
265
|
+
|
|
266
|
+
# Dynamically build the list of inlet names
|
|
267
|
+
inlet_names = [inlet["name"] for inlet in self.inl.values()]
|
|
268
|
+
|
|
269
|
+
equations[counter + chem_row] = {
|
|
270
|
+
"kind": "aux_mixing",
|
|
271
|
+
"objects": [self.name] + inlet_names + [self.outl[0]["name"]],
|
|
272
|
+
"property": "c_M",
|
|
273
|
+
}
|
|
265
274
|
|
|
266
275
|
# Set the right-hand side entries to zero for the added rows.
|
|
267
276
|
if chemical_exergy_enabled:
|
|
@@ -273,40 +282,208 @@ class Mixer(Component):
|
|
|
273
282
|
counter += 1 # Only one row was added.
|
|
274
283
|
|
|
275
284
|
return A, b, counter, equations
|
|
276
|
-
|
|
277
|
-
def exergoeconomic_balance(self, T0):
|
|
278
|
-
"""
|
|
279
|
-
Perform exergoeconomic balance
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
285
|
+
|
|
286
|
+
def exergoeconomic_balance(self, T0, chemical_exergy_enabled=False):
|
|
287
|
+
r"""
|
|
288
|
+
Perform exergoeconomic cost balance for the mixer.
|
|
289
|
+
|
|
290
|
+
The mixer is a component where multiple streams combine. The general
|
|
291
|
+
exergoeconomic balance equation is:
|
|
292
|
+
|
|
293
|
+
.. math::
|
|
294
|
+
\sum_{\mathrm{in}} \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
295
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
296
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}\right)
|
|
297
|
+
- \sum_{\mathrm{out}} \left(\dot{C}^{\mathrm{T}}_{\mathrm{out}}
|
|
298
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
299
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{out}}\right)
|
|
300
|
+
+ \dot{Z}
|
|
301
|
+
= 0
|
|
302
|
+
|
|
303
|
+
The product is defined as the outlet stream. The fuel consists of all inlet
|
|
304
|
+
streams, with treatment depending on temperature levels and whether chemical
|
|
305
|
+
exergy is enabled. The cost balance is closed using:
|
|
306
|
+
|
|
307
|
+
.. math::
|
|
308
|
+
\dot{C}_{\mathrm{P}} = \dot{C}_{\mathrm{F}} + \dot{Z}
|
|
309
|
+
|
|
310
|
+
**Case 1: Outlet above ambient temperature**
|
|
311
|
+
|
|
312
|
+
When :math:`T_{\mathrm{out}} > T_0`:
|
|
313
|
+
|
|
314
|
+
For cold inlets (:math:`T_{\mathrm{in}} < T_{\mathrm{out}}`):
|
|
315
|
+
|
|
316
|
+
Without chemical exergy:
|
|
317
|
+
|
|
318
|
+
.. math::
|
|
319
|
+
\dot{C}_{\mathrm{F,cold}} = \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
320
|
+
|
|
321
|
+
With chemical exergy enabled:
|
|
322
|
+
|
|
323
|
+
.. math::
|
|
324
|
+
\dot{C}_{\mathrm{F,cold}} = \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
325
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}
|
|
326
|
+
|
|
327
|
+
For hot inlets (:math:`T_{\mathrm{in}} \geq T_{\mathrm{out}}`):
|
|
328
|
+
|
|
329
|
+
Without chemical exergy:
|
|
330
|
+
|
|
331
|
+
.. math::
|
|
332
|
+
\dot{C}_{\mathrm{F,hot}} = -\dot{m}_{\mathrm{in}} \cdot c^{\mathrm{T}}_{\mathrm{in}}
|
|
333
|
+
\cdot e^{\mathrm{T}}_{\mathrm{in}}
|
|
334
|
+
+ \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
335
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}\right)
|
|
336
|
+
|
|
337
|
+
With chemical exergy enabled:
|
|
338
|
+
|
|
339
|
+
.. math::
|
|
340
|
+
\dot{C}_{\mathrm{F,hot}} = -\dot{m}_{\mathrm{in}} \cdot c^{\mathrm{T}}_{\mathrm{in}}
|
|
341
|
+
\cdot e^{\mathrm{T}}_{\mathrm{in}}
|
|
342
|
+
+ \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
343
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
344
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}\right)
|
|
345
|
+
|
|
346
|
+
Total fuel cost (without chemical exergy):
|
|
347
|
+
|
|
348
|
+
.. math::
|
|
349
|
+
\dot{C}_{\mathrm{F}} = \sum \dot{C}_{\mathrm{F,cold}}
|
|
350
|
+
+ \sum \dot{C}_{\mathrm{F,hot}}
|
|
351
|
+
- \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
352
|
+
|
|
353
|
+
Total fuel cost (with chemical exergy):
|
|
354
|
+
|
|
355
|
+
.. math::
|
|
356
|
+
\dot{C}_{\mathrm{F}} = \sum \dot{C}_{\mathrm{F,cold}}
|
|
357
|
+
+ \sum \dot{C}_{\mathrm{F,hot}}
|
|
358
|
+
- \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
359
|
+
- \dot{C}^{\mathrm{CH}}_{\mathrm{out}}
|
|
360
|
+
|
|
361
|
+
**Case 2: Outlet at ambient temperature (dissipative)**
|
|
362
|
+
|
|
363
|
+
When :math:`|T_{\mathrm{out}} - T_0| < 10^{-6}`:
|
|
364
|
+
|
|
365
|
+
.. math::
|
|
366
|
+
\dot{C}_{\mathrm{F}} = \sum_{\mathrm{in}} \dot{C}^{\mathrm{TOT}}_{\mathrm{in}}
|
|
367
|
+
|
|
368
|
+
**Case 3: Outlet below ambient temperature**
|
|
369
|
+
|
|
370
|
+
When :math:`T_{\mathrm{out}} < T_0`:
|
|
371
|
+
|
|
372
|
+
For hot inlets (:math:`T_{\mathrm{in}} > T_{\mathrm{out}}`):
|
|
373
|
+
|
|
374
|
+
Without chemical exergy:
|
|
375
|
+
|
|
376
|
+
.. math::
|
|
377
|
+
\dot{C}_{\mathrm{F,hot}} = \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
378
|
+
|
|
379
|
+
With chemical exergy enabled:
|
|
380
|
+
|
|
381
|
+
.. math::
|
|
382
|
+
\dot{C}_{\mathrm{F,hot}} = \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
383
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}
|
|
384
|
+
|
|
385
|
+
For cold inlets (:math:`T_{\mathrm{in}} \leq T_{\mathrm{out}}`):
|
|
386
|
+
|
|
387
|
+
Without chemical exergy:
|
|
388
|
+
|
|
389
|
+
.. math::
|
|
390
|
+
\dot{C}_{\mathrm{F,cold}} = -\dot{m}_{\mathrm{in}} \cdot c^{\mathrm{T}}_{\mathrm{in}}
|
|
391
|
+
\cdot e^{\mathrm{T}}_{\mathrm{in}}
|
|
392
|
+
+ \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
393
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}\right)
|
|
394
|
+
|
|
395
|
+
With chemical exergy enabled:
|
|
396
|
+
|
|
397
|
+
.. math::
|
|
398
|
+
\dot{C}_{\mathrm{F,cold}} = -\dot{m}_{\mathrm{in}} \cdot c^{\mathrm{T}}_{\mathrm{in}}
|
|
399
|
+
\cdot e^{\mathrm{T}}_{\mathrm{in}}
|
|
400
|
+
+ \left(\dot{C}^{\mathrm{T}}_{\mathrm{in}}
|
|
401
|
+
+ \dot{C}^{\mathrm{M}}_{\mathrm{in}}
|
|
402
|
+
+ \dot{C}^{\mathrm{CH}}_{\mathrm{in}}\right)
|
|
403
|
+
|
|
404
|
+
Total fuel cost (without chemical exergy):
|
|
405
|
+
|
|
406
|
+
.. math::
|
|
407
|
+
\dot{C}_{\mathrm{F}} = \sum \dot{C}_{\mathrm{F,hot}}
|
|
408
|
+
+ \sum \dot{C}_{\mathrm{F,cold}}
|
|
409
|
+
- \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
410
|
+
|
|
411
|
+
Total fuel cost (with chemical exergy):
|
|
412
|
+
|
|
413
|
+
.. math::
|
|
414
|
+
\dot{C}_{\mathrm{F}} = \sum \dot{C}_{\mathrm{F,hot}}
|
|
415
|
+
+ \sum \dot{C}_{\mathrm{F,cold}}
|
|
416
|
+
- \dot{C}^{\mathrm{M}}_{\mathrm{out}}
|
|
417
|
+
- \dot{C}^{\mathrm{CH}}_{\mathrm{out}}
|
|
418
|
+
|
|
419
|
+
**Calculated exergoeconomic indicators:**
|
|
420
|
+
|
|
421
|
+
.. math::
|
|
422
|
+
c_{\mathrm{F}} = \frac{\dot{C}_{\mathrm{F}}}{\dot{E}_{\mathrm{F}}}
|
|
423
|
+
|
|
424
|
+
.. math::
|
|
425
|
+
c_{\mathrm{P}} = \frac{\dot{C}_{\mathrm{P}}}{\dot{E}_{\mathrm{P}}}
|
|
426
|
+
|
|
427
|
+
.. math::
|
|
428
|
+
\dot{C}_{\mathrm{D}} = c_{\mathrm{F}} \cdot \dot{E}_{\mathrm{D}}
|
|
429
|
+
|
|
430
|
+
.. math::
|
|
431
|
+
r = \frac{c_{\mathrm{P}} - c_{\mathrm{F}}}{c_{\mathrm{F}}}
|
|
432
|
+
|
|
433
|
+
.. math::
|
|
434
|
+
f = \frac{\dot{Z}}{\dot{Z} + \dot{C}_{\mathrm{D}}}
|
|
435
|
+
|
|
288
436
|
Parameters
|
|
289
437
|
----------
|
|
290
438
|
T0 : float
|
|
291
|
-
Ambient temperature
|
|
292
|
-
|
|
439
|
+
Ambient temperature (K).
|
|
440
|
+
chemical_exergy_enabled : bool, optional
|
|
441
|
+
If True, chemical exergy is considered in the calculations.
|
|
442
|
+
Default is False.
|
|
443
|
+
|
|
444
|
+
Attributes Set
|
|
445
|
+
--------------
|
|
446
|
+
C_P : float
|
|
447
|
+
Cost rate of product (currency/time).
|
|
448
|
+
C_F : float
|
|
449
|
+
Cost rate of fuel (currency/time).
|
|
450
|
+
c_P : float
|
|
451
|
+
Specific cost of product (currency/energy).
|
|
452
|
+
c_F : float
|
|
453
|
+
Specific cost of fuel (currency/energy).
|
|
454
|
+
C_D : float
|
|
455
|
+
Cost rate of exergy destruction (currency/time).
|
|
456
|
+
r : float
|
|
457
|
+
Relative cost difference (dimensionless).
|
|
458
|
+
f : float
|
|
459
|
+
Exergoeconomic factor (dimensionless).
|
|
460
|
+
|
|
293
461
|
Notes
|
|
294
462
|
-----
|
|
295
|
-
The
|
|
296
|
-
|
|
463
|
+
The mixer treats thermal, mechanical, and chemical exergy components
|
|
464
|
+
differently depending on whether inlets are "hot" or "cold" relative to
|
|
465
|
+
the outlet temperature. The distinction ensures proper cost allocation
|
|
466
|
+
for streams that provide heating versus those being heated.
|
|
467
|
+
|
|
468
|
+
Future development may include merging profits from dissipative components.
|
|
297
469
|
"""
|
|
298
470
|
self.C_P = 0
|
|
299
471
|
self.C_F = 0
|
|
300
472
|
if self.outl[0]["T"] > T0:
|
|
301
|
-
for i in self.inl:
|
|
473
|
+
for i in self.inl.values():
|
|
302
474
|
if i["T"] < self.outl[0]["T"]:
|
|
303
475
|
# cold inlets
|
|
304
|
-
self.C_F += i["C_M"]
|
|
476
|
+
self.C_F += i["C_M"]
|
|
477
|
+
if chemical_exergy_enabled:
|
|
478
|
+
self.C_F += i["C_CH"]
|
|
305
479
|
else:
|
|
306
480
|
# hot inlets
|
|
307
|
-
self.C_F += -
|
|
308
|
-
|
|
309
|
-
|
|
481
|
+
self.C_F += -i["m"] * i["c_T"] * i["e_T"] + (i["C_T"] + i["C_M"])
|
|
482
|
+
if chemical_exergy_enabled:
|
|
483
|
+
self.C_F += i["C_CH"]
|
|
484
|
+
self.C_F += -self.outl[0]["C_M"]
|
|
485
|
+
if chemical_exergy_enabled:
|
|
486
|
+
self.C_F += -self.outl[0]["C_CH"]
|
|
310
487
|
elif self.outl[0]["T"] - 1e-6 < T0 and self.outl[0]["T"] + 1e-6 > T0:
|
|
311
488
|
# dissipative
|
|
312
489
|
for i in self.inl:
|
|
@@ -315,18 +492,22 @@ class Mixer(Component):
|
|
|
315
492
|
for i in self.inl:
|
|
316
493
|
if i["T"] > self.outl[0]["T"]:
|
|
317
494
|
# hot inlets
|
|
318
|
-
self.C_F += i["C_M"]
|
|
495
|
+
self.C_F += i["C_M"]
|
|
496
|
+
if chemical_exergy_enabled:
|
|
497
|
+
self.C_F += i["C_M"] + i["C_CH"]
|
|
319
498
|
else:
|
|
320
499
|
# cold inlets
|
|
321
|
-
self.C_F += -
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
500
|
+
self.C_F += -i["m"] * i["c_T"] * i["e_T"] + (i["C_T"] + i["C_M"])
|
|
501
|
+
if chemical_exergy_enabled:
|
|
502
|
+
self.C_F += i["C_CH"]
|
|
503
|
+
self.C_F += -self.outl[0]["C_M"]
|
|
504
|
+
if chemical_exergy_enabled:
|
|
505
|
+
self.C_F += -self.outl[0]["C_CH"]
|
|
506
|
+
self.C_P = self.C_F + self.Z_costs # +1/num_serving_comps * C_diff
|
|
325
507
|
# ToDo: add case that merge profits from dissipative component(s)
|
|
326
508
|
|
|
327
|
-
|
|
328
509
|
self.c_F = self.C_F / self.E_F
|
|
329
510
|
self.c_P = self.C_P / self.E_P
|
|
330
511
|
self.C_D = self.c_F * self.E_D
|
|
331
512
|
self.r = (self.c_P - self.c_F) / self.c_F
|
|
332
|
-
self.f = self.Z_costs / (self.Z_costs + self.C_D)
|
|
513
|
+
self.f = self.Z_costs / (self.Z_costs + self.C_D)
|