230 lines
12 KiB
Python
230 lines
12 KiB
Python
def refstate_meandensity(rho_in,grd,area_xyz_in):
|
|
# refstate_meandensity(rho,zlev,area_xyz) ################################################
|
|
# written by : Gabriel Wolf, g.a.wolf@reading.ac.uk
|
|
# adapted from get_refstate_meandensity.m of Remi Tailleux (10.04.2013)
|
|
# last modified : 20.09.2018
|
|
# Content/Description ####################################################################
|
|
# Usage : from gw_ocean_refstate import refstate_meandensity
|
|
# Input : area_xyz, rho, zlev
|
|
# area_xyz : hor. area for 3d grid [m**2], 3d
|
|
# rho : density [kg m**-3], 3d
|
|
# grd : Input grid [python class]
|
|
# Output : pp_rhor
|
|
# pp_rhor : interpolant for reference state
|
|
# ########################################################################################
|
|
# Load modules
|
|
import numpy as np
|
|
from scipy import interpolate
|
|
import pickle # To load interpolants of bathymetry data
|
|
# Allocation
|
|
rhor = np.zeros([grd.Nz,1])
|
|
# compute hor. averaged density field
|
|
rho_surf = area_xyz_in*rho_in
|
|
mask = np.isfinite(rho_surf)
|
|
rhor = sum(sum(mask*rho_surf,1),0)/sum(sum(area_xyz_in*mask,1),0)
|
|
# define arrays for interpolation of density profiles
|
|
pp_rhor = interpolate.PchipInterpolator(grd.z, rhor, axis=0)
|
|
# return interpolant for reference state
|
|
return pp_rhor
|
|
|
|
def refstate_sorted_stheta(th,s,rho,mask,ztarget,grd,sbin=[0.0,43.0,0.002],\
|
|
thbin=[-2.6,30.0,0.005],ref_EOS='jackettetal2004',test=False,case_str=[]):
|
|
# refstate_sorted_stheta(th,s,rho,mask,ztarget,grd,test) #################################
|
|
# written by : Gabriel Wolf, g.a.wolf@reading.ac.uk
|
|
# adapted from get_refstate_sorted.m of Remi Tailleux (10.04.2013)
|
|
# last modified : 24.09.2018
|
|
# Content/Description ####################################################################
|
|
# Reference : method based on Tailleux (2013), -> https://doi.org/10.1017/jfm.2013.509
|
|
# : summary of this framework in Saenz et al. (2015):
|
|
# -> https://doi.org/10.1175/JPO-D-14-0105.1
|
|
# Usage : from gw_ocean_refstate import refstate_sorted_stheta
|
|
# Input : grd, mask, ,ref_equofstate, rho, s, sbin, test, thbin, th, ztarget
|
|
# grd : Input grid [python class]
|
|
# mask : valid points [boolean], 3d
|
|
# ref_EOS : defines equ. of state [reference]
|
|
# : reference def. by publication, e.g. author1year for one author-public.,
|
|
# : author1andauthor2year for 2-author-public. or author1etalyear for more
|
|
# : than 2 authors
|
|
# rho : density [kg m**-3], 3d
|
|
# s : salinity [psu], 3d
|
|
# sbin : bin range for s to construct s-th-diagram [min,max,delta]
|
|
# test : further test plotting and value checking [boolean], 1d
|
|
# th : potential temperature [deg C], 3d
|
|
# thbin : bin range for th to construct s-th-diagram [min,max,delta]
|
|
# ztarget : target height level [m], 1d
|
|
# Output :pp_rhor_botup, pp_rhor_topdn
|
|
# pp_rhor_botup : interpolant for density reference state (calc. from bottom up)
|
|
# pp_rhor_topdn : interpolant for density reference state (calc. from bottom up)
|
|
# Testing : plot_sth_pdf
|
|
# plot_sth_pdf : plotting of sorted ocena-volumes in the S-TH-diagram
|
|
# ########################################################################################
|
|
|
|
# Testing variables %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
plot_sth_pdf = 1*test
|
|
if plot_sth_pdf == 1:
|
|
print ' Create test plot for sorted ocean-volumes in S-Th-diagram'
|
|
from myplot import myplot_2d
|
|
|
|
# Load modules %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
import numpy as np
|
|
from scipy import interpolate # for interpolation
|
|
from mycalc_ocean import calc_rho_from_theta, volume_census_levitus
|
|
# calc_rho_from_theta : to calculate density from pot. temperature
|
|
# volume_census_levitus : to create s-th-pdf with vol info
|
|
from myconstants import rho0, grav # necessary constants
|
|
|
|
# Allocation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
n_target = len(ztarget)
|
|
s[mask==False] = np.nan
|
|
th[mask==False] = np.nan
|
|
rho[mask==False] = np.nan
|
|
|
|
# Compute the pdf of the salinity/theta data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
try:
|
|
import pickle
|
|
with open('data_pdf_salth' + case_str + '.pickle', 'rb') as data_pdf:
|
|
dummy = pickle.load(data_pdf)
|
|
pdf_vol_lev = dummy[0]
|
|
vol_tot_ocean = dummy[1]
|
|
del dummy, data_pdf
|
|
pdf_vol_lev_norm = pdf_vol_lev/vol_tot_ocean
|
|
except:
|
|
pdf_vol_lev, vol_tot_ocean = volume_census_levitus(th, s, grd, thbin, sbin)
|
|
print ' Total volume ocean: ' + str(vol_tot_ocean) + ' m**3'
|
|
pdf_vol_lev_norm = pdf_vol_lev/vol_tot_ocean
|
|
import pickle
|
|
with open('data_pdf_salth' + case_str + '.pickle', 'wb') as output:
|
|
pdf_salth = [pdf_vol_lev, vol_tot_ocean]
|
|
pickle.dump(pdf_salth, output, -1)
|
|
|
|
# Define properties of the binned temperature/salinity data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
print ' *** MISSING: property definition of binned temperature/salinity data ***'
|
|
n_sbin, n_thbin = pdf_vol_lev.shape
|
|
s_axis = np.arange(sbin[0]+sbin[2]*0.5,sbin[1],sbin[2])
|
|
th_axis = np.arange(thbin[0]+thbin[2]*0.5,thbin[1],thbin[2])
|
|
# Testing pdf-output (pdf_vol_lev_norm)
|
|
if plot_sth_pdf:
|
|
d_step = 1
|
|
xxx = np.arange(sbin[0],sbin[1],sbin[2]*d_step)
|
|
yyy = yyy=np.arange(thbin[0],thbin[1],thbin[2]*d_step)
|
|
ddd = pdf_vol_lev_norm[::d_step,::d_step]
|
|
ddd[ddd==0] = np.nan
|
|
ddd = np.log10(ddd)
|
|
print 'np.nanmax(ddd) = ',np.nanmax(ddd)
|
|
import datetime
|
|
plotname = 'Testplot_for_oceanvol_in_s_th_diagram_' + \
|
|
str(datetime.date.today()) + case_str + '.png'
|
|
myplot_2d(xxx,yyy,ddd.T,xlabel_c='salinity [psu]',ylabel_c='potential temp. [deg C]',\
|
|
plotname=plotname,saveplot=1,FS=14,d_xtick=0.2,title_c='S-TH',\
|
|
cbarlabel_c='Volume freq. distribution [log_10]')
|
|
#import pdb
|
|
#pdb.set_trace()
|
|
#iprint 'stop here'
|
|
del xxx, yyy, ddd
|
|
|
|
# define target pressure from target depths %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
ptarget = rho0 * grav * ztarget / 1e4
|
|
n_target = len(ptarget)
|
|
print ' *** why using constant density for target pressure and not variable one? ***'
|
|
|
|
# Seek the global min. and max. of density by bringing all parcels to the ocean surface
|
|
# (to find min.) and to ocean bottom (to find max.) --------------------------------------
|
|
# Allocation
|
|
rho_theta_surf = rho
|
|
rho_theta_deep = rho
|
|
p_surf = np.ones([grd.Nlon,grd.Nlat,grd.Nz])*ptarget[0]
|
|
p_deep = np.ones([grd.Nlon,grd.Nlat,grd.Nz])*ptarget[-1]
|
|
# Compute potential density reference to target pressure at surface
|
|
rho_theta_surf[mask] = calc_rho_from_theta(s[mask],th[mask],p_surf[mask],reference=ref_EOS)
|
|
# Compute potential density referenced to last target pressure
|
|
rho_theta_deep[mask] = calc_rho_from_theta(s[mask],th[mask],p_deep[mask],reference=ref_EOS)
|
|
# Compute global density minimum and maximum
|
|
rho_min = np.min(rho_theta_surf[mask])
|
|
rho_max = np.max(rho_theta_deep[mask])
|
|
|
|
# Compute upper and lower salinity curves in theta/salt space %%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
# Allocation
|
|
s_lower = np.zeros(n_thbin)
|
|
s_upper = np.zeros(n_thbin)
|
|
# Computation
|
|
s_lower = calc_sal_from_rho(rho_min,th_axis,ptarget[0],reference=ref_EOS)
|
|
s_upper = calc_sal_from_rho(rho_max,th_axis,ptarget[-1],reference=ref_EOS)
|
|
|
|
# Compute the topography statistics %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
print ' Load topographic data for z-dependent ocean area and volume'
|
|
# Load or calculate z-dep. ocean area/volume
|
|
fn_topo = 'interp_of_topo' + '.pickle'
|
|
try:
|
|
with open(fn_topo, 'rb') as data_interp:
|
|
dummy = pickle.load(data_interp)
|
|
pp_area = dummy[0]
|
|
pp_volume = dummy[1]
|
|
del dummy, data_interp
|
|
except:
|
|
print ' -> Data could not be loaded. Therefore it will be calculated.'
|
|
pp_area, pp_volume = volume_etopo(fn_topo)
|
|
del fn_topo
|
|
# define z-dep. volume and its fraction
|
|
vol_target = pp_volume(ztarget)
|
|
frac_vol_target = vol_target/vol_target[-1]
|
|
|
|
# New attempt to compute the top-down profile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
print ' Computing top-down profile for reference density'
|
|
# Allocation/Initialization
|
|
rhor_topdn = np.zeros(n_target)
|
|
rhor_topdn[0] = rho_min
|
|
rhor_topdn[-1] = rho_max
|
|
s_curves_td = np.zeros([n_target,n_thbin])
|
|
s_curves_td[0,:] = s_lower
|
|
s_curves_td[-1,:] = s_upper
|
|
scurv = np.copy(s_lower)
|
|
rho_l = np.copy(rho_min)
|
|
# Use optimization method to converge to correct salinity curve
|
|
print ' *** this loop is not necessary ***'
|
|
for i_iter in range(0,n_target-1):
|
|
rho_u = calc_rho_from_theta(sbin[1],thbin[0],ptarget[i_iter+1])
|
|
func = lambda rho_i : volume_from_sth(rho_i, pdf_vol_lev_norm,\
|
|
th_axis, ptarget[i_iter+1], scurv, sbin) - \
|
|
(frac_vol_target[i_iter+1]-frac_vol_target[i_iter])
|
|
rhor_topdn[i_iter+1] = fsolve(func, np.array([rho_l,rho_u]))
|
|
s_curves_td[i_iter+1,:] = calc_sal_from_rho(rhor_topdn[i_iter+1]*np.ones(n_thbin),\
|
|
th_axis,ptarget[i_iter+1]*np.ones(n_thbin))
|
|
s_curv = s_curves_td[i_iter+1,:]
|
|
rho_l = rhor_topdn[i_iter+1]
|
|
print ' -> [iter(target) rhor_topdn(iter) rho_l rho_u]',\
|
|
[i_iter,rhor_topdn[i_iter+1],rho_l, rho_u]
|
|
|
|
# New attempt at computing bottom-up profile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
print ' *** MISSING: rhor bottom-up profile ***'
|
|
print ' Computing bottom-up profile for reference density'
|
|
# Allocation/Initialization
|
|
rhor_botup = np.zeros(n_target)
|
|
rhor_botup[0] = rho_min
|
|
rhor_botup[-1] = rho_max
|
|
s_curves_bu = np.zeros([n_target,n_thbin])
|
|
s_curves_bu[0,:] = s_lower
|
|
s_curves_bu[-1,:] = s_upper
|
|
scurv = np.copy(s_upper)
|
|
rho_u = np.copy(rho_max)
|
|
# Use optimization method to converge to correct salinity curve
|
|
print ' *** this loop is not necessary ***'
|
|
for i_iter in range(n_target-1,1,-1):
|
|
rho_l = calc_rho_from_theta(sbin[0],thbin[1],ptarget[i_iter-1])
|
|
func = lambda rho_i : vol_from_sth(rho_i, pdf_vol_lev_norm,\
|
|
th_axis, ptarget[i_iter-1],scurv, sbin) - \
|
|
(frac_vol_target[i_iter]-frac_vol_target[i_iter-1])
|
|
rhor_botup[i_iter+1] = fsolve(func, np.array([rho_l,rho_u]))
|
|
s_curves_bu[i_iter-1,:] = calc_sal_from_rho(rhor_botup[i_iter-1]*np.ones(n_thbin),\
|
|
th_axis,ptarget[i_iter-1]*np.ones(n_thbin))
|
|
s_curv = s_curves_bu[i_iter-1,:]
|
|
rho_u = rhor_botup[i_iter-1]
|
|
print ' -> [iter(target) rhor_botup(iter) rho_l rho_u]',\
|
|
[i_iter,rhor_botup[i_iter+1],rho_l, rho_u]
|
|
|
|
# Assign interpolants for the two possible reference states %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
pp_rhor_botup = interpolate.PchipInterpolator(ztarget, rhor_botup, axis=0)
|
|
pp_rhor_topdn = interpolate.PchipInterpolator(ztarget, rhor_topdn, axis=0)
|
|
|
|
# return interpolant for the two reference states %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
return pp_rhor_botup, pp_rhor_topdn
|