Skip to content
Snippets Groups Projects
zdfosm.F90 213 KiB
Newer Older
Guillaume Samson's avatar
Guillaume Samson committed
      !!----------------------------------------------------------------------
      !
      zb_coup(:,:) = 0.0_wp
      !
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         IF ( l_conv(ji,jj) ) THEN
            !
            zvel_sc_pyc = ( 0.15_wp * svstr(ji,jj)**3 + swstrc(ji,jj)**3 + 4.25_wp * pshear(ji,jj) * phbl(ji,jj) )**pthird
            zvel_sc_ml  = ( svstr(ji,jj)**3 + 0.5_wp * swstrc(ji,jj)**3 )**pthird
            zstab_fac   = ( phml(ji,jj) / zvel_sc_ml *   &
               &            ( 1.4_wp - 0.4_wp / ( 1.0_wp + EXP(-3.5_wp * LOG10( -1.0_wp * shol(ji,jj) ) ) )**1.25_wp ) )**2
            !
            zdifml_sc(ji,jj) = pp_dif_ml * phml(ji,jj) * zvel_sc_ml
            zvisml_sc(ji,jj) = pp_vis_ml * zdifml_sc(ji,jj)
            !
            IF ( l_pyc(ji,jj) ) THEN
               zdifpyc_n_sc(ji,jj) = pp_dif_pyc * zvel_sc_ml * pdh(ji,jj)
               zvispyc_n_sc(ji,jj) = 0.09_wp * zvel_sc_pyc * ( 1.0_wp - phbl(ji,jj) / pdh(ji,jj) )**2 *   &
                  &                  ( 0.005_wp  * ( av_u_ml(ji,jj) - av_u_bl(ji,jj) )**2 +     &
                  &                    0.0075_wp * ( av_v_ml(ji,jj) - av_v_bl(ji,jj) )**2 ) /   &
                  &                  pdh(ji,jj)
               zvispyc_n_sc(ji,jj) = pp_vis_pyc * zvel_sc_ml * pdh(ji,jj) + zvispyc_n_sc(ji,jj) * zstab_fac
               !
               IF ( l_shear(ji,jj) .AND. n_ddh(ji,jj) /= 2 ) THEN
                  ztmp = pp_vispyc_shr * ( pshear(ji,jj) * phbl(ji,jj) )**pthird * phbl(ji,jj)
                  zdifpyc_n_sc(ji,jj) = zdifpyc_n_sc(ji,jj) + ztmp
                  zvispyc_n_sc(ji,jj) = zvispyc_n_sc(ji,jj) + ztmp
               ENDIF
               !
               zdifpyc_s_sc(ji,jj) = pwb_ent(ji,jj) + 0.0025_wp * zvel_sc_pyc * ( phbl(ji,jj) / pdh(ji,jj) - 1.0_wp ) *   &
                  &                                   ( av_b_ml(ji,jj) - av_b_bl(ji,jj) )
               zvispyc_s_sc(ji,jj) = 0.09_wp * ( pwb_min(ji,jj) + 0.0025_wp * zvel_sc_pyc *                 &
                  &                                               ( phbl(ji,jj) / pdh(ji,jj) - 1.0_wp ) *   &
                  &                                               ( av_b_ml(ji,jj) - av_b_bl(ji,jj) ) )
               zdifpyc_s_sc(ji,jj) = 0.09_wp * zdifpyc_s_sc(ji,jj) * zstab_fac
               zvispyc_s_sc(ji,jj) = zvispyc_s_sc(ji,jj) * zstab_fac
               !
               zdifpyc_s_sc(ji,jj) = MAX( zdifpyc_s_sc(ji,jj), -0.5_wp * zdifpyc_n_sc(ji,jj) )
               zvispyc_s_sc(ji,jj) = MAX( zvispyc_s_sc(ji,jj), -0.5_wp * zvispyc_n_sc(ji,jj) )
               
               zbeta_d_sc(ji,jj) = 1.0_wp - ( ( zdifpyc_n_sc(ji,jj) + 1.4_wp * zdifpyc_s_sc(ji,jj) ) /   &
                  &                           ( zdifml_sc(ji,jj) + epsln ) )**p2third
               zbeta_v_sc(ji,jj) = 1.0_wp - 2.0_wp * ( zvispyc_n_sc(ji,jj) + zvispyc_s_sc(ji,jj) ) / ( zvisml_sc(ji,jj) + epsln )
            ELSE
               zdifpyc_n_sc(ji,jj) = pp_dif_pyc * zvel_sc_ml * pdh(ji,jj)   ! ag 19/03
               zdifpyc_s_sc(ji,jj) = 0.0_wp   ! ag 19/03
               zvispyc_n_sc(ji,jj) = pp_vis_pyc * zvel_sc_ml * pdh(ji,jj)   ! ag 19/03
               zvispyc_s_sc(ji,jj) = 0.0_wp   ! ag 19/03
               IF(l_coup(ji,jj) ) THEN   ! ag 19/03
                  ! code from SUBROUTINE tke_tke zdftke.F90; uses bottom drag velocity rCdU_bot(ji,jj) = -Cd|ub|
                  !     already calculated at T-points in SUBROUTINE zdf_drg from zdfdrg.F90
                  !  Gives friction velocity sqrt bottom drag/rho_0 i.e. u* = SQRT(rCdU_bot*ub)
                  ! wet-cell averaging ..
                  zmsku = 0.5_wp * ( 2.0_wp - umask(ji-1,jj,mbkt(ji,jj)) * umask(ji,jj,mbkt(ji,jj)) )
                  zmskv = 0.5_wp * ( 2.0_wp - vmask(ji,jj-1,mbkt(ji,jj)) * vmask(ji,jj,mbkt(ji,jj)) )
                  zb_coup(ji,jj) = 0.4_wp * SQRT(-1.0_wp * rCdU_bot(ji,jj) *   &
                     &             SQRT(  ( zmsku*( uu(ji,jj,mbkt(ji,jj),Kbb)+uu(ji-1,jj,mbkt(ji,jj),Kbb) ) )**2   &
                     &                  + ( zmskv*( vv(ji,jj,mbkt(ji,jj),Kbb)+vv(ji,jj-1,mbkt(ji,jj),Kbb) ) )**2  ) )
                  
                  zz_b = -1.0_wp * gdepw(ji,jj,mbkt(ji,jj)+1,Kmm)   ! ag 19/03
                  zc_coup_vis(ji,jj) = -0.5_wp * ( 0.5_wp * zvisml_sc(ji,jj) / phml(ji,jj) - zb_coup(ji,jj) ) /   &
                     &                 ( phml(ji,jj) + zz_b )   ! ag 19/03
                  zz_b = -1.0_wp * phml(ji,jj) + gdepw(ji,jj,mbkt(ji,jj)+1,Kmm)   ! ag 19/03
                  zbeta_v_sc(ji,jj) = 1.0_wp - 2.0_wp * ( zb_coup(ji,jj) * zz_b + zc_coup_vis(ji,jj) * zz_b**2 ) /   &
                     &                                  zvisml_sc(ji,jj)   ! ag 19/03
                  zbeta_d_sc(ji,jj) = 1.0_wp - ( ( zb_coup(ji,jj) * zz_b + zc_coup_vis(ji,jj) * zz_b**2 ) /   &
                     &                           zdifml_sc(ji,jj) )**p2third
                  zc_coup_dif(ji,jj) = 0.5_wp * ( -zdifml_sc(ji,jj) / phml(ji,jj) * ( 1.0_wp - zbeta_d_sc(ji,jj) )**1.5_wp +   &
                     &                 1.5_wp * ( zdifml_sc(ji,jj) / phml(ji,jj) ) * zbeta_d_sc(ji,jj) *   &
                     &                          SQRT( 1.0_wp - zbeta_d_sc(ji,jj) ) - zb_coup(ji,jj) ) / zz_b   ! ag 19/03
               ELSE   ! ag 19/03
                  zbeta_d_sc(ji,jj) = 1.0_wp - ( ( zdifpyc_n_sc(ji,jj) + 1.4_wp * zdifpyc_s_sc(ji,jj) ) /   &
                     &                           ( zdifml_sc(ji,jj) + epsln ) )**p2third   ! ag 19/03
                  zbeta_v_sc(ji,jj) = 1.0_wp - 2.0_wp * ( zvispyc_n_sc(ji,jj) + zvispyc_s_sc(ji,jj) ) /   &
                     &                         ( zvisml_sc(ji,jj) + epsln )   ! ag 19/03
               ENDIF   ! ag 19/03
            ENDIF      ! ag 19/03
         ELSE
            zdifml_sc(ji,jj) = svstr(ji,jj) * phbl(ji,jj) * MAX( EXP ( -1.0_wp * ( shol(ji,jj) / 0.6_wp )**2 ), 0.2_wp)
            zvisml_sc(ji,jj) = zdifml_sc(ji,jj)
         END IF
      END_2D
      !
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         IF ( l_conv(ji,jj) ) THEN
            DO jk = 2, nmld(ji,jj)   ! Mixed layer diffusivity
               zznd_ml = gdepw(ji,jj,jk,Kmm) / phml(ji,jj)
               pdiffut(ji,jj,jk) = zdifml_sc(ji,jj) * zznd_ml * ( 1.0_wp - zbeta_d_sc(ji,jj) * zznd_ml )**1.5
               pviscos(ji,jj,jk) = zvisml_sc(ji,jj) * zznd_ml * ( 1.0_wp - zbeta_v_sc(ji,jj) * zznd_ml ) *   &
                  &                ( 1.0_wp - 0.5_wp * zznd_ml**2 )
            END DO
            !
            ! Coupling to bottom
            !
            IF ( l_coup(ji,jj) ) THEN                                                         ! ag 19/03
               DO jk = mbkt(ji,jj), nmld(ji,jj), -1                                           ! ag 19/03
                  zz_b = -1.0_wp * ( gdepw(ji,jj,jk,Kmm) - gdepw(ji,jj,mbkt(ji,jj)+1,Kmm) )   ! ag 19/03
                  pviscos(ji,jj,jk) = zb_coup(ji,jj) * zz_b + zc_coup_vis(ji,jj) * zz_b**2    ! ag 19/03
                  pdiffut(ji,jj,jk) = zb_coup(ji,jj) * zz_b + zc_coup_dif(ji,jj) * zz_b**2    ! ag 19/03
               END DO                                                                         ! ag 19/03
            ENDIF                                                                             ! ag 19/03
            ! Pycnocline
            IF ( l_pyc(ji,jj) ) THEN 
               ! Diffusivity and viscosity profiles in the pycnocline given by
               ! cubic polynomial. Note, if l_pyc TRUE can't be coupled to seabed.
               za_cubic = 0.5_wp
               zb_d_cubic = -1.75_wp * zdifpyc_s_sc(ji,jj) / zdifpyc_n_sc(ji,jj)
               zd_d_cubic = ( pdh(ji,jj) * zdifml_sc(ji,jj) / phml(ji,jj) * SQRT( 1.0_wp - zbeta_d_sc(ji,jj) ) *   &
                  &           ( 2.5_wp * zbeta_d_sc(ji,jj) - 1.0_wp ) - 0.85_wp * zdifpyc_s_sc(ji,jj) ) /            &
                  &           MAX( zdifpyc_n_sc(ji,jj), 1.0e-8_wp )
               zd_d_cubic = zd_d_cubic - zb_d_cubic - 2.0_wp * ( 1.0_wp - za_cubic  - zb_d_cubic )
               zc_d_cubic = 1.0_wp - za_cubic - zb_d_cubic - zd_d_cubic
               zb_v_cubic = -1.75_wp * zvispyc_s_sc(ji,jj) / zvispyc_n_sc(ji,jj)
               zd_v_cubic = ( 0.5_wp * zvisml_sc(ji,jj) * pdh(ji,jj) / phml(ji,jj) - 0.85_wp * zvispyc_s_sc(ji,jj) ) /   &
                  &           MAX( zvispyc_n_sc(ji,jj), 1.0e-8_wp )
               zd_v_cubic = zd_v_cubic - zb_v_cubic - 2.0_wp * ( 1.0_wp - za_cubic - zb_v_cubic )
               zc_v_cubic = 1.0_wp - za_cubic - zb_v_cubic - zd_v_cubic
               DO jk = nmld(ji,jj) , nbld(ji,jj)
                  zznd_pyc = -1.0_wp * ( gdepw(ji,jj,jk,Kmm) - phbl(ji,jj) ) / MAX(pdh(ji,jj), 1.0e-6_wp )
                  ztmp = ( 1.75_wp * zznd_pyc - 0.15_wp * zznd_pyc**2 - 0.2_wp * zznd_pyc**3 )
                  !
                  pdiffut(ji,jj,jk) = zdifpyc_n_sc(ji,jj) *   &
                     &                ( za_cubic + zb_d_cubic * zznd_pyc + zc_d_cubic * zznd_pyc**2 + zd_d_cubic * zznd_pyc**3 )
                  !
                  pdiffut(ji,jj,jk) = pdiffut(ji,jj,jk) + zdifpyc_s_sc(ji,jj) * ztmp
                  pviscos(ji,jj,jk) = zvispyc_n_sc(ji,jj) *   &
                     &                ( za_cubic + zb_v_cubic * zznd_pyc + zc_v_cubic * zznd_pyc**2 + zd_v_cubic * zznd_pyc**3 )
                  pviscos(ji,jj,jk) = pviscos(ji,jj,jk) + zvispyc_s_sc(ji,jj) * ztmp
               END DO
   !                  IF ( pdhdt(ji,jj) > 0._wp ) THEN
   !                     zdiffut(ji,jj,nbld(ji,jj)+1) = MAX( 0.5 * pdhdt(ji,jj) * e3w(ji,jj,nbld(ji,jj)+1,Kmm), 1.0e-6 )
   !                     zviscos(ji,jj,nbld(ji,jj)+1) = MAX( 0.5 * pdhdt(ji,jj) * e3w(ji,jj,nbld(ji,jj)+1,Kmm), 1.0e-6 )
   !                  ELSE
   !                     zdiffut(ji,jj,nbld(ji,jj)) = 0._wp
   !                     zviscos(ji,jj,nbld(ji,jj)) = 0._wp
   !                  ENDIF
            ENDIF
         ELSE
            ! Stable conditions
            DO jk = 2, nbld(ji,jj)
               zznd_ml = gdepw(ji,jj,jk,Kmm) / phbl(ji,jj)
               pdiffut(ji,jj,jk) = 0.75_wp * zdifml_sc(ji,jj) * zznd_ml * ( 1.0_wp - zznd_ml )**1.5_wp
               pviscos(ji,jj,jk) = 0.375_wp * zvisml_sc(ji,jj) * zznd_ml * ( 1.0_wp - zznd_ml ) * ( 1.0_wp - zznd_ml**2 )
            END DO
            !
            IF ( pdhdt(ji,jj) > 0.0_wp ) THEN
               pdiffut(ji,jj,nbld(ji,jj)) = MAX( pdhdt(ji,jj), 1.0e-6_wp) * e3w(ji, jj, nbld(ji,jj), Kmm)
               pviscos(ji,jj,nbld(ji,jj)) = pdiffut(ji,jj,nbld(ji,jj))
            ENDIF
         ENDIF   ! End if ( l_conv )
         !
      END_2D
      CALL zdf_osm_iomput( "pb_coup", tmask(T2D(0),1) * zb_coup(T2D(0)) )   ! BBL-coupling velocity scale
