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.
Files changed (48) hide show
  1. exerpy/__init__.py +2 -4
  2. exerpy/analyses.py +849 -304
  3. exerpy/components/__init__.py +3 -0
  4. exerpy/components/combustion/base.py +53 -35
  5. exerpy/components/component.py +8 -8
  6. exerpy/components/heat_exchanger/base.py +188 -121
  7. exerpy/components/heat_exchanger/condenser.py +98 -62
  8. exerpy/components/heat_exchanger/simple.py +237 -137
  9. exerpy/components/heat_exchanger/steam_generator.py +46 -41
  10. exerpy/components/helpers/cycle_closer.py +61 -34
  11. exerpy/components/helpers/power_bus.py +117 -0
  12. exerpy/components/nodes/deaerator.py +176 -58
  13. exerpy/components/nodes/drum.py +50 -39
  14. exerpy/components/nodes/flash_tank.py +218 -43
  15. exerpy/components/nodes/mixer.py +249 -69
  16. exerpy/components/nodes/splitter.py +173 -0
  17. exerpy/components/nodes/storage.py +130 -0
  18. exerpy/components/piping/valve.py +311 -115
  19. exerpy/components/power_machines/generator.py +105 -38
  20. exerpy/components/power_machines/motor.py +111 -39
  21. exerpy/components/turbomachinery/compressor.py +214 -68
  22. exerpy/components/turbomachinery/pump.py +215 -68
  23. exerpy/components/turbomachinery/turbine.py +182 -74
  24. exerpy/cost_estimation/__init__.py +65 -0
  25. exerpy/cost_estimation/turton.py +1260 -0
  26. exerpy/data/cost_correlations/cepci_index.json +135 -0
  27. exerpy/data/cost_correlations/component_mapping.json +450 -0
  28. exerpy/data/cost_correlations/material_factors.json +428 -0
  29. exerpy/data/cost_correlations/pressure_factors.json +206 -0
  30. exerpy/data/cost_correlations/turton2008.json +726 -0
  31. exerpy/data/cost_correlations/turton2008_design_analysis_synthesis_components_tables.pdf +0 -0
  32. exerpy/data/cost_correlations/turton2008_design_analysis_synthesis_components_theory.pdf +0 -0
  33. exerpy/functions.py +389 -264
  34. exerpy/parser/from_aspen/aspen_config.py +57 -48
  35. exerpy/parser/from_aspen/aspen_parser.py +373 -280
  36. exerpy/parser/from_ebsilon/__init__.py +2 -2
  37. exerpy/parser/from_ebsilon/check_ebs_path.py +15 -19
  38. exerpy/parser/from_ebsilon/ebsilon_config.py +328 -226
  39. exerpy/parser/from_ebsilon/ebsilon_functions.py +205 -38
  40. exerpy/parser/from_ebsilon/ebsilon_parser.py +392 -255
  41. exerpy/parser/from_ebsilon/utils.py +16 -11
  42. exerpy/parser/from_tespy/tespy_config.py +33 -1
  43. exerpy/parser/from_tespy/tespy_parser.py +151 -0
  44. {exerpy-0.0.2.dist-info → exerpy-0.0.4.dist-info}/METADATA +43 -2
  45. exerpy-0.0.4.dist-info/RECORD +57 -0
  46. exerpy-0.0.2.dist-info/RECORD +0 -44
  47. {exerpy-0.0.2.dist-info → exerpy-0.0.4.dist-info}/WHEEL +0 -0
  48. {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
- # Step 1: Get the molar masses for each component
26
- for fraction in mass_fractions.keys():
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
- # Step 2: Check if we have valid molar masses
34
- if not molar_masses:
35
- raise ValueError("No valid molar masses were retrieved. Exiting...")
26
+ else:
27
+ molar_masses = {}
36
28
 
37
- # Step 3: Calculate total moles in the mixture
38
- total_moles = sum(mass_fractions[comp] / molar_masses[comp] for comp in molar_masses)
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
- # Step 4: Calculate molar fractions
41
- for component in molar_masses.keys():
42
- molar_fractions[component] = (mass_fractions[component] / molar_masses[component]) / total_moles
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
- # Step 5: Check if molar fractions sum to approximately 1
45
- molar_sum = sum(molar_fractions.values())
46
- if abs(molar_sum - 1.0) > 1e-6:
47
- raise ValueError(f"Error: Molar fractions do not sum to 1. Sum is {molar_sum}")
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.keys():
72
+ for fraction in molar_fractions:
67
73
  try:
68
- molar_masses[fraction] = CP.PropsSI('M', fraction)
69
- except Exception as e:
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.keys():
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(f"Starting chemical exergy calculation with Tamb={Tamb}, pamb={pamb}")
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 'molar_composition' in stream_data:
112
- molar_fractions = stream_data['molar_composition']
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['mass_composition'])
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'{chemExLib}.json')
122
- with open(chem_ex_file, 'r') as 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('H2O')
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
- if set(aliases) & set(aliases_water):
141
- eCH = chem_ex_data['WATER'][2] / CP.PropsSI('M', 'H2O') # liquid water, in J/kg
142
- logging.info(f"Pure water detected. Chemical exergy: {eCH} J/kg")
143
- else:
144
- for alias in aliases:
145
- if alias.upper() in chem_ex_data:
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
- logging.error(f"No matching alias found for {substance}")
151
- raise KeyError(f"No matching alias found for {substance}")
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('M', substance) # Molar mass in kg/mol
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.keys() for alias in aliases_water)
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.keys())
172
- pH2O_sat = CP.PropsSI('P', 'T', Tamb, 'Q', 1, 'Water') # Saturation pressure of water in bar
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(f"Condensation occurs in the mixture.")
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['WATER'][2]) # Liquid phase contribution, in J/mol
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]) # Exergy is in J/mol
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(f"Water does not condense.")
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(f"No water present in the mixture.")
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("Ambient temperature (Tamb) and pressure (pamb) are required for chemical exergy calculation. "
268
- "Please ensure they are included in the JSON or passed as arguments.")
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['connections'].items():
272
- if conn_data['kind'] == 'material':
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('molar_composition', {})
275
- mass_composition = conn_data.get('mass_composition', {})
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 = {'molar_composition': molar_composition}
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 = {'mass_composition': mass_composition}
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['e_CH'] = calc_chemical_exergy(stream_data, Tamb, pamb, chemExLib)
287
- conn_data['e_CH_unit'] = fluid_property_data['e']['SI_unit']
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(f"Skipped chemical exergy calculation for non-material connection {conn_name} ({conn_data['kind']})")
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['connections'].items():
335
+ for conn_name, conn_data in my_json["connections"].items():
323
336
  try:
