Transitory functions

This module contains transitory functions which all have a specific physical meaning for modeling the PEM fuel cell.

C_v_sat(T)

This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the temperature.

Parameters:
  • T (float) –

    Temperature in K.

Returns:
  • float

    Saturated vapor concentration for a perfect gas in mol.m-3.

Source code in modules/transitory_functions.py
def C_v_sat(T):
    """This function calculates the saturated vapor concentration for a perfect gas, in mol.m-3, as a function of the
    temperature.

    Parameters
    ----------
    T : float
        Temperature in K.

    Returns
    -------
    float
        Saturated vapor concentration for a perfect gas in mol.m-3.
    """
    return Psat(T) / (R * T)

D(lambdaa)

This function calculates the diffusion coefficient of water in the membrane, in m².s-1.

Parameters:
  • lambdaa (float) –

    Water content in the membrane.

Returns:
  • float

    Diffusion coefficient of water in the membrane in m².s-1.

Source code in modules/transitory_functions.py
def D(lambdaa):
    """This function calculates the diffusion coefficient of water in the membrane, in m².s-1.

    Parameters
    ----------
    lambdaa : float
        Water content in the membrane.

    Returns
    -------
    float
        Diffusion coefficient of water in the membrane in m².s-1.
    """
    return 4.1e-10 * (lambdaa / 25.0) ** 0.15 * (1.0 + np.tanh((lambdaa - 2.5) / 1.4))

Da(P, T)

This function calculates the diffusion coefficient at the anode, in m².s-1.

Parameters:
  • P (float) –

    Pressure in Pa.

  • T (float) –

    Temperature in K.

Returns:
  • float

    Diffusion coefficient at the anode in m².s-1.

Source code in modules/transitory_functions.py
def Da(P, T):
    """This function calculates the diffusion coefficient at the anode, in m².s-1.

    Parameters
    ----------
    P : float
        Pressure in Pa.
    T : float
        Temperature in K.

    Returns
    -------
    float
        Diffusion coefficient at the anode in m².s-1.
    """
    return 1.644e-4 * (T / 333) ** 2.334 * (101325 / P)

Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl)

This function calculates the effective diffusion coefficient at the anode, in m².s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl.

Parameters:
  • s (float) –

    Liquid water saturation variable.

  • epsilon (float) –

    Porosity.

  • P (float) –

    Pressure in Pa.

  • T (float) –

    Temperature in K.

  • epsilon_c (float) –

    Compression ratio of the GDL.

  • epsilon_gdl (float) –

    Porosity of the GDL.

Returns:
  • float

    Effective diffusion coefficient at the anode in m².s-1.

Source code in modules/transitory_functions.py
def Da_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl):
    """This function calculates the effective diffusion coefficient at the anode, in m².s-1, considering GDL
    compression.
    Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which
    may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl.

    Parameters
    ----------
    s : float
        Liquid water saturation variable.
    epsilon : float
        Porosity.
    P : float
        Pressure in Pa.
    T : float
        Temperature in K.
    epsilon_c : float
        Compression ratio of the GDL.
    epsilon_gdl : float
        Porosity of the GDL.

    Returns
    -------
    float
        Effective diffusion coefficient at the anode in m².s-1.
    """

    # According to the GDL porosity, the GDL compression effect is different.
    if 0.55 <= epsilon_gdl < 0.67:
        beta2 = -1.59
    elif 0.67 <= epsilon_gdl < 0.8:
        beta2 = -0.90
    else:
        raise ValueError("In order to calculate the effects of the GDL compression on its structure, "
                         "epsilon_gdl should be between 0.55 and 0.8.")

    return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Da(P, T)

Dc(P, T)

This function calculates the diffusion coefficient at the cathode, in m².s-1.

Parameters:
  • P (float) –

    Pressure in Pa.

  • T (float) –

    Temperature in K.

Returns:
  • float

    Diffusion coefficient at the cathode in m².s-1.

Source code in modules/transitory_functions.py
def Dc(P, T):
    """This function calculates the diffusion coefficient at the cathode, in m².s-1.

    Parameters
    ----------
    P : float
        Pressure in Pa.
    T : float
        Temperature in K.

    Returns
    -------
    float
        Diffusion coefficient at the cathode in m².s-1.
    """
    return 3.242e-5 * (T / 333) ** 2.334 * (101325 / P)

Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl)

