cdfmaxmoc.f90 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. PROGRAM cdfmaxmoc
  2. !!---------------------------------------------------------------------------------------------------
  3. !! *** PROGRAM cdfmaxmoc ***
  4. !!
  5. !! ** Purpose : Compute the maximum of the overturning fonction from a file calculated by cdfmoc
  6. !!
  7. !! ** Method : maxovt 'ovtfile' latmin latmax depmin depmax
  8. !! return ovtmaximum and ovt minimum in the defined range.
  9. !! Also give location of those extrema
  10. !! works for Atlantic and Global MOC
  11. !!
  12. !! * history:
  13. !! July 2005 : original : J.M. Molines
  14. !! November : modified and adapted to cdf output R. Dussin.
  15. !!---------------------------------------------------------------------------------------------------
  16. !! $Rev: 319 $
  17. !! $Date: 2010-05-19 12:19:07 +0200 (Wed, 19 May 2010) $
  18. !! $Id: cdfmaxmoc.f90 319 2010-05-19 10:19:07Z dussin $
  19. !!--------------------------------------------------------------
  20. USE netcdf
  21. USE cdfio
  22. USE io_ezcdf
  23. IMPLICIT NONE
  24. !!
  25. INTEGER :: jj, jk, jt, jt_pos ! dummy loop index !LB
  26. INTEGER :: id_moc, id_lat_max, id_depthw_max, idd_t, idv_time, idf_out
  27. LOGICAL :: lfncout
  28. INTEGER :: npjglo, npk, nt ! size of the overturning !LB
  29. INTEGER :: narg, iargc, istatus ! line command stuff
  30. INTEGER :: jmin, jmax, kmin, kmax ! (latitude, depth) window where to look at extrema
  31. INTEGER :: imaxloc(3) ! temporary array to use with minloc/maxloc
  32. ! added to write in netcdf
  33. INTEGER :: kx=1, ky=1, kz=1 ! dims of netcdf output file
  34. INTEGER :: nboutput=6 ! number of values to write in cdf output
  35. INTEGER :: ncout, ierr ! for netcdf output
  36. INTEGER, DIMENSION(:), ALLOCATABLE :: ipk, id_varout
  37. !
  38. REAL(KIND=4), DIMENSION(:,:,:), ALLOCATABLE :: zomoc ! zonal MOC (1,npjglo,jpk)
  39. REAL(KIND=4), DIMENSION(:,:), ALLOCATABLE :: rlat ! latitude (1, npjglo)
  40. REAL(KIND=4), DIMENSION(:), ALLOCATABLE :: gdepw ! depth read in the header
  41. REAL(KIND=4), DIMENSION(:), ALLOCATABLE :: ovtmax
  42. INTEGER, DIMENSION(:), ALLOCATABLE :: jlatmax, kdmax
  43. CHARACTER(len=4) :: clatmin, clatmax
  44. REAL(KIND=4) :: rlatmin, rlatmax, depmin , depmax
  45. ! added to write in netcdf
  46. REAL(KIND=4), DIMENSION(:,:), ALLOCATABLE :: dumlon, dumlat
  47. REAL(KIND=4), DIMENSION (1) :: tim ! time counter
  48. TYPE(variable), DIMENSION(:), ALLOCATABLE :: typvar ! structure of output
  49. !
  50. CHARACTER(LEN=256) :: cdum, cfile, comment, cbasin, cvar, cdep, ctim, cv_dum
  51. CHARACTER(LEN=512) :: cd_out='.', cf_out
  52. REAL(4) :: ryear, rmon, rdt
  53. INTEGER :: idf_moc=0 , idv_moc=0
  54. ! * main program
  55. narg=iargc()
  56. IF (narg == 8) THEN
  57. CALL getarg(1,cfile)
  58. CALL getarg(2,cbasin)
  59. CALL getarg(3,cdum)
  60. READ(cdum,*) rlatmin
  61. CALL getarg(4,cdum)
  62. READ(cdum,*) rlatmax
  63. CALL getarg(5,cdum)
  64. READ(cdum,*) depmin
  65. CALL getarg(6,cdum)
  66. READ(cdum,*) depmax
  67. CALL getarg(7,cdum)
  68. READ(cdum,*) ryear
  69. CALL getarg(8,cd_out)
  70. ELSE
  71. PRINT *,' USAGE: cdfmaxmoc ''ovt_file.nc'' cbasin latmin latmax depmin depmax <year> <DIROUT>'
  72. PRINT *,' cbasin is one of atl glo inp ind or pac '
  73. PRINT *,' Output on standard output by default and maxmoc.nc '
  74. STOP
  75. ENDIF
  76. npjglo = getdim(cfile,'y')
  77. cdep='none'
  78. npk = getdim(cfile,'olevel',cdtrue=cdep,kstatus=istatus) !LB
  79. ctim='none'
  80. nt = getdim(cfile,'time', cdtrue=ctim,kstatus=istatus) !LB
  81. ALLOCATE ( zomoc (1,npjglo,npk) ,gdepw(npk), rlat(1,npjglo), ovtmax(nt), jlatmax(nt), kdmax(nt) )
  82. gdepw(:) = -getvar1d(cfile,'olevel',npk)
  83. rlat(:,:) = getvar(cfile,'nav_lat',1,1,npjglo)
  84. SELECT CASE (cbasin)
  85. CASE ('atl')
  86. cvar='zomsfatl'
  87. CASE ('glo')
  88. cvar='zomsfglo'
  89. CASE ('pac')
  90. cvar='zomsfpac'
  91. CASE ('inp')
  92. cvar='zomsfinp'
  93. CASE ('ind')
  94. cvar='zomsfind'
  95. CASE DEFAULT
  96. STOP 'basin not found'
  97. END SELECT
  98. ! look for jmin-jmax :
  99. DO jj=1, npjglo
  100. IF ( rlat(1,jj) <= rlatmin ) jmin = jj
  101. IF ( rlat(1,jj) <= rlatmax ) jmax = jj
  102. END DO
  103. ! look for kmin kmax
  104. DO jk=1,npk
  105. IF ( gdepw(jk) <= depmin ) kmin = jk
  106. IF ( gdepw(jk) <= depmax ) kmax = jk
  107. END DO
  108. DO jt = 1, nt !LB
  109. !PRINT *, ' * [cdfmaxmoc] jt = ', jt
  110. CALL GETVAR_3D(idf_moc, idv_moc, cfile, cvar, nt, jt, zomoc)
  111. ! look for max/min overturning
  112. ovtmax(jt) = MAXVAL(zomoc(1,jmin:jmax,kmin:kmax))
  113. ! find location of min/max
  114. !iminloc =MINLOC(zomoc(:,jmin:jmax,kmin:kmax))
  115. imaxloc =MAXLOC(zomoc(:,jmin:jmax,kmin:kmax))
  116. ! results from minloc/maxloc is relative to the sub -array given as arguments
  117. jlatmax(jt) = imaxloc(2)+jmin -1
  118. kdmax(jt) = imaxloc(3)+kmin -1
  119. END DO !LB nt
  120. WRITE( clatmin, '(i2.2)') INT(ABS(rlatmin))
  121. WRITE( clatmax, '(i2.2)') INT(ABS(rlatmax))
  122. IF ( rlatmin >= 0. ) THEN
  123. clatmin = '+'//trim(clatmin)//'N'
  124. ELSE
  125. clatmin = '-'//trim(clatmin)//'N'
  126. END IF
  127. IF ( rlatmax >= 0. ) THEN
  128. clatmax = '+'//trim(clatmax)//'N'
  129. ELSE
  130. clatmax = '-'//trim(clatmax)//'N'
  131. END IF
  132. WRITE( cf_out , '(a,"/max_moc_",a,"_",2a,".nc")' ) trim(cd_out), trim(cbasin), clatmin, clatmax
  133. id_moc = 0 ; id_lat_max = 0 ; id_depthw_max = 0
  134. INQUIRE( FILE=cf_out, EXIST=lfncout )
  135. IF ( .NOT. lfncout ) THEN
  136. !! Creating file
  137. PRINT *, ' Creating file '//trim(cf_out)//' !!!'
  138. ierr = NF90_CREATE(cf_out, NF90_CLOBBER, idf_out)
  139. ierr = NF90_DEF_DIM(idf_out, 'time', NF90_UNLIMITED, idd_t)
  140. ierr = NF90_DEF_VAR(idf_out, 'time', NF90_DOUBLE, idd_t, idv_time)
  141. ierr = NF90_DEF_VAR(idf_out, 'moc_'//trim(cbasin), NF90_FLOAT, (/idd_t/), id_moc)
  142. ierr = NF90_PUT_ATT(idf_out, id_moc, 'long_name', 'Meridional Overturning Circulation')
  143. ierr = NF90_PUT_ATT(idf_out, id_moc, 'units', 'Sv')
  144. ierr = NF90_DEF_VAR(idf_out, 'lat_max_'//trim(cbasin), NF90_FLOAT, (/idd_t/), id_lat_max)
  145. ierr = NF90_PUT_ATT(idf_out, id_lat_max, 'long_name', 'Latitude for maximum of MOC')
  146. ierr = NF90_PUT_ATT(idf_out, id_lat_max, 'units', 'deg.N')
  147. ierr = NF90_DEF_VAR(idf_out, 'depthw_max_'//trim(cbasin), NF90_FLOAT, (/idd_t/), id_depthw_max)
  148. ierr = NF90_PUT_ATT(idf_out, id_depthw_max, 'long_name', 'W-depth for maximum of MOC')
  149. ierr = NF90_PUT_ATT(idf_out, id_depthw_max, 'units', 'm')
  150. ierr = NF90_PUT_ATT(idf_out, NF90_GLOBAL, 'About', &
  151. & 'Created by BaraKuda (cdfmaxmoc.f90) => https://github.com/brodeau/barakuda')
  152. ierr = NF90_ENDDEF(idf_out)
  153. jt_pos = 0
  154. ELSE
  155. !! Opening already existing file
  156. ierr = NF90_OPEN (cf_out, NF90_WRITE, idf_out)
  157. !! Need IDs of variables to append... NF90_INQ_VARID
  158. ierr = NF90_INQ_VARID(idf_out, 'moc_'//trim(cbasin), id_moc)
  159. !! Need IDs of variables to append... NF90_INQ_VARID
  160. ierr = NF90_INQ_VARID(idf_out, 'lat_max_'//trim(cbasin), id_lat_max)
  161. !! Need IDs of variables to append... NF90_INQ_VARID
  162. ierr = NF90_INQ_VARID(idf_out, 'depthw_max_'//trim(cbasin), id_depthw_max)
  163. ! Get ID of unlimited dimension
  164. ierr = NF90_INQUIRE(idf_out, unlimitedDimId = idv_time)
  165. ! Need to know jt_pos, record number of the last time record writen in the file
  166. ierr = NF90_INQUIRE_DIMENSION(idf_out, idv_time, name=cv_dum, len=jt_pos)
  167. END IF
  168. WRITE(*,'("Going to write record ",i4.4," to ",i4.4," into ",a)') jt_pos+1, jt_pos+1+nt, trim(cf_out)
  169. DO jt = 1, nt
  170. ! Writing record jt for time vector and 1d fields:
  171. ierr = NF90_PUT_VAR( idf_out, idv_time, (/ryear+1./12.*(REAL(jt)-1.+0.5)/), start=(/jt_pos+jt/), count=(/1/) )
  172. !! Default variable is the only one present (index = 1) :
  173. ierr = NF90_PUT_VAR(idf_out, id_moc, (/ ovtmax(jt) /), start=(/jt_pos+jt/), count=(/1/))
  174. ierr = NF90_PUT_VAR(idf_out, id_lat_max, (/ rlat(1,jlatmax(jt)) /), start=(/jt_pos+jt/), count=(/1/))
  175. ierr = NF90_PUT_VAR(idf_out, id_depthw_max, (/ gdepw(kdmax(jt)) /), start=(/jt_pos+jt/), count=(/1/))
  176. END DO
  177. ierr = NF90_CLOSE(idf_out)
  178. PRINT *, ''
  179. END PROGRAM cdfmaxmoc