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.
trcadv_muscl.F90 in trunk/NEMO/TOP_SRC/TRP – NEMO

source: trunk/NEMO/TOP_SRC/TRP/trcadv_muscl.F90 @ 204

Last change on this file since 204 was 204, checked in by opalod, 19 years ago

CT : UPDATE142 : Check the consistency between passive tracers transport modules (in TRP directory) and those used for the active tracers

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1MODULE trcadv_muscl
2   !!==============================================================================
3   !!                       ***  MODULE  trcadv_muscl  ***
4   !! Ocean passive tracers:  horizontal & vertical advective trend
5   !!==============================================================================
6#if defined key_passivetrc
7   !!----------------------------------------------------------------------
8   !!   trc_adv_muscl : update the tracer trend with the horizontal
9   !!                   and vertical advection trends using MUSCL scheme
10   !!----------------------------------------------------------------------
11   !! * Modules used
12   USE oce_trc         ! ocean dynamics and active tracers variables
13   USE trc             ! ocean passive tracers variables
14   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
15   USE trcbbl          ! advective passive tracers in the BBL
16
17   IMPLICIT NONE
18   PRIVATE
19
20   !! * Accessibility
21   PUBLIC trc_adv_muscl  ! routine called by trcstp.F90
22
23   !! * Module variable
24   REAL(wp), DIMENSION(jpk) ::   &
25      rdttrc                     ! vertical profile of tracer time-step
26
27   !! * Substitutions
28#  include "passivetrc_substitute.h90"
29   !!----------------------------------------------------------------------
30   !!   OPA 9.0 , LODYC-IPSL (2003)
31   !!----------------------------------------------------------------------
32
33CONTAINS
34
35   SUBROUTINE trc_adv_muscl( kt )
36      !!----------------------------------------------------------------------
37      !!                    ***  ROUTINE trc_adv_muscl  ***
38      !!         
39      !! ** Purpose :   Compute the now trend due to total advection of any pas-
40      !!      sive tracer using a MUSCL scheme (Monotone Upstream-centered Scheme
41      !!      for Conservation Laws) and add it to the general tracer trend.
42      !!
43      !! ** Method  :
44      !!
45      !! ** Action  : - update tra with the now advective tracer trends
46      !!              - save trends in trtrd ('key_trc_diatrd')
47      !!
48      !! References :               
49      !!      Estubier, A., and M. Levy, Notes Techn. Pole de Modelisation
50      !! IPSL, Sept. 2000 (http://www.lodyc.jussieu.fr/opa)
51      !!
52      !! History :
53      !!        !  06-00  (A.Estublier)  for passive tracers
54      !!   9.0  !  03-04  (C. Ethe, G. Madec)  F90: Free form and module
55      !!----------------------------------------------------------------------
56      !! * modules used
57#if defined key_trcbbl_adv
58      USE oce_trc            , zun => ua,  &  ! use ua as workspace
59         &                     zvn => va      ! use va as workspace
60      REAL(wp), DIMENSION(jpi,jpj,jpk) :: zwn
61#else
62      USE oce_trc            , zun => un,  &  ! When no bbl, zun == un
63                               zvn => vn,  &  !              zvn == vn
64                               zwn => wn      !              zwn == wn
65#endif
66
67      !! * Arguments
68      INTEGER, INTENT( in ) ::   kt         ! ocean time-step
69
70      !! * Local declarations
71      INTEGER ::   ji, jj, jk,jn            ! dummy loop indices
72      REAL(wp), DIMENSION (jpi,jpj,jpk) ::   &
73         zt1, zt2, ztp1, ztp2
74
75      REAL(wp) ::   zu, zv, zw, zeu, zev, zew, zbtr, ztra
76      REAL(wp) ::   z0u, z0v, z0w
77      REAL(wp) ::   zzt1, zzt2, zalpha
78#if defined key_trc_diatrd
79      REAL(wp) ::   ztai, ztaj
80      REAL(wp) ::   zfui, zfvj
81#endif
82
83      !!----------------------------------------------------------------------
84
85
86      IF( kt == nittrc000 .AND. lwp ) THEN
87         WRITE(numout,*)
88         WRITE(numout,*) 'trc_adv : MUSCL advection scheme'
89         WRITE(numout,*) '~~~~~~~'
90         rdttrc(:) =  rdttra(:) * FLOAT(ndttrc)
91      ENDIF
92
93 
94
95#if defined key_trcbbl_adv
96      ! Advective bottom boundary layer
97      ! -------------------------------
98      zun(:,:,:) = un (:,:,:) - u_trc_bbl(:,:,:)
99      zvn(:,:,:) = vn (:,:,:) - v_trc_bbl(:,:,:)
100      zwn(:,:,:) = wn (:,:,:) + w_trc_bbl(:,:,:)
101#endif
102
103 
104
105      DO jn = 1, jptra
106
107         ! I. Horizontal advective fluxes
108         ! ------------------------------
109
110         ! first guess of the slopes
111         ! interior values
112         DO jk = 1, jpkm1
113            DO jj = 1, jpjm1     
114               DO ji = 1, fs_jpim1   ! vector opt.
115                  zt1(ji,jj,jk) = umask(ji,jj,jk) * ( trb(ji+1,jj,jk,jn) - trb(ji,jj,jk,jn) )
116                  zt2(ji,jj,jk) = vmask(ji,jj,jk) * ( trb(ji,jj+1,jk,jn) - trb(ji,jj,jk,jn) )
117               END DO
118            END DO
119         END DO
120         ! bottom values
121         zt1(:,:,jpk) = 0.e0
122         zt2(:,:,jpk) = 0.e0
123
124         ! lateral boundary conditions on zt1, zt2
125         CALL lbc_lnk( zt1, 'U', -1. )   
126         CALL lbc_lnk( zt2, 'V', -1. ) 
127
128
129         ! Slopes
130         ! interior values
131         DO jk = 1, jpkm1
132            DO jj = 2, jpj
133               DO ji = fs_2, jpi   ! vector opt.
134                  ztp1(ji,jj,jk) =                    ( zt1(ji,jj,jk) + zt1(ji-1,jj  ,jk) )   &
135                     &           * ( 0.25 + SIGN( 0.25, zt1(ji,jj,jk) * zt1(ji-1,jj  ,jk) ) )
136                  ztp2(ji,jj,jk) =                    ( zt2(ji,jj,jk) + zt2(ji  ,jj-1,jk) )   &
137                     &           * ( 0.25 + SIGN( 0.25, zt2(ji,jj,jk) * zt2(ji  ,jj-1,jk) ) )
138               END DO
139            END DO
140         END DO
141         ! bottom values
142         ztp1(:,:,jpk) = 0.e0
143         ztp2(:,:,jpk) = 0.e0
144
145
146         ! Slopes limitation
147         DO jk = 1, jpkm1
148            DO jj = 2, jpj
149               DO ji = fs_2, fs_jpim1   ! vector opt.
150                  ztp1(ji,jj,jk) = SIGN( 1., ztp1(ji,jj,jk) )   &
151                     &           * MIN(    ABS( ztp1(ji  ,jj,jk) ),   &
152                     &                  2.*ABS( zt1 (ji-1,jj,jk) ),   &
153                     &                  2.*ABS( zt1 (ji  ,jj,jk) ) )
154
155                  ztp2(ji,jj,jk) = SIGN( 1., ztp2(ji,jj,jk) )   &
156                     &           * MIN(    ABS( ztp2(ji,jj  ,jk) ),   &
157                     &                  2.*ABS( zt2 (ji,jj-1,jk) ),   &
158                     &                  2.*ABS( zt2 (ji,jj  ,jk) ) )
159
160               END DO
161            END DO
162         END DO
163
164
165         ! Advection terms
166         ! interior values
167         DO jk = 1, jpkm1
168            DO jj = 2, jpjm1     
169               DO ji = fs_2, fs_jpim1   ! vector opt.
170                  ! volume fluxes
171#if defined key_s_coord || defined key_partial_steps
172                  zeu = e2u(ji,jj) * fse3u(ji,jj,jk) * zun(ji,jj,jk)
173                  zev = e1v(ji,jj) * fse3v(ji,jj,jk) * zvn(ji,jj,jk)
174#else
175                  zeu = e2u(ji,jj) * zun(ji,jj,jk)
176                  zev = e1v(ji,jj) * zvn(ji,jj,jk)
177#endif
178                  ! MUSCL fluxes
179                  z0u = SIGN( 0.5, zun(ji,jj,jk) )           
180                  zalpha = 0.5 - z0u
181                  zu  = z0u - 0.5 * zun(ji,jj,jk) * rdttrc(jk) / e1u(ji,jj)
182                  zzt1 = trb(ji+1,jj,jk,jn) + zu*ztp1(ji+1,jj,jk)
183                  zzt2 = trb(ji  ,jj,jk,jn) + zu*ztp1(ji  ,jj,jk)
184                  zt1(ji,jj,jk) = zeu * ( zalpha * zzt1 + (1.-zalpha) * zzt2 )
185
186                  z0v = SIGN( 0.5, zvn(ji,jj,jk) )           
187                  zalpha = 0.5 - z0v
188                  zv  = z0v - 0.5 * zvn(ji,jj,jk) * rdttrc(jk) / e2v(ji,jj)
189                  zzt1 = trb(ji,jj+1,jk,jn) + zv*ztp2(ji,jj+1,jk)
190                  zzt2 = trb(ji,jj  ,jk,jn) + zv*ztp2(ji,jj  ,jk)
191                  zt2(ji,jj,jk) = zev * ( zalpha * zzt1 + (1.-zalpha) * zzt2 )
192               END DO
193            END DO
194         END DO
195
196         ! lateral boundary conditions on zt1, zt2 (changed sign)
197         CALL lbc_lnk( zt1, 'U', -1. ) 
198         CALL lbc_lnk( zt2, 'V', -1. ) 
199
200         ! Compute and add the horizontal advective trend
201
202         DO jk = 1, jpkm1
203            DO jj = 2, jpjm1     
204               DO ji = fs_2, fs_jpim1   ! vector opt.
205#if defined key_s_coord || defined key_partial_steps
206                  zbtr = 1. / ( e1t(ji,jj)*e2t(ji,jj)*fse3t(ji,jj,jk) )
207#else
208                  zbtr = 1. / ( e1t(ji,jj)*e2t(ji,jj) )
209#endif
210                  ! horizontal advective trends
211                  ztra = - zbtr * ( zt1(ji,jj,jk) - zt1(ji-1,jj  ,jk  )   &
212                     &            + zt2(ji,jj,jk) - zt2(ji  ,jj-1,jk  ) )
213                  ! add it to the general tracer trends
214                  tra(ji,jj,jk,jn) = tra(ji,jj,jk,jn) + ztra
215#if defined key_trc_diatrd
216                  ! recompute the trends in i- and j-direction as Uh gradh(T)
217#   if defined key_s_coord || defined key_partial_steps
218                  zfui =  e2u(ji  ,jj) * fse3u(ji,  jj,jk) * un(ji,  jj,jk)   &
219                     & -  e2u(ji-1,jj) * fse3u(ji-1,jj,jk) * un(ji-1,jj,jk)
220                  zfvj =  e1v(ji,jj  ) * fse3v(ji,jj  ,jk) * vn(ji,jj  ,jk)   &
221                     & -  e1v(ji,jj-1) * fse3v(ji,jj-1,jk) * vn(ji,jj-1,jk)
222#   else
223                  zfui = e2u(ji  ,jj) * un(ji,  jj,jk)   &
224                     & - e2u(ji-1,jj) * un(ji-1,jj,jk)
225                  zfvj = e1v(ji,jj  ) * vn(ji,jj  ,jk)   &
226                     & - e1v(ji,jj-1) * vn(ji,jj-1,jk)
227#   endif
228                  ztai =-zbtr * (  zt1(ji,jj,jk) - zt1(ji-1,jj  ,jk) - trn(ji,jj,jk,jn) * zfui  )
229                  ztaj =-zbtr * (  zt2(ji,jj,jk) - zt2(ji  ,jj-1,jk) - trn(ji,jj,jk,jn) * zfvj  )
230                  ! save i- and j- advective trends computed as Uh gradh(T)
231                  trtrd(ji,jj,jk,jn,1) = ztai
232                  trtrd(ji,jj,jk,jn,2) = ztaj
233#endif
234               END DO
235            END DO
236         END DO
237
238         IF(l_ctl) THEN         ! print mean trends (used for debugging)
239            ztra = SUM( tra(2:nictl,2:njctl,1:jpkm1,jn) * tmask(2:nictl,2:njctl,1:jpkm1) )
240            WRITE(numout,*) ' trc/had  - ',ctrcnm(jn),' : ', ztra-tra_ctl(jn), ' muscl' 
241            tra_ctl(jn) = ztra 
242         ENDIF
243
244         ! II. Vertical advective fluxes
245         ! -----------------------------
246
247         ! First guess of the slope
248         ! interior values
249         DO jk = 2, jpkm1
250            zt1(:,:,jk) = tmask(:,:,jk) * ( trb(:,:,jk-1,jn) - trb(:,:,jk,jn) )
251         END DO
252         ! surface and bottom boundary conditions
253         zt1 (:,:, 1 ) = 0.e0 
254         zt1 (:,:,jpk) = 0.e0
255         ! Slopes
256         DO jk = 2, jpkm1
257            DO jj = 1, jpj
258               DO ji = 1, jpi
259                  ztp1(ji,jj,jk) =                    ( zt1(ji,jj,jk) + zt1(ji,jj,jk+1) )   &
260                     &           * ( 0.25 + SIGN( 0.25, zt1(ji,jj,jk) * zt1(ji,jj,jk+1) ) )
261               END DO
262            END DO
263         END DO
264
265         ! Slopes limitation
266         ! interior values
267         DO jk = 2, jpkm1
268            DO jj = 1, jpj
269               DO ji = 1, jpi
270                  ztp1(ji,jj,jk) = SIGN( 1., ztp1(ji,jj,jk) )   &
271                     &           * MIN(    ABS( ztp1(ji,jj,jk  ) ),   &
272                     &                  2.*ABS( zt1 (ji,jj,jk+1) ),   &
273                     &                  2.*ABS( zt1 (ji,jj,jk  ) ) )
274               END DO
275            END DO
276         END DO
277         ! surface values
278         ztp1(:,:,1) = 0. 
279         ! vertical advective flux
280         ! interior values
281         DO jk = 1, jpkm1
282            DO jj = 2, jpjm1     
283               DO ji = fs_2, fs_jpim1   ! vector opt.
284                  zew = zwn(ji,jj,jk+1)
285                  z0w = SIGN( 0.5, zwn(ji,jj,jk+1) )
286                  zalpha = 0.5 + z0w
287                  zw  = z0w - 0.5 * zwn(ji,jj,jk+1)*rdttrc(jk) / fse3w(ji,jj,jk+1)
288                  zzt1 = trb(ji,jj,jk+1,jn) + zw*ztp1(ji,jj,jk+1)
289                  zzt2 = trb(ji,jj,jk  ,jn) + zw*ztp1(ji,jj,jk  )
290                  zt1(ji,jj,jk+1) = zew * ( zalpha * zzt1 + (1.-zalpha)*zzt2 )
291               END DO
292            END DO
293         END DO
294         ! surface values
295         IF( lk_dynspg_fsc .OR. lk_dynspg_fsc_tsk ) THEN        ! free surface-constant volume
296            zt1(:,:, 1 ) = zwn(:,:,1) * trb(:,:,1,jn)
297         ELSE                                                   ! rigid lid : flux set to zero
298            zt1(:,:, 1 ) = 0.e0
299         ENDIF
300
301         ! bottom values
302         zt1(:,:,jpk) = 0.e0
303
304         ! Compute & add the vertical advective trend
305
306         DO jk = 1, jpkm1
307            DO jj = 2, jpjm1     
308               DO ji = fs_2, fs_jpim1   ! vector opt.
309                  zbtr = 1. / fse3t(ji,jj,jk)
310                  ! horizontal advective trends
311                  ztra = - zbtr * ( zt1(ji,jj,jk) - zt1(ji,jj,jk+1) )
312                  ! add it to the general tracer trends
313                  tra(ji,jj,jk,jn) =  tra(ji,jj,jk,jn) + ztra
314#if defined key_trc_diatrd
315                  ! save the vertical advective trends computed as w gradz(T)
316                  trtrd(ji,jj,jk,jn,3) = ztra - trn(ji,jj,jk,jn) * hdivn(ji,jj,jk)
317#endif
318               END DO
319            END DO
320         END DO
321
322         IF(l_ctl) THEN         ! print mean trends (used for debugging)
323            ztra = SUM( tra(2:nictl,2:njctl,1:jpkm1,jn) * tmask(2:nictl,2:njctl,1:jpkm1) )
324            WRITE(numout,*) ' trc/zad  - ',ctrcnm(jn),' : ', ztra-tra_ctl(jn), ' muscl' 
325            tra_ctl(jn) = ztra 
326         ENDIF
327
328      END DO
329
330END SUBROUTINE trc_adv_muscl
331
332#else
333   !!----------------------------------------------------------------------
334   !!   Default option                                         Empty module
335   !!----------------------------------------------------------------------
336CONTAINS
337   SUBROUTINE trc_adv_muscl( kt ) 
338      INTEGER, INTENT(in) :: kt
339      WRITE(*,*) 'trc_adv_muscl: You should not have seen this print! error?', kt
340   END SUBROUTINE trc_adv_muscl
341#endif
342
343   !!======================================================================
344END MODULE trcadv_muscl
Note: See TracBrowser for help on using the repository browser.