This function calculates the effective diffusion coefficient at the cathode, in m².s-1, considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl.

Parameters:
  • s (float) –

    Liquid water saturation variable.

  • epsilon (float) –

    Porosity.

  • P (float) –

    Pressure in Pa.

  • T (float) –

    Temperature in K.

  • epsilon_c (float) –

    Compression ratio of the GDL.

  • epsilon_gdl (float) –

    Porosity of the GDL.

Returns:
  • float

    Effective diffusion coefficient at the cathode in m².s-1.

Source code in modules/transitory_functions.py
def Dc_eff(s, epsilon, P, T, epsilon_c, epsilon_gdl):
    """This function calculates the effective diffusion coefficient at the cathode, in m².s-1, considering GDL
    compression.
    Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which
    may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl.

    Parameters
    ----------
    s : float
        Liquid water saturation variable.
    epsilon : float
        Porosity.
    P : float
        Pressure in Pa.
    T : float
        Temperature in K.
    epsilon_c : float
        Compression ratio of the GDL.
    epsilon_gdl : float
        Porosity of the GDL.

    Returns
    -------
    float
        Effective diffusion coefficient at the cathode in m².s-1.
    """

    # According to the GDL porosity, the GDL compression effect is different.
    if 0.55 <= epsilon_gdl < 0.67:
        beta2 = -1.59
    elif 0.67 <= epsilon_gdl < 0.8:
        beta2 = -0.90
    else:
        raise ValueError("In order to calculate the effects of the GDL compression on its structure, "
                         "epsilon_gdl should be between 0.55 and 0.8.")

    return epsilon * ((epsilon - 0.11) / (1 - 0.11)) ** 0.785 * np.exp(beta2 * epsilon_c) * (1 - s) ** 2 * Dc(P, T)

K0(epsilon, epsilon_c, epsilon_gdl)

This function calculates the intrinsic permeability, in m², considering GDL compression. Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl.

Parameters:
  • epsilon (float) –

    Porosity.

  • epsilon_c (float) –

    Compression ratio of the GDL.

  • epsilon_gdl (float) –

    Porosity of the GDL.

Returns:
  • float

    Intrinsic permeability in m².

Source code in modules/transitory_functions.py
def K0(epsilon, epsilon_c, epsilon_gdl):
    """This function calculates the intrinsic permeability, in m², considering GDL compression.
    Remark: it is considered here that the compression of the stack has a similar effect on the GDL and the CL, which
    may be wrong. This is why two porosities are considered in the parameters of this function: epsilon and epsilon_gdl.

    Parameters
    ----------
    epsilon : float
        Porosity.
    epsilon_c : float
        Compression ratio of the GDL.
    epsilon_gdl : float
        Porosity of the GDL.

    Returns
    -------
    float
        Intrinsic permeability in m².
    """

    # According to the GDL porosity, the GDL compression effect is different.
    if 0.55 <= epsilon_gdl < 0.67:
        beta1 = -3.60
    elif 0.67 <= epsilon_gdl < 0.8:
        beta1 = -2.60
    else:
        raise ValueError("In order to calculate the effects of the GDL compression on its structure, "
                         "epsilon_gdl should be between 0.55 and 0.8.")

    return epsilon / (8 * np.log(epsilon) ** 2) * (epsilon - 0.11) ** (0.785 + 2) * \
        4.6e-6 ** 2 / ((1 - 0.11) ** 0.785 * ((0.785 + 1) * epsilon - 0.11) ** 2) * np.exp(beta1 * epsilon_c)

Psat(T)

This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature.

Parameters:
  • T (float) –

    Temperature in K.

Returns:
  • float

    Saturated partial pressure of vapor in Pa.

Source code in modules/transitory_functions.py
def Psat(T):
    """This function calculates the saturated partial pressure of vapor, in Pa, as a function of the temperature.

    Parameters
    ----------
    T : float
        Temperature in K.

    Returns
    -------
    float
        Saturated partial pressure of vapor in Pa.
    """
    return 101325 * 10 ** (-2.1794 + 0.02953 * (T - 273.15) - 9.1837e-5 * (T - 273.15) ** 2 +
                           1.4454e-7 * (T - 273.15) ** 3)

Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap)

