Newer
Older

WAUTELET Philippe
committed
!MNH_LIC Copyright 1997-2022 CNRS, Meteo-France and Universite Paul Sabatier
!MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence

WAUTELET Philippe
committed
!MNH_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
!MNH_LIC for details. version 1.
!-----------------------------------------------------------------
! ################
MODULE MODI_BL89
! ################
INTERFACE
SUBROUTINE BL89(KKA,KKU,KKL,PZZ,PDZZ,PTHVREF,PTHLM,KRR,PRM,PTKEM,PSHEAR,PLM)
!
INTEGER, INTENT(IN) :: KKA
INTEGER, INTENT(IN) :: KKU
INTEGER, INTENT(IN) :: KKL
REAL, DIMENSION(:,:,:), INTENT(IN) :: PZZ
REAL, DIMENSION(:,:,:), INTENT(IN) :: PDZZ
REAL, DIMENSION(:,:,:), INTENT(IN) :: PTHVREF
REAL, DIMENSION(:,:,:), INTENT(IN) :: PTHLM
INTEGER, INTENT(IN) :: KRR
REAL, DIMENSION(:,:,:,:), INTENT(IN) :: PRM
REAL, DIMENSION(:,:,:), INTENT(IN) :: PTKEM
REAL, DIMENSION(:,:,:), INTENT(IN) :: PSHEAR
REAL, DIMENSION(:,:,:), INTENT(OUT) :: PLM
END SUBROUTINE BL89
END INTERFACE
END MODULE MODI_BL89
!
! #########################################################
SUBROUTINE BL89(KKA,KKU,KKL,PZZ,PDZZ,PTHVREF,PTHLM,KRR,PRM,PTKEM,PSHEAR,PLM)
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
! #########################################################
!
!!**** *BL89* -
!!
!! PURPOSE
!! -------
!! This routine computes the mixing length from Bougeault-Lacarrere 89
!! formula.
!!
!!** METHOD
!! ------
!!
!! EXTERNAL
!! --------
!!
!! IMPLICIT ARGUMENTS
!! ------------------
!!
!!
!! REFERENCE
!! ---------
!!
!! Book 2
!!
!! AUTHOR
!! ------
!!
!! J. Cuxart INM and Meteo-France
!!
!! MODIFICATIONS
!! -------------
!! Original 27/04/97 (V. Masson) separation from turb.f90
!! and optimization
!! 06/01/98 (V. Masson and P. Jabouille) optimization
!! 15/03/99 (V. Masson) new lup ldown averaging
!! 21/02/01 (P. Jabouille) improve vectorization
!! 2012-02 (Y. Seity) add possibility to run with
!! reversed vertical levels
!! Philippe 13/02/2018: use ifdef MNH_REAL to prevent problems with intrinsics on Blue Gene/Q

RODIER Quentin
committed
!! 01/2019 (Q. Rodier) support for RM17 mixing length

RODIER Quentin
committed
!! 03/2021 (JL Redelsperger) Ocean model case

RODIER Quentin
committed
!! 06/2021 (P. Marquet) correction of exponent on final length according to Lemarié et al. 2021
!-------------------------------------------------------------------------------
!
!* 0. DECLARATIONS
! ------------
!

WAUTELET Philippe
committed
USE MODD_CONF, ONLY: CPROGRAM

WAUTELET Philippe
committed
USE MODD_DYN_n, ONLY: LOCEAN
use modd_precision, only: MNHREAL

WAUTELET Philippe
committed
#ifdef MNH_OPENACC
USE MODE_MNH_ZWORK, ONLY: MNH_MEM_GET, MNH_MEM_POSITION_PIN, MNH_MEM_RELEASE
#endif

