MODULE varbc_to3
!-----------------------------------------------------------------------
!   VARBC_TO3 - Module for variational bias correction (ozone data)

!   Purpose. 
!   --------
!   Data structures and controls for variational bias correction (ozone data)

!   Author.
!   -------
!   Dick Dee (ECMWF)

!   Modifications.
!   --------------
!   Original    2008/10/01
!   A. Inness   2009/07/22 Add varno as selection criterion and activate bias
!                          correction for GRG
!   A. Benedetti 2009/08/15 Activate bias correction for aerosol optical depth (AOD) 
!------------------------------------------------------------------------

USE parkind1  , ONLY : JPIM, JPRB
USE yomhook   , ONLY : LHOOK, DR_HOOK
USE yomlun    , ONLY : NULOUT, NULNAM
!USE yomcoctp  , ONLY : NSTRO3
USE yomtvrad  , ONLY : SATREO3GRP_TABLE, NSATREO3GRP
USE varbc_pred, ONLY : NPREDCS_TO3
USE yomdb

IMPLICIT NONE

SAVE

PRIVATE
PUBLIC lbc_to3
PUBLIC varbc_to3_config, varbc_to3_groups
PUBLIC varbc_to3_varbcix, varbc_to3_pred
PUBLIC varbc_to3_min, varbc_to3_groupdescr

INTERFACE varbc_to3_config
  MODULE PROCEDURE config
END INTERFACE varbc_to3_config

INTERFACE varbc_to3_groups
  MODULE PROCEDURE find_groups
END INTERFACE varbc_to3_groups

INTERFACE varbc_to3_groupdescr
  MODULE PROCEDURE groupdescr
END INTERFACE varbc_to3_groupdescr

INTERFACE varbc_to3_pred
  MODULE PROCEDURE get_predictors
END INTERFACE varbc_to3_pred

INTERFACE varbc_to3_varbcix
  MODULE PROCEDURE set_varbcix
END INTERFACE varbc_to3_varbcix

INTERFACE varbc_to3_min
  MODULE PROCEDURE get_min
END INTERFACE varbc_to3_min

CHARACTER(LEN=*), PARAMETER :: modname = 'VarBC_TO3'

! Table for available satellite/sensor/varno combinations 
! -------------------------------------------------------
TYPE type_sensors
  INTEGER(KIND=JPIM) :: nbufrid 
  INTEGER(KIND=JPIM) :: nsensor 
  INTEGER(KIND=JPIM) :: nvarno 
  INTEGER(KIND=JPIM) :: nprod_type 
END TYPE type_sensors

INTEGER(KIND=JPIM), PARAMETER :: jpmxns = 100   ! max number of sat/sensor/varno combinations
TYPE(type_sensors) :: YSENSORS(1:jpmxns)

INTEGER(KIND=JPIM), PARAMETER :: jpmxnl = 21    ! max number of layers per instrument
INTEGER(KIND=JPIM), PARAMETER :: jpmxnp = SIZE(NPREDCS_TO3) ! max number of parameters per group

! Table for settings by instrument
! --------------------------------
TYPE type_config
  CHARACTER(LEN=20)  :: name              ! instrument name
  INTEGER(KIND=JPIM) :: nsensor           ! sensor id
  INTEGER(KIND=JPIM) :: nvarno            ! variable number
  INTEGER(KIND=JPIM) :: nlayers           ! number of layers
  INTEGER(KIND=JPIM) :: nprod_type        ! product type
  REAL(KIND=JPRB)    :: press(jpmxnl)     ! layer edges
  INTEGER(KIND=JPIM) :: nparam            ! number of parameters
  INTEGER(KIND=JPIM) :: npredcs(jpmxnp)   ! list of predictors
  LOGICAL            :: llconst(jpmxnp)   ! flags for constant parameters
  REAL(KIND=JPRB)    :: zparams(jpmxnp)   ! a priori parameter values
  REAL(KIND=JPRB)    :: dfgdep(jpmxnl)    ! histogram range, for estimating the mode
  INTEGER(KIND=JPIM) :: ncstart           ! cold start option
  INTEGER(KIND=JPIM) :: nbgstdv           ! eqv #obs for background constraint
  LOGICAL            :: lreset            ! flag to reset parameters
  LOGICAL            :: llmode            ! flag for mode correction
END TYPE type_config

!-----------------------------------------------------------------------
! Namelist parameters
!-----------------------------------------------------------------------
TYPE(type_config)  :: yconfig(1:32)
LOGICAL            :: lbc_to3
LOGICAL            :: lbc_toms, lbc_sbuv, lbc_gome, lbc_sciamachy, lbc_gomos, &
                    & lbc_mipas, lbc_seviri, lbc_omi, lbc_mls, lbc_gome2
INTEGER(KIND=JPIM) :: nbg_toms, nbg_sbuv, nbg_gome, nbg_sciamachy, nbg_gomos, &
                    & nbg_mipas, nbg_seviri, nbg_omi, nbg_mls, nbg_gome2
LOGICAL            :: lbc_go3_toms, lbc_go3_sbuv, lbc_go3_gome, &
                    & lbc_go3_sciamachy, lbc_go3_gomos, lbc_go3_mipas, &
                    & lbc_go3_seviri, lbc_go3_omi, lbc_go3_mls, lbc_go3_gome2
INTEGER(KIND=JPIM) :: nbg_go3_toms, nbg_go3_sbuv, nbg_go3_gome, &
                    & nbg_go3_sciamachy, nbg_go3_gomos, nbg_go3_mipas, &
                    & nbg_go3_seviri, nbg_go3_omi, nbg_go3_mls, nbg_go3_gome2
LOGICAL            :: lbc_co_mopitt, lbc_co_iasi
INTEGER(KIND=JPIM) :: nbg_co_mopitt, nbg_co_iasi
LOGICAL            :: lbc_no2_sciamachy, lbc_no2_omi, lbc_no2_gome2
INTEGER(KIND=JPIM) :: nbg_no2_sciamachy, nbg_no2_omi, nbg_no2_gome2
LOGICAL            :: lbc_hcho_sciamachy, lbc_hcho_omi
INTEGER(KIND=JPIM) :: nbg_hcho_sciamachy, nbg_hcho_omi
LOGICAL            :: lbc_so2_sciamachy, lbc_so2_omi
INTEGER(KIND=JPIM) :: nbg_so2_sciamachy, nbg_so2_omi
!BEN Add predictor for AOD bias
LOGICAL            :: lbc_aod_modis
INTEGER(KIND=JPIM) :: nbg_aod_modis
LOGICAL            :: lconst             ! Keep all VarBC parameters fixed
LOGICAL            :: lmode              ! Correct pdf mode rather than mean