This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1.

Parameters:
  • s (float) –

    Liquid water saturation variable.

  • C_v (float) –

    Water concentration variable in mol.m-3.

  • Ctot (float) –

    Total gas concentration in mol.m-3.

  • epsilon (float) –

    Porosity.

  • T (float) –

    Temperature in K.

  • gamma_cond (float) –

    Overall condensation rate constant for water in s-1.

  • gamma_evap (float) –

    Overall evaporation rate constant for water in Pa-1.s-1.

Returns:
  • float

    Phase transfer rate of water condensation or evaporation in mol.m-3.s-1.

Source code in modules/transitory_functions.py
def Svl(s, C_v, Ctot, epsilon, T, gamma_cond, gamma_evap):
    """This function calculates the phase transfer rate of water condensation or evaporation, in mol.m-3.s-1.

    Parameters
    ----------
    s : float
        Liquid water saturation variable.
    C_v : float
        Water concentration variable in mol.m-3.
    Ctot : float
        Total gas concentration in mol.m-3.
    epsilon : float
        Porosity.
    T : float
        Temperature in K.
    gamma_cond : float
        Overall condensation rate constant for water in s-1.
    gamma_evap : float
        Overall evaporation rate constant for water in Pa-1.s-1.

    Returns
    -------
    float
        Phase transfer rate of water condensation or evaporation in mol.m-3.s-1.
    """

    if C_v > C_v_sat(T):  # condensation
        return gamma_cond * epsilon * (1 - s) * (C_v / Ctot) * (C_v - C_v_sat(T))
    else:  # evaporation
        return -gamma_evap * epsilon * s * rho_H2O(T) / M_H2O * R * T * (C_v_sat(T) - C_v)

gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape)

This function calculates the sorption rate of water in the membrane, in s-1.

Parameters:
  • C_v (float) –

    Water concentration variable in mol.m-3.

  • s (float) –

    Liquid water saturation variable.

  • lambdaa (float) –

    Water content in the membrane.

  • T (float) –

    Temperature in K.

  • Hcl (float) –

    Thickness of the CL layer.

  • Kshape (float) –

    Mathematical factor governing lambda_eq smoothing

Returns:
  • float

    Sorption rate of water in the membrane in s-1.

Source code in modules/transitory_functions.py
def gamma_sorp(C_v, s, lambdaa, T, Hcl, Kshape):
    """This function calculates the sorption rate of water in the membrane, in s-1.

    Parameters
    ----------
    C_v : float
        Water concentration variable in mol.m-3.
    s : float
        Liquid water saturation variable.
    lambdaa : float
        Water content in the membrane.
    T : float
        Temperature in K.
    Hcl : float
        Thickness of the CL layer.
    Kshape : float
        Mathematical factor governing lambda_eq smoothing

    Returns
    -------
    float
        Sorption rate of water in the membrane in s-1.
    """

    fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T))  # water volume fraction of
    #                                                                                       the membrane
    if lambda_eq(C_v, s, T, Kshape) >= lambdaa:  # type_flow = absorption
        return (1.14e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T))
    else:  # type_flow = desorption
        return (4.59e-5 * fv) / Hcl * np.exp(2416 * (1 / 303 - 1 / T))

h_a(P, T, Wgc, Hgc)

This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1.

Parameters:
  • P (float) –

    Pressure in Pa.

  • T (float) –

    Temperature in K.

  • Wgc (float) –

    Width of the gas channel in m.

  • Hgc (float) –

    Thickness of the gas channel in m.

Returns:
  • float

    Effective convective-conductive mass transfer coefficient at the anode in m.s-1.

Source code in modules/transitory_functions.py
def h_a(P, T, Wgc, Hgc):
    """This function calculates the effective convective-conductive mass transfer coefficient at the anode, in m.s-1.

    Parameters
    ----------
    P : float
        Pressure in Pa.
    T : float
        Temperature in K.
    Wgc : float
        Width of the gas channel in m.
    Hgc : float
        Thickness of the gas channel in m.

    Returns
    -------
    float
        Effective convective-conductive mass transfer coefficient at the anode in m.s-1.
    """
    Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787  # Sherwood coefficient.
    return Sh * Da(P, T) / Hgc

