SUBROUTINE GP_SSMI

!**** *GP_SSMI* - RAIN ASSIMILATION - GET SSMI OBS IN GRID-POINT SPACE for
!     1D-Var in clouds/precipitation for SSM/I radiances

!     P. Bauer, P. Lopez, E. Moreau, D. Salmond   ECMWF    May 2004

!     PURPOSE.
!     -------
!     GET SSMI OBS FROM ODB TO GRID-POINT SPACE

!**   INTERFACE.
!**   ---------
!**   *CALL* * GP_SSMI()*  (FROM GP_MODEL)

!        Explicit arguments :


!     AUTHOR: Deborah Salmond
!     DATE  : 02-04-2004

!     Modifications :
!     M.Hamrud    : 15-Mar-2005 New GOM structures
!     D.Salmond   : 01-Jul-2005 Bit reproducible OBS/GP matching
!     P. Bauer    : 16-Oct-2006 Allow other passive microwave imagers
!     A.Geer      : 23-Oct-2006 Extra minimisation info and failure codes 
!     A.Geer      : 27-Feb-2007 Multiple sensors
!     S.Saarinen  : 06-Nov-2007 Channel search replaced with much faster alternative
!     S.Saarinen  : 06-Nov-2007 ZLATOBS, ZLONOBS as POINTERs
!     ------------------------------------------------------------------
USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
USE YOMDB
USE YOM_SSMI  ,ONLY : RAIN_1D_GP, RAIN_1DDIAG_GP, RAIN_2DCHAN_GP, &
 &   MID_GP, MIT_GP, MIS_GP, MEPSG_GP, MIM_GP, MISATID_GP, MIFOV_GP, &
 &   MIZEN_GP, MIAZI_GP
USE YOM_PTR_SSMI ,ONLY : MFLDS_1D,MFLDS_1DDIAG,MFLDS_2DCHAN
USE PARONEDVAR,ONLY : NMAX_CHANNELS, RMISSING_ANGLE
USE YOMONEDVAR,ONLY : STREAM1D_NUM
USE YOMGEM    ,ONLY : NGPTOT
USE YOMECTAB  ,ONLY : NTSLOTNOS
USE YOMCOCTP , ONLY : NSATEM

IMPLICIT NONE

REAL(KIND=JPRB),POINTER :: ZLONOBS(:), ZLATOBS(:)
REAL(KIND=JPRB),ALLOCATABLE :: ZZEN_OBS(:), ZAZI_OBS(:)
INTEGER(KIND=JPIM),ALLOCATABLE :: ISEQNO(:)
INTEGER(KIND=JPIM),ALLOCATABLE :: IISATID_OBS(:)
INTEGER(KIND=JPIM),ALLOCATABLE :: ISENSID_OBS(:)
INTEGER(KIND=JPIM),ALLOCATABLE :: IIFOV_OBS(:)
REAL(KIND=JPRB),ALLOCATABLE :: ZOBSV_OBS(:,:)
INTEGER(KIND=JPIM) :: ILEN,ITS,JOBS,ICHAN,IOFFSET,IOBSTYPE
INTEGER(KIND=JPIM) :: JBODY, INFO(0), IRET, JSTREAM1D
INTEGER(KIND=JPIM) :: ICMBDY
REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZINFO(0)

INTERFACE
#include "getdb.h"
#include "putdb.h"
END INTERFACE

#include "gp_nearest.intfb.h"
#include "gp_ssmi_obs2gp.intfb.h"
#include "gp_ssmi_iobs2gp.intfb.h"
#include "openmp_obs.h"

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

CALL GSTATS(1975,0)

ITS=NTSLOTNOS

IF (.NOT.ALLOCATED(RAIN_1D_GP))     ALLOCATE(RAIN_1D_GP(NGPTOT,STREAM1D_NUM,MFLDS_1D))
IF (.NOT.ALLOCATED(RAIN_1DDIAG_GP))  &
    &     ALLOCATE(RAIN_1DDIAG_GP(NGPTOT,STREAM1D_NUM,MFLDS_1DDIAG))
IF (.NOT.ALLOCATED(RAIN_2DCHAN_GP)) ALLOCATE(RAIN_2DCHAN_GP(NGPTOT,&
    &  STREAM1D_NUM,NMAX_CHANNELS,MFLDS_2DCHAN))
IF (.NOT.ALLOCATED(MID_GP))         ALLOCATE(MID_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MIT_GP))         ALLOCATE(MIT_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MIS_GP))         ALLOCATE(MIS_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MEPSG_GP))       ALLOCATE(MEPSG_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MIM_GP))         ALLOCATE(MIM_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MISATID_GP))     ALLOCATE(MISATID_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MIFOV_GP))       ALLOCATE(MIFOV_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MIZEN_GP))       ALLOCATE(MIZEN_GP(NGPTOT,STREAM1D_NUM))
IF (.NOT.ALLOCATED(MIAZI_GP))       ALLOCATE(MIAZI_GP(NGPTOT,STREAM1D_NUM))

RAIN_1D_GP=0.0_JPRB
RAIN_1DDIAG_GP=0.0_JPRB
RAIN_2DCHAN_GP=0.0_JPRB
MIT_GP=0
MIS_GP=0
MEPSG_GP=0.0_JPRB
MIM_GP=0
MID_GP=-1
MISATID_GP=0
MIFOV_GP=0
MIZEN_GP=RMISSING_ANGLE
MIAZI_GP=RMISSING_ANGLE

