SUBROUTINE SUJQ

!     Purpose.
!     --------
!       Setup model error covariances

!     Author.
!     -------
!       Yannick Tremolet

!     Modifications.
!     --------------
!       Original  : 30-01-03
!        M.Hamrud      01-Oct-2003 CY28 Cleaning
!        Y.Tremolet    18-Mar-2004 Complete rewrite
!        Y.Tremolet    12-May-2004 Complete rewrite again
! ------------------------------------------------------------------

USE PARKIND1, ONLY: JPIM, JPRB
USE YOMHOOK , ONLY: LHOOK, DR_HOOK
USE YOMVAR  , ONLY: NUPTRA
USE YOMDIM  , ONLY: NFLEVG, NFLEVL
USE YOMLUN  , ONLY: NULOUT
USE YOMMP   , ONLY: MYLEVS
USE YOMLAP  , ONLY: MYMS
USE YOMJQ   , ONLY: LJQHCOR, LJQVCOR, ERRMODMN, ERRHCOR, ERRVCOR, ERRVCORIN, &
                  & NVALERR, SPJQMODERR, SPJQMODER5, LQEQB
USE YOMMODEL_ERROR, ONLY: NVE2D, NVE3D, NSERR, SPCTLMODERR, NTYPE_MODERR, &
                        & NDIM_MODERR, NGRBMERRCTL, LOVERLAPPING4D, &
                        & ALPHAQ_Q,ALPHAQ_O
USE SPECTRAL_FIELDS_MOD

IMPLICIT NONE
REAL(KIND=JPRB) :: ZCOVT(NFLEVG+1,NFLEVG+1,0:NSERR) ! (Tem,Ps)
REAL(KIND=JPRB) :: ZCOVV(NFLEVG,  NFLEVG,  0:NSERR) ! Vorticity
REAL(KIND=JPRB) :: ZCOVD(NFLEVG,  NFLEVG,  0:NSERR) ! Divergence
REAL(KIND=JPRB) :: ZCOVQ(NFLEVG,  NFLEVG,  0:NSERR) ! Humidity
REAL(KIND=JPRB) :: ZCOVO(NFLEVG,  NFLEVG,  0:NSERR) ! Ozone
REAL(KIND=JPRB) :: ZHCORV(NFLEVG,0:NSERR), ZHCORD(NFLEVG,0:NSERR)
REAL(KIND=JPRB) :: ZHCORQ(NFLEVG,0:NSERR), ZHCORO(NFLEVG,0:NSERR)
REAL(KIND=JPRB) :: ZHCORT(NFLEVG+1,0:NSERR)
INTEGER(KIND=JPIM) :: jl,il,ii,im,jm,jn,jc
CHARACTER(LEN=14) :: clfile
REAL(KIND=JPRB) :: ZHOOK_HANDLE

#include "abor1.intfb.h"
#include "sujqdata.intfb.h"
#include "sujqcor.intfb.h"
#include "sujqstd.intfb.h"
#include "rdmoderr.intfb.h"
! -----------------------------------------------------------------

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

IF (.NOT.LQEQB) THEN 

  WRITE(NULOUT,*)'SUJQ: Setting up model error covariances'

  IF (ASSOCIATED(ERRMODMN%V2D).OR.ASSOCIATED(ERRMODMN%V3D)) &
   & CALL ABOR1('SUJQ: ERRMODMN already allocated')
  IF (ASSOCIATED(ERRHCOR%SP2D).OR.ASSOCIATED(ERRHCOR%SP3D)) &
   & CALL ABOR1('SUJQ: ERRHCOR already allocated')
  IF (ASSOCIATED(ERRVCOR%VOR).OR.ASSOCIATED(ERRVCOR%DIV)) &
   & CALL ABOR1('SUJQ: ERRVCOR already allocated')
  IF (ASSOCIATED(ERRVCORIN%VOR).OR.ASSOCIATED(ERRVCORIN%DIV)) &
   & CALL ABOR1('SUJQ: ERRVCORIN already allocated')

