Skip to content

Commit

Permalink
Fix exergy implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
fwitte committed Sep 9, 2023
1 parent 2581710 commit b133ad5
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 12 deletions.
12 changes: 9 additions & 3 deletions src/tespy/connections/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -952,14 +952,17 @@ def get_physical_exergy(self, pamb, Tamb):
E^\mathrm{M} = \dot{m} \cdot e^\mathrm{M}\\
E^\mathrm{PH} = \dot{m} \cdot e^\mathrm{PH}
"""
self.ex_therm, self.ex_mech = fp.calc_physical_exergy(self, p0, T0)
self.ex_therm, self.ex_mech = fp.functions.calc_physical_exergy(
self.h.val_SI, self.s.val_SI, self.p.val_SI, pamb, Tamb,
self.fluid_data, self.mixing_rule, self.T.val_SI
)
self.Ex_therm = self.ex_therm * self.m.val_SI
self.Ex_mech = self.ex_mech * self.m.val_SI

self.ex_physical = self.ex_therm + self.ex_mech
self.Ex_physical = self.m.val_SI * self.ex_physical

def get_chemical_exergy(self, p0, T0, Chem_Ex):
def get_chemical_exergy(self, pamb, Tamb, Chem_Ex):
r"""
Get the value of a connection's specific chemical exergy.
Expand All @@ -983,7 +986,10 @@ def get_chemical_exergy(self, p0, T0, Chem_Ex):
if Chem_Ex is None:
self.ex_chemical = 0
else:
self.ex_chemical = fp.calc_chemical_exergy(self, p0, T0, Chem_Ex)
self.ex_chemical = fp.functions.calc_chemical_exergy(
pamb, Tamb, self.fluid_data, Chem_Ex, self.mixing_rule,
self.T.val_SI
)

self.Ex_chemical = self.m.val_SI * self.ex_chemical

Expand Down
56 changes: 54 additions & 2 deletions src/tespy/tools/fluid_properties/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
from .helpers import get_pure_fluid
from .helpers import get_number_of_fluids
from .helpers import inverse_temperature_mixture
from .mixtures import T_MIX_PH_REVERSE
from .mixtures import T_MIX_PS_REVERSE
from .mixtures import EXERGY_CHEMICAL
from .mixtures import H_MIX_PT_DIRECT
from .mixtures import S_MIX_PT_DIRECT
from .mixtures import T_MIX_PH_REVERSE
from .mixtures import T_MIX_PS_REVERSE
from .mixtures import V_MIX_PT_DIRECT
from .mixtures import VISCOSITY_MIX_PT_DIRECT

Expand All @@ -20,6 +21,57 @@ def isentropic(p_1, h_1, p_2, fluid_data, mixing_rule=None, T0=None):
return h_mix_pT(p_2, T_2, fluid_data, mixing_rule)


def calc_physical_exergy(h, s, p, pamb, Tamb, fluid_data, mixing_rule=None, T0=None):
r"""
Calculate specific physical exergy.
Physical exergy is allocated to a thermal and a mechanical share according
to :cite:`Morosuk2019`.
Parameters
----------
pamb : float
Ambient pressure p0 / Pa.
Tamb : float
Ambient temperature T0 / K.
Returns
-------
e_ph : tuple
Specific thermal and mechanical exergy
(:math:`e^\mathrm{T}`, :math:`e^\mathrm{M}`) in J / kg.
.. math::
e^\mathrm{T} = \left( h - h \left( p, T_0 \right) \right) -
T_0 \cdot \left(s - s\left(p, T_0\right)\right)
e^\mathrm{M}=\left(h\left(p,T_0\right)-h\left(p_0,T_0\right)\right)
-T_0\cdot\left(s\left(p, T_0\right)-s\left(p_0,T_0\right)\right)
e^\mathrm{PH} = e^\mathrm{T} + e^\mathrm{M}
"""
h_T0_p = h_mix_pT(p, Tamb, fluid_data, mixing_rule)
s_T0_p = s_mix_pT(p, Tamb, fluid_data, mixing_rule)
ex_therm = (h - h_T0_p) - T0 * (s - s_T0_p)
h0 = h_mix_pT(pamb, Tamb, fluid_data, mixing_rule)
s0 = s_mix_pT(pamb, Tamb, fluid_data, mixing_rule)
ex_mech = (h_T0_p - h0) - T0 * (s_T0_p - s0)
return ex_therm, ex_mech


def calc_chemical_exergy(pamb, Tamb, fluid_data, Chem_Ex, mixing_rule=None, T0=None):
if get_number_of_fluids(fluid_data) == 1:
pure_fluid = get_pure_fluid(fluid_data)
fluid_aliases = pure_fluid["wrapper"]._aliases
y = [Chem_Ex[k][Chem_Ex[k][4]] for k in fluid_aliases if k in Chem_Ex]
return y[0] / pure_fluid["wrapper"]._molar_mass * 1e3
else:
_check_mixing_rule(mixing_rule, EXERGY_CHEMICAL, "chemical exergy")
return EXERGY_CHEMICAL[mixing_rule](pamb, Tamb, fluid_data, Chem_Ex)


def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None):
if get_number_of_fluids(fluid_data) == 1:
pure_fluid = get_pure_fluid(fluid_data)
Expand Down
54 changes: 47 additions & 7 deletions src/tespy/tools/fluid_properties/mixtures.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import CoolProp as CP
import numpy as np

from tespy.tools.global_vars import gas_constants
from .helpers import _is_larger_than_precision
from .helpers import calc_molar_mass_mixture
from .helpers import get_molar_fractions



def h_mix_pT_ideal(p=None, T=None, fluid_data=None, **kwargs):
molar_fractions = get_molar_fractions(fluid_data)

Expand Down Expand Up @@ -49,12 +50,9 @@ def h_mix_pT_forced_gas(p, T, fluid_data, **kwargs):

if _is_larger_than_precision(data["mass_fraction"]):
pp = p * molar_fractions[fluid]
if fluid == "H2O":
if pp >= data["wrapper"]._p_min:
if T <= data["wrapper"].T_sat(pp):
h += data["wrapper"].h_QT(1, T) * data["mass_fraction"]
else:
h += data["wrapper"].h_pT(pp, T) * data["mass_fraction"]
if fluid == "H2O" and pp >= data["wrapper"]._p_min:
if T <= data["wrapper"].T_sat(pp):
h += data["wrapper"].h_QT(1, T) * data["mass_fraction"]
else:
h += data["wrapper"].h_pT(pp, T) * data["mass_fraction"]
else:
Expand Down Expand Up @@ -220,6 +218,44 @@ def viscosity_mix_pT_incompressible(p=None, T=None, fluid_data=None, **kwargs):
return viscosity


def exergy_chemical_ideal_cond(pamb, Tamb, fluid_data, Chem_Ex):

molar_fractions = get_molar_fractions(fluid_data)
water_alias = _water_in_mixture(fluid_data)
if water_alias:
water_alias = next(iter(water_alias))
_, molar_fractions_gas, _, molar_liquid = cond_check(
pamb, Tamb, fluid_data, water_alias
)
else:
molar_fractions_gas = molar_fractions
molar_liquid = 0

ex_cond = 0
ex_dry = 0
for fluid, x in molar_fractions_gas.items():
if x == 0:
continue

fluid_aliases = fluid_data[fluid]["wrapper"]._aliases

if molar_liquid > 0:
y = [
Chem_Ex[k][2] for k in fluid_aliases if k in Chem_Ex
]
ex_cond += molar_liquid * y[0]

y = [Chem_Ex[k][3] for k in fluid_aliases if k in Chem_Ex]
ex_dry += x * y[0] + Tamb * gas_constants['uni'] * 1e-3 * x * np.log(x)

ex_chemical = ex_cond + ex_dry * (1 - molar_liquid)
ex_chemical *= 1 / calc_molar_mass_mixture(
fluid_data, molar_fractions
)

return ex_chemical * 1e3 # Data from Chem_Ex are in kJ / mol


def _water_in_mixture(fluid_data):
water_aliases = set(CP.CoolProp.get_aliases("H2O"))
return water_aliases & set([f for f in fluid_data if _is_larger_than_precision(fluid_data[f]["mass_fraction"])])
Expand Down Expand Up @@ -324,3 +360,7 @@ def cond_check(p, T, fluid_data, water_alias):
"ideal-cond": viscosity_mix_pT_ideal,
"incompressible": viscosity_mix_pT_incompressible
}

EXERGY_CHEMICAL = {
"ideal-cond": exergy_chemical_ideal_cond,
}
1 change: 1 addition & 0 deletions src/tespy/tools/fluid_properties/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def __init__(self, fluid, back_end=None) -> None:
def _set_constants(self):
self._T_min = self.AS.trivial_keyed_output(CP.iT_min)
self._T_max = self.AS.trivial_keyed_output(CP.iT_max)
self._aliases = CP.CoolProp.get_aliases(self.fluid)

if self.back_end == "INCOMP":
self._p_min = 1e2
Expand Down

0 comments on commit b133ad5

Please sign in to comment.