ec_build_curl.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #!/usr/bin/env python
  2. #
  3. # L. Brodeau, 2017
  4. #
  5. # Compute curl, aka relative vorticity from 2D vector on a lat-lon spherical
  6. # grid a la ECMWF
  7. #
  8. import sys
  9. import numpy as nmp
  10. from netCDF4 import Dataset
  11. import string
  12. import barakuda_tool as bt
  13. cv_crl='CURL'
  14. radius_Earth = 6371. ; # km !!! Not m !!! => curl will be in XXX !!!
  15. to_rad = nmp.pi/180.
  16. #jt1=10
  17. #jt2=12
  18. if len(sys.argv) != 4:
  19. print 'Usage: '+sys.argv[0]+' <FILE_VEC_V.nc> <name_Vx> <name_Vy>'
  20. sys.exit(0)
  21. cf_Vx = sys.argv[1]
  22. cv_Vx = sys.argv[2]
  23. cv_Vy = sys.argv[3]
  24. cf_Vy = string.replace(cf_Vx, cv_Vx, cv_Vy)
  25. cf_crl = string.replace(cf_Vx, cv_Vx, cv_crl)
  26. print " cf_Vx = ", cf_Vx
  27. print " cf_Vy = ", cf_Vy
  28. print " cf_crl = ", cf_crl
  29. print "\n"
  30. rmult = 1.
  31. if cv_Vx == 'EWSS':
  32. rmult = 1000.
  33. CUNIT_CRL= '???'
  34. if cv_Vx == 'U10M':
  35. rmult = 1.
  36. CUNIT_CRL= 's^-1'
  37. # TAUY
  38. # ~~~~
  39. bt.chck4f(cf_Vy)
  40. f_Vy_in = Dataset(cf_Vy)
  41. # Extracting the longitude and 1D array:
  42. vlon = f_Vy_in.variables['lon'][:]
  43. clnm_lon = f_Vy_in.variables['lon'].long_name ; cunt_lon = f_Vy_in.variables['lon'].units
  44. csnm_lon = f_Vy_in.variables['lon'].standard_name
  45. print 'LONGITUDE: ', clnm_lon, cunt_lon, csnm_lon
  46. # Extracting the longitude 1D array:
  47. vlat = f_Vy_in.variables['lat'][:]
  48. clnm_lat = f_Vy_in.variables['lat'].long_name ; cunt_lat = f_Vy_in.variables['lat'].units
  49. csnm_lat = f_Vy_in.variables['lat'].standard_name
  50. print 'LATGITUDE: ', clnm_lat, cunt_lat, csnm_lat
  51. # Extracting time 1D array:
  52. vtime = f_Vy_in.variables['time'][:] ; cunt_time = f_Vy_in.variables['time'].units
  53. print 'TIME: ', cunt_time, '\n'
  54. # Extracting a variable, ex: "t" the 3D+T field of temperature:
  55. xty0 = f_Vy_in.variables[cv_Vy][0,:,:]
  56. cunt_Vy = f_Vy_in.variables[cv_Vy].units
  57. code_Vy = f_Vy_in.variables[cv_Vy].code
  58. ctab_Vy = f_Vy_in.variables[cv_Vy].table
  59. print cv_Vy+': ', cunt_Vy, code_Vy, ctab_Vy, '\n'
  60. # TAUX
  61. # ~~~
  62. bt.chck4f(cf_Vx)
  63. f_Vx_in = Dataset(cf_Vx)
  64. xtx0 = f_Vx_in.variables[cv_Vx][0,:,:]
  65. cunt_Vx = f_Vx_in.variables[cv_Vx].units
  66. code_Vx = f_Vx_in.variables[cv_Vx].code
  67. ctab_Vx = f_Vx_in.variables[cv_Vx].table
  68. print cv_Vx+': ', cunt_Vx, code_Vx, ctab_Vx, '\n'
  69. # Checking dimensions
  70. # ~~~~~~~~~~~~~~~~~~~
  71. dim_Vy = xty0.shape ; dim_Vx = xtx0.shape
  72. if dim_Vy != dim_Vx:
  73. print 'Shape problem!!!'; print dim_Vy , dim_Vx
  74. print '\n'
  75. Nt = len(vtime)
  76. (nj, ni) = dim_Vy
  77. print 'ni, nj, Nt = ', ni, nj, Nt
  78. # Building Curl
  79. # ~~~~~~~~~~~
  80. xcurl = nmp.zeros(( nj, ni ))
  81. dlamx2 = 2.*(vlon[1] - vlon[0])*to_rad
  82. dphix2 = 2.*(vlat[0] - vlat[1])*to_rad
  83. xcosphi = nmp.zeros(( nj, ni ))
  84. one_on_xcosphi = nmp.zeros(( nj, ni ))
  85. for ji in range(ni):
  86. xcosphi[:,ji] = nmp.cos(vlat[:]*to_rad)
  87. one_on_xcosphi[:,:] = 1./xcosphi[:,:]
  88. print ' dlamx2, dphix2 = ', dlamx2, dphix2
  89. xtmp = nmp.zeros(( nj, ni ))
  90. # Creating output file
  91. # ~~~~~~~~~~~~~~~~~~~~
  92. f_out = Dataset(cf_crl, 'w', format='NETCDF3_CLASSIC')
  93. # Dimensions:
  94. f_out.createDimension('lon', ni)
  95. f_out.createDimension('lat', nj)
  96. f_out.createDimension('time', None)
  97. # Variables
  98. id_lon = f_out.createVariable('lon','f4',('lon',))
  99. id_lat = f_out.createVariable('lat','f4',('lat',))
  100. id_tim = f_out.createVariable('time','f4',('time',))
  101. id_crl = f_out.createVariable(cv_crl,'f4',('time','lat','lon',))
  102. # Attributes
  103. id_tim.units = cunt_time
  104. id_lat.long_name = clnm_lat
  105. id_lat.units = cunt_lat
  106. id_lat.standard_name = csnm_lat
  107. id_lon.long_name = clnm_lon
  108. id_lon.units = cunt_lon
  109. id_lon.standard_name = csnm_lon
  110. id_tim.units = cunt_time
  111. id_crl.long_name = 'Curl of vector '+cv_Vx+' and '+cv_Vy
  112. id_crl.units = CUNIT_CRL
  113. id_crl.code = '???'
  114. id_crl.table = '128'
  115. f_out.About = 'Created by Barakuda using '+cv_Vx+' and '+cv_Vy+'.'
  116. # Filling variables:
  117. id_lat[:] = vlat[:]
  118. id_lon[:] = vlon[:]
  119. for jt in range(Nt):
  120. print ' *** jt = ', jt
  121. xty = rmult*f_Vy_in.variables[cv_Vy][jt,:,:]
  122. xtx = rmult*f_Vx_in.variables[cv_Vx][jt,:,:]
  123. xtmp[:,:] = xtx[:,:] * xcosphi[:,:]
  124. xcurl[1:nj-1,1:ni-1] = ( xty[1:nj-1,2:ni] - xty[1:nj-1,0:ni-2] ) / dlamx2 \
  125. - one_on_xcosphi[1:nj-1,1:ni-1]*( xtmp[2:nj,1:ni-1] - xtmp[0:nj-2,1:ni-1] ) / dphix2
  126. # If periodic East-West:
  127. # Easter side:
  128. xcurl[1:nj-1,ni-1] = ( xty[1:nj-1,0] - xty[1:nj-1,ni-2] ) / dlamx2 \
  129. - one_on_xcosphi[1:nj-1,ni-1]*( xtmp[2:nj,ni-1] - xtmp[0:nj-2,ni-1] ) / dphix2
  130. # Western side:
  131. xcurl[1:nj-1,0] = ( xty[1:nj-1,1] - xty[1:nj-1,ni-1] ) / dlamx2 \
  132. - one_on_xcosphi[1:nj-1,0]*( xtmp[2:nj,0] - xtmp[0:nj-2,0] ) / dphix2
  133. xcurl[:,:] = -1./radius_Earth * xcurl[:,:]
  134. id_tim[jt] = vtime[jt]
  135. id_crl[jt,:,:] = xcurl[:,:]
  136. f_out.close()
  137. f_Vx_in.close()
  138. f_Vy_in.close()
  139. print 'Bye!'