WAUTELET Philippe
committed
#ifdef MNH_BITREP
USE MODI_BITREP
#endif
!
!
IMPLICIT NONE
!
!* 0.1 Declaration of arguments
! ------------------------
!
INTEGER, INTENT(IN) :: KKA !near ground array index
INTEGER, INTENT(IN) :: KKU !uppest atmosphere array index
INTEGER, INTENT(IN) :: KKL !vert. levels type 1=MNH -1=ARO
REAL, DIMENSION(:,:,:), INTENT(IN) :: PZZ
REAL, DIMENSION(:,:,:), INTENT(IN) :: PDZZ
REAL, DIMENSION(:,:,:), INTENT(IN) :: PTHVREF
REAL, DIMENSION(:,:,:), INTENT(IN) :: PTHLM ! conservative pot. temp.
INTEGER, INTENT(IN) :: KRR
REAL, DIMENSION(:,:,:,:), INTENT(IN) :: PRM ! water var.
REAL, DIMENSION(:,:,:), INTENT(IN) :: PTKEM ! TKE
REAL, DIMENSION(:,:,:), INTENT(IN) :: PSHEAR
REAL, DIMENSION(:,:,:), INTENT(OUT) :: PLM ! Mixing length
! thermodynamical variables PTHLM=Theta at the begining
!
!* 0.2 Declaration of local variables
! ------------------------------
!
INTEGER :: IKB,IKE
INTEGER :: IKT ! array size in k direction
INTEGER :: IKTB,IKTE ! start, end of k loops in physical domain

WAUTELET Philippe
committed
#ifndef MNH_OPENACC

WAUTELET Philippe
committed
real, dimension(:,:), allocatable :: ZVPT ! Virtual Potential Temp at half levels
real, dimension(:,:), allocatable :: ZDELTVPT
! Increment of Virtual Potential Temp between two following levels

WAUTELET Philippe
committed
real, dimension(:,:), allocatable :: ZHLVPT
! Virtual Potential Temp at half levels

WAUTELET Philippe
committed
real, dimension(:), allocatable :: ZLWORK,ZINTE
! ! downwards then upwards vertical displacement,
! ! residual internal energy,
! ! residual potential energy

WAUTELET Philippe
committed
real, dimension(:,:), allocatable :: ZZZ,ZDZZ, &
ZG_O_THVREF, &
ZTHM,ZTKEM,ZLM, &
ZLMDN,ZSHEAR, &
ZSQRT_TKE
! ! input and output arrays packed according one horizontal coord.

WAUTELET Philippe
committed
real, dimension(:,:,:), allocatable :: ZRM
! ! input array packed according one horizontal coord.

WAUTELET Philippe
committed
real, dimension(:,:), allocatable :: ZSUM ! to replace SUM function

WAUTELET Philippe
committed
#else
real, dimension(:,:), pointer, contiguous :: ZVPT ! Virtual Potential Temp at half levels
real, dimension(:,:), pointer, contiguous :: ZDELTVPT
! Increment of Virtual Potential Temp between two following levels
real, dimension(:,:), pointer, contiguous :: ZHLVPT
! Virtual Potential Temp at half levels
real, dimension(:), pointer, contiguous :: ZLWORK,ZINTE
! ! downwards then upwards vertical displacement,
! ! residual internal energy,
! ! residual potential energy
real, dimension(:,:), pointer, contiguous :: ZZZ,ZDZZ, &
ZG_O_THVREF, &
ZTHM,ZTKEM,ZLM, &
ZLMDN,ZSHEAR, &
ZSQRT_TKE
! ! input and output arrays packed according one horizontal coord.
real, dimension(:,:,:), pointer, contiguous :: ZRM
! ! input array packed according one horizontal coord.
real, dimension(:,:), pointer, contiguous :: ZSUM ! to replace SUM function
#endif

WAUTELET Philippe
committed
INTEGER :: IIU, IJU
INTEGER :: J1D ! horizontal loop counter
INTEGER :: JK,JKK,J3RD ! loop counters
INTEGER :: JRR ! moist loop counter

WAUTELET Philippe
committed
integer :: ji, jj