h_c(P, T, Wgc, Hgc)

This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1.

Parameters:
  • P (float) –

    Pressure in Pa.

  • T (float) –

    Temperature in K.

  • Wgc (float) –

    Width of the gas channel in m.

  • Hgc (float) –

    Thickness of the gas channel in m.

Returns:
  • float

    Effective convective-conductive mass transfer coefficient at the cathode in m.s-1.

Source code in modules/transitory_functions.py
def h_c(P, T, Wgc, Hgc):
    """This function calculates the effective convective-conductive mass transfer coefficient at the cathode, in m.s-1.

    Parameters
    ----------
    P : float
        Pressure in Pa.
    T : float
        Temperature in K.
    Wgc : float
        Width of the gas channel in m.
    Hgc : float
        Thickness of the gas channel in m.

    Returns
    -------
    float
        Effective convective-conductive mass transfer coefficient at the cathode in m.s-1.
    """
    Sh = 0.9247 * np.log(Wgc / Hgc) + 2.3787  # Sherwood coefficient.
    return Sh * Dc(P, T) / Hgc

k_H2(lambdaa, T, kappa_co)

This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m−1.s−1.Pa−1.

Parameters:
  • lambdaa (float) –

    Water content in the membrane.

  • T (float) –

    Temperature in K.

  • kappa_co (float) –

    Crossover correction coefficient in mol.m-1.s-1.Pa-1.

Returns:
  • float

    Permeability coefficient of the membrane for hydrogen in mol.m−1.s−1.Pa−1.

Source code in modules/transitory_functions.py
def k_H2(lambdaa, T, kappa_co):
    """This function calculates the permeability coefficient of the membrane for hydrogen, in mol.m−1.s−1.Pa−1.

    Parameters
    ----------
    lambdaa : float
        Water content in the membrane.
    T : float
        Temperature in K.
    kappa_co : float
        Crossover correction coefficient in mol.m-1.s-1.Pa-1.

    Returns
    -------
    float
        Permeability coefficient of the membrane for hydrogen in mol.m−1.s−1.Pa−1.
    """

    # Initialisation of the constants
    E_H2_v = 2.1e4  # J.mol-1. It is the activation energy of H2 for crossover in the under saturated membrane.
    E_H2_l = 1.8e4  # J.mol-1. It is the activation energy of H2 for crossover in the liquide-equilibrated membrane.
    Tref = 303.15  # K.

    # Calculation of the permeability coefficient of the membrane for hydrogen
    if lambdaa < 17.6:
        fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T))
        return kappa_co * (0.29 + 2.2 * fv) * 1e-14 * np.exp(E_H2_v / R * (1 / Tref - 1 / T))
    else:
        return kappa_co * 1.8 * 1e-14 * np.exp(E_H2_l / R * (1 / Tref - 1 / T))

k_O2(lambdaa, T, kappa_co)

This function calculates the permeability coefficient of the membrane for oxygen, in mol.m−1.s−1.Pa−1.

Parameters:
  • lambdaa (float) –

    Water content in the membrane.

  • T (float) –

    Temperature in K.

  • kappa_co (float) –

    Crossover correction coefficient in mol.m-1.s-1.Pa-1.

Returns:
  • float

    Permeability coefficient of the membrane for oxygen in mol.m−1.s−1.Pa−1.

Source code in modules/transitory_functions.py
def k_O2(lambdaa, T, kappa_co):
    """This function calculates the permeability coefficient of the membrane for oxygen, in mol.m−1.s−1.Pa−1.

    Parameters
    ----------
    lambdaa : float
        Water content in the membrane.
    T : float
        Temperature in K.
    kappa_co : float
        Crossover correction coefficient in mol.m-1.s-1.Pa-1.

    Returns
    -------
    float
        Permeability coefficient of the membrane for oxygen in mol.m−1.s−1.Pa−1.
    """

    # Initialisation of the constants
    E_O2_v = 2.2e4  # J.mol-1. It is the activation energy of oxygen for crossover in the under saturated membrane.
    E_O2_l = 2.0e4  # J.mol-1. It is the activation energy of oxygen for crossover in the liquide-equilibrated membrane.
    Tref = 303.15  # K.

    # Calculation of the permeability coefficient of the membrane for oxygen
    if lambdaa < 17.6:
        fv = (lambdaa * M_H2O / rho_H2O(T)) / (M_eq / rho_mem + lambdaa * M_H2O / rho_H2O(T))
        return kappa_co * (0.11 + 1.9 * fv) * 1e-14 * np.exp(E_O2_v / R * (1 / Tref - 1 / T))
    else:
        return kappa_co * 1.2 * 1e-14 * np.exp(E_O2_l / R * (1 / Tref - 1 / T))

