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
exerpy/functions.py
CHANGED
|
@@ -2,7 +2,6 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import math
|
|
4
4
|
import os
|
|
5
|
-
import sys
|
|
6
5
|
|
|
7
6
|
import CoolProp.CoolProp as CP
|
|
8
7
|
|
|
@@ -19,32 +18,39 @@ def mass_to_molar_fractions(mass_fractions):
|
|
|
19
18
|
Returns:
|
|
20
19
|
- molar_fractions: Dictionary with component names as keys and molar fractions as values.
|
|
21
20
|
"""
|
|
22
|
-
molar_masses = {}
|
|
23
21
|
molar_fractions = {}
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
try:
|
|
28
|
-
molar_masses[fraction] = CP.PropsSI('M', fraction)
|
|
29
|
-
except Exception as e:
|
|
30
|
-
# print(f"Warning: Could not retrieve molar mass for {fraction} ({fraction}). Error: {e}")
|
|
31
|
-
continue # Skip this fraction if there's an issue
|
|
23
|
+
if len(mass_fractions.values()) == 1:
|
|
24
|
+
molar_fractions = {comp: 1.0 for comp in mass_fractions}
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
raise ValueError("No valid molar masses were retrieved. Exiting...")
|
|
26
|
+
else:
|
|
27
|
+
molar_masses = {}
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
# Step 1: Get the molar masses for each component
|
|
30
|
+
for fraction in mass_fractions:
|
|
31
|
+
try:
|
|
32
|
+
molar_masses[fraction] = CP.PropsSI("M", fraction)
|
|
33
|
+
except Exception:
|
|
34
|
+
# print(f"Warning: Could not retrieve molar mass for {fraction} ({fraction}). Error: {e}")
|
|
35
|
+
continue # Skip this fraction if there's an issue
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
# Step 2: Check if we have valid molar masses
|
|
38
|
+
if not molar_masses:
|
|
39
|
+
raise ValueError(f"No valid molar masses were retrieved for substances {list(mass_fractions.keys())}")
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
else:
|
|
42
|
+
|
|
43
|
+
# Step 3: Calculate total moles in the mixture
|
|
44
|
+
total_moles = sum(mass_fractions[comp] / molar_masses[comp] for comp in molar_masses)
|
|
45
|
+
|
|
46
|
+
# Step 4: Calculate molar fractions
|
|
47
|
+
for component in molar_masses:
|
|
48
|
+
molar_fractions[component] = (mass_fractions[component] / molar_masses[component]) / total_moles
|
|
49
|
+
|
|
50
|
+
# Step 5: Check if molar fractions sum to approximately 1
|
|
51
|
+
molar_sum = sum(molar_fractions.values())
|
|
52
|
+
if abs(molar_sum - 1.0) > 1e-6:
|
|
53
|
+
raise ValueError(f"Error: Molar fractions do not sum to 1. Sum is {molar_sum}")
|
|
48
54
|
|
|
49
55
|
return molar_fractions
|
|
50
56
|
|
|
@@ -63,10 +69,10 @@ def molar_to_mass_fractions(molar_fractions):
|
|
|
63
69
|
mass_fractions = {}
|
|
64
70
|
|
|
65
71
|
# Step 1: Get the molar masses for each component
|
|
66
|
-
for fraction in molar_fractions
|
|
72
|
+
for fraction in molar_fractions:
|
|
67
73
|
try:
|
|
68
|
-
molar_masses[fraction] = CP.PropsSI(
|
|
69
|
-
except Exception
|
|
74
|
+
molar_masses[fraction] = CP.PropsSI("M", fraction)
|
|
75
|
+
except Exception:
|
|
70
76
|
# print(f"Warning: Could not retrieve molar mass for {fraction} ({fraction}). Error: {e}")
|
|
71
77
|
continue # Skip this fraction if there's an issue
|
|
72
78
|
|
|
@@ -78,7 +84,7 @@ def molar_to_mass_fractions(molar_fractions):
|
|
|
78
84
|
total_mass = sum(molar_fractions[comp] * molar_masses[comp] for comp in molar_masses)
|
|
79
85
|
|
|
80
86
|
# Step 4: Calculate mass fractions
|
|
81
|
-
for component in molar_masses
|
|
87
|
+
for component in molar_masses:
|
|
82
88
|
mass_fractions[component] = (molar_fractions[component] * molar_masses[component]) / total_mass
|
|
83
89
|
|
|
84
90
|
# Step 5: Check if mass fractions sum to approximately 1
|
|
@@ -104,51 +110,54 @@ def calc_chemical_exergy(stream_data, Tamb, pamb, chemExLib):
|
|
|
104
110
|
Returns:
|
|
105
111
|
- eCH: Chemical exergy in kJ/kg.
|
|
106
112
|
"""
|
|
107
|
-
logging.info(
|
|
113
|
+
logging.info(
|
|
114
|
+
f"Starting chemical exergy of stream of composition {stream_data} calculation with Tamb={Tamb}, pamb={pamb}"
|
|
115
|
+
)
|
|
108
116
|
|
|
109
117
|
try:
|
|
110
118
|
# Check if molar fractions already exist
|
|
111
|
-
if
|
|
112
|
-
molar_fractions = stream_data[
|
|
113
|
-
logging.info("Molar fractions found in stream.")
|
|
119
|
+
if "molar_composition" in stream_data:
|
|
120
|
+
molar_fractions = stream_data["molar_composition"]
|
|
114
121
|
else:
|
|
115
122
|
# If not, convert mass composition to molar fractions
|
|
116
|
-
molar_fractions = mass_to_molar_fractions(stream_data[
|
|
117
|
-
logging.info(f"Converted mass composition to molar fractions: {molar_fractions}")
|
|
118
|
-
|
|
123
|
+
molar_fractions = mass_to_molar_fractions(stream_data["mass_composition"])
|
|
119
124
|
try:
|
|
120
125
|
# Load chemical exergy data
|
|
121
|
-
chem_ex_file = os.path.join(__datapath__, f
|
|
122
|
-
with open(chem_ex_file
|
|
126
|
+
chem_ex_file = os.path.join(__datapath__, f"{chemExLib}.json")
|
|
127
|
+
with open(chem_ex_file) as file:
|
|
123
128
|
chem_ex_data = json.load(file) # data in J/kmol
|
|
124
|
-
logging.info("Chemical exergy data loaded successfully.")
|
|
125
129
|
except FileNotFoundError:
|
|
126
130
|
error_msg = f"Chemical exergy data file '{chemExLib}.json' not found. Please ensure the file exists or set chemExLib to 'Ahrendts'."
|
|
127
131
|
logging.error(error_msg)
|
|
128
132
|
raise FileNotFoundError(error_msg)
|
|
129
133
|
|
|
130
|
-
|
|
131
134
|
R = 8.314 # Universal gas constant in J/(molK)
|
|
132
|
-
aliases_water = CP.get_aliases(
|
|
135
|
+
aliases_water = CP.get_aliases("H2O")
|
|
133
136
|
|
|
134
137
|
# Handle pure substance (Case A)
|
|
135
138
|
if len(molar_fractions) == 1:
|
|
136
139
|
logging.info("Handling pure substance case (Case A).")
|
|
137
140
|
substance = next(iter(molar_fractions)) # Get the single key
|
|
138
|
-
aliases = CP.get_aliases(substance)
|
|
139
141
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
eCH = chem_ex_data[alias.upper()][3] / CP.PropsSI('M', substance) # in J/kg
|
|
147
|
-
logging.info(f"Found exergy data for {substance}. Chemical exergy: {eCH} J/kg")
|
|
148
|
-
break
|
|
142
|
+
try:
|
|
143
|
+
aliases = CP.get_aliases(substance)
|
|
144
|
+
|
|
145
|
+
if set(aliases) & set(aliases_water):
|
|
146
|
+
eCH = chem_ex_data["WATER"][2] / CP.PropsSI("M", "H2O") # liquid water, in J/kg
|
|
147
|
+
logging.info(f"Pure water detected. Chemical exergy: {eCH} J/kg")
|
|
149
148
|
else:
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
for alias in aliases:
|
|
150
|
+
if alias.upper() in chem_ex_data:
|
|
151
|
+
eCH = chem_ex_data[alias.upper()][3] / CP.PropsSI("M", substance) # in J/kg
|
|
152
|
+
logging.info(f"Found exergy data for {substance}. Chemical exergy: {eCH} J/kg")
|
|
153
|
+
break
|
|
154
|
+
else:
|
|
155
|
+
logging.error(f"No matching alias found for {substance}")
|
|
156
|
+
raise KeyError(f"No matching alias found for {substance}")
|
|
157
|
+
|
|
158
|
+
except Exception:
|
|
159
|
+
eCH = 0 # If no aliases found, set chemical exergy to 0
|
|
160
|
+
logging.warning(f"No CoolProp aliases found for {substance}. Setting chemical exergy to 0 J/kg.")
|
|
152
161
|
|
|
153
162
|
# Handle mixtures (Case B or C)
|
|
154
163
|
else:
|
|
@@ -161,25 +170,25 @@ def calc_chemical_exergy(stream_data, Tamb, pamb, chemExLib):
|
|
|
161
170
|
|
|
162
171
|
# Calculate the total molar mass of the mixture
|
|
163
172
|
for substance, fraction in molar_fractions.items():
|
|
164
|
-
molar_mass = CP.PropsSI(
|
|
173
|
+
molar_mass = CP.PropsSI("M", substance) # Molar mass in kg/mol
|
|
165
174
|
total_molar_mass += fraction * molar_mass # Weighted sum for molar mass in kg/mol
|
|
166
175
|
logging.info(f"Total molar mass of the mixture: {total_molar_mass} kg/mol")
|
|
167
176
|
|
|
168
|
-
water_present = any(alias in molar_fractions
|
|
177
|
+
water_present = any(alias in molar_fractions for alias in aliases_water)
|
|
169
178
|
|
|
170
179
|
if water_present:
|
|
171
|
-
water_alias = next(alias for alias in aliases_water if alias in molar_fractions
|
|
172
|
-
pH2O_sat = CP.PropsSI(
|
|
180
|
+
water_alias = next(alias for alias in aliases_water if alias in molar_fractions)
|
|
181
|
+
pH2O_sat = CP.PropsSI("P", "T", Tamb, "Q", 1, "Water") # Saturation pressure of water in bar
|
|
173
182
|
pH2O = molar_fractions[water_alias] * pamb # Partial pressure of water
|
|
174
183
|
|
|
175
184
|
if pH2O > pH2O_sat: # Case B: Water condenses
|
|
176
|
-
logging.info(
|
|
185
|
+
logging.info("Condensation occurs in the mixture.")
|
|
177
186
|
x_dry = sum(fraction for comp, fraction in molar_fractions.items() if comp != water_alias)
|
|
178
|
-
x_H2O_gas = x_dry / (pamb/pH2O_sat - 1) # Vaporous water fraction in the total mixture
|
|
187
|
+
x_H2O_gas = x_dry / (pamb / pH2O_sat - 1) # Vaporous water fraction in the total mixture
|
|
179
188
|
x_H2O_liquid = molar_fractions[water_alias] - x_H2O_gas # Liquid water fraction
|
|
180
189
|
x_total_gas = 1 - x_H2O_liquid # Total gas phase fraction
|
|
181
190
|
|
|
182
|
-
eCH_liquid_mol = x_H2O_liquid * (chem_ex_data[
|
|
191
|
+
eCH_liquid_mol = x_H2O_liquid * (chem_ex_data["WATER"][2]) # Liquid phase contribution, in J/mol
|
|
183
192
|
|
|
184
193
|
for substance, fraction in molar_fractions.items():
|
|
185
194
|
if substance == water_alias:
|
|
@@ -191,7 +200,7 @@ def calc_chemical_exergy(stream_data, Tamb, pamb, chemExLib):
|
|
|
191
200
|
aliases = CP.get_aliases(substance)
|
|
192
201
|
for alias in aliases:
|
|
193
202
|
if alias.upper() in chem_ex_data:
|
|
194
|
-
eCH_gas_mol += fraction * (chem_ex_data[alias.upper()][3])
|
|
203
|
+
eCH_gas_mol += fraction * (chem_ex_data[alias.upper()][3]) # Exergy is in J/mol
|
|
195
204
|
break
|
|
196
205
|
else:
|
|
197
206
|
logging.error(f"No matching alias found for {substance}")
|
|
@@ -205,7 +214,7 @@ def calc_chemical_exergy(stream_data, Tamb, pamb, chemExLib):
|
|
|
205
214
|
logging.info(f"Condensed phase chemical exergy: {eCH_mol} J/kmol")
|
|
206
215
|
|
|
207
216
|
else: # Case C: Water doesn't condense
|
|
208
|
-
logging.info(
|
|
217
|
+
logging.info("Water does not condense.")
|
|
209
218
|
eCH_mol = 0
|
|
210
219
|
for substance, fraction in molar_fractions.items():
|
|
211
220
|
aliases = CP.get_aliases(substance)
|
|
@@ -223,7 +232,7 @@ def calc_chemical_exergy(stream_data, Tamb, pamb, chemExLib):
|
|
|
223
232
|
eCH_mol += R * Tamb * entropy_mixing
|
|
224
233
|
|
|
225
234
|
else: # Case C: No water present
|
|
226
|
-
logging.info(
|
|
235
|
+
logging.info("No water present in the mixture.")
|
|
227
236
|
eCH_mol = 0
|
|
228
237
|
for substance, fraction in molar_fractions.items():
|
|
229
238
|
aliases = CP.get_aliases(substance)
|
|
@@ -264,43 +273,47 @@ def add_chemical_exergy(my_json, Tamb, pamb, chemExLib):
|
|
|
264
273
|
"""
|
|
265
274
|
# Check if Tamb and pamb are provided and not None
|
|
266
275
|
if Tamb is None or pamb is None:
|
|
267
|
-
raise ValueError(
|
|
268
|
-
|
|
276
|
+
raise ValueError(
|
|
277
|
+
"Ambient temperature (Tamb) and pressure (pamb) are required for chemical exergy calculation. "
|
|
278
|
+
"Please ensure they are included in the JSON or passed as arguments."
|
|
279
|
+
)
|
|
269
280
|
|
|
270
281
|
# Iterate over each material connection with kind == 'material'
|
|
271
|
-
for conn_name, conn_data in my_json[
|
|
272
|
-
if conn_data[
|
|
282
|
+
for conn_name, conn_data in my_json["connections"].items():
|
|
283
|
+
if conn_data["kind"] == "material":
|
|
273
284
|
# Prefer molar composition if available, otherwise use mass composition
|
|
274
|
-
molar_composition = conn_data.get(
|
|
275
|
-
mass_composition = conn_data.get(
|
|
285
|
+
molar_composition = conn_data.get("molar_composition", {})
|
|
286
|
+
mass_composition = conn_data.get("mass_composition", {})
|
|
276
287
|
|
|
277
288
|
# Prepare stream data for exergy calculation, prioritizing molar composition
|
|
278
289
|
if molar_composition:
|
|
279
|
-
stream_data = {
|
|
290
|
+
stream_data = {"molar_composition": molar_composition}
|
|
280
291
|
logging.info(f"Using molar composition for connection {conn_name}")
|
|
281
292
|
else:
|
|
282
|
-
stream_data = {
|
|
293
|
+
stream_data = {"mass_composition": mass_composition}
|
|
283
294
|
logging.info(f"Using mass composition for connection {conn_name}")
|
|
284
295
|
|
|
285
296
|
# Add the chemical exergy value
|
|
286
|
-
conn_data[
|
|
287
|
-
conn_data[
|
|
297
|
+
conn_data["e_CH"] = calc_chemical_exergy(stream_data, Tamb, pamb, chemExLib)
|
|
298
|
+
conn_data["e_CH_unit"] = fluid_property_data["e"]["SI_unit"]
|
|
288
299
|
logging.info(f"Added chemical exergy to connection {conn_name}: {conn_data['e_CH']} kJ/kg")
|
|
289
300
|
else:
|
|
290
|
-
logging.info(
|
|
301
|
+
logging.info(
|
|
302
|
+
f"Skipped chemical exergy calculation for non-material connection {conn_name} ({conn_data['kind']})"
|
|
303
|
+
)
|
|
291
304
|
|
|
292
305
|
return my_json
|
|
293
306
|
|
|
294
307
|
|
|
295
308
|
def add_total_exergy_flow(my_json, split_physical_exergy):
|
|
296
|
-
"""
|
|
309
|
+
r"""
|
|
297
310
|
Adds the total exergy flow to each connection in the JSON data based on its kind.
|
|
298
311
|
|
|
299
312
|
- For 'material' connections, the exergy is calculated as before.
|
|
300
313
|
- For 'power' connections, the energy flow value is used directly.
|
|
301
314
|
- For 'heat' connections, if the associated component is of class
|
|
302
315
|
SimpleHeatExchanger, the thermal exergy difference is computed as:
|
|
303
|
-
..math::
|
|
316
|
+
.. math::
|
|
304
317
|
E = (e^\mathrm{T}_\mathrm{in} \cdot \dot m_\mathrm{in})
|
|
305
318
|
- (e^\mathrm{T}_\mathrm{out} \cdot \dot m_\mathrm{out})
|
|
306
319
|
|
|
@@ -319,109 +332,137 @@ def add_total_exergy_flow(my_json, split_physical_exergy):
|
|
|
319
332
|
The modified JSON object with added total exergy flow for each
|
|
320
333
|
connection.
|
|
321
334
|
"""
|
|
322
|
-
for conn_name, conn_data in my_json[
|
|
335
|
+
for conn_name, conn_data in my_json["connections"].items():
|
|
323
336
|
try:
|
|
324
|
-
if conn_data[
|
|
337
|
+
if conn_data["kind"] == "material":
|
|
325
338
|
# For material connections: E = m * (e^PH + e^CH)
|
|
326
|
-
conn_data[
|
|
327
|
-
if conn_data.get(
|
|
328
|
-
conn_data[
|
|
329
|
-
conn_data[
|
|
339
|
+
conn_data["E_PH"] = conn_data["m"] * conn_data["e_PH"]
|
|
340
|
+
if conn_data.get("e_CH") is not None:
|
|
341
|
+
conn_data["E_CH"] = conn_data["m"] * conn_data["e_CH"]
|
|
342
|
+
conn_data["E"] = conn_data["E_PH"] + conn_data["E_CH"]
|
|
330
343
|
else:
|
|
331
|
-
conn_data[
|
|
344
|
+
conn_data["E"] = conn_data["E_PH"]
|
|
332
345
|
logging.info(f"Missing chemical exergy for connection {conn_name}. Using only physical exergy.")
|
|
333
346
|
if split_physical_exergy:
|
|
334
|
-
if conn_data.get(
|
|
335
|
-
conn_data[
|
|
347
|
+
if conn_data.get("e_T") is not None:
|
|
348
|
+
conn_data["E_T"] = conn_data["m"] * conn_data["e_T"]
|
|
336
349
|
else:
|
|
337
350
|
msg = f"Missing thermal exergy for connection {conn_name}."
|
|
338
351
|
logging.error(msg)
|
|
339
352
|
raise KeyError(msg)
|
|
340
|
-
if conn_data.get(
|
|
341
|
-
conn_data[
|
|
353
|
+
if conn_data.get("e_M") is not None:
|
|
354
|
+
conn_data["E_M"] = conn_data["m"] * conn_data["e_M"]
|
|
342
355
|
else:
|
|
343
356
|
msg = f"Missing mechanical exergy for connection {conn_name}."
|
|
344
357
|
logging.error(msg)
|
|
345
358
|
raise KeyError(msg)
|
|
346
|
-
elif conn_data[
|
|
359
|
+
elif conn_data["kind"] == "power":
|
|
347
360
|
# For power connections, use the energy flow value directly.
|
|
348
|
-
conn_data[
|
|
349
|
-
elif conn_data[
|
|
361
|
+
conn_data["E"] = conn_data["energy_flow"]
|
|
362
|
+
elif conn_data["kind"] == "heat":
|
|
350
363
|
# For heat connections, attempt the new calculation.
|
|
351
364
|
# Identify the associated component (either source or target)
|
|
352
|
-
comp_name = conn_data[
|
|
365
|
+
comp_name = conn_data["source_component"] or conn_data["target_component"]
|
|
353
366
|
# Check if the component is either a SimpleHeatExchanger or a SteamGenerator.
|
|
354
|
-
if (
|
|
355
|
-
|
|
367
|
+
if (
|
|
368
|
+
"SimpleHeatExchanger" in my_json["components"]
|
|
369
|
+
and comp_name in my_json["components"]["SimpleHeatExchanger"]
|
|
370
|
+
):
|
|
356
371
|
# Retrieve the inlet material streams: those with this component as target.
|
|
357
|
-
inlet_conns = [
|
|
358
|
-
|
|
372
|
+
inlet_conns = [
|
|
373
|
+
c
|
|
374
|
+
for c in my_json["connections"].values()
|
|
375
|
+
if c.get("target_component") == comp_name and c.get("kind") == "material"
|
|
376
|
+
]
|
|
359
377
|
# Retrieve the outlet material streams: those with this component as source.
|
|
360
|
-
outlet_conns = [
|
|
361
|
-
|
|
378
|
+
outlet_conns = [
|
|
379
|
+
c
|
|
380
|
+
for c in my_json["connections"].values()
|
|
381
|
+
if c.get("source_component") == comp_name and c.get("kind") == "material"
|
|
382
|
+
]
|
|
362
383
|
# Determine which exergy key to use based on the flag.
|
|
363
|
-
exergy_key =
|
|
384
|
+
exergy_key = "e_T" if split_physical_exergy else "e_PH"
|
|
364
385
|
|
|
365
386
|
if inlet_conns and outlet_conns:
|
|
366
387
|
# For simplicity, take the first inlet and first outlet.
|
|
367
388
|
inlet = inlet_conns[0]
|
|
368
389
|
outlet = outlet_conns[0]
|
|
369
390
|
# Calculate the heat exergy difference using the selected key:
|
|
370
|
-
conn_data[
|
|
391
|
+
conn_data["E"] = abs(
|
|
392
|
+
inlet.get(exergy_key, 0) * inlet.get("m", 0)
|
|
393
|
+
- outlet.get(exergy_key, 0) * outlet.get("m", 0)
|
|
394
|
+
)
|
|
371
395
|
else:
|
|
372
|
-
conn_data[
|
|
373
|
-
logging.warning(
|
|
374
|
-
|
|
375
|
-
|
|
396
|
+
conn_data["E"] = None
|
|
397
|
+
logging.warning(
|
|
398
|
+
f"Not enough material connections for heat exchanger {comp_name} for heat exergy calculation."
|
|
399
|
+
)
|
|
400
|
+
elif "SteamGenerator" in my_json["components"] and comp_name in my_json["components"]["SteamGenerator"]:
|
|
376
401
|
# Retrieve material connections for the steam generator.
|
|
377
|
-
inlet_conns = [
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
402
|
+
inlet_conns = [
|
|
403
|
+
c
|
|
404
|
+
for c in my_json["connections"].values()
|
|
405
|
+
if c.get("target_component") == comp_name and c.get("kind") == "material"
|
|
406
|
+
]
|
|
407
|
+
outlet_conns = [
|
|
408
|
+
c
|
|
409
|
+
for c in my_json["connections"].values()
|
|
410
|
+
if c.get("source_component") == comp_name and c.get("kind") == "material"
|
|
411
|
+
]
|
|
381
412
|
if inlet_conns and outlet_conns:
|
|
382
413
|
# For the steam generator, group the material connections as follows:
|
|
383
|
-
feed_water
|
|
384
|
-
steam_inlet
|
|
385
|
-
superheated_HP = outlet_conns[0]
|
|
386
|
-
superheated_IP =
|
|
414
|
+
feed_water = inlet_conns[0] # inl[0]: Feed water inlet (HP)
|
|
415
|
+
steam_inlet = inlet_conns[1] if len(inlet_conns) > 1 else {} # inl[1]: Steam inlet (IP)
|
|
416
|
+
superheated_HP = outlet_conns[0] # outl[0]: Superheated steam outlet (HP)
|
|
417
|
+
superheated_IP = (
|
|
418
|
+
outlet_conns[1] if len(outlet_conns) > 1 else {}
|
|
419
|
+
) # outl[1]: Superheated steam outlet (IP)
|
|
387
420
|
water_inj_HP = inlet_conns[2] if len(inlet_conns) > 2 else {} # inl[2]: Water injection (HP)
|
|
388
421
|
water_inj_IP = inlet_conns[3] if len(inlet_conns) > 3 else {} # inl[3]: Water injection (IP)
|
|
389
422
|
|
|
390
|
-
exergy_type =
|
|
423
|
+
exergy_type = "e_T" if split_physical_exergy else "e_PH"
|
|
391
424
|
# Calculate the contributions based on the new E_F definition:
|
|
392
|
-
E_F_HP = superheated_HP.get(
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
425
|
+
E_F_HP = superheated_HP.get("m", 0) * superheated_HP.get(exergy_type, 0) - feed_water.get(
|
|
426
|
+
"m", 0
|
|
427
|
+
) * feed_water.get(exergy_type, 0)
|
|
428
|
+
E_F_IP = superheated_IP.get("m", 0) * superheated_IP.get(exergy_type, 0) - steam_inlet.get(
|
|
429
|
+
"m", 0
|
|
430
|
+
) * steam_inlet.get(exergy_type, 0)
|
|
431
|
+
E_F_w_inj = water_inj_HP.get("m", 0) * water_inj_HP.get(exergy_type, 0) + water_inj_IP.get(
|
|
432
|
+
"m", 0
|
|
433
|
+
) * water_inj_IP.get(exergy_type, 0)
|
|
398
434
|
# Total exergy flow for the heat input (E_TOT) is taken as the exergy fuel E_F:
|
|
399
435
|
E_TOT = E_F_HP + E_F_IP - E_F_w_inj
|
|
400
|
-
conn_data[
|
|
436
|
+
conn_data["E"] = E_TOT
|
|
401
437
|
else:
|
|
402
|
-
conn_data[
|
|
403
|
-
logging.warning(
|
|
438
|
+
conn_data["E"] = None
|
|
439
|
+
logging.warning(
|
|
440
|
+
f"Not enough material connections for steam generator {comp_name} for heat exergy calculation."
|
|
441
|
+
)
|
|
404
442
|
else:
|
|
405
|
-
conn_data[
|
|
406
|
-
logging.warning(
|
|
407
|
-
|
|
443
|
+
conn_data["E"] = None
|
|
444
|
+
logging.warning(
|
|
445
|
+
f"Heat connection {conn_name} is not associated with a recognized heat exchanger component."
|
|
446
|
+
)
|
|
447
|
+
elif conn_data["kind"] == "other":
|
|
408
448
|
# No exergy flow calculation for 'other' kind.
|
|
409
449
|
pass
|
|
410
450
|
else:
|
|
411
|
-
logging.warning(
|
|
412
|
-
|
|
451
|
+
logging.warning(
|
|
452
|
+
f"Unknown connection kind: {conn_data['kind']} for connection {conn_name}. Skipping exergy flow calculation."
|
|
453
|
+
)
|
|
454
|
+
conn_data["E"] = None
|
|
413
455
|
|
|
414
456
|
# Assign the exergy unit (assuming fluid_property_data is defined elsewhere)
|
|
415
|
-
conn_data[
|
|
457
|
+
conn_data["E_unit"] = fluid_property_data["power"]["SI_unit"]
|
|
416
458
|
|
|
417
459
|
except Exception as e:
|
|
418
460
|
logging.error(f"Error calculating total exergy flow for connection {conn_name}: {e}")
|
|
419
|
-
conn_data[
|
|
461
|
+
conn_data["E"] = None
|
|
420
462
|
|
|
421
463
|
return my_json
|
|
422
464
|
|
|
423
465
|
|
|
424
|
-
|
|
425
466
|
def convert_to_SI(property, value, unit):
|
|
426
467
|
r"""
|
|
427
468
|
Convert a value to its SI value.
|
|
@@ -453,27 +494,27 @@ def convert_to_SI(property, value, unit):
|
|
|
453
494
|
|
|
454
495
|
# Check if the property is valid and exists in fluid_property_data
|
|
455
496
|
if property not in fluid_property_data:
|
|
456
|
-
logging.warning(f"Unrecognized property: '{property}'. Returning original value.")
|
|
497
|
+
logging.warning(f"Unrecognized property: '{property}'. Returning original value {value} {unit}.")
|
|
457
498
|
return value
|
|
458
499
|
|
|
459
500
|
# Check if the unit is valid
|
|
460
|
-
if unit ==
|
|
461
|
-
logging.warning(f"Unrecognized unit for property '{property}'. Returning original value.")
|
|
501
|
+
if unit == "Unknown":
|
|
502
|
+
logging.warning(f"Unrecognized unit {unit} for property '{property}'. Returning original value {value} {unit}.")
|
|
462
503
|
return value
|
|
463
504
|
|
|
464
505
|
try:
|
|
465
506
|
# Handle temperature conversions separately
|
|
466
|
-
if property ==
|
|
467
|
-
if unit not in fluid_property_data[
|
|
507
|
+
if property == "T":
|
|
508
|
+
if unit not in fluid_property_data["T"]["units"]:
|
|
468
509
|
raise ValueError(f"Invalid unit '{unit}' for temperature. Unit not found.")
|
|
469
|
-
converters = fluid_property_data[
|
|
510
|
+
converters = fluid_property_data["T"]["units"][unit]
|
|
470
511
|
return (value + converters[0]) * converters[1]
|
|
471
512
|
|
|
472
513
|
# Handle all other property conversions
|
|
473
514
|
else:
|
|
474
|
-
if unit not in fluid_property_data[property][
|
|
515
|
+
if unit not in fluid_property_data[property]["units"]:
|
|
475
516
|
raise ValueError(f"Invalid unit '{unit}' for property '{property}'. Unit not found.")
|
|
476
|
-
conversion_factor = fluid_property_data[property][
|
|
517
|
+
conversion_factor = fluid_property_data[property]["units"][unit]
|
|
477
518
|
return value * conversion_factor
|
|
478
519
|
|
|
479
520
|
except KeyError as e:
|
|
@@ -482,156 +523,240 @@ def convert_to_SI(property, value, unit):
|
|
|
482
523
|
raise ValueError(f"An error occurred during the unit conversion: {e}")
|
|
483
524
|
|
|
484
525
|
|
|
485
|
-
|
|
486
526
|
fluid_property_data = {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
527
|
+
"m": {
|
|
528
|
+
"text": "mass flow",
|
|
529
|
+
"SI_unit": "kg / s",
|
|
530
|
+
"units": {
|
|
531
|
+
"kg / s": 1,
|
|
532
|
+
"kg / min": 1 / 60,
|
|
533
|
+
"kg / h": 1 / 3.6e3,
|
|
534
|
+
"kg/s": 1,
|
|
535
|
+
"kg/min": 1 / 60,
|
|
536
|
+
"kg/h": 1 / 3.6e3,
|
|
537
|
+
"kg / sec": 1,
|
|
538
|
+
"kg/sec": 1,
|
|
539
|
+
"t / h": 1 / 3.6,
|
|
540
|
+
"g / s": 1e-3,
|
|
541
|
+
"t/h": 1 / 3.6,
|
|
542
|
+
"g/s": 1e-3,
|
|
543
|
+
"g / sec": 1e-3,
|
|
544
|
+
"g/sec": 1e-3,
|
|
495
545
|
},
|
|
496
|
-
|
|
497
|
-
|
|
546
|
+
"latex_eq": r"0 = \dot{m} - \dot{m}_\mathrm{spec}",
|
|
547
|
+
"documentation": {"float_fmt": "{:,.3f}"},
|
|
498
548
|
},
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
549
|
+
"n": {
|
|
550
|
+
"text": "molar flow",
|
|
551
|
+
"SI_unit": "mol / s",
|
|
552
|
+
"units": {
|
|
553
|
+
"mol / s": 1,
|
|
554
|
+
"mol / min": 1 / 60,
|
|
555
|
+
"mol / h": 1 / 3.6e3,
|
|
556
|
+
"mol/s": 1,
|
|
557
|
+
"mol/min": 1 / 60,
|
|
558
|
+
"mol/h": 1 / 3.6e3,
|
|
559
|
+
"kmol / s": 1e3,
|
|
560
|
+
"kmol / min": 1 / 60e3,
|
|
561
|
+
"kmol / h": 1 / 3.6e6,
|
|
562
|
+
"kmol/s": 1e3,
|
|
563
|
+
"kmol/min": 1 / 60e3,
|
|
564
|
+
"kmol/h": 1 / 3.6e6,
|
|
565
|
+
"mol / sec": 1,
|
|
566
|
+
"mol/sec": 1,
|
|
567
|
+
"kmol / sec": 1e3,
|
|
568
|
+
"kmol/sec": 1e3,
|
|
506
569
|
},
|
|
507
|
-
|
|
508
|
-
|
|
570
|
+
"latex_eq": r"0 = \dot{n} - \dot{n}_\mathrm{spec}",
|
|
571
|
+
"documentation": {"float_fmt": "{:,.3f}"},
|
|
509
572
|
},
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
573
|
+
"v": {
|
|
574
|
+
"text": "volumetric flow",
|
|
575
|
+
"SI_unit": "m3 / s",
|
|
576
|
+
"units": {
|
|
577
|
+
"m3 / s": 1,
|
|
578
|
+
"m3 / min": 1 / 60,
|
|
579
|
+
"m3 / h": 1 / 3.6e3,
|
|
580
|
+
"l / s": 1 / 1e3,
|
|
581
|
+
"l / min": 1 / 60e3,
|
|
582
|
+
"l / h": 1 / 3.6e6,
|
|
516
583
|
},
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
'documentation': {'float_fmt': '{:,.3f}'}
|
|
584
|
+
"latex_eq": (r"0 = \dot{m} \cdot v \left(p,h\right)- \dot{V}_\mathrm{spec}"),
|
|
585
|
+
"documentation": {"float_fmt": "{:,.3f}"},
|
|
520
586
|
},
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
},
|
|
528
|
-
'latex_eq': r'0 = p - p_\mathrm{spec}',
|
|
529
|
-
'documentation': {'float_fmt': '{:,.3f}'}
|
|
587
|
+
"p": {
|
|
588
|
+
"text": "pressure",
|
|
589
|
+
"SI_unit": "Pa",
|
|
590
|
+
"units": {"Pa": 1, "kPa": 1e3, "psi": 6.8948e3, "bar": 1e5, "atm": 1.01325e5, "MPa": 1e6},
|
|
591
|
+
"latex_eq": r"0 = p - p_\mathrm{spec}",
|
|
592
|
+
"documentation": {"float_fmt": "{:,.3f}"},
|
|
530
593
|
},
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
594
|
+
"h": {
|
|
595
|
+
"text": "enthalpy",
|
|
596
|
+
"SI_unit": "J / kg",
|
|
597
|
+
"SI_unit_molar:": "J / mol",
|
|
598
|
+
"units": {
|
|
599
|
+
"J / kg": 1,
|
|
600
|
+
"kJ / kg": 1e3,
|
|
601
|
+
"MJ / kg": 1e6,
|
|
602
|
+
"J/kg": 1,
|
|
603
|
+
"kJ/kg": 1e3,
|
|
604
|
+
"MJ/kg": 1e6,
|
|
605
|
+
"cal / kg": 4.184,
|
|
606
|
+
"kcal / kg": 4.184e3,
|
|
607
|
+
"cal/kg": 4.184,
|
|
608
|
+
"kcal/kg": 4.184e3,
|
|
609
|
+
"Wh / kg": 3.6e3,
|
|
610
|
+
"kWh / kg": 3.6e6,
|
|
611
|
+
"Wh/kg": 3.6e3,
|
|
612
|
+
"kWh kg": 3.6e6,
|
|
613
|
+
"J / mol": 1,
|
|
614
|
+
"kJ / mol": 1e3,
|
|
615
|
+
"MJ / mol": 1e6,
|
|
616
|
+
"J/mol": 1,
|
|
617
|
+
"kJ/mol": 1e3,
|
|
618
|
+
"MJ/mol": 1e6,
|
|
619
|
+
"J / kmol": 1e-3,
|
|
620
|
+
"kJ / kmol": 1,
|
|
621
|
+
"MJ / kmol": 1e3,
|
|
622
|
+
"J/kmol": 1e-3,
|
|
623
|
+
"kJ/kmol": 1,
|
|
624
|
+
"MJ/kmol": 1e3,
|
|
541
625
|
},
|
|
542
|
-
|
|
543
|
-
|
|
626
|
+
"latex_eq": r"0 = h - h_\mathrm{spec}",
|
|
627
|
+
"documentation": {"float_fmt": "{:,.3f}"},
|
|
544
628
|
},
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
629
|
+
"e": {
|
|
630
|
+
"text": "exergy",
|
|
631
|
+
"SI_unit": "J / kg",
|
|
632
|
+
"SI_unit_molar:": "J / mol",
|
|
633
|
+
"units": {
|
|
634
|
+
"J / kg": 1,
|
|
635
|
+
"kJ / kg": 1e3,
|
|
636
|
+
"MJ / kg": 1e6,
|
|
637
|
+
"J/kg": 1,
|
|
638
|
+
"kJ/kg": 1e3,
|
|
639
|
+
"MJ/kg": 1e6,
|
|
640
|
+
"cal / kg": 4.184,
|
|
641
|
+
"kcal / kg": 4.184e3,
|
|
642
|
+
"cal/kg": 4.184,
|
|
643
|
+
"kcal/kg": 4.184e3,
|
|
644
|
+
"Wh / kg": 3.6e3,
|
|
645
|
+
"kWh / kg": 3.6e6,
|
|
646
|
+
"Wh/kg": 3.6e3,
|
|
647
|
+
"kWh kg": 3.6e6,
|
|
648
|
+
"J / mol": 1,
|
|
649
|
+
"kJ / mol": 1e3,
|
|
650
|
+
"MJ / mol": 1e6,
|
|
651
|
+
"J/mol": 1,
|
|
652
|
+
"kJ/mol": 1e3,
|
|
653
|
+
"MJ/mol": 1e6,
|
|
654
|
+
"J / kmol": 1e-3,
|
|
655
|
+
"kJ / kmol": 1,
|
|
656
|
+
"MJ / kmol": 1e3,
|
|
657
|
+
"J/kmol": 1e-3,
|
|
658
|
+
"kJ/kmol": 1,
|
|
659
|
+
"MJ/kmol": 1e3,
|
|
555
660
|
},
|
|
556
|
-
|
|
557
|
-
|
|
661
|
+
"latex_eq": r"0 = h - h_\mathrm{spec}",
|
|
662
|
+
"documentation": {"float_fmt": "{:,.3f}"},
|
|
558
663
|
},
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
},
|
|
566
|
-
'latex_eq': r'0 = T \left(p, h \right) - T_\mathrm{spec}',
|
|
567
|
-
'documentation': {'float_fmt': '{:,.1f}'}
|
|
664
|
+
"T": {
|
|
665
|
+
"text": "temperature",
|
|
666
|
+
"SI_unit": "K",
|
|
667
|
+
"units": {"K": [0, 1], "R": [0, 5 / 9], "C": [273.15, 1], "F": [459.67, 5 / 9]},
|
|
668
|
+
"latex_eq": r"0 = T \left(p, h \right) - T_\mathrm{spec}",
|
|
669
|
+
"documentation": {"float_fmt": "{:,.1f}"},
|
|
568
670
|
},
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
},
|
|
575
|
-
'latex_eq': r'0 = \Delta T_\mathrm{spec}- T_\mathrm{sat}\left(p\right)',
|
|
576
|
-
'documentation': {'float_fmt': '{:,.1f}'}
|
|
671
|
+
"Td_bp": {
|
|
672
|
+
"text": "temperature difference to boiling point",
|
|
673
|
+
"SI_unit": "K",
|
|
674
|
+
"units": {"K": 1, "R": 5 / 9, "C": 1, "F": 5 / 9},
|
|
675
|
+
"latex_eq": r"0 = \Delta T_\mathrm{spec}- T_\mathrm{sat}\left(p\right)",
|
|
676
|
+
"documentation": {"float_fmt": "{:,.1f}"},
|
|
577
677
|
},
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
'documentation': {'float_fmt': '{:,.3f}'}
|
|
678
|
+
"vol": {
|
|
679
|
+
"text": "specific volume",
|
|
680
|
+
"SI_unit": "m3 / kg",
|
|
681
|
+
"units": {"m3 / kg": 1, "l / kg": 1e-3},
|
|
682
|
+
"latex_eq": (r"0 = v\left(p,h\right) \cdot \dot{m} - \dot{V}_\mathrm{spec}"),
|
|
683
|
+
"documentation": {"float_fmt": "{:,.3f}"},
|
|
585
684
|
},
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
685
|
+
"x": {
|
|
686
|
+
"text": "vapor mass fraction",
|
|
687
|
+
"SI_unit": "-",
|
|
688
|
+
"units": {"1": 1, "-": 1, "%": 1e-2, "ppm": 1e-6},
|
|
689
|
+
"latex_eq": r"0 = h - h\left(p, x_\mathrm{spec}\right)",
|
|
690
|
+
"documentation": {"float_fmt": "{:,.2f}"},
|
|
691
|
+
},
|
|
692
|
+
"s": {
|
|
693
|
+
"text": "entropy",
|
|
694
|
+
"SI_unit": "J / kgK",
|
|
695
|
+
"SI_unit_molar:": "J / molK",
|
|
696
|
+
"units": {
|
|
697
|
+
"J / kgK": 1,
|
|
698
|
+
"kJ / kgK": 1e3,
|
|
699
|
+
"MJ / kgK": 1e6,
|
|
700
|
+
"J/kgK": 1,
|
|
701
|
+
"kJ/kgK": 1e3,
|
|
702
|
+
"MJ/kgK": 1e6,
|
|
703
|
+
"J / kg-K": 1,
|
|
704
|
+
"kJ / kg-K": 1e3,
|
|
705
|
+
"MJ / kg-K": 1e6,
|
|
706
|
+
"J/kg-K": 1,
|
|
707
|
+
"kJ/kg-K": 1e3,
|
|
708
|
+
"MJ/kg-K": 1e6,
|
|
709
|
+
"J / molK": 1,
|
|
710
|
+
"kJ / molK": 1e3,
|
|
711
|
+
"MJ / molK": 1e6,
|
|
712
|
+
"J/molK": 1,
|
|
713
|
+
"kJ/molK": 1e3,
|
|
714
|
+
"MJ/molK": 1e6,
|
|
715
|
+
"J / mol-K": 1,
|
|
716
|
+
"kJ / mol-K": 1e3,
|
|
717
|
+
"MJ / mol-K": 1e6,
|
|
718
|
+
"J/mol-K": 1,
|
|
719
|
+
"kJ/mol-K": 1e3,
|
|
720
|
+
"MJ/mol-K": 1e6,
|
|
721
|
+
"J / kmolK": 1e-3,
|
|
722
|
+
"kJ / kmolK": 1,
|
|
723
|
+
"MJ / kmolK": 1e3,
|
|
724
|
+
"J/kmolK": 1e-3,
|
|
725
|
+
"kJ/kmolK": 1,
|
|
726
|
+
"MJ/kmolK": 1e3,
|
|
727
|
+
"J / kmol-K": 1e-3,
|
|
728
|
+
"kJ / kmol-K": 1,
|
|
729
|
+
"MJ / kmol-K": 1e3,
|
|
730
|
+
"J/kmol-K": 1e-3,
|
|
731
|
+
"kJ/kmol-K": 1,
|
|
732
|
+
"MJ/kmol-K": 1e3,
|
|
733
|
+
},
|
|
734
|
+
"latex_eq": r"0 = s_\mathrm{spec} - s\left(p, h \right)",
|
|
735
|
+
"documentation": {"float_fmt": "{:,.2f}"},
|
|
592
736
|
},
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
'units': {
|
|
598
|
-
'J / kgK': 1, 'kJ / kgK': 1e3, 'MJ / kgK': 1e6, 'J/kgK': 1, 'kJ/kgK': 1e3, 'MJ/kgK': 1e6,
|
|
599
|
-
'J / kg-K': 1, 'kJ / kg-K': 1e3, 'MJ / kg-K': 1e6, 'J/kg-K': 1, 'kJ/kg-K': 1e3, 'MJ/kg-K': 1e6,
|
|
600
|
-
'J / molK': 1, 'kJ / molK': 1e3, 'MJ / molK': 1e6, 'J/molK': 1, 'kJ/molK': 1e3, 'MJ/molK': 1e6,
|
|
601
|
-
'J / mol-K': 1, 'kJ / mol-K': 1e3, 'MJ / mol-K': 1e6, 'J/mol-K': 1, 'kJ/mol-K': 1e3, 'MJ/mol-K': 1e6,
|
|
602
|
-
'J / kmolK': 1e-3, 'kJ / kmolK': 1, 'MJ / kmolK': 1e3, 'J/kmolK': 1e-3, 'kJ/kmolK': 1, 'MJ/kmolK': 1e3,
|
|
603
|
-
'J / kmol-K': 1e-3, 'kJ / kmol-K': 1, 'MJ / kmol-K': 1e3, 'J/kmol-K': 1e-3, 'kJ/kmol-K': 1, 'MJ/kmol-K': 1e3
|
|
604
|
-
},
|
|
605
|
-
'latex_eq': r'0 = s_\mathrm{spec} - s\left(p, h \right)',
|
|
606
|
-
'documentation': {'float_fmt': '{:,.2f}'}
|
|
737
|
+
"power": {
|
|
738
|
+
"text": "power",
|
|
739
|
+
"SI_unit": "W",
|
|
740
|
+
"units": {"W": 1, "kW": 1e3, "MW": 1e6},
|
|
607
741
|
},
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
742
|
+
"heat": {
|
|
743
|
+
"text": "heat",
|
|
744
|
+
"SI_unit": "W",
|
|
745
|
+
"units": {"W": 1, "kW": 1e3, "MW": 1e6},
|
|
612
746
|
},
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
747
|
+
"kA": {
|
|
748
|
+
"text": "kA",
|
|
749
|
+
"SI_unit": "W / K",
|
|
750
|
+
"units": {"W / K": 1, "kW / K": 1e3, "MW / K": 1e6, "W/K": 1, "kW/K": 1e3, "MW/K": 1e6},
|
|
617
751
|
},
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
'W / K': 1, 'kW / K': 1e3, 'MW / K': 1e6,
|
|
623
|
-
'W/K': 1, 'kW/K': 1e3, 'MW/K': 1e6},
|
|
752
|
+
"A": {
|
|
753
|
+
"text": "area",
|
|
754
|
+
"SI_unit": "m2",
|
|
755
|
+
"units": {"m2": 1, "cm2": 1e-4, "mm2": 1e-6, "m²": 1, "cm²": 1e-4, "mm²": 1e-6},
|
|
624
756
|
},
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
'm²': 1, 'cm²': 1e-4, 'mm²': 1e-6},
|
|
757
|
+
"VM": {
|
|
758
|
+
"text": "volume flow",
|
|
759
|
+
"SI_unit": "m3 / s",
|
|
760
|
+
"units": {"m3 / s": 1, "l / s": 1e-3, "l/s": 1e-3, "m³/s": 1, "l/min": 1 / 60e3, "l/h": 1 / 3.6e6},
|
|
630
761
|
},
|
|
631
|
-
'VM': {
|
|
632
|
-
'text': 'volume flow',
|
|
633
|
-
'SI_unit': 'm3 / s',
|
|
634
|
-
'units': {'m3 / s': 1, 'l / s': 1e-3, 'l/s': 1e-3,
|
|
635
|
-
'm³/s': 1, 'l/min': 1 / 60e3, 'l/h': 1 / 3.6e6},
|
|
636
|
-
}
|
|
637
762
|
}
|