324
- if conn_data['kind'] == 'material':
337
+ if conn_data["kind"] == "material":
325
338
  # For material connections: E = m * (e^PH + e^CH)
326
- conn_data['E_PH'] = conn_data['m'] * conn_data['e_PH']
327
- if conn_data.get('e_CH') is not None:
328
- conn_data['E_CH'] = conn_data['m'] * conn_data['e_CH']
329
- conn_data['E'] = conn_data['E_PH'] + conn_data['E_CH']
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['E'] = conn_data['E_PH']
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('e_T') is not None:
335
- conn_data['E_T'] = conn_data['m'] * conn_data['e_T']
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('e_M') is not None:
341
- conn_data['E_M'] = conn_data['m'] * conn_data['e_M']
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['kind'] == 'power':
359
+ elif conn_data["kind"] == "power":
347
360
  # For power connections, use the energy flow value directly.
348
- conn_data['E'] = conn_data['energy_flow']
349
- elif conn_data['kind'] == 'heat':
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['source_component'] or conn_data['target_component']
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 ("SimpleHeatExchanger" in my_json['components'] and
355
- comp_name in my_json['components']["SimpleHeatExchanger"]):
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 = [c for c in my_json['connections'].values()
358
- if c.get('target_component') == comp_name and c.get('kind') == 'material']
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 = [c for c in my_json['connections'].values()
361
- if c.get('source_component') == comp_name and c.get('kind') == 'material']
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 = 'e_T' if split_physical_exergy else 'e_PH'
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['E'] = inlet.get(exergy_key, 0) * inlet.get('m', 0) - outlet.get(exergy_key, 0) * outlet.get('m', 0)
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['E'] = None
373
- logging.warning(f"Not enough material connections for heat exchanger {comp_name} for heat exergy calculation.")
374
- elif ("SteamGenerator" in my_json['components'] and
375
- comp_name in my_json['components']["SteamGenerator"]):
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 = [c for c in my_json['connections'].values()
378
- if c.get('target_component') == comp_name and c.get('kind') == 'material']
379
- outlet_conns = [c for c in my_json['connections'].values()
380
- if c.get('source_component') == comp_name and c.get('kind') == 'material']
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 = inlet_conns[0] # inl[0]: Feed water inlet (HP)
384
- steam_inlet = inlet_conns[1] if len(inlet_conns) > 1 else {} # inl[1]: Steam inlet (IP)
385
- superheated_HP = outlet_conns[0] # outl[0]: Superheated steam outlet (HP)
386
- superheated_IP = outlet_conns[1] if len(outlet_conns) > 1 else {} # outl[1]: Superheated steam outlet (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 = 'e_T' if split_physical_exergy else 'e_PH'
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('m', 0) * superheated_HP.get(exergy_type, 0) - \
393
- feed_water.get('m', 0) * feed_water.get(exergy_type, 0)
394
- E_F_IP = (superheated_IP.get('m', 0) * superheated_IP.get(exergy_type, 0) -
395
- steam_inlet.get('m', 0) * steam_inlet.get(exergy_type, 0))
396
- E_F_w_inj = (water_inj_HP.get('m', 0) * water_inj_HP.get(exergy_type, 0) +
397
- water_inj_IP.get('m', 0) * water_inj_IP.get(exergy_type, 0))
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['E'] = E_TOT
436
+ conn_data["E"] = E_TOT
401
437
  else:
402
- conn_data['E'] = None
403
- logging.warning(f"Not enough material connections for steam generator {comp_name} for heat exergy calculation.")
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['E'] = None
406
- logging.warning(f"Heat connection {conn_name} is not associated with a recognized heat exchanger component.")
407
- elif conn_data['kind'] == 'other':
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(f"Unknown connection kind: {conn_data['kind']} for connection {conn_name}. Skipping exergy flow calculation.")
412
- conn_data['E'] = None
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['E_unit'] = fluid_property_data['power']['SI_unit']
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['E'] = None
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 == 'Unknown':
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 == 'T':
467
- if unit not in fluid_property_data['T']['units']:
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['T']['units'][unit]
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]['units']:
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]['units'][unit]
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
- 'm': {
488
- 'text': 'mass flow',
489
- 'SI_unit': 'kg / s',
490
- 'units': {
491
- 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, 'kg/s': 1, 'kg/min': 1 / 60, 'kg/h': 1 / 3.6e3,
492
- 'kg / sec': 1, 'kg/sec': 1,
493
- 't / h': 1 / 3.6, 'g / s': 1e-3, 't/h': 1 / 3.6, 'g/s': 1e-3,
494
- 'g / sec': 1e-3, 'g/sec': 1e-3,
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
- 'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}',
497
- 'documentation': {'float_fmt': '{:,.3f}'}
546
+ "latex_eq": r"0 = \dot{m} - \dot{m}_\mathrm{spec}",
547
+ "documentation": {"float_fmt": "{:,.3f}"},
498
548
  },
499
- 'n': {
500
- 'text': 'molar flow',
501
- 'SI_unit': 'mol / s',
502
- 'units': {
503
- 'mol / s': 1, 'mol / min': 1 / 60, 'mol / h': 1 / 3.6e3, 'mol/s': 1, 'mol/min': 1 / 60, 'mol/h': 1 / 3.6e3,
504
- 'kmol / s': 1e3, 'kmol / min': 1 / 60e3, 'kmol / h': 1 / 3.6e6, 'kmol/s': 1e3, 'kmol/min': 1 / 60e3, 'kmol/h': 1 / 3.6e6,
505
- 'mol / sec': 1, 'mol/sec': 1, 'kmol / sec': 1e3, 'kmol/sec': 1e3,
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
- 'latex_eq': r'0 = \dot{n} - \dot{n}_\mathrm{spec}',
508
- 'documentation': {'float_fmt': '{:,.3f}'}
570
+ "latex_eq": r"0 = \dot{n} - \dot{n}_\mathrm{spec}",
571
+ "documentation": {"float_fmt": "{:,.3f}"},
509
572
  },
510
- 'v': {
511
- 'text': 'volumetric flow',
512
- 'SI_unit': 'm3 / s',
513
- 'units': {
514
- 'm3 / s': 1, 'm3 / min': 1 / 60, 'm3 / h': 1 / 3.6e3,
515
- 'l / s': 1 / 1e3, 'l / min': 1 / 60e3, 'l / h': 1 / 3.6e6
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
- 'latex_eq': (
518
- r'0 = \dot{m} \cdot v \left(p,h\right)- \dot{V}_\mathrm{spec}'),
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
- 'p': {
522
- 'text': 'pressure',
523
- 'SI_unit': 'Pa',
524
- 'units': {
525
- 'Pa': 1, 'kPa': 1e3, 'psi': 6.8948e3,
526
- 'bar': 1e5, 'atm': 1.01325e5, 'MPa': 1e6
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
- 'h': {
532
- 'text': 'enthalpy',
533
- 'SI_unit': 'J / kg',
534
- 'SI_unit_molar:': 'J / mol',
535
- 'units': {
536
- 'J / kg': 1, 'kJ / kg': 1e3, 'MJ / kg': 1e6, 'J/kg': 1, 'kJ/kg': 1e3, 'MJ/kg': 1e6,
537
- 'cal / kg': 4.184, 'kcal / kg': 4.184e3, 'cal/kg': 4.184, 'kcal/kg': 4.184e3,
538
- 'Wh / kg': 3.6e3, 'kWh / kg': 3.6e6, 'Wh/kg': 3.6e3, 'kWh kg': 3.6e6,
539
- 'J / mol': 1, 'kJ / mol': 1e3, 'MJ / mol': 1e6, 'J/mol': 1, 'kJ/mol': 1e3, 'MJ/mol': 1e6,
540
- 'J / kmol': 1e-3, 'kJ / kmol': 1, 'MJ / kmol': 1e3, 'J/kmol': 1e-3, 'kJ/kmol': 1, 'MJ/kmol': 1e3
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
- 'latex_eq': r'0 = h - h_\mathrm{spec}',
543
- 'documentation': {'float_fmt': '{:,.3f}'}
626
+ "latex_eq": r"0 = h - h_\mathrm{spec}",
627
+ "documentation": {"float_fmt": "{:,.3f}"},
544
628
  },
545
- 'e': {
546
- 'text': 'exergy',
547
- 'SI_unit': 'J / kg',
548
- 'SI_unit_molar:': 'J / mol',
549
- 'units': {
550
- 'J / kg': 1, 'kJ / kg': 1e3, 'MJ / kg': 1e6, 'J/kg': 1, 'kJ/kg': 1e3, 'MJ/kg': 1e6,
551
- 'cal / kg': 4.184, 'kcal / kg': 4.184e3, 'cal/kg': 4.184, 'kcal/kg': 4.184e3,
552
- 'Wh / kg': 3.6e3, 'kWh / kg': 3.6e6, 'Wh/kg': 3.6e3, 'kWh kg': 3.6e6,
553
- 'J / mol': 1, 'kJ / mol': 1e3, 'MJ / mol': 1e6, 'J/mol': 1, 'kJ/mol': 1e3, 'MJ/mol': 1e6,
554
- 'J / kmol': 1e-3, 'kJ / kmol': 1, 'MJ / kmol': 1e3, 'J/kmol': 1e-3, 'kJ/kmol': 1, 'MJ/kmol': 1e3
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
- 'latex_eq': r'0 = h - h_\mathrm{spec}',
557
- 'documentation': {'float_fmt': '{:,.3f}'}
661
+ "latex_eq": r"0 = h - h_\mathrm{spec}",
662
+ "documentation": {"float_fmt": "{:,.3f}"},
558
663
  },
559
- 'T': {
560
- 'text': 'temperature',
561
- 'SI_unit': 'K',
562
- 'units': {
563
- 'K': [0, 1], 'R': [0, 5 / 9],
564
- 'C': [273.15, 1], 'F': [459.67, 5 / 9]
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
- 'Td_bp': {
570
- 'text': 'temperature difference to boiling point',
571
- 'SI_unit': 'K',
572
- 'units': {
573
- 'K': 1, 'R': 5 / 9, 'C': 1, 'F': 5 / 9
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
- 'vol': {
579
- 'text': 'specific volume',
580
- 'SI_unit': 'm3 / kg',
581
- 'units': {'m3 / kg': 1, 'l / kg': 1e-3},
582
- 'latex_eq': (
583
- r'0 = v\left(p,h\right) \cdot \dot{m} - \dot{V}_\mathrm{spec}'),
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
- 'x': {
587
- 'text': 'vapor mass fraction',
588
- 'SI_unit': '-',
589
- 'units': {'1': 1, '-': 1, '%': 1e-2, 'ppm': 1e-6},
590
- 'latex_eq': r'0 = h - h\left(p, x_\mathrm{spec}\right)',
591
- 'documentation': {'float_fmt': '{:,.2f}'}
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
- 's': {
594
- 'text': 'entropy',
595
- 'SI_unit': 'J / kgK',
596
- 'SI_unit_molar:': 'J / molK',
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
- 'power': {
609
- 'text': 'power',
610
- 'SI_unit': 'W',
611
- 'units': {'W': 1, 'kW': 1e3, 'MW': 1e6},
742
+ "heat": {
743
+ "text": "heat",
744
+ "SI_unit": "W",
745
+ "units": {"W": 1, "kW": 1e3, "MW": 1e6},
612
746
  },
613
- 'heat': {
614
- 'text': 'heat',
615
- 'SI_unit': 'W',
616
- 'units': {'W': 1, 'kW': 1e3, 'MW': 1e6},
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
- 'kA': {
619
- 'text': 'kA',
620
- 'SI_unit': 'W / K',
621
- 'units': {
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
- 'A': {
626
- 'text': 'area',
627
- 'SI_unit': 'm2',
628
- 'units': {'m2': 1, 'cm2': 1e-4, 'mm2': 1e-6,
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
  }