lambda_eq(C_v, s, T, Kshape)

This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with Bao's formulation has been selected.

Parameters:
  • C_v (float) –

    Water concentration variable in mol.m-3.

  • s (float) –

    Liquid water saturation variable.

  • T (float) –

    Temperature in K.

  • Kshape (float) –

    Mathematical factor governing lambda_eq smoothing

Returns:
  • float

    Equilibrium water content in the membrane.

Source code in modules/transitory_functions.py
def lambda_eq(C_v, s, T, Kshape):
    """This function calculates the equilibrium water content in the membrane. Hinatsu's expression modified with
    Bao's formulation has been selected.

    Parameters
    ----------
    C_v : float
        Water concentration variable in mol.m-3.
    s : float
        Liquid water saturation variable.
    T : float
        Temperature in K.
    Kshape : float
        Mathematical factor governing lambda_eq smoothing

    Returns
    -------
    float
        Equilibrium water content in the membrane.
    """
    a_w = C_v / C_v_sat(T) + 2 * s  # water activity
    return 0.5 * (0.300 + 10.8 * a_w - 16.0 * a_w ** 2 + 14.1 * a_w ** 3) * (1 - np.tanh(100 * (a_w - 1))) \
        + 0.5 * (9.2 + 8.6 * (1 - np.exp(-Kshape * (a_w - 1)))) * (1 + np.tanh(100 * (a_w - 1)))

nu_l(T)

This function calculates the liquid water kinematic viscosity, in m².s-1, as a function of the temperature.

Parameters:
  • T (float) –

    Temperature in K.

Returns:
  • float

    Liquid water kinematic viscosity in m².s-1.

Source code in modules/transitory_functions.py
def nu_l(T):
    """This function calculates the liquid water kinematic viscosity, in m².s-1, as a function of the temperature.

    Parameters
    ----------
    T : float
        Temperature in K.

    Returns
    -------
    float
        Liquid water kinematic viscosity in m².s-1.
    """
    mu_l = 2.414 * 10 ** (-5 + 247.8 / (T - 140.0))  # Pa.s. It is the liquid water dynamic viscosity.
    return mu_l / rho_H2O(T)

rho_H2O(T)

This function calculates the water density, in kg.m-3, as a function of the temperature.

Parameters:
  • T (float) –

    Temperature in K.

Returns:
  • float

    Water density in kg.m-3.

Source code in modules/transitory_functions.py
def rho_H2O(T):
    """This function calculates the water density, in kg.m-3, as a function of the temperature.

    Parameters
    ----------
    T : float
        Temperature in K.

    Returns
    -------
    float
        Water density in kg.m-3.
    """
    return ((999.83952 + 16.945176 * (T - 273.15) - 7.9870401e-3 * (T - 273.15) ** 2 - 46.170461e-6 * (T - 273.15) ** 3
             + 105.56302e-9 * (T - 273.15) ** 4 - 280.54253e-12 * (T - 273.15) ** 5) /
            (1 + 16.879850e-3 * (T - 273.15)))

sigma(T)

This function calculates the water surface tension, in N.m-1, as a function of the temperature.

Parameters:
  • T (float) –

    Temperature in K.

Returns:
  • float

    Water surface tension in N.m-1.

Source code in modules/transitory_functions.py
def sigma(T):
    """This function calculates the water surface tension, in N.m-1, as a function of the temperature.

    Parameters
    ----------
    T : float
        Temperature in K.

    Returns
    -------
    float
        Water surface tension in N.m-1.
    """
    return 235.8e-3 * ((647.15 - T) / 647.15) ** 1.256 * (1 - 0.625 * (647.15 - T) / 647.15)