mean_2d.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. #!/usr/bin/env python
  2. #
  3. # B a r a K u d a
  4. #
  5. # Generate misc. spatial 2D averaging out of NEMO output files...
  6. #
  7. # L. Brodeau, november 2013
  8. #
  9. import sys
  10. from os import path
  11. import numpy as nmp
  12. from netCDF4 import Dataset
  13. from string import replace
  14. import barakuda_tool as bt
  15. import barakuda_orca as bo
  16. import barakuda_ncio as bnc
  17. # Box nino 3.4:
  18. lon1_nino = 360. - 170. ; # east
  19. lat1_nino = -5.
  20. lon2_nino = 360. - 120. ; # east
  21. lat2_nino = 5.
  22. venv_needed = {'ORCA','EXP','DIAG_D','MM_FILE','BM_FILE','NEMO_SAVED_FILES','FILE_FLX_SUFFIX',
  23. 'NN_SST','NN_SSS','NN_SSH','NN_MLD','TSTAMP','NN_FWF','NN_EMP','NN_P','NN_RNF',
  24. 'NN_CLV','NN_E','NN_QNET','NN_QSOL'}
  25. vdic = bt.check_env_var(sys.argv[0], venv_needed)
  26. CONFEXP = vdic['ORCA']+'-'+vdic['EXP']
  27. if len(sys.argv) != 3:
  28. print 'Usage : sys.argv[1] <ORCA1_EXP_grid_T.nc> <year>'
  29. sys.exit(0)
  30. cnexec = sys.argv[0]
  31. cf_T_in = sys.argv[1]
  32. cyear = sys.argv[2] ; jyear = int(cyear); cyear = '%4.4i'%jyear
  33. print 'Current year is '+cyear+' !\n'
  34. vtime = nmp.zeros(12)
  35. for jt in range(12):
  36. vtime[jt] = float(jyear) + (float(jt)+0.5)*1./12.
  37. # Checking if the land-sea mask file is here:
  38. for cf in [vdic['MM_FILE'], vdic['BM_FILE']]:
  39. if not path.exists(cf):
  40. print 'Mask file '+cf+' not found'; sys.exit(0)
  41. # Reading the grid metrics:
  42. id_mm = Dataset(vdic['MM_FILE'])
  43. list_variables = id_mm.variables.keys()
  44. rmask = id_mm.variables['tmask'][0,0,:,:]
  45. xlon = id_mm.variables['glamt'][0,:,:]
  46. xlat = id_mm.variables['gphit'][0,:,:]
  47. xe1t = id_mm.variables['e1t'][0,:,:]
  48. xe2t = id_mm.variables['e2t'][0,:,:]
  49. id_mm.close()
  50. [ nj, ni ] = rmask.shape
  51. # About heat and freshwater fluxes:
  52. cfe_sflx = vdic['FILE_FLX_SUFFIX']
  53. l_fwf = False
  54. l_htf = False
  55. l_evp = False
  56. if cfe_sflx in vdic['NEMO_SAVED_FILES']:
  57. if vdic['NN_FWF'] != 'X':
  58. l_fwf = True
  59. cvfwf, isfwf = bt.var_and_signs(vdic['NN_FWF'])
  60. print ' cvfwf => ', cvfwf ; # might be the sum (+/-) of variables
  61. if vdic['NN_QNET'] != 'X':
  62. l_htf = True
  63. cvhtf, ishtf = bt.var_and_signs(vdic['NN_QNET'])
  64. print ' cvhtf => ', cvhtf ; # might be the sum of variables
  65. cf_F_in = replace(cf_T_in, 'grid_T', cfe_sflx)
  66. Xa = nmp.zeros((nj, ni))
  67. Xa[:,:] = xe1t[:,:]*xe2t[:,:]
  68. del xe1t, xe2t
  69. Xarea_t = nmp.zeros((nj, ni))
  70. Xarea_t[:,:] = Xa[:,:]*rmask[:,:]*1.E-6 ; # [10^6 m^2] !
  71. Socean = nmp.sum( Xarea_t[:-2,:-2] ) ; # Mind the 2 point folding overlap, must not be included in sum!
  72. print '\n *** Surface of the ocean = ', Socean* 1.E-6, ' [10^6 km^2]\n'
  73. print 'Reading all basin masks in file '+vdic['BM_FILE']
  74. list_basin_names, list_basin_lgnms = bo.get_basin_info(vdic['BM_FILE'])
  75. nb_basins = len(list_basin_names)
  76. mask = nmp.zeros((nb_basins,nj,ni))
  77. msk_tmp = nmp.zeros((nj,ni))
  78. mask[0,:,:] = rmask[:,:] ; # global
  79. id_bm = Dataset(vdic['BM_FILE'])
  80. for jb in range(1,nb_basins) :
  81. msk_tmp[:,:] = id_bm.variables['tmask'+list_basin_names[jb]][:,:]
  82. mask[jb,:,:] = msk_tmp[:,:]*rmask[:,:]
  83. id_bm.close()
  84. del rmask, msk_tmp
  85. #######################################################################
  86. # Time-series of globally averaged surface heat and freshwater fluxes #
  87. ######################################################################
  88. # Getting dimensions of flux fields:
  89. if l_htf or l_fwf:
  90. id_in = Dataset(cf_F_in)
  91. vtime = id_in.variables['time_counter'][:]; Nt = len(vtime)
  92. tmp = id_in.variables['nav_lon'][:,:]; (nj,ni) = nmp.shape(tmp)
  93. print ' *** dimensions in file '+path.basename(cf_F_in)+' => ni, nj, Nt =>', ni, nj, Nt
  94. del tmp
  95. for jt in range(Nt): vtime[jt] = float(jyear) + (float(jt)+0.5)*1./12.
  96. # Heat fluxes
  97. if l_htf:
  98. print '\n\n +++ '+cnexec+' => Starting heat flux diags! \n => '+cf_F_in
  99. #cv_qnt = vdic['NN_QNET']
  100. cv_qsr = vdic['NN_QSOL']
  101. id_in = Dataset(cf_F_in)
  102. list_variables = id_in.variables.keys()
  103. l_qnt = False ; jv=0
  104. for cv_qnt in cvhtf:
  105. if cv_qnt in list_variables[:]:
  106. l_qnt = True
  107. if jv == 0: QNT_m = nmp.zeros((Nt,nj,ni))
  108. print ' * Adding '+str(ishtf[jv])+'*'+cv_qnt+' to Qnet!'
  109. QNT_m[:,:,:] = id_in.variables[cv_qnt][:,:,:] + ishtf[jv]*QNT_m[:,:,:]
  110. jv=jv+1
  111. l_qsr = False
  112. if cv_qsr in list_variables[:]:
  113. l_qsr = True
  114. print ' * Adding '+cv_qsr+' to Qsol!'
  115. QSR_m = id_in.variables[cv_qsr][:,:,:]
  116. id_in.close()
  117. l_htf = l_qnt ; # Forgeting heat flux if both Qnet is missing...
  118. if l_qnt or l_qsr:
  119. vqnt = [] ; vqsr = []
  120. if l_qnt: vqnt = nmp.zeros(Nt)
  121. if l_qsr: vqsr = nmp.zeros(Nt)
  122. for jt in range(Nt):
  123. # Mind the 2 point folding overlap, must not be included in sum!
  124. if l_qnt: vqnt[jt] = nmp.sum( QNT_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-9 ; # to PW
  125. if l_qsr: vqsr[jt] = nmp.sum( QSR_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-9 ; # to PW
  126. cf_out = vdic['DIAG_D']+'/mean_htf_'+CONFEXP+'_GLO.nc'
  127. bnc.wrt_appnd_1d_series(vtime, vqnt, cf_out, 'Qnet',
  128. cu_t='year', cu_d='PW', cln_d ='Globally averaged net heat flux (nemo:'+vdic['NN_QNET']+')',
  129. vd2=vqsr, cvar2='Qsol', cln_d2='Globally averaged net solar heat flux (nemo:'+vdic['NN_QSOL']+')')
  130. print ' +++ '+cnexec+' => Done with heat flux diags!\n'
  131. # Freshwater fluxes
  132. if l_fwf:
  133. print '\n\n +++ '+cnexec+' => Starting freshwater flux diags!'
  134. #cv_fwf = vdic['NN_FWF']
  135. #cv_emp = vdic['NN_EMP']
  136. cv_prc = vdic['NN_P']
  137. cv_rnf = vdic['NN_RNF']
  138. cv_clv = vdic['NN_CLV']
  139. #cv_evp = vdic['NN_E']
  140. id_in = Dataset(cf_F_in)
  141. list_variables = id_in.variables.keys()
  142. # E - P - R (possible sum!)
  143. jv=0
  144. for cv_fwf in cvfwf:
  145. if not cv_fwf in list_variables[:]: print 'PROBLEM with fwf! '+cnexec+'!'; sys.exit(0)
  146. if jv == 0: FWF_m = nmp.zeros((Nt,nj,ni))
  147. print ' * Adding '+str(isfwf[jv])+'*'+cv_fwf+' to E-P-R!'
  148. FWF_m[:,:,:] = id_in.variables[cv_fwf][:,:,:] + isfwf[jv]*FWF_m[:,:,:]
  149. jv=jv+1
  150. # E (possible sum!)
  151. l_evp = False
  152. if vdic['NN_E'] != 'X':
  153. cvevp, isevp = bt.var_and_signs(vdic['NN_E'])
  154. print ' cvevp => ', cvevp ; # might be the sum of variables
  155. l_evp = True
  156. jv=0
  157. for cv_evp in cvevp:
  158. if jv == 0: EVP_m = nmp.zeros((Nt,nj,ni))
  159. print ' * Adding '+str(isevp[jv])+'*'+cv_evp+' to E!'
  160. EVP_m[:,:,:] = id_in.variables[cv_evp][:,:,:] + isevp[jv]*EVP_m[:,:,:]
  161. jv=jv+1
  162. # E - P (possible sum!)
  163. l_emp = False
  164. if vdic['NN_EMP'] != 'X':
  165. cvemp, isemp = bt.var_and_signs(vdic['NN_EMP'])
  166. print ' cvemp => ', cvemp ; # might be the sum of variables
  167. l_emp = True
  168. jv=0
  169. for cv_emp in cvemp:
  170. if jv == 0: EMP_m = nmp.zeros((Nt,nj,ni))
  171. print ' * Adding '+str(isemp[jv])+'*'+cv_emp+' to E-P!'
  172. EMP_m[:,:,:] = id_in.variables[cv_emp][:,:,:] + isemp[jv]*EMP_m[:,:,:]
  173. jv=jv+1
  174. # P
  175. l_prc = False
  176. if cv_prc in list_variables[:]:
  177. l_prc = True
  178. PRC_m = id_in.variables[cv_prc][:,:,:]
  179. print ' *** P ('+cv_prc+') read!'
  180. # R
  181. l_rnf = False
  182. if cv_rnf in list_variables[:]:
  183. l_rnf = True
  184. RNF_m = id_in.variables[cv_rnf][:,:,:]
  185. print ' *** Runoffs ('+cv_rnf+') read!'
  186. # Calving
  187. l_clv = False
  188. if cv_clv in list_variables[:]:
  189. l_clv = True
  190. CLV_m = id_in.variables[cv_clv][:,:,:]
  191. print ' *** Calving ('+cv_clv+') read!'
  192. id_in.close()
  193. if l_emp and not l_rnf:
  194. l_rnf = True
  195. RNF_m = nmp.zeros((nj0,ni0))
  196. RNF_m = - ( FWF_m - EMP_m )
  197. vfwf = nmp.zeros(Nt)
  198. vemp = [] ; vrnf = [] ; vprc = [] ; vclv = [] ; vevp = []
  199. if l_emp: vemp = nmp.zeros(Nt)
  200. if l_rnf: vrnf = nmp.zeros(Nt)
  201. if l_prc: vprc = nmp.zeros(Nt)
  202. if l_clv: vclv = nmp.zeros(Nt)
  203. if l_evp: vevp = nmp.zeros(Nt)
  204. for jt in range(Nt):
  205. # Mind the 2 point folding overlap, must not be included in sum!
  206. vfwf[jt] = nmp.sum( FWF_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-3 ; # to Sv
  207. if l_emp: vemp[jt] = nmp.sum( EMP_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-3 ; # to Sv
  208. if l_rnf: vrnf[jt] = nmp.sum( RNF_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-3 ; # to Sv
  209. if l_prc: vprc[jt] = nmp.sum( PRC_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-3 ; # to Sv
  210. if l_clv: vclv[jt] = nmp.sum( CLV_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-3 ; # to Sv
  211. if l_evp: vevp[jt] = nmp.sum( EVP_m[jt,:-2,:-2]*Xarea_t[:-2,:-2] ) * 1.E-3 ; # to Sv
  212. cf_out = vdic['DIAG_D']+'/mean_fwf_'+CONFEXP+'_GLO.nc'
  213. bnc.wrt_appnd_1d_series(vtime, vfwf, cf_out, 'EmPmR',
  214. cu_t='year', cu_d='Sv', cln_d ='Globally averaged net freshwater flux (nemo:'+vdic['NN_FWF']+')',
  215. vd2=vemp, cvar2='EmP', cln_d2='Globally averaged Evap - Precip (nemo:'+vdic['NN_EMP']+')',
  216. vd3=vrnf, cvar3='R', cln_d3='Globally averaged continental runoffs (nemo:'+vdic['NN_RNF']+')',
  217. vd4=vprc, cvar4='P', cln_d4='Globally averaged total precip (nemo:'+vdic['NN_P']+')',
  218. vd5=vclv, cvar5='ICalv', cln_d5='Globally averaged ice calving from icebergs (nemo:'+vdic['NN_CLV']+')',
  219. vd6=vevp, cvar6='E', cln_d6='Globally averaged evaporation (nemo:'+vdic['NN_E']+')')
  220. print ' +++ '+cnexec+' => Done with freshwater flux diags!\n'
  221. ####################################
  222. # MLD time serie in different boxes:
  223. ####################################
  224. #print '\n\n +++ '+cnexec+' => Starting MLD diags!'
  225. #l_mld = False
  226. #print '\nSpatially-averaged MLD in different boxes'
  227. #
  228. #cvar = vdic['NN_MLD']
  229. #id_in = Dataset(cf_T_in)
  230. #list_variables = id_in.variables.keys()
  231. #if cvar in list_variables[:]: # check if MLD variable is present!
  232. # MLD_m = id_in.variables[cvar][:,:,:]
  233. # print ' *** MLD ('+cvar+') found and read!'
  234. # l_mld = True
  235. #else:
  236. # print ' *** OOPS! MLD ('+cvar+') not found, skipping MLD time series diag...'
  237. #id_in.close()
  238. #if l_mld:
  239. #
  240. # [ nt, nj0, ni0 ] = MLD_m.shape
  241. #
  242. # if nt != 12: print 'ERROR: '+cnexec+' => only treating monthly data so far...'; sys.exit(0)
  243. #
  244. # if [ nj0, ni0 ] != [ nj, ni ]: print 'ERROR: '+cnexec+' => Field and metrics do not agree in size!'; sys.exit(0)
  245. #
  246. # vtime = nmp.zeros(nt)
  247. # for jt in range(nt): vtime[jt] = float(jyear) + (float(jt)+0.5)*1./12.
  248. #
  249. # mask2d = nmp.zeros((nj,ni))
  250. #
  251. # # Reading boxes definitions into barakuda_orca.py:
  252. # cname_b = bo.cname_mld_boxes
  253. # nb_boxes = len(cname_b)
  254. #
  255. # for ib in range(nb_boxes):
  256. #
  257. # cbox = cname_b[ib] ; print ' *** treating '+cvar+' for '+cbox+', ('+bo.clgnm_mld_boxes[ib]+')'
  258. #
  259. # i1 = nmp.argmax(xlat[nj-1,:])
  260. # j1 = 0 ; i2 = ni-1 ; j2 = nj-1
  261. #
  262. # rx1 = bo.r_lon_p1_mld[ib] ; rx2 = bo.r_lon_p2_mld[ib] ; ry1 = bo.r_lat_p1_mld[ib] ; ry2 = bo.r_lat_p2_mld[ib]
  263. #
  264. # # Need to itterate because ORCA grid distorded in the North...
  265. # vold = [ -999, -999, -999, -999 ] ; itt = 0
  266. # while [ i1, i2, j1, j2 ] != vold and itt < 10 :
  267. # itt = itt+1
  268. # #print ' .... itt =', itt
  269. # vold = [ i1, i2, j1, j2 ]
  270. # #print 'seraching for rx1, rx2, ry1, ry2 = ', rx1, rx2, ry1, ry2
  271. # if ry1 > -900.: j1 = bt.find_index_from_value( ry1, xlat[:,i1] )
  272. # if rx1 > -900.: i1 = bt.find_index_from_value( rx1, xlon[j1,:] )
  273. # if rx2 > -900.: i2 = bt.find_index_from_value( rx2, xlon[j2,:] )
  274. # if ry1 > -900.: j1 = bt.find_index_from_value( ry1, xlat[:,i1] )
  275. # if ry2 > -900.: j2 = bt.find_index_from_value( ry2, xlat[:,i2] )
  276. # #print ' => i1, i2, j1, j2 =>', i1, i2, j1, j2, '\n'
  277. #
  278. #
  279. #
  280. # mask2d[:,:] = 0.
  281. # mask2d[j1:j2,i1:i2] = mask[0,j1:j2,i1:i2]
  282. #
  283. # Vts = bo.mean_2d(MLD_m, mask2d[:,:], Xa[:,:])
  284. #
  285. # # NETCDF:
  286. # cf_out = vdic['DIAG_D']+'/mean_'+cvar+'_'+CONFEXP+'_'+cbox+'.nc' ; cv1 = cvar
  287. #
  288. # bnc.wrt_appnd_1d_series(vtime, Vts, cf_out, cv1,
  289. # cu_t='year', cu_d='m', cln_d='2D-average of '+cvar+' on rectangular box '+cbox)
  290. #
  291. #print ' +++ '+cnexec+' => Done with MLD diags!\n'
  292. ###############################################
  293. # 2D (surface) averaging for T,S, SSH and MLD #
  294. ###############################################
  295. print '\n\n +++ '+cnexec+' => Starting 2D surface averaging diags!'
  296. id_in = Dataset(cf_T_in)
  297. list_variables = id_in.variables.keys()
  298. jvar = 0
  299. for cvar in [ vdic['NN_SST'], vdic['NN_SSS'], vdic['NN_SSH'], vdic['NN_MLD'] ]:
  300. if cvar in list_variables:
  301. print ' *** reading '+cvar+' into '+cf_T_in
  302. if cvar in ['thetao','so','votemper','vosaline']:
  303. Xs_m = id_in.variables[cvar][:,0,:,:]
  304. else:
  305. Xs_m = id_in.variables[cvar][:,:,:]
  306. print ' ...read!'
  307. ( nt, nj0, ni0 ) = Xs_m.shape
  308. if nt != 12: print 'ERROR: '+cnexec+' => only treating monthly data so far...'; sys.exit(0)
  309. if ( nj0, ni0 ) != ( nj, ni ): print 'ERROR: '+cnexec+' => Field and metrics do not agree in size!'; sys.exit(0)
  310. if jvar == 0:
  311. vtime = nmp.zeros(nt)
  312. for jt in range(nt): vtime[jt] = float(jyear) + (float(jt)+0.5)*1./12.
  313. print ' * Montly calendar: ', vtime[:]
  314. joce = 0
  315. for cocean in list_basin_names[:]:
  316. print 'Treating '+cvar+' for '+cocean
  317. Vts = bo.mean_2d(Xs_m, mask[joce,:,:], Xa[:,:])
  318. cf_out = vdic['DIAG_D']+'/mean_'+cvar+'_'+CONFEXP+'_'+cocean+'.nc' ; cv1 = cvar
  319. bnc.wrt_appnd_1d_series(vtime, Vts, cf_out, cv1,
  320. cu_t='year', cu_d='m', cln_d='2D-average of '+cvar+' over '+list_basin_lgnms[joce])
  321. joce = joce + 1
  322. jvar = jvar + 1
  323. else:
  324. print 'WARNING: '+cnexec+' => '+cvar+' was not found in '+cf_T_in
  325. id_in.close()
  326. print ' +++ '+cnexec+' => Done with 2D surface averaging diags!\n'
  327. ###################
  328. # El nino box 3.4 #
  329. ###################
  330. print '\n\n +++ '+cnexec+' => Starting ENSO diag!'
  331. print lon1_nino, lon2_nino, lat1_nino, lat2_nino
  332. ( i1, j1 ) = bo.ij_from_xy(lon1_nino, lat1_nino, xlon, xlat)
  333. ( i2, j2 ) = bo.ij_from_xy(lon2_nino, lat2_nino, xlon, xlat)
  334. print ' Nino box 3.4, longitude: '+str(xlon[j1,i1])+' => '+str(xlon[j2,i2])+' \ latitude: '+str(xlat[j1,i1])+' => '+str(xlat[j2,i2])
  335. id_in = Dataset(cf_T_in)
  336. if vdic['NN_SST'] == 'thetao':
  337. Xs_m = id_in.variables[vdic['NN_SST']][:,0,:,:]
  338. else:
  339. Xs_m = id_in.variables[vdic['NN_SST']][:,:,:]
  340. id_in.close()
  341. Vts = bo.mean_2d(Xs_m[:,j1:j2+1,i1:i2+1], mask[0,j1:j2+1,i1:i2+1], Xa[j1:j2+1,i1:i2+1])
  342. cunit='deg.C'
  343. if Vts[0] > 100.: cunit='K'
  344. cf_out = vdic['DIAG_D']+'/Nino34_'+CONFEXP+'.nc' ; cv1 = vdic['NN_SST']
  345. bnc.wrt_appnd_1d_series(vtime, Vts, cf_out, cv1, cu_t='year', cu_d=cunit,
  346. cln_d='2D-average of SST over Nino box 3.4 for ENSO computation later')
  347. print ' +++ '+cnexec+' => Done with ENSO diags!\n'
  348. ##########################################################
  349. # AMO (Atlantic Multidecadal Oscillation) Index
  350. ##########################################################
  351. print '\n\n +++ '+cnexec+' => Starting AMO diag!'
  352. # Finding index jb of Atlantic mask:
  353. jb=0
  354. while list_basin_names[jb] != 'atl' : jb=jb+1
  355. print ' *** index Atl is ', jb, list_basin_names[jb]
  356. msk_natl = nmp.zeros((nj,ni))
  357. msk_natl[:,:] = mask[jb,:,:]
  358. msk_natl[nmp.where(xlat< 2.)] = 0
  359. msk_natl[nmp.where(xlat>68.)] = 0
  360. #debug:bnc.write_2d_mask('mask_AMO.nc', msk_natl)
  361. id_in = Dataset(cf_T_in)
  362. if vdic['NN_SST'] == 'thetao':
  363. Xs_m = id_in.variables[vdic['NN_SST']][:,0,:,:]
  364. else:
  365. Xs_m = id_in.variables[vdic['NN_SST']][:,:,:]
  366. id_in.close()
  367. Vts = bo.mean_2d(Xs_m, msk_natl, Xa)
  368. cunit='deg.C'
  369. if Vts[0] > 100.: cunit='K'
  370. cf_out = vdic['DIAG_D']+'/mean_SST_NAtl_'+CONFEXP+'.nc' ; cv1 = vdic['NN_SST']
  371. bnc.wrt_appnd_1d_series(vtime, Vts, cf_out, cv1, cu_t='year', cu_d=cunit,
  372. cln_d='2D-average of SST over North Atlantic to compute AMO later')
  373. del msk_natl, Vts
  374. print ' +++ '+cnexec+' => Done with AMO diag!\n'
  375. print '\n *** EXITING '+cnexec+' for year '+cyear+' !\n'