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.
traldf_iso.F90 in branches/2016/dev_r6519_HPC_4/NEMOGCM/NEMO/OPA_SRC/TRA – NEMO

source: branches/2016/dev_r6519_HPC_4/NEMOGCM/NEMO/OPA_SRC/TRA/traldf_iso.F90 @ 7037

Last change on this file since 7037 was 7037, checked in by mocavero, 8 years ago

ORCA2_LIM_PISCES hybrid version update

  • Property svn:keywords set to Id
File size: 26.5 KB
Line 
1MODULE traldf_iso
2   !!======================================================================
3   !!                   ***  MODULE  traldf_iso  ***
4   !! Ocean  tracers:  horizontal component of the lateral tracer mixing trend
5   !!======================================================================
6   !! History :  OPA  ! 1994-08  (G. Madec, M. Imbard)
7   !!            8.0  ! 1997-05  (G. Madec)  split into traldf and trazdf
8   !!            NEMO ! 2002-08  (G. Madec)  Free form, F90
9   !!            1.0  ! 2005-11  (G. Madec)  merge traldf and trazdf :-)
10   !!            3.3  ! 2010-09  (C. Ethe, G. Madec) Merge TRA-TRC
11   !!            3.7  ! 2014-01  (G. Madec, S. Masson)  restructuration/simplification of aht/aeiv specification
12   !!             -   ! 2014-02  (F. Lemarie, G. Madec)  triad operator (Griffies) + Method of Stabilizing Correction
13   !!----------------------------------------------------------------------
14
15   !!----------------------------------------------------------------------
16   !!   tra_ldf_iso   : update the tracer trend with the horizontal component of a iso-neutral laplacian operator
17   !!                   and with the vertical part of the isopycnal or geopotential s-coord. operator
18   !!----------------------------------------------------------------------
19   USE oce            ! ocean dynamics and active tracers
20   USE dom_oce        ! ocean space and time domain
21   USE trc_oce        ! share passive tracers/Ocean variables
22   USE zdf_oce        ! ocean vertical physics
23   USE ldftra         ! lateral diffusion: tracer eddy coefficients
24   USE ldfslp         ! iso-neutral slopes
25   USE diaptr         ! poleward transport diagnostics
26   !
27   USE in_out_manager ! I/O manager
28   USE iom            ! I/O library
29   USE phycst         ! physical constants
30   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
31   USE wrk_nemo       ! Memory Allocation
32   USE timing         ! Timing
33
34   IMPLICIT NONE
35   PRIVATE
36
37   PUBLIC   tra_ldf_iso   ! routine called by step.F90
38
39   !! * Substitutions
40#  include "vectopt_loop_substitute.h90"
41   !!----------------------------------------------------------------------
42   !! NEMO/OPA 3.7 , NEMO Consortium (2015)
43   !! $Id$
44   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
45   !!----------------------------------------------------------------------
46CONTAINS
47
48  SUBROUTINE tra_ldf_iso( kt, kit000, cdtype, pahu, pahv, pgu , pgv ,   &
49      &                                                   pgui, pgvi,   &
50      &                                       ptb , ptbb, pta , kjpt, kpass )
51      !!----------------------------------------------------------------------
52      !!                  ***  ROUTINE tra_ldf_iso  ***
53      !!
54      !! ** Purpose :   Compute the before horizontal tracer (t & s) diffusive
55      !!      trend for a laplacian tensor (ezxcept the dz[ dz[.] ] term) and
56      !!      add it to the general trend of tracer equation.
57      !!
58      !! ** Method  :   The horizontal component of the lateral diffusive trends
59      !!      is provided by a 2nd order operator rotated along neural or geopo-
60      !!      tential surfaces to which an eddy induced advection can be added
61      !!      It is computed using before fields (forward in time) and isopyc-
62      !!      nal or geopotential slopes computed in routine ldfslp.
63      !!
64      !!      1st part :  masked horizontal derivative of T  ( di[ t ] )
65      !!      ========    with partial cell update if ln_zps=T
66      !!                  with top     cell update if ln_isfcav
67      !!
68      !!      2nd part :  horizontal fluxes of the lateral mixing operator
69      !!      ========   
70      !!         zftu =  pahu e2u*e3u/e1u di[ tb ]
71      !!               - pahu e2u*uslp    dk[ mi(mk(tb)) ]
72      !!         zftv =  pahv e1v*e3v/e2v dj[ tb ]
73      !!               - pahv e2u*vslp    dk[ mj(mk(tb)) ]
74      !!      take the horizontal divergence of the fluxes:
75      !!         difft = 1/(e1e2t*e3t) {  di-1[ zftu ] +  dj-1[ zftv ]  }
76      !!      Add this trend to the general trend (ta,sa):
77      !!         ta = ta + difft
78      !!
79      !!      3rd part: vertical trends of the lateral mixing operator
80      !!      ========  (excluding the vertical flux proportional to dk[t] )
81      !!      vertical fluxes associated with the rotated lateral mixing:
82      !!         zftw = - {  mi(mk(pahu)) * e2t*wslpi di[ mi(mk(tb)) ]
83      !!                   + mj(mk(pahv)) * e1t*wslpj dj[ mj(mk(tb)) ]  }
84      !!      take the horizontal divergence of the fluxes:
85      !!         difft = 1/(e1e2t*e3t) dk[ zftw ]
86      !!      Add this trend to the general trend (ta,sa):
87      !!         pta = pta + difft
88      !!
89      !! ** Action :   Update pta arrays with the before rotated diffusion
90      !!----------------------------------------------------------------------
91      INTEGER                              , INTENT(in   ) ::   kt         ! ocean time-step index
92      INTEGER                              , INTENT(in   ) ::   kit000     ! first time step index
93      CHARACTER(len=3)                     , INTENT(in   ) ::   cdtype     ! =TRA or TRC (tracer indicator)
94      INTEGER                              , INTENT(in   ) ::   kjpt       ! number of tracers
95      INTEGER                              , INTENT(in   ) ::   kpass      ! =1/2 first or second passage
96      REAL(wp), DIMENSION(jpi,jpj,jpk)     , INTENT(in   ) ::   pahu, pahv ! eddy diffusivity at u- and v-points  [m2/s]
97      REAL(wp), DIMENSION(jpi,jpj    ,kjpt), INTENT(in   ) ::   pgu, pgv   ! tracer gradient at pstep levels
98      REAL(wp), DIMENSION(jpi,jpj,    kjpt), INTENT(in   ) ::   pgui, pgvi ! tracer gradient at top   levels
99      REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in   ) ::   ptb        ! tracer (kpass=1) or laplacian of tracer (kpass=2)
100      REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in   ) ::   ptbb       ! tracer (only used in kpass=2)
101      REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(inout) ::   pta        ! tracer trend
102      !
103      INTEGER  ::  ji, jj, jk, jn   ! dummy loop indices
104      INTEGER  ::  ikt
105      INTEGER  ::  ierr             ! local integer
106      REAL(wp) ::  zmsku, zahu_w, zabe1, zcof1, zcoef3   ! local scalars
107      REAL(wp) ::  zmskv, zahv_w, zabe2, zcof2, zcoef4   !   -      -
108      REAL(wp) ::  zcoef0, ze3w_2, zsign, z2dt, z1_2dt   !   -      -
109#if defined key_diaar5
110      REAL(wp) ::   zztmp   ! local scalar
111#endif
112      REAL(wp), POINTER, DIMENSION(:,:)   ::   zdkt, zdk1t, z2d
113      REAL(wp), POINTER, DIMENSION(:,:,:) ::   zdit, zdjt, zftu, zftv, ztfw 
114      !!----------------------------------------------------------------------
115      !
116      IF( nn_timing == 1 )  CALL timing_start('tra_ldf_iso')
117      !
118      CALL wrk_alloc( jpi,jpj,       zdkt, zdk1t, z2d ) 
119      CALL wrk_alloc( jpi,jpj,jpk,   zdit, zdjt , zftu, zftv, ztfw  ) 
120      !
121      IF( kt == kit000 )  THEN
122         IF(lwp) WRITE(numout,*)
123         IF(lwp) WRITE(numout,*) 'tra_ldf_iso : rotated laplacian diffusion operator on ', cdtype
124         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~'
125         !
126!$OMP PARALLEL WORKSHARE
127         akz     (:,:,:) = 0._wp     
128         ah_wslp2(:,:,:) = 0._wp
129!$OMP END PARALLEL WORKSHARE
130      ENDIF
131      !                                               ! set time step size (Euler/Leapfrog)
132      IF( neuler == 0 .AND. kt == nit000 ) THEN   ;   z2dt =     rdt      ! at nit000   (Euler)
133      ELSE                                        ;   z2dt = 2.* rdt      !             (Leapfrog)
134      ENDIF
135      z1_2dt = 1._wp / z2dt
136      !
137      IF( kpass == 1 ) THEN   ;   zsign =  1._wp      ! bilaplacian operator require a minus sign (eddy diffusivity >0)
138      ELSE                    ;   zsign = -1._wp
139      ENDIF
140         
141      !!----------------------------------------------------------------------
142      !!   0 - calculate  ah_wslp2 and akz
143      !!----------------------------------------------------------------------
144      !
145      IF( kpass == 1 ) THEN                  !==  first pass only  ==!
146         !
147!$OMP PARALLEL DO schedule(static) private(jk, jj, ji, zmsku, zmskv, zahu_w, zahv_w)
148         DO jk = 2, jpkm1
149            DO jj = 2, jpjm1
150               DO ji = fs_2, fs_jpim1   ! vector opt.
151                  !
152                  zmsku = wmask(ji,jj,jk) / MAX(   umask(ji  ,jj,jk-1) + umask(ji-1,jj,jk)          &
153                     &                           + umask(ji-1,jj,jk-1) + umask(ji  ,jj,jk) , 1._wp  )
154                  zmskv = wmask(ji,jj,jk) / MAX(   vmask(ji,jj  ,jk-1) + vmask(ji,jj-1,jk)          &
155                     &                           + vmask(ji,jj-1,jk-1) + vmask(ji,jj  ,jk) , 1._wp  )
156                     !
157                  zahu_w = (   pahu(ji  ,jj,jk-1) + pahu(ji-1,jj,jk)    &
158                     &       + pahu(ji-1,jj,jk-1) + pahu(ji  ,jj,jk)  ) * zmsku
159                  zahv_w = (   pahv(ji,jj  ,jk-1) + pahv(ji,jj-1,jk)    &
160                     &       + pahv(ji,jj-1,jk-1) + pahv(ji,jj  ,jk)  ) * zmskv
161                     !
162                  ah_wslp2(ji,jj,jk) = zahu_w * wslpi(ji,jj,jk) * wslpi(ji,jj,jk)   &
163                     &               + zahv_w * wslpj(ji,jj,jk) * wslpj(ji,jj,jk)
164               END DO
165            END DO
166         END DO
167         !
168         IF( ln_traldf_msc ) THEN                ! stabilizing vertical diffusivity coefficient
169!$OMP PARALLEL DO schedule(static) private(jk, jj, ji)
170            DO jk = 2, jpkm1
171               DO jj = 2, jpjm1
172                  DO ji = fs_2, fs_jpim1
173                     akz(ji,jj,jk) = 0.25_wp * (                                                                     &
174                        &              ( pahu(ji  ,jj,jk) + pahu(ji  ,jj,jk-1) ) / ( e1u(ji  ,jj) * e1u(ji  ,jj) )   &
175                        &            + ( pahu(ji-1,jj,jk) + pahu(ji-1,jj,jk-1) ) / ( e1u(ji-1,jj) * e1u(ji-1,jj) )   &
176                        &            + ( pahv(ji,jj  ,jk) + pahv(ji,jj  ,jk-1) ) / ( e2v(ji,jj  ) * e2v(ji,jj  ) )   &
177                        &            + ( pahv(ji,jj-1,jk) + pahv(ji,jj-1,jk-1) ) / ( e2v(ji,jj-1) * e2v(ji,jj-1) )   )
178                  END DO
179               END DO
180            END DO
181            !
182            IF( ln_traldf_blp ) THEN                ! bilaplacian operator
183!$OMP PARALLEL DO schedule(static) private(jk, jj, ji)
184               DO jk = 2, jpkm1
185                  DO jj = 1, jpjm1
186                     DO ji = 1, fs_jpim1
187                        akz(ji,jj,jk) = 16._wp * ah_wslp2(ji,jj,jk)   &
188                           &          * (  akz(ji,jj,jk) + ah_wslp2(ji,jj,jk) / ( e3w_n(ji,jj,jk) * e3w_n(ji,jj,jk) )  )
189                     END DO
190                  END DO
191               END DO
192            ELSEIF( ln_traldf_lap ) THEN              ! laplacian operator
193!$OMP PARALLEL DO schedule(static) private(jk, jj, ji, ze3w_2, zcoef0)
194               DO jk = 2, jpkm1
195                  DO jj = 1, jpjm1
196                     DO ji = 1, fs_jpim1
197                        ze3w_2 = e3w_n(ji,jj,jk) * e3w_n(ji,jj,jk)
198                        zcoef0 = z2dt * (  akz(ji,jj,jk) + ah_wslp2(ji,jj,jk) / ze3w_2  )
199                        akz(ji,jj,jk) = MAX( zcoef0 - 0.5_wp , 0._wp ) * ze3w_2 * z1_2dt
200                     END DO
201                  END DO
202               END DO
203           ENDIF
204           !
205         ELSE                                    ! 33 flux set to zero with akz=ah_wslp2 ==>> computed in full implicit
206!$OMP PARALLEL WORKSHARE
207            akz(:,:,:) = ah_wslp2(:,:,:)     
208!$OMP END PARALLEL WORKSHARE
209         ENDIF
210      ENDIF
211      !
212      !                                                          ! ===========
213      DO jn = 1, kjpt                                            ! tracer loop
214         !                                                       ! ===========
215         !                                               
216         !!----------------------------------------------------------------------
217         !!   I - masked horizontal derivative
218         !!----------------------------------------------------------------------
219!!gm : bug.... why (x,:,:)?   (1,jpj,:) and (jpi,1,:) should be sufficient....
220!$OMP PARALLEL
221!$OMP WORKSHARE
222         zdit (1,:,:) = 0._wp     ;     zdit (jpi,:,:) = 0._wp
223         zdjt (1,:,:) = 0._wp     ;     zdjt (jpi,:,:) = 0._wp
224!$OMP END WORKSHARE
225         !!end
226
227         ! Horizontal tracer gradient
228!$OMP DO schedule(static) private(jk, jj, ji)
229         DO jk = 1, jpkm1
230            DO jj = 1, jpjm1
231               DO ji = 1, fs_jpim1   ! vector opt.
232                  zdit(ji,jj,jk) = ( ptb(ji+1,jj  ,jk,jn) - ptb(ji,jj,jk,jn) ) * umask(ji,jj,jk)
233                  zdjt(ji,jj,jk) = ( ptb(ji  ,jj+1,jk,jn) - ptb(ji,jj,jk,jn) ) * vmask(ji,jj,jk)
234               END DO
235            END DO
236         END DO
237!$OMP END DO NOWAIT
238!$OMP END PARALLEL
239         IF( ln_zps ) THEN      ! botton and surface ocean correction of the horizontal gradient
240!$OMP PARALLEL DO schedule(static) private(jj, ji)
241            DO jj = 1, jpjm1              ! bottom correction (partial bottom cell)
242               DO ji = 1, fs_jpim1   ! vector opt.
243                  zdit(ji,jj,mbku(ji,jj)) = pgu(ji,jj,jn)         
244                  zdjt(ji,jj,mbkv(ji,jj)) = pgv(ji,jj,jn)
245               END DO
246            END DO
247            IF( ln_isfcav ) THEN      ! first wet level beneath a cavity
248!$OMP PARALLEL DO schedule(static) private(jj, ji)
249               DO jj = 1, jpjm1
250                  DO ji = 1, fs_jpim1   ! vector opt.
251                     IF( miku(ji,jj) > 1 )   zdit(ji,jj,miku(ji,jj)) = pgui(ji,jj,jn)         
252                     IF( mikv(ji,jj) > 1 )   zdjt(ji,jj,mikv(ji,jj)) = pgvi(ji,jj,jn)     
253                  END DO
254               END DO
255            ENDIF
256         ENDIF
257         !
258         !!----------------------------------------------------------------------
259         !!   II - horizontal trend  (full)
260         !!----------------------------------------------------------------------
261!$OMP PARALLEL
262!$OMP DO schedule(static) private(jj, ji)
263               DO jj = 1 , jpj            !==  Horizontal fluxes
264                  DO ji = 1, jpi   ! vector opt.
265                         zdk1t(ji,jj) = ( ptb(ji,jj,1,jn) - ptb(ji,jj,2,jn) ) * wmask(ji,jj,2) 
266                         zdkt(ji,jj) = zdk1t(ji,jj)
267                  END DO
268               END DO
269!$OMP DO schedule(static) private(jj, ji, zmsku, zmskv, zabe1, zabe2, zcof1, zcof2)
270               DO jj = 1 , jpjm1            !==  Horizontal fluxes
271                  DO ji = 1, fs_jpim1   ! vector opt.
272                  zabe1 = pahu(ji,jj,1) * e2_e1u(ji,jj) * e3u_n(ji,jj,1)
273                  zabe2 = pahv(ji,jj,1) * e1_e2v(ji,jj) * e3v_n(ji,jj,1)
274                  !
275                  zmsku = 1. / MAX(  wmask(ji+1,jj,1  ) + wmask(ji,jj,2)   &
276                     &             + wmask(ji+1,jj,2) + wmask(ji,jj,1 ), 1.)
277                  !
278                  zmskv = 1. / MAX(  wmask(ji,jj+1,1  ) + wmask(ji,jj,2)   &
279                     &             + wmask(ji,jj+1,2) + wmask(ji,jj,1  ), 1.)
280                  !
281                  zcof1 = - pahu(ji,jj,1) * e2u(ji,jj) * uslp(ji,jj,1) * zmsku
282                  zcof2 = - pahv(ji,jj,1) * e1v(ji,jj) * vslp(ji,jj,1) * zmskv
283                  !
284                  zftu(ji,jj,1 ) = (  zabe1 * zdit(ji,jj,1)   &
285                     &               + zcof1 * (  zdkt (ji+1,jj) + zdk1t(ji,jj)   &
286                     &                          + zdk1t(ji+1,jj) + zdkt (ji,jj))  ) * umask(ji,jj,1)
287                  zftv(ji,jj,1 ) = (  zabe2 * zdjt(ji,jj,1)   &
288                     &               + zcof2 * (  zdkt (ji,jj+1) + zdk1t(ji,jj)   &
289                     &                          + zdk1t(ji,jj+1) + zdkt (ji,jj))  ) * vmask(ji,jj,1)
290               END DO
291            END DO
292            !
293!$OMP DO schedule(static) private(jj, ji)
294            DO jj = 2 , jpjm1          !== horizontal divergence and add to pta
295               DO ji = fs_2, fs_jpim1   ! vector opt.
296                  pta(ji,jj,1,jn) = pta(ji,jj,1,jn) + zsign * (zftu(ji,jj,1) - zftu(ji-1,jj,1)      &
297                     &               + zftv(ji,jj,1) - zftv(ji,jj-1,1)  )   &
298                     &                          * r1_e1e2t(ji,jj) / e3t_n(ji,jj,1)
299               END DO
300            END DO
301!$OMP END DO NOWAIT
302            DO jk = 2, jpkm1
303!$OMP DO schedule(static) private(jj, ji)
304               DO jj = 1 , jpj            !==  Horizontal fluxes
305                  DO ji = 1, jpi   ! vector opt.
306                zdk1t(ji,jj) = ( ptb(ji,jj,jk,jn) - ptb(ji,jj,jk+1,jn) ) * wmask(ji,jj,jk+1)
307                zdkt(ji,jj) = ( ptb(ji,jj,jk-1,jn) - ptb(ji,jj,jk,jn) ) * wmask(ji,jj,jk)
308                  END DO
309               END DO
310!$OMP DO schedule(static) private(jj, ji, zmsku, zmskv, zabe1, zabe2, zcof1, zcof2)
311               DO jj = 1 , jpjm1            !==  Horizontal fluxes
312                  DO ji = 1, fs_jpim1   ! vector opt.
313                        zabe1 = pahu(ji,jj,jk) * e2_e1u(ji,jj) * e3u_n(ji,jj,jk)
314                        zabe2 = pahv(ji,jj,jk) * e1_e2v(ji,jj) * e3v_n(ji,jj,jk)
315                        !
316                        zmsku = 1. / MAX(  wmask(ji+1,jj,jk  ) + wmask(ji,jj,jk+1)   &
317                     &             + wmask(ji+1,jj,jk+1) + wmask(ji,jj,jk  ), 1.)
318                        !
319                        zmskv = 1. / MAX(  wmask(ji,jj+1,jk  ) + wmask(ji,jj,jk+1)   &
320                     &             + wmask(ji,jj+1,jk+1) + wmask(ji,jj,jk  ), 1.)
321                        !
322                        zcof1 = - pahu(ji,jj,jk) * e2u(ji,jj) * uslp(ji,jj,jk) * zmsku
323                        zcof2 = - pahv(ji,jj,jk) * e1v(ji,jj) * vslp(ji,jj,jk) * zmskv
324                  !
325                        zftu(ji,jj,jk ) = (  zabe1 * zdit(ji,jj,jk)   &
326                     &               + zcof1 * (  zdkt (ji+1,jj) + zdk1t(ji,jj) &
327                     &                          + zdk1t(ji+1,jj) + zdkt (ji,jj))  ) * umask(ji,jj,jk)
328                        zftv(ji,jj,jk) = (  zabe2 * zdjt(ji,jj,jk)   &
329                     &               + zcof2 * (  zdkt (ji,jj+1) + zdk1t(ji,jj) &
330                     &                          + zdk1t(ji,jj+1) + zdkt (ji,jj))  ) * vmask(ji,jj,jk)
331                  END DO
332               END DO
333            !
334!$OMP DO schedule(static) private(jj, ji)
335               DO jj = 2 , jpjm1          !== horizontal divergence and add to pta
336                  DO ji = fs_2, fs_jpim1   ! vector opt.
337                        pta(ji,jj,jk,jn) = pta(ji,jj,jk,jn) + zsign * (zftu(ji,jj,jk) - zftu(ji-1,jj,jk)      &
338                     &               + zftv(ji,jj,jk) - zftv(ji,jj-1,jk)  )   &
339                     &                          * r1_e1e2t(ji,jj) / e3t_n(ji,jj,jk)
340                  END DO
341               END DO
342!$OMP END DO NOWAIT
343            END DO
344!$OMP END PARALLEL
345
346
347         !!----------------------------------------------------------------------
348         !!   III - vertical trend (full)
349         !!----------------------------------------------------------------------
350         !
351!$OMP PARALLEL
352!$OMP WORKSHARE
353         ztfw(1,:,:) = 0._wp     ;     ztfw(jpi,:,:) = 0._wp
354         !
355         ! Vertical fluxes
356         ! ---------------
357         !                          ! Surface and bottom vertical fluxes set to zero
358         ztfw(:,:, 1 ) = 0._wp      ;      ztfw(:,:,jpk) = 0._wp
359!$OMP END WORKSHARE
360         
361!$OMP DO schedule(static) private(jk, jj, ji, zmsku, zmskv, zahu_w, zahv_w, zcoef3, zcoef4)
362         DO jk = 2, jpkm1           ! interior (2=<jk=<jpk-1)
363            DO jj = 2, jpjm1
364               DO ji = fs_2, fs_jpim1   ! vector opt.
365                  !
366                  zmsku = wmask(ji,jj,jk) / MAX(   umask(ji  ,jj,jk-1) + umask(ji-1,jj,jk)          &
367                     &                           + umask(ji-1,jj,jk-1) + umask(ji  ,jj,jk) , 1._wp  )
368                  zmskv = wmask(ji,jj,jk) / MAX(   vmask(ji,jj  ,jk-1) + vmask(ji,jj-1,jk)          &
369                     &                           + vmask(ji,jj-1,jk-1) + vmask(ji,jj  ,jk) , 1._wp  )
370                     !
371                  zahu_w = (   pahu(ji  ,jj,jk-1) + pahu(ji-1,jj,jk)    &
372                     &       + pahu(ji-1,jj,jk-1) + pahu(ji  ,jj,jk)  ) * zmsku
373                  zahv_w = (   pahv(ji,jj  ,jk-1) + pahv(ji,jj-1,jk)    &
374                     &       + pahv(ji,jj-1,jk-1) + pahv(ji,jj  ,jk)  ) * zmskv
375                     !
376                  zcoef3 = - zahu_w * e2t(ji,jj) * zmsku * wslpi (ji,jj,jk)   !wslpi & j are already w-masked
377                  zcoef4 = - zahv_w * e1t(ji,jj) * zmskv * wslpj (ji,jj,jk)
378                  !
379                  ztfw(ji,jj,jk) = zcoef3 * (   zdit(ji  ,jj  ,jk-1) + zdit(ji-1,jj  ,jk)      &
380                     &                        + zdit(ji-1,jj  ,jk-1) + zdit(ji  ,jj  ,jk)  )   &
381                     &           + zcoef4 * (   zdjt(ji  ,jj  ,jk-1) + zdjt(ji  ,jj-1,jk)      &
382                     &                        + zdjt(ji  ,jj-1,jk-1) + zdjt(ji  ,jj  ,jk)  )
383               END DO
384            END DO
385         END DO
386!$OMP END DO NOWAIT
387!$OMP END PARALLEL
388         !                                !==  add the vertical 33 flux  ==!
389         IF( ln_traldf_lap ) THEN               ! laplacian case: eddy coef = ah_wslp2 - akz
390!$OMP PARALLEL DO schedule(static) private(jk, jj, ji)
391            DO jk = 2, jpkm1       
392               DO jj = 1, jpjm1
393                  DO ji = fs_2, fs_jpim1
394                     ztfw(ji,jj,jk) = ztfw(ji,jj,jk) + e1e2t(ji,jj) / e3w_n(ji,jj,jk) * wmask(ji,jj,jk)   &
395                        &                            * ( ah_wslp2(ji,jj,jk) - akz(ji,jj,jk) )             &
396                        &                            * ( ptb(ji,jj,jk-1,jn) - ptb(ji,jj,jk,jn) )
397                  END DO
398               END DO
399            END DO
400            !
401         ELSE                                   ! bilaplacian
402            SELECT CASE( kpass )
403            CASE(  1  )                            ! 1st pass : eddy coef = ah_wslp2
404!$OMP PARALLEL DO schedule(static) private(jk, jj, ji)
405               DO jk = 2, jpkm1 
406                  DO jj = 1, jpjm1
407                     DO ji = fs_2, fs_jpim1
408                        ztfw(ji,jj,jk) = ztfw(ji,jj,jk)    &
409                           &           + ah_wslp2(ji,jj,jk) * e1e2t(ji,jj)   &
410                           &           * ( ptb(ji,jj,jk-1,jn) - ptb(ji,jj,jk,jn) ) / e3w_n(ji,jj,jk) * wmask(ji,jj,jk)
411                     END DO
412                  END DO
413               END DO
414            CASE(  2  )                         ! 2nd pass : eddy flux = ah_wslp2 and akz applied on ptb  and ptbb gradients, resp.
415!$OMP PARALLEL DO schedule(static) private(jk, jj, ji)
416               DO jk = 2, jpkm1 
417                  DO jj = 1, jpjm1
418                     DO ji = fs_2, fs_jpim1
419                        ztfw(ji,jj,jk) = ztfw(ji,jj,jk) + e1e2t(ji,jj) / e3w_n(ji,jj,jk) * wmask(ji,jj,jk)                      &
420                           &                            * (  ah_wslp2(ji,jj,jk) * ( ptb (ji,jj,jk-1,jn) - ptb (ji,jj,jk,jn) )   &
421                           &                               + akz     (ji,jj,jk) * ( ptbb(ji,jj,jk-1,jn) - ptbb(ji,jj,jk,jn) )   )
422                     END DO
423                  END DO
424               END DO
425            END SELECT
426         ENDIF
427         !         
428!$OMP PARALLEL DO schedule(static) private(jk, jj, ji)
429         DO jk = 1, jpkm1                 !==  Divergence of vertical fluxes added to pta  ==!
430            DO jj = 2, jpjm1
431               DO ji = fs_2, fs_jpim1   ! vector opt.
432                  pta(ji,jj,jk,jn) = pta(ji,jj,jk,jn) + zsign * (  ztfw (ji,jj,jk) - ztfw(ji,jj,jk+1)  )   &
433                     &                                        * r1_e1e2t(ji,jj) / e3t_n(ji,jj,jk)
434               END DO
435            END DO
436         END DO
437         !
438         IF( ( kpass == 1 .AND. ln_traldf_lap ) .OR.  &     !==  first pass only (  laplacian)  ==!
439             ( kpass == 2 .AND. ln_traldf_blp ) ) THEN      !==  2nd   pass      (bilaplacian)  ==!
440            !
441            !                             ! "Poleward" diffusive heat or salt transports (T-S case only)
442            IF( cdtype == 'TRA' .AND. ln_diaptr ) THEN
443               ! note sign is reversed to give down-gradient diffusive transports (#1043)
444               IF( jn == jp_tem)   htr_ldf(:) = ptr_sj( -zftv(:,:,:) )
445               IF( jn == jp_sal)   str_ldf(:) = ptr_sj( -zftv(:,:,:) )
446            ENDIF
447            !
448            IF( iom_use("udiff_heattr") .OR. iom_use("vdiff_heattr") ) THEN
449              !
450              IF( cdtype == 'TRA' .AND. jn == jp_tem  ) THEN
451!$OMP PARALLEL
452!$OMP WORKSHARE
453                  z2d(:,:) = zftu(ji,jj,1) 
454!$OMP END WORKSHARE
455!$OMP DO schedule(static) private(jk, jj, ji)
456                  DO jk = 2, jpkm1
457                     DO jj = 2, jpjm1
458                        DO ji = fs_2, fs_jpim1   ! vector opt.
459                           z2d(ji,jj) = z2d(ji,jj) + zftu(ji,jj,jk) 
460                        END DO
461                     END DO
462                  END DO
463!!gm CAUTION I think there is an error of sign when using BLP operator....
464!!gm         a multiplication by zsign is required (to be checked twice !)
465!$OMP WORKSHARE
466                  z2d(:,:) = - rau0_rcp * z2d(:,:)     ! note sign is reversed to give down-gradient diffusive transports (#1043)
467!$OMP END WORKSHARE NOWAIT
468!$OMP END PARALLEL
469                  CALL lbc_lnk( z2d, 'U', -1. )
470                  CALL iom_put( "udiff_heattr", z2d )                  ! heat transport in i-direction
471                  !
472!$OMP PARALLEL
473!$OMP WORKSHARE
474                  z2d(:,:) = zftv(ji,jj,1) 
475!$OMP END WORKSHARE
476!$OMP DO schedule(static) private(jk, jj, ji)
477                  DO jk = 2, jpkm1
478                     DO jj = 2, jpjm1
479                        DO ji = fs_2, fs_jpim1   ! vector opt.
480                           z2d(ji,jj) = z2d(ji,jj) + zftv(ji,jj,jk) 
481                        END DO
482                     END DO
483                  END DO
484!$OMP WORKSHARE
485                  z2d(:,:) = - rau0_rcp * z2d(:,:)     ! note sign is reversed to give down-gradient diffusive transports (#1043)
486!$OMP END WORKSHARE NOWAIT
487!$OMP END PARALLEL
488                  CALL lbc_lnk( z2d, 'V', -1. )
489                  CALL iom_put( "vdiff_heattr", z2d )                  !  heat transport in i-direction
490               END IF
491               !
492            ENDIF
493            !
494         ENDIF                                                    !== end pass selection  ==!
495         !
496         !                                                        ! ===============
497      END DO                                                      ! end tracer loop
498      !                                                           ! ===============
499      !
500      CALL wrk_dealloc( jpi, jpj,      zdkt, zdk1t, z2d ) 
501      CALL wrk_dealloc( jpi, jpj, jpk, zdit, zdjt , zftu, zftv, ztfw  ) 
502      !
503      IF( nn_timing == 1 )  CALL timing_stop('tra_ldf_iso')
504      !
505   END SUBROUTINE tra_ldf_iso
506
507   !!==============================================================================
508END MODULE traldf_iso
Note: See TracBrowser for help on using the repository browser.