cdfmhst.f90 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. PROGRAM cdfmhst
  2. !!--------------------------------------------------------------------
  3. !! *** PROGRAM cdfmhst ***
  4. !!
  5. !! ** Purpose : Compute Meridional Heat Salt Transport.
  6. !!
  7. !! ** Method : Starts from the mean VT, VS fields computed by cdfvT
  8. !! The program looks for the file "new_maskglo.nc". If it does not exist,
  9. !! only the calculation over all the domain is performed (this is adequate
  10. !! for a basin configuration like NATL4).
  11. !!
  12. !!
  13. !! history :
  14. !! Original : J.M. Molines (jan. 2005)
  15. !! J.M. Molines apr. 2005 : use modules
  16. !! A.M. Treguier (april 2006) adaptation to NATL4 case
  17. !! J.M. Molines ( April 2007) : add netcdf output
  18. !!--------------------------------------------------------------------
  19. !! $Rev: 298 $
  20. !! $Date: 2010-04-14 18:09:06 +0200 (Wed, 14 Apr 2010) $
  21. !! $Id: cdfmhst.f90 298 2010-04-14 16:09:06Z dussin9r $
  22. !!--------------------------------------------------------------
  23. USE netcdf
  24. !! * Modules used
  25. USE cdfio
  26. !! * Local variables
  27. IMPLICIT NONE
  28. INTEGER :: jj,jk,jt !: dummy loop index
  29. INTEGER :: narg, iargc !: command line
  30. INTEGER :: npiglo, npjglo, npk, Nt !: size of the domain
  31. INTEGER :: numout = 10
  32. INTEGER, DIMENSION(2) :: iloc
  33. LOGICAL :: llglo = .false. !: indicator for presence of new_maskglo.nc file
  34. LOGICAL :: lfncout = .false.
  35. REAL(KIND=4), DIMENSION(:,:), ALLOCATABLE :: e1v, e3v ,gphiv, zvt, zvs !: mask, metrics
  36. REAL(KIND=4), DIMENSION(:,:,:), ALLOCATABLE :: zmask
  37. REAL(KIND=4), DIMENSION (:,:), ALLOCATABLE :: dumlon !: dummy longitude = 0.
  38. REAL(KIND=4), DIMENSION (:,:), ALLOCATABLE :: dumlat !: latitude for i = north pole
  39. REAL(KIND=4), DIMENSION (:), ALLOCATABLE :: tim !LB
  40. REAL(KIND=8), DIMENSION (:,:), ALLOCATABLE :: zwkt, zwks
  41. REAL(KIND=8), DIMENSION (:,:,:), ALLOCATABLE :: ztrpt, ztrps !LB
  42. REAL(KIND=8) ,DIMENSION(:,:) , ALLOCATABLE :: vmerid_heat, vmerid_salt
  43. REAL(KIND=8) ,DIMENSION(:) , ALLOCATABLE :: vback_1d
  44. REAL(KIND=8) ,DIMENSION(:,:) , ALLOCATABLE :: merid_heat_glo, merid_heat_atl, merid_heat_pac,&
  45. & merid_heat_ind, merid_heat_inp
  46. REAL(KIND=8) ,DIMENSION(:,:) , ALLOCATABLE :: merid_salt_glo, merid_salt_atl, merid_salt_pac,&
  47. & merid_salt_ind, merid_salt_inp, zmtrp
  48. CHARACTER(LEN=256) :: cfileVT
  49. CHARACTER(LEN=256), PARAMETER :: cfileout='merid_heat_trp.dat', cfileouts='merid_salt_trp.dat'
  50. ! to be put in namelist eventually
  51. CHARACTER(LEN=256) :: cf_mm='mesh_mask.nc', cf_bm='new_maskglo.nc'
  52. ! NC output
  53. INTEGER :: jbasin, js, jvar !: dummy loop index
  54. INTEGER :: nbasins, ierr
  55. REAL(KIND=4), PARAMETER :: rpspval=9999.99
  56. REAL(KIND=4), DIMENSION(1) :: gdep
  57. CHARACTER(LEN=256) :: cdum, ctim
  58. CHARACTER(LEN=256), DIMENSION(:), ALLOCATABLE :: vcv_name_t, vcv_name_s !: array of var name for input
  59. CHARACTER(LEN=4), DIMENSION(4) :: cbasin= (/ '_GLO','_atl','_pac','_ind' /)
  60. ! constants
  61. REAL(KIND=4),PARAMETER :: rau0=1000., rcp=4000.
  62. CHARACTER(LEN=64) :: cv_out = 'mht', cv_dum
  63. CHARACTER(LEN=1024) :: cf_out = 'mht_1d.nc'
  64. INTEGER :: idf_out, idd_y, idv_lat, idd_t, idv_time, jt_pos
  65. INTEGER, DIMENSION(5) :: vid_heat, vid_salt
  66. REAL :: ryear
  67. REAL, PARAMETER :: rmissing = -9999.
  68. !! Read command line and output usage message if not compliant.
  69. narg= iargc()
  70. IF ( narg /= 3 ) THEN
  71. PRINT *,' Usage : cdfmhst <VTfile> <file_output.nc> <year>'
  72. PRINT *,' Files mesh_mask.nc and new_maskglo.nc must be in te current directory'
  73. PRINT *,' NetCDF Output in <file_output.nc> with variables :'
  74. PRINT *,' zomht_glo, zomht_atl, zomht_inp, zomht_pac'
  75. PRINT *,' zomst_glo, zomst_atl, zomst_inp, zomst_pac'
  76. STOP
  77. ENDIF
  78. CALL getarg(1, cfileVT)
  79. CALL getarg(2, cf_out)
  80. CALL getarg(3,cdum) ; READ(cdum,*) ryear
  81. npiglo= getdim (cfileVT,'x')
  82. npjglo= getdim (cfileVT,'y')
  83. npk = getdim (cfileVT,'depth')
  84. ctim = 'none'
  85. Nt = getdim (cfileVT,'time', cdtrue=ctim) !LB
  86. !LB:
  87. IF (Nt == 0) THEN
  88. PRINT *, 'Nt=0, assume 1' ; Nt = 1
  89. END IF
  90. !LB.
  91. PRINT *, 'npiglo=', npiglo
  92. PRINT *, 'npjglo=', npjglo
  93. PRINT *, 'npk =', npk
  94. PRINT *, 'Nt =', Nt
  95. ! Allocate arrays
  96. ALLOCATE ( zwkt(npiglo,npjglo), zmask(npiglo,npjglo,5), zvt(npiglo,npjglo) )
  97. ALLOCATE ( zwks(npiglo,npjglo) ,zvs(npiglo,npjglo) )
  98. ALLOCATE ( e1v(npiglo,npjglo),e3v(npiglo,npjglo), gphiv(npiglo,npjglo) )
  99. ALLOCATE ( ztrpt(npiglo,npjglo,Nt) , ztrps(npiglo,npjglo,Nt) )
  100. ALLOCATE ( vmerid_heat(npjglo,5), vmerid_salt(npjglo,5), vback_1d(npjglo) )
  101. ALLOCATE ( merid_heat_glo(npjglo,Nt), merid_heat_atl(npjglo,Nt), merid_heat_pac(npjglo,Nt) )
  102. ALLOCATE ( merid_heat_ind(npjglo,Nt), merid_heat_inp(npjglo,Nt) )
  103. ALLOCATE ( merid_salt_glo(npjglo,Nt), merid_salt_atl(npjglo,Nt), merid_salt_pac(npjglo,Nt) )
  104. ALLOCATE ( merid_salt_ind(npjglo,Nt), merid_salt_inp(npjglo,Nt) )
  105. ALLOCATE ( zmtrp(npjglo,Nt) )
  106. ALLOCATE ( dumlon(1,npjglo) , dumlat(1,npjglo))
  107. ALLOCATE ( tim(Nt) )
  108. ! create output fileset
  109. e1v(:,:) = getvar(cf_mm, 'e1v', 1,npiglo,npjglo)
  110. gphiv(:,:) = getvar(cf_mm, 'gphiv', 1,npiglo,npjglo)
  111. gdep(:) = getvare3(cf_mm, 'nav_lev' ,1)
  112. iloc=maxloc(gphiv)
  113. dumlat(1,:) = gphiv(iloc(1),:)
  114. dumlon(:,:) = 0. ! set the dummy longitude to 0
  115. ztrpt(:,:,:)= 0
  116. ztrps(:,:,:)= 0
  117. DO jt = 1, Nt !LB
  118. DO jk = 1,npk
  119. ! Get temperature and salinity at jk
  120. zvt(:,:) = getvar(cfileVT, 'vomevt', jk, npiglo,npjglo, ktime=jt) !LB
  121. zvs(:,:) = getvar(cfileVT, 'vomevs', jk, npiglo,npjglo, ktime=jt) !LB
  122. ! get e3v at level jk
  123. e3v(:,:) = getvar(cf_mm, 'e3v_0', jk,npiglo,npjglo, ldiom=.true.)
  124. zwkt(:,:) = zvt(:,:)*e1v(:,:)*e3v(:,:)
  125. zwks(:,:) = zvs(:,:)*e1v(:,:)*e3v(:,:)
  126. ! integrates vertically
  127. ztrpt(:,:,jt) = ztrpt(:,:,jt) + zwkt(:,:)*rau0*rcp
  128. ztrps(:,:,jt) = ztrps(:,:,jt) + zwks(:,:)
  129. END DO ! jk
  130. ! ~~~~~~
  131. ! global
  132. ! ~~~~~~~
  133. IF ( jt == 1 ) zmask(:,:,1) = getvar(cf_mm, 'vmask', 1, npiglo, npjglo) !LB
  134. DO jj=1,npjglo
  135. merid_heat_glo(jj,jt) = SUM( ztrpt(2:npiglo-1,jj,jt)*zmask(2:npiglo-1,jj,1) )
  136. merid_salt_glo(jj,jt) = SUM( ztrps(2:npiglo-1,jj,jt)*zmask(2:npiglo-1,jj,1) )
  137. END DO
  138. END DO ! jt
  139. ! Detects newmaskglo file
  140. INQUIRE( FILE=cf_bm, EXIST=llglo )
  141. nbasins=1 ! 1 basin (Global)
  142. IF ( llglo ) nbasins=4 ! 4 basins (Global, Pacific, Atlantic, Inidan)
  143. ! Allocate output variables
  144. ALLOCATE(vcv_name_t(nbasins), vcv_name_s(nbasins))
  145. PRINT *, ''
  146. IF ( llglo ) THEN
  147. DO jt = 1, Nt !LB
  148. ! Merid mean with mask
  149. ! Atlantic
  150. IF ( jt == 1 ) zmask(:,:,2) = getvar(cf_bm,'tmaskatl',1,npiglo,npjglo)
  151. DO jj=1,npjglo
  152. merid_heat_atl(jj,jt) = SUM( ztrpt(:,jj,jt)*zmask(:,jj,2) )
  153. merid_salt_atl(jj,jt) = SUM( ztrps(:,jj,jt)*zmask(:,jj,2) )
  154. END DO
  155. ! Pacific
  156. IF ( jt == 1 ) zmask(:,:,3) = getvar(cf_bm,'tmaskpac',1,npiglo,npjglo)
  157. DO jj=1,npjglo
  158. merid_heat_pac(jj,jt)= SUM( ztrpt(:,jj,jt)*zmask(:,jj,3) )
  159. merid_salt_pac(jj,jt)= SUM( ztrps(:,jj,jt)*zmask(:,jj,3) )
  160. END DO
  161. ! Indian
  162. IF ( jt == 1 ) zmask(:,:,4) = getvar(cf_bm,'tmaskind',1,npiglo,npjglo)
  163. DO jj=1,npjglo
  164. merid_heat_ind(jj,jt)= SUM( ztrpt(:,jj,jt)*zmask(:,jj,4) )
  165. merid_salt_ind(jj,jt)= SUM( ztrps(:,jj,jt)*zmask(:,jj,4) )
  166. END DO
  167. END DO
  168. END IF
  169. tim = getvar1d(cfileVT, trim(ctim), Nt) !LB: nt
  170. !! Plotting annually-averaged profiles: !LB
  171. !! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  172. DO jj = 1, npjglo
  173. vmerid_heat(jj,1) = SUM(merid_heat_glo(jj,:))/Nt/1e15
  174. vmerid_heat(jj,2) = SUM(merid_heat_atl(jj,:))/Nt/1e15
  175. vmerid_heat(jj,3) = SUM(merid_heat_pac(jj,:))/Nt/1e15
  176. vmerid_heat(jj,4) = SUM(merid_heat_ind(jj,:))/Nt/1e15
  177. vmerid_salt(jj,1) = SUM(merid_salt_glo(jj,:))/Nt/1e6
  178. vmerid_salt(jj,2) = SUM(merid_salt_atl(jj,:))/Nt/1e6
  179. vmerid_salt(jj,3) = SUM(merid_salt_pac(jj,:))/Nt/1e6
  180. vmerid_salt(jj,4) = SUM(merid_salt_ind(jj,:))/Nt/1e6
  181. IF ( (vmerid_salt(jj,2) == 0.0).AND.(jj > 20) ) THEN
  182. vmerid_salt(jj,4) = 0.0
  183. vmerid_salt(jj,5) = 0.0
  184. END IF
  185. IF ( (vmerid_heat(jj,2) == 0.0).AND.(jj > 20) ) THEN
  186. vmerid_heat(jj,4) = 0.0
  187. vmerid_heat(jj,5) = 0.0
  188. END IF
  189. END DO
  190. !! WTF:
  191. WHERE ( vmerid_heat == 0.0 ) vmerid_heat = rmissing
  192. WHERE ( vmerid_salt == 0.0 ) vmerid_salt = rmissing
  193. DO jbasin = 1, nbasins
  194. vcv_name_t(jbasin) = 'zomht'//TRIM(cbasin(jbasin))
  195. vcv_name_s(jbasin) = 'zomst'//TRIM(cbasin(jbasin))
  196. END DO
  197. !
  198. !! LOLO netcdf
  199. INQUIRE( FILE=cf_out, EXIST=lfncout )
  200. IF ( .NOT. lfncout ) THEN
  201. !! Creating file
  202. PRINT *, ' Creating file '//trim(cf_out)//' !!!'
  203. ierr = NF90_CREATE(cf_out, NF90_CLOBBER, idf_out)
  204. ierr = NF90_DEF_DIM(idf_out, 'y', npjglo, idd_y) !
  205. ierr = NF90_DEF_VAR(idf_out, 'lat', NF90_FLOAT, idd_y, idv_lat)
  206. ierr = NF90_DEF_DIM(idf_out, 'time', NF90_UNLIMITED, idd_t)
  207. ierr = NF90_DEF_VAR(idf_out, 'time', NF90_DOUBLE, idd_t, idv_time)
  208. DO jbasin = 1, nbasins
  209. ierr = NF90_DEF_VAR(idf_out, trim(vcv_name_t(jbasin)), NF90_FLOAT, (/idd_y,idd_t/), vid_heat(jbasin))
  210. ierr = NF90_PUT_ATT(idf_out, vid_heat(jbasin), '_FillValue', rmissing)
  211. ierr = NF90_DEF_VAR(idf_out, TRIM(vcv_name_s(jbasin)), NF90_FLOAT, (/idd_y,idd_t/), vid_salt(jbasin))
  212. ierr = NF90_PUT_ATT(idf_out, vid_salt(jbasin), '_FillValue', rmissing)
  213. END DO
  214. ierr = NF90_ENDDEF(idf_out)
  215. ierr = NF90_PUT_VAR(idf_out, idv_lat, dumlat(1,:))
  216. jt_pos = 0
  217. ELSE
  218. !! Opening already existing file
  219. ierr = NF90_OPEN (cf_out, NF90_WRITE, idf_out)
  220. !! Need IDs of variables to append... NF90_INQ_VARID
  221. DO jbasin = 1, nbasins
  222. ierr = NF90_INQ_VARID(idf_out, trim(vcv_name_t(jbasin)), vid_heat(jbasin))
  223. ierr = NF90_INQ_VARID(idf_out, trim(vcv_name_s(jbasin)), vid_salt(jbasin))
  224. END DO
  225. ! Get ID of unlimited dimension
  226. ierr = NF90_INQUIRE(idf_out, unlimitedDimId = idv_time)
  227. ! Need to know jt_pos, record number of the last time record writen in the file
  228. ierr = NF90_INQUIRE_DIMENSION(idf_out, idv_time, name=cv_dum, len=jt_pos)
  229. !PRINT *, 'cv_dum, jt_pos = ', trim(cv_dum), jt_pos
  230. END IF
  231. WRITE(*,'("Going to write record #",i4.4," into ",a)') jt_pos+1, trim(cf_out)
  232. !DO jt = 1, Nt
  233. jt = 1 ! saving 1 record per year!
  234. ! Writing record jt for time vector and 1d fields:
  235. ierr = NF90_PUT_VAR( idf_out, idv_time, (/ryear+0.5/), start=(/jt_pos+jt/), count=(/1/) )
  236. DO jbasin = 1, nbasins
  237. ierr = NF90_PUT_VAR(idf_out, vid_heat(jbasin), vmerid_heat(:,jbasin), start=(/1,jt_pos+jt/), count=(/npjglo,1/))
  238. ierr = NF90_PUT_VAR(idf_out, vid_salt(jbasin), vmerid_salt(:,jbasin), start=(/1,jt_pos+jt/), count=(/npjglo,1/))
  239. END DO
  240. !END DO
  241. ierr = NF90_PUT_ATT(idf_out, NF90_GLOBAL, 'About', 'Created by BaraKuda (cdfmhst.f90) => https://github.com/brodeau/barakuda')
  242. ierr = NF90_CLOSE(idf_out)
  243. END PROGRAM cdfmhst