WAUTELET Philippe
committed
LOGICAL :: LAROME
REAL :: ZRVORD ! Rv/Rd
REAL :: ZPOTE,ZLWORK1,ZLWORK2
REAL :: ZTEST,ZTEST0,ZTESTM ! test for vectorization

RODIER Quentin
committed
REAL :: Z2SQRT2,ZUSRBL89,ZBL89EXP
!-------------------------------------------------------------------------------

WAUTELET Philippe
committed
!$acc data present( pzz, pdzz, pthvref, pthlm, prm, ptkem, pshear, plm )

WAUTELET Philippe
committed
if ( mppdb_initialized ) then
!Check all in arrays
call Mppdb_check( pzz, "Bl89 beg:pzz" )
call Mppdb_check( pdzz, "Bl89 beg:pdzz" )
call Mppdb_check( pthvref, "Bl89 beg:pthvref" )
call Mppdb_check( pthlm, "Bl89 beg:pthlm" )
call Mppdb_check( prm, "Bl89 beg:prm" )
call Mppdb_check( ptkem, "Bl89 beg:ptkem" )
call Mppdb_check( pshear, "Bl89 beg:pshear" )
end if

WAUTELET Philippe
committed
IF ( CPROGRAM == 'AROME' ) THEN
LAROME = .TRUE.
ELSE
LAROME = .FALSE.
END IF
IIU = SIZE( PTKEM, 1 )
IJU = SIZE( PTKEM, 2 )
IKT = SIZE( PTKEM, 3 )
#ifndef MNH_OPENACC
allocate( zvpt (IIU * IJU, IKT ) )
allocate( zdeltvpt (IIU * IJU, IKT ) )
allocate( zhlvpt (IIU * IJU, IKT ) )
allocate( zlwork (IIU * IJU ) )
allocate( zinte (IIU * IJU ) )
allocate( zzz (IIU * IJU, IKT ) , &
zdzz (IIU * IJU, IKT ) , &
zg_o_thvref(IIU * IJU, IKT ) , &
zthm (IIU * IJU, IKT ) , &
ztkem (IIU * IJU, IKT ) , &
zlm (IIU * IJU, IKT ) , &
zlmdn (IIU * IJU, IKT ) , &
zshear (IIU * IJU, IKT ) , &
zsqrt_tke (IIU * IJU, IKT ) )

WAUTELET Philippe
committed
allocate( zrm (size( prm, 1 ) * size( prm, 2 ), size( prm, 3 ), size( prm, 4 ) ) )
if ( krr > 0 ) &
allocate( zsum (size( prm, 1 ) * size( prm, 2 ), size( prm, 3 ) ) )

WAUTELET Philippe
committed
#else
!Pin positions in the pools of MNH memory

WAUTELET Philippe
committed
CALL MNH_MEM_POSITION_PIN( 'BL89' )

WAUTELET Philippe
committed
CALL MNH_MEM_GET( zvpt, IIU * IJU, IKT )
CALL MNH_MEM_GET( zdeltvpt, IIU * IJU, IKT )
CALL MNH_MEM_GET( zhlvpt, IIU * IJU, IKT )
CALL MNH_MEM_GET( zlwork, IIU * IJU )
CALL MNH_MEM_GET( zinte, IIU * IJU )
CALL MNH_MEM_GET( zzz, IIU * IJU, IKT )
CALL MNH_MEM_GET( zdzz, IIU * IJU, IKT )
CALL MNH_MEM_GET( zg_o_thvref, IIU * IJU, IKT )
CALL MNH_MEM_GET( zthm, IIU * IJU, IKT )
CALL MNH_MEM_GET( ztkem, IIU * IJU, IKT )
CALL MNH_MEM_GET( zlm, IIU * IJU, IKT )
CALL MNH_MEM_GET( zlmdn, IIU * IJU, IKT )
CALL MNH_MEM_GET( zshear, IIU * IJU, IKT )
CALL MNH_MEM_GET( zsqrt_tke, IIU * IJU, IKT )
CALL MNH_MEM_GET( zrm, size( prm, 1 ) * size( prm, 2 ), size( prm, 3 ), size( prm, 4 ) )
if ( krr > 0 ) &
CALL MNH_MEM_GET( zsum, size( prm, 1 ) * size( prm, 2 ), size( prm, 3 ) )