NAMELIST /NAMVARBC_TO3/ yconfig, &
                      & lbc_to3, &
                      & lbc_toms, lbc_sbuv, lbc_gome, lbc_sciamachy, lbc_gomos,&
                      & lbc_mipas, lbc_seviri, lbc_omi, lbc_mls, lbc_gome2, &
                      & nbg_toms, nbg_sbuv, nbg_gome, nbg_sciamachy, nbg_gomos,&
                      & nbg_mipas, nbg_seviri, nbg_omi, nbg_mls, nbg_gome2, &
                      & lconst, lmode, &
                      & lbc_go3_toms, lbc_go3_sbuv, lbc_go3_gome, &
                      & lbc_go3_sciamachy, lbc_go3_gomos, lbc_go3_mipas, &
                      & lbc_go3_seviri, lbc_go3_omi, lbc_go3_mls, &
                      & lbc_go3_gome2, nbg_go3_toms, nbg_go3_sbuv, &
                      & nbg_go3_gome, nbg_go3_sciamachy, nbg_go3_gomos, &
                      & nbg_go3_mipas, nbg_go3_seviri, nbg_go3_omi, &
                      & nbg_go3_mls, nbg_go3_gome2, &
                      & lbc_co_mopitt, lbc_co_iasi, nbg_co_mopitt, nbg_co_iasi, &
                      & lbc_no2_sciamachy, lbc_no2_omi, lbc_no2_gome2, &
                      & nbg_no2_sciamachy, nbg_no2_omi,  nbg_no2_gome2, &
                      & lbc_hcho_sciamachy, lbc_hcho_omi, nbg_hcho_sciamachy, nbg_hcho_omi, &
                      & lbc_so2_sciamachy, lbc_so2_omi, nbg_so2_sciamachy, nbg_so2_omi, &
                      & lbc_aod_modis, nbg_aod_modis
!-----------------------------------------------------------------------

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

#include "abor1.intfb.h"
#include "posnam.intfb.h"

! ========
CONTAINS
! ========

SUBROUTINE config

!-----------------------------------------------------------------------
!   config - Configure ozone VarBC

!   Interface.
!   ----------
!   CALL config

!   Author.
!   -------
!   Dick Dee (ECMWF)

!   Modifications.
!   --------------
!   Original    2008/03/01
!-----------------------------------------------------------------------

INTEGER(KIND=JPIM) :: is
REAL(KIND=JPRB)    :: zhook_handle

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (config)'

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

WRITE(NULOUT,'(/,a)') myname//': Configuring ozone VarBC'

DO is = 1, SIZE(yconfig,1)
  yconfig(is)%nparam       = 2  
  yconfig(is)%npredcs(:)   = NPREDCS_TO3  ! available predictors for ozone 
  yconfig(is)%zparams(:)   = 0.0_JPRB     ! a priori parameter estimates
  yconfig(is)%llconst(:)   = .false.      ! keep this parameter fixed
  yconfig(is)%ncstart      = 2            ! cold start option
  yconfig(is)%nbgstdv      = 0            ! background error std dev parameter
  yconfig(is)%llmode       = .false.      ! correct mode of pdf, rather than mean
ENDDO

! List of sensors for operational ozone
!--------------------------------------
yconfig(1)%name    = 'TOMS'
yconfig(1)%nsensor = 431
yconfig(1)%nvarno  = 206
yconfig(1)%nlayers = 1
yconfig(1)%nprod_type = 1
yconfig(1)%press(1) = 0.0_JPRB
yconfig(1)%dfgdep(1) = 1E-2_JPRB

yconfig(2)%name    = 'SBUV'
yconfig(2)%nsensor = 624
yconfig(2)%nvarno  = 206
yconfig(2)%nlayers = 6
yconfig(2)%nprod_type = 1
yconfig(2)%press(1:6) = (/1600.0_JPRB, 640.0_JPRB, 410.0_JPRB, 160.0_JPRB, 100.0_JPRB, 10.0_JPRB/)
yconfig(2)%dfgdep(1:6) = (/1E-2_JPRB, 5E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 1E-4_JPRB, 1E-4_JPRB/)

yconfig(3)%name    = 'GOME'
yconfig(3)%nsensor = 170
yconfig(3)%nvarno  = 206
yconfig(3)%nlayers = 15
yconfig(3)%nprod_type = 31
yconfig(3)%press(1:15) = (/42170.0_JPRB, 17783.0_JPRB, 10000.0_JPRB, 5623.0_JPRB, &
  &  3162.0_JPRB, 1778.0_JPRB, 1000.0_JPRB, 562.0_JPRB, 316.0_JPRB, 178.0_JPRB, &
  &  100.0_JPRB, 56.0_JPRB, 32.0_JPRB, 18.0_JPRB, 10.0_JPRB/)
yconfig(3)%dfgdep(1:15) = (/1E-2_JPRB, 5E-3_JPRB, 2E-3_JPRB, 2E-3_JPRB, &
  &  2E-3_JPRB, 1E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 5E-4_JPRB, 2E-4_JPRB, &
  &  2E-4_JPRB, 1E-4_JPRB, 5E-5_JPRB, 5E-5_JPRB, 2E-5_JPRB/)

yconfig(4)%name    = 'SCIAMACHY'
yconfig(4)%nsensor = 175
yconfig(4)%nvarno  = 206
yconfig(4)%nlayers = 1
yconfig(4)%nprod_type = 11
yconfig(4)%press(1) = 0.0_JPRB
yconfig(4)%dfgdep(1) = 1E-2_JPRB

yconfig(5)%name    = 'GOMOS'
yconfig(5)%nsensor = 172
yconfig(5)%nvarno  = 206
yconfig(5)%nlayers = 16
yconfig(5)%nprod_type = 4
yconfig(5)%press(1:16) = (/20.0_JPRB, 40.0_JPRB, 70.0_JPRB, 110.0_JPRB, &
  &  170.0_JPRB, 260.0_JPRB, 390.0_JPRB, 610.0_JPRB, 1000.0_JPRB, 2000.0_JPRB,   &
  &  4000.0_JPRB, 6000.0_JPRB, 8000.0_JPRB, 10000.0_JPRB, 12000.0_JPRB, 15000.0_JPRB/)
yconfig(5)%dfgdep(1:16) = (/2E-5_JPRB, 2E-5_JPRB, 5E-5_JPRB, 5E-5_JPRB, 1E-4_JPRB,  &
  &  2E-4_JPRB, 2E-4_JPRB, 5E-4_JPRB, 5E-4_JPRB, 1E-3_JPRB, 1E-3_JPRB,2E-3_JPRB, &    
  &  2E-3_JPRB, 2E-3_JPRB, 5E-3_JPRB, 1E-2_JPRB/)

yconfig(6)%name    = 'MIPAS'
yconfig(6)%nsensor = 161
yconfig(6)%nvarno  = 206
yconfig(6)%nlayers = 16
yconfig(6)%nprod_type = 2
yconfig(5)%press(1:16) = (/20.0_JPRB, 40.0_JPRB, 70.0_JPRB, 110.0_JPRB, &
  &  170.0_JPRB, 260.0_JPRB, 390.0_JPRB, 610.0_JPRB, 1000.0_JPRB, 2000.0_JPRB,   &
  &  4000.0_JPRB, 6000.0_JPRB, 8000.0_JPRB, 10000.0_JPRB, 12000.0_JPRB, 15000.0_JPRB/)
