Ocean Surface Mixed Layers Analysis#

Before proceeding with all the steps, first import some necessary libraries and packages

import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
import easyclimate as ecl

Preprocessed data

temper_data = xr.open_dataset('temp_soda3.4.2_mn_ocean_reg_2020_EN4.nc', chunks="auto").temp.rename({'st_ocean': 'depth'})
slt_data = xr.open_dataset('salt_soda3.4.2_mn_ocean_reg_2020_EN4.nc', chunks="auto").salt.rename({'st_ocean': 'depth'})

u_data = xr.open_dataset('u_soda3.4.2_mn_ocean_reg_2020_EN4.nc', chunks="auto").u.rename({'st_ocean': 'depth'})
v_data = xr.open_dataset('v_soda3.4.2_mn_ocean_reg_2020_EN4.nc', chunks="auto").v.rename({'st_ocean': 'depth'})
net_heating_data = xr.open_dataset('net_heating_soda3.4.2_mn_ocean_reg_2020_EN4.nc', chunks="auto").net_heating

wt_data = xr.open_dataset('wt_soda3.4.2_mn_ocean_reg_2020_EN4.nc', chunks="auto").wt.rename({'sw_ocean': 'depth'})

The following data is the depth data of the mixed layer output by the oceanic models (we will compare it with it later).

mld_data = xr.open_dataset('mlp_soda3.4.2_mn_ocean_reg_2020_EN4.nc', chunks="auto").mlp

Warning

Mix-Layer Depth#

Here, we use easyclimate.field.ocean.calc_mixed_layer_depth to calculate the depth of mix-layer (MLD).

mixed_layer_depth = ecl.field.ocean.calc_mixed_layer_depth(
    seawater_temperature_data = temper_data,
    seawater_practical_salinity_data = slt_data,
).to_netcdf("sample_mixed_layer_depth.nc")

Next, we open the dataset containing the results

mixed_layer_depth = xr.open_dataarray("sample_mixed_layer_depth.nc")
mixed_layer_depth
<xarray.DataArray 'mixed_layer_depth' (time: 12, lat: 173, lon: 360)> Size: 6MB
[747360 values with dtype=float64]
Coordinates:
  * lat      (lat) float32 692B -83.0 -82.0 -81.0 -80.0 ... 86.0 87.0 88.0 89.0
  * lon      (lon) float32 1kB 1.0 2.0 3.0 4.0 5.0 ... 357.0 358.0 359.0 360.0
  * time     (time) datetime64[ns] 96B 2020-01-16T01:00:00 ... 2020-12-13T13:...


Draw the figure of mix-layer depth

fig, ax = ecl.plot.quick_draw_spatial_basemap()

mixed_layer_depth.isel(time = 0).plot(
    vmax = 300,
    cmap = "viridis_r",
    cbar_kwargs = {'location': 'bottom'},
)
ax.set_title("Mixed Layer Depth (Jan., 2021)")
Mixed Layer Depth (Jan., 2021)
Text(0.5, 1.0, 'Mixed Layer Depth (Jan., 2021)')

Compare with the depth data of the mixed layer output by the oceanic models

fig, ax = ecl.plot.quick_draw_spatial_basemap()
diff = mld_data.isel(time = 0) - mixed_layer_depth.isel(time = 0)
diff.plot(
    vmax = 200,
    cbar_kwargs = {'location': 'bottom', 'label': 'units: m'},
)
ax.set_title("SODA minus Easyclimate (pyoceans)")
SODA minus Easyclimate (pyoceans)
Text(0.5, 1.0, 'SODA minus Easyclimate (pyoceans)')

MLD Internal Temperature#

We use easyclimate.field.ocean.get_temper_within_MLD to receive MLD internal temperature.

mld_t = ecl.field.ocean.get_temper_within_MLD(
    seawater_temperature_data = temper_data,
    mixed_layer_depth = mld_data,
).to_netcdf("sample_mld_t.nc")

Next, we open the dataset containing the results

mld_t = xr.open_dataarray("sample_mld_t.nc")
mld_t
<xarray.DataArray 'temp' (time: 12, depth: 50, lat: 173, lon: 360)> Size: 149MB
[37368000 values with dtype=float32]
Coordinates:
  * time     (time) datetime64[ns] 96B 2020-01-16T01:00:00 ... 2020-12-13T13:...
  * lon      (lon) float32 1kB 1.0 2.0 3.0 4.0 5.0 ... 357.0 358.0 359.0 360.0
  * lat      (lat) float32 692B -83.0 -82.0 -81.0 -80.0 ... 86.0 87.0 88.0 89.0
  * depth    (depth) float64 400B 5.034 15.1 25.22 ... 5.185e+03 5.395e+03
Attributes:
    standard_name:  sea_water_potential_temperature
    long_name:      Potential temperature
    units:          degrees C
    cell_methods:   time: mean
    time_avg_info:  average_T1,average_T2,average_DT


