limrhg.F90 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. MODULE limrhg
  2. !!======================================================================
  3. !! *** MODULE limrhg ***
  4. !! Ice rheology : sea ice rheology
  5. !!======================================================================
  6. !! History : - ! 2007-03 (M.A. Morales Maqueda, S. Bouillon) Original code
  7. !! 3.0 ! 2008-03 (M. Vancoppenolle) LIM3
  8. !! - ! 2008-11 (M. Vancoppenolle, S. Bouillon, Y. Aksenov) add surface tilt in ice rheolohy
  9. !! 3.3 ! 2009-05 (G.Garric) addition of the lim2_evp cas
  10. !! 3.4 ! 2011-01 (A. Porter) dynamical allocation
  11. !! 3.5 ! 2012-08 (R. Benshila) AGRIF
  12. !! 3.6 ! 2016-06 (C. Rousset) Rewriting (conserves energy)
  13. !!----------------------------------------------------------------------
  14. #if defined key_lim3 || ( defined key_lim2 && ! defined key_lim2_vp )
  15. !!----------------------------------------------------------------------
  16. !! 'key_lim3' OR LIM-3 sea-ice model
  17. !! 'key_lim2' AND NOT 'key_lim2_vp' EVP LIM-2 sea-ice model
  18. !!----------------------------------------------------------------------
  19. !! lim_rhg : computes ice velocities
  20. !!----------------------------------------------------------------------
  21. USE phycst ! Physical constant
  22. USE oce , ONLY : snwice_mass, snwice_mass_b
  23. USE par_oce ! Ocean parameters
  24. USE dom_oce ! Ocean domain
  25. USE sbc_oce ! Surface boundary condition: ocean fields
  26. USE sbc_ice ! Surface boundary condition: ice fields
  27. #if defined key_lim3
  28. USE ice ! LIM-3: ice variables
  29. USE dom_ice ! LIM-3: ice domain
  30. USE limitd_me ! LIM-3:
  31. #else
  32. USE ice_2 ! LIM-2: ice variables
  33. USE dom_ice_2 ! LIM-2: ice domain
  34. #endif
  35. USE lbclnk ! Lateral Boundary Condition / MPP link
  36. USE lib_mpp ! MPP library
  37. USE wrk_nemo ! work arrays
  38. USE in_out_manager ! I/O manager
  39. USE prtctl ! Print control
  40. USE lib_fortran ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined)
  41. #if defined key_agrif && defined key_lim2
  42. USE agrif_lim2_interp
  43. #endif
  44. #if defined key_bdy
  45. USE bdyice_lim
  46. #endif
  47. IMPLICIT NONE
  48. PRIVATE
  49. PUBLIC lim_rhg ! routine called by lim_dyn (or lim_dyn_2)
  50. !! * Substitutions
  51. # include "vectopt_loop_substitute.h90"
  52. !!----------------------------------------------------------------------
  53. !! NEMO/LIM3 4.0 , UCL - NEMO Consortium (2011)
  54. !! $Id: limrhg.F90 4990 2014-12-15 16:42:49Z timgraham $
  55. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  56. !!----------------------------------------------------------------------
  57. CONTAINS
  58. SUBROUTINE lim_rhg( k_j1, k_jpj )
  59. !!-------------------------------------------------------------------
  60. !! *** SUBROUTINE lim_rhg ***
  61. !! EVP-C-grid
  62. !!
  63. !! ** purpose : determines sea ice drift from wind stress, ice-ocean
  64. !! stress and sea-surface slope. Ice-ice interaction is described by
  65. !! a non-linear elasto-viscous-plastic (EVP) law including shear
  66. !! strength and a bulk rheology (Hunke and Dukowicz, 2002).
  67. !!
  68. !! The points in the C-grid look like this, dear reader
  69. !!
  70. !! (ji,jj)
  71. !! |
  72. !! |
  73. !! (ji-1,jj) | (ji,jj)
  74. !! ---------
  75. !! | |
  76. !! | (ji,jj) |------(ji,jj)
  77. !! | |
  78. !! ---------
  79. !! (ji-1,jj-1) (ji,jj-1)
  80. !!
  81. !! ** Inputs : - wind forcing (stress), oceanic currents
  82. !! ice total volume (vt_i) per unit area
  83. !! snow total volume (vt_s) per unit area
  84. !!
  85. !! ** Action : - compute u_ice, v_ice : the components of the
  86. !! sea-ice velocity vector
  87. !! - compute delta_i, shear_i, divu_i, which are inputs
  88. !! of the ice thickness distribution
  89. !!
  90. !! ** Steps : 1) Compute ice snow mass, ice strength
  91. !! 2) Compute wind, oceanic stresses, mass terms and
  92. !! coriolis terms of the momentum equation
  93. !! 3) Solve the momentum equation (iterative procedure)
  94. !! 4) Recompute invariants of the strain rate tensor
  95. !! which are inputs of the ITD, store stress
  96. !! for the next time step
  97. !! 5) Control prints of residual (convergence)
  98. !! and charge ellipse.
  99. !! The user should make sure that the parameters
  100. !! nn_nevp, elastic time scale and rn_creepl maintain stress state
  101. !! on the charge ellipse for plastic flow
  102. !! e.g. in the Canadian Archipelago
  103. !!
  104. !! ** Notes : Boundary condition for ice is chosen no-slip
  105. !! but can be adjusted with param rn_shlat
  106. !!
  107. !! References : Hunke and Dukowicz, JPO97
  108. !! Bouillon et al., Ocean Modelling 2009
  109. !!-------------------------------------------------------------------
  110. INTEGER, INTENT(in) :: k_j1 ! southern j-index for ice computation
  111. INTEGER, INTENT(in) :: k_jpj ! northern j-index for ice computation
  112. !!
  113. INTEGER :: ji, jj ! dummy loop indices
  114. INTEGER :: jter ! local integers
  115. CHARACTER (len=50) :: charout
  116. REAL(wp) :: zdtevp, z1_dtevp ! time step for subcycling
  117. REAL(wp) :: ecc2, z1_ecc2 ! square of yield ellipse eccenticity
  118. REAL(wp) :: zbeta, zalph1, z1_alph1, zalph2, z1_alph2 ! alpha and beta from Bouillon 2009 and 2013
  119. REAL(wp) :: zm1, zm2, zm3, zmassU, zmassV ! ice/snow mass
  120. REAL(wp) :: zdelta, zp_delf, zds2, zdt, zdt2, zdiv, zdiv2 ! temporary scalars
  121. REAL(wp) :: zTauO, zTauE, zCor ! temporary scalars
  122. REAL(wp) :: zsig1, zsig2 ! internal ice stress
  123. REAL(wp) :: zresm ! Maximal error on ice velocity
  124. REAL(wp) :: zintb, zintn ! dummy argument
  125. REAL(wp), POINTER, DIMENSION(:,:) :: zpresh ! temporary array for ice strength
  126. REAL(wp), POINTER, DIMENSION(:,:) :: z1_e1t0, z1_e2t0 ! scale factors
  127. REAL(wp), POINTER, DIMENSION(:,:) :: zp_delt ! P/delta at T points
  128. !
  129. REAL(wp), POINTER, DIMENSION(:,:) :: zaU , zaV ! ice fraction on U/V points
  130. REAL(wp), POINTER, DIMENSION(:,:) :: zmU_t, zmV_t ! ice/snow mass/dt on U/V points
  131. REAL(wp), POINTER, DIMENSION(:,:) :: zmf ! coriolis parameter at T points
  132. REAL(wp), POINTER, DIMENSION(:,:) :: zTauU_ia , ztauV_ia ! ice-atm. stress at U-V points
  133. REAL(wp), POINTER, DIMENSION(:,:) :: zspgU , zspgV ! surface pressure gradient at U/V points
  134. REAL(wp), POINTER, DIMENSION(:,:) :: v_oceU, u_oceV, v_iceU, u_iceV ! ocean/ice u/v component on V/U points
  135. REAL(wp), POINTER, DIMENSION(:,:) :: zfU , zfV ! internal stresses
  136. REAL(wp), POINTER, DIMENSION(:,:) :: zds ! shear
  137. REAL(wp), POINTER, DIMENSION(:,:) :: zs1, zs2, zs12 ! stress tensor components
  138. REAL(wp), POINTER, DIMENSION(:,:) :: zu_ice, zv_ice, zresr ! check convergence
  139. REAL(wp), POINTER, DIMENSION(:,:) :: zpice ! array used for the calculation of ice surface slope:
  140. ! ocean surface (ssh_m) if ice is not embedded
  141. ! ice top surface if ice is embedded
  142. REAL(wp), POINTER, DIMENSION(:,:) :: zswitchU, zswitchV ! dummy arrays
  143. REAL(wp), POINTER, DIMENSION(:,:) :: zmaskU, zmaskV ! mask for ice presence
  144. REAL(wp), POINTER, DIMENSION(:,:) :: zfmask, zwf ! mask at F points for the ice
  145. REAL(wp), PARAMETER :: zepsi = 1.0e-20_wp ! tolerance parameter
  146. REAL(wp), PARAMETER :: zmmin = 1._wp ! ice mass (kg/m2) below which ice velocity equals ocean velocity
  147. REAL(wp), PARAMETER :: zshlat = 2._wp ! boundary condition for sea-ice velocity (2=no slip ; 0=free slip)
  148. !!-------------------------------------------------------------------
  149. CALL wrk_alloc( jpi,jpj, zpresh, z1_e1t0, z1_e2t0, zp_delt )
  150. CALL wrk_alloc( jpi,jpj, zaU, zaV, zmU_t, zmV_t, zmf, zTauU_ia, ztauV_ia )
  151. CALL wrk_alloc( jpi,jpj, zspgU, zspgV, v_oceU, u_oceV, v_iceU, u_iceV, zfU, zfV )
  152. CALL wrk_alloc( jpi,jpj, zds, zs1, zs2, zs12, zu_ice, zv_ice, zresr, zpice )
  153. CALL wrk_alloc( jpi,jpj, zswitchU, zswitchV, zmaskU, zmaskV, zfmask, zwf )
  154. #if defined key_lim2 && ! defined key_lim2_vp
  155. # if defined key_agrif
  156. USE ice_2, vt_s => hsnm
  157. USE ice_2, vt_i => hicm
  158. # else
  159. vt_s => hsnm
  160. vt_i => hicm
  161. # endif
  162. at_i(:,:) = 1. - frld(:,:)
  163. #endif
  164. #if defined key_agrif && defined key_lim2
  165. CALL agrif_rhg_lim2_load ! First interpolation of coarse values
  166. #endif
  167. !
  168. !------------------------------------------------------------------------------!
  169. ! 0) mask at F points for the ice (on the whole domain, not only k_j1,k_jpj)
  170. !------------------------------------------------------------------------------!
  171. ! ocean/land mask
  172. DO jj = 1, jpjm1
  173. DO ji = 1, jpim1 ! NO vector opt.
  174. zfmask(ji,jj) = tmask(ji,jj,1) * tmask(ji+1,jj,1) * tmask(ji,jj+1,1) * tmask(ji+1,jj+1,1)
  175. END DO
  176. END DO
  177. CALL lbc_lnk( zfmask, 'F', 1._wp )
  178. ! Lateral boundary conditions on velocity (modify zfmask)
  179. zwf(:,:) = zfmask(:,:)
  180. DO jj = 2, jpjm1
  181. DO ji = fs_2, fs_jpim1 ! vector opt.
  182. IF( zfmask(ji,jj) == 0._wp ) THEN
  183. zfmask(ji,jj) = zshlat * MIN( 1._wp , MAX( zwf(ji+1,jj), zwf(ji,jj+1), zwf(ji-1,jj), zwf(ji,jj-1) ) )
  184. ENDIF
  185. END DO
  186. END DO
  187. DO jj = 2, jpjm1
  188. IF( zfmask(1,jj) == 0._wp ) THEN
  189. zfmask(1 ,jj) = zshlat * MIN( 1._wp , MAX( zwf(2,jj), zwf(1,jj+1), zwf(1,jj-1) ) )
  190. ENDIF
  191. IF( zfmask(jpi,jj) == 0._wp ) THEN
  192. zfmask(jpi,jj) = zshlat * MIN( 1._wp , MAX( zwf(jpi,jj+1), zwf(jpim1,jj), zwf(jpi,jj-1) ) )
  193. ENDIF
  194. END DO
  195. DO ji = 2, jpim1
  196. IF( zfmask(ji,1) == 0._wp ) THEN
  197. zfmask(ji,1 ) = zshlat * MIN( 1._wp , MAX( zwf(ji+1,1), zwf(ji,2), zwf(ji-1,1) ) )
  198. ENDIF
  199. IF( zfmask(ji,jpj) == 0._wp ) THEN
  200. zfmask(ji,jpj) = zshlat * MIN( 1._wp , MAX( zwf(ji+1,jpj), zwf(ji-1,jpj), zwf(ji,jpjm1) ) )
  201. ENDIF
  202. END DO
  203. CALL lbc_lnk( zfmask, 'F', 1._wp )
  204. !------------------------------------------------------------------------------!
  205. ! 1) define some variables and initialize arrays
  206. !------------------------------------------------------------------------------!
  207. ! ecc2: square of yield ellipse eccenticrity
  208. ecc2 = rn_ecc * rn_ecc
  209. z1_ecc2 = 1._wp / ecc2
  210. ! Time step for subcycling
  211. zdtevp = rdt_ice / REAL( nn_nevp )
  212. z1_dtevp = 1._wp / zdtevp
  213. ! alpha parameters (Bouillon 2009)
  214. #if defined key_lim3
  215. zalph1 = ( 2._wp * rn_relast * rdt_ice ) * z1_dtevp
  216. #else
  217. zalph1 = ( 2._wp * telast ) * z1_dtevp
  218. #endif
  219. zalph2 = zalph1 * z1_ecc2
  220. z1_alph1 = 1._wp / ( zalph1 + 1._wp )
  221. z1_alph2 = 1._wp / ( zalph2 + 1._wp )
  222. ! Initialise stress tensor
  223. zs1 (:,:) = stress1_i (:,:)
  224. zs2 (:,:) = stress2_i (:,:)
  225. zs12(:,:) = stress12_i(:,:)
  226. ! Ice strength
  227. #if defined key_lim3
  228. CALL lim_itd_me_icestrength( nn_icestr )
  229. zpresh(:,:) = tmask(:,:,1) * strength(:,:)
  230. #else
  231. zpresh(:,:) = tmask(:,:,1) * pstar * vt_i(:,:) * EXP( -c_rhg * (1. - at_i(:,:) ) )
  232. #endif
  233. ! scale factors
  234. DO jj = k_j1+1, k_jpj-1
  235. DO ji = fs_2, fs_jpim1
  236. z1_e1t0(ji,jj) = 1._wp / ( e1t(ji+1,jj ) + e1t(ji,jj ) )
  237. z1_e2t0(ji,jj) = 1._wp / ( e2t(ji ,jj+1) + e2t(ji,jj ) )
  238. END DO
  239. END DO
  240. !
  241. !------------------------------------------------------------------------------!
  242. ! 2) Wind / ocean stress, mass terms, coriolis terms
  243. !------------------------------------------------------------------------------!
  244. IF( nn_ice_embd == 2 ) THEN !== embedded sea ice: compute representative ice top surface ==!
  245. !
  246. ! average interpolation coeff as used in dynspg = (1/nn_fsbc) * {SUM[n/nn_fsbc], n=0,nn_fsbc-1}
  247. ! = (1/nn_fsbc)^2 * {SUM[n], n=0,nn_fsbc-1}
  248. zintn = REAL( nn_fsbc - 1 ) / REAL( nn_fsbc ) * 0.5_wp
  249. !
  250. ! average interpolation coeff as used in dynspg = (1/nn_fsbc) * {SUM[1-n/nn_fsbc], n=0,nn_fsbc-1}
  251. ! = (1/nn_fsbc)^2 * (nn_fsbc^2 - {SUM[n], n=0,nn_fsbc-1})
  252. zintb = REAL( nn_fsbc + 1 ) / REAL( nn_fsbc ) * 0.5_wp
  253. !
  254. zpice(:,:) = ssh_m(:,:) + ( zintn * snwice_mass(:,:) + zintb * snwice_mass_b(:,:) ) * r1_rau0
  255. !
  256. ELSE !== non-embedded sea ice: use ocean surface for slope calculation ==!
  257. zpice(:,:) = ssh_m(:,:)
  258. ENDIF
  259. DO jj = k_j1+1, k_jpj-1
  260. DO ji = fs_2, fs_jpim1
  261. ! ice fraction at U-V points
  262. zaU(ji,jj) = 0.5_wp * ( at_i(ji,jj) * e12t(ji,jj) + at_i(ji+1,jj) * e12t(ji+1,jj) ) * r1_e12u(ji,jj) * umask(ji,jj,1)
  263. zaV(ji,jj) = 0.5_wp * ( at_i(ji,jj) * e12t(ji,jj) + at_i(ji,jj+1) * e12t(ji,jj+1) ) * r1_e12v(ji,jj) * vmask(ji,jj,1)
  264. ! Ice/snow mass at U-V points
  265. zm1 = ( rhosn * vt_s(ji ,jj ) + rhoic * vt_i(ji ,jj ) )
  266. zm2 = ( rhosn * vt_s(ji+1,jj ) + rhoic * vt_i(ji+1,jj ) )
  267. zm3 = ( rhosn * vt_s(ji ,jj+1) + rhoic * vt_i(ji ,jj+1) )
  268. zmassU = 0.5_wp * ( zm1 * e12t(ji,jj) + zm2 * e12t(ji+1,jj) ) * r1_e12u(ji,jj) * umask(ji,jj,1)
  269. zmassV = 0.5_wp * ( zm1 * e12t(ji,jj) + zm3 * e12t(ji,jj+1) ) * r1_e12v(ji,jj) * vmask(ji,jj,1)
  270. ! Ocean currents at U-V points
  271. v_oceU(ji,jj) = 0.5_wp * ( ( v_oce(ji ,jj) + v_oce(ji ,jj-1) ) * e1t(ji+1,jj) &
  272. & + ( v_oce(ji+1,jj) + v_oce(ji+1,jj-1) ) * e1t(ji ,jj) ) * z1_e1t0(ji,jj) * umask(ji,jj,1)
  273. u_oceV(ji,jj) = 0.5_wp * ( ( u_oce(ji,jj ) + u_oce(ji-1,jj ) ) * e2t(ji,jj+1) &
  274. & + ( u_oce(ji,jj+1) + u_oce(ji-1,jj+1) ) * e2t(ji,jj ) ) * z1_e2t0(ji,jj) * vmask(ji,jj,1)
  275. ! Coriolis at T points (m*f)
  276. zmf(ji,jj) = zm1 * fcor(ji,jj)
  277. ! m/dt
  278. zmU_t(ji,jj) = zmassU * z1_dtevp
  279. zmV_t(ji,jj) = zmassV * z1_dtevp
  280. ! Drag ice-atm.
  281. zTauU_ia(ji,jj) = zaU(ji,jj) * utau_ice(ji,jj)
  282. zTauV_ia(ji,jj) = zaV(ji,jj) * vtau_ice(ji,jj)
  283. ! Surface pressure gradient (- m*g*GRAD(ssh)) at U-V points
  284. zspgU(ji,jj) = - zmassU * grav * ( zpice(ji+1,jj) - zpice(ji,jj) ) * r1_e1u(ji,jj)
  285. zspgV(ji,jj) = - zmassV * grav * ( zpice(ji,jj+1) - zpice(ji,jj) ) * r1_e2v(ji,jj)
  286. ! masks
  287. zmaskU(ji,jj) = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zmassU ) ) ! 0 if no ice
  288. zmaskV(ji,jj) = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zmassV ) ) ! 0 if no ice
  289. ! switches
  290. zswitchU(ji,jj) = MAX( 0._wp, SIGN( 1._wp, zmassU - zmmin ) ) ! 0 if ice mass < zmmin
  291. zswitchV(ji,jj) = MAX( 0._wp, SIGN( 1._wp, zmassV - zmmin ) ) ! 0 if ice mass < zmmin
  292. END DO
  293. END DO
  294. CALL lbc_lnk( zmf, 'T', 1. )
  295. !
  296. !------------------------------------------------------------------------------!
  297. ! 3) Solution of the momentum equation, iterative procedure
  298. !------------------------------------------------------------------------------!
  299. !
  300. ! !----------------------!
  301. DO jter = 1 , nn_nevp ! loop over jter !
  302. ! !----------------------!
  303. IF(ln_ctl) THEN ! Convergence test
  304. DO jj = k_j1, k_jpj-1
  305. zu_ice(:,jj) = u_ice(:,jj) ! velocity at previous time step
  306. zv_ice(:,jj) = v_ice(:,jj)
  307. END DO
  308. ENDIF
  309. ! --- divergence, tension & shear (Appendix B of Hunke & Dukowicz, 2002) --- !
  310. DO jj = k_j1, k_jpj-1 ! loops start at 1 since there is no boundary condition (lbc_lnk) at i=1 and j=1 for F points
  311. DO ji = 1, jpim1
  312. ! shear at F points
  313. zds(ji,jj) = ( ( u_ice(ji,jj+1) * r1_e1u(ji,jj+1) - u_ice(ji,jj) * r1_e1u(ji,jj) ) * e1f(ji,jj) * e1f(ji,jj) &
  314. & + ( v_ice(ji+1,jj) * r1_e2v(ji+1,jj) - v_ice(ji,jj) * r1_e2v(ji,jj) ) * e2f(ji,jj) * e2f(ji,jj) &
  315. & ) * r1_e12f(ji,jj) * zfmask(ji,jj)
  316. END DO
  317. END DO
  318. CALL lbc_lnk( zds, 'F', 1. )
  319. DO jj = k_j1+1, k_jpj-1
  320. DO ji = 2, jpim1 ! no vector loop
  321. ! shear**2 at T points (doc eq. A16)
  322. zds2 = ( zds(ji,jj ) * zds(ji,jj ) * e12f(ji,jj ) + zds(ji-1,jj ) * zds(ji-1,jj ) * e12f(ji-1,jj ) &
  323. & + zds(ji,jj-1) * zds(ji,jj-1) * e12f(ji,jj-1) + zds(ji-1,jj-1) * zds(ji-1,jj-1) * e12f(ji-1,jj-1) &
  324. & ) * 0.25_wp * r1_e12t(ji,jj)
  325. ! divergence at T points
  326. zdiv = ( e2u(ji,jj) * u_ice(ji,jj) - e2u(ji-1,jj) * u_ice(ji-1,jj) &
  327. & + e1v(ji,jj) * v_ice(ji,jj) - e1v(ji,jj-1) * v_ice(ji,jj-1) &
  328. & ) * r1_e12t(ji,jj)
  329. zdiv2 = zdiv * zdiv
  330. ! tension at T points
  331. zdt = ( ( u_ice(ji,jj) * r1_e2u(ji,jj) - u_ice(ji-1,jj) * r1_e2u(ji-1,jj) ) * e2t(ji,jj) * e2t(ji,jj) &
  332. & - ( v_ice(ji,jj) * r1_e1v(ji,jj) - v_ice(ji,jj-1) * r1_e1v(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj) &
  333. & ) * r1_e12t(ji,jj)
  334. zdt2 = zdt * zdt
  335. ! delta at T points
  336. zdelta = SQRT( zdiv2 + ( zdt2 + zds2 ) * usecc2 )
  337. ! P/delta at T points
  338. zp_delt(ji,jj) = zpresh(ji,jj) / ( zdelta + rn_creepl )
  339. ! stress at T points
  340. zs1(ji,jj) = ( zs1(ji,jj) * zalph1 + zp_delt(ji,jj) * ( zdiv - zdelta ) ) * z1_alph1
  341. zs2(ji,jj) = ( zs2(ji,jj) * zalph2 + zp_delt(ji,jj) * ( zdt * z1_ecc2 ) ) * z1_alph2
  342. END DO
  343. END DO
  344. CALL lbc_lnk( zp_delt, 'T', 1. )
  345. DO jj = k_j1, k_jpj-1
  346. DO ji = 1, jpim1
  347. ! P/delta at F points
  348. zp_delf = 0.25_wp * ( zp_delt(ji,jj) + zp_delt(ji+1,jj) + zp_delt(ji,jj+1) + zp_delt(ji+1,jj+1) )
  349. ! stress at F points
  350. zs12(ji,jj)= ( zs12(ji,jj) * zalph2 + zp_delf * ( zds(ji,jj) * z1_ecc2 ) * 0.5_wp ) * z1_alph2
  351. END DO
  352. END DO
  353. CALL lbc_lnk_multi( zs1, 'T', 1., zs2, 'T', 1., zs12, 'F', 1. )
  354. ! --- Ice internal stresses (Appendix C of Hunke and Dukowicz, 2002) --- !
  355. DO jj = k_j1+1, k_jpj-1
  356. DO ji = fs_2, fs_jpim1
  357. ! U points
  358. zfU(ji,jj) = 0.5_wp * ( ( zs1(ji+1,jj) - zs1(ji,jj) ) * e2u(ji,jj) &
  359. & + ( zs2(ji+1,jj) * e2t(ji+1,jj) * e2t(ji+1,jj) - zs2(ji,jj) * e2t(ji,jj) * e2t(ji,jj) &
  360. & ) * r1_e2u(ji,jj) &
  361. & + ( zs12(ji,jj) * e1f(ji,jj) * e1f(ji,jj) - zs12(ji,jj-1) * e1f(ji,jj-1) * e1f(ji,jj-1) &
  362. & ) * 2._wp * r1_e1u(ji,jj) &
  363. & ) * r1_e12u(ji,jj)
  364. ! V points
  365. zfV(ji,jj) = 0.5_wp * ( ( zs1(ji,jj+1) - zs1(ji,jj) ) * e1v(ji,jj) &
  366. & - ( zs2(ji,jj+1) * e1t(ji,jj+1) * e1t(ji,jj+1) - zs2(ji,jj) * e1t(ji,jj) * e1t(ji,jj) &
  367. & ) * r1_e1v(ji,jj) &
  368. & + ( zs12(ji,jj) * e2f(ji,jj) * e2f(ji,jj) - zs12(ji-1,jj) * e2f(ji-1,jj) * e2f(ji-1,jj) &
  369. & ) * 2._wp * r1_e2v(ji,jj) &
  370. & ) * r1_e12v(ji,jj)
  371. ! u_ice at V point
  372. u_iceV(ji,jj) = 0.5_wp * ( ( u_ice(ji,jj ) + u_ice(ji-1,jj ) ) * e2t(ji,jj+1) &
  373. & + ( u_ice(ji,jj+1) + u_ice(ji-1,jj+1) ) * e2t(ji,jj ) ) * z1_e2t0(ji,jj) * vmask(ji,jj,1)
  374. ! v_ice at U point
  375. v_iceU(ji,jj) = 0.5_wp * ( ( v_ice(ji ,jj) + v_ice(ji ,jj-1) ) * e1t(ji+1,jj) &
  376. & + ( v_ice(ji+1,jj) + v_ice(ji+1,jj-1) ) * e1t(ji ,jj) ) * z1_e1t0(ji,jj) * umask(ji,jj,1)
  377. END DO
  378. END DO
  379. !
  380. ! --- Computation of ice velocity --- !
  381. ! Bouillon et al. 2013 (eq 47-48) => unstable unless alpha, beta are chosen wisely and large nn_nevp
  382. ! Bouillon et al. 2009 (eq 34-35) => stable
  383. IF( MOD(jter,2) .EQ. 0 ) THEN ! even iterations
  384. DO jj = k_j1+1, k_jpj-1
  385. DO ji = fs_2, fs_jpim1
  386. ! tau_io/(v_oce - v_ice)
  387. zTauO = zaV(ji,jj) * rhoco * SQRT( ( v_ice (ji,jj) - v_oce (ji,jj) ) * ( v_ice (ji,jj) - v_oce (ji,jj) ) &
  388. & + ( u_iceV(ji,jj) - u_oceV(ji,jj) ) * ( u_iceV(ji,jj) - u_oceV(ji,jj) ) )
  389. ! Coriolis at V-points (energy conserving formulation)
  390. zCor = - 0.25_wp * r1_e2v(ji,jj) * &
  391. & ( zmf(ji,jj ) * ( e2u(ji,jj ) * u_ice(ji,jj ) + e2u(ji-1,jj ) * u_ice(ji-1,jj ) ) &
  392. & + zmf(ji,jj+1) * ( e2u(ji,jj+1) * u_ice(ji,jj+1) + e2u(ji-1,jj+1) * u_ice(ji-1,jj+1) ) )
  393. ! Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
  394. zTauE = zfV(ji,jj) + zTauV_ia(ji,jj) + zCor + zspgV(ji,jj) + zTauO * ( v_oce(ji,jj) - v_ice(ji,jj) )
  395. ! ice velocity using implicit formulation (cf Madec doc & Bouillon 2009)
  396. v_ice(ji,jj) = ( ( zmV_t(ji,jj) * v_ice(ji,jj) + zTauE + zTauO * v_ice(ji,jj) & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
  397. & ) / MAX( zepsi, zmV_t(ji,jj) + zTauO ) * zswitchV(ji,jj) & ! m/dt + tau_io(only ice part)
  398. & + v_oce(ji,jj) * ( 1._wp - zswitchV(ji,jj) ) & ! v_ice = v_oce if mass < zmmin
  399. & ) * zmaskV(ji,jj)
  400. END DO
  401. END DO
  402. CALL lbc_lnk( v_ice, 'V', -1. )
  403. #if defined key_agrif && defined key_lim2
  404. CALL agrif_rhg_lim2( jter, nn_nevp, 'V' )
  405. #endif
  406. #if defined key_bdy
  407. CALL bdy_ice_lim_dyn( 'V' )
  408. #endif
  409. DO jj = k_j1+1, k_jpj-1
  410. DO ji = fs_2, fs_jpim1
  411. ! tau_io/(u_oce - u_ice)
  412. zTauO = zaU(ji,jj) * rhoco * SQRT( ( u_ice (ji,jj) - u_oce (ji,jj) ) * ( u_ice (ji,jj) - u_oce (ji,jj) ) &
  413. & + ( v_iceU(ji,jj) - v_oceU(ji,jj) ) * ( v_iceU(ji,jj) - v_oceU(ji,jj) ) )
  414. ! Coriolis at U-points (energy conserving formulation)
  415. zCor = 0.25_wp * r1_e1u(ji,jj) * &
  416. & ( zmf(ji ,jj) * ( e1v(ji ,jj) * v_ice(ji ,jj) + e1v(ji ,jj-1) * v_ice(ji ,jj-1) ) &
  417. & + zmf(ji+1,jj) * ( e1v(ji+1,jj) * v_ice(ji+1,jj) + e1v(ji+1,jj-1) * v_ice(ji+1,jj-1) ) )
  418. ! Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
  419. zTauE = zfU(ji,jj) + zTauU_ia(ji,jj) + zCor + zspgU(ji,jj) + zTauO * ( u_oce(ji,jj) - u_ice(ji,jj) )
  420. ! ice velocity using implicit formulation (cf Madec doc & Bouillon 2009)
  421. u_ice(ji,jj) = ( ( zmU_t(ji,jj) * u_ice(ji,jj) + zTauE + zTauO * u_ice(ji,jj) & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
  422. & ) / MAX( zepsi, zmU_t(ji,jj) + zTauO ) * zswitchU(ji,jj) & ! m/dt + tau_io(only ice part)
  423. & + u_oce(ji,jj) * ( 1._wp - zswitchU(ji,jj) ) & ! v_ice = v_oce if mass < zmmin
  424. & ) * zmaskU(ji,jj)
  425. END DO
  426. END DO
  427. CALL lbc_lnk( u_ice, 'U', -1. )
  428. #if defined key_agrif && defined key_lim2
  429. CALL agrif_rhg_lim2( jter, nn_nevp, 'U' )
  430. #endif
  431. #if defined key_bdy
  432. CALL bdy_ice_lim_dyn( 'U' )
  433. #endif
  434. ELSE ! odd iterations
  435. DO jj = k_j1+1, k_jpj-1
  436. DO ji = fs_2, fs_jpim1
  437. ! tau_io/(u_oce - u_ice)
  438. zTauO = zaU(ji,jj) * rhoco * SQRT( ( u_ice (ji,jj) - u_oce (ji,jj) ) * ( u_ice (ji,jj) - u_oce (ji,jj) ) &
  439. & + ( v_iceU(ji,jj) - v_oceU(ji,jj) ) * ( v_iceU(ji,jj) - v_oceU(ji,jj) ) )
  440. ! Coriolis at U-points (energy conserving formulation)
  441. zCor = 0.25_wp * r1_e1u(ji,jj) * &
  442. & ( zmf(ji ,jj) * ( e1v(ji ,jj) * v_ice(ji ,jj) + e1v(ji ,jj-1) * v_ice(ji ,jj-1) ) &
  443. & + zmf(ji+1,jj) * ( e1v(ji+1,jj) * v_ice(ji+1,jj) + e1v(ji+1,jj-1) * v_ice(ji+1,jj-1) ) )
  444. ! Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
  445. zTauE = zfU(ji,jj) + zTauU_ia(ji,jj) + zCor + zspgU(ji,jj) + zTauO * ( u_oce(ji,jj) - u_ice(ji,jj) )
  446. ! ice velocity using implicit formulation (cf Madec doc & Bouillon 2009)
  447. u_ice(ji,jj) = ( ( zmU_t(ji,jj) * u_ice(ji,jj) + zTauE + zTauO * u_ice(ji,jj) & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
  448. & ) / MAX( zepsi, zmU_t(ji,jj) + zTauO ) * zswitchU(ji,jj) & ! m/dt + tau_io(only ice part)
  449. & + u_oce(ji,jj) * ( 1._wp - zswitchU(ji,jj) ) & ! v_ice = v_oce if mass < zmmin
  450. & ) * zmaskU(ji,jj)
  451. END DO
  452. END DO
  453. CALL lbc_lnk( u_ice, 'U', -1. )
  454. #if defined key_agrif && defined key_lim2
  455. CALL agrif_rhg_lim2( jter, nn_nevp, 'U' )
  456. #endif
  457. #if defined key_bdy
  458. CALL bdy_ice_lim_dyn( 'U' )
  459. #endif
  460. DO jj = k_j1+1, k_jpj-1
  461. DO ji = fs_2, fs_jpim1
  462. ! tau_io/(v_oce - v_ice)
  463. zTauO = zaV(ji,jj) * rhoco * SQRT( ( v_ice (ji,jj) - v_oce (ji,jj) ) * ( v_ice (ji,jj) - v_oce (ji,jj) ) &
  464. & + ( u_iceV(ji,jj) - u_oceV(ji,jj) ) * ( u_iceV(ji,jj) - u_oceV(ji,jj) ) )
  465. ! Coriolis at V-points (energy conserving formulation)
  466. zCor = - 0.25_wp * r1_e2v(ji,jj) * &
  467. & ( zmf(ji,jj ) * ( e2u(ji,jj ) * u_ice(ji,jj ) + e2u(ji-1,jj ) * u_ice(ji-1,jj ) ) &
  468. & + zmf(ji,jj+1) * ( e2u(ji,jj+1) * u_ice(ji,jj+1) + e2u(ji-1,jj+1) * u_ice(ji-1,jj+1) ) )
  469. ! Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
  470. zTauE = zfV(ji,jj) + zTauV_ia(ji,jj) + zCor + zspgV(ji,jj) + zTauO * ( v_oce(ji,jj) - v_ice(ji,jj) )
  471. ! ice velocity using implicit formulation (cf Madec doc & Bouillon 2009)
  472. v_ice(ji,jj) = ( ( zmV_t(ji,jj) * v_ice(ji,jj) + zTauE + zTauO * v_ice(ji,jj) & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
  473. & ) / MAX( zepsi, zmV_t(ji,jj) + zTauO ) * zswitchV(ji,jj) & ! m/dt + tau_io(only ice part)
  474. & + v_oce(ji,jj) * ( 1._wp - zswitchV(ji,jj) ) & ! v_ice = v_oce if mass < zmmin
  475. & ) * zmaskV(ji,jj)
  476. END DO
  477. END DO
  478. CALL lbc_lnk( v_ice, 'V', -1. )
  479. #if defined key_agrif && defined key_lim2
  480. CALL agrif_rhg_lim2( jter, nn_nevp, 'V' )
  481. #endif
  482. #if defined key_bdy
  483. CALL bdy_ice_lim_dyn( 'V' )
  484. #endif
  485. ENDIF
  486. IF(ln_ctl) THEN ! Convergence test
  487. DO jj = k_j1+1, k_jpj-1
  488. zresr(:,jj) = MAX( ABS( u_ice(:,jj) - zu_ice(:,jj) ), ABS( v_ice(:,jj) - zv_ice(:,jj) ) )
  489. END DO
  490. zresm = MAXVAL( zresr( 1:jpi, k_j1+1:k_jpj-1 ) )
  491. IF( lk_mpp ) CALL mpp_max( zresm ) ! max over the global domain
  492. ENDIF
  493. !
  494. ! ! ==================== !
  495. END DO ! end loop over jter !
  496. ! ! ==================== !
  497. !
  498. !------------------------------------------------------------------------------!
  499. ! 4) Recompute delta, shear and div (inputs for mechanical redistribution)
  500. !------------------------------------------------------------------------------!
  501. DO jj = k_j1, k_jpj-1
  502. DO ji = 1, jpim1
  503. ! shear at F points
  504. zds(ji,jj) = ( ( u_ice(ji,jj+1) * r1_e1u(ji,jj+1) - u_ice(ji,jj) * r1_e1u(ji,jj) ) * e1f(ji,jj) * e1f(ji,jj) &
  505. & + ( v_ice(ji+1,jj) * r1_e2v(ji+1,jj) - v_ice(ji,jj) * r1_e2v(ji,jj) ) * e2f(ji,jj) * e2f(ji,jj) &
  506. & ) * r1_e12f(ji,jj) * zfmask(ji,jj)
  507. END DO
  508. END DO
  509. CALL lbc_lnk( zds, 'F', 1. )
  510. DO jj = k_j1+1, k_jpj-1
  511. DO ji = 2, jpim1 ! no vector loop
  512. ! tension**2 at T points
  513. zdt = ( ( u_ice(ji,jj) * r1_e2u(ji,jj) - u_ice(ji-1,jj) * r1_e2u(ji-1,jj) ) * e2t(ji,jj) * e2t(ji,jj) &
  514. & - ( v_ice(ji,jj) * r1_e1v(ji,jj) - v_ice(ji,jj-1) * r1_e1v(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj) &
  515. & ) * r1_e12t(ji,jj)
  516. zdt2 = zdt * zdt
  517. ! shear**2 at T points (doc eq. A16)
  518. zds2 = ( zds(ji,jj ) * zds(ji,jj ) * e12f(ji,jj ) + zds(ji-1,jj ) * zds(ji-1,jj ) * e12f(ji-1,jj ) &
  519. & + zds(ji,jj-1) * zds(ji,jj-1) * e12f(ji,jj-1) + zds(ji-1,jj-1) * zds(ji-1,jj-1) * e12f(ji-1,jj-1) &
  520. & ) * 0.25_wp * r1_e12t(ji,jj)
  521. ! shear at T points
  522. shear_i(ji,jj) = SQRT( zdt2 + zds2 )
  523. ! divergence at T points
  524. divu_i(ji,jj) = ( e2u(ji,jj) * u_ice(ji,jj) - e2u(ji-1,jj) * u_ice(ji-1,jj) &
  525. & + e1v(ji,jj) * v_ice(ji,jj) - e1v(ji,jj-1) * v_ice(ji,jj-1) &
  526. & ) * r1_e12t(ji,jj)
  527. ! delta at T points
  528. zdelta = SQRT( divu_i(ji,jj) * divu_i(ji,jj) + ( zdt2 + zds2 ) * usecc2 )
  529. rswitch = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zdelta ) ) ! 0 if delta=0
  530. delta_i(ji,jj) = zdelta + rn_creepl * rswitch
  531. END DO
  532. END DO
  533. CALL lbc_lnk_multi( shear_i, 'T', 1., divu_i, 'T', 1., delta_i, 'T', 1. )
  534. ! --- Store the stress tensor for the next time step --- !
  535. stress1_i (:,:) = zs1 (:,:)
  536. stress2_i (:,:) = zs2 (:,:)
  537. stress12_i(:,:) = zs12(:,:)
  538. !
  539. !------------------------------------------------------------------------------!
  540. ! 5) Control prints of residual and charge ellipse
  541. !------------------------------------------------------------------------------!
  542. !
  543. ! print the residual for convergence
  544. IF(ln_ctl) THEN
  545. WRITE(charout,FMT="('lim_rhg : res =',D23.16, ' iter =',I4)") zresm, jter
  546. CALL prt_ctl_info(charout)
  547. CALL prt_ctl(tab2d_1=u_ice, clinfo1=' lim_rhg : u_ice :', tab2d_2=v_ice, clinfo2=' v_ice :')
  548. ENDIF
  549. ! print charge ellipse
  550. ! This can be desactivated once the user is sure that the stress state
  551. ! lie on the charge ellipse. See Bouillon et al. 08 for more details
  552. IF(ln_ctl) THEN
  553. CALL prt_ctl_info('lim_rhg : numit :',ivar1=numit)
  554. CALL prt_ctl_info('lim_rhg : nwrite :',ivar1=nwrite)
  555. CALL prt_ctl_info('lim_rhg : MOD :',ivar1=MOD(numit,nwrite))
  556. IF( MOD(numit,nwrite) .EQ. 0 ) THEN
  557. WRITE(charout,FMT="('lim_rhg :', I4, I6, I1, I1, A10)") 1000, numit, 0, 0, ' ch. ell. '
  558. CALL prt_ctl_info(charout)
  559. DO jj = k_j1+1, k_jpj-1
  560. DO ji = 2, jpim1
  561. IF (zpresh(ji,jj) > 1.0) THEN
  562. zsig1 = ( zs1(ji,jj) + (zs2(ji,jj)**2 + 4*zs12(ji,jj)**2 )**0.5 ) / ( 2*zpresh(ji,jj) )
  563. zsig2 = ( zs1(ji,jj) - (zs2(ji,jj)**2 + 4*zs12(ji,jj)**2 )**0.5 ) / ( 2*zpresh(ji,jj) )
  564. WRITE(charout,FMT="('lim_rhg :', I4, I4, D23.16, D23.16, D23.16, D23.16, A10)")
  565. CALL prt_ctl_info(charout)
  566. ENDIF
  567. END DO
  568. END DO
  569. WRITE(charout,FMT="('lim_rhg :', I4, I6, I1, I1, A10)") 2000, numit, 0, 0, ' ch. ell. '
  570. CALL prt_ctl_info(charout)
  571. ENDIF
  572. ENDIF
  573. !
  574. CALL wrk_dealloc( jpi,jpj, zpresh, z1_e1t0, z1_e2t0, zp_delt )
  575. CALL wrk_dealloc( jpi,jpj, zaU, zaV, zmU_t, zmV_t, zmf, zTauU_ia, ztauV_ia )
  576. CALL wrk_dealloc( jpi,jpj, zspgU, zspgV, v_oceU, u_oceV, v_iceU, u_iceV, zfU, zfV )
  577. CALL wrk_dealloc( jpi,jpj, zds, zs1, zs2, zs12, zu_ice, zv_ice, zresr, zpice )
  578. CALL wrk_dealloc( jpi,jpj, zswitchU, zswitchV, zmaskU, zmaskV, zfmask, zwf )
  579. END SUBROUTINE lim_rhg
  580. #else
  581. !!----------------------------------------------------------------------
  582. !! Default option Dummy module NO LIM sea-ice model
  583. !!----------------------------------------------------------------------
  584. CONTAINS
  585. SUBROUTINE lim_rhg( k1 , k2 ) ! Dummy routine
  586. WRITE(*,*) 'lim_rhg: You should not have seen this print! error?', k1, k2
  587. END SUBROUTINE lim_rhg
  588. #endif
  589. !!==============================================================================
  590. END MODULE limrhg