WAUTELET Philippe
committed

WAUTELET Philippe
committed
!$acc data present ( zvpt, zdeltvpt, zhlvpt, zlwork, zinte, &
!$acc & zzz, zdzz, zg_o_thvref, zthm, ztkem, zlm, zlmdn, &
!$acc & zshear, zsqrt_tke, zrm, zsum )
#endif

WAUTELET Philippe
committed
!$acc kernels
Z2SQRT2=2.*SQRT(2.)
!
IKB=KKA+JPVEXT_TURB*KKL
IKE=KKU-JPVEXT_TURB*KKL
IKTB = JPVEXT_TURB + 1
IKT = SIZE(PTKEM,3)
IKTE = IKT-JPVEXT_TURB
ZRVORD = XRV / XRD
!
!-------------------------------------------------------------------------------
!
!* 1. pack the horizontal dimensions into one
! ---------------------------------------
!

WAUTELET Philippe
committed
IF ( LAROME ) THEN
!$acc loop independent
DO JK=1,IKT
ZZZ (:,JK) = PZZ (:,1,JK)
ZDZZ (:,JK) = PDZZ (:,1,JK)
ZTHM (:,JK) = PTHLM (:,1,JK)
ZTKEM (:,JK) = PTKEM (:,1,JK)
ZG_O_THVREF(:,JK) = XG/PTHVREF(:,1,JK)
END DO

WAUTELET Philippe
committed
!$acc loop independent collapse(2)
DO JK=1,IKT
DO JRR=1,KRR
ZRM (:,JK,JRR) = PRM (:,1,JK,JRR)
END DO
END DO
ELSE

WAUTELET Philippe
committed
#ifndef MNH_OPENACC
DO JK=1,IKT
ZZZ (:,JK) = RESHAPE(PZZ (:,:,JK),(/ IIU*IJU /) )
ZDZZ (:,JK) = RESHAPE(PDZZ (:,:,JK),(/ IIU*IJU /) )
ZTHM (:,JK) = RESHAPE(PTHLM (:,:,JK),(/ IIU*IJU /) )
ZSHEAR (:,JK) = RESHAPE(PSHEAR (:,:,JK),(/ IIU*IJU /) )
ZTKEM (:,JK) = RESHAPE(PTKEM (:,:,JK),(/ IIU*IJU /) )
ZG_O_THVREF(:,JK) = RESHAPE(XG/PTHVREF(:,:,JK),(/ IIU*IJU /) )

RODIER Quentin
committed
IF (LOCEAN) ZG_O_THVREF(:,JK) = XG * XALPHAOC
DO JRR=1,KRR
ZRM (:,JK,JRR) = RESHAPE(PRM (:,:,JK,JRR),(/ IIU*IJU /) )
END DO
END DO

WAUTELET Philippe
committed
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#else
!$acc loop independent collapse(3)
do jk = 1, ikt
do jj = 1, iju
do ji = 1, iiu
zzz (( jj - 1 ) * iiu + ji, jk ) = pzz (ji, jj, jk)
zdzz (( jj - 1 ) * iiu + ji, jk ) = pdzz (ji, jj, jk)
zthm (( jj - 1 ) * iiu + ji, jk ) = pthlm (ji, jj, jk)
zshear (( jj - 1 ) * iiu + ji, jk ) = pshear (ji, jj, jk)
ztkem (( jj - 1 ) * iiu + ji, jk ) = ptkem (ji, jj, jk)
zg_o_thvref(( jj - 1 ) * iiu + ji, jk ) = xg / pthvref(ji, jj, jk)
end do
end do
end do
!$acc loop independent collapse(4)
do jrr = 1, krr
do jk = 1, ikt
do jj = 1, iju
do ji = 1, iiu
zrm(( jj - 1 ) * iiu + ji, jk, jrr ) = prm(ji, jj, jk, jrr )
end do
end do
end do
end do
#endif