Guillaume Samson's avatar
Guillaume Samson committed
      !
   END SUBROUTINE zdf_osm_diffusivity_viscosity

   SUBROUTINE zdf_osm_fgr_terms( Kmm, kp_ext, phbl, phml, pdh,                              &
      &                          pdhdt, pshear, pdtdz_bl_ext, pdsdz_bl_ext, pdbdz_bl_ext,   &
      &                          pdiffut, pviscos )
      !!---------------------------------------------------------------------
      !!                 ***  ROUTINE zdf_osm_fgr_terms ***
      !!
      !! ** Purpose : Compute non-gradient terms in flux-gradient relationship
      !!
      !! ** Method  :
      !!
      !!----------------------------------------------------------------------
      INTEGER,                                 INTENT(in   ) ::   Kmm            ! Time-level index
      INTEGER,  DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   kp_ext         ! Offset for external level
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   phbl           ! BL depth
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   phml           ! ML depth
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   pdh            ! Pycnocline depth
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   pdhdt          ! BL depth tendency
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   pshear         ! Shear production
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   pdtdz_bl_ext   ! External temperature gradients
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   pdsdz_bl_ext   ! External salinity gradients
      REAL(wp), DIMENSION(T2D(nn_hls-1)),      INTENT(in   ) ::   pdbdz_bl_ext   ! External buoyancy gradients
      REAL(wp), DIMENSION(T2D(nn_hls-1),jpk),  INTENT(in   ) ::   pdiffut        ! t-diffusivity
      REAL(wp), DIMENSION(T2D(nn_hls-1),jpk),  INTENT(in   ) ::   pviscos        ! Viscosity
      !!
      REAL(wp), DIMENSION(T2D(nn_hls-1))     ::   zalpha_pyc   !
      REAL(wp), DIMENSION(T2D(nn_hls-1),jpk) ::   zdbdz_pyc    ! Parametrised gradient of buoyancy in the pycnocline
Guillaume Samson's avatar
Guillaume Samson committed
      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::   z3ddz_pyc_1, z3ddz_pyc_2   ! Pycnocline gradient/shear profiles
      !!
      INTEGER                            ::   ji, jj, jk, jkm_bld, jkf_mld, jkm_mld   ! Loop indices
      INTEGER                            ::   istat                                   ! Memory allocation status
      REAL(wp)                           ::   zznd_d, zznd_ml, zznd_pyc, znd          ! Temporary non-dimensional depths
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zsc_wth_1,zsc_ws_1                      ! Temporary scales
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zsc_uw_1, zsc_uw_2                      ! Temporary scales
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zsc_vw_1, zsc_vw_2                      ! Temporary scales
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   ztau_sc_u                               ! Dissipation timescale at base of WML
Guillaume Samson's avatar
Guillaume Samson committed
      REAL(wp)                           ::   zbuoy_pyc_sc, zdelta_pyc                !
      REAL(wp)                           ::   zl_c,zl_l,zl_eps                        ! Used to calculate turbulence length scale
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   za_cubic, zb_cubic                      ! Coefficients in cubic polynomial specifying
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zc_cubic, zd_cubic                      !    diffusivity in pycnocline
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zwt_pyc_sc_1, zws_pyc_sc_1              !
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zzeta_pyc                               !
Guillaume Samson's avatar
Guillaume Samson committed
      REAL(wp)                           ::   zomega, zvw_max                         !
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zuw_bse,zvw_bse                         ! Momentum, heat, and salinity fluxes
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zwth_ent,zws_ent                        !    at the top of the pycnocline
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   zsc_wth_pyc, zsc_ws_pyc                 ! Scales for pycnocline transport term
Guillaume Samson's avatar
Guillaume Samson committed
      REAL(wp)                           ::   ztmp                                    !
      REAL(wp)                           ::   ztgrad, zsgrad, zbgrad                  ! Variables used to calculate pycnocline
      !!                                                                              !    gradients
      REAL(wp)                           ::   zugrad, zvgrad                          ! Variables for calculating pycnocline shear
      REAL(wp)                           ::   zdtdz_pyc                               ! Parametrized gradient of temperature in
      !!                                                                              !    pycnocline
      REAL(wp)                           ::   zdsdz_pyc                               ! Parametrised gradient of salinity in
      !!                                                                              !    pycnocline
      REAL(wp)                           ::   zdudz_pyc                               ! u-shear across the pycnocline
      REAL(wp)                           ::   zdvdz_pyc                               ! v-shear across the pycnocline
      !!----------------------------------------------------------------------
      !
      !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
      !  Pycnocline gradients for scalars and velocity
      !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
      CALL zdf_osm_pycnocline_buoyancy_profiles( Kmm, kp_ext, zdbdz_pyc, zalpha_pyc, pdh,    &
         &                                       phbl, pdbdz_bl_ext, phml, pdhdt )
      !
      ! Auxiliary indices
      ! -----------------
      jkm_bld = 0
      jkf_mld = jpk
      jkm_mld = 0
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         IF ( nbld(ji,jj) > jkm_bld ) jkm_bld = nbld(ji,jj)
         IF ( nmld(ji,jj) < jkf_mld ) jkf_mld = nmld(ji,jj)
         IF ( nmld(ji,jj) > jkm_mld ) jkm_mld = nmld(ji,jj)
      END_2D
      !
      ! Stokes term in scalar flux, flux-gradient relationship
      ! ------------------------------------------------------
      WHERE ( l_conv(T2D(nn_hls-1)) )
         zsc_wth_1(:,:) = swstrl(T2D(nn_hls-1))**3 * swth0(T2D(nn_hls-1)) /   &
            &             ( svstr(T2D(nn_hls-1))**3 + 0.5_wp * swstrc(T2D(nn_hls-1))**3 + epsln )
         zsc_ws_1(:,:)  = swstrl(T2D(nn_hls-1))**3 * sws0(T2D(nn_hls-1))  /   &
            &             ( svstr(T2D(nn_hls-1))**3 + 0.5_wp * swstrc(T2D(nn_hls-1))**3 + epsln )
