From db35d8614da80a00d931339dd687e9ba3793e1c8 Mon Sep 17 00:00:00 2001
From: ESCOBAR Juan <escj@nuwa>
Date: Wed, 26 Oct 2022 18:13:44 +0200
Subject: [PATCH] Juan 26/10/2022:add orig
 advec_4th_order_aux.f90/advecuvw_4th.f90 in ZSOLVER for GPU port of CEN4TH

---
 src/ZSOLVER/advec_4th_order_aux.f90 | 735 ++++++++++++++++++++++++++++
 src/ZSOLVER/advecuvw_4th.f90        | 382 +++++++++++++++
 2 files changed, 1117 insertions(+)
 create mode 100644 src/ZSOLVER/advec_4th_order_aux.f90
 create mode 100644 src/ZSOLVER/advecuvw_4th.f90

diff --git a/src/ZSOLVER/advec_4th_order_aux.f90 b/src/ZSOLVER/advec_4th_order_aux.f90
new file mode 100644
index 000000000..041ac4517
--- /dev/null
+++ b/src/ZSOLVER/advec_4th_order_aux.f90
@@ -0,0 +1,735 @@
+!MNH_LIC Copyright 2005-2022 CNRS, Meteo-France and Universite Paul Sabatier
+!MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence
+!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_ADVEC_4TH_ORDER_AUX
+!     ###############################
+!
+INTERFACE
+!
+      SUBROUTINE ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PFIELDT, KGRID, & 
+                                      PMEANX, PMEANY,TPHALO2 )
+!
+USE MODD_ARGSLIST_ll, ONLY : HALO2_ll
+!
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCX ! X direction LBC type
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCY ! Y direction LBC type
+!
+REAL, DIMENSION(:,:,:), INTENT(OUT)   :: PMEANX, PMEANY ! fluxes
+REAL, DIMENSION(:,:,:), INTENT(IN)    :: PFIELDT  ! variable at t
+INTEGER,                INTENT(IN)    :: KGRID    ! C grid localisation
+!
+TYPE(HALO2_ll), POINTER :: TPHALO2      ! halo2 for the field at t
+!
+END SUBROUTINE ADVEC_4TH_ORDER_ALGO
+!
+!-------------------------------------------------------------------------------
+!
+      FUNCTION MZF4(PA)  RESULT(PMZF4)
+!
+REAL, DIMENSION(:,:,:), INTENT(IN)                :: PA     ! variable at flux
+                                                            !         side
+REAL, DIMENSION(SIZE(PA,1),SIZE(PA,2),SIZE(PA,3)) :: PMZF4  ! result at mass
+                                                            ! localization 
+!
+END FUNCTION MZF4
+!
+!-------------------------------------------------------------------------------
+!
+      FUNCTION MZM4(PA)  RESULT(PMZM4)
+!
+REAL, DIMENSION(:,:,:), INTENT(IN)                :: PA     ! variable at mass 
+                                                            ! localization
+REAL, DIMENSION(SIZE(PA,1),SIZE(PA,2),SIZE(PA,3)) :: PMZM4  ! result at flux 
+                                                            ! localization 
+END FUNCTION MZM4
+!
+!-------------------------------------------------------------------------------
+!
+END INTERFACE
+!
+END MODULE MODI_ADVEC_4TH_ORDER_AUX
+!
+!-------------------------------------------------------------------------------
+!
+!     ########################################################################
+      SUBROUTINE ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PFIELDT, KGRID, & 
+                                      PMEANX, PMEANY,TPHALO2 )
+!     ########################################################################
+!!
+!!****  *ADVEC_4TH_ORDER_ALGO * - routine used to compute 4th order horizontal
+!!                                advection fluxes of 3D prognostic variables
+!!
+!!    PURPOSE
+!!    -------
+!!      The purpose of this routine is to compute 2sd or 4th order horizontal
+!!    advection fluxes of a prognostic variable.
+!!
+!!**  METHOD
+!!    ------
+!!      In case of cyclic LBCs, the routine returns the scalar component of the 
+!!    advection fluxes by applying a 4th order horizontal averaging operator to
+!!    the prognostic variable on each grid level. In the case of open LBCs, the
+!!    averaging operator degenerates to a 2nd order one on the first ring 
+!!    inside the computationnal domain.
+!!      The "halo2" (or the second layer of the halo) of the prognostic
+!!    variable is passed as argument.
+!!
+!!    IMPLICIT ARGUMENTS
+!!    ------------------
+!!
+!!    MODULE MODD_ARGSLIST
+!!         HALO2LIST_ll : type for a list of "HALO2_lls"
+!!
+!!    REFERENCE
+!!    ---------
+!!      Book2 of documentation ( routine ADVEC_4TH_ORDER )
+!!      User Interface for the MesoNH Parallel Package
+!!
+!!    AUTHOR
+!!    ------
+!!      J.-P. Pinty      * Laboratoire d'Aerologie*
+!!
+!!    MODIFICATIONS
+!!    -------------
+!!      Original   25/10/05
+! J. Escobar  21/03/2013: for HALOK comment all NHALO=1 test
+! P. Wautelet 21/11/2019: TPHALO2 dummy argument is no longer optional
+!
+!-------------------------------------------------------------------------------
+!
+!*       0.    DECLARATIONS
+!              ------------
+!
+USE MODD_ARGSLIST_ll, ONLY: HALO2_ll
+USE MODD_CONF
+!
+#ifdef MNH_OPENACC
+USE MODE_DEVICE
+#endif
+use mode_ll,          only: GET_INDICE_ll, LWEST_ll, LEAST_ll, LNORTH_ll, LSOUTH_ll
+#ifdef MNH_OPENACC
+USE MODE_MNH_ZWORK,   ONLY: MNH_MEM_GET, MNH_MEM_POSITION_PIN, MNH_MEM_RELEASE
+#endif
+use mode_mppdb
+#ifdef MNH_OPENACC
+use mode_msg
+#endif
+!
+IMPLICIT NONE
+!
+!*       0.1   Declarations of dummy arguments :
+!
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCX ! X direction LBC type
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCY ! Y direction LBC type
+!
+REAL, DIMENSION(:,:,:), INTENT(OUT)   :: PMEANX, PMEANY ! fluxes
+REAL, DIMENSION(:,:,:), INTENT(IN)    :: PFIELDT  ! variable at t
+INTEGER,                INTENT(IN)    :: KGRID    ! C grid localisation
+!
+TYPE(HALO2_ll), POINTER :: TPHALO2      ! halo2 for the field at t
+!
+!*       0.2   Declarations of local variables :
+!
+INTEGER:: IW,IE,IS,IN,IT,IB,IWF,IEF,ISF,INF   ! Coordinate of forth order diffusion area
+!
+INTEGER:: IIB,IJB        ! Begining useful area in x,y directions
+INTEGER:: IIE,IJE        ! End useful area in x,y directions
+!
+INTEGER:: ILUOUT,IRESP   ! for prints
+!
+! JUAN ACC
+LOGICAL                                               :: GWEST , GEAST
+LOGICAL                                               :: GSOUTH , GNORTH
+#ifndef MNH_OPENACC
+REAL, DIMENSION(:,:), ALLOCATABLE :: ZHALO2_WEST,  ZHALO2_EAST
+REAL, DIMENSION(:,:), ALLOCATABLE :: ZHALO2_SOUTH, ZHALO2_NORTH
+#else
+REAL, DIMENSION(:,:), pointer, contiguous :: ZHALO2_WEST,  ZHALO2_EAST
+REAL, DIMENSION(:,:), pointer, contiguous :: ZHALO2_SOUTH, ZHALO2_NORTH
+#endif
+!
+
+!$acc data present( PMEANX, PMEANY, PFIELDT )
+
+IF (MPPDB_INITIALIZED) THEN
+  !Check all IN arrays
+  CALL MPPDB_CHECK(PFIELDT,"ADVEC_4TH_ORDER_ALGO beg:PFIELDT")
+END IF
+
+#ifndef MNH_OPENACC
+allocate( zhalo2_west ( size( pfieldt, 2 ), size( pfieldt, 3 ) ) )
+allocate( zhalo2_east ( size( pfieldt, 2 ), size( pfieldt, 3 ) ) )
+allocate( zhalo2_south( size( pfieldt, 2 ), size( pfieldt, 3 ) ) )
+allocate( zhalo2_north( size( pfieldt, 2 ), size( pfieldt, 3 ) ) )
+#else
+!Pin positions in the pools of MNH memory
+CALL MNH_MEM_POSITION_PIN( 'ADVEC_4TH_ORDER_ALGO' )
+
+CALL MNH_MEM_GET( zhalo2_west,  size( pfieldt, 2 ), size( pfieldt, 3 ) )
+CALL MNH_MEM_GET( zhalo2_east,  size( pfieldt, 2 ), size( pfieldt, 3 ) )
+CALL MNH_MEM_GET( zhalo2_south, size( pfieldt, 2 ), size( pfieldt, 3 ) )
+CALL MNH_MEM_GET( zhalo2_north, size( pfieldt, 2 ), size( pfieldt, 3 ) )
+
+!$acc data present ( zhalo2_west, zhalo2_east, zhalo2_south, zhalo2_north )
+#endif
+
+!-------------------------------------------------------------------------------
+!
+!*       0.3.     COMPUTES THE DOMAIN DIMENSIONS
+!                 ------------------------------
+!
+#ifdef MNH_OPENACC
+CALL INIT_ON_HOST_AND_DEVICE(ZHALO2_WEST,-1e99,'ADVEC_4TH_ORDER_ALGO::ZHALO2_WEST')
+CALL INIT_ON_HOST_AND_DEVICE(ZHALO2_EAST,-1e99,'ADVEC_4TH_ORDER_ALGO::ZHALO2_EAST')
+CALL INIT_ON_HOST_AND_DEVICE(ZHALO2_SOUTH,-1e99,'ADVEC_4TH_ORDER_ALGO::ZHALO2_SOUTH')
+CALL INIT_ON_HOST_AND_DEVICE(ZHALO2_NORTH,-1e99,'ADVEC_4TH_ORDER_ALGO::ZHALO2_NORTH')
+#endif
+!
+CALL GET_INDICE_ll(IIB,IJB,IIE,IJE)
+!
+GWEST  = LWEST_ll()
+GEAST  = LEAST_ll()
+GSOUTH = LSOUTH_ll()
+GNORTH = LNORTH_ll()
+!
+!-------------------------------------------------------------------------------
+!
+!*       0.4.   INITIALIZE THE FIELDS 
+!               ---------------------
+!
+!$acc kernels present(PMEANX,PMEANY)
+PMEANX(:,:,:) = 0.0
+PMEANY(:,:,:) = 0.0
+!$acc end kernels
+!
+!-------------------------------------------------------------------------------
+!
+!
+!*       1.     CALCULATE THE NUMERICAL MEAN IN THE X DIRECTION
+!               -----------------------------------------------
+!
+SELECT CASE ( HLBCX(1) ) ! X direction LBC type: (1) for left side
+!
+!*       1.1    CYCLIC CASE IN THE X DIRECTION:
+!
+CASE ('CYCL')          ! In that case one must have HLBCX(1) == HLBCX(2)
+!
+#ifdef MNH_OPENACC
+call Print_msg( NVERB_WARNING, 'GEN', 'ADVEC_4TH_ORDER_ALGO', 'OpenACC: HLBCX(1) AND CYCL not yet tested' )
+#endif
+ZHALO2_WEST(:,:) = TPHALO2%WEST(:,:)
+ZHALO2_EAST(:,:) = TPHALO2%EAST(:,:)
+!$acc update device (ZHALO2_WEST,ZHALO2_EAST)
+!
+!$acc kernels present(PMEANX)
+    IW=IIB+1
+    IE=IIE
+!
+  IF(KGRID == 2) THEN
+    IWF=IW-1
+    IEF=IE-1
+  ELSE
+    IWF=IW
+    IEF=IE
+  END IF
+!
+!* lateral boundary conditions
+  PMEANX(IWF-1,:,:) = (7.0*( PFIELDT(IW-1,:,:)+PFIELDT(IW-2,:,:) ) -  &
+                           ( PFIELDT(IW,:,:)+ZHALO2_WEST(:,:) ) )/12.0
+!
+  PMEANX(IEF+1,:,:) = (7.0*( PFIELDT(IE+1,:,:)+PFIELDT(IE,:,:) ) -  &
+                       ( ZHALO2_EAST(:,:)+PFIELDT(IE-1,:,:) ) )/12.0
+!
+!* inner domain
+  PMEANX(IWF:IEF,:,:) = (7.0*( PFIELDT(IW:IE,:,:)+PFIELDT(IW-1:IE-1,:,:) ) -  &
+                       ( PFIELDT(IW+1:IE+1,:,:)+PFIELDT(IW-2:IE-2,:,:) ) )/12.0
+!$acc end kernels
+!
+!!$!
+!!$
+!!$  IF(NHALO == 1) THEN
+!!$    PMEANX(IWF-1,:,:) = (7.0*( PFIELDT(IW-1,:,:)+PFIELDT(IW-2,:,:) ) -  &
+!!$                             ( PFIELDT(IW,:,:)+ZPHALO2_WEST(:,:) ) )/12.0
+!!$!
+!!$    PMEANX(IEF+1,:,:) = (7.0*( PFIELDT(IE+1,:,:)+PFIELDT(IE,:,:) ) -  &
+!!$                         ( ZPHALO2_EAST(:,:)+PFIELDT(IE-1,:,:) ) )/12.0
+!!$  ENDIF
+!!$!
+!!$  PMEANX(IWF:IEF,:,:) = (7.0*( PFIELDT(IW:IE,:,:)+PFIELDT(IW-1:IE-1,:,:) ) -  &
+!!$                       ( PFIELDT(IW+1:IE+1,:,:)+PFIELDT(IW-2:IE-2,:,:) ) )/12.0
+!!$!
+!*       1.2    NON CYCLIC CASE IN THE X DIRECTION 
+!
+CASE ('OPEN','WALL','NEST')
+!
+ZHALO2_WEST(:,:) = TPHALO2%WEST(:,:)
+ZHALO2_EAST(:,:) = TPHALO2%EAST(:,:)
+!$acc update device (ZHALO2_WEST,ZHALO2_EAST)
+!
+!$acc kernels present(PMEANX)
+  IF (GWEST) THEN
+    IF(KGRID == 2) THEN
+      IW=IIB+2          ! special case of C grid
+    ELSE
+      IW=IIB+1
+    END IF
+  ELSE
+!!$    IF(NHALO == 1) THEN
+      IW=IIB+1
+!!$    ELSE
+!!$      IW=IIB
+!!$    ENDIF
+  ENDIF
+!!$  IF (GEAST .OR. NHALO == 1) THEN
+  IF (GEAST) THEN
+! T. Maric
+!    IE=IIE-1 ! original
+    IE=IIE
+  ELSE
+    IE=IIE
+  END IF  
+!
+  IF(KGRID == 2) THEN
+    IWF=IW-1
+    IEF=IE-1
+  ELSE
+    IWF=IW
+    IEF=IE
+  END IF
+!
+! T. Maric. 16.1.2006.
+!  write(*,*)' IW, IE, IWF, IEF = ',IW, IE, IWF, IEF
+!  stop 'Stopping in advec_4th_order_aux.f90'
+!
+!*             Use a second order scheme at the physical border
+!
+  IF (GWEST) THEN
+    PMEANX(IWF-1,:,:) = 0.5*( PFIELDT(IW-1,:,:)+PFIELDT(IW-2,:,:) )
+    ! T. Maric
+    ! PMEANX(1,:,:) = PMEANX(IWF-1,:,:)
+    ! extrapolate
+    !PMEANX(1,:,:) = 0.5*(3.0*PFIELDT(1,:,:) - PFIELDT(2,:,:))
+!!$  ELSE IF (NHALO == 1) THEN
+  ELSE
+    PMEANX(IWF-1,:,:) = (7.0*( PFIELDT(IW-1,:,:)+PFIELDT(IW-2,:,:) ) -  &
+                             ( PFIELDT(IW,:,:)+ZHALO2_WEST(:,:) ) )/12.0
+  ENDIF
+!
+  IF (GEAST) THEN
+    PMEANX(IEF+1,:,:) = 0.5*( PFIELDT(IE+1,:,:)+PFIELDT(IE,:,:) )
+!!$  ELSEIF (NHALO == 1) THEN
+  ELSE
+    PMEANX(IEF+1,:,:) = (7.0*( PFIELDT(IE+1,:,:)+PFIELDT(IE,:,:) ) -  &
+                         ( ZHALO2_EAST(:,:)+PFIELDT(IE-1,:,:) ) )/12.0
+  ENDIF
+!
+!*             Use a fourth order scheme elsewhere 
+!
+  PMEANX(IWF:IEF,:,:) = (7.0*( PFIELDT(IW:IE,:,:)+PFIELDT(IW-1:IE-1,:,:) ) -  &
+                       ( PFIELDT(IW+1:IE+1,:,:)+PFIELDT(IW-2:IE-2,:,:) ) )/12.0
+!$acc end kernels
+END SELECT
+!
+!-------------------------------------------------------------------------------
+!
+!*       2.     COMPUTES THE 4TH ORDER MEAN IN THE Y DIRECTION
+!               ----------------------------------------------
+!
+IF ( .NOT. L2D ) THEN
+  SELECT CASE ( HLBCY(1) ) ! Y direction LBC type: (1) for left side
+!
+!*       2.1    CYCLIC CASE IN THE Y DIRECTION:
+!
+  CASE ('CYCL')          ! In that case one must have HLBCY(1) == HLBCY(2)
+!
+#ifdef MNH_OPENACC
+call Print_msg( NVERB_WARNING, 'GEN', 'ADVEC_4TH_ORDER_ALGO', 'OpenACC: HLBCX(2) AND CYCL not yet tested' )
+#endif
+ZHALO2_SOUTH(:,:) = TPHALO2%SOUTH(:,:) 
+ZHALO2_NORTH(:,:) = TPHALO2%NORTH(:,:)
+!$acc update device (ZHALO2_SOUTH,ZHALO2_NORTH)
+!
+!$acc kernels present(PMEANY)
+!
+!
+      IS=IJB+1
+      IN=IJE
+!
+    IF(KGRID == 3) THEN
+      ISF=IS-1
+      INF=IN-1
+    ELSE
+      ISF=IS
+      INF=IN
+    END IF
+!
+!* lateral boundary conditions
+    PMEANY(:,ISF-1,:) = (7.0*( PFIELDT(:,IS-1,:)+PFIELDT(:,IS-2,:) ) -  &
+                        ( PFIELDT(:,IS,:)+ZHALO2_SOUTH(:,:) ) )/12.0
+!
+    PMEANY(:,INF+1,:) = (7.0*( PFIELDT(:,IN+1,:)+PFIELDT(:,IN,:) ) -  &
+                        ( ZHALO2_NORTH(:,:)+PFIELDT(:,IN-1,:) ) )/12.0
+!
+!* inner domain
+    PMEANY(:,ISF:INF,:) = (7.0*( PFIELDT(:,IS:IN,:)+PFIELDT(:,IS-1:IN-1,:)) -  &
+                         ( PFIELDT(:,IS+1:IN+1,:)+PFIELDT(:,IS-2:IN-2,:) ))/12.0
+!$acc end kernels
+!!$!
+!!$    IF(NHALO == 1) THEN
+!!$      PMEANY(:,ISF-1,:) = (7.0*( PFIELDT(:,IS,:)+PFIELDT(:,IS-1,:) ) -  &
+!!$                          ( PFIELDT(:,IS+1,:)+ZPHALO2_SOUTH(:,:) ) )/12.0
+!!$!
+!!$      PMEANY(:,ISF+1,:) = (7.0*( PFIELDT(:,IS,:)+PFIELDT(:,IS-1,:) ) -  &
+!!$                          ( ZPHALO2_NORTH(:,:)+PFIELDT(:,IS-2,:) ) )/12.0
+!!$    ENDIF
+!!$!
+!!$    PMEANY(:,ISF:INF,:) = (7.0*( PFIELDT(:,IS:IN,:)+PFIELDT(:,IS-1:IN-1,:)) -  &
+!!$                         ( PFIELDT(:,IS+1:IN+1,:)+PFIELDT(:,IS-2:IN-2,:) ))/12.0
+!!$!
+!*       2.2    NON CYCLIC CASE IN THE Y DIRECTION
+!
+  CASE ('OPEN','WALL','NEST')
+!
+ZHALO2_SOUTH(:,:) = TPHALO2%SOUTH(:,:)
+ZHALO2_NORTH(:,:) = TPHALO2%NORTH(:,:)
+!$acc update device (ZHALO2_SOUTH,ZHALO2_NORTH)
+!
+!$acc kernels present(PMEANY)
+    IF (GSOUTH) THEN
+      IF(KGRID == 3) THEN
+        IS=IJB+2          ! special case of C grid
+      ELSE
+        IS=IJB+1
+      END IF
+    ELSE
+!!$      IF(NHALO == 1) THEN
+        IS=IJB+1
+!!$      ELSE
+!!$        IS=IJB
+!!$      ENDIF
+    ENDIF
+!!$    IF (GNORTH .OR. NHALO == 1) THEN
+    IF (GNORTH) THEN
+! T. Maric
+!      IN=IJE-1  ! original
+      IN=IJE
+    ELSE
+      IN=IJE
+    END IF  
+!
+    IF(KGRID == 3) THEN
+      ISF=IS-1
+      INF=IN-1
+    ELSE
+      ISF=IS
+      INF=IN
+    END IF
+!
+!*             Use a second order scheme at the physical border
+!
+    IF (GSOUTH) THEN
+      PMEANY(:,ISF-1,:) = 0.5*( PFIELDT(:,IS-1,:)+PFIELDT(:,IS-2,:) )
+      ! T. Maric
+      ! PMEANY(:,1,:) = PMEANY(:,ISF-1,:)
+      ! extrapolate
+      !PMEANY(:,1,:) = 0.5*(3.0*PFIELDT(:,1,:) - PFIELDT(:,2,:))
+!!$    ELSEIF (NHALO == 1) THEN
+    ELSE
+!!$      PMEANY(:,ISF-1,:) = (7.0*( PFIELDT(:,IS,:)+PFIELDT(:,IS-1,:)) -  &
+!!$                          ( PFIELDT(:,IS+1,:)+TPHALO2%SOUTH(:,:) ))/12.0
+       PMEANY(:,ISF-1,:) = (7.0*( PFIELDT(:,IS-1,:)+PFIELDT(:,IS-2,:)) -  &
+                           ( PFIELDT(:,IS,:)+ZHALO2_SOUTH(:,:) ))/12.0
+    ENDIF
+!
+    IF (GNORTH) THEN
+      PMEANY(:,INF+1,:) = 0.5*( PFIELDT(:,IN+1,:)+PFIELDT(:,IN,:) )
+!!$    ELSEIF (NHALO == 1) THEN
+    ELSE
+!!$      PMEANY(:,INF+1,:) = (7.0*( PFIELDT(:,IN,:)+PFIELDT(:,IN-1,:)) -  &
+!!$                          ( TPHALO2%NORTH(:,:)+PFIELDT(:,IN-2,:) ))/12.0
+       PMEANY(:,INF+1,:) = (7.0*( PFIELDT(:,IN+1,:)+PFIELDT(:,IN,:)) -  &
+                           ( ZHALO2_NORTH(:,:)+PFIELDT(:,IN-1,:) ))/12.0
+    ENDIF
+!
+!*             Use a fourth order scheme elsewhere 
+!
+    PMEANY(:,ISF:INF,:) = (7.0*( PFIELDT(:,IS:IN,:)+PFIELDT(:,IS-1:IN-1,:)) -  &
+                         ( PFIELDT(:,IS+1:IN+1,:)+PFIELDT(:,IS-2:IN-2,:) ))/12.0
+!$acc end kernels
+!
+  END SELECT
+ELSE
+!$acc kernels present(PMEANY)
+  PMEANY(:,:,:) = 0.0
+!$acc end kernels
+ENDIF
+!
+IF (MPPDB_INITIALIZED) THEN
+  !Check all OUT arrays
+  CALL MPPDB_CHECK(PMEANX,"ADVEC_4TH_ORDER_ALGO end:PMEANX")
+  CALL MPPDB_CHECK(PMEANY,"ADVEC_4TH_ORDER_ALGO end:PMEANY")
+END IF
+
+!$acc end data
+
+#ifdef MNH_OPENACC
+!Release all memory allocated with MNH_MEM_GET calls since last call to MNH_MEM_POSITION_PIN
+CALL MNH_MEM_RELEASE( 'ADVEC_4TH_ORDER_ALGO' )
+#endif
+
+!$acc end data
+
+!-------------------------------------------------------------------------------
+!
+END SUBROUTINE ADVEC_4TH_ORDER_ALGO
+!
+!-------------------------------------------------------------------------------
+!
+!     ################################
+      FUNCTION MZF4(PA)  RESULT(PMZF4)
+!     ################################
+!
+!!****  *MZF4* - 4th order Shuman operator : mean operator in z direction for a 
+!!                                 variable at a flux side
+!!
+!!    PURPOSE
+!!    -------
+!!      The purpose of this function is to compute a 4th order mean value
+!!    along the z direction (K index) for a field PA localized at a z-flux
+!!    point (w point). The result is localized at a mass point.
+!
+!!**  METHOD
+!!    ------ 
+!!        The result PMZF4(:,:,k) is defined by 
+!!        PMZF4(:,:,k)=0.5*(PA(:,:,k)+PA(:,:,k+1)) at k=1 and size(PA,3)-1
+!!        PMZF4(:,:,k)=-999.                       at k=size(PA,3)
+!!        PMZF4(:,:,k)=7/12*(PA(:,:,k)+PA(:,:,k+1))
+!!                    -1/12*(PA(:,:,k-1)+PA(:,:,k+2)) elsewhere
+!!
+!!    EXTERNAL
+!!    --------
+!!      NONE
+!!
+!!    IMPLICIT ARGUMENTS
+!!    ------------------
+!!      NONE
+!!
+!!    REFERENCE
+!!    ---------
+!!      Book2 of documentation of Meso-NH (SHUMAN operators)
+!!      Technical specifications Report of The Meso-NH (chapters 3)  
+!!
+!!    AUTHOR
+!!    ------
+!!      J.-P. Pinty       * Lab Aerologie *
+!!
+!!    MODIFICATIONS
+!!    -------------
+!!      Original    25/10/05
+!!
+!-------------------------------------------------------------------------------
+!
+!*       0.    DECLARATIONS
+!              ------------
+!
+IMPLICIT NONE
+!
+!*       0.1   Declarations of argument and result
+!
+!
+REAL, DIMENSION(:,:,:), INTENT(IN)                :: PA     ! variable at flux
+                                                            !         side
+REAL, DIMENSION(SIZE(PA,1),SIZE(PA,2),SIZE(PA,3)) :: PMZF4  ! result at mass
+                                                            ! localization
+!
+!*       0.2   Declarations of local variables
+!
+!
+INTEGER :: JK               ! loop index in z direction
+INTEGER :: IKU              ! upper bound in z direction of PA 
+!     
+INTEGER :: IIU,IJU,IIJU     ! upper bounds in the x and y directions of PA
+INTEGER :: JIJ,JIJK         ! running loop indexes after linearisation
+INTEGER :: JIJKOR1,JIJKEND1 ! loop boundaries
+INTEGER :: JIJKOR2,JIJKEND2 ! loop boundaries
+INTEGER :: JIJKOR3,JIJKEND3 ! loop boundaries
+!
+!-------------------------------------------------------------------------------
+
+!$acc data present( PA, PMZF4 )
+!
+!*       1.    DEFINITION OF MZF4
+!              ------------------
+!
+IIU = SIZE(PA,1)
+IJU = SIZE(PA,2)
+IKU = SIZE(PA,3)
+!
+IIJU = IIU*IJU
+!
+JIJKOR1  = 1 + IIJU
+JIJKEND1 = 2*IIJU
+!
+!$acc kernels
+!CDIR NODEP
+!OCL NOVREC
+DO JIJK=JIJKOR1 , JIJKEND1
+   PMZF4(JIJK-IIJU,1,1) = 0.5*( PA(JIJK-IIJU,1,1)+PA(JIJK,1,1) )
+END DO
+!
+JIJKOR2  = 1 + JIJKEND1
+JIJKEND2 = IIJU*IKU - IIJU
+!
+!CDIR NODEP
+!OCL NOVREC
+DO JIJK=JIJKOR2 , JIJKEND2
+   PMZF4(JIJK-IIJU,1,1) = (7.0*( PA(JIJK,1,1)+PA(JIJK-IIJU,1,1) ) -      &
+                          ( PA(JIJK+IIJU,1,1)+PA(JIJK-2*IIJU,1,1) ) )/12.0
+END DO
+!
+JIJKOR3  = 1 + JIJKEND2
+JIJKEND3 = IIJU*IKU
+!
+!CDIR NODEP
+!OCL NOVREC
+DO JIJK=JIJKOR3 , JIJKEND3
+   PMZF4(JIJK-IIJU,1,1) = 0.5*( PA(JIJK-IIJU,1,1)+PA(JIJK,1,1) )
+END DO
+!
+!CDIR NODEP
+!OCL NOVREC
+DO JIJ=1,IIJU
+   PMZF4(JIJ,1,IKU)    = -999.
+END DO
+!$acc end kernels
+
+!$acc end data
+
+!-------------------------------------------------------------------------------
+!
+END FUNCTION MZF4
+!
+!-------------------------------------------------------------------------------
+!
+!     ################################
+      FUNCTION MZM4(PA)  RESULT(PMZM4)
+!     ################################
+!
+!!****  *MZM4* - 4th order Shuman operator : mean operator in z direction for a 
+!!                                 mass variable 
+!!
+!!    PURPOSE
+!!    -------
+!!      The purpose of this function is to compute a 4th order mean value
+!!    along the z direction (K index) for a field PA localized at a mass
+!!    point. The result is localized at a z-flux point (w point).
+!!
+!!**  METHOD
+!!    ------ 
+!!        The result PMZM4(:,:,k) is defined by 
+!!        PMZM4(:,:,k)=0.5*(PA(:,:,k)+PA(:,:,k+1)) at k=2 and size(PA,3)
+!!        PMZM4(:,:,k)=-999.                       at k=1
+!!        PMZM4(:,:,k)=7/12*(PA(:,:,k)+PA(:,:,k+1))
+!!                    -1/12*(PA(:,:,k-1)+PA(:,:,k+2)) elsewhere
+!!    
+!!    EXTERNAL
+!!    --------
+!!      NONE
+!!
+!!    IMPLICIT ARGUMENTS(PMEANX,PMEANY)
+!!    ------------------
+!!      NONE
+!!
+!!    REFERENCE
+!!    ---------
+!!      Book2 of documentation of Meso-NH (SHUMAN operators)
+!!      Technical specifications Report of The Meso-NH (chapters 3)  
+!!
+!!    AUTHOR
+!!    ------
+!!      J.-P. Pinty       * Lab Aerologie *
+!!
+!!    MODIFICATIONS
+!!    -------------
+!!      Original    25/10/05
+!!
+!-------------------------------------------------------------------------------
+!
+!*       0.    DECLARATIONS
+!              ------------
+!
+IMPLICIT NONE
+!
+!*       0.1   Declarations of argument and result
+!
+!
+REAL, DIMENSION(:,:,:), INTENT(IN)                :: PA     ! variable at mass 
+                                                            ! localization
+REAL, DIMENSION(SIZE(PA,1),SIZE(PA,2),SIZE(PA,3)) :: PMZM4  ! result at flux
+                                                            ! localization
+!
+!*       0.2   Declarations of local variables
+!
+!
+INTEGER :: JK               ! loop index in z direction
+INTEGER :: IKU              ! upper bound in z direction of PA 
+!     
+INTEGER :: IIU,IJU,IIJU     ! upper bounds in the x and y directions of PA
+INTEGER :: JIJ,JIJK         ! running loop indexes after linearisation
+INTEGER :: JIJKOR1,JIJKEND1 ! loop boundaries
+INTEGER :: JIJKOR2,JIJKEND2 ! loop boundaries
+!
+!-------------------------------------------------------------------------------
+
+!$acc data present( PA, PMZM4 )
+!
+!*       1.    DEFINITION OF MZM4
+!              ------------------
+!
+IIU = SIZE(PA,1)
+IJU = SIZE(PA,2)
+IKU = SIZE(PA,3)
+!
+IIJU = IIU*IJU
+!
+JIJKOR1  = 1 + IIJU
+JIJKEND1 = JIJKOR1 + IIJU
+!
+!$acc kernels
+!CDIR NODEP
+!OCL NOVREC
+DO JIJK=JIJKOR1 , JIJKEND1
+   PMZM4(JIJK,1,1) = 0.5*( PA(JIJK,1,1)+PA(JIJK-IIJU,1,1) )
+END DO
+!
+JIJKOR2  = 1 + JIJKEND1
+JIJKEND2 = IIJU*IKU - IIJU
+!
+!CDIR NODEP
+!OCL NOVREC
+DO JIJK=JIJKOR2 , JIJKEND2
+   PMZM4(JIJK,1,1) = (7.0*( PA(JIJK,1,1)+PA(JIJK-IIJU,1,1) ) -      &
+                          ( PA(JIJK+IIJU,1,1)+PA(JIJK-2*IIJU,1,1) ) )/12.0
+END DO
+!
+!CDIR NODEP
+!OCL NOVREC
+DO JIJ=1,IIJU
+   PMZM4(JIJ,1,IKU) = 0.5*( PA(JIJ,1,IKU)+PA(JIJ-IIJU,1,IKU) )
+END DO
+!
+!CDIR NODEP
+!OCL NOVREC
+DO JIJ=1,IIJU
+   PMZM4(JIJ,1,1)    = -999.
+END DO
+!$acc end kernels
+
+!$acc end data
+
+!-------------------------------------------------------------------------------
+!
+END FUNCTION MZM4
diff --git a/src/ZSOLVER/advecuvw_4th.f90 b/src/ZSOLVER/advecuvw_4th.f90
new file mode 100644
index 000000000..d523b56f5
--- /dev/null
+++ b/src/ZSOLVER/advecuvw_4th.f90
@@ -0,0 +1,382 @@
+!MNH_LIC Copyright 2005-2022 CNRS, Meteo-France and Universite Paul Sabatier
+!MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence
+!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_ADVECUVW_4TH
+!     ###########################
+!
+INTERFACE
+!
+      SUBROUTINE ADVECUVW_4TH ( HLBCX, HLBCY, PRUCT, PRVCT, PRWCT,           &
+                                PUT, PVT, PWT, PRUS, PRVS, PRWS, TPHALO2LIST )              
+!
+USE MODD_ARGSLIST_ll, ONLY : HALO2LIST_ll
+!
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCX ! X direction LBC type
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCY ! Y direction LBC type
+!
+REAL, DIMENSION(:,:,:),   INTENT(IN)    :: PRUCT ! contravariant
+REAL, DIMENSION(:,:,:),   INTENT(IN)    :: PRVCT !  components
+REAL, DIMENSION(:,:,:),   INTENT(IN)    :: PRWCT ! of momentum
+!
+REAL, DIMENSION(:,:,:),   INTENT(IN) :: PUT, PVT, PWT        ! U,V,W at t
+!
+REAL, DIMENSION(:,:,:),   INTENT(INOUT) :: PRUS, PRVS, PRWS     ! Source terms
+!
+TYPE(HALO2LIST_ll), POINTER :: TPHALO2LIST ! list for diffusion
+!
+END SUBROUTINE ADVECUVW_4TH
+!
+END INTERFACE
+!
+END MODULE MODI_ADVECUVW_4TH
+!
+!
+!     ######################################################################
+      SUBROUTINE ADVECUVW_4TH ( HLBCX, HLBCY, PRUCT, PRVCT, PRWCT,           &
+                                PUT, PVT, PWT, PRUS, PRVS, PRWS, TPHALO2LIST )              
+!     ######################################################################
+!
+!!****  *ADVECUVW_4TH * - routine to compute the 4th order centered
+!!                           advection tendency of momentum (U,V,W)
+!!
+!!    PURPOSE
+!!    -------
+!!      The purpose of this routine is to call the ADVEC_4TH_ORDER_ALGO
+!!    routine for the horizontal advection and the MZM4 and MZF4 functions for
+!!    the vertical advection of momentum. The code is 
+!!    parallelized and works for various boundary conditions.
+!!
+!!**  METHOD
+!!    ------
+!!      For each wind component the ADVECUVW_4TH routine calls
+!!    the ADVEC_4TH_ORDER_ALGO routine which computes the numerical advection
+!!    of any 3D field.
+!!      The following variables are passed as argument to ADVEC_4TH_ORDER_ALGO :
+!!
+!!    -- The variable at t
+!!    -- The second layer of the halo of the field at t
+!!    -- The horizontal advection fluxes
+!!    -- The localisation on the model grid :
+!!
+!!        IGRID = 1 for mass grid point
+!!        IGRID = 2 for U grid point
+!!        IGRID = 3 for V grid point
+!!        IGRID = 4 for W grid point
+!!
+!!    EXTERNAL
+!!    --------
+!!      BUDGET      : Stores the different budget components
+!!                    (not used in current version)
+!!      ADVEC_4TH_ORDER_ALGO : computes the horizontal advection fluxes
+!!      MZF4 and MZM4 : computes the vertical advection fluxes
+!!
+!!    IMPLICIT ARGUMENTS
+!!    ------------------
+!!    MODULE MODD_BUDGET:
+!!         NBUMOD       : model in which budget is calculated
+!!         CBUTYPE      : type of desired budget
+!!                          'CART' for cartesian box configuration
+!!                          'MASK' for budget zone defined by a mask
+!!                          'NONE'  ' for no budget
+!!         NBUPROCCTR   : process counter used for each budget variable
+!!         Switches for budgets activations:
+!!
+!!    MODULE MODD_ARGSLIST
+!!         HALO2LIST_ll : type for a list of "HALO2_lls"
+!!
+!!    REFERENCE
+!!    ---------
+!!      Book2 of documentation ( routine ADVECUVW_4TH )
+!!
+!!    AUTHOR
+!!    ------
+!!      J.-P. Pinty      * Laboratoire d'Aerologie*
+!!
+!!    MODIFICATIONS
+!!    -------------
+!!      Original   25/10/05
+!!      Modif
+!!      J.Escobar 21/03/2013: for HALOK comment all NHALO=1 test
+!!
+!-------------------------------------------------------------------------------
+!
+!*       0.    DECLARATIONS
+!              ------------
+!
+USE MODD_ARGSLIST_ll, ONLY : HALO2LIST_ll
+USE MODD_CONF
+USE MODD_GRID_n
+USE MODD_PARAMETERS
+
+USE MODE_ll
+#ifdef MNH_OPENACC
+USE MODE_MNH_ZWORK,   ONLY: MNH_MEM_GET, MNH_MEM_POSITION_PIN, MNH_MEM_RELEASE
+#endif
+use mode_mppdb
+
+USE MODI_ADVEC_4TH_ORDER_AUX
+#ifndef MNH_OPENACC
+USE MODI_SHUMAN
+#else
+USE MODI_SHUMAN_DEVICE
+#endif
+!
+IMPLICIT NONE
+!
+!*       0.1   Declarations of dummy arguments :
+!
+!
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCX ! X direction LBC type
+CHARACTER (LEN=4), DIMENSION(2), INTENT(IN) :: HLBCY ! Y direction LBC type
+!
+!
+REAL, DIMENSION(:,:,:),   INTENT(IN)    :: PRUCT  ! contravariant
+REAL, DIMENSION(:,:,:),   INTENT(IN)    :: PRVCT  !  components
+REAL, DIMENSION(:,:,:),   INTENT(IN)    :: PRWCT  ! of momentum
+!
+REAL, DIMENSION(:,:,:),   INTENT(IN) :: PUT, PVT, PWT        ! Variables at t
+!
+REAL, DIMENSION(:,:,:),   INTENT(INOUT) :: PRUS, PRVS, PRWS     ! Source terms
+!
+TYPE(HALO2LIST_ll), POINTER :: TPHALO2LIST ! list for diffusion
+!
+!*       0.2   Declarations of local variables :
+!
+TYPE(HALO2LIST_ll), POINTER :: TZHALO2LIST
+!
+INTEGER :: IGRID ! localisation on the model grid
+#ifndef MNH_OPENACC
+REAL, DIMENSION(SIZE(PUT,1),SIZE(PUT,2),SIZE(PUT,3)) :: ZMEANX, ZMEANY ! fluxes
+#else
+INTEGER                                     :: IIU, IJU, IKU
+REAL, DIMENSION(:,:,:), POINTER, CONTIGUOUS :: ZMEANX, ZMEANY ! fluxes
+!
+REAL, DIMENSION(:,:,:), POINTER, CONTIGUOUS :: ZTEMP1, ZTEMP2, ZTEMP3, ZTEMP4
+#endif
+!
+#if 0
+#define dxm(PDXM,PA) PDXM(2:IIU,:,:)   = PA(2:IIU,:,:) - PA(1:IIU-1,:,:)       ; PDXM(1,:,:) = PDXM(IIU-2*JPHEXT+1,:,:) ! DXM(PDXM,PA)
+#define mxf(PMXF,PA) PMXF(1:IIU-1,:,:) = 0.5*( PA(2:IIU,:,:)+PA(1:IIU-1,:,:) ) ; PMXF(IIU,:,:) = PMXF(2*JPHEXT,:,:) ! MXF(PMXF,PA)
+#define mxm(PMXM,PA) PMXM(2:IIU,:,:) = 0.5*( PA(2:IIU,:,:)+PA(1:IIU-1,:,:) ) ; PMXM(1,:,:) = PMXM(IIU-2*JPHEXT+1,:,:) ! MXM(PMXM,PA)
+#define dyf(PDYF,PA) PDYF(:,1:IJU-1,:) = PA(:,2:IJU,:) - PA(:,1:IJU-1,:) ; PDYF(:,IJU,:) = PDYF(:,2*JPHEXT,:) ! DYF(PDYF,PA)
+#define dzf(PDZF,PA) PDZF(:,:,1:IKU-1) = PA(:,:,2:IKU) - PA(:,:,1:IKU-1) ; PDZF(:,:,IKU) = -999. ! DZF(PDZF,PA)
+#define mzm4(PMZM4,PA) PMZM4(:,:,3:IKU-1) = (7.0*( PA(:,:,3:IKU-1)+PA(:,:,2:IKU-2) ) - (PA(:,:,4:IKU)+PA(:,:,1:IKU-3) ) )/12.0 ; \
+  PMZM4(:,:,2) = 0.5*( PA(:,:,2)+PA(:,:,1) ) ; PMZM4(:,:,IKU) = 0.5*( PA(:,:,IKU)+PA(:,:,IKU-1) ) ; PMZM4(:,:,1) = -999.
+#define mym(PMYM,PA) PMYM(:,2:IJU,:) = 0.5*( PA(:,2:IJU,:)+PA(:,1:IJU-1,:) ) ; PMYM(:,1,:) = PMYM(:,IJU-2*JPHEXT+1,:) !  MYM(PMYM,PA)
+#define dxf(PDXF,PA) PDXF(1:IIU-1,:,:) = PA(2:IIU,:,:) - PA(1:IIU-1,:,:) ; PDXF(IIU,:,:)    = PDXF(2*JPHEXT,:,:) ! DXF(PDXF,PA)
+#define myf(PMYF,PA) PMYF(:,1:IJU-1,:) = 0.5*( PA(:,1:IJU-1,:)+PA(:,2:IJU,:) ) ; PMYF(:,IJU,:) = PMYF(:,2*JPHEXT,:) ! MYF(PMYF,PA)
+#define dym(PDYM,PA) PDYM(:,2:IJU,:) = PA(:,2:IJU,:) - PA(:,1:IJU-1,:) ; PDYM(:,1,:) = PDYM(:,IJU-2*JPHEXT+1,:) ! DYM(PDYM,PA)
+#define mzm(PMZM,PA) PMZM(:,:,2:IKU) = 0.5*( PA(:,:,2:IKU)+PA(:,:,1:IKU-1) ) ; PMZM(:,:,1)    = -999. !  MZM(PMZM,PA)
+#define mzf(PMZF,PA) PMZF(:,:,1:IKU-1) = 0.5*( PA(:,:,1:IKU-1)+PA(:,:,2:IKU) ) ; PMZF(:,:,IKU) = -999. ! MZF(PMZF,PA)
+#define dzm(PDZM,PA) PDZM(:,:,2:IKU) = PA(:,:,2:IKU) - PA(:,:,1:IKU-1) ; PDZM(:,:,1) = -999. !  DZM(PDZM,PA)
+#define mzf4(PMZF4,PA) PMZF4(:,:,2:IKU-2) = (7.0*( PA(:,:,3:IKU-1)+PA(:,:,2:IKU-2) ) - (PA(:,:,4:IKU)+PA(:,:,1:IKU-3) ) )/12.0 ; \
+  PMZF4(:,:,1) = 0.5*( PA(:,:,2)+PA(:,:,1) ) ; PMZF4(:,:,IKU-1) = 0.5*( PA(:,:,IKU)+PA(:,:,IKU-1) ) ; PMZF4(:,:,IKU) = -999.
+#endif
+!
+IF (MPPDB_INITIALIZED) THEN
+  !Check all IN arrays
+  CALL MPPDB_CHECK(PRUCT,"ADVECUVW_4TH beg:PRUCT")
+  CALL MPPDB_CHECK(PRVCT,"ADVECUVW_4TH beg:PRVCT")
+  CALL MPPDB_CHECK(PRWCT,"ADVECUVW_4TH beg:PRWCT")
+  CALL MPPDB_CHECK(PUT,"ADVECUVW_4TH beg:PUT")
+  CALL MPPDB_CHECK(PVT,"ADVECUVW_4TH beg:PVT")
+  CALL MPPDB_CHECK(PWT,"ADVECUVW_4TH beg:PWT")
+  !Check all INOUT arrays
+  CALL MPPDB_CHECK(PRUS,"ADVECUVW_4TH beg:PRUS")
+  CALL MPPDB_CHECK(PRVS,"ADVECUVW_4TH beg:PRVS")
+  CALL MPPDB_CHECK(PRWS,"ADVECUVW_4TH beg:PRWS")
+END IF
+
+#ifdef MNH_OPENACC
+IIU = SIZE( PUT, 1 )
+IJU = SIZE( PUT, 2 )
+IKU = SIZE( PUT, 3 )
+
+!Pin positions in the pools of MNH memory
+CALL MNH_MEM_POSITION_PIN()
+
+CALL MNH_MEM_GET( ZMEANX, IIU, IJU, IKU )
+CALL MNH_MEM_GET( ZMEANY, IIU, IJU, IKU )
+
+CALL MNH_MEM_GET( ZTEMP1, IIU, IJU, IKU )
+CALL MNH_MEM_GET( ZTEMP2, IIU, IJU, IKU )
+CALL MNH_MEM_GET( ZTEMP3, IIU, IJU, IKU )
+CALL MNH_MEM_GET( ZTEMP4, IIU, IJU, IKU )
+#endif
+
+!$acc data present( PRUCT, PRVCT, PRWCT, PUT, PVT, PWT, PRUS, PRVS, PRWS, ZMEANX, ZMEANY, ZTEMP1, ZTEMP2, ZTEMP3, ZTEMP4 )
+
+!-------------------------------------------------------------------------------
+!
+!*       2.     CALL THE ADVEC_4TH_ORDER_ALGO ROUTINE FOR MOMENTUM
+!               --------------------------------------------------
+!
+IGRID = 2
+!!$IF(NHALO == 1) THEN
+  TZHALO2LIST => TPHALO2LIST
+  CALL ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PUT, IGRID, ZMEANX, ZMEANY, &
+                            TZHALO2LIST%HALO2 )
+!!$ELSE
+!!$  CALL ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PUT, IGRID, ZMEANX, ZMEANY)
+!!$ENDIF
+!
+#ifndef MNH_OPENACC
+PRUS(:,:,:) = PRUS(:,:,:)                          &
+             -DXM( MXF(PRUCT(:,:,:))*ZMEANX(:,:,:) ) 
+!
+PRUS(:,:,:) = PRUS(:,:,:)                          &
+             -DYF( MXM(PRVCT(:,:,:))*ZMEANY(:,:,:) ) 
+!
+PRUS(:,:,:) = PRUS(:,:,:)                             &
+             -DZF( MXM(PRWCT(:,:,:))*MZM4(PUT(:,:,:)) )
+#else
+call mxf_device(PRUCT,ZTEMP1)
+!$acc kernels
+ZTEMP2 = ZTEMP1 * ZMEANX
+!$acc end kernels
+call dxm_device(ZTEMP2,ZTEMP3)
+!$acc kernels
+PRUS(:,:,:) = PRUS(:,:,:) -  ZTEMP3
+!$acc end kernels
+!
+call mxm_device(PRVCT,ZTEMP1)
+!$acc kernels
+ZTEMP2 = ZTEMP1 * ZMEANY
+!$acc end kernels
+call dyf_device(ZTEMP2,ZTEMP3)
+!$acc kernels
+PRUS(:,:,:) = PRUS(:,:,:) - ZTEMP3
+!$acc end kernels
+!
+ZTEMP1 = MZM4( PUT )
+call mxm_device(PRWCT,ZTEMP2)
+!$acc kernels
+ZTEMP3 = ZTEMP1 * ZTEMP2
+!$acc end kernels
+call dzf_device( ZTEMP3, ZTEMP4 )
+!$acc kernels
+PRUS(:,:,:) = PRUS(:,:,:) - ZTEMP4
+!$acc end kernels
+#endif
+!
+!
+IGRID = 3
+!!$IF(NHALO == 1) THEN
+  TZHALO2LIST => TZHALO2LIST%NEXT
+  CALL ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PVT, IGRID, ZMEANX, ZMEANY, &
+                            TZHALO2LIST%HALO2 )
+!!$ELSE
+!!$  CALL ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PVT, IGRID, ZMEANX, ZMEANY)
+!!$ENDIF
+!
+#ifndef MNH_OPENACC
+PRVS(:,:,:) = PRVS(:,:,:)                          &
+             -DXF( MYM(PRUCT(:,:,:))*ZMEANX(:,:,:) ) 
+!
+PRVS(:,:,:) = PRVS(:,:,:)                          &
+             -DYM( MYF(PRVCT(:,:,:))*ZMEANY(:,:,:) )  
+!
+PRVS(:,:,:) = PRVS(:,:,:)                             &
+             -DZF( MYM(PRWCT(:,:,:))*MZM4(PVT(:,:,:)) )
+#else
+call mym_device(PRUCT,ZTEMP1)
+!$acc kernels
+ZTEMP2 = ZTEMP1 * ZMEANX
+!$acc end kernels
+call dxf_device(ZTEMP2,ZTEMP3)
+!$acc kernels
+PRVS(:,:,:) = PRVS(:,:,:) -  ZTEMP3
+!$acc end kernels
+!
+call myf_device(PRVCT,ZTEMP1)
+!$acc kernels
+ZTEMP2 = ZTEMP1 * ZMEANY
+!$acc end kernels
+call dym_device(ZTEMP2,ZTEMP3)
+!$acc kernels
+PRVS(:,:,:) = PRVS(:,:,:) - ZTEMP3
+!$acc end kernels
+!
+call mym_device(PRWCT,ZTEMP1)
+ZTEMP2 = MZM4( PVT )
+!$acc kernels
+ZTEMP3 = ZTEMP1 * ZTEMP2
+!$acc end kernels
+call dzf_device( ZTEMP3, ZTEMP4 )
+!$acc kernels
+PRVS(:,:,:) = PRVS(:,:,:) - ZTEMP4
+!$acc end kernels
+#endif
+CALL MPPDB_CHECK(PRUCT,"ADVECUVW_4TH 02: PRUCT")
+!
+!
+IGRID = 4
+!
+!!$IF(NHALO == 1) THEN
+  TZHALO2LIST => TZHALO2LIST%NEXT
+  CALL ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PWT, IGRID, ZMEANX, ZMEANY, &
+                            TZHALO2LIST%HALO2 )
+!!$ELSE
+!!$  CALL ADVEC_4TH_ORDER_ALGO(HLBCX, HLBCY, PWT, IGRID, ZMEANX, ZMEANY)
+!!$ENDIF
+!
+#ifndef MNH_OPENACC
+PRWS(:,:,:) = PRWS(:,:,:)                          &
+             -DXF( MZM(PRUCT(:,:,:))*ZMEANX(:,:,:) )
+!
+PRWS(:,:,:) = PRWS(:,:,:)                          &
+             -DYF( MZM(PRVCT(:,:,:))*ZMEANY(:,:,:) )
+!
+PRWS(:,:,:) = PRWS(:,:,:)                             &
+             -DZM( MZF(PRWCT(:,:,:))*MZF4(PWT(:,:,:)) )
+#else
+call mzm_device(PRUCT,ZTEMP1)
+!$acc kernels
+ZTEMP2 = ZTEMP1 * ZMEANX
+!$acc end kernels
+call dxf_device(ZTEMP2,ZTEMP3)
+!$acc kernels
+PRWS(:,:,:) = PRWS(:,:,:)  - ZTEMP3
+!$acc end kernels
+!
+call mzm_device(PRVCT,ZTEMP1)
+!$acc kernels
+ZTEMP2 = ZTEMP1 * ZMEANY
+!$acc end kernels
+call dyf_device(ZTEMP2,ZTEMP3)
+!$acc kernels
+PRWS(:,:,:) = PRWS(:,:,:) - ZTEMP3
+!$acc end kernels
+!
+call mzf_device( PRWCT, ZTEMP1 )
+ZTEMP2 = MZF4( PWT )
+!$acc kernels
+ZTEMP1 = ZTEMP1 * ZTEMP2
+!$acc end kernels
+call dzm_device( ZTEMP1, ZTEMP4 )
+!$acc kernels
+PRWS(:,:,:) = PRWS(:,:,:) - ZTEMP4
+!$acc end kernels
+#endif
+
+!$acc end data
+
+#ifdef MNH_OPENACC
+!Release all memory allocated with MNH_MEM_GET calls since last call to MNH_MEM_POSITION_PIN
+CALL MNH_MEM_RELEASE()
+#endif
+
+IF (MPPDB_INITIALIZED) THEN
+  !Check all INOUT arrays
+  CALL MPPDB_CHECK(PRUS,"ADVECUVW_4TH end:PRUS")
+  CALL MPPDB_CHECK(PRVS,"ADVECUVW_4TH end:PRVS")
+  CALL MPPDB_CHECK(PRWS,"ADVECUVW_4TH end:PRWS")
+END IF
+
+!-------------------------------------------------------------------------------
+!
+!
+END SUBROUTINE ADVECUVW_4TH
-- 
GitLab