|
||||
File indexing completed on 2021-04-23 05:12:38 UTC
view on githubraw file Latest commit ce0d9af5 on 2021-04-21 19:30:20 UTCce0d9af5ea Jeff*0001 # import python modules 0002 import numpy as np 0003 import matplotlib.pyplot as plt 0004 import netCDF4 as nc 0005 0006 0007 ########### load grid data ########### 0008 0009 # Load grid variables; names correspond with MITgcm source code. 0010 # (if using standard binary output instead of netcdf, these are dumped 0011 # to individual files, e.g. 'RC.data' etc.) 0012 # Assumes that output in multiple tiles has been concatenated into 0013 # global files (used script utils/python/MITgcmutils/scripts/gluemncbig) 0014 # and moved into the top directory; 0015 # see MITgcm user manual section 4.2.4.1 0016 0017 # Using a spherical polar grid, all X,Y variables in lon,lat coordinates 0018 # vertical grid provided in meters, area in m^2 0019 0020 grid = nc.Dataset('grid.nc') 0021 # 1-D fields 0022 RC = grid['RC'][:] # vertical grid, cell center locations 0023 drF = grid['drF'][:] # vertical spacing of grid cells (thickness of cells) 0024 # 2-D fields (y,x) 0025 XC = grid['XC'][:] # x-location of gridcell centers 0026 YC = grid['YC'][:] # y-location of gridcell centers 0027 dyG = grid['dyG'][:] # grid spacing in y-dim (separation between corners) 0028 rA = grid['rA'][:] # surface area of gridcells 0029 # 3-D fields (z,y,x) 0030 HFacC = grid['HFacC'][:] # vertical fraction of cell which is ocean 0031 0032 # For convenience, load additional dimensional variables from 0033 # netcdf files (these variables are NOT included in binary output) 0034 # These grid variables are also present in netcdf diagnostic data files. 0035 # 1-D fields 0036 X = grid['X'][:] # 1-D version of XC data 0037 Y = grid['Y'][:] # 1-D version of YC data 0038 Xp1 = grid['Xp1'][:] # x-location of lower left corner 0039 Yp1 = grid['Yp1'][:] # y-location of lower left corner 0040 # Xp1 and Yp1 are effectively 1-D versions of grid variables XG,YG with 0041 # an extra data value at the eastern and northern ends of the domain. 0042 # See MITgcm users manual section 2.11 for additional MITgcm grid info 0043 0044 # Number of gridcells in x,y for full domain: 0045 Nx = X.size 0046 Ny = Y.size 0047 # out-of-the-box tutorial configuration is 62x62 0048 0049 0050 ########### load diagnostics ########### 0051 0052 # unit for temperature is degrees Celsius, velocity in m/s, 0053 # surface height in m, heat flux in W/m^2 0054 # see run output file available_diagnostics.log 0055 0056 # load statistical diagnostic output (set to monthly time-avg output) 0057 # only one output region is defined: global (the default) 0058 dynStDiag = nc.Dataset('dynStDiag.nc') 0059 TRELAX_ave = dynStDiag['TRELAX_ave'][:] # (time, region, depth); region=0 (global), depth=0 (surf-only) 0060 THETA_lv_ave = dynStDiag['THETA_lv_ave'][:] # (time, region, depth); region=0 (global) 0061 THETA_lv_std = dynStDiag['THETA_lv_std'][:] # (time, region, depth); region=0 (global) 0062 0063 # load 2-D and 3-D variable diagnostic output, annual mean data 0064 surfDiag = nc.Dataset('surfDiag.nc') 0065 TRELAX = surfDiag['TRELAX'][:] # (time, depth, y, x); depth=0 (surface-only) 0066 ETAN = surfDiag['ETAN'][:] # (time, depth, y, x); depth=0 (surface-only) 0067 dynDiag = nc.Dataset('dynDiag.nc') 0068 UVEL = dynDiag['UVEL'][:] # (time, depth, y, x); x dim is Nx+1, includes eastern edge 0069 VVEL = dynDiag['VVEL'][:] # (time, depth, y, x); y dim is Ny+1, includes northern edge 0070 THETA = dynDiag['THETA'][:] # (time, depth, y, x) 0071 0072 0073 ########### plot diagnostics ########### 0074 0075 # figure 4.6 - time series of global mean TRELAX and THETA by level 0076 # 0077 # plot THETA at MITgcm k levels 1,5,15 (SST, -305 m, -1705 m) 0078 klevs = [0, 4, 14] 0079 0080 # MITgcm time unit (dim='T') is seconds, so create new time series 0081 # for (dynStDiag) monthly time averages and convert into years. 0082 # Note that the MITgcm time array values correspond to time at the end 0083 # of the time-avg periods, i.e. subtract 1/24 to plot at mid-month. 0084 Tmon = dynStDiag['T'][:]/(86400*360) - 1/24 0085 # and repeat to create time series for annual mean time output, 0086 # subtract 0.5 to plot at mid-year. 0087 Tann = surfDiag['T'][:]/(86400*360) - 0.5 0088 0089 plt.figure(figsize=(16,10)) 0090 # global mean TRELAX 0091 plt.subplot(221) 0092 plt.plot(Tmon, TRELAX_ave[:,0,0], 'b', linewidth=4) 0093 plt.grid('both') 0094 plt.title('a) Net Heat Flux into Ocean (TRELAX_ave)') 0095 plt.xlabel('Time (yrs)') 0096 plt.ylabel('$\mathregular{W/m^2}$') 0097 plt.xlim(0, np.ceil(Tmon[-1])) 0098 plt.ylim(-400, 0) 0099 # Alternatively, a global mean area-weighted TRELAX (annual mean) 0100 # could be computed as follows, using HfacC[0,:,:], i.e. HfacC in 0101 # the surface layer, as a land-ocean mask. 0102 # First, compute total surface area of ocean points: 0103 total_ocn_area = (rA * HFacC[0,:,:]).sum() 0104 # numpy is often smart enough to figure out broadcasting, 0105 # depending on axis position. 0106 # In next line, note a np.tile command is NOT necessary to span 0107 # the grid array across the time axis: 0108 TRELAX_ave_ann = (TRELAX[:,0,:,:] * rA * HFacC[0,:,:]).sum((1,2)) / total_ocn_area 0109 plt.plot(Tann, TRELAX_ave_ann, 'm--', linewidth=4) 0110 0111 plt.subplot(223) 0112 plt.plot(Tmon, THETA_lv_ave[:,0,klevs], linewidth=4) 0113 # To specify colors for specific lines, either change the 0114 # default a priori, e.g. ax.set_prop_cycle(color=['r','g','c']) 0115 # or after the fact, e.g. lh[0].set_color('r') etc. 0116 plt.grid('both') 0117 plt.title('b) Mean Potential Temp. by Level (THETA_lv_avg)') 0118 plt.xlabel('Time (yrs)') 0119 plt.ylabel('$\mathregular{^oC}$') 0120 plt.xlim(0, np.ceil(Tmon[-1])) 0121 plt.ylim(0, 30) 0122 plt.legend(RC[klevs], title='Z (m)') 0123 0124 plt.subplot(224) 0125 plt.plot(Tmon, THETA_lv_std[:,0,klevs], linewidth=4) 0126 plt.grid('both') 0127 plt.title('c) Std. Dev. Potential Temp. by Level (THETA_lv_std)') 0128 plt.xlabel('Time (years)') 0129 plt.ylabel('$\mathregular{^oC}$') 0130 plt.xlim(0, np.ceil(Tmon[-1])) 0131 plt.ylim(0, 8) 0132 plt.legend(RC[klevs], title='Z (m)') 0133 plt.show() 0134 0135 # figure 4.7 - 2-D plot of TRELAX and contours of free surface height 0136 # (ETAN) at simulation end ( endTime = 3110400000. is t=100 yrs). 0137 # 0138 eta_masked = np.ma.MaskedArray(ETAN[-1,0,:,:], HFacC[0,:,:]==0) 0139 plt.figure(figsize=(10,8)) 0140 plt.pcolormesh(Xp1, Yp1, TRELAX[-1,0,:,:], cmap='RdBu_r') 0141 plt.xlim(0, 60) 0142 plt.ylim(15, 75) 0143 plt.colorbar() 0144 plt.clim(-250, 250) 0145 plt.contour(X, Y, eta_masked, levels=np.r_[-.6:.7:.1], colors='black') 0146 plt.title('Free surface height (contours, CI .1 m) and ' 0147 'TRELAX (shading, $\mathregular{W/m^2}$)') 0148 plt.xlabel('Longitude') 0149 plt.ylabel('Latitude') 0150 plt.show() 0151 # Note we have used routine pcolormesh with Xp1, Yp1, which are the 0152 # locations of the lower left corners of grid cells 0153 # (here, length Nx+1,Ny+1 as they include the ending right and upper 0154 # locations of the grid, respectively). 0155 # Alternative one could plot shading using contourf with dimensions 0156 # X and Y, the grid cell center locations. 0157 # Also note we mask the land values when contouring the free 0158 # surface height. 0159 0160 # figure 4.8 - barotropic streamfunction, plot at simulation end 0161 # (w/overlaid labeled contours) 0162 # 0163 ubt = (UVEL * drF[:,np.newaxis,np.newaxis]).sum(1) # depth-integrated u velocity 0164 # For ubt calculation numpy needs a bit of help with broadcasting 0165 # the drF vector across [time,y,x] axes 0166 psi = np.zeros((dynDiag['T'].size, Ny+1, Nx+1)) 0167 psi[:,1:,:] = (-ubt * dyG).cumsum(1) / 1E6 # compute streamfn in Sv (for each yr) 0168 # Note psi is computed and plotted at the grid cell corners and we 0169 # compute as dimensioned (Ny,Nx+1); as noted, UVEL contains an extra 0170 # data point in x, at the eastern edge. cumsum is done in y-direction. 0171 # We have a wall at southern boundary (i.e. no reentrant flow from 0172 # north), ergo psi(j=0) is accomplished by declaring psi 0173 # to be shape (dynDiag['T'].size,Ny+1,Nx+1). 0174 0175 plt.figure(figsize=(10,8)) 0176 plt.contourf(Xp1, Yp1, psi[-1], np.arange(-35, 40, 5), cmap='RdYlBu_r') 0177 plt.colorbar() 0178 cs = plt.contour(Xp1, Yp1, psi[-1], np.arange(-35, 40, 5), colors='black') 0179 plt.clabel(cs, fmt = '%.0f') 0180 plt.xlim(0, 60) 0181 plt.ylim(15, 75) 0182 plt.title('Barotropic Streamfunction (Sv)') 0183 plt.xlabel('Longitude') 0184 plt.ylabel('Latitude'); 0185 plt.show() 0186 0187 # figure 4.9 - potential temp at depth and xz slice, at simulation end 0188 # 0189 # plot THETA at MITgcm k=4 (220 m depth) and j=15 (28.5N) 0190 klev = 3 0191 jloc = 14 0192 0193 theta_masked = np.ma.MaskedArray(THETA[-1, klev,:,:], HFacC[klev,:,:]==0) 0194 plt.figure(figsize=(16,6)) 0195 plt.subplot(121) 0196 # again we use pcolor for the plan view and provide the 0197 # corner point locations XG,YG thru Xp1,Yp1 0198 plt.pcolormesh(Xp1, Yp1, THETA[-1,klev,:,:], cmap='coolwarm') 0199 plt.clim(0, 30) 0200 plt.colorbar() 0201 # but to overlay contours we provide the cell centers 0202 # and mask out boundary/land cells 0203 plt.contour(X, Y, theta_masked, np.arange(0,30,2), colors='black') 0204 plt.title('a) THETA at %g m Depth ($\mathregular{^oC}$)' %RC[klev]) 0205 plt.xlim(0, 60) 0206 plt.ylim(15, 75) 0207 plt.xlabel('Longitude') 0208 plt.ylabel('Latitude') 0209 0210 # For the xz slice, our limited vertical resolution makes for an ugly 0211 # pcolor plot, we'll shade using contour instead, providing the centers 0212 # of the vertical grid cells and cell centers in the x-dimension. 0213 # Also mask out land cells at the boundary, which results in slight 0214 # white space at domain edges. 0215 theta_masked = np.ma.MaskedArray(THETA[-1,:,jloc,:], HFacC[:,jloc,:]==0) 0216 plt.subplot(122) 0217 plt.contourf(X, RC, theta_masked, np.arange(0,30,.2), cmap='coolwarm') 0218 plt.colorbar() 0219 plt.contour(X, RC, theta_masked, np.arange(0,32,2), colors='black') 0220 plt.title('b) THETA at %gN ($\mathregular{^oC}$)' %YC[jloc,0]) 0221 plt.xlim(0, 60) 0222 plt.ylim(-1800, 0) 0223 plt.xlabel('Longitude') 0224 plt.ylabel('Depth (m)') 0225 plt.show() 0226 # One approach to avoiding the white space at boundaries/top/bottom 0227 # is to copy neighboring tracer values to land cells prior to contouring 0228 # (and don't mask), and augment a row of z=0 data at the ocean surface 0229 # and a row at the ocean bottom. 0230 # (see tutorial Southern Ocean Reentrant Channel for an example) 0231 # The white space occurs because contour uses data at cell centers, with 0232 # values masked/undefined beyond the cell centers toward boundaries. 0233 0234 # To instead plot using pcolor, pass location of vertical cell faces RF: 0235 # RF=grid['RF'][:] 0236 # plt.pcolormesh(Xp1, RF, THETA[-1,:,jloc,:], cmap='coolwarm') 0237 0238 0239 # Note, the gluemncbig steps outlined in tutorial section 4.2.4.1 can be 0240 # avoided by using the python package "MITgcmutils". Loading the grid 0241 # and diagnostic output, in place of steps at the beginning of this 0242 # script, can be accomplished by reading directly from the mnc output 0243 # directories: 0244 # 0245 # from MITgcmutils import mnc 0246 # grid=mnc.mnc_files('mnc_test_*/grid.t*.nc') 0247 # XC=grid.variables['XC'][:] 0248 # ... 0249 # dynStDiag=mnc.mnc_files('mnc_test_*/dynStDiag.0000000000.t*.nc') 0250 # TRELAX_ave=dynStDiag.variables['TRELAX_ave'][:] 0251 # ... 0252 # surfDiag=mnc.mnc_files('mnc_test_*/surfDiag.0000000000.t*.nc') 0253 # TRELAX=surfDiag.variables['TRELAX'][:] 0254 # ... 0255 # dynDiag=mnc.mnc_files('mnc_test_*/dynDiag.0000000000.t*.nc') 0256 # THETA=dynDiag.variables['THETA'][:] 0257 # ... 0258 0259 # An advantage using mnc_files() is that you aren't required to waste 0260 # disk space assembling glued files. See MITgcm users manual chapter 11 0261 # for reference information on MITgcmutils. Note mnc_file() will 0262 # generally NOT work with wildcard mnc_test_* directories from multiple 0263 # runs are present unless you pass it the specific directories to read, 0264 # e.g. for a 4-core mpi run output in mnc_test_0009 thru mnc_test_0012: 0265 # dynStDiag=mnc.mnc_files('mnc_test_{0009..0012}/dynStDiag.0000000000.t*.nc')
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated from https://github.com/MITgcm/MITgcm by the 2.2.1-MITgcm-0.1 LXR engine. The LXR team |