Skip to content

Commit f15b916

Browse files
authored
Merge pull request mom-ocean#163 from jkrasting/basin_refinediag
CMIP6 Refine Diag Script - Closes mom-ocean#178 .
2 parents 8d4de1e + bcd2b90 commit f15b916

9 files changed

Lines changed: 1079 additions & 58 deletions

ice_ocean_SIS2/OM4_025/diag_table.MOM6

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
# Generally save annuals, and sometimes monthly and daily.
7272
"ocean_model_z", "volcello", "volcello", "ocean_annual_z", "all", "mean", "none",2 # Cell measure for 3d data
7373
"ocean_model_z", "volcello", "volcello", "ocean_month_z", "all", "mean", "none",2 # Cell measure for 3d data
74+
"ocean_model_rho2", "volcello", "volcello", "ocean_annual_rho2", "all", "mean", "none",2 # Cell measure for 3d data
75+
"ocean_model_rho2", "volcello", "volcello", "ocean_month_rho2", "all", "mean", "none",2 # Cell measure for 3d data
7476
"ocean_model", "volcello", "volcello", "ocean_annual", "all", "mean", "none",2 # Cell measure for 3d data
7577
#"ocean_model", "volcello", "volcello", "ocean_month", "all", "mean", "none",2 # Cell measure for 3d data
7678
"ocean_model", "pbo", "pbo", "ocean_annual", "all", "mean", "none",2
@@ -82,6 +84,8 @@
8284
"ocean_model", "masso", "masso", "ocean_scalar_month", "all", "mean", "none",2 # global sum masscello
8385
"ocean_model", "masso", "masso", "ocean_scalar_annual", "all", "mean", "none",2 # global sum masscello
8486
"ocean_model", "thkcello", "thkcello", "ocean_annual", "all", "mean", "none",2 # Only needed in native space a static field needs to be provided for CMIP6
87+
"ocean_model_rho2", "thkcello", "thkcello", "ocean_annual_rho2", "all", "mean", "none",2 # Only needed in native space a static field needs to be provided for CMIP6
88+
"ocean_model_rho2", "thkcello", "thkcello", "ocean_month_rho2", "all", "mean", "none",2 # Only needed in native space a static field needs to be provided for CMIP6
8589
#"ocean_model", "thkcello", "thkcello", "ocean_month", "all", "mean", "none",2
8690
"ocean_model", "volo", "volo", "ocean_scalar_month", "all", "mean", "none",2 # global sum thkcello
8791
"ocean_model", "volo", "volo", "ocean_scalar_annual", "all", "mean", "none",2 # global sum thkcello
@@ -163,7 +167,7 @@
163167
#"ocean_model", "vo", "vo", "ocean_month", "all", "mean", "none",2
164168
#"ocean_model", "umo", "umo", "ocean_annual", "all", "mean", "none",2
165169
"ocean_model_z","umo", "umo", "ocean_annual_z", "all", "mean", "none",2
166-
#"ocean_model_z","umo", "umo", "ocean_month_z", "all", "mean", "none",2
170+
"ocean_model_z","umo", "umo", "ocean_month_z", "all", "mean", "none",2
167171
#"ocean_model", "vmo", "vmo", "ocean_annual", "all", "mean", "none",2
168172
"ocean_model_z","vmo", "vmo", "ocean_annual_z", "all", "mean", "none",2
169173
"ocean_model_z","vmo", "vmo", "ocean_month_z", "all", "mean", "none",2
@@ -185,16 +189,16 @@
185189
"ocean_model_z","vh", "vh", "ocean_annual_z", "all", "mean", "none",2
186190
"ocean_model_z","T_adx", "T_adx", "ocean_annual_z", "all", "mean", "none",2
187191
"ocean_model_z","T_ady", "T_ady", "ocean_annual_z", "all", "mean", "none",2
188-
"ocean_model", "T_adx_2d", "T_adx_2d", "ocean_annual", "all", "mean", "none",2
189-
"ocean_model", "T_ady_2d", "T_ady_2d", "ocean_annual", "all", "mean", "none",2
192+
"ocean_model", "T_adx_2d", "T_adx_2d", "ocean_month", "all", "mean", "none",2
193+
"ocean_model", "T_ady_2d", "T_ady_2d", "ocean_month", "all", "mean", "none",2
190194
"ocean_model_z","S_adx", "S_adx", "ocean_annual_z", "all", "mean", "none",2
191195
"ocean_model_z","S_ady", "S_ady", "ocean_annual_z", "all", "mean", "none",2
192-
"ocean_model", "S_adx_2d", "S_adx_2d", "ocean_annual", "all", "mean", "none",2
193-
"ocean_model", "S_ady_2d", "S_ady_2d", "ocean_annual", "all", "mean", "none",2
194-
"ocean_model", "ndiff_tracer_trans_x_2d_T","ndiff_tracer_trans_x_2d_T", "ocean_annual", "all", "mean", "none",2
195-
"ocean_model", "ndiff_tracer_trans_y_2d_T","ndiff_tracer_trans_y_2d_T", "ocean_annual", "all", "mean", "none",2
196-
"ocean_model", "ndiff_tracer_trans_x_2d_S","ndiff_tracer_trans_x_2d_S", "ocean_annual", "all", "mean", "none",2
197-
"ocean_model", "ndiff_tracer_trans_y_2d_S","ndiff_tracer_trans_y_2d_S", "ocean_annual", "all", "mean", "none",2
196+
"ocean_model", "S_adx_2d", "S_adx_2d", "ocean_month", "all", "mean", "none",2
197+
"ocean_model", "S_ady_2d", "S_ady_2d", "ocean_month", "all", "mean", "none",2
198+
"ocean_model", "ndiff_tracer_trans_x_2d_T","ndiff_tracer_trans_x_2d_T", "ocean_month", "all", "mean", "none",2
199+
"ocean_model", "ndiff_tracer_trans_y_2d_T","ndiff_tracer_trans_y_2d_T", "ocean_month", "all", "mean", "none",2
200+
"ocean_model", "ndiff_tracer_trans_x_2d_S","ndiff_tracer_trans_x_2d_S", "ocean_month", "all", "mean", "none",2
201+
"ocean_model", "ndiff_tracer_trans_y_2d_S","ndiff_tracer_trans_y_2d_S", "ocean_month", "all", "mean", "none",2
198202

