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_tam.F90 in branches/TAM_V3_0/NEMOTAM/OPATAM_SRC/TRA – NEMO

source: branches/TAM_V3_0/NEMOTAM/OPATAM_SRC/TRA/traldf_tam.F90 @ 2587

Last change on this file since 2587 was 2587, checked in by vidard, 13 years ago

refer to ticket #798

File size: 12.5 KB
Line 
1MODULE traldf_tam
2#ifdef key_tam
3   !!======================================================================
4   !!                       ***  MODULE  traldf_tam  ***
5   !! Ocean Active tracers : lateral diffusive trends
6   !!                       Tangent and Adjoint Module
7   !!=====================================================================
8   !! History of the direct module: 
9   !!          9.0  ! 05-11 (G. Madec)  Original code
10   !! History of the TAM module:
11   !!          9.0  ! 08-06 (A. Vidard) Skeleton
12   !!          9.0  ! 09-03 (F. Vigilant) adding tra_ldf_lap option
13   !!          9.0  ! 10-06 (P.A. Bouttier) adding tra_ldf_bilap option
14   !!----------------------------------------------------------------------
15
16   !!----------------------------------------------------------------------
17   !!   tra_ldf     : update the tracer trend with the lateral diffusion
18   !!       ldf_ctl : initialization, namelist read, and parameters control
19   !!       ldf_ano : compute lateral diffusion for constant T-S profiles
20   !!----------------------------------------------------------------------
21   USE traldf_iso_tam, ONLY: & ! lateral mixing               (tra_ldf_iso routine)
22      & tra_ldf_iso_tan,     &
23      & tra_ldf_iso_adj,     &
24      & tra_ldf_iso_adj_tst
25   USE traldf_lap_tam, ONLY: & ! lateral mixing               (tra_ldf_lap_routine)
26      & tra_ldf_lap_tan,     &
27      & tra_ldf_lap_adj,     &
28#if defined key_tst_tlm
29      & tra_ldf_lap_tlm_tst, &
30#endif
31      & tra_ldf_lap_adj_tst
32   USE traldf_bilap_tam, ONLY: & !lateral mixing                (tra_ldf_bilap routine)
33      & tra_ldf_bilap_tan,   &
34      & tra_ldf_bilap_adj
35   USE in_out_manager, ONLY: & ! I/O manager
36      & ctl_stop, nit000, lwp, numout, nitend
37   USE ldftra_oce    , ONLY: & 
38      & lk_traldf_eiv,       &
39      & ln_traldf_lap,       & 
40      & ln_traldf_bilap,     &
41      & ln_traldf_level,     &
42      & ln_traldf_hor,       & 
43      & ln_traldf_iso 
44   USE dom_oce       , ONLY: & ! Ocean space and time domain
45      & ln_sco,              &
46      & ln_zps,              &
47      & ln_zco
48   USE oce           , ONLY: &
49      &  l_traldf_rot
50   USE ldfslp        , ONLY: &
51      & lk_ldfslp
52   IMPLICIT NONE
53   PRIVATE
54
55   PUBLIC   tra_ldf_tan     ! called by step_tam.F90
56   PUBLIC   tra_ldf_adj     ! called by step_tam.F90
57   PUBLIC   tra_ldf_adj_tst ! called by tamtst.F90
58#if defined key_tst_tlm
59   PUBLIC   tra_ldf_tlm_tst ! called by tamtst.F90
60#endif
61   PUBLIC   ldf_ctl_tam     ! called by trazdf_imp (init of l_traldf_rot)
62
63   INTEGER ::  nldf
64
65#  include "domzgr_substitute.h90"
66#  include "vectopt_loop_substitute.h90"
67
68CONTAINS
69
70   SUBROUTINE tra_ldf_tan( kt )
71      !!----------------------------------------------------------------------
72      !!                  ***  ROUTINE tra_ldf_tan  ***
73      !!
74      !! ** Purpose of the direct routine:
75      !!            compute the lateral ocean tracer physics.
76      !!
77      !!----------------------------------------------------------------------
78      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
79      !!
80      !!----------------------------------------------------------------------
81
82      IF( kt == nit000 )   CALL ldf_ctl_tam          ! initialisation & control of options
83
84      SELECT CASE ( nldf )                       ! compute lateral mixing trend and add it to the general trend
85      CASE ( 0 )   ;   CALL tra_ldf_lap_tan   ( kt )      ! iso-level laplacian
86      CASE ( 1 )   ;   CALL tra_ldf_iso_tan   ( kt )      ! rotated laplacian (except dk[ dk[.] ] part)
87      CASE ( 2 )   ;   CALL tra_ldf_bilap_tan ( kt )      ! iso-level bilaplacian
88      END SELECT
89   END SUBROUTINE tra_ldf_tan
90
91   SUBROUTINE tra_ldf_adj( kt )
92      !!----------------------------------------------------------------------
93      !!                  ***  ROUTINE tra_ldf_adj  ***
94      !!
95      !! ** Purpose of the direct routine:
96      !!            compute the lateral ocean tracer physics.
97      !!
98      !!----------------------------------------------------------------------
99      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
100      !!
101      IF( kt == nitend )   CALL ldf_ctl_tam      ! initialisation & control of options
102
103      SELECT CASE ( nldf )                       ! compute lateral mixing trend and add it to the general trend
104      CASE ( 0 )   ;   CALL tra_ldf_lap_adj   ( kt )      ! rotated laplacian (except dk[ dk[.] ] part)
105      CASE ( 1 )   ;   CALL tra_ldf_iso_adj   ( kt )      ! rotated laplacian (except dk[ dk[.] ] part)
106      CASE ( 2 )   ;   CALL tra_ldf_bilap_adj ( kt )      ! iso-level bilaplacian
107      END SELECT
108      !
109   END SUBROUTINE tra_ldf_adj
110
111   SUBROUTINE tra_ldf_adj_tst( kumadt )
112      !!-----------------------------------------------------------------------
113      !!
114      !!                  ***  ROUTINE example_adj_tst ***
115      !!
116      !! ** Purpose : Test the adjoint routine.
117      !!
118      !! ** Method  : Verify the scalar product
119      !!           
120      !!                 ( L dx )^T W dy  =  dx^T L^T W dy
121      !!
122      !!              where  L   = tangent routine
123      !!                     L^T = adjoint routine
124      !!                     W   = diagonal matrix of scale factors
125      !!                     dx  = input perturbation (random field)
126      !!                     dy  = L dx
127      !!
128      !!                   
129      !! History :
130      !!        ! 08-08 (A. Vidard)
131      !!-----------------------------------------------------------------------
132      !! * Modules used
133
134      !! * Arguments
135      INTEGER, INTENT(IN) :: &
136         & kumadt             ! Output unit
137
138      CALL ldf_ctl_tam
139
140      SELECT CASE ( nldf )                       ! compute lateral mixing trend and add it to the general trend
141       CASE ( 0 )   ;   CALL tra_ldf_lap_adj_tst( kumadt )
142       CASE ( 1 )   ;   CALL tra_ldf_iso_adj_tst( kumadt )
143      END SELECT
144
145   END SUBROUTINE tra_ldf_adj_tst
146
147   SUBROUTINE ldf_ctl_tam
148      !!----------------------------------------------------------------------
149      !!                  ***  ROUTINE ldf_ctl  ***
150      !!
151      !! ** Purpose :   Choice of the operator for the lateral tracer diffusion
152      !!
153      !! ** Method  :   set nldf from the nam_traldf logicals
154      !!      nldf == -1   ESOPA test: ALL operators are used
155      !!      nldf ==  0   laplacian operator
156      !!      nldf ==  1   Rotated laplacian operator
157      !!      nldf ==  2   bilaplacian operator
158      !!      nldf ==  3   Rotated bilaplacian
159      !!----------------------------------------------------------------------
160      INTEGER ::   ioptio, ierr         ! temporary integers
161!     
162!     NAMELIST/nam_traldf/ ln_traldf_lap  , ln_traldf_bilap,                &
163!        &                 ln_traldf_level, ln_traldf_hor, ln_traldf_iso,   &
164!        &                 aht0, ahtb0, aeiv0
165      !!----------------------------------------------------------------------
166
167      !  Define the lateral mixing oparator for tracers
168      ! ===============================================
169   
170      ! Namelist nam_traldf already read in ldftra module
171!     ! Read Namelist nam_traldf : Lateral physics on tracers
172!     REWIND( numnam )
173!     READ  ( numnam, nam_traldf )
174
175      IF(lwp) THEN                    ! Namelist print
176         WRITE(numout,*)
177         WRITE(numout,*) 'tra:ldf_ctl : lateral tracer diffusive operator'
178         WRITE(numout,*) '~~~~~~~~~~~'
179         WRITE(numout,*) '       Namelist nam_traldf : set lateral mixing parameters (type, direction, coefficients)'
180         WRITE(numout,*) '          laplacian operator          ln_traldf_lap   = ', ln_traldf_lap
181         WRITE(numout,*) '          bilaplacian operator        ln_traldf_bilap = ', ln_traldf_bilap
182         WRITE(numout,*) '          iso-level                   ln_traldf_level = ', ln_traldf_level
183         WRITE(numout,*) '          horizontal (geopotential)   ln_traldf_hor   = ', ln_traldf_hor
184         WRITE(numout,*) '          iso-neutral                 ln_traldf_iso   = ', ln_traldf_iso
185      ENDIF
186
187      !                               ! control the input
188      ioptio = 0
189      IF( ln_traldf_lap   )   ioptio = ioptio + 1
190      IF( ln_traldf_bilap )   ioptio = ioptio + 1
191      IF( ioptio >  1 )   CALL ctl_stop( '          use ONE or NONE of the 2 lap/bilap operator type on tracer' )
192      IF( ioptio == 0 )   nldf = -2   ! No lateral diffusion
193      ioptio = 0
194      IF( ln_traldf_level )   ioptio = ioptio + 1
195      IF( ln_traldf_hor   )   ioptio = ioptio + 1
196      IF( ln_traldf_iso   )   ioptio = ioptio + 1
197      IF( ioptio /= 1 )   CALL ctl_stop( '          use only ONE direction (level/hor/iso)' )
198
199      ! defined the type of lateral diffusion from ln_traldf_... logicals
200      ! CAUTION : nldf = 1 is used in trazdf_imp, change it carefully
201      ierr = 0
202      IF( ln_traldf_lap ) THEN       ! laplacian operator
203         IF ( ln_zco ) THEN                ! z-coordinate
204            IF ( ln_traldf_level )   nldf = 0      ! iso-level  (no rotation)
205            IF ( ln_traldf_hor   )   nldf = 0      ! horizontal (no rotation)
206            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
207         ENDIF
208         IF ( ln_zps ) THEN             ! z-coordinate
209            IF ( ln_traldf_level )   ierr = 1      ! iso-level not allowed
210            IF ( ln_traldf_hor   )   nldf = 0      ! horizontal (no rotation)
211            IF ( ln_traldf_iso   )   nldf = 1      ! isoneutral (   rotation)
212         ENDIF
213         IF ( ln_sco ) THEN             ! z-coordinate
214           CALL ctl_stop( '          You shouldn t have seen this error message, ln_sco option not impemented yet for tam' )
215         ENDIF
216      ENDIF
217
218      IF( ln_traldf_bilap ) THEN      ! bilaplacian operator
219         IF ( ln_zco ) THEN                ! z-coordinate
220            IF ( ln_traldf_level )   nldf = 2      ! iso-level  (no rotation)
221            IF ( ln_traldf_hor   )   nldf = 2      ! horizontal (no rotation)
222            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
223      ENDIF
224         IF ( ln_zps ) THEN             ! z-coordinate
225            IF ( ln_traldf_level )   ierr = 1      ! iso-level not allowed
226            IF ( ln_traldf_hor   )   nldf = 2      ! horizontal (no rotation)
227            IF ( ln_traldf_iso   )   ierr = 2      ! isoneutral (   rotation)
228         ENDIF
229      ENDIF
230
231      IF( ierr == 1 )   CALL ctl_stop( ' iso-level in z-coordinate - partial step, not allowed' )
232      IF( ierr == 2 )   CALL ctl_stop( ' isoneutral bilaplacian operator does not exist' )
233      IF( lk_traldf_eiv .AND. .NOT.ln_traldf_iso )   &
234           CALL ctl_stop( '          eddy induced velocity on tracers',   &
235           &              ' the eddy induced velocity on tracers requires isopycnal laplacian diffusion' )
236      IF( nldf == 1 .OR. nldf == 3 ) THEN      ! rotation
237         IF( .NOT.lk_ldfslp )   CALL ctl_stop( '          the rotation of the diffusive tensor require key_ldfslp' )
238         l_traldf_rot = .TRUE.                 ! needed for trazdf_imp
239      ENDIF
240
241      IF(lwp) THEN
242         WRITE(numout,*)
243         IF( nldf == -2 )   WRITE(numout,*) '          NO lateral diffusion'
244         IF( nldf ==  0 )   WRITE(numout,*) '          laplacian operator'
245         IF( nldf ==  1 )   WRITE(numout,*) '          Rotated laplacian operator'
246      ENDIF
247
248   END SUBROUTINE ldf_ctl_tam
249
250#if defined key_tst_tlm
251   SUBROUTINE tra_ldf_tlm_tst( kumadt )
252      !!-----------------------------------------------------------------------
253      !!
254      !!                  ***  ROUTINE tra_ldf_tlm_tst ***
255      !!
256      !! ** Purpose : Test the tangent routine.
257      !!
258      !! ** Method  : Verify the tangent with Taylor expansion
259      !!           
260      !!                 M(x+hdx) = M(x) + L(hdx) + O(h^2)
261      !!
262      !!              where  L   = tangent routine
263      !!                     M   = direct routine
264      !!                     dx  = input perturbation (random field)
265      !!                     h   = ration on perturbation
266      !!                   
267      !! History :
268      !!        ! 09-08 (A. Vigilant)
269      !!-----------------------------------------------------------------------
270      !! * Modules used
271
272      !! * Arguments
273      INTEGER, INTENT(IN) :: &
274         & kumadt             ! Output unit
275
276      CALL ldf_ctl_tam
277
278      ! Force nldf to 0
279      nldf = 0
280
281      SELECT CASE ( nldf )                       ! compute lateral mixing trend and add it to the general trend
282       CASE ( 0 )   ;   CALL tra_ldf_lap_tlm_tst( kumadt )
283!       CASE ( 1 )   ;   CALL tra_ldf_iso_adj_tst( kumadt )
284      END SELECT
285
286   END SUBROUTINE tra_ldf_tlm_tst
287   !!======================================================================
288#endif
289#endif
290END MODULE traldf_tam
Note: See TracBrowser for help on using the repository browser.