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

source: branches/TAM_V3_0/NEMOTAM/OPATAM_SRC/DYN/dynadv_tam.F90 @ 3400

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

refer to ticket #798

File size: 36.1 KB
Line 
1MODULE dynadv_tam
2#ifdef key_tam
3   !!==============================================================================
4   !!                       ***  MODULE  dynadv_tam  ***
5   !! Ocean active tracers:  advection scheme control
6   !!                        Tangent and Adjoint module
7   !!==============================================================================
8   !! History of the direct module: 
9   !!           9.0  !  06-11  (G. Madec)  Original code
10   !! History of the TAM module:
11   !!           9.0  !  08-08  (A. Vidard) first version
12   !!----------------------------------------------------------------------
13
14   !!----------------------------------------------------------------------
15   !!   dyn_adv      : compute the momentum advection trend
16   !!   dyn_adv_ctl  : control the different options of advection scheme
17   !!----------------------------------------------------------------------
18   USE par_kind,       ONLY: & ! Precision variables
19      & wp
20   USE par_oce,        ONLY: & ! Ocean space and time domain variables
21      & jpi,                 &
22      & jpj,                 & 
23      & jpk,                 &
24      & jpiglo   
25   USE oce,            ONLY: &
26      & un,                  &
27      & vn,                  &
28      & wn,                  &
29      & ua,                  &
30      & va
31   USE dom_oce,        ONLY: & ! ocean space and time domain
32      & umask,               &
33      & vmask,               &
34      & mig,                 &
35      & mjg,                 &
36      & e1u,                 &
37      & e2u,                 &
38      & e1v,                 &
39      & e2v,                 &
40# if defined key_zco
41      & e3t_0,               &
42# else
43      & e3u,                 &
44      & e3v,                 &
45# endif
46      & nldi,                &
47      & nldj,                &
48      & nlei,                &
49      & nlej
50   USE oce_tam,        ONLY: &
51      & un_tl,               &
52      & vn_tl,               &
53      & wn_tl,               &
54      & ua_tl,               &
55      & va_tl,               &
56      & un_ad,               &
57      & vn_ad,               &
58      & wn_ad,               &
59      & ua_ad,               &
60      & va_ad
61
62   USE in_out_manager, ONLY: & ! I/O manager
63      & ctl_stop,            &
64      & lwp,                 &
65      & lk_esopa,            & 
66      & numout,              & 
67      & numnam,              & 
68      & nit000,              & 
69      & nitend
70   USE gridrandom,     ONLY: & ! Random Gaussian noise on grids
71      & grid_random
72   USE dotprodfld,     ONLY: & ! Computes dot product for 3D and 2D fields
73      & dot_product
74   USE tstool_tam,     ONLY: &
75      & prntst_adj,          & !
76      & prntst_tlm,          & !
77      & stdu,                & ! stdev for u-velocity
78      & stdv,                & !           v-velocity
79      & stdw                   !           w-velocity
80
81   USE dynadv,         ONLY: &
82      & dyn_adv_ctl,         &
83      & ln_dynadv_vec,       & ! vector form flag
84      & ln_dynadv_cen2,      & ! flux form - 2nd order centered scheme flag
85      & ln_dynadv_ubs          ! flux form - 3rd order UBS s
86
87!   USE dynadv_cen2_tam ! centred flux form advection      (dyn_adv_cen2 routine)
88!   USE dynadv_ubs_tam  ! UBS flux form advection          (dyn_adv_ubs  routine)
89   USE dynkeg_tam,     ONLY: & ! kinetic energy gradient          (dyn_keg      routine)
90      & dyn_keg_tan,         &
91      & dyn_keg_adj
92   USE dynzad_tam,     ONLY: & ! vertical advection               (dyn_zad    routine) 
93      & dyn_zad_tan,         &
94      & dyn_zad_adj
95
96   USE wzvmod        , ONLY: &
97      & wzv
98   USE divcur        , ONLY: &
99      & div_cur
100   USE wzvmod_tam    , ONLY: &
101      & wzv_tan
102   USE divcur_tam    , ONLY: &
103      & div_cur_tan
104
105
106   IMPLICIT NONE
107   PRIVATE
108
109   PUBLIC dyn_adv_tan     ! routine called by steptan module
110   PUBLIC dyn_adv_adj     ! routine called by stepadj module
111   PUBLIC dyn_adv_adj_tst ! routine called by the tst module
112   PUBLIC dyn_adv_tlm_tst ! routine called by tamtst.F90
113 
114   INTEGER    ::   nadv   ! choice of the formulation and scheme for the advection
115   LOGICAL    ::   lfirst=.TRUE.     
116   !! * Substitutions
117#  include "domzgr_substitute.h90"
118#  include "vectopt_loop_substitute.h90"
119
120CONTAINS
121
122   SUBROUTINE dyn_adv_tan( kt )
123      !!---------------------------------------------------------------------
124      !!                  ***  ROUTINE dyn_adv_tan  ***
125      !!               
126      !! ** Purpose of the direct routine:
127      !!            compute the ocean momentum advection trend.
128      !!
129      !! ** Method  : - Update (ua,va) with the advection term following nadv
130      !!      NB: in flux form advection (ln_dynadv_cen2 or ln_dynadv_ubs=T)
131      !!      a metric term is add to the coriolis term while in vector form
132      !!      it is the relative vorticity which is added to coriolis term
133      !!      (see dynvor module).
134      !!----------------------------------------------------------------------
135      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
136      !!----------------------------------------------------------------------
137      !
138      IF( kt == nit000 )   CALL dyn_adv_ctl_tam! initialisation & control of options
139
140      SELECT CASE ( nadv )                     ! compute advection trend and add it to general trend
141      CASE ( 0 )     
142                      CALL dyn_keg_tan     ( kt )    ! vector form : horizontal gradient of kinetic energy
143                      CALL dyn_zad_tan     ( kt )    ! vector form : vertical advection
144      CASE ( 1 ) 
145         IF (lwp) WRITE(numout,*) 'dyn_adv_cen2_tan not available yet' 
146         CALL abort
147!                      CALL dyn_adv_cen2_tan( kt )    ! 2nd order centered scheme
148      CASE ( 2 )   
149         IF (lwp) WRITE(numout,*) 'dyn_adv_ubs_tan not available yet' 
150         CALL abort
151!                      CALL dyn_adv_ubs_tan ( kt )    ! 3rd order UBS      scheme
152      !
153      CASE (-1 )                                 ! esopa: test all possibility with control print
154                      CALL dyn_keg_tan     ( kt )
155                      CALL dyn_zad_tan     ( kt )
156!                      CALL dyn_adv_cen2_tan( kt )
157!                      CALL dyn_adv_ubs_tan ( kt )
158      END SELECT
159      !
160   END SUBROUTINE dyn_adv_tan
161
162   SUBROUTINE dyn_adv_adj( kt )
163      !!---------------------------------------------------------------------
164      !!                  ***  ROUTINE dyn_adv_adj  ***
165      !!               
166      !! ** Purpose of the direct routine:
167      !!            compute the ocean momentum advection trend.
168      !!
169      !! ** Method  : - Update (ua,va) with the advection term following nadv
170      !!      NB: in flux form advection (ln_dynadv_cen2 or ln_dynadv_ubs=T)
171      !!      a metric term is add to the coriolis term while in vector form
172      !!      it is the relative vorticity which is added to coriolis term
173      !!      (see dynvor module).
174      !!----------------------------------------------------------------------
175      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
176      !!----------------------------------------------------------------------
177      !
178      IF  ( kt == nitend ) CALL dyn_adv_ctl_tam
179
180      SELECT CASE ( nadv )                     ! compute advection trend and add it to general trend
181      CASE ( 0 )     
182                      CALL dyn_zad_adj     ( kt )    ! vector form : vertical advection
183                      CALL dyn_keg_adj     ( kt )    ! vector form : horizontal gradient of kinetic energy
184      CASE ( 1 ) 
185         IF (lwp) WRITE(numout,*) 'dyn_adv_cen2_adj not available yet' 
186         CALL abort
187!         CALL dyn_adv_cen2_adj( kt )    ! 2nd order centered scheme
188      CASE ( 2 )   
189         IF (lwp) WRITE(numout,*) 'dyn_adv_ubs_adj not available yet' 
190         CALL abort
191!                      CALL dyn_adv_ubs_adj ( kt )    ! 3rd order UBS      scheme
192      !
193      CASE (-1 )                                 ! esopa: test all possibility with control print
194!                      CALL dyn_adv_ubs_adj ( kt )
195!                      CALL dyn_adv_cen2_adj( kt )
196                      CALL dyn_zad_adj     ( kt )
197                      CALL dyn_keg_adj     ( kt )
198      END SELECT
199      !
200   END SUBROUTINE dyn_adv_adj
201
202   SUBROUTINE dyn_adv_adj_tst( kumadt )
203      !!-----------------------------------------------------------------------
204      !!
205      !!                  ***  ROUTINE dyn_adv_adj_tst ***
206      !!
207      !! ** Purpose : Test the adjoint routine.
208      !!
209      !! ** Method  : Verify the scalar product
210      !!           
211      !!                 ( L dx )^T W dy  =  dx^T L^T W dy
212      !!
213      !!              where  L   = tangent routine
214      !!                     L^T = adjoint routine
215      !!                     W   = diagonal matrix of scale factors
216      !!                     dx  = input perturbation (random field)
217      !!                     dy  = L dx
218      !!
219      !!                   
220      !! History :
221      !!        ! 08-08 (A. Vidard)
222      !!-----------------------------------------------------------------------
223      !! * Modules used
224
225      !! * Arguments
226      INTEGER, INTENT(IN) :: &
227         & kumadt             ! Output unit
228 
229      !! * Local declarations
230      INTEGER :: &
231         & ji,    &        ! dummy loop indices
232         & jj,    &       
233         & jk     
234      INTEGER, DIMENSION(jpi,jpj) :: &
235         & iseed_2d        ! 2D seed for the random number generator
236
237      REAL(KIND=wp), DIMENSION(:,:,:), ALLOCATABLE :: &
238         & zun_tlin,     & ! Tangent input:  now  u-velocity
239         & zvn_tlin,     & ! Tangent input:  now  v-velocity
240         & zwn_tlin,     & ! Tangent input:  now  w-velocity
241         & zua_tlin,     & ! Tangent input: after u-velocity
242         & zva_tlin,     & ! Tangent input: after u-velocity         
243         & zua_tlout,    & ! Tangent output:after u-velocity
244         & zva_tlout,    & ! Tangent output:after v-velocity
245         & zua_adin,     & ! adjoint input: after u-velocity
246         & zva_adin,     & ! adjoint input: after v-velocity
247         & zun_adout,    & ! adjoint output: now  u-velocity
248         & zvn_adout,    & ! adjoint output: now  v-velocity
249         & zwn_adout,    & ! adjoint output: now  u-velocity
250         & zua_adout,    & ! adjoint output:after v-velocity
251         & zva_adout,    & ! adjoint output:after u-velocity
252         & zuvw            ! 3D random field for u, v and w
253
254      REAL(KIND=wp) ::   &
255         & zsp1,         & ! scalar product involving the tangent routine
256         & zsp1_1,       & !   scalar product components
257         & zsp1_2,       & 
258         & zsp2,         & ! scalar product involving the adjoint routine
259         & zsp2_1,       & !   scalar product components
260         & zsp2_2,       & 
261         & zsp2_3,       & 
262         & zsp2_4,       & 
263         & zsp2_5
264
265      CHARACTER(LEN=14) :: cl_name
266
267
268      ! Allocate memory
269
270      ALLOCATE( &
271         & zun_tlin(jpi,jpj,jpk),     &
272         & zvn_tlin(jpi,jpj,jpk),     &
273         & zwn_tlin(jpi,jpj,jpk),     &
274         & zua_tlin(jpi,jpj,jpk),     &
275         & zva_tlin(jpi,jpj,jpk),     &
276         & zua_tlout(jpi,jpj,jpk),    &
277         & zva_tlout(jpi,jpj,jpk),    &
278         & zua_adin(jpi,jpj,jpk),     &
279         & zva_adin(jpi,jpj,jpk),     &
280         & zun_adout(jpi,jpj,jpk),    &
281         & zvn_adout(jpi,jpj,jpk),    &
282         & zwn_adout(jpi,jpj,jpk),    &
283         & zua_adout(jpi,jpj,jpk),    &
284         & zva_adout(jpi,jpj,jpk),    &
285         & zuvw(jpi,jpj,jpk)           & 
286         & )
287
288
289      !==================================================================
290      ! 1) dx = ( un_tl, vn_tl, hdivn_tl ) and
291      !    dy = ( hdivb_tl, hdivn_tl )
292      !==================================================================
293
294      !--------------------------------------------------------------------
295      ! Reset the tangent and adjoint variables
296      !--------------------------------------------------------------------
297          zun_tlin(:,:,:)  = 0.0_wp
298          zvn_tlin(:,:,:)  = 0.0_wp
299          zwn_tlin(:,:,:)  = 0.0_wp
300          zua_tlin(:,:,:)  = 0.0_wp
301          zva_tlin(:,:,:)  = 0.0_wp
302          zua_tlout(:,:,:) = 0.0_wp
303          zva_tlout(:,:,:) = 0.0_wp
304          zua_adin(:,:,:)  = 0.0_wp
305          zva_adin(:,:,:)  = 0.0_wp
306          zun_adout(:,:,:) = 0.0_wp
307          zvn_adout(:,:,:) = 0.0_wp
308          zwn_adout(:,:,:) = 0.0_wp
309          zua_adout(:,:,:) = 0.0_wp
310          zva_adout(:,:,:) = 0.0_wp
311          zuvw(:,:,:)      = 0.0_wp
312
313          un_tl(:,:,:) = 0.0_wp
314          vn_tl(:,:,:) = 0.0_wp
315          wn_tl(:,:,:) = 0.0_wp
316          ua_tl(:,:,:) = 0.0_wp
317          va_tl(:,:,:) = 0.0_wp
318          un_ad(:,:,:) = 0.0_wp
319          vn_ad(:,:,:) = 0.0_wp
320          wn_ad(:,:,:) = 0.0_wp
321          ua_ad(:,:,:) = 0.0_wp
322          va_ad(:,:,:) = 0.0_wp
323
324          !recompute wn from un and vn
325          CALL div_cur( nit000 )
326          CALL wzv( nit000 )
327
328      !--------------------------------------------------------------------
329      ! Initialize the tangent input with random noise: dx
330      !--------------------------------------------------------------------
331
332      DO jj = 1, jpj
333         DO ji = 1, jpi
334            iseed_2d(ji,jj) = - ( 596035 + &
335               &                  mig(ji) + ( mjg(jj) - 1 ) * jpiglo )
336         END DO
337      END DO
338      CALL grid_random( iseed_2d, zuvw, 'U', 0.0_wp, stdu )
339      DO jk = 1, jpk
340         DO jj = nldj, nlej
341            DO ji = nldi, nlei
342               zun_tlin(ji,jj,jk) = zuvw(ji,jj,jk) 
343            END DO
344         END DO
345      END DO
346      DO jj = 1, jpj
347         DO ji = 1, jpi
348            iseed_2d(ji,jj) = - ( 523432 + &
349               &                  mig(ji) + ( mjg(jj) - 1 ) * jpiglo )
350         END DO
351      END DO
352      CALL grid_random( iseed_2d, zuvw, 'V', 0.0_wp, stdv )
353      DO jk = 1, jpk
354         DO jj = nldj, nlej
355            DO ji = nldi, nlei
356               zvn_tlin(ji,jj,jk) = zuvw(ji,jj,jk) 
357            END DO
358         END DO
359      END DO
360
361      DO jj = 1, jpj
362         DO ji = 1, jpi
363            iseed_2d(ji,jj) = - ( 456953 + &
364               &                  mig(ji) + ( mjg(jj) - 1 ) * jpiglo )
365         END DO
366      END DO
367      CALL grid_random( iseed_2d, zuvw, 'W', 0.0_wp, stdw )
368      DO jk = 1, jpk
369         DO jj = nldj, nlej
370            DO ji = nldi, nlei
371               zwn_tlin(ji,jj,jk) = zuvw(ji,jj,jk)
372            END DO
373         END DO
374      END DO
375
376      DO jj = 1, jpj
377         DO ji = 1, jpi
378            iseed_2d(ji,jj) = - ( 432545 + &
379               &                  mig(ji) + ( mjg(jj) - 1 ) * jpiglo )
380         END DO
381      END DO
382      CALL grid_random( iseed_2d, zuvw, 'U', 0.0_wp, stdu )
383      DO jk = 1, jpk
384         DO jj = nldj, nlej
385            DO ji = nldi, nlei
386               zua_tlin(ji,jj,jk) = zuvw(ji,jj,jk)
387            END DO
388         END DO
389      END DO
390
391      DO jj = 1, jpj
392         DO ji = 1, jpi
393            iseed_2d(ji,jj) = - ( 287503 + &
394               &                  mig(ji) + ( mjg(jj) - 1 ) * jpiglo )
395         END DO
396      END DO
397      CALL grid_random( iseed_2d, zuvw, 'V', 0.0_wp, stdv )
398      DO jk = 1, jpk
399         DO jj = nldj, nlej
400            DO ji = nldi, nlei
401               zva_tlin(ji,jj,jk) = zuvw(ji,jj,jk)
402            END DO
403         END DO
404      END DO
405
406      un_tl(:,:,:) = zun_tlin(:,:,:)
407      vn_tl(:,:,:) = zvn_tlin(:,:,:)
408      !recompute wn_tl from un_tl and vn_tl
409      CALL div_cur_tan( nit000 )
410      CALL wzv_tan( nit000 )
411      DO jk = 1, jpk
412         DO jj = nldj, nlej
413            DO ji = nldi, nlei
414               zwn_tlin(ji,jj,jk) = wn_tl(ji,jj,jk)
415            END DO
416         END DO
417      END DO
418      wn_tl(:,:,:) = zwn_tlin(:,:,:)
419      ua_tl(:,:,:) = zua_tlin(:,:,:)
420      va_tl(:,:,:) = zva_tlin(:,:,:)
421
422      CALL dyn_adv_tan ( nit000 )
423      zua_tlout(:,:,:) = ua_tl(:,:,:)
424      zva_tlout(:,:,:) = va_tl(:,:,:)
425
426      !--------------------------------------------------------------------
427      ! Initialize the adjoint variables: dy^* = W dy
428      !--------------------------------------------------------------------
429
430      DO jk = 1, jpk
431        DO jj = nldj, nlej
432           DO ji = nldi, nlei
433              zua_adin(ji,jj,jk) = zua_tlout(ji,jj,jk) &
434                 &               * e1u(ji,jj) * e2u(ji,jj) * fse3u(ji,jj,jk) &
435                 &               * umask(ji,jj,jk) 
436              zva_adin(ji,jj,jk) = zva_tlout(ji,jj,jk) &
437                 &               * e1v(ji,jj) * e2v(ji,jj) * fse3v(ji,jj,jk) &
438                 &               * vmask(ji,jj,jk) 
439            END DO
440         END DO
441      END DO
442      !--------------------------------------------------------------------
443      ! Compute the scalar product: ( L dx )^T W dy
444      !--------------------------------------------------------------------
445
446      zsp1_1 = DOT_PRODUCT( zua_tlout, zua_adin )
447      zsp1_2 = DOT_PRODUCT( zva_tlout, zva_adin )
448      zsp1   = zsp1_1 + zsp1_2
449
450      !--------------------------------------------------------------------
451      ! Call the adjoint routine: dx^* = L^T dy^*
452      !--------------------------------------------------------------------
453
454      ua_ad(:,:,:) = zua_adin(:,:,:)
455      va_ad(:,:,:) = zva_adin(:,:,:)
456
457      CALL dyn_adv_adj ( nit000 )
458
459      zun_adout(:,:,:) = un_ad(:,:,:)
460      zvn_adout(:,:,:) = vn_ad(:,:,:)
461      zwn_adout(:,:,:) = wn_ad(:,:,:)
462      zua_adout(:,:,:) = ua_ad(:,:,:)
463      zva_adout(:,:,:) = va_ad(:,:,:)
464
465      zsp2_1 = DOT_PRODUCT( zun_tlin, zun_adout )
466      zsp2_2 = DOT_PRODUCT( zvn_tlin, zvn_adout )
467      zsp2_3 = DOT_PRODUCT( zwn_tlin, zwn_adout )
468      zsp2_4 = DOT_PRODUCT( zua_tlin, zua_adout )
469      zsp2_5 = DOT_PRODUCT( zva_tlin, zva_adout )
470      zsp2   = zsp2_1 + zsp2_2 + zsp2_3 + zsp2_4 + zsp2_5
471
472      ! Compare the scalar products
473
474      cl_name = 'dyn_adv_adj   '
475      CALL prntst_adj( cl_name, kumadt, zsp1, zsp2 )
476
477      DEALLOCATE( &
478         & zun_tlin,     &
479         & zvn_tlin,     &
480         & zwn_tlin,     &
481         & zua_tlin,     &
482         & zva_tlin,     &
483         & zua_tlout,    &
484         & zva_tlout,    &
485         & zua_adin,     &
486         & zva_adin,     &
487         & zun_adout,    &
488         & zvn_adout,    &
489         & zwn_adout,    &
490         & zua_adout,    &
491         & zva_adout,    &
492         & zuvw          & 
493         & )
494
495   END SUBROUTINE dyn_adv_adj_tst
496  !!======================================================================
497   SUBROUTINE dyn_adv_ctl_tam
498      !!---------------------------------------------------------------------
499      !!                  ***  ROUTINE dyn_adv_ctl  ***
500      !!               
501      !! ** Purpose :   Control the consistency between namelist options for
502      !!              momentum advection formulation & scheme and set nadv
503      !!----------------------------------------------------------------------
504      INTEGER ::   ioptio
505
506      NAMELIST/nam_dynadv/ ln_dynadv_vec, ln_dynadv_cen2 , ln_dynadv_ubs
507      !!----------------------------------------------------------------------
508     
509      IF (lfirst) THEN
510
511         REWIND ( numnam )               ! Read Namelist nam_dynadv : momentum advection scheme
512         READ   ( numnam, nam_dynadv )
513
514         IF(lwp) THEN                    ! Namelist print
515            WRITE(numout,*)
516            WRITE(numout,*) 'dyn_adv_ctl : choice/control of the momentum advection scheme'
517            WRITE(numout,*) '~~~~~~~~~~~'
518            WRITE(numout,*) '       Namelist nam_dynadv : chose a advection formulation & scheme for momentum'
519            WRITE(numout,*) '          Vector/flux form (T/F)             ln_dynadv_vec  = ', ln_dynadv_vec
520            WRITE(numout,*) '          2nd order centred advection scheme ln_dynadv_cen2 = ', ln_dynadv_cen2
521            WRITE(numout,*) '          3rd order UBS advection scheme     ln_dynadv_ubs  = ', ln_dynadv_ubs
522         ENDIF
523
524         ioptio = 0                      ! Parameter control
525         IF( ln_dynadv_vec  )   ioptio = ioptio + 1
526         IF( ln_dynadv_cen2 )   ioptio = ioptio + 1
527         IF( ln_dynadv_ubs  )   ioptio = ioptio + 1
528         IF( lk_esopa       )   ioptio =          1
529
530         IF( ioptio /= 1 )   CALL ctl_stop( 'Choose ONE advection scheme in namelist nam_dynadv' )
531
532      !                               ! Set nadv
533         IF( ln_dynadv_vec  )   nadv =  0 
534         IF( ln_dynadv_cen2 )   nadv =  1
535         IF( ln_dynadv_ubs  )   nadv =  2
536         IF( lk_esopa       )   nadv = -1
537
538         IF(lwp) THEN                    ! Print the choice
539            WRITE(numout,*)
540            IF( nadv ==  0 )   WRITE(numout,*) '         vector form : keg + zad + vor is used'
541            IF( nadv ==  1 )   WRITE(numout,*) '         flux form   : 2nd order scheme is used'
542            IF( nadv ==  2 )   WRITE(numout,*) '         flux form   : UBS       scheme is used'
543            IF( nadv == -1 )   WRITE(numout,*) '         esopa test: use all advection formulation'
544         ENDIF
545         !
546         lfirst = .FALSE.
547      END IF
548   END SUBROUTINE dyn_adv_ctl_tam
549#if defined key_tst_tlm
550   SUBROUTINE dyn_adv_tlm_tst( kumadt )
551      !!-----------------------------------------------------------------------
552      !!
553      !!                  ***  ROUTINE dyn_adv_tlm_tst ***
554      !!
555      !! ** Purpose : Test the adjoint routine.
556      !!
557      !! ** Method  : Verify the tangent with Taylor expansion
558      !!           
559      !!                 M(x+hdx) = M(x) + L(hdx) + O(h^2)
560      !!
561      !!              where  L   = tangent routine
562      !!                     M   = direct routine
563      !!                     dx  = input perturbation (random field)
564      !!                     h   = ration on perturbation
565      !! 
566      !!    In the tangent test we verify that:
567      !!                M(x+h*dx) - M(x)
568      !!        g(h) = ------------------ --->  1    as  h ---> 0
569      !!                    L(h*dx)
570      !!    and
571      !!                g(h) - 1
572      !!        f(h) = ----------         --->  k (costant) as  h ---> 0
573      !!                    p
574      !!                   
575      !! History :
576      !!        ! 09-08 (A. Vigilant)
577      !!-----------------------------------------------------------------------
578      !! * Modules used
579      USE dynadv
580      USE tamtrj              ! writing out state trajectory
581      USE par_tlm,    ONLY: &
582        & tlm_bch,          &
583        & cur_loop,         &
584        & h_ratio
585      USE istate_mod
586      USE divcur             ! horizontal divergence and relative vorticity
587      USE wzvmod             !  vertical velocity
588      USE gridrandom, ONLY: &
589        & grid_rd_sd
590      USE trj_tam
591      USE oce           , ONLY: & ! ocean dynamics and tracers variables
592        & ua, va
593      USE opatam_tst_ini, ONLY: &
594       & tlm_namrd
595      USE tamctl,         ONLY: & ! Control parameters
596       & numtan, numtan_sc
597      !! * Arguments
598      INTEGER, INTENT(IN) :: &
599         & kumadt             ! Output unit
600 
601      !! * Local declarations
602      INTEGER :: &
603         & ji,    &        ! dummy loop indices
604         & jj,    &       
605         & jk     
606
607      REAL(KIND=wp), DIMENSION(:,:,:), ALLOCATABLE :: &
608         & zun_tlin,     & ! Tangent input:  now  u-velocity
609         & zvn_tlin,     & ! Tangent input:  now  v-velocity
610         & zwn_tlin,     & ! Tangent input:  now  w-velocity
611         & zua_tlin,     & ! Tangent input: after u-velocity
612         & zva_tlin,     & ! Tangent input: after u-velocity         
613         & zua_out,      & ! Tangent output:after u-velocity
614         & zva_out,      & ! Tangent output:after v-velocity
615         & zua_wop,      & ! Tangent output:after u-velocity
616         & zva_wop,      & ! Tangent output:after v-velocity
617         & z3r             ! 3D field
618
619      REAL(KIND=wp) ::   &
620         & zsp1,         & ! scalar product
621         & zsp1_1,       & ! scalar product
622         & zsp1_2,       & 
623         & zsp2,         & ! scalar product
624         & zsp2_1,       & ! scalar product
625         & zsp2_2,       & 
626         & zsp3,         & ! scalar product
627         & zsp3_1,       & ! scalar product
628         & zsp3_2,       & 
629         & zsp2_3,       & 
630         & zsp2_4,       & 
631         & zzsp,         &
632         & zzsp_1,       &
633         & zzsp_2,       &
634         & gamma,            &
635         & zgsp1,            &
636         & zgsp2,            &
637         & zgsp3,            &
638         & zgsp4,            &
639         & zgsp5,            &
640         & zgsp6,            &
641         & zgsp7
642
643      CHARACTER(LEN=14)   :: cl_name
644      CHARACTER (LEN=128) :: file_out, file_wop, file_xdx
645      CHARACTER (LEN=90)  ::  FMT
646      REAL(KIND=wp), DIMENSION(100):: &
647         & zscua, zscva,    &
648         & zscerrua,        &
649         & zscerrva
650      INTEGER, DIMENSION(100):: &
651         & iiposua, iiposva,    &
652         & ijposua, ijposva,    & 
653         & ikposua, ikposva
654      INTEGER::             &
655         & ii,              &
656         & isamp=40,        &
657         & jsamp=40,        &
658         & ksamp=10,        &
659         & numsctlm
660     REAL(KIND=wp), DIMENSION(jpi,jpj,jpk) :: &
661         & zerrua, zerrva 
662      ! Allocate memory
663
664      ALLOCATE( &
665         & zun_tlin(jpi,jpj,jpk),     &
666         & zvn_tlin(jpi,jpj,jpk),     &
667         & zwn_tlin(jpi,jpj,jpk),     &
668         & zua_tlin(jpi,jpj,jpk),     &
669         & zva_tlin(jpi,jpj,jpk),     &
670         & zua_out(jpi,jpj,jpk),      &
671         & zva_out(jpi,jpj,jpk),      &
672         & zua_wop(jpi,jpj,jpk),      &
673         & zva_wop(jpi,jpj,jpk),      &
674         & z3r    (jpi,jpj,jpk)       &
675         & )
676
677      !--------------------------------------------------------------------
678      ! Reset variables
679      !--------------------------------------------------------------------
680      zun_tlin( :,:,:) = 0.0_wp
681      zvn_tlin( :,:,:) = 0.0_wp
682      zwn_tlin( :,:,:) = 0.0_wp
683      zua_tlin( :,:,:) = 0.0_wp
684      zva_tlin( :,:,:) = 0.0_wp
685      zua_out ( :,:,:) = 0.0_wp
686      zva_out ( :,:,:) = 0.0_wp
687      zua_wop ( :,:,:) = 0.0_wp
688      zva_wop ( :,:,:) = 0.0_wp
689
690      zscua(:)         = 0.0_wp
691      zscva(:)         = 0.0_wp
692      zscerrua(:)      = 0.0_wp
693      zscerrva(:)      = 0.0_wp
694      zerrua(:,:,:)    = 0.0_wp
695      zerrva(:,:,:)    = 0.0_wp
696      !--------------------------------------------------------------------
697      ! Output filename Xn=F(X0)
698      !--------------------------------------------------------------------
699      CALL tlm_namrd
700      gamma = h_ratio
701      file_wop='trj_wop_dynadv'
702      file_xdx='trj_xdx_dynadv'
703      !--------------------------------------------------------------------
704      ! Initialize the tangent input with random noise: dx
705      !--------------------------------------------------------------------
706      IF (( cur_loop .NE. 0) .OR. ( gamma .NE. 0.0_wp) )THEN
707      CALL grid_rd_sd( 596035, z3r,  'U', 0.0_wp, stdu)
708      DO jk = 1, jpk
709         DO jj = nldj, nlej
710            DO ji = nldi, nlei
711               zun_tlin(ji,jj,jk) = z3r(ji,jj,jk)
712            END DO
713         END DO
714      END DO
715      CALL grid_rd_sd( 523432, z3r,  'V', 0.0_wp, stdv)
716      DO jk = 1, jpk
717         DO jj = nldj, nlej
718            DO ji = nldi, nlei
719               zvn_tlin(ji,jj,jk) = z3r(ji,jj,jk)
720            END DO
721         END DO
722      END DO
723      CALL grid_rd_sd( 432545, z3r,  'U', 0.0_wp, stdu)
724      DO jk = 1, jpk
725         DO jj = nldj, nlej
726            DO ji = nldi, nlei
727               zua_tlin(ji,jj,jk) = z3r(ji,jj,jk)
728            END DO
729         END DO
730      END DO
731      CALL grid_rd_sd( 287503, z3r,  'V', 0.0_wp, stdv) 
732      DO jk = 1, jpk
733         DO jj = nldj, nlej
734            DO ji = nldi, nlei
735               zva_tlin(ji,jj,jk) = z3r(ji,jj,jk)
736            END DO
737         END DO
738      END DO
739      ENDIF   
740      !--------------------------------------------------------------------
741      ! Complete Init for Direct
742      !-------------------------------------------------------------------
743      IF ( tlm_bch /= 2 )      CALL istate_p 
744
745      ! *** initialize the reference trajectory
746      ! ------------
747      CALL  trj_rea( nit000-1, 1 )
748      CALL  trj_rea( nit000, 1 )
749      ua(:,:,:)       = un(:,:,:)
750      va(:,:,:)       = vn(:,:,:)
751
752      IF (( cur_loop .NE. 0) .OR. ( gamma .NE. 0.0_wp) )THEN
753         zun_tlin(:,:,:) = gamma * zun_tlin(:,:,:)
754         un(:,:,:)       = un(:,:,:) + zun_tlin(:,:,:)
755
756         zvn_tlin(:,:,:) = gamma * zvn_tlin(:,:,:)
757         vn(:,:,:)       = vn(:,:,:) + zvn_tlin(:,:,:)
758
759         zua_tlin(:,:,:) = gamma * zua_tlin(:,:,:)
760         ua(:,:,:)       = ua(:,:,:) + zua_tlin(:,:,:)
761
762         zva_tlin(:,:,:) = gamma * zva_tlin(:,:,:)
763         va(:,:,:)       = va(:,:,:) + zva_tlin(:,:,:)
764         !recompute wn from un and vn
765         CALL div_cur( nit000)
766         CALL wzv( nit000)
767      ENDIF 
768      !--------------------------------------------------------------------
769      !  Compute the direct model F(X0,t=n) = Xn
770      !--------------------------------------------------------------------
771      IF ( tlm_bch /= 2 ) CALL dyn_adv(nit000)
772      IF ( tlm_bch == 0 ) CALL trj_wri_spl(file_wop)
773      IF ( tlm_bch == 1 ) CALL trj_wri_spl(file_xdx)
774      !--------------------------------------------------------------------
775      !  Compute the Tangent
776      !--------------------------------------------------------------------
777      IF ( tlm_bch == 2 ) THEN       
778         !--------------------------------------------------------------------
779         ! Initialize the tangent variables
780         !--------------------------------------------------------------------
781         CALL  trj_rea( nit000-1, 1 ) 
782         CALL  trj_rea( nit000, 1 ) 
783         ua(:,:,:)       = un(:,:,:)
784         va(:,:,:)       = vn(:,:,:)
785         un_tl  (:,:,:) = zun_tlin  (:,:,:)
786         vn_tl  (:,:,:) = zvn_tlin  (:,:,:)
787         !recompute wn_tl from un_tl and vn_tl
788         CALL div_cur_tan( nit000 )
789         CALL wzv_tan( nit000 )
790         ua_tl  (:,:,:) = zua_tlin  (:,:,:)
791         va_tl  (:,:,:) = zva_tlin  (:,:,:)
792 
793         CALL dyn_adv_tan(nit000)
794
795         !--------------------------------------------------------------------
796         ! Compute the scalar product: ( L(t0,tn) gamma dx0 ) )
797         !--------------------------------------------------------------------
798
799         zsp2_1    = DOT_PRODUCT( ua_tl, ua_tl  )
800         zsp2_2    = DOT_PRODUCT( va_tl, va_tl  )
801
802         zsp2      = zsp2_1 + zsp2_2
803         !--------------------------------------------------------------------
804         !  Storing data
805         !--------------------------------------------------------------------
806         CALL trj_rd_spl(file_wop) 
807         zua_wop  (:,:,:) = ua  (:,:,:)
808         zva_wop  (:,:,:) = va  (:,:,:)
809         CALL trj_rd_spl(file_xdx) 
810         zua_out  (:,:,:) = ua  (:,:,:)
811         zva_out  (:,:,:) = va  (:,:,:)
812         !--------------------------------------------------------------------
813         ! Compute the Linearization Error
814         ! Nn = M( X0+gamma.dX0, t0,tn) - M(X0, t0,tn)
815         ! and
816         ! Compute the Linearization Error
817         ! En = Nn -TL(gamma.dX0, t0,tn)
818         !--------------------------------------------------------------------
819         ! Warning: Here we re-use local variables z()_out and z()_wop
820         ii=0
821         DO jk = 1, jpk
822            DO jj = 1, jpj
823               DO ji = 1, jpi
824                  zua_out   (ji,jj,jk) = zua_out    (ji,jj,jk) - zua_wop  (ji,jj,jk)
825                  zua_wop   (ji,jj,jk) = zua_out    (ji,jj,jk) - ua_tl    (ji,jj,jk)
826                  IF (  ua_tl(ji,jj,jk) .NE. 0.0_wp ) &
827                     & zerrua(ji,jj,jk) = zua_out(ji,jj,jk)/ua_tl(ji,jj,jk)
828                  IF( (MOD(ji, isamp) .EQ. 0) .AND. &
829                  &   (MOD(jj, jsamp) .EQ. 0) .AND. &
830                  &   (MOD(jk, ksamp) .EQ. 0)     ) THEN
831                      ii = ii+1
832                      iiposua(ii) = ji
833                      ijposua(ii) = jj
834                      ikposua(ii) = jk
835                      IF ( INT(umask(ji,jj,jk)) .NE. 0)  THEN
836                         zscua (ii) =  zua_wop(ji,jj,jk)
837                         zscerrua (ii) =  ( zerrua(ji,jj,jk) - 1.0_wp ) / gamma
838                      ENDIF
839                  ENDIF
840               END DO
841            END DO
842         END DO
843         ii=0
844         DO jk = 1, jpk
845            DO jj = 1, jpj
846               DO ji = 1, jpi
847                  zva_out   (ji,jj,jk) = zva_out    (ji,jj,jk) - zva_wop  (ji,jj,jk)
848                  zva_wop   (ji,jj,jk) = zva_out    (ji,jj,jk) - va_tl    (ji,jj,jk)
849                  IF (  va_tl(ji,jj,jk) .NE. 0.0_wp ) &
850                     & zerrva(ji,jj,jk) = zva_out(ji,jj,jk)/va_tl(ji,jj,jk)
851                  IF( (MOD(ji, isamp) .EQ. 0) .AND. &
852                  &   (MOD(jj, jsamp) .EQ. 0) .AND. &
853                  &   (MOD(jk, ksamp) .EQ. 0)     ) THEN
854                      ii = ii+1
855                      iiposva(ii) = ji
856                      ijposva(ii) = jj
857                      ikposva(ii) = jk
858                      IF ( INT(vmask(ji,jj,jk)) .NE. 0)  THEN
859                         zscva (ii) =  zua_wop(ji,jj,jk)
860                         zscerrva (ii) =  ( zerrva(ji,jj,jk) - 1.0_wp ) / gamma
861                      ENDIF
862                  ENDIF
863               END DO
864            END DO
865         END DO
866
867         zsp1_1    = DOT_PRODUCT( zua_out, zua_out )
868         zsp1_2    = DOT_PRODUCT( zva_out, zva_out  )
869         zsp1      = zsp1_1 + zsp1_2
870
871         zsp3_1    = DOT_PRODUCT( zua_wop, zua_wop )
872         zsp3_2    = DOT_PRODUCT( zva_wop, zva_wop  )
873         zsp3      = zsp3_1 + zsp3_2
874         !--------------------------------------------------------------------
875         ! Print the linearization error En - norme 2
876         !--------------------------------------------------------------------
877         ! 14 char:'12345678901234'
878         cl_name  = 'dynadv_tam:En '
879         zzsp     = SQRT(zsp3)
880         zzsp_1   = SQRT(zsp3_1)
881         zzsp_2   = SQRT(zsp3_2)
882         zgsp5    = zzsp
883         CALL prntst_tlm( cl_name, kumadt, zzsp, h_ratio )
884         !--------------------------------------------------------------------
885         ! Compute TLM norm2
886         !--------------------------------------------------------------------
887         zzsp     = SQRT(zsp2)
888         zzsp_1   = SQRT(zsp2_1)
889         zzsp_2   = SQRT(zsp2_2)
890         zgsp4    = zzsp
891         cl_name  = 'dynadv_tam:Ln2'
892         CALL prntst_tlm( cl_name, kumadt, zzsp, h_ratio )
893         !--------------------------------------------------------------------
894         ! Print the linearization error Nn - norme 2
895         !--------------------------------------------------------------------
896         zzsp     = SQRT(zsp1)
897         zzsp_1   = SQRT(zsp1_1)
898         zzsp_2   = SQRT(zsp1_2)
899         cl_name  = 'dynadv:Mhdx-Mx'
900         CALL prntst_tlm( cl_name, kumadt, zzsp, h_ratio )
901         zgsp3    = SQRT( zsp3/zsp2 )
902         zgsp7    = zgsp3/gamma
903         zgsp1    = zzsp
904         zgsp2    = zgsp1 / zgsp4
905         zgsp6    = (zgsp2 - 1.0_wp)/gamma
906
907         FMT = "(A8,2X,I4.4,2X,E6.1,2X,E20.13,2X,E20.13,2X,E20.13,2X,E20.13,2X,E20.13,2X,E20.13,2X,E20.13)"
908         WRITE(numtan,FMT) 'dynadv  ', cur_loop, h_ratio, zgsp1, zgsp2, zgsp3, zgsp4, zgsp5, zgsp6, zgsp7
909         !--------------------------------------------------------------------
910         ! Unitary calculus
911         !--------------------------------------------------------------------
912         FMT = "(A8,2X,A8,2X,I4.4,2X,E6.1,2X,I4.4,2X,I4.4,2X,I4.4,2X,E20.13,1X)"
913         cl_name = 'dynadv  '
914         IF (lwp) THEN
915            DO ii=1, 100, 1
916               IF ( zscua(ii) .NE. 0.0_wp ) WRITE(numtan_sc,FMT) cl_name, 'zscua     ', &
917                    & cur_loop, h_ratio, ii, iiposua(ii), ijposua(ii), zscua(ii)
918            ENDDO
919            DO ii=1, 100, 1
920               IF ( zscva(ii) .NE. 0.0_wp ) WRITE(numtan_sc,FMT) cl_name, 'zscva     ', &
921                    & cur_loop, h_ratio, ii, iiposva(ii), ijposva(ii), zscva(ii)
922            ENDDO
923            DO ii=1, 100, 1
924               IF ( zscerrua(ii) .NE. 0.0_wp ) WRITE(numtan_sc,FMT) cl_name, 'zscerrua  ', &
925                 & cur_loop, h_ratio, ii, iiposua(ii), ijposua(ii), zscerrua(ii)
926            ENDDO
927            DO ii=1, 100, 1
928               IF ( zscerrva(ii) .NE. 0.0_wp ) WRITE(numtan_sc,FMT) cl_name, 'zscerrva  ', &
929                    & cur_loop, h_ratio, ii, iiposva(ii), ijposva(ii), zscerrva(ii)
930            ENDDO
931      ! write separator
932      WRITE(numtan_sc,"(A4)") '===='
933         ENDIF
934      ENDIF
935      DEALLOCATE(                           &
936         & zun_tlin, zvn_tlin, zwn_tlin,    & 
937         & zua_tlin, zva_tlin,              & 
938         & zua_out, zva_out,                & 
939         & zua_wop, zva_wop,                &
940         & z3r                              &
941         & )
942   END SUBROUTINE dyn_adv_tlm_tst
943#endif
944#endif
945END MODULE dynadv_tam
Note: See TracBrowser for help on using the repository browser.