Source code for pyseaflux.gas_transfer_velocity

"""
Gas Transfer Velocity
---------------------

Modulates the magnitude of the flux between the atmosphere and the ocean.
"""


def _add_xarray_attrs(func):
    """A helper function to add attributes to xarray."""
    import re

    from functools import wraps

    from xarray import DataArray

    def get_refs(func):
        """gets the reference from the docs where the reference is formatted
        as \nReferences: ..."""
        found = re.findall("References:(.*)", func.__doc__, flags=re.DOTALL)
        if any(found):
            ref = " ".join([s.strip() for s in found[0].split("\n")]).strip()
            return ref
        else:
            return ""

    def get_code(func):
        """get the formulation of kw from the function code. Requires the line
        to start with k = ..."""
        import inspect

        raw = "".join(inspect.getsource(func))
        found = re.findall("(k = .*)", raw)

        if any(found):
            code = found[0]
            return code
        else:
            return ""

    @wraps(func)
    def wrapper(*args, **kwargs):
        """wrapper that adds the xarray metadata if input is xarray"""
        out = func(*args, **kwargs)
        if isinstance(out, DataArray):
            # full reference based on function name. This is manually added
            names = {
                "k_Li86": "Liss and Merlivat (1986)",
                "k_Wa92": "Wanninkhof (1992)",
                "k_Wa99": "Wanninkhof and McGillis(1999)",
                "k_Ni00": "Nightingale et al. (2000)",
                "k_Mc01": "McGillis et al (2001)",
                "k_Ho06": "Ho et al. (2006)",
                "k_Sw07": "Sweeney et al. (2007)",
                "k_Wa09": "Wanninkhof et al. (2009)",
                "k_Wa14": "Wanninkhof et al. (2014)",
            }
            name = names[func.__name__]
            out = out.assign_attrs(
                units="cm/hr",
                description=f"gas transfer velocity of CO2 in seawater using {name}",
                reference=get_refs(func),
                formulation=get_code(func),
            )
        return out

    return wrapper


