SUBROUTINE GNH_CONV_PRHS( &
 ! ----- INPUT ---------------------------------------------------------------
 & LDMODEL_TO_FILE,PT,PQ,PL,PI,PR,PS,PG, &
 ! ----- INPUT-OUTPUT --------------------------------------------------------
 & PSPD,PSP)

!* GNH_CONV_PRHS 
!  - Conversion of NH variables (model to file and vice-versa).
!    Part of the conversion relevant if LRWSDLR=T, to convert quantities 
!    based on "prehyd" towards quantities based on "presim" (or the reverse
!    one).
!    Grid-point part.

! Purpose
! -------
!   Converts:
!    log(prehyds) <-> log(presims)
!    pre-prehyd <-> pre-presim 
!   Conversion also acts on derivatives, but it does not appear in this routine.

!   Note that:
!   - in theory, GPPREH+GPXYB+GPPREF can be used for "presim", not for "prehyd"
!     ("prehyd" no longer writes as prehyd=A+B*prehyds).
!   - the conversion FILE to MODEL requires an iterative algorithm because
!     we must compute both "r/a" and "presim", and we need to use "prehyd"
!     to compute a first guess of "r/a".
!   - the conversion MODEL to FILE is simpler: we can use routine GNHDLRA
!     to compute "r/a", and then use "r/a" to convert from "presim" to "prehyd".
!   - variables such as NPDVAR, NVDVAR, LNH_PDVD, LNH_GEOGW should never be
!     used in this routine, because we simply modify quantities as they are
!     stored on files, we never use the "prognostic-variable" format in this
!     routine.
!   - more generally, this routine exists because we don't want to make the
!     file stored variables dependent on the dynamical options: even if the
!     model discretisation is based on "presim", variables stored on files
!     should always be based on "prehyd", and "presim" should never appear in
!     files.

!   Model to file: the code has the following structure:
!   - compute "a/r", and also "presim" at full levels,
!     [Delta presim] at full levels.
!   - compute "prehyd" from "presim" at half and full levels.
!   - compute log(prehyds).
!   - compute "pre-prehyd" from "pre-presim" at full levels.
!     pre-prehyd=(pre-presim)+(presim-prehyd).

!   File to model: the code has the following structure:
!   - save the original value of "prehyds".
!   - save the original value of "pre-prehyd" at full levels.
!   - do a "first guess" iteration, with the following structure:
!     * compute a first guess for "r/a", denoted by r(i=0)/a.
!     * compute "presim(i=0)" at half and full levels.
!     * fill PSPD with "pre-presim(i=0)".
!     * compute "presims(i=1)" and fill PSP with log(presims(i=1)).
!   - do iterations, with the following structure:
!     * compute "r(i=jiter)/a" and "presim(i=jiter)".
!     * compute "prehyd(i=jiter)" at half and full levels.
!     * fill PSPD with "pre-presim(i=jiter)".
!     * compute "presims(i=jiter+1)" and fill PSP with log(presims(i=jiter+1)).
!   - after the last iteration:
!     * print the maximum value of abs(r(i=jiter)/a - r(i=jiter-1)/a), to check
!       that the iterative algorithm converges.

!   This routine has a structure similar to GNH_CONV_NHVAR.

! Interface
! ---------
!  * INPUT:
!     LDMODEL_TO_FILE - switch for model to file / file to model conversion
!     PT     : temperature
!     PQ     : moisture
!     PL     : liquid water
!     PI     : ice
!     PR     : rain
!     PS     : snow
!     PG     : graupels

!  * INPUT-OUTPUT:
!     PSPD   : NH pressure departure variable "spd"
!     PSP    : log(prehyd)

! Externals
! ---------

! Method
! ------
!   See documentation

! Reference
! ---------
!        ECMWF Research Department documentation of the IFS
!        ARPEGE documentation (IDEUL)
!        Wood and Staniforth, 2003 (in QJRMS)

