SUBROUTINE PPOBSAAD(KDLEN,KLEN,KDCOUNT,CDPAR,KOBSTYPE,KCOUNT,PRESO,POROG,&
 & PXP,PXPD,PUF,PVF,PTF,PQF,PO3F,&
 & PCLWF,PCIWF,PCCF,PTSTAR,PT0,PLNPR,PALPH,&
 & KDPP,PXPP,&
 & PRESH5,PRESF5,PXP5,PXPD5,PUF5,PVF5,PTF5,PQF5,PO3F5,&
 & PCCF5,PTSTAR5,PT05,PLNPR5,PALPH5,YDGEMSPROF,YDGEMSPROF5,&
 & PNO2,PNO25)

!**** PPOBSAAD - ADJOINT OF POST-PROCESSING

!     D. VASILJEVIC          ECMWF           91-01-03

!     PURPOSE
!     -------

!        FIND OUT A GRADIENT WITH RESPECT TO POST-PROCESSED VALUES.

!**   INTERFACE
!     ---------

!        CALL PPOBSAAD(KDLEN,KLEN,KDCOUNT,CDPAR,KOBSTYPE,KCOUNT,PRESO,POROG,
!    O                 PXP,PXPD,PUF,PVF,PTF,PQF,
!    O                 PCLWF,PCIWF,PCCF,PTSTAR,PT0,PLNPR,PALPH,
!    I                 KDPP,PXPP,
!    R                 PRESH5,PRESF5,PXP5,PXPD5,PUF5,PVF5,PTF5,PQF5,
!    R                 YDGEMSPROF,YDGEMSPROF5,PNO2,PNO25)
!     WHERE KDLEN   : FIRST DIMENSION (Observations)
!           KLEN    : ACTUAL NUMBER OF OBSERVATIONS
!           KDCOUNT : SECOND DIMENSION (Data)
!           CDPAR   : PARAMETER FOR POST-PROCESSING
!           KOBSTYPE    : OBS. SET NUMBER
!           KCOUNT  : COUNTER FOR THE PARTICULAR OBS. PARAMETER
!           PRESO   : OBSERVED PRESSURES
!           POROG   : OROGRAPHY
!           PRESH   : GRAD. WITH RESPECT TO HALF LEVELS
!           PRESF   : GRAD. WITH RESPECT TO FULL LEVELS
!           PXP     : GRAD. WITH RESPECT TO PXP5
!           PXPD    : ..................... PXPD5
!           PUF     : GRAD. WITH RESPECT TO U (MODEL VALUES)
!           PVF     :            "          V       "
!           PTF     :            "          T       "
!           PQF     :            "          Q       "
!           PO3F    :            "          O3      "
!           PCLWF   :            "          CLW     "
!           PCIWF   :            "          CIW     "
!           PCCF    :            "          CC      "
!           PTSTAR  :            "          PTSTAR5
!           PT0     :            "          PT05
!           PLNPR   :            "          PLNPR5
!           PALPH   :            "          PALPH5
!           KDPP    : Number of fields, dimension of PXPP.
!           PXPP    : POST-PROCESSED VARIABLES
!           PNO2    : NO2 (optional)
!           PNO25   : NO2 (optional)
!           YDGEMSPROF    : GEMS PROFILES (OPTIONAL)


!        PPOBSAAD IS CALLED FROM HOPAD

!**   METHOD
!     ------

!**   EXTERNALS
!     ---------

!        PPFLEV  - FIND PRESSURE LEVEL UNDER SPECIFIED PRESSURES
!        PPUVAD  - ADJOINT OF PPUV
!        PPTAD   -      "     PPT
!        PPRHAD  -      "     PPRH
!        PPPWCAD -      "     PPPWC
!        PPGEOPAD-      "     PPGEOP
!        GPRCP   - COMPUTE R, CP AND KAPPA
!        GPRCPAD - COMPUTE R, CP AND KAPPA - ADJOINT

