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.2.F90 on Ticket #1584 – Attachment – NEMO

Ticket #1584: dynzdf.2.F90

File dynzdf.2.F90, 8.8 KB (added by Robin_Waldman, 5 years ago)
Line 
1MODULE dynzdf
2   !!==============================================================================
3   !!                 ***  MODULE  dynzdf  ***
4   !! Ocean dynamics :  vertical component of the momentum mixing trend
5   !!==============================================================================
6   !! History :  1.0  !  2005-11  (G. Madec)  Original code
7   !!            3.3  !  2010-10  (C. Ethe, G. Madec) reorganisation of initialisation phase
8   !!            3.6  !  2019-09  (R. Waldman) debug of momentum trend diag and
9   !inclusion of barotropic correction into dyn_zdf
10   !!----------------------------------------------------------------------
11
12   !!----------------------------------------------------------------------
13   !!   dyn_zdf      : Update the momentum trend with the vertical diffusion
14   !!   dyn_zdf_init : initializations of the vertical diffusion scheme
15   !!----------------------------------------------------------------------
16   USE oce             ! ocean dynamics and tracers variables
17   USE dom_oce         ! ocean space and time domain variables
18   USE zdf_oce         ! ocean vertical physics variables
19
20   USE dynzdf_exp      ! vertical diffusion: explicit (dyn_zdf_exp     routine)
21   USE dynzdf_imp      ! vertical diffusion: implicit (dyn_zdf_imp     routine)
22
23   USE ldfdyn_oce      ! ocean dynamics: lateral physics
24   USE trd_oce         ! trends: ocean variables
25   USE trddyn          ! trend manager: dynamics
26   USE in_out_manager  ! I/O manager
27   USE lib_mpp         ! MPP library
28   USE prtctl          ! Print control
29   USE wrk_nemo        ! Memory Allocation
30   USE timing          ! Timing
31
32   IMPLICIT NONE
33   PRIVATE
34
35   PUBLIC   dyn_zdf       !  routine called by step.F90
36   PUBLIC   dyn_zdf_init  !  routine called by opa.F90
37
38   INTEGER  ::   nzdf = 0   ! type vertical diffusion algorithm used, defined from ln_zdf... namlist logicals
39   REAL(wp) ::   r2dt       ! time-step, = 2 rdttra except at nit000 (=rdttra) if neuler=0
40
41   !! * Substitutions
42#  include "domzgr_substitute.h90"
43#  include "zdfddm_substitute.h90"
44#  include "vectopt_loop_substitute.h90"
45   !!----------------------------------------------------------------------
46   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
47   !! $Id: dynzdf.F90 4990 2014-12-15 16:42:49Z timgraham $
48   !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
49   !!----------------------------------------------------------------------
50
51CONTAINS
52   
53   SUBROUTINE dyn_zdf( kt )
54      !!----------------------------------------------------------------------
55      !!                  ***  ROUTINE dyn_zdf  ***
56      !!
57      !! ** Purpose :   compute the vertical ocean dynamics physics.
58      !!---------------------------------------------------------------------
59      !!
60      INTEGER, INTENT( in ) ::   kt      ! ocean time-step index
61      !
62      REAL(wp), POINTER, DIMENSION(:,:,:) ::  ztrdu, ztrdv
63! CR 20161028 --- begin ---
64      INTEGER                             ::  jk   ! dummy loop indices
65      REAL(wp)                            ::  z1_2dt 
66      REAL(wp), POINTER, DIMENSION(:,:)   ::  zue, zve
67      REAL(wp), POINTER, DIMENSION(:,:,:) ::  zua, zva 
68! CR 20161028 --- end ---
69      !!---------------------------------------------------------------------
70      !
71      IF( nn_timing == 1 )  CALL timing_start('dyn_zdf')
72! CR 20161028 --- begin ---
73!       CALL wrk_alloc( jpi,jpj,jpk, zua, zva )
74!       CALL wrk_alloc( jpi,jpj, zue, zve )
75! CR 20161028 --- end ---
76      !
77      !                                          ! set time step
78      IF( neuler == 0 .AND. kt == nit000     ) THEN   ;   r2dt =      rdt   ! = rdtra (restart with Euler time stepping)
79      ELSEIF(               kt <= nit000 + 1 ) THEN   ;   r2dt = 2. * rdt   ! = 2 rdttra (leapfrog)
80      ENDIF
81
82      IF( l_trddyn )   THEN                      ! temporary save of ta and sa trends
83         CALL wrk_alloc( jpi, jpj, jpk, ztrdu, ztrdv ) 
84         ztrdu(:,:,:) = ua(:,:,:)
85         ztrdv(:,:,:) = va(:,:,:)
86      ENDIF
87
88      SELECT CASE ( nzdf )                       ! compute lateral mixing trend and add it to the general trend
89      !
90      CASE ( 0 )   ;   CALL dyn_zdf_exp( kt, r2dt )      ! explicit scheme
91      CASE ( 1 )   ;   CALL dyn_zdf_imp( kt, r2dt )      ! implicit scheme
92      CASE ( -1 )                                        ! esopa: test all possibility with control print
93                       CALL dyn_zdf_exp( kt, r2dt )
94                       CALL prt_ctl( tab3d_1=ua, clinfo1=' zdf0 - Ua: ', mask1=umask,               &
95                          &          tab3d_2=va, clinfo2=       ' Va: ', mask2=vmask, clinfo3='dyn' )
96                       CALL dyn_zdf_imp( kt, r2dt )
97                       CALL prt_ctl( tab3d_1=ua, clinfo1=' zdf1 - Ua: ', mask1=umask,               &
98                          &          tab3d_2=va, clinfo2=       ' Va: ', mask2=vmask, clinfo3='dyn' )
99      END SELECT
100
101! RW 20190930 --- begin ---
102# if defined key_dynspg_ts
103
104       ! Update of the barotropic trend with time splitting estimate (copied
105       ! from dynnxt.F90):
106       CALL wrk_alloc( jpi,jpj, zue, zve )
107       zue(:,:) = fse3u_a(:,:,1) * ua(:,:,1) * umask(:,:,1)
108       zve(:,:) = fse3v_a(:,:,1) * va(:,:,1) * vmask(:,:,1)
109       DO jk = 2, jpkm1
110          zue(:,:) = zue(:,:) + fse3u_a(:,:,jk) * ua(:,:,jk) * umask(:,:,jk)
111          zve(:,:) = zve(:,:) + fse3v_a(:,:,jk) * va(:,:,jk) * vmask(:,:,jk)
112       END DO
113       DO jk = 1, jpkm1
114          ua(:,:,jk) = ( ua(:,:,jk) - zue(:,:) * hur_a(:,:) + ua_b(:,:) ) * umask(:,:,jk)
115          va(:,:,jk) = ( va(:,:,jk) - zve(:,:) * hvr_a(:,:) + va_b(:,:) ) * vmask(:,:,jk)
116       END DO   
117       CALL wrk_dealloc( jpi,jpj, zue, zve )
118
119      IF( l_trddyn )   THEN
120      ! In dyn_zdf_imp, ua & va become velocities and are not trends anymore. Thus, we have to back-calculate
121      ! in order to obtain the trend due to vertical diffusion.
122      ! Before, replace barotropic component: (copied from dynnxt.F90))
123      ! Ensure below that barotropic velocities match time splitting estimate
124      ! Compute actual transport and replace it with its estimate at "after" time step
125         CALL wrk_alloc( jpi,jpj,jpk, zua, zva )
126         z1_2dt = 1._wp / (2. * rdt)        ! Euler or leap-frog time step
127         IF( neuler == 0 .AND. kt == nit000 )   z1_2dt = 1._wp / rdt     
128         !
129         zua(:,:,:) = ( ua(:,:,:) - ub(:,:,:) ) * z1_2dt - ztrdu
130         zva(:,:,:) = ( va(:,:,:) - vb(:,:,:) ) * z1_2dt - ztrdv
131         CALL trd_dyn( zua, zva, jpdyn_zdf, kt )
132         CALL wrk_dealloc( jpi,jpj,jpk, zua, zva )
133         CALL wrk_dealloc( jpi, jpj, jpk, ztrdu, ztrdv ) 
134      ENDIF
135# endif
136! RW 20190930 --- end ---
137
138      !                                          ! print mean trends (used for debugging)
139      IF(ln_ctl)   CALL prt_ctl( tab3d_1=ua, clinfo1=' zdf  - Ua: ', mask1=umask,               &
140            &                    tab3d_2=va, clinfo2=       ' Va: ', mask2=vmask, clinfo3='dyn' )
141      !
142      IF( nn_timing == 1 )  CALL timing_stop('dyn_zdf')
143      !
144   END SUBROUTINE dyn_zdf
145
146
147   SUBROUTINE dyn_zdf_init
148      !!----------------------------------------------------------------------
149      !!                 ***  ROUTINE dyn_zdf_init  ***
150      !!
151      !! ** Purpose :   initializations of the vertical diffusion scheme
152      !!
153      !! ** Method  :   implicit (euler backward) scheme (default)
154      !!                explicit (time-splitting) scheme if ln_zdfexp=T
155      !!----------------------------------------------------------------------
156      USE zdftke
157      USE zdfgls
158      USE zdfkpp
159      !!----------------------------------------------------------------------
160      !
161      ! Choice from ln_zdfexp read in namelist in zdfini
162      IF( ln_zdfexp ) THEN   ;   nzdf = 0           ! use explicit scheme
163      ELSE                   ;   nzdf = 1           ! use implicit scheme
164      ENDIF
165      !
166      ! Force implicit schemes
167      IF( lk_zdftke .OR. lk_zdfgls .OR. lk_zdfkpp )   nzdf = 1   ! TKE, GLS or KPP physics
168      IF( ln_dynldf_iso                           )   nzdf = 1   ! iso-neutral lateral physics
169      IF( ln_dynldf_hor .AND. ln_sco              )   nzdf = 1   ! horizontal lateral physics in s-coordinate
170      !
171      IF( lk_esopa )    nzdf = -1                   ! Esopa key: All schemes used
172      !
173      IF(lwp) THEN                                  ! Print the choice
174         WRITE(numout,*)
175         WRITE(numout,*) 'dyn_zdf_init : vertical dynamics physics scheme'
176         WRITE(numout,*) '~~~~~~~~~~~'
177         IF( nzdf == -1 )   WRITE(numout,*) '              ESOPA test All scheme used'
178         IF( nzdf ==  0 )   WRITE(numout,*) '              Explicit time-splitting scheme'
179         IF( nzdf ==  1 )   WRITE(numout,*) '              Implicit (euler backward) scheme'
180      ENDIF
181      !
182   END SUBROUTINE dyn_zdf_init
183
184   !!==============================================================================
185END MODULE dynzdf