.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_gallery/plot_aerobulk.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_gallery_plot_aerobulk.py: Estimate Turbulent Air-sea Fluxes =================================== **AeroBulk** is a FORTRAN90-based library and suite of tools that feature *state of the art* parameterizations to estimate turbulent air-sea fluxes by means of the traditional **aerodynamic bulk formulae**. These turbulent fluxes, namely, wind stress, evaporation (latent heat flux) and sensible heat flux, are estimated using the sea surface temperature (bulk or skin), and the near-surface atmospheric surface state: wind speed, air temperature and humidity. If the *cool-skin/warm-layer* schemes need to be called to estimate the skin temperature, surface downwelling shortwave and longwave radiative fluxes are required. .. seealso:: - https://github.com/brodeau/aerobulk - https://github.com/xgcm/aerobulk-python - https://ams.confex.com/ams/103ANNUAL/meetingapp.cgi/Session/63444 Before proceeding with all the steps, first import some necessary libraries and packages .. GENERATED FROM PYTHON SOURCE LINES 22-27 .. code-block:: Python import xarray as xr import cartopy.crs as ccrs import matplotlib.pyplot as plt import easyclimate as ecl .. GENERATED FROM PYTHON SOURCE LINES 28-31 Load the NetCDF sample ERA5 dataset containing near-surface atmospheric variables (e.g., 2m temperature, dewpoint temperature, 10m wind components, mean sea level pressure) and sea surface temperature (SST), and display its metadata structure to verify the dimensions and attributes of input variables. .. GENERATED FROM PYTHON SOURCE LINES 31-34 .. code-block:: Python sample_data = xr.open_dataset("sample_data_N20.nc") sample_data .. raw:: html
<xarray.Dataset> Size: 411kB
    Dimensions:  (time: 4, lon: 80, lat: 40)
    Coordinates:
      * time     (time) datetime64[ns] 32B 2024-01-01 ... 2024-01-01T18:00:00
      * lon      (lon) float64 640B 0.0 4.5 9.0 13.5 ... 342.0 346.5 351.0 355.5
      * lat      (lat) float64 320B 86.6 82.19 77.76 73.32 ... -77.76 -82.19 -86.6
    Data variables:
        u10      (time, lat, lon) float32 51kB ...
        v10      (time, lat, lon) float32 51kB ...
        d2m      (time, lat, lon) float32 51kB ...
        t2m      (time, lat, lon) float32 51kB ...
        msl      (time, lat, lon) float32 51kB ...
        sst      (time, lat, lon) float32 51kB ...
        ssrd     (time, lat, lon) float32 51kB ...
        strd     (time, lat, lon) float32 51kB ...
    Attributes:
        CDI:          Climate Data Interface version 2.4.4 (https://mpimet.mpg.de...
        Conventions:  CF-1.6
        history:      Fri May 02 15:46:46 2025: cdo -f nc4 -z zip5 remapbil,N20 d...
        CDO:          Climate Data Operators version 2.4.4 (https://mpimet.mpg.de...


.. GENERATED FROM PYTHON SOURCE LINES 35-39 Convert 2m dewpoint temperature (d2m) and mean sea level pressure (msl) data to near-surface specific humidity (q) using :py:func:`easyclimate.transfer_dewpoint_2_specific_humidity `, leveraging thermodynamic relationships; this specific humidity is a critical humidity parameter for calculating turbulent heat fluxes (latent heat flux). .. GENERATED FROM PYTHON SOURCE LINES 39-47 .. code-block:: Python q_data = ecl.transfer_dewpoint_2_specific_humidity( dewpoint_data = sample_data.d2m, pressure_data = sample_data.msl, dewpoint_data_units = "K", pressure_data_units = "Pa" ) q_data .. raw:: html
<xarray.DataArray 'specific_humidity' (time: 4, lat: 40, lon: 80)> Size: 51kB
    array([[[0.00071787, 0.00076128, 0.00079259, ..., 0.00052519,
             0.00058627, 0.00065293],
            [0.00129225, 0.00162815, 0.00196439, ..., 0.00068812,
             0.00073899, 0.00094276],
            [0.0019641 , 0.00253472, 0.00247658, ..., 0.00117425,
             0.0014484 , 0.00163637],
            ...,
            [0.00029264, 0.00026416, 0.00021988, ..., 0.00051915,
             0.00040085, 0.00033248],
            [0.00030657, 0.00027718, 0.00025185, ..., 0.00038103,
             0.00034929, 0.00032894],
            [0.00023752, 0.00023008, 0.0002227 , ..., 0.00026972,
             0.00025686, 0.00024608]],

           [[0.00068884, 0.00072928, 0.00076127, ..., 0.00056283,
             0.00060715, 0.00064756],
            [0.0011774 , 0.00152747, 0.00190248, ..., 0.00066314,
             0.00070415, 0.00087111],
            [0.0023589 , 0.00248486, 0.00281265, ..., 0.00113027,
             0.00114993, 0.00155959],
    ...
            [0.00035771, 0.00032354, 0.00031127, ..., 0.00061581,
             0.00052843, 0.00040916],
            [0.00036641, 0.00033005, 0.0003105 , ..., 0.00044219,
             0.00041493, 0.00039646],
            [0.00027146, 0.00025957, 0.00025106, ..., 0.00033539,
             0.00030939, 0.00028785]],

           [[0.00054111, 0.00054275, 0.0005398 , ..., 0.00053521,
             0.00053701, 0.00053964],
            [0.00073773, 0.00088102, 0.00115099, ..., 0.00054648,
             0.00055368, 0.00060174],
            [0.00175801, 0.00260998, 0.0029205 , ..., 0.00089693,
             0.00087427, 0.00103874],
            ...,
            [0.00034639, 0.00030798, 0.00027416, ..., 0.0006007 ,
             0.00053428, 0.00043464],
            [0.00035812, 0.00032369, 0.00030032, ..., 0.00043612,
             0.00040482, 0.00038519],
            [0.00030552, 0.00028482, 0.00026813, ..., 0.00038573,
             0.00034988, 0.00032437]]], shape=(4, 40, 80), dtype=float32)
    Coordinates:
      * time     (time) datetime64[ns] 32B 2024-01-01 ... 2024-01-01T18:00:00
      * lon      (lon) float64 640B 0.0 4.5 9.0 13.5 ... 342.0 346.5 351.0 355.5
      * lat      (lat) float64 320B 86.6 82.19 77.76 73.32 ... -77.76 -82.19 -86.6
    Attributes:
        units:    g/g


.. GENERATED FROM PYTHON SOURCE LINES 48-52 Compute turbulent air-sea fluxes without sea surface skin temperature correction using :py:func:`easyclimate.field.boundary_layer.calc_turbulent_fluxes_without_skin_correction ` (employing the NCAR parameterization scheme). Inputs include SST, 2m air temperature, specific humidity, 10m wind components, and mean sea level pressure, yielding outputs of latent heat flux (ql), sensible heat flux (qh), wind stress components (taux, tauy), and evaporation (evap) as an xarray ``Dataset``. .. GENERATED FROM PYTHON SOURCE LINES 52-68 .. code-block:: Python flux_no_skin = ecl.field.boundary_layer.calc_turbulent_fluxes_without_skin_correction( sst_data = sample_data.sst, sst_data_units = 'K', absolute_temperature_data = sample_data.t2m, absolute_temperature_data_units = 'degK', specific_humidity_data = q_data, specific_humidity_data_units = 'g/g', zonal_wind_speed_data = sample_data.u10, meridional_wind_speed_data = sample_data.v10, mean_sea_level_pressure_data = sample_data.msl, mean_sea_level_pressure_data_units = 'Pa', algorithm = 'ncar', ) flux_no_skin .. raw:: html
<xarray.Dataset> Size: 257kB
    Dimensions:  (time: 4, lon: 80, lat: 40)
    Coordinates:
      * time     (time) datetime64[ns] 32B 2024-01-01 ... 2024-01-01T18:00:00
      * lon      (lon) float64 640B 0.0 4.5 9.0 13.5 ... 342.0 346.5 351.0 355.5
      * lat      (lat) float64 320B 86.6 82.19 77.76 73.32 ... -77.76 -82.19 -86.6
    Data variables:
        ql       (time, lat, lon) float32 51kB -63.44 -62.87 -63.89 ... nan nan nan
        qh       (time, lat, lon) float32 51kB -156.2 -152.3 -153.7 ... nan nan nan
        taux     (time, lat, lon) float32 51kB 0.009611 0.003981 ... nan nan
        tauy     (time, lat, lon) float32 51kB -0.02646 -0.02885 ... nan nan
        evap     (time, lat, lon) float32 51kB -2.532e-05 -2.51e-05 ... nan nan
    Attributes:
        method:                                    aerobulk without skin correction
        algorithm:                                 ncar
        height_for_temperature_specific_humidity:  2
        height_for_wind:                           10
        iteration:                                 8


.. GENERATED FROM PYTHON SOURCE LINES 69-74 Visualize the turbulent flux results without skin correction using Cartopy and Matplotlib. A 2x2 subplot layout displays the initial time-step latent heat flux (filled contour), sensible heat flux (filled contour), wind stress vectors (Quiver plot), and evaporation (filled contour). The Plate Carrée projection is applied with coastlines and gridlines to enhance geographic referencing. .. GENERATED FROM PYTHON SOURCE LINES 74-138 .. code-block:: Python proj = ccrs.PlateCarree(central_longitude = 200) proj_trans = ccrs.PlateCarree() fig, ax = plt.subplots(2, 2, figsize = (10, 7), subplot_kw={"projection": proj}) # ----------------------------------------------- axi = ax[0, 0] draw_data = flux_no_skin["ql"].isel(time = 0) draw_data.plot.contourf( ax = axi, vmax = 600, levels = 21, transform = proj_trans, cbar_kwargs={"location": "bottom", "aspect": 50, "pad" : 0.1} ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Latent Heat Flux") # ----------------------------------------------- axi = ax[0, 1] draw_data = flux_no_skin["qh"].isel(time = 0) draw_data.plot.contourf( ax = axi, vmax = 200, levels = 21, transform = proj_trans, cbar_kwargs={"location": "bottom", "aspect": 50, "pad" : 0.1} ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Sensible Heat Flux") # ----------------------------------------------- axi = ax[1, 0] draw_data = flux_no_skin[["taux", "tauy"]].isel(time = 0) draw_data.plot.quiver( x = "lon", y = "lat", u = "taux", v = "tauy", transform = proj_trans, ax = axi, ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Zonal/Meridional wind stress") # ----------------------------------------------- axi = ax[1, 1] draw_data = flux_no_skin["evap"].isel(time = 0) draw_data.plot.contourf( ax = axi, vmax = 0.0002, levels = 21, transform = proj_trans, cbar_kwargs={"location": "bottom", "aspect": 50, "pad" : 0.1} ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Evaporation") # ----------------------------------------------- fig.suptitle("Flux no skin", size = 20) .. image-sg:: /auto_gallery/images/sphx_glr_plot_aerobulk_001.png :alt: Flux no skin, Latent Heat Flux, Sensible Heat Flux, Zonal/Meridional wind stress, Evaporation :srcset: /auto_gallery/images/sphx_glr_plot_aerobulk_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 0.98, 'Flux no skin') .. GENERATED FROM PYTHON SOURCE LINES 139-152 Compute turbulent air-sea fluxes with sea surface skin temperature correction using :py:func:`easyclimate.field.boundary_layer.calc_turbulent_fluxes_skin_correction ` (utilizing the COARE3.0 parameterization scheme). In addition to base inputs, time-normalized (divided by 3600 seconds) downwelling shortwave and longwave radiation fluxes (converted to :math:`\mathrm{W/m^2}`) are included to account for sea surface skin temperature effects, yielding an xarray Dataset of corrected fluxes. .. warning:: For the ERA5 reanalysis, the processing period is over the 1 hour ending at the validity date and time. To convert to watts per square metre ( :math:`\mathrm{W/m^2}` ), the accumulated values should be divided by the accumulation period expressed in seconds. .. GENERATED FROM PYTHON SOURCE LINES 152-172 .. code-block:: Python flux_skin = ecl.field.boundary_layer.calc_turbulent_fluxes_skin_correction( sst_data = sample_data.sst, sst_data_units = 'K', absolute_temperature_data = sample_data.t2m, absolute_temperature_data_units = 'degK', specific_humidity_data = q_data, specific_humidity_data_units = 'g/g', zonal_wind_speed_data = sample_data.u10, meridional_wind_speed_data = sample_data.v10, mean_sea_level_pressure_data = sample_data.msl, mean_sea_level_pressure_data_units = 'Pa', downwelling_shortwave_radiation = sample_data.ssrd/(3600), downwelling_shortwave_radiation_units = "W/m^2", downwelling_longwave_radiation = sample_data.ssrd/(3600), downwelling_longwave_radiation_units = "W/m^2", algorithm = 'coare3p0', ) flux_skin .. rst-class:: sphx-glr-script-out .. code-block:: none /home/runner/work/easyclimate/easyclimate/src/easyclimate/field/boundary_layer/aerobulk.py:151: UserWarning: The varable rad_lw of values 1189.8050537109375 is beyond [0, 750]。 warnings.warn( .. raw:: html
<xarray.Dataset> Size: 615kB
    Dimensions:  (time: 4, lon: 80, lat: 40)
    Coordinates:
      * time     (time) datetime64[ns] 32B 2024-01-01 ... 2024-01-01T18:00:00
      * lon      (lon) float64 640B 0.0 4.5 9.0 13.5 ... 342.0 346.5 351.0 355.5
      * lat      (lat) float64 320B 86.6 82.19 77.76 73.32 ... -77.76 -82.19 -86.6
    Data variables:
        ql       (time, lat, lon) float64 102kB -60.25 -59.51 -60.23 ... nan nan nan
        qh       (time, lat, lon) float64 102kB -166.4 -161.4 -161.9 ... nan nan nan
        taux     (time, lat, lon) float64 102kB 0.009765 0.004058 ... nan nan
        tauy     (time, lat, lon) float64 102kB -0.02688 -0.02941 ... nan nan
        t_s      (time, lat, lon) float64 102kB 270.5 270.5 270.5 ... nan nan nan
        evap     (time, lat, lon) float64 102kB -2.403e-05 -2.374e-05 ... nan nan
    Attributes:
        method:                                    aerobulk with skin correction
        algorithm:                                 coare3p0
        height_for_temperature_specific_humidity:  2
        height_for_wind:                           10
        iteration:                                 8


.. GENERATED FROM PYTHON SOURCE LINES 173-178 Visualize the turbulent flux results with skin correction, maintaining the same 2x2 subplot layout and visualization parameters (projection, contour ranges, coastlines, etc.) as the non-skin-corrected plots to facilitate direct comparison of the impacts of skin temperature correction on latent heat flux, sensible heat flux, wind stress, and evaporation. .. GENERATED FROM PYTHON SOURCE LINES 178-240 .. code-block:: Python proj = ccrs.PlateCarree(central_longitude = 200) proj_trans = ccrs.PlateCarree() fig, ax = plt.subplots(2, 2, figsize = (10, 7), subplot_kw={"projection": proj}) # ----------------------------------------------- axi = ax[0, 0] draw_data = flux_skin["ql"].isel(time = 0) draw_data.plot.contourf( ax = axi, vmax = 600, levels = 21, transform = proj_trans, cbar_kwargs={"location": "bottom", "aspect": 50, "pad" : 0.1} ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Latent Heat Flux") # ----------------------------------------------- axi = ax[0, 1] draw_data = flux_skin["qh"].isel(time = 0) draw_data.plot.contourf( ax = axi, vmax = 200, levels = 21, transform = proj_trans, cbar_kwargs={"location": "bottom", "aspect": 50, "pad" : 0.1} ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Sensible Heat Flux") # ----------------------------------------------- axi = ax[1, 0] draw_data = flux_skin[["taux", "tauy"]].isel(time = 0) draw_data.plot.quiver( x = "lon", y = "lat", u = "taux", v = "tauy", transform = proj_trans, ax = axi, ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Zonal/Meridional wind stress") # ----------------------------------------------- axi = ax[1, 1] draw_data = flux_skin["evap"].isel(time = 0) draw_data.plot.contourf( ax = axi, vmax = 0.0002, levels = 21, transform = proj_trans, cbar_kwargs={"location": "bottom", "aspect": 50, "pad" : 0.1} ) axi.coastlines() axi.gridlines(draw_labels=["left", "bottom"], color="grey", alpha=0.5, linestyle="--") axi.set_title("Evaporation") # ----------------------------------------------- fig.suptitle("Flux skin", size = 20) .. image-sg:: /auto_gallery/images/sphx_glr_plot_aerobulk_002.png :alt: Flux skin, Latent Heat Flux, Sensible Heat Flux, Zonal/Meridional wind stress, Evaporation :srcset: /auto_gallery/images/sphx_glr_plot_aerobulk_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 0.98, 'Flux skin') .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 12.278 seconds) .. _sphx_glr_download_auto_gallery_plot_aerobulk.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_aerobulk.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_aerobulk.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_aerobulk.zip `