p_fixhycom.F90 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. ! File: p_fixhycom.F90
  2. !
  3. ! Created: ???
  4. !
  5. ! Last modified: 29/06/2010
  6. !
  7. ! Purpose: Fixes EnKF output.
  8. !
  9. ! Description:
  10. !
  11. ! Modifications:
  12. ! 25/10/2011 FC:
  13. ! - set the two time levels equal
  14. ! 29/06/2010 PS:
  15. ! - set the maximum ICEC to 0.995 to match the model
  16. ! ?/?/? KAL:
  17. ! - Modification of the "fixhycom" subroutine, into separate
  18. ! program, working on a file-by-file basis
  19. ! Prior history:
  20. ! Not documented.
  21. ! KAL -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  22. ! KAL -- Input arguments:
  23. ! KAL -- template restart file
  24. ! KAL -- ensemble member
  25. ! KAL -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  26. program fixhycom
  27. use mod_raw_io
  28. use m_parse_blkdat
  29. use m_put_mod_fld
  30. use m_get_mod_fld
  31. use m_get_mod_grid
  32. implicit none
  33. integer*4, external :: iargc
  34. real, parameter :: onem=9806.
  35. real, parameter :: PSTARB0 = 1000;
  36. integer imem ! ensemble member
  37. character(len=80) :: restart,icerestart ! restart template
  38. character(len=80) :: afile,newfile, char80
  39. integer :: fnd, rstind, tmpindx, iafile
  40. logical :: ex, allok, nomatch
  41. character(len=8) :: cfld, ctmp
  42. character(len=3) :: cproc,cmem
  43. integer :: tlevel, vlevel, nproc
  44. real :: bmin, bmax, rdummy
  45. integer :: idm,jdm,kdm
  46. real, allocatable:: fld(:,:)
  47. real*8, allocatable, dimension(:,:) :: &
  48. ficem,hicem,hsnwm,ticem,tsrfm
  49. real, allocatable, dimension(:,:) :: depths,modlon,modlat,saln
  50. real*4, allocatable:: fldr4(:,:)
  51. real*4 :: spval,amin,amax
  52. real, allocatable :: press(:)
  53. real, allocatable, dimension(:,:) :: dpsum
  54. real, allocatable, dimension(:,:,:) :: dp, dpold
  55. integer,parameter :: numfields=2
  56. integer :: ios,ios2, reclICE,ifld
  57. integer :: i,j,k
  58. real :: mindx,meandx
  59. icerestart=''
  60. if (iargc()==2 .or. iargc()==3) then
  61. call getarg(1,restart)
  62. call getarg(2,ctmp)
  63. read(ctmp,*) imem
  64. write(cmem,'(i3.3)') imem
  65. if (iargc()==3) call getarg(3,icerestart)
  66. else
  67. print *,'"fixhycom" -- A crude routine to correct restart files for obvious errors'
  68. print *
  69. print *,'usage: '
  70. print *,' fixhycom restart_file ensemble_member <ice_file>'
  71. print *,' "restart_file" the restart file you want to fix (.a-file)"'
  72. print *,' "ensemble_member" is the ensemble member - should corr. to that of restart file'
  73. print *,' "ice_file" is optional - it is the restart file for ice fields'
  74. call exit(1)
  75. endif
  76. ! Get dimensions from blkdat
  77. call parse_blkdat('idm ','integer',rdummy,idm)
  78. call parse_blkdat('jdm ','integer',rdummy,jdm)
  79. call parse_blkdat('kdm ','integer',rdummy,kdm)
  80. if (idm>0 .and. idm < 1e4 .and. jdm>0 .and. jdm<1e4) then
  81. allocate(fld (idm,jdm))
  82. allocate(fldr4(idm,jdm))
  83. allocate(saln (idm,jdm))
  84. allocate(ficem(idm,jdm))
  85. allocate(hicem(idm,jdm))
  86. allocate(hsnwm(idm,jdm))
  87. allocate(ticem(idm,jdm))
  88. allocate(tsrfm(idm,jdm))
  89. allocate(dpsum(idm,jdm))
  90. allocate(depths(idm,jdm))
  91. allocate(modlon(idm,jdm))
  92. allocate(modlat(idm,jdm))
  93. allocate(dpold(idm,jdm,kdm))
  94. allocate(dp (idm,jdm,kdm))
  95. allocate(press(kdm+1))
  96. else
  97. print *,'fld allocate error'
  98. stop '(EnKF_postprocess)'
  99. end if
  100. ! Remove postfix of restart file
  101. fnd=max(index(restart,'.a'),index(restart,'.b'))
  102. ! Inquire for existence
  103. inquire(exist=ex,file=restart(1:fnd-1)//'.b')
  104. if (.not.ex) then
  105. write(*,*) 'Can not find '//restart(1:fnd-1)//'.b'
  106. stop '(EnKF_postprocess)'
  107. end if
  108. print *,restart(1:fnd-1)//'.b'
  109. newfile='fix'//restart(1:fnd-1)
  110. ! Get model grid
  111. call get_mod_grid(modlon,modlat,depths,mindx,meandx,idm,jdm)
  112. !loop over the two time level
  113. ! Get layer thickness
  114. dpsum=0.
  115. do k=1,kdm
  116. call get_mod_fld_new(restart(1:fnd-1),dp(:,:,k),imem,'dp ',k,1,idm,jdm)
  117. dpsum=dpsum+dp(:,:,k)
  118. end do
  119. dpold=dp(:,:,:)
  120. ! DP correction
  121. do j=1,jdm
  122. do i=1,idm
  123. !!! Move negative layers to neighbouring layers.
  124. do k = 1, kdm-1
  125. dp(i,j,k+1) = dp(i,j,k+1) + min(0.0,dp(i,j,k))
  126. dp(i,j,k ) = max(dp(i,j,k),0.0)
  127. end do
  128. !!! Go backwards to fix lowermost layer.
  129. do k = kdm, 3, -1
  130. dp(i,j,k-1) = dp(i,j,k-1) + min(0.0,dp(i,j,k))
  131. dp(i,j,k ) = max(dp(i,j,k),0.0)
  132. end do
  133. !!! No layers below the sea bed.
  134. press( 1) = 0.0
  135. do k = 1, kdm-1
  136. press(k+1) = press(k) + dp(i,j,k)
  137. press(k+1) = min(depths(i,j)*onem,press(k+1))
  138. end do
  139. press(kdm+1) = depths(i,j)*onem
  140. do k = 1, kdm
  141. dp(i,j,k) = press(k+1) - press(k)
  142. end do
  143. if (depths(i,j)>100000. .or. depths(i,j) < 1. ) then
  144. dp(i,j,:)=dpold(i,j,:)
  145. endif
  146. end do
  147. end do
  148. do k = 1, kdm
  149. print *,'max diff is:',maxval(dpold(:,:,k)-dp(:,:,k))/onem,maxloc(dpold(:,:,k)-dp(:,:,k))
  150. end do
  151. ! Loop over restart file
  152. rstind=1 ! Restart index
  153. allok=.true.
  154. do while ( allok)
  155. ! Get header info from restart
  156. call rst_header_from_index(restart(1:fnd-1)//'.b', &
  157. cfld,vlevel,tlevel,rstind,bmin,bmax,.true.)
  158. allok=tlevel/=-1 ! test to see if read was ok
  159. print *,cfld
  160. if (allok ) then
  161. ! Here reading the time record 1 whatever tlevel
  162. call get_mod_fld_new(restart(1:fnd-1),fld(:,:),imem,cfld,vlevel,1,idm,jdm)
  163. if (trim(cfld)=='temp') then
  164. ! need salinity as well
  165. ! reading the time record 1 whatever tlevel
  166. call get_mod_fld_new(restart(1:fnd-1),saln(:,:),imem,'saln ',vlevel,1,idm,jdm)
  167. ! keep water warmer than freezing point
  168. do j=1,jdm
  169. do i=1,idm
  170. fld(i,j)=max(-.057*saln(i,j),fld(i,j))
  171. fld(i,j)=min(fld(i,j),35.0) !cut off values that are too warm :FC
  172. end do
  173. end do
  174. else if (trim(cfld)=='saln') then
  175. do j=1,jdm
  176. do i=1,idm
  177. fld(i,j)=max(5.,fld(i,j)) ! LB :no water fresher than 5 psu (Baltic)
  178. fld(i,j)=min(41.,fld(i,j)) ! FC :no water saltier than 40 psu
  179. end do
  180. end do
  181. else if (trim(cfld)=='pstarb') then
  182. fld(:,:) = (sqrt(PSTARB0 ** 2 + fld(:,:) ** 2) + fld(:,:)) / 2.0d0;
  183. else if (trim(cfld)=='dp') then
  184. !set it equal to the time level 1 that has been corrected
  185. fld = dp(:,:,vlevel)
  186. #if defined (TOPAZ)
  187. ! in west of Mediterranean
  188. else if (trim(cfld)=='pbavg' .or. trim(cfld)=='ubavg' .or. trim(cfld)=='vbavg'&
  189. .or. trim(cfld)=='u' .or. trim(cfld)=='v') then
  190. do i = 701, 704
  191. do j = 482, 484
  192. fld(i, j) = 0.0d0
  193. end do
  194. end do
  195. #endif
  196. #if defined (SINGLE_RESTART)
  197. else if (trim(cfld)=='ficem') then
  198. do j=1,jdm
  199. do i=1,idm
  200. fld(i,j)=min(max(0.,fld(i,j)),0.995)
  201. end do
  202. end do
  203. else if (trim(cfld)=='hicem') then
  204. do j=1,jdm
  205. do i=1,idm
  206. fld(i,j)=min(max(0.,fld(i,j)),15.)
  207. end do
  208. end do
  209. else if (trim(cfld)=='hsnwm') then
  210. do j=1,jdm
  211. do i=1,idm
  212. fld(i,j)=min(max(0.,fld(i,j)),0.4)
  213. end do
  214. end do
  215. #endif
  216. end if ! No correction for other fields in the hycom restart file
  217. !dump the field from the first time level into tlevel (1 or 2)
  218. call put_mod_fld(trim(newfile),fld,imem,cfld,vlevel,tlevel,rstind,idm,jdm)
  219. rstind=rstind+1
  220. end if ! read of template was ok
  221. end do
  222. ! put_mod_fld does not include the header from the original file
  223. open(10,file=trim(newfile)//'.b',status='old')
  224. open(20,file=restart(1:fnd-1)//'.b',status='old')
  225. ! Supports parallel execution with different members
  226. open(11,file='tmp'//cmem//'.b',status='replace')
  227. ! Header from original file
  228. read(20,'(a80)') char80 ; write(11,'(a80)') char80
  229. read(20,'(a80)') char80 ; write(11,'(a80)') char80
  230. close(20)
  231. ! The rest from the newly created file
  232. ios=0
  233. do while(ios==0)
  234. read(10,'(a80)',iostat=ios) char80
  235. if (ios==0) write(11,'(a80)') char80
  236. end do
  237. close(10)
  238. close(11)
  239. close(20)
  240. ! Move the new .b file to "newfile"
  241. !SERIAL call system('mv tmp'//cmem//'.b '//trim(newfile)//'.b')
  242. !###################################################################
  243. !####################### FIX ICE MODEL #########################
  244. !###################################################################
  245. #if ! defined (SINGLE_RESTART)
  246. if (iargc()==3) then
  247. inquire(exist=ex,file=trim(icerestart))
  248. if (.not.ex) then
  249. print *,icerestart//' does not exist!'
  250. print *,'(fixhycom)'
  251. stop
  252. end if
  253. inquire(iolength=reclICE)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
  254. open(10,file=icerestart,form='unformatted',access='direct',recl=reclICE)
  255. read(10,rec=imem)ficem,hicem,hsnwm,ticem,tsrfm !,iceU,iceV
  256. close(10)
  257. ! PS 25/06/2010 max(ficem) = 0.995 - max the model allows
  258. ficem=min(max(0.,ficem), 0.995)
  259. hicem=min(max(0.,hicem),15.)
  260. hsnwm=min(max(0.,hsnwm), 4.)
  261. open (10,file='fix'//trim(icerestart),form='unformatted',access='direct',recl=reclICE)
  262. write(10,rec=imem)ficem,hicem,hsnwm,ticem,tsrfm
  263. close(10)
  264. end if
  265. #endif
  266. end program