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/dev_001_GM/NEMO/OPA_SRC/TRA – NEMO

source: branches/dev_001_GM/NEMO/OPA_SRC/TRA/traadv_ubs.F90 @ 791

Last change on this file since 791 was 791, checked in by gm, 16 years ago

dev_001_GM - TRA/traadv : switch from velocity to transport + optimised traadv_eiv2 introduced - compilation OK

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