In [1]:
'''
Test to integrate XAD quantities in NEMO from coastline
After discussion with Sarah Wakelin
'''
Out[1]:
In [2]:
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')
In [3]:
import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import matplotlib.colors as colors
%matplotlib inline
import math
In [4]:
%ls c:\Users\tams00\Documents\nerc_ssb\c_fluxes\AMM7-HINDCAST-v0-erosion\1981\01\
In [5]:
modelpaths='c:/Users/tams00/Documents/nerc_ssb/c_fluxes/AMM7-HINDCAST-v0-erosion/1981/01/amm7_1m_19810101_19810131_grid_T.nc'
modelpaths='c:/Users/tams00/Documents/nerc_ssb/selected_outputs/amm7_1d_20050501_20050531_grid_T_time_counter0.nc'
bathy_path='c:/Users/tams00/Documents/nerc_ssb/selected_outputs/bathy_meter.nc'
xadv_3d='XAD_O3_c_e3t'
yadv_3d='YAD_O3_c_e3t'
bathy = xr.open_dataset(bathy_path)['Bathymetry'].squeeze()
modelout = xr.open_mfdataset([modelpaths])
modelout;
In [6]:
def is_land(bathy,row,col):
if math.isclose(bathy.values[row,col], 0.0):
return True
else:
return False
In [7]:
# integrate varArr from row,col in the given direction
# and save in intArr
#
# XAD[r,c] = adv_x[r,c+1] - adv_x[r,c] (tested empirically in embayment case)
# adv_x[r,c] = adv_x[r,c+1] - XAD[r,c] use when going west
# adv_x[r,c+1] = XAD[r,c] + adv_x[r,c] use when going east
#
# NOTE: imshow shows geographic array upside down
# YAD[r,c] = adv_y[r+1,c] - adv_y[r,c] (tested empirically in embayment case)
# adv_x[r,c] = adv_x[r+1,c] - YAD[r,c] use when going south
# adv_x[r+1,c] = YAD[r,c] + adv_x[r,c] use when going north
# Corrected Arakawa C indexing in NEMO
# https://www.nemo-ocean.eu/wp-content/uploads/NEMO_book.pdf pp.54
#
# V
# _
# j T |U
# i
#
# XAD[r,c] = adv_x[r,c] - adv_x[r,c-1]
# adv_x[r,c] = adv_x[r,c-1] + XAD[r,c] use when going east
# adv_x[r,c] = adv_x[r,c+1] - XAD[r,c+1] use when going west
#
# YAD[r,c] = adv_y[r,c] - adv_y[r-1,c]
# adv_y[r,c] = adv_y[r-1,c] + YAD[r,c] use when going north
# adv_y[r,c] = adv_y[r+1,c] - YAD[r+1,c] use when going south
# S.W.: as below, which results in opposite direction (postive right and up?)
# YAD[r,c] = adv_y[r-1,c] - adv_y[r,c]
# adv_y[r,c] = adv_y[r-1,c] - YAD[r,c] use when going north
# adv_y[r,c] = adv_y[r+1,c] + YAD[r+1,c] use when going south
def integrate_vector(varArr, intArr, bathy, row,col,direction):
#print('integrate ',row,col,direction)
[rows,cols]=varArr.shape
if direction=='west':
for c in range(col,0,-1):
if is_land(bathy,row,c):
break
if not(math.isclose( intArr[row,c],0. )):
#print("Break in integrate west. Already integrated east!",row,c)
break
# Eastern open boundary
if ( c == cols-2 ):
intArr[row,c] = +1 * varArr[row,c]
else:
intArr[row,c] = intArr[row,c+1] - varArr[row,c+1]
#print('west',row,c,varArr[row,c+1],intArr[row,c])
#print(row,c,intArr[row,c])
if direction=='east':
for c in range(col,cols-1):
if is_land(bathy,row,c):
break
# Western open boundary
if ( c == 1 ):
intArr[row,c] = +1 * varArr[row,c]
else:
intArr[row,c] = varArr[row,c] + intArr[row,c-1]
#print('east',row,c,varArr[row,c],intArr[row,c])
#print(row,c,intArr[row,c])
if direction=='south':
for r in range(row,0,-1):
if is_land(bathy,r,col):
break
if not(math.isclose( intArr[r,col],0. )):
#print("Break in integrate south. Already integrated north!",r,col)
break
# Northern open boundary
if ( r == rows-2 ):
intArr[r,col] = +1 * varArr[r,col]
else:
intArr[r,col] = intArr[r+1,col] - varArr[r+1,col]
#print('south adv-YAD=adv',r,col,intArr[r+1,col],varArr[r+1,col],intArr[r,col],is_land(bathy,r,col),bathy[r,col])
#print(r,col,intArr[r,col])
if direction=='north':
for r in range(row,rows-1):
if is_land(bathy,r,col):
break
# Southern open boundary
if ( r == 1 ):
intArr[r,col] = +1 * varArr[r,col]
else:
intArr[r,col] = varArr[r,col] + intArr[r-1,col]
#print('north',r,col,varArr[r,col],intArr[r,col])
#print(r,col,intArr[r,col])
return intArr
In [8]:
def integrate_xadv(varArr,bathy):
# for XAD
[rows,cols]=varArr.shape
horArr=np.zeros([rows,cols])
for row in range(1,rows-1):
for col in range(1,cols-1):
#print(row,col,varArr[row,col])
# W coast
if ( not(is_land(bathy,row,col)) and is_land(bathy,row,col+1) ):
horArr=integrate_vector(varArr,horArr,bathy,row,col,'west')
# E coast
elif ( is_land(bathy,row,col) and not(is_land(bathy,row,col+1)) ):
horArr=integrate_vector(varArr,horArr,bathy,row,col+1,'east')
# Second passage uses boundary flux as reference
#print(' Second passage using boundary as reference')
# This is only used where there are no coastal reference as
# the error is larger
for col in [1,cols-2]:
for row in range(1,rows-1):
#print('2nd- ',rows,cols,row,col)
# Open Western boundary
if (( col == 1 ) and not(is_land(bathy,row,col))):
#pass
horArr=integrate_vector(varArr,horArr,bathy,row,col,'north')
# Open Eastern boundary
elif (( col == cols-2 ) and not(is_land(bathy,row,col))):
horArr=integrate_vector(varArr,horArr,bathy,row,col,'south')
return horArr
In [9]:
def integrate_yadv(varArr,bathy):
# for YAD
[rows,cols]=varArr.shape
#print('inegrate_yadv,rows,cols',rows,cols)
verArr=np.zeros([rows,cols])
# First passage uses coastal zero flux as reference
# Does't visit last row or col due to the way it checks coastlines
for row in range(1,rows-1):
for col in range(1,cols-1):
#print('1st- ',rows,cols,row,col)
# N coast
if ( not(is_land(bathy,row,col)) and is_land(bathy,row+1,col) ):
verArr=integrate_vector(varArr,verArr,bathy,row,col,'south')
# S coast
elif ( is_land(bathy,row,col) and not(is_land(bathy,row+1,col)) ):
verArr=integrate_vector(varArr,verArr,bathy,row+1,col,'north')
#print(' Second passage using boundary as reference')
# Second passage uses boundary flux as reference
# This is only used where there are no coastal reference as
# the error is larger
for row in [1,rows-2]:
for col in range(1,cols-1):
#print('2nd- ',rows,cols,row,col)
# Open Southern boundary
if (( row == 1 ) and not(is_land(bathy,row,col))):
#pass
verArr=integrate_vector(varArr,verArr,bathy,row,col,'north')
elif (( row == rows-2 ) and not(is_land(bathy,row,col))):
verArr=integrate_vector(varArr,verArr,bathy,row,col,'south')
return verArr
In [11]:
varDA=modelout[yadv_3d]
#varDA=modelout[test_2d]
# Test off Portuguese coast
varArr=varDA.values[0,0,367:,52:58].squeeze()
bath=bathy[367:,52:58]
print(varArr.shape)
verArr= integrate_yadv(varArr,bath)
# plot YAD
fig,axs = plt.subplots(1,3,figsize=(12,6),squeeze=False)
plt0 = axs[0,0].imshow(~(bath>0),origin='lower')
axs[0,0].set_title('land')
plt.colorbar(plt0,ax=axs[0,0])
plt1 = axs[0,1].imshow(varArr,origin='lower')
axs[0,1].set_title('YAD')
plt.colorbar(plt1, ax=axs[0,1])
plt2 = axs[0,2].imshow(verArr,origin='lower')
axs[0,2].set_title('adv tracer')
plt.colorbar(plt2,ax=axs[0,2])
#axs[0,0].colorbar()
#print(bath)
#print('YAD')
#print(varArr[:,:])
#print('y adv')
#print(verArr[:,:])
Out[11]:
In [14]:
varDA=modelout[yadv_3d]
#varDA=modelout[test_2d]
# Test off Portuguese coast
varArr=varDA.values[0,0,0:5,98:104].squeeze()
bath=bathy[0:5,98:104]
print(varArr.shape)
verArr= integrate_yadv(varArr,bath)
# plot YAD
fig,axs = plt.subplots(1,3,figsize=(12,6),squeeze=False)
plt0 = axs[0,0].imshow(~(bath>0),origin='lower')
axs[0,0].set_title('land')
plt.colorbar(plt0,ax=axs[0,0])
plt1 = axs[0,1].imshow(varArr,origin='lower')
axs[0,1].set_title('YAD')
plt.colorbar(plt1, ax=axs[0,1])
plt2 = axs[0,2].imshow(verArr,origin='lower')
axs[0,2].set_title('adv tracer')
plt.colorbar(plt2,ax=axs[0,2])
#axs[0,0].colorbar()
#print(bath)
#print('YAD')
#print(varArr[:,:])
#print('y adv')
#print(verArr[:,:])
# there is an error 1000x below value of fluxa
Out[14]:
In [15]:
varDA=modelout[xadv_3d]
#varDA=modelout[test_2d]
# test small embayment
varArr=varDA.values[0,0,208:212,149:154].squeeze()
bath=bathy[208:212,149:154]
# Test off Portuguese coast
#varArr=varDA.values[0,0,0:50,70:120].squeeze()
print(varArr.shape)
horArr = integrate_xadv(varArr,bath)
fig,axs = plt.subplots(1,3,figsize=(12,6),squeeze=False)
plt0 = axs[0,0].imshow(~(bath>0),origin='lower')
axs[0,0].set_title('land')
plt.colorbar(plt0,ax=axs[0,0])
plt1 = axs[0,1].imshow(varArr,origin='lower')
axs[0,1].set_title('XAD')
plt.colorbar(plt1, ax=axs[0,1])
plt2 = axs[0,2].imshow(horArr,origin='lower')
axs[0,2].set_title('adv tracer')
plt.colorbar(plt2,ax=axs[0,2])
#axs[0,0].colorbar()
#print(varArr[:,:])
#print(horArr[:,:])
# there is an error 1000x below value of flux
Out[15]:
In [18]:
varDA=modelout[yadv_3d]
#varDA=modelout[test_2d]
# test small embayment
varArr=varDA.values[0,0,208:212,149:154].squeeze()
bath=bathy[208:212,149:154]
# Test off Portuguese coast
#varArr=varDA.values[0,0,0:50,70:120].squeeze()
print(varArr.shape)
verArr = integrate_yadv(varArr,bath)
# plot YAD
fig,axs = plt.subplots(1,3,figsize=(12,6),squeeze=False)
plt0 = axs[0,0].imshow(~(bath>0))
axs[0,0].set_title('land')
plt.colorbar(plt0,ax=axs[0,0])
plt1 = axs[0,1].imshow(varArr)
axs[0,1].set_title('YAD')
plt.colorbar(plt1, ax=axs[0,1])
plt2 = axs[0,2].imshow(verArr)
axs[0,2].set_title('adv tracer')
plt.colorbar(plt2,ax=axs[0,2])
#axs[0,0].colorbar()
#print(varArr[:,:])
#print(verArr[:,:])
# there is an error 1000x below value of flux
Out[18]:
In [19]:
varDA=modelout[xadv_3d]
#varDA=modelout[test_2d]
varArr=varDA.values[0,0,:,:].squeeze()
horArr = integrate_xadv(varArr,bathy)
varDA=modelout[yadv_3d]
varArr=varDA.values[0,0,:,:].squeeze()
verArr = integrate_yadv(varArr,bathy)
print(varArr.shape)
In [20]:
fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(12,12))
lim1=max(abs(np.array([verArr.max(),verArr.min(),horArr.max(),horArr.min()])))/5
lim2=max(abs(np.array([modelout[xadv_3d][0,0,:,:].max(),modelout[xadv_3d][0,0,:,:].min()])))/2
#axs[0,0].imshow(np.log10(bathy))
axs[0,0].imshow(np.log10(bathy),origin='lower')
axs[0,0].set_title('bathymetry from bathy_meter.nc')
im = axs[0,1].imshow(horArr,origin='lower',vmax=lim1,vmin=-1*lim1,cmap='seismic')
axs[0,1].set_title('abs. hor. advection')
fig.colorbar(im, ax=axs[0,1])
im = axs[1,1].imshow(modelout[xadv_3d][0,0,:,:],origin='lower',vmax=lim2,vmin=-1*lim2,cmap='seismic')
axs[1,1].set_title(xadv_3d)
fig.colorbar(im, ax=axs[1,1])
im = axs[0,2].imshow(verArr,origin='lower',vmax=lim1,vmin=-1*lim1,cmap='seismic')
axs[0,2].set_title('abs. ver. advection')
fig.colorbar(im, ax=axs[0,2])
im = axs[1,2].imshow(modelout[xadv_3d][0,0,:,:],origin='lower',vmax=lim2,vmin=-1*lim2,cmap='seismic')
axs[1,2].set_title(yadv_3d)
fig.colorbar(im, ax=axs[1,2])
Out[20]: