#ifdef RS6K
@PROCESS NOCHECK
#endif
MODULE GOMS_MIX

!     Purpose.
!     --------
!       Contains observation equivalants "GOM" arrays and setup routines etc.

!     Author.
!     -------
!        M.Hamrud *ECMWF*

!     Modifications.
!     --------------
!        Original : 15-02-2005
!           ??-05-2005 C. Payan adds integer key NUSE_ECCI
!           ??-06-2006 E.Wattrelot adds three GOMGFL variables for rain
!                      snow and graupel (for AROME)
!           20070226   consistent codes for ECMWF prognostic aerosols 
!           20080704   H.Hersbach add ocean currents plus wave charnock
!           20091204   H.Hersbach add 10-m neutral wind; introduce LUPD
!     ------------------------------------------------------------------

USE PARKIND1 , ONLY : JPIM     ,JPRB
USE PARDIMO  , ONLY : JPNOTP
USE YOMECTAB , ONLY : NOBSPROFS
USE YOMHOOK  , ONLY : LHOOK,   DR_HOOK
USE YOMLUN   , ONLY : NULERR 
USE YOM_YGFL , ONLY : JPGHG, JPGRG, JPAERO

IMPLICIT NONE
SAVE

!     -------------------------------------------------------------------------
! Number of defined GOM upper air variables (see type YGOMV)
INTEGER(KIND=JPIM),PARAMETER :: JPGOMVARSUA=8+JPGHG+JPGRG+JPAERO+3
!Logical defining what GOM upper air variables are needed for each obs type
LOGICAL :: LGOMUA(JPNOTP,JPGOMVARSUA)
!Logical defining what GOM upper air GFL variables are needed for specific obs type
LOGICAL,ALLOCATABLE :: LGOMGFL(:,:) ! LGOMGFL(NOOBST,YGFL%NUMFLDS)

INTEGER(KIND=JPIM)  :: NGOMS   ! Total number of gom structures (= NOBTOT)
INTEGER(KIND=JPIM)  :: NGOMS1D ! Number of 1D GOM structures
INTEGER(KIND=JPIM)  :: NGOMS2D ! Number of 2D GOM structures
INTEGER(KIND=JPIM)  :: NGOMGFL ! Number of GFL variables used in (any) GOM arrays
INTEGER(KIND=JPIM)  :: NUSE_ECCI
INTEGER(KIND=JPIM)  :: MGOMGFL(JPGOMVARSUA) ! Pointer to individual GFL fields in interpolation buffer
! === Type declarations for obs.equiv. data structures ===
! Type for 1-D upper air GOM
TYPE TYPE_GOMUA 
LOGICAL :: LU,LV,LT,LQ,LO3,LCLW,LCIW,LCC, & ! True if variable present in this GOM
 & LGHG(JPGHG),LGRG(JPGRG),LAERO(JPAERO), &
 & LS,LR,LG ! True if variable present in this GOM
