New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
icedyn_rhg_evp.F90 in NEMO/trunk/src/ICE – NEMO

source: NEMO/trunk/src/ICE/icedyn_rhg_evp.F90 @ 15375

Last change on this file since 15375 was 15375, checked in by clem, 2 years ago

change convergence test from the max over the domain to the average. This way it resembles more to what exists in the literature. Also, add alternate directions for the upstream advection scheme used in the rheology. However this scheme seems to slow down convergence, hence it should not be used

  • Property svn:keywords set to Id
File size: 68.9 KB
Line 
1MODULE icedyn_rhg_evp
2   !!======================================================================
3   !!                     ***  MODULE  icedyn_rhg_evp  ***
4   !!   Sea-Ice dynamics : rheology Elasto-Viscous-Plastic
5   !!======================================================================
6   !! History :   -   !  2007-03  (M.A. Morales Maqueda, S. Bouillon) Original code
7   !!            3.0  !  2008-03  (M. Vancoppenolle) adaptation to new model
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 evp case
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 + landfast ice + mEVP (Bouillon 2013)
13   !!            3.7  !  2017     (C. Rousset)  add aEVP (Kimmritz 2016-2017)
14   !!            4.0  !  2018     (many people) SI3 [aka Sea Ice cube]
15   !!----------------------------------------------------------------------
16#if defined key_si3
17   !!----------------------------------------------------------------------
18   !!   'key_si3'                                       SI3 sea-ice model
19   !!----------------------------------------------------------------------
20   !!   ice_dyn_rhg_evp : computes ice velocities from EVP rheology
21   !!   rhg_evp_rst     : read/write EVP fields in ice restart
22   !!----------------------------------------------------------------------
23   USE phycst         ! Physical constant
24   USE dom_oce        ! Ocean domain
25   USE sbc_oce , ONLY : ln_ice_embd, nn_fsbc, ssh_m
26   USE sbc_ice , ONLY : utau_ice, vtau_ice, snwice_mass, snwice_mass_b
27   USE ice            ! sea-ice: ice variables
28   USE icevar         ! ice_var_sshdyn
29   USE icedyn_rdgrft  ! sea-ice: ice strength
30   USE bdy_oce , ONLY : ln_bdy
31   USE bdyice
32#if defined key_agrif
33   USE agrif_ice_interp
34#endif
35   !
36   USE in_out_manager ! I/O manager
37   USE iom            ! I/O manager library
38   USE lib_mpp        ! MPP library
39   USE lib_fortran    ! fortran utilities (glob_sum + no signed zero)
40   USE lbclnk         ! lateral boundary conditions (or mpp links)
41   USE prtctl         ! Print control
42
43   USE netcdf         ! NetCDF library for convergence test
44   IMPLICIT NONE
45   PRIVATE
46
47   PUBLIC   ice_dyn_rhg_evp   ! called by icedyn_rhg.F90
48   PUBLIC   rhg_evp_rst       ! called by icedyn_rhg.F90
49
50   !! for convergence tests
51   INTEGER ::   ncvgid   ! netcdf file id
52   INTEGER ::   nvarid   ! netcdf variable id
53   REAL(wp), DIMENSION(:,:), ALLOCATABLE ::   fimask   ! mask at F points for the ice
54   
55   !! * Substitutions
56#  include "do_loop_substitute.h90"
57#  include "domzgr_substitute.h90"
58   !!----------------------------------------------------------------------
59   !! NEMO/ICE 4.0 , NEMO Consortium (2018)
60   !! $Id$
61   !! Software governed by the CeCILL license (see ./LICENSE)
62   !!----------------------------------------------------------------------
63CONTAINS
64
65   SUBROUTINE ice_dyn_rhg_evp( kt, Kmm, pstress1_i, pstress2_i, pstress12_i, pshear_i, pdivu_i, pdelta_i )
66      !!-------------------------------------------------------------------
67      !!                 ***  SUBROUTINE ice_dyn_rhg_evp  ***
68      !!                             EVP-C-grid
69      !!
70      !! ** purpose : determines sea ice drift from wind stress, ice-ocean
71      !!  stress and sea-surface slope. Ice-ice interaction is described by
72      !!  a non-linear elasto-viscous-plastic (EVP) law including shear
73      !!  strength and a bulk rheology (Hunke and Dukowicz, 2002).
74      !!
75      !!  The points in the C-grid look like this, dear reader
76      !!
77      !!                              (ji,jj)
78      !!                                 |
79      !!                                 |
80      !!                      (ji-1,jj)  |  (ji,jj)
81      !!                             ---------
82      !!                            |         |
83      !!                            | (ji,jj) |------(ji,jj)
84      !!                            |         |
85      !!                             ---------
86      !!                     (ji-1,jj-1)     (ji,jj-1)
87      !!
88      !! ** Inputs  : - wind forcing (stress), oceanic currents
89      !!                ice total volume (vt_i) per unit area
90      !!                snow total volume (vt_s) per unit area
91      !!
92      !! ** Action  : - compute u_ice, v_ice : the components of the
93      !!                sea-ice velocity vector
94      !!              - compute delta_i, shear_i, divu_i, which are inputs
95      !!                of the ice thickness distribution
96      !!
97      !! ** Steps   : 0) compute mask at F point
98      !!              1) Compute ice snow mass, ice strength
99      !!              2) Compute wind, oceanic stresses, mass terms and
100      !!                 coriolis terms of the momentum equation
101      !!              3) Solve the momentum equation (iterative procedure)
102      !!              4) Recompute delta, shear and divergence
103      !!                 (which are inputs of the ITD) & store stress
104      !!                 for the next time step
105      !!              5) Diagnostics including charge ellipse
106      !!
107      !! ** Notes   : There is the possibility to use aEVP from the nice work of Kimmritz et al. (2016 & 2017)
108      !!              by setting up ln_aEVP=T (i.e. changing alpha and beta parameters).
109      !!              This is an upgraded version of mEVP from Bouillon et al. 2013
110      !!              (i.e. more stable and better convergence)
111      !!
112      !! References : Hunke and Dukowicz, JPO97
113      !!              Bouillon et al., Ocean Modelling 2009
114      !!              Bouillon et al., Ocean Modelling 2013
115      !!              Kimmritz et al., Ocean Modelling 2016 & 2017
116      !!-------------------------------------------------------------------
117      INTEGER                 , INTENT(in   ) ::   kt                                    ! time step
118      INTEGER                 , INTENT(in   ) ::   Kmm                                   ! ocean time level index
119      REAL(wp), DIMENSION(:,:), INTENT(inout) ::   pstress1_i, pstress2_i, pstress12_i   !
120      REAL(wp), DIMENSION(:,:), INTENT(  out) ::   pshear_i  , pdivu_i   , pdelta_i      !
121      !!
122      INTEGER ::   ji, jj       ! dummy loop indices
123      INTEGER ::   jter         ! local integers
124      !
125      REAL(wp) ::   zrhoco                                              ! rho0 * rn_cio
126      REAL(wp) ::   zdtevp, z1_dtevp                                    ! time step for subcycling
127      REAL(wp) ::   ecc2, z1_ecc2                                       ! square of yield ellipse eccenticity
128      REAL(wp) ::   zalph1, z1_alph1, zalph2, z1_alph2                  ! alpha coef from Bouillon 2009 or Kimmritz 2017
129      REAl(wp) ::   zbetau, zbetav
130      REAL(wp) ::   zm1, zm2, zm3, zmassU, zmassV, zvU, zvV             ! ice/snow mass and volume
131      REAL(wp) ::   zp_delf, zds2, zdt, zdt2, zdiv, zdiv2               ! temporary scalars
132      REAL(wp) ::   zTauO, zTauB, zRHS, zvel                            ! temporary scalars
133      REAL(wp) ::   zkt                                                 ! isotropic tensile strength for landfast ice
134      REAL(wp) ::   zvCr                                                ! critical ice volume above which ice is landfast
135      !
136      REAL(wp) ::   zintb, zintn                                        ! dummy argument
137      REAL(wp) ::   zfac_x, zfac_y
138      REAL(wp) ::   zshear, zdum1, zdum2
139      !
140      REAL(wp), DIMENSION(jpi,jpj) ::   zdelta, zp_delt                 ! delta and P/delta at T points
141      REAL(wp), DIMENSION(jpi,jpj) ::   zbeta                           ! beta coef from Kimmritz 2017
142      !
143      REAL(wp), DIMENSION(jpi,jpj) ::   zdt_m                           ! (dt / ice-snow_mass) on T points
144      REAL(wp), DIMENSION(jpi,jpj) ::   zaU  , zaV                      ! ice fraction on U/V points
145      REAL(wp), DIMENSION(jpi,jpj) ::   zmU_t, zmV_t                    ! (ice-snow_mass / dt) on U/V points
146      REAL(wp), DIMENSION(jpi,jpj) ::   zmf                             ! coriolis parameter at T points
147      REAL(wp), DIMENSION(jpi,jpj) ::   v_oceU, u_oceV, v_iceU, u_iceV  ! ocean/ice u/v component on V/U points
148      !
149      REAL(wp), DIMENSION(jpi,jpj) ::   zds                             ! shear
150      REAL(wp), DIMENSION(jpi,jpj) ::   zten_i                          ! tension
151      REAL(wp), DIMENSION(jpi,jpj) ::   zs1, zs2, zs12                  ! stress tensor components
152      REAL(wp), DIMENSION(jpi,jpj) ::   zsshdyn                         ! array used for the calculation of ice surface slope:
153      !                                                                 !    ocean surface (ssh_m) if ice is not embedded
154      !                                                                 !    ice bottom surface if ice is embedded
155      REAL(wp), DIMENSION(jpi,jpj) ::   zfU  , zfV                      ! internal stresses
156      REAL(wp), DIMENSION(jpi,jpj) ::   zspgU, zspgV                    ! surface pressure gradient at U/V points
157      REAL(wp), DIMENSION(jpi,jpj) ::   zCorU, zCorV                    ! Coriolis stress array
158      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_ai, ztauy_ai              ! ice-atm. stress at U-V points
159      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_oi, ztauy_oi              ! ice-ocean stress at U-V points
160      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_bi, ztauy_bi              ! ice-OceanBottom stress at U-V points (landfast)
161      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_base, ztauy_base          ! ice-bottom stress at U-V points (landfast)
162      !
163      REAL(wp), DIMENSION(jpi,jpj) ::   zmsk00, zmsk15
164      REAL(wp), DIMENSION(jpi,jpj) ::   zmsk01x, zmsk01y                ! dummy arrays
165      REAL(wp), DIMENSION(jpi,jpj) ::   zmsk00x, zmsk00y                ! mask for ice presence
166
167      REAL(wp), PARAMETER          ::   zepsi  = 1.0e-20_wp             ! tolerance parameter
168      REAL(wp), PARAMETER          ::   zmmin  = 1._wp                  ! ice mass (kg/m2)  below which ice velocity becomes very small
169      REAL(wp), PARAMETER          ::   zamin  = 0.001_wp               ! ice concentration below which ice velocity becomes very small
170      !! --- check convergence
171      REAL(wp), DIMENSION(jpi,jpj) ::   zu_ice, zv_ice
172      !! --- diags
173      REAL(wp) ::   zsig1, zsig2, zsig12, zfac, z1_strength
174      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zsig_I, zsig_II, zsig1_p, zsig2_p
175      !! --- SIMIP diags
176      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_xmtrp_ice ! X-component of ice mass transport (kg/s)
177      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_ymtrp_ice ! Y-component of ice mass transport (kg/s)
178      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_xmtrp_snw ! X-component of snow mass transport (kg/s)
179      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_ymtrp_snw ! Y-component of snow mass transport (kg/s)
180      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_xatrp     ! X-component of area transport (m2/s)
181      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_yatrp     ! Y-component of area transport (m2/s)
182      !! -- advect fields at the rheology time step for the calculation of strength
183      !!    it seems that convergence is worse when ll_advups=true. So it not really a good idea
184      LOGICAL  ::   ll_advups = .FALSE.
185      REAL(wp) ::   zdt_ups
186      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   ztmp
187      REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) ::   za_i_ups, zv_i_ups   ! tracers advected upstream
188      !!-------------------------------------------------------------------
189
190      IF( kt == nit000 .AND. lwp )   WRITE(numout,*) '-- ice_dyn_rhg_evp: EVP sea-ice rheology'
191      !
192      ! for diagnostics and convergence tests
193      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
194         zmsk00(ji,jj) = MAX( 0._wp , SIGN( 1._wp , at_i(ji,jj) - epsi06  ) ) ! 1 if ice    , 0 if no ice
195      END_2D
196      IF( nn_rhg_chkcvg > 0 ) THEN
197         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
198            zmsk15(ji,jj) = MAX( 0._wp , SIGN( 1._wp , at_i(ji,jj) - 0.15_wp ) ) ! 1 if 15% ice, 0 if less
199         END_2D
200      ENDIF
201      !
202      !------------------------------------------------------------------------------!
203      ! 0) mask at F points for the ice
204      !------------------------------------------------------------------------------!
205      IF( kt == nit000 ) THEN
206         ! ocean/land mask
207         ALLOCATE( fimask(jpi,jpj) )
208         IF( rn_ishlat == 0._wp ) THEN
209            DO_2D( 0, 0, 0, 0 )
210               fimask(ji,jj) = tmask(ji,jj,1) * tmask(ji+1,jj,1) * tmask(ji,jj+1,1) * tmask(ji+1,jj+1,1)
211            END_2D
212         ELSE
213            DO_2D( 0, 0, 0, 0 )
214               fimask(ji,jj) = tmask(ji,jj,1) * tmask(ji+1,jj,1) * tmask(ji,jj+1,1) * tmask(ji+1,jj+1,1)
215               ! Lateral boundary conditions on velocity (modify fimask)
216               IF( fimask(ji,jj) == 0._wp ) THEN
217                  fimask(ji,jj) = rn_ishlat * MIN( 1._wp , MAX( umask(ji,jj,1), umask(ji,jj+1,1), &
218                     &                                          vmask(ji,jj,1), vmask(ji+1,jj,1) ) )
219               ENDIF
220            END_2D
221         ENDIF
222         CALL lbc_lnk( 'icedyn_rhg_evp', fimask, 'F', 1._wp )
223      ENDIF
224      !------------------------------------------------------------------------------!
225      ! 1) define some variables and initialize arrays
226      !------------------------------------------------------------------------------!
227      zrhoco = rho0 * rn_cio
228
229      ! ecc2: square of yield ellipse eccenticrity
230      ecc2    = rn_ecc * rn_ecc
231      z1_ecc2 = 1._wp / ecc2
232
233      ! alpha parameters (Bouillon 2009)
234      IF( .NOT. ln_aEVP ) THEN
235         zdtevp   = rDt_ice / REAL( nn_nevp )
236         zalph1 =   2._wp * rn_relast * REAL( nn_nevp )
237         zalph2 = zalph1 * z1_ecc2
238
239         z1_alph1 = 1._wp / ( zalph1 + 1._wp )
240         z1_alph2 = 1._wp / ( zalph2 + 1._wp )
241      ELSE
242         zdtevp   = rDt_ice
243         ! zalpha parameters set later on adaptatively
244      ENDIF
245      z1_dtevp = 1._wp / zdtevp
246
247      ! Initialise stress tensor
248      zs1 (:,:) = pstress1_i (:,:)
249      zs2 (:,:) = pstress2_i (:,:)
250      zs12(:,:) = pstress12_i(:,:)
251
252      ! Ice strength
253      CALL ice_strength
254
255      ! landfast param from Lemieux(2016): add isotropic tensile strength (following Konig Beatty and Holland, 2010)
256      IF( ln_landfast_L16 ) THEN   ;   zkt = rn_lf_tensile
257      ELSE                         ;   zkt = 0._wp
258      ENDIF
259      !
260      !------------------------------------------------------------------------------!
261      ! 2) Wind / ocean stress, mass terms, coriolis terms
262      !------------------------------------------------------------------------------!
263      ! sea surface height
264      !    embedded sea ice: compute representative ice top surface
265      !    non-embedded sea ice: use ocean surface for slope calculation
266      zsshdyn(:,:) = ice_var_sshdyn( ssh_m, snwice_mass, snwice_mass_b)
267
268      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
269         zm1          = ( rhos * vt_s(ji,jj) + rhoi * vt_i(ji,jj) )  ! Ice/snow mass at U-V points
270         zmf  (ji,jj) = zm1 * ff_t(ji,jj)                            ! Coriolis at T points (m*f)
271         zdt_m(ji,jj) = zdtevp / MAX( zm1, zmmin )                   ! dt/m at T points (for alpha and beta coefficients)
272      END_2D
273     
274      DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
275
276         ! ice fraction at U-V points
277         zaU(ji,jj) = 0.5_wp * ( at_i(ji,jj) * e1e2t(ji,jj) + at_i(ji+1,jj) * e1e2t(ji+1,jj) ) * r1_e1e2u(ji,jj) * umask(ji,jj,1)
278         zaV(ji,jj) = 0.5_wp * ( at_i(ji,jj) * e1e2t(ji,jj) + at_i(ji,jj+1) * e1e2t(ji,jj+1) ) * r1_e1e2v(ji,jj) * vmask(ji,jj,1)
279
280         ! Ice/snow mass at U-V points
281         zm1 = ( rhos * vt_s(ji  ,jj  ) + rhoi * vt_i(ji  ,jj  ) )
282         zm2 = ( rhos * vt_s(ji+1,jj  ) + rhoi * vt_i(ji+1,jj  ) )
283         zm3 = ( rhos * vt_s(ji  ,jj+1) + rhoi * vt_i(ji  ,jj+1) )
284         zmassU = 0.5_wp * ( zm1 * e1e2t(ji,jj) + zm2 * e1e2t(ji+1,jj) ) * r1_e1e2u(ji,jj) * umask(ji,jj,1)
285         zmassV = 0.5_wp * ( zm1 * e1e2t(ji,jj) + zm3 * e1e2t(ji,jj+1) ) * r1_e1e2v(ji,jj) * vmask(ji,jj,1)
286
287         ! Ocean currents at U-V points
288         ! (brackets added to fix the order of floating point operations for halo 1 - halo 2 compatibility)
289         v_oceU(ji,jj)   = 0.25_wp * ( (v_oce(ji,jj) + v_oce(ji,jj-1)) + (v_oce(ji+1,jj) + v_oce(ji+1,jj-1)) ) * umask(ji,jj,1)
290         u_oceV(ji,jj)   = 0.25_wp * ( (u_oce(ji,jj) + u_oce(ji-1,jj)) + (u_oce(ji,jj+1) + u_oce(ji-1,jj+1)) ) * vmask(ji,jj,1)
291
292         ! m/dt
293         zmU_t(ji,jj)    = zmassU * z1_dtevp
294         zmV_t(ji,jj)    = zmassV * z1_dtevp
295
296         ! Drag ice-atm.
297         ztaux_ai(ji,jj) = zaU(ji,jj) * utau_ice(ji,jj)
298         ztauy_ai(ji,jj) = zaV(ji,jj) * vtau_ice(ji,jj)
299
300         ! Surface pressure gradient (- m*g*GRAD(ssh)) at U-V points
301         zspgU(ji,jj)    = - zmassU * grav * ( zsshdyn(ji+1,jj) - zsshdyn(ji,jj) ) * r1_e1u(ji,jj)
302         zspgV(ji,jj)    = - zmassV * grav * ( zsshdyn(ji,jj+1) - zsshdyn(ji,jj) ) * r1_e2v(ji,jj)
303
304         ! masks
305         zmsk00x(ji,jj) = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zmassU ) )  ! 0 if no ice
306         zmsk00y(ji,jj) = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zmassV ) )  ! 0 if no ice
307
308         ! switches
309         IF( zmassU <= zmmin .AND. zaU(ji,jj) <= zamin ) THEN   ;   zmsk01x(ji,jj) = 0._wp
310         ELSE                                                   ;   zmsk01x(ji,jj) = 1._wp   ;   ENDIF
311         IF( zmassV <= zmmin .AND. zaV(ji,jj) <= zamin ) THEN   ;   zmsk01y(ji,jj) = 0._wp
312         ELSE                                                   ;   zmsk01y(ji,jj) = 1._wp   ;   ENDIF
313
314      END_2D
315      !
316      !                                  !== Landfast ice parameterization ==!
317      !
318      IF( ln_landfast_L16 ) THEN         !-- Lemieux 2016
319         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
320            ! ice thickness at U-V points
321            zvU = 0.5_wp * ( vt_i(ji,jj) * e1e2t(ji,jj) + vt_i(ji+1,jj) * e1e2t(ji+1,jj) ) * r1_e1e2u(ji,jj) * umask(ji,jj,1)
322            zvV = 0.5_wp * ( vt_i(ji,jj) * e1e2t(ji,jj) + vt_i(ji,jj+1) * e1e2t(ji,jj+1) ) * r1_e1e2v(ji,jj) * vmask(ji,jj,1)
323            ! ice-bottom stress at U points
324            zvCr = zaU(ji,jj) * rn_lf_depfra * hu(ji,jj,Kmm) * ( 1._wp - icb_mask(ji,jj) ) ! if grounded icebergs are read: ocean depth = 0
325            ztaux_base(ji,jj) = - rn_lf_bfr * MAX( 0._wp, zvU - zvCr ) * EXP( -rn_crhg * ( 1._wp - zaU(ji,jj) ) )
326            ! ice-bottom stress at V points
327            zvCr = zaV(ji,jj) * rn_lf_depfra * hv(ji,jj,Kmm) * ( 1._wp - icb_mask(ji,jj) ) ! if grounded icebergs are read: ocean depth = 0
328            ztauy_base(ji,jj) = - rn_lf_bfr * MAX( 0._wp, zvV - zvCr ) * EXP( -rn_crhg * ( 1._wp - zaV(ji,jj) ) )
329            ! ice_bottom stress at T points
330            zvCr = at_i(ji,jj) * rn_lf_depfra * ht(ji,jj) * ( 1._wp - icb_mask(ji,jj) )    ! if grounded icebergs are read: ocean depth = 0
331            tau_icebfr(ji,jj) = - rn_lf_bfr * MAX( 0._wp, vt_i(ji,jj) - zvCr ) * EXP( -rn_crhg * ( 1._wp - at_i(ji,jj) ) )
332         END_2D
333         CALL lbc_lnk( 'icedyn_rhg_evp', tau_icebfr(:,:), 'T', 1.0_wp )
334         !
335      ELSE                               !-- no landfast
336         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
337            ztaux_base(ji,jj) = 0._wp
338            ztauy_base(ji,jj) = 0._wp
339         END_2D
340      ENDIF
341
342      !------------------------------------------------------------------------------!
343      ! 3) Solution of the momentum equation, iterative procedure
344      !------------------------------------------------------------------------------!
345      !
346      !                                               ! ==================== !
347      DO jter = 1 , nn_nevp                           !    loop over jter    !
348         !                                            ! ==================== !
349         l_full_nf_update = jter == nn_nevp   ! false: disable full North fold update (performances) for iter = 1 to nn_nevp-1
350         !
351         ! convergence test
352         IF( nn_rhg_chkcvg == 1 .OR. nn_rhg_chkcvg == 2  ) THEN
353            DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
354               zu_ice(ji,jj) = u_ice(ji,jj) * umask(ji,jj,1) ! velocity at previous time step
355               zv_ice(ji,jj) = v_ice(ji,jj) * vmask(ji,jj,1)
356            END_2D
357         ENDIF
358
359         ! --- divergence, tension & shear (Appendix B of Hunke & Dukowicz, 2002) --- !
360         DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls-1 )
361
362            ! shear at F points
363            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)   &
364               &         + ( v_ice(ji+1,jj) * r1_e2v(ji+1,jj) - v_ice(ji,jj) * r1_e2v(ji,jj) ) * e2f(ji,jj) * e2f(ji,jj)   &
365               &         ) * r1_e1e2f(ji,jj) * fimask(ji,jj)
366
367         END_2D
368
369         DO_2D( 0, 0, 0, 0 )
370
371            ! shear**2 at T points (doc eq. A16)
372            zds2 = ( zds(ji,jj  ) * zds(ji,jj  ) * e1e2f(ji,jj  ) + zds(ji-1,jj  ) * zds(ji-1,jj  ) * e1e2f(ji-1,jj  )  &
373               &   + zds(ji,jj-1) * zds(ji,jj-1) * e1e2f(ji,jj-1) + zds(ji-1,jj-1) * zds(ji-1,jj-1) * e1e2f(ji-1,jj-1)  &
374               &   ) * 0.25_wp * r1_e1e2t(ji,jj)
375
376            ! divergence at T points
377            zdiv  = ( e2u(ji,jj) * u_ice(ji,jj) - e2u(ji-1,jj) * u_ice(ji-1,jj)   &
378               &    + e1v(ji,jj) * v_ice(ji,jj) - e1v(ji,jj-1) * v_ice(ji,jj-1)   &
379               &    ) * r1_e1e2t(ji,jj)
380            zdiv2 = zdiv * zdiv
381
382            ! tension at T points
383            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)   &
384               &   - ( v_ice(ji,jj) * r1_e1v(ji,jj) - v_ice(ji,jj-1) * r1_e1v(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj)   &
385               &   ) * r1_e1e2t(ji,jj)
386            zdt2 = zdt * zdt
387
388            ! delta at T points
389            zdelta(ji,jj) = SQRT( zdiv2 + ( zdt2 + zds2 ) * z1_ecc2 )
390
391            ! P/delta at T points
392            zp_delt(ji,jj) = strength(ji,jj) / ( zdelta(ji,jj) + rn_creepl )
393
394         END_2D
395         CALL lbc_lnk( 'icedyn_rhg_evp', zdelta, 'T', 1.0_wp, zp_delt, 'T', 1.0_wp )
396
397         !
398         DO_2D( nn_hls-1, nn_hls, nn_hls-1, nn_hls )   ! loop ends at jpi,jpj so that no lbc_lnk are needed for zs1 and zs2
399
400            ! divergence at T points (duplication to avoid communications)
401            ! (brackets added to fix the order of floating point operations for halo 1 - halo 2 compatibility)
402            zdiv  = ( (e2u(ji,jj) * u_ice(ji,jj) - e2u(ji-1,jj) * u_ice(ji-1,jj))   &
403               &    + (e1v(ji,jj) * v_ice(ji,jj) - e1v(ji,jj-1) * v_ice(ji,jj-1))   &
404               &    ) * r1_e1e2t(ji,jj)
405
406            ! tension at T points (duplication to avoid communications)
407            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)   &
408               &   - ( v_ice(ji,jj) * r1_e1v(ji,jj) - v_ice(ji,jj-1) * r1_e1v(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj)   &
409               &   ) * r1_e1e2t(ji,jj)
410
411            ! alpha for aEVP
412            !   gamma = 0.5*P/(delta+creepl) * (c*pi)**2/Area * dt/m
413            !   alpha = beta = sqrt(4*gamma)
414            IF( ln_aEVP ) THEN
415               zalph1   = MAX( 50._wp, rpi * SQRT( 0.5_wp * zp_delt(ji,jj) * r1_e1e2t(ji,jj) * zdt_m(ji,jj) ) )
416               z1_alph1 = 1._wp / ( zalph1 + 1._wp )
417               zalph2   = zalph1
418               z1_alph2 = z1_alph1
419               ! explicit:
420               ! z1_alph1 = 1._wp / zalph1
421               ! z1_alph2 = 1._wp / zalph1
422               ! zalph1 = zalph1 - 1._wp
423               ! zalph2 = zalph1
424            ENDIF
425
426            ! stress at T points (zkt/=0 if landfast)
427            zs1(ji,jj) = ( zs1(ji,jj)*zalph1 + zp_delt(ji,jj) * ( zdiv*(1._wp + zkt) - zdelta(ji,jj)*(1._wp - zkt) ) ) * z1_alph1
428            zs2(ji,jj) = ( zs2(ji,jj)*zalph2 + zp_delt(ji,jj) * ( zdt * z1_ecc2 * (1._wp + zkt) ) ) * z1_alph2
429
430         END_2D
431
432         ! Save beta at T-points for further computations
433         IF( ln_aEVP ) THEN
434            DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
435               zbeta(ji,jj) = MAX( 50._wp, rpi * SQRT( 0.5_wp * zp_delt(ji,jj) * r1_e1e2t(ji,jj) * zdt_m(ji,jj) ) )
436            END_2D
437         ENDIF
438
439         DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls-1 )
440
441            ! alpha for aEVP
442            IF( ln_aEVP ) THEN
443               zalph2   = MAX( zbeta(ji,jj), zbeta(ji+1,jj), zbeta(ji,jj+1), zbeta(ji+1,jj+1) )
444               z1_alph2 = 1._wp / ( zalph2 + 1._wp )
445               ! explicit:
446               ! z1_alph2 = 1._wp / zalph2
447               ! zalph2 = zalph2 - 1._wp
448            ENDIF
449
450            ! P/delta at F points
451            ! (brackets added to fix the order of floating point operations for halo 1 - halo 2 compatibility)
452            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)) )
453
454            ! stress at F points (zkt/=0 if landfast)
455            zs12(ji,jj)= ( zs12(ji,jj) * zalph2 + zp_delf * ( zds(ji,jj) * z1_ecc2 * (1._wp + zkt) ) * 0.5_wp ) * z1_alph2
456
457         END_2D
458
459         ! --- Ice internal stresses (Appendix C of Hunke and Dukowicz, 2002) --- !
460         ! (brackets added to fix the order of floating point operations for halo 1 - halo 2 compatibility)
461         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
462            !                   !--- U points
463            zfU(ji,jj) = 0.5_wp * ( (( zs1(ji+1,jj) - zs1(ji,jj) ) * e2u(ji,jj)                                             &
464               &                  + ( zs2(ji+1,jj) * e2t(ji+1,jj) * e2t(ji+1,jj) - zs2(ji,jj) * e2t(ji,jj) * e2t(ji,jj)    &
465               &                    ) * r1_e2u(ji,jj))                                                                      &
466               &                  + ( zs12(ji,jj) * e1f(ji,jj) * e1f(ji,jj) - zs12(ji,jj-1) * e1f(ji,jj-1) * e1f(ji,jj-1)  &
467               &                    ) * 2._wp * r1_e1u(ji,jj)                                                              &
468               &                  ) * r1_e1e2u(ji,jj)
469            !
470            !                !--- V points
471            zfV(ji,jj) = 0.5_wp * ( (( zs1(ji,jj+1) - zs1(ji,jj) ) * e1v(ji,jj)                                             &
472               &                  - ( zs2(ji,jj+1) * e1t(ji,jj+1) * e1t(ji,jj+1) - zs2(ji,jj) * e1t(ji,jj) * e1t(ji,jj)    &
473               &                    ) * r1_e1v(ji,jj))                                                                      &
474               &                  + ( zs12(ji,jj) * e2f(ji,jj) * e2f(ji,jj) - zs12(ji-1,jj) * e2f(ji-1,jj) * e2f(ji-1,jj)  &
475               &                    ) * 2._wp * r1_e2v(ji,jj)                                                              &
476               &                  ) * r1_e1e2v(ji,jj)
477            !
478            !                !--- ice currents at U-V point
479            v_iceU(ji,jj) = 0.25_wp * ( (v_ice(ji,jj) + v_ice(ji,jj-1)) + (v_ice(ji+1,jj) + v_ice(ji+1,jj-1)) ) * umask(ji,jj,1)
480            u_iceV(ji,jj) = 0.25_wp * ( (u_ice(ji,jj) + u_ice(ji-1,jj)) + (u_ice(ji,jj+1) + u_ice(ji-1,jj+1)) ) * vmask(ji,jj,1)
481            !
482         END_2D
483         !
484         ! --- Computation of ice velocity --- !
485         !  Bouillon et al. 2013 (eq 47-48) => unstable unless alpha, beta vary as in Kimmritz 2016 & 2017
486         !  Bouillon et al. 2009 (eq 34-35) => stable
487         IF( MOD(jter,2) == 0 ) THEN ! even iterations
488            !
489            DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
490               !                 !--- tau_io/(v_oce - v_ice)
491               zTauO = zaV(ji,jj) * zrhoco * SQRT( ( v_ice (ji,jj) - v_oce (ji,jj) ) * ( v_ice (ji,jj) - v_oce (ji,jj) )  &
492                  &                              + ( u_iceV(ji,jj) - u_oceV(ji,jj) ) * ( u_iceV(ji,jj) - u_oceV(ji,jj) ) )
493               !                 !--- Ocean-to-Ice stress
494               ztauy_oi(ji,jj) = zTauO * ( v_oce(ji,jj) - v_ice(ji,jj) )
495               !
496               !                 !--- tau_bottom/v_ice
497               zvel  = 5.e-05_wp + SQRT( v_ice(ji,jj) * v_ice(ji,jj) + u_iceV(ji,jj) * u_iceV(ji,jj) )
498               zTauB = ztauy_base(ji,jj) / zvel
499               !                 !--- OceanBottom-to-Ice stress
500               ztauy_bi(ji,jj) = zTauB * v_ice(ji,jj)
501               !
502               !                 !--- Coriolis at V-points (energy conserving formulation)
503               zCorV(ji,jj)  = - 0.25_wp * r1_e2v(ji,jj) *  &
504                  &    ( zmf(ji,jj  ) * ( e2u(ji,jj  ) * u_ice(ji,jj  ) + e2u(ji-1,jj  ) * u_ice(ji-1,jj  ) )  &
505                  &    + zmf(ji,jj+1) * ( e2u(ji,jj+1) * u_ice(ji,jj+1) + e2u(ji-1,jj+1) * u_ice(ji-1,jj+1) ) )
506               !
507               !                 !--- Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
508               zRHS = zfV(ji,jj) + ztauy_ai(ji,jj) + zCorV(ji,jj) + zspgV(ji,jj) + ztauy_oi(ji,jj)
509               !
510               !                 !--- landfast switch => 0 = static  friction : TauB > RHS & sign(TauB) /= sign(RHS)
511               !                                         1 = sliding friction : TauB < RHS
512               rswitch = 1._wp - MIN( 1._wp, ABS( SIGN( 1._wp, zRHS + ztauy_base(ji,jj) ) - SIGN( 1._wp, zRHS ) ) )
513               !
514               IF( ln_aEVP ) THEN !--- ice velocity using aEVP (Kimmritz et al 2016 & 2017)
515                  zbetav = MAX( zbeta(ji,jj), zbeta(ji,jj+1) )
516                  v_ice(ji,jj) = ( (          rswitch   * ( zmV_t(ji,jj) * ( zbetav * v_ice(ji,jj) + v_ice_b(ji,jj) )         & ! previous velocity
517                     &                                    + zRHS + zTauO * v_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
518                     &                                    ) / MAX( zepsi, zmV_t(ji,jj) * ( zbetav + 1._wp ) + zTauO - zTauB ) & ! m/dt + tau_io(only ice part) + landfast
519                     &            + ( 1._wp - rswitch ) * (  v_ice_b(ji,jj)                                                   &
520                     &                                     + v_ice  (ji,jj) * MAX( 0._wp, zbetav - zdtevp * rn_lf_relax )     & ! static friction => slow decrease to v=0
521                     &                                    ) / ( zbetav + 1._wp )                                              &
522                     &             ) * zmsk01y(ji,jj) + v_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01y(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
523                     &           )   * zmsk00y(ji,jj)
524               ELSE               !--- ice velocity using EVP implicit formulation (cf Madec doc & Bouillon 2009)
525                  v_ice(ji,jj) = ( (          rswitch   * ( zmV_t(ji,jj) * v_ice(ji,jj)                                       & ! previous velocity
526                     &                                    + zRHS + zTauO * v_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
527                     &                                    ) / MAX( zepsi, zmV_t(ji,jj) + zTauO - zTauB )                      & ! m/dt + tau_io(only ice part) + landfast
528                     &            + ( 1._wp - rswitch ) *   v_ice(ji,jj) * MAX( 0._wp, 1._wp - zdtevp * rn_lf_relax )         & ! static friction => slow decrease to v=0
529                     &             ) * zmsk01y(ji,jj) + v_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01y(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
530                     &            )  * zmsk00y(ji,jj)
531               ENDIF
532            END_2D
533            IF( nn_hls == 1 )   CALL lbc_lnk( 'icedyn_rhg_evp', v_ice, 'V', -1.0_wp )
534            !
535            DO_2D( 0, 0, 0, 0 )
536               !                 !--- tau_io/(u_oce - u_ice)
537               zTauO = zaU(ji,jj) * zrhoco * SQRT( ( u_ice (ji,jj) - u_oce (ji,jj) ) * ( u_ice (ji,jj) - u_oce (ji,jj) )  &
538                  &                              + ( v_iceU(ji,jj) - v_oceU(ji,jj) ) * ( v_iceU(ji,jj) - v_oceU(ji,jj) ) )
539               !                 !--- Ocean-to-Ice stress
540               ztaux_oi(ji,jj) = zTauO * ( u_oce(ji,jj) - u_ice(ji,jj) )
541               !
542               !                 !--- tau_bottom/u_ice
543               zvel  = 5.e-05_wp + SQRT( v_iceU(ji,jj) * v_iceU(ji,jj) + u_ice(ji,jj) * u_ice(ji,jj) )
544               zTauB = ztaux_base(ji,jj) / zvel
545               !                 !--- OceanBottom-to-Ice stress
546               ztaux_bi(ji,jj) = zTauB * u_ice(ji,jj)
547               !
548               !                 !--- Coriolis at U-points (energy conserving formulation)
549               zCorU(ji,jj)  =   0.25_wp * r1_e1u(ji,jj) *  &
550                  &    ( zmf(ji  ,jj) * ( e1v(ji  ,jj) * v_ice(ji  ,jj) + e1v(ji  ,jj-1) * v_ice(ji  ,jj-1) )  &
551                  &    + zmf(ji+1,jj) * ( e1v(ji+1,jj) * v_ice(ji+1,jj) + e1v(ji+1,jj-1) * v_ice(ji+1,jj-1) ) )
552               !
553               !                 !--- Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
554               zRHS = zfU(ji,jj) + ztaux_ai(ji,jj) + zCorU(ji,jj) + zspgU(ji,jj) + ztaux_oi(ji,jj)
555               !
556               !                 !--- landfast switch => 0 = static  friction : TauB > RHS & sign(TauB) /= sign(RHS)
557               !                                         1 = sliding friction : TauB < RHS
558               rswitch = 1._wp - MIN( 1._wp, ABS( SIGN( 1._wp, zRHS + ztaux_base(ji,jj) ) - SIGN( 1._wp, zRHS ) ) )
559               !
560               IF( ln_aEVP ) THEN !--- ice velocity using aEVP (Kimmritz et al 2016 & 2017)
561                  zbetau = MAX( zbeta(ji,jj), zbeta(ji+1,jj) )
562                  u_ice(ji,jj) = ( (          rswitch   * ( zmU_t(ji,jj) * ( zbetau * u_ice(ji,jj) + u_ice_b(ji,jj) )         & ! previous velocity
563                     &                                    + zRHS + zTauO * u_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
564                     &                                    ) / MAX( zepsi, zmU_t(ji,jj) * ( zbetau + 1._wp ) + zTauO - zTauB ) & ! m/dt + tau_io(only ice part) + landfast
565                     &            + ( 1._wp - rswitch ) * (  u_ice_b(ji,jj)                                                   &
566                     &                                     + u_ice  (ji,jj) * MAX( 0._wp, zbetau - zdtevp * rn_lf_relax )     & ! static friction => slow decrease to v=0
567                     &                                    ) / ( zbetau + 1._wp )                                              &
568                     &             ) * zmsk01x(ji,jj) + u_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01x(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
569                     &           )   * zmsk00x(ji,jj)
570               ELSE               !--- ice velocity using EVP implicit formulation (cf Madec doc & Bouillon 2009)
571                  u_ice(ji,jj) = ( (          rswitch   * ( zmU_t(ji,jj) * u_ice(ji,jj)                                       & ! previous velocity
572                     &                                    + zRHS + zTauO * u_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
573                     &                                    ) / MAX( zepsi, zmU_t(ji,jj) + zTauO - zTauB )                      & ! m/dt + tau_io(only ice part) + landfast
574                     &            + ( 1._wp - rswitch ) *   u_ice(ji,jj) * MAX( 0._wp, 1._wp - zdtevp * rn_lf_relax )         & ! static friction => slow decrease to v=0
575                     &             ) * zmsk01x(ji,jj) + u_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01x(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
576                     &           )   * zmsk00x(ji,jj)
577               ENDIF
578            END_2D
579            IF( nn_hls == 1 ) THEN   ;   CALL lbc_lnk( 'icedyn_rhg_evp', u_ice, 'U', -1.0_wp )
580            ELSE                     ;   CALL lbc_lnk( 'icedyn_rhg_evp', u_ice, 'U', -1.0_wp, v_ice, 'V', -1.0_wp )
581            ENDIF
582            !
583         ELSE ! odd iterations
584            !
585            DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
586               !                 !--- tau_io/(u_oce - u_ice)
587               zTauO = zaU(ji,jj) * zrhoco * SQRT( ( u_ice (ji,jj) - u_oce (ji,jj) ) * ( u_ice (ji,jj) - u_oce (ji,jj) )  &
588                  &                              + ( v_iceU(ji,jj) - v_oceU(ji,jj) ) * ( v_iceU(ji,jj) - v_oceU(ji,jj) ) )
589               !                 !--- Ocean-to-Ice stress
590               ztaux_oi(ji,jj) = zTauO * ( u_oce(ji,jj) - u_ice(ji,jj) )
591               !
592               !                 !--- tau_bottom/u_ice
593               zvel  = 5.e-05_wp + SQRT( v_iceU(ji,jj) * v_iceU(ji,jj) + u_ice(ji,jj) * u_ice(ji,jj) )
594               zTauB = ztaux_base(ji,jj) / zvel
595               !                 !--- OceanBottom-to-Ice stress
596               ztaux_bi(ji,jj) = zTauB * u_ice(ji,jj)
597               !
598               !                 !--- Coriolis at U-points (energy conserving formulation)
599               zCorU(ji,jj)  =   0.25_wp * r1_e1u(ji,jj) *  &
600                  &    ( zmf(ji  ,jj) * ( e1v(ji  ,jj) * v_ice(ji  ,jj) + e1v(ji  ,jj-1) * v_ice(ji  ,jj-1) )  &
601                  &    + zmf(ji+1,jj) * ( e1v(ji+1,jj) * v_ice(ji+1,jj) + e1v(ji+1,jj-1) * v_ice(ji+1,jj-1) ) )
602               !
603               !                 !--- Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
604               zRHS = zfU(ji,jj) + ztaux_ai(ji,jj) + zCorU(ji,jj) + zspgU(ji,jj) + ztaux_oi(ji,jj)
605               !
606               !                 !--- landfast switch => 0 = static  friction : TauB > RHS & sign(TauB) /= sign(RHS)
607               !                                         1 = sliding friction : TauB < RHS
608               rswitch = 1._wp - MIN( 1._wp, ABS( SIGN( 1._wp, zRHS + ztaux_base(ji,jj) ) - SIGN( 1._wp, zRHS ) ) )
609               !
610               IF( ln_aEVP ) THEN !--- ice velocity using aEVP (Kimmritz et al 2016 & 2017)
611                  zbetau = MAX( zbeta(ji,jj), zbeta(ji+1,jj) )
612                  u_ice(ji,jj) = ( (          rswitch   * ( zmU_t(ji,jj) * ( zbetau * u_ice(ji,jj) + u_ice_b(ji,jj) )         & ! previous velocity
613                     &                                    + zRHS + zTauO * u_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
614                     &                                    ) / MAX( zepsi, zmU_t(ji,jj) * ( zbetau + 1._wp ) + zTauO - zTauB ) & ! m/dt + tau_io(only ice part) + landfast
615                     &            + ( 1._wp - rswitch ) * (  u_ice_b(ji,jj)                                                   &
616                     &                                     + u_ice  (ji,jj) * MAX( 0._wp, zbetau - zdtevp * rn_lf_relax )     & ! static friction => slow decrease to v=0
617                     &                                    ) / ( zbetau + 1._wp )                                              &
618                     &             ) * zmsk01x(ji,jj) + u_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01x(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
619                     &           )   * zmsk00x(ji,jj)
620               ELSE               !--- ice velocity using EVP implicit formulation (cf Madec doc & Bouillon 2009)
621                  u_ice(ji,jj) = ( (          rswitch   * ( zmU_t(ji,jj) * u_ice(ji,jj)                                       & ! previous velocity
622                     &                                    + zRHS + zTauO * u_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
623                     &                                    ) / MAX( zepsi, zmU_t(ji,jj) + zTauO - zTauB )                      & ! m/dt + tau_io(only ice part) + landfast
624                     &            + ( 1._wp - rswitch ) *   u_ice(ji,jj) * MAX( 0._wp, 1._wp - zdtevp * rn_lf_relax )         & ! static friction => slow decrease to v=0
625                     &             ) * zmsk01x(ji,jj) + u_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01x(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
626                     &           )   * zmsk00x(ji,jj)
627               ENDIF
628            END_2D
629            IF( nn_hls == 1 )   CALL lbc_lnk( 'icedyn_rhg_evp', u_ice, 'U', -1.0_wp )
630            !
631            DO_2D( 0, 0, 0, 0 )
632               !                 !--- tau_io/(v_oce - v_ice)
633               zTauO = zaV(ji,jj) * zrhoco * SQRT( ( v_ice (ji,jj) - v_oce (ji,jj) ) * ( v_ice (ji,jj) - v_oce (ji,jj) )  &
634                  &                              + ( u_iceV(ji,jj) - u_oceV(ji,jj) ) * ( u_iceV(ji,jj) - u_oceV(ji,jj) ) )
635               !                 !--- Ocean-to-Ice stress
636               ztauy_oi(ji,jj) = zTauO * ( v_oce(ji,jj) - v_ice(ji,jj) )
637               !
638               !                 !--- tau_bottom/v_ice
639               zvel  = 5.e-05_wp + SQRT( v_ice(ji,jj) * v_ice(ji,jj) + u_iceV(ji,jj) * u_iceV(ji,jj) )
640               zTauB = ztauy_base(ji,jj) / zvel
641               !                 !--- OceanBottom-to-Ice stress
642               ztauy_bi(ji,jj) = zTauB * v_ice(ji,jj)
643               !
644               !                 !--- Coriolis at v-points (energy conserving formulation)
645               zCorV(ji,jj)  = - 0.25_wp * r1_e2v(ji,jj) *  &
646                  &    ( zmf(ji,jj  ) * ( e2u(ji,jj  ) * u_ice(ji,jj  ) + e2u(ji-1,jj  ) * u_ice(ji-1,jj  ) )  &
647                  &    + zmf(ji,jj+1) * ( e2u(ji,jj+1) * u_ice(ji,jj+1) + e2u(ji-1,jj+1) * u_ice(ji-1,jj+1) ) )
648               !
649               !                 !--- Sum of external forces (explicit solution) = F + tau_ia + Coriolis + spg + tau_io
650               zRHS = zfV(ji,jj) + ztauy_ai(ji,jj) + zCorV(ji,jj) + zspgV(ji,jj) + ztauy_oi(ji,jj)
651               !
652               !                 !--- landfast switch => 0 = static  friction : TauB > RHS & sign(TauB) /= sign(RHS)
653               !                                         1 = sliding friction : TauB < RHS
654               rswitch = 1._wp - MIN( 1._wp, ABS( SIGN( 1._wp, zRHS + ztauy_base(ji,jj) ) - SIGN( 1._wp, zRHS ) ) )
655               !
656               IF( ln_aEVP ) THEN !--- ice velocity using aEVP (Kimmritz et al 2016 & 2017)
657                  zbetav = MAX( zbeta(ji,jj), zbeta(ji,jj+1) )
658                  v_ice(ji,jj) = ( (          rswitch   * ( zmV_t(ji,jj) * ( zbetav * v_ice(ji,jj) + v_ice_b(ji,jj) )         & ! previous velocity
659                     &                                    + zRHS + zTauO * v_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
660                     &                                    ) / MAX( zepsi, zmV_t(ji,jj) * ( zbetav + 1._wp ) + zTauO - zTauB ) & ! m/dt + tau_io(only ice part) + landfast
661                     &            + ( 1._wp - rswitch ) * (  v_ice_b(ji,jj)                                                   &
662                     &                                     + v_ice  (ji,jj) * MAX( 0._wp, zbetav - zdtevp * rn_lf_relax )     & ! static friction => slow decrease to v=0
663                     &                                    ) / ( zbetav + 1._wp )                                              &
664                     &             ) * zmsk01y(ji,jj) + v_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01y(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
665                     &           )   * zmsk00y(ji,jj)
666               ELSE               !--- ice velocity using EVP implicit formulation (cf Madec doc & Bouillon 2009)
667                  v_ice(ji,jj) = ( (          rswitch   * ( zmV_t(ji,jj) * v_ice(ji,jj)                                       & ! previous velocity
668                     &                                    + zRHS + zTauO * v_ice(ji,jj)                                       & ! F + tau_ia + Coriolis + spg + tau_io(only ocean part)
669                     &                                    ) / MAX( zepsi, zmV_t(ji,jj) + zTauO - zTauB )                      & ! m/dt + tau_io(only ice part) + landfast
670                     &            + ( 1._wp - rswitch ) *   v_ice(ji,jj) * MAX( 0._wp, 1._wp - zdtevp * rn_lf_relax )         & ! static friction => slow decrease to v=0
671                     &             ) * zmsk01y(ji,jj) + v_oce(ji,jj) * 0.01_wp * ( 1._wp - zmsk01y(ji,jj) )                   & ! v_ice = v_oce/100 if mass < zmmin & conc < zamin
672                     &           )   * zmsk00y(ji,jj)
673               ENDIF
674            END_2D
675            IF( nn_hls == 1 ) THEN   ;   CALL lbc_lnk( 'icedyn_rhg_evp', v_ice, 'V', -1.0_wp )
676            ELSE                     ;   CALL lbc_lnk( 'icedyn_rhg_evp', u_ice, 'U', -1.0_wp, v_ice, 'V', -1.0_wp )
677            ENDIF
678            !
679         ENDIF
680         !
681#if defined key_agrif
682!!       CALL agrif_interp_ice( 'U', jter, nn_nevp )
683!!       CALL agrif_interp_ice( 'V', jter, nn_nevp )
684         CALL agrif_interp_ice( 'U' )
685         CALL agrif_interp_ice( 'V' )
686#endif
687         IF( ln_bdy )   CALL bdy_ice_dyn( 'U' )
688         IF( ln_bdy )   CALL bdy_ice_dyn( 'V' )
689         !
690         ! convergence test
691         IF( nn_rhg_chkcvg == 2 )   CALL rhg_cvg( kt, jter, nn_nevp, u_ice, v_ice, zu_ice, zv_ice, zmsk15 )
692         !
693         !
694         ! --- change strength according to advected a_i and v_i (upstream for now) --- !
695         IF( ll_advups .AND. ln_str_H79 ) THEN
696            !
697            IF( jter == 1 ) THEN                               ! init
698               ALLOCATE( za_i_ups(jpi,jpj,jpl), zv_i_ups(jpi,jpj,jpl) )
699               ALLOCATE( ztmp(jpi,jpj) )
700               zdt_ups = rDt_ice / REAL( nn_nevp )
701               za_i_ups(:,:,:) = a_i(:,:,:)
702               zv_i_ups(:,:,:) = v_i(:,:,:)
703            ELSE
704               CALL lbc_lnk( 'icedyn_rhg_evp', za_i_ups, 'T', 1.0_wp, zv_i_ups, 'T', 1.0_wp )               
705            ENDIF
706            !
707            CALL rhg_upstream( jter, zdt_ups, u_ice, v_ice, za_i_ups )   ! upstream advection: a_i
708            CALL rhg_upstream( jter, zdt_ups, u_ice, v_ice, zv_i_ups )   ! upstream advection: v_i
709            !
710            DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )    ! strength
711               strength(ji,jj) = rn_pstar * SUM( zv_i_ups(ji,jj,:) ) * EXP( -rn_crhg * ( 1._wp - SUM( za_i_ups(ji,jj,:) ) ) )
712            END_2D
713            IF( nn_hls == 1 )  CALL lbc_lnk( 'icedyn_rhg_evp', strength, 'T', 1.0_wp )
714            !
715            DO_2D( 0, 0, 0, 0 )                                ! strength smoothing
716               IF( SUM( za_i_ups(ji,jj,:) ) > 0._wp ) THEN
717                  ztmp(ji,jj) = ( 4._wp * strength(ji,jj) + strength(ji-1,jj  ) + strength(ji+1,jj  ) &
718                     &                                    + strength(ji  ,jj-1) + strength(ji  ,jj+1) &
719                     &          ) / ( 4._wp + tmask(ji-1,jj,1) + tmask(ji+1,jj,1) + tmask(ji,jj-1,1) + tmask(ji,jj+1,1) )
720               ELSE
721                  ztmp(ji,jj) = 0._wp
722               ENDIF
723            END_2D
724            DO_2D( 0, 0, 0, 0 )
725               strength(ji,jj) = ztmp(ji,jj)
726            END_2D
727            !
728            IF( jter == nn_nevp ) THEN
729               DEALLOCATE( za_i_ups, zv_i_ups )
730               DEALLOCATE( ztmp )
731            ENDIF
732         ENDIF
733         !                                                ! ==================== !
734      END DO                                              !  end loop over jter  !
735      !                                                   ! ==================== !
736      IF( ln_aEVP )   CALL iom_put( 'beta_evp' , zbeta )
737      !
738      IF( ll_advups .AND. ln_str_H79 )   CALL lbc_lnk( 'icedyn_rhg_evp', strength, 'T', 1.0_wp )
739      !
740      !------------------------------------------------------------------------------!
741      ! 4) Recompute delta, shear and div (inputs for mechanical redistribution)
742      !------------------------------------------------------------------------------!
743      DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls-1 )
744
745         ! shear at F points
746         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)   &
747            &         + ( v_ice(ji+1,jj) * r1_e2v(ji+1,jj) - v_ice(ji,jj) * r1_e2v(ji,jj) ) * e2f(ji,jj) * e2f(ji,jj)   &
748            &         ) * r1_e1e2f(ji,jj) * fimask(ji,jj)
749
750      END_2D
751
752      DO_2D( 0, 0, 0, 0 )   ! no vector loop
753
754         ! tension**2 at T points
755         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)   &
756            &   - ( v_ice(ji,jj) * r1_e1v(ji,jj) - v_ice(ji,jj-1) * r1_e1v(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj)   &
757            &   ) * r1_e1e2t(ji,jj)
758         zdt2 = zdt * zdt
759
760         zten_i(ji,jj) = zdt
761
762         ! shear**2 at T points (doc eq. A16)
763         zds2 = ( zds(ji,jj  ) * zds(ji,jj  ) * e1e2f(ji,jj  ) + zds(ji-1,jj  ) * zds(ji-1,jj  ) * e1e2f(ji-1,jj  )  &
764            &   + zds(ji,jj-1) * zds(ji,jj-1) * e1e2f(ji,jj-1) + zds(ji-1,jj-1) * zds(ji-1,jj-1) * e1e2f(ji-1,jj-1)  &
765            &   ) * 0.25_wp * r1_e1e2t(ji,jj)
766
767         ! shear at T points
768         pshear_i(ji,jj) = SQRT( zdt2 + zds2 )
769
770         ! divergence at T points
771         pdivu_i(ji,jj) = ( e2u(ji,jj) * u_ice(ji,jj) - e2u(ji-1,jj) * u_ice(ji-1,jj)   &
772            &             + e1v(ji,jj) * v_ice(ji,jj) - e1v(ji,jj-1) * v_ice(ji,jj-1)   &
773            &             ) * r1_e1e2t(ji,jj)
774
775         ! delta at T points
776         zfac            = SQRT( pdivu_i(ji,jj) * pdivu_i(ji,jj) + ( zdt2 + zds2 ) * z1_ecc2 ) ! delta
777         rswitch         = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zfac ) ) ! 0 if delta=0
778         pdelta_i(ji,jj) = zfac + rn_creepl * rswitch ! delta+creepl
779
780      END_2D
781      CALL lbc_lnk( 'icedyn_rhg_evp', pshear_i, 'T', 1._wp, pdivu_i, 'T', 1._wp, pdelta_i, 'T', 1._wp, zten_i, 'T', 1._wp, &
782         &                            zs1     , 'T', 1._wp, zs2    , 'T', 1._wp, zs12    , 'F', 1._wp )
783
784      ! --- Store the stress tensor for the next time step --- !
785      pstress1_i (:,:) = zs1 (:,:)
786      pstress2_i (:,:) = zs2 (:,:)
787      pstress12_i(:,:) = zs12(:,:)
788      !
789
790      !------------------------------------------------------------------------------!
791      ! 5) diagnostics
792      !------------------------------------------------------------------------------!
793      ! --- ice-ocean, ice-atm. & ice-oceanbottom(landfast) stresses --- !
794      IF(  iom_use('utau_oi') .OR. iom_use('vtau_oi') .OR. iom_use('utau_ai') .OR. iom_use('vtau_ai') .OR. &
795         & iom_use('utau_bi') .OR. iom_use('vtau_bi') ) THEN
796         !
797         CALL lbc_lnk( 'icedyn_rhg_evp', ztaux_oi, 'U', -1.0_wp, ztauy_oi, 'V', -1.0_wp, &
798            &                            ztaux_ai, 'U', -1.0_wp, ztauy_ai, 'V', -1.0_wp, &
799            &                            ztaux_bi, 'U', -1.0_wp, ztauy_bi, 'V', -1.0_wp )
800         !
801         CALL iom_put( 'utau_oi' , ztaux_oi * zmsk00 )
802         CALL iom_put( 'vtau_oi' , ztauy_oi * zmsk00 )
803         CALL iom_put( 'utau_ai' , ztaux_ai * zmsk00 )
804         CALL iom_put( 'vtau_ai' , ztauy_ai * zmsk00 )
805         CALL iom_put( 'utau_bi' , ztaux_bi * zmsk00 )
806         CALL iom_put( 'vtau_bi' , ztauy_bi * zmsk00 )
807      ENDIF
808
809      ! --- divergence, shear and strength --- !
810      IF( iom_use('icediv') )   CALL iom_put( 'icediv' , pdivu_i  * zmsk00 )   ! divergence
811      IF( iom_use('iceshe') )   CALL iom_put( 'iceshe' , pshear_i * zmsk00 )   ! shear
812      IF( iom_use('icestr') )   CALL iom_put( 'icestr' , strength * zmsk00 )   ! strength
813      IF( iom_use('icedlt') )   CALL iom_put( 'icedlt' , pdelta_i * zmsk00 )   ! delta
814
815      ! --- Stress tensor invariants (SIMIP diags) --- !
816      IF( iom_use('normstr') .OR. iom_use('sheastr') ) THEN
817         !
818         ALLOCATE( zsig_I(jpi,jpj) , zsig_II(jpi,jpj) )
819         !
820         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
821
822            ! Ice stresses
823            ! sigma1, sigma2, sigma12 are some useful recombination of the stresses (Hunke and Dukowicz MWR 2002, Bouillon et al., OM2013)
824            ! These are NOT stress tensor components, neither stress invariants, neither stress principal components
825            ! I know, this can be confusing...
826            zfac             =   strength(ji,jj) / ( pdelta_i(ji,jj) + rn_creepl )
827            zsig1            =   zfac * ( pdivu_i(ji,jj) - pdelta_i(ji,jj) )
828            zsig2            =   zfac * z1_ecc2 * zten_i(ji,jj)
829            zsig12           =   zfac * z1_ecc2 * pshear_i(ji,jj)
830
831            ! Stress invariants (sigma_I, sigma_II, Coon 1974, Feltham 2008)
832            zsig_I (ji,jj)   =   zsig1 * 0.5_wp                                           ! 1st stress invariant, aka average normal stress, aka negative pressure
833            zsig_II(ji,jj)   =   SQRT ( MAX( 0._wp, zsig2 * zsig2 * 0.25_wp + zsig12 ) )  ! 2nd  ''       '', aka maximum shear stress
834
835         END_2D
836         !
837         ! Stress tensor invariants (normal and shear stress N/m) - SIMIP diags - definitions following Coon (1974) and Feltham (2008)
838         IF( iom_use('normstr') )   CALL iom_put( 'normstr', zsig_I (:,:) * zmsk00(:,:) ) ! Normal stress
839         IF( iom_use('sheastr') )   CALL iom_put( 'sheastr', zsig_II(:,:) * zmsk00(:,:) ) ! Maximum shear stress
840
841         DEALLOCATE ( zsig_I, zsig_II )
842
843      ENDIF
844
845      ! --- Normalized stress tensor principal components --- !
846      ! This are used to plot the normalized yield curve, see Lemieux & Dupont, 2020
847      ! Recommendation 1 : we use ice strength, not replacement pressure
848      ! Recommendation 2 : need to use deformations at PREVIOUS iterate for viscosities
849      IF( iom_use('sig1_pnorm') .OR. iom_use('sig2_pnorm') ) THEN
850         !
851         ALLOCATE( zsig1_p(jpi,jpj) , zsig2_p(jpi,jpj) , zsig_I(jpi,jpj) , zsig_II(jpi,jpj) )
852         !
853         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
854
855            ! Ice stresses computed with **viscosities** (delta, p/delta) at **previous** iterates
856            !                        and **deformations** at current iterates
857            !                        following Lemieux & Dupont (2020)
858            zfac             =   zp_delt(ji,jj)
859            zsig1            =   zfac * ( pdivu_i(ji,jj) - ( zdelta(ji,jj) + rn_creepl ) )
860            zsig2            =   zfac * z1_ecc2 * zten_i(ji,jj)
861            zsig12           =   zfac * z1_ecc2 * pshear_i(ji,jj)
862
863            ! Stress invariants (sigma_I, sigma_II, Coon 1974, Feltham 2008), T-point
864            zsig_I(ji,jj)    =   zsig1 * 0.5_wp                                            ! 1st stress invariant, aka average normal stress, aka negative pressure
865            zsig_II(ji,jj)   =   SQRT ( MAX( 0._wp, zsig2 * zsig2 * 0.25_wp + zsig12 ) )   ! 2nd  ''       '', aka maximum shear stress
866
867            ! Normalized  principal stresses (used to display the ellipse)
868            z1_strength      =   1._wp / MAX( 1._wp, strength(ji,jj) )
869            zsig1_p(ji,jj)   =   ( zsig_I(ji,jj) + zsig_II(ji,jj) ) * z1_strength
870            zsig2_p(ji,jj)   =   ( zsig_I(ji,jj) - zsig_II(ji,jj) ) * z1_strength
871         END_2D
872         !
873         CALL iom_put( 'sig1_pnorm' , zsig1_p )
874         CALL iom_put( 'sig2_pnorm' , zsig2_p )
875
876         DEALLOCATE( zsig1_p , zsig2_p , zsig_I, zsig_II )
877
878      ENDIF
879
880      ! --- SIMIP --- !
881      IF(  iom_use('dssh_dx') .OR. iom_use('dssh_dy') .OR. &
882         & iom_use('corstrx') .OR. iom_use('corstry') .OR. iom_use('intstrx') .OR. iom_use('intstry') ) THEN
883         !
884         CALL lbc_lnk( 'icedyn_rhg_evp', zspgU, 'U', -1.0_wp, zspgV, 'V', -1.0_wp, &
885            &                            zCorU, 'U', -1.0_wp, zCorV, 'V', -1.0_wp, zfU, 'U', -1.0_wp, zfV, 'V', -1.0_wp )
886
887         CALL iom_put( 'dssh_dx' , zspgU * zmsk00 )   ! Sea-surface tilt term in force balance (x)
888         CALL iom_put( 'dssh_dy' , zspgV * zmsk00 )   ! Sea-surface tilt term in force balance (y)
889         CALL iom_put( 'corstrx' , zCorU * zmsk00 )   ! Coriolis force term in force balance (x)
890         CALL iom_put( 'corstry' , zCorV * zmsk00 )   ! Coriolis force term in force balance (y)
891         CALL iom_put( 'intstrx' , zfU   * zmsk00 )   ! Internal force term in force balance (x)
892         CALL iom_put( 'intstry' , zfV   * zmsk00 )   ! Internal force term in force balance (y)
893      ENDIF
894
895      IF(  iom_use('xmtrpice') .OR. iom_use('ymtrpice') .OR. &
896         & iom_use('xmtrpsnw') .OR. iom_use('ymtrpsnw') .OR. iom_use('xatrp') .OR. iom_use('yatrp') ) THEN
897         !
898         ALLOCATE( zdiag_xmtrp_ice(jpi,jpj) , zdiag_ymtrp_ice(jpi,jpj) , &
899            &      zdiag_xmtrp_snw(jpi,jpj) , zdiag_ymtrp_snw(jpi,jpj) , zdiag_xatrp(jpi,jpj) , zdiag_yatrp(jpi,jpj) )
900         !
901         DO_2D( 0, 0, 0, 0 )
902            ! 2D ice mass, snow mass, area transport arrays (X, Y)
903            zfac_x = 0.5 * u_ice(ji,jj) * e2u(ji,jj) * zmsk00(ji,jj)
904            zfac_y = 0.5 * v_ice(ji,jj) * e1v(ji,jj) * zmsk00(ji,jj)
905
906            zdiag_xmtrp_ice(ji,jj) = rhoi * zfac_x * ( vt_i(ji+1,jj) + vt_i(ji,jj) ) ! ice mass transport, X-component
907            zdiag_ymtrp_ice(ji,jj) = rhoi * zfac_y * ( vt_i(ji,jj+1) + vt_i(ji,jj) ) !        ''           Y-   ''
908
909            zdiag_xmtrp_snw(ji,jj) = rhos * zfac_x * ( vt_s(ji+1,jj) + vt_s(ji,jj) ) ! snow mass transport, X-component
910            zdiag_ymtrp_snw(ji,jj) = rhos * zfac_y * ( vt_s(ji,jj+1) + vt_s(ji,jj) ) !          ''          Y-   ''
911
912            zdiag_xatrp(ji,jj)     = zfac_x * ( at_i(ji+1,jj) + at_i(ji,jj) )        ! area transport,      X-component
913            zdiag_yatrp(ji,jj)     = zfac_y * ( at_i(ji,jj+1) + at_i(ji,jj) )        !        ''            Y-   ''
914
915         END_2D
916
917         CALL lbc_lnk( 'icedyn_rhg_evp', zdiag_xmtrp_ice, 'U', -1.0_wp, zdiag_ymtrp_ice, 'V', -1.0_wp, &
918            &                            zdiag_xmtrp_snw, 'U', -1.0_wp, zdiag_ymtrp_snw, 'V', -1.0_wp, &
919            &                            zdiag_xatrp    , 'U', -1.0_wp, zdiag_yatrp    , 'V', -1.0_wp )
920
921         CALL iom_put( 'xmtrpice' , zdiag_xmtrp_ice )   ! X-component of sea-ice mass transport (kg/s)
922         CALL iom_put( 'ymtrpice' , zdiag_ymtrp_ice )   ! Y-component of sea-ice mass transport
923         CALL iom_put( 'xmtrpsnw' , zdiag_xmtrp_snw )   ! X-component of snow mass transport (kg/s)
924         CALL iom_put( 'ymtrpsnw' , zdiag_ymtrp_snw )   ! Y-component of snow mass transport
925         CALL iom_put( 'xatrp'    , zdiag_xatrp     )   ! X-component of ice area transport
926         CALL iom_put( 'yatrp'    , zdiag_yatrp     )   ! Y-component of ice area transport
927
928         DEALLOCATE( zdiag_xmtrp_ice , zdiag_ymtrp_ice , &
929            &        zdiag_xmtrp_snw , zdiag_ymtrp_snw , zdiag_xatrp , zdiag_yatrp )
930
931      ENDIF
932      !
933      ! --- convergence tests --- !
934      IF( nn_rhg_chkcvg == 1 .OR. nn_rhg_chkcvg == 2 ) THEN
935         IF( iom_use('uice_cvg') ) THEN
936            IF( ln_aEVP ) THEN   ! output: beta * ( u(t=nn_nevp) - u(t=nn_nevp-1) )
937               CALL iom_put( 'uice_cvg', MAX( ABS( u_ice(:,:) - zu_ice(:,:) ) * zbeta(:,:) * umask(:,:,1) , &
938                  &                           ABS( v_ice(:,:) - zv_ice(:,:) ) * zbeta(:,:) * vmask(:,:,1) ) * zmsk15(:,:) )
939            ELSE                 ! output: nn_nevp * ( u(t=nn_nevp) - u(t=nn_nevp-1) )
940               CALL iom_put( 'uice_cvg', REAL( nn_nevp ) * MAX( ABS( u_ice(:,:) - zu_ice(:,:) ) * umask(:,:,1) , &
941                  &                                             ABS( v_ice(:,:) - zv_ice(:,:) ) * vmask(:,:,1) ) * zmsk15(:,:) )
942            ENDIF
943         ENDIF
944      ENDIF
945      !
946   END SUBROUTINE ice_dyn_rhg_evp
947
948
949   SUBROUTINE rhg_cvg( kt, kiter, kitermax, pu, pv, pub, pvb, pmsk15 )
950      !!----------------------------------------------------------------------
951      !!                    ***  ROUTINE rhg_cvg  ***
952      !!
953      !! ** Purpose :   check convergence of oce rheology
954      !!
955      !! ** Method  :   create a file ice_cvg.nc containing the convergence of ice velocity
956      !!                during the sub timestepping of rheology so as:
957      !!                  uice_cvg = MAX( u(t+1) - u(t) , v(t+1) - v(t) )
958      !!                This routine is called every sub-iteration, so it is cpu expensive
959      !!
960      !! ** Note    :   for the first sub-iteration, uice_cvg is set to 0 (too large otherwise)
961      !!----------------------------------------------------------------------
962      INTEGER ,                 INTENT(in) ::   kt, kiter, kitermax       ! ocean time-step index
963      REAL(wp), DIMENSION(:,:), INTENT(in) ::   pu, pv, pub, pvb          ! now and before velocities
964      REAL(wp), DIMENSION(:,:), INTENT(in) ::   pmsk15
965      !!
966      INTEGER           ::   it, idtime, istatus
967      INTEGER           ::   ji, jj          ! dummy loop indices
968      REAL(wp)          ::   zresm           ! local real
969      CHARACTER(len=20) ::   clname
970      LOGICAL           ::   ll_maxcvg
971      REAL(wp), DIMENSION(jpi,jpj,2) ::   zres
972      REAL(wp), DIMENSION(2)         ::   ztmp
973      !!----------------------------------------------------------------------
974      ll_maxcvg = .FALSE.
975      !
976      ! create file
977      IF( kt == nit000 .AND. kiter == 1 ) THEN
978         !
979         IF( lwp ) THEN
980            WRITE(numout,*)
981            WRITE(numout,*) 'rhg_cvg : ice rheology convergence control'
982            WRITE(numout,*) '~~~~~~~'
983         ENDIF
984         !
985         IF( lwm ) THEN
986            clname = 'ice_cvg.nc'
987            IF( .NOT. Agrif_Root() )   clname = TRIM(Agrif_CFixed())//"_"//TRIM(clname)
988            istatus = NF90_CREATE( TRIM(clname), NF90_CLOBBER, ncvgid )
989            istatus = NF90_DEF_DIM( ncvgid, 'time'  , NF90_UNLIMITED, idtime )
990            istatus = NF90_DEF_VAR( ncvgid, 'uice_cvg', NF90_DOUBLE , (/ idtime /), nvarid )
991            istatus = NF90_ENDDEF(ncvgid)
992         ENDIF
993         !
994      ENDIF
995
996      ! time
997      it = ( kt - 1 ) * kitermax + kiter
998
999      ! convergence
1000      IF( kiter == 1 ) THEN ! remove the first iteration for calculations of convergence (always very large)
1001         zresm = 0._wp
1002      ELSE
1003         zresm = 0._wp
1004         IF( ll_maxcvg ) THEN   ! error max over the domain
1005            DO_2D( 0, 0, 0, 0 )
1006               zresm = MAX( zresm, MAX( ABS( pu(ji,jj) - pub(ji,jj) ) * umask(ji,jj,1), &
1007                  &                     ABS( pv(ji,jj) - pvb(ji,jj) ) * vmask(ji,jj,1) ) * pmsk15(ji,jj) )
1008            END_2D
1009            CALL mpp_max( 'icedyn_rhg_evp', zresm )
1010         ELSE                   ! error averaged over the domain
1011            DO_2D( 0, 0, 0, 0 )
1012               zres(ji,jj,1) = MAX( ABS( pu(ji,jj) - pub(ji,jj) ) * umask(ji,jj,1), &
1013                  &                 ABS( pv(ji,jj) - pvb(ji,jj) ) * vmask(ji,jj,1) ) * pmsk15(ji,jj)
1014               zres(ji,jj,2) = pmsk15(ji,jj)
1015            END_2D
1016            ztmp(:) = glob_sum_vec( 'icedyn_rhg_evp', zres )
1017            IF( ztmp(2) /= 0._wp )   zresm = ztmp(1) / ztmp(2)
1018         ENDIF
1019      ENDIF
1020
1021      IF( lwm ) THEN
1022         ! write variables
1023         istatus = NF90_PUT_VAR( ncvgid, nvarid, (/zresm/), (/it/), (/1/) )
1024         ! close file
1025         IF( kt == nitend - nn_fsbc + 1 )   istatus = NF90_CLOSE(ncvgid)
1026      ENDIF
1027
1028   END SUBROUTINE rhg_cvg
1029
1030
1031   SUBROUTINE rhg_evp_rst( cdrw, kt )
1032      !!---------------------------------------------------------------------
1033      !!                   ***  ROUTINE rhg_evp_rst  ***
1034      !!
1035      !! ** Purpose :   Read or write RHG file in restart file
1036      !!
1037      !! ** Method  :   use of IOM library
1038      !!----------------------------------------------------------------------
1039      CHARACTER(len=*) , INTENT(in) ::   cdrw   ! "READ"/"WRITE" flag
1040      INTEGER, OPTIONAL, INTENT(in) ::   kt     ! ice time-step
1041      !
1042      INTEGER  ::   iter            ! local integer
1043      INTEGER  ::   id1, id2, id3   ! local integers
1044      !!----------------------------------------------------------------------
1045      !
1046      IF( TRIM(cdrw) == 'READ' ) THEN        ! Read/initialize
1047         !                                   ! ---------------
1048         IF( ln_rstart ) THEN                   !* Read the restart file
1049            !
1050            id1 = iom_varid( numrir, 'stress1_i' , ldstop = .FALSE. )
1051            id2 = iom_varid( numrir, 'stress2_i' , ldstop = .FALSE. )
1052            id3 = iom_varid( numrir, 'stress12_i', ldstop = .FALSE. )
1053            !
1054            IF( MIN( id1, id2, id3 ) > 0 ) THEN      ! fields exist
1055               CALL iom_get( numrir, jpdom_auto, 'stress1_i' , stress1_i , cd_type = 'T' )
1056               CALL iom_get( numrir, jpdom_auto, 'stress2_i' , stress2_i , cd_type = 'T' )
1057               CALL iom_get( numrir, jpdom_auto, 'stress12_i', stress12_i, cd_type = 'F' )
1058            ELSE                                     ! start rheology from rest
1059               IF(lwp) WRITE(numout,*)
1060               IF(lwp) WRITE(numout,*) '   ==>>>   previous run without rheology, set stresses to 0'
1061               stress1_i (:,:) = 0._wp
1062               stress2_i (:,:) = 0._wp
1063               stress12_i(:,:) = 0._wp
1064            ENDIF
1065         ELSE                                   !* Start from rest
1066            IF(lwp) WRITE(numout,*)
1067            IF(lwp) WRITE(numout,*) '   ==>>>   start from rest: set stresses to 0'
1068            stress1_i (:,:) = 0._wp
1069            stress2_i (:,:) = 0._wp
1070            stress12_i(:,:) = 0._wp
1071         ENDIF
1072         !
1073      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN   ! Create restart file
1074         !                                   ! -------------------
1075         IF(lwp) WRITE(numout,*) '---- rhg-rst ----'
1076         iter = kt + nn_fsbc - 1             ! ice restarts are written at kt == nitrst - nn_fsbc + 1
1077         !
1078         CALL iom_rstput( iter, nitrst, numriw, 'stress1_i' , stress1_i )
1079         CALL iom_rstput( iter, nitrst, numriw, 'stress2_i' , stress2_i )
1080         CALL iom_rstput( iter, nitrst, numriw, 'stress12_i', stress12_i )
1081         !
1082      ENDIF
1083      !
1084   END SUBROUTINE rhg_evp_rst
1085
1086   SUBROUTINE rhg_upstream( jter, pdt, pu, pv, pt )
1087      !!---------------------------------------------------------------------
1088      !!                    ***  ROUTINE rhg_upstream  ***
1089      !!
1090      !! **  Purpose :   compute the upstream fluxes and upstream guess of tracer
1091      !!----------------------------------------------------------------------
1092      INTEGER                    , INTENT(in   ) ::   jter
1093      REAL(wp)                   , INTENT(in   ) ::   pdt              ! tracer time-step
1094      REAL(wp), DIMENSION(:,:  ) , INTENT(in   ) ::   pu, pv           ! 2 ice velocity components
1095      REAL(wp), DIMENSION(:,:,:) , INTENT(inout) ::   pt               ! tracer fields
1096      !
1097      INTEGER  ::   ji, jj, jl    ! dummy loop indices
1098      REAL(wp) ::   ztra          ! local scalar
1099      LOGICAL  ::   ll_upsxy = .TRUE.
1100      REAL(wp), DIMENSION(jpi,jpj) ::   zfu_ups, zfv_ups, zpt   ! upstream fluxes and tracer guess
1101      !!----------------------------------------------------------------------
1102      DO jl = 1, jpl
1103         IF( .NOT. ll_upsxy ) THEN         !** no alternate directions **!
1104            !
1105            DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls-1 )
1106               zfu_ups(ji,jj) = MAX(pu(ji,jj)*e2u(ji,jj), 0._wp) * pt(ji,jj,jl) + MIN(pu(ji,jj)*e2u(ji,jj), 0._wp) * pt(ji+1,jj,jl)
1107               zfv_ups(ji,jj) = MAX(pv(ji,jj)*e1v(ji,jj), 0._wp) * pt(ji,jj,jl) + MIN(pv(ji,jj)*e1v(ji,jj), 0._wp) * pt(ji,jj+1,jl)
1108            END_2D
1109            !
1110         ELSE                              !** alternate directions **!
1111            !
1112            IF( MOD(jter,2) == 1 ) THEN   !==  odd ice time step:  adv_x then adv_y  ==!
1113               !
1114               DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls )       !-- flux in x-direction
1115                  zfu_ups(ji,jj) = MAX( pu(ji,jj)*e2u(ji,jj), 0._wp ) * pt(ji  ,jj,jl) + &
1116                     &             MIN( pu(ji,jj)*e2u(ji,jj), 0._wp ) * pt(ji+1,jj,jl)
1117               END_2D
1118               !
1119               DO_2D( nn_hls-1, nn_hls-1, nn_hls, nn_hls )     !-- first guess of tracer from u-flux
1120                  ztra       = - ( zfu_ups(ji,jj) - zfu_ups(ji-1,jj) )
1121                  zpt(ji,jj) =   ( pt(ji,jj,jl) + ztra * pdt * r1_e1e2t(ji,jj) ) * tmask(ji,jj,1)
1122               END_2D
1123               !
1124               DO_2D( nn_hls-1, nn_hls-1, nn_hls, nn_hls-1 )   !-- flux in y-direction
1125                  zfv_ups(ji,jj) = MAX( pv(ji,jj)*e1v(ji,jj), 0._wp ) * zpt(ji,jj  ) + &
1126                     &             MIN( pv(ji,jj)*e1v(ji,jj), 0._wp ) * zpt(ji,jj+1)
1127               END_2D
1128               !
1129            ELSE                          !==  even ice time step:  adv_y then adv_x  ==!
1130               !
1131               DO_2D( nn_hls, nn_hls, nn_hls, nn_hls-1 )       !-- flux in y-direction
1132                  zfv_ups(ji,jj) = MAX( pv(ji,jj)*e1v(ji,jj), 0._wp ) * pt(ji,jj  ,jl) + &
1133                     &             MIN( pv(ji,jj)*e1v(ji,jj), 0._wp ) * pt(ji,jj+1,jl)
1134               END_2D
1135               !
1136               DO_2D( nn_hls, nn_hls, nn_hls-1, nn_hls-1 )     !-- first guess of tracer from v-flux
1137                  ztra       = - ( zfv_ups(ji,jj) - zfv_ups(ji,jj-1) )
1138                  zpt(ji,jj) =   ( pt(ji,jj,jl) + ztra * pdt * r1_e1e2t(ji,jj) ) * tmask(ji,jj,1)
1139               END_2D
1140               !
1141               DO_2D( nn_hls, nn_hls-1, nn_hls-1, nn_hls-1 )   !-- flux in x-direction
1142                  zfu_ups(ji,jj) = MAX( pu(ji,jj)*e2u(ji,jj), 0._wp ) * zpt(ji  ,jj) + &
1143                     &             MIN( pu(ji,jj)*e2u(ji,jj), 0._wp ) * zpt(ji+1,jj)
1144               END_2D
1145               !
1146            ENDIF
1147            !
1148         ENDIF
1149         !
1150         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
1151            ztra         = - ( zfu_ups(ji,jj) - zfu_ups(ji-1,jj) + zfv_ups(ji,jj) - zfv_ups(ji,jj-1) )
1152            pt(ji,jj,jl) =   ( pt(ji,jj,jl) + ztra * pdt * r1_e1e2t(ji,jj) ) * tmask(ji,jj,1)
1153         END_2D
1154      END DO
1155      !
1156   END SUBROUTINE rhg_upstream
1157
1158#else
1159   !!----------------------------------------------------------------------
1160   !!   Default option         Empty module           NO SI3 sea-ice model
1161   !!----------------------------------------------------------------------
1162#endif
1163
1164   !!==============================================================================
1165END MODULE icedyn_rhg_evp
Note: See TracBrowser for help on using the repository browser.