Now, Plotting the temperature of a marine model layer within a mixed layer

ax = plt.figure().add_subplot(projection='3d')

for depth_value in np.arange(50):
    mld_t.isel(time = 5).sel(lon = slice(160, 180), lat = slice(-10, 10)).isel(depth = depth_value).plot.surface(
        alpha=0.3,
    )
time = 2020-06-14T01:00:00, depth = 5.395e+03 [...

MLD Internal Average Temperature#

We use easyclimate.field.ocean.calc_MLD_depth_weighted to calculate MLD internal average temperature.

weight = ecl.field.ocean.calc_MLD_depth_weighted(
    seawater_temperature_data = temper_data,
    mixed_layer_depth = mld_data
)

mld_t_ave = ecl.field.ocean.get_data_average_within_MLD(
    data_input = temper_data,
    mixed_layer_depth = mld_data,
    depth_weight = weight
).to_netcdf("sample_mld_t_ave.nc")

Warning

You can NOT use above result (i.e., mld_t) to directly calculate MLD internal average temperature by mld_t.mean(dim = "depth"), because the vertical layers in ocean models are usually not uniformly distributed.

Next, we open the dataset containing the results

mld_t_ave = xr.open_dataarray("sample_mld_t_ave.nc")
mld_t_ave
<xarray.DataArray (time: 12, lat: 173, lon: 360)> Size: 6MB
[747360 values with dtype=float64]
Coordinates:
  * time     (time) datetime64[ns] 96B 2020-01-16T01:00:00 ... 2020-12-13T13:...
  * lon      (lon) float32 1kB 1.0 2.0 3.0 4.0 5.0 ... 357.0 358.0 359.0 360.0
  * lat      (lat) float32 692B -83.0 -82.0 -81.0 -80.0 ... 86.0 87.0 88.0 89.0
Attributes:
    standard_name:  sea_water_potential_temperature
    long_name:      Potential temperature
    units:          degrees C
    cell_methods:   time: mean
    time_avg_info:  average_T1,average_T2,average_DT


Now, Plotting the MLD internal average temperature

fig, ax = ecl.plot.quick_draw_spatial_basemap()

mld_t_ave.isel(time = 0).plot.contourf(
    levels = 21,
    cbar_kwargs = {'location': 'bottom', 'label': 'degC'},
)
ax.set_title("Mixed Layer Temperature (Jan., 2021)")
Mixed Layer Temperature (Jan., 2021)
Text(0.5, 1.0, 'Mixed Layer Temperature (Jan., 2021)')

MLD Average Temperature Tendency#

We use easyclimate.field.ocean.calc_MLD_temper_tendency to calculate MLD internal average temperature tendency.

weight = ecl.field.ocean.calc_MLD_depth_weighted(
    seawater_temperature_data = temper_data,
    mixed_layer_depth = mld_data
)

mld_t_tendency = ecl.field.ocean.calc_MLD_temper_tendency(
    seawater_temperature_anomaly_data = temper_data,
    mixed_layer_depth = mld_data,
    depth_weight = weight
).to_netcdf("sample_mld_t_tendency.nc")
mld_t_tendency = xr.open_dataarray("sample_mld_t_tendency.nc")
mld_t_tendency
<xarray.DataArray (time: 12, lat: 173, lon: 360)> Size: 6MB
[747360 values with dtype=float64]
Coordinates:
  * time     (time) datetime64[ns] 96B 2020-01-16T01:00:00 ... 2020-12-13T13:...
  * lon      (lon) float32 1kB 1.0 2.0 3.0 4.0 5.0 ... 357.0 358.0 359.0 360.0
  * lat      (lat) float32 692B -83.0 -82.0 -81.0 -80.0 ... 86.0 87.0 88.0 89.0
Attributes:
    standard_name:  sea_water_potential_temperature
    long_name:      Potential temperature
    units:          degrees C
    cell_methods:   time: mean
    time_avg_info:  average_T1,average_T2,average_DT


Now, Plotting the result.

fig, ax = ecl.plot.quick_draw_spatial_basemap()

mld_t_tendency.isel(time = 5).plot.contourf(
    vmax = 8,
    levels = 21,
    cbar_kwargs = {'location': 'bottom'},
)
ax.set_title("Mixed Layer Temperature Tendency (Jun., 2021)")
Mixed Layer Temperature Tendency (Jun., 2021)
Text(0.5, 1.0, 'Mixed Layer Temperature Tendency (Jun., 2021)')

MLD Average Horizontal Advection#

We use easyclimate.field.ocean.calc_MLD_average_horizontal_advection to calculate MLD average horizontal advection.

weight = ecl.field.ocean.calc_MLD_depth_weighted(
    seawater_temperature_data = temper_data,
    mixed_layer_depth = mld_data
)

mld_horizontal_advection = ecl.field.ocean.calc_MLD_average_horizontal_advection(
    u_monthly_data = u_data,
    v_monthly_data = v_data,
    seawater_temperature_data = temper_data,
    mixed_layer_depth = mld_data,
    depth_weight = weight
).to_netcdf("sample_mld_horizontal_advection.nc")
mld_horizontal_advection = xr.open_dataset("sample_mld_horizontal_advection.nc")

Now, Plotting the result for zonal advection.

fig, ax = ecl.plot.quick_draw_spatial_basemap()

mld_horizontal_advection["u_advection"].isel(time = 5).plot(
    vmax = 2,
    levels = 21,
    cbar_kwargs = {'location': 'bottom'},
)
ax.set_title("Mixed Layer U advection (Jun., 2021)")
Mixed Layer U advection (Jun., 2021)
Text(0.5, 1.0, 'Mixed Layer U advection (Jun., 2021)')

And meridional advection.

fig, ax = ecl.plot.quick_draw_spatial_basemap()

mld_horizontal_advection["v_advection"].isel(time = 5).plot(
    vmax = 2,
    levels = 21,
    cbar_kwargs = {'location': 'bottom'},
)
ax.set_title("Mixed Layer V advection (Jun., 2021)")
Mixed Layer V advection (Jun., 2021)
Text(0.5, 1.0, 'Mixed Layer V advection (Jun., 2021)')

MLD Average Vertical Advection#

We use easyclimate.field.ocean.calc_MLD_average_vertical_advection to calculate MLD average vertical advection.

weight = ecl.field.ocean.calc_MLD_depth_weighted(
    seawater_temperature_data = temper_data,
    mixed_layer_depth = mld_data
)

mld_vertical_advection = ecl.field.ocean.calc_MLD_average_vertical_advection(
    w_monthly_data = wt_data,
    seawater_temperature_data = temper_data,
    mixed_layer_depth = mld_data,
    depth_weight = weight
).to_netcdf("sample_mld_vertical_advection.nc")
mld_vertical_advection = xr.open_dataarray("sample_mld_vertical_advection.nc")
mld_vertical_advection
<xarray.DataArray (time: 12, lat: 173, lon: 360)> Size: 6MB
[747360 values with dtype=float64]
Coordinates:
  * time     (time) datetime64[ns] 96B 2020-01-16T01:00:00 ... 2020-12-13T13:...
  * lon      (lon) float32 1kB 1.0 2.0 3.0 4.0 5.0 ... 357.0 358.0 359.0 360.0
  * lat      (lat) float32 692B -83.0 -82.0 -81.0 -80.0 ... 86.0 87.0 88.0 89.0
Attributes:
    long_name:      dia-surface velocity T-points
    units:          m/sec
    cell_methods:   time: mean
    time_avg_info:  average_T1,average_T2,average_DT


Now, Plotting the result.

fig, ax = ecl.plot.quick_draw_spatial_basemap()

mld_vertical_advection.isel(time = 5).plot(
    vmax = 2,
    levels = 21,
    cbar_kwargs = {'location': 'bottom'},
)
ax.set_title("Mixed Layer vertical advection (Jun., 2021)")
Mixed Layer vertical advection (Jun., 2021)
Text(0.5, 1.0, 'Mixed Layer vertical advection (Jun., 2021)')

Surface Heat Flux#

We use easyclimate.field.ocean.calc_ocean_surface_heat_flux to calculate ocean surface heat flux.

surface_heat_flux = ecl.field.ocean.calc_ocean_surface_heat_flux(
    qnet_monthly_anomaly_data = net_heating_data,
    mixed_layer_depth = mld_data,
).to_netcdf("sample_surface_heat_flux.nc")
surface_heat_flux = xr.open_dataarray("sample_surface_heat_flux.nc")
surface_heat_flux
<xarray.DataArray (time: 12, lat: 173, lon: 360)> Size: 6MB
[747360 values with dtype=float64]
Coordinates:
  * time     (time) datetime64[ns] 96B 2020-01-16T01:00:00 ... 2020-12-13T13:...
  * lon      (lon) float32 1kB 1.0 2.0 3.0 4.0 5.0 ... 357.0 358.0 359.0 360.0
  * lat      (lat) float32 692B -83.0 -82.0 -81.0 -80.0 ... 86.0 87.0 88.0 89.0
Attributes:
    long_name:      surface ocean heat flux coming through coupler and mass t...
    units:          Watts/m^2
    cell_methods:   time: mean
    time_avg_info:  average_T1,average_T2,average_DT


Now, Plotting the result.

fig, ax = ecl.plot.quick_draw_spatial_basemap()

surface_heat_flux.isel(time = 5).plot(
    vmax = 10,
    levels = 21,
    cbar_kwargs = {'location': 'bottom'},
)
ax.set_title("Surface Heat Flux (Jun., 2021)")
Surface Heat Flux (Jun., 2021)
Text(0.5, 1.0, 'Surface Heat Flux (Jun., 2021)')

Total running time of the script: (0 minutes 26.382 seconds)