Guillaume Samson's avatar
Guillaume Samson committed
      ELSEWHERE
         zsc_wth_1(:,:) = 2.0_wp * swthav(T2D(nn_hls-1))
         zsc_ws_1(:,:)  = 2.0_wp * swsav(T2D(nn_hls-1))
Guillaume Samson's avatar
Guillaume Samson committed
      ENDWHERE
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, MAX( jkm_mld, jkm_bld ) )
         IF ( l_conv(ji,jj) ) THEN
            IF ( jk <= nmld(ji,jj) ) THEN
               zznd_d = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
               ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + 1.35_wp * EXP( -1.0_wp * zznd_d ) *   &
                  &                                ( 1.0_wp - EXP( -2.0_wp * zznd_d ) ) * zsc_wth_1(ji,jj)
               ghams(ji,jj,jk) = ghams(ji,jj,jk) + 1.35_wp * EXP( -1.0_wp * zznd_d ) *   &
                  &                                ( 1.0_wp - EXP( -2.0_wp * zznd_d ) ) * zsc_ws_1(ji,jj)
            END IF
         ELSE   ! Stable conditions
            IF ( jk <= nbld(ji,jj) ) THEN
               zznd_d = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
               ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + 2.15_wp * EXP( -0.85_wp * zznd_d ) *   &
                  &                                ( 1.0_wp - EXP( -4.0_wp * zznd_d ) ) * zsc_wth_1(ji,jj)
               ghams(ji,jj,jk) = ghams(ji,jj,jk) + 2.15_wp * EXP( -0.85_wp * zznd_d ) *   &
                  &                                ( 1.0_wp - EXP( -4.0_wp * zznd_d ) ) * zsc_ws_1(ji,jj)
            END IF
         END IF   ! Check on l_conv
      END_3D
      !
      IF ( ln_dia_osm ) THEN
         CALL zdf_osm_iomput( "ghamu_00", wmask(T2D(0),:) * ghamu(T2D(0),:) )
         CALL zdf_osm_iomput( "ghamv_00", wmask(T2D(0),:) * ghamv(T2D(0),:) )
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      !
      ! Stokes term in flux-gradient relationship (note in zsc_uw_n don't use
      ! svstr since term needs to go to zero as swstrl goes to zero)
      ! ---------------------------------------------------------------------
      WHERE ( l_conv(T2D(nn_hls-1)) )
         zsc_uw_1(:,:) = ( swstrl(T2D(nn_hls-1))**3 +                                                &
            &              0.5_wp * swstrc(T2D(nn_hls-1))**3 )**pthird * sustke(T2D(nn_hls-1)) /   &
            &              MAX( ( 1.0_wp - 1.0_wp * 6.5_wp * sla(T2D(nn_hls-1))**( 8.0_wp / 3.0_wp ) ), 0.2_wp )
         zsc_uw_2(:,:) = ( swstrl(T2D(nn_hls-1))**3 +                                                &
            &              0.5_wp * swstrc(T2D(nn_hls-1))**3 )**pthird * sustke(T2D(nn_hls-1)) /   &
            &              MIN( sla(T2D(nn_hls-1))**( 8.0_wp / 3.0_wp ) + epsln, 0.12_wp )
         zsc_vw_1(:,:) = ff_t(T2D(nn_hls-1)) * phml(T2D(nn_hls-1)) * sustke(T2D(nn_hls-1))**3 *   &
            &            MIN( sla(T2D(nn_hls-1))**( 8.0_wp / 3.0_wp ), 0.12_wp ) /                    &
            &            ( ( svstr(T2D(nn_hls-1))**3 + 0.5_wp * swstrc(T2D(nn_hls-1))**3 )**( 2.0_wp / 3.0_wp ) + epsln )
Guillaume Samson's avatar
Guillaume Samson committed
      ELSEWHERE
         zsc_uw_1(:,:) = sustar(T2D(nn_hls-1))**2
         zsc_vw_1(:,:) = ff_t(T2D(nn_hls-1)) * phbl(T2D(nn_hls-1)) * sustke(T2D(nn_hls-1))**3 *   &
            &            MIN( sla(T2D(nn_hls-1))**( 8.0_wp / 3.0_wp ), 0.12_wp ) / ( svstr(T2D(nn_hls-1))**2 + epsln )
Guillaume Samson's avatar
Guillaume Samson committed
      ENDWHERE
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, MAX( jkm_mld, jkm_bld ) )
         IF ( l_conv(ji,jj) ) THEN
            IF ( jk <= nmld(ji,jj) ) THEN
               zznd_d = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
               ghamu(ji,jj,jk) = ghamu(ji,jj,jk) + ( -0.05_wp   * EXP( -0.4_wp * zznd_d ) * zsc_uw_1(ji,jj) +     &
                  &                                  0.00125_wp * EXP( -1.0_wp * zznd_d ) * zsc_uw_2(ji,jj) ) *   &
                  &                                ( 1.0_wp - EXP( -2.0_wp * zznd_d ) )
               ghamv(ji,jj,jk) = ghamv(ji,jj,jk) - 0.65_wp *  0.15_wp * EXP( -1.0_wp * zznd_d ) *                 &
                  &                                ( 1.0_wp - EXP( -2.0_wp * zznd_d ) ) * zsc_vw_1(ji,jj)
            END IF
         ELSE   ! Stable conditions
            IF ( jk <= nbld(ji,jj) ) THEN   ! Corrected to nbld
               zznd_d = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
               ghamu(ji,jj,jk) = ghamu(ji,jj,jk) - 0.75_wp * 1.3_wp * EXP( -0.5_wp * zznd_d ) *             &
                  &                                ( 1.0_wp - EXP( -4.0_wp * zznd_d ) ) * zsc_uw_1(ji,jj)
            END IF
         END IF
      END_3D
      !
      ! Buoyancy term in flux-gradient relationship [note : includes ROI ratio
      ! (X0.3) and pressure (X0.5)]
      ! ----------------------------------------------------------------------
      WHERE ( l_conv(T2D(nn_hls-1)) )
         zsc_wth_1(:,:) = swbav(T2D(nn_hls-1)) * swth0(T2D(nn_hls-1)) * ( 1.0_wp + EXP( 0.2_wp * shol(T2D(nn_hls-1)) ) ) *   &
            &             phml(T2D(nn_hls-1)) / ( svstr(T2D(nn_hls-1))**3 + 0.5_wp * swstrc(T2D(nn_hls-1))**3 + epsln )
         zsc_ws_1(:,:)  = swbav(T2D(nn_hls-1)) * sws0(T2D(nn_hls-1))  * ( 1.0_wp + EXP( 0.2_wp * shol(T2D(nn_hls-1)) ) ) *   &
            &             phml(T2D(nn_hls-1)) / ( svstr(T2D(nn_hls-1))**3 + 0.5_wp * swstrc(T2D(nn_hls-1))**3 + epsln )
