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
exerpy/components/__init__.py
CHANGED
|
@@ -4,10 +4,13 @@ from .heat_exchanger.condenser import Condenser
|
|
|
4
4
|
from .heat_exchanger.simple import SimpleHeatExchanger
|
|
5
5
|
from .heat_exchanger.steam_generator import SteamGenerator
|
|
6
6
|
from .helpers.cycle_closer import CycleCloser
|
|
7
|
+
from .helpers.power_bus import PowerBus
|
|
7
8
|
from .nodes.deaerator import Deaerator
|
|
8
9
|
from .nodes.drum import Drum
|
|
9
10
|
from .nodes.flash_tank import FlashTank
|
|
10
11
|
from .nodes.mixer import Mixer
|
|
12
|
+
from .nodes.splitter import Splitter
|
|
13
|
+
from .nodes.storage import Storage
|
|
11
14
|
from .piping.valve import Valve
|
|
12
15
|
from .power_machines.generator import Generator
|
|
13
16
|
from .power_machines.motor import Motor
|
|
@@ -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
|
|
@@ -67,8 +64,8 @@ class CombustionChamber(Component):
|
|
|
67
64
|
"""
|
|
68
65
|
super().__init__(**kwargs)
|
|
69
66
|
# Initialize additional attributes if necessary
|
|
70
|
-
self.Ex_C_col = kwargs.get(
|
|
71
|
-
self.Z_costs = kwargs.get(
|
|
67
|
+
self.Ex_C_col = kwargs.get("Ex_C_col", {})
|
|
68
|
+
self.Z_costs = kwargs.get("Z_costs", 0.0) # Cost rate in currency/h
|
|
72
69
|
|
|
73
70
|
def calc_exergy_balance(self, T0: float, p0: float, split_physical_exergy) -> None:
|
|
74
71
|
r"""
|
|
@@ -99,25 +96,25 @@ class CombustionChamber(Component):
|
|
|
99
96
|
If fewer than two inlets or no outlets are defined.
|
|
100
97
|
"""
|
|
101
98
|
# Check for necessary inlet and outlet data
|
|
102
|
-
if not hasattr(self,
|
|
99
|
+
if not hasattr(self, "inl") or not hasattr(self, "outl") or len(self.inl) < 2 or len(self.outl) < 1:
|
|
103
100
|
msg = "CombustionChamber requires at least two inlets (air and fuel) and one outlet (exhaust)."
|
|
104
101
|
logging.error(msg)
|
|
105
102
|
raise ValueError(msg)
|
|
106
103
|
|
|
107
104
|
# Calculate total physical exergy of outlets
|
|
108
|
-
total_E_P_out = sum(outlet[
|
|
105
|
+
total_E_P_out = sum(outlet["m"] * outlet["e_PH"] for outlet in self.outl.values())
|
|
109
106
|
|
|
110
107
|
# Calculate total physical exergy of inlets
|
|
111
|
-
total_E_P_in = sum(inlet[
|
|
108
|
+
total_E_P_in = sum(inlet["m"] * inlet["e_PH"] for inlet in self.inl.values())
|
|
112
109
|
|
|
113
110
|
# Exergy Product (E_P)
|
|
114
111
|
self.E_P = total_E_P_out - total_E_P_in
|
|
115
112
|
|
|
116
113
|
# Calculate total chemical exergy of inlets
|
|
117
|
-
total_E_F_in = sum(inlet[
|
|
114
|
+
total_E_F_in = sum(inlet["m"] * inlet["e_CH"] for inlet in self.inl.values())
|
|
118
115
|
|
|
119
116
|
# Calculate total chemical exergy of outlets
|
|
120
|
-
total_E_F_out = sum(outlet[
|
|
117
|
+
total_E_F_out = sum(outlet["m"] * outlet["e_CH"] for outlet in self.outl.values())
|
|
121
118
|
|
|
122
119
|
# Exergy Fuel (E_F)
|
|
123
120
|
self.E_F = total_E_F_in - total_E_F_out
|
|
@@ -130,12 +127,11 @@ class CombustionChamber(Component):
|
|
|
130
127
|
|
|
131
128
|
# Log the results
|
|
132
129
|
logging.info(
|
|
133
|
-
f"CombustionChamber
|
|
130
|
+
f"Exergy balance of CombustionChamber {self.name} calculated: "
|
|
134
131
|
f"E_P={self.E_P:.2f}, E_F={self.E_F:.2f}, E_D={self.E_D:.2f}, "
|
|
135
132
|
f"Efficiency={self.epsilon:.2%}"
|
|
136
133
|
)
|
|
137
134
|
|
|
138
|
-
|
|
139
135
|
def aux_eqs(self, A, b, counter, T0, equations, chemical_exergy_enabled):
|
|
140
136
|
r"""
|
|
141
137
|
Add auxiliary cost equations for the combustion chamber.
|
|
@@ -195,40 +191,59 @@ class CombustionChamber(Component):
|
|
|
195
191
|
"""
|
|
196
192
|
# For the combustion chamber, chemical exergy is mandatory.
|
|
197
193
|
if not chemical_exergy_enabled:
|
|
198
|
-
raise ValueError(
|
|
199
|
-
|
|
194
|
+
raise ValueError(
|
|
195
|
+
"Chemical exergy is mandatory for the combustion chamber!",
|
|
196
|
+
"Please make sure that your exergy analysis consider the chemical exergy.",
|
|
197
|
+
)
|
|
200
198
|
|
|
201
199
|
# Convert inlet and outlet dictionaries to lists for ordered access.
|
|
202
200
|
inlets = list(self.inl.values())
|
|
203
201
|
outlets = list(self.outl.values())
|
|
204
202
|
|
|
205
203
|
# --- Mechanical cost auxiliary equation ---
|
|
206
|
-
if
|
|
204
|
+
if outlets[0]["e_M"] != 0 and inlets[0]["e_M"] != 0 and inlets[1]["e_M"] != 0:
|
|
207
205
|
A[counter, outlets[0]["CostVar_index"]["M"]] = -1 / outlets[0]["E_M"]
|
|
208
|
-
A[counter, inlets[0]["CostVar_index"]["M"]] = (
|
|
209
|
-
|
|
206
|
+
A[counter, inlets[0]["CostVar_index"]["M"]] = (
|
|
207
|
+
(1 / inlets[0]["E_M"]) * inlets[0]["m"] / (inlets[0]["m"] + inlets[1]["m"])
|
|
208
|
+
)
|
|
209
|
+
A[counter, inlets[1]["CostVar_index"]["M"]] = (
|
|
210
|
+
(1 / inlets[1]["E_M"]) * inlets[1]["m"] / (inlets[0]["m"] + inlets[1]["m"])
|
|
211
|
+
)
|
|
210
212
|
else: # pressure can only decrease in the combustion chamber (case with p_inlet = p0 and p_outlet < p0 NOT considered)
|
|
211
213
|
A[counter, outlets[0]["CostVar_index"]["M"]] = 1
|
|
212
214
|
equations[counter] = f"aux_mixing_mech_{self.outl[0]['name']}"
|
|
215
|
+
equations[counter] = {
|
|
216
|
+
"kind": "aux_mixing",
|
|
217
|
+
"objects": [self.name, self.inl[0]["name"], self.inl[1]["name"], self.outl[0]["name"]],
|
|
218
|
+
"property": "c_M",
|
|
219
|
+
}
|
|
213
220
|
|
|
214
221
|
# --- Chemical cost auxiliary equation ---
|
|
215
|
-
if
|
|
216
|
-
A[counter+1, outlets[0]["CostVar_index"]["CH"]] = -1 / outlets[0]["E_CH"]
|
|
217
|
-
A[counter+1, inlets[0]["CostVar_index"]["CH"]] = (
|
|
218
|
-
|
|
222
|
+
if outlets[0]["e_CH"] != 0 and inlets[0]["e_CH"] != 0 and inlets[1]["e_CH"] != 0:
|
|
223
|
+
A[counter + 1, outlets[0]["CostVar_index"]["CH"]] = -1 / outlets[0]["E_CH"]
|
|
224
|
+
A[counter + 1, inlets[0]["CostVar_index"]["CH"]] = (
|
|
225
|
+
(1 / inlets[0]["E_CH"]) * inlets[0]["m"] / (inlets[0]["m"] + inlets[1]["m"])
|
|
226
|
+
)
|
|
227
|
+
A[counter + 1, inlets[1]["CostVar_index"]["CH"]] = (
|
|
228
|
+
(1 / inlets[1]["E_CH"]) * inlets[1]["m"] / (inlets[0]["m"] + inlets[1]["m"])
|
|
229
|
+
)
|
|
219
230
|
elif inlets[0]["e_CH"] == 0:
|
|
220
|
-
A[counter+1, inlets[0]["CostVar_index"]["CH"]] = 1
|
|
231
|
+
A[counter + 1, inlets[0]["CostVar_index"]["CH"]] = 1
|
|
221
232
|
elif inlets[1]["e_CH"] == 0:
|
|
222
|
-
A[counter+1, inlets[1]["CostVar_index"]["CH"]] = 1
|
|
223
|
-
equations[counter
|
|
233
|
+
A[counter + 1, inlets[1]["CostVar_index"]["CH"]] = 1
|
|
234
|
+
equations[counter] = {
|
|
235
|
+
"kind": "aux_mixing",
|
|
236
|
+
"objects": [self.name, self.inl[0]["name"], self.inl[1]["name"], self.outl[0]["name"]],
|
|
237
|
+
"property": "c_CH",
|
|
238
|
+
}
|
|
224
239
|
|
|
225
240
|
# Set the right-hand side entries to zero.
|
|
226
|
-
b[counter]
|
|
227
|
-
b[counter+1] = 0
|
|
241
|
+
b[counter] = 0
|
|
242
|
+
b[counter + 1] = 0
|
|
228
243
|
|
|
229
244
|
return [A, b, counter + 2, equations]
|
|
230
245
|
|
|
231
|
-
def exergoeconomic_balance(self, T0):
|
|
246
|
+
def exergoeconomic_balance(self, T0, chemical_exergy_enabled=False):
|
|
232
247
|
r"""
|
|
233
248
|
Perform exergoeconomic cost balance for the combustion chamber.
|
|
234
249
|
|
|
@@ -257,17 +272,20 @@ class CombustionChamber(Component):
|
|
|
257
272
|
----------
|
|
258
273
|
T0 : float
|
|
259
274
|
Ambient temperature (K).
|
|
275
|
+
chemical_exergy_enabled : bool, optional
|
|
276
|
+
If True, chemical exergy is considered in the calculations.
|
|
260
277
|
"""
|
|
261
|
-
self.C_P = self.outl[0]["C_T"] - (
|
|
262
|
-
self.inl[0]["C_T"] + self.inl[1]["C_T"]
|
|
263
|
-
)
|
|
278
|
+
self.C_P = self.outl[0]["C_T"] - (self.inl[0]["C_T"] + self.inl[1]["C_T"])
|
|
264
279
|
self.C_F = (
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
280
|
+
self.inl[0]["C_CH"]
|
|
281
|
+
+ self.inl[1]["C_CH"]
|
|
282
|
+
- self.outl[0]["C_CH"]
|
|
283
|
+
+ self.inl[0]["C_M"]
|
|
284
|
+
+ self.inl[1]["C_M"]
|
|
285
|
+
- self.outl[0]["C_M"]
|
|
268
286
|
)
|
|
269
287
|
self.c_F = self.C_F / self.E_F
|
|
270
288
|
self.c_P = self.C_P / self.E_P
|
|
271
289
|
self.C_D = self.c_F * self.E_D
|
|
272
290
|
self.r = (self.c_P - self.c_F) / self.c_F
|
|
273
|
-
self.f = self.Z_costs / (self.Z_costs + self.C_D)
|
|
291
|
+
self.f = self.Z_costs / (self.Z_costs + self.C_D)
|
exerpy/components/component.py
CHANGED
|
@@ -20,7 +20,7 @@ class Component:
|
|
|
20
20
|
Base class for all ExerPy components.
|
|
21
21
|
|
|
22
22
|
This class serves as the parent class for all exergy analysis components. It provides
|
|
23
|
-
the basic structure and methods for exergy analysis calculations including the
|
|
23
|
+
the basic structure and methods for exergy analysis calculations including the
|
|
24
24
|
calculation of exergetic efficiency and exergy balance.
|
|
25
25
|
|
|
26
26
|
Parameters
|
|
@@ -41,7 +41,7 @@ class Component:
|
|
|
41
41
|
|
|
42
42
|
Notes
|
|
43
43
|
-----
|
|
44
|
-
The exergetic efficiency is calculated as the ratio of exergy product to
|
|
44
|
+
The exergetic efficiency is calculated as the ratio of exergy product to
|
|
45
45
|
exergy fuel:
|
|
46
46
|
|
|
47
47
|
.. math::
|
|
@@ -84,14 +84,14 @@ class Component:
|
|
|
84
84
|
r"""
|
|
85
85
|
Calculate the exergetic efficiency of the component.
|
|
86
86
|
|
|
87
|
-
The exergetic efficiency is defined as the ratio of exergy product to
|
|
88
|
-
exergy fuel. If the exergy fuel is zero, the function returns NaN to
|
|
87
|
+
The exergetic efficiency is defined as the ratio of exergy product to
|
|
88
|
+
exergy fuel. If the exergy fuel is zero, the function returns NaN to
|
|
89
89
|
avoid division by zero.
|
|
90
90
|
|
|
91
91
|
Returns
|
|
92
92
|
-------
|
|
93
93
|
float or nan
|
|
94
|
-
Exergetic efficiency :math:`\varepsilon = \frac{\dot{E}_\mathrm{P}}{\dot{E}_\mathrm{F}}`
|
|
94
|
+
Exergetic efficiency :math:`\varepsilon = \frac{\dot{E}_\mathrm{P}}{\dot{E}_\mathrm{F}}`
|
|
95
95
|
or NaN if :math:`\dot{E}_\mathrm{F} = 0`.
|
|
96
96
|
|
|
97
97
|
Notes
|
|
@@ -106,9 +106,8 @@ class Component:
|
|
|
106
106
|
return np.nan
|
|
107
107
|
else:
|
|
108
108
|
return self.E_P / self.E_F
|
|
109
|
-
|
|
110
109
|
|
|
111
|
-
def exergoeconomic_balance(self, T0):
|
|
110
|
+
def exergoeconomic_balance(self, T0, chemical_exergy_enabled=False):
|
|
112
111
|
r"""
|
|
113
112
|
Placeholder method for exergoeconomic balance.
|
|
114
113
|
|
|
@@ -121,6 +120,7 @@ class Component:
|
|
|
121
120
|
----------
|
|
122
121
|
T0 : float
|
|
123
122
|
Ambient temperature in :math:`\mathrm{K}`.
|
|
123
|
+
chemical_exergy_enabled : bool, optional
|
|
124
|
+
If True, chemical exergy is considered in the calculations.
|
|
124
125
|
"""
|
|
125
126
|
return
|
|
126
|
-
|