yconfig(5)%dfgdep(1:16) = (/2E-5_JPRB, 2E-5_JPRB, 5E-5_JPRB, 5E-5_JPRB, 1E-4_JPRB,  &
  &  2E-4_JPRB, 2E-4_JPRB, 5E-4_JPRB, 5E-4_JPRB, 1E-3_JPRB, 1E-3_JPRB,2E-3_JPRB, &    
  &  2E-3_JPRB, 2E-3_JPRB, 5E-3_JPRB, 1E-2_JPRB/)

yconfig(7)%name    = 'SEVIRI'
yconfig(7)%nsensor = 207
yconfig(7)%nvarno  = 206
yconfig(7)%nlayers = 1
yconfig(7)%nprod_type = 1
yconfig(7)%press(1) = 0.0_JPRB
yconfig(7)%dfgdep(1) = 1E-2_JPRB

yconfig(8)%name    = 'OMI'
yconfig(8)%nsensor = 394
yconfig(8)%nvarno  = 206
yconfig(8)%nlayers = 1
yconfig(8)%nprod_type = 1
yconfig(8)%press(1) = 0.0_JPRB
yconfig(8)%dfgdep(1) = 1E-2_JPRB

yconfig(9)%name    = 'MLS'
yconfig(9)%nsensor = 387
yconfig(9)%nvarno  = 206
yconfig(9)%nlayers = 17
yconfig(9)%nprod_type = 2
yconfig(9)%press(1:17) = (/22.0_JPRB, 68.1_JPRB, 100.0_JPRB, 147.0_JPRB, 215.0_JPRB, &
   &  316.0_JPRB, 464.0_JPRB, 681.0_JPRB, 1000.0_JPRB, 1468.0_JPRB, 2154.0_JPRB, &
   &  3162.0_JPRB, 4642.0_JPRB, 6813.0_JPRB, 10000.0_JPRB, 14678.0_JPRB, 21544.0_JPRB/)
yconfig(9)%dfgdep(1:17) = (/2E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, &
  &  5E-4_JPRB, 5E-4_JPRB, 5E-4_JPRB, 5E-4_JPRB, 5E-4_JPRB,1E-3_JPRB, 1E-3_JPRB, 1E-3_JPRB, &
  &  2E-3_JPRB, 2E-3_JPRB, 2E-3_JPRB, 1E-2_JPRB/)

yconfig(10)%name    = 'GOME2'
yconfig(10)%nsensor = 220
yconfig(10)%nvarno  = 206
yconfig(10)%nlayers = 1
yconfig(10)%nprod_type = 1
yconfig(10)%press(1) = 0.0_JPRB
yconfig(10)%dfgdep(1) = 1E-2_JPRB

yconfig(11)%name    = 'GOME'
yconfig(11)%nsensor = 170
yconfig(11)%nvarno  = 206
yconfig(11)%nlayers = 1
yconfig(11)%nprod_type = 1
yconfig(11)%press(1) = 0.0_JPRB
yconfig(11)%dfgdep(1) = 1E-2_JPRB
! End List of sensors for operational ozone

! List of sensors for MACC ozone
yconfig(12)%name    = 'TOMS'
yconfig(12)%nsensor = 431
yconfig(12)%nvarno  = 185
yconfig(12)%nlayers = 1
yconfig(12)%nprod_type = 1
yconfig(12)%press(1) = 0.0_JPRB
yconfig(12)%dfgdep(1) = 1E-2_JPRB

yconfig(13)%name    = 'SBUV'
yconfig(13)%nsensor = 624
yconfig(13)%nvarno  = 185
yconfig(13)%nlayers = 6
yconfig(13)%nprod_type = 1
yconfig(13)%press(1:6) = (/1583.0_JPRB, 792.0_JPRB, 396.0_JPRB, 198.0_JPRB, 99.0_JPRB, 12.0_JPRB/)
yconfig(13)%dfgdep(1:6) = (/1E-2_JPRB, 5E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 1E-4_JPRB, 1E-4_JPRB/)

yconfig(14)%name    = 'GOME'
yconfig(14)%nsensor = 170
yconfig(14)%nvarno  = 185
yconfig(14)%nlayers = 15
yconfig(14)%nprod_type = 31
yconfig(14)%press(1:15) = (/42170.0_JPRB, 17783.0_JPRB, 10000.0_JPRB, 5623.0_JPRB, &
  &  3162.0_JPRB, 1778.0_JPRB, 1000.0_JPRB, 562.0_JPRB, 316.0_JPRB, 178.0_JPRB, &
  &  100.0_JPRB, 56.0_JPRB, 32.0_JPRB, 18.0_JPRB, 10.0_JPRB/)
yconfig(14)%dfgdep(1:15) = (/1E-2_JPRB, 5E-3_JPRB, 2E-3_JPRB, 2E-3_JPRB, &
  &  2E-3_JPRB, 1E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 5E-4_JPRB, 2E-4_JPRB, &
  &  2E-4_JPRB, 1E-4_JPRB, 5E-5_JPRB, 5E-5_JPRB, 2E-5_JPRB/)

yconfig(15)%name    = 'SCIAMACHY'
yconfig(15)%nsensor = 175
yconfig(15)%nvarno  = 185
yconfig(15)%nlayers = 1
yconfig(15)%nprod_type = 11
yconfig(15)%press(1) = 0.0_JPRB
yconfig(15)%dfgdep(1) = 1E-2_JPRB

yconfig(16)%name    = 'GOMOS'
yconfig(16)%nsensor = 172
yconfig(16)%nvarno  = 185
yconfig(16)%nlayers = 15
yconfig(16)%nprod_type = 4
yconfig(16)%press(1:15) = (/42170.0_JPRB, 17783.0_JPRB, 10000.0_JPRB, 5623.0_JPRB, &
  &  3162.0_JPRB, 1778.0_JPRB, 1000.0_JPRB, 562.0_JPRB, 316.0_JPRB, 178.0_JPRB, &
  &  100.0_JPRB, 56.0_JPRB, 32.0_JPRB, 18.0_JPRB, 10.0_JPRB/)
yconfig(16)%dfgdep(1:15) = (/1E-2_JPRB, 5E-3_JPRB, 2E-3_JPRB, 2E-3_JPRB, &
  &  2E-3_JPRB, 1E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 5E-4_JPRB, 2E-4_JPRB, &
  &  2E-4_JPRB, 1E-4_JPRB, 5E-5_JPRB, 5E-5_JPRB, 2E-5_JPRB/)

