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/UKMO/dev_r5518_GO6_package_for_static_diagnostics/NEMOGCM/NEMO/OPA_SRC/TRA – NEMO

source: branches/UKMO/dev_r5518_GO6_package_for_static_diagnostics/NEMOGCM/NEMO/OPA_SRC/TRA/traldf.F90 @ 7582

Last change on this file since 7582 was 7582, checked in by timgraham, 8 years ago

Added code to allow output of some diagnostics which are constant in Met Office CMIP6 models
Changes described in UKESM ticket 324 (https://code.metoffice.gov.uk/trac/UKESM/ticket/324)

File size: 17.9 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   USE traldf_iso_grif ! lateral mixing          (tra_ldf_iso_grif routine)
24   USE traldf_lap      ! lateral mixing               (tra_ldf_lap routine)
25   USE trd_oce         ! trends: ocean variables
26   USE trdtra          ! trends manager: tracers
27   !
28   USE prtctl          ! Print control
29   USE in_out_manager  ! I/O manager
30   USE lib_mpp         ! distribued memory computing library
31   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
32   USE wrk_nemo        ! Memory allocation
33   USE timing          ! Timing
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   !! * Substitutions
47#  include "domzgr_substitute.h90"
48#  include "vectopt_loop_substitute.h90"
49   !!----------------------------------------------------------------------
50   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
51   !! $Id$
52   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
53   !!----------------------------------------------------------------------
54CONTAINS
55
56   SUBROUTINE tra_ldf( kt )
57      !!----------------------------------------------------------------------
58      !!                  ***  ROUTINE tra_ldf  ***
59      !!
60      !! ** Purpose :   compute the lateral ocean tracer physics.
61      !!----------------------------------------------------------------------
62      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
63      !!
64      REAL(wp), POINTER, DIMENSION(:,:,:) ::  ztrdt, ztrds
65      !!----------------------------------------------------------------------
66      !
67      IF( nn_timing == 1 )  CALL timing_start('tra_ldf')
68      !
69      rldf = 1     ! For active tracers the
70      r_fact_lap(:,:,:) = 1.0
71
72      IF( l_trdtra )   THEN                    !* Save ta and sa trends
73         CALL wrk_alloc( jpi, jpj, jpk, ztrdt, ztrds ) 
74         ztrdt(:,:,:) = tsa(:,:,:,jp_tem) 
75         ztrds(:,:,:) = tsa(:,:,:,jp_sal)
76      ENDIF
77
78
79#ifdef key_traldf_c2d
80      IF (kt == nit000) THEN
81         CALL iom_put( "aht2D", ahtw)
82#endif
83
84
85      SELECT CASE ( nldf )                       ! compute lateral mixing trend and add it to the general trend
86      CASE ( 0 )   ;   CALL tra_ldf_lap     ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi,        &
87                               &                                   tsb, tsa, jpts        )  ! iso-level laplacian
88      CASE ( 1 )                                                                              ! rotated laplacian
89         IF( ln_traldf_grif ) THEN                                                         
90                       CALL tra_ldf_iso_grif( kt, nit000,'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 )      ! Griffies operator
91         ELSE                                                                               
92                       CALL tra_ldf_iso     ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi,        &
93                               &                                  tsb, tsa, jpts, ahtb0 )      ! Madec operator
94         ENDIF
95      CASE ( 2 )   ;   CALL tra_ldf_bilap   ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi,        &
96                               &                                   tsb, tsa, jpts        )  ! iso-level bilaplacian
97      CASE ( 3 )   ;   CALL tra_ldf_bilapg  ( kt, nit000, 'TRA',             tsb, tsa, jpts        )  ! s-coord. geopot. bilap.
98         !
99      CASE ( -1 )                                ! esopa: test all possibility with control print
100         CALL tra_ldf_lap   ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi,        &
101         &                                       tsb, tsa, jpts        ) 
102         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf0 - Ta: ', mask1=tmask,               &
103         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
104         IF( ln_traldf_grif ) THEN
105            CALL tra_ldf_iso_grif( kt, nit000, 'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 )
106         ELSE
107            CALL tra_ldf_iso     ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi,        &
108            &                                               tsb, tsa, jpts, ahtb0 ) 
109         ENDIF
110         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf1 - Ta: ', mask1=tmask,               &
111         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
112         CALL tra_ldf_bilap ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi,        &
113         &                                       tsb, tsa, jpts        ) 
114         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf2 - Ta: ', mask1=tmask,               &
115         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
116         CALL tra_ldf_bilapg( kt, nit000, 'TRA',             tsb, tsa, jpts        ) 
117         CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf3 - Ta: ', mask1=tmask,               &
118         &             tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
119      END SELECT
120
121#if defined key_traldf_ano
122      tsa(:,:,:,jp_tem) = tsa(:,:,:,jp_tem) - t0_ldf(:,:,:)      ! anomaly: substract the reference diffusivity
123      tsa(:,:,:,jp_sal) = tsa(:,:,:,jp_sal) - s0_ldf(:,:,:)
124#endif
125
126      IF( l_trdtra )   THEN                      ! save the horizontal diffusive trends for further diagnostics
127         ztrdt(:,:,:) = tsa(:,:,:,jp_tem) - ztrdt(:,:,:)
128         ztrds(:,:,:) = tsa(:,:,:,jp_sal) - ztrds(:,:,:)
129         CALL trd_tra( kt, 'TRA', jp_tem, jptra_ldf, ztrdt )
130         CALL trd_tra( kt, 'TRA', jp_sal, jptra_ldf, ztrds )
131         CALL wrk_dealloc( jpi, jpj, jpk, ztrdt, ztrds ) 
132      ENDIF
133      !                                          ! print mean trends (used for debugging)
134      IF(ln_ctl)   CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf  - Ta: ', mask1=tmask,               &
135         &                       tab3d_2=tsa(:,:,:,jp_sal), clinfo2=       ' Sa: ', mask2=tmask, clinfo3='tra' )
136      !
137      IF( nn_timing == 1 )  CALL timing_stop('tra_ldf')
138      !
139   END SUBROUTINE tra_ldf
140
141
142   SUBROUTINE tra_ldf_init
143      !!----------------------------------------------------------------------
144      !!                  ***  ROUTINE tra_ldf_init  ***
145      !!
146      !! ** Purpose :   Choice of the operator for the lateral tracer diffusion
147      !!
148      !! ** Method  :   set nldf from the namtra_ldf logicals
149      !!      nldf == -1   ESOPA test: ALL operators are used
150      !!      nldf ==  0   laplacian operator
151      !!      nldf ==  1   Rotated laplacian operator
152      !!      nldf ==  2   bilaplacian operator
153      !!      nldf ==  3   Rotated bilaplacian
154      !!----------------------------------------------------------------------
155      INTEGER ::   ioptio, ierr         ! temporary integers
156      !!----------------------------------------------------------------------
157
158      !  Define the lateral mixing oparator for tracers
159      ! ===============================================
160   
161      IF(lwp) THEN                    ! Namelist print
162         WRITE(numout,*)
163         WRITE(numout,*) 'tra_ldf_init : lateral tracer diffusive operator'
164         WRITE(numout,*) '~~~~~~~~~~~'
165         WRITE(numout,*) '   Namelist namtra_ldf already read in ldftra module'
166         WRITE(numout,*) '   see ldf_tra_init report for lateral mixing parameters'
167         WRITE(numout,*)
168      ENDIF
169
170      !                               ! control the input
171      ioptio = 0
172      IF( ln_traldf_lap   )   ioptio = ioptio + 1
173      IF( ln_traldf_bilap )   ioptio = ioptio + 1
174      IF( ioptio >  1 )   CALL ctl_stop( '          use ONE or NONE of the 2 lap/bilap operator type on tracer' )
175      IF( ioptio == 0 )   nldf = -2   ! No lateral diffusion
176      ioptio = 0
177      IF( ln_traldf_level )   ioptio = ioptio + 1
178      IF( ln_traldf_hor   )   ioptio = ioptio + 1
179      IF( ln_traldf_iso   )   ioptio = ioptio + 1
180      IF( ioptio >  1 )   CALL ctl_stop( '          use only ONE direction (level/hor/iso)' )
181
182      ! defined the type of lateral diffusion from ln_traldf_... logicals
183      ! CAUTION : nldf = 1 is used in trazdf_imp, change it carefully
184      ierr = 0
185      IF( ln_traldf_lap ) THEN       ! laplacian operator
186         IF ( ln_zco ) THEN                ! z-coordinate
187            IF ( ln_traldf_level )   nldf = 0      ! iso-level  (no rotation)
188            IF ( ln_traldf_hor   )   nldf = 0      ! horizontal (no rotation)
189            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
190         ENDIF
191         IF ( ln_zps ) THEN             ! zps-coordinate
192            IF ( ln_traldf_level )   ierr = 1      ! iso-level not allowed
193            IF ( ln_traldf_hor   )   nldf = 0      ! horizontal (no rotation)
194            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
195         ENDIF
196         IF ( ln_sco ) THEN             ! s-coordinate
197            IF ( ln_traldf_level )   nldf = 0      ! iso-level  (no rotation)
198            IF ( ln_traldf_hor   )   nldf = 1      ! horizontal (   rotation)
199            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
200         ENDIF
201      ENDIF
202
203      IF( ln_traldf_bilap ) THEN      ! bilaplacian operator
204         IF ( ln_zco ) THEN                ! z-coordinate
205            IF ( ln_traldf_level )   nldf = 2      ! iso-level  (no rotation)
206            IF ( ln_traldf_hor   )   nldf = 2      ! horizontal (no rotation)
207            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
208         ENDIF
209         IF ( ln_zps ) THEN             ! zps-coordinate
210            IF ( ln_traldf_level )   ierr = 1      ! iso-level not allowed
211            IF ( ln_traldf_hor   )   nldf = 2      ! horizontal (no rotation)
212            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
213         ENDIF
214         IF ( ln_sco ) THEN             ! s-coordinate
215            IF ( ln_traldf_level )   nldf = 2      ! iso-level  (no rotation)
216            IF ( ln_traldf_hor   )   nldf = 3      ! horizontal (   rotation)
217            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
218         ENDIF
219      ENDIF
220
221      IF( nldf == 3 )   CALL ctl_warn( 'geopotential bilaplacian tracer diffusion in s-coords not thoroughly tested' )
222      IF( ierr == 1 )   CALL ctl_stop( ' iso-level in z-coordinate - partial step, not allowed' )
223      IF( ierr == 2 )   CALL ctl_stop( ' isoneutral bilaplacian operator does not exist' )
224      IF( ln_traldf_grif .AND. ln_isfcav         )   &
225           CALL ctl_stop( ' ice shelf and traldf_grif not tested')
226      IF( lk_traldf_eiv .AND. .NOT.ln_traldf_iso )   &
227           CALL ctl_stop( '          eddy induced velocity on tracers',   &
228           &              ' the eddy induced velocity on tracers requires isopycnal laplacian diffusion' )
229      IF( nldf == 1 .OR. nldf == 3 ) THEN      ! rotation
230         IF( .NOT.lk_ldfslp )   CALL ctl_stop( '          the rotation of the diffusive tensor require key_ldfslp' )
231         l_traldf_rot = .TRUE.                 ! needed for trazdf_imp
232      ENDIF
233
234      IF( lk_esopa ) THEN
235         IF(lwp) WRITE(numout,*) '          esopa control: use all lateral physics options'
236         nldf = -1
237      ENDIF
238
239      IF(lwp) THEN
240         WRITE(numout,*)
241         IF( nldf == -2 )   WRITE(numout,*) '          NO lateral diffusion'
242         IF( nldf == -1 )   WRITE(numout,*) '          ESOPA test All scheme used'
243         IF( nldf ==  0 )   WRITE(numout,*) '          laplacian operator'
244         IF( nldf ==  1 )   WRITE(numout,*) '          Rotated laplacian operator'
245         IF( nldf ==  2 )   WRITE(numout,*) '          bilaplacian operator'
246         IF( nldf ==  3 )   WRITE(numout,*) '          Rotated bilaplacian'
247      ENDIF
248
249      ! Reference T & S diffusivity (if necessary)
250      ! ===========================
251      CALL ldf_ano
252      !
253   END SUBROUTINE tra_ldf_init
254
255#if defined key_traldf_ano
256   !!----------------------------------------------------------------------
257   !!   'key_traldf_ano'               T & S lateral diffusion on anomalies
258   !!----------------------------------------------------------------------
259
260   SUBROUTINE ldf_ano
261      !!----------------------------------------------------------------------
262      !!                  ***  ROUTINE ldf_ano  ***
263      !!
264      !! ** Purpose :   initializations of
265      !!----------------------------------------------------------------------
266      !
267      USE zdf_oce         ! vertical mixing
268      USE trazdf          ! vertical mixing: double diffusion
269      USE zdfddm          ! vertical mixing: double diffusion
270      !
271      INTEGER  ::   jk              ! Dummy loop indice
272      INTEGER  ::   ierr            ! local integer
273      LOGICAL  ::   llsave          ! local logical
274      REAL(wp) ::   zt0, zs0, z12   ! local scalar
275      REAL(wp), POINTER, DIMENSION(:,:,:) :: zt_ref, zs_ref, ztb, zsb, zavt     
276      !!----------------------------------------------------------------------
277      !
278      IF( nn_timing == 1 )  CALL timing_start('ldf_ano')
279      !
280      CALL wrk_alloc( jpi, jpj, jpk, zt_ref, zs_ref, ztb, zsb, zavt ) 
281      !
282
283      IF(lwp) THEN
284         WRITE(numout,*)
285         WRITE(numout,*) 'tra:ldf_ano : lateral diffusion acting on anomalies'
286         WRITE(numout,*) '~~~~~~~~~~~'
287      ENDIF
288
289      !                              ! allocate trabbl arrays
290      ALLOCATE( t0_ldf(jpi,jpj,jpk) , s0_ldf(jpi,jpj,jpk) , STAT=ierr )
291      IF( lk_mpp    )   CALL mpp_sum( ierr )
292      IF( ierr /= 0 )   CALL ctl_stop( 'STOP', 'ldf_ano: unable to allocate arrays' )
293
294      ! defined the T & S reference profiles
295      ! ------------------------------------
296      zt0 =10.e0                               ! homogeneous ocean
297      zs0 =35.e0
298      zt_ref(:,:,:) = 10.0 * tmask(:,:,:)
299      zs_ref(:,:,:) = 35.0 * tmask(:,:,:)
300      IF(lwp) WRITE(numout,*) '              homogeneous ocean T = ', zt0, ' S = ',zs0
301
302      ! Initialisation of gtui/gtvi in case of no cavity
303      IF ( .NOT. ln_isfcav ) THEN
304         gtui(:,:,:) = 0.0_wp
305         gtvi(:,:,:) = 0.0_wp
306      END IF
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         DO jk = 1, jpkm1
343            t0_ldf(:,:,jk) = ( tsa(:,:,jk,jp_tem) - tsb(:,:,jk,jp_tem) ) / ( z12 *rdttra(jk) )
344            s0_ldf(:,:,jk) = ( tsa(:,:,jk,jp_sal) - tsb(:,:,jk,jp_sal) ) / ( z12 *rdttra(jk) )
345         END DO
346      ENDIF
347      tsb(:,:,:,jp_tem) = ztb (:,:,:)
348      tsb(:,:,:,jp_sal) = zsb (:,:,:)
349      tsa(:,:,:,jp_tem) = ua  (:,:,:)
350      tsa(:,:,:,jp_sal) = va  (:,:,:)
351      avt(:,:,:)        = zavt(:,:,:)
352      !
353      CALL wrk_dealloc( jpi, jpj, jpk, zt_ref, zs_ref, ztb, zsb, zavt ) 
354      !
355      IF( nn_timing == 1 )  CALL timing_stop('ldf_ano')
356      !
357   END SUBROUTINE ldf_ano
358
359#else
360   !!----------------------------------------------------------------------
361   !!   default option :   Dummy code   NO T & S background profiles
362   !!----------------------------------------------------------------------
363   SUBROUTINE ldf_ano
364      IF(lwp) THEN
365         WRITE(numout,*)
366         WRITE(numout,*) 'tra:ldf_ano : lateral diffusion acting on the full fields'
367         WRITE(numout,*) '~~~~~~~~~~~'
368      ENDIF
369   END SUBROUTINE ldf_ano
370#endif
371
372   !!======================================================================
373END MODULE traldf
Note: See TracBrowser for help on using the repository browser.