WAUTELET Philippe
committed
#ifndef MNH_BITREP
ZSQRT_TKE = SQRT(ZTKEM)

RODIER Quentin
committed
!ZBL89EXP is defined here because (and not in ini_cturb) because XCED is defined in read_exseg (depending on BL89/RM17)
ZBL89EXP = LOG(16.)/(4.*LOG(XKARMAN)+LOG(XCED)-3.*LOG(XCMFS))

WAUTELET Philippe
committed
#else

WAUTELET Philippe
committed
#ifdef MNH_COMPILER_NVHPC
!$acc loop independent collapse(2)
#endif
do concurrent( ji = 1 : iiu * iju, jk = 1 : ikt )
zsqrt_tke(ji, jk) = Br_pow( ztkem(ji,jk), 0.5 )

WAUTELET Philippe
committed
end do
!ZBL89EXP is defined here because (and not in ini_cturb) because XCED is defined in read_exseg (depending on BL89/RM17)
ZBL89EXP = Br_log( 16. ) / ( 4. * Br_log( XKARMAN )+ Br_log( XCED ) - 3. * Br_log( XCMFS) )

WAUTELET Philippe
committed
#endif
ZUSRBL89 = 1./ZBL89EXP

WAUTELET Philippe
committed
!$acc end kernels
!-------------------------------------------------------------------------------
!
!* 2. Virtual potential temperature on the model grid
! -----------------------------------------------
!

WAUTELET Philippe
committed
IF( KRR > 0 ) THEN

WAUTELET Philippe
committed
!$acc kernels

WAUTELET Philippe
committed
ZSUM(:,:) = ZRM(:,:,1)
DO JRR = 2, KRR
!$mnh_do_concurrent ( JI=1:IIU,JJ=1:IJU )
ZSUM(JI,JJ) = ZSUM(JI,JJ) + ZRM(JI,JJ,JRR)
!$mnh_end_do()

WAUTELET Philippe
committed
ZVPT(:,:)=ZTHM(:,:) * ( 1. + ZRVORD*ZRM(:,:,1) ) / ( 1. + ZSUM(:,:) )

WAUTELET Philippe
committed
!$acc end kernels

WAUTELET Philippe
committed
!$acc kernels
ZVPT(:,:)=ZTHM(:,:)
!$acc end kernels
END IF
!
!!!!!!!!!!!!
!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!! WARNING !!
!!!!!!!!!!!!
!!!!!!!!!!!!
!Any modification done to the following lines and to the sections 4 and
!6 must be copied in compute_bl89_ml routine.
!We do not call directly this routine for numerical performance reasons
!but algorithm must remain the same.
!!!!!!!!!!!!
!$acc kernels present_cr(ZTEST0,ZPOTE,ZTEST,ZTESTM,ZLWORK1,ZLWORK2,ZLWORK,ZINTE) &
!$acc & present_cr(ZTEST0,ZPOTE,ZTEST,ZTESTM,ZLWORK1,ZLWORK2,ZLWORK,ZINTE) &
!$acc & present_cr(ZLWORK1,ZLWORK2,ZPOTE,ZLWORK2,ZLM)
ZDELTVPT(:,IKTB:IKTE)=ZVPT(:,IKTB:IKTE)-ZVPT(:,IKTB-KKL:IKTE-KKL)
ZDELTVPT(:,KKU)=ZVPT(:,KKU)-ZVPT(:,KKU-KKL)
ZDELTVPT(:,KKA)=0.

WAUTELET Philippe
committed
#ifndef MNH_OPENACC
WHERE (ABS(ZDELTVPT(:,:))<XLINF)
ZDELTVPT(:,:)=XLINF
END WHERE