Guillaume Samson's avatar
Guillaume Samson committed
      ELSEWHERE
         zsc_wth_1(:,:) = 0.0_wp
         zsc_ws_1(:,:)  = 0.0_wp
      ENDWHERE
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, MAX( jkm_mld, jkm_bld ) )
         IF ( l_conv(ji,jj) ) THEN
            IF ( jk <= nmld(ji,jj) ) THEN
               zznd_ml = gdepw(ji,jj,jk,Kmm) / phml(ji,jj)
               ! Calculate turbulent time scale
               zl_c   = 0.9_wp * ( 1.0_wp - EXP( -5.0_wp * ( zznd_ml + zznd_ml**3 / 3.0_wp ) ) ) *                         &
                  &     ( 1.0_wp - EXP( -15.0_wp * ( 1.2_wp - zznd_ml ) ) )
               zl_l   = 2.0_wp * ( 1.0_wp - EXP( -2.0_wp * ( zznd_ml + zznd_ml**3 / 3.0_wp ) ) ) *                         &
                  &     ( 1.0_wp - EXP( -8.0_wp  * ( 1.15_wp - zznd_ml ) ) ) * ( 1.0_wp + dstokes(ji,jj) / phml (ji,jj) )
               zl_eps = zl_l + ( zl_c - zl_l ) / ( 1.0_wp + EXP( -3.0_wp * LOG10( -1.0_wp * shol(ji,jj) ) ) )**( 3.0_wp / 2.0_wp )
               ! Non-gradient buoyancy terms
               ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + 0.3_wp * 0.4_wp * zsc_wth_1(ji,jj) * zl_eps / ( 0.15_wp + zznd_ml )
               ghams(ji,jj,jk) = ghams(ji,jj,jk) + 0.3_wp * 0.4_wp *  zsc_ws_1(ji,jj) * zl_eps / ( 0.15_wp + zznd_ml )
            END IF
         ELSE   ! Stable conditions
            IF ( jk <= nbld(ji,jj) ) THEN
               ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + zsc_wth_1(ji,jj)
               ghams(ji,jj,jk) = ghams(ji,jj,jk) +  zsc_ws_1(ji,jj)
            END IF
         END IF
      END_3D
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         IF ( l_conv(ji,jj) .AND. l_pyc(ji,jj) ) THEN
            ztau_sc_u(ji,jj)    = phml(ji,jj) / ( svstr(ji,jj)**3 + swstrc(ji,jj)**3 )**pthird *                             &
               &                ( 1.4_wp - 0.4_wp / ( 1.0_wp + EXP( -3.5_wp * LOG10( -1.0_wp * shol(ji,jj) ) ) )**1.5_wp )
            zwth_ent(ji,jj)     = -0.003_wp * ( 0.15_wp * svstr(ji,jj)**3 + swstrc(ji,jj)**3 )**pthird *   &
               &                ( 1.0_wp - pdh(ji,jj) / phbl(ji,jj) ) * av_dt_ml(ji,jj)
            zws_ent(ji,jj)      = -0.003_wp * ( 0.15_wp * svstr(ji,jj)**3 + swstrc(ji,jj)**3 )**pthird *   &
               &                ( 1.0_wp - pdh(ji,jj) / phbl(ji,jj) ) * av_ds_ml(ji,jj)
            IF ( dh(ji,jj) < 0.2_wp * hbl(ji,jj) ) THEN
               zbuoy_pyc_sc        = 2.0_wp * MAX( av_db_ml(ji,jj), 0.0_wp ) / pdh(ji,jj)
               zdelta_pyc          = ( svstr(ji,jj)**3 + swstrc(ji,jj)**3 )**pthird /   &
                  &                       SQRT( MAX( zbuoy_pyc_sc, ( svstr(ji,jj)**3 + swstrc(ji,jj)**3 )**p2third / pdh(ji,jj)**2 ) )
               zwt_pyc_sc_1(ji,jj) = 0.325_wp * ( zalpha_pyc(ji,jj) * av_dt_ml(ji,jj) / pdh(ji,jj) + pdtdz_bl_ext(ji,jj) ) *   &
                  &                     zdelta_pyc**2 / pdh(ji,jj)
               zws_pyc_sc_1(ji,jj) = 0.325_wp * ( zalpha_pyc(ji,jj) * av_ds_ml(ji,jj) / pdh(ji,jj) + pdsdz_bl_ext(ji,jj) ) *   &
                  &                     zdelta_pyc**2 / pdh(ji,jj)
               zzeta_pyc(ji,jj)    = 0.15_wp - 0.175_wp / ( 1.0_wp + EXP( -3.5_wp * LOG10( -1.0_wp * shol(ji,jj) ) ) )
            END IF
         END IF
      END_2D
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, jkm_bld )
         IF ( l_conv(ji,jj) .AND. l_pyc(ji,jj) .AND. ( jk <= nbld(ji,jj) ) ) THEN
            zznd_pyc = -1.0_wp * ( gdepw(ji,jj,jk,Kmm) - phbl(ji,jj) ) / pdh(ji,jj)
            ghamt(ji,jj,jk) = ghamt(ji,jj,jk) -                                                                                &
               &              0.045_wp * ( ( zwth_ent(ji,jj) * zdbdz_pyc(ji,jj,jk) ) * ztau_sc_u(ji,jj)**2 ) *                 &
               &                         MAX( ( 1.75_wp * zznd_pyc -0.15_wp * zznd_pyc**2 - 0.2_wp * zznd_pyc**3 ), 0.0_wp )
            ghams(ji,jj,jk) = ghams(ji,jj,jk) -                                                                                &
               &              0.045_wp * ( ( zws_ent(ji,jj)  * zdbdz_pyc(ji,jj,jk) ) * ztau_sc_u(ji,jj)**2 ) *                 &
               &                         MAX( ( 1.75_wp * zznd_pyc -0.15_wp * zznd_pyc**2 - 0.2_wp * zznd_pyc**3 ), 0.0_wp )
            IF ( dh(ji,jj) < 0.2_wp * hbl(ji,jj) .AND. nbld(ji,jj) - nmld(ji,jj) > 3 ) THEN
               ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + 0.05_wp  * zwt_pyc_sc_1(ji,jj) *                              &
                  &                                EXP( -0.25_wp * ( zznd_pyc / zzeta_pyc(ji,jj) )**2 ) *        &
                  &                                pdh(ji,jj) / ( svstr(ji,jj)**3 + swstrc(ji,jj)**3 )**pthird
               ghams(ji,jj,jk) = ghams(ji,jj,jk) + 0.05_wp  * zws_pyc_sc_1(ji,jj) *                              &
                  &                                EXP( -0.25_wp * ( zznd_pyc / zzeta_pyc(ji,jj) )**2 ) *        &
                  &                                pdh(ji,jj) / ( svstr(ji,jj)**3 + swstrc(ji,jj)**3 )**pthird
            END IF
         END IF   ! End of pycnocline
      END_3D
      !
      IF ( ln_dia_osm ) THEN
         CALL zdf_osm_iomput( "zwth_ent", tmask(T2D(0),1) * zwth_ent(T2D(0)) )   ! Upward turb. temperature entrainment flux
         CALL zdf_osm_iomput( "zws_ent",  tmask(T2D(0),1) * zws_ent(T2D(0))  )   ! Upward turb. salinity entrainment flux
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      !
      zsc_vw_1(:,:) = 0.0_wp
      WHERE ( l_conv(T2D(nn_hls-1)) )
         zsc_uw_1(:,:) = -1.0_wp * swb0(T2D(nn_hls-1)) * sustar(T2D(nn_hls-1))**2 * phml(T2D(nn_hls-1)) /   &
            &            ( svstr(T2D(nn_hls-1))**3 + 0.5_wp * swstrc(T2D(nn_hls-1))**3 + epsln )
         zsc_uw_2(:,:) =           swb0(T2D(nn_hls-1)) * sustke(T2D(nn_hls-1))    * phml(T2D(nn_hls-1)) /   &
            &            ( svstr(T2D(nn_hls-1))**3 + 0.5_wp * swstrc(T2D(nn_hls-1))**3 + epsln )**( 2.0_wp / 3.0_wp )
Guillaume Samson's avatar
Guillaume Samson committed
      ELSEWHERE
         zsc_uw_1(:,:) = 0.0_wp
      ENDWHERE
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, MAX( jkm_mld, jkm_bld ) )
         IF ( l_conv(ji,jj) ) THEN
            IF ( jk <= nmld(ji,jj) ) THEN
               zznd_d = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
               ghamu(ji,jj,jk) = ghamu(ji,jj,jk) + 0.3_wp * 0.5_wp *   &
                  &                                ( zsc_uw_1(ji,jj) + 0.125_wp * EXP( -0.5_wp * zznd_d ) *       &
                  &                                  (   1.0_wp - EXP( -0.5_wp * zznd_d ) ) * zsc_uw_2(ji,jj) )
               ghamv(ji,jj,jk) = ghamv(ji,jj,jk) + zsc_vw_1(ji,jj)
            END IF
         ELSE   ! Stable conditions
            IF ( jk <= nbld(ji,jj) ) THEN
               ghamu(ji,jj,jk) = ghamu(ji,jj,jk) + zsc_uw_1(ji,jj)
               ghamv(ji,jj,jk) = ghamv(ji,jj,jk) + zsc_vw_1(ji,jj)
            END IF
         ENDIF
      END_3D
      !
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         IF ( l_conv(ji,jj) .AND. l_pyc(ji,jj) ) THEN
            IF ( n_ddh(ji,jj) == 0 ) THEN
               ! Place holding code. Parametrization needs checking for these conditions.
               zomega = ( 0.15_wp * swstrl(ji,jj)**3 + swstrc(ji,jj)**3 + 4.75_wp * ( pshear(ji,jj) * phbl(ji,jj) ) )**pthird
               zuw_bse(ji,jj) = -0.0035_wp * zomega * ( 1.0_wp - pdh(ji,jj) / phbl(ji,jj) ) * av_du_ml(ji,jj)
               zvw_bse(ji,jj) = -0.0075_wp * zomega * ( 1.0_wp - pdh(ji,jj) / phbl(ji,jj) ) * av_dv_ml(ji,jj)
            ELSE
               zomega = ( 0.15_wp * swstrl(ji,jj)**3 + swstrc(ji,jj)**3 + 4.75_wp * ( pshear(ji,jj) * phbl(ji,jj) ) )**pthird
               zuw_bse(ji,jj) = -0.0035_wp * zomega * ( 1.0_wp - pdh(ji,jj) / phbl(ji,jj) ) * av_du_ml(ji,jj)
               zvw_bse(ji,jj) = -0.0075_wp * zomega * ( 1.0_wp - pdh(ji,jj) / phbl(ji,jj) ) * av_dv_ml(ji,jj)
            ENDIF
            zb_cubic(ji,jj) = pdh(ji,jj) / phbl(ji,jj) * suw0(ji,jj) - ( 2.0_wp + pdh(ji,jj) / phml(ji,jj) ) * zuw_bse(ji,jj)
            za_cubic(ji,jj) = zuw_bse(ji,jj) - zb_cubic(ji,jj)
            zvw_max = 0.7_wp * ff_t(ji,jj) * ( sustke(ji,jj) * dstokes(ji,jj) + 0.7_wp * sustar(ji,jj) * phml(ji,jj) )
            zd_cubic(ji,jj) = zvw_max * pdh(ji,jj) / phml(ji,jj) - ( 2.0_wp + pdh(ji,jj) / phml(ji,jj) ) * zvw_bse(ji,jj)
            zc_cubic(ji,jj) = zvw_bse(ji,jj) - zd_cubic(ji,jj)
         END IF
      END_2D
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, jkf_mld, jkm_bld )   ! Need ztau_sc_u to be available. Change to array.
         IF ( l_conv(ji,jj) .AND. l_pyc(ji,jj) .AND. ( jk >= nmld(ji,jj) ) .AND. ( jk <= nbld(ji,jj) ) ) THEN
            zznd_pyc = -1.0_wp * ( gdepw(ji,jj,jk,Kmm) - phbl(ji,jj) ) / pdh(ji,jj)
            ghamu(ji,jj,jk) = ghamu(ji,jj,jk) - 0.045_wp * ( ztau_sc_u(ji,jj)**2 ) * zuw_bse(ji,jj) *                 &
               &                                ( za_cubic(ji,jj) * zznd_pyc**2 + zb_cubic(ji,jj) * zznd_pyc**3 ) *   &
               &                                ( 0.75_wp + 0.25_wp * zznd_pyc )**2 * zdbdz_pyc(ji,jj,jk)
            ghamv(ji,jj,jk) = ghamv(ji,jj,jk) - 0.045_wp * ( ztau_sc_u(ji,jj)**2 ) * zvw_bse(ji,jj) *                 &
               &                                ( zc_cubic(ji,jj) * zznd_pyc**2 + zd_cubic(ji,jj) * zznd_pyc**3 ) *   &
               &                                ( 0.75_wp + 0.25_wp * zznd_pyc )**2 * zdbdz_pyc(ji,jj,jk)
         END IF   ! l_conv .AND. l_pyc
      END_3D
      !
      IF ( ln_dia_osm ) THEN
         CALL zdf_osm_iomput( "ghamu_0",    wmask(T2D(0),:) * ghamu(T2D(0),:)  )
         CALL zdf_osm_iomput( "zsc_uw_1_0", tmask(T2D(0),1) * zsc_uw_1(T2D(0)) )
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      !
      ! Transport term in flux-gradient relationship [note : includes ROI ratio
      ! (X0.3) ]
      ! -----------------------------------------------------------------------
      WHERE ( l_conv(T2D(nn_hls-1)) )
         zsc_wth_1(:,:) = swth0(T2D(nn_hls-1)) / ( 1.0_wp - 0.56_wp * EXP( shol(T2D(nn_hls-1)) ) )
         zsc_ws_1(:,:)  = sws0(T2D(nn_hls-1))  / ( 1.0_wp - 0.56_wp * EXP( shol(T2D(nn_hls-1)) ) )
         WHERE ( l_pyc(T2D(nn_hls-1)) )   ! Pycnocline scales
            zsc_wth_pyc(:,:) = -0.003_wp * swstrc(T2D(nn_hls-1)) * ( 1.0_wp - pdh(T2D(nn_hls-1)) / phbl(T2D(nn_hls-1)) ) *   &
               &               av_dt_ml(T2D(nn_hls-1))
            zsc_ws_pyc(:,:)  = -0.003_wp * swstrc(T2D(nn_hls-1)) * ( 1.0_wp - pdh(T2D(nn_hls-1)) / phbl(T2D(nn_hls-1)) ) *   &
               &               av_ds_ml(T2D(nn_hls-1))
