SUBROUTINE PERTOBS_UNCORR (KDLEN,KDBDY,KSET,KTSLOT,YDSTREAM)

!**** SUBROUTINE PERTOBS_UNCORR - ADD SPATIALLY-UNCORRELATED RANDOM PERTURBATIONS TO OBSERVATIONS

!          MIKE FISHER ECMWF 11-Oct-2004

!*    PURPOSE
!     -------

!          ADD SPATIALLY-UNCORRELATED RANDOM PERTURBATIONS TO OBSERVATIONS

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

!     ***CALL PERTOBS_UNCORR (KDLEN,KDBDY,KSET,YDSTREAM)

!        PERTOBS_UNCORR IS CALLED FROM PERTORBS

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

!*    METHOD
!     ------

!       STRIPPED-DOWN VERSION OF HRETR

!**   MODIFICATIONS
!     -------------

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

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,  DR_HOOK
USE YOMLUN   , ONLY : NULERR
USE YOMOBSET , ONLY : MLNSET, MTYPOB
USE YOMCOCTP , ONLY : NSATOB, NSCATT, NSCAT2, NSCAT5, NSCAT6
USE YOMSCC   , ONLY : NAENSEMBLE, NAEMEMBER
USE YOMANCS  , ONLY : RMDI
USE YOMDB
USE RANDOM_NUMBERS_MIX

IMPLICIT NONE

INTEGER(KIND=JPIM),       INTENT(IN)    :: KDLEN, KDBDY, KSET, KTSLOT
TYPE(randomNumberStream), INTENT(INOUT) :: YDSTREAM

INTEGER(KIND=JPIM) :: ILEN, IMXBDY, ISEED, I, ICOUNT_DSTA, &
                    & IRET, JOBS, JBODY, IBODY, ICOUNT_RSTA, IOBSTYPE
INTEGER(KIND=JPIM) :: INFO(1), IRSTA(4), IDSTA(4), ICMBDY(KDLEN)
REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZINFO(1), ZPERT
REAL(KIND=JPRB), ALLOCATABLE :: ZRAND(:)

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

#include "ngedsta.intfb.h"
#include "ngersta.intfb.h"
#include "setran.intfb.h"

#include "openmp_obs.h"

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

IOBSTYPE = MOD(MTYPOB(KSET),100)
ILEN=MLNSET(KSET)

! SATOBs are treated in PERTOBS
  
IF (ILEN>0 .AND. IOBSTYPE /= NSATOB) THEN

!    Get obs from ODB


  CALL GETDB ('PERTOBS_UNCORR',1,IRET,INFO,0,ZINFO,0, &
            & KSET,KTSLOT,-1,-1,-1,-1)
  IF (IRET/=ILEN) THEN
    WRITE(NULERR,'('' ** INCONSISTENT NO. OF OBSERVATIONS FROM GETDB'')')
    WRITE(NULERR,*)' Expecting ',ILEN,', but got =',IRET
    CALL ABORTDB('PERTOBS_UNCORR', 'INCONSISTENCIES FROM GETDB', IRET)
  ENDIF

  DO JOBS = 1,ILEN
    ICMBDY(JOBS)=MLNKH2B(JOBS+1)-MLNKH2B(JOBS)
  ENDDO

  IMXBDY   = MAXVAL(ICMBDY(1:ILEN))

!    Generate random numbers for this KSET

  ISEED = KSET * 10000 + NAENSEMBLE * 100 + NAEMEMBER
  CALL SETRAN (ISEED,YDSTREAM)
  ALLOCATE(ZRAND(IMXBDY*ILEN))
  CALL GAUSSIAN_DISTRIBUTION(ZRAND,YDSTREAM)

!    Add the random perturbations to the observed values

  OBS_LOOP: DO JOBS = 1,ILEN
!      Skip passive/rejected/blacklisted reports
    CALL NGERSTA(INT(ROBHDR(JOBS,MDBRST)),ICOUNT_RSTA,IRSTA)
    IF (( IRSTA(2) + IRSTA(3) + IRSTA(4) ) > 0 ) CYCLE OBS_LOOP

    BODY_LOOP: DO JBODY=1,ICMBDY(JOBS)
      IBODY=MLNKH2B(JOBS)+(JBODY-1)
!      Skip passive/rejected/blacklisted reports
      CALL NGEDSTA(INT(ROBODY(IBODY,MDBDSTA)),ICOUNT_DSTA,IDSTA)
      IF( ( IDSTA(2) + IDSTA(3) + IDSTA(4) ) > 0 ) CYCLE BODY_LOOP

!      Skip missing final obserror
      IF (ROBODY(IBODY,MDBFOE)==RMDI) CYCLE BODY_LOOP

!      Generate the perturbation.
      I = JBODY + (JOBS-1)*IMXBDY

      IF (IOBSTYPE==NSCATT) THEN
        IF (ANY(ROBHDR(JOBS,MDB_CODETYPE_AT_HDR)==(/NSCAT5,NSCAT6/))) THEN
!      QuickSCAT/Oceansat obseravtion error is too large -- use smaller perturbation
          ZPERT = ZRAND(I)*1.2_JPRB
        ELSEIF (ROBHDR(JOBS,MDB_CODETYPE_AT_HDR)==NSCAT2) THEN
!      ERS obseravtion error is too large -- use smaller perturbation
          ZPERT = ZRAND(I)*1.4_JPRB
        ELSE
!      Any other SCATT: use the specified observation error
          ZPERT = ZRAND(I)*ROBODY(IBODY,MDBFOE)
        ENDIF
      ELSE
!      Any other observation type: use the specified observation error
        ZPERT = ZRAND(I)*ROBODY(IBODY,MDBFOE)
      ENDIF

!      Add the perturbation
      IF (ROBODY(IBODY,MDBVAR)     /= RMDI) &
        & ROBODY(IBODY,MDBVAR)     = ROBODY(IBODY,MDBVAR)     + ZPERT
      IF (ROBODY(IBODY,MDBOMF)     /= RMDI) &
        & ROBODY(IBODY,MDBOMF)     = ROBODY(IBODY,MDBOMF)     + ZPERT
      IF (ROBODY(IBODY,MDBIFC1(1)) /= RMDI) &
        & ROBODY(IBODY,MDBIFC1(1)) = ROBODY(IBODY,MDBIFC1(1)) + ZPERT
    ENDDO BODY_LOOP
  ENDDO OBS_LOOP

!    Store the perturbed obs in the ODB

  CALL PUTDB ('PERTOBS_UNCORR',1,IRET,INFO,0,ZINFO,0)

  DEALLOCATE(ZRAND)
ENDIF

IF (LHOOK) CALL DR_HOOK('PERTOBS_UNCORR',1,ZHOOK_HANDLE)
END SUBROUTINE PERTOBS_UNCORR
