-
Notifications
You must be signed in to change notification settings - Fork 21
Description
Hi!
I am using the ECCO v4r4 product and realized that the bolus velocity is not purely divergent-free. I think this is the repo that hosts the code that is responsible for converting GMPsiX and GMPsiY to UVELSTAR, VVELSTAR, WVELSTAR (https://github.com/MITgcm/gcmfaces/blob/master/gcmfaces_calc/calc_bolus.m#L1).
The finite divergence appears at grids that have exactly 2 layers in depth around land boundaries, and it only appears in the first two layers. This is what the convergence of bolus velocity looks like:

Here is my code to go from downloading to producing the above plot. (Excuse me for not able to write in MATLAB)
# Download one daily mean data
# !wget https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/ECCO_L4_BOLUS_LLC0090GRID_DAILY_V4R4/OCEAN_BOLUS_VELOCITY_day_mean_1992-01-01_ECCO_V4r4_native_llc0090.nc
import xarray as xr
import numpy as np
import xgcm
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
grd = xr.open_dataset('~/ECCO-grid/ECCO-GRID.nc')
bolus = xr.open_dataset('OCEAN_BOLUS_VELOCITY_day_mean_1992-01-01_ECCO_V4r4_native_llc0090.nc')
ds = xr.merge([bolus,grd])
# Calculate the transport
# NaN means no transport across rocks, fill them as 0
ds['utrans'] = (ds['UVELSTAR']*ds['drF']*ds['dyG']).fillna(0)
ds['vtrans'] = (ds['VVELSTAR']*ds['drF']*ds['dxG']).fillna(0)
ds['wtrans'] = (ds['WVELSTAR']*ds['rA']).fillna(0)
# Creating the xgcm object for the divergence calculation
face_connections = {
"tile": {
0: {"i": ((12, "j", False), (3, "i", False)), "j": (None, (1, "j", False))},
1: {"i": ((11, "j", False), (4, "i", False)),"j": ((0, "j", False), (2, "j", False))},
2: {"i": ((10, "j", False), (5, "i", False)),"j": ((1, "j", False), (6, "i", False))},
3: {"i": ((0, "i", False), (9, "j", False)), "j": (None, (4, "j", False))},
4: {"i": ((1, "i", False), (8, "j", False)),"j": ((3, "j", False), (5, "j", False))},
5: {"i": ((2, "i", False), (7, "j", False)),"j": ((4, "j", False), (6, "j", False))},
6: {"i": ((2, "j", False), (7, "i", False)),"j": ((5, "j", False), (10, "i", False)),},
7: {"i": ((6, "i", False), (8, "i", False)),"j": ((5, "i", False), (10, "j", False)),},
8: {"i": ((7, "i", False), (9, "i", False)),"j": ((4, "i", False), (11, "j", False)),},
9: {"i": ((8, "i", False), None), "j": ((3, "i", False), (12, "j", False))},
10: {"i": ((6, "j", False), (11, "i", False)),"j": ((7, "j", False), (2, "i", False))},
11: {"i": ((10, "i", False), (12, "i", False)),"j": ((8, "j", False), (1, "i", False))},
12: {"i": ((11, "i", False), None),"j": ((9, "j", False), (0, "i", False))},
}
}
xgcmgrd = xgcm.Grid(
ds,
periodic=False,
face_connections=face_connections,
coords={
"i": {"center": "i", "left": "i_g"},
"j": {"center": "j", "left": "j_g"},
"k": {"center": "k", "left": "k_l"},
},
)
# Calculating the derivative (actually convergence)
xy_diff = xgcmgrd.diff_2d_vector(
{"i": ds['utrans'], "j": ds['vtrans']}, boundary="fill", fill_value=0.0
)
x_diff = xy_diff["i"]
y_diff = xy_diff["j"]
hConv = -(x_diff + y_diff)
vConv = xgcmgrd.diff(ds['wtrans'], "k", boundary="fill", fill_value=0.0)
# Combine the convergences and get rid of the time dimension
conv = (hConv+vConv).squeeze()
# Plot the convergence in face 10 of the second level (k = 1)
ax = plt.axes(projection = ccrs.PlateCarree())
ct = ax.pcolormesh(ds.XC[10],ds.YC[10],conv[1,10])
ax.coastlines()
plt.colorbar(ct)
For comparison, the divergence should be many orders of magnitude smaller. Here is what it looks like in the third layer.
The code for reproducing this is:
# Plot the convergence for the level beneath it.
ax = plt.axes(projection = ccrs.PlateCarree())
ct = ax.pcolormesh(ds.XC[10],ds.YC[10],conv[2,10])
ax.coastlines()
plt.colorbar(ct)
Although I don't know how to write MATLAB, please let me know how I can help.