199203
# Density space diagnostics (not necessarily using CMIP names but needed to generate CMIP output in post-processing)
200204
"ocean_model_rho2","umo", "umo", "ocean_annual_rho2", "all", "mean", "none",2

tools/analysis/MOM6_refineDiag.csh

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@
22
#------------------------------------------------------------------------------
33
# MOM6_refineDiag.csh
44
#
5-
# DESCRIPTION: This is a script that is inteded to drive all the
5+
# DESCRIPTION: This is a script that is inteded to drive all the
66
# pre-postprocessing stages of data manipulations on analysis nodes.
7-
# It is intended to be called by FRE at the "refineDiag" stage
7+
# It is intended to be called by FRE at the "refineDiag" stage
88
# which happens just before the components are post processed by frepp.
9-
# To make this happen a path to the (would be) script should appear
10-
# in the <refineDiag> tag of the xmls, e.g.,
9+
# To make this happen a path to the (would be) script should appear
10+
# in the <refineDiag> tag of the xmls, e.g.,
1111
# <refineDiag script="$(NB_ROOT)/mom6/tools/analysis/MOM6_refineDiag.csh"/>
1212
# Note that the above script should exist when frepp is called.
13-
# This could be achieved by cloning the mom6 git repo in the <csh> section of the setup block
14-
# in the corresponding the gfdl platfrom. E.g.,
13+
# This could be achieved by cloning the mom6 git repo in the <csh> section of the setup block
14+
# in the corresponding the gfdl platfrom. E.g.,
1515
# <csh><![CDATA[
1616
# source $MODULESHOME/init/csh
1717
# module use -a /home/John.Krasting/local/modulefiles
1818
# module purge
1919
# module load jpk-analysis/0.0.4
2020
# module load $(FRE_VERSION)
21-
### The following clones the mom6 git repo which should contain all the pp scripts
21+
### The following clones the mom6 git repo which should contain all the pp scripts
2222
# setenv NBROOT /nbhome/$USER/$(FRE_STEM)$(DEBUGLEVEL)
2323
# mkdir -p $NBROOT
2424
# cd $NBROOT
@@ -45,19 +45,19 @@ echo ""
4545
#Niki: Note that here we do not have any FRE environment to /nbhome
4646
# NBROOT should be set as an environ vatiable at the setup in the xml
4747
# setenv NBROOT /nbhome/$USER/$(FRE_STEM)$(DEBUGLEVEL)
48-
set src_dir=$NBROOT/mom6/tools/analysis
48+
set src_dir=$NBROOT/mom6/tools/analysis
4949
# The following variables are set by frepp, but frepp is not called yet at refineDiag stage of FRE workflow,
5050
# so we need to explicitly set them here
51-
set descriptor = $name
51+
set descriptor = $name
5252
set out_dir = $NBROOT #Niki: How can we set this to frepp analysisdir /nbhome
53-
set yr1 = $oname
54-
set yr2 = $oname
55-
set databegyr = $oname
56-
set dataendyr = $oname
53+
set yr1 = $oname
54+
set yr2 = $oname
55+
set databegyr = $oname
56+
set dataendyr = $oname
5757
set datachunk = 1
5858
#Try setting fre version to the caller version
5959
if ( ! $?FREVERSION ) set FREVERSION = fre
60-
set fremodule = $FREVERSION
60+
set fremodule = $FREVERSION
6161
set freanalysismodule = fre-analysis/test
6262