! Allocate model error vertical correlations
! ------------------------------------------
  IF (LJQVCOR) THEN
    ALLOCATE(ERRVCOR%VOR(NFLEVG,NFLEVG,0:NSERR))
    ALLOCATE(ERRVCOR%DIV(NFLEVG,NFLEVG,0:NSERR))
    ALLOCATE(ERRVCOR%TPS(NFLEVG+1,NFLEVG+1,0:NSERR))
    ALLOCATE(ERRVCOR%HUM(NFLEVG,NFLEVG,0:NSERR))
    ALLOCATE(ERRVCOR%OZN(NFLEVG,NFLEVG,0:NSERR))

    ALLOCATE(ERRVCORIN%VOR(NFLEVG,NFLEVG,0:NSERR))
    ALLOCATE(ERRVCORIN%DIV(NFLEVG,NFLEVG,0:NSERR))
    ALLOCATE(ERRVCORIN%TPS(NFLEVG+1,NFLEVG+1,0:NSERR))
    ALLOCATE(ERRVCORIN%HUM(NFLEVG,NFLEVG,0:NSERR))
    ALLOCATE(ERRVCORIN%OZN(NFLEVG,NFLEVG,0:NSERR))

    WRITE(NULOUT,9)'ERRVCOR%VOR',SIZE(ERRVCOR%VOR),SHAPE(ERRVCOR%VOR)
    WRITE(NULOUT,9)'ERRVCOR%DIV',SIZE(ERRVCOR%DIV),SHAPE(ERRVCOR%DIV)
    WRITE(NULOUT,9)'ERRVCOR%TPS',SIZE(ERRVCOR%TPS),SHAPE(ERRVCOR%TPS)
    WRITE(NULOUT,9)'ERRVCOR%HUM',SIZE(ERRVCOR%HUM),SHAPE(ERRVCOR%HUM)
    WRITE(NULOUT,9)'ERRVCOR%OZN',SIZE(ERRVCOR%OZN),SHAPE(ERRVCOR%OZN)
  ENDIF

! Allocate model error horizontal correlations
! --------------------------------------------
  IF (LJQHCOR) THEN
    ALLOCATE(ERRHCOR%SP2D(0:NSERR,NVE2D))
    ALLOCATE(ERRHCOR%SP3D(NFLEVL,0:NSERR,NVE3D))
    WRITE(NULOUT,9)'ERRHCOR%SP2D',SIZE(ERRHCOR%SP2D),SHAPE(ERRHCOR%SP2D)
    WRITE(NULOUT,9)'ERRHCOR%SP3D',SIZE(ERRHCOR%SP3D),SHAPE(ERRHCOR%SP3D)
  ENDIF
9 FORMAT(1X,'SUJQ ',A15,' ALLOCATED ',4I8)

! Allocate mean model error
! -------------------------
  ALLOCATE(ERRMODMN%V2D(NVE2D))
  ALLOCATE(ERRMODMN%V2DINV(NVE2D))
  ALLOCATE(ERRMODMN%V3D(NFLEVL,NVE3D))
  ALLOCATE(ERRMODMN%V3DINV(NFLEVL,NVE3D))
  ALLOCATE(ERRMODMN%VALPHA(NFLEVL))

! Read data from file
! -------------------
  CALL SUJQDATA(NFLEVG,NSERR,ZCOVT,ZCOVV,ZCOVD,ZCOVQ,ZCOVO)

! Set up vertical correlations (spectral)
! ---------------------------------------
  IF (LJQVCOR) THEN
    CALL SUJQCOR(NFLEVG+1,NSERR,ZCOVT,ERRVCORIN%TPS,ERRVCOR%TPS,ZHCORT,"TPS")
    CALL SUJQCOR(NFLEVG  ,NSERR,ZCOVV,ERRVCORIN%VOR,ERRVCOR%VOR,ZHCORV,"VOR")
    CALL SUJQCOR(NFLEVG  ,NSERR,ZCOVD,ERRVCORIN%DIV,ERRVCOR%DIV,ZHCORD,"DIV")
    CALL SUJQCOR(NFLEVG  ,NSERR,ZCOVQ,ERRVCORIN%HUM,ERRVCOR%HUM,ZHCORQ,"HUM")
    CALL SUJQCOR(NFLEVG  ,NSERR,ZCOVO,ERRVCORIN%OZN,ERRVCOR%OZN,ZHCORO,"OZN")

    ALLOCATE(NVALERR(SPCTLMODERR%nspec2))
    ii=0
    DO jm=1,SPCTLMODERR%NUMP
      im=MYMS(jm)
      DO jn=im,NSERR
        NVALERR(ii+1)=jn
        NVALERR(ii+2)=jn
        ii=ii+2
      ENDDO
    ENDDO
    IF (ii/=SPCTLMODERR%nspec2) CALL ABOR1('SUJQ: Error setup NVALERR')
  ENDIF

! Set up horizontal correlations (spectral)
! -----------------------------------------
  IF (LJQHCOR) THEN
    DO jl=1,NFLEVL
      il=MYLEVS(jl)
      ERRHCOR%SP3D(jl,:,1)=ZHCORV(il,:)
      ERRHCOR%SP3D(jl,:,2)=ZHCORD(il,:)
      ERRHCOR%SP3D(jl,:,3)=ZHCORT(il,:)
      ii=3
      IF (ALPHAQ_Q>0.0_JPRB) THEN
        ii=ii+1
        ERRHCOR%SP3D(jl,:,ii)=ZHCORQ(il,:)
      ENDIF
      IF (ALPHAQ_O>0.0_JPRB) THEN
        ii=ii+1
        ERRHCOR%SP3D(jl,:,ii)=ZHCORO(il,:)
      ENDIF
    ENDDO
    ERRHCOR%SP2D(:,1)=ZHCORT(NFLEVG+1,:)
  ENDIF

! Set up standard error profiles
! ------------------------------
  CALL SUJQSTD(ZCOVT,ZCOVV,ZCOVD,ZCOVQ,ZCOVO,ERRMODMN)

! Done
! ----
  WRITE(NULOUT,*)'SUJQ: Model error covariances have been set up'
ENDIF   !LQEQB 

! Allocate space to store M(x_i) for computation of M(x_i)-x_{i+1} in Jq.
! -----------------------------------------------------------------------
IF (NTYPE_MODERR==1) THEN

  ALLOCATE(SPJQMODERR(NDIM_MODERR))
  DO jc=1,NDIM_MODERR
    CALL ALLOCATE_SPEC(SPJQMODERR(jc),NSERR,0,NVE3D,NVE2D,0,NGRBMERRCTL)
  ENDDO
  WRITE(NULOUT,*)'SUJQ: SPJQMODERR allocated'

  IF (NUPTRA>0.OR.ANY(LOVERLAPPING4D)) THEN
    ALLOCATE(SPJQMODER5(NDIM_MODERR))
    WRITE(NULOUT,*)'SUJQ: SPJQMODER5 allocated'

    DO jc=1,NDIM_MODERR
      IF (NUPTRA>0.OR.LOVERLAPPING4D(jc)) THEN
        CALL ALLOCATE_SPEC(SPJQMODER5(jc),NSERR,0,NVE3D,NVE2D,0,NGRBMERRCTL)
        clfile(1:14)='spmoderrjqXXYY'
        write(clfile(11:12),'(I2.2)')NUPTRA
        write(clfile(13:14),'(I2.2)')jc
        WRITE(NULOUT,*)'SUJQ: Reading',clfile
        CALL RDMODERR(clfile,SPJQMODER5(jc))
      ENDIF
    ENDDO
  ENDIF

ENDIF

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