Guillaume Samson's avatar
Guillaume Samson committed
         END WHERE
      ELSEWHERE
         zsc_wth_1(:,:) = 2.0_wp * swthav(T2D(nn_hls-1))
         zsc_ws_1(:,:)  =          sws0(T2D(nn_hls-1))
Guillaume Samson's avatar
Guillaume Samson committed
      END WHERE
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 1, MAX( jkm_mld, jkm_bld ) )
         IF ( l_conv(ji,jj) ) THEN
            IF ( ( jk > 1 ) .AND. ( jk <= nmld(ji,jj) ) ) THEN
               zznd_ml = gdepw(ji,jj,jk,Kmm) / phml(ji,jj)
               ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + 0.3_wp * zsc_wth_1(ji,jj) *                                  &
                  &                                ( -2.0_wp + 2.75_wp * ( ( 1.0_wp + 0.6_wp * zznd_ml**4 ) -   &
                  &                                                        EXP( -6.0_wp * zznd_ml ) ) ) *       &
                  &                                ( 1.0_wp - EXP( -15.0_wp * ( 1.0_wp - zznd_ml ) ) )
               ghams(ji,jj,jk) = ghams(ji,jj,jk) + 0.3_wp * zsc_ws_1(ji,jj) *                                   &
                  &                                ( -2.0_wp + 2.75_wp * ( ( 1.0_wp + 0.6_wp * zznd_ml**4 ) -   &
                  &                                EXP( -6.0_wp * zznd_ml ) ) ) * ( 1.0_wp - EXP( -15.0_wp * ( 1.0_wp - zznd_ml ) ) )
            END IF
            !
            ! may need to comment out lpyc block
            IF ( l_pyc(ji,jj) .AND. ( jk >= nmld(ji,jj) ) .AND. ( jk <= nbld(ji,jj) ) ) THEN   ! Pycnocline
               zznd_pyc = -1.0_wp * ( gdepw(ji,jj,jk,Kmm) - phbl(ji,jj) ) / pdh(ji,jj)
               ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + 4.0_wp * zsc_wth_pyc(ji,jj) *   &
                  &                                ( 0.48_wp - EXP( -1.5_wp * ( zznd_pyc - 0.3_wp )**2 ) )
               ghams(ji,jj,jk) = ghams(ji,jj,jk) + 4.0_wp * zsc_ws_pyc(ji,jj)  *   &
                  &                                ( 0.48_wp - EXP( -1.5_wp * ( zznd_pyc - 0.3_wp )**2 ) )
            END IF
         ELSE
            IF( pdhdt(ji,jj) > 0. ) THEN
               IF ( ( jk > 1 ) .AND. ( jk <= nbld(ji,jj) ) ) THEN
                  zznd_d = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
                  znd    = gdepw(ji,jj,jk,Kmm) / phbl(ji,jj)
                  ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + 0.3_wp * ( -4.06_wp * EXP( -2.0_wp * zznd_d ) * ( 1.0_wp - EXP( -4.0_wp * zznd_d ) ) +   &
                     7.5_wp * EXP ( -10.0_wp * ( 0.95_wp - znd )**2 ) * ( 1.0_wp - znd ) ) * zsc_wth_1(ji,jj)
                  ghams(ji,jj,jk) = ghams(ji,jj,jk) + 0.3_wp * ( -4.06_wp * EXP( -2.0_wp * zznd_d ) * ( 1.0_wp - EXP( -4.0_wp * zznd_d ) ) +   &
                     7.5_wp * EXP ( -10.0_wp * ( 0.95_wp - znd )**2 ) * ( 1.0_wp - znd ) ) * zsc_ws_1(ji,jj)
               END IF
            ENDIF
         ENDIF
      END_3D
      !
      WHERE ( l_conv(T2D(nn_hls-1)) )
         zsc_uw_1(:,:) = sustar(T2D(nn_hls-1))**2
         zsc_vw_1(:,:) = ff_t(T2D(nn_hls-1)) * sustke(T2D(nn_hls-1)) * phml(T2D(nn_hls-1))
Guillaume Samson's avatar
Guillaume Samson committed
      ELSEWHERE
         zsc_uw_1(:,:) = sustar(T2D(nn_hls-1))**2
Guillaume Samson's avatar
Guillaume Samson committed
         zsc_uw_2(:,:) = ( 2.25_wp - 3.0_wp * ( 1.0_wp - EXP( -1.25_wp * 2.0_wp ) ) ) * ( 1.0_wp - EXP( -4.0_wp * 2.0_wp ) ) *   &
            &            zsc_uw_1(:,:)
         zsc_vw_1(:,:) = ff_t(T2D(nn_hls-1)) * sustke(T2D(nn_hls-1)) * phbl(T2D(nn_hls-1))
Guillaume Samson's avatar
Guillaume Samson committed
         zsc_vw_2(:,:) = -0.11_wp * SIN( 3.14159_wp * ( 2.0_wp + 0.4_wp ) ) * EXP( -1.0_wp * ( 1.5_wp + 2.0_wp )**2 ) *   &
            &            zsc_vw_1(:,:)
      ENDWHERE
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, MAX( jkm_mld, jkm_bld ) )
         IF ( l_conv(ji,jj) ) THEN
            IF ( jk <= nmld(ji,jj) ) THEN
               zznd_ml = gdepw(ji,jj,jk,Kmm) / phml(ji,jj)
               zznd_d  = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
               ghamu(ji,jj,jk) = ghamu(ji,jj,jk) +   &
                  &              0.3_wp * ( -2.0_wp + 2.5_wp * ( 1.0_wp + 0.1_wp * zznd_ml**4 ) - EXP( -8.0_wp * zznd_ml ) ) *   &
                  &              zsc_uw_1(ji,jj)
               ghamv(ji,jj,jk) = ghamv(ji,jj,jk) +   &
                  &              0.3_wp * 0.1_wp * ( EXP( -1.0_wp * zznd_d ) + EXP( -5.0_wp * ( 1.0_wp - zznd_ml ) ) ) *   &
                  &              zsc_vw_1(ji,jj)
            END IF
         ELSE
            IF ( jk <= nbld(ji,jj) ) THEN
               znd    = gdepw(ji,jj,jk,Kmm) / phbl(ji,jj)
               zznd_d = gdepw(ji,jj,jk,Kmm) / dstokes(ji,jj)
               IF ( zznd_d <= 2.0_wp ) THEN
                  ghamu(ji,jj,jk) = ghamu(ji,jj,jk) + 0.5_wp * 0.3_wp *                                              &
                     &                                ( 2.25_wp - 3.0_wp * ( 1.0_wp - EXP( -1.25_wp * zznd_d ) ) *   &
                     &                                  ( 1.0_wp - EXP( -2.0_wp * zznd_d ) ) ) * zsc_uw_1(ji,jj)
               ELSE
                  ghamu(ji,jj,jk) = ghamu(ji,jj,jk) + 0.5_wp * 0.3_wp *   &
                     &                                ( 1.0_wp - EXP( -5.0_wp * ( 1.0_wp - znd ) ) ) * zsc_uw_2(ji,jj)
               ENDIF
               ghamv(ji,jj,jk) = ghamv(ji,jj,jk) + 0.3_wp * 0.15_wp * SIN( 3.14159_wp * ( 0.65_wp * zznd_d ) ) *   &
                  &                                EXP( -0.25_wp * zznd_d**2 ) * zsc_vw_1(ji,jj)
               ghamv(ji,jj,jk) = ghamv(ji,jj,jk) + 0.3_wp * 0.15_wp * EXP( -5.0 * ( 1.0 - znd ) ) *   &
                  &                                ( 1.0 - EXP( -20.0 * ( 1.0 - znd ) ) ) * zsc_vw_2(ji,jj)
            END IF
         END IF
      END_3D
      !
      IF ( ln_dia_osm ) THEN
         CALL zdf_osm_iomput( "ghamu_f",    wmask(T2D(0),:) * ghamu(T2D(0),:)  )
         CALL zdf_osm_iomput( "ghamv_f",    wmask(T2D(0),:) * ghamv(T2D(0),:)  )
         CALL zdf_osm_iomput( "zsc_uw_1_f", tmask(T2D(0),1) * zsc_uw_1(T2D(0)) )
         CALL zdf_osm_iomput( "zsc_vw_1_f", tmask(T2D(0),1) * zsc_vw_1(T2D(0)) )
         CALL zdf_osm_iomput( "zsc_uw_2_f", tmask(T2D(0),1) * zsc_uw_2(T2D(0)) )
         CALL zdf_osm_iomput( "zsc_vw_2_f", tmask(T2D(0),1) * zsc_vw_2(T2D(0)) )
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      !
      ! Make surface forced velocity non-gradient terms go to zero at the base
      ! of the mixed layer.
      !
      ! Make surface forced velocity non-gradient terms go to zero at the base
      ! of the boundary layer.
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, jkm_bld )
         IF ( ( .NOT. l_conv(ji,jj) ) .AND. ( jk <= nbld(ji,jj) ) ) THEN
            znd = -1.0_wp * ( gdepw(ji,jj,jk,Kmm) - phbl(ji,jj) ) / phbl(ji,jj)   ! ALMG to think about
            IF ( znd >= 0.0_wp ) THEN
               ghamu(ji,jj,jk) = ghamu(ji,jj,jk) * ( 1.0_wp - EXP( -10.0_wp * znd**2 ) )
               ghamv(ji,jj,jk) = ghamv(ji,jj,jk) * ( 1.0_wp - EXP( -10.0_wp * znd**2 ) )
            ELSE
               ghamu(ji,jj,jk) = 0.0_wp
               ghamv(ji,jj,jk) = 0.0_wp
            ENDIF
         END IF
      END_3D
      !
      ! Pynocline contributions
      !
      IF ( ln_dia_pyc_scl .OR. ln_dia_pyc_shr ) THEN   ! Allocate arrays for output of pycnocline gradient/shear profiles
         ALLOCATE( z3ddz_pyc_1(T2D(nn_hls),jpk), z3ddz_pyc_2(T2D(nn_hls),jpk), STAT=istat )