LOGICAL,POINTER :: LGFL(:) => NULL()! True if GFL variable present in this GOM
INTEGER(KIND=JPIM) :: IOBS   ! Obs. number (for checks)  
INTEGER(KIND=JPIM) :: ITYP   ! Obs. type
INTEGER(KIND=JPIM) :: IGOMGFL ! Number of GFL fields in this GOM
! The indivual variables in this GOM structure
REAL(KIND=JPRB),POINTER :: U(:) => NULL()
REAL(KIND=JPRB),POINTER :: V(:) => NULL()
REAL(KIND=JPRB),POINTER :: T(:) => NULL()
REAL(KIND=JPRB),POINTER :: Q(:) => NULL()
REAL(KIND=JPRB),POINTER :: O3(:) => NULL()
REAL(KIND=JPRB),POINTER :: CLW(:) => NULL()
REAL(KIND=JPRB),POINTER :: CIW(:) => NULL()
REAL(KIND=JPRB),POINTER :: CC(:) => NULL()
REAL(KIND=JPRB),POINTER :: GHG(:) => NULL()
REAL(KIND=JPRB),POINTER :: GRG(:) => NULL()
REAL(KIND=JPRB),POINTER :: AERO(:) => NULL()
REAL(KIND=JPRB),POINTER :: S(:)  => NULL()
REAL(KIND=JPRB),POINTER :: R(:)  => NULL()
REAL(KIND=JPRB),POINTER :: G(:)  => NULL()
REAL(KIND=JPRB),POINTER :: GFL(:) => NULL()
END TYPE TYPE_GOMUA
! Type for 2-D upper air GOM
TYPE TYPE_GOMUA_2D 
LOGICAL :: LU,LV,LT,LQ,LO3,LCLW,LCIW,LCC,LGHG(JPGHG),LGRG(JPGRG),LAERO(JPAERO)&
&          ,LS,LR,LG
LOGICAL,POINTER :: LGFL(:) => NULL()
INTEGER(KIND=JPIM) :: IOBS
INTEGER(KIND=JPIM) :: ITYP
INTEGER(KIND=JPIM) :: IGOMGFL
REAL(KIND=JPRB),POINTER :: U(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: V(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: T(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: Q(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: O3(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: CLW(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: CIW(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: CC(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: GHG(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: GRG(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: AERO(:,:) => NULL()
REAL(KIND=JPRB),POINTER :: S(:,:)  => NULL()
REAL(KIND=JPRB),POINTER :: R(:,:)  => NULL()
REAL(KIND=JPRB),POINTER :: G(:,:)  => NULL()
REAL(KIND=JPRB),POINTER :: GFL(:,:) => NULL()
END TYPE TYPE_GOMUA_2D
! Type for 1-D surface GOM
TYPE TYPE_GOMS
INTEGER(KIND=JPIM) :: IOBS
INTEGER(KIND=JPIM) :: ITYP
LOGICAL         :: LUPD    ! true in case surface has been updated
REAL(KIND=JPRB) :: SP
REAL(KIND=JPRB) :: TS
REAL(KIND=JPRB) :: WS
REAL(KIND=JPRB) :: SN
REAL(KIND=JPRB) :: Z0
REAL(KIND=JPRB) :: U0
REAL(KIND=JPRB) :: V0
REAL(KIND=JPRB) :: U10N
REAL(KIND=JPRB) :: V10N
REAL(KIND=JPRB) :: WL
REAL(KIND=JPRB) :: UL
REAL(KIND=JPRB) :: VL
REAL(KIND=JPRB) :: TL
REAL(KIND=JPRB) :: QL
REAL(KIND=JPRB) :: SST
REAL(KIND=JPRB) :: CHN
REAL(KIND=JPRB) :: TCLS
REAL(KIND=JPRB) :: HUCLS
END TYPE TYPE_GOMS
! Type for 2-D surface GOM
TYPE TYPE_GOMS_2D
INTEGER(KIND=JPIM) :: IOBS
INTEGER(KIND=JPIM) :: ITYP
REAL(KIND=JPRB),POINTER :: SP(:)
REAL(KIND=JPRB),POINTER :: TS(:)
REAL(KIND=JPRB),POINTER :: WS(:)
REAL(KIND=JPRB),POINTER :: SN(:)
REAL(KIND=JPRB),POINTER :: Z0(:)
REAL(KIND=JPRB),POINTER :: U0(:)
REAL(KIND=JPRB),POINTER :: V0(:)
REAL(KIND=JPRB),POINTER :: U10N(:)
REAL(KIND=JPRB),POINTER :: V10N(:)
REAL(KIND=JPRB),POINTER :: WL(:)
REAL(KIND=JPRB),POINTER :: UL(:)
REAL(KIND=JPRB),POINTER :: VL(:)
REAL(KIND=JPRB),POINTER :: TL(:)
REAL(KIND=JPRB),POINTER :: QL(:)
REAL(KIND=JPRB),POINTER :: CHN(:)
REAL(KIND=JPRB),POINTER :: SST(:)
END TYPE TYPE_GOMS_2D
! Type for 1-D constant/climate GOM
TYPE TYPE_GOMEC
REAL(KIND=JPRB) :: ECOROG
REAL(KIND=JPRB) :: ECCORI
REAL(KIND=JPRB) :: ECALBE
REAL(KIND=JPRB) :: ECEMIS
REAL(KIND=JPRB) :: ECLSMA
REAL(KIND=JPRB) :: ECCI
REAL(KIND=JPRB) :: ECCVH
REAL(KIND=JPRB) :: ECCVL
REAL(KIND=JPRB) :: ECTVH
REAL(KIND=JPRB) :: ECTVL
REAL(KIND=JPRB) :: ECVEGE
REAL(KIND=JPRB) :: ECDL
REAL(KIND=JPRB) :: ECDM
REAL(KIND=JPRB) :: ECARG
REAL(KIND=JPRB) :: ECSAB
REAL(KIND=JPRB) :: ECHV
REAL(KIND=JPRB) :: ECZ0H
END TYPE TYPE_GOMEC
! Type for 2-D constant/climate GOM
TYPE TYPE_GOMEC_2D
REAL(KIND=JPRB),POINTER :: ECOROG(:)
REAL(KIND=JPRB),POINTER :: ECCORI(:)
REAL(KIND=JPRB),POINTER :: ECALBE(:)
REAL(KIND=JPRB),POINTER :: ECEMIS(:)
REAL(KIND=JPRB),POINTER :: ECLSMA(:)
REAL(KIND=JPRB),POINTER :: ECCI(:)
REAL(KIND=JPRB),POINTER :: ECCVH(:)
REAL(KIND=JPRB),POINTER :: ECCVL(:)
REAL(KIND=JPRB),POINTER :: ECTVH(:)
REAL(KIND=JPRB),POINTER :: ECTVL(:)
REAL(KIND=JPRB),POINTER :: ECVEGE(:)
REAL(KIND=JPRB),POINTER :: ECDL(:)
REAL(KIND=JPRB),POINTER :: ECDM(:)
REAL(KIND=JPRB),POINTER :: ECARG(:)
REAL(KIND=JPRB),POINTER :: ECSAB(:)
REAL(KIND=JPRB),POINTER :: ECHV(:)
REAL(KIND=JPRB),POINTER :: ECZ0H(:)
REAL(KIND=JPRB),POINTER :: RLAT(:)
REAL(KIND=JPRB),POINTER :: RLON(:)
END TYPE TYPE_GOMEC_2D
! Type for 1-D CANARI specific GOM
TYPE TYPE_GOMCAN
REAL(KIND=JPRB) :: EMMST
REAL(KIND=JPRB) :: EMMSN
REAL(KIND=JPRB) :: EMMT2
REAL(KIND=JPRB) :: EMMH2
REAL(KIND=JPRB) :: EMMV1
REAL(KIND=JPRB) :: ECPRWA
REAL(KIND=JPRB) :: ECPRSN
REAL(KIND=JPRB) :: ECCLITS
REAL(KIND=JPRB) :: ECCLISN
END TYPE TYPE_GOMCAN
TYPE TYPE_GOMCAN_ALT
REAL(KIND=JPRB),POINTER :: EMMZ(:)
REAL(KIND=JPRB),POINTER :: EMMH(:)
END TYPE TYPE_GOMCAN_ALT
! === Type declarations for support data structures ===
! Describing interface beetwen model and GOM GFL
TYPE TYPE_GOMGFL
LOGICAL :: LINTERP ! Not really used
CHARACTER(LEN=10) :: CSLINT ! Interpolation method to be used for field
INTEGER(KIND=JPIM) :: MPMDL ! Pointer to model GFL (for use in COBS)
END TYPE TYPE_GOMGFL
! Supported upper air variables in GOM
TYPE TYPE_YGOMV
INTEGER(KIND=JPIM) :: MU=1
INTEGER(KIND=JPIM) :: MV=2
INTEGER(KIND=JPIM) :: MT=3
INTEGER(KIND=JPIM) :: MQ=4
INTEGER(KIND=JPIM) :: MO3=5
INTEGER(KIND=JPIM) :: MCLW=6
INTEGER(KIND=JPIM) :: MCIW=7
INTEGER(KIND=JPIM) :: MCC=8
INTEGER(KIND=JPIM), DIMENSION(JPGHG) :: MGHG=(/9,10,11/)
INTEGER(KIND=JPIM), DIMENSION(JPGRG) :: MGRG=(/12,13,14,15,16/)
INTEGER(KIND=JPIM), DIMENSION(JPAERO) :: MAERO=(/17,18,19,20,21,22,23,24,25,26,27,28,29,30,31/)
INTEGER(KIND=JPIM) :: MS=32
INTEGER(KIND=JPIM) :: MR=33
INTEGER(KIND=JPIM) :: MG=34
END TYPE TYPE_YGOMV

! == Arrays of data structures containing observation equivalents ==
! Single profile:
TYPE(TYPE_GOMUA) ,ALLOCATABLE :: YGOMUA(:)  !upper air
TYPE(TYPE_GOMUA) ,ALLOCATABLE :: YGOMUA5(:) !upper air trajectory
TYPE(TYPE_GOMS)  ,ALLOCATABLE :: YGOMS(:)   !surface 
TYPE(TYPE_GOMS)  ,ALLOCATABLE :: YGOMS5(:)  !surface trajectory
TYPE(TYPE_GOMEC) ,ALLOCATABLE :: YGOMEC(:)  !constant/climate surface
TYPE(TYPE_GOMCAN),ALLOCATABLE :: YGOMCAN(:) !CANARI specific surface
! Multi (2D) profile:
TYPE(TYPE_GOMCAN_ALT),ALLOCATABLE :: YGOMCANA(:)
TYPE(TYPE_GOMUA_2D),ALLOCATABLE :: YGOMUA_2D(:)  !upper air 
TYPE(TYPE_GOMUA_2D),ALLOCATABLE :: YGOMUA5_2D(:) !upper air - traj.
TYPE(TYPE_GOMS_2D) ,ALLOCATABLE :: YGOMS_2D(:)   !surface 
TYPE(TYPE_GOMS_2D) ,ALLOCATABLE :: YGOMS5_2D(:)  !surface -traj
TYPE(TYPE_GOMEC_2D),ALLOCATABLE :: YGOMEC_2D(:)  !constant/climate surface 

! == Support data structures ==
! Describing interface beetwen model and GOM GFL
TYPE(TYPE_GOMGFL),ALLOCATABLE :: YGOMGFL(:)
! Pointers to supported upper air variables in GOM
#ifdef RS6K
! xlf90 bug
TYPE(TYPE_YGOMV),SAVE :: YGOMV
#else
TYPE(TYPE_YGOMV) :: YGOMV
#endif
! Data storage areas for upper air GOM 1-D arrys (to ensure data proximity)
REAL(KIND=JPRB),ALLOCATABLE,TARGET :: GOMDATUA(:)
REAL(KIND=JPRB),ALLOCATABLE,TARGET :: GOMDATUA5(:)

INTEGER(KIND=JPIM) :: NOFF=0  ! Offset in GOMDATUA
INTEGER(KIND=JPIM) :: NOFF5=0 ! Offset in GOMDATUA5

#include "abor1.intfb.h"

CONTAINS
!--------------------------------------------------------------------
SUBROUTINE GOMCONSTR(YDGOM,KLEV,KTYP,KOBS,LDALLO,LD5)
! Constructor for individual upper-air GOM 1-D structure
TYPE(TYPE_GOMUA),INTENT(OUT) :: YDGOM
INTEGER(KIND=JPIM),INTENT(IN) :: KLEV,KTYP,KOBS
LOGICAL,INTENT(IN) :: LDALLO,LD5
REAL(KIND=JPRB) :: ZHOOK_HANDLE

IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCONSTR',0,ZHOOK_HANDLE)
IF(LD5) THEN
  CALL GOMCONSTRB(YDGOM,KLEV,KTYP,KOBS,NOFF5,LDALLO,GOMDATUA5)
ELSE
  CALL GOMCONSTRB(YDGOM,KLEV,KTYP,KOBS,NOFF,LDALLO,GOMDATUA)
ENDIF
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCONSTR',1,ZHOOK_HANDLE)
END SUBROUTINE GOMCONSTR
!--------------------------------------------------------------------
SUBROUTINE GOMCONSTRB(YDGOM,KLEV,KTYP,KOBS,KOFF,LDALLO,POMDATUA)
! Constructor for individual upper-air 1-D GOM structure
TYPE(TYPE_GOMUA),INTENT(OUT) :: YDGOM     ! Upper air GOM structure
INTEGER(KIND=JPIM),INTENT(IN) :: KLEV     ! Number of levels
INTEGER(KIND=JPIM),INTENT(IN) :: KTYP     ! Observation type
INTEGER(KIND=JPIM),INTENT(IN) :: KOBS     ! GOM number (MDB_MAPOMM_AT_INDEX)
INTEGER(KIND=JPIM),INTENT(INOUT) :: KOFF  ! Offset in POMDATUA
REAL(KIND=JPRB),INTENT(IN),TARGET :: POMDATUA(:)  ! Data storage area
LOGICAL,INTENT(IN) :: LDALLO ! If TRUE point to POMDATA otherwise only update offset
REAL(KIND=JPRB) :: ZHOOK_HANDLE

INTEGER(KIND=JPIM) :: IOFF, JGFL
INTEGER(KIND=JPIM) :: JGHG, IENGHG, JGRG, IENGRG, JAERO, IENAERO
INTEGER(KIND=JPIM),SAVE :: IQ,IO3,ICLW,ICIW,ICC,IGHG,IGRG,IAERO,IS,IR,IG

IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCONSTRB',0,ZHOOK_HANDLE)

IF(.NOT. ASSOCIATED(YDGOM%LGFL)) THEN
  ALLOCATE(YDGOM%LGFL(NGOMGFL))
  YDGOM%ITYP = KTYP
  YDGOM%IOBS = KOBS

  YDGOM%LU   = LGOMUA(KTYP,YGOMV%MU)
  YDGOM%LV   = LGOMUA(KTYP,YGOMV%MV)
  YDGOM%LT   = LGOMUA(KTYP,YGOMV%MT)
  YDGOM%IGOMGFL = 0

  YDGOM%LGFL(:) = .FALSE.
  YDGOM%LQ   = .FALSE.
  YDGOM%LO3  = .FALSE.
  YDGOM%LCLW = .FALSE.
  YDGOM%LCIW = .FALSE.
  YDGOM%LCC  = .FALSE.
  YDGOM%LGHG(:) = .FALSE.
  YDGOM%LGRG(:) = .FALSE.
  YDGOM%LAERO(:) = .FALSE.
  YDGOM%LS   = .FALSE.
  YDGOM%LR   = .FALSE.
  YDGOM%LG   = .FALSE.
  IGHG=0
  IGRG=0
  IAERO=0

  DO JGFL=1,NGOMGFL
    IF(LGOMGFL(KTYP,JGFL)) THEN
      YDGOM%LGFL(JGFL) = .TRUE.
      YDGOM%IGOMGFL =  YDGOM%IGOMGFL+1
      IF(MGOMGFL(YGOMV%MQ)   == JGFL) THEN
        YDGOM%LQ   = .TRUE.
        IQ = YDGOM%IGOMGFL
      ENDIF
      IF(MGOMGFL(YGOMV%MO3)  == JGFL) THEN
        YDGOM%LO3  = .TRUE.
        IO3 = YDGOM%IGOMGFL
      ENDIF
      IF(MGOMGFL(YGOMV%MCLW) == JGFL) THEN
        YDGOM%LCLW = .TRUE.
        ICLW = YDGOM%IGOMGFL
      ENDIF
      IF(MGOMGFL(YGOMV%MCIW) == JGFL) THEN
        YDGOM%LCIW = .TRUE.
        ICIW = YDGOM%IGOMGFL
      ENDIF
      IF(MGOMGFL(YGOMV%MCC)  == JGFL) THEN
        YDGOM%LCC  = .TRUE.
        ICC = YDGOM%IGOMGFL
      ENDIF
      DO JGHG=1,JPGHG
        IF(MGOMGFL(YGOMV%MGHG(JGHG))  == JGFL) THEN
          YDGOM%LGHG(JGHG)  = .TRUE.
          IF(IGHG == 0) IGHG = YDGOM%IGOMGFL
        ENDIF
      ENDDO
      DO JGRG=1,JPGRG
        IF(MGOMGFL(YGOMV%MGRG(JGRG))  == JGFL) THEN
          YDGOM%LGRG(JGRG)  = .TRUE.
          IF(IGRG == 0) IGRG = YDGOM%IGOMGFL
        ENDIF
      ENDDO
      DO JAERO=1,JPAERO
        IF(MGOMGFL(YGOMV%MAERO(JAERO))  == JGFL) THEN
          YDGOM%LAERO(JAERO)  = .TRUE.
          IF(IAERO == 0) IAERO = YDGOM%IGOMGFL
        ENDIF
      ENDDO
! below add rain, snow and graupel: e.wattrelot
      IF(MGOMGFL(YGOMV%MS)   == JGFL) THEN
        YDGOM%LS   = .TRUE.
        IS  = YDGOM%IGOMGFL
      ENDIF
      IF(MGOMGFL(YGOMV%MR)   == JGFL) THEN
        YDGOM%LR   = .TRUE.
        IR  = YDGOM%IGOMGFL
      ENDIF
      IF(MGOMGFL(YGOMV%MG)   == JGFL) THEN
        YDGOM%LG   = .TRUE.
        IG  = YDGOM%IGOMGFL
      ENDIF
! end rain, snow and graupel
    ENDIF
  ENDDO
ENDIF

IF(YDGOM%LU) THEN
   IF (LDALLO) YDGOM%U => POMDATUA(KOFF+1:KOFF+KLEV)
   KOFF = KOFF+KLEV
ENDIF
IF(YDGOM%LV) THEN
   IF (LDALLO) YDGOM%V => POMDATUA(KOFF+1:KOFF+KLEV)
   KOFF = KOFF+KLEV
ENDIF
IF(YDGOM%LT) THEN
   IF (LDALLO) YDGOM%T => POMDATUA(KOFF+1:KOFF+KLEV)
   KOFF = KOFF+KLEV
ENDIF

IF(YDGOM%IGOMGFL > 0 ) THEN
  IF (LDALLO) YDGOM%GFL => POMDATUA(KOFF+1:KOFF+KLEV*YDGOM%IGOMGFL)
  IF(YDGOM%LQ) THEN
    IOFF = KOFF+(IQ-1)*KLEV
    IF (LDALLO) YDGOM%Q => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  IF(YDGOM%LO3) THEN
    IOFF = KOFF+(IO3-1)*KLEV
    IF (LDALLO) YDGOM%O3 => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  IF(YDGOM%LCLW) THEN
    IOFF = KOFF+(ICLW-1)*KLEV
    IF (LDALLO) YDGOM%CLW => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  IF(YDGOM%LCIW) THEN
    IOFF = KOFF+(ICIW-1)*KLEV
    IF (LDALLO) YDGOM%CIW => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  IF(YDGOM%LCC) THEN
    IOFF = KOFF+(ICC-1)*KLEV
    IF (LDALLO) YDGOM%CC => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  IF(ANY(YDGOM%LGHG)) THEN
    IOFF = KOFF+(IGHG-1)*KLEV
    IENGHG = IOFF
    DO JGHG=1,JPGHG
      IF(YDGOM%LGHG(JGHG)) IENGHG = IENGHG+KLEV
    ENDDO
    IF (LDALLO) YDGOM%GHG => POMDATUA(IOFF+1:IENGHG)
  ENDIF
  IF(ANY(YDGOM%LGRG)) THEN
    IOFF = KOFF+(IGRG-1)*KLEV
    IENGRG = IOFF
    DO JGRG=1,JPGRG
      IF(YDGOM%LGRG(JGRG)) IENGRG = IENGRG+KLEV
    ENDDO
    IF (LDALLO) YDGOM%GRG => POMDATUA(IOFF+1:IENGRG)
  ENDIF
  IF(ANY(YDGOM%LAERO)) THEN
    IOFF = KOFF+(IAERO-1)*KLEV
    IENAERO = IOFF
    DO JAERO=1,JPAERO
      IF(YDGOM%LAERO(JAERO)) IENAERO = IENAERO+KLEV
    ENDDO
    IF (LDALLO) YDGOM%AERO => POMDATUA(IOFF+1:IENAERO)
  ENDIF
! add rain, snow and graupel
  IF(YDGOM%LS) THEN
    IOFF = KOFF+(IS-1)*KLEV
    IF (LDALLO) YDGOM%S  => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  IF(YDGOM%LR) THEN
    IOFF = KOFF+(IR-1)*KLEV
    IF (LDALLO) YDGOM%R  => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  IF(YDGOM%LG) THEN
    IOFF = KOFF+(IG-1)*KLEV
    IF (LDALLO) YDGOM%G  => POMDATUA(IOFF+1:IOFF+KLEV)
  ENDIF
  KOFF = KOFF+KLEV*YDGOM%IGOMGFL
ENDIF

IF(LDALLO) THEN
  IF(KOFF > SIZE(POMDATUA)) THEN
    WRITE(NULERR,*) 'GOMS_MIX:GOMCONSTRB ',KOFF,SIZE(POMDATUA)
    CALL ABOR1('GOMS_MIX:GOMCONSTRB - POMDATUA TOO SMALL')
  ENDIF
ENDIF
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCONSTRB',1,ZHOOK_HANDLE)
  
END SUBROUTINE GOMCONSTRB
!-------------------------------------------------------------------
SUBROUTINE GOMCONSTR_2D(YDGOMUA,YDGOMS,YDGOMEC,KLEV,KPROF,KTYP,KOBS,LD5)
! Constructor for  indiviual 2-D GOM structures
TYPE(TYPE_GOMUA_2D),INTENT(OUT) :: YDGOMUA ! Upper air
TYPE(TYPE_GOMS_2D),INTENT(OUT)  :: YDGOMS  ! Surface
TYPE(TYPE_GOMEC_2D),INTENT(OUT) :: YDGOMEC ! Constant/climate
INTEGER(KIND=JPIM),INTENT(IN) :: KLEV      ! Number of levels
INTEGER(KIND=JPIM),INTENT(IN) :: KPROF     ! Number of profiles 
INTEGER(KIND=JPIM),INTENT(IN) :: KTYP      ! Observation type
INTEGER(KIND=JPIM),INTENT(IN) :: KOBS      ! GOM number (MDB_MAPOMM_AT_INDEX)
LOGICAL,INTENT(IN) :: LD5                  ! TRUE if trajectory

INTEGER(KIND=JPIM) :: IOFF, JGFL,JGHG,JGRG,JAERO
INTEGER(KIND=JPIM),SAVE :: IQ,IO3,ICLW,ICIW,ICC,IS,IR,IG
INTEGER(KIND=JPIM) :: IGHG,IENGHG,IGRG,IENGRG,IAERO,IENAERO
REAL(KIND=JPRB) :: ZHOOK_HANDLE

IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCONSTR_2D',0,ZHOOK_HANDLE)
YDGOMUA%ITYP = KTYP
YDGOMUA%IOBS = KOBS

YDGOMUA%LU   = LGOMUA(KTYP,YGOMV%MU)
YDGOMUA%LV   = LGOMUA(KTYP,YGOMV%MV)
YDGOMUA%LT   = LGOMUA(KTYP,YGOMV%MT)
YDGOMUA%IGOMGFL = 0
ALLOCATE(YDGOMUA%LGFL(NGOMGFL))
YDGOMUA%LGFL(:) = .FALSE.
YDGOMUA%LQ   = .FALSE.
YDGOMUA%LO3  = .FALSE.
YDGOMUA%LCLW = .FALSE.
YDGOMUA%LCIW = .FALSE.
YDGOMUA%LCC  = .FALSE.
YDGOMUA%LS   = .FALSE.
YDGOMUA%LR   = .FALSE.
YDGOMUA%LG   = .FALSE.
YDGOMUA%LGHG(:)  = .FALSE.
YDGOMUA%LGRG(:)  = .FALSE.
YDGOMUA%LAERO(:)  = .FALSE.
IGHG=0
IGRG=0
IAERO=0
DO JGFL=1,NGOMGFL
  IF(LGOMGFL(KTYP,JGFL)) THEN
    YDGOMUA%LGFL(JGFL) = .TRUE.
    YDGOMUA%IGOMGFL =  YDGOMUA%IGOMGFL+1
    IF(MGOMGFL(YGOMV%MQ)   == JGFL) THEN
      YDGOMUA%LQ   = .TRUE.
      IQ = YDGOMUA%IGOMGFL
    ENDIF
    IF(MGOMGFL(YGOMV%MO3)  == JGFL) THEN
      YDGOMUA%LO3  = .TRUE.
      IO3 = YDGOMUA%IGOMGFL
    ENDIF
    IF(MGOMGFL(YGOMV%MCLW) == JGFL) THEN
      YDGOMUA%LCLW = .TRUE.
      ICLW = YDGOMUA%IGOMGFL
    ENDIF
    IF(MGOMGFL(YGOMV%MCIW) == JGFL) THEN
      YDGOMUA%LCIW = .TRUE.
      ICIW = YDGOMUA%IGOMGFL
    ENDIF
    IF(MGOMGFL(YGOMV%MCC)  == JGFL) THEN
      YDGOMUA%LCC  = .TRUE.
      ICC = YDGOMUA%IGOMGFL
    ENDIF
    DO JGHG=1,JPGHG
      IF(MGOMGFL(YGOMV%MGHG(JGHG))  == JGFL) THEN
        YDGOMUA%LGHG(JGHG)  = .TRUE.
        IF(IGHG == 0) IGHG = YDGOMUA%IGOMGFL
      ENDIF
    ENDDO
    DO JGRG=1,JPGRG
      IF(MGOMGFL(YGOMV%MGRG(JGRG))  == JGFL) THEN
        YDGOMUA%LGRG(JGRG)  = .TRUE.
        IF(IGRG == 0) IGRG = YDGOMUA%IGOMGFL
      ENDIF
    ENDDO
    DO JAERO=1,JPAERO
      IF(MGOMGFL(YGOMV%MAERO(JAERO))  == JGFL) THEN
        YDGOMUA%LAERO(JAERO)  = .TRUE.
        IF(IAERO == 0) IAERO = YDGOMUA%IGOMGFL
      ENDIF
    ENDDO
    IF(MGOMGFL(YGOMV%MS)   == JGFL) THEN
      YDGOMUA%LS   = .TRUE.
      IS  = YDGOMUA%IGOMGFL
    ENDIF
    IF(MGOMGFL(YGOMV%MR)   == JGFL) THEN
      YDGOMUA%LR   = .TRUE.
      IR  = YDGOMUA%IGOMGFL
    ENDIF
    IF(MGOMGFL(YGOMV%MG)   == JGFL) THEN
      YDGOMUA%LG   = .TRUE.
      IG  = YDGOMUA%IGOMGFL
    ENDIF
  ENDIF
ENDDO
IF(YDGOMUA%LU) ALLOCATE(YDGOMUA%U(KLEV,KPROF))
IF(YDGOMUA%LV) ALLOCATE(YDGOMUA%V(KLEV,KPROF))
IF(YDGOMUA%LT) ALLOCATE(YDGOMUA%T(KLEV,KPROF))
IF(YDGOMUA%IGOMGFL > 0 ) THEN
  ALLOCATE(YDGOMUA%GFL(YDGOMUA%IGOMGFL*KLEV,KPROF))
  IF(YDGOMUA%LQ) THEN
    IOFF = (IQ-1)*KLEV
    YDGOMUA%Q => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
  IF(YDGOMUA%LO3) THEN
    IOFF = (IO3-1)*KLEV
    YDGOMUA%O3 => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
  IF(YDGOMUA%LCLW) THEN
    IOFF = (ICLW-1)*KLEV
    YDGOMUA%CLW => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
  IF(YDGOMUA%LCIW) THEN
    IOFF = (ICIW-1)*KLEV
    YDGOMUA%CIW => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
  IF(YDGOMUA%LCC) THEN
    IOFF = (ICC-1)*KLEV
    YDGOMUA%CC => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
  IF (ANY(YDGOMUA%LGHG)) THEN
    IOFF = (IGHG-1)*KLEV
    DO JGHG=1,JPGHG
      IF(YDGOMUA%LGHG(JGHG)) IENGHG = IOFF+KLEV
    ENDDO
    YDGOMUA%GHG=> YDGOMUA%GFL(IOFF+1:IENGHG,:)
  ENDIF
  IF (ANY(YDGOMUA%LGRG)) THEN
    IOFF = (IGRG-1)*KLEV
    DO JGRG=1,JPGRG
      IF(YDGOMUA%LGRG(JGRG)) IENGRG = IOFF+KLEV
    ENDDO
    YDGOMUA%GRG=> YDGOMUA%GFL(IOFF+1:IENGRG,:)
  ENDIF
  IF (ANY(YDGOMUA%LAERO)) THEN
    IOFF = (IAERO-1)*KLEV
    DO JAERO=1,JPAERO
      IF(YDGOMUA%LAERO(JAERO)) IENAERO = IOFF+KLEV
    ENDDO
    YDGOMUA%AERO=> YDGOMUA%GFL(IOFF+1:IENAERO,:)
  ENDIF
  IF(YDGOMUA%LS) THEN
    IOFF = (IS-1)*KLEV
    YDGOMUA%S => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
  IF(YDGOMUA%LR) THEN
    IOFF = (IR-1)*KLEV
    YDGOMUA%R => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
  IF(YDGOMUA%LG) THEN
    IOFF = (IG-1)*KLEV
    YDGOMUA%G => YDGOMUA%GFL(IOFF+1:IOFF+KLEV,:)
  ENDIF
ENDIF  

ALLOCATE(YDGOMS%SP(KPROF))
ALLOCATE(YDGOMS%TS(KPROF))
ALLOCATE(YDGOMS%WS(KPROF))
ALLOCATE(YDGOMS%SN(KPROF))
ALLOCATE(YDGOMS%Z0(KPROF))
ALLOCATE(YDGOMS%U0(KPROF))
ALLOCATE(YDGOMS%V0(KPROF))
ALLOCATE(YDGOMS%U10N(KPROF))
ALLOCATE(YDGOMS%V10N(KPROF))
ALLOCATE(YDGOMS%WL(KPROF))
ALLOCATE(YDGOMS%UL(KPROF))
ALLOCATE(YDGOMS%VL(KPROF))
ALLOCATE(YDGOMS%TL(KPROF))
ALLOCATE(YDGOMS%QL(KPROF))
ALLOCATE(YDGOMS%SST(KPROF))
ALLOCATE(YDGOMS%CHN(KPROF))

IF( .NOT. LD5) THEN
  ALLOCATE(YDGOMEC%ECOROG(KPROF))
  ALLOCATE(YDGOMEC%ECCORI(KPROF))
  ALLOCATE(YDGOMEC%ECALBE(KPROF))
  ALLOCATE(YDGOMEC%ECEMIS(KPROF))
  ALLOCATE(YDGOMEC%ECLSMA(KPROF))
  ALLOCATE(YDGOMEC%ECCI(KPROF))
  ALLOCATE(YDGOMEC%ECCVH(KPROF))
  ALLOCATE(YDGOMEC%ECCVL(KPROF))
  ALLOCATE(YDGOMEC%ECTVH(KPROF))
  ALLOCATE(YDGOMEC%ECTVL(KPROF))

  ALLOCATE(YDGOMEC%ECDL(KPROF))
  ALLOCATE(YDGOMEC%ECDM(KPROF))
  ALLOCATE(YDGOMEC%ECVEGE(KPROF))

  ALLOCATE(YDGOMEC%ECARG(KPROF))
  ALLOCATE(YDGOMEC%ECSAB(KPROF))
  ALLOCATE(YDGOMEC%ECHV(KPROF))
  ALLOCATE(YDGOMEC%ECZ0H(KPROF))

  ALLOCATE(YDGOMEC%RLAT(KPROF))
  ALLOCATE(YDGOMEC%RLON(KPROF))

ENDIF
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCONSTR_2D',1,ZHOOK_HANDLE)

END SUBROUTINE GOMCONSTR_2D
!-----------------------------------------------------------------
SUBROUTINE GOMCOCA(YDGOM,KLEV)
TYPE(TYPE_GOMCAN_ALT),INTENT(OUT) :: YDGOM
INTEGER(KIND=JPIM),INTENT(IN) :: KLEV
REAL(KIND=JPRB) :: ZHOOK_HANDLE
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCOCA',0,ZHOOK_HANDLE)
ALLOCATE(YDGOM%EMMZ(KLEV))
ALLOCATE(YDGOM%EMMH(KLEV))
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:GOMCOCA',1,ZHOOK_HANDLE)
END SUBROUTINE GOMCOCA
!---------------------------------------------------------------
SUBROUTINE SET_GOM(KOBSTYPE,KNUM,PVAL)
! Set individual GOM structures (not constant/climate) to PVAL
INTEGER(KIND=JPIM),INTENT(IN) :: KOBSTYPE ! Obs type
INTEGER(KIND=JPIM),INTENT(IN) :: KNUM     ! GOM number (MDB_MAPOMM_AT_INDEX)
REAL(KIND=JPRB)   ,INTENT(IN) :: PVAL     ! Value to be set

REAL(KIND=JPRB) :: ZHOOK_HANDLE

IF (LHOOK) CALL DR_HOOK('GOMS_MIX:SET_GOM',0,ZHOOK_HANDLE)
IF(NOBSPROFS(KOBSTYPE) <= 1) THEN
  IF(YGOMUA(KNUM)%LU) YGOMUA(KNUM)%U(:) = PVAL
  IF(YGOMUA(KNUM)%LV) YGOMUA(KNUM)%V(:) = PVAL
  IF(YGOMUA(KNUM)%LT) YGOMUA(KNUM)%T(:) = PVAL
  IF(YGOMUA(KNUM)%IGOMGFL > 0 ) THEN
    YGOMUA(KNUM)%GFL(:)  = PVAL
  ENDIF
  YGOMS(KNUM)%LUPD=.FALSE.
  YGOMS(KNUM)%SP = PVAL
  YGOMS(KNUM)%TS = PVAL
  YGOMS(KNUM)%WS = PVAL
  YGOMS(KNUM)%SN = PVAL
  YGOMS(KNUM)%Z0 = PVAL
  YGOMS(KNUM)%U0 = PVAL
  YGOMS(KNUM)%V0 = PVAL
  YGOMS(KNUM)%U10N=PVAL
  YGOMS(KNUM)%V10N=PVAL
  YGOMS(KNUM)%WL = PVAL
  YGOMS(KNUM)%UL = PVAL
  YGOMS(KNUM)%VL = PVAL
  YGOMS(KNUM)%TL = PVAL
  YGOMS(KNUM)%QL = PVAL
  YGOMS(KNUM)%SST= PVAL
  YGOMS(KNUM)%CHN= PVAL
ELSE
  IF(YGOMUA_2D(KNUM)%LU) YGOMUA_2D(KNUM)%U(:,:) = PVAL
  IF(YGOMUA_2D(KNUM)%LV) YGOMUA_2D(KNUM)%V(:,:) = PVAL
  IF(YGOMUA_2D(KNUM)%LT) YGOMUA_2D(KNUM)%T(:,:) = PVAL
  IF(YGOMUA_2D(KNUM)%IGOMGFL > 0 ) THEN
    YGOMUA_2D(KNUM)%GFL(:,:)  = PVAL
  ENDIF

  YGOMS_2D(KNUM)%SP(:) = PVAL
  YGOMS_2D(KNUM)%TS(:) = PVAL
  YGOMS_2D(KNUM)%WS(:) = PVAL
  YGOMS_2D(KNUM)%SN(:) = PVAL
  YGOMS_2D(KNUM)%Z0(:) = PVAL
  YGOMS_2D(KNUM)%U10N(:)=PVAL
  YGOMS_2D(KNUM)%V10N(:)=PVAL
  YGOMS_2D(KNUM)%WL(:) = PVAL
  YGOMS_2D(KNUM)%UL(:) = PVAL
  YGOMS_2D(KNUM)%VL(:) = PVAL
  YGOMS_2D(KNUM)%TL(:) = PVAL
  YGOMS_2D(KNUM)%QL(:) = PVAL
  YGOMS_2D(KNUM)%SST(:) = PVAL
ENDIF
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:SET_GOM',1,ZHOOK_HANDLE)

END SUBROUTINE SET_GOM
!-------------------------------------------------------------------
SUBROUTINE CPGOM5T0
!Copy all GOM structures to GOM trajectory structures (not constant/climate)
INTEGER(KIND=JPIM) :: JOBS
REAL(KIND=JPRB) :: ZHOOK_HANDLE

IF (LHOOK) CALL DR_HOOK('GOMS_MIX:CPGOM5T0',0,ZHOOK_HANDLE)

GOMDATUA(:) = GOMDATUA5(:) !Copy storage area for upper-air 1D goms_mix

DO JOBS=1,NGOMS1D
  YGOMS(JOBS)%LUPD=YGOMS5(JOBS)%LUPD
  YGOMS(JOBS)%SP = YGOMS5(JOBS)%SP
  YGOMS(JOBS)%TS = YGOMS5(JOBS)%TS
  YGOMS(JOBS)%TCLS = YGOMS5(JOBS)%TCLS
  YGOMS(JOBS)%HUCLS = YGOMS5(JOBS)%HUCLS
  YGOMS(JOBS)%WS = YGOMS5(JOBS)%WS
  YGOMS(JOBS)%SN = YGOMS5(JOBS)%SN
  YGOMS(JOBS)%Z0 = YGOMS5(JOBS)%Z0
  YGOMS(JOBS)%U0 = YGOMS5(JOBS)%U0
  YGOMS(JOBS)%V0 = YGOMS5(JOBS)%V0
  YGOMS(JOBS)%U10N=YGOMS5(JOBS)%U10N
  YGOMS(JOBS)%V10N=YGOMS5(JOBS)%V10N
  YGOMS(JOBS)%WL = YGOMS5(JOBS)%WL
  YGOMS(JOBS)%UL = YGOMS5(JOBS)%UL
  YGOMS(JOBS)%VL = YGOMS5(JOBS)%VL
  YGOMS(JOBS)%TL = YGOMS5(JOBS)%TL
  YGOMS(JOBS)%QL = YGOMS5(JOBS)%QL
  YGOMS(JOBS)%SST= YGOMS5(JOBS)%SST
  YGOMS(JOBS)%CHN= YGOMS5(JOBS)%CHN
ENDDO

DO JOBS=1,NGOMS2D
  IF(YGOMUA_2D(JOBS)%LU) YGOMUA_2D(JOBS)%U(:,:) = YGOMUA5_2D(JOBS)%U(:,:)
  IF(YGOMUA_2D(JOBS)%LV) YGOMUA_2D(JOBS)%V(:,:) = YGOMUA5_2D(JOBS)%V(:,:)
  IF(YGOMUA_2D(JOBS)%LT) YGOMUA_2D(JOBS)%T(:,:) = YGOMUA5_2D(JOBS)%T(:,:)
  IF(YGOMUA_2D(JOBS)%IGOMGFL > 0) THEN
    YGOMUA_2D(JOBS)%GFL(:,:) = YGOMUA5_2D(JOBS)%GFL(:,:)
  ENDIF

  YGOMS_2D(JOBS)%SP(:) = YGOMS5_2D(JOBS)%SP(:)
  YGOMS_2D(JOBS)%TS(:) = YGOMS5_2D(JOBS)%TS(:)
  YGOMS_2D(JOBS)%WS(:) = YGOMS5_2D(JOBS)%WS(:)
  YGOMS_2D(JOBS)%SN(:) = YGOMS5_2D(JOBS)%SN(:)
  YGOMS_2D(JOBS)%Z0(:) = YGOMS5_2D(JOBS)%Z0(:)
  YGOMS_2D(JOBS)%U10N(:)=YGOMS5_2D(JOBS)%U10N(:)
  YGOMS_2D(JOBS)%V10N(:)=YGOMS5_2D(JOBS)%V10N(:)
  YGOMS_2D(JOBS)%WL(:) = YGOMS5_2D(JOBS)%WL(:)
  YGOMS_2D(JOBS)%UL(:) = YGOMS5_2D(JOBS)%UL(:)
  YGOMS_2D(JOBS)%VL(:) = YGOMS5_2D(JOBS)%VL(:)
  YGOMS_2D(JOBS)%TL(:) = YGOMS5_2D(JOBS)%TL(:)
  YGOMS_2D(JOBS)%QL(:) = YGOMS5_2D(JOBS)%QL(:)
  YGOMS_2D(JOBS)%SST(:)  = YGOMS5_2D(JOBS)%SST(:)
ENDDO

IF (LHOOK) CALL DR_HOOK('GOMS_MIX:CPGOM5T0',1,ZHOOK_HANDLE)
END SUBROUTINE CPGOM5T0
!-------------------------------------------------------------------
SUBROUTINE DEALLGOMS
REAL(KIND=JPRB) :: ZHOOK_HANDLE
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:DEALLGOMS',0,ZHOOK_HANDLE)
!write(0,*) 'IN GOMS_MIX - SUBROUTINE DEALLGOMS YET TO BE WRITTEN'
IF (LHOOK) CALL DR_HOOK('GOMS_MIX:DEALLGOMS',1,ZHOOK_HANDLE)
END SUBROUTINE DEALLGOMS
!---------------------------------------------------------------
END MODULE GOMS_MIX