6363
# make sure valid platform and required modules are loaded
@@ -82,7 +82,7 @@ if (! $?FRE_ANALYSIS_HOME) then
8282
endif
8383

8484
#
85-
#At this point of the FRE workflow we are in a /vftmp directory on an analysis node
85+
#At this point of the FRE workflow we are in a /vftmp directory on an analysis node
8686
#with all the history files for the current finished year ${yr1} unpacked and present
8787
#
8888
echo "We are inside the refineDiag script"
@@ -91,14 +91,26 @@ ls -l
9191

9292
set script_dir=${out_dir}/mom6/tools/analysis
9393

94-
echo '==Run some example annual scripts. These are not reviewed by scientists.'
94+
set ocean_static_file = $yr1.ocean_static.nc
95+
if ( -e $yr1.ocean_static_no_mask_table.nc ) set ocean_static_file = $yr1.ocean_static_no_mask_table.nc
96+
97+
set basin_codes_file = $yr1.basin_codes.nc
9598

9699
echo '====annual mean Eddy Kinetic Energy======'
97100
mkdir -p $out_dir/refineDiag_ocean_annual/EddyKineticEnergy
98-
set ocean_static_file = $yr1.ocean_static.nc
99-
if ( -e $yr1.ocean_static_no_mask_table.nc ) set ocean_static_file = $yr1.ocean_static_no_mask_table.nc
100101
$script_dir/EddyKineticEnergy.py -g $ocean_static_file -o $out_dir/refineDiag_ocean_annual/EddyKineticEnergy/EKE_mean_${yr1}.png -l ${yr1} $yr1.ocean_daily.nc
101-
$script_dir/calc_variance.py zos $yr1.ocean_daily.nc $refineDiagDir/$yr1.ocean_month_refined.nc
102+
103+
104+
echo '==== Offline Diagnostics ===='
105+
$script_dir/refineDiag_ocean_month.py -b $basin_codes_file -r $refineDiagDir $yr1.ocean_month.nc
106+
$script_dir/refineDiag_ocean_month_z.py -b $basin_codes_file -r $refineDiagDir -s ./ $yr1.ocean_month_z.nc
107+
$script_dir/refineDiag_ocean_month_rho2.py -b $basin_codes_file -r $refineDiagDir $yr1.ocean_month_rho2.nc
108+
#$script_dir/calc_variance.py zos $yr1.ocean_daily.nc $refineDiagDir/$yr1.ocean_month_refined.nc
109+
110+
#-- Note: The calc_variance script pre-dated refineDiag efforts just prior to the start of the GFDL-CM4 DECK runs.
111+
# Based on the diag_table, it looks like the calc_variance script is no longer needed and is now commented out.
112+
# If it is reactivated, it should be called LAST, since it appends to the ocean_month_refined.nc file that is
113+
# created first by the other scripts.
102114

103115
echo " ---------- end yearly analysis ---------- "
104116

tools/analysis/calc_variance.py

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import netCDF4
44
import numpy
5+
import os
56

67
try: import argparse
78
except: raise Exception('This version of python is not new enough. python 2.7 or newer is required.')
@@ -23,7 +24,25 @@
2324
nxy = shape[1:]
2425

