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.
dynzdf_tam.F90 in branches/2012/dev_r3604_LEGI8_TAM/NEMOGCM/NEMO/OPATAM_SRC/DYN – NEMO

source: branches/2012/dev_r3604_LEGI8_TAM/NEMOGCM/NEMO/OPATAM_SRC/DYN/dynzdf_tam.F90 @ 3627

Last change on this file since 3627 was 3611, checked in by pabouttier, 11 years ago

Add TAM code and ORCA2_TAM configuration - see Ticket #1007

  • Property svn:executable set to *
File size: 14.2 KB
Line 
1MODULE dynzdf_tam
2#ifdef key_tam
3   !!==============================================================================
4   !!                 ***  MODULE  dynzdf_tam  ***
5   !! Ocean dynamics :  vertical component of the momentum mixing trend
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 T&A module:
11   !!         9.0  !  08-06  (A. Vidard) Skeleton
12   !!         9.0  !  08-08  (A. Vidard) tam of the 05-11 version
13   !!----------------------------------------------------------------------
14
15   !!----------------------------------------------------------------------
16   !!   dyn_zdf      : Update the momentum trend with the vertical diffusion
17   !!       zdf_ctl  : initializations of the vertical diffusion scheme
18   !!----------------------------------------------------------------------
19   USE par_oce
20   USE oce_tam
21   USE dom_oce
22   USE zdf_oce
23   USE dynzdf_exp_tam
24   USE dynzdf_imp_tam
25   USE ldfdyn_oce
26   USE in_out_manager
27   USE gridrandom
28   USE dotprodfld
29   USE tstool_tam
30   USE lib_mpp
31   USE wrk_nemo
32   USE timing
33
34   IMPLICIT NONE
35   PRIVATE
36
37   PUBLIC   dyn_zdf_tan    !  routine called by step_tam.F90
38   PUBLIC   dyn_zdf_adj    !  routine called by step_tam.F90
39   PUBLIC   dyn_zdf_adj_tst!  routine called by tst.F90
40   PUBLIC   dyn_zdf_init_tam
41
42   INTEGER  ::   nzdf = 0              ! type vertical diffusion algorithm used
43      !                                ! defined from ln_zdf...  namlist logicals)
44
45   REAL(wp) ::   r2dt                  ! time-step, = 2 rdttra
46      !                                ! except at nit000 (=rdttra) if neuler=0
47   LOGICAL :: lfirst = .TRUE.
48
49   !! * Substitutions
50#  include "domzgr_substitute.h90"
51#  include "zdfddm_substitute.h90"
52#  include "vectopt_loop_substitute.h90"
53
54CONTAINS
55
56   SUBROUTINE dyn_zdf_tan( kt )
57      !!----------------------------------------------------------------------
58      !!                  ***  ROUTINE dyn_zdf_tan  ***
59      !!
60      !! ** Purpose of the direct routine:
61      !!            compute the vertical ocean dynamics physics.
62      !!---------------------------------------------------------------------
63      INTEGER, INTENT( in ) ::   kt      ! ocean time-step index
64      !!
65      !
66      IF( nn_timing == 1 )  CALL timing_start('dyn_zdf_tan')
67      !
68      !                                          ! set time step
69      IF( neuler == 0 .AND. kt == nit000    ) THEN   ;   r2dt =      rdt      ! = rdtra (restarting with Euler time stepping)
70      ELSEIF(               kt <= nit000 + 1) THEN   ;   r2dt = 2. * rdt      ! = 2 rdttra (leapfrog)
71      ENDIF
72      SELECT CASE ( nzdf )                       ! compute lateral mixing trend and add it to the general trend
73      !
74      CASE ( 0 )   ;   CALL dyn_zdf_exp_tan    ( kt, r2dt )      ! explicit scheme
75      CASE ( 1 )   ;   CALL dyn_zdf_imp_tan    ( kt, r2dt )      ! implicit scheme (k-j-i loop)
76      !
77      END SELECT
78      !
79      IF( nn_timing == 1 )  CALL timing_stop('dyn_zdf_tan')
80      !
81   END SUBROUTINE dyn_zdf_tan
82
83   SUBROUTINE dyn_zdf_adj( kt )
84      !!----------------------------------------------------------------------
85      !!                  ***  ROUTINE dyn_zdf_adj  ***
86      !!
87      !! ** Purpose of the direct routine:
88      !!            compute the vertical ocean dynamics physics.
89      !!---------------------------------------------------------------------
90      INTEGER, INTENT( in ) ::   kt      ! ocean time-step index
91      !!
92      !
93      IF( nn_timing == 1 )  CALL timing_start('dyn_zdf_adj')
94      !
95      !                                          ! set time step
96      IF( neuler == 0 .AND. kt == nit000    ) THEN   ;   r2dt =      rdt      ! = rdtra (restarting with Euler time stepping)
97      ELSEIF(               kt <= nit000 + 1) THEN   ;   r2dt = 2. * rdt      ! = 2 rdttra (leapfrog)
98      ELSEIF( kt == nitend ) THEN ; r2dt = 2. * rdt
99      ENDIF
100      SELECT CASE ( nzdf )                       ! compute lateral mixing trend and add it to the general trend
101      !
102      CASE ( 0 )   ;   CALL dyn_zdf_exp_adj    ( kt, r2dt )      ! explicit scheme
103      CASE ( 1 )   ;   CALL dyn_zdf_imp_adj    ( kt, r2dt )      ! implicit scheme (k-j-i loop)
104      !
105      END SELECT
106      !
107      IF( nn_timing == 1 )  CALL timing_stop('dyn_zdf_adj')
108      !
109   END SUBROUTINE dyn_zdf_adj
110   SUBROUTINE dyn_zdf_init_tam
111      !!----------------------------------------------------------------------
112      !!                 ***  ROUTINE zdf_ctl_tam  ***
113      !!
114      !! ** Purpose :   initializations of the vertical diffusion scheme
115      !!
116      !! ** Method  :   implicit (euler backward) scheme (default)
117      !!                explicit (time-splitting) scheme if ln_zdfexp=T
118      !!----------------------------------------------------------------------
119      USE zdfgls
120      USE zdftke, ONLY : lk_zdftke
121      USE zdfkpp, ONLY : lk_zdfkpp
122      !!----------------------------------------------------------------------
123
124      ! Choice from ln_zdfexp read in namelist in zdfini
125      IF( ln_zdfexp ) THEN   ;   nzdf = 0           ! use explicit scheme
126      ELSE                   ;   nzdf = 1           ! use implicit scheme
127      ENDIF
128
129      ! Force implicit schemes
130      IF( lk_zdfgls .OR. lk_zdftke .OR. lk_zdfkpp )   nzdf = 1   ! TKE or KPP physics
131      IF( ln_dynldf_iso                               )   nzdf = 1   ! iso-neutral lateral physics
132      IF( ln_dynldf_hor .AND. ln_sco                  )   nzdf = 1   ! horizontal lateral physics in s-coordinate
133
134      IF( lk_esopa )    nzdf = -1                   ! Esopa key: All schemes used
135
136      IF(lwp) THEN                                  ! Print the choice
137         WRITE(numout,*)
138         WRITE(numout,*) 'dyn:zdf_init_tam : vertical dynamics physics scheme'
139         WRITE(numout,*) '~~~~~~~~~~~~~~~'
140         IF( nzdf == -1 )   WRITE(numout,*) '              ESOPA test All scheme used'
141         IF( nzdf ==  0 )   WRITE(numout,*) '              Explicit time-splitting scheme'
142         IF( nzdf ==  1 )   WRITE(numout,*) '              Implicit (euler backward) scheme'
143      ENDIF
144      !
145      lfirst = .FALSE.
146   END SUBROUTINE dyn_zdf_init_tam
147   SUBROUTINE dyn_zdf_adj_tst( kumadt )
148      !!-----------------------------------------------------------------------
149      !!
150      !!                  ***  ROUTINE dyn_zdf_adj_tst ***
151      !!
152      !! ** Purpose : Test the adjoint routine.
153      !!
154      !! ** Method  : Verify the scalar product
155      !!
156      !!                 ( L dx )^T W dy  =  dx^T L^T W dy
157      !!
158      !!              where  L   = tangent routine
159      !!                     L^T = adjoint routine
160      !!                     W   = diagonal matrix of scale factors
161      !!                     dx  = input perturbation (random field)
162      !!                     dy  = L dx
163      !!
164      !! ** Action  : Separate tests are applied for the following dx and dy:
165      !!
166      !!              1) dx = ( SSH ) and dy = ( SSH )
167      !!
168      !! History :
169      !!        ! 08-08 (A. Vidard)
170      !!-----------------------------------------------------------------------
171      !! * Modules used
172
173      !! * Arguments
174      INTEGER, INTENT(IN) :: &
175         & kumadt          ! Output unit
176      INTEGER :: &
177         & ji,    &        ! dummy loop indices
178         & jj,    &
179         & jk
180
181      !! * Local declarations
182       REAL(KIND=wp), DIMENSION(:,:,:), ALLOCATABLE :: &
183         & zub_tlin,     & ! Tangent input: before u-velocity
184         & zvb_tlin,     & ! Tangent input: before v-velocity
185         & zua_tlin,     & ! Tangent input: after u-velocity
186         & zva_tlin,     & ! Tangent input: after v-velocity
187         & zua_tlout,    & ! Tangent output: after u-velocity
188         & zva_tlout,    & ! Tangent output: after v-velocity
189         & zua_adin,     & ! Adjoint input: after u-velocity
190         & zva_adin,     & ! Adjoint input: after v-velocity
191         & zub_adout,    & ! Adjoint output: before u-velocity
192         & zvb_adout,    & ! Adjoint output: before v-velocity
193         & zua_adout,    & ! Adjoint output: after u-velocity
194         & zva_adout,    & ! Adjoint output: after v-velocity
195         & zau,          & ! 3D random field for ua
196         & zav,          & ! 3D random field for va
197         & zbu,          & ! 3D random field for ub
198         & zbv             ! 3D random field for vb
199      REAL(KIND=wp) :: &
200         & zsp1,         & ! scalar product involving the tangent routine
201         & zsp1_1,       & !   scalar product components
202         & zsp1_2,       &
203         & zsp2,         & ! scalar product involving the adjoint routine
204         & zsp2_1,       & !   scalar product components
205         & zsp2_2,       &
206         & zsp2_3,       &
207         & zsp2_4
208      CHARACTER(LEN=14) :: cl_name
209      ! Allocate memory
210
211      ALLOCATE( &
212         & zua_tlin(jpi,jpj,jpk),     &
213         & zva_tlin(jpi,jpj,jpk),     &
214         & zub_tlin(jpi,jpj,jpk),     &
215         & zvb_tlin(jpi,jpj,jpk),     &
216         & zua_tlout(jpi,jpj,jpk),    &
217         & zva_tlout(jpi,jpj,jpk),    &
218         & zua_adin(jpi,jpj,jpk),     &
219         & zva_adin(jpi,jpj,jpk),     &
220         & zua_adout(jpi,jpj,jpk),    &
221         & zva_adout(jpi,jpj,jpk),    &
222         & zub_adout(jpi,jpj,jpk),    &
223         & zvb_adout(jpi,jpj,jpk),    &
224         & zau(jpi,jpj,jpk),          &
225         & zav(jpi,jpj,jpk),          &
226         & zbu(jpi,jpj,jpk),          &
227         & zbv(jpi,jpj,jpk)           &
228         & )
229
230      ! Initialize the direct trajectory
231      avmu(:,:,:) = rn_avm0 * umask(:,:,:)
232      avmv(:,:,:) = rn_avm0 * vmask(:,:,:)
233
234      !==================================================================
235      ! 1) dx = ( un_tl, vn_tl, hdivn_tl ) and
236      !    dy = ( hdivb_tl, hdivn_tl )
237      !==================================================================
238
239      !--------------------------------------------------------------------
240      ! Reset the tangent and adjoint variables
241      !--------------------------------------------------------------------
242
243      zua_tlin(:,:,:)  = 0.0_wp
244      zva_tlin(:,:,:)  = 0.0_wp
245      zub_tlin(:,:,:)  = 0.0_wp
246      zvb_tlin(:,:,:)  = 0.0_wp
247      zua_tlout(:,:,:) = 0.0_wp
248      zva_tlout(:,:,:) = 0.0_wp
249      zua_adin(:,:,:)  = 0.0_wp
250      zva_adin(:,:,:)  = 0.0_wp
251      zua_adout(:,:,:) = 0.0_wp
252      zva_adout(:,:,:) = 0.0_wp
253      zub_adout(:,:,:) = 0.0_wp
254      zvb_adout(:,:,:) = 0.0_wp
255      zau(:,:,:)       = 0.0_wp
256      zav(:,:,:)       = 0.0_wp
257      zbu(:,:,:)       = 0.0_wp
258      zbv(:,:,:)       = 0.0_wp
259
260      ub_tl(:,:,:)     = 0.0_wp
261      vb_tl(:,:,:)     = 0.0_wp
262      ua_tl(:,:,:)     = 0.0_wp
263      va_tl(:,:,:)     = 0.0_wp
264      ub_ad(:,:,:)     = 0.0_wp
265      vb_ad(:,:,:)     = 0.0_wp
266      ua_ad(:,:,:)     = 0.0_wp
267      va_ad(:,:,:)     = 0.0_wp
268
269      !--------------------------------------------------------------------
270      ! Initialize the tangent input with random noise: dx
271      !--------------------------------------------------------------------
272
273      CALL grid_random(  zbu, 'U', 0.0_wp, stdu )
274      CALL grid_random(  zbv, 'V', 0.0_wp, stdv )
275      CALL grid_random(  zau, 'U', 0.0_wp, stdu )
276      CALL grid_random(  zav, 'V', 0.0_wp, stdv )
277      DO jk = 1, jpk
278         DO jj = nldj, nlej
279            DO ji = nldi, nlei
280               zub_tlin(ji,jj,jk) = zbu(ji,jj,jk)
281               zvb_tlin(ji,jj,jk) = zbv(ji,jj,jk)
282               zua_tlin(ji,jj,jk) = zau(ji,jj,jk)
283               zva_tlin(ji,jj,jk) = zav(ji,jj,jk)
284            END DO
285         END DO
286      END DO
287
288      ub_tl(:,:,:) = zub_tlin(:,:,:)
289      vb_tl(:,:,:) = zvb_tlin(:,:,:)
290      ua_tl(:,:,:) = zua_tlin(:,:,:)
291      va_tl(:,:,:) = zva_tlin(:,:,:)
292
293      CALL dyn_zdf_tan( nit000 )
294
295      zua_tlout(:,:,:) = ua_tl(:,:,:)
296      zva_tlout(:,:,:) = va_tl(:,:,:)
297
298      !--------------------------------------------------------------------
299      ! Initialize the adjoint variables: dy^* = W dy
300      !--------------------------------------------------------------------
301
302      DO jk = 1, jpk
303        DO jj = nldj, nlej
304           DO ji = nldi, nlei
305              zua_adin(ji,jj,jk) = zua_tlout(ji,jj,jk) &
306                 &               * e1u(ji,jj) * e2u(ji,jj) * fse3u(ji,jj,jk) &
307                 &               * umask(ji,jj,jk)
308              zva_adin(ji,jj,jk) = zva_tlout(ji,jj,jk) &
309                 &               * e1v(ji,jj) * e2v(ji,jj) * fse3v(ji,jj,jk) &
310                 &               * vmask(ji,jj,jk)
311            END DO
312         END DO
313      END DO
314      !--------------------------------------------------------------------
315      ! Compute the scalar product: ( L dx )^T W dy
316      !--------------------------------------------------------------------
317
318      zsp1_1 = DOT_PRODUCT( zua_tlout, zua_adin )
319      zsp1_2 = DOT_PRODUCT( zva_tlout, zva_adin )
320      zsp1   = zsp1_1 + zsp1_2
321
322      !--------------------------------------------------------------------
323      ! Call the adjoint routine: dx^* = L^T dy^*
324      !--------------------------------------------------------------------
325
326      ua_ad(:,:,:) = zua_adin(:,:,:)
327      va_ad(:,:,:) = zva_adin(:,:,:)
328
329      CALL dyn_zdf_adj ( nit000 )
330      zub_adout(:,:,:)   = ub_ad(:,:,:)
331      zvb_adout(:,:,:)   = vb_ad(:,:,:)
332      zua_adout(:,:,:)   = ua_ad(:,:,:)
333      zva_adout(:,:,:)   = va_ad(:,:,:)
334
335      zsp2_1 = DOT_PRODUCT( zub_tlin, zub_adout )
336      zsp2_2 = DOT_PRODUCT( zvb_tlin, zvb_adout )
337      zsp2_3 = DOT_PRODUCT( zua_tlin, zua_adout )
338      zsp2_4 = DOT_PRODUCT( zva_tlin, zva_adout )
339      zsp2   = zsp2_1 + zsp2_2 + zsp2_3 + zsp2_4
340
341      ! Compare the scalar products
342
343      ! 14 char:'12345678901234'
344      cl_name = 'dyn_zdf_adj   '
345      CALL prntst_adj( cl_name, kumadt, zsp1, zsp2 )
346
347      DEALLOCATE( &
348         & zua_tlin,     &
349         & zva_tlin,     &
350         & zub_tlin,     &
351         & zvb_tlin,     &
352         & zua_tlout,    &
353         & zva_tlout,    &
354         & zua_adin,     &
355         & zva_adin,     &
356         & zua_adout,    &
357         & zva_adout,    &
358         & zub_adout,    &
359         & zvb_adout,    &
360         & zau,          &
361         & zav,          &
362         & zbu,          &
363         & zbv           &
364         & )
365
366  END SUBROUTINE dyn_zdf_adj_tst
367   !!==============================================================================
368#endif
369END MODULE dynzdf_tam
Note: See TracBrowser for help on using the repository browser.