! Author
! ------
!   March-2008 K. Yessad (METEO-FRANCE/CNRM/GMAP)

! Modifications
! -------------
!  K. Yessad (March 2009): fix a bug for LRWSDLG=T
! End Modifications
!------------------------------------------------------------------------------

USE PARKIND1 , ONLY : JPIM     ,JPRB
USE YOMHOOK  , ONLY : LHOOK    ,DR_HOOK
USE YOMLUN   , ONLY : NULOUT
USE YOMDIM   , ONLY : NFLEVG   ,NPROMA
USE YOMDYNA  , ONLY : LRWSDLR  ,LRWSDLG
USE YOMDYN   , ONLY : NITPRHS
USE YOMGC    , ONLY : OROG
USE YOMGEM   , ONLY : NGPTOT
USE PAR_RDLR , ONLY : JP_ASRF  ,JP_RSAF  ,JP_DIMR

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

IMPLICIT NONE

LOGICAL,INTENT(IN)            :: LDMODEL_TO_FILE 
REAL(KIND=JPRB),INTENT(IN)    :: PT(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(IN)    :: PQ(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(IN)    :: PL(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(IN)    :: PI(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(IN)    :: PR(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(IN)    :: PS(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(IN)    :: PG(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(INOUT) :: PSPD(NGPTOT,NFLEVG)
REAL(KIND=JPRB),INTENT(INOUT) :: PSP(NGPTOT)

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

INTEGER(KIND=JPIM) :: JIST,JLEV,JROF,JITER
INTEGER(KIND=JPIM) :: IST,IEND,IPROMA

REAL(KIND=JPRB) :: ZDELP(NPROMA,NFLEVG)
REAL(KIND=JPRB) :: ZPREH(NPROMA,0:NFLEVG)
REAL(KIND=JPRB) :: ZPREHYDH(NPROMA,0:NFLEVG)
REAL(KIND=JPRB) :: ZPREF(NPROMA,NFLEVG)
REAL(KIND=JPRB) :: ZPREF_OLD(NPROMA,NFLEVG)
REAL(KIND=JPRB) :: ZPREHYDF(NPROMA,NFLEVG)
REAL(KIND=JPRB) :: ZPREHYDS_ORIG(NPROMA),ZSPD_ORIG(NPROMA,NFLEVG)
REAL(KIND=JPRB) :: ZRDLR(NPROMA,0:NFLEVG,JP_DIMR)
REAL(KIND=JPRB) :: ZRSA_OLD(NGPTOT,NFLEVG),ZRSA_NEW(NGPTOT,NFLEVG)
REAL(KIND=JPRB) :: ZRSA_DIF(NGPTOT,NFLEVG)
REAL(KIND=JPRB) :: ZZRSA2,ZZASR2,ZZRSA4,ZZASR4,ZPRT

REAL(KIND=JPRB) :: ZHOOK_HANDLE

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

#include "abor1.intfb.h"
#include "gnhdlra.intfb.h"

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

IF (LHOOK) CALL DR_HOOK('GNH_CONV_PRHS',0,ZHOOK_HANDLE)

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

!* 1. GRID POINT COMPUTATIONS
!     -----------------------

IF (.NOT.LRWSDLR) &
 & CALL ABOR1(' GNH_CONV_PRHS should not be called if LRWSDLR=F!')

IF ( LDMODEL_TO_FILE ) THEN

  !* 1.1 TRANSFORM FROM MODEL TO FILE

  ! loop through sections of length NPROMA
  DO JIST=1,NGPTOT,NPROMA

    IST    = JIST                      ! first element
    IEND   = MIN(IST+NPROMA-1,NGPTOT)  ! last element
    IPROMA = IEND-IST+1                ! actual number of elements

    !* 1.1.1 COMPUTE "r/a", "a/r" AND 'PRESIM' PRESSURES 

    CALL GNHDLRA(IPROMA,1,1,IPROMA,0,.TRUE.,.FALSE., &
     & OROG(IST:IEND),PSP(IST:IEND),&
     & PT(IST:IEND,:),PSPD(IST:IEND,:),ZRDLR(1:IPROMA,:,:), &
     & PQ=PQ(IST:IEND,:),PL=PL(IST:IEND,:),PI=PI(IST:IEND,:), &
     & PR=PR(IST:IEND,:),PS=PS(IST:IEND,:),PG=PG(IST:IEND,:), &
     & PDPI=ZDELP(1:IPROMA,:),PIF=ZPREF(1:IPROMA,:),PIH=ZPREH(1:IPROMA,:))

    !* 1.1.2 COMPUTE "PREHYD" PRESSURES 

    ZPREHYDH(1:IPROMA,0)=ZPREH(1:IPROMA,0)
    IF (LRWSDLG) THEN
      DO JLEV=1,NFLEVG
        DO JROF=1,IPROMA
          ZZASR4=ZRDLR(JROF,JLEV,JP_ASRF)**4
          ZPREHYDH(JROF,JLEV)=ZPREHYDH(JROF,JLEV-1)+ZZASR4*ZDELP(JROF,JLEV)
          ZPREHYDF(JROF,JLEV)=ZPREHYDH(JROF,JLEV) &
           & +ZZASR4*(ZPREF(JROF,JLEV)-ZPREH(JROF,JLEV))
        ENDDO
      ENDDO
    ELSE
      DO JLEV=1,NFLEVG
        DO JROF=1,IPROMA
          ZZASR2=ZRDLR(JROF,JLEV,JP_ASRF)*ZRDLR(JROF,JLEV,JP_ASRF)
          ZPREHYDH(JROF,JLEV)=ZPREHYDH(JROF,JLEV-1)+ZZASR2*ZDELP(JROF,JLEV)
          ZPREHYDF(JROF,JLEV)=ZPREHYDH(JROF,JLEV) &
           & +ZZASR2*(ZPREF(JROF,JLEV)-ZPREH(JROF,JLEV))
        ENDDO
      ENDDO
    ENDIF

    !* 1.1.3 COMPUTE LOG(PREHYDS), UPDATE "PSP"

    PSP(IST:IEND)=LOG(ZPREHYDH(1:IPROMA,NFLEVG))

    !* 1.1.4 COMPUTE "PRE-PREHYD" FROM "PRE-PRESIM", UPDATE "PSPD"

    DO JLEV=1,NFLEVG
      PSPD(IST:IEND,JLEV)=PSPD(IST:IEND,JLEV) &
       & +ZPREF(1:IPROMA,JLEV)-ZPREHYDF(1:IPROMA,JLEV)
    ENDDO

  ENDDO  ! JIST = 1,NGPTOT,NPROMA

ELSE

  !* 1.2 TRANSFORM FROM FILE TO MODEL

  ! loop through sections of length NPROMA
  DO JIST=1,NGPTOT,NPROMA

    IST    = JIST                      ! first element
    IEND   = MIN(IST+NPROMA-1,NGPTOT)  ! last element
    IPROMA = IEND-IST+1                ! actual number of elements

    !* 1.2.1 Save input "PSPD" and surface hydrostatic pressure. 

    ZSPD_ORIG(1:IPROMA,1:NFLEVG)=PSPD(IST:IEND,1:NFLEVG)
    ZPREHYDS_ORIG(1:IPROMA)=EXP(PSP(IST:IEND))

    !* 1.2.2 ITERATION 0: COMPUTE FIRST GUESS FOR "r/a". 

    DO JITER=0,0

      ! 1.2.2.A: Compute "r(i=0)/a"
      CALL GNHDLRA(IPROMA,1,1,IPROMA,0,.TRUE.,.TRUE., &
       & OROG(IST:IEND),PSP(IST:IEND),&
       & PT(IST:IEND,:),PSPD(IST:IEND,:),ZRDLR(1:IPROMA,:,:), &
       & PQ=PQ(IST:IEND,:),PL=PL(IST:IEND,:),PI=PI(IST:IEND,:), &
       & PR=PR(IST:IEND,:),PS=PS(IST:IEND,:),PG=PG(IST:IEND,:), &
       & PDPI=ZDELP(1:IPROMA,:),PIF=ZPREHYDF(1:IPROMA,:), &
       & PIH=ZPREHYDH(1:IPROMA,:))

      ! 1.2.2.B: Compute presim(i=0).
      ZPREH(1:IPROMA,0)=ZPREHYDH(1:IPROMA,0)
      IF (LRWSDLG) THEN
        DO JLEV=1,NFLEVG
          DO JROF=1,IPROMA
            ZZRSA4=ZRDLR(JROF,JLEV,JP_RSAF)**4
            ZPREH(JROF,JLEV)=ZPREH(JROF,JLEV-1) &
             & +ZZRSA4*(ZPREHYDH(JROF,JLEV)-ZPREHYDH(JROF,JLEV-1))
            ZPREF(JROF,JLEV)=ZPREH(JROF,JLEV) &
             & +ZZRSA4*(ZPREHYDF(JROF,JLEV)-ZPREHYDH(JROF,JLEV))
          ENDDO
        ENDDO
      ELSE
        DO JLEV=1,NFLEVG
          DO JROF=1,IPROMA
            ZZRSA2=ZRDLR(JROF,JLEV,JP_RSAF)*ZRDLR(JROF,JLEV,JP_RSAF)
            ZPREH(JROF,JLEV)=ZPREH(JROF,JLEV-1) &
             & +ZZRSA2*(ZPREHYDH(JROF,JLEV)-ZPREHYDH(JROF,JLEV-1))
            ZPREF(JROF,JLEV)=ZPREH(JROF,JLEV) &
             & +ZZRSA2*(ZPREHYDF(JROF,JLEV)-ZPREHYDH(JROF,JLEV))
          ENDDO
        ENDDO
      ENDIF

      ! 1.2.2.C: Update "PSPD" with "pre - presim(i=0)"
      !          PSPD(i=1)=PSPD(i=0)+(prehyd(i=0)-presim(i=0))
      DO JLEV=1,NFLEVG
        PSPD(IST:IEND,JLEV)=ZSPD_ORIG(1:IPROMA,JLEV) &
         & +ZPREHYDF(1:IPROMA,JLEV)-ZPREF(1:IPROMA,JLEV)
      ENDDO

      ! 1.2.2.D: Compute log(presims(i=1)), update "PSP"
      PSP(IST:IEND)=LOG(ZPREH(1:IPROMA,NFLEVG))
      ZPREF_OLD(1:IPROMA,1:NFLEVG)=ZPREF(1:IPROMA,1:NFLEVG)

    ENDDO

    !* 1.2.3 ITERATIONS 1 TO NITPRHS. 

    DO JITER=1,NITPRHS

      ! 1.2.3.A: Compute "r(i=jiter)/a" and "presim(i=jiter)".
      ZRSA_OLD(IST:IEND,1:NFLEVG)=ZRDLR(1:IPROMA,1:NFLEVG,JP_RSAF)
      CALL GNHDLRA(IPROMA,1,1,IPROMA,0,.TRUE.,.FALSE., &
       & OROG(IST:IEND),PSP(IST:IEND),&
       & PT(IST:IEND,:),PSPD(IST:IEND,:),ZRDLR(1:IPROMA,:,:), &
       & PIIF=ZPREF_OLD(1:IPROMA,:), &
       & PQ=PQ(IST:IEND,:),PL=PL(IST:IEND,:),PI=PI(IST:IEND,:), &
       & PR=PR(IST:IEND,:),PS=PS(IST:IEND,:),PG=PG(IST:IEND,:), &
       & PDPI=ZDELP(1:IPROMA,:), &
       & PIF=ZPREF(1:IPROMA,:),PIH=ZPREH(1:IPROMA,:))
      ZRSA_NEW(IST:IEND,1:NFLEVG)=ZRDLR(1:IPROMA,1:NFLEVG,JP_RSAF)

      ! 1.2.3.B: Use presim(i=jiter) to have a new estimation of "prehyd":
      !          provides prehyd(i=jiter).
      ZPREHYDH(1:IPROMA,0)=ZPREH(1:IPROMA,0)
      IF (LRWSDLG) THEN
        DO JLEV=1,NFLEVG
          DO JROF=1,IPROMA
            ZZASR4=ZRDLR(JROF,JLEV,JP_ASRF)**4
            ZPREHYDH(JROF,JLEV)=ZPREHYDH(JROF,JLEV-1) &
             & +ZZASR4*(ZPREH(JROF,JLEV)-ZPREH(JROF,JLEV-1))
            ZPREHYDF(JROF,JLEV)=ZPREHYDH(JROF,JLEV) &
             & +ZZASR4*(ZPREF(JROF,JLEV)-ZPREH(JROF,JLEV))
          ENDDO
        ENDDO
      ELSE
        DO JLEV=1,NFLEVG
          DO JROF=1,IPROMA
            ZZASR2=ZRDLR(JROF,JLEV,JP_ASRF)*ZRDLR(JROF,JLEV,JP_ASRF)
            ZPREHYDH(JROF,JLEV)=ZPREHYDH(JROF,JLEV-1) &
             & +ZZASR2*(ZPREH(JROF,JLEV)-ZPREH(JROF,JLEV-1))
            ZPREHYDF(JROF,JLEV)=ZPREHYDH(JROF,JLEV) &
             & +ZZASR2*(ZPREF(JROF,JLEV)-ZPREH(JROF,JLEV))
          ENDDO
        ENDDO
      ENDIF

      ! 1.2.3.C: Update "PSPD" with "pre - presim(i=jiter)"
      !          PSPD(i=jiter+1)=PSPD(i=0)+(prehyd(i=jiter)-presim(i=jiter))
      DO JLEV=1,NFLEVG
        PSPD(IST:IEND,JLEV)=ZSPD_ORIG(1:IPROMA,JLEV) &
         & +ZPREHYDF(1:IPROMA,JLEV)-ZPREF(1:IPROMA,JLEV)
      ENDDO

      ! 1.2.3.D: "prehyds(i=jiter)" may be different from the original
      !          "prehyds", so we apply a correction to "presims":
      !          presims(i=jiter+1)=presims(i=jiter)
      !           +(prehyds_orig-prehyds(i=jiter)) 
      !          Compute log(presims(i=jiter+1)), update "PSP"
      PSP(IST:IEND)=LOG(ZPREH(1:IPROMA,NFLEVG) &
       & +ZPREHYDS_ORIG(1:IPROMA)-ZPREHYDH(1:IPROMA,NFLEVG))
      ZPREF_OLD(1:IPROMA,1:NFLEVG)=ZPREF(1:IPROMA,1:NFLEVG)

    ENDDO ! JITER

  ENDDO ! JIST

  IF (NITPRHS > 0) THEN
    DO JLEV=1,NFLEVG
      DO JROF=1,NGPTOT
        ZRSA_DIF(JROF,JLEV)=ABS(ZRSA_NEW(JROF,JLEV)-ZRSA_OLD(JROF,JLEV))
      ENDDO
    ENDDO
    ZPRT=MAXVAL(ZRSA_DIF(1:NGPTOT,1:NFLEVG))
    WRITE (NULOUT,*)
    WRITE (NULOUT,*) ' TEST OF CONVERGENCE IN GNH_CONV_PRHS: ZPRT=',ZPRT
  ENDIF

ENDIF  ! LDMODEL_TO_FILE

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

IF (LHOOK) CALL DR_HOOK('GNH_CONV_PRHS',1,ZHOOK_HANDLE)

END SUBROUTINE GNH_CONV_PRHS

