source: NEMO/branches/UKMO/NEMO_4.0_surge/src/OCE/ZDF/zdfphy.F90 @ 11180

Last change on this file since 11180 was 11180, checked in by clne, 22 months ago

Initial commit of code for 2d (surge) work in NEMO4.
This is aiming to replicate the 3.6 version in branches/UKMO/dev_r5518_Surge_Modelling

File size: 19.5 KB
Line 
1MODULE zdfphy
2   !!======================================================================
3   !!                      ***  MODULE  zdfphy  ***
4   !! Vertical ocean physics :   manager of all vertical physics packages
5   !!======================================================================
6   !! History :  4.0  !  2017-04  (G. Madec)  original code
7   !!----------------------------------------------------------------------
8
9   !!----------------------------------------------------------------------
10   !!   zdf_phy_init  : initialization of all vertical physics packages
11   !!   zdf_phy       : upadate at each time-step the vertical mixing coeff.
12   !!----------------------------------------------------------------------
13   USE oce            ! ocean dynamics and tracers variables
14   USE zdf_oce        ! vertical physics: shared variables         
15   USE zdfdrg         ! vertical physics: top/bottom drag coef.
16   USE zdfsh2         ! vertical physics: shear production term of TKE
17   USE zdfric         ! vertical physics: RIChardson dependent vertical mixing   
18   USE zdftke         ! vertical physics: TKE vertical mixing
19   USE zdfgls         ! vertical physics: GLS vertical mixing
20   USE zdfosm         ! vertical physics: OSMOSIS vertical mixing
21   USE zdfddm         ! vertical physics: double diffusion mixing     
22   USE zdfevd         ! vertical physics: convection via enhanced vertical diffusion 
23   USE zdfiwm         ! vertical physics: internal wave-induced mixing 
24   USE zdfswm         ! vertical physics: surface  wave-induced mixing
25   USE zdfmxl         ! vertical physics: mixed layer
26   USE tranpc         ! convection: non penetrative adjustment
27   USE trc_oce        ! variables shared between passive tracer & ocean           
28   USE sbc_oce        ! surface module (only for nn_isf in the option compatibility test)
29   USE sbcrnf         ! surface boundary condition: runoff variables
30#if defined key_agrif
31   USE agrif_oce_interp   ! interpavm
32#endif
33   !
34   USE in_out_manager ! I/O manager
35   USE iom            ! IOM library
36   USE lbclnk         ! lateral boundary conditions
37   USE lib_mpp        ! distribued memory computing
38   USE timing         ! Timing
39
40   IMPLICIT NONE
41   PRIVATE
42
43   PUBLIC   zdf_phy_init  ! called by nemogcm.F90
44   PUBLIC   zdf_phy       ! called by step.F90
45
46   INTEGER ::   nzdf_phy   ! type of vertical closure used
47   !                       ! associated indicators
48   INTEGER, PARAMETER ::   np_CST = 1   ! Constant Kz
49   INTEGER, PARAMETER ::   np_RIC = 2   ! Richardson number dependent Kz
50   INTEGER, PARAMETER ::   np_TKE = 3   ! Turbulente Kinetic Eenergy closure scheme for Kz
51   INTEGER, PARAMETER ::   np_GLS = 4   ! Generic Length Scale closure scheme for Kz
52   INTEGER, PARAMETER ::   np_OSM = 5   ! OSMOSIS-OBL closure scheme for Kz
53
54   LOGICAL ::   l_zdfsh2   ! shear production term flag (=F for CST, =T otherwise (i.e. TKE, GLS, RIC))
55
56   !!----------------------------------------------------------------------
57   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
58   !! $Id$
59   !! Software governed by the CeCILL license (see ./LICENSE)
60   !!----------------------------------------------------------------------
61CONTAINS
62
63   SUBROUTINE zdf_phy_init
64      !!----------------------------------------------------------------------
65      !!                  ***  ROUTINE zdf_phy_init  ***
66      !!
67      !! ** Purpose :   initializations of the vertical ocean physics
68      !!
69      !! ** Method  :   Read namelist namzdf, control logicals
70      !!                set horizontal shape and vertical profile of background mixing coef.
71      !!----------------------------------------------------------------------
72      INTEGER ::   jk            ! dummy loop indices
73      INTEGER ::   ioptio, ios   ! local integers
74      !!
75      NAMELIST/namzdf/ ln_zdfcst, ln_zdfric, ln_zdftke, ln_zdfgls,   &     ! type of closure scheme
76         &             ln_zdfosm,                                    &     ! type of closure scheme
77         &             ln_zdfevd, nn_evdm, rn_evd ,                  &     ! convection : evd
78         &             ln_zdfnpc, nn_npc , nn_npcp,                  &     ! convection : npc
79         &             ln_zdfddm, rn_avts, rn_hsbfr,                 &     ! double diffusion
80         &             ln_zdfswm,                                    &     ! surface  wave-induced mixing
81         &             ln_zdfiwm,                                    &     ! internal  -      -      -
82         &             ln_zad_Aimp,                                  &     ! apdative-implicit vertical advection
83         &             rn_avm0, rn_avt0, nn_avb, nn_havtb                  ! coefficients
84      !!----------------------------------------------------------------------
85      !
86      IF( .NOT. ln_2d ) THEN
87
88      IF(lwp) THEN
89         WRITE(numout,*)
90         WRITE(numout,*) 'zdf_phy_init: ocean vertical physics'
91         WRITE(numout,*) '~~~~~~~~~~~~'
92      ENDIF
93      !
94      !                           !==  Namelist  ==!
95      REWIND( numnam_ref )              ! Namelist namzdf in reference namelist : Vertical mixing parameters
96      READ  ( numnam_ref, namzdf, IOSTAT = ios, ERR = 901)
97901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namzdf in reference namelist', lwp )
98      !
99      REWIND( numnam_cfg )              ! Namelist namzdf in reference namelist : Vertical mixing parameters
100      READ  ( numnam_cfg, namzdf, IOSTAT = ios, ERR = 902 )
101902   IF( ios >  0 )   CALL ctl_nam ( ios , 'namzdf in configuration namelist', lwp )
102      IF(lwm)   WRITE ( numond, namzdf )
103      !
104      IF(lwp) THEN                      ! Parameter print
105         WRITE(numout,*) '   Namelist namzdf : set vertical mixing mixing parameters'
106         WRITE(numout,*) '      adaptive-implicit vertical advection'
107         WRITE(numout,*) '         Courant number targeted application   ln_zad_Aimp = ', ln_zad_Aimp
108         WRITE(numout,*) '      vertical closure scheme'
109         WRITE(numout,*) '         constant vertical mixing coefficient    ln_zdfcst = ', ln_zdfcst
110         WRITE(numout,*) '         Richardson number dependent closure     ln_zdfric = ', ln_zdfric
111         WRITE(numout,*) '         Turbulent Kinetic Energy closure (TKE)  ln_zdftke = ', ln_zdftke
112         WRITE(numout,*) '         Generic Length Scale closure (GLS)      ln_zdfgls = ', ln_zdfgls
113         WRITE(numout,*) '         OSMOSIS-OBL closure (OSM)               ln_zdfosm = ', ln_zdfosm
114         WRITE(numout,*) '      convection: '
115         WRITE(numout,*) '         enhanced vertical diffusion             ln_zdfevd = ', ln_zdfevd
116         WRITE(numout,*) '            applied on momentum (=1/0)             nn_evdm = ', nn_evdm
117         WRITE(numout,*) '            vertical coefficient for evd           rn_evd  = ', rn_evd
118         WRITE(numout,*) '         non-penetrative convection (npc)        ln_zdfnpc = ', ln_zdfnpc
119         WRITE(numout,*) '            npc call  frequency                    nn_npc  = ', nn_npc
120         WRITE(numout,*) '            npc print frequency                    nn_npcp = ', nn_npcp
121         WRITE(numout,*) '      double diffusive mixing                    ln_zdfddm = ', ln_zdfddm
122         WRITE(numout,*) '         maximum avs for dd mixing                 rn_avts = ', rn_avts
123         WRITE(numout,*) '         heat/salt buoyancy flux ratio             rn_hsbfr= ', rn_hsbfr
124         WRITE(numout,*) '      gravity wave-induced mixing'
125         WRITE(numout,*) '         surface  wave (Qiao et al 2010)         ln_zdfswm = ', ln_zdfswm                                          ! surface wave induced mixing
126         WRITE(numout,*) '         internal wave (de Lavergne et al 2017)  ln_zdfiwm = ', ln_zdfiwm
127         WRITE(numout,*) '      coefficients : '
128         WRITE(numout,*) '         vertical eddy viscosity                 rn_avm0   = ', rn_avm0
129         WRITE(numout,*) '         vertical eddy diffusivity               rn_avt0   = ', rn_avt0
130         WRITE(numout,*) '         constant background or profile          nn_avb    = ', nn_avb
131         WRITE(numout,*) '         horizontal variation for avtb           nn_havtb  = ', nn_havtb
132      ENDIF
133
134      IF( ln_zad_Aimp ) THEN
135         IF( zdf_phy_alloc() /= 0 )   &
136            &       CALL ctl_stop( 'STOP', 'zdf_phy_init : unable to allocate adaptive-implicit z-advection arrays' )
137         Cu_adv(:,:,:) = 0._wp
138         wi    (:,:,:) = 0._wp
139      ENDIF
140      !                          !==  Background eddy viscosity and diffusivity  ==!
141      IF( nn_avb == 0 ) THEN             ! Define avmb, avtb from namelist parameter
142         avmb(:) = rn_avm0
143         avtb(:) = rn_avt0                     
144      ELSE                               ! Background profile of avt (fit a theoretical/observational profile (Krauss 1990)
145         avmb(:) = rn_avm0
146         avtb(:) = rn_avt0 + ( 3.e-4_wp - 2._wp * rn_avt0 ) * 1.e-4_wp * gdepw_1d(:)   ! m2/s
147         IF(ln_sco .AND. lwp)   CALL ctl_warn( 'avtb profile not valid in sco' )
148      ENDIF
149      !                                  ! 2D shape of the avtb
150      avtb_2d(:,:) = 1._wp                   ! uniform
151      !
152      IF( nn_havtb == 1 ) THEN               ! decrease avtb by a factor of ten in the equatorial band
153           !                                 !   -15S -5S : linear decrease from avt0 to avt0/10.
154           !                                 !   -5S  +5N : cst value avt0/10.
155           !                                 !    5N  15N : linear increase from avt0/10, to avt0
156           WHERE(-15. <= gphit .AND. gphit < -5 )   avtb_2d = (1.  - 0.09 * (gphit + 15.))
157           WHERE( -5. <= gphit .AND. gphit <  5 )   avtb_2d =  0.1
158           WHERE(  5. <= gphit .AND. gphit < 15 )   avtb_2d = (0.1 + 0.09 * (gphit -  5.))
159      ENDIF
160      !
161      DO jk = 1, jpk                      ! set turbulent closure Kz to the background value (avt_k, avm_k)
162         avt_k(:,:,jk) = avtb_2d(:,:) * avtb(jk) * wmask (:,:,jk)
163         avm_k(:,:,jk) =                avmb(jk) * wmask (:,:,jk)
164      END DO
165!!gm  to be tested only the 1st & last levels
166!      avt  (:,:, 1 ) = 0._wp   ;   avs(:,:, 1 ) = 0._wp   ;   avm  (:,:, 1 ) = 0._wp
167!      avt  (:,:,jpk) = 0._wp   ;   avs(:,:,jpk) = 0._wp   ;   avm  (:,:,jpk) = 0._wp
168!!gm
169      avt  (:,:,:) = 0._wp   ;   avs(:,:,:) = 0._wp   ;   avm  (:,:,:) = 0._wp
170
171      !                          !==  Convection  ==!
172      !
173      IF( ln_zdfnpc .AND. ln_zdfevd )   CALL ctl_stop( 'zdf_phy_init: chose between ln_zdfnpc and ln_zdfevd' )
174      IF( ln_zdfosm .AND. ln_zdfevd )   CALL ctl_stop( 'zdf_phy_init: chose between ln_zdfosm and ln_zdfevd' )
175      IF( lk_top    .AND. ln_zdfnpc )   CALL ctl_stop( 'zdf_phy_init: npc scheme is not working with key_top' )
176      IF( lk_top    .AND. ln_zdfosm )   CALL ctl_stop( 'zdf_phy_init: osmosis scheme is not working with key_top' )
177      IF(lwp) THEN
178         WRITE(numout,*)
179         IF    ( ln_zdfnpc ) THEN  ;   WRITE(numout,*) '   ==>>>   convection: use non penetrative convective scheme'
180         ELSEIF( ln_zdfevd ) THEN  ;   WRITE(numout,*) '   ==>>>   convection: use enhanced vertical diffusion scheme'
181         ELSE                      ;   WRITE(numout,*) '   ==>>>   convection: no specific scheme used'
182         ENDIF
183      ENDIF
184
185      IF(lwp) THEN               !==  Double Diffusion Mixing parameterization  ==!   (ddm)
186         WRITE(numout,*)
187         IF( ln_zdfddm ) THEN   ;   WRITE(numout,*) '   ==>>>   use double diffusive mixing: avs /= avt'
188         ELSE                   ;   WRITE(numout,*) '   ==>>>   No  double diffusive mixing: avs = avt'
189         ENDIF
190      ENDIF
191
192      !                          !==  type of vertical turbulent closure  ==!    (set nzdf_phy)
193      ioptio = 0 
194      IF( ln_zdfcst ) THEN   ;   ioptio = ioptio + 1   ;    nzdf_phy = np_CST   ;   ENDIF
195      IF( ln_zdfric ) THEN   ;   ioptio = ioptio + 1   ;    nzdf_phy = np_RIC   ;   CALL zdf_ric_init   ;   ENDIF
196      IF( ln_zdftke ) THEN   ;   ioptio = ioptio + 1   ;    nzdf_phy = np_TKE   ;   CALL zdf_tke_init   ;   ENDIF
197      IF( ln_zdfgls ) THEN   ;   ioptio = ioptio + 1   ;    nzdf_phy = np_GLS   ;   CALL zdf_gls_init   ;   ENDIF
198      IF( ln_zdfosm ) THEN   ;   ioptio = ioptio + 1   ;    nzdf_phy = np_OSM   ;   CALL zdf_osm_init   ;   ENDIF
199      !
200      IF( ioptio /= 1 )    CALL ctl_stop( 'zdf_phy_init: one and only one vertical diffusion option has to be defined ' )
201      IF( ln_isfcav ) THEN
202      IF( ln_zdfric .OR. ln_zdfgls )    CALL ctl_stop( 'zdf_phy_init: zdfric and zdfgls never tested with ice shelves cavities ' )
203      ENDIF
204      !                                ! shear production term flag
205      IF( ln_zdfcst ) THEN   ;   l_zdfsh2 = .FALSE.
206      ELSE                   ;   l_zdfsh2 = .TRUE.
207      ENDIF
208
209      !                          !== gravity wave-driven mixing  ==!
210      IF( ln_zdfiwm )   CALL zdf_iwm_init       ! internal wave-driven mixing
211      IF( ln_zdfswm )   CALL zdf_swm_init       ! surface  wave-driven mixing
212
213      ENDIF  ! .NOT. ln_2d
214
215      !                          !== top/bottom friction  ==!
216      CALL zdf_drg_init
217      !
218      !                          !== time-stepping  ==!
219      ! Check/update of time stepping done in dynzdf_init/trazdf_init
220      !!gm move it here ?
221      !
222   END SUBROUTINE zdf_phy_init
223
224
225   SUBROUTINE zdf_phy( kt )
226      !!----------------------------------------------------------------------
227      !!                     ***  ROUTINE zdf_phy  ***
228      !!
229      !! ** Purpose :  Update ocean physics at each time-step
230      !!
231      !! ** Method  :
232      !!
233      !! ** Action  :   avm, avt vertical eddy viscosity and diffusivity at w-points
234      !!                nmld ??? mixed layer depth in level and meters   <<<<====verifier !
235      !!                bottom stress.....                               <<<<====verifier !
236      !!----------------------------------------------------------------------
237      INTEGER, INTENT(in) ::   kt   ! ocean time-step index
238      !
239      INTEGER ::   ji, jj, jk   ! dummy loop indice
240      REAL(wp), DIMENSION(jpi,jpj,jpk) ::   zsh2   ! shear production
241      !! ---------------------------------------------------------------------
242      !
243      IF( ln_timing )   CALL timing_start('zdf_phy')
244      !
245      IF( l_zdfdrg ) THEN     !==  update top/bottom drag  ==!   (non-linear cases)
246         !
247         !                       !* bottom drag
248         CALL zdf_drg( kt, mbkt    , r_Cdmin_bot, r_Cdmax_bot,   &   ! <<== in
249            &              r_z0_bot,   r_ke0_bot,    rCd0_bot,   &
250            &                                        rCdU_bot  )     ! ==>> out : bottom drag [m/s]
251         IF( ln_isfcav ) THEN    !* top drag   (ocean cavities)
252            CALL zdf_drg( kt, mikt    , r_Cdmin_top, r_Cdmax_top,   &   ! <<== in
253               &              r_z0_top,   r_ke0_top,    rCd0_top,   &
254               &                                        rCdU_top  )     ! ==>> out : bottom drag [m/s]
255         ENDIF
256      ENDIF
257     
258      IF( .NOT. ln_2d ) THEN ! 2D case only uses bottom friction from this routine     
259      !
260      !                       !==  Kz from chosen turbulent closure  ==!   (avm_k, avt_k)
261      !
262      IF( l_zdfsh2 )   &         !* shear production at w-points (energy conserving form)
263         CALL zdf_sh2( ub, vb, un, vn, avm_k,   &     ! <<== in
264            &                           zsh2    )     ! ==>> out : shear production
265      !
266      SELECT CASE ( nzdf_phy )                  !* Vertical eddy viscosity and diffusivity coefficients at w-points
267      CASE( np_RIC )   ;   CALL zdf_ric( kt, gdept_n, zsh2, avm_k, avt_k )    ! Richardson number dependent Kz
268      CASE( np_TKE )   ;   CALL zdf_tke( kt         , zsh2, avm_k, avt_k )    ! TKE closure scheme for Kz
269      CASE( np_GLS )   ;   CALL zdf_gls( kt         , zsh2, avm_k, avt_k )    ! GLS closure scheme for Kz
270      CASE( np_OSM )   ;   CALL zdf_osm( kt               , avm_k, avt_k )    ! OSMOSIS closure scheme for Kz
271!     CASE( np_CST )                                  ! Constant Kz (reset avt, avm to the background value)
272!         ! avt_k and avm_k set one for all at initialisation phase
273!!gm         avt(2:jpim1,2:jpjm1,1:jpkm1) = rn_avt0 * wmask(2:jpim1,2:jpjm1,1:jpkm1)
274!!gm         avm(2:jpim1,2:jpjm1,1:jpkm1) = rn_avm0 * wmask(2:jpim1,2:jpjm1,1:jpkm1)
275      END SELECT
276     
277      !                          !==  ocean Kz  ==!   (avt, avs, avm)
278      !
279      !                                         !* start from turbulent closure values
280      avt(:,:,2:jpkm1) = avt_k(:,:,2:jpkm1)
281      avm(:,:,2:jpkm1) = avm_k(:,:,2:jpkm1)
282      !
283      IF( ln_rnf_mouth ) THEN                   !* increase diffusivity at rivers mouths
284         DO jk = 2, nkrnf
285            avt(:,:,jk) = avt(:,:,jk) + 2._wp * rn_avt_rnf * rnfmsk(:,:) * wmask(:,:,jk)
286         END DO
287      ENDIF
288      !
289      IF( ln_zdfevd )   CALL zdf_evd( kt, avm, avt )  !* convection: enhanced vertical eddy diffusivity
290      !
291      !                                         !* double diffusive mixing
292      IF( ln_zdfddm ) THEN                            ! update avt and compute avs
293                        CALL zdf_ddm( kt, avm, avt, avs )
294      ELSE                                            ! same mixing on all tracers
295         avs(2:jpim1,2:jpjm1,1:jpkm1) = avt(2:jpim1,2:jpjm1,1:jpkm1)
296      ENDIF
297      !
298      !                                         !* wave-induced mixing
299      IF( ln_zdfswm )   CALL zdf_swm( kt, avm, avt, avs )   ! surface  wave (Qiao et al. 2004)
300      IF( ln_zdfiwm )   CALL zdf_iwm( kt, avm, avt, avs )   ! internal wave (de Lavergne et al 2017)
301
302#if defined key_agrif 
303      ! interpolation parent grid => child grid for avm_k ( ex : at west border: update column 1 and 2)
304      IF( l_zdfsh2 )   CALL Agrif_avm
305#endif
306
307      !                                         !* Lateral boundary conditions (sign unchanged)
308      IF( l_zdfsh2 ) THEN
309         CALL lbc_lnk_multi( 'zdfphy', avm_k, 'W', 1. , avt_k, 'W', 1.,   &
310            &                avm  , 'W', 1. , avt  , 'W', 1. , avs , 'W', 1. )
311      ELSE
312         CALL lbc_lnk_multi( 'zdfphy', avm  , 'W', 1. , avt  , 'W', 1. , avs , 'W', 1. )
313      ENDIF
314      !
315      IF( l_zdfdrg ) THEN     ! drag  have been updated (non-linear cases)
316         IF( ln_isfcav ) THEN   ;  CALL lbc_lnk_multi( 'zdfphy', rCdU_top, 'T', 1. , rCdU_bot, 'T', 1. )   ! top & bot drag
317         ELSE                   ;  CALL lbc_lnk      ( 'zdfphy', rCdU_bot, 'T', 1. )                       ! bottom drag only
318         ENDIF
319      ENDIF
320      !
321      CALL zdf_mxl( kt )                        !* mixed layer depth, and level
322      !
323      IF( lrst_oce ) THEN                       !* write TKE, GLS or RIC fields in the restart file
324         IF( ln_zdftke )   CALL tke_rst( kt, 'WRITE' )
325         IF( ln_zdfgls )   CALL gls_rst( kt, 'WRITE' )
326         IF( ln_zdfric )   CALL ric_rst( kt, 'WRITE' ) 
327         ! NB. OSMOSIS restart (osm_rst) will be called in step.F90 after wn has been updated
328      ENDIF
329     
330      ENDIF  ! .NOT. ln_2d
331      !
332      IF( ln_timing )   CALL timing_stop('zdf_phy')
333      !
334   END SUBROUTINE zdf_phy
335   INTEGER FUNCTION zdf_phy_alloc()
336      !!----------------------------------------------------------------------
337      !!                 ***  FUNCTION zdf_phy_alloc  ***
338      !!----------------------------------------------------------------------
339     ! Allocate wi array (declared in oce.F90) for use with the adaptive-implicit vertical velocity option
340     ALLOCATE(     wi(jpi,jpj,jpk), Cu_adv(jpi,jpj,jpk),  STAT= zdf_phy_alloc )
341     IF( zdf_phy_alloc /= 0 )   CALL ctl_warn('zdf_phy_alloc: failed to allocate ln_zad_Aimp=T required arrays')
342     CALL mpp_sum ( 'zdfphy', zdf_phy_alloc )
343   END FUNCTION zdf_phy_alloc
344
345   !!======================================================================
346END MODULE zdfphy
Note: See TracBrowser for help on using the repository browser.