Guillaume Samson's avatar
Guillaume Samson committed
         IF ( istat /= 0 ) CALL ctl_stop( 'zdf_osm: failed to allocate temporary arrays' )
         z3ddz_pyc_1(:,:,:) = 0.0_wp
         z3ddz_pyc_2(:,:,:) = 0.0_wp
      END IF
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, jkm_bld )
         IF ( l_conv (ji,jj) ) THEN
            ! Unstable conditions. Shouldn;t be needed with no pycnocline code.
            !                  zugrad = 0.7 * av_du_ml(ji,jj) / zdh(ji,jj) + 0.3 * zustar(ji,jj)*zustar(ji,jj) / &
            !                       &      ( ( ( zvstr(ji,jj)**3 + 0.5 * zwstrc(ji,jj)**3 )**pthird * zhml(ji,jj) ) * &
            !                      &      MIN(zla(ji,jj)**(8.0/3.0) + epsln, 0.12 ))
            !Alan is this right?
            !                  zvgrad = ( 0.7 * av_dv_ml(ji,jj) + &
            !                       &    2.0 * ff_t(ji,jj) * zustke(ji,jj) * dstokes(ji,jj) / &
            !                       &          ( ( zvstr(ji,jj)**3 + 0.5 * zwstrc(ji,jj)**3 )**pthird  + epsln ) &
            !                       &      )/ (zdh(ji,jj)  + epsln )
            !                  DO jk = 2, nbld(ji,jj) - 1 + ibld_ext
            !                     znd = -( gdepw(ji,jj,jk,Kmm) - zhbl(ji,jj) ) / (zdh(ji,jj) + epsln ) - zzeta_v
            !                     IF ( znd <= 0.0 ) THEN
            !                        zdudz(ji,jj,jk) = 1.25 * zugrad * EXP( 3.0 * znd )
            !                        zdvdz(ji,jj,jk) = 1.25 * zvgrad * EXP( 3.0 * znd )
            !                     ELSE
            !                        zdudz(ji,jj,jk) = 1.25 * zugrad * EXP( -2.0 * znd )
            !                        zdvdz(ji,jj,jk) = 1.25 * zvgrad * EXP( -2.0 * znd )
            !                     ENDIF
            !                  END DO
         ELSE   ! Stable conditions
            IF ( nbld(ji,jj) + kp_ext(ji,jj) < mbkt(ji,jj) ) THEN
               ! Pycnocline profile only defined when depth steady of increasing.
               IF ( pdhdt(ji,jj) > 0.0_wp ) THEN   ! Depth increasing, or steady.
                  IF ( av_db_bl(ji,jj) > 0.0_wp ) THEN
                     IF ( shol(ji,jj) >= 0.5_wp ) THEN   ! Very stable - 'thick' pycnocline
                        ztmp = 1.0_wp / MAX( phbl(ji,jj), epsln )
                        ztgrad = av_dt_bl(ji,jj) * ztmp
                        zsgrad = av_ds_bl(ji,jj) * ztmp
                        zbgrad = av_db_bl(ji,jj) * ztmp
                        IF ( jk <= nbld(ji,jj) ) THEN
                           znd = gdepw(ji,jj,jk,Kmm) * ztmp
                           zdtdz_pyc =  ztgrad * EXP( -15.0_wp * ( znd - 0.9_wp )**2 )
                           zdsdz_pyc =  zsgrad * EXP( -15.0_wp * ( znd - 0.9_wp )**2 )
                           ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + pdiffut(ji,jj,jk) * zdtdz_pyc
                           ghams(ji,jj,jk) = ghams(ji,jj,jk) + pdiffut(ji,jj,jk) * zdsdz_pyc
                           IF ( ln_dia_pyc_scl ) THEN
                              z3ddz_pyc_1(ji,jj,jk) = zdtdz_pyc
                              z3ddz_pyc_2(ji,jj,jk) = zdsdz_pyc
                           END IF
                        END IF
                     ELSE   ! Slightly stable - 'thin' pycnoline - needed when stable layer begins to form.
                        ztmp = 1.0_wp / MAX( pdh(ji,jj), epsln )
                        ztgrad = av_dt_bl(ji,jj) * ztmp
                        zsgrad = av_ds_bl(ji,jj) * ztmp
                        zbgrad = av_db_bl(ji,jj) * ztmp
                        IF ( jk <= nbld(ji,jj) ) THEN
                           znd = -1.0_wp * ( gdepw(ji,jj,jk,Kmm) - phml(ji,jj) ) * ztmp
                           zdtdz_pyc =  ztgrad * EXP( -1.75_wp * ( znd + 0.75_wp )**2 )
                           zdsdz_pyc =  zsgrad * EXP( -1.75_wp * ( znd + 0.75_wp )**2 )
                           ghamt(ji,jj,jk) = ghamt(ji,jj,jk) + pdiffut(ji,jj,jk) * zdtdz_pyc
                           ghams(ji,jj,jk) = ghams(ji,jj,jk) + pdiffut(ji,jj,jk) * zdsdz_pyc
                           IF ( ln_dia_pyc_scl ) THEN
                              z3ddz_pyc_1(ji,jj,jk) = zdtdz_pyc
                              z3ddz_pyc_2(ji,jj,jk) = zdsdz_pyc
                           END IF
                        END IF
                     ENDIF   ! IF (shol >=0.5)
                  ENDIF      ! IF (av_db_bl> 0.)
               ENDIF         ! IF (zdhdt >= 0) zdhdt < 0 not considered since pycnocline profile is zero and profile arrays are
               !             !    intialized to zero
            END IF
         END IF
      END_3D
      IF ( ln_dia_pyc_scl ) THEN   ! Output of pycnocline gradient profiles
         CALL zdf_osm_iomput( "zdtdz_pyc", wmask(T2D(0),:) * z3ddz_pyc_1(T2D(0),:) )
         CALL zdf_osm_iomput( "zdsdz_pyc", wmask(T2D(0),:) * z3ddz_pyc_2(T2D(0),:) )
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 2, jkm_bld )
         IF ( .NOT. l_conv (ji,jj) ) THEN
            IF ( nbld(ji,jj) + kp_ext(ji,jj) < mbkt(ji,jj) ) THEN
               zugrad = 3.25_wp * av_du_bl(ji,jj) / phbl(ji,jj)
               zvgrad = 2.75_wp * av_dv_bl(ji,jj) / phbl(ji,jj)
               IF ( jk <= nbld(ji,jj) ) THEN
                  znd = gdepw(ji,jj,jk,Kmm) / phbl(ji,jj)
                  IF ( znd < 1.0 ) THEN
                     zdudz_pyc = zugrad * EXP( -40.0_wp * ( znd - 1.0_wp )**2 )
                  ELSE
                     zdudz_pyc = zugrad * EXP( -20.0_wp * ( znd - 1.0_wp )**2 )
                  ENDIF
                  zdvdz_pyc = zvgrad * EXP( -20.0_wp * ( znd - 0.85_wp )**2 )
                  ghamu(ji,jj,jk) = ghamu(ji,jj,jk) + pviscos(ji,jj,jk) * zdudz_pyc
                  ghamv(ji,jj,jk) = ghamv(ji,jj,jk) + pviscos(ji,jj,jk) * zdvdz_pyc
                  IF ( ln_dia_pyc_shr ) THEN
                     z3ddz_pyc_1(ji,jj,jk) = zdudz_pyc
                     z3ddz_pyc_2(ji,jj,jk) = zdvdz_pyc
                  END IF
               END IF
            END IF
         END IF
      END_3D
      IF ( ln_dia_pyc_shr ) THEN   ! Output of pycnocline shear profiles
         CALL zdf_osm_iomput( "zdudz_pyc", wmask(T2D(0),:) * z3ddz_pyc_1(T2D(0),:) )
         CALL zdf_osm_iomput( "zdvdz_pyc", wmask(T2D(0),:) * z3ddz_pyc_2(T2D(0),:) )
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      IF ( ln_dia_osm ) THEN
         CALL zdf_osm_iomput( "ghamu_b", wmask(T2D(0),:) * ghamu(T2D(0),:) )
         CALL zdf_osm_iomput( "ghamv_b", wmask(T2D(0),:) * ghamv(T2D(0),:) )
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      IF ( ln_dia_pyc_scl .OR. ln_dia_pyc_shr ) THEN   ! Deallocate arrays used for output of pycnocline gradient/shear profiles
         DEALLOCATE( z3ddz_pyc_1, z3ddz_pyc_2 )
      END IF
      !
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         ghamt(ji,jj,nbld(ji,jj)) = 0.0_wp
         ghams(ji,jj,nbld(ji,jj)) = 0.0_wp
         ghamu(ji,jj,nbld(ji,jj)) = 0.0_wp
         ghamv(ji,jj,nbld(ji,jj)) = 0.0_wp
      END_2D
      !
      IF ( ln_dia_osm ) THEN
         CALL zdf_osm_iomput( "ghamu_1", wmask(T2D(0),:) * ghamu(T2D(0),:)   )
         CALL zdf_osm_iomput( "ghamv_1", wmask(T2D(0),:) * ghamv(T2D(0),:)   )
         CALL zdf_osm_iomput( "zviscos", wmask(T2D(0),:) * pviscos(T2D(0),:) )
