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_vp.F90 in NEMO/trunk/src/ICE – NEMO

source: NEMO/trunk/src/ICE/icedyn_rhg_vp.F90

Last change on this file was 15531, checked in by vancop, 2 years ago

Bugfixed VP rheology for trunk

File size: 85.8 KB
Line 
1MODULE icedyn_rhg_vp
2   !!======================================================================
3   !!                     ***  MODULE  icedyn_rhg_vp  ***
4   !!   Sea-Ice dynamics : Viscous-plastic rheology with LSR technique
5   !!======================================================================
6   !!
7   !! History :   -   !  1997-20  (J. Zhang, M. Losch) Original code, implementation into mitGCM
8   !!            4.0  !  2020-09  (M. Vancoppenolle) Adaptation to SI3
9   !!
10   !!----------------------------------------------------------------------
11#if defined key_si3
12   !!----------------------------------------------------------------------
13   !!   'key_si3'                                       SI3 sea-ice model
14   !!----------------------------------------------------------------------
15   !!   ice_dyn_rhg_vp : computes ice velocities from VP rheolog with LSR solvery
16   !!----------------------------------------------------------------------
17   USE phycst         ! Physical constants
18   USE dom_oce        ! Ocean domain
19   USE sbc_oce , ONLY : ln_ice_embd, nn_fsbc, ssh_m
20   USE sbc_ice , ONLY : utau_ice, vtau_ice, snwice_mass, snwice_mass_b
21   USE ice            ! sea-ice: ice variables
22   USE icevar         ! ice_var_sshdyn
23   USE icedyn_rdgrft  ! sea-ice: ice strength
24   USE bdy_oce , ONLY : ln_bdy 
25   USE bdyice 
26#if defined key_agrif
27   USE agrif_ice_interp
28#endif
29   !
30   USE in_out_manager ! I/O manager
31   USE iom            ! I/O manager library
32   USE lib_mpp        ! MPP library
33   USE lib_fortran    ! fortran utilities (glob_sum + no signed zero)
34   USE lbclnk         ! lateral boundary conditions (or mpp links)
35   USE prtctl         ! Print control
36
37   USE netcdf         ! NetCDF library for convergence test
38   IMPLICIT NONE
39   PRIVATE
40
41   PUBLIC   ice_dyn_rhg_vp   ! called by icedyn_rhg.F90
42
43   INTEGER  ::   nn_nvp              ! total number of VP iterations (n_out_vp*n_inn_vp)
44   LOGICAL  ::   lp_zebra_vp =.TRUE. ! activate zebra (solve the linear system problem every odd j-band, then one every even one)
45   REAL(wp) ::   zrelaxu_vp=0.95     ! U-relaxation factor (MV: can probably be merged with V-factor once ok)
46   REAL(wp) ::   zrelaxv_vp=0.95     ! V-relaxation factor
47   REAL(wp) ::   zuerr_max_vp=0.80   ! maximum velocity error, above which a forcing error is considered and solver is stopped
48   REAL(wp) ::   zuerr_min_vp=1.e-04 ! minimum velocity error, beyond which convergence is assumed
49
50   !! for convergence tests
51   INTEGER ::   ncvgid        ! netcdf file id
52   INTEGER ::   nvarid_ures, nvarid_vres, nvarid_velres
53   INTEGER ::   nvarid_uerr_max, nvarid_verr_max, nvarid_velerr_max
54   INTEGER ::   nvarid_umad, nvarid_vmad, nvarid_velmad
55   INTEGER ::   nvarid_umad_outer, nvarid_vmad_outer, nvarid_velmad_outer
56   INTEGER ::   nvarid_mke
57
58   REAL(wp), DIMENSION(:,:), ALLOCATABLE ::   fimask   ! mask at F points for the ice
59   
60   !! * Substitutions
61#  include "do_loop_substitute.h90"
62   !!----------------------------------------------------------------------
63   !! NEMO/ICE 4.0 , NEMO Consortium (2018)
64   !! $Id: icedyn_rhg_vp.F90 13279 2020-07-09 10:39:43Z clem $
65   !! Software governed by the CeCILL license (see ./LICENSE)
66   !!----------------------------------------------------------------------
67   
68CONTAINS
69
70   SUBROUTINE ice_dyn_rhg_vp( kt, pshear_i, pdivu_i, pdelta_i )
71      !!-------------------------------------------------------------------
72      !!
73      !!                 ***  SUBROUTINE ice_dyn_rhg_vp  ***
74      !!                             VP-LSR-C-grid
75      !!
76      !! ** Purpose : determines sea ice drift from wind stress, ice-ocean
77      !!  stress and sea-surface slope. Internal forces assume viscous-plastic rheology (Hibler, 1979)
78      !!
79      !! ** Method
80      !! 
81      !!  The resolution algorithm  follows from Zhang and Hibler (1997) and Losch (2010)
82      !!  with elements from Lemieux and Tremblay (2008) and Lemieux and Tremblay (2009)
83      !! 
84      !!  The components of the momentum equations are arranged following the ideas of Zhang and Hibler (1997)
85      !!
86      !!  f1(u) = g1(v)
87      !!  f2(v) = g2(u)
88      !!
89      !!  The right-hand side (RHS) is explicit
90      !!  The left-hand side (LHS) is implicit
91      !!  Coriolis is part of explicit terms, whereas ice-ocean drag is implicit
92      !!
93      !!  Two iteration levels (outer and inner loops) are used to solve the equations
94      !!
95      !!  The outer loop (OL, typically 10 iterations) is there to deal with the (strong) non-linearities in the equation
96      !!
97      !!  The inner loop (IL, typically 1500 iterations) is there to solve the linear problem with a line-successive-relaxation algorithm
98      !!
99      !!  The velocity used in the non-linear terms uses a "modified euler time step" (not sure its the correct term),
100      !!! with uk = ( uk-1 + uk-2 ) / 2.
101      !! 
102      !!  * Spatial discretization
103      !!
104      !!  Assumes a C-grid
105      !!
106      !!  The points in the C-grid look like this, my darling
107      !!
108      !!                              (ji,jj)
109      !!                                 |
110      !!                                 |
111      !!                      (ji-1,jj)  |  (ji,jj)
112      !!                             ---------   
113      !!                            |         |
114      !!                            | (ji,jj) |------(ji,jj)
115      !!                            |         |
116      !!                             ---------   
117      !!                     (ji-1,jj-1)     (ji,jj-1)
118      !!
119      !! ** Inputs  : - wind forcing (stress), oceanic currents
120      !!                ice total volume (vt_i) per unit area
121      !!                snow total volume (vt_s) per unit area
122      !!
123      !! ** Action  :
124      !!             
125      !! ** Steps   :
126      !!           
127      !! ** Notes   :
128      !!             
129      !! References : Zhang and Hibler, JGR 1997; Losch et al., OM 2010., Lemieux et al., 2008, 2009, ... 
130      !!             
131      !!             
132      !!-------------------------------------------------------------------
133      !!
134      INTEGER                 , INTENT(in   ) ::   kt                                    ! time step
135      REAL(wp), DIMENSION(:,:), INTENT(  out) ::   pshear_i  , pdivu_i   , pdelta_i      !
136      !!
137      LOGICAL ::   ll_u_iterate, ll_v_iterate   ! continue iteration or not
138      !
139      INTEGER ::   ji, ji2, jj, jj2, jn          ! dummy loop indices
140      INTEGER ::   i_out, i_inn, i_inn_tot  !
141      INTEGER ::   ji_min, jj_min      !
142      INTEGER ::   nn_zebra_vp         ! number of zebra steps
143
144      !
145      REAL(wp) ::   zrhoco                                              ! rho0 * rn_cio
146      REAL(wp) ::   ecc2, z1_ecc2                                       ! square of yield ellipse eccenticity
147      REAL(wp) ::   zglob_area                                          ! global ice area for diagnostics
148      REAL(wp) ::   zkt                                                 ! isotropic tensile strength for landfast ice
149      REAL(wp) ::   zm1, zm2, zm3, zmassU, zmassV                       ! ice/snow mass and volume
150      REAL(wp) ::   zds2, zdt, zdt2, zdiv, zdiv2                        ! temporary scalars
151      REAL(wp) ::   zp_delstar_f                                        !
152      REAL(wp) ::   zu_cV, zv_cU                                        !
153      REAL(wp) ::   zfac, zfac1, zfac2, zfac3
154      REAL(wp) ::   zt12U, zt11U, zt22U, zt21U, zt122U, zt121U
155      REAL(wp) ::   zt12V, zt11V, zt22V, zt21V, zt122V, zt121V
156      REAL(wp) ::   zAA3, zw, ztau, zuerr_max, zverr_max
157      !
158      REAL(wp), DIMENSION(jpi,jpj) ::   za_iU  , za_iV                      ! ice fraction on U/V points
159      REAL(wp), DIMENSION(jpi,jpj) ::   zmU_t, zmV_t                    ! Acceleration term contribution to RHS
160      REAL(wp), DIMENSION(jpi,jpj) ::   zmassU_t, zmassV_t              ! Mass per unit area divided by time step
161      !
162      REAL(wp), DIMENSION(jpi,jpj) ::   zdeltat, zdelstar_t             ! Delta & Delta* at T-points
163      REAL(wp), DIMENSION(jpi,jpj) ::   ztens, zshear                   ! Tension, shear
164      REAL(wp), DIMENSION(jpi,jpj) ::   zp_delstar_t                    ! P/delta* at T points
165      REAL(wp), DIMENSION(jpi,jpj) ::   zzt, zet                        ! Viscosity pre-factors at T points
166      REAL(wp), DIMENSION(jpi,jpj) ::   zef                             ! Viscosity pre-factor at F point
167      !
168      REAL(wp), DIMENSION(jpi,jpj) ::   zmt                             ! Mass per unit area at t-point
169      REAL(wp), DIMENSION(jpi,jpj) ::   zmf                             ! Coriolis factor (m*f) at t-point
170      REAL(wp), DIMENSION(jpi,jpj) ::   v_oceU, u_oceV, v_iceU, u_iceV  ! ocean/ice u/v component on V/U points
171      REAL(wp), DIMENSION(jpi,jpj) ::   zu_c, zv_c                      ! "current" ice velocity (m/s), average of previous two OL iterates
172      REAL(wp), DIMENSION(jpi,jpj) ::   zu_b, zv_b                      ! velocity at previous sub-iterate
173      REAL(wp), DIMENSION(jpi,jpj) ::   zuerr, zverr                    ! absolute U/Vvelocity difference between current and previous sub-iterates
174      !
175      REAL(wp), DIMENSION(jpi,jpj) ::   zds                             ! shear
176      REAL(wp), DIMENSION(jpi,jpj) ::   zsshdyn                         ! array used for the calculation of ice surface slope:
177      !                                                                 !    ocean surface (ssh_m) if ice is not embedded
178      !                                                                 !    ice bottom surface if ice is embedded   
179      REAL(wp), DIMENSION(jpi,jpj) ::   zCwU, zCwV                      ! ice-ocean drag pre-factor (rho*c*module(u))
180      REAL(wp), DIMENSION(jpi,jpj) ::   zspgU, zspgV                    ! surface pressure gradient at U/V points
181      REAL(wp), DIMENSION(jpi,jpj) ::   zCorU, zCorV                    ! Coriolis stress array
182      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_ai, ztauy_ai              ! ice-atm. stress at U-V points
183      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_oi_rhsu, ztauy_oi_rhsv    ! ice-ocean stress RHS contribution at U-V points
184      REAL(wp), DIMENSION(jpi,jpj) ::   zs1_rhsu, zs2_rhsu, zs12_rhsu   ! internal stress contributions to RHSU
185      REAL(wp), DIMENSION(jpi,jpj) ::   zs1_rhsv, zs2_rhsv, zs12_rhsv   ! internal stress contributions to RHSV
186      REAL(wp), DIMENSION(jpi,jpj) ::   zf_rhsu, zf_rhsv                ! U- and V- components of internal force RHS contributions
187      REAL(wp), DIMENSION(jpi,jpj) ::   zrhsu, zrhsv                    ! U and V RHS
188      REAL(wp), DIMENSION(jpi,jpj) ::   zAU, zBU, zCU, zDU, zEU         ! Linear system coefficients, U equation
189      REAL(wp), DIMENSION(jpi,jpj) ::   zAV, zBV, zCV, zDV, zEV         ! Linear system coefficients, V equation
190      REAL(wp), DIMENSION(jpi,jpj) ::   zFU, zFU_prime, zBU_prime       ! Rearranged linear system coefficients, U equation
191      REAL(wp), DIMENSION(jpi,jpj) ::   zFV, zFV_prime, zBV_prime       ! Rearranged linear system coefficients, V equation
192!!!      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_bi, ztauy_bi              ! ice-OceanBottom stress at U-V points (landfast)
193!!!      REAL(wp), DIMENSION(jpi,jpj) ::   ztaux_base, ztauy_base          ! ice-bottom stress at U-V points (landfast)
194     !
195      REAL(wp), DIMENSION(jpi,jpj) ::   zmsk00
196      REAL(wp), DIMENSION(jpi,jpj) ::   zmsk01x, zmsk01y                ! mask for lots of ice (1), little ice (0)
197      REAL(wp), DIMENSION(jpi,jpj) ::   zmsk00x, zmsk00y                ! mask for ice presence (1), no ice (0)
198      !
199      REAL(wp), PARAMETER          ::   zepsi  = 1.0e-20_wp             ! tolerance parameter
200      REAL(wp), PARAMETER          ::   zmmin  = 1._wp                  ! ice mass (kg/m2)  below which ice velocity becomes very small
201      REAL(wp), PARAMETER          ::   zamin  = 0.001_wp               ! ice concentration below which ice velocity becomes very small
202      !! --- diags
203      REAL(wp)                     ::   zsig1, zsig2, zsig12, zdelta, z1_strength, zfac_x, zfac_y
204      REAL(wp), DIMENSION(jpi,jpj) ::   zs1, zs2, zs12, zs12f           ! stress tensor components
205      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zsig_I, zsig_II, zsig1_p, zsig2_p
206      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   ztaux_oi, ztauy_oi
207      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_xmtrp_ice, zdiag_ymtrp_ice ! X/Y-component of ice mass transport (kg/s, SIMIP)
208      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_xmtrp_snw, zdiag_ymtrp_snw ! X/Y-component of snow mass transport (kg/s, SIMIP)
209      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zdiag_xatrp, zdiag_yatrp         ! X/Y-component of area transport (m2/s, SIMIP)
210
211      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zvel_res                         ! Residual of the linear system at last iteration
212      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   zvel_diff                        ! Absolute velocity difference @last outer iteration
213                       
214     
215      !!----------------------------------------------------------------------------------------------------------------------
216
217      IF( kt == nit000 .AND. lwp )   WRITE(numout,*) '-- ice_dyn_rhg_vp: VP sea-ice rheology (LSR solver)'
218      IF( lwp )   WRITE(numout,*) '-- ice_dyn_rhg_vp: VP sea-ice rheology (LSR solver)'
219           
220      !------------------------------------------------------------------------------!
221      !
222      ! --- Initialization
223      !
224      !------------------------------------------------------------------------------!
225     
226      ! for diagnostics and convergence tests
227      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
228         zmsk00(ji,jj) = MAX( 0._wp , SIGN( 1._wp , at_i(ji,jj) - epsi06  ) ) ! 1 if ice    , 0 if no ice
229      END_2D
230     
231      IF ( lp_zebra_vp ) THEN; nn_zebra_vp = 2
232                         ELSE; nn_zebra_vp = 1; ENDIF
233
234      nn_nvp = nn_vp_nout * nn_vp_ninn ! maximum number of iterations
235
236      IF( lwp )   WRITE(numout,*) ' lp_zebra_vp : ', lp_zebra_vp
237      IF( lwp )   WRITE(numout,*) ' nn_zebra_vp : ', nn_zebra_vp
238      IF( lwp )   WRITE(numout,*) ' nn_nvp      : ', nn_nvp
239     
240      zrhoco = rho0 * rn_cio 
241
242      ! ecc2: square of yield ellipse eccentricity
243      ecc2    = rn_ecc * rn_ecc
244      z1_ecc2 = 1._wp / ecc2
245               
246      ! Initialise convergence checks
247      IF( nn_rhg_chkcvg /= 0 ) THEN
248     
249         ! ice area for global mean kinetic energy (m2)
250         zglob_area = glob_sum( 'ice_rhg_vp', at_i(:,:) * e1e2t(:,:) * tmask(:,:,1) )
251         
252      ENDIF
253
254      ! Landfast param from Lemieux(2016): add isotropic tensile strength (following Konig Beatty and Holland, 2010)
255      ! MV: Not working yet...
256      IF( ln_landfast_L16 ) THEN   ;   zkt = rn_lf_tensile
257      ELSE                         ;   zkt = 0._wp
258      ENDIF
259
260      zs1_rhsu(:,:) = 0._wp; zs2_rhsu(:,:) = 0._wp; zs1_rhsv(:,:) = 0._wp; zs2_rhsv(:,:) = 0._wp
261      zrhsu  (:,:)  = 0._wp; zrhsv  (:,:)  = 0._wp; zf_rhsu(:,:)  = 0._wp; zf_rhsv(:,:)  = 0._wp
262      zAU(:,:) = 0._wp; zBU(:,:) = 0._wp; zCU(:,:) = 0._wp; zDU(:,:) = 0._wp; zEU(:,:) = 0._wp
263      zAV(:,:) = 0._wp; zBV(:,:) = 0._wp; zCV(:,:) = 0._wp; zDV(:,:) = 0._wp; zEV(:,:) = 0._wp
264
265      !------------------------------------------------------------------------------!
266      !
267      ! --- Time-independent quantities
268      !
269      !------------------------------------------------------------------------------!
270     
271      CALL ice_strength ! strength at T points
272     
273      !---------------------------
274      ! -- F-mask (code from EVP)
275      !---------------------------
276      IF( kt == nit000 ) THEN
277         ! MartinV:
278         ! In EVP routine, fimask is applied on shear at F-points, in order to enforce the lateral boundary condition (no-slip, ..., free-slip)
279         ! I am not sure the same recipe applies here
280         
281         ! - ocean/land mask
282         ALLOCATE( fimask(jpi,jpj) )
283         IF( rn_ishlat == 0._wp ) THEN
284            DO_2D( 0, 0, 0, 0 )
285               fimask(ji,jj) = tmask(ji,jj,1) * tmask(ji+1,jj,1) * tmask(ji,jj+1,1) * tmask(ji+1,jj+1,1)
286            END_2D
287         ELSE
288            DO_2D( 0, 0, 0, 0 )
289               fimask(ji,jj) = tmask(ji,jj,1) * tmask(ji+1,jj,1) * tmask(ji,jj+1,1) * tmask(ji+1,jj+1,1)
290               ! Lateral boundary conditions on velocity (modify fimask)
291               IF( fimask(ji,jj) == 0._wp ) THEN
292                  fimask(ji,jj) = rn_ishlat * MIN( 1._wp , MAX( umask(ji,jj,1), umask(ji,jj+1,1), &
293                     &                                          vmask(ji,jj,1), vmask(ji+1,jj,1) ) )
294               ENDIF
295            END_2D
296         ENDIF
297         
298         CALL lbc_lnk( 'icedyn_rhg_vp', fimask, 'F', 1._wp )
299      ENDIF
300     
301      !----------------------------------------------------------------------------------------------------------
302      ! -- Time-independent pre-factors for acceleration, ocean drag, coriolis, atmospheric drag, surface tilt
303      !----------------------------------------------------------------------------------------------------------
304      ! Compute all terms & factors independent of velocities, or only depending on velocities at previous time step     
305     
306      ! sea surface height
307      !    embedded sea ice: compute representative ice top surface
308      !    non-embedded sea ice: use ocean surface for slope calculation
309      zsshdyn(:,:) = ice_var_sshdyn( ssh_m, snwice_mass, snwice_mass_b)   
310
311      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
312         zmt(ji,jj) = rhos * vt_s(ji,jj) + rhoi * vt_i(ji,jj)       ! Snow and ice mass at T-point
313         zmf(ji,jj) = zmt(ji,jj) * ff_t(ji,jj)                      ! Coriolis factor at T points (m*f)
314      END_2D
315     
316      DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
317
318         ! Ice fraction at U-V points
319         za_iU(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)
320         za_iV(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)
321
322         ! Snow and ice mass at U-V points
323         zm1             = zmt(ji,jj)
324         zm2             = zmt(ji+1,jj)
325         zm3             = zmt(ji,jj+1)
326         zmassU          = 0.5_wp * ( zm1 * e1e2t(ji,jj) + zm2 * e1e2t(ji+1,jj) ) * r1_e1e2u(ji,jj) * umask(ji,jj,1)
327         zmassV          = 0.5_wp * ( zm1 * e1e2t(ji,jj) + zm3 * e1e2t(ji,jj+1) ) * r1_e1e2v(ji,jj) * vmask(ji,jj,1)
328         
329         ! Mass per unit area divided by time step
330         zmassU_t(ji,jj) = zmassU * r1_Dt_ice
331         zmassV_t(ji,jj) = zmassV * r1_Dt_ice
332         
333         ! Acceleration term contribution to RHS (depends on velocity at previous time step)           
334         zmU_t(ji,jj)    = zmassU_t(ji,jj) * u_ice(ji,jj)
335         zmV_t(ji,jj)    = zmassV_t(ji,jj) * v_ice(ji,jj)
336         
337         ! Ocean currents at U-V points
338         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)
339         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)
340         
341         ! Wind stress
342         ztaux_ai(ji,jj) = za_iU(ji,jj) * utau_ice(ji,jj)
343         ztauy_ai(ji,jj) = za_iV(ji,jj) * vtau_ice(ji,jj)
344         
345         ! Force due to sea surface tilt(- m*g*GRAD(ssh))
346         zspgU(ji,jj)    = - zmassU * grav * ( zsshdyn(ji+1,jj) - zsshdyn(ji,jj) ) * r1_e1u(ji,jj)
347         zspgV(ji,jj)    = - zmassV * grav * ( zsshdyn(ji,jj+1) - zsshdyn(ji,jj) ) * r1_e2v(ji,jj)
348         
349         ! Mask for ice presence (1) or absence (0)
350         zmsk00x(ji,jj)  = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zmassU ) )  ! 0 if no ice
351         zmsk00y(ji,jj)  = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zmassV ) )  ! 0 if no ice
352         
353         ! Mask for lots of ice (1) or little ice (0)
354         IF ( zmassU <= zmmin .AND. za_iU(ji,jj) <= zamin ) THEN   ;   zmsk01x(ji,jj) = 0._wp
355         ELSE                                                      ;   zmsk01x(ji,jj) = 1._wp   ;   ENDIF
356         IF ( zmassV <= zmmin .AND. za_iV(ji,jj) <= zamin ) THEN   ;   zmsk01y(ji,jj) = 0._wp
357         ELSE                                                      ;   zmsk01y(ji,jj) = 1._wp   ;   ENDIF             
358
359      END_2D 
360           
361      !------------------------------------------------------------------------------!
362      !
363      ! --- Start outer loop
364      !
365      !------------------------------------------------------------------------------!
366     
367      zu_c(:,:) = u_ice(:,:)
368      zv_c(:,:) = v_ice(:,:)
369     
370      i_inn_tot = 0
371
372      DO i_out = 1, nn_vp_nout
373
374         ! Velocities used in the non linear terms are the average of the past two iterates
375         ! u_it = 0.5 * ( u_{it-1} + u_{it-2} )
376         ! Also used in Hibler and Ackley (1983); Zhang and Hibler (1997); Lemieux and Tremblay (2009)
377         zu_c(:,:) = 0.5_wp * ( u_ice(:,:) + zu_c(:,:) )
378         zv_c(:,:) = 0.5_wp * ( v_ice(:,:) + zv_c(:,:) )
379         
380         !------------------------------------------------------------------------------!
381         !
382         ! --- Right-hand side (RHS) of the linear problem
383         !
384         !------------------------------------------------------------------------------!
385         ! In the outer loop, one needs to update all RHS terms
386         ! with explicit velocity dependencies (viscosities, coriolis, ocean stress)
387         ! as a function of "current" velocities (uc, vc)
388     
389         !------------------------------------------
390         ! -- Strain rates, viscosities and P/Delta
391         !------------------------------------------
392
393         ! --- divergence, tension & shear (Appendix B of Hunke & Dukowicz, 2002) --- !
394         DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls-1 ) ! 1->jpi-1
395         
396            ! loops start at 1 since there is no boundary condition (lbc_lnk) at i=1 and j=1 for F points
397            ! shear at F points
398            zds(ji,jj) = ( ( zu_c(ji,jj+1) * r1_e1u(ji,jj+1) - zu_c(ji,jj) * r1_e1u(ji,jj) ) * e1f(ji,jj) * e1f(ji,jj)   &
399               &         + ( zv_c(ji+1,jj) * r1_e2v(ji+1,jj) - zv_c(ji,jj) * r1_e2v(ji,jj) ) * e2f(ji,jj) * e2f(ji,jj)   &
400               &         ) * r1_e1e2f(ji,jj) * fimask(ji,jj)
401
402         END_2D
403
404         CALL lbc_lnk( 'icedyn_rhg_vp', zds, 'F', 1. ) ! necessary, zds2 uses jpi/jpj values for zds
405
406         DO_2D( nn_hls-1, nn_hls, nn_hls-1, nn_hls ) ! 2 -> jpj; 2,jpi !!! CHECK !!!
407            ! loop to jpi,jpj to avoid making a communication for zs1,zs2,zs12
408
409            ! shear**2 at T points (doc eq. A16)
410            zds2  = ( zds(ji,jj  ) * zds(ji,jj  ) * e1e2f(ji,jj  ) + zds(ji-1,jj  ) * zds(ji-1,jj  ) * e1e2f(ji-1,jj  )  &
411               &    + 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)  &
412               &    ) * 0.25_wp * r1_e1e2t(ji,jj)
413             
414            ! divergence at T points
415            zdiv  = ( e2u(ji,jj) * zu_c(ji,jj) - e2u(ji-1,jj) * zu_c(ji-1,jj)   &
416               &    + e1v(ji,jj) * zv_c(ji,jj) - e1v(ji,jj-1) * zv_c(ji,jj-1)   &
417               &    ) * r1_e1e2t(ji,jj)
418            zdiv2 = zdiv * zdiv
419               
420            ! tension at T points
421            zdt   = ( ( zu_c(ji,jj) * r1_e2u(ji,jj) - zu_c(ji-1,jj) * r1_e2u(ji-1,jj) ) * e2t(ji,jj) * e2t(ji,jj)   &
422               &    - ( zv_c(ji,jj) * r1_e1v(ji,jj) - zv_c(ji,jj-1) * r1_e1v(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj)   &
423               &    ) * r1_e1e2t(ji,jj)
424            zdt2  = zdt * zdt
425               
426            ! delta at T points
427            zdeltat(ji,jj)        = SQRT( zdiv2 + ( zdt2 + zds2 ) * z1_ecc2 ) 
428               
429            ! delta* at T points (following Lemieux and Dupont, GMD 2020)
430            zdelstar_t(ji,jj)     = zdeltat(ji,jj) + rn_creepl ! OPT zdelstar_t can be totally removed and put into next line directly. Could change results
431             
432            ! P/delta* at T-points
433            zp_delstar_t(ji,jj)   = strength(ji,jj) / zdelstar_t(ji,jj)
434               
435            ! Temporary zzt and zet factors at T-points
436            zzt(ji,jj)            = zp_delstar_t(ji,jj) * r1_e1e2t(ji,jj)
437            zet(ji,jj)            = zzt(ji,jj)     * z1_ecc2 
438                         
439         END_2D
440         
441         CALL lbc_lnk( 'icedyn_rhg_vp', zp_delstar_t , 'T', 1. ) ! necessary, used for ji = 1 and jj = 1
442
443         DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls-1 )! 1-> jpj-1; 1->jpi-1
444         
445               ! P/delta* at F points
446               zp_delstar_f = 0.25_wp * ( zp_delstar_t(ji,jj) + zp_delstar_t(ji+1,jj) + zp_delstar_t(ji,jj+1) + zp_delstar_t(ji+1,jj+1) )
447               
448               ! Temporary zef factor at F-point
449               zef(ji,jj)      = zp_delstar_f * r1_e1e2f(ji,jj) * z1_ecc2 * fimask(ji,jj) * 0.5_wp
450               
451         END_2D
452         
453         !---------------------------------------------------
454         ! -- Ocean-ice drag and Coriolis RHS contributions
455         !---------------------------------------------------
456
457         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
458         
459            !--- ice u-velocity @V points, v-velocity @U points (for non-linear drag computation)
460            zu_cV            = 0.25_wp * ( zu_c(ji,jj) + zu_c(ji-1,jj) + zu_c(ji,jj+1) + zu_c(ji-1,jj+1) ) * vmask(ji,jj,1)
461            zv_cU            = 0.25_wp * ( zv_c(ji,jj) + zv_c(ji,jj-1) + zv_c(ji+1,jj) + zv_c(ji+1,jj-1) ) * umask(ji,jj,1)
462               
463            !--- non-linear drag coefficients (need to be updated at each outer loop, see Lemieux and Tremblay JGR09, p.3, beginning of Section 3)
464            zCwU(ji,jj)          = za_iU(ji,jj) * zrhoco * SQRT( ( zu_c (ji,jj) - u_oce (ji,jj) ) * ( zu_c (ji,jj) - u_oce (ji,jj) )  &
465              &                                                + ( zv_cU - v_oceU(ji,jj) ) * ( zv_cU - v_oceU(ji,jj) ) )
466            zCwV(ji,jj)          = za_iV(ji,jj) * zrhoco * SQRT( ( zv_c (ji,jj) - v_oce (ji,jj) ) * ( zv_c (ji,jj) - v_oce (ji,jj) )  &
467              &                                                + ( zu_cV - u_oceV(ji,jj) ) * ( zu_cV - u_oceV(ji,jj) ) )
468                 
469            !--- Ocean-ice drag contributions to RHS
470            ztaux_oi_rhsu(ji,jj) = zCwU(ji,jj) * u_oce(ji,jj)
471            ztauy_oi_rhsv(ji,jj) = zCwV(ji,jj) * v_oce(ji,jj)
472               
473            !--- U-component of Coriolis Force (energy conserving formulation)
474            zCorU(ji,jj)         =   0.25_wp * r1_e1u(ji,jj) *  &
475                       &             ( zmf(ji  ,jj) * ( e1v(ji  ,jj) * zv_c(ji  ,jj) + e1v(ji  ,jj-1) * zv_c(ji  ,jj-1) )  &
476                       &             + zmf(ji+1,jj) * ( e1v(ji+1,jj) * zv_c(ji+1,jj) + e1v(ji+1,jj-1) * zv_c(ji+1,jj-1) ) )
477                           
478            !--- V-component of Coriolis Force (energy conserving formulation)
479            zCorV(ji,jj)         = - 0.25_wp * r1_e2v(ji,jj) *  &
480                       &             ( zmf(ji,jj  ) * ( e2u(ji,jj  ) * zu_c(ji,jj  ) + e2u(ji-1,jj  ) * zu_c(ji-1,jj  ) )  &
481                       &             + zmf(ji,jj+1) * ( e2u(ji,jj+1) * zu_c(ji,jj+1) + e2u(ji-1,jj+1) * zu_c(ji-1,jj+1) ) )
482
483         END_2D
484         
485         !-------------------------------------
486         ! -- Internal stress RHS contribution
487         !-------------------------------------
488
489         ! --- Stress contributions at T-points
490         DO_2D( nn_hls-1, nn_hls, nn_hls-1, nn_hls ) ! 2 -> jpj; 2,jpi !!! CHECK !!!
491         
492         ! loop to jpi,jpj to avoid making a communication for zs1 & zs2
493           
494            ! sig1 contribution to RHS of U-equation at T-points
495            zs1_rhsu(ji,jj) =   zzt(ji,jj) * ( e1v(ji,jj)    * zv_c(ji,jj) - e1v(ji,jj-1)    * zv_c(ji,jj-1) )   &
496                            &                - zp_delstar_t(ji,jj) * zdeltat(ji,jj)
497                                           
498            ! sig2 contribution to RHS of U-equation at T-points           
499            zs2_rhsu(ji,jj) = - zet(ji,jj) * ( r1_e1v(ji,jj) * zv_c(ji,jj) - r1_e1v(ji,jj-1) * zv_c(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj) 
500
501            ! sig1 contribution to RHS of V-equation at T-points
502            zs1_rhsv(ji,jj) =   zzt(ji,jj) * ( e2u(ji,jj)    * zu_c(ji,jj) - e2u(ji-1,jj)    * zu_c(ji-1,jj) )   & 
503                            &                - zp_delstar_t(ji,jj) * zdeltat(ji,jj)
504
505            ! sig2 contribution to RHS of V-equation  at T-points
506            zs2_rhsv(ji,jj) =   zet(ji,jj) * ( r1_e2u(ji,jj) * zu_c(ji,jj) - r1_e2u(ji-1,jj) * zu_c(ji-1,jj) ) * e2t(ji,jj) * e2t(ji,jj)
507
508         END_2D
509                 
510         ! --- Stress contributions at F-points         
511         ! MV NOTE: I applied fimask on zds, by mimetism on EVP, but without deep understanding of what I was doing
512         ! My guess is that this is the way to enforce boundary conditions on strain rate tensor
513
514         DO_2D( nn_hls, nn_hls-1, nn_hls, nn_hls-1 ) ! 1->jpi-1
515         
516            ! sig12 contribution to RHS of U equation at F-points
517            zs12_rhsu(ji,jj) =   zef(ji,jj)  * ( r1_e2v(ji+1,jj) * zv_c(ji+1,jj) + r1_e2v(ji,jj) * zv_c(ji,jj) ) * e2f(ji,jj) * e2f(ji,jj) * fimask(ji,jj)
518
519            ! sig12 contribution to RHS of V equation at F-points
520            zs12_rhsv(ji,jj) =   zef(ji,jj)  * ( r1_e1u(ji,jj+1) * zu_c(ji,jj+1) + r1_e1u(ji,jj) * zu_c(ji,jj) ) * e1f(ji,jj) * e1f(ji,jj) * fimask(ji,jj)
521
522         END_2D
523         
524         ! --- Internal force contributions to RHS, taken as divergence of stresses (Appendix C of Hunke and Dukowicz, 2002)
525         ! OPT: merge with next loop and use intermediate scalars for zf_rhsu
526         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
527         
528               ! --- U component of internal force contribution to RHS at U points
529               zf_rhsu(ji,jj) = 0.5_wp * r1_e1e2u(ji,jj) * & 
530                              (    e2u(ji,jj)    * ( zs1_rhsu(ji+1,jj) - zs1_rhsu(ji,jj) )                                                                 &
531                  &      +         r1_e2u(ji,jj) * ( e2t(ji+1,jj) * e2t(ji+1,jj) * zs2_rhsu(ji+1,jj) - e2t(ji,jj)   * e2t(ji,jj)   * zs2_rhsu(ji,jj) )     &
532                  &      + 2._wp * r1_e1u(ji,jj) * ( e1f(ji,jj)   * e1f(ji,jj)   * zs12_rhsu(ji,jj)  - e1f(ji,jj-1) * e1f(ji,jj-1) * zs12_rhsu(ji,jj-1) ) )
533                 
534               ! --- V component of internal force contribution to RHS at V points
535               zf_rhsv(ji,jj) = 0.5_wp * r1_e1e2v(ji,jj) * &
536                  &           (    e1v(ji,jj)    * ( zs1_rhsv(ji,jj+1) - zs1_rhsv(ji,jj) )                                                                 &
537                  &      -         r1_e1v(ji,jj) * ( e1t(ji,jj+1) * e1t(ji,jj+1) * zs2_rhsv(ji,jj+1) - e1t(ji,jj)   * e1t(ji,jj)   * zs2_rhsv(ji,jj) )     &
538                  &      + 2._wp * r1_e2v(ji,jj) * ( e2f(ji,jj)   * e2f(ji,jj)   * zs12_rhsv(ji,jj)  - e2f(ji-1,jj) * e2f(ji-1,jj) * zs12_rhsv(ji-1,jj) ) )
539
540         END_2D
541         
542         !---------------------------
543         ! -- Sum RHS contributions
544         !---------------------------
545         !
546         ! OPT: could use intermediate scalars to reduce memory access
547         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
548                     
549            zrhsu(ji,jj) = zmU_t(ji,jj) + ztaux_ai(ji,jj) + ztaux_oi_rhsu(ji,jj) + zspgU(ji,jj) + zCorU(ji,jj) + zf_rhsu(ji,jj)
550            zrhsv(ji,jj) = zmV_t(ji,jj) + ztauy_ai(ji,jj) + ztauy_oi_rhsv(ji,jj) + zspgV(ji,jj) + zCorV(ji,jj) + zf_rhsv(ji,jj)
551
552         END_2D
553         
554         !---------------------------------------------------------------------------------------!
555         !
556         ! --- Linear system matrix
557         !
558         !---------------------------------------------------------------------------------------!
559     
560         ! Linear system matrix contains all implicit contributions
561         ! 1) internal forces, 2) acceleration, 3) ice-ocean drag
562
563         ! The linear system equation is written as follows
564         ! AU * u_{i-1,j} + BU * u_{i,j}   + CU * u_{i+1,j}
565         !                = DU * u_{i,j-1} + EU * u_{i,j+1} + RHS          (! my convention, not the same as ZH97 )         
566         
567         ! MV Note 1: martin losch applies boundary condition to BU in mitGCM - check whether it is necessary here ?
568         ! MV Note 2: "T" factor calculations can be optimized by putting things out of the loop
569         !         only zzt and zet are iteration-dependent, other only depend on scale factors
570                 
571         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
572         
573            !-------------------------------------
574            ! -- Internal forces LHS contribution
575            !-------------------------------------
576            !
577            ! --- U-component
578            !
579            ! "T" factors (intermediate results)
580            !
581            zfac       = 0.5_wp * r1_e1e2u(ji,jj)
582            zfac1      =         zfac * e2u(ji,jj)
583            zfac2      =         zfac * r1_e2u(ji,jj)
584            zfac3      = 2._wp * zfac * r1_e1u(ji,jj)
585
586            zt11U      =   zfac1 * zzt(ji,jj)
587            zt12U      =   zfac1 * zzt(ji+1,jj)
588         
589            zt21U      =   zfac2 * zet(ji,jj)   * e2t(ji,jj)   * e2t(ji,jj)   * e2t(ji,jj)   * e2t(ji,jj)
590            zt22U      =   zfac2 * zet(ji+1,jj) * e2t(ji+1,jj) * e2t(ji+1,jj) * e2t(ji+1,jj) * e2t(ji+1,jj)
591         
592            zt121U     =   zfac3 * zef(ji,jj-1) * e1f(ji,jj-1) * e1f(ji,jj-1) * e1f(ji,jj-1) * e1f(ji,jj-1)
593            zt122U     =   zfac3 * zef(ji,jj)   * e1f(ji,jj)   * e1f(ji,jj)   * e1f(ji,jj)   * e1f(ji,jj)
594               
595            !
596            ! Linear system coefficients
597            !
598            zAU(ji,jj) = -   zt11U           * e2u(ji-1,jj) -   zt21U           * r1_e2u(ji-1,jj)
599            zBU(ji,jj) =   ( zt11U + zt12U ) * e2u(ji,jj)   + ( zt21U + zt22U ) * r1_e2u(ji,jj)   + ( zt121U + zt122U ) * r1_e1u(ji,jj)
600            zCU(ji,jj) = -   zt12U           * e2u(ji+1,jj) -   zt22U           * r1_e2u(ji+1,jj)
601         
602            zDU(ji,jj) =     zt121U * r1_e1u(ji,jj-1)
603            zEU(ji,jj) =     zt122U * r1_e1u(ji,jj+1)
604             
605            !
606            ! --- V-component
607            !
608            ! "T" factors (intermediate results)
609            !
610            zfac       = 0.5_wp * r1_e1e2v(ji,jj)
611            zfac1      =         zfac * e1v(ji,jj)
612            zfac2      =         zfac * r1_e1v(ji,jj)
613            zfac3      = 2._wp * zfac * r1_e2v(ji,jj)
614
615            zt11V      =   zfac1 * zzt(ji,jj)
616            zt12V      =   zfac1 * zzt(ji,jj+1)
617
618            zt21V      =   zfac2 * zet(ji,jj)   * e1t(ji,jj)   * e1t(ji,jj)   * e1t(ji,jj)   * e1t(ji,jj)
619            zt22V      =   zfac2 * zet(ji,jj+1) * e1t(ji,jj+1) * e1t(ji,jj+1) * e1t(ji,jj+1) * e1t(ji,jj+1)
620         
621            zt121V     =   zfac3 * zef(ji-1,jj) * e2f(ji-1,jj) * e2f(ji-1,jj) * e2f(ji-1,jj) * e2f(ji-1,jj)
622            zt122V     =   zfac3 * zef(ji,jj)   * e2f(ji,jj)   * e2f(ji,jj)   * e2f(ji,jj)   * e2f(ji,jj)
623
624            !
625            ! Linear system coefficients
626            !
627            zAV(ji,jj) = -   zt11V           * e1v(ji,jj-1) -   zt21V           * r1_e1v(ji,jj-1)
628            zBV(ji,jj) =   ( zt11V + zt12V ) * e1v(ji,jj)   + ( zt21V + zt22V ) * r1_e1v(ji,jj)   + ( zt122V + zt121V ) * r1_e2v(ji,jj)
629            zCV(ji,jj) = -   zt12V           * e1v(ji,jj+1) -   zt22V           * r1_e1v(ji,jj+1)
630
631            zDV(ji,jj) =     zt121V * r1_e2v(ji-1,jj)
632            zEV(ji,jj) =     zt122V * r1_e2v(ji+1,jj)
633                 
634            !-----------------------------------------------------
635            ! -- Ocean-ice drag and acceleration LHS contribution
636            !-----------------------------------------------------
637            zBU(ji,jj) = zBU(ji,jj) + zCwU(ji,jj) + zmassU_t(ji,jj)
638            zBV(ji,jj) = zBV(ji,jj) + zCwV(ji,jj) + zmassV_t(ji,jj)
639         
640         END_2D
641         
642      !------------------------------------------------------------------------------!
643      !
644      ! --- Inner loop: solve linear system, check convergence
645      !
646      !------------------------------------------------------------------------------!
647               
648         ! Inner loop solves the linear problem .. requires 1500 iterations
649         ll_u_iterate = .TRUE.
650         ll_v_iterate = .TRUE.
651
652         DO i_inn = 1, nn_vp_ninn ! inner loop iterations
653
654            !--- mitgcm computes initial value of residual here...
655
656            i_inn_tot             = i_inn_tot + 1
657            ! l_full_nf_update = i_inn_tot == nn_nvp   ! false: disable full North fold update (performances) for iter = 1 to nn_nevp-1
658
659            zu_b(:,:)       = u_ice(:,:) ! velocity at previous inner-iterate
660            zv_b(:,:)       = v_ice(:,:)
661
662            IF ( ll_u_iterate .OR. ll_v_iterate )   THEN
663
664                                           ! ---------------------------- !
665               IF ( ll_u_iterate ) THEN    ! --- Solve for u-velocity --- !
666                                           ! ---------------------------- !
667
668                  ! What follows could be subroutinized...
669     
670                  ! Thomas Algorithm  for tridiagonal solver
671                  ! A*u(i-1,j)+B*u(i,j)+C*u(i+1,j) = F
672
673                  zFU(:,:)       = 0._wp ; zFU_prime(:,:) = 0._wp ; zBU_prime(:,:) = 0._wp; 
674                 
675                  DO jn = 1, nn_zebra_vp ! "zebra" loop (! red-black-sor!!! )
676                 
677                     ! OPT: could be even better optimized with a true red-black SOR
678     
679                     IF ( jn == 1 ) THEN   ;   jj_min = 2 
680                     ELSE                  ;   jj_min = 3
681                     ENDIF
682
683                     DO jj = jj_min, jpj - 1, nn_zebra_vp
684                     
685                        !------------------------
686                        ! Independent term (zFU)
687                        !------------------------
688                        DO ji = 2, jpi - 1   
689                           ! note: these are key lines linking information between processors
690                           ! u_ice/v_ice need to be lbc_linked
691
692                           ! sub-domain boundary condition substitution
693                           ! see Zhang and Hibler, 1997, Appendix B
694                           zAA3 = 0._wp
695                           IF ( ji == 2 )         zAA3 = zAA3 - zAU(ji,jj) * u_ice(ji-1,jj)
696                           IF ( ji == jpi - 1 )   zAA3 = zAA3 - zCU(ji,jj) * u_ice(ji+1,jj)
697
698                           ! right hand side
699                           zFU(ji,jj) = ( zrhsu(ji,jj) &                                      ! right-hand side terms
700                               &      +   zAA3         &                                      ! boundary condition translation
701                               &      +   zDU(ji,jj) * u_ice(ji,jj-1)   &                     ! internal force, j-1
702                               &      +   zEU(ji,jj) * u_ice(ji,jj+1) ) * umask(ji,jj,1)      ! internal force, j+1
703
704                        END DO
705
706                     END DO
707                     
708                     !---------------
709                     ! Forward sweep
710                     !---------------   
711                     DO jj = jj_min, jpj - 1, nn_zebra_vp
712     
713                        zBU_prime(2,jj)     = zBU(2,jj)
714                        zFU_prime(2,jj)     = zFU(2,jj)
715
716                        DO ji = 3, jpi - 1
717
718                           zfac             = SIGN( 1._wp , zBU(ji-1,jj) ) * MAX( 0._wp , SIGN( 1._wp , ABS( zBU(ji-1,jj) ) - epsi20 ) )
719                           zw               = zfac * zAU(ji,jj) / MAX ( ABS( zBU(ji-1,jj) ) , epsi20 ) 
720                           zBU_prime(ji,jj) = zBU(ji,jj) - zw * zCU(ji-1,jj)
721                           zFU_prime(ji,jj) = zFU(ji,jj) - zw * zFU(ji-1,jj)
722
723                        END DO
724
725                     END DO
726                                                                                                     
727                     !-----------------------------
728                     ! Backward sweep & relaxation
729                     !-----------------------------
730
731                     DO jj = jj_min, jpj - 1, nn_zebra_vp
732                   
733                        ! --- Backward sweep
734
735                        ! last row
736                        zfac = SIGN( 1._wp , zBU_prime(jpi-1,jj) ) * MAX( 0._wp , SIGN( 1._wp , ABS( zBU_prime(jpi-1,jj) ) - epsi20 ) )
737                        u_ice(jpi-1,jj)    = zfac * zFU_prime(jpi-1,jj) / MAX( ABS ( zBU_prime(jpi-1,jj) ) , epsi20 ) & 
738                                           &            * umask(jpi-1,jj,1)
739
740                        DO ji = jpi - 2 , 2, -1 ! all other rows    !  ---> original backward loop
741                           zfac = SIGN( 1._wp , zBU_prime(ji,jj) ) * MAX( 0._wp , SIGN( 1._wp , ABS( zBU_prime(ji,jj) ) - epsi20 ) )
742                           u_ice(ji,jj)    = zfac * ( zFU_prime(ji,jj) - zCU(ji,jj) * u_ice(ji+1,jj) ) * umask(ji,jj,1)   & 
743                                           &                  / MAX ( ABS ( zBU_prime(ji,jj) ) , epsi20 ) 
744                        END DO
745
746                        !--- Relaxation and masking (for low-ice/no-ice cases)
747                        DO ji = 2, jpi - 1   
748                       
749                           u_ice(ji,jj) = zu_b(ji,jj) + zrelaxu_vp * ( u_ice(ji,jj) - zu_b(ji,jj) ) ! relaxation
750                           
751                           u_ice(ji,jj) =   zmsk00x(ji,jj)                                        &   ! masking
752                              &         * (           zmsk01x(ji,jj)   * u_ice(ji,jj)             &
753                              &           + ( 1._wp - zmsk01x(ji,jj) ) * u_oce(ji,jj) * 0.01_wp     ) * umask(ji,jj,1)
754                           
755                        END DO
756
757                     END DO ! jj
758
759                     CALL lbc_lnk( 'icedyn_rhg_vp', u_ice, 'U', -1. )
760                     
761                  END DO ! zebra loop
762
763               ENDIF !   ll_u_iterate
764
765               !                           ! ---------------------------- !
766               IF ( ll_v_iterate ) THEN    ! --- Solve for V-velocity --- !
767               !                           ! ---------------------------- !
768                                         
769                  ! MV OPT: what follows could be subroutinized...                 
770                  ! Thomas Algorithm  for tridiagonal solver
771                  ! A*v(i,j-1)+B*v(i,j)+C*v(i,j+1) = F
772                  ! It is intentional to have a ji then jj loop for V-velocity
773                  !!! ZH97 explain it is critical for convergence speed
774
775                  zFV(:,:)       = 0._wp ; zFV_prime(:,:) = 0._wp ; zBV_prime(:,:) = 0._wp; 
776
777                  DO jn = 1, nn_zebra_vp ! "zebra" loop
778     
779                     IF ( jn == 1 ) THEN   ;   ji_min = 2 
780                     ELSE                  ;   ji_min = 3
781                     ENDIF
782
783                     DO ji = ji_min, jpi - 1, nn_zebra_vp 
784                     
785                        !------------------------
786                        ! Independent term (zFV)
787                        !------------------------
788                        DO jj = 2, jpj - 1
789
790                           ! subdomain boundary condition substitution (check it is correctly applied !!!)
791                           ! see Zhang and Hibler, 1997, Appendix B
792                           zAA3 = 0._wp
793                           IF ( jj == 2 )       zAA3 = zAA3 - zAV(ji,jj) * v_ice(ji,jj-1)
794                           IF ( jj == jpj - 1 ) zAA3 = zAA3 - zCV(ji,jj) * v_ice(ji,jj+1)
795     
796                           ! right hand side
797                           zFV(ji,jj) = ( zrhsv(ji,jj) &                                   ! right-hand side terms
798                               &        + zAA3                                           & ! boundary condition translation
799                               &        + zDV(ji,jj) * v_ice(ji-1,jj)                    & ! internal force, j-1
800                               &        + zEV(ji,jj) * v_ice(ji+1,jj) ) * vmask(ji,jj,1)   ! internal force, j+1
801
802                        END DO
803                       
804                     END DO
805
806                     !---------------
807                     ! Forward sweep
808                     !---------------
809                     DO ji = ji_min, jpi - 1, nn_zebra_vp 
810                     
811                        zBV_prime(ji,2)     = zBV(ji,2)
812                        zFV_prime(ji,2)     = zFV(ji,2)
813
814                        DO jj = 3, jpj - 1 
815
816                           zfac             = SIGN( 1._wp , zBV(ji,jj-1) ) * MAX( 0._wp , SIGN( 1._wp , ABS( zBV(ji,jj-1) ) - epsi20 ) )
817                           zw               = zfac * zAV(ji,jj) / MAX ( ABS( zBV(ji,jj-1) ) , epsi20 )
818                           zBV_prime(ji,jj) = zBV(ji,jj) - zw * zCV(ji,jj-1)
819                           zFV_prime(ji,jj) = zFV(ji,jj) - zw * zFV(ji,jj-1) 
820
821                        END DO
822
823                     END DO
824
825                     !-----------------------------
826                     ! Backward sweep & relaxation
827                     !-----------------------------
828                     DO ji = ji_min, jpi - 1, nn_zebra_vp 
829                   
830                        ! --- Backward sweep
831                        ! last row
832                        zfac = SIGN( 1._wp , zBV_prime(ji,jpj-1) ) * MAX( 0._wp , SIGN( 1._wp , ABS( zBV_prime(ji,jpj-1) ) - epsi20 ) )
833                        v_ice(ji,jpj-1)  = zfac * zFV_prime(ji,jpj-1) / MAX ( ABS(zBV_prime(ji,jpj-1) ) , epsi20 ) & 
834                                         &         * vmask(ji,jpj-1,1)  ! last row
835
836                        ! other rows
837                        DO jj = jpj-2, 2, -1 ! original back loop
838                           zfac = SIGN( 1._wp , zBV_prime(ji,jj) ) * MAX( 0._wp , SIGN( 1._wp , ABS( zBV_prime(ji,jj) ) - epsi20 ) )
839                           v_ice(ji,jj)   = zfac * ( zFV_prime(ji,jj) - zCV(ji,jj) * v_ice(ji,jj+1) ) * vmask(ji,jj,1) &
840                                          &  / MAX ( ABS( zBV_prime(ji,jj) ) , epsi20 )       
841                        END DO           
842                                                   
843                        ! --- Relaxation & masking
844                        DO jj = 2, jpj - 1
845                       
846                            v_ice(ji,jj) = zv_b(ji,jj) + zrelaxv_vp * ( v_ice(ji,jj) - zv_b(ji,jj) )    ! relaxation
847                           
848                            v_ice(ji,jj) =   zmsk00y(ji,jj)                                        &      ! masking
849                              &         * (           zmsk01y(ji,jj)   * v_ice(ji,jj)              &
850                              &           + ( 1._wp - zmsk01y(ji,jj) ) * v_oce(ji,jj) * 0.01_wp    ) * vmask(ji,jj,1)
851
852                        END DO ! jj
853                       
854                     END DO ! ji
855
856                     CALL lbc_lnk( 'icedyn_rhg_vp', v_ice, 'V', -1. )
857                     
858                  END DO ! zebra loop
859                                   
860               ENDIF !   ll_v_iterate
861
862               ! I suspect the communication should go into the zebra loop if we want reproducibility
863                             
864               !--------------------------------------------------------------------------------------
865               ! -- Check convergence based on maximum velocity difference, continue or stop the loop
866               !--------------------------------------------------------------------------------------
867
868               !------
869               ! on U
870               !------
871               ! MV OPT: if the number of iterations to convergence is really variable, and keep the convergence check
872               ! then we must optimize the use of the mpp_max, which is prohibitive                           
873               zuerr_max  = 0._wp
874                               
875               IF ( ll_u_iterate .AND. MOD ( i_inn, nn_vp_chkcvg ) == 0 ) THEN
876
877                  ! - Maximum U-velocity difference               
878                  zuerr(:,:) = 0._wp
879                  DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
880                 
881                     zuerr(ji,jj) = ABS ( ( u_ice(ji,jj) - zu_b(ji,jj) ) ) * umask(ji,jj,1) 
882                 
883                  END_2D
884         
885                  zuerr_max = MAXVAL( zuerr )
886                  CALL mpp_max( 'icedyn_rhg_evp', zuerr_max )   ! max over the global domain - damned!
887
888                  ! - Stop if max error is too large ("safeguard against bad forcing" of original Zhang routine)
889                  IF ( i_inn > 1 .AND. zuerr_max > zuerr_max_vp ) THEN
890                      IF ( lwp ) WRITE(numout,*) " VP rheology error was too large : ", zuerr_max, " in outer U-iteration ", i_out, " after ", i_inn, " iterations, we stopped "
891                      ll_u_iterate = .FALSE.
892                  ENDIF
893                 
894                  ! - Stop if error small enough
895                  IF ( zuerr_max < zuerr_min_vp ) THEN                                       
896                      IF ( lwp ) WRITE(numout,*) " VP rheology nicely done in outer U-iteration ", i_out, " after ", i_inn, " iterations, finished! "
897                      ll_u_iterate = .FALSE.
898                  ENDIF
899                                               
900               ENDIF ! ll_u_iterate
901
902               !------
903               ! on V
904               !------
905               zverr_max = 0._wp
906               
907               IF ( ll_v_iterate .AND. MOD ( i_inn, nn_vp_chkcvg ) == 0 ) THEN
908               
909                  ! - Maximum V-velocity difference
910                  zverr(:,:)   = 0._wp   
911                  DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
912                 
913                        zverr(ji,jj) = ABS ( ( v_ice(ji,jj) - zv_b(ji,jj) ) ) * vmask(ji,jj,1)
914                 
915                  END_2D
916                           
917                  zverr_max = MAXVAL( zverr )
918                  CALL mpp_max( 'icedyn_rhg_evp', zverr_max )   ! max over the global domain - damned!
919                 
920                  ! - Stop if error is too large ("safeguard against bad forcing" of original Zhang routine)
921                  IF ( i_inn > 1 .AND. zverr_max > zuerr_max_vp ) THEN
922                      IF ( lwp ) WRITE(numout,*) " VP rheology error was too large : ", zverr_max, " in outer V-iteration ", i_out, " after ", i_inn, " iterations, we stopped "
923                      ll_v_iterate = .FALSE.
924                  ENDIF
925                 
926                  ! - Stop if error small enough
927                  IF ( zverr_max < zuerr_min_vp ) THEN                                       
928                      IF ( lwp ) WRITE(numout,*) " VP rheology nicely done in outer V-iteration ", i_out, " after ", i_inn, " iterations, finished! "
929                      ll_v_iterate = .FALSE.
930                  ENDIF
931                 
932               ENDIF ! ll_v_iterate
933
934            ENDIF ! ---    end ll_u_iterate or ll_v_iterate
935               
936            !---------------------------------------------------------------------------------------
937            !
938            ! --- Calculate extra convergence diagnostics and save them
939            !
940            !---------------------------------------------------------------------------------------
941            IF( nn_rhg_chkcvg/=0 .AND. MOD ( i_inn - 1, nn_vp_chkcvg ) == 0 ) THEN
942
943               CALL rhg_cvg_vp( kt, i_out, i_inn, i_inn_tot, nn_vp_nout, nn_vp_ninn, nn_nvp,        &
944                      &         u_ice, v_ice, zu_b, zv_b, zu_c, zv_c,                               &
945                      &         zmt, za_iU, za_iV, zuerr_max, zverr_max, zglob_area,                &
946                      &         zrhsu, zAU, zBU, zCU, zDU, zEU, zFU,                                &
947                      &         zrhsv, zAV, zBV, zCV, zDV, zEV, zFV,                                &
948                                zvel_res, zvel_diff )
949
950            ENDIF
951
952         END DO ! i_inn, end of inner loop
953
954      END DO ! End of outer loop (i_out) =============================================================================================
955
956      IF( nn_rhg_chkcvg/=0  ) THEN
957         
958         IF( iom_use('velo_res') )   CALL iom_put( 'velo_res', zvel_res  )   ! linear system residual  @last inner&outer iteration
959         IF( iom_use('velo_ero') )   CALL iom_put( 'velo_ero', zvel_diff )   ! abs velocity difference @last outer iteration
960         IF( iom_use('uice_eri') )   CALL iom_put( 'uice_eri', zuerr     )   ! abs velocity difference @last inner iteration
961         IF( iom_use('vice_eri') )   CALL iom_put( 'vice_eri', zverr     )   ! abs velocity difference @last inner iteration
962
963         DEALLOCATE( zvel_res , zvel_diff )
964       
965      ENDIF ! nn_rhg_chkcvg
966
967      !------------------------------------------------------------------------------!
968      !
969      ! --- Recompute delta, shear and div (inputs for mechanical redistribution)
970      !
971      !------------------------------------------------------------------------------!
972      !
973      ! MV OPT: subroutinize ?
974      DO_2D( nn_hls, nn_hls, nn_hls-1, nn_hls-1 ) ! 1->jpj-1; 1->jpi-1
975
976            ! shear at F points
977            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)   &
978               &         + ( v_ice(ji+1,jj) * r1_e2v(ji+1,jj) - v_ice(ji,jj) * r1_e2v(ji,jj) ) * e2f(ji,jj) * e2f(ji,jj)   &
979               &         ) * r1_e1e2f(ji,jj) * fimask(ji,jj)
980
981      END_2D     
982     
983      DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
984           
985            ! tension**2 at T points
986            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)   &
987               &   - ( v_ice(ji,jj) * r1_e1v(ji,jj) - v_ice(ji,jj-1) * r1_e1v(ji,jj-1) ) * e1t(ji,jj) * e1t(ji,jj)   &
988               &   ) * r1_e1e2t(ji,jj)
989            zdt2 = zdt * zdt
990           
991            ztens(ji,jj)    = zdt
992           
993            ! shear**2 at T points (doc eq. A16)
994            zds2 = ( zds(ji,jj  ) * zds(ji,jj  ) * e1e2f(ji,jj  ) + zds(ji-1,jj  ) * zds(ji-1,jj  ) * e1e2f(ji-1,jj  )  &
995               &   + 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)  &
996               &   ) * 0.25_wp * r1_e1e2t(ji,jj)
997           
998            ! maximum shear rate at T points (includees tension, output only)
999            pshear_i(ji,jj) = SQRT( zdt2 + zds2 ) ! i think this is maximum shear rate and not actual shear --- i'm not totally sure here
1000
1001            ! shear at T-points
1002            zshear(ji,jj)   = SQRT( zds2 )
1003
1004            ! divergence at T points
1005            pdivu_i(ji,jj) = ( e2u(ji,jj) * u_ice(ji,jj) - e2u(ji-1,jj) * u_ice(ji-1,jj)   &
1006               &             + e1v(ji,jj) * v_ice(ji,jj) - e1v(ji,jj-1) * v_ice(ji,jj-1)   &
1007               &             ) * r1_e1e2t(ji,jj)
1008
1009            zdiv2          =  pdivu_i(ji,jj) *  pdivu_i(ji,jj)
1010           
1011            ! delta at T points
1012            zdelta         = SQRT( zdiv2 + ( zdt2 + zds2 ) * z1_ecc2 )
1013            rswitch        = 1._wp - MAX( 0._wp, SIGN( 1._wp, -zdelta ) ) ! 0 if delta=0
1014
1015            pdelta_i(ji,jj) = zdelta + rn_creepl ! * rswitch
1016
1017      END_2D
1018     
1019      CALL lbc_lnk( 'icedyn_rhg_vp', pshear_i, 'T', 1., pdivu_i, 'T', 1., pdelta_i, 'T', 1. )
1020     
1021      !------------------------------------------------------------------------------!
1022      !
1023      ! --- Diagnostics
1024      !
1025      !------------------------------------------------------------------------------!
1026      !
1027      ! MV OPT: subroutinize ?
1028      !
1029      !----------------------------------
1030      ! --- Recompute stresses if needed
1031      !----------------------------------
1032      !
1033      ! ---- Sea ice stresses at T-points
1034      IF ( iom_use('normstr')    .OR. iom_use('sheastr')    .OR. &
1035     &     iom_use('intstrx')    .OR. iom_use('intstry')    .OR. &
1036     &     iom_use('sig1_pnorm') .OR. iom_use('sig2_pnorm') ) THEN
1037     
1038         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1039         
1040               zp_delstar_t(ji,jj)     =   strength(ji,jj) / pdelta_i(ji,jj) 
1041               zfac                    =   zp_delstar_t(ji,jj) 
1042               zs1(ji,jj)              =   zfac * ( pdivu_i(ji,jj) - pdelta_i(ji,jj) )
1043               zs2(ji,jj)              =   zfac * z1_ecc2 * ztens(ji,jj)
1044               zs12(ji,jj)             =   zfac * z1_ecc2 * zshear(ji,jj) * 0.5_wp ! Bug 12 nov
1045
1046         END_2D
1047
1048         CALL lbc_lnk( 'icedyn_rhg_vp', zs1, 'T', 1., zs2, 'T', 1., zs12, 'T', 1. )
1049     
1050      ENDIF
1051     
1052      ! ---- s12 at F-points     
1053      IF ( iom_use('intstrx') .OR. iom_use('intstry') ) THEN
1054
1055         DO_2D( nn_hls, nn_hls, nn_hls-1, nn_hls-1 ) ! 1->jpj-1; 1->jpi-1
1056           
1057               ! P/delta* at F points
1058               zp_delstar_f = 0.25_wp * ( zp_delstar_t(ji,jj) + zp_delstar_t(ji+1,jj) + zp_delstar_t(ji,jj+1) + zp_delstar_t(ji+1,jj+1) )
1059               
1060               ! s12 at F-points
1061               zs12f(ji,jj) = zp_delstar_f * z1_ecc2 * zds(ji,jj)
1062               
1063         END_2D
1064
1065         CALL lbc_lnk( 'icedyn_rhg_vp', zs12f, 'F', 1. )
1066         
1067      ENDIF
1068
1069      !
1070      !-----------------------
1071      ! --- Store diagnostics
1072      !-----------------------
1073      !
1074      ! --- Ice-ocean, ice-atm. & ice-ocean bottom (landfast) stresses --- !
1075      IF(  iom_use('utau_oi') .OR. iom_use('vtau_oi') .OR. iom_use('utau_ai') .OR. iom_use('vtau_ai') .OR. &
1076         & iom_use('utau_bi') .OR. iom_use('vtau_bi') ) THEN
1077
1078         ALLOCATE( ztaux_oi(jpi,jpj) , ztauy_oi(jpi,jpj) )
1079
1080         !--- Recalculate oceanic stress at last inner iteration
1081         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1082
1083                !--- ice u-velocity @V points, v-velocity @U points (for non-linear drag computation)
1084                zu_cV            = 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)
1085                zv_cU            = 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)
1086               
1087                !--- non-linear drag coefficients (need to be updated at each outer loop, see Lemieux and Tremblay JGR09, p.3, beginning of Section 3)
1088                zCwU(ji,jj)          = za_iU(ji,jj) * zrhoco * SQRT( ( u_ice(ji,jj) - u_oce (ji,jj) ) * ( u_ice(ji,jj) - u_oce (ji,jj) )  &
1089                  &                                                + ( zv_cU - v_oceU(ji,jj) ) * ( zv_cU - v_oceU(ji,jj) ) )
1090                zCwV(ji,jj)          = za_iV(ji,jj) * zrhoco * SQRT( ( v_ice(ji,jj) - v_oce (ji,jj) ) * ( v_ice(ji,jj) - v_oce (ji,jj) )  &
1091                  &                                                + ( zu_cV - u_oceV(ji,jj) ) * ( zu_cV - u_oceV(ji,jj) ) )
1092                 
1093                !--- Ocean-ice stress
1094                ztaux_oi(ji,jj) = zCwU(ji,jj) * ( u_oce(ji,jj) - u_ice(ji,jj) )
1095                ztauy_oi(ji,jj) = zCwV(ji,jj) * ( v_oce(ji,jj) - v_ice(ji,jj) )
1096               
1097         END_2D
1098         
1099         !
1100         CALL lbc_lnk( 'icedyn_rhg_vp', ztaux_oi, 'U', -1., ztauy_oi, 'V', -1., ztaux_ai, 'U', -1., ztauy_ai, 'V', -1. ) !, &
1101!            &                          ztaux_bi, 'U', -1., ztauy_bi, 'V', -1. )
1102         !
1103         CALL iom_put( 'utau_oi' , ztaux_oi * zmsk00 )
1104         CALL iom_put( 'vtau_oi' , ztauy_oi * zmsk00 )
1105         CALL iom_put( 'utau_ai' , ztaux_ai * zmsk00 )
1106         CALL iom_put( 'vtau_ai' , ztauy_ai * zmsk00 )
1107!        CALL iom_put( 'utau_bi' , ztaux_bi * zmsk00 )
1108!        CALL iom_put( 'vtau_bi' , ztauy_bi * zmsk00 )
1109
1110         DEALLOCATE( ztaux_oi , ztauy_oi )
1111
1112      ENDIF
1113       
1114      ! --- Divergence, shear and strength --- !
1115      IF( iom_use('icediv') )   CALL iom_put( 'icediv' , pdivu_i  * zmsk00 )   ! divergence
1116      IF( iom_use('iceshe') )   CALL iom_put( 'iceshe' , pshear_i * zmsk00 )   ! maximum shear rate
1117      IF( iom_use('icedlt') )   CALL iom_put( 'icedlt' , pdelta_i * zmsk00 )   ! delta
1118      IF( iom_use('icestr') )   CALL iom_put( 'icestr' , strength * zmsk00 )   ! strength
1119
1120      ! --- Stress tensor invariants (SIMIP diags) --- !
1121      IF( iom_use('normstr') .OR. iom_use('sheastr') ) THEN
1122         !
1123         ! Stress tensor invariants (normal and shear stress N/m) - SIMIP diags.
1124         ! Definitions following Coon (1974) and Feltham (2008)
1125         !
1126         ! sigma1, sigma2, sigma12 are useful (Hunke and Dukowicz MWR 2002, Bouillon et al., OM2013)
1127         ! however these are NOT stress tensor components, neither stress invariants, nor stress principal components
1128         !
1129         ALLOCATE( zsig_I(jpi,jpj) , zsig_II(jpi,jpj) )
1130         !         
1131         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1132               ! Stress invariants
1133               zsig_I(ji,jj)    =   zs1(ji,jj) * 0.5_wp   ! 1st invariant, aka average normal stress aka negative pressure
1134               zsig_II(ji,jj)   =   0.5_wp * SQRT ( zs2(ji,jj) * zs2(ji,jj) + 4. * zs12(ji,jj) * zs12(ji,jj) )   ! 2nd invariant, aka maximum shear stress               
1135         END_2D
1136
1137         CALL lbc_lnk( 'icedyn_rhg_vp', zsig_I, 'T', 1., zsig_II, 'T', 1.)
1138         
1139         IF( iom_use('normstr') )   CALL iom_put( 'normstr' ,   zsig_I(:,:)  * zmsk00(:,:) ) ! Normal stress
1140         IF( iom_use('sheastr') )   CALL iom_put( 'sheastr' ,   zsig_II(:,:) * zmsk00(:,:) ) ! Maximum shear stress
1141         
1142         DEALLOCATE ( zsig_I, zsig_II )
1143         
1144      ENDIF
1145
1146      ! --- Normalized stress tensor principal components --- !
1147      ! These are used to plot the normalized yield curve (Lemieux & Dupont, GMD 2020)
1148      ! To plot the yield curve and evaluate physical convergence, they have two recommendations
1149      ! Recommendation 1 : Use ice strength, not replacement pressure
1150      ! Recommendation 2 : Need to use deformations at PREVIOUS iterate for viscosities (see p. 1765)
1151      ! R2 means we need to recompute stresses
1152
1153      IF( iom_use('sig1_pnorm') .OR. iom_use('sig2_pnorm') ) THEN
1154         !
1155         ALLOCATE( zsig1_p(jpi,jpj) , zsig2_p(jpi,jpj) , zsig_I(jpi,jpj) , zsig_II(jpi,jpj) )
1156         !         
1157         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1158         
1159               ! Ice stresses computed with **viscosities** (delta, p/delta) at **previous** iterates
1160               !                        and **deformations** at current iterates
1161               !                        following Lemieux & Dupont (2020)
1162               zfac             =   zp_delstar_t(ji,jj)
1163               zsig1            =   zfac * ( pdivu_i(ji,jj) - zdeltat(ji,jj) )
1164               zsig2            =   zfac * z1_ecc2 * ztens(ji,jj)
1165               zsig12           =   zfac * z1_ecc2 * zshear(ji,jj) * 0.5_wp ! Bugfix 12 Nov
1166               
1167               ! Stress invariants (sigma_I, sigma_II, Coon 1974, Feltham 2008), T-point
1168               zsig_I(ji,jj)    =   zsig1 * 0.5_wp                                       ! 1st invariant
1169               zsig_II(ji,jj)   =   0.5_wp * SQRT ( zsig2 * zsig2 + 4. *zsig12 * zsig12 )   ! 2nd invariant
1170
1171               ! Normalized  principal stresses (used to display the ellipse)
1172               z1_strength      =   1._wp / MAX ( 1._wp , strength(ji,jj) )
1173               zsig1_p(ji,jj)   =   ( zsig_I(ji,jj) + zsig_II(ji,jj) ) * z1_strength
1174               zsig2_p(ji,jj)   =   ( zsig_I(ji,jj) - zsig_II(ji,jj) ) * z1_strength
1175               
1176         END_2D
1177         !
1178         CALL lbc_lnk( 'icedyn_rhg_vp', zsig1_p, 'T', 1., zsig2_p, 'T', 1.)
1179         !
1180         CALL iom_put( 'sig1_pnorm' , zsig1_p ) 
1181         CALL iom_put( 'sig2_pnorm' , zsig2_p ) 
1182
1183         DEALLOCATE( zsig1_p , zsig2_p , zsig_I , zsig_II )
1184         
1185      ENDIF
1186
1187      ! --- SIMIP, terms of tendency for momentum equation  --- !
1188      IF(  iom_use('dssh_dx') .OR. iom_use('dssh_dy') .OR. &
1189         & iom_use('corstrx') .OR. iom_use('corstry') ) THEN
1190
1191         ! --- Recalculate Coriolis stress at last inner iteration
1192         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1193                ! --- U-component
1194                zCorU(ji,jj)         =   0.25_wp * r1_e1u(ji,jj) *  &
1195                           &             ( zmf(ji  ,jj) * ( e1v(ji  ,jj) * v_ice(ji  ,jj) + e1v(ji  ,jj-1) * v_ice(ji  ,jj-1) )  &
1196                           &             + zmf(ji+1,jj) * ( e1v(ji+1,jj) * v_ice(ji+1,jj) + e1v(ji+1,jj-1) * v_ice(ji+1,jj-1) ) )
1197                zCorV(ji,jj)         = - 0.25_wp * r1_e2v(ji,jj) *  &
1198                           &             ( zmf(ji,jj  ) * ( e2u(ji,jj  ) * u_ice(ji,jj  ) + e2u(ji-1,jj  ) * u_ice(ji-1,jj  ) )  &
1199                           &             + zmf(ji,jj+1) * ( e2u(ji,jj+1) * u_ice(ji,jj+1) + e2u(ji-1,jj+1) * u_ice(ji-1,jj+1) ) )
1200         END_2D
1201         !
1202         CALL lbc_lnk( 'icedyn_rhg_vp', zspgU, 'U', -1., zspgV, 'V', -1., &
1203            &                           zCorU, 'U', -1., zCorV, 'V', -1. )
1204         !
1205         CALL iom_put( 'dssh_dx' , zspgU * zmsk00 )   ! Sea-surface tilt term in force balance (x)
1206         CALL iom_put( 'dssh_dy' , zspgV * zmsk00 )   ! Sea-surface tilt term in force balance (y)
1207         CALL iom_put( 'corstrx' , zCorU * zmsk00 )   ! Coriolis force term in force balance (x)
1208         CALL iom_put( 'corstry' , zCorV * zmsk00 )   ! Coriolis force term in force balance (y)
1209
1210      ENDIF
1211     
1212      IF ( iom_use('intstrx') .OR. iom_use('intstry') ) THEN
1213
1214         ! Recalculate internal forces (divergence of stress tensor) at last inner iteration
1215         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1216
1217               zfU(ji,jj) = 0.5_wp * ( ( zs1(ji+1,jj) - zs1(ji,jj) ) * e2u(ji,jj)                                             &
1218                  &                  + ( zs2(ji+1,jj) * e2t(ji+1,jj) * e2t(ji+1,jj) - zs2(ji,jj) * e2t(ji,jj) * e2t(ji,jj)    &
1219                  &                    ) * r1_e2u(ji,jj)                                                                      &
1220                  &                  + ( zs12f(ji,jj) * e1f(ji,jj) * e1f(ji,jj) - zs12f(ji,jj-1) * e1f(ji,jj-1) * e1f(ji,jj-1)  &
1221                  &                    ) * 2._wp * r1_e1u(ji,jj)                                                              &
1222                  &                  ) * r1_e1e2u(ji,jj)
1223
1224               zfV(ji,jj) = 0.5_wp * ( ( zs1(ji,jj+1) - zs1(ji,jj) ) * e1v(ji,jj)                                             &
1225                  &                  - ( zs2(ji,jj+1) * e1t(ji,jj+1) * e1t(ji,jj+1) - zs2(ji,jj) * e1t(ji,jj) * e1t(ji,jj)    &
1226                  &                    ) * r1_e1v(ji,jj)                                                                      &
1227                  &                  + ( zs12f(ji,jj) * e2f(ji,jj) * e2f(ji,jj) - zs12f(ji-1,jj) * e2f(ji-1,jj) * e2f(ji-1,jj)  &
1228                  &                    ) * 2._wp * r1_e2v(ji,jj)                                                              &
1229                  &                  ) * r1_e1e2v(ji,jj)
1230
1231         END_2D
1232           
1233         CALL lbc_lnk( 'icedyn_rhg_vp', zfU, 'U', -1., zfV, 'V', -1. )
1234         
1235         CALL iom_put( 'intstrx' , zfU   * zmsk00 )   ! Internal force term in force balance (x)
1236         CALL iom_put( 'intstry' , zfV   * zmsk00 )   ! Internal force term in force balance (y)
1237         
1238      ENDIF
1239
1240      ! --- Ice & snow mass and ice area transports
1241      IF(  iom_use('xmtrpice') .OR. iom_use('ymtrpice') .OR. &
1242         & iom_use('xmtrpsnw') .OR. iom_use('ymtrpsnw') .OR. iom_use('xatrp') .OR. iom_use('yatrp') ) THEN
1243         !
1244         ALLOCATE( zdiag_xmtrp_ice(jpi,jpj) , zdiag_ymtrp_ice(jpi,jpj) , &
1245            &      zdiag_xmtrp_snw(jpi,jpj) , zdiag_ymtrp_snw(jpi,jpj) , zdiag_xatrp(jpi,jpj) , zdiag_yatrp(jpi,jpj) )
1246         !
1247         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1               ! 2D ice mass, snow mass, area transport arrays (X, Y)
1248
1249               zfac_x = 0.5 * u_ice(ji,jj) * e2u(ji,jj) * zmsk00(ji,jj)
1250               zfac_y = 0.5 * v_ice(ji,jj) * e1v(ji,jj) * zmsk00(ji,jj)
1251
1252               zdiag_xmtrp_ice(ji,jj) = rhoi * zfac_x * ( vt_i(ji+1,jj) + vt_i(ji,jj) ) ! ice mass transport, X-component
1253               zdiag_ymtrp_ice(ji,jj) = rhoi * zfac_y * ( vt_i(ji,jj+1) + vt_i(ji,jj) ) !        ''           Y-   ''
1254
1255               zdiag_xmtrp_snw(ji,jj) = rhos * zfac_x * ( vt_s(ji+1,jj) + vt_s(ji,jj) ) ! snow mass transport, X-component
1256               zdiag_ymtrp_snw(ji,jj) = rhos * zfac_y * ( vt_s(ji,jj+1) + vt_s(ji,jj) ) !          ''          Y-   ''
1257
1258               zdiag_xatrp(ji,jj)     = zfac_x * ( at_i(ji+1,jj) + at_i(ji,jj) )        ! area transport,      X-component
1259               zdiag_yatrp(ji,jj)     = zfac_y * ( at_i(ji,jj+1) + at_i(ji,jj) )        !        ''            Y-   ''
1260
1261         END_2D
1262         
1263         CALL lbc_lnk( 'icedyn_rhg_vp', zdiag_xmtrp_ice, 'U', -1., zdiag_ymtrp_ice, 'V', -1., &
1264            &                           zdiag_xmtrp_snw, 'U', -1., zdiag_ymtrp_snw, 'V', -1., &
1265            &                           zdiag_xatrp    , 'U', -1., zdiag_yatrp    , 'V', -1. )
1266
1267         CALL iom_put( 'xmtrpice' , zdiag_xmtrp_ice )   ! X-component of sea-ice mass transport (kg/s)
1268         CALL iom_put( 'ymtrpice' , zdiag_ymtrp_ice )   ! Y-component of sea-ice mass transport
1269         CALL iom_put( 'xmtrpsnw' , zdiag_xmtrp_snw )   ! X-component of snow mass transport (kg/s)
1270         CALL iom_put( 'ymtrpsnw' , zdiag_ymtrp_snw )   ! Y-component of snow mass transport
1271         CALL iom_put( 'xatrp'    , zdiag_xatrp     )   ! X-component of ice area transport
1272         CALL iom_put( 'yatrp'    , zdiag_yatrp     )   ! Y-component of ice area transport
1273
1274         DEALLOCATE( zdiag_xmtrp_ice , zdiag_ymtrp_ice , &
1275            &        zdiag_xmtrp_snw , zdiag_ymtrp_snw , zdiag_xatrp , zdiag_yatrp )
1276
1277      ENDIF
1278
1279   END SUBROUTINE ice_dyn_rhg_vp
1280   
1281   
1282   SUBROUTINE rhg_cvg_vp( kt, kitout, kitinn, kitinntot, kitoutmax, kitinnmax, kitinntotmax , &
1283                  &       pu, pv, pub, pvb, pub_outer, pvb_outer                     , &
1284                  &       pmt, pat_iu, pat_iv, puerr_max, pverr_max, pglob_area      , &
1285                  &       prhsu, pAU, pBU, pCU, pDU, pEU, pFU                        , &
1286                  &       prhsv, pAV, pBV, pCV, pDV, pEV, pFV                        , &   
1287                  &       pvel_res, pvel_diff                                            )
1288      !!
1289      !!----------------------------------------------------------------------
1290      !!                    ***  ROUTINE rhg_cvg_vp  ***
1291      !!                     
1292      !! ** Purpose :   check convergence of VP ice rheology
1293      !!
1294      !! ** Method  :   create a file ice_cvg.nc containing a few convergence diagnostics
1295      !!                This routine is called every sub-iteration, so it is cpu expensive
1296      !!
1297      !!                Calculates / stores
1298      !!                   - maximum absolute U-V difference (uice_cvg, u_dif, v_dif, m/s)
1299      !!                   - residuals in U, V and UV-mean taken as square-root of area-weighted mean square residual (u_res, v_res, vel_res, N/m2)
1300      !!                   - mean kinetic energy (mke_ice, J/m2)
1301      !!
1302      !! ** Note    :   for the first sub-iteration, uice_cvg is set to 0 (too large otherwise)   
1303      !!
1304      !!----------------------------------------------------------------------
1305      !!
1306      INTEGER ,                 INTENT(in) ::   kt, kitout, kitinn, kitinntot    ! ocean model iterate, outer, inner and total n-iterations
1307      INTEGER ,                 INTENT(in) ::   kitoutmax, kitinnmax             ! max number of outer & inner iterations
1308      INTEGER ,                 INTENT(in) ::   kitinntotmax                     ! max number of total sub-iterations
1309      REAL(wp), DIMENSION(:,:), INTENT(in) ::   pu, pv, pub, pvb                 ! now & sub-iter-before velocities
1310      REAL(wp), DIMENSION(:,:), INTENT(in) ::   pub_outer, pvb_outer             ! velocities @before outer iterations
1311      REAL(wp), DIMENSION(:,:), INTENT(in) ::   pmt, pat_iu, pat_iv              ! mass at T-point, ice concentration at U&V
1312      REAL(wp),                 INTENT(in) ::   puerr_max, pverr_max             ! absolute mean velocity difference
1313      REAL(wp),                 INTENT(in) ::   pglob_area                       ! global ice area
1314      REAL(wp), DIMENSION(:,:), INTENT(in) ::   prhsu, pAU, pBU, pCU, pDU, pEU, pFU ! linear system coefficients
1315      REAL(wp), DIMENSION(:,:), INTENT(in) ::   prhsv, pAV, pBV, pCV, pDV, pEV, pFV
1316      REAL(wp), DIMENSION(:,:), INTENT(inout) ::  pvel_res                       ! velocity residual @last inner iteration
1317      REAL(wp), DIMENSION(:,:), INTENT(inout) ::  pvel_diff                      ! velocity difference @last outer iteration
1318      !!
1319
1320      INTEGER           ::   idtime, istatus, ix_dim, iy_dim
1321      INTEGER           ::   ji, jj          ! dummy loop indices
1322      INTEGER           ::   it_inn_file, it_out_file
1323      REAL(wp)          ::   zu_res_mean, zv_res_mean, zvel_res_mean                  ! mean residuals of the linear system
1324      REAL(wp)          ::   zu_mad, zv_mad, zvel_mad                                 ! mean absolute deviation, sub-iterates
1325      REAL(wp)          ::   zu_mad_outer, zv_mad_outer, zvel_mad_outer               ! mean absolute deviation, outer-iterates
1326      REAL(wp)          ::   zvel_err_max, zmke, zu, zv                               ! local scalars
1327      REAL(wp)          ::   z1_pglob_area                                            ! inverse global ice area
1328
1329      REAL(wp), DIMENSION(jpi,jpj) ::   zu_res, zv_res, zvel2                         ! local arrays
1330      REAL(wp), DIMENSION(jpi,jpj) ::   zu_diff, zv_diff                              ! local arrays
1331                                                                             
1332      CHARACTER(len=20) ::   clname
1333      !!----------------------------------------------------------------------
1334
1335
1336      IF( lwp ) THEN
1337
1338         WRITE(numout,*)
1339         WRITE(numout,*) 'rhg_cvg_vp : ice rheology convergence control'
1340         WRITE(numout,*) '~~~~~~~~~~~'
1341         WRITE(numout,*) ' kt          =  : ', kt
1342         WRITE(numout,*) ' kitout      =  : ', kitout
1343         WRITE(numout,*) ' kitinn      =  : ', kitinn
1344         WRITE(numout,*) ' kitinntot   =  : ', kitinntot
1345         WRITE(numout,*) ' kitoutmax (nn_vp_nout) =  ', kitoutmax
1346         WRITE(numout,*) ' kitinnmax (nn_vp_ninn) =  ', kitinnmax
1347         WRITE(numout,*) ' kitinntotmax (nn_nvp)  =  ', kitinntotmax
1348         WRITE(numout,*)
1349
1350      ENDIF
1351
1352      z1_pglob_area = 1._wp / pglob_area      ! inverse global ice area
1353
1354      ! create file
1355      IF( kt == nit000 .AND. kitinntot == 1 ) THEN
1356         !
1357         IF( lwm ) THEN
1358
1359            clname = 'ice_cvg.nc'
1360            IF( .NOT. Agrif_Root() )   clname = TRIM(Agrif_CFixed())//"_"//TRIM(clname)
1361            istatus = NF90_CREATE( TRIM(clname), NF90_CLOBBER, ncvgid )
1362
1363            istatus = NF90_DEF_DIM( ncvgid, 'time'  , NF90_UNLIMITED, idtime )
1364            istatus = NF90_DEF_DIM( ncvgid, 'x'     , jpi, ix_dim )
1365            istatus = NF90_DEF_DIM( ncvgid, 'y'     , jpj, iy_dim )
1366
1367            istatus = NF90_DEF_VAR( ncvgid, 'u_res'         , NF90_DOUBLE  , (/ idtime /), nvarid_ures )
1368            istatus = NF90_DEF_VAR( ncvgid, 'v_res'         , NF90_DOUBLE  , (/ idtime /), nvarid_vres )
1369            istatus = NF90_DEF_VAR( ncvgid, 'vel_res'       , NF90_DOUBLE  , (/ idtime /), nvarid_velres )
1370
1371            istatus = NF90_DEF_VAR( ncvgid, 'uerr_max_sub'  , NF90_DOUBLE  , (/ idtime /), nvarid_uerr_max )
1372            istatus = NF90_DEF_VAR( ncvgid, 'verr_max_sub'  , NF90_DOUBLE  , (/ idtime /), nvarid_verr_max )
1373            istatus = NF90_DEF_VAR( ncvgid, 'velerr_max_sub', NF90_DOUBLE  , (/ idtime /), nvarid_velerr_max )
1374
1375            istatus = NF90_DEF_VAR( ncvgid, 'umad_sub'      , NF90_DOUBLE  , (/ idtime /), nvarid_umad )
1376            istatus = NF90_DEF_VAR( ncvgid, 'vmad_sub'      , NF90_DOUBLE  , (/ idtime /), nvarid_vmad )
1377            istatus = NF90_DEF_VAR( ncvgid, 'velmad_sub'    , NF90_DOUBLE  , (/ idtime /), nvarid_velmad )
1378           
1379            istatus = NF90_DEF_VAR( ncvgid, 'umad_outer'    , NF90_DOUBLE  , (/ idtime /), nvarid_umad_outer   )
1380            istatus = NF90_DEF_VAR( ncvgid, 'vmad_outer'    , NF90_DOUBLE  , (/ idtime /), nvarid_vmad_outer   )
1381            istatus = NF90_DEF_VAR( ncvgid, 'velmad_outer'  , NF90_DOUBLE  , (/ idtime /), nvarid_velmad_outer )
1382
1383            istatus = NF90_DEF_VAR( ncvgid, 'mke_ice', NF90_DOUBLE  , (/ idtime /), nvarid_mke )
1384
1385            istatus = NF90_ENDDEF(ncvgid)
1386
1387         ENDIF
1388         !
1389      ENDIF
1390
1391      !------------------------------------------------------------
1392      !
1393      ! Max absolute velocity difference with previous sub-iterate
1394      ! ( zvel_err_max )
1395      !
1396      !------------------------------------------------------------
1397      !
1398      ! This comes from the criterion used to stop the iterative procedure
1399      zvel_err_max   = 0.5_wp * ( puerr_max + pverr_max ) ! average of U- and V- maximum error over the whole domain
1400
1401      !----------------------------------------------
1402      !
1403      ! Mean-absolute-deviation (sub-iterates)
1404      ! ( zu_mad, zv_mad, zvel_mad)
1405      !
1406      !----------------------------------------------
1407      !
1408      ! U
1409      zu_diff(:,:) = 0._wp
1410     
1411      DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1412     
1413         zu_diff(ji,jj) = ABS ( ( pu(ji,jj) - pub(ji,jj) ) ) * e1e2u(ji,jj) * pat_iu(ji,jj) * umask(ji,jj,1) * z1_pglob_area
1414     
1415      END_2D
1416     
1417      ! V
1418      zv_diff(:,:)   = 0._wp
1419     
1420      DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1421     
1422         zv_diff(ji,jj) = ABS ( ( pv(ji,jj) - pvb(ji,jj) ) ) * e1e2v(ji,jj) * pat_iv(ji,jj) * vmask(ji,jj,1) * z1_pglob_area
1423     
1424      END_2D
1425
1426      ! global sum & U-V average
1427      CALL lbc_lnk( 'icedyn_rhg_cvg_vp', zu_diff,  'U',  1., zv_diff , 'V',  1. )
1428      zu_mad   = glob_sum( 'icedyn_rhg_vp : ', zu_diff )
1429      zv_mad   = glob_sum( 'icedyn_rhg_vp : ', zv_diff )
1430
1431      zvel_mad = 0.5_wp * ( zu_mad + zv_mad )
1432
1433      !-----------------------------------------------
1434      !
1435      ! Mean-absolute-deviation (outer-iterates)
1436      ! ( zu_mad_outer, zv_mad_outer, zvel_mad_outer)
1437      !
1438      !-----------------------------------------------
1439      !
1440      IF ( kitinn == kitinnmax ) THEN ! only work at the end of outer iterates
1441
1442         ! * U
1443         zu_diff(:,:) = 0._wp
1444         
1445         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1446         
1447            zu_diff(ji,jj) = ABS ( ( pu(ji,jj) - pub_outer(ji,jj) ) ) * e1e2u(ji,jj) * pat_iu(ji,jj) * umask(ji,jj,1) * &
1448                              &    z1_pglob_area
1449                             
1450         END_2D
1451         
1452         ! * V
1453         zv_diff(:,:)   = 0._wp
1454         
1455         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1456         
1457            zv_diff(ji,jj) = ABS ( ( pv(ji,jj) - pvb_outer(ji,jj) ) ) * e1e2v(ji,jj) * pat_iv(ji,jj) * vmask(ji,jj,1) * &
1458                              &    z1_pglob_area
1459         
1460         END_2D
1461         
1462         ! Global ice-concentration, grid-cell-area weighted mean
1463         CALL lbc_lnk( 'icedyn_rhg_cvg_vp', zu_diff,  'U',  1., zv_diff , 'V',  1. ) ! abs behaves as a scalar no ?
1464
1465         zu_mad_outer   = glob_sum( 'icedyn_rhg_vp : ', zu_diff )
1466         zv_mad_outer   = glob_sum( 'icedyn_rhg_vp : ', zv_diff )
1467   
1468         ! Average of both U & V
1469         zvel_mad_outer = 0.5_wp * ( zu_mad_outer + zv_mad_outer )
1470                 
1471      ENDIF
1472
1473      ! --- Spatially-resolved absolute difference to send back to main routine
1474      ! (last iteration only, T-point)
1475
1476      IF ( kitinntot == kitinntotmax) THEN
1477
1478         zu_diff(:,:) = 0._wp
1479         zv_diff(:,:) = 0._wp
1480
1481         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1482
1483               zu_diff(ji,jj) = ( ABS ( ( pu(ji-1,jj) - pub_outer(ji-1,jj) ) ) * umask(ji-1,jj,1) &
1484    &                           + ABS ( ( pu(ji,jj  ) - pub_outer(ji,jj)   ) ) * umask(ji,jj,1) ) &
1485    &                           / ( umask(ji-1,jj,1) + umask(ji,jj,1) )
1486
1487               zv_diff(ji,jj) = ( ABS ( ( pv(ji,jj-1)   - pvb_outer(ji,jj-1) ) ) * vmask(ji,jj-1,1) &
1488    &                           + ABS ( ( pv(ji,jj  ) - pvb_outer(ji,jj)     ) ) * vmask(ji,jj,1)   &
1489    &                           / ( vmask(ji,jj-1,1) + vmask(ji,jj,1) ) )
1490     
1491   
1492         END_2D
1493         
1494         CALL lbc_lnk( 'icedyn_rhg_cvg_vp', zu_diff,  'T',  1., zv_diff , 'T',  1. )
1495         pvel_diff(:,:) = 0.5_wp * ( zu_diff(:,:) + zv_diff(:,:) )
1496
1497      ELSE
1498
1499         pvel_diff(:,:) = 0._wp
1500
1501      ENDIF
1502
1503      !---------------------------------------
1504      !
1505      ! ---  Mean residual & kinetic energy
1506      !
1507      !---------------------------------------
1508
1509      IF ( kitinntot == 1 ) THEN
1510
1511         zu_res_mean   = 0._wp
1512         zv_res_mean   = 0._wp
1513         zvel_res_mean = 0._wp
1514         zmke          = 0._wp
1515
1516      ELSE
1517
1518         ! * Mean residual (N/m2)
1519         ! Here we take the residual of the linear system (N/m2),
1520         ! We define it as in mitgcm: global area-weighted mean of square-root residual
1521         ! Local residual r = Ax - B expresses to which extent the momentum balance is verified
1522         ! i.e., how close we are to a solution
1523         zu_res(:,:) = 0._wp; zv_res(:,:) = 0._wp
1524         
1525         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1526
1527               zu_res(ji,jj)  = ( prhsu(ji,jj) + pDU(ji,jj) * pu(ji,jj-1) + pEU(ji,jj) * pu(ji,jj+1)               &
1528                  &             - pAU(ji,jj) * pu(ji-1,jj) - pBU(ji,jj) * pu(ji,jj) - pCU(ji,jj) * pu(ji+1,jj) )
1529               zv_res(ji,jj)  = ( prhsv(ji,jj) + pDV(ji,jj) * pv(ji-1,jj) + pEV(ji,jj) * pv(ji+1,jj)               &
1530                  &             - pAV(ji,jj) * pv(ji,jj-1) - pBV(ji,jj) * pv(ji,jj) - pCV(ji,jj) * pv(ji,jj+1) )
1531
1532!              zu_res(ji,jj)  = pFU(ji,jj) - pAU(ji,jj) * pu(ji-1,jj) - pBU(ji,jj) * pu(ji,jj) - pCU(ji,jj) * pu(ji+1,jj)
1533!              zv_res(ji,jj)  = pFV(ji,jj) - pAV(ji,jj) * pv(ji,jj-1) - pBV(ji,jj) * pv(ji,jj) - pCV(ji,jj) * pv(ji,jj+1)
1534   
1535               zu_res(ji,jj)  = SQRT( zu_res(ji,jj) * zu_res(ji,jj) ) * umask(ji,jj,1) * pat_iu(ji,jj) * e1e2u(ji,jj) * z1_pglob_area
1536               zv_res(ji,jj)  = SQRT( zv_res(ji,jj) * zv_res(ji,jj) ) * vmask(ji,jj,1) * pat_iv(ji,jj) * e1e2v(ji,jj) * z1_pglob_area
1537   
1538         END_2D
1539         
1540         ! Global ice-concentration, grid-cell-area weighted mean
1541         CALL lbc_lnk( 'icedyn_rhg_cvg_vp', zu_res,  'U', 1., zv_res , 'V', 1. )
1542   
1543         zu_res_mean   = glob_sum( 'ice_rhg_vp', zu_res(:,:) )
1544         zv_res_mean   = glob_sum( 'ice_rhg_vp', zv_res(:,:) )
1545         zvel_res_mean = 0.5_wp * ( zu_res_mean + zv_res_mean )
1546   
1547         ! --- Global mean kinetic energy per unit area (J/m2)
1548         zvel2(:,:) = 0._wp
1549
1550         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1551                 
1552               zu     = 0.5_wp * ( pu(ji-1,jj) + pu(ji,jj) ) ! u-vel at T-point
1553               zv     = 0.5_wp * ( pv(ji,jj-1) + pv(ji,jj) )
1554               zvel2(ji,jj)  = zu*zu + zv*zv              ! square of ice velocity at T-point 
1555
1556         END_2D
1557                   
1558         zmke = 0.5_wp * glob_sum( 'ice_rhg_vp', pmt(:,:) * e1e2t(:,:) * zvel2(:,:) ) / pglob_area
1559   
1560      ENDIF ! kitinntot
1561
1562      !--- Spatially-resolved residual at last iteration to send back to main routine (last iteration only)
1563      !--- Calculation @T-point
1564
1565      IF ( kitinntot == kitinntotmax) THEN
1566
1567         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1568
1569               zu_res(ji,jj)  = ( prhsu(ji,jj) + pDU(ji,jj) * pu(ji,jj-1) + pEU(ji,jj) * pu(ji,jj+1)               &
1570                  &             - pAU(ji,jj) * pu(ji-1,jj) - pBU(ji,jj) * pu(ji,jj) - pCU(ji,jj) * pu(ji+1,jj) )
1571               zv_res(ji,jj)  = ( prhsv(ji,jj) + pDV(ji,jj) * pv(ji-1,jj) + pEV(ji,jj) * pv(ji+1,jj)               &
1572                  &             - pAV(ji,jj) * pv(ji,jj-1) - pBV(ji,jj) * pv(ji,jj) - pCV(ji,jj) * pv(ji,jj+1) )
1573
1574               zu_res(ji,jj)  = SQRT( zu_res(ji,jj) * zu_res(ji,jj) ) * umask(ji,jj,1) 
1575               zv_res(ji,jj)  = SQRT( zv_res(ji,jj) * zv_res(ji,jj) ) * vmask(ji,jj,1) 
1576
1577         END_2D
1578         
1579         CALL lbc_lnk( 'icedyn_rhg_cvg_vp', zu_res,  'U',  1., zv_res , 'V',  1. )
1580
1581         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 ) ! 2->jpj-1; 2->jpi-1
1582         
1583               pvel_res(ji,jj) = 0.25_wp * ( zu_res(ji-1,jj) + zu_res(ji,jj) + zv_res(ji,jj-1) + zv_res(ji,jj) )
1584         
1585         END_2D
1586         CALL lbc_lnk( 'icedyn_rhg_cvg_vp', pvel_res, 'T', 1. )
1587
1588      ELSE
1589
1590         pvel_res(:,:) = 0._wp
1591
1592      ENDIF
1593                 
1594      !                                                ! ==================== !
1595
1596      it_inn_file =  ( kt - nit000 ) * kitinntotmax + kitinntot ! time step in the file
1597      it_out_file =  ( kt - nit000 ) * kitoutmax    + kitout
1598
1599      ! write variables
1600      IF( lwm ) THEN
1601
1602         istatus = NF90_PUT_VAR( ncvgid, nvarid_ures  , (/zu_res_mean/), (/it_inn_file/), (/1/) )        ! Residuals of the linear system, area weighted mean
1603         istatus = NF90_PUT_VAR( ncvgid, nvarid_vres  , (/zv_res_mean/), (/it_inn_file/), (/1/) )        !
1604         istatus = NF90_PUT_VAR( ncvgid, nvarid_velres, (/zvel_res_mean/), (/it_inn_file/), (/1/) )      !
1605
1606         istatus = NF90_PUT_VAR( ncvgid, nvarid_uerr_max  , (/puerr_max/), (/it_inn_file/), (/1/) )      ! Max velocit_inn_filey error, sub-it_inn_fileerates
1607         istatus = NF90_PUT_VAR( ncvgid, nvarid_verr_max  , (/pverr_max/), (/it_inn_file/), (/1/) )      !
1608         istatus = NF90_PUT_VAR( ncvgid, nvarid_velerr_max, (/zvel_err_max/), (/it_inn_file/), (/1/) )   !
1609
1610         istatus = NF90_PUT_VAR( ncvgid, nvarid_umad    , (/zu_mad/)  , (/it_inn_file/), (/1/) )         ! velocit_inn_filey MAD, area/sic-weighted, sub-it_inn_fileerates
1611         istatus = NF90_PUT_VAR( ncvgid, nvarid_vmad    , (/zv_mad/)  , (/it_inn_file/), (/1/) )         !
1612         istatus = NF90_PUT_VAR( ncvgid, nvarid_velmad  , (/zvel_mad/), (/it_inn_file/), (/1/) )         !
1613
1614         istatus = NF90_PUT_VAR( ncvgid, nvarid_mke, (/zmke/), (/kitinntot/), (/1/) )                    ! mean kinetic energy
1615
1616         IF ( kitinn == kitinnmax ) THEN ! only print outer mad at the end of inner loop
1617
1618            istatus = NF90_PUT_VAR( ncvgid, nvarid_umad_outer    , (/zu_mad_outer/)  , (/it_out_file/), (/1/) )   ! velocity MAD, area/sic-weighted, outer-iterates
1619            istatus = NF90_PUT_VAR( ncvgid, nvarid_vmad_outer    , (/zv_mad_outer/)  , (/it_out_file/), (/1/) )   !
1620            istatus = NF90_PUT_VAR( ncvgid, nvarid_velmad_outer  , (/zvel_mad_outer/), (/it_out_file/), (/1/) )   !
1621
1622         ENDIF
1623
1624         IF( kt == nitend - nn_fsbc + 1 .AND. kitinntot == kitinntotmax )    istatus = NF90_CLOSE( ncvgid )
1625      ENDIF
1626     
1627   END SUBROUTINE rhg_cvg_vp
1628   
1629
1630   
1631#else
1632   !!----------------------------------------------------------------------
1633   !!   Default option         Empty module           NO SI3 sea-ice model
1634   !!----------------------------------------------------------------------
1635#endif
1636
1637   !!==============================================================================
1638END MODULE icedyn_rhg_vp
1639
Note: See TracBrowser for help on using the repository browser.