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.
dynspg_flt.F90 in branches/2015/dev_r5056_CMCC4_simplification/NEMOGCM/NEMO/OPA_SRC/DYN – NEMO

source: branches/2015/dev_r5056_CMCC4_simplification/NEMOGCM/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 5282

Last change on this file since 5282 was 5282, checked in by diovino, 9 years ago

Dev. branch CMCC4_simplification ticket #1456

  • Property svn:keywords set to Id
File size: 19.8 KB
Line 
1MODULE dynspg_flt
2   !!======================================================================
3   !!                   ***  MODULE  dynspg_flt  ***
4   !! Ocean dynamics:  surface pressure gradient trend
5   !!======================================================================
6   !! History    OPA  !  1998-05  (G. Roullet)  free surface
7   !!                 !  1998-10  (G. Madec, M. Imbard)  release 8.2
8   !!   NEMO     O.1  !  2002-08  (G. Madec)  F90: Free form and module
9   !!             -   !  2002-11  (C. Talandier, A-M Treguier) Open boundaries
10   !!            1.0  !  2004-08  (C. Talandier) New trends organization
11   !!             -   !  2005-11  (V. Garnier) Surface pressure gradient organization
12   !!            2.0  !  2006-07  (S. Masson)  distributed restart using iom
13   !!             -   !  2006-08  (J.Chanut, A.Sellar) Calls to BDY routines.
14   !!            3.2  !  2009-03  (G. Madec, M. Leclair, R. Benshila) introduce sshwzv module
15   !!            3.7  !  2014-04  (F. Roquet, G. Madec)  add some trends diag
16   !!----------------------------------------------------------------------
17#if defined key_dynspg_flt   ||   defined key_esopa 
18   !!----------------------------------------------------------------------
19   !!   'key_dynspg_flt'                              filtered free surface
20   !!----------------------------------------------------------------------
21   !!   dyn_spg_flt  : update the momentum trend with the surface pressure gradient in the filtered free surface case
22   !!   flt_rst      : read/write the time-splitting restart fields in the ocean restart file
23   !!----------------------------------------------------------------------
24   USE oce             ! ocean dynamics and tracers
25   USE dom_oce         ! ocean space and time domain
26   USE zdf_oce         ! ocean vertical physics
27   USE sbc_oce         ! surface boundary condition: ocean
28   USE bdy_oce         ! Lateral open boundary condition
29   USE sol_oce         ! ocean elliptic solver
30   USE phycst          ! physical constants
31   USE domvvl          ! variable volume
32   USE dynadv          ! advection
33   USE solmat          ! matrix construction for elliptic solvers
34   USE solpcg          ! preconditionned conjugate gradient solver
35   USE solsor          ! Successive Over-relaxation solver
36   USE bdydyn          ! ocean open boundary condition on dynamics
37   USE bdyvol          ! ocean open boundary condition (bdy_vol routine)
38   USE trd_oce         ! trends: ocean variables
39   USE trddyn          ! trend manager: dynamics
40   !
41   USE in_out_manager  ! I/O manager
42   USE lib_mpp         ! distributed memory computing library
43   USE wrk_nemo        ! Memory Allocation
44   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
45   USE prtctl          ! Print control
46   USE iom
47   USE lib_fortran
48   USE timing          ! Timing
49#if defined key_agrif
50   USE agrif_opa_interp
51#endif
52
53   IMPLICIT NONE
54   PRIVATE
55
56   PUBLIC   dyn_spg_flt  ! routine called by step.F90
57   PUBLIC   flt_rst      ! routine called by istate.F90
58
59   !! * Substitutions
60#  include "domzgr_substitute.h90"
61#  include "vectopt_loop_substitute.h90"
62   !!----------------------------------------------------------------------
63   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
64   !! $Id$
65   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
66   !!----------------------------------------------------------------------
67CONTAINS
68
69   SUBROUTINE dyn_spg_flt( kt, kindic )
70      !!----------------------------------------------------------------------
71      !!                  ***  routine dyn_spg_flt  ***
72      !!
73      !! ** Purpose :   Compute the now trend due to the surface pressure
74      !!      gradient in case of filtered free surface formulation  and add
75      !!      it to the general trend of momentum equation.
76      !!
77      !! ** Method  :   Filtered free surface formulation. The surface
78      !!      pressure gradient is given by:
79      !!         spgu = 1/rau0 d/dx(ps) =  1/e1u di( sshn + btda )
80      !!         spgv = 1/rau0 d/dy(ps) =  1/e2v dj( sshn + btda )
81      !!      where sshn is the free surface elevation and btda is the after
82      !!      time derivative of the free surface elevation
83      !!       -1- evaluate the surface presure trend (including the addi-
84      !!      tional force) in three steps:
85      !!        a- compute the right hand side of the elliptic equation:
86      !!            gcb = 1/(e1t e2t) [ di(e2u spgu) + dj(e1v spgv) ]
87      !!         where (spgu,spgv) are given by:
88      !!            spgu = vertical sum[ e3u (ub+ 2 rdt ua ) ]
89      !!                 - grav 2 rdt hu /e1u di[sshn + (emp-rnf)]
90      !!            spgv = vertical sum[ e3v (vb+ 2 rdt va) ]
91      !!                 - grav 2 rdt hv /e2v dj[sshn + (emp-rnf)]
92      !!         and define the first guess from previous computation :
93      !!            zbtd = btda
94      !!            btda = 2 zbtd - btdb
95      !!            btdb = zbtd
96      !!        b- compute the relative accuracy to be reached by the
97      !!         iterative solver
98      !!        c- apply the solver by a call to sol... routine
99      !!       -2- compute and add the free surface pressure gradient inclu-
100      !!      ding the additional force used to stabilize the equation.
101      !!
102      !! ** Action : - Update (ua,va) with the surf. pressure gradient trend
103      !!
104      !! References : Roullet and Madec, JGR, 2000.
105      !!---------------------------------------------------------------------
106      INTEGER, INTENT(in   ) ::   kt       ! ocean time-step index
107      INTEGER, INTENT(  out) ::   kindic   ! solver convergence flag (<0 if not converge)
108      !
109      INTEGER  ::   ji, jj, jk   ! dummy loop indices
110      REAL(wp) ::   z2dt, z2dtg, zgcb, zbtd, ztdgu, ztdgv   ! local scalars
111      REAL(wp), POINTER, DIMENSION(:,:,:) ::  ztrdu, ztrdv
112      REAL(wp), POINTER, DIMENSION(:,:)   ::  zpw
113      !!----------------------------------------------------------------------
114      !
115      IF( nn_timing == 1 )  CALL timing_start('dyn_spg_flt')
116      !
117      IF( kt == nit000 ) THEN
118         IF(lwp) WRITE(numout,*)
119         IF(lwp) WRITE(numout,*) 'dyn_spg_flt : surface pressure gradient trend'
120         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~   (free surface constant volume case)'
121       
122         ! set to zero free surface specific arrays
123         spgu(:,:) = 0._wp                     ! surface pressure gradient (i-direction)
124         spgv(:,:) = 0._wp                     ! surface pressure gradient (j-direction)
125
126         ! read filtered free surface arrays in restart file
127         ! when using agrif, sshn, gcx have to be read in istate
128         IF(.NOT. lk_agrif)   CALL flt_rst( nit000, 'READ' )      ! read or initialize the following fields:
129         !                                                        ! gcx, gcxb
130      ENDIF
131
132      ! Local constant initialization
133      z2dt = 2. * rdt                                             ! time step: leap-frog
134      IF( neuler == 0 .AND. kt == nit000   )   z2dt = rdt         ! time step: Euler if restart from rest
135      IF( neuler == 0 .AND. kt == nit000+1 )   CALL sol_mat( kt )
136      z2dtg  = grav * z2dt
137
138      ! Evaluate the masked next velocity (effect of the additional force not included)
139      ! --------------------------------- 
140      IF( lk_vvl ) THEN          ! variable volume  (surface pressure gradient already included in dyn_hpg)
141         !
142         IF( ln_dynadv_vec ) THEN      ! vector form : applied on velocity
143            DO jk = 1, jpkm1
144               DO jj = 2, jpjm1
145                  DO ji = fs_2, fs_jpim1   ! vector opt.
146                     ua(ji,jj,jk) = (  ub(ji,jj,jk) + z2dt * ua(ji,jj,jk)  ) * umask(ji,jj,jk)
147                     va(ji,jj,jk) = (  vb(ji,jj,jk) + z2dt * va(ji,jj,jk)  ) * vmask(ji,jj,jk)
148                  END DO
149               END DO
150            END DO
151            !
152         ELSE                          ! flux form : applied on thickness weighted velocity
153            DO jk = 1, jpkm1
154               DO jj = 2, jpjm1
155                  DO ji = fs_2, fs_jpim1   ! vector opt.
156                     ua(ji,jj,jk) = (        ub(ji,jj,jk) * fse3u_b(ji,jj,jk)      &
157                        &           + z2dt * ua(ji,jj,jk) * fse3u_n(ji,jj,jk)  )   &
158                        &         / fse3u_a(ji,jj,jk) * umask(ji,jj,jk)
159                     va(ji,jj,jk) = (        vb(ji,jj,jk) * fse3v_b(ji,jj,jk)      &
160                        &           + z2dt * va(ji,jj,jk) * fse3v_n(ji,jj,jk)  )   &
161                        &         / fse3v_a(ji,jj,jk) * vmask(ji,jj,jk)
162                 END DO
163               END DO
164            END DO
165            !
166         ENDIF
167         !
168      ELSE                       ! fixed volume  (add the surface pressure gradient + unweighted time stepping)
169         !
170         DO jj = 2, jpjm1              ! Surface pressure gradient (now)
171            DO ji = fs_2, fs_jpim1   ! vector opt.
172               spgu(ji,jj) = - grav * ( sshn(ji+1,jj) - sshn(ji,jj) ) / e1u(ji,jj)
173               spgv(ji,jj) = - grav * ( sshn(ji,jj+1) - sshn(ji,jj) ) / e2v(ji,jj)
174            END DO
175         END DO
176         DO jk = 1, jpkm1              ! unweighted time stepping
177            DO jj = 2, jpjm1
178               DO ji = fs_2, fs_jpim1   ! vector opt.
179                  ua(ji,jj,jk) = (  ub(ji,jj,jk) + z2dt * ( ua(ji,jj,jk) + spgu(ji,jj) )  ) * umask(ji,jj,jk)
180                  va(ji,jj,jk) = (  vb(ji,jj,jk) + z2dt * ( va(ji,jj,jk) + spgv(ji,jj) )  ) * vmask(ji,jj,jk)
181               END DO
182            END DO
183         END DO
184         !
185         IF( l_trddyn )   THEN                      ! temporary save of spg trends
186            CALL wrk_alloc( jpi, jpj, jpk, ztrdu, ztrdv )
187            DO jk = 1, jpkm1              ! unweighted time stepping
188               DO jj = 2, jpjm1
189                  DO ji = fs_2, fs_jpim1   ! vector opt.
190                     ztrdu(ji,jj,jk) = spgu(ji,jj) * umask(ji,jj,jk)
191                     ztrdv(ji,jj,jk) = spgv(ji,jj) * vmask(ji,jj,jk)
192                  END DO
193               END DO
194            END DO
195            CALL trd_dyn( ztrdu, ztrdv, jpdyn_spgexp, kt )
196         ENDIF
197         !
198      ENDIF
199
200#if defined key_bdy
201      IF( lk_bdy ) CALL bdy_dyn( kt )   ! Update velocities on each open boundary
202      IF( lk_bdy ) CALL bdy_vol( kt )   ! Correction of the barotropic component velocity to control the volume of the system
203#endif
204#if defined key_agrif
205      CALL Agrif_dyn( kt )    ! Update velocities on each coarse/fine interfaces
206#endif
207
208      ! compute the next vertically averaged velocity (effect of the additional force not included)
209      ! ---------------------------------------------
210      DO jj = 2, jpjm1
211         DO ji = fs_2, fs_jpim1   ! vector opt.
212            spgu(ji,jj) = fse3u_a(ji,jj,1) * ua(ji,jj,1)
213            spgv(ji,jj) = fse3v_a(ji,jj,1) * va(ji,jj,1)
214         END DO
215      END DO
216      DO jk = 2, jpkm1                     ! vertical sum
217         DO jj = 2, jpjm1
218            DO ji = fs_2, fs_jpim1   ! vector opt.
219               spgu(ji,jj) = spgu(ji,jj) + fse3u_a(ji,jj,jk) * ua(ji,jj,jk)
220               spgv(ji,jj) = spgv(ji,jj) + fse3v_a(ji,jj,jk) * va(ji,jj,jk)
221            END DO
222         END DO
223      END DO
224
225      DO jj = 2, jpjm1                     ! transport: multiplied by the horizontal scale factor
226         DO ji = fs_2, fs_jpim1   ! vector opt.
227            spgu(ji,jj) = spgu(ji,jj) * e2u(ji,jj)
228            spgv(ji,jj) = spgv(ji,jj) * e1v(ji,jj)
229         END DO
230      END DO
231      CALL lbc_lnk( spgu, 'U', -1. )       ! lateral boundary conditions
232      CALL lbc_lnk( spgv, 'V', -1. )
233
234      IF( lk_vvl ) CALL sol_mat( kt )      ! build the matrix at kt (vvl case only)
235
236      ! Right hand side of the elliptic equation and first guess
237      ! --------------------------------------------------------
238      DO jj = 2, jpjm1
239         DO ji = fs_2, fs_jpim1   ! vector opt.
240            ! Divergence of the after vertically averaged velocity
241            zgcb =  spgu(ji,jj) - spgu(ji-1,jj)   &
242                  + spgv(ji,jj) - spgv(ji,jj-1)
243            gcb(ji,jj) = gcdprc(ji,jj) * zgcb
244            ! First guess of the after barotropic transport divergence
245            zbtd = gcx(ji,jj)
246            gcx (ji,jj) = 2. * zbtd   - gcxb(ji,jj)
247            gcxb(ji,jj) =      zbtd
248         END DO
249      END DO
250      ! applied the lateral boundary conditions
251      IF( nn_solv == 2 .AND. MAX( jpr2di, jpr2dj ) > 0 )   CALL lbc_lnk_e( gcb, c_solver_pt, 1., jpr2di, jpr2dj )   
252
253#if defined key_agrif
254      IF( .NOT. AGRIF_ROOT() ) THEN
255         ! add contribution of gradient of after barotropic transport divergence
256         IF( nbondi == -1 .OR. nbondi == 2 )   gcb(3     ,:) =   &
257            &    gcb(3     ,:) - z2dtg * z2dt * laplacu(2     ,:) * gcdprc(3     ,:) * hu(2     ,:) * e2u(2     ,:)
258         IF( nbondi ==  1 .OR. nbondi == 2 )   gcb(nlci-2,:) =   &
259            &    gcb(nlci-2,:) + z2dtg * z2dt * laplacu(nlci-2,:) * gcdprc(nlci-2,:) * hu(nlci-2,:) * e2u(nlci-2,:)
260         IF( nbondj == -1 .OR. nbondj == 2 )   gcb(:     ,3) =   &
261            &    gcb(:,3     ) - z2dtg * z2dt * laplacv(:,2     ) * gcdprc(:,3     ) * hv(:,2     ) * e1v(:,2     )
262         IF( nbondj ==  1 .OR. nbondj == 2 )   gcb(:,nlcj-2) =   &
263            &    gcb(:,nlcj-2) + z2dtg * z2dt * laplacv(:,nlcj-2) * gcdprc(:,nlcj-2) * hv(:,nlcj-2) * e1v(:,nlcj-2)
264      ENDIF
265#endif
266
267
268      ! Relative precision (computation on one processor)
269      ! ------------------
270      rnorme =0.e0
271      rnorme = GLOB_SUM( gcb(1:jpi,1:jpj) * gcdmat(1:jpi,1:jpj) * gcb(1:jpi,1:jpj) * bmask(:,:) )
272
273      epsr = eps * eps * rnorme
274      ncut = 0
275      ! if rnorme is 0, the solution is 0, the solver is not called
276      IF( rnorme == 0._wp ) THEN
277         gcx(:,:) = 0._wp
278         res   = 0._wp
279         niter = 0
280         ncut  = 999
281      ENDIF
282
283      ! Evaluate the next transport divergence
284      ! --------------------------------------
285      !    Iterarive solver for the elliptic equation (except IF sol.=0)
286      !    (output in gcx with boundary conditions applied)
287      kindic = 0
288      IF( ncut == 0 ) THEN
289         IF    ( nn_solv == 1 ) THEN   ;   CALL sol_pcg( kindic )      ! diagonal preconditioned conjuguate gradient
290         ELSEIF( nn_solv == 2 ) THEN   ;   CALL sol_sor( kindic )      ! successive-over-relaxation
291         ENDIF
292      ENDIF
293
294      ! Transport divergence gradient multiplied by z2dt
295      ! --------------------------------------------====
296      DO jj = 2, jpjm1
297         DO ji = fs_2, fs_jpim1   ! vector opt.
298            ! trend of Transport divergence gradient
299            ztdgu = z2dtg * (gcx(ji+1,jj  ) - gcx(ji,jj) ) / e1u(ji,jj)
300            ztdgv = z2dtg * (gcx(ji  ,jj+1) - gcx(ji,jj) ) / e2v(ji,jj)
301            ! multiplied by z2dt
302#if defined key_bdy
303            IF(lk_bdy) THEN
304            ! caution : grad D = 0 along open boundaries
305               spgu(ji,jj) = z2dt * ztdgu * bdyumask(ji,jj)
306               spgv(ji,jj) = z2dt * ztdgv * bdyvmask(ji,jj)
307            ELSE
308               spgu(ji,jj) = z2dt * ztdgu
309               spgv(ji,jj) = z2dt * ztdgv
310            ENDIF
311#else
312            spgu(ji,jj) = z2dt * ztdgu
313            spgv(ji,jj) = z2dt * ztdgv
314#endif
315         END DO
316      END DO
317
318#if defined key_agrif     
319      IF( .NOT. Agrif_Root() ) THEN
320         ! caution : grad D (fine) = grad D (coarse) at coarse/fine interface
321         IF( nbondi == -1 .OR. nbondi == 2 ) spgu(2     ,:) = z2dtg * z2dt * laplacu(2     ,:) * umask(2     ,:,1)
322         IF( nbondi ==  1 .OR. nbondi == 2 ) spgu(nlci-2,:) = z2dtg * z2dt * laplacu(nlci-2,:) * umask(nlci-2,:,1)
323         IF( nbondj == -1 .OR. nbondj == 2 ) spgv(:,2     ) = z2dtg * z2dt * laplacv(:,2     ) * vmask(:     ,2,1)
324         IF( nbondj ==  1 .OR. nbondj == 2 ) spgv(:,nlcj-2) = z2dtg * z2dt * laplacv(:,nlcj-2) * vmask(:,nlcj-2,1)
325      ENDIF
326#endif     
327
328      IF( l_trddyn )   THEN                     
329         ztrdu(:,:,:) = ua(:,:,:)                 ! save the after velocity before the filtered SPG
330         ztrdv(:,:,:) = va(:,:,:)
331         !
332         CALL wrk_alloc( jpi, jpj, zpw )
333         !
334         zpw(:,:) = - z2dt * gcx(:,:)
335         CALL iom_put( "ssh_flt" , zpw )          ! output equivalent ssh modification due to implicit filter
336         !
337         !                                        ! save surface pressure flux: -pw at z=0
338         zpw(:,:) = - rau0 * grav * sshn(:,:) * wn(:,:,1) * tmask(:,:,1)
339         CALL iom_put( "pw0_exp" , zpw )
340         zpw(:,:) = wn(:,:,1)
341         CALL iom_put( "w0" , zpw )
342         zpw(:,:) =  rau0 * z2dtg * gcx(:,:) * wn(:,:,1) * tmask(:,:,1)
343         CALL iom_put( "pw0_flt" , zpw )
344         !
345         CALL wrk_dealloc( jpi, jpj, zpw ) 
346         !                                   
347      ENDIF
348     
349      ! Add the trends multiplied by z2dt to the after velocity
350      ! -------------------------------------------------------
351      !     ( c a u t i o n : (ua,va) here are the after velocity not the
352      !                       trend, the leap-frog time stepping will not
353      !                       be done in dynnxt.F90 routine)
354      DO jk = 1, jpkm1
355         DO jj = 2, jpjm1
356            DO ji = fs_2, fs_jpim1   ! vector opt.
357               ua(ji,jj,jk) = ( ua(ji,jj,jk) + spgu(ji,jj) ) * umask(ji,jj,jk)
358               va(ji,jj,jk) = ( va(ji,jj,jk) + spgv(ji,jj) ) * vmask(ji,jj,jk)
359            END DO
360         END DO
361      END DO
362
363      IF( l_trddyn )   THEN                      ! save the explicit SPG trends for further diagnostics
364         ztrdu(:,:,:) = ( ua(:,:,:) - ztrdu(:,:,:) ) / z2dt
365         ztrdv(:,:,:) = ( va(:,:,:) - ztrdv(:,:,:) ) / z2dt
366         CALL trd_dyn( ztrdu, ztrdv, jpdyn_spgflt, kt )
367         !
368         CALL wrk_dealloc( jpi, jpj, jpk, ztrdu, ztrdv ) 
369      ENDIF
370
371      IF( lrst_oce )   CALL flt_rst( kt, 'WRITE' )      ! write filtered free surface arrays in restart file
372      !
373      IF( nn_timing == 1 )   CALL timing_stop('dyn_spg_flt')
374      !
375   END SUBROUTINE dyn_spg_flt
376
377
378   SUBROUTINE flt_rst( kt, cdrw )
379      !!---------------------------------------------------------------------
380      !!                   ***  ROUTINE ts_rst  ***
381      !!
382      !! ** Purpose : Read or write filtered free surface arrays in restart file
383      !!----------------------------------------------------------------------
384      INTEGER         , INTENT(in) ::   kt     ! ocean time-step
385      CHARACTER(len=*), INTENT(in) ::   cdrw   ! "READ"/"WRITE" flag
386      !!----------------------------------------------------------------------
387      !
388      IF( TRIM(cdrw) == 'READ' ) THEN
389         IF( iom_varid( numror, 'gcx', ldstop = .FALSE. ) > 0 ) THEN
390! Caution : extra-hallow
391! gcx and gcxb are defined as: DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj)
392            CALL iom_get( numror, jpdom_autoglo, 'gcx' , gcx (1:jpi,1:jpj) )
393            CALL iom_get( numror, jpdom_autoglo, 'gcxb', gcxb(1:jpi,1:jpj) )
394            IF( neuler == 0 )   gcxb(:,:) = gcx (:,:)
395         ELSE
396            gcx (:,:) = 0.e0
397            gcxb(:,:) = 0.e0
398         ENDIF
399      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN
400! Caution : extra-hallow
401! gcx and gcxb are defined as: DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj)
402         CALL iom_rstput( kt, nitrst, numrow, 'gcx' , gcx (1:jpi,1:jpj) )
403         CALL iom_rstput( kt, nitrst, numrow, 'gcxb', gcxb(1:jpi,1:jpj) )
404      ENDIF
405      !
406   END SUBROUTINE flt_rst
407
408#else
409   !!----------------------------------------------------------------------
410   !!   Default case :   Empty module   No standart free surface cst volume
411   !!----------------------------------------------------------------------
412CONTAINS
413   SUBROUTINE dyn_spg_flt( kt, kindic )       ! Empty routine
414      WRITE(*,*) 'dyn_spg_flt: You should not have seen this print! error?', kt, kindic
415   END SUBROUTINE dyn_spg_flt
416   SUBROUTINE flt_rst    ( kt, cdrw )         ! Empty routine
417      INTEGER         , INTENT(in) ::   kt         ! ocean time-step
418      CHARACTER(len=*), INTENT(in) ::   cdrw       ! "READ"/"WRITE" flag
419      WRITE(*,*) 'flt_rst: You should not have seen this print! error?', kt, cdrw
420   END SUBROUTINE flt_rst
421#endif
422   
423   !!======================================================================
424END MODULE dynspg_flt
Note: See TracBrowser for help on using the repository browser.