Guillaume Samson's avatar
Guillaume Samson committed
      END IF
      !
   END SUBROUTINE zdf_osm_fgr_terms

   SUBROUTINE zdf_osm_zmld_horizontal_gradients( Kmm, pmld, pdtdx, pdtdy, pdsdx,   &
      &                                          pdsdy, pdbds_mle )
      !!----------------------------------------------------------------------
      !!          ***  ROUTINE zdf_osm_zmld_horizontal_gradients  ***
      !!
      !! ** Purpose : Calculates horizontal gradients of buoyancy for use with
      !!              Fox-Kemper parametrization
      !!
      !! ** Method  :
      !!
      !! References: Fox-Kemper et al., JPO, 38, 1145-1165, 2008
      !!             Fox-Kemper and Ferrari, JPO, 38, 1166-1179, 2008
      !!
      !!----------------------------------------------------------------------
      INTEGER,                            INTENT(in   ) ::   Kmm          ! Time-level index
      REAL(wp), DIMENSION(T2D(nn_hls)),   INTENT(  out) ::   pmld         ! == Estimated FK BLD used for MLE horizontal gradients == !
      REAL(wp), DIMENSION(T2D(nn_hls)),   INTENT(inout) ::   pdtdx        ! Horizontal gradient for Fox-Kemper parametrization
      REAL(wp), DIMENSION(T2D(nn_hls)),   INTENT(inout) ::   pdtdy        ! Horizontal gradient for Fox-Kemper parametrization
      REAL(wp), DIMENSION(T2D(nn_hls)),   INTENT(inout) ::   pdsdx        ! Horizontal gradient for Fox-Kemper parametrization
      REAL(wp), DIMENSION(T2D(nn_hls)),   INTENT(inout) ::   pdsdy        ! Horizontal gradient for Fox-Kemper parametrization
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(inout) ::   pdbds_mle    ! Magnitude of horizontal buoyancy gradient
Guillaume Samson's avatar
Guillaume Samson committed
      !!
      INTEGER                               ::   ji, jj, jk   ! Dummy loop indices
      INTEGER,  DIMENSION(T2D(nn_hls))      ::   jk_mld_prof  ! Base level of MLE layer
Guillaume Samson's avatar
Guillaume Samson committed
      INTEGER                               ::   ikt, ikmax   ! Local integers      
      REAL(wp)                              ::   zc
      REAL(wp)                              ::   zN2_c        ! Local buoyancy difference from 10m value
      REAL(wp), DIMENSION(T2D(nn_hls))      ::   ztm
      REAL(wp), DIMENSION(T2D(nn_hls))      ::   zsm
      REAL(wp), DIMENSION(T2D(nn_hls),jpts) ::   ztsm_midu
      REAL(wp), DIMENSION(T2D(nn_hls),jpts) ::   ztsm_midv
      REAL(wp), DIMENSION(T2D(nn_hls),jpts) ::   zabu
      REAL(wp), DIMENSION(T2D(nn_hls),jpts) ::   zabv
      REAL(wp), DIMENSION(T2D(nn_hls))      ::   zmld_midu
      REAL(wp), DIMENSION(T2D(nn_hls))      ::   zmld_midv
Guillaume Samson's avatar
Guillaume Samson committed
      !!----------------------------------------------------------------------
      !
      ! ==  MLD used for MLE  ==!
      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
         jk_mld_prof(ji,jj) = nlb10    ! Initialization to the number of w ocean point
         pmld(ji,jj)        = 0.0_wp   ! Here hmlp used as a dummy variable, integrating vertically N^2
      END_2D
      zN2_c = grav * rn_osm_mle_rho_c * r1_rho0   ! Convert density criteria into N^2 criteria
      DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, nlb10, jpkm1 )
         ikt = mbkt(ji,jj)
         pmld(ji,jj) = pmld(ji,jj) + MAX( rn2b(ji,jj,jk), 0.0_wp ) * e3w(ji,jj,jk,Kmm)
         IF( pmld(ji,jj) < zN2_c ) jk_mld_prof(ji,jj) = MIN( jk , ikt ) + 1   ! Mixed layer level
      END_3D
      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
         jk_mld_prof(ji,jj) = MAX( jk_mld_prof(ji,jj), nbld(ji,jj) )   ! Ensure jk_mld_prof .ge. nbld
         pmld(ji,jj)     = gdepw(ji,jj,jk_mld_prof(ji,jj),Kmm)
      END_2D
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         mld_prof(ji,jj) = jk_mld_prof(ji,jj)
      END_2D
      !
      ikmax = MIN( MAXVAL( jk_mld_prof(T2D(nn_hls)) ), jpkm1 )   ! Max level of the computation
Guillaume Samson's avatar
Guillaume Samson committed
      ztm(:,:) = 0.0_wp
      zsm(:,:) = 0.0_wp
      DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, ikmax )
         zc = e3t(ji,jj,jk,Kmm) * REAL( MIN( MAX( 0, jk_mld_prof(ji,jj) - jk ), 1  ), KIND=wp )   ! zc being 0 outside the ML
         !                                                                                        !    t-points
         ztm(ji,jj) = ztm(ji,jj) + zc * ts(ji,jj,jk,jp_tem,Kmm)
         zsm(ji,jj) = zsm(ji,jj) + zc * ts(ji,jj,jk,jp_sal,Kmm)
      END_3D
      ! Average temperature and salinity
      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
         ztm(ji,jj) = ztm(ji,jj) / MAX( e3t(ji,jj,1,Kmm), pmld(ji,jj) )
         zsm(ji,jj) = zsm(ji,jj) / MAX( e3t(ji,jj,1,Kmm), pmld(ji,jj) )
      END_2D
      ! Calculate horizontal gradients at u & v points
      zmld_midu(:,:)   =  0.0_wp
      ztsm_midu(:,:,:) = 10.0_wp
      DO_2D( nn_hls, nn_hls-1, nn_hls-1, nn_hls-1 )
         pdtdx(ji,jj)            = ( ztm(ji+1,jj) - ztm(ji,jj) )  * umask(ji,jj,1) / e1u(ji,jj)
         pdsdx(ji,jj)            = ( zsm(ji+1,jj) - zsm(ji,jj) )  * umask(ji,jj,1) / e1u(ji,jj)
         zmld_midu(ji,jj)        = 0.25_wp * ( pmld(ji+1,jj) + pmld(ji,jj))
         ztsm_midu(ji,jj,jp_tem) =  0.5_wp * ( ztm( ji+1,jj)  + ztm( ji,jj) )
         ztsm_midu(ji,jj,jp_sal) =  0.5_wp * ( zsm( ji+1,jj)  + zsm( ji,jj) )
      END_2D
      zmld_midv(:,:)   =  0.0_wp
      ztsm_midv(:,:,:) = 10.0_wp
      DO_2D( nn_hls-1, nn_hls-1, nn_hls, nn_hls-1 )
         pdtdy(ji,jj)            = ( ztm(ji,jj+1) - ztm(ji,jj) ) * vmask(ji,jj,1) / e1v(ji,jj)
         pdsdy(ji,jj)            = ( zsm(ji,jj+1) - zsm(ji,jj) ) * vmask(ji,jj,1) / e1v(ji,jj)
         zmld_midv(ji,jj)        = 0.25_wp * ( pmld(ji,jj+1) + pmld( ji,jj) )
         ztsm_midv(ji,jj,jp_tem) =  0.5_wp * ( ztm( ji,jj+1)  + ztm( ji,jj) )
         ztsm_midv(ji,jj,jp_sal) =  0.5_wp * ( zsm( ji,jj+1)  + zsm( ji,jj) )
      END_2D
      CALL eos_rab( ztsm_midu, zmld_midu, zabu, Kmm )
      CALL eos_rab( ztsm_midv, zmld_midv, zabv, Kmm )
      DO_2D_OVR( nn_hls, nn_hls-1, nn_hls-1, nn_hls-1 )
         dbdx_mle(ji,jj) = grav * ( pdtdx(ji,jj) * zabu(ji,jj,jp_tem) - pdsdx(ji,jj) * zabu(ji,jj,jp_sal) )
      END_2D
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls, nn_hls-1 )
         dbdy_mle(ji,jj) = grav * ( pdtdy(ji,jj) * zabv(ji,jj,jp_tem) - pdsdy(ji,jj) * zabv(ji,jj,jp_sal) )
      END_2D
      DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         pdbds_mle(ji,jj) = SQRT( 0.5_wp * ( dbdx_mle(ji,  jj) * dbdx_mle(ji,  jj) + dbdy_mle(ji,jj  ) * dbdy_mle(ji,jj  ) +   &
            &                                dbdx_mle(ji-1,jj) * dbdx_mle(ji-1,jj) + dbdy_mle(ji,jj-1) * dbdy_mle(ji,jj-1) ) )
      END_2D
      !
   END SUBROUTINE zdf_osm_zmld_horizontal_gradients

   SUBROUTINE zdf_osm_osbl_state_fk( Kmm, pwb_fk, phbl, phmle, pwb_ent,   &
      &                              pdbds_mle )
      !!---------------------------------------------------------------------
      !!               ***  ROUTINE zdf_osm_osbl_state_fk  ***
      !!
      !! ** Purpose : Determines the state of the OSBL and MLE layer. Info is
      !!              returned in the logicals l_pyc, l_flux and ldmle. Used
      !!              with Fox-Kemper scheme.
      !!                l_pyc  :: determines whether pycnocline flux-grad
      !!                          relationship needs to be determined
      !!                l_flux :: determines whether effects of surface flux
      !!                          extend below the base of the OSBL
      !!                ldmle  :: determines whether the layer with MLE is
      !!                          increasing with time or if base is relaxing
      !!                          towards hbl
      !!
      !! ** Method  :
      !!
      !!----------------------------------------------------------------------      
      INTEGER,                            INTENT(in   ) ::   Kmm         ! Time-level index
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(inout) ::   pwb_fk
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(in   ) ::   phbl        ! BL depth
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(in   ) ::   phmle       ! MLE depth
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(in   ) ::   pwb_ent     ! Buoyancy entrainment flux
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(in   ) ::   pdbds_mle   ! Magnitude of horizontal buoyancy gradient
Guillaume Samson's avatar
Guillaume Samson committed
      !!
      INTEGER                            ::   ji, jj, jk        ! Dummy loop indices
      REAL(wp), DIMENSION(T2D(nn_hls-1)) ::   znd_param