!**   MODIFICATIONS
!     -------------
!     E.Andersson 92-06-22 : Introduce PWC
!     E.Andersson 96-02-07 : Remove 'V'-option
!     E.Andersson 97-11-14 : GOM-variables more flexible
!     E.Holm      98-05-08 : Introduce integrated ozone option (TO3)
!     E.Andersson 98-06-11 : Pass dimension as argument
!     E.Andersson 99-07-02 : Incorporate clouds
!     N.Bormann   04-12-23 : New CDPAR-flavour 'RTL' for limb radiances
!     M.Hamrud    15-Jan-2006  Revised GPRCP
!     D.Tan       02-Mar-2007  Introduce HLoS (horizontal line-of-sight wind component)
!     ------------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
USE GOMS_MIX     , ONLY : LGOMUA,YGOMV
USE YOMDIM   , ONLY : NFLEVG   ,NPPM
USE YOMLUN   , ONLY : NULERR
USE TYPE_GEMS_PROFILES
USE YOM_YGFL , ONLY : NGRG,YGRG_NL

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN)    :: KDLEN 
INTEGER(KIND=JPIM),INTENT(IN)    :: KLEN 
INTEGER(KIND=JPIM),INTENT(IN)    :: KDCOUNT
CHARACTER(LEN=*)  ,INTENT(IN)    :: CDPAR 
INTEGER(KIND=JPIM),INTENT(IN)    :: KOBSTYPE
INTEGER(KIND=JPIM),INTENT(IN)    :: KCOUNT(KDLEN) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PRESO(KDLEN,KDCOUNT) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROG(KDLEN) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PXP(KDLEN,0:NFLEVG,NPPM) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PXPD(KDLEN,0:NFLEVG,NPPM) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PUF(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PVF(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PTF(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PQF(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PO3F(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PCLWF(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PCIWF(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PCCF(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PTSTAR(KDLEN) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PT0(KDLEN) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PLNPR(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PALPH(KDLEN,NFLEVG) 
INTEGER(KIND=JPIM),INTENT(IN)    :: KDPP 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PXPP(KDLEN,KDCOUNT,KDPP) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PRESH5(KDLEN,0:NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PRESF5(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PXP5(KDLEN,0:NFLEVG,NPPM) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PXPD5(KDLEN,0:NFLEVG,NPPM) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PUF5(KDLEN,0:NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PVF5(KDLEN,0:NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PTF5(KDLEN,0:NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PQF5(KDLEN,0:NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PO3F5(KDLEN,0:NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PCCF5(KDLEN,0:NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PTSTAR5(KDLEN) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PT05(KDLEN) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLNPR5(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PALPH5(KDLEN,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT), OPTIONAL:: PNO2(KDLEN,0:NFLEVG)
REAL(KIND=JPRB)   ,INTENT(IN), OPTIONAL:: PNO25(KDLEN,0:NFLEVG)


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

INTEGER(KIND=JPIM), ALLOCATABLE :: ILEVB (:,:,:)
LOGICAL, ALLOCATABLE :: LLBELO(:,:),LLBLOW(:),LLBELS(:,:),LLBLES(:)
REAL(KIND=JPRB), ALLOCATABLE :: ZLNPRESO(:,:)
REAL(KIND=JPRB), DIMENSION(KDLEN,NFLEVG) :: ZR05,ZR0
REAL(KIND=JPRB), DIMENSION(KDLEN,0:NFLEVG) :: ZGRAX1,ZGRAX2
INTEGER(KIND=JPIM) :: ILEN,IMXCNT,INPP,JLEN,IND_NOX
INTEGER(KIND=JPIM) :: JLEVP,JLEV,JOBS
LOGICAL :: LLEXTR,LLU,LLT,LLQ,LLO3,LLH,LLZ,LLPWC,LLTO3,LLGHG
LOGICAL :: LLCC,LLCLW,LLCIW,LLTCC,LLNO2
LOGICAL, DIMENSION(NGRG) :: LLGRG
REAL(KIND=JPRB) :: ZRHMAX,ZRHMIN
REAL(KIND=JPRB) :: ZHOOK_HANDLE

REAL(KIND=JPRB), ALLOCATABLE :: ZGEMSMODEL(:,:),ZGEMSRTTOV(:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZGEMSMODEL5(:,:),ZGEMSRTTOV5(:,:)
TYPE (TYPE_GEMSPROF), INTENT(INOUT), OPTIONAL :: YDGEMSPROF(KDLEN,NGEMS)
TYPE (TYPE_GEMSPROF), INTENT(IN), OPTIONAL :: YDGEMSPROF5(KDLEN,NGEMS)
INTEGER(KIND=JPIM) :: JGEMS,JGRG

#include "abor1.intfb.h"
#include "gprcp.intfb.h"
#include "gprcpad.intfb.h"
#include "ppccad.intfb.h"
#include "ppclwad.intfb.h"
#include "ppflev.intfb.h"
#include "ppgeopad.intfb.h"
#include "pppwcad.intfb.h"
#include "ppqad.intfb.h"
#include "pprhad.intfb.h"
#include "pptad.intfb.h"
#include "ppuvad.intfb.h"

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

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

!     ------------------------------------------------------------------
!*    1.  PREPARATION
!*    1.1 MAX. NO. OF LEVELS

ILEN=KLEN
IMXCNT = MAXVAL(KCOUNT(1:ILEN))
IF(IMXCNT == 0) GOTO 9

LLU=  CDPAR == 'U'   .OR. CDPAR == 'FF'  .OR. CDPAR == 'BG1' &
 &                   .OR. CDPAR == 'HLS'
LLT=  CDPAR == 'T'   .OR. CDPAR == 'BG1' .OR. CDPAR == 'TV1' &
 &                   .OR. CDPAR == 'RTL'
LLQ=  CDPAR == 'Q'   .OR. CDPAR == 'BG1' .OR. CDPAR == 'TV1' &
 &                   .OR. CDPAR == 'RTL'
LLO3= CDPAR == 'O3'  .OR. CDPAR == 'BG1' .OR. CDPAR == 'TV1' &
 &                   .OR. CDPAR == 'RTL'
LLTO3=CDPAR == 'TO3' .OR. CDPAR == 'BG1'
LLGHG=CDPAR == 'BG1' .OR. CDPAR == 'TV1'
LLH=  CDPAR == 'H'   .OR. CDPAR == 'LH'
LLZ=  CDPAR == 'Z'   .OR. CDPAR == 'DZ'  .OR. CDPAR == 'BG1' &
 &                   .OR. CDPAR == 'RTL'
LLPWC=CDPAR == 'PWC' .OR. CDPAR == 'BG1'
LLCC =CDPAR == 'CC'
LLCLW=CDPAR == 'CLW'
LLCIW=CDPAR == 'CIW'
LLTCC=CDPAR == 'TCC'

DO JGRG=1,NGRG
  LLGRG(JGRG)=CDPAR == TRIM(YGRG_NL(JGRG)%cname) .OR. CDPAR == 'BG1'
ENDDO


LLNO2=.FALSE.
IND_NOX=-1
IF(PRESENT(PNO25)) THEN
  LLNO2=.TRUE.
  DO JGRG=1,NGRG
    IF(TRIM(YGRG_NL(JGRG)%cname) =='NOX') IND_NOX=JGRG
    IF (IND_NOX==-1) THEN
      WRITE(NULERR,*) 'PPOBSAAD: PROBLEM WITH NOX OPERATOR. NOX FIELD NEEDED BUT DOES NOT EXIST.'
      CALL ABOR1('PPOBSAAD: PROBLEM WITH NOX OPERATOR. NOX FIELD DOES NOT EXIST')
    ENDIF
  ENDDO
ENDIF

IF(.NOT.ANY((/LLU,LLT,LLQ,LLO3,LLH,LLZ,LLPWC,LLTO3,&
   & LLCC,LLCLW,LLCIW,LLTCC,LLGRG,LLGHG/))) THEN  
  WRITE(NULERR,'('' *** REQUESTED PARAMETER='',A)') CDPAR
  CALL ABOR1('ERROR PPOBSAAD: WRONG REQUESTED PARAMETER')
ENDIF

!*    1.2 FIND OUT PRESSURE LEVEL BELOW SPECIFIED (OBSERVED) PRESSURES

ALLOCATE(ILEVB(KDLEN,IMXCNT,NPPM))
ALLOCATE(LLBELO(KDLEN,IMXCNT))
ALLOCATE(LLBELS(KDLEN,IMXCNT))
ALLOCATE(LLBLOW(IMXCNT))
ALLOCATE(LLBLES(IMXCNT))
CALL PPFLEV(KDLEN,1,ILEN,NFLEVG,IMXCNT,&
 & PRESO,PRESH5,PRESF5,&
 & ILEVB,&
 & LLBELO,LLBELS,LLBLOW,LLBLES)  

!*    1.3 LN(P)

IF(LLZ .OR. LLPWC .OR. LLT .OR. LLU .OR. LLTO3 .OR. LLGHG .OR. ANY(LLGRG) ) THEN
  ALLOCATE(ZLNPRESO(KDLEN,IMXCNT))
  DO JLEVP=1,IMXCNT
    IF(CDPAR == 'TV1') THEN
      ZLNPRESO(1:ILEN,JLEVP) = LOG(PRESO(1,JLEVP))
    ELSE
      ZLNPRESO(1:ILEN,JLEVP) = LOG(PRESO(1:ILEN,JLEVP))
    ENDIF
  ENDDO
ENDIF

!*    1.4 ZERO LIQUID WATER AND ICE AND GRADIENT

IF(LLZ .OR. LLT) THEN
  DO JLEV=1,NFLEVG
    DO JOBS=1,ILEN
      ZR0 (JOBS,JLEV)=0.0_JPRB
    ENDDO
  ENDDO
ENDIF
INPP=0
!*    2.  U AND V CONTRIBUTIONS

IF(LLU) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+2 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, UV')
  INPP=INPP+2

  CALL PPUVAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & LLBELO,LLBLOW,ZLNPRESO,&
   & PXP,PXPD,ZGRAX1,ZGRAX2,&
   & PXPP(1,1,INPP-1),PXPP(1,1,INPP),&
   & PXP5,PXPD5,PUF5,PVF5)  

  PUF(1:ILEN,1:NFLEVG) = PUF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
  PVF(1:ILEN,1:NFLEVG) = PVF(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    4.  TEMPERATURE

IF(LLT) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  LLEXTR = .TRUE.
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, T')
  INPP=INPP+1

  CALL GPRCP(KDLEN,1,ILEN,NFLEVG,PQ=PQF5(1,1),PR=ZR05)
  CALL PPTAD (KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & PRESO,ZLNPRESO,LLBELO,LLBELS,LLBLOW,LLBLES,LLEXTR,POROG,&
   & PXP,PXPD,PTSTAR,PT0,ZR0,ZGRAX1,&
   & PXPP(1,1,INPP),&
   & PXP5,PXPD5,PTSTAR5,PT05,ZR05,PTF5)  
  CALL GPRCPAD(KDLEN,1,ILEN,NFLEVG,PQ=ZGRAX2(1,1),PR=ZR0)

  PTF(1:ILEN,1:NFLEVG) = PTF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
  PQF(1:ILEN,1:NFLEVG) = PQF(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    5.  HUMIDITY
!*    5.1 REL. HUMIDITY

IF(LLH) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, RH')
  INPP=INPP+1

  ZRHMAX=1.2_JPRB
  ZRHMIN=-0.2_JPRB
  CALL PPRHAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & PRESO,LLBELO,LLBLOW,ZRHMAX,ZRHMIN,&
   & PXP,PXPD,ZGRAX2,ZGRAX1,&
   & PXPP(1,1,INPP),&
   & PXP5,PXPD5,PTF5,PQF5)  

  PTF(1:ILEN,1:NFLEVG) = PTF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
  PQF(1:ILEN,1:NFLEVG) = PQF(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    5.2 Q

IF(LLQ) THEN
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, Q')
  INPP=INPP+1

  CALL PPQAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & PRESO,LLBELO,LLBLOW,&
   & PXP,PXPD,ZGRAX2,&
   & PXPP(1,1,INPP),&
   & PXP5,PXPD5,PQF5)  

  PQF(1:ILEN,1:NFLEVG) = PQF(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    5.3 HUMIDITY, PWC. GIVES PWC FROM P=PRESO TO P=0.

IF(LLPWC) THEN
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, PWC')
  INPP=INPP+1

  CALL PPPWCAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & PRESO,ZLNPRESO,LLBELS,LLBLES,&
   & PXP,PXPD,ZGRAX2,&
   & PXPP(1,1,INPP),&
   & PXP5,PXPD5,PQF5)  

  PQF(1:ILEN,1:NFLEVG) = PQF(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    6.  GEOPOTENTIAL

IF(LLZ) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, Z')
  INPP=INPP+1

  LLEXTR=.TRUE.
  CALL GPRCP(KDLEN,1,ILEN,NFLEVG,PQ=PQF5(1,1),PR=ZR05)
  CALL PPGEOPAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & ZLNPRESO,LLBELO,LLBELS,LLBLOW,LLBLES,LLEXTR,POROG,&
   & PXP,PXPD,PTSTAR,ZR0,PLNPR,PALPH,ZGRAX1,&
   & PXPP(1,1,INPP),&
   & PXP5,PXPD5,PTSTAR5,ZR05,PLNPR5,PALPH5,PTF5)  
  CALL GPRCPAD(KDLEN,1,ILEN,NFLEVG,PQ=ZGRAX2(1,1),PR=ZR0)

  PTF(1:ILEN,1:NFLEVG) = PTF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
  PQF(1:ILEN,1:NFLEVG) = PQF(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    7.  OZON
!*    7.1 INTERPOLATED OZONE
!*        For now, use PPQAD awaiting a dedicated routine PPO3AD

IF(LLO3 .AND. .NOT.(CDPAR == 'TV1' .AND. .NOT. LGOMUA(KOBSTYPE,YGOMV%MO3))) THEN
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, O3')
  INPP=INPP+1

  CALL PPQAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & PRESO,LLBELO,LLBLOW,&
   & PXP,PXPD,ZGRAX2,&
   & PXPP(1,1,INPP),&
   & PXP5,PXPD5,PO3F5)  

  PO3F(1:ILEN,1:NFLEVG) = PO3F(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    7.2 INTEGRATED OZONE
!*        For now, use PPPWCAD awaiting a dedicated routine PPTO3AD
IF(LLTO3) THEN
  ZGRAX2(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, TO3')
  INPP=INPP+1

  CALL PPPWCAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & PRESO,ZLNPRESO,LLBELS,LLBLES,&
   & PXP,PXPD,ZGRAX2,&
   & PXPP(1,1,INPP),&
   & PXP5,PXPD5,PO3F5)  

  PO3F(1:ILEN,1:NFLEVG) = PO3F(1:ILEN,1:NFLEVG) + ZGRAX2(1:ILEN,1:NFLEVG)
ENDIF

!*    8.  CLOUDS
!*    8.1 CLOUD COVER

IF(LLCC) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, CC')
  INPP=INPP+1

  CALL PPCCAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & ZGRAX1,&
   & PXPP(1,1,INPP),&
   & PCCF5)  

  PCCF(1:ILEN,1:NFLEVG) = PCCF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
ENDIF

!*    8.2 CLOUD LIQUID WATER

IF(LLCLW) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, CLW')
  INPP=INPP+1

  CALL PPCLWAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & ZGRAX1,&
   & PXPP(1,1,INPP))  

  PCLWF(1:ILEN,1:NFLEVG) = PCLWF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
ENDIF

!*    8.3 CLOUD ICE (Use PPCLWTL for now)

IF(LLCIW) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, CIW')
  INPP=INPP+1

  CALL PPCLWAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
   & ZGRAX1,&
   & PXPP(1,1,INPP))

  PCIWF(1:ILEN,1:NFLEVG) = PCIWF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
ENDIF

!*    8.4 TOTAL CLOUD COVER

IF(LLTCC) THEN
  ZGRAX1(1:ILEN,0:NFLEVG)=0.0_JPRB
  IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, CIW')
!  INPP=INPP+1

  WRITE(NULERR,'('' *** ERROR IN PPOBSAAD: TOTAL CLOUD'',&
   & '' COVER OPERATOR NOT DONE YET '')')  
  CALL ABOR1('ERROR PPOBSAAD: PPTCCAD DOES NOT EXIST')

!   CALL PPTCCAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,
!    &ZGRAX1,
!    &PXPP(1,1,INPP),
!    &PCCF5)

  PCCF(1:ILEN,1:NFLEVG) = PCCF(1:ILEN,1:NFLEVG) + ZGRAX1(1:ILEN,1:NFLEVG)
ENDIF

!*    9.  GREENHOUSE GASES
!*        For now, use PPQ awaiting a dedicated routine PPO3
IF(PRESENT(YDGEMSPROF5) .AND. PRESENT(YDGEMSPROF)) THEN

IF(LLGHG .AND. .NOT.(CDPAR == 'TV1' .AND. .NOT. ANY(LGOMUA(KOBSTYPE,YGOMV%MGHG(:))))) THEN
  DO JGEMS=1,NGEMS
    IF(YDGEMSPROF5(1,JGEMS)%LRTTOV) THEN
      ALLOCATE(ZGEMSMODEL(KDLEN,0:NFLEVG),ZGEMSRTTOV(KDLEN,IMXCNT))
      ALLOCATE(ZGEMSMODEL5(KDLEN,0:NFLEVG),ZGEMSRTTOV5(KDLEN,IMXCNT))
      DO JLEN=1,ILEN
        ZGEMSMODEL(JLEN,:)=0.0_JPRB
        ZGEMSMODEL5(JLEN,0)=YDGEMSPROF5(JLEN,JGEMS)%MODELPROF(1)
        ZGEMSMODEL5(JLEN,1:NFLEVG)=YDGEMSPROF5(JLEN,JGEMS)%MODELPROF(:)
        ZGEMSRTTOV(JLEN,:)=YDGEMSPROF(JLEN,JGEMS)%RTTOVPROF(:)
      ENDDO
     CALL PPQAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
      & PRESO,LLBELO,LLBLOW,&
      & PXP,PXPD,ZGEMSMODEL,&
      & ZGEMSRTTOV,&
      & PXP5,PXPD5,ZGEMSMODEL5)  

      DO JLEN=1,ILEN
        YDGEMSPROF(JLEN,JGEMS)%MODELPROF(1:NFLEVG)=&
        & YDGEMSPROF(JLEN,JGEMS)%MODELPROF(1:NFLEVG)+ZGEMSMODEL(JLEN,1:NFLEVG)
      ENDDO
      DEALLOCATE(ZGEMSMODEL,ZGEMSRTTOV)
      DEALLOCATE(ZGEMSMODEL5,ZGEMSRTTOV5)
    ENDIF
  ENDDO
ENDIF

!*    10. Reactive Gases  
!*        For now, use PPPWCAD awaiting a dedicated routine PPTO3AD
IF(ANY(LLGRG) .AND. .NOT.(CDPAR == 'BG1')) THEN

  JGRG=0
  DO JGEMS=1,NGEMS
    IF(YDGEMSPROF5(1,JGEMS)%CSPECIES=='GRG') THEN
      JGRG=JGRG+1
      IF(LLGRG(JGRG)) THEN
        IF(INPP+1 > KDPP) CALL ABOR1('PPOBSAAD: KDPP EXCEEDED, GRG')
        INPP=INPP+1

        ALLOCATE(ZGEMSMODEL(KDLEN,0:NFLEVG))
        ALLOCATE(ZGEMSMODEL5(KDLEN,0:NFLEVG))
        IF(LLNO2.AND.JGRG==IND_NOX) THEN
          DO JLEN=1,ILEN
            ZGEMSMODEL(JLEN,:)=0.0_JPRB 
            ZGEMSMODEL5(JLEN,0:NFLEVG)= PNO25(JLEN,0:NFLEVG)
          ENDDO
        ELSE
          DO JLEN=1,ILEN
            ZGEMSMODEL(JLEN,:)=0.0_JPRB 
            ZGEMSMODEL5(JLEN,0)= &
             & YDGEMSPROF5(JLEN,JGEMS)%MODELPROF(1)
            ZGEMSMODEL5(JLEN,1:NFLEVG)= &
             & YDGEMSPROF5(JLEN,JGEMS)%MODELPROF(:)
          ENDDO
        ENDIF

        CALL PPPWCAD(KDLEN,1,ILEN,NFLEVG,IMXCNT,1,ILEVB,&
         & PRESO,ZLNPRESO,LLBELS,LLBLES,&
         & PXP,PXPD,ZGEMSMODEL,&
         & PXPP(1,1,INPP),&
         & PXP5,PXPD5,ZGEMSMODEL5)  

        IF(LLNO2.AND.JGRG==IND_NOX) THEN
          DO JLEN=1,ILEN
            PNO2(JLEN,1:NFLEVG)=&
            & PNO2(JLEN,1:NFLEVG)+ZGEMSMODEL(JLEN,1:NFLEVG)
          ENDDO
        ELSE
          DO JLEN=1,ILEN
            YDGEMSPROF(JLEN,JGEMS)%MODELPROF(1:NFLEVG)=&
            & YDGEMSPROF(JLEN,JGEMS)%MODELPROF(1:NFLEVG)+ZGEMSMODEL(JLEN,1:NFLEVG)
          ENDDO
        ENDIF
        DEALLOCATE(ZGEMSMODEL)
        DEALLOCATE(ZGEMSMODEL5)
      ENDIF
    ENDIF
  ENDDO

ENDIF

ENDIF
!*    10.  FINALLY, DEALLOCATE AND RETURN

DEALLOCATE(ILEVB,LLBELO,LLBELS,LLBLOW,LLBLES)
IF(ALLOCATED(ZLNPRESO)) DEALLOCATE(ZLNPRESO)

9 CONTINUE

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