SUBROUTINE PREGPFPOS (LDBEFORE,LDPHY,LDXFU,LDCFU)

!**** *PREGPFPOS*  - Prepare Full Post-Processing on grid point fields

!     PURPOSE.
!     --------
!        To save model gp data and pack current data before go post-processing

!**   INTERFACE.
!     ----------
!       *CALL* *PREGPFPOS*

!        EXPLICIT ARGUMENTS
!        --------------------
!           LDBEFORE: .TRUE.  = operation to be performed BEFORE post-processing
!                   : .FALSE. = operation to be performed AFTER  post-processing
!           LDPHY   : Post-processing on physical fields activated
!           LDXFU   : Post-processing on instantaneous fluxes activated
!           LDCFU   : Post-processing on cumulated fluxes activated

!        IMPLICIT ARGUMENTS
!        --------------------
!        NONE.

!     METHOD.
!     -------
!        SEE DOCUMENTATION

!     EXTERNALS.
!     ----------

!     REFERENCE.
!     ----------
!        ECMWF Research Department documentation of the IFS

!     AUTHOR.
!     -------
!        RYAD EL KHATIB *METEO-FRANCE*

!     MODIFICATIONS.
!     --------------
!        ORIGINAL : 98-01-28 by R. El Khatib (from gridfpos)

!        Modified : 00-11-23 by R. Randriamampianina: 
!                                  Skip process for empty buffers.
!       R. El Khatib : 03-05-16 (Fix) parity array
!        M.Hamrud      01-Oct-2003 CY28 Cleaning
!        M.Hamrud      10-Jan-2004 CY28R1 Cleaning
!        M.Hamrud      01-Jul-2006  Revised surface fields
!     ------------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
USE YOMCT0   , ONLY : LARPEGEF ,LRPLANE
USE YOMCFU   , ONLY : NFDCFU   ,NTYPCFU  ,TYPE_CFU
USE YOMGFUB  , ONLY : GFUBUF
USE YOMXFU   , ONLY : NFDXFU   ,NTYPXFU  ,TYPE_XFU
USE YOMXFUB  , ONLY : XFUBUF
USE YOMGPSK  , ONLY : GPSCFBUF ,GPSXFBUF
USE SURFACE_FIELDS_MIX  , ONLY : NSURF, SURF_STORE, SURF_RESTORE, &
 & YSP_SBD  ,SP_SB    ,YSP_SGD  ,SP_SG    ,YSP_RRD  ,SP_RR    ,YSP_EPD  , &
 & SP_EP    ,YSP_X2D  ,SP_X2    ,YSP_CID  ,SP_CI    ,YSD_VFD  ,SD_VF    , &
 & YSD_VPD  ,SD_VP    ,YSD_VVD  ,SD_VV    ,YSD_VND  ,SD_VN    ,YSD_VHD  , &
 & SD_VH    ,YSD_VAD  ,SD_VA    ,YSD_VCD  ,SD_VC    ,YSD_VDD  ,SD_VD    , &
 & YSD_WSD  ,SD_WS
USE YOMGC    , ONLY : GM
USE YOMDIM   , ONLY : NPROMA
USE YOMGEM   , ONLY : NGPTOT
USE GRIDPOINT_BUFFERS_MIX , ONLY : ALLOCATED_GRIDPOINT_BUFFER, &
 & ALLOCATE_GRIDPOINT_BUFFER,  &
 & DEALLOCATE_GRIDPOINT_BUFFER  

IMPLICIT NONE
LOGICAL           ,INTENT(IN)    :: LDBEFORE 
LOGICAL           ,INTENT(IN)    :: LDPHY 
LOGICAL           ,INTENT(IN)    :: LDXFU 
LOGICAL           ,INTENT(IN)    :: LDCFU 
INTEGER(KIND=JPIM) :: IFLDPTC(NFDCFU), IFLDPTX(NFDXFU)
INTEGER(KIND=JPIM) :: IPARC(NFDCFU), IPARX(NFDXFU)

INTEGER(KIND=JPIM) :: JF, JL, IOFF, JKGLO, IST, IEND, JROF

REAL(KIND=JPRB) :: Z1SGM(NPROMA)
REAL(KIND=JPRB), ALLOCATABLE :: ZGP(:,:)

LOGICAL :: LLAFTER
REAL(KIND=JPRB) :: ZHOOK_HANDLE


#include "cpgridf.intfb.h"
#include "pkgrida.intfb.h"
#include "pksurfa.intfb.h"
#include "sc2rdg.intfb.h"
#include "sc2wrg.intfb.h"

!     ------------------------------------------------------------------

IF (LHOOK) CALL DR_HOOK('PREGPFPOS',0,ZHOOK_HANDLE)
CALL GSTATS(1742,0)

