limtrp_2.F90 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. MODULE limtrp_2
  2. !!======================================================================
  3. !! *** MODULE limtrp_2 ***
  4. !! LIM 2.0 transport ice model : sea-ice advection/diffusion
  5. !!======================================================================
  6. !! History : LIM ! 2000-01 (UCL) Original code
  7. !! 2.0 ! 2001-05 (G. Madec, R. Hordoir) opa norm
  8. !! - ! 2004-01 (G. Madec, C. Ethe) F90, mpp
  9. !! 3.3 ! 2009-05 (G. Garric, C. Bricaud) addition of the lim2_evp case
  10. !!----------------------------------------------------------------------
  11. #if defined key_lim2
  12. !!----------------------------------------------------------------------
  13. !! 'key_lim2' : LIM 2.0 sea-ice model
  14. !!----------------------------------------------------------------------
  15. !! lim_trp_2 : advection/diffusion process of sea ice
  16. !! lim_trp_init_2 : initialization and namelist read
  17. !!----------------------------------------------------------------------
  18. USE phycst ! physical constant
  19. USE sbc_oce ! ocean surface boundary condition
  20. USE dom_oce ! ocean domain
  21. USE in_out_manager ! I/O manager
  22. USE dom_ice_2 ! LIM-2 domain
  23. USE ice_2 ! LIM-2 variables
  24. USE limistate_2 ! LIM-2 initial state
  25. USE limadv_2 ! LIM-2 advection
  26. USE limhdf_2 ! LIM-2 horizontal diffusion
  27. USE lbclnk ! lateral boundary conditions -- MPP exchanges
  28. USE lib_mpp ! MPP library
  29. USE wrk_nemo ! work arrays
  30. # if defined key_agrif
  31. USE agrif_lim2_interp ! nesting
  32. # endif
  33. USE lib_fortran ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined)
  34. IMPLICIT NONE
  35. PRIVATE
  36. PUBLIC lim_trp_2 ! called by sbc_ice_lim_2
  37. REAL(wp), PUBLIC :: bound !: boundary condit. (0.0 no-slip, 1.0 free-slip)
  38. REAL(wp) :: epsi06 = 1.e-06 ! constant values
  39. REAL(wp) :: epsi03 = 1.e-03
  40. REAL(wp) :: epsi16 = 1.e-16
  41. REAL(wp) :: rzero = 0.e0
  42. REAL(wp) :: rone = 1.e0
  43. !! * Substitution
  44. # include "vectopt_loop_substitute.h90"
  45. !!----------------------------------------------------------------------
  46. !! NEMO/LIM2 3.3 , UCL - NEMO Consortium (2010)
  47. !! $Id: limtrp_2.F90 4624 2014-04-28 12:09:03Z acc $
  48. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  49. !!----------------------------------------------------------------------
  50. CONTAINS
  51. SUBROUTINE lim_trp_2( kt )
  52. !!-------------------------------------------------------------------
  53. !! *** ROUTINE lim_trp_2 ***
  54. !!
  55. !! ** purpose : advection/diffusion process of sea ice
  56. !!
  57. !! ** method : variables included in the process are scalar,
  58. !! other values are considered as second order.
  59. !! For advection, a second order Prather scheme is used.
  60. !!
  61. !! ** action :
  62. !!---------------------------------------------------------------------
  63. INTEGER, INTENT(in) :: kt ! number of iteration
  64. !!
  65. INTEGER :: ji, jj, jk ! dummy loop indices
  66. INTEGER :: initad ! number of sub-timestep for the advection
  67. REAL(wp) :: zindb , zindsn , zindic, zacrith ! local scalars
  68. REAL(wp) :: zusvosn, zusvoic, zignm , zindhe ! - -
  69. REAL(wp) :: zvbord , zcfl , zusnit ! - -
  70. REAL(wp) :: zrtt , ztsn , ztic1 , ztic2 ! - -
  71. REAL(wp), POINTER, DIMENSION(:,:) :: zui_u , zvi_v , zsm ! 2D workspace
  72. REAL(wp), POINTER, DIMENSION(:,:) :: zs0ice, zs0sn , zs0a ! - -
  73. REAL(wp), POINTER, DIMENSION(:,:) :: zs0c0 , zs0c1 , zs0c2 , zs0st ! - -
  74. !---------------------------------------------------------------------
  75. CALL wrk_alloc( jpi, jpj, zui_u , zvi_v , zsm, zs0ice, zs0sn , zs0a, zs0c0 , zs0c1 , zs0c2 , zs0st )
  76. IF( kt == nit000 ) CALL lim_trp_init_2 ! Initialization (first time-step only)
  77. # if defined key_agrif
  78. CALL agrif_trp_lim2_load ! First interpolation
  79. # endif
  80. zsm(:,:) = area(:,:)
  81. IF( ln_limdyn ) THEN
  82. !-------------------------------------!
  83. ! Advection of sea ice properties !
  84. !-------------------------------------!
  85. ! ice velocities at ocean U- and V-points (zui_u,zvi_v)
  86. ! ---------------------------------------
  87. IF( lk_lim2_vp ) THEN ! VP rheology : B-grid sea-ice dynamics (I-point ice velocity)
  88. zvbord = 1._wp + ( 1._wp - bound ) ! zvbord=2 no-slip, =0 free slip boundary conditions
  89. DO jj = 1, jpjm1
  90. DO ji = 1, jpim1 ! NO vector opt.
  91. zui_u(ji,jj) = ( u_ice(ji+1,jj) + u_ice(ji+1,jj+1) ) / ( MAX( tmu(ji+1,jj)+tmu(ji+1,jj+1), zvbord ) )
  92. zvi_v(ji,jj) = ( v_ice(ji,jj+1) + v_ice(ji+1,jj+1) ) / ( MAX( tmu(ji,jj+1)+tmu(ji+1,jj+1), zvbord ) )
  93. END DO
  94. END DO
  95. CALL lbc_lnk( zui_u, 'U', -1. ) ; CALL lbc_lnk( zvi_v, 'V', -1. ) ! Lateral boundary conditions
  96. !
  97. ELSE ! EVP rheology : C-grid sea-ice dynamics (u- & v-points ice velocity)
  98. zui_u(:,:) = u_ice(:,:) ! EVP rheology: ice (u,v) at u- and v-points
  99. zvi_v(:,:) = v_ice(:,:)
  100. ENDIF
  101. ! CFL test for stability
  102. ! ----------------------
  103. zcfl = 0._wp
  104. zcfl = MAX( zcfl, MAXVAL( ABS( zui_u(1:jpim1, : ) ) * rdt_ice / e1u(1:jpim1, : ) ) )
  105. zcfl = MAX( zcfl, MAXVAL( ABS( zvi_v( : ,1:jpjm1) ) * rdt_ice / e2v( : ,1:jpjm1) ) )
  106. !
  107. IF(lk_mpp) CALL mpp_max( zcfl )
  108. !
  109. IF( zcfl > 0.5 .AND. lwp ) WRITE(numout,*) 'lim_trp_2 : violation of cfl criterion the ',nday,'th day, cfl = ', zcfl
  110. ! content of properties
  111. ! ---------------------
  112. zs0sn (:,:) = hsnm(:,:) * area (:,:) ! Snow volume.
  113. zs0ice(:,:) = hicm(:,:) * area (:,:) ! Ice volume.
  114. zs0a (:,:) = ( 1.0 - frld(:,:) ) * area (:,:) ! Surface covered by ice.
  115. zs0c0 (:,:) = tbif(:,:,1) / rt0_snow * zs0sn (:,:) ! Heat content of the snow layer.
  116. zs0c1 (:,:) = tbif(:,:,2) / rt0_ice * zs0ice(:,:) ! Heat content of the first ice layer.
  117. zs0c2 (:,:) = tbif(:,:,3) / rt0_ice * zs0ice(:,:) ! Heat content of the second ice layer.
  118. zs0st (:,:) = qstoif(:,:) / xlic * zs0a (:,:) ! Heat reservoir for brine pockets.
  119. ! Advection (Prather scheme)
  120. ! ---------
  121. initad = 1 + INT( MAX( rzero, SIGN( rone, zcfl-0.5 ) ) ) ! If ice drift field is too fast,
  122. zusnit = 1.0 / REAL( initad ) ! split the ice time step in two
  123. !
  124. IF( MOD( ( kt - 1) / nn_fsbc , 2 ) == 0) THEN !== odd ice time step: adv_x then adv_y ==!
  125. DO jk = 1, initad
  126. CALL lim_adv_x_2( zusnit, zui_u, rone , zsm, zs0ice, sxice, sxxice, syice, syyice, sxyice )
  127. CALL lim_adv_y_2( zusnit, zvi_v, rzero, zsm, zs0ice, sxice, sxxice, syice, syyice, sxyice )
  128. CALL lim_adv_x_2( zusnit, zui_u, rone , zsm, zs0sn , sxsn , sxxsn , sysn , syysn , sxysn )
  129. CALL lim_adv_y_2( zusnit, zvi_v, rzero, zsm, zs0sn , sxsn , sxxsn , sysn , syysn , sxysn )
  130. CALL lim_adv_x_2( zusnit, zui_u, rone , zsm, zs0a , sxa , sxxa , sya , syya , sxya )
  131. CALL lim_adv_y_2( zusnit, zvi_v, rzero, zsm, zs0a , sxa , sxxa , sya , syya , sxya )
  132. CALL lim_adv_x_2( zusnit, zui_u, rone , zsm, zs0c0 , sxc0 , sxxc0 , syc0 , syyc0 , sxyc0 )
  133. CALL lim_adv_y_2( zusnit, zvi_v, rzero, zsm, zs0c0 , sxc0 , sxxc0 , syc0 , syyc0 , sxyc0 )
  134. CALL lim_adv_x_2( zusnit, zui_u, rone , zsm, zs0c1 , sxc1 , sxxc1 , syc1 , syyc1 , sxyc1 )
  135. CALL lim_adv_y_2( zusnit, zvi_v, rzero, zsm, zs0c1 , sxc1 , sxxc1 , syc1 , syyc1 , sxyc1 )
  136. CALL lim_adv_x_2( zusnit, zui_u, rone , zsm, zs0c2 , sxc2 , sxxc2 , syc2 , syyc2 , sxyc2 )
  137. CALL lim_adv_y_2( zusnit, zvi_v, rzero, zsm, zs0c2 , sxc2 , sxxc2 , syc2 , syyc2 , sxyc2 )
  138. CALL lim_adv_x_2( zusnit, zui_u, rone , zsm, zs0st , sxst , sxxst , syst , syyst , sxyst )
  139. CALL lim_adv_y_2( zusnit, zvi_v, rzero, zsm, zs0st , sxst , sxxst , syst , syyst , sxyst )
  140. END DO
  141. ELSE !== even ice time step: adv_x then adv_y ==!
  142. DO jk = 1, initad
  143. CALL lim_adv_y_2( zusnit, zvi_v, rone , zsm, zs0ice, sxice, sxxice, syice, syyice, sxyice )
  144. CALL lim_adv_x_2( zusnit, zui_u, rzero, zsm, zs0ice, sxice, sxxice, syice, syyice, sxyice )
  145. CALL lim_adv_y_2( zusnit, zvi_v, rone , zsm, zs0sn , sxsn , sxxsn , sysn , syysn , sxysn )
  146. CALL lim_adv_x_2( zusnit, zui_u, rzero, zsm, zs0sn , sxsn , sxxsn , sysn , syysn , sxysn )
  147. CALL lim_adv_y_2( zusnit, zvi_v, rone , zsm, zs0a , sxa , sxxa , sya , syya , sxya )
  148. CALL lim_adv_x_2( zusnit, zui_u, rzero, zsm, zs0a , sxa , sxxa , sya , syya , sxya )
  149. CALL lim_adv_y_2( zusnit, zvi_v, rone , zsm, zs0c0 , sxc0 , sxxc0 , syc0 , syyc0 , sxyc0 )
  150. CALL lim_adv_x_2( zusnit, zui_u, rzero, zsm, zs0c0 , sxc0 , sxxc0 , syc0 , syyc0 , sxyc0 )
  151. CALL lim_adv_y_2( zusnit, zvi_v, rone , zsm, zs0c1 , sxc1 , sxxc1 , syc1 , syyc1 , sxyc1 )
  152. CALL lim_adv_x_2( zusnit, zui_u, rzero, zsm, zs0c1 , sxc1 , sxxc1 , syc1 , syyc1 , sxyc1 )
  153. CALL lim_adv_y_2( zusnit, zvi_v, rone , zsm, zs0c2 , sxc2 , sxxc2 , syc2 , syyc2 , sxyc2 )
  154. CALL lim_adv_x_2( zusnit, zui_u, rzero, zsm, zs0c2 , sxc2 , sxxc2 , syc2 , syyc2 , sxyc2 )
  155. CALL lim_adv_y_2( zusnit, zvi_v, rone , zsm, zs0st , sxst , sxxst , syst , syyst , sxyst )
  156. CALL lim_adv_x_2( zusnit, zui_u, rzero, zsm, zs0st , sxst , sxxst , syst , syyst , sxyst )
  157. END DO
  158. ENDIF
  159. ! recover the properties from their contents
  160. ! ------------------------------------------
  161. !!gm Define in limmsh one for all area = 1 /area (CPU time saved !)
  162. zs0ice(:,:) = zs0ice(:,:) / area(:,:)
  163. zs0sn (:,:) = zs0sn (:,:) / area(:,:)
  164. zs0a (:,:) = zs0a (:,:) / area(:,:)
  165. zs0c0 (:,:) = zs0c0 (:,:) / area(:,:)
  166. zs0c1 (:,:) = zs0c1 (:,:) / area(:,:)
  167. zs0c2 (:,:) = zs0c2 (:,:) / area(:,:)
  168. zs0st (:,:) = zs0st (:,:) / area(:,:)
  169. !-------------------------------------!
  170. ! Diffusion of sea ice properties !
  171. !-------------------------------------!
  172. ! Masked eddy diffusivity coefficient at ocean U- and V-points
  173. ! ------------------------------------------------------------
  174. DO jj = 1, jpjm1 ! NB: has not to be defined on jpj line and jpi row
  175. DO ji = 1 , fs_jpim1 ! vector opt.
  176. pahu(ji,jj) = ( 1.0 - MAX( rzero, SIGN( rone, -zs0a(ji ,jj) ) ) ) &
  177. & * ( 1.0 - MAX( rzero, SIGN( rone, -zs0a(ji+1,jj) ) ) ) * ahiu(ji,jj)
  178. pahv(ji,jj) = ( 1.0 - MAX( rzero, SIGN( rone, -zs0a(ji,jj ) ) ) ) &
  179. & * ( 1.0 - MAX( rzero, SIGN( rone,- zs0a(ji,jj+1) ) ) ) * ahiv(ji,jj)
  180. END DO
  181. END DO
  182. !!gm more readable coding: (and avoid an error in F90 with sign of zero)
  183. ! DO jj = 1, jpjm1 ! NB: has not to be defined on jpj line and jpi row
  184. ! DO ji = 1 , fs_jpim1 ! vector opt.
  185. ! IF( MIN( zs0a(ji,jj) , zs0a(ji+1,jj) ) == 0.e0 ) pahu(ji,jj) = 0._wp
  186. ! IF( MIN( zs0a(ji,jj) , zs0a(ji,jj+1) ) == 0.e0 ) pahv(ji,jj) = 0._wp
  187. ! END DO
  188. ! END DO
  189. !!gm end
  190. ! diffusion
  191. ! ---------
  192. CALL lim_hdf_2( zs0ice )
  193. CALL lim_hdf_2( zs0sn )
  194. CALL lim_hdf_2( zs0a )
  195. CALL lim_hdf_2( zs0c0 )
  196. CALL lim_hdf_2( zs0c1 )
  197. CALL lim_hdf_2( zs0c2 )
  198. CALL lim_hdf_2( zs0st )
  199. !!gm see comment this can be skipped
  200. zs0ice(:,:) = MAX( rzero, zs0ice(:,:) * area(:,:) ) !!bug: useless
  201. zs0sn (:,:) = MAX( rzero, zs0sn (:,:) * area(:,:) ) !!bug: cf /area just below
  202. zs0a (:,:) = MAX( rzero, zs0a (:,:) * area(:,:) ) !! caution: the suppression of the 2 changes
  203. zs0c0 (:,:) = MAX( rzero, zs0c0 (:,:) * area(:,:) ) !! the last digit of the results
  204. zs0c1 (:,:) = MAX( rzero, zs0c1 (:,:) * area(:,:) )
  205. zs0c2 (:,:) = MAX( rzero, zs0c2 (:,:) * area(:,:) )
  206. zs0st (:,:) = MAX( rzero, zs0st (:,:) * area(:,:) )
  207. !-------------------------------------------------------------------!
  208. ! Updating and limitation of sea ice properties after transport !
  209. !-------------------------------------------------------------------!
  210. DO jj = 1, jpj
  211. zindhe = MAX( 0.e0, SIGN( 1.e0, fcor(1,jj) ) ) ! = 0 for SH, =1 for NH
  212. DO ji = 1, jpi
  213. !
  214. ! Recover mean values over the grid squares.
  215. zs0sn (ji,jj) = MAX( rzero, zs0sn (ji,jj)/area(ji,jj) )
  216. zs0ice(ji,jj) = MAX( rzero, zs0ice(ji,jj)/area(ji,jj) )
  217. zs0a (ji,jj) = MAX( rzero, zs0a (ji,jj)/area(ji,jj) )
  218. zs0c0 (ji,jj) = MAX( rzero, zs0c0 (ji,jj)/area(ji,jj) )
  219. zs0c1 (ji,jj) = MAX( rzero, zs0c1 (ji,jj)/area(ji,jj) )
  220. zs0c2 (ji,jj) = MAX( rzero, zs0c2 (ji,jj)/area(ji,jj) )
  221. zs0st (ji,jj) = MAX( rzero, zs0st (ji,jj)/area(ji,jj) )
  222. ! Recover in situ values.
  223. zindb = MAX( rzero, SIGN( rone, zs0a(ji,jj) - epsi06 ) )
  224. zacrith = 1.0 - ( zindhe * acrit(1) + ( 1.0 - zindhe ) * acrit(2) )
  225. zs0a (ji,jj) = zindb * MIN( zs0a(ji,jj), zacrith )
  226. hsnif(ji,jj) = zindb * ( zs0sn(ji,jj) /MAX( zs0a(ji,jj), epsi16 ) )
  227. hicif(ji,jj) = zindb * ( zs0ice(ji,jj)/MAX( zs0a(ji,jj), epsi16 ) )
  228. zindsn = MAX( rzero, SIGN( rone, hsnif(ji,jj) - epsi06 ) )
  229. zindic = MAX( rzero, SIGN( rone, hicif(ji,jj) - epsi03 ) )
  230. zindb = MAX( zindsn, zindic )
  231. zs0a (ji,jj) = zindb * zs0a(ji,jj)
  232. frld (ji,jj) = 1.0 - zs0a(ji,jj)
  233. hsnif(ji,jj) = zindsn * hsnif(ji,jj)
  234. hicif(ji,jj) = zindic * hicif(ji,jj)
  235. zusvosn = 1.0/MAX( hsnif(ji,jj) * zs0a(ji,jj), epsi16 )
  236. zusvoic = 1.0/MAX( hicif(ji,jj) * zs0a(ji,jj), epsi16 )
  237. zignm = MAX( rzero, SIGN( rone, hsndif - hsnif(ji,jj) ) )
  238. zrtt = 173.15 * rone
  239. ztsn = zignm * tbif(ji,jj,1) &
  240. + ( 1.0 - zignm ) * MIN( MAX( zrtt, rt0_snow * zusvosn * zs0c0(ji,jj)) , tfu(ji,jj) )
  241. ztic1 = MIN( MAX( zrtt, rt0_ice * zusvoic * zs0c1(ji,jj) ) , tfu(ji,jj) )
  242. ztic2 = MIN( MAX( zrtt, rt0_ice * zusvoic * zs0c2(ji,jj) ) , tfu(ji,jj) )
  243. tbif(ji,jj,1) = zindsn * ztsn + ( 1.0 - zindsn ) * tfu(ji,jj)
  244. tbif(ji,jj,2) = zindic * ztic1 + ( 1.0 - zindic ) * tfu(ji,jj)
  245. tbif(ji,jj,3) = zindic * ztic2 + ( 1.0 - zindic ) * tfu(ji,jj)
  246. qstoif(ji,jj) = zindb * xlic * zs0st(ji,jj) / MAX( zs0a(ji,jj), epsi16 )
  247. END DO
  248. END DO
  249. !
  250. ENDIF
  251. !
  252. # if defined key_agrif
  253. CALL agrif_trp_lim2 ! Fill boundaries of the fine grid
  254. # endif
  255. !
  256. CALL wrk_dealloc( jpi, jpj, zui_u , zvi_v , zsm, zs0ice, zs0sn , zs0a, zs0c0 , zs0c1 , zs0c2 , zs0st )
  257. !
  258. END SUBROUTINE lim_trp_2
  259. SUBROUTINE lim_trp_init_2
  260. !!-------------------------------------------------------------------
  261. !! *** ROUTINE lim_trp_init_2 ***
  262. !!
  263. !! ** Purpose : initialization of ice advection parameters
  264. !!
  265. !! ** Method : Read the namicetrp namelist and check the parameter
  266. !! values called at the first timestep (nit000)
  267. !!
  268. !! ** input : Namelist namicetrp
  269. !!-------------------------------------------------------------------
  270. INTEGER :: ios ! Local integer output status for namelist read
  271. NAMELIST/namicetrp/ bound
  272. !!-------------------------------------------------------------------
  273. REWIND( numnam_ice_ref ) ! Namelist namicetrp in reference namelist : Ice advection
  274. READ ( numnam_ice_ref, namicetrp, IOSTAT = ios, ERR = 901)
  275. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namicetrp in reference namelist', lwp )
  276. REWIND( numnam_ice_cfg ) ! Namelist namicetrp in configuration namelist : Ice advection
  277. READ ( numnam_ice_cfg, namicetrp, IOSTAT = ios, ERR = 902 )
  278. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namicetrp in configuration namelist', lwp )
  279. IF(lwm) WRITE ( numoni, namicetrp )
  280. IF(lwp) THEN
  281. WRITE(numout,*)
  282. WRITE(numout,*) 'lim_trp_init_2 : Ice parameters for advection '
  283. WRITE(numout,*) '~~~~~~~~~~~~~~'
  284. WRITE(numout,*) ' boundary conditions (0. no-slip, 1. free-slip) bound = ', bound
  285. ENDIF
  286. !
  287. END SUBROUTINE lim_trp_init_2
  288. #else
  289. !!----------------------------------------------------------------------
  290. !! Default option Empty Module No sea-ice model
  291. !!----------------------------------------------------------------------
  292. CONTAINS
  293. SUBROUTINE lim_trp_2 ! Empty routine
  294. END SUBROUTINE lim_trp_2
  295. #endif
  296. !!======================================================================
  297. END MODULE limtrp_2