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.F90 in branches/2011/DEV_r2739_STFC_dCSE/NEMOGCM/NEMO/OPA_SRC/TRA – NEMO

source: branches/2011/DEV_r2739_STFC_dCSE/NEMOGCM/NEMO/OPA_SRC/TRA/traldf.F90 @ 4431

Last change on this file since 4431 was 3211, checked in by spickles2, 12 years ago

Stephen Pickles, 11 Dec 2011

Commit to bring the rest of the DCSE NEMO development branch
in line with the latest development version. This includes
array index re-ordering of all OPA_SRC/.

  • Property svn:keywords set to Id
File size: 18.0 KB
Line 
1MODULE traldf
2   !!======================================================================
3   !!                       ***  MODULE  traldf  ***
4   !! Ocean Active tracers : lateral diffusive trends
5   !!=====================================================================
6   !! History :  9.0  ! 2005-11 (G. Madec)  Original code
7   !!       NEMO 3.0  ! 2008-01  (C. Ethe, G. Madec)  merge TRC-TRA
8   !!----------------------------------------------------------------------
9
10   !!----------------------------------------------------------------------
11   !!   tra_ldf      : update the tracer trend with the lateral diffusion
12   !!   tra_ldf_init : initialization, namelist read, and parameters control
13   !!       ldf_ano  : compute lateral diffusion for constant T-S profiles
14   !!----------------------------------------------------------------------
15   USE oce             ! ocean dynamics and tracers
16   USE dom_oce         ! ocean space and time domain
17   USE phycst          ! physical constants
18   USE ldftra_oce      ! ocean tracer   lateral physics
19   USE ldfslp          ! ???
20   USE traldf_bilapg   ! lateral mixing            (tra_ldf_bilapg routine)
21   USE traldf_bilap    ! lateral mixing             (tra_ldf_bilap routine)
22   USE traldf_iso      ! lateral mixing               (tra_ldf_iso routine)
23
24!! DCSE_NEMO
25!  USE traldf_iso_grif ! lateral mixing          (tra_ldf_iso_grif routine)
26   USE traldf_iso_grif, ONLY : tra_ldf_iso_grif ! lateral mixing
27   USE traldf_lap      ! lateral mixing               (tra_ldf_lap routine)
28   USE trdmod_oce      ! ocean space and time domain
29   USE trdtra          ! ocean active tracers trends
30   USE prtctl          ! Print control
31   USE in_out_manager  ! I/O manager
32   USE lib_mpp         ! distribued memory computing library
33   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
34
35   IMPLICIT NONE
36   PRIVATE
37
38   PUBLIC   tra_ldf         ! called by step.F90
39   PUBLIC   tra_ldf_init    ! called by opa.F90
40   !
41   INTEGER ::   nldf = 0   ! type of lateral diffusion used defined from ln_traldf_... namlist logicals)
42
43   REAL, SAVE, ALLOCATABLE, DIMENSION(:,:,:) ::   t0_ldf, s0_ldf   !: lateral diffusion trends of T & S for a cst profile
44   !                                                               !  (key_traldf_ano only)
45
46   !! * Control permutation of array indices
47#  include "oce_ftrans.h90"
48#  include "dom_oce_ftrans.h90"
49#  include "ldftra_oce_ftrans.h90"
50#  include "ldfslp_ftrans.h90"
51#  include "trc_oce_ftrans.h90"
52!FTRANS t0_ldf s0_ldf :I :I :z
53
54   !! * Substitutions
55#  include "domzgr_substitute.h90"
56#  include "vectopt_loop_substitute.h90"
57   !!----------------------------------------------------------------------
58   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
59   !! $Id$
60   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
61   !!----------------------------------------------------------------------
62CONTAINS
63
64   SUBROUTINE tra_ldf( kt )
65      !!----------------------------------------------------------------------
66      !!                  ***  ROUTINE tra_ldf  ***
67      !!
68      !! ** Purpose :   compute the lateral ocean tracer physics.
69      !!----------------------------------------------------------------------
70      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
71      !!
72!FTRANS ztrdt ztrds :I :I :z
73      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  ztrdt, ztrds
74      !!----------------------------------------------------------------------
75
76      IF( l_trdtra )   THEN                    !* Save ta and sa trends
77         ALLOCATE( ztrdt(jpi,jpj,jpk) )   ;    ztrdt(:,:,:) = tsa(:,:,:,jp_tem) 
78         ALLOCATE( ztrds(jpi,jpj,jpk) )   ;    ztrds(:,:,:) = tsa(:,:,:,jp_sal)
79      ENDIF
80
81      SELECT CASE ( nldf )                       ! compute lateral mixing trend and add it to the general trend
82      CASE ( 0 )   ;   CALL tra_ldf_lap     ( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts        )  ! iso-level laplacian
83      CASE ( 1 )                                                                              ! rotated laplacian
84         IF( ln_traldf_grif ) THEN                                                         
85                       CALL tra_ldf_iso_grif( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 )      ! Griffies operator
86         ELSE                                                                               
87                       CALL tra_ldf_iso     ( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 )      ! Madec operator
88         ENDIF
89      CASE ( 2 )   ;   CALL tra_ldf_bilap   ( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts        )  ! iso-level bilaplacian
90      CASE ( 3 )   ;   CALL tra_ldf_bilapg  ( kt, 'TRA',             tsb, tsa, jpts        )  ! s-coord. geopot. bilap.
91         !
92      CASE ( -1 )                                ! esopa: test all possibility with control print
93         CALL tra_ldf_lap   ( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts        ) 
94         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf0 - Ta: ', mask1=tmask,               &
95         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
96         IF( ln_traldf_grif ) THEN
97            CALL tra_ldf_iso_grif( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 )
98         ELSE
99            CALL tra_ldf_iso     ( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 ) 
100         ENDIF
101         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf1 - Ta: ', mask1=tmask,               &
102         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
103         CALL tra_ldf_bilap ( kt, 'TRA', gtsu, gtsv, tsb, tsa, jpts        ) 
104         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf2 - Ta: ', mask1=tmask,               &
105         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
106         CALL tra_ldf_bilapg( kt, 'TRA',             tsb, tsa, jpts        ) 
107         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf3 - Ta: ', mask1=tmask,               &
108         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
109      END SELECT
110
111#if defined key_traldf_ano
112      tsa(:,:,:,jp_tem) = tsa(:,:,:,jp_tem) - t0_ldf(:,:,:)      ! anomaly: substract the reference diffusivity
113      tsa(:,:,:,jp_sal) = tsa(:,:,:,jp_sal) - s0_ldf(:,:,:)
114#endif
115
116      IF( l_trdtra )   THEN                      ! save the horizontal diffusive trends for further diagnostics
117         ztrdt(:,:,:) = tsa(:,:,:,jp_tem) - ztrdt(:,:,:)
118         ztrds(:,:,:) = tsa(:,:,:,jp_sal) - ztrds(:,:,:)
119         CALL trd_tra( kt, 'TRA', jp_tem, jptra_trd_ldf, ztrdt )
120         CALL trd_tra( kt, 'TRA', jp_sal, jptra_trd_ldf, ztrds )
121         DEALLOCATE( ztrdt )      ;     DEALLOCATE( ztrds ) 
122      ENDIF
123      !                                          ! print mean trends (used for debugging)
124      IF(ln_ctl)   CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf  - Ta: ', mask1=tmask,               &
125         &                       tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
126      !
127   END SUBROUTINE tra_ldf
128
129   !! * Reset control of array index permutation
130!FTRANS CLEAR
131#  include "oce_ftrans.h90"
132#  include "dom_oce_ftrans.h90"
133#  include "ldftra_oce_ftrans.h90"
134#  include "ldfslp_ftrans.h90"
135#  include "trc_oce_ftrans.h90"
136!FTRANS t0_ldf s0_ldf :I :I :z
137
138   SUBROUTINE tra_ldf_init
139      !!----------------------------------------------------------------------
140      !!                  ***  ROUTINE tra_ldf_init  ***
141      !!
142      !! ** Purpose :   Choice of the operator for the lateral tracer diffusion
143      !!
144      !! ** Method  :   set nldf from the namtra_ldf logicals
145      !!      nldf == -1   ESOPA test: ALL operators are used
146      !!      nldf ==  0   laplacian operator
147      !!      nldf ==  1   Rotated laplacian operator
148      !!      nldf ==  2   bilaplacian operator
149      !!      nldf ==  3   Rotated bilaplacian
150      !!----------------------------------------------------------------------
151      INTEGER ::   ioptio, ierr         ! temporary integers
152      !!----------------------------------------------------------------------
153
154      !  Define the lateral mixing oparator for tracers
155      ! ===============================================
156   
157      IF(lwp) THEN                    ! Namelist print
158         WRITE(numout,*)
159         WRITE(numout,*) 'tra_ldf_init : lateral tracer diffusive operator'
160         WRITE(numout,*) '~~~~~~~~~~~'
161         WRITE(numout,*) '   Namelist namtra_ldf already read in ldftra module'
162         WRITE(numout,*) '   see ldf_tra_init report for lateral mixing parameters'
163         WRITE(numout,*)
164      ENDIF
165
166      !                               ! control the input
167      ioptio = 0
168      IF( ln_traldf_lap   )   ioptio = ioptio + 1
169      IF( ln_traldf_bilap )   ioptio = ioptio + 1
170      IF( ioptio >  1 )   CALL ctl_stop( '          use ONE or NONE of the 2 lap/bilap operator type on tracer' )
171      IF( ioptio == 0 )   nldf = -2   ! No lateral diffusion
172      ioptio = 0
173      IF( ln_traldf_level )   ioptio = ioptio + 1
174      IF( ln_traldf_hor   )   ioptio = ioptio + 1
175      IF( ln_traldf_iso   )   ioptio = ioptio + 1
176      IF( ioptio /= 1 )   CALL ctl_stop( '          use only ONE direction (level/hor/iso)' )
177
178      ! defined the type of lateral diffusion from ln_traldf_... logicals
179      ! CAUTION : nldf = 1 is used in trazdf_imp, change it carefully
180      ierr = 0
181      IF( ln_traldf_lap ) THEN       ! laplacian operator
182         IF ( ln_zco ) THEN                ! z-coordinate
183            IF ( ln_traldf_level )   nldf = 0      ! iso-level  (no rotation)
184            IF ( ln_traldf_hor   )   nldf = 0      ! horizontal (no rotation)
185            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
186         ENDIF
187         IF ( ln_zps ) THEN             ! z-coordinate
188            IF ( ln_traldf_level )   ierr = 1      ! iso-level not allowed
189            IF ( ln_traldf_hor   )   nldf = 0      ! horizontal (no rotation)
190            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
191         ENDIF
192         IF ( ln_sco ) THEN             ! z-coordinate
193            IF ( ln_traldf_level )   nldf = 0      ! iso-level  (no rotation)
194            IF ( ln_traldf_hor   )   nldf = 1      ! horizontal (   rotation)
195            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
196         ENDIF
197      ENDIF
198
199      IF( ln_traldf_bilap ) THEN      ! bilaplacian operator
200         IF ( ln_zco ) THEN                ! z-coordinate
201            IF ( ln_traldf_level )   nldf = 2      ! iso-level  (no rotation)
202            IF ( ln_traldf_hor   )   nldf = 2      ! horizontal (no rotation)
203            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
204         ENDIF
205         IF ( ln_zps ) THEN             ! z-coordinate
206            IF ( ln_traldf_level )   ierr = 1      ! iso-level not allowed
207            IF ( ln_traldf_hor   )   nldf = 2      ! horizontal (no rotation)
208            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
209         ENDIF
210         IF ( ln_sco ) THEN             ! z-coordinate
211            IF ( ln_traldf_level )   nldf = 2      ! iso-level  (no rotation)
212            IF ( ln_traldf_hor   )   nldf = 3      ! horizontal (   rotation)
213            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
214         ENDIF
215      ENDIF
216
217      IF( ierr == 1 )   CALL ctl_stop( ' iso-level in z-coordinate - partial step, not allowed' )
218      IF( ierr == 2 )   CALL ctl_stop( ' isoneutral bilaplacian operator does not exist' )
219      IF( lk_traldf_eiv .AND. .NOT.ln_traldf_iso )   &
220           CALL ctl_stop( '          eddy induced velocity on tracers',   &
221           &              ' the eddy induced velocity on tracers requires isopycnal laplacian diffusion' )
222      IF( nldf == 1 .OR. nldf == 3 ) THEN      ! rotation
223         IF( .NOT.lk_ldfslp )   CALL ctl_stop( '          the rotation of the diffusive tensor require key_ldfslp' )
224         l_traldf_rot = .TRUE.                 ! needed for trazdf_imp
225      ENDIF
226
227      IF( lk_esopa ) THEN
228         IF(lwp) WRITE(numout,*) '          esopa control: use all lateral physics options'
229         nldf = -1
230      ENDIF
231
232      IF(lwp) THEN
233         WRITE(numout,*)
234         IF( nldf == -2 )   WRITE(numout,*) '          NO lateral diffusion'
235         IF( nldf == -1 )   WRITE(numout,*) '          ESOPA test All scheme used'
236         IF( nldf ==  0 )   WRITE(numout,*) '          laplacian operator'
237         IF( nldf ==  1 )   WRITE(numout,*) '          Rotated laplacian operator'
238         IF( nldf ==  2 )   WRITE(numout,*) '          bilaplacian operator'
239         IF( nldf ==  3 )   WRITE(numout,*) '          Rotated bilaplacian'
240      ENDIF
241
242      ! Reference T & S diffusivity (if necessary)
243      ! ===========================
244      CALL ldf_ano
245      !
246   END SUBROUTINE tra_ldf_init
247
248#if defined key_traldf_ano
249   !!----------------------------------------------------------------------
250   !!   'key_traldf_ano'               T & S lateral diffusion on anomalies
251   !!----------------------------------------------------------------------
252
253   SUBROUTINE ldf_ano
254      !!----------------------------------------------------------------------
255      !!                  ***  ROUTINE ldf_ano  ***
256      !!
257      !! ** Purpose :   initializations of
258      !!----------------------------------------------------------------------
259      USE wrk_nemo, ONLY:   wrk_in_use, wrk_not_released
260      USE wrk_nemo, ONLY:   zt_ref => wrk_3d_1, ztb => wrk_3d_2, zavt => wrk_3d_3   ! 3D workspaces
261      USE wrk_nemo, ONLY:   zs_ref => wrk_3d_4, zsb => wrk_3d_5                     ! 3D workspaces
262
263      !! DCSE_NEMO: need additional directives for renamed module variables
264!FTRANS zt_ref ztb zavt zs_ref zsb :I :I :z
265      !
266      USE zdf_oce         ! vertical mixing
267      USE trazdf          ! vertical mixing: double diffusion
268      USE zdfddm          ! vertical mixing: double diffusion
269
270#  include "zdf_oce_ftrans.h90"
271#  include "zdfddm_ftrans.h90"
272
273      !
274#if defined key_z_first
275      INTEGER  ::   ji, jj, jk      ! Dummy loop indices
276#else
277      INTEGER  ::   jk              ! Dummy loop indice
278#endif
279      INTEGER  ::   ierr            ! local integer
280      LOGICAL  ::   llsave          ! local logical
281      REAL(wp) ::   zt0, zs0, z12   ! local scalar
282      !!----------------------------------------------------------------------
283
284      IF( wrk_in_use(3, 1,2,3,4,5) ) THEN
285         CALL ctl_stop('ldf_ano : requested workspace arrays unavailable')   ;   RETURN
286      ENDIF
287
288      IF(lwp) THEN
289         WRITE(numout,*)
290         WRITE(numout,*) 'tra:ldf_ano : lateral diffusion acting on anomalies'
291         WRITE(numout,*) '~~~~~~~~~~~'
292      ENDIF
293
294      !                              ! allocate trabbl arrays
295      ALLOCATE( t0_ldf(jpi,jpj,jpk) , s0_ldf(jpi,jpj,jpk) , STAT=ierr )
296      IF( lk_mpp    )   CALL mpp_sum( ierr )
297      IF( ierr /= 0 )   CALL ctl_stop( 'STOP', 'ldf_ano: unable to allocate arrays' )
298
299      ! defined the T & S reference profiles
300      ! ------------------------------------
301      zt0 =10.e0                               ! homogeneous ocean
302      zs0 =35.e0
303      zt_ref(:,:,:) = 10.0 * tmask(:,:,:)
304      zs_ref(:,:,:) = 35.0 * tmask(:,:,:)
305      IF(lwp) WRITE(numout,*) '              homogeneous ocean T = ', zt0, ' S = ',zs0
306
307      !                                        ! T & S profile (to be coded +namelist parameter
308
309      ! prepare the ldf computation
310      ! ---------------------------
311      llsave = l_trdtra
312      l_trdtra = .false.      ! desactivate trend computation
313      t0_ldf(:,:,:) = 0.e0
314      s0_ldf(:,:,:) = 0.e0
315      ztb   (:,:,:) = tsb (:,:,:,jp_tem)
316      zsb   (:,:,:) = tsb (:,:,:,jp_sal)
317      ua    (:,:,:) = tsa (:,:,:,jp_tem)
318      va    (:,:,:) = tsa (:,:,:,jp_sal)
319      zavt  (:,:,:) = avt(:,:,:)
320      IF( lk_zdfddm ) THEN CALL ctl_stop( ' key_traldf_ano with key_zdfddm not implemented' )
321      ! set tb, sb to reference values and avr to zero
322      tsb (:,:,:,jp_tem) = zt_ref(:,:,:)
323      tsb (:,:,:,jp_sal) = zs_ref(:,:,:)
324      tsa (:,:,:,jp_tem) = 0.e0
325      tsa (:,:,:,jp_sal) = 0.e0
326      avt(:,:,:)         = 0.e0
327
328      ! Compute the ldf trends
329      ! ----------------------
330      CALL tra_ldf( nit000+1 )      ! horizontal components (+1: no more init)
331      CALL tra_zdf( nit000   )      ! vertical component (if necessary nit000 to performed the init)
332
333      ! finalise the computation and recover all arrays
334      ! -----------------------------------------------
335      l_trdtra = llsave
336      z12 = 2.e0
337      IF( neuler == 1)   z12 = 1.e0
338      IF( ln_zdfexp ) THEN      ! ta,sa are the trends
339         t0_ldf(:,:,:) = tsa(:,:,:,jp_tem)
340         s0_ldf(:,:,:) = tsa(:,:,:,jp_sal)
341      ELSE
342#if defined key_z_first
343         DO jj = 1, jpj
344            DO ji = 1, jpi
345               DO jk = 1, jpkm1
346                  t0_ldf(ji,jj,jk) = ( tsa(ji,jj,jk,jp_tem) - tsb(ji,jj,jk,jp_tem) ) / ( z12 *rdttra(jk) )
347                  s0_ldf(ji,jj,jk) = ( tsa(ji,jj,jk,jp_sal) - tsb(ji,jj,jk,jp_sal) ) / ( z12 *rdttra(jk) )
348               END DO
349            END DO
350         END DO
351#else
352         DO jk = 1, jpkm1
353            t0_ldf(:,:,jk) = ( tsa(:,:,jk,jp_tem) - tsb(:,:,jk,jp_tem) ) / ( z12 *rdttra(jk) )
354            s0_ldf(:,:,jk) = ( tsa(:,:,jk,jp_sal) - tsb(:,:,jk,jp_sal) ) / ( z12 *rdttra(jk) )
355         END DO
356#endif
357      ENDIF
358      tsb(:,:,:,jp_tem) = ztb (:,:,:)
359      tsb(:,:,:,jp_sal) = zsb (:,:,:)
360      tsa(:,:,:,jp_tem) = ua  (:,:,:)
361      tsa(:,:,:,jp_sal) = va  (:,:,:)
362      avt(:,:,:)        = zavt(:,:,:)
363      !
364      IF( wrk_not_released(3, 1,2,3,4,5) )   CALL ctl_stop('ldf_ano: failed to release workspace arrays')
365      !
366   END SUBROUTINE ldf_ano
367
368#else
369   !!----------------------------------------------------------------------
370   !!   default option :   Dummy code   NO T & S background profiles
371   !!----------------------------------------------------------------------
372   SUBROUTINE ldf_ano
373      IF(lwp) THEN
374         WRITE(numout,*)
375         WRITE(numout,*) 'tra:ldf_ano : lateral diffusion acting on the full fields'
376         WRITE(numout,*) '~~~~~~~~~~~'
377      ENDIF
378   END SUBROUTINE ldf_ano
379#endif
380
381   !!======================================================================
382END MODULE traldf
Note: See TracBrowser for help on using the repository browser.