WAUTELET Philippe
committed
#else
do jk = 1, ikt
do ji = 1, iiu * iju
if ( abs( zdeltvpt(ji, jk ) ) < xlinf ) zdeltvpt(ji, jk ) = xlinf
end do
end do
#endif
!
ZHLVPT(:,IKTB:IKTE)= 0.5 * ( ZVPT(:,IKTB:IKTE)+ZVPT(:,IKTB-KKL:IKTE-KKL) )
ZHLVPT(:,KKU)= 0.5 * ( ZVPT(:,KKU)+ZVPT(:,KKU-KKL) )
ZHLVPT(:,KKA) = ZVPT(:,KKA)

WAUTELET Philippe
committed
!$acc end kernels
!-------------------------------------------------------------------------------
!
!* 3. loop on model levels
! --------------------
DO JK=IKTB,IKTE

WAUTELET Philippe
committed
!$acc kernels
!
!-------------------------------------------------------------------------------
!
!* 4. mixing length for a downwards displacement
! ------------------------------------------
ZINTE(:)=ZTKEM(:,JK)

WAUTELET Philippe
committed
ZLWORK(:)=0.

WAUTELET Philippe
committed
!$acc loop seq
DO JKK=JK,IKB,-KKL
IF(ZTESTM > 0.) THEN
ZTESTM=0.

WAUTELET Philippe
committed
!$mnh_do_concurrent( J1D = 1 : IIU*IJU )
ZTEST0=0.5+SIGN(0.5,ZINTE(J1D))
!--------- SHEAR + STABILITY -----------
ZPOTE = ZTEST0* &
(-ZG_O_THVREF(J1D,JK)*(ZHLVPT(J1D,JKK)-ZVPT(J1D,JK)) &
+ XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
)*ZDZZ(J1D,JKK)
ZTEST =0.5+SIGN(0.5,ZINTE(J1D)-ZPOTE)
ZTESTM=ZTESTM+ZTEST0
ZLWORK1=ZDZZ(J1D,JKK)
!-------- ORIGINAL -------------
! ZLWORK2= ( + ZG_O_THVREF(J1D,JK) * &
! ( ZVPT(J1D,JKK) - ZVPT(J1D,JK) ) &
! + SQRT (ABS( &
! ( ZG_O_THVREF(J1D,JK) * (ZVPT(J1D,JKK) - ZVPT(J1D,JK)) )**2 &
! + 2. * ZINTE(J1D) * ZG_O_THVREF(J1D,JK) &
! * ZDELTVPT(J1D,JKK) / ZDZZ(J1D,JKK) ))) / &
! ( ZG_O_THVREF(J1D,JK) * ZDELTVPT(J1D,JKK) / ZDZZ(J1D,JKK))
!--------- SHEAR + STABILITY -----------