Guillaume Samson's avatar
Guillaume Samson committed
      REAL(wp)                           ::   zthermal, zbeta
      REAL(wp)                           ::   zbuoy
      REAL(wp)                           ::   ztmp
      REAL(wp)                           ::   zpe_mle_layer
      REAL(wp)                           ::   zpe_mle_ref
      REAL(wp)                           ::   zdbdz_mle_int
      !!----------------------------------------------------------------------      
      !
      znd_param(:,:) = 0.0_wp
      !
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         ztmp =  r1_ft(ji,jj) *  MIN( 111.e3_wp , e1u(ji,jj) ) / rn_osm_mle_lf
         pwb_fk(ji,jj) = rn_osm_mle_ce * hmle(ji,jj) * hmle(ji,jj) * ztmp * pdbds_mle(ji,jj) * pdbds_mle(ji,jj)
      END_2D
      !
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         !
         IF ( l_conv(ji,jj) ) THEN
            IF ( phmle(ji,jj) > 1.2_wp * phbl(ji,jj) ) THEN
               av_t_mle(ji,jj) = ( av_t_mle(ji,jj) * phmle(ji,jj) - av_t_bl(ji,jj) * phbl(ji,jj) ) / ( phmle(ji,jj) - phbl(ji,jj) )
               av_s_mle(ji,jj) = ( av_s_mle(ji,jj) * phmle(ji,jj) - av_s_bl(ji,jj) * phbl(ji,jj) ) / ( phmle(ji,jj) - phbl(ji,jj) )
               av_b_mle(ji,jj) = ( av_b_mle(ji,jj) * phmle(ji,jj) - av_b_bl(ji,jj) * phbl(ji,jj) ) / ( phmle(ji,jj) - phbl(ji,jj) )
               zdbdz_mle_int = ( av_b_bl(ji,jj) - ( 2.0_wp * av_b_mle(ji,jj) - av_b_bl(ji,jj) ) ) / ( phmle(ji,jj) - phbl(ji,jj) )
               ! Calculate potential energies of actual profile and reference profile
               zpe_mle_layer = 0.0_wp
               zpe_mle_ref   = 0.0_wp
               zthermal = rab_n(ji,jj,1,jp_tem)
               zbeta    = rab_n(ji,jj,1,jp_sal)
               DO jk = nbld(ji,jj), mld_prof(ji,jj)
                  zbuoy         = grav * ( zthermal * ts(ji,jj,jk,jp_tem,Kmm) - zbeta * ts(ji,jj,jk,jp_sal,Kmm) )
                  zpe_mle_layer = zpe_mle_layer + zbuoy * gdepw(ji,jj,jk,Kmm) * e3w(ji,jj,jk,Kmm)
                  zpe_mle_ref   = zpe_mle_ref   + ( av_b_bl(ji,jj) - zdbdz_mle_int * ( gdepw(ji,jj,jk,Kmm) - phbl(ji,jj) ) ) *   &
                     &                            gdepw(ji,jj,jk,Kmm) * e3w(ji,jj,jk,Kmm)
               END DO
               ! Non-dimensional parameter to diagnose the presence of thermocline
               znd_param(ji,jj) = ( zpe_mle_layer - zpe_mle_ref ) * ABS( ff_t(ji,jj) ) /   &
                  &               ( MAX( pwb_fk(ji,jj), 1e-10 ) * phmle(ji,jj) )
            END IF
         END IF
         !
      END_2D
      !
      ! Diagnosis
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         !
         IF ( l_conv(ji,jj) ) THEN
            IF ( -2.0_wp * pwb_fk(ji,jj) / pwb_ent(ji,jj) > 0.5_wp ) THEN
               IF ( phmle(ji,jj) > 1.2_wp * phbl(ji,jj) ) THEN   ! MLE layer growing
                  IF ( znd_param (ji,jj) > 100.0_wp ) THEN   ! Thermocline present
                     l_flux(ji,jj) = .FALSE.
                     l_mle(ji,jj)  = .FALSE.
                  ELSE   ! Thermocline not present
                     l_flux(ji,jj) = .TRUE.
                     l_mle(ji,jj)  = .TRUE.
                  ENDIF  ! znd_param > 100
                  !
                  IF ( av_db_bl(ji,jj) < rn_osm_bl_thresh ) THEN
                     l_pyc(ji,jj) = .FALSE.
                  ELSE
                     l_pyc(ji,jj) = .TRUE.
                  ENDIF
               ELSE   ! MLE layer restricted to OSBL or just below
                  IF ( av_db_bl(ji,jj) < rn_osm_bl_thresh ) THEN   ! Weak stratification MLE layer can grow
                     l_pyc(ji,jj)  = .FALSE.
                     l_flux(ji,jj) = .TRUE.
                     l_mle(ji,jj)  = .TRUE.
                  ELSE   ! Strong stratification
                     l_pyc(ji,jj)  = .TRUE.
                     l_flux(ji,jj) = .FALSE.
                     l_mle(ji,jj)  = .FALSE.
                  END IF   ! av_db_bl < rn_mle_thresh_bl and
               END IF   ! phmle > 1.2 phbl
            ELSE
               l_pyc(ji,jj)  = .TRUE.
               l_flux(ji,jj) = .FALSE.
               l_mle(ji,jj)  = .FALSE.
               IF ( av_db_bl(ji,jj) < rn_osm_bl_thresh ) l_pyc(ji,jj) = .FALSE.
            END IF   !  -2.0 * pwb_fk(ji,jj) / pwb_ent > 0.5
         ELSE   ! Stable Boundary Layer
            l_pyc(ji,jj)  = .FALSE.
            l_flux(ji,jj) = .FALSE.
            l_mle(ji,jj)  = .FALSE.
         END IF   ! l_conv
         !
      END_2D
      !
   END SUBROUTINE zdf_osm_osbl_state_fk

   SUBROUTINE zdf_osm_mle_parameters( Kmm, pmld, phmle, pvel_mle, pdiff_mle,   &
      &                               pdbds_mle, phbl, pwb0tot )
      !!----------------------------------------------------------------------
      !!               ***  ROUTINE zdf_osm_mle_parameters  ***
      !!
      !! ** Purpose : Timesteps the mixed layer eddy depth, hmle and calculates
      !!              the mixed layer eddy fluxes for buoyancy, heat and
      !!              salinity.
      !!
      !! ** Method  :
      !!
      !! References: Fox-Kemper et al., JPO, 38, 1145-1165, 2008
      !!             Fox-Kemper and Ferrari, JPO, 38, 1166-1179, 2008
      !!
      !!----------------------------------------------------------------------
      INTEGER,                            INTENT(in   ) ::   Kmm         ! Time-level index
      REAL(wp), DIMENSION(T2D(nn_hls)),   INTENT(in   ) ::   pmld        ! == Estimated FK BLD used for MLE horiz gradients == !
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(inout) ::   phmle       ! MLE depth
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(inout) ::   pvel_mle    ! Velocity scale for dhdt with stable ML and FK
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(inout) ::   pdiff_mle   ! Extra MLE vertical diff
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(in   ) ::   pdbds_mle   ! Magnitude of horizontal buoyancy gradient
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(in   ) ::   phbl        ! BL depth
      REAL(wp), DIMENSION(T2D(nn_hls-1)), INTENT(in   ) ::   pwb0tot     ! Total surface buoyancy flux including insolation
Guillaume Samson's avatar
Guillaume Samson committed
      !!
      INTEGER  ::   ji, jj, jk   ! Dummy loop indices
      REAL(wp) ::   ztmp
      REAL(wp) ::   zdbdz
      REAL(wp) ::   zdtdz
      REAL(wp) ::   zdsdz
      REAL(wp) ::   zthermal
      REAL(wp) ::   zbeta
      REAL(wp) ::   zbuoy
      REAL(wp) ::   zdb_mle
      !!----------------------------------------------------------------------
      !
      ! Calculate vertical buoyancy, heat and salinity fluxes due to MLE
      ! BUG: [zdfosm_avt_diag] lbc_lnk changes the value of avt on the northfold (see zdfphy.F90 comment). It seems to stem from here- if ztmp is converted to an array, calling lbc_lnk on this array has the same effect as calling lbc_lnk on avt. I think it could be related to l_conv.
Guillaume Samson's avatar
Guillaume Samson committed
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         IF ( l_conv(ji,jj) ) THEN
            ztmp =  r1_ft(ji,jj) * MIN( 111e3_wp, e1u(ji,jj) ) / rn_osm_mle_lf
            ! This velocity scale, defined in Fox-Kemper et al (2008), is needed for calculating dhdt
            pvel_mle(ji,jj)  = pdbds_mle(ji,jj) * ztmp * hmle(ji,jj) * tmask(ji,jj,1)
            pdiff_mle(ji,jj) = 5e-4_wp * rn_osm_mle_ce * ztmp * pdbds_mle(ji,jj) * phmle(ji,jj)**2
         END IF
      END_2D
      ! Timestep mixed layer eddy depth
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         IF ( l_mle(ji,jj) ) THEN   ! MLE layer growing
            ! Buoyancy gradient at base of MLE layer
            zthermal = rab_n(ji,jj,1,jp_tem)
            zbeta    = rab_n(ji,jj,1,jp_sal)
            zbuoy = grav * ( zthermal * ts(ji,jj,mld_prof(ji,jj)+2,jp_tem,Kmm) -   &
               &             zbeta    * ts(ji,jj,mld_prof(ji,jj)+2,jp_sal,Kmm) )
            zdb_mle = av_b_bl(ji,jj) - zbuoy
            ! Timestep hmle
            hmle(ji,jj) = hmle(ji,jj) + pwb0tot(ji,jj) * rn_Dt / zdb_mle
         ELSE
            IF ( phmle(ji,jj) > phbl(ji,jj) ) THEN
               hmle(ji,jj) = hmle(ji,jj) - ( hmle(ji,jj) - hbl(ji,jj) ) * rn_Dt / rn_osm_mle_tau
            ELSE
               hmle(ji,jj) = hmle(ji,jj) - 10.0_wp * ( hmle(ji,jj) - hbl(ji,jj) ) * rn_Dt / rn_osm_mle_tau
            END IF
         END IF
         hmle(ji,jj) = MAX( MIN( hmle(ji,jj), ht(ji,jj,Kmm) ), gdepw(ji,jj,4,Kmm) )
Guillaume Samson's avatar
Guillaume Samson committed
         IF ( ln_osm_hmle_limit ) hmle(ji,jj) = MIN( hmle(ji,jj), rn_osm_hmle_limit*hbl(ji,jj) )
         hmle(ji,jj) = pmld(ji,jj)   ! For now try just set hmle to pmld
      END_2D
      !
      DO_3D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1, 5, jpkm1 )
         IF ( hmle(ji,jj) >= gdepw(ji,jj,jk,Kmm) ) mld_prof(ji,jj) = MIN( mbkt(ji,jj), jk )
      END_3D
      DO_2D_OVR( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )
         phmle(ji,jj) = gdepw(ji,jj,mld_prof(ji,jj),Kmm)
      END_2D
      !
   END SUBROUTINE zdf_osm_mle_parameters

   SUBROUTINE zdf_osm_init( Kmm )
      !!----------------------------------------------------------------------
      !!                  ***  ROUTINE zdf_osm_init  ***
      !!
      !! ** Purpose :   Initialization of the vertical eddy diffivity and
      !!      viscosity when using a osm turbulent closure scheme
      !!
      !! ** Method  :   Read the namosm namelist and check the parameters
      !!      called at the first timestep (nit000)
      !!
      !! ** input   :   Namlists namzdf_osm and namosm_mle
      !!