budget_rectangle_box.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. #!/usr/bin/env python
  2. # B a r a K u d a
  3. #
  4. # Budget and other stuffs on rectangular boxes!
  5. #
  6. # L. Brodeau, 2013
  7. import sys
  8. import numpy as nmp
  9. from netCDF4 import Dataset
  10. from os.path import basename
  11. import barakuda_tool as bt
  12. import barakuda_ncio as bnc
  13. from barakuda_physics import sigma0
  14. #next = 10
  15. next = 10
  16. # The density of seawater is about 1025 kg/m^3 and the specific heat is about 3850 J/(kg C)
  17. #rho0 = 1025. ; # kg/m^3
  18. #rCp = 3850. ; # 3850 J/kg/deg.C
  19. rho0 = 1000. ; # kg/m^3 => to stay consistent with cdftransportiz.f90 of CDFTOOLS...
  20. rCp = 4000. ; # 3850 J/kg/deg.C => to stay consistent with cdftransportiz.f90 of CDFTOOLS...
  21. #l_plot_debug = True
  22. l_plot_debug = False
  23. venv_needed = {'ORCA','EXP','CPREF','DIAG_D','MM_FILE','FILE_DEF_BOXES','NN_T','NN_S', \
  24. 'NN_SST','NN_SSS','NN_SSH'}
  25. vdic = bt.check_env_var(sys.argv[0], venv_needed)
  26. corca = vdic['ORCA']
  27. CONFEXP = corca+'-'+vdic['EXP']
  28. cname_script = basename(sys.argv[0])
  29. print '\n'+cname_script
  30. narg = len(sys.argv)
  31. if narg < 3 or narg > 4:
  32. print 'Usage: '+cname_script+' <year> <depth for surface properties> (uv)'
  33. print ' by specifying "uv" as 3rd argument, budget will be extended to'
  34. print ' some variables found in grid_U and grid_V files such as wind stress\n'
  35. sys.exit(0)
  36. cy = sys.argv[1] ; jy=int(cy)
  37. czs= sys.argv[2] ; zs = float(int(czs))
  38. # Shall we need U and V files???
  39. luv = False
  40. if narg == 4 and sys.argv[3] == 'uv':
  41. luv = True
  42. venv_uv = {'NN_TAUX','NN_TAUY'}
  43. vdic_uv = bt.check_env_var(sys.argv[0], venv_uv)
  44. path_fig = vdic['DIAG_D']+'/'
  45. # Image type? eps, png, jpg...
  46. #FIG_FORM = 'pdf'
  47. FIG_FORM = 'png'
  48. # First will read name and coordinates of rectangular boxes to treat into file FILE_DEF_BOXES
  49. ##############################################################################################
  50. vboxes, vi1, vj1, vi2, vj2 = bt.read_coor(vdic['FILE_DEF_BOXES'])
  51. nbb = len(vboxes)
  52. print ''
  53. # Checking presence of NEMO files:
  54. cfroot = vdic['CPREF']+cy+'0101_'+cy+'1231'
  55. cf_in_T = cfroot+'_grid_T.nc'; bt.chck4f(cf_in_T, script_name=cname_script)
  56. if luv:
  57. cf_in_U = cfroot+'_grid_U.nc'; bt.chck4f(cf_in_U, script_name=cname_script)
  58. cf_in_V = cfroot+'_grid_V.nc'; bt.chck4f(cf_in_V, script_name=cname_script)
  59. # Coordinates, mask and metrics:
  60. bt.chck4f(vdic['MM_FILE'], script_name=cname_script)
  61. id_mm = Dataset(vdic['MM_FILE'])
  62. Xmask = id_mm.variables['tmask'] [0,:,:,:]
  63. ze1t = id_mm.variables['e1t'] [0,:,:]
  64. ze2t = id_mm.variables['e2t'] [0,:,:]
  65. ve3t = id_mm.variables['e3t_1d'] [0,:]
  66. zlon = id_mm.variables['nav_lon'] [:,:]
  67. zlat = id_mm.variables['nav_lat'] [:,:]
  68. vzt = id_mm.variables['gdept_1d'][0,:]
  69. vzw = id_mm.variables['gdepw_1d'][0,:]
  70. id_mm.close()
  71. lqnet = False ; lqsw = False ; lpme = False; ltau = False
  72. # NEMO output, Grid T
  73. # ~~~~~~~~~~~~~~~~~~~
  74. id_in_T = Dataset(cf_in_T)
  75. list_variables = id_in_T.variables.keys()
  76. Vtime = id_in_T.variables['time_counter'][:]
  77. if vdic['NN_SST'] == 'thetao':
  78. Zsst = id_in_T.variables[vdic['NN_SST']][:,0,:,:]
  79. else:
  80. Zsst = id_in_T.variables[vdic['NN_SST']][:,:,:]
  81. if vdic['NN_SSS'] == 'so':
  82. Zsss = id_in_T.variables[vdic['NN_SSS']][:,0,:,:]
  83. else:
  84. Zsss = id_in_T.variables[vdic['NN_SSS']][:,:,:]
  85. Zssh = id_in_T.variables[vdic['NN_SSH']][:,:,:]
  86. Xtemp = id_in_T.variables[vdic['NN_T']][:,:,:,:]
  87. Xsali = id_in_T.variables[vdic['NN_S']][:,:,:,:]
  88. if 'sohefldo' in list_variables[:]:
  89. Zqnet = id_in_T.variables['sohefldo'] [:,:,:] ; # Net Downward Heat Flux
  90. lqnet = True
  91. if 'tohfls' in list_variables[:]:
  92. Zqnet = id_in_T.variables['tohfls'] [:,:,:] ; # Net Downward Heat Flux
  93. lqnet = True
  94. if 'soshfldo' in list_variables[:]:
  95. Zqsw = id_in_T.variables['soshfldo'] [:,:,:] ; # Shortwave Radiation
  96. lqsw = True
  97. if 'rsntds' in list_variables[:]:
  98. Zqsw = id_in_T.variables['rsntds'] [:,:,:] ; # Shortwave Radiation
  99. lqsw = True
  100. # Want PmE (positive when ocean gains FW), in NEMO files its the oposite EmP...
  101. if 'wfo' in list_variables[:]:
  102. Zpme = -id_in_T.variables['wfo'] [:,:,:] ; # wfo same as below = EmP, > 0 when ocean losing water
  103. lpme = True
  104. if 'sowaflup' in list_variables[:]:
  105. Zpme = -id_in_T.variables['sowaflup'] [:,:,:] ; # Net Downward Heat Flux
  106. # # sowaflup = EmP (>0 if more evaporation than P)
  107. lpme = True
  108. print '(has ',Xtemp.shape[0],' time snapshots)\n'
  109. id_in_T.close()
  110. [ Nt, nk, nj, ni ] = Xtemp.shape ; print 'Nt, nk, nj, ni =', Nt, nk, nj, ni
  111. Zss0 = sigma0( Zsst, Zsss )
  112. print len(ve3t[:])
  113. if len(ve3t[:]) != nk: print 'Problem with nk!!!'; sys.exit(0)
  114. # NEMO output, Grid U and V
  115. # ~~~~~~~~~~~~~~~~~~~~~~~~~
  116. if luv:
  117. id_in_U = Dataset(cf_in_U)
  118. list_variables = id_in_U.variables.keys()
  119. if vdic_uv['NN_TAUX'] in list_variables[:]:
  120. Ztaux = id_in_U.variables[vdic_uv['NN_TAUX']][:,:,:] ; # Net Downward Heat Flux
  121. ltau = True
  122. print vdic_uv['NN_TAUX']+' found in '+cf_in_U
  123. else:
  124. print vdic_uv['NN_TAUX']+' NOT found in '+cf_in_U
  125. id_in_U.close()
  126. id_in_V = Dataset(cf_in_V)
  127. list_variables = id_in_V.variables.keys()
  128. if ltau and vdic_uv['NN_TAUY'] in list_variables[:]:
  129. Ztauy = id_in_V.variables[vdic_uv['NN_TAUY']][:,:,:] ; # Net Downward Heat Flux
  130. print vdic_uv['NN_TAUY']+' found in '+cf_in_V+'\n'
  131. else:
  132. print vdic_uv['NN_TAUY']+' NOT found in '+cf_in_V
  133. ltau = False
  134. id_in_V.close()
  135. if ltau:
  136. # Must interpolate Taux and Tauy on T-grid:
  137. Ztau = nmp.zeros(Nt*nj*ni) ; Ztau.shape = [ Nt, nj, ni ]
  138. xtmp1 = nmp.zeros(nj*ni) ; xtmp1.shape = [ nj, ni ]
  139. xtmp2 = nmp.zeros(nj*ni) ; xtmp2.shape = [ nj, ni ]
  140. for jm in range(Nt):
  141. xtmp1[:,1:] = 0.5*(Ztaux[jm,:,1:]+Ztaux[jm,:,:ni-1]) ; # u on Tgrid
  142. xtmp2[1:,:] = 0.5*(Ztauy[jm,1:,:]+Ztauy[jm,:nj-1,:]) ; # v on Tgrid
  143. Ztau[jm,:,:] = nmp.sqrt(xtmp1*xtmp1 + xtmp2*xtmp2)
  144. #print Ztau[3,100,:]
  145. #del Ztaux, Ztaux, xtmp1, xtmp2
  146. jks = 0
  147. for jk in range(nk-1):
  148. if zs >= vzw[jk] and zs < vzw[jk+1]: jks = jk+1
  149. czs = str(int(round(vzw[jks],0))) ; print czs
  150. print ' *** for depth '+czs+': jks = '+str(jks)+', depthw = '+str(vzw[jks])+' => '+czs+'m'
  151. print ' => will average from jk=0 to jk='+str(jks)+'-1 on T-points => X[:jks-1]'
  152. jks = jks - 1
  153. print ' => that\'s on T-points from jk=0 to jk='+str(jks)+' (depth of deepest T-point used ='+str(vzt[jks])+'m)'
  154. # Loop along boxes:
  155. for jb in range(nbb):
  156. cbox = vboxes[jb]
  157. i1 = vi1[jb]
  158. j1 = vj1[jb]
  159. i2 = vi2[jb]+1
  160. j2 = vj2[jb]+1
  161. print '\n *** Treating box '+cbox+' => ', i1, j1, i2-1, j2-1
  162. # Filling box arrays:
  163. # ~~~~~~~~~~~~~~~~~~~
  164. nx_b = i2 - i1
  165. ny_b = j2 - j1
  166. shape_array = [ Nt, nk, ny_b, nx_b ]
  167. XVolu = nmp.zeros(nk*ny_b*nx_b) ; XVolu.shape = [ nk, ny_b, nx_b ]
  168. ZArea = nmp.zeros( ny_b*nx_b) ; ZArea.shape = [ ny_b, nx_b ]
  169. Ztmp = nmp.zeros( ny_b*nx_b) ; Ztmp.shape = [ ny_b, nx_b ]
  170. Xs0 = nmp.zeros(nk*ny_b*nx_b) ; Xs0.shape = [ nk, ny_b, nx_b ]
  171. ssh_m = nmp.zeros(Nt) ; ssh_m.shape = [ Nt ]
  172. sst_m = nmp.zeros(Nt) ; sst_m.shape = [ Nt ]
  173. sss_m = nmp.zeros(Nt) ; sss_m.shape = [ Nt ]
  174. ss0_m = nmp.zeros(Nt) ; ss0_m.shape = [ Nt ]
  175. surf_T_m = nmp.zeros(Nt) ; surf_T_m.shape = [ Nt ]
  176. surf_S_m = nmp.zeros(Nt) ; surf_S_m.shape = [ Nt ]
  177. surf_s0_m = nmp.zeros(Nt) ; surf_s0_m.shape = [ Nt ]
  178. T_m = nmp.zeros(Nt) ; T_m.shape = [ Nt ]
  179. Tau_m = nmp.zeros(Nt) ; Tau_m.shape = [ Nt ]
  180. Qnet_m = nmp.zeros(Nt) ; Qnet_m.shape = [ Nt ]
  181. Qnet_x_S_m = nmp.zeros(Nt) ; Qnet_x_S_m.shape = [ Nt ]
  182. Qsw_m = nmp.zeros(Nt) ; Qsw_m.shape = [ Nt ]
  183. Qsw_x_S_m = nmp.zeros(Nt) ; Qsw_x_S_m.shape = [ Nt ]
  184. PmE_m = nmp.zeros(Nt) ; PmE_m.shape = [ Nt ]
  185. H_m = nmp.zeros(Nt) ; H_m.shape = [ Nt ] ; # Heat coNtent
  186. S_m = nmp.zeros(Nt) ; S_m.shape = [ Nt ]
  187. Vol_m = nmp.zeros(Nt) ; Vol_m.shape = [ Nt ] ; # Volume derived from SSH!
  188. # On the sea of the box only:
  189. ZArea[:,:] = ze1t[j1:j2, i1:i2]*ze2t[j1:j2, i1:i2]
  190. for jk in range(nk): XVolu[jk,:,:] = Xmask[jk, j1:j2, i1:i2]*ZArea[:,:]*ve3t[jk]
  191. ZArea[:,:] = Xmask[0, j1:j2, i1:i2]*ZArea[:,:]
  192. #if l_plot_debug: bp.check_with_fig_2(ZArea, ZArea*0.+1., 'ZArea', fig_type=FIG_FORM)
  193. Tot_area = nmp.sum(ZArea) ; print 'Total area of '+cbox+' (m^2): ', Tot_area
  194. Tot_vol = nmp.sum(XVolu)
  195. Tot_vol_jks = nmp.sum(XVolu[:jks,:,:])
  196. for jm in range(Nt):
  197. # 3D sigma0 density for current month
  198. Xs0[:,:,:] = 0.
  199. Xs0[:,:,:] = sigma0( Xtemp[jm,:, j1:j2, i1:i2], Xsali[jm,:, j1:j2, i1:i2] )
  200. # Mean SSH
  201. ssh_m[jm] = nmp.sum(Zssh[jm, j1:j2, i1:i2]*ZArea) / Tot_area
  202. # Mean SST
  203. sst_m[jm] = nmp.sum(Zsst[jm, j1:j2, i1:i2]*ZArea) / Tot_area
  204. # Mean SSS
  205. sss_m[jm] = nmp.sum(Zsss[jm, j1:j2, i1:i2]*ZArea) / Tot_area
  206. # Mean SS0
  207. ss0_m[jm] = nmp.sum(Zss0[jm, j1:j2, i1:i2]*ZArea) / Tot_area
  208. # Mean surface temp (first Xm)
  209. surf_T_m[jm] = nmp.sum(Xtemp[jm, :jks, j1:j2, i1:i2]*XVolu[:jks,:,:]) / Tot_vol_jks
  210. # Mean temperature
  211. T_m[jm] = nmp.sum(Xtemp[jm, : , j1:j2, i1:i2]*XVolu[:,:,:]) / Tot_vol
  212. # Heat content in Peta Joules:
  213. H_m[jm] = nmp.sum(Xtemp[jm,:, j1:j2, i1:i2]*(XVolu/1.E6))*rho0*rCp * 1.E-9 ; # => PJ (E15)
  214. # Mean surface salinity (first Xm)
  215. surf_S_m[jm] = nmp.sum(Xsali[jm,:jks, j1:j2, i1:i2]*XVolu[:jks,:,:]) / Tot_vol_jks
  216. # Mean salinity
  217. S_m[jm] = nmp.sum(Xsali[jm,:, j1:j2, i1:i2]*XVolu) / Tot_vol
  218. # Mean surface sigma0 density (first Xm)
  219. surf_s0_m[jm] = nmp.sum(Xs0[:jks,:,:]*XVolu[:jks,:,:]) / Tot_vol_jks
  220. # Sea-ice area
  221. #Aice_m[jm] = nmp.sum(Zicec[jm,:,:]*ZArea) * 1.E-12; # Million km^2
  222. # For open-sea:
  223. #Ztmp[:,:] = 1. - Zicec[jm,:,:] ; # 1 => 100% open sea / 0 => 100% ice
  224. Ztmp[:,:] = 1.
  225. # ZArea is in m^2
  226. if ltau:
  227. # Surface wind stress:
  228. Tau_m[jm] = nmp.sum(Ztau[jm, j1:j2, i1:i2]*ZArea) / Tot_area
  229. # Surface heat flux
  230. if lqnet:
  231. rr = nmp.sum(Zqnet[jm, j1:j2, i1:i2]*ZArea)
  232. Qnet_m[jm] = rr / Tot_area # W/m^2
  233. Qnet_x_S_m[jm] = rr * 1.E-15 # PW
  234. # Shortwave heat flux
  235. if lqsw:
  236. rr = nmp.sum(Zqsw[jm, j1:j2, i1:i2]*ZArea)
  237. Qsw_m[jm] = rr / Tot_area # W/m^2
  238. Qsw_x_S_m[jm] = rr * 1.E-15 # PW
  239. # PmE
  240. if lpme: PmE_m[jm] = nmp.sum( Zpme[jm, j1:j2, i1:i2]*ZArea) * 1.E-9; # (Sv) 1 kg/m^2/s x S => 1E-3 m^3/s
  241. # # 1 Sv = 1E6 m^3
  242. # Volume associated with SSH
  243. Vol_m[jm] = nmp.sum(Zssh[jm, j1:j2, i1:i2]*ZArea) * 1.E-9; # km^3
  244. if l_plot_debug:
  245. VMN = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
  246. print ' *** month ', str(jm+1), '***'
  247. print 'Mean sst = ', sst_m[jm]
  248. print 'Mean ssh = ', ssh_m[jm]
  249. print 'Mean sss (0-'+czs+'m) = ', sss_m[jm]
  250. print 'Mean ss0 (0-'+czs+'m) = ', ss0_m[jm]
  251. print 'Mean T = ', T_m[jm]
  252. print 'Heat content (PJ) / ref T=0C => ', H_m[jm]
  253. if jm>0: print 'Volume heat flux (PW) / ref T=0C => ', (H_m[jm] - H_m[jm-1]) / (VMN[jm-1]*24.*3600.)
  254. print 'Mean S = ', S_m[jm]
  255. #print 'Sea-ice (10^6 km^2) = ', Aice_m[jm]
  256. print 'Shortwave Radiation (PW) = ', Qsw_m[jm]
  257. print 'Net surface heat flux (PW) = ', Qnet_m[jm], '\n'
  258. print 'Surface freshwater flux (Sv) = ', PmE_m[jm], '\n'
  259. print 'Volume associated with SSH (km^3) = ', Vol_m[jm], '\n'
  260. Vtime = nmp.zeros(Nt)
  261. for jm in range(Nt): Vtime[jm] = float(jy) + (float(jm)+0.5)/12.
  262. cc = 'Box-averaged '
  263. cf_out = vdic['DIAG_D']+'/budget_'+CONFEXP+'_box_'+cbox+'.nc'
  264. bnc.wrt_appnd_1d_series(Vtime, ssh_m, cf_out, 'ssh', cu_t='year', cu_d='m', cln_d=cc+'sea surface height',
  265. vd2=sst_m, cvar2='sst', cln_d2=cc+'sea surface temperature', cun2='deg.C',
  266. vd3=sss_m, cvar3='sss', cln_d3=cc+'sea surface salinity', cun3='PSU',
  267. vd4=surf_T_m, cvar4='surf_T', cln_d4=cc+'Temperature (first '+czs+'m)', cun4='deg.C',
  268. vd5=T_m, cvar5='theta', cln_d5=cc+'potential temperature', cun5='deg.C',
  269. vd6=H_m, cvar6='HC', cln_d6=cc+'heat content', cun6='PJ',
  270. vd7=surf_S_m, cvar7='surf_S', cln_d7=cc+'salinity (first '+czs+'m)', cun7='PSU',
  271. vd8=S_m, cvar8='S', cln_d8=cc+'salinity', cun8='PSU',
  272. vd9=ss0_m, cvar9='SSs0', cln_d9=cc+'sea surface sigma0 (sst&sss)', cun9='',
  273. vd10=surf_s0_m,cvar10='surf_s0', cln_d10=cc+'surface sigma0 (first '+czs+'m)', cun10=''
  274. )
  275. cf_out = vdic['DIAG_D']+'/budget_srf_flx_'+CONFEXP+'_box_'+cbox+'.nc'
  276. bnc.wrt_appnd_1d_series(Vtime, Qnet_m, cf_out, 'Qnet', cu_t='year', cu_d='W/m^2', cln_d=cc+'net heat flux',
  277. vd2=Qnet_x_S_m, cvar2='Qnet_x_S', cln_d2=cc+'net heat flux x Surface', cun2='PW',
  278. vd3=Qsw_m, cvar3='Qsw', cln_d3=cc+'solar radiation', cun3='W/m^2',
  279. vd4=Qsw_x_S_m, cvar4='Qsw_x_S', cln_d4=cc+'solar radiation x Surface', cun4='PW',
  280. vd5=PmE_m, cvar5='PmE', cln_d5=cc+'net freshwater flux', cun5='Sv',
  281. vd6=Tau_m, cvar6='Tau', cln_d6=cc+'wind stress module', cun6='N/m^2'
  282. )