[docs]def schmidt_number(temp_C): """ Calculates the Schmidt number as defined by Jahne et al. (1987) and listed in Wanninkhof (2014) Table 1. Args: temp_C (array): temperature in degrees C Returns: array: Schmidt number (dimensionless) Examples: >>> schmidt_number(20) # from Wanninkhof (2014) 668.344 References: Jähne, B., Heinz, G., & Dietrich, W. (1987). Measurement of the diffusion coefficients of sparingly soluble gases in water. Journal of Geophysical Research: Oceans, 92(C10), 10767–10776. https://doi.org/10.1029/JC092iC10p10767 """ from numpy import nanmedian if nanmedian(temp_C) > 270: raise ValueError("temperature is not in degC") T = temp_C a = +2116.8 b = -136.25 c = +4.7353 d = -0.092307 e = +0.0007555 Sc = a + b * T + c * T ** 2 + d * T ** 3 + e * T ** 4 return Sc
[docs]def k_Li86(wind_ms, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of Liss and Merlivat (1986) Note: This is an old parameterization and we recommend using updated parameterisations that are calculated based on the wind product you choose to use. We include this parameterisation based purely for legacy purposes. Args: wind_ms (array): wind speed in m/s temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k600) in cm/hr References: Liss, P. S., & Merlivat, L. (1986). The Role of Air-Sea Exchange in Geochemical Cycling (Vol. 1983, Issue June 1983). D. Reidel Publishing Company. """ from numpy import zeros_like U = wind_ms T = temp_C Sc = schmidt_number(T) k = zeros_like(temp_C) i1 = U <= 3.6 i2 = (U > 3.6) & (U < 13.0) i3 = U >= 13.0 k[i1] = (0.17 * U[i1]) * (Sc[i1] / 600) ** (-2.0 / 3.0) k[i2] = ((U[i2] - 3.4) * 2.8) * (600 / Sc[i2]) ** 0.5 k[i3] = ((U[i3] - 8.4) * 5.9) * (600 / Sc[i3]) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Wa92(wind_second_moment, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of Wanninkhof (1992) Note: This is an old parameterization and we recommend using updated parameterisations that are calculated based on the wind product you choose to use. We include this parameterisation based purely for legacy purposes. The gas transfer velocity is scaled from instantaneous wind speeds. The study applies a correction to the scaling (0.39) based on instantaneous wind speeds to lower it to 0.31. This correction is based on the variability of wind. .. math:: k_{660} = 0.31 \\cdot U^2 Args: wind_second_moment (array): wind speed squared in m2/s2. Note that the second moment should be calculated at the native resolution of the wind to avoid losses of variability when taking the square product. temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k660) in cm/hr References: Wanninkhof, R. H. (1992). Relationship between wind speed and gas exchange over the ocean. Journal of Geophysical Research, 97(C5), 7373. https://doi.org/10.1029/92JC00188 """ U2 = wind_second_moment Sc = schmidt_number(temp_C) k = (0.31 * U2) * (660 / Sc) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Wa99(wind_ms, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of Wanninkhof and McGillis (1999) The gas transfer velocity has been scaled for in-situ short term wind products. Note that using this function for any other wind product is not correct. .. math:: k_{600} = 0.0283 \\cdot U^3 Args: wind_ms (array): wind speed in m/s temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k600) in cm/hr References: Wanninkhof, R. H., & McGillis, W. R. (1999). A cubic relationship between air-sea CO2 exchange and wind speed. Geophysical Research Letters, 26(13), 1889–1892. https://doi.org/10.1029/1999GL900363 """ U = wind_ms Sc = schmidt_number(temp_C) k = (0.0283 * U ** 3) * (600 / Sc) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Ni00(wind_ms, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of Nightingale et al (2000) .. math:: k_{600} = 0.333 \\cdot U + 0.222 \\cdot U^2 Args: wind_ms (array): wind speed in m/s temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k600) in cm/hr References: Nightingale, P. D., Malin, G., Law, C. S., Watson, A. J., Liss, P. S., Liddicoat, M. I., Boutin, J., & Upstill-Goddard, R. C. (2000). In situ evaluation of air-sea gas exchange parameterizations using novel conservative and volatile tracers. In Global Biogeochemical Cycles (Vol. 14, Issue 1, p. 373). https://doi.org/10.1029/1999GB900091 """ U = wind_ms Sc = schmidt_number(temp_C) k = (0.333 * U + 0.222 * U ** 2) * (600 / Sc) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Mc01(wind_ms, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of McGillis et al. (2001) The gas transfer velocity has been scaled for in-situ short term wind products. Note that using this function for any other wind product is not correct. .. math:: k_{660} = 3.3 + 0.026 \\cdot U^3 Args: wind_ms (array): wind speed in m/s temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k660) in cm/hr References: McGillis, W. R., Edson, J. B., Ware, J. D., Dacey, J. W. H., Hare, J. E., Fairall, C. W., & Wanninkhof, R. H. (2001). Carbon dioxide flux techniques performed during GasEx-98. Marine Chemistry, 75(4), 267–280. https://doi.org/10.1016/S0304-4203(01)00042-1 """ U = wind_ms Sc = schmidt_number(temp_C) k = 3.3 + (0.026 * U ** 3) * (660 / Sc) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Ho06(wind_second_moment, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of Ho et al. (2006) The gas transfer velocity is for the QuickSCAT satellite wind product. Note that using this function for any other wind product is stricktly speaking not correct. .. math:: k_{600} = 0.266 \\cdot U^2 The parameterization is based on the SOLAS Air-Sea Gas Exchange (SAGE) experiment. Args: wind_ms (array): wind speed in m/s temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k600) in cm/hr References: Ho, D. T., Law, C. S., Smith, M. J., Schlosser, P., Harvey, M., & Hill, P. (2006). Measurements of air-sea gas exchange at high wind speeds in the Southern Ocean: Implications for global parameterizations. Geophysical Research Letters, 33(16), 1–6. https://doi.org/10.1029/2006GL026817 """ U2 = wind_second_moment Sc = schmidt_number(temp_C) k = (0.266 * U2) * (600 / Sc) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Sw07(wind_second_moment, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation Wanninkhof (1992) rescaled by Sweeny et al (2007) The gas transfer velocity has been scaled for the NCEP/NCAR reanalysis 1 product. Note that using this function for any other wind product is not correct. .. math:: k_{660} = 0.27 \\cdot U^2 Args: wind_second_moment (array): wind speed squared in m2/s2. Note that the second moment should be calculated at the native resolution of the wind to avoid losses of variability when taking the square product. temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k660) in cm/hr References: Sweeney, C., Gloor, E., Jacobson, A. R., Key, R. M., McKinley, G. A., Sarmiento, J. L., & Wanninkhof, R. H. (2007). Constraining global air-sea gas exchange for CO2 with recent bomb 14C measurements. Global Biogeochemical Cycles, 21(2). https://doi.org/10.1029/2006GB002784 """ U2 = wind_second_moment Sc = schmidt_number(temp_C) k = (0.27 * U2) * (660 / Sc) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Wa09(wind_ms, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of Wanninkhof et al. (2009) The gas transfer velocity has been scaled for the Cross-Calibrated Multi- Platform (CCMP) Winds product. Note that using this function for any other wind product is not correct. .. math:: k_{660} = 3.0 + 0.1 \\cdot U + 0.064 \\cdot U^2 + 0.011 \\cdot U^3 Args: wind_ms (array): wind speed in m/s temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k660) in cm/hr References: Wanninkhof, R. H., Asher, W. E., Ho, D. T., Sweeney, C., & McGillis, W. R. (2009). Advances in Quantifying Air-Sea Gas Exchange and Environmental Forcing*. Annual Review of Marine Science, 1(1), 213–244. https://doi.org/10.1146/annurev.marine.010908.163742 """ U = wind_ms Sc = schmidt_number(temp_C) k = (3.0 + 0.1 * U + 0.064 * U ** 2 + 0.011 * U ** 3) * (660 / Sc) ** 0.5 return k
[docs]@_add_xarray_attrs def k_Wa14(wind_second_moment, temp_C): """ Calculates the gas transfer coeffcient for CO2 using the formulation of Wanninkhof et al. (2014) The gas transfer velocity has been scaled for the Cross-Calibrated Multi- Platform (CCMP) Winds product. Note that using this function for any other wind product is not correct. .. math:: k_{660} = 0.251 \\cdot U^2 Args: wind_second_moment (array): wind speed squared in m2/s2. Note that the second moment should be calculated at the native resolution of the wind to avoid losses of variability when taking the square product. temp_C (array): temperature in degrees C Returns: kw (array): gas transfer velocity (k660) in cm/hr References: Wanninkhof, R. H. (2014). Relationship between wind speed and gas exchange over the ocean revisited. Limnology and Oceanography: Methods, 12(JUN), 351–362. https://doi.org/10.4319/lom.2014.12.351 """ U2 = wind_second_moment Sc = schmidt_number(temp_C) k = 0.251 * U2 * (660 / Sc) ** 0.5 return k