WAUTELET Philippe
committed
ZLWORK2 = (ZG_O_THVREF(J1D,JK) *(ZVPT(J1D,JKK) - ZVPT(J1D,JK)) &
-XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &

WAUTELET Philippe
committed
#ifndef MNH_BITREP
+ SQRT(ABS( (XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
+ ( -ZG_O_THVREF(J1D,JK) * (ZVPT(J1D,JKK) - ZVPT(J1D,JK)) ))**2.0 + &

WAUTELET Philippe
committed
#else
+ SQRT(ABS( BR_P2(XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
+ ( -ZG_O_THVREF(J1D,JK) * (ZVPT(J1D,JKK) - ZVPT(J1D,JK)) )) + &

WAUTELET Philippe
committed
#endif
2. * ZINTE(J1D) * &
(ZG_O_THVREF(J1D,JK) * ZDELTVPT(J1D,JKK)/ ZDZZ(J1D,JKK))))) / &
(ZG_O_THVREF(J1D,JK) * ZDELTVPT(J1D,JKK) / ZDZZ(J1D,JKK))
ZLWORK(J1D)=ZLWORK(J1D)+ZTEST0*(ZTEST*ZLWORK1+(1-ZTEST)*ZLWORK2)
ZINTE(J1D) = ZINTE(J1D) - ZPOTE

WAUTELET Philippe
committed
!$mnh_end_do()
ENDIF
END DO
!-------------------------------------------------------------------------------
!
!* 5. intermediate storage of the final mixing length
! -----------------------------------------------
!
ZLMDN(:,JK)=MIN(ZLWORK(:),0.5*(ZZZ(:,JK)+ZZZ(:,JK+KKL))-ZZZ(:,IKB))
!
!-------------------------------------------------------------------------------
!
!* 6. mixing length for an upwards displacement
! -----------------------------------------
!
ZINTE(:)=ZTKEM(:,JK)

WAUTELET Philippe
committed
ZLWORK(:)=0.

WAUTELET Philippe
committed
!$acc loop seq
DO JKK=JK+KKL,IKE,KKL
IF(ZTESTM > 0.) THEN
ZTESTM=0.

WAUTELET Philippe
committed
!$mnh_do_concurrent( J1D = 1 : IIU*IJU )
!-------- ORIGINAL -------------
!ZPOTE = ZTEST0*ZG_O_THVREF(J1D,JK) * &
! (ZHLVPT(J1D,JKK) - ZVPT(J1D,JK) ) *ZDZZ(J1D,JKK)
!--------- SHEAR + STABILITY -----------
ZPOTE = ZTEST0* &
(ZG_O_THVREF(J1D,JK)*(ZHLVPT(J1D,JKK)-ZVPT(J1D,JK)) &
+XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
)*ZDZZ(J1D,JKK)
ZTEST =0.5+SIGN(0.5,ZINTE(J1D)-ZPOTE)
ZTESTM=ZTESTM+ZTEST0
ZLWORK1=ZDZZ(J1D,JKK)
!-------- ORIGINAL -------------
! ZLWORK2= ( - ZG_O_THVREF(J1D,JK) * &
! ( ZVPT(J1D,JKK-KKL) - ZVPT(J1D,JK) ) &
! + SQRT (ABS( &
! ( ZG_O_THVREF(J1D,JK) * (ZVPT(J1D,JKK-KKL) - ZVPT(J1D,JK)) )**2 &
! + 2. * ZINTE(J1D) * ZG_O_THVREF(J1D,JK) &
! * ZDELTVPT(J1D,JKK) / ZDZZ(J1D,JKK) )) ) / &
! ( ZG_O_THVREF(J1D,JK) * ZDELTVPT(J1D,JKK) / ZDZZ(J1D,JKK) )
!--------- SHEAR + STABILITY -----------

WAUTELET Philippe
committed
#ifndef MNH_BITREP
ZLWORK2= ( - ZG_O_THVREF(J1D,JK) *(ZVPT(J1D,JKK-KKL) - ZVPT(J1D,JK) ) &
- XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
(XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
+ ( ZG_O_THVREF(J1D,JK) * (ZVPT(J1D,JKK-KKL) - ZVPT(J1D,JK))) )**2 &

WAUTELET Philippe
committed
+ 2. * ZINTE(J1D) * &
( ZG_O_THVREF(J1D,JK)* ZDELTVPT(J1D,JKK)/ZDZZ(J1D,JKK))))) / &
(ZG_O_THVREF(J1D,JK) * ZDELTVPT(J1D,JKK) / ZDZZ(J1D,JKK))

WAUTELET Philippe
committed
#else