2526
if args.verbose: print 'Creating',args.annual_file
26-
nc_out = netCDF4.Dataset( args.annual_file, 'w', format='NETCDF3_64BIT' )
27+
if os.path.exists(args.annual_file):
28+
mode = 'r+'
29+
append = True
30+
else:
31+
mode = 'w'
32+
append = False
33+
nc_out = netCDF4.Dataset( args.annual_file, mode, format='NETCDF3_CLASSIC' )
34+
35+
if append is True:
36+
if 'time' in nc_out.variables.keys():
37+
time_var = 'time'
38+
elif 'Time' in nc_out.variables.keys():
39+
time_var = 'Time'
40+
else:
41+
nc_out.close()
42+
raise ValueError('Time dimension could not be found in existing file.')
43+
if len(nc_out.variables[time_var][:]) <= 1:
44+
nc_out.close()
45+
raise ValueError('Existing file has only one time value. Assuming this is annual output. Aborting.')
2746

2847
if nt==365: days_in_month = [31,28,31,30,31,30,31,31,30,31,30,31]
2948
elif nt==366: days_in_month = [31,29,31,30,31,30,31,31,30,31,30,31]
@@ -32,12 +51,15 @@
3251

3352
# Create dimensions
3453
for d in variable.dimensions:
35-
if nc_in.dimensions[d].isunlimited(): nc_out.createDimension(d, None)
36-
else: nc_out.createDimension(d, len(nc_in.dimensions[d]))
54+
if d not in nc_out.dimensions:
55+
if nc_in.dimensions[d].isunlimited(): nc_out.createDimension(d, None)
56+
else: nc_out.createDimension(d, len(nc_in.dimensions[d]))
3757

3858
# Copy global attributes
39-
for a in nc_in.ncattrs():
40-
nc_out.__setattr__(a ,nc_in.__getattr__(a))
59+
if append is False:
60+
for a in nc_in.ncattrs():
61+
if a not in nc_out.dimensions:
62+
nc_out.__setattr__(a ,nc_in.__getattr__(a))
4163

4264
# Copy variables corresponding to dimensions used by variable
4365
copy_vars = list(variable.dimensions)
@@ -46,31 +68,49 @@
4668
else: time_bounds_vars = []
4769
for v in copy_vars+time_bounds_vars:
4870
if v in nc_in.variables:
49-
hv = nc_out.createVariable(v, nc_in.variables[v].dtype, nc_in.variables[v].dimensions)
50-
for a in nc_in.variables[v].ncattrs():
51-
hv.setncattr(a, nc_in.variables[v].__getattr__(a))
71+
if v not in nc_out.variables:
72+
hv = nc_out.createVariable(v, nc_in.variables[v].dtype, nc_in.variables[v].dimensions)
73+
for a in nc_in.variables[v].ncattrs():
74+
hv.setncattr(a, nc_in.variables[v].__getattr__(a))
75+
if v in variable.dimensions:
76+
if not nc_in.dimensions[v].isunlimited():
77+
hv[:] = nc_in.variables[v][:]
5278
if v in variable.dimensions:
53-
if not nc_in.dimensions[v].isunlimited():
54-
hv[:] = nc_in.variables[v][:]
55-
else:
79+
if nc_in.dimensions[v].isunlimited():
5680
intime = nc_in.variables[v]
57-
time = hv # Keep around for later
81+
time = intime[:] # Keep around for later
5882

5983
# Create new variables
60-
new_mean = nc_out.createVariable(args.variable, variable.dtype, variable.dimensions)
61-
new_squared = nc_out.createVariable(args.variable+'_squared', variable.dtype, variable.dimensions)
62-
new_variance = nc_out.createVariable(args.variable+'_var', variable.dtype, variable.dimensions)
84+
if args.variable not in nc_out.variables:
85+
new_mean = nc_out.createVariable(args.variable, variable.dtype, variable.dimensions)
86+
do_mean = True
87+
else:
88+
do_mean = False
89+
90+
if args.variable+'_squared' not in nc_out.variables:
91+
new_squared = nc_out.createVariable(args.variable+'_squared', variable.dtype, variable.dimensions)
92+
do_squared = True
93+
else:
94+
do_squared = False
95+
96+
if args.variable+'_var' not in nc_out.variables:
97+
new_variance = nc_out.createVariable(args.variable+'_var', variable.dtype, variable.dimensions)
98+
do_variance = True
99+
else:
100+
do_variance = False
101+
102+
63103
for a in variable.ncattrs():
64-
new_mean.setncattr(a, variable.__getattr__(a))
104+
if do_mean: new_mean.setncattr(a, variable.__getattr__(a))
65105
if a == 'long_name':
66-
new_squared.setncattr(a, 'Square of '+variable.__getattr__(a))
67-
new_variance.setncattr(a, 'Variance of '+variable.__getattr__(a))
106+
if do_squared: new_squared.setncattr(a, 'Square of '+variable.__getattr__(a))
107+
if do_variance: new_variance.setncattr(a, 'Variance of '+variable.__getattr__(a))
68108
elif a == 'units':
69-
new_squared.setncattr(a, '('+variable.__getattr__(a)+')^2')
70-
new_variance.setncattr(a, '('+variable.__getattr__(a)+')^2')
109+
if do_squared: new_squared.setncattr(a, '('+variable.__getattr__(a)+')^2')
110+
if do_variance: new_variance.setncattr(a, '('+variable.__getattr__(a)+')^2')
71111
else:
72-
new_squared.setncattr(a, variable.__getattr__(a))
73-
new_variance.setncattr(a, variable.__getattr__(a))
112+
if do_squared: new_squared.setncattr(a, variable.__getattr__(a))
113+
if do_variance: new_variance.setncattr(a, variable.__getattr__(a))
74114

