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_adv_pra.F90 in NEMO/branches/2019/dev_r11842_SI3-10_EAP/src/ICE – NEMO

source: NEMO/branches/2019/dev_r11842_SI3-10_EAP/src/ICE/icedyn_adv_pra.F90 @ 13662

Last change on this file since 13662 was 13662, checked in by clem, 4 years ago

update to almost r4.0.4

  • Property svn:keywords set to Id
File size: 71.0 KB
Line 
1MODULE icedyn_adv_pra 
2   !!======================================================================
3   !!                       ***  MODULE icedyn_adv_pra   ***
4   !!   sea-ice : advection => Prather scheme
5   !!======================================================================
6   !! History :       !  2008-03  (M. Vancoppenolle) original code
7   !!            4.0  !  2018     (many people)      SI3 [aka Sea Ice cube]
8   !!--------------------------------------------------------------------
9#if defined key_si3
10   !!----------------------------------------------------------------------
11   !!   'key_si3'                                       SI3 sea-ice model
12   !!----------------------------------------------------------------------
13   !!   ice_dyn_adv_pra : advection of sea ice using Prather scheme
14   !!   adv_x, adv_y    : Prather scheme applied in i- and j-direction, resp.
15   !!   adv_pra_init    : initialisation of the Prather scheme
16   !!   adv_pra_rst     : read/write Prather field in ice restart file, or initialized to zero
17   !!----------------------------------------------------------------------
18   USE phycst         ! physical constant
19   USE dom_oce        ! ocean domain
20   USE ice            ! sea-ice variables
21   USE sbc_oce , ONLY : nn_fsbc   ! frequency of sea-ice call
22   USE icevar         ! sea-ice: operations
23   !
24   USE in_out_manager ! I/O manager
25   USE iom            ! I/O manager library
26   USE lib_mpp        ! MPP library
27   USE lib_fortran    ! fortran utilities (glob_sum + no signed zero)
28   USE lbclnk         ! lateral boundary conditions (or mpp links)
29
30   IMPLICIT NONE
31   PRIVATE
32
33   PUBLIC   ice_dyn_adv_pra   ! called by icedyn_adv
34   PUBLIC   adv_pra_init      ! called by icedyn_adv
35
36   ! Moments for advection
37   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxice, syice, sxxice, syyice, sxyice   ! ice thickness
38   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxsn , sysn , sxxsn , syysn , sxysn    ! snow thickness
39   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxa  , sya  , sxxa  , syya  , sxya     ! ice concentration
40   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxsal, sysal, sxxsal, syysal, sxysal   ! ice salinity
41   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxage, syage, sxxage, syyage, sxyage   ! ice age
42   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:,:) ::   sxc0 , syc0 , sxxc0 , syyc0 , sxyc0    ! snow layers heat content
43   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:,:) ::   sxe  , sye  , sxxe  , syye  , sxye     ! ice layers heat content
44   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxap , syap , sxxap , syyap , sxyap    ! melt pond fraction
45   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxvp , syvp , sxxvp , syyvp , sxyvp    ! melt pond volume
46   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:)   ::   sxvl , syvl , sxxvl , syyvl , sxyvl    ! melt pond lid volume
47
48   !! * Substitutions
49#  include "vectopt_loop_substitute.h90"
50   !!----------------------------------------------------------------------
51   !! NEMO/ICE 4.0 , NEMO Consortium (2018)
52   !! $Id$
53   !! Software governed by the CeCILL license (see ./LICENSE)
54   !!----------------------------------------------------------------------
55CONTAINS
56
57   SUBROUTINE ice_dyn_adv_pra(         kt, pu_ice, pv_ice, ph_i, ph_s, ph_ip,  &
58      &                        pato_i, pv_i, pv_s, psv_i, poa_i, pa_i, pa_ip, pv_ip, pv_il, pe_s, pe_i )
59      !!----------------------------------------------------------------------
60      !!                **  routine ice_dyn_adv_pra  **
61      !! 
62      !! ** purpose :   Computes and adds the advection trend to sea-ice
63      !!
64      !! ** method  :   Uses Prather second order scheme that advects tracers
65      !!                but also their quadratic forms. The method preserves
66      !!                tracer structures by conserving second order moments.
67      !!
68      !! Reference:  Prather, 1986, JGR, 91, D6. 6671-6681.
69      !!----------------------------------------------------------------------
70      INTEGER                     , INTENT(in   ) ::   kt         ! time step
71      REAL(wp), DIMENSION(:,:)    , INTENT(in   ) ::   pu_ice     ! ice i-velocity
72      REAL(wp), DIMENSION(:,:)    , INTENT(in   ) ::   pv_ice     ! ice j-velocity
73      REAL(wp), DIMENSION(:,:,:)  , INTENT(in   ) ::   ph_i       ! ice thickness
74      REAL(wp), DIMENSION(:,:,:)  , INTENT(in   ) ::   ph_s       ! snw thickness
75      REAL(wp), DIMENSION(:,:,:)  , INTENT(in   ) ::   ph_ip      ! ice pond thickness
76      REAL(wp), DIMENSION(:,:)    , INTENT(inout) ::   pato_i     ! open water area
77      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pv_i       ! ice volume
78      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pv_s       ! snw volume
79      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   psv_i      ! salt content
80      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   poa_i      ! age content
81      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pa_i       ! ice concentration
82      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pa_ip      ! melt pond fraction
83      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pv_ip      ! melt pond volume
84      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pv_il      ! melt pond lid thickness
85      REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) ::   pe_s       ! snw heat content
86      REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) ::   pe_i       ! ice heat content
87      !
88      INTEGER  ::   ji, jj, jk, jl, jt      ! dummy loop indices
89      INTEGER  ::   icycle                  ! number of sub-timestep for the advection
90      REAL(wp) ::   zdt, z1_dt              !   -      -
91      REAL(wp), DIMENSION(1)                  ::   zcflprv, zcflnow   ! for global communication
92      REAL(wp), DIMENSION(jpi,jpj)            ::   zati1, zati2
93      REAL(wp), DIMENSION(jpi,jpj)            ::   zudy, zvdx
94      REAL(wp), DIMENSION(jpi,jpj,jpl)        ::   zhi_max, zhs_max, zhip_max, zs_i, zsi_max
95      REAL(wp), DIMENSION(jpi,jpj,nlay_i,jpl) ::   ze_i, zei_max
96      REAL(wp), DIMENSION(jpi,jpj,nlay_s,jpl) ::   ze_s, zes_max
97      REAL(wp), DIMENSION(jpi,jpj,jpl)        ::   zarea
98      REAL(wp), DIMENSION(jpi,jpj,jpl)        ::   z0ice, z0snw, z0ai, z0smi, z0oi
99      REAL(wp), DIMENSION(jpi,jpj,jpl)        ::   z0ap , z0vp, z0vl
100      REAL(wp), DIMENSION(jpi,jpj,nlay_s,jpl) ::   z0es
101      REAL(wp), DIMENSION(jpi,jpj,nlay_i,jpl) ::   z0ei
102      !! diagnostics
103      REAL(wp), DIMENSION(jpi,jpj)            ::   zdiag_adv_mass, zdiag_adv_salt, zdiag_adv_heat     
104      !!----------------------------------------------------------------------
105      !
106      IF( kt == nit000 .AND. lwp )   WRITE(numout,*) '-- ice_dyn_adv_pra: Prather advection scheme'
107      !
108      ! --- Record max of the surrounding 9-pts (for call Hbig) --- !
109      ! thickness and salinity
110      WHERE( pv_i(:,:,:) >= epsi10 ) ; zs_i(:,:,:) = psv_i(:,:,:) / pv_i(:,:,:)
111      ELSEWHERE                      ; zs_i(:,:,:) = 0._wp
112      END WHERE
113      CALL icemax3D( ph_i , zhi_max )
114      CALL icemax3D( ph_s , zhs_max )
115      CALL icemax3D( ph_ip, zhip_max)
116      CALL icemax3D( zs_i , zsi_max )
117      CALL lbc_lnk_multi( 'icedyn_adv_pra', zhi_max, 'T', 1., zhs_max, 'T', 1., zhip_max, 'T', 1., zsi_max, 'T', 1. )
118
119      ! enthalpies
120      DO jk = 1, nlay_i
121         WHERE( pv_i(:,:,:) >= epsi10 ) ; ze_i(:,:,jk,:) = pe_i(:,:,jk,:) / pv_i(:,:,:)
122         ELSEWHERE                      ; ze_i(:,:,jk,:) = 0._wp
123         END WHERE
124      END DO
125      DO jk = 1, nlay_s
126         WHERE( pv_s(:,:,:) >= epsi10 ) ; ze_s(:,:,jk,:) = pe_s(:,:,jk,:) / pv_s(:,:,:)
127         ELSEWHERE                      ; ze_s(:,:,jk,:) = 0._wp
128         END WHERE
129      END DO   
130      CALL icemax4D( ze_i , zei_max )
131      CALL icemax4D( ze_s , zes_max )
132      CALL lbc_lnk( 'icedyn_adv_pra', zei_max, 'T', 1. )
133      CALL lbc_lnk( 'icedyn_adv_pra', zes_max, 'T', 1. )
134      !
135      !
136      ! --- If ice drift is too fast, use  subtime steps for advection (CFL test for stability) --- !
137      !        Note: the advection split is applied at the next time-step in order to avoid blocking global comm.
138      !              this should not affect too much the stability
139      zcflnow(1) =                  MAXVAL( ABS( pu_ice(:,:) ) * rdt_ice * r1_e1u(:,:) )
140      zcflnow(1) = MAX( zcflnow(1), MAXVAL( ABS( pv_ice(:,:) ) * rdt_ice * r1_e2v(:,:) ) )
141     
142      ! non-blocking global communication send zcflnow and receive zcflprv
143      CALL mpp_delay_max( 'icedyn_adv_pra', 'cflice', zcflnow(:), zcflprv(:), kt == nitend - nn_fsbc + 1 )
144
145      IF( zcflprv(1) > .5 ) THEN   ;   icycle = 2
146      ELSE                         ;   icycle = 1
147      ENDIF
148      zdt = rdt_ice / REAL(icycle)
149      z1_dt = 1._wp / zdt
150     
151      ! --- transport --- !
152      zudy(:,:) = pu_ice(:,:) * e2u(:,:)
153      zvdx(:,:) = pv_ice(:,:) * e1v(:,:)
154
155      DO jt = 1, icycle
156
157         ! diagnostics
158         zdiag_adv_mass(:,:) =   SUM(  pv_i(:,:,:) , dim=3 ) * rhoi + SUM(  pv_s(:,:,:) , dim=3 ) * rhos
159         zdiag_adv_salt(:,:) =   SUM( psv_i(:,:,:) , dim=3 ) * rhoi
160         zdiag_adv_heat(:,:) = - SUM(SUM( pe_i(:,:,1:nlay_i,:) , dim=4 ), dim=3 ) &
161            &                  - SUM(SUM( pe_s(:,:,1:nlay_s,:) , dim=4 ), dim=3 )
162
163         ! record at_i before advection (for open water)
164         zati1(:,:) = SUM( pa_i(:,:,:), dim=3 )
165         
166         ! --- transported fields --- !                                       
167         DO jl = 1, jpl
168            zarea(:,:,jl) = e1e2t(:,:)
169            z0snw(:,:,jl) = pv_s (:,:,jl) * e1e2t(:,:)        ! Snow volume
170            z0ice(:,:,jl) = pv_i (:,:,jl) * e1e2t(:,:)        ! Ice  volume
171            z0ai (:,:,jl) = pa_i (:,:,jl) * e1e2t(:,:)        ! Ice area
172            z0smi(:,:,jl) = psv_i(:,:,jl) * e1e2t(:,:)        ! Salt content
173            z0oi (:,:,jl) = poa_i(:,:,jl) * e1e2t(:,:)        ! Age content
174            DO jk = 1, nlay_s
175               z0es(:,:,jk,jl) = pe_s(:,:,jk,jl) * e1e2t(:,:) ! Snow heat content
176            END DO
177            DO jk = 1, nlay_i
178               z0ei(:,:,jk,jl) = pe_i(:,:,jk,jl) * e1e2t(:,:) ! Ice  heat content
179            END DO
180            IF ( ln_pnd_LEV ) THEN
181               z0ap(:,:,jl) = pa_ip(:,:,jl) * e1e2t(:,:)      ! Melt pond fraction
182               z0vp(:,:,jl) = pv_ip(:,:,jl) * e1e2t(:,:)      ! Melt pond volume
183               IF ( ln_pnd_lids ) THEN
184                  z0vl(:,:,jl) = pv_il(:,:,jl) * e1e2t(:,:)   ! Melt pond lid volume
185               ENDIF
186            ENDIF
187         END DO
188         !
189         !                                                                  !--------------------------------------------!
190         IF( MOD( (kt - 1) / nn_fsbc , 2 ) ==  MOD( (jt - 1) , 2 ) ) THEN   !==  odd ice time step:  adv_x then adv_y  ==!
191            !                                                               !--------------------------------------------!
192            CALL adv_x( zdt , zudy , 1._wp , zarea , z0ice , sxice , sxxice , syice , syyice , sxyice ) !--- ice volume
193            CALL adv_y( zdt , zvdx , 0._wp , zarea , z0ice , sxice , sxxice , syice , syyice , sxyice )
194            CALL adv_x( zdt , zudy , 1._wp , zarea , z0snw , sxsn  , sxxsn  , sysn  , syysn  , sxysn  ) !--- snow volume
195            CALL adv_y( zdt , zvdx , 0._wp , zarea , z0snw , sxsn  , sxxsn  , sysn  , syysn  , sxysn  )
196            CALL adv_x( zdt , zudy , 1._wp , zarea , z0smi , sxsal , sxxsal , sysal , syysal , sxysal ) !--- ice salinity
197            CALL adv_y( zdt , zvdx , 0._wp , zarea , z0smi , sxsal , sxxsal , sysal , syysal , sxysal )
198            CALL adv_x( zdt , zudy , 1._wp , zarea , z0ai  , sxa   , sxxa   , sya   , syya   , sxya   ) !--- ice concentration
199            CALL adv_y( zdt , zvdx , 0._wp , zarea , z0ai  , sxa   , sxxa   , sya   , syya   , sxya   )
200            CALL adv_x( zdt , zudy , 1._wp , zarea , z0oi  , sxage , sxxage , syage , syyage , sxyage ) !--- ice age
201            CALL adv_y( zdt , zvdx , 0._wp , zarea , z0oi  , sxage , sxxage , syage , syyage , sxyage )
202            !
203            DO jk = 1, nlay_s                                                                           !--- snow heat content
204               CALL adv_x( zdt, zudy, 1._wp, zarea, z0es (:,:,jk,:), sxc0(:,:,jk,:),   &
205                  &                                 sxxc0(:,:,jk,:), syc0(:,:,jk,:), syyc0(:,:,jk,:), sxyc0(:,:,jk,:) )
206               CALL adv_y( zdt, zvdx, 0._wp, zarea, z0es (:,:,jk,:), sxc0(:,:,jk,:),   &
207                  &                                 sxxc0(:,:,jk,:), syc0(:,:,jk,:), syyc0(:,:,jk,:), sxyc0(:,:,jk,:) )
208            END DO
209            DO jk = 1, nlay_i                                                                           !--- ice heat content
210               CALL adv_x( zdt, zudy, 1._wp, zarea, z0ei(:,:,jk,:), sxe(:,:,jk,:),   & 
211                  &                                 sxxe(:,:,jk,:), sye(:,:,jk,:), syye(:,:,jk,:), sxye(:,:,jk,:) )
212               CALL adv_y( zdt, zvdx, 0._wp, zarea, z0ei(:,:,jk,:), sxe(:,:,jk,:),   & 
213                  &                                 sxxe(:,:,jk,:), sye(:,:,jk,:), syye(:,:,jk,:), sxye(:,:,jk,:) )
214            END DO
215            !
216            IF ( ln_pnd_LEV ) THEN
217               CALL adv_x( zdt , zudy , 1._wp , zarea , z0ap , sxap , sxxap , syap , syyap , sxyap )    !--- melt pond fraction
218               CALL adv_y( zdt , zvdx , 0._wp , zarea , z0ap , sxap , sxxap , syap , syyap , sxyap ) 
219               CALL adv_x( zdt , zudy , 1._wp , zarea , z0vp , sxvp , sxxvp , syvp , syyvp , sxyvp )    !--- melt pond volume
220               CALL adv_y( zdt , zvdx , 0._wp , zarea , z0vp , sxvp , sxxvp , syvp , syyvp , sxyvp ) 
221               IF ( ln_pnd_lids ) THEN
222                  CALL adv_x( zdt , zudy , 1._wp , zarea , z0vl , sxvl , sxxvl , syvl , syyvl , sxyvl ) !--- melt pond lid volume
223                  CALL adv_y( zdt , zvdx , 0._wp , zarea , z0vl , sxvl , sxxvl , syvl , syyvl , sxyvl ) 
224               ENDIF
225            ENDIF
226            !                                                               !--------------------------------------------!
227         ELSE                                                               !== even ice time step:  adv_y then adv_x  ==!
228            !                                                               !--------------------------------------------!
229            CALL adv_y( zdt , zvdx , 1._wp , zarea , z0ice , sxice , sxxice , syice , syyice , sxyice ) !--- ice volume
230            CALL adv_x( zdt , zudy , 0._wp , zarea , z0ice , sxice , sxxice , syice , syyice , sxyice )
231            CALL adv_y( zdt , zvdx , 1._wp , zarea , z0snw , sxsn  , sxxsn  , sysn  , syysn  , sxysn  ) !--- snow volume
232            CALL adv_x( zdt , zudy , 0._wp , zarea , z0snw , sxsn  , sxxsn  , sysn  , syysn  , sxysn  )
233            CALL adv_y( zdt , zvdx , 1._wp , zarea , z0smi , sxsal , sxxsal , sysal , syysal , sxysal ) !--- ice salinity
234            CALL adv_x( zdt , zudy , 0._wp , zarea , z0smi , sxsal , sxxsal , sysal , syysal , sxysal )
235            CALL adv_y( zdt , zvdx , 1._wp , zarea , z0ai  , sxa   , sxxa   , sya   , syya   , sxya   ) !--- ice concentration
236            CALL adv_x( zdt , zudy , 0._wp , zarea , z0ai  , sxa   , sxxa   , sya   , syya   , sxya   )
237            CALL adv_y( zdt , zvdx , 1._wp , zarea , z0oi  , sxage , sxxage , syage , syyage , sxyage ) !--- ice age
238            CALL adv_x( zdt , zudy , 0._wp , zarea , z0oi  , sxage , sxxage , syage , syyage , sxyage )
239            DO jk = 1, nlay_s                                                                           !--- snow heat content
240               CALL adv_y( zdt, zvdx, 1._wp, zarea, z0es (:,:,jk,:), sxc0(:,:,jk,:),   &
241                  &                                 sxxc0(:,:,jk,:), syc0(:,:,jk,:), syyc0(:,:,jk,:), sxyc0(:,:,jk,:) )
242               CALL adv_x( zdt, zudy, 0._wp, zarea, z0es (:,:,jk,:), sxc0(:,:,jk,:),   &
243                  &                                 sxxc0(:,:,jk,:), syc0(:,:,jk,:), syyc0(:,:,jk,:), sxyc0(:,:,jk,:) )
244            END DO
245            DO jk = 1, nlay_i                                                                           !--- ice heat content
246               CALL adv_y( zdt, zvdx, 1._wp, zarea, z0ei(:,:,jk,:), sxe(:,:,jk,:),   & 
247                  &                                 sxxe(:,:,jk,:), sye(:,:,jk,:), syye(:,:,jk,:), sxye(:,:,jk,:) )
248               CALL adv_x( zdt, zudy, 0._wp, zarea, z0ei(:,:,jk,:), sxe(:,:,jk,:),   & 
249                  &                                 sxxe(:,:,jk,:), sye(:,:,jk,:), syye(:,:,jk,:), sxye(:,:,jk,:) )
250            END DO
251            IF ( ln_pnd_LEV ) THEN
252               CALL adv_y( zdt , zvdx , 1._wp , zarea , z0ap , sxap , sxxap , syap , syyap , sxyap )    !--- melt pond fraction
253               CALL adv_x( zdt , zudy , 0._wp , zarea , z0ap , sxap , sxxap , syap , syyap , sxyap )
254               CALL adv_y( zdt , zvdx , 1._wp , zarea , z0vp , sxvp , sxxvp , syvp , syyvp , sxyvp )    !--- melt pond volume
255               CALL adv_x( zdt , zudy , 0._wp , zarea , z0vp , sxvp , sxxvp , syvp , syyvp , sxyvp )
256               IF ( ln_pnd_lids ) THEN
257                  CALL adv_y( zdt , zvdx , 1._wp , zarea , z0vl , sxvl , sxxvl , syvl , syyvl , sxyvl ) !--- melt pond lid volume
258                  CALL adv_x( zdt , zudy , 0._wp , zarea , z0vl , sxvl , sxxvl , syvl , syyvl , sxyvl ) 
259               ENDIF
260            ENDIF
261            !
262         ENDIF
263       
264         ! --- Lateral boundary conditions --- !
265         !     caution: for gradients (sx and sy) the sign changes
266         CALL lbc_lnk_multi( 'icedyn_adv_pra', z0ice , 'T', 1._wp, sxice , 'T', -1._wp, syice , 'T', -1._wp  & ! ice volume
267            &                                , sxxice, 'T', 1._wp, syyice, 'T',  1._wp, sxyice, 'T',  1._wp  &
268            &                                , z0snw , 'T', 1._wp, sxsn  , 'T', -1._wp, sysn  , 'T', -1._wp  & ! snw volume
269            &                                , sxxsn , 'T', 1._wp, syysn , 'T',  1._wp, sxysn , 'T',  1._wp  )
270         CALL lbc_lnk_multi( 'icedyn_adv_pra', z0smi , 'T', 1._wp, sxsal , 'T', -1._wp, sysal , 'T', -1._wp  & ! ice salinity
271            &                                , sxxsal, 'T', 1._wp, syysal, 'T',  1._wp, sxysal, 'T',  1._wp  &
272            &                                , z0ai  , 'T', 1._wp, sxa   , 'T', -1._wp, sya   , 'T', -1._wp  & ! ice concentration
273            &                                , sxxa  , 'T', 1._wp, syya  , 'T',  1._wp, sxya  , 'T',  1._wp  )
274         CALL lbc_lnk_multi( 'icedyn_adv_pra', z0oi  , 'T', 1._wp, sxage , 'T', -1._wp, syage , 'T', -1._wp  & ! ice age
275            &                                , sxxage, 'T', 1._wp, syyage, 'T',  1._wp, sxyage, 'T',  1._wp  )
276         CALL lbc_lnk_multi( 'icedyn_adv_pra', z0es  , 'T', 1._wp, sxc0  , 'T', -1._wp, syc0  , 'T', -1._wp  & ! snw enthalpy
277            &                                , sxxc0 , 'T', 1._wp, syyc0 , 'T',  1._wp, sxyc0 , 'T',  1._wp  ) 
278         CALL lbc_lnk_multi( 'icedyn_adv_pra', z0ei  , 'T', 1._wp, sxe   , 'T', -1._wp, sye   , 'T', -1._wp  & ! ice enthalpy
279            &                                , sxxe  , 'T', 1._wp, syye  , 'T',  1._wp, sxye  , 'T',  1._wp  )
280         IF ( ln_pnd_LEV ) THEN
281            CALL lbc_lnk_multi( 'icedyn_adv_pra', z0ap , 'T', 1._wp, sxap , 'T', -1._wp, syap , 'T', -1._wp  & ! melt pond fraction
282               &                                , sxxap, 'T', 1._wp, syyap, 'T',  1._wp, sxyap, 'T',  1._wp  &
283               &                                , z0vp , 'T', 1._wp, sxvp , 'T', -1._wp, syvp , 'T', -1._wp  & ! melt pond volume
284               &                                , sxxvp, 'T', 1._wp, syyvp, 'T',  1._wp, sxyvp, 'T',  1._wp  ) 
285            IF ( ln_pnd_lids ) THEN
286               CALL lbc_lnk_multi( 'icedyn_adv_pra', z0vl ,'T', 1._wp, sxvl ,'T', -1._wp, syvl ,'T', -1._wp  & ! melt pond lid volume
287                  &                                , sxxvl,'T', 1._wp, syyvl,'T',  1._wp, sxyvl,'T',  1._wp  ) 
288            ENDIF
289         ENDIF
290         
291         ! --- Recover the properties from their contents --- !
292         DO jl = 1, jpl
293            pv_i (:,:,jl) = z0ice(:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
294            pv_s (:,:,jl) = z0snw(:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
295            psv_i(:,:,jl) = z0smi(:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
296            poa_i(:,:,jl) = z0oi (:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
297            pa_i (:,:,jl) = z0ai (:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
298            DO jk = 1, nlay_s
299               pe_s(:,:,jk,jl) = z0es(:,:,jk,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
300            END DO
301            DO jk = 1, nlay_i
302               pe_i(:,:,jk,jl) = z0ei(:,:,jk,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
303            END DO
304            IF ( ln_pnd_LEV ) THEN
305               pa_ip(:,:,jl) = z0ap(:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
306               pv_ip(:,:,jl) = z0vp(:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
307               IF ( ln_pnd_lids ) THEN
308                  pv_il(:,:,jl) = z0vl(:,:,jl) * r1_e1e2t(:,:) * tmask(:,:,1)
309               ENDIF
310            ENDIF
311         END DO
312         !
313         ! derive open water from ice concentration
314         zati2(:,:) = SUM( pa_i(:,:,:), dim=3 )
315         DO jj = 2, jpjm1
316            DO ji = fs_2, fs_jpim1
317               pato_i(ji,jj) = pato_i(ji,jj) - ( zati2(ji,jj) - zati1(ji,jj) ) &                        !--- open water
318                  &                          - ( zudy(ji,jj) - zudy(ji-1,jj) + zvdx(ji,jj) - zvdx(ji,jj-1) ) * r1_e1e2t(ji,jj) * zdt
319            END DO
320         END DO
321         CALL lbc_lnk( 'icedyn_adv_pra', pato_i, 'T',  1. )
322         !
323         ! --- diagnostics --- !
324         diag_adv_mass(:,:) = diag_adv_mass(:,:) + (   SUM( pv_i(:,:,:) , dim=3 ) * rhoi + SUM( pv_s(:,:,:) , dim=3 ) * rhos &
325            &                                        - zdiag_adv_mass(:,:) ) * z1_dt
326         diag_adv_salt(:,:) = diag_adv_salt(:,:) + (   SUM( psv_i(:,:,:) , dim=3 ) * rhoi &
327            &                                        - zdiag_adv_salt(:,:) ) * z1_dt
328         diag_adv_heat(:,:) = diag_adv_heat(:,:) + ( - SUM(SUM( pe_i(:,:,1:nlay_i,:) , dim=4 ), dim=3 ) &
329            &                                        - SUM(SUM( pe_s(:,:,1:nlay_s,:) , dim=4 ), dim=3 ) &
330            &                                        - zdiag_adv_heat(:,:) ) * z1_dt
331         !
332         ! --- Ensure non-negative fields --- !
333         !     Remove negative values (conservation is ensured)
334         !     (because advected fields are not perfectly bounded and tiny negative values can occur, e.g. -1.e-20)
335         CALL ice_var_zapneg( zdt, pato_i, pv_i, pv_s, psv_i, poa_i, pa_i, pa_ip, pv_ip, pv_il, pe_s, pe_i )
336         !
337         ! --- Make sure ice thickness is not too big --- !
338         !     (because ice thickness can be too large where ice concentration is very small)
339         CALL Hbig( zdt, zhi_max, zhs_max, zhip_max, zsi_max, zes_max, zei_max, &
340            &            pv_i, pv_s, pa_i, pa_ip, pv_ip, psv_i, pe_s, pe_i )
341         !
342         ! --- Ensure snow load is not too big --- !
343         CALL Hsnow( zdt, pv_i, pv_s, pa_i, pa_ip, pe_s )
344         !
345      END DO
346      !
347      IF( lrst_ice )   CALL adv_pra_rst( 'WRITE', kt )   !* write Prather fields in the restart file
348      !
349   END SUBROUTINE ice_dyn_adv_pra
350   
351   
352   SUBROUTINE adv_x( pdt, put , pcrh, psm , ps0 ,   &
353      &              psx, psxx, psy , psyy, psxy )
354      !!----------------------------------------------------------------------
355      !!                **  routine adv_x  **
356      !! 
357      !! ** purpose :   Computes and adds the advection trend to sea-ice
358      !!                variable on x axis
359      !!----------------------------------------------------------------------
360      REAL(wp)                  , INTENT(in   ) ::   pdt                ! the time step
361      REAL(wp)                  , INTENT(in   ) ::   pcrh               ! call adv_x then adv_y (=1) or the opposite (=0)
362      REAL(wp), DIMENSION(:,:)  , INTENT(in   ) ::   put                ! i-direction ice velocity at U-point [m/s]
363      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   psm                ! area
364      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   ps0                ! field to be advected
365      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   psx , psy          ! 1st moments
366      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   psxx, psyy, psxy   ! 2nd moments
367      !!
368      INTEGER  ::   ji, jj, jl, jcat                     ! dummy loop indices
369      INTEGER  ::   jjmin, jjmax                         ! dummy loop indices
370      REAL(wp) ::   zs1max, zslpmax, ztemp               ! local scalars
371      REAL(wp) ::   zs1new, zalf , zalfq , zbt           !   -      -
372      REAL(wp) ::   zs2new, zalf1, zalf1q, zbt1          !   -      -
373      REAL(wp) ::   zpsm, zps0
374      REAL(wp) ::   zpsx, zpsy, zpsxx, zpsyy, zpsxy
375      REAL(wp), DIMENSION(jpi,jpj) ::   zf0 , zfx  , zfy   , zbet   ! 2D workspace
376      REAL(wp), DIMENSION(jpi,jpj) ::   zfm , zfxx , zfyy  , zfxy   !  -      -
377      REAL(wp), DIMENSION(jpi,jpj) ::   zalg, zalg1, zalg1q         !  -      -
378      !-----------------------------------------------------------------------
379      ! in order to avoid lbc_lnk (communications):
380      !    jj loop must be 1:jpj   if adv_x is called first
381      !                and 2:jpj-1 if adv_x is called second
382      jjmin = 2     - NINT(pcrh)   ! 1   or 2
383      jjmax = jpjm1 + NINT(pcrh)   ! jpj or jpj-1
384      !
385      jcat = SIZE( ps0 , 3 )   ! size of input arrays
386      !
387      DO jl = 1, jcat   ! loop on categories
388         !
389         ! Limitation of moments.                                           
390         DO jj = jjmin, jjmax
391           
392            DO ji = 1, jpi
393
394               zpsm  = psm (ji,jj,jl) ! optimization
395               zps0  = ps0 (ji,jj,jl)
396               zpsx  = psx (ji,jj,jl)
397               zpsxx = psxx(ji,jj,jl)
398               zpsy  = psy (ji,jj,jl)
399               zpsyy = psyy(ji,jj,jl)
400               zpsxy = psxy(ji,jj,jl)
401
402               !  Initialize volumes of boxes  (=area if adv_x first called, =psm otherwise)                                     
403               zpsm = MAX( pcrh * e1e2t(ji,jj) + ( 1.0 - pcrh ) * zpsm , epsi20 )
404               !
405               zslpmax = MAX( 0._wp, zps0 )
406               zs1max  = 1.5 * zslpmax
407               zs1new  = MIN( zs1max, MAX( -zs1max, zpsx ) )
408               zs2new  = MIN( 2.0 * zslpmax - 0.3334 * ABS( zs1new ), MAX( ABS( zs1new ) - zslpmax, zpsxx ) )
409               rswitch = ( 1.0 - MAX( 0._wp, SIGN( 1._wp, -zslpmax) ) ) * tmask(ji,jj,1)   ! Case of empty boxes & Apply mask
410
411               zps0  = zslpmax 
412               zpsx  = zs1new  * rswitch
413               zpsxx = zs2new  * rswitch
414               zpsy  = zpsy    * rswitch
415               zpsyy = zpsyy   * rswitch
416               zpsxy = MIN( zslpmax, MAX( -zslpmax, zpsxy ) ) * rswitch
417
418               !  Calculate fluxes and moments between boxes i<-->i+1             
419               !                                !  Flux from i to i+1 WHEN u GT 0
420               zbet(ji,jj)  =  MAX( 0._wp, SIGN( 1._wp, put(ji,jj) ) )
421               zalf         =  MAX( 0._wp, put(ji,jj) ) * pdt / zpsm
422               zalfq        =  zalf * zalf
423               zalf1        =  1.0 - zalf
424               zalf1q       =  zalf1 * zalf1
425               !
426               zfm (ji,jj)  =  zalf  *   zpsm 
427               zf0 (ji,jj)  =  zalf  * ( zps0  + zalf1 * ( zpsx + (zalf1 - zalf) * zpsxx ) )
428               zfx (ji,jj)  =  zalfq * ( zpsx  + 3.0 * zalf1 * zpsxx )
429               zfxx(ji,jj)  =  zalf  *   zpsxx * zalfq
430               zfy (ji,jj)  =  zalf  * ( zpsy  + zalf1 * zpsxy )
431               zfxy(ji,jj)  =  zalfq *   zpsxy
432               zfyy(ji,jj)  =  zalf  *   zpsyy
433
434               !                                !  Readjust moments remaining in the box.
435               zpsm  =  zpsm  - zfm(ji,jj)
436               zps0  =  zps0  - zf0(ji,jj)
437               zpsx  =  zalf1q * ( zpsx - 3.0 * zalf * zpsxx )
438               zpsxx =  zalf1  * zalf1q * zpsxx
439               zpsy  =  zpsy  - zfy (ji,jj)
440               zpsyy =  zpsyy - zfyy(ji,jj)
441               zpsxy =  zalf1q * zpsxy
442               !
443               psm (ji,jj,jl) = zpsm ! optimization
444               ps0 (ji,jj,jl) = zps0 
445               psx (ji,jj,jl) = zpsx 
446               psxx(ji,jj,jl) = zpsxx
447               psy (ji,jj,jl) = zpsy 
448               psyy(ji,jj,jl) = zpsyy
449               psxy(ji,jj,jl) = zpsxy
450               !
451            END DO
452
453            DO ji = 1, fs_jpim1
454               !                                !  Flux from i+1 to i when u LT 0.
455               zalf          = MAX( 0._wp, -put(ji,jj) ) * pdt / psm(ji+1,jj,jl) 
456               zalg  (ji,jj) = zalf
457               zalfq         = zalf * zalf
458               zalf1         = 1.0 - zalf
459               zalg1 (ji,jj) = zalf1
460               zalf1q        = zalf1 * zalf1
461               zalg1q(ji,jj) = zalf1q
462               !
463               zfm   (ji,jj) = zfm (ji,jj) + zalf  *    psm (ji+1,jj,jl)
464               zf0   (ji,jj) = zf0 (ji,jj) + zalf  * (  ps0 (ji+1,jj,jl) &
465                  &                                   - zalf1 * ( psx(ji+1,jj,jl) - (zalf1 - zalf ) * psxx(ji+1,jj,jl) ) )
466               zfx   (ji,jj) = zfx (ji,jj) + zalfq * (  psx (ji+1,jj,jl) - 3.0 * zalf1 * psxx(ji+1,jj,jl) )
467               zfxx  (ji,jj) = zfxx(ji,jj) + zalf  *    psxx(ji+1,jj,jl) * zalfq
468               zfy   (ji,jj) = zfy (ji,jj) + zalf  * (  psy (ji+1,jj,jl) - zalf1 * psxy(ji+1,jj,jl) )
469               zfxy  (ji,jj) = zfxy(ji,jj) + zalfq *    psxy(ji+1,jj,jl)
470               zfyy  (ji,jj) = zfyy(ji,jj) + zalf  *    psyy(ji+1,jj,jl)
471            END DO
472
473            DO ji = fs_2, fs_jpim1 
474               !
475               zpsm  = psm (ji,jj,jl) ! optimization
476               zps0  = ps0 (ji,jj,jl)
477               zpsx  = psx (ji,jj,jl)
478               zpsxx = psxx(ji,jj,jl)
479               zpsy  = psy (ji,jj,jl)
480               zpsyy = psyy(ji,jj,jl)
481               zpsxy = psxy(ji,jj,jl)
482               !                                !  Readjust moments remaining in the box.
483               zbt  =       zbet(ji-1,jj)
484               zbt1 = 1.0 - zbet(ji-1,jj)
485               !
486               zpsm  = zbt * zpsm + zbt1 * ( zpsm - zfm(ji-1,jj) )
487               zps0  = zbt * zps0 + zbt1 * ( zps0 - zf0(ji-1,jj) )
488               zpsx  = zalg1q(ji-1,jj) * ( zpsx + 3.0 * zalg(ji-1,jj) * zpsxx )
489               zpsxx = zalg1 (ji-1,jj) * zalg1q(ji-1,jj) * zpsxx
490               zpsy  = zbt * zpsy  + zbt1 * ( zpsy  - zfy (ji-1,jj) )
491               zpsyy = zbt * zpsyy + zbt1 * ( zpsyy - zfyy(ji-1,jj) )
492               zpsxy = zalg1q(ji-1,jj) * zpsxy
493
494               !   Put the temporary moments into appropriate neighboring boxes.   
495               !                                !   Flux from i to i+1 IF u GT 0.
496               zbt   =       zbet(ji-1,jj)
497               zbt1  = 1.0 - zbet(ji-1,jj)
498               zpsm  = zbt * ( zpsm + zfm(ji-1,jj) ) + zbt1 * zpsm
499               zalf  = zbt * zfm(ji-1,jj) / zpsm
500               zalf1 = 1.0 - zalf
501               ztemp = zalf * zps0 - zalf1 * zf0(ji-1,jj)
502               !
503               zps0  =  zbt  * ( zps0 + zf0(ji-1,jj) ) + zbt1 * zps0
504               zpsx  =  zbt  * ( zalf * zfx(ji-1,jj) + zalf1 * zpsx + 3.0 * ztemp ) + zbt1 * zpsx
505               zpsxx =  zbt  * ( zalf * zalf * zfxx(ji-1,jj) + zalf1 * zalf1 * zpsxx                            &
506                  &            + 5.0 * ( zalf * zalf1 * ( zpsx  - zfx(ji-1,jj) ) - ( zalf1 - zalf ) * ztemp ) ) &
507                  &            + zbt1 * zpsxx
508               zpsxy =  zbt  * ( zalf * zfxy(ji-1,jj) + zalf1 * zpsxy            &
509                  &            + 3.0 * (- zalf1*zfy(ji-1,jj)  + zalf * zpsy ) )  &
510                  &            + zbt1 * zpsxy
511               zpsy  =  zbt  * ( zpsy  + zfy (ji-1,jj) ) + zbt1 * zpsy 
512               zpsyy =  zbt  * ( zpsyy + zfyy(ji-1,jj) ) + zbt1 * zpsyy
513
514               !                                !  Flux from i+1 to i IF u LT 0.
515               zbt   =       zbet(ji,jj)
516               zbt1  = 1.0 - zbet(ji,jj)
517               zpsm  = zbt * zpsm + zbt1 * ( zpsm + zfm(ji,jj) )
518               zalf  = zbt1 * zfm(ji,jj) / zpsm
519               zalf1 = 1.0 - zalf
520               ztemp = - zalf * zps0 + zalf1 * zf0(ji,jj)
521               !
522               zps0  = zbt * zps0  + zbt1 * ( zps0 + zf0(ji,jj) )
523               zpsx  = zbt * zpsx  + zbt1 * ( zalf * zfx(ji,jj) + zalf1 * zpsx + 3.0 * ztemp )
524               zpsxx = zbt * zpsxx + zbt1 * ( zalf * zalf * zfxx(ji,jj) + zalf1 * zalf1 * zpsxx &
525                  &                         + 5.0 * ( zalf * zalf1 * ( - zpsx + zfx(ji,jj) )    &
526                  &                         + ( zalf1 - zalf ) * ztemp ) )
527               zpsxy = zbt * zpsxy + zbt1 * ( zalf * zfxy(ji,jj) + zalf1 * zpsxy  &
528                  &                         + 3.0 * ( zalf1 * zfy(ji,jj) - zalf * zpsy ) )
529               zpsy  = zbt * zpsy  + zbt1 * ( zpsy  + zfy (ji,jj) )
530               zpsyy = zbt * zpsyy + zbt1 * ( zpsyy + zfyy(ji,jj) )
531               !
532               psm (ji,jj,jl) = zpsm  ! optimization
533               ps0 (ji,jj,jl) = zps0 
534               psx (ji,jj,jl) = zpsx 
535               psxx(ji,jj,jl) = zpsxx
536               psy (ji,jj,jl) = zpsy 
537               psyy(ji,jj,jl) = zpsyy
538               psxy(ji,jj,jl) = zpsxy
539            END DO
540           
541         END DO
542
543      END DO
544      !
545   END SUBROUTINE adv_x
546
547
548   SUBROUTINE adv_y( pdt, pvt , pcrh, psm , ps0 ,   &
549      &              psx, psxx, psy , psyy, psxy )
550      !!---------------------------------------------------------------------
551      !!                **  routine adv_y  **
552      !!           
553      !! ** purpose :   Computes and adds the advection trend to sea-ice
554      !!                variable on y axis
555      !!---------------------------------------------------------------------
556      REAL(wp)                  , INTENT(in   ) ::   pdt                ! time step
557      REAL(wp)                  , INTENT(in   ) ::   pcrh               ! call adv_x then adv_y (=1) or the opposite (=0)
558      REAL(wp), DIMENSION(:,:)  , INTENT(in   ) ::   pvt                ! j-direction ice velocity at V-point [m/s]
559      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   psm                ! area
560      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   ps0                ! field to be advected
561      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   psx , psy          ! 1st moments
562      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   psxx, psyy, psxy   ! 2nd moments
563      !!
564      INTEGER  ::   ji, jj, jl, jcat                     ! dummy loop indices
565      INTEGER  ::   jimin, jimax                         ! dummy loop indices
566      REAL(wp) ::   zs1max, zslpmax, ztemp               ! temporary scalars
567      REAL(wp) ::   zs1new, zalf , zalfq , zbt           !    -         -
568      REAL(wp) ::   zs2new, zalf1, zalf1q, zbt1          !    -         -
569      REAL(wp) ::   zpsm, zps0
570      REAL(wp) ::   zpsx, zpsy, zpsxx, zpsyy, zpsxy
571      REAL(wp), DIMENSION(jpi,jpj) ::   zf0, zfx , zfy , zbet   ! 2D workspace
572      REAL(wp), DIMENSION(jpi,jpj) ::   zfm, zfxx, zfyy, zfxy   !  -      -
573      REAL(wp), DIMENSION(jpi,jpj) ::   zalg, zalg1, zalg1q     !  -      -
574      !---------------------------------------------------------------------
575      ! in order to avoid lbc_lnk (communications):
576      !    ji loop must be 1:jpi   if adv_y is called first
577      !                and 2:jpi-1 if adv_y is called second
578      jimin = 2     - NINT(pcrh)   ! 1   or 2
579      jimax = jpim1 + NINT(pcrh)   ! jpi or jpi-1
580      !
581      jcat = SIZE( ps0 , 3 )   ! size of input arrays
582      !     
583      DO jl = 1, jcat   ! loop on categories
584         !
585         ! Limitation of moments.
586         DO jj = 1, jpj
587            DO ji = jimin, jimax
588               !
589               zpsm  = psm (ji,jj,jl) ! optimization
590               zps0  = ps0 (ji,jj,jl)
591               zpsx  = psx (ji,jj,jl)
592               zpsxx = psxx(ji,jj,jl)
593               zpsy  = psy (ji,jj,jl)
594               zpsyy = psyy(ji,jj,jl)
595               zpsxy = psxy(ji,jj,jl)
596               !
597               !  Initialize volumes of boxes (=area if adv_y first called, =psm otherwise)
598               zpsm = MAX(  pcrh * e1e2t(ji,jj) + ( 1.0 - pcrh ) * zpsm , epsi20  )
599               !
600               zslpmax = MAX( 0._wp, zps0 )
601               zs1max  = 1.5 * zslpmax
602               zs1new  = MIN( zs1max, MAX( -zs1max, zpsy ) )
603               zs2new  = MIN( ( 2.0 * zslpmax - 0.3334 * ABS( zs1new ) ), MAX( ABS( zs1new )-zslpmax, zpsyy ) )
604               rswitch = ( 1.0 - MAX( 0._wp, SIGN( 1._wp, -zslpmax) ) ) * tmask(ji,jj,1)   ! Case of empty boxes & Apply mask
605               !
606               zps0  = zslpmax 
607               zpsx  = zpsx  * rswitch
608               zpsxx = zpsxx * rswitch
609               zpsy  = zs1new         * rswitch
610               zpsyy = zs2new         * rswitch
611               zpsxy = MIN( zslpmax, MAX( -zslpmax, zpsxy ) ) * rswitch
612 
613               !  Calculate fluxes and moments between boxes j<-->j+1             
614               !                                !  Flux from j to j+1 WHEN v GT 0   
615               zbet(ji,jj)  =  MAX( 0._wp, SIGN( 1._wp, pvt(ji,jj) ) )
616               zalf         =  MAX( 0._wp, pvt(ji,jj) ) * pdt / zpsm
617               zalfq        =  zalf * zalf
618               zalf1        =  1.0 - zalf
619               zalf1q       =  zalf1 * zalf1
620               !
621               zfm (ji,jj)  =  zalf  * zpsm
622               zf0 (ji,jj)  =  zalf  * ( zps0 + zalf1 * ( zpsy  + (zalf1-zalf) * zpsyy ) ) 
623               zfy (ji,jj)  =  zalfq *( zpsy + 3.0*zalf1*zpsyy )
624               zfyy(ji,jj)  =  zalf  * zalfq * zpsyy
625               zfx (ji,jj)  =  zalf  * ( zpsx + zalf1 * zpsxy )
626               zfxy(ji,jj)  =  zalfq * zpsxy
627               zfxx(ji,jj)  =  zalf  * zpsxx
628               !
629               !                                !  Readjust moments remaining in the box.
630               zpsm   =  zpsm  - zfm(ji,jj)
631               zps0   =  zps0  - zf0(ji,jj)
632               zpsy   =  zalf1q * ( zpsy -3.0 * zalf * zpsyy )
633               zpsyy  =  zalf1 * zalf1q * zpsyy
634               zpsx   =  zpsx  - zfx(ji,jj)
635               zpsxx  =  zpsxx - zfxx(ji,jj)
636               zpsxy  =  zalf1q * zpsxy
637               !
638               psm (ji,jj,jl) = zpsm ! optimization
639               ps0 (ji,jj,jl) = zps0 
640               psx (ji,jj,jl) = zpsx 
641               psxx(ji,jj,jl) = zpsxx
642               psy (ji,jj,jl) = zpsy 
643               psyy(ji,jj,jl) = zpsyy
644               psxy(ji,jj,jl) = zpsxy
645            END DO
646         END DO
647         !
648         DO jj = 1, jpjm1
649            DO ji = jimin, jimax
650               !                                !  Flux from j+1 to j when v LT 0.
651               zalf          = MAX( 0._wp, -pvt(ji,jj) ) * pdt / psm(ji,jj+1,jl) 
652               zalg  (ji,jj) = zalf
653               zalfq         = zalf * zalf
654               zalf1         = 1.0 - zalf
655               zalg1 (ji,jj) = zalf1
656               zalf1q        = zalf1 * zalf1
657               zalg1q(ji,jj) = zalf1q
658               !
659               zfm   (ji,jj) = zfm (ji,jj) + zalf  *    psm (ji,jj+1,jl)
660               zf0   (ji,jj) = zf0 (ji,jj) + zalf  * (  ps0 (ji,jj+1,jl) &
661                  &                                   - zalf1 * (psy(ji,jj+1,jl) - (zalf1 - zalf ) * psyy(ji,jj+1,jl) ) )
662               zfy   (ji,jj) = zfy (ji,jj) + zalfq * (  psy (ji,jj+1,jl) - 3.0 * zalf1 * psyy(ji,jj+1,jl) )
663               zfyy  (ji,jj) = zfyy(ji,jj) + zalf  *    psyy(ji,jj+1,jl) * zalfq
664               zfx   (ji,jj) = zfx (ji,jj) + zalf  * (  psx (ji,jj+1,jl) - zalf1 * psxy(ji,jj+1,jl) )
665               zfxy  (ji,jj) = zfxy(ji,jj) + zalfq *    psxy(ji,jj+1,jl)
666               zfxx  (ji,jj) = zfxx(ji,jj) + zalf  *    psxx(ji,jj+1,jl)
667            END DO
668         END DO
669
670         DO jj = 2, jpjm1
671            DO ji = jimin, jimax
672               !                                !  Readjust moments remaining in the box.
673               zbt  =         zbet(ji,jj-1)
674               zbt1 = ( 1.0 - zbet(ji,jj-1) )
675               !
676               zpsm  = psm (ji,jj,jl) ! optimization
677               zps0  = ps0 (ji,jj,jl)
678               zpsx  = psx (ji,jj,jl)
679               zpsxx = psxx(ji,jj,jl)
680               zpsy  = psy (ji,jj,jl)
681               zpsyy = psyy(ji,jj,jl)
682               zpsxy = psxy(ji,jj,jl)
683               !
684               zpsm  = zbt * zpsm + zbt1 * ( zpsm - zfm(ji,jj-1) )
685               zps0  = zbt * zps0 + zbt1 * ( zps0 - zf0(ji,jj-1) )
686               zpsy  = zalg1q(ji,jj-1) * ( zpsy + 3.0 * zalg(ji,jj-1) * zpsyy )
687               zpsyy = zalg1 (ji,jj-1) * zalg1q(ji,jj-1) * zpsyy
688               zpsx  = zbt * zpsx  + zbt1 * ( zpsx  - zfx (ji,jj-1) )
689               zpsxx = zbt * zpsxx + zbt1 * ( zpsxx - zfxx(ji,jj-1) )
690               zpsxy = zalg1q(ji,jj-1) * zpsxy
691
692               !   Put the temporary moments into appropriate neighboring boxes.   
693               !                                !   Flux from j to j+1 IF v GT 0.
694               zbt   =       zbet(ji,jj-1)
695               zbt1  = 1.0 - zbet(ji,jj-1)
696               zpsm  = zbt * ( zpsm + zfm(ji,jj-1) ) + zbt1 * zpsm 
697               zalf  = zbt * zfm(ji,jj-1) / zpsm 
698               zalf1 = 1.0 - zalf
699               ztemp = zalf * zps0 - zalf1 * zf0(ji,jj-1)
700               !
701               zps0  =   zbt  * ( zps0 + zf0(ji,jj-1) ) + zbt1 * zps0
702               zpsy  =   zbt  * ( zalf * zfy(ji,jj-1) + zalf1 * zpsy + 3.0 * ztemp )  &
703                  &             + zbt1 * zpsy 
704               zpsyy =   zbt  * ( zalf * zalf * zfyy(ji,jj-1) + zalf1 * zalf1 * zpsyy                           &
705                  &             + 5.0 * ( zalf * zalf1 * ( zpsy - zfy(ji,jj-1) ) - ( zalf1 - zalf ) * ztemp ) ) & 
706                  &             + zbt1 * zpsyy
707               zpsxy =   zbt  * ( zalf * zfxy(ji,jj-1) + zalf1 * zpsxy             &
708                  &             + 3.0 * (- zalf1 * zfx(ji,jj-1) + zalf * zpsx ) )  &
709                  &             + zbt1 * zpsxy
710               zpsx  =   zbt * ( zpsx  + zfx (ji,jj-1) ) + zbt1 * zpsx 
711               zpsxx =   zbt * ( zpsxx + zfxx(ji,jj-1) ) + zbt1 * zpsxx
712
713               !                                !  Flux from j+1 to j IF v LT 0.
714               zbt   =       zbet(ji,jj)
715               zbt1  = 1.0 - zbet(ji,jj)
716               zpsm  = zbt * zpsm + zbt1 * ( zpsm + zfm(ji,jj) )
717               zalf  = zbt1 * zfm(ji,jj) / zpsm
718               zalf1 = 1.0 - zalf
719               ztemp = - zalf * zps0 + zalf1 * zf0(ji,jj)
720               !
721               zps0  = zbt * zps0  + zbt1 * (  zps0 + zf0(ji,jj) )
722               zpsy  = zbt * zpsy  + zbt1 * (  zalf * zfy(ji,jj) + zalf1 * zpsy + 3.0 * ztemp )
723               zpsyy = zbt * zpsyy + zbt1 * (  zalf * zalf * zfyy(ji,jj) + zalf1 * zalf1 * zpsyy &
724                  &                         + 5.0 * ( zalf * zalf1 * ( - zpsy + zfy(ji,jj) )     &
725                  &                         + ( zalf1 - zalf ) * ztemp ) )
726               zpsxy = zbt * zpsxy + zbt1 * (  zalf * zfxy(ji,jj) + zalf1 * zpsxy  &
727                  &                         + 3.0 * ( zalf1 * zfx(ji,jj) - zalf * zpsx ) )
728               zpsx  = zbt * zpsx  + zbt1 * ( zpsx  + zfx (ji,jj) )
729               zpsxx = zbt * zpsxx + zbt1 * ( zpsxx + zfxx(ji,jj) )
730               !
731               psm (ji,jj,jl) = zpsm ! optimization
732               ps0 (ji,jj,jl) = zps0 
733               psx (ji,jj,jl) = zpsx 
734               psxx(ji,jj,jl) = zpsxx
735               psy (ji,jj,jl) = zpsy 
736               psyy(ji,jj,jl) = zpsyy
737               psxy(ji,jj,jl) = zpsxy
738            END DO
739         END DO
740
741      END DO
742      !
743   END SUBROUTINE adv_y
744
745
746   SUBROUTINE Hbig( pdt, phi_max, phs_max, phip_max, psi_max, pes_max, pei_max, &
747      &                  pv_i, pv_s, pa_i, pa_ip, pv_ip, psv_i, pe_s, pe_i )
748      !!-------------------------------------------------------------------
749      !!                  ***  ROUTINE Hbig  ***
750      !!
751      !! ** Purpose : Thickness correction in case advection scheme creates
752      !!              abnormally tick ice or snow
753      !!
754      !! ** Method  : 1- check whether ice thickness is larger than the surrounding 9-points
755      !!                 (before advection) and reduce it by adapting ice concentration
756      !!              2- check whether snow thickness is larger than the surrounding 9-points
757      !!                 (before advection) and reduce it by sending the excess in the ocean
758      !!
759      !! ** input   : Max thickness of the surrounding 9-points
760      !!-------------------------------------------------------------------
761      REAL(wp)                    , INTENT(in   ) ::   pdt                                   ! tracer time-step
762      REAL(wp), DIMENSION(:,:,:)  , INTENT(in   ) ::   phi_max, phs_max, phip_max, psi_max   ! max ice thick from surrounding 9-pts
763      REAL(wp), DIMENSION(:,:,:,:), INTENT(in   ) ::   pes_max
764      REAL(wp), DIMENSION(:,:,:,:), INTENT(in   ) ::   pei_max
765      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pv_i, pv_s, pa_i, pa_ip, pv_ip, psv_i
766      REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) ::   pe_s
767      REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) ::   pe_i
768      !
769      INTEGER  ::   ji, jj, jk, jl         ! dummy loop indices
770      REAL(wp) ::   z1_dt, zhip, zhi, zhs, zsi, zes, zei, zfra
771      !!-------------------------------------------------------------------
772      !
773      z1_dt = 1._wp / pdt
774      !
775      DO jl = 1, jpl
776         DO jj = 1, jpj
777            DO ji = 1, jpi
778               IF ( pv_i(ji,jj,jl) > 0._wp ) THEN
779                  !
780                  !                               ! -- check h_ip -- !
781                  ! if h_ip is larger than the surrounding 9 pts => reduce h_ip and increase a_ip
782                  IF( ln_pnd_LEV .AND. pv_ip(ji,jj,jl) > 0._wp ) THEN
783                     zhip = pv_ip(ji,jj,jl) / MAX( epsi20, pa_ip(ji,jj,jl) )
784                     IF( zhip > phip_max(ji,jj,jl) .AND. pa_ip(ji,jj,jl) < 0.15 ) THEN
785                        pa_ip(ji,jj,jl) = pv_ip(ji,jj,jl) / phip_max(ji,jj,jl)
786                     ENDIF
787                  ENDIF
788                  !
789                  !                               ! -- check h_i -- !
790                  ! if h_i is larger than the surrounding 9 pts => reduce h_i and increase a_i
791                  zhi = pv_i(ji,jj,jl) / pa_i(ji,jj,jl)
792                  IF( zhi > phi_max(ji,jj,jl) .AND. pa_i(ji,jj,jl) < 0.15 ) THEN
793                     pa_i(ji,jj,jl) = pv_i(ji,jj,jl) / MIN( phi_max(ji,jj,jl), hi_max(jpl) )   !-- bound h_i to hi_max (99 m)
794                  ENDIF
795                  !
796                  !                               ! -- check h_s -- !
797                  ! if h_s is larger than the surrounding 9 pts => put the snow excess in the ocean
798                  zhs = pv_s(ji,jj,jl) / pa_i(ji,jj,jl)
799                  IF( pv_s(ji,jj,jl) > 0._wp .AND. zhs > phs_max(ji,jj,jl) .AND. pa_i(ji,jj,jl) < 0.15 ) THEN
800                     zfra = phs_max(ji,jj,jl) / MAX( zhs, epsi20 )
801                     !
802                     wfx_res(ji,jj) = wfx_res(ji,jj) + ( pv_s(ji,jj,jl) - pa_i(ji,jj,jl) * phs_max(ji,jj,jl) ) * rhos * z1_dt
803                     hfx_res(ji,jj) = hfx_res(ji,jj) - SUM( pe_s(ji,jj,1:nlay_s,jl) ) * ( 1._wp - zfra ) * z1_dt ! W.m-2 <0
804                     !
805                     pe_s(ji,jj,1:nlay_s,jl) = pe_s(ji,jj,1:nlay_s,jl) * zfra
806                     pv_s(ji,jj,jl)          = pa_i(ji,jj,jl) * phs_max(ji,jj,jl)
807                  ENDIF           
808                  !                 
809                  !                               ! -- check s_i -- !
810                  ! if s_i is larger than the surrounding 9 pts => put salt excess in the ocean
811                  zsi = psv_i(ji,jj,jl) / pv_i(ji,jj,jl)
812                  IF( zsi > psi_max(ji,jj,jl) .AND. pa_i(ji,jj,jl) < 0.15 ) THEN
813                     zfra = psi_max(ji,jj,jl) / zsi
814                     sfx_res(ji,jj) = sfx_res(ji,jj) + psv_i(ji,jj,jl) * ( 1._wp - zfra ) * rhoi * z1_dt
815                     psv_i(ji,jj,jl) = psv_i(ji,jj,jl) * zfra
816                  ENDIF
817                  !
818               ENDIF
819            END DO
820         END DO
821      END DO 
822      !
823      !                                           ! -- check e_i/v_i -- !
824      DO jl = 1, jpl
825         DO jk = 1, nlay_i
826            DO jj = 1, jpj
827               DO ji = 1, jpi
828                  IF ( pv_i(ji,jj,jl) > 0._wp ) THEN
829                     ! if e_i/v_i is larger than the surrounding 9 pts => put the heat excess in the ocean
830                     zei = pe_i(ji,jj,jk,jl) / pv_i(ji,jj,jl)
831                     IF( zei > pei_max(ji,jj,jk,jl) .AND. pa_i(ji,jj,jl) < 0.15 ) THEN
832                        zfra = pei_max(ji,jj,jk,jl) / zei
833                        hfx_res(ji,jj) = hfx_res(ji,jj) - pe_i(ji,jj,jk,jl) * ( 1._wp - zfra ) * z1_dt ! W.m-2 <0
834                        pe_i(ji,jj,jk,jl) = pe_i(ji,jj,jk,jl) * zfra
835                     ENDIF
836                  ENDIF
837               END DO
838            END DO
839         END DO
840      END DO
841      !                                           ! -- check e_s/v_s -- !
842      DO jl = 1, jpl
843         DO jk = 1, nlay_s
844            DO jj = 1, jpj
845               DO ji = 1, jpi
846                  IF ( pv_s(ji,jj,jl) > 0._wp ) THEN
847                     ! if e_s/v_s is larger than the surrounding 9 pts => put the heat excess in the ocean
848                     zes = pe_s(ji,jj,jk,jl) / pv_s(ji,jj,jl)
849                     IF( zes > pes_max(ji,jj,jk,jl) .AND. pa_i(ji,jj,jl) < 0.15 ) THEN
850                        zfra = pes_max(ji,jj,jk,jl) / zes
851                        hfx_res(ji,jj) = hfx_res(ji,jj) - pe_s(ji,jj,jk,jl) * ( 1._wp - zfra ) * z1_dt ! W.m-2 <0
852                        pe_s(ji,jj,jk,jl) = pe_s(ji,jj,jk,jl) * zfra
853                     ENDIF
854                  ENDIF
855               END DO
856            END DO
857         END DO
858      END DO
859      !
860   END SUBROUTINE Hbig
861
862
863   SUBROUTINE Hsnow( pdt, pv_i, pv_s, pa_i, pa_ip, pe_s )
864      !!-------------------------------------------------------------------
865      !!                  ***  ROUTINE Hsnow  ***
866      !!
867      !! ** Purpose : 1- Check snow load after advection
868      !!              2- Correct pond concentration to avoid a_ip > a_i
869      !!
870      !! ** Method :  If snow load makes snow-ice interface to deplet below the ocean surface
871      !!              then put the snow excess in the ocean
872      !!
873      !! ** Notes :   This correction is crucial because of the call to routine icecor afterwards
874      !!              which imposes a mini of ice thick. (rn_himin). This imposed mini can artificially
875      !!              make the snow very thick (if concentration decreases drastically)
876      !!              This behavior has been seen in Ultimate-Macho and supposedly it can also be true for Prather
877      !!-------------------------------------------------------------------
878      REAL(wp)                    , INTENT(in   ) ::   pdt   ! tracer time-step
879      REAL(wp), DIMENSION(:,:,:)  , INTENT(inout) ::   pv_i, pv_s, pa_i, pa_ip
880      REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) ::   pe_s
881      !
882      INTEGER  ::   ji, jj, jl   ! dummy loop indices
883      REAL(wp) ::   z1_dt, zvs_excess, zfra
884      !!-------------------------------------------------------------------
885      !
886      z1_dt = 1._wp / pdt
887      !
888      ! -- check snow load -- !
889      DO jl = 1, jpl
890         DO jj = 1, jpj
891            DO ji = 1, jpi
892               IF ( pv_i(ji,jj,jl) > 0._wp ) THEN
893                  !
894                  zvs_excess = MAX( 0._wp, pv_s(ji,jj,jl) - pv_i(ji,jj,jl) * (rau0-rhoi) * r1_rhos )
895                  !
896                  IF( zvs_excess > 0._wp ) THEN   ! snow-ice interface deplets below the ocean surface
897                     ! put snow excess in the ocean
898                     zfra = ( pv_s(ji,jj,jl) - zvs_excess ) / MAX( pv_s(ji,jj,jl), epsi20 )
899                     wfx_res(ji,jj) = wfx_res(ji,jj) + zvs_excess * rhos * z1_dt
900                     hfx_res(ji,jj) = hfx_res(ji,jj) - SUM( pe_s(ji,jj,1:nlay_s,jl) ) * ( 1._wp - zfra ) * z1_dt ! W.m-2 <0
901                     ! correct snow volume and heat content
902                     pe_s(ji,jj,1:nlay_s,jl) = pe_s(ji,jj,1:nlay_s,jl) * zfra
903                     pv_s(ji,jj,jl)          = pv_s(ji,jj,jl) - zvs_excess
904                  ENDIF
905                  !
906               ENDIF
907            END DO
908         END DO
909      END DO
910      !
911      !-- correct pond concentration to avoid a_ip > a_i -- !
912      WHERE( pa_ip(:,:,:) > pa_i(:,:,:) )   pa_ip(:,:,:) = pa_i(:,:,:)
913      !
914   END SUBROUTINE Hsnow
915
916
917   SUBROUTINE adv_pra_init
918      !!-------------------------------------------------------------------
919      !!                  ***  ROUTINE adv_pra_init  ***
920      !!
921      !! ** Purpose :   allocate and initialize arrays for Prather advection
922      !!-------------------------------------------------------------------
923      INTEGER ::   ierr
924      !!-------------------------------------------------------------------
925      !
926      !                             !* allocate prather fields
927      ALLOCATE( sxice(jpi,jpj,jpl) , syice(jpi,jpj,jpl) , sxxice(jpi,jpj,jpl) , syyice(jpi,jpj,jpl) , sxyice(jpi,jpj,jpl) ,   &
928         &      sxsn (jpi,jpj,jpl) , sysn (jpi,jpj,jpl) , sxxsn (jpi,jpj,jpl) , syysn (jpi,jpj,jpl) , sxysn (jpi,jpj,jpl) ,   &
929         &      sxa  (jpi,jpj,jpl) , sya  (jpi,jpj,jpl) , sxxa  (jpi,jpj,jpl) , syya  (jpi,jpj,jpl) , sxya  (jpi,jpj,jpl) ,   &
930         &      sxsal(jpi,jpj,jpl) , sysal(jpi,jpj,jpl) , sxxsal(jpi,jpj,jpl) , syysal(jpi,jpj,jpl) , sxysal(jpi,jpj,jpl) ,   &
931         &      sxage(jpi,jpj,jpl) , syage(jpi,jpj,jpl) , sxxage(jpi,jpj,jpl) , syyage(jpi,jpj,jpl) , sxyage(jpi,jpj,jpl) ,   &
932         &      sxap (jpi,jpj,jpl) , syap (jpi,jpj,jpl) , sxxap (jpi,jpj,jpl) , syyap (jpi,jpj,jpl) , sxyap (jpi,jpj,jpl) ,   &
933         &      sxvp (jpi,jpj,jpl) , syvp (jpi,jpj,jpl) , sxxvp (jpi,jpj,jpl) , syyvp (jpi,jpj,jpl) , sxyvp (jpi,jpj,jpl) ,   &
934         &      sxvl (jpi,jpj,jpl) , syvl (jpi,jpj,jpl) , sxxvl (jpi,jpj,jpl) , syyvl (jpi,jpj,jpl) , sxyvl (jpi,jpj,jpl) ,   &
935         !
936         &      sxc0 (jpi,jpj,nlay_s,jpl) , syc0 (jpi,jpj,nlay_s,jpl) , sxxc0(jpi,jpj,nlay_s,jpl) , &
937         &      syyc0(jpi,jpj,nlay_s,jpl) , sxyc0(jpi,jpj,nlay_s,jpl)                             , &
938         !
939         &      sxe  (jpi,jpj,nlay_i,jpl) , sye  (jpi,jpj,nlay_i,jpl) , sxxe (jpi,jpj,nlay_i,jpl) , &
940         &      syye (jpi,jpj,nlay_i,jpl) , sxye (jpi,jpj,nlay_i,jpl)                             , &
941         &      STAT = ierr )
942      !
943      CALL mpp_sum( 'icedyn_adv_pra', ierr )
944      IF( ierr /= 0 )   CALL ctl_stop('STOP', 'adv_pra_init : unable to allocate ice arrays for Prather advection scheme')
945      !
946      CALL adv_pra_rst( 'READ' )    !* read or initialize all required files
947      !
948   END SUBROUTINE adv_pra_init
949
950
951   SUBROUTINE adv_pra_rst( cdrw, kt )
952      !!---------------------------------------------------------------------
953      !!                   ***  ROUTINE adv_pra_rst  ***
954      !!                     
955      !! ** Purpose :   Read or write file in restart file
956      !!
957      !! ** Method  :   use of IOM library
958      !!----------------------------------------------------------------------
959      CHARACTER(len=*) , INTENT(in) ::   cdrw   ! "READ"/"WRITE" flag
960      INTEGER, OPTIONAL, INTENT(in) ::   kt     ! ice time-step
961      !
962      INTEGER ::   jk, jl   ! dummy loop indices
963      INTEGER ::   iter     ! local integer
964      INTEGER ::   id1      ! local integer
965      CHARACTER(len=25) ::   znam
966      CHARACTER(len=2)  ::   zchar, zchar1
967      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z3d   ! 3D workspace
968      !!----------------------------------------------------------------------
969      !
970      !                                      !==========================!
971      IF( TRIM(cdrw) == 'READ' ) THEN        !==  Read or initialize  ==!
972         !                                   !==========================!
973         !
974         IF( ln_rstart ) THEN   ;   id1 = iom_varid( numrir, 'sxice' , ldstop = .FALSE. )    ! file exist: id1>0
975         ELSE                   ;   id1 = 0                                                  ! no restart: id1=0
976         ENDIF
977         !
978         IF( id1 > 0 ) THEN                     !**  Read the restart file  **!
979            !
980            !                                                        ! ice thickness
981            CALL iom_get( numrir, jpdom_autoglo, 'sxice' , sxice  )
982            CALL iom_get( numrir, jpdom_autoglo, 'syice' , syice  )
983            CALL iom_get( numrir, jpdom_autoglo, 'sxxice', sxxice )
984            CALL iom_get( numrir, jpdom_autoglo, 'syyice', syyice )
985            CALL iom_get( numrir, jpdom_autoglo, 'sxyice', sxyice )
986            !                                                        ! snow thickness
987            CALL iom_get( numrir, jpdom_autoglo, 'sxsn'  , sxsn   )
988            CALL iom_get( numrir, jpdom_autoglo, 'sysn'  , sysn   )
989            CALL iom_get( numrir, jpdom_autoglo, 'sxxsn' , sxxsn  )
990            CALL iom_get( numrir, jpdom_autoglo, 'syysn' , syysn  )
991            CALL iom_get( numrir, jpdom_autoglo, 'sxysn' , sxysn  )
992            !                                                        ! ice concentration
993            CALL iom_get( numrir, jpdom_autoglo, 'sxa'   , sxa    )
994            CALL iom_get( numrir, jpdom_autoglo, 'sya'   , sya    )
995            CALL iom_get( numrir, jpdom_autoglo, 'sxxa'  , sxxa   )
996            CALL iom_get( numrir, jpdom_autoglo, 'syya'  , syya   )
997            CALL iom_get( numrir, jpdom_autoglo, 'sxya'  , sxya   )
998            !                                                        ! ice salinity
999            CALL iom_get( numrir, jpdom_autoglo, 'sxsal' , sxsal  )
1000            CALL iom_get( numrir, jpdom_autoglo, 'sysal' , sysal  )
1001            CALL iom_get( numrir, jpdom_autoglo, 'sxxsal', sxxsal )
1002            CALL iom_get( numrir, jpdom_autoglo, 'syysal', syysal )
1003            CALL iom_get( numrir, jpdom_autoglo, 'sxysal', sxysal )
1004            !                                                        ! ice age
1005            CALL iom_get( numrir, jpdom_autoglo, 'sxage' , sxage  )
1006            CALL iom_get( numrir, jpdom_autoglo, 'syage' , syage  )
1007            CALL iom_get( numrir, jpdom_autoglo, 'sxxage', sxxage )
1008            CALL iom_get( numrir, jpdom_autoglo, 'syyage', syyage )
1009            CALL iom_get( numrir, jpdom_autoglo, 'sxyage', sxyage )
1010            !                                                        ! snow layers heat content
1011            DO jk = 1, nlay_s
1012               WRITE(zchar1,'(I2.2)') jk
1013               znam = 'sxc0'//'_l'//zchar1  ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   sxc0 (:,:,jk,:) = z3d(:,:,:)
1014               znam = 'syc0'//'_l'//zchar1  ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   syc0 (:,:,jk,:) = z3d(:,:,:)
1015               znam = 'sxxc0'//'_l'//zchar1 ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   sxxc0(:,:,jk,:) = z3d(:,:,:)
1016               znam = 'syyc0'//'_l'//zchar1 ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   syyc0(:,:,jk,:) = z3d(:,:,:)
1017               znam = 'sxyc0'//'_l'//zchar1 ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   sxyc0(:,:,jk,:) = z3d(:,:,:)
1018            END DO
1019            !                                                        ! ice layers heat content
1020            DO jk = 1, nlay_i
1021               WRITE(zchar1,'(I2.2)') jk
1022               znam = 'sxe'//'_l'//zchar1   ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   sxe (:,:,jk,:) = z3d(:,:,:)
1023               znam = 'sye'//'_l'//zchar1   ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   sye (:,:,jk,:) = z3d(:,:,:)
1024               znam = 'sxxe'//'_l'//zchar1  ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   sxxe(:,:,jk,:) = z3d(:,:,:)
1025               znam = 'syye'//'_l'//zchar1  ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   syye(:,:,jk,:) = z3d(:,:,:)
1026               znam = 'sxye'//'_l'//zchar1  ;   CALL iom_get( numrir, jpdom_autoglo, znam , z3d )   ;   sxye(:,:,jk,:) = z3d(:,:,:)
1027            END DO
1028            !
1029            IF( ln_pnd_LEV ) THEN                                    ! melt pond fraction
1030               IF( iom_varid( numrir, 'sxap', ldstop = .FALSE. ) > 0 ) THEN
1031                  CALL iom_get( numrir, jpdom_autoglo, 'sxap' , sxap  )
1032                  CALL iom_get( numrir, jpdom_autoglo, 'syap' , syap  )
1033                  CALL iom_get( numrir, jpdom_autoglo, 'sxxap', sxxap )
1034                  CALL iom_get( numrir, jpdom_autoglo, 'syyap', syyap )
1035                  CALL iom_get( numrir, jpdom_autoglo, 'sxyap', sxyap )
1036                  !                                                     ! melt pond volume
1037                  CALL iom_get( numrir, jpdom_autoglo, 'sxvp' , sxvp  )
1038                  CALL iom_get( numrir, jpdom_autoglo, 'syvp' , syvp  )
1039                  CALL iom_get( numrir, jpdom_autoglo, 'sxxvp', sxxvp )
1040                  CALL iom_get( numrir, jpdom_autoglo, 'syyvp', syyvp )
1041                  CALL iom_get( numrir, jpdom_autoglo, 'sxyvp', sxyvp )
1042               ELSE
1043                  sxap = 0._wp ;   syap = 0._wp    ;   sxxap = 0._wp    ;   syyap = 0._wp    ;   sxyap = 0._wp   ! melt pond fraction
1044                  sxvp = 0._wp ;   syvp = 0._wp    ;   sxxvp = 0._wp    ;   syyvp = 0._wp    ;   sxyvp = 0._wp   ! melt pond volume
1045               ENDIF
1046                  !
1047               IF ( ln_pnd_lids ) THEN                               ! melt pond lid volume
1048                  IF( iom_varid( numrir, 'sxvl', ldstop = .FALSE. ) > 0 ) THEN
1049                     CALL iom_get( numrir, jpdom_autoglo, 'sxvl' , sxvl  )
1050                     CALL iom_get( numrir, jpdom_autoglo, 'syvl' , syvl  )
1051                     CALL iom_get( numrir, jpdom_autoglo, 'sxxvl', sxxvl )
1052                     CALL iom_get( numrir, jpdom_autoglo, 'syyvl', syyvl )
1053                     CALL iom_get( numrir, jpdom_autoglo, 'sxyvl', sxyvl )
1054                  ELSE
1055                     sxvl = 0._wp; syvl = 0._wp    ;   sxxvl = 0._wp    ;   syyvl = 0._wp    ;   sxyvl = 0._wp   ! melt pond lid volume
1056                  ENDIF
1057               ENDIF
1058            ENDIF
1059            !
1060         ELSE                                   !**  start rheology from rest  **!
1061            !
1062            IF(lwp) WRITE(numout,*) '   ==>>   start from rest OR previous run without Prather, set moments to 0'
1063            !
1064            sxice = 0._wp   ;   syice = 0._wp   ;   sxxice = 0._wp   ;   syyice = 0._wp   ;   sxyice = 0._wp      ! ice thickness
1065            sxsn  = 0._wp   ;   sysn  = 0._wp   ;   sxxsn  = 0._wp   ;   syysn  = 0._wp   ;   sxysn  = 0._wp      ! snow thickness
1066            sxa   = 0._wp   ;   sya   = 0._wp   ;   sxxa   = 0._wp   ;   syya   = 0._wp   ;   sxya   = 0._wp      ! ice concentration
1067            sxsal = 0._wp   ;   sysal = 0._wp   ;   sxxsal = 0._wp   ;   syysal = 0._wp   ;   sxysal = 0._wp      ! ice salinity
1068            sxage = 0._wp   ;   syage = 0._wp   ;   sxxage = 0._wp   ;   syyage = 0._wp   ;   sxyage = 0._wp      ! ice age
1069            sxc0  = 0._wp   ;   syc0  = 0._wp   ;   sxxc0  = 0._wp   ;   syyc0  = 0._wp   ;   sxyc0  = 0._wp      ! snow layers heat content
1070            sxe   = 0._wp   ;   sye   = 0._wp   ;   sxxe   = 0._wp   ;   syye   = 0._wp   ;   sxye   = 0._wp      ! ice layers heat content
1071            IF( ln_pnd_LEV ) THEN
1072               sxap = 0._wp ;   syap = 0._wp    ;   sxxap = 0._wp    ;   syyap = 0._wp    ;   sxyap = 0._wp       ! melt pond fraction
1073               sxvp = 0._wp ;   syvp = 0._wp    ;   sxxvp = 0._wp    ;   syyvp = 0._wp    ;   sxyvp = 0._wp       ! melt pond volume
1074               IF ( ln_pnd_lids ) THEN
1075                  sxvl = 0._wp; syvl = 0._wp    ;   sxxvl = 0._wp    ;   syyvl = 0._wp    ;   sxyvl = 0._wp       ! melt pond lid volume
1076               ENDIF
1077            ENDIF
1078         ENDIF
1079         !
1080         !                                   !=====================================!
1081      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN   !==  write in the ice restart file  ==!
1082         !                                   !=====================================!
1083         IF(lwp) WRITE(numout,*) '----  ice-adv-rst  ----'
1084         iter = kt + nn_fsbc - 1             ! ice restarts are written at kt == nitrst - nn_fsbc + 1
1085         !
1086         !
1087         ! In case Prather scheme is used for advection, write second order moments
1088         ! ------------------------------------------------------------------------
1089         !
1090         !                                                           ! ice thickness
1091         CALL iom_rstput( iter, nitrst, numriw, 'sxice' , sxice  )
1092         CALL iom_rstput( iter, nitrst, numriw, 'syice' , syice  )
1093         CALL iom_rstput( iter, nitrst, numriw, 'sxxice', sxxice )
1094         CALL iom_rstput( iter, nitrst, numriw, 'syyice', syyice )
1095         CALL iom_rstput( iter, nitrst, numriw, 'sxyice', sxyice )
1096         !                                                           ! snow thickness
1097         CALL iom_rstput( iter, nitrst, numriw, 'sxsn'  , sxsn   )
1098         CALL iom_rstput( iter, nitrst, numriw, 'sysn'  , sysn   )
1099         CALL iom_rstput( iter, nitrst, numriw, 'sxxsn' , sxxsn  )
1100         CALL iom_rstput( iter, nitrst, numriw, 'syysn' , syysn  )
1101         CALL iom_rstput( iter, nitrst, numriw, 'sxysn' , sxysn  )
1102         !                                                           ! ice concentration
1103         CALL iom_rstput( iter, nitrst, numriw, 'sxa'   , sxa    )
1104         CALL iom_rstput( iter, nitrst, numriw, 'sya'   , sya    )
1105         CALL iom_rstput( iter, nitrst, numriw, 'sxxa'  , sxxa   )
1106         CALL iom_rstput( iter, nitrst, numriw, 'syya'  , syya   )
1107         CALL iom_rstput( iter, nitrst, numriw, 'sxya'  , sxya   )
1108         !                                                           ! ice salinity
1109         CALL iom_rstput( iter, nitrst, numriw, 'sxsal' , sxsal  )
1110         CALL iom_rstput( iter, nitrst, numriw, 'sysal' , sysal  )
1111         CALL iom_rstput( iter, nitrst, numriw, 'sxxsal', sxxsal )
1112         CALL iom_rstput( iter, nitrst, numriw, 'syysal', syysal )
1113         CALL iom_rstput( iter, nitrst, numriw, 'sxysal', sxysal )
1114         !                                                           ! ice age
1115         CALL iom_rstput( iter, nitrst, numriw, 'sxage' , sxage  )
1116         CALL iom_rstput( iter, nitrst, numriw, 'syage' , syage  )
1117         CALL iom_rstput( iter, nitrst, numriw, 'sxxage', sxxage )
1118         CALL iom_rstput( iter, nitrst, numriw, 'syyage', syyage )
1119         CALL iom_rstput( iter, nitrst, numriw, 'sxyage', sxyage )
1120         !                                                           ! snow layers heat content
1121         DO jk = 1, nlay_s
1122            WRITE(zchar1,'(I2.2)') jk
1123            znam = 'sxc0'//'_l'//zchar1  ;   z3d(:,:,:) = sxc0 (:,:,jk,:)  ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1124            znam = 'syc0'//'_l'//zchar1  ;   z3d(:,:,:) = syc0 (:,:,jk,:)  ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1125            znam = 'sxxc0'//'_l'//zchar1 ;   z3d(:,:,:) = sxxc0(:,:,jk,:)  ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1126            znam = 'syyc0'//'_l'//zchar1 ;   z3d(:,:,:) = syyc0(:,:,jk,:)  ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1127            znam = 'sxyc0'//'_l'//zchar1 ;   z3d(:,:,:) = sxyc0(:,:,jk,:)  ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1128         END DO
1129         !                                                           ! ice layers heat content
1130         DO jk = 1, nlay_i
1131            WRITE(zchar1,'(I2.2)') jk
1132            znam = 'sxe'//'_l'//zchar1   ;   z3d(:,:,:) = sxe (:,:,jk,:)   ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1133            znam = 'sye'//'_l'//zchar1   ;   z3d(:,:,:) = sye (:,:,jk,:)   ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1134            znam = 'sxxe'//'_l'//zchar1  ;   z3d(:,:,:) = sxxe(:,:,jk,:)   ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1135            znam = 'syye'//'_l'//zchar1  ;   z3d(:,:,:) = syye(:,:,jk,:)   ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1136            znam = 'sxye'//'_l'//zchar1  ;   z3d(:,:,:) = sxye(:,:,jk,:)   ;   CALL iom_rstput( iter, nitrst, numriw, znam , z3d )
1137         END DO
1138         !
1139         IF( ln_pnd_LEV ) THEN                                       ! melt pond fraction
1140            CALL iom_rstput( iter, nitrst, numriw, 'sxap' , sxap  )
1141            CALL iom_rstput( iter, nitrst, numriw, 'syap' , syap  )
1142            CALL iom_rstput( iter, nitrst, numriw, 'sxxap', sxxap )
1143            CALL iom_rstput( iter, nitrst, numriw, 'syyap', syyap )
1144            CALL iom_rstput( iter, nitrst, numriw, 'sxyap', sxyap )
1145            !                                                        ! melt pond volume
1146            CALL iom_rstput( iter, nitrst, numriw, 'sxvp' , sxvp  )
1147            CALL iom_rstput( iter, nitrst, numriw, 'syvp' , syvp  )
1148            CALL iom_rstput( iter, nitrst, numriw, 'sxxvp', sxxvp )
1149            CALL iom_rstput( iter, nitrst, numriw, 'syyvp', syyvp )
1150            CALL iom_rstput( iter, nitrst, numriw, 'sxyvp', sxyvp )
1151            !
1152            IF ( ln_pnd_lids ) THEN                                  ! melt pond lid volume
1153               CALL iom_rstput( iter, nitrst, numriw, 'sxvl' , sxvl  )
1154               CALL iom_rstput( iter, nitrst, numriw, 'syvl' , syvl  )
1155               CALL iom_rstput( iter, nitrst, numriw, 'sxxvl', sxxvl )
1156               CALL iom_rstput( iter, nitrst, numriw, 'syyvl', syyvl )
1157               CALL iom_rstput( iter, nitrst, numriw, 'sxyvl', sxyvl )
1158            ENDIF
1159         ENDIF
1160         !
1161      ENDIF
1162      !
1163   END SUBROUTINE adv_pra_rst
1164
1165   SUBROUTINE icemax3D( pice , pmax )
1166      !!---------------------------------------------------------------------
1167      !!                   ***  ROUTINE icemax3D ***                     
1168      !! ** Purpose :  compute the max of the 9 points around
1169      !!----------------------------------------------------------------------
1170      REAL(wp), DIMENSION(:,:,:)      , INTENT(in ) ::   pice   ! input
1171      REAL(wp), DIMENSION(:,:,:)      , INTENT(out) ::   pmax   ! output
1172      REAL(wp), DIMENSION(2:jpim1,jpj)              ::   zmax   ! temporary array
1173      INTEGER  ::   ji, jj, jl   ! dummy loop indices
1174      !!----------------------------------------------------------------------
1175      DO jl = 1, jpl
1176         DO jj = 1, jpj
1177            DO ji = 2, jpim1
1178               zmax(ji,jj) = MAX( epsi20, pice(ji,jj,jl), pice(ji-1,jj,jl), pice(ji+1,jj,jl) )
1179            END DO
1180         END DO
1181         DO jj = 2, jpjm1
1182            DO ji = 2, jpim1
1183               pmax(ji,jj,jl) = MAX( epsi20, zmax(ji,jj), zmax(ji,jj-1), zmax(ji,jj+1) )
1184            END DO
1185         END DO
1186      END DO
1187   END SUBROUTINE icemax3D
1188
1189   SUBROUTINE icemax4D( pice , pmax )
1190      !!---------------------------------------------------------------------
1191      !!                   ***  ROUTINE icemax4D ***                     
1192      !! ** Purpose :  compute the max of the 9 points around
1193      !!----------------------------------------------------------------------
1194      REAL(wp), DIMENSION(:,:,:,:)    , INTENT(in ) ::   pice   ! input
1195      REAL(wp), DIMENSION(:,:,:,:)    , INTENT(out) ::   pmax   ! output
1196      REAL(wp), DIMENSION(2:jpim1,jpj)              ::   zmax   ! temporary array
1197      INTEGER  ::   jlay, ji, jj, jk, jl   ! dummy loop indices
1198      !!----------------------------------------------------------------------
1199      jlay = SIZE( pice , 3 )   ! size of input arrays
1200      DO jl = 1, jpl
1201         DO jk = 1, jlay
1202            DO jj = 1, jpj
1203               DO ji = 2, jpim1
1204                  zmax(ji,jj) = MAX( epsi20, pice(ji,jj,jk,jl), pice(ji-1,jj,jk,jl), pice(ji+1,jj,jk,jl) )
1205               END DO
1206            END DO
1207            DO jj = 2, jpjm1
1208               DO ji = 2, jpim1
1209                  pmax(ji,jj,jk,jl) = MAX( epsi20, zmax(ji,jj), zmax(ji,jj-1), zmax(ji,jj+1) )
1210               END DO
1211            END DO
1212         END DO
1213      END DO
1214   END SUBROUTINE icemax4D
1215   
1216#else
1217   !!----------------------------------------------------------------------
1218   !!   Default option            Dummy module        NO SI3 sea-ice model
1219   !!----------------------------------------------------------------------
1220#endif
1221
1222   !!======================================================================
1223END MODULE icedyn_adv_pra
Note: See TracBrowser for help on using the repository browser.