!*       1. BEFORE POST-PROCESSING
!           ----------------------

IST=1

!        1.1 Save & pack physical fields

IF (LDPHY.AND.LDBEFORE) THEN
  CALL SURF_STORE
  IF (LARPEGEF) THEN
    IF (YSP_SBD%NUMFLDS > 0) CALL PKSURFA(KN=YSP_SBD%NUMFLDS,KL=YSP_SBD%NLEVS,P3=SP_SB)
    IF (YSP_SGD%NUMFLDS > 0) CALL PKSURFA(KN=YSP_SGD%NUMFLDS,P2=SP_SG)
    IF (YSP_RRD%NUMFLDS > 0) CALL PKSURFA(KN=YSP_RRD%NUMFLDS,P2=SP_RR)
    IF (YSP_EPD%NUMFLDS > 0) CALL PKSURFA(KN=YSP_EPD%NUMFLDS,KL=YSP_SBD%NLEVS,P3=SP_EP)
    IF (YSP_X2D%NUMFLDS > 0) CALL PKSURFA(KN=YSP_X2D%NUMFLDS,P2=SP_X2)
    IF (YSP_CID%NUMFLDS > 0) CALL PKSURFA(KN=YSP_CID%NUMFLDS,P2=SP_CI)
    IF (YSD_VFD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VFD%NUMFLDS,P2=SD_VF)
    IF (YSD_VPD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VPD%NUMFLDS,P2=SD_VP)
    IF (YSD_VVD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VVD%NUMFLDS,P2=SD_VV)
    IF (YSD_VND%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VND%NUMFLDS,P2=SD_VN)
    IF (YSD_VHD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VHD%NUMFLDS,P2=SD_VH)
    IF (YSD_VAD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VAD%NUMFLDS,P2=SD_VA)
    IF (YSD_VCD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VCD%NUMFLDS,P2=SD_VC)
    IF (YSD_VDD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_VDD%NUMFLDS,P2=SD_VD)
    IF (YSD_WSD%NUMFLDS > 0) CALL PKSURFA(KN=YSD_WSD%NUMFLDS,P2=SD_WS)
  ENDIF
ENDIF

!        1.2 Save & pack instantaneous fluxes

IF (LDXFU.AND.LDBEFORE.AND.NFDXFU > 0) THEN
  IF(.NOT.ALLOCATED_GRIDPOINT_BUFFER(GPSXFBUF))THEN
    CALL ALLOCATE_GRIDPOINT_BUFFER('GPSXFBUF',GPSXFBUF,XFUBUF%IFIELDS, &
     & XFUBUF%IPACK)  
  ENDIF
  CALL CPGRIDF(XFUBUF,GPSXFBUF)
  DO JF=1,NFDXFU
    IFLDPTX(JF)=JF
  ENDDO
  IF (LRPLANE) THEN
    IOFF=0
    DO JF=1,NTYPXFU
      DO JL=1,TYPE_XFU(JF)%ILEV
        IPARX(IOFF+JL)=TYPE_XFU(JF)%IPARITY
      ENDDO
      IOFF=IOFF+TYPE_XFU(JF)%ILEV
    ENDDO
    IF (ANY(IPARX==1)) THEN
      ALLOCATE(ZGP(NPROMA,NFDXFU))
      DO JKGLO=1,NGPTOT,NPROMA
        IEND=MIN(NPROMA,NGPTOT-JKGLO+1)
        CALL SC2RDG(XFUBUF,JKGLO,IST,IEND,ZGP)
        DO JF=1,NFDXFU
          IF (IPARX(JF) == 1) THEN
            DO JROF=IST,IEND
              ZGP(JROF,JF)=ZGP(JROF,JF)*GM(JROF+JKGLO-1)
            ENDDO
          ENDIF
        ENDDO
        CALL SC2WRG(XFUBUF,JKGLO,IST,IEND,ZGP)
      ENDDO
    ENDIF
  ENDIF
  IF (LARPEGEF) THEN
    CALL PKGRIDA(NFDXFU,XFUBUF,IFLDPTX)
  ENDIF
  IF (LRPLANE) THEN
    IF (ANY(IPARX==1)) THEN
      DO JKGLO=1,NGPTOT,NPROMA
        IEND=MIN(NPROMA,NGPTOT-JKGLO+1)
        CALL SC2RDG(XFUBUF,JKGLO,IST,IEND,ZGP)
        DO JROF=IST,IEND
          Z1SGM(JROF)=1.0_JPRB/GM(JROF+JKGLO-1)
        ENDDO
        DO JF=1,NFDXFU
          IF (IPARX(JF) == 1) THEN
            DO JROF=IST,IEND
              ZGP(JROF,JF)=ZGP(JROF,JF)*Z1SGM(JROF)
            ENDDO
          ENDIF
        ENDDO
        CALL SC2WRG(XFUBUF,JKGLO,IST,IEND,ZGP)
      ENDDO
      DEALLOCATE(ZGP)
    ENDIF
  ENDIF