WAUTELET Philippe
committed
ZLWORK2= ( - ZG_O_THVREF(J1D,JK) *(ZVPT(J1D,JKK-KKL) - ZVPT(J1D,JK) ) &
- XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
+ BR_POW (ABS( &
BR_P2(XRM17*ZSHEAR(J1D,JKK)*ZSQRT_TKE(J1D,JK) &
+ ( ZG_O_THVREF(J1D,JK) * (ZVPT(J1D,JKK-KKL) - ZVPT(J1D,JK))) ) &
+ 2. * ZINTE(J1D) * &

WAUTELET Philippe
committed
( ZG_O_THVREF(J1D,JK)* ZDELTVPT(J1D,JKK)/ZDZZ(J1D,JKK))), 0.5 ) ) / &
(ZG_O_THVREF(J1D,JK) * ZDELTVPT(J1D,JKK) / ZDZZ(J1D,JKK))

WAUTELET Philippe
committed
#endif
ZLWORK(J1D)=ZLWORK(J1D)+ZTEST0*(ZTEST*ZLWORK1+(1-ZTEST)*ZLWORK2)
ZINTE(J1D) = ZINTE(J1D) - ZPOTE

WAUTELET Philippe
committed
!$mnh_end_do()
ENDIF
END DO
!
!-------------------------------------------------------------------------------
!
!* 7. final mixing length
!

WAUTELET Philippe
committed
!$mnh_do_concurrent( J1D = 1 : IIU*IJU )
ZLWORK1=MAX(ZLMDN(J1D,JK),1.E-10_MNHREAL)
ZLWORK2=MAX(ZLWORK(J1D),1.E-10_MNHREAL)

WAUTELET Philippe
committed
#ifndef MNH_BITREP

RODIER Quentin
committed
ZLWORK2=1.d0 + ZPOTE**ZBL89EXP
ZLM(J1D,JK) = ZLWORK1*(2./ZLWORK2)**ZUSRBL89

WAUTELET Philippe
committed
#else
ZLWORK2=1.d0 + br_pow( ZPOTE, ZBL89EXP )
ZLM(J1D,JK) = ZLWORK1 * br_pow( 2. / ZLWORK2, ZUSRBL89 )

WAUTELET Philippe
committed
#endif

WAUTELET Philippe
committed
!$mnh_end_do()

WAUTELET Philippe
committed
ZLM(:,JK)=MAX(ZLM(:,JK),XLINI)
!* 8. end of the loop on the vertical levels
! --------------------------------------
!

WAUTELET Philippe
committed
!$acc end kernels
END DO
!
!-------------------------------------------------------------------------------
!
!* 9. boundaries
! ----------
!

WAUTELET Philippe
committed
!$acc kernels
ZLM(:,KKA)=ZLM(:,IKB)
ZLM(:,IKE)=ZLM(:,IKE-KKL)
ZLM(:,KKU)=ZLM(:,IKE-KKL)
!
!-------------------------------------------------------------------------------
!
!* 10. retrieve output array in model coordinates
! ------------------------------------------
!

WAUTELET Philippe
committed
IF ( LAROME ) THEN
DO JK=1,IKT
PLM (:,1,JK) = ZLM (:,JK)
END DO
ELSE

WAUTELET Philippe
committed
#ifndef MNH_OPENACC
DO JK=1,IKT
PLM (:,:,JK) = RESHAPE(ZLM (:,JK), (/ IIU,IJU /) )
END DO

WAUTELET Philippe
committed
#else
do jk = 1, ikt
do jj = 1, iju
do ji = 1, iiu
plm(ji, jj, jk ) = zlm(( jj - 1 ) * iiu + ji, jk )
end do
end do
end do
#endif

WAUTELET Philippe
committed
!$acc end kernels
if ( mppdb_initialized ) then
!Check all out arrays
call Mppdb_check( plm, "Bl89 end:plm" )
end if

WAUTELET Philippe
committed
!$acc end data

WAUTELET Philippe
committed
#ifdef MNH_OPENACC
!Release all memory allocated with MNH_MEM_GET calls since last call to MNH_MEM_POSITION_PIN

WAUTELET Philippe
committed
CALL MNH_MEM_RELEASE( 'BL89')

WAUTELET Philippe
committed
#endif

WAUTELET Philippe
committed
!$acc end data