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.
traadv_ubs.F90 in branches/UKMO/dev_r5518_obs_oper_update_icethick/NEMOGCM/NEMO/OPA_SRC/TRA – NEMO

source: branches/UKMO/dev_r5518_obs_oper_update_icethick/NEMOGCM/NEMO/OPA_SRC/TRA/traadv_ubs.F90 @ 9987

Last change on this file since 9987 was 9987, checked in by emmafiedler, 6 years ago

Merge with GO6 FOAMv14 package branch r9288

File size: 18.5 KB
RevLine 
[503]1MODULE traadv_ubs
2   !!==============================================================================
3   !!                       ***  MODULE  traadv_ubs  ***
4   !! Ocean active tracers:  horizontal & vertical advective trend
5   !!==============================================================================
[2528]6   !! History :  1.0  !  2006-08  (L. Debreu, R. Benshila)  Original code
7   !!            3.3  !  2010-05  (C. Ethe, G. Madec)  merge TRC-TRA + switch from velocity to transport
[503]8   !!----------------------------------------------------------------------
9
10   !!----------------------------------------------------------------------
11   !!   tra_adv_ubs : update the tracer trend with the horizontal
12   !!                 advection trends using a third order biaised scheme 
13   !!----------------------------------------------------------------------
[3625]14   USE oce            ! ocean dynamics and active tracers
15   USE dom_oce        ! ocean space and time domain
[4990]16   USE trc_oce        ! share passive tracers/Ocean variables
17   USE trd_oce        ! trends: ocean variables
18   USE trdtra         ! trends manager: tracers
19   USE dynspg_oce     ! choice/control of key cpp for surface pressure gradient
20   USE diaptr         ! poleward transport diagnostics
21   !
22   USE lib_mpp        ! I/O library
[3625]23   USE lbclnk         ! ocean lateral boundary condition (or mpp link)
24   USE in_out_manager ! I/O manager
25   USE wrk_nemo       ! Memory Allocation
26   USE timing         ! Timing
27   USE lib_fortran    ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined) 
[503]28
29   IMPLICIT NONE
30   PRIVATE
31
32   PUBLIC   tra_adv_ubs   ! routine called by traadv module
33
[2528]34   LOGICAL :: l_trd  ! flag to compute trends or not
[503]35
36   !! * Substitutions
37#  include "domzgr_substitute.h90"
38#  include "vectopt_loop_substitute.h90"
39   !!----------------------------------------------------------------------
[2528]40   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
[1152]41   !! $Id$
[2528]42   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
[503]43   !!----------------------------------------------------------------------
44CONTAINS
45
[3294]46   SUBROUTINE tra_adv_ubs ( kt, kit000, cdtype, p2dt, pun, pvn, pwn,      &
[2528]47      &                                       ptb, ptn, pta, kjpt )
[503]48      !!----------------------------------------------------------------------
49      !!                  ***  ROUTINE tra_adv_ubs  ***
50      !!                 
51      !! ** Purpose :   Compute the now trend due to the advection of tracers
52      !!      and add it to the general trend of passive tracer equations.
53      !!
[4990]54      !! ** Method  :   The upstream biased scheme (UBS) is based on a 3rd order
[3787]55      !!      upstream-biased parabolic interpolation (Shchepetkin and McWilliams 2005)
[519]56      !!      It is only used in the horizontal direction.
57      !!      For example the i-component of the advective fluxes are given by :
[3787]58      !!                !  e2u e3u un ( mi(Tn) - zltu(i  ) )   if un(i) >= 0
[4990]59      !!          ztu = !  or
[3787]60      !!                !  e2u e3u un ( mi(Tn) - zltu(i+1) )   if un(i) < 0
[519]61      !!      where zltu is the second derivative of the before temperature field:
62      !!          zltu = 1/e3t di[ e2u e3u / e1u di[Tb] ]
63      !!      This results in a dissipatively dominant (i.e. hyper-diffusive)
64      !!      truncation error. The overall performance of the advection scheme
65      !!      is similar to that reported in (Farrow and Stevens, 1995).
66      !!      For stability reasons, the first term of the fluxes which corresponds
67      !!      to a second order centered scheme is evaluated using the now velocity
68      !!      (centered in time) while the second term which is the diffusive part
69      !!      of the scheme, is evaluated using the before velocity (forward in time).
70      !!      Note that UBS is not positive. Do not use it on passive tracers.
[3787]71      !!                On the vertical, the advection is evaluated using a TVD scheme,
72      !!      as the UBS have been found to be too diffusive.
[503]73      !!
[2528]74      !! ** Action : - update (pta) with the now advective tracer trends
[519]75      !!
76      !! Reference : Shchepetkin, A. F., J. C. McWilliams, 2005, Ocean Modelling, 9, 347-404.
77      !!             Farrow, D.E., Stevens, D.P., 1995, J. Phys. Ocean. 25, 1731Ð1741.
[503]78      !!----------------------------------------------------------------------
[2528]79      INTEGER                              , INTENT(in   ) ::   kt              ! ocean time-step index
[3294]80      INTEGER                              , INTENT(in   ) ::   kit000          ! first time step index
[2528]81      CHARACTER(len=3)                     , INTENT(in   ) ::   cdtype          ! =TRA or TRC (tracer indicator)
82      INTEGER                              , INTENT(in   ) ::   kjpt            ! number of tracers
83      REAL(wp), DIMENSION(        jpk     ), INTENT(in   ) ::   p2dt            ! vertical profile of tracer time-step
[3787]84      REAL(wp), DIMENSION(jpi,jpj,jpk     ), INTENT(in   ) ::   pun, pvn, pwn   ! 3 ocean transport components
[2528]85      REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in   ) ::   ptb, ptn        ! before and now tracer fields
86      REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(inout) ::   pta             ! tracer trend
[2715]87      !
88      INTEGER  ::   ji, jj, jk, jn   ! dummy loop indices
89      REAL(wp) ::   ztra, zbtr, zcoef, z2dtt                       ! local scalars
90      REAL(wp) ::   zfp_ui, zfm_ui, zcenut, ztak, zfp_wk, zfm_wk   !   -      -
91      REAL(wp) ::   zfp_vj, zfm_vj, zcenvt, zeeu, zeev, z_hdivn    !   -      -
[3294]92      REAL(wp), POINTER, DIMENSION(:,:,:) :: ztu, ztv, zltu, zltv, zti, ztw
[503]93      !!----------------------------------------------------------------------
[3294]94      !
95      IF( nn_timing == 1 )  CALL timing_start('tra_adv_ubs')
96      !
97      CALL wrk_alloc( jpi, jpj, jpk, ztu, ztv, zltu, zltv, zti, ztw )
98      !
99      IF( kt == kit000 )  THEN
[503]100         IF(lwp) WRITE(numout,*)
[2528]101         IF(lwp) WRITE(numout,*) 'tra_adv_ubs :  horizontal UBS advection scheme on ', cdtype
[503]102         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~'
103      ENDIF
[2528]104      !
[4499]105      l_trd = .FALSE.
106      IF( ( cdtype == 'TRA' .AND. l_trdtra ) .OR. ( cdtype == 'TRC' .AND. l_trdtrc ) ) l_trd = .TRUE.
107      !
[2528]108      !                                                          ! ===========
109      DO jn = 1, kjpt                                            ! tracer loop
110         !                                                       ! ===========
111         ! 1. Bottom value : flux set to zero
112         ! ----------------------------------
113         zltu(:,:,jpk) = 0.e0       ;      zltv(:,:,jpk) = 0.e0
114         !                                             
115         DO jk = 1, jpkm1                                 ! Horizontal slab
116            !                                   
117            !  Laplacian
118            DO jj = 1, jpjm1            ! First derivative (gradient)
119               DO ji = 1, fs_jpim1   ! vector opt.
120                  zeeu = e2u(ji,jj) * fse3u(ji,jj,jk) / e1u(ji,jj) * umask(ji,jj,jk)
121                  zeev = e1v(ji,jj) * fse3v(ji,jj,jk) / e2v(ji,jj) * vmask(ji,jj,jk)
122                  ztu(ji,jj,jk) = zeeu * ( ptb(ji+1,jj  ,jk,jn) - ptb(ji,jj,jk,jn) )
123                  ztv(ji,jj,jk) = zeev * ( ptb(ji  ,jj+1,jk,jn) - ptb(ji,jj,jk,jn) )
124               END DO
[503]125            END DO
[2528]126            DO jj = 2, jpjm1            ! Second derivative (divergence)
127               DO ji = fs_2, fs_jpim1   ! vector opt.
128                  zcoef = 1. / ( 6. * fse3t(ji,jj,jk) )
129                  zltu(ji,jj,jk) = (  ztu(ji,jj,jk) - ztu(ji-1,jj,jk)  ) * zcoef
130                  zltv(ji,jj,jk) = (  ztv(ji,jj,jk) - ztv(ji,jj-1,jk)  ) * zcoef
131               END DO
[503]132            END DO
[2528]133            !                                   
134         END DO                                           ! End of slab         
135         CALL lbc_lnk( zltu, 'T', 1. )   ;    CALL lbc_lnk( zltv, 'T', 1. )   ! Lateral boundary cond. (unchanged sgn)
[503]136
[2528]137         !   
138         !  Horizontal advective fluxes               
139         DO jk = 1, jpkm1                                 ! Horizontal slab
140            DO jj = 1, jpjm1
141               DO ji = 1, fs_jpim1   ! vector opt.
[3787]142                  ! upstream transport (x2)
[2528]143                  zfp_ui = pun(ji,jj,jk) + ABS( pun(ji,jj,jk) )
144                  zfm_ui = pun(ji,jj,jk) - ABS( pun(ji,jj,jk) )
145                  zfp_vj = pvn(ji,jj,jk) + ABS( pvn(ji,jj,jk) )
146                  zfm_vj = pvn(ji,jj,jk) - ABS( pvn(ji,jj,jk) )
[3787]147                  ! 2nd order centered advective fluxes (x2)
148                  zcenut = pun(ji,jj,jk) * ( ptn(ji,jj,jk,jn) + ptn(ji+1,jj  ,jk,jn) )
149                  zcenvt = pvn(ji,jj,jk) * ( ptn(ji,jj,jk,jn) + ptn(ji  ,jj+1,jk,jn) )
150                  ! UBS advective fluxes
[4990]151                  ztu(ji,jj,jk) = 0.5 * ( zcenut - zfp_ui * zltu(ji,jj,jk) - zfm_ui * zltu(ji+1,jj,jk) )
152                  ztv(ji,jj,jk) = 0.5 * ( zcenvt - zfp_vj * zltv(ji,jj,jk) - zfm_vj * zltv(ji,jj+1,jk) )
[2528]153               END DO
[503]154            END DO
[2528]155         END DO                                           ! End of slab         
[503]156
[2528]157         zltu(:,:,:) = pta(:,:,:,jn)      ! store pta trends
[503]158
[4990]159         DO jk = 1, jpkm1                 ! Horizontal advective trends
[503]160            DO jj = 2, jpjm1
161               DO ji = fs_2, fs_jpim1   ! vector opt.
[4990]162                  pta(ji,jj,jk,jn) = pta(ji,jj,jk,jn)                        &
163                     &             - (  ztu(ji,jj,jk) - ztu(ji-1,jj  ,jk)    &
164                     &                + ztv(ji,jj,jk) - ztv(ji  ,jj-1,jk)  ) / ( e1e2t(ji,jj) * fse3t(ji,jj,jk) )
[503]165               END DO
166            END DO
[2528]167            !                                             
168         END DO                                           !   End of slab
[503]169
[2528]170         ! Horizontal trend used in tra_adv_ztvd subroutine
171         zltu(:,:,:) = pta(:,:,:,jn) - zltu(:,:,:)
[503]172
[4990]173         !               
174         IF( l_trd ) THEN                  ! trend diagnostics
175             CALL trd_tra( kt, cdtype, jn, jptra_xad, ztu, pun, ptn(:,:,:,jn) )
176             CALL trd_tra( kt, cdtype, jn, jptra_yad, ztv, pvn, ptn(:,:,:,jn) )
[2528]177         END IF
178         !                                 ! "Poleward" heat and salt transports (contribution of upstream fluxes)
[9987]179         IF( cdtype == 'TRA' .AND. ln_diaptr ) CALL dia_ptr_ohst_components( jn, 'adv', ztv(:,:,:) )
[2528]180         
181         ! TVD scheme for the vertical direction 
182         ! ----------------------
183         IF( l_trd )   zltv(:,:,:) = pta(:,:,:,jn)          ! store pta if trend diag.
[503]184
[2528]185         !  Bottom value : flux set to zero
186         ztw(:,:,jpk) = 0.e0   ;   zti(:,:,jpk) = 0.e0
[503]187
[2528]188         ! Surface value
189         IF( lk_vvl ) THEN   ;   ztw(:,:,1) = 0.e0                      ! variable volume : flux set to zero
190         ELSE                ;   ztw(:,:,1) = pwn(:,:,1) * ptb(:,:,1,jn)   ! free constant surface
191         ENDIF
192         !  upstream advection with initial mass fluxes & intermediate update
193         ! -------------------------------------------------------------------
194         ! Interior value
195         DO jk = 2, jpkm1
196            DO jj = 1, jpj
197               DO ji = 1, jpi
198                   zfp_wk = pwn(ji,jj,jk) + ABS( pwn(ji,jj,jk) )
199                   zfm_wk = pwn(ji,jj,jk) - ABS( pwn(ji,jj,jk) )
200                   ztw(ji,jj,jk) = 0.5 * (  zfp_wk * ptb(ji,jj,jk,jn) + zfm_wk * ptb(ji,jj,jk-1,jn)  )
201               END DO
202            END DO
203         END DO 
204         ! update and guess with monotonic sheme
[503]205         DO jk = 1, jpkm1
[2528]206            z2dtt = p2dt(jk)
[503]207            DO jj = 2, jpjm1
208               DO ji = fs_2, fs_jpim1   ! vector opt.
[2528]209                  zbtr = 1. / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
210                  ztak = - ( ztw(ji,jj,jk) - ztw(ji,jj,jk+1) ) * zbtr
211                  pta(ji,jj,jk,jn) =   pta(ji,jj,jk,jn) +  ztak 
212                  zti(ji,jj,jk)    = ( ptb(ji,jj,jk,jn) + z2dtt * ( ztak + zltu(ji,jj,jk) ) ) * tmask(ji,jj,jk)
[503]213               END DO
214            END DO
215         END DO
216         !
[2528]217         CALL lbc_lnk( zti, 'T', 1. )      ! Lateral boundary conditions on zti, zsi   (unchanged sign)
[503]218
[2528]219         !  antidiffusive flux : high order minus low order
220         ztw(:,:,1) = 0.e0       ! Surface value
221         DO jk = 2, jpkm1        ! Interior value
222            DO jj = 1, jpj
223               DO ji = 1, jpi
224                  ztw(ji,jj,jk) = 0.5 * pwn(ji,jj,jk) * ( ptn(ji,jj,jk,jn) + ptn(ji,jj,jk-1,jn) ) - ztw(ji,jj,jk)
225               END DO
[503]226            END DO
227         END DO
[2528]228         !
229         CALL nonosc_z( ptb(:,:,:,jn), ztw, zti, p2dt )      !  monotonicity algorithm
[503]230
[2528]231         !  final trend with corrected fluxes
232         DO jk = 1, jpkm1
233            DO jj = 2, jpjm1 
234               DO ji = fs_2, fs_jpim1   ! vector opt.   
235                  zbtr = 1. / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
236                  ! k- vertical advective trends 
237                  ztra = - zbtr * ( ztw(ji,jj,jk) - ztw(ji,jj,jk+1) )
238                  ! added to the general tracer trends
239                  pta(ji,jj,jk,jn) = pta(ji,jj,jk,jn) + ztra
240               END DO
[503]241            END DO
242         END DO
243
[2528]244         !  Save the final vertical advective trends
245         IF( l_trd )  THEN                        ! vertical advective trend diagnostics
246            DO jk = 1, jpkm1                       ! (compute -w.dk[ptn]= -dk[w.ptn] + ptn.dk[w])
247               DO jj = 2, jpjm1
248                  DO ji = fs_2, fs_jpim1   ! vector opt.
249                     zbtr = 1.e0 / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
250                     z_hdivn = (  pwn(ji,jj,jk) - pwn(ji,jj,jk+1)  ) * zbtr
251                     zltv(ji,jj,jk) = pta(ji,jj,jk,jn) - zltv(ji,jj,jk) + ptn(ji,jj,jk,jn) * z_hdivn
252                  END DO
253               END DO
[503]254            END DO
[4990]255            CALL trd_tra( kt, cdtype, jn, jptra_zad, zltv )
[2528]256         ENDIF
257         !
[4990]258      END DO
[503]259      !
[3294]260      CALL wrk_dealloc( jpi, jpj, jpk, ztu, ztv, zltu, zltv, zti, ztw )
[2715]261      !
[3294]262      IF( nn_timing == 1 )  CALL timing_stop('tra_adv_ubs')
263      !
[2528]264   END SUBROUTINE tra_adv_ubs
[503]265
266
[2528]267   SUBROUTINE nonosc_z( pbef, pcc, paft, p2dt )
[503]268      !!---------------------------------------------------------------------
269      !!                    ***  ROUTINE nonosc_z  ***
270      !!     
271      !! **  Purpose :   compute monotonic tracer fluxes from the upstream
272      !!       scheme and the before field by a nonoscillatory algorithm
273      !!
274      !! **  Method  :   ... ???
275      !!       warning : pbef and paft must be masked, but the boundaries
276      !!       conditions on the fluxes are not necessary zalezak (1979)
277      !!       drange (1995) multi-dimensional forward-in-time and upstream-
278      !!       in-space based differencing for fluid
279      !!----------------------------------------------------------------------
[2528]280      REAL(wp), INTENT(in   ), DIMENSION(jpk)          ::   p2dt   ! vertical profile of tracer time-step
281      REAL(wp),                DIMENSION (jpi,jpj,jpk) ::   pbef   ! before field
[503]282      REAL(wp), INTENT(inout), DIMENSION (jpi,jpj,jpk) ::   paft   ! after field
283      REAL(wp), INTENT(inout), DIMENSION (jpi,jpj,jpk) ::   pcc    ! monotonic flux in the k direction
[2715]284      !
285      INTEGER  ::   ji, jj, jk   ! dummy loop indices
286      INTEGER  ::   ikm1         ! local integer
287      REAL(wp) ::   zpos, zneg, zbt, za, zb, zc, zbig, zrtrn, z2dtt   ! local scalars
[3294]288      REAL(wp), POINTER, DIMENSION(:,:,:) :: zbetup, zbetdo
[503]289      !!----------------------------------------------------------------------
[3294]290      !
291      IF( nn_timing == 1 )  CALL timing_start('nonosc_z')
292      !
293      CALL wrk_alloc( jpi, jpj, jpk, zbetup, zbetdo )
294      !
[2715]295      zbig  = 1.e+40_wp
296      zrtrn = 1.e-15_wp
297      zbetup(:,:,:) = 0._wp   ;   zbetdo(:,:,:) = 0._wp
298
[503]299      ! Search local extrema
300      ! --------------------
301      ! large negative value (-zbig) inside land
302      pbef(:,:,:) = pbef(:,:,:) * tmask(:,:,:) - zbig * ( 1.e0 - tmask(:,:,:) )
303      paft(:,:,:) = paft(:,:,:) * tmask(:,:,:) - zbig * ( 1.e0 - tmask(:,:,:) )
304      ! search maximum in neighbourhood
305      DO jk = 1, jpkm1
306         ikm1 = MAX(jk-1,1)
307         DO jj = 2, jpjm1
308            DO ji = fs_2, fs_jpim1   ! vector opt.
309               zbetup(ji,jj,jk) = MAX(  pbef(ji  ,jj  ,jk  ), paft(ji  ,jj  ,jk  ),   &
310                  &                     pbef(ji  ,jj  ,ikm1), pbef(ji  ,jj  ,jk+1),   &
311                  &                     paft(ji  ,jj  ,ikm1), paft(ji  ,jj  ,jk+1)  )
312            END DO
313         END DO
314      END DO
315      ! large positive value (+zbig) inside land
316      pbef(:,:,:) = pbef(:,:,:) * tmask(:,:,:) + zbig * ( 1.e0 - tmask(:,:,:) )
317      paft(:,:,:) = paft(:,:,:) * tmask(:,:,:) + zbig * ( 1.e0 - tmask(:,:,:) )
318      ! search minimum in neighbourhood
319      DO jk = 1, jpkm1
320         ikm1 = MAX(jk-1,1)
321         DO jj = 2, jpjm1
322            DO ji = fs_2, fs_jpim1   ! vector opt.
323               zbetdo(ji,jj,jk) = MIN(  pbef(ji  ,jj  ,jk  ), paft(ji  ,jj  ,jk  ),   &
324                  &                     pbef(ji  ,jj  ,ikm1), pbef(ji  ,jj  ,jk+1),   &
325                  &                     paft(ji  ,jj  ,ikm1), paft(ji  ,jj  ,jk+1)  )
326            END DO
327         END DO
328      END DO
329
330      ! restore masked values to zero
331      pbef(:,:,:) = pbef(:,:,:) * tmask(:,:,:)
332      paft(:,:,:) = paft(:,:,:) * tmask(:,:,:)
333
[2528]334
[503]335      ! 2. Positive and negative part of fluxes and beta terms
336      ! ------------------------------------------------------
337
338      DO jk = 1, jpkm1
[2528]339         z2dtt = p2dt(jk)
[503]340         DO jj = 2, jpjm1
341            DO ji = fs_2, fs_jpim1   ! vector opt.
342               ! positive & negative part of the flux
343               zpos = MAX( 0., pcc(ji  ,jj  ,jk+1) ) - MIN( 0., pcc(ji  ,jj  ,jk  ) )
344               zneg = MAX( 0., pcc(ji  ,jj  ,jk  ) ) - MIN( 0., pcc(ji  ,jj  ,jk+1) )
345               ! up & down beta terms
346               zbt = e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) / z2dtt
347               zbetup(ji,jj,jk) = ( zbetup(ji,jj,jk) - paft(ji,jj,jk) ) / (zpos+zrtrn) * zbt
348               zbetdo(ji,jj,jk) = ( paft(ji,jj,jk) - zbetdo(ji,jj,jk) ) / (zneg+zrtrn) * zbt
349            END DO
350         END DO
351      END DO
352      ! monotonic flux in the k direction, i.e. pcc
353      ! -------------------------------------------
354      DO jk = 2, jpkm1
355         DO jj = 2, jpjm1
356            DO ji = fs_2, fs_jpim1   ! vector opt.
357               za = MIN( 1., zbetdo(ji,jj,jk), zbetup(ji,jj,jk-1) )
358               zb = MIN( 1., zbetup(ji,jj,jk), zbetdo(ji,jj,jk-1) )
359               zc = 0.5 * ( 1.e0 + SIGN( 1.e0, pcc(ji,jj,jk) ) )
360               pcc(ji,jj,jk) = pcc(ji,jj,jk) * ( zc * za + ( 1.e0 - zc) * zb )
361            END DO
362         END DO
363      END DO
364      !
[3294]365      CALL wrk_dealloc( jpi, jpj, jpk, zbetup, zbetdo )
[2715]366      !
[3294]367      IF( nn_timing == 1 )  CALL timing_stop('nonosc_z')
368      !
[503]369   END SUBROUTINE nonosc_z
370
371   !!======================================================================
372END MODULE traadv_ubs
Note: See TracBrowser for help on using the repository browser.