IOBSTYPE=NSATEM

CALL GSTATS(1975,2)
CALL GSTATS(1794,0)
CALL GETDB('GP_GET_SSMI',0, ILEN, INFO, 0, ZINFO, 0, -1, ITS, -1, IOBSTYPE, -1, -1)
CALL GSTATS(1794,1)
CALL GSTATS(1975,3)

ALLOCATE(ZOBSV_OBS(ILEN,NMAX_CHANNELS))
ZOBSV_OBS=0.0_JPRB
!ALLOCATE(ZLATOBS(ILEN))
ZLATOBS => ROBHDR(:,MDBLAT)
!ALLOCATE(ZLONOBS(ILEN))
ZLONOBS => ROBHDR(:,MDBLON)
ALLOCATE(ISEQNO(ILEN))
ALLOCATE(IISATID_OBS(ILEN))
ALLOCATE(ISENSID_OBS(ILEN))
ALLOCATE(IIFOV_OBS(ILEN))
ALLOCATE(ZZEN_OBS(ILEN))
ALLOCATE(ZAZI_OBS(ILEN))

! Extract observation "Header" info
DO JOBS=1,ILEN
!  ZLATOBS(JOBS)=ROBHDR(JOBS,MDBLAT)
!  ZLONOBS(JOBS)=ROBHDR(JOBS,MDBLON)
  ISEQNO(JOBS)=ROBHDR(JOBS,MDBONM)
  IISATID_OBS(JOBS) = ROBHDR(JOBS,MDB_SATID_AT_SAT)
  ISENSID_OBS(JOBS) = ROBHDR(JOBS, MDBSSIA)
  IIFOV_OBS(JOBS)=ROBHDR(JOBS,MDB_SCANPOS_AT_RADIANCE) ! FOV for SSM/I
  ZZEN_OBS(JOBS) = ROBHDR(JOBS,MDB_ZENITH_AT_SAT)
  if (ZZEN_OBS(JOBS) < 0.0_JPRB) ZZEN_OBS(JOBS) = RMISSING_ANGLE
  ZAZI_OBS(JOBS) = ROBHDR(JOBS,MDB_AZIMUTH_AT_SAT)
  if (ZAZI_OBS(JOBS) < -180.0_JPRB) ZAZI_OBS(JOBS) = RMISSING_ANGLE
ENDDO

! Extract observation "Body" info - i.e. brightness temperatures in each channel

DO JOBS=1,ILEN
  ICMBDY=MLNKH2B(JOBS+1)-MLNKH2B(JOBS)
  IOFFSET=MLNKH2B(JOBS)-1
  DO JBODY=IOFFSET+1,IOFFSET+ICMBDY
    ICHAN=ROBODY(JBODY,MDBPPP)
    IF (ICHAN >= 1 .AND. ICHAN <= NMAX_CHANNELS) THEN
      ZOBSV_OBS(JOBS,ICHAN)=ROBODY(JBODY,MDBVAR)
    ENDIF
  ENDDO    
ENDDO
  
! Loop through each stream in turn
CALL GSTATS(1975,2)
DO JSTREAM1D=1,STREAM1D_NUM

  ! Match observations to grid points 
  CALL GP_NEAREST(ZLATOBS,ZLONOBS,IISATID_OBS,ISEQNO,ILEN,JSTREAM1D)

  ! Transfer observation data to grid point space 
  CALL GP_SSMI_OBS2GP  (ZOBSV_OBS,RAIN_2DCHAN_GP(:,JSTREAM1D,:,:),NMAX_CHANNELS,ILEN,JSTREAM1D)
  CALL GP_SSMI_IOBS2GP (IISATID_OBS,MISATID_GP(:,JSTREAM1D),ILEN,JSTREAM1D)
  CALL GP_SSMI_IOBS2GP (IIFOV_OBS,MIFOV_GP(:,JSTREAM1D),ILEN,JSTREAM1D)
  CALL GP_SSMI_OBS2GP (ZZEN_OBS,MIZEN_GP(:,JSTREAM1D),1,ILEN,JSTREAM1D)
  CALL GP_SSMI_OBS2GP (ZAZI_OBS,MIAZI_GP(:,JSTREAM1D),1,ILEN,JSTREAM1D)
  
ENDDO
CALL GSTATS(1975,3)

DEALLOCATE(ZOBSV_OBS)
DEALLOCATE(IISATID_OBS)
DEALLOCATE(ISENSID_OBS)
DEALLOCATE(IIFOV_OBS)
!DEALLOCATE(ZLATOBS)
!DEALLOCATE(ZLONOBS)
DEALLOCATE(ISEQNO)
DEALLOCATE(ZZEN_OBS)
DEALLOCATE(ZAZI_OBS)

CALL GSTATS(1975,2)
CALL GSTATS(1794,0)
CALL PUTDB('GP_GET_SSMI', 0, IRET, INFO, 0, ZINFO, 0)
CALL GSTATS(1794,1)
CALL GSTATS(1975,3)

CALL GSTATS(1975,1)

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

END SUBROUTINE GP_SSMI