ENDIF

!        1.3 Save & pack cumulated fluxes

IF (LDCFU.AND.LDBEFORE.AND.NFDCFU > 0) THEN
  IF(.NOT.ALLOCATED_GRIDPOINT_BUFFER(GPSCFBUF))THEN
    CALL ALLOCATE_GRIDPOINT_BUFFER('GPSCFBUF',GPSCFBUF,GFUBUF%IFIELDS, &
     & GFUBUF%IPACK)  
  ENDIF
  CALL CPGRIDF(GFUBUF,GPSCFBUF)
  IOFF=0
  DO JF=1,NFDCFU
    IFLDPTC(JF)=JF
  ENDDO
  IF (LRPLANE) THEN
    IOFF=0
    DO JF=1,NTYPCFU
      DO JL=1,TYPE_CFU(JF)%ILEV
        IPARC(IOFF+JL)=TYPE_CFU(JF)%IPARITY
      ENDDO
      IOFF=IOFF+TYPE_CFU(JF)%ILEV
    ENDDO
    IF (ANY(IPARC==1)) THEN
      ALLOCATE(ZGP(NPROMA,NFDCFU))
      DO JKGLO=1,NGPTOT,NPROMA
        IEND=MIN(NPROMA,NGPTOT-JKGLO+1)
        CALL SC2RDG(GFUBUF,JKGLO,IST,IEND,ZGP)
        DO JF=1,NFDCFU
          IF (IPARC(JF) == 1) THEN
            DO JROF=IST,IEND
              ZGP(JROF,JF)=ZGP(JROF,JF)*GM(JROF+JKGLO-1)
            ENDDO
          ENDIF
        ENDDO
        CALL SC2WRG(GFUBUF,JKGLO,IST,IEND,ZGP)
      ENDDO
    ENDIF
  ENDIF  
  IF (LARPEGEF) THEN
    CALL PKGRIDA(NFDCFU,GFUBUF,IFLDPTC)
  ENDIF
  IF (LRPLANE) THEN
    IF (ANY(IPARC==1)) THEN
      DO JKGLO=1,NGPTOT,NPROMA
        IEND=MIN(NPROMA,NGPTOT-JKGLO+1)
        CALL SC2RDG(GFUBUF,JKGLO,IST,IEND,ZGP)
        DO JROF=IST,IEND
          Z1SGM(JROF)=1.0_JPRB/GM(JROF+JKGLO-1)
        ENDDO
        DO JF=1,NFDCFU
          IF (IPARC(JF) == 1) THEN
            DO JROF=IST,IEND
              ZGP(JROF,JF)=ZGP(JROF,JF)*Z1SGM(JROF)
            ENDDO
          ENDIF
        ENDDO
        CALL SC2WRG(GFUBUF,JKGLO,IST,IEND,ZGP)
      ENDDO
      DEALLOCATE(ZGP)
    ENDIF
  ENDIF
ENDIF

!*       2. AFTER POST-PROCESSING
!           ---------------------

LLAFTER=.NOT.LDBEFORE

!        1.2 Recover physical fields

IF (LDPHY.AND.LLAFTER.AND.NSURF > 0) THEN
  CALL SURF_RESTORE
ENDIF

!        1.2 Recover instantaneous fluxes 

IF (LDXFU.AND.LLAFTER.AND.NFDXFU > 0) THEN
  CALL CPGRIDF(GPSXFBUF,XFUBUF)
  IF ( ALLOCATED_GRIDPOINT_BUFFER(GPSXFBUF) ) THEN
    CALL DEALLOCATE_GRIDPOINT_BUFFER(GPSXFBUF)
  ENDIF
ENDIF

!        1.3 Recover cumulated fluxes 

IF (LDCFU.AND.LLAFTER.AND.NFDCFU > 0) THEN
  CALL CPGRIDF(GPSCFBUF,GFUBUF)
  IF (ALLOCATED_GRIDPOINT_BUFFER(GPSCFBUF) ) THEN
    CALL DEALLOCATE_GRIDPOINT_BUFFER(GPSCFBUF)
  ENDIF
ENDIF

CALL GSTATS(1742,1)

! ---------------------------------------------------------------------
IF (LHOOK) CALL DR_HOOK('PREGPFPOS',1,ZHOOK_HANDLE)
END SUBROUTINE PREGPFPOS