75115
numpy.seterr(divide='ignore', invalid='ignore', over='ignore') # To avoid warnings
76116
record = -1
@@ -97,14 +137,15 @@
97137
count += 1.
98138
mean_val = mean_val/count
99139
squared_val = squared_val/count
100-
new_mean[month,:] = mean_val
101-
new_squared[month,:] = squared_val
102-
new_variance[month,:] = squared_val - mean_val**2
103-
time[month] = time_val/count
104-
if len(time_bounds_vars):
105-
nc_out.variables[time_bounds_vars[0]][month] = b0
106-
nc_out.variables[time_bounds_vars[1]][month] = b1
107-
nc_out.variables[time_bounds_vars[2]][month] = count
140+
if do_mean: new_mean[month,:] = mean_val
141+
if do_squared: new_squared[month,:] = squared_val
142+
if do_variance: new_variance[month,:] = squared_val - mean_val**2
143+
if append is False:
144+
time[month] = time_val/count
145+
if len(time_bounds_vars):
146+
nc_out.variables[time_bounds_vars[0]][month] = b0
147+
nc_out.variables[time_bounds_vars[1]][month] = b1
148+
nc_out.variables[time_bounds_vars[2]][month] = count
108149

109150
nc_out.close()
110151
nc_in.close()

tools/analysis/m6toolbox.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,36 @@ def maskFromDepth(depth, zCellTop):
169169
wet[depth>-zCellTop] = 1
170170
return wet
171171

172+
def MOCpsi(vh, vmsk=None):
173+
"""Sums 'vh' zonally and cumulatively in the vertical to yield an overturning stream function, psi(y,z)."""
174+
shape = list(vh.shape); shape[-3] += 1
175+
psi = np.zeros(shape[:-1])
176+
if len(shape)==3:
177+
for k in range(shape[-3]-1,0,-1):
178+
if vmsk is None: psi[k-1,:] = psi[k,:] - vh[k-1].sum(axis=-1)
179+
else: psi[k-1,:] = psi[k,:] - (vmsk*vh[k-1]).sum(axis=-1)
180+
else:
181+
for n in range(shape[0]):
182+
for k in range(shape[-3]-1,0,-1):
183+
if vmsk is None: psi[n,k-1,:] = psi[n,k,:] - vh[n,k-1].sum(axis=-1)
184+
else: psi[n,k-1,:] = psi[n,k,:] - (vmsk*vh[n,k-1]).sum(axis=-1)
185+
return psi
186+
187+
188+
def moc_maskedarray(vh,mask=None):
189+
if mask is not None:
190+
_mask = np.ma.masked_where(np.not_equal(mask,1.),mask)
191+
else:
192+
_mask = 1.
193+
_vh = vh * _mask
194+
_vh_btm = np.ma.expand_dims(_vh[:,-1,:,:]*0.,axis=1)
195+
_vh = np.ma.concatenate((_vh,_vh_btm),axis=1)
196+
_vh = np.ma.sum(_vh,axis=-1) * -1.
197+
_vh = _vh[:,::-1] # flip z-axis so running sum is from ocean floor to surface
198+
_vh = np.ma.cumsum(_vh,axis=1)
199+
_vh = _vh[:,::-1] # flip z-axis back to original order
200+
return _vh
201+
172202
def nearestJI(x, y, xy0):
173203
"""
174204
Find (j,i) of cell with center nearest to (x0,y0).

0 commit comments

Comments
 (0)