yconfig(17)%name    = 'MIPAS'
yconfig(17)%nsensor = 161
yconfig(17)%nvarno  = 185
yconfig(17)%nlayers = 15
yconfig(17)%nprod_type = 2
yconfig(17)%press(1:15) = (/42170.0_JPRB, 17783.0_JPRB, 10000.0_JPRB, 5623.0_JPRB, &
  &  3162.0_JPRB, 1778.0_JPRB, 1000.0_JPRB, 562.0_JPRB, 316.0_JPRB, 178.0_JPRB, &
  &  100.0_JPRB, 56.0_JPRB, 32.0_JPRB, 18.0_JPRB, 10.0_JPRB/)
yconfig(17)%dfgdep(1:15) = (/1E-2_JPRB, 5E-3_JPRB, 2E-3_JPRB, 2E-3_JPRB, &
  &  2E-3_JPRB, 1E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 5E-4_JPRB, 2E-4_JPRB, &
  &  2E-4_JPRB, 1E-4_JPRB, 5E-5_JPRB, 5E-5_JPRB, 2E-5_JPRB/)

yconfig(18)%name    = 'SEVIRI'
yconfig(18)%nsensor = 207
yconfig(18)%nvarno  = 185
yconfig(18)%nlayers = 1
yconfig(18)%nprod_type = 1
yconfig(18)%press(1) = 0.0_JPRB
yconfig(18)%dfgdep(1) = 1E-2_JPRB

yconfig(19)%name    = 'OMI'
yconfig(19)%nsensor = 394
yconfig(19)%nvarno  = 185
yconfig(19)%nlayers = 1
yconfig(19)%nprod_type = 1
yconfig(19)%press(1) = 0.0_JPRB
yconfig(19)%dfgdep(1) = 1E-2_JPRB

yconfig(20)%name    = 'MLS'
yconfig(20)%nsensor = 387
yconfig(20)%nvarno  = 185
yconfig(20)%nlayers = 21
yconfig(20)%nprod_type = 2
!yconfig(20)%press(1:21) = (/21544.0_JPRB, 14678.0_JPRB, 10000.0_JPRB, 6813.0_JPRB,&
!   & 4642.0_JPRB, 3162.0_JPRB, 2154.0_JPRB, 1468.0_JPRB, 1000.0_JPRB, 681.0_JPRB,&
!   & 464.0_JPRB, 316.0_JPRB, 215.0_JPRB, 147.0_JPRB, 100.0_JPRB, 68.1_JPRB,&
!   & 46.4_JPRB, 31.6_JPRB, 21.5_JPRB, 14.7_JPRB, 10.0_JPRB/)
!yconfig(20)%dfgdep(1:21) = (/1E-2_JPRB, 2E-3_JPRB, 2E-3_JPRB, 2E-3_JPRB, &
!  &  1E-3_JPRB, 1E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 5E-4_JPRB, 5E-4_JPRB, &
!  &  5E-4_JPRB, 5E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, &
!  &  2E-4_JPRB, 1E-4_JPRB, 5E-5_JPRB, 5E-5_JPRB, 2E-5_JPRB/)
yconfig(20)%nlayers = 17
yconfig(20)%press(1:17) = (/21544.0_JPRB, 14678.0_JPRB, 10000.0_JPRB, 6813.0_JPRB,&
   & 4642.0_JPRB, 3162.0_JPRB, 2154.0_JPRB, 1468.0_JPRB, 1000.0_JPRB, 681.0_JPRB,&
   & 464.0_JPRB, 316.0_JPRB, 215.0_JPRB, 147.0_JPRB, 100.0_JPRB, 68.1_JPRB,&
   & 21.5_JPRB/)
yconfig(20)%dfgdep(1:17) = (/1E-2_JPRB, 2E-3_JPRB, 2E-3_JPRB, 2E-3_JPRB, &
  &  1E-3_JPRB, 1E-3_JPRB, 1E-3_JPRB, 5E-4_JPRB, 5E-4_JPRB, 5E-4_JPRB, &
  &  5E-4_JPRB, 5E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, 2E-4_JPRB, &
  &  2E-4_JPRB/)

yconfig(21)%name    = 'GOME2'
yconfig(21)%nsensor = 220
yconfig(21)%nvarno  = 185
yconfig(21)%nlayers = 1
yconfig(21)%nprod_type = 1
yconfig(21)%press(1) = 0.0_JPRB
yconfig(21)%dfgdep(1) = 1E-2_JPRB

yconfig(22)%name    = 'GOME'
yconfig(22)%nsensor = 170
yconfig(22)%nvarno  = 185
yconfig(22)%nlayers = 1
yconfig(22)%nprod_type = 1
yconfig(22)%press(1) = 0.0_JPRB
yconfig(22)%dfgdep(1) = 1E-2_JPRB
! End List of sensors for MACC ozone

! List of sensors for MACC CO
yconfig(23)%name    = 'MOPITT'
yconfig(23)%nsensor = 090
yconfig(23)%nvarno  = 183
yconfig(23)%nlayers = 1
yconfig(23)%nprod_type = 1
yconfig(23)%press(1) = 0.0_JPRB
yconfig(23)%dfgdep(1) = 1E-2_JPRB
yconfig(23)%nparam    = 1  
yconfig(23)%npredcs(:)= 0  ! p0 as predictor for CO

yconfig(24)%name    = 'IASI'
yconfig(24)%nsensor = 221
yconfig(24)%nvarno  = 183
yconfig(24)%nlayers = 1
yconfig(24)%nprod_type = 1
yconfig(24)%press(1) = 0.0_JPRB
yconfig(24)%dfgdep(1) = 1E-2_JPRB
yconfig(24)%nparam    = 1  
yconfig(24)%npredcs(:)= 0  ! p0 as predictor for CO
! END List of sensors for MACC CO

! List of sensors for MACC NO2
yconfig(25)%name    = 'SCIAMACHY'
yconfig(25)%nsensor = 175
yconfig(25)%nvarno  = 181
yconfig(25)%nlayers = 1
yconfig(25)%nprod_type = 1
yconfig(25)%press(1) = 0.0_JPRB
yconfig(25)%dfgdep(1) = 1E-2_JPRB

yconfig(26)%name    = 'OMI'
yconfig(26)%nsensor = 394
yconfig(26)%nvarno  = 181
yconfig(26)%nlayers = 1
yconfig(26)%nprod_type = 1
yconfig(26)%press(1) = 0.0_JPRB
yconfig(26)%dfgdep(1) = 1E-2_JPRB

yconfig(27)%name    = 'GOME2'
yconfig(27)%nsensor = 220
yconfig(27)%nvarno  = 181
yconfig(27)%nlayers = 1
yconfig(27)%nprod_type = 1
yconfig(27)%press(1) = 0.0_JPRB
yconfig(27)%dfgdep(1) = 1E-2_JPRB
! END List of sensors for MACC NO2

! List of sensors for MACC HCHO
yconfig(28)%name    = 'SCIAMACHY'
yconfig(28)%nsensor = 175
yconfig(28)%nvarno  = 184
yconfig(28)%nlayers = 1
yconfig(28)%nprod_type = 1
yconfig(28)%press(1) = 0.0_JPRB
yconfig(28)%dfgdep(1) = 1E-2_JPRB

yconfig(29)%name    = 'OMI'
yconfig(29)%nsensor = 394
yconfig(29)%nvarno  = 184
yconfig(29)%nlayers = 1
yconfig(29)%nprod_type = 1
yconfig(29)%press(1) = 0.0_JPRB
yconfig(29)%dfgdep(1) = 1E-2_JPRB
! END List of sensors for MACC HCHO

! List of sensors for MACC SO2
yconfig(30)%name    = 'SCIAMACHY'
yconfig(30)%nsensor = 175
yconfig(30)%nvarno  = 182
yconfig(30)%nlayers = 1
yconfig(30)%nprod_type = 1
yconfig(30)%press(1) = 0.0_JPRB
yconfig(30)%dfgdep(1) = 1E-2_JPRB

yconfig(31)%name    = 'OMI'
yconfig(31)%nsensor = 394
yconfig(31)%nvarno  = 182
yconfig(31)%nlayers = 1
yconfig(31)%nprod_type = 1
yconfig(31)%press(1) = 0.0_JPRB
yconfig(31)%dfgdep(1) = 1E-2_JPRB
! END List of sensors for MACC SO2

! List of sensors for MACC AEROSOL (AOD)
yconfig(32)%name    = 'MODIS'
yconfig(32)%nsensor = 389
yconfig(32)%nvarno  = 174
yconfig(32)%nlayers = 1
yconfig(32)%nprod_type = 1
yconfig(32)%press(1) = 0.0_JPRB
yconfig(32)%dfgdep(1) = 10._JPRB
yconfig(32)%nparam    = 1
yconfig(32)%npredcs(:)= 0  ! p0 as predictor for CO - CHECK WITH ANTJE ABOUT THIS!!!!!!!!!!!!!
yconfig(32)%ncstart   = 0            ! cold start option - starts from zero
! END List of sensors for MACC AEROSOL

! Switches by sensor:
! ------------------
! operational ozone
lbc_toms      = .true. 
lbc_sbuv      = .false.        ! Use SBUV as anchor to VarBC
lbc_gome      = .true.
lbc_sciamachy = .true. 
lbc_gomos     = .true.
lbc_mipas     = .true. 
lbc_seviri    = .true. 
lbc_omi       = .true. 
lbc_mls       = .true. 
lbc_gome2     = .true.
! MACC ozone
lbc_go3_toms      = .true. 
lbc_go3_sbuv      = .false.   ! Use SBUV as anchor to VarBC for GO3
lbc_go3_gome      = .true.
lbc_go3_sciamachy = .true. 
lbc_go3_gomos     = .true.
lbc_go3_mipas     = .true. 
lbc_go3_seviri    = .true. 
lbc_go3_omi       = .true. 
lbc_go3_mls       = .true. 
lbc_go3_gome2     = .true.
! MACC CO
lbc_co_mopitt     = .false.   ! No varbc for CO
lbc_co_iasi       = .false.   ! No varbc for CO
!MACC NO2
lbc_no2_sciamachy = .false.   
lbc_no2_omi       = .false.   
lbc_no2_gome2     = .false.   ! GOME-2 as anchor
!MACC HCHO
lbc_hcho_sciamachy = .false.  ! No varbc for HCHO
lbc_hcho_omi       = .false.  ! No varbc for HCHO
!MACC SO2
lbc_so2_sciamachy = .false.   ! No varbc for SO2
lbc_so2_omi       = .false.   ! No varbc for SO2
! MACC AEROSOL
lbc_aod_modis     = .false.   ! No varbc for AOD


! Background error parameters by sensor:
! -------------------------------------
! operational ozone
nbg_toms      = 5000 
nbg_sbuv      = 5000 
nbg_gome      = 5000
nbg_sciamachy = 5000 
nbg_gomos     = 5000
nbg_mipas     = 5000 
nbg_seviri    = 5000 
nbg_omi       = 5000 
nbg_mls       = 5000 
nbg_gome2     = 5000
! MACC ozone
nbg_go3_toms      = 5000 
nbg_go3_sbuv      = 5000 
nbg_go3_gome      = 5000
nbg_go3_sciamachy = 5000 
nbg_go3_gomos     = 5000
nbg_go3_mipas     = 5000 
nbg_go3_seviri    = 5000 
nbg_go3_omi       = 5000 
nbg_go3_mls       = 5000 
nbg_go3_gome2     = 5000
! MACC CO
nbg_co_mopitt     = 5000 
nbg_co_iasi       = 5000 
! MACC NO2
nbg_no2_sciamachy = 5000
nbg_no2_omi       = 5000 
nbg_no2_gome2     = 5000 
! MACC HCHO
nbg_hcho_sciamachy = 5000
nbg_hcho_omi       = 5000 
! MACC SO2
nbg_so2_sciamachy = 5000
nbg_so2_omi       = 5000 
! MACC AEROSOL
nbg_aod_modis     = 100

! Panic button:
! ------------
lbc_to3 = .true. ! If this is false then no ozone bias correction

! All parameters constant:
! -----------------------
lconst = .false.

! Correct mode rather than mean:
! -----------------------------
lmode = .false.

WRITE(NULOUT,'(a)') myname//': Reading namelist NAMVARBC_TO3, first iteration'
CALL posnam(NULNAM,'NAMVARBC_TO3')
READ(NULNAM,NAMVARBC_TO3)
      
! Operational ozone
IF (.NOT. (lbc_to3 .AND. lbc_toms     )) yconfig( 1)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_sbuv     )) yconfig( 2)%nparam = 0     
IF (.NOT. (lbc_to3 .AND. lbc_gome     )) yconfig( 3)%nparam = 0     
IF (.NOT. (lbc_to3 .AND. lbc_sciamachy)) yconfig( 4)%nparam = 0
IF (.NOT. (lbc_to3 .AND. lbc_gomos    )) yconfig( 5)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_mipas    )) yconfig( 6)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_omi      )) yconfig( 7)%nparam = 0      
IF (.NOT. (lbc_to3 .AND. lbc_seviri   )) yconfig( 8)%nparam = 0   
IF (.NOT. (lbc_to3 .AND. lbc_mls      )) yconfig( 9)%nparam = 0      
IF (.NOT. (lbc_to3 .AND. lbc_gome2    )) yconfig(10)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_gome     )) yconfig(11)%nparam = 0    
! MACC ozone
IF (.NOT. (lbc_to3 .AND. lbc_go3_toms     )) yconfig(12)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_go3_sbuv     )) yconfig(13)%nparam = 0     
IF (.NOT. (lbc_to3 .AND. lbc_go3_gome     )) yconfig(14)%nparam = 0     
IF (.NOT. (lbc_to3 .AND. lbc_go3_sciamachy)) yconfig(15)%nparam = 0
IF (.NOT. (lbc_to3 .AND. lbc_go3_gomos    )) yconfig(16)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_go3_mipas    )) yconfig(17)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_go3_omi      )) yconfig(18)%nparam = 0      
IF (.NOT. (lbc_to3 .AND. lbc_go3_seviri   )) yconfig(19)%nparam = 0   
IF (.NOT. (lbc_to3 .AND. lbc_go3_mls      )) yconfig(20)%nparam = 0      
IF (.NOT. (lbc_to3 .AND. lbc_go3_gome2    )) yconfig(21)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_go3_gome     )) yconfig(22)%nparam = 0    
! MACC CO
IF (.NOT. (lbc_to3 .AND. lbc_co_mopitt    )) yconfig(23)%nparam = 0    
IF (.NOT. (lbc_to3 .AND. lbc_co_iasi      )) yconfig(24)%nparam = 0     
!MACC NO2
IF (.NOT. (lbc_to3 .AND. lbc_no2_sciamachy)) yconfig(25)%nparam = 0
IF (.NOT. (lbc_to3 .AND. lbc_no2_omi      )) yconfig(26)%nparam = 0
IF (.NOT. (lbc_to3 .AND. lbc_no2_gome2    )) yconfig(27)%nparam = 0
!MACC HCHO
IF (.NOT. (lbc_to3 .AND. lbc_hcho_sciamachy)) yconfig(28)%nparam = 0
IF (.NOT. (lbc_to3 .AND. lbc_hcho_omi      )) yconfig(29)%nparam = 0
!MACC SO2
IF (.NOT. (lbc_to3 .AND. lbc_so2_sciamachy)) yconfig(30)%nparam = 0
IF (.NOT. (lbc_to3 .AND. lbc_so2_omi      )) yconfig(31)%nparam = 0
! MACC AEROSOL
IF (.NOT. (lbc_to3 .AND. lbc_aod_modis    )) yconfig(32)%nparam = 0

! Operational ozone
yconfig( 1)%nbgstdv = nbg_toms     
yconfig( 2)%nbgstdv = nbg_sbuv     
yconfig( 3)%nbgstdv = nbg_gome     
yconfig( 4)%nbgstdv = nbg_sciamachy
yconfig( 5)%nbgstdv = nbg_gomos    
yconfig( 6)%nbgstdv = nbg_mipas    
yconfig( 7)%nbgstdv = nbg_seviri   
yconfig( 8)%nbgstdv = nbg_omi      
yconfig( 9)%nbgstdv = nbg_mls      
yconfig(10)%nbgstdv = nbg_gome2    
yconfig(11)%nbgstdv = nbg_gome    
! MACC ozone
yconfig(12)%nbgstdv = nbg_go3_toms     
yconfig(13)%nbgstdv = nbg_go3_sbuv     
yconfig(14)%nbgstdv = nbg_go3_gome     
yconfig(15)%nbgstdv = nbg_go3_sciamachy
yconfig(16)%nbgstdv = nbg_go3_gomos    
yconfig(17)%nbgstdv = nbg_go3_mipas    
yconfig(18)%nbgstdv = nbg_go3_seviri   
yconfig(19)%nbgstdv = nbg_go3_omi      
yconfig(20)%nbgstdv = nbg_go3_mls      
yconfig(21)%nbgstdv = nbg_go3_gome2    
yconfig(22)%nbgstdv = nbg_go3_gome    
! MACC CO
yconfig(23)%nbgstdv = nbg_co_mopitt
yconfig(24)%nbgstdv = nbg_co_iasi
!MACC NO2
yconfig(25)%nbgstdv = nbg_no2_sciamachy
yconfig(26)%nbgstdv = nbg_no2_omi
yconfig(27)%nbgstdv = nbg_no2_gome2
!MACC HCHO
yconfig(28)%nbgstdv = nbg_hcho_sciamachy
yconfig(29)%nbgstdv = nbg_hcho_omi
!MACC SO2
yconfig(30)%nbgstdv = nbg_so2_sciamachy
yconfig(31)%nbgstdv = nbg_so2_omi
! MACC AEROSOL
yconfig(32)%nbgstdv = nbg_aod_modis

DO is = 1, SIZE(yconfig,1)
  yconfig(is)%llconst(:) = lconst
  yconfig(is)%llmode     = lmode
ENDDO

! Override settings for individual layers/predictors:
! ---------------------------------------------------
WRITE(NULOUT,'(a)') myname//': Reading namelist NAMVARBC_TO3, second iteration'
CALL posnam(NULNAM,'NAMVARBC_TO3')
READ(NULNAM,NAMVARBC_TO3)

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE config
!-----------------------------------------------------------------------------

SUBROUTINE encode_groupkey (cdkey, kbufrid, ksensor, klayer, kvarno, kprod_type)

!-----------------------------------------------------------------------
! Encodes group description

! cdkey:  encoded string defining a group of ozone data
!-----------------------------------------------------------------------
CHARACTER(LEN=*)  , INTENT(OUT) :: cdkey
INTEGER(KIND=JPIM), INTENT(IN)  :: kbufrid, ksensor, klayer, kvarno, kprod_type

REAL(KIND=JPRB) :: zhook_handle

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (encode_groupkey)'

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

WRITE(cdkey,'(5(i0,x))') kbufrid, ksensor, klayer, kvarno, kprod_type

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE encode_groupkey
!-----------------------------------------------------------------------

SUBROUTINE decode_groupkey (cdkey, kbufrid, ksensor, klayer, kvarno, kprod_type, kerr)

!-----------------------------------------------------------------------
! Decodes group description

! cdkey:  encoded string defining a group of ozone data
!-----------------------------------------------------------------------
CHARACTER(LEN=*)  , INTENT(IN)  :: cdkey
INTEGER(KIND=JPIM), INTENT(OUT) :: kbufrid, ksensor, klayer, kvarno, kprod_type, kerr

REAL(KIND=JPRB) :: zhook_handle

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (decode_groupkey)'

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

kerr=0
kbufrid=-999
ksensor=-999
klayer=-999
kvarno=-999
kprod_type=-999

READ(cdkey,*,ERR=100,END=100,IOSTAT=kerr) kbufrid, ksensor, klayer, kvarno,  kprod_type
IF(kbufrid<0 .OR. ksensor<0 .OR. kvarno<0 .OR. klayer<0 .OR. kprod_type<0) kerr=-999

100 continue

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE decode_groupkey
!-----------------------------------------------------------------------

SUBROUTINE groupdescr (cdkey, cdescr)

!-----------------------------------------------------------------------
! Returns group description

! cdkey:      encoded string defining a group of ozone data
! cdescr:     string suitable for printing

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

CHARACTER(LEN=*), INTENT(IN)  :: cdkey
CHARACTER(LEN=*), INTENT(OUT) :: cdescr

CHARACTER(LEN=80)  :: cldesc
INTEGER(KIND=JPIM) :: ibufrid, isensor, ilayer, ivarno, iprod_type, ierr, j, ilen
REAL(KIND=JPRB)    :: zhook_handle

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (groupdescr)'

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

CALL decode_groupkey (cdkey, ibufrid, isensor, ilayer, ivarno, iprod_type, ierr)

! Fallback string

WRITE(cldesc,'(a,4x,5(a,i0))') 'ozone', &
          & ' satid=', ibufrid, ' sensor=', isensor, ' layer number=', ilayer, &
          & ' varno=', ivarno,' prod type=', iprod_type

!! Try to get string from SATREO3GRP_TABLE


DO j = 1, NSATREO3GRP
  IF (SATREO3GRP_TABLE(j)%bufrid   /=ibufrid   ) CYCLE  
  IF (SATREO3GRP_TABLE(j)%sensor   /=isensor   ) CYCLE 
  IF (SATREO3GRP_TABLE(j)%varno    /=ivarno    ) CYCLE 
  IF (SATREO3GRP_TABLE(j)%prodtype /=iprod_type) CYCLE 

!  WRITE(cldesc,'(a,4x,a,4x,2(a,i0))') 'ozone', &
WRITE(cldesc,'(a,4x,5(a,i0))') 'ozone', &
          & ' satid=', ibufrid, ' sensor=', isensor, ' layer number=', ilayer, &
          & ' varno=', ivarno,' prod type=', iprod_type
ENDDO

ilen = LEN(TRIM(cldesc))
IF (LEN(cdescr)<ilen) CALL ABOR1(myname//': Increase string length')

cdescr(1:ilen) = cldesc

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE groupdescr
!-----------------------------------------------------------------------

SUBROUTINE find_groups (cdkeys, kng)

!-----------------------------------------------------------------------
!   find_groups - Find data groups present in ODB requiring VarBC

!   Interface.
!   ----------
!   CALL find_groups (cdkeys, kng)

!       cdkeys(1:kng)    group descriptions

!   Author.
!   -------
!   Dick Dee (ECMWF)

!   Modifications.
!   --------------
!   Original    2008/03/01
!-----------------------------------------------------------------------

CHARACTER(LEN=*)  , INTENT(OUT) :: cdkeys(:)
INTEGER(KIND=JPIM), INTENT(OUT) :: kng

INTEGER(KIND=JPIM) :: ibufrid, isensor, ivarno, ilayer, iprod_type
INTEGER(KIND=JPIM) :: is, js, ins
REAL(KIND=JPRB)    :: zhook_handle

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (find_groups)'

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

WRITE(NULOUT,'(a)') myname//': Looking for ozone data groups..'

! Find all satellite/sensor/varno combinations for this codetype 
! --------------------------------------------------------
CALL find_sensors (ins)

! Return group descriptions for VarBC
! -----------------------------------
kng = 0
IF (lbc_to3 .AND. ins>0) THEN

  DO is = 1, ins  ! Look at each sensor

    ibufrid = YSENSORS(is)%nbufrid
    isensor = YSENSORS(is)%nsensor
    ivarno  = YSENSORS(is)%nvarno
    iprod_type = YSENSORS(is)%nprod_type
    DO js = 1, size(yconfig)     
      IF (yconfig(js)%nsensor==isensor .AND. yconfig(js)%nvarno==ivarno &
       & .AND. yconfig(js)%nprod_type==iprod_type .AND. yconfig(js)%nparam>0) THEN 
        DO ilayer = 1, yconfig(js)%nlayers  ! Bias correction for each layer 
          kng = kng + 1
          IF (kng>size(cdkeys)) CALL ABOR1(myname//': Insufficient allocation.')
          CALL encode_groupkey (cdkeys(kng), ibufrid, isensor, ilayer, ivarno, iprod_type)
        ENDDO
      ENDIF
    ENDDO

  ENDDO

  WRITE(NULOUT,'(a,i3,a)') myname//': ', kng, ' ozone data groups for VarBC'

ENDIF

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE find_groups
!-----------------------------------------------------------------------------

SUBROUTINE get_min ( cdkey, knparam, kbgstdv, pdfgdep )

!-----------------------------------------------------------------------
!   get_min - Return parameters used in the minimisation for a particular 
!             group of ozone data

!   Author.
!   -------
!   Dick Dee (ECMWF)

!   Modifications.
!   --------------
!   Original    2008/03/01
!-----------------------------------------------------------------------

CHARACTER(LEN=*)  , INTENT(IN)  :: cdkey
INTEGER(KIND=JPIM), INTENT(IN)  :: knparam
INTEGER(KIND=JPIM), INTENT(OUT) :: kbgstdv
REAL(KIND=JPRB)   , INTENT(OUT) :: pdfgdep

INTEGER(KIND=JPIM) :: js, jl, ibufrid, isensor, ivarno, ilayer, iprod_type, ierr
REAL(KIND=JPRB)    :: zhook_handle
LOGICAL            :: llmatch

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (get_min)'

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

CALL decode_groupkey (cdkey, ibufrid, isensor, ilayer, ivarno, iprod_type, ierr)

llmatch = .false.    
DO js = 1, size(yconfig)
  IF (yconfig(js)%nsensor==isensor .AND. yconfig(js)%nvarno==ivarno &
    & .AND. yconfig(js)%nprod_type==iprod_type) THEN
    kbgstdv = yconfig(js)%nbgstdv
    DO jl = 1, yconfig(js)%nlayers 
      IF (jl==ilayer) THEN
        pdfgdep = yconfig(js)%dfgdep(jl)
        llmatch = .true.
      ENDIF
    ENDDO
    EXIT
  ENDIF
ENDDO

IF (.NOT. llmatch) CALL ABOR1(myname//': No match.')

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE get_min
!-----------------------------------------------------------------------------

SUBROUTINE find_sensors (kns)

INTEGER(KIND=JPIM), INTENT(OUT) :: kns

INTEGER(KIND=JPIM) :: ibufrid, is, isensor, ivarno, iprod_type, ipt
INTEGER(KIND=JPIM) :: iret, info(1), ic, j
REAL(KIND=JPRB)    :: zinfo(0)
REAL(KIND=JPRB)    :: zhook_handle

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (find_sensors)'


#include "openmp_obs.h"

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

WRITE(NULOUT,'(a)') &
 &   myname//': Checking ODB for available bufrid/sensor/varno combinations'

CALL getdb('GETSATID_REO3', 0, iret, info, 0, zinfo, 0, &
          & -1, -1, -1, -1, -1, -1)  
! ROBSU(:,MDB_SATID_AT_SAT   ) contains bufrid
! ROBSU(:,MDBSSIA            ) contains sensor
! ROBSU(:,MDBVNM             ) contains varno
! ROBSU(:,MDBRO3PT           ) contains product type

ic = 0
DO is = 1, size(yconfig) ! For each sensor, ..
  isensor = yconfig(is)%nsensor
  ivarno  = yconfig(is)%nvarno
  ipt     = yconfig(is)%nprod_type
  ibufrid = -1
  iprod_type = -1
  DO j = 1, NROWS_ROBSU ! .. find all distinct bufrid's
    IF (ROBSU(j,MDBSSIA            )/=isensor) CYCLE
    
!! The "IF ... CYCLE" below is redundant as GETSATID_REO3 extracts only data "WHERE codetype=$reo3" (i.e. 206)   
!    IF (ROBSU(j,MDB_CODETYPE_AT_HDR)/= NSTRO3) CYCLE
    IF (ROBSU(j,MDB_SATID_AT_SAT) == ibufrid .AND. ROBSU(j,MDBRO3PT) == iprod_type) CYCLE ! duplicate
    IF (ROBSU(j,MDBVNM)   /= ivarno ) CYCLE ! avoid variable numbers not wanted
    IF (ROBSU(j,MDBRO3PT) /= ipt ) CYCLE    ! avoid data type no longer available in ODB 
    ibufrid = ROBSU(j,MDB_SATID_AT_SAT)
    iprod_type = ROBSU(j,MDBRO3PT)   
    ic = ic + 1
    IF (ic>jpmxns) &
      & CALL ABOR1(myname//': Insufficient allocation - increase jpmxnsAT')
    YSENSORS(ic)%NBUFRID = ibufrid
    YSENSORS(ic)%NSENSOR = isensor
    YSENSORS(ic)%NVARNO  = ivarno
    YSENSORS(ic)%NPROD_TYPE = iprod_type
    WRITE(NULOUT,'(4(a,i0))') myname//': bufrid=', ibufrid, ' sensor=', isensor, &
      & ' varno=', ivarno, ' prod_type=', iprod_type
  ENDDO
ENDDO
kns = ic

CALL putdb('GETSATID_REO3', 0, iret, info, 0, zinfo, 0)

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE find_sensors
!-----------------------------------------------------------------------------

SUBROUTINE get_predictors (cdkey, knparam, &
                         & kpredcs, pparams, ldreset, kcstart, pdfgdep)

! Return list of predictors, a-priori parameter values, ..
 
CHARACTER(LEN=*)  , INTENT(IN)  :: cdkey
INTEGER(KIND=JPIM), INTENT(OUT) :: knparam, kcstart
LOGICAL           , INTENT(OUT) :: ldreset
INTEGER(KIND=JPIM), INTENT(OUT) :: kpredcs(jpmxnp)
REAL(KIND=JPRB)   , INTENT(OUT) :: pparams(jpmxnp)
REAL(KIND=JPRB)   , INTENT(OUT) :: pdfgdep

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (get_predictors)'

LOGICAL            :: llmatch
INTEGER(KIND=JPIM) :: ibufrid, isensor, ilayer, ivarno, iprod_type, ierr, js, jl
REAL(KIND=JPRB)    :: zhook_handle

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

CALL decode_groupkey (cdkey, ibufrid, isensor, ilayer, ivarno, iprod_type, ierr)

llmatch = .false.
IF (ierr==0) THEN
  DO js = 1, size(yconfig)
    IF (yconfig(js)%nsensor==isensor .AND. yconfig(js)%nvarno==ivarno &
      & .AND. yconfig(js)%nprod_type==iprod_type) THEN
      knparam           = yconfig(js)%nparam
      kpredcs(1:knparam) = yconfig(js)%npredcs(1:knparam)
      pparams(1:knparam) = yconfig(js)%zparams(1:knparam) 
      kcstart           = yconfig(js)%ncstart
      ldreset           = yconfig(js)%lreset
      DO jl = 1, yconfig(js)%nlayers 
        IF (jl==ilayer) THEN
          pdfgdep = yconfig(js)%dfgdep(jl)
          llmatch   = .true.
        ENDIF
      ENDDO
      EXIT   
    ENDIF
  ENDDO
ELSE
  knparam = 0
ENDIF

!IF (.NOT. llmatch) CALL ABOR1(myname//': No match.')

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE get_predictors
!-----------------------------------------------------------------------------

SUBROUTINE set_varbcix (cdkeys, kix, kng)

!-----------------------------------------------------------------------
!   set_varbcix - Set VarBC group indices in ODB

!   Author.
!   -------
!   Dick Dee (ECMWF)

!   Modifications.
!   --------------
!   Original    2008/03/01
!-----------------------------------------------------------------------

INTEGER(KIND=JPIM), INTENT(IN) :: kix(kng), kng
CHARACTER(LEN=*)  , INTENT(IN) :: cdkeys(kng)

INTEGER(KIND=JPIM) :: iret, ilen, jg, info(1), jobs, jlev
INTEGER(KIND=JPIM) :: ibufrid, isensor, ilayer, ivarno, iprod_type, ierr
REAL(KIND=JPRB)    :: zinfo(0), zhook_handle

CHARACTER(LEN=*), PARAMETER :: myname = modname//' (set_varbcix)'


#include "openmp_obs.h"

IF (LHOOK) CALL DR_HOOK(myname,0,zhook_handle)

WRITE (NULOUT,'(/,a)') myname//': Setting VarBC group indices (varbc_ix@body) in ODB'

CALL GETDB('VARBC_TO3',0,iret,info,0,zinfo,0, -1, -1, -1, -1, -1, -1)  

ilen = iret
DO jg = 1, kng

  CALL decode_groupkey (cdkeys(jg), ibufrid, isensor, ilayer, ivarno, iprod_type,ierr)

  DO jobs = 1, ilen

! BEN AOD specifications (no iprod_type and levels)
   IF( ivarno == 174) THEN

     IF (ROBHDR(jobs,MDB_SATID_AT_SAT) == ibufrid .AND. &
       & ROBHDR(jobs,MDBSSIA         ) == isensor .AND. &
       & ROBODY(MLNKH2B(jobs),MDBVNM)==ivarno) THEN
          ROBODY(MLNKH2B(jobs),MDB_VARBC_IX_AT_BODY) = kix(jg)
     ENDIF

   ELSE

     IF (ROBHDR(jobs,MDB_SATID_AT_SAT) == ibufrid .AND. &
       & ROBHDR(jobs,MDBSSIA         ) == isensor .AND. &
       & ROBHDR(jobs,MDBRO3PT        ) == iprod_type      ) THEN

       DO jlev = MLNKH2B(jobs), MLNKH2B(jobs+1)-1
         IF (ROBODY(jlev,MDB_NLAYER_AT_BODY)==ilayer.AND. ROBODY(jlev,MDBVNM)==ivarno) THEN
          ROBODY(jlev,MDB_VARBC_IX_AT_BODY) = kix(jg)
         ENDIF
       ENDDO

      ENDIF

   ENDIF ! if on ivarno = 174 (AOD)


  ENDDO
  
WRITE (NULOUT,'(/,a,i4,a,i4)') myname//': Found ', kix(jg), 'VarBC group indices (varbc_ix@body) in ODB ', jg
ENDDO

CALL PUTDB('VARBC_TO3',0,iret,info,0,zinfo,0)

IF (LHOOK) CALL DR_HOOK(myname,1,zhook_handle)

END SUBROUTINE set_varbcix
!-----------------------------------------------------------------------------

END MODULE VARBC_TO3
