SUBROUTINE CH_SETFGE 1,7
C
*---------------------------------------------------------
#if defined (DOC)
*
***s/r CH_SETFGE   - Compute  THE FIRST GUESS ERROR STD. DEV.
*                    of F(x) related to 'TR' family obs.
*
*
*Author  : Y.J. Rochon *ARQX/EC March 2006
*          Based on SETFGEFAM by P. Koclas *CMC/CMSV November 1998
*          and CH_JOCALC by Y.J. Rochon
*
*Revision:
*          Y.J. Rochon, ARQX/EC, Feb 2007
*                - Addition of IREJECT flag and
*                  SUM(MOBDATA(NCMASS,IDATA:IDATEND)).NE.0 condition
*                - Added option of applying day/night/near-terminator 
*                  obs acceptance criteria
*           Y.J. Rochon ARQX, June 2008
*                - Addition of Doppler wind operator CH_DOPWIND
*                  (IOBSNMB.EQ.NVNUMB(58))
*          Y.J. Rochon ARQX Aug 2010
*                - Added possible use of avg kernel matrices
*          Y.J. Rochon ARQI Feb 2013
*                - Added iobstyp=4 option
*
*    -------------------
*
**    Purpose: - Compute THE FIRST GUESS ERROR STD. DEV. of F(x).
*                It assumes a linear interpolation in ln(p) of
*                the trial field is performed.
*
**
*
*     Comments:
*
*     1) This routine must be quasi-identical to CH_JOCALC. 
*        When the call to a new TLM is added to CH_JOCALC, 
*        then it should also be added to CH_SETFGE.
*
**    Assumptions: 
*
*     1) GOMOBS contains forecast error std. dev.
*   
*     2) Estimation of max std. dev. done by doing calc.
*        as though all points are entirely correlated with
*        the others (correlation coefficients of 1).
*
*        Why: Accounting for correlations more complicated.
*
*             Allows direct use of TLM by subsituting the
*             the increments by the std. dev. That is,
*             the resultant std. dev. is 
*
*                    the sum of weights values
*
*             instead of 
*
*                    the root of sum of squared weighted values
*                    + accounting for correlation effects.
*
*-----------------------------------------------------------
#endif
      IMPLICIT NONE
*implicits
#include "pardim.cdk"
#include "comdim.cdk"
#include "comdimo.cdk"
#include "comgem.cdk"
#include "comoabdy.cdk"
#include "comoahdr.cdk"
#include "comoba.cdk"
#include "comstate.cdk"
#include "commvo.cdk"
#include "commvog.cdk"
#include "commvohr.cdk"
#include "comnumbr.cdk"
#include "cvcord.cdk"
#include "comlun.cdk"
#include "comchem.cdk"
#include "cparbrp.cdk"  
#include "comcst.cdk"
C     
C*    Declaration of local variables
C          
      INTEGER IOBS,IPOS,I1,I2
      INTEGER JDATA,J,IBEGIN,ILAST,JJ
      INTEGER IOBSNMB, IOBSTYP,IOBSLEV,IIFLAG,ID
      INTEGER JOBS, IDATA, IDATEND, J1
      INTEGER IBEGIN1, ILAST1,ILAT
      INTEGER JLT,ILMAX,IREJECT
      INTEGER IDIM
      PARAMETER (IDIM=500)  ! Must be >=JPNFLEV
      INTEGER ICOND(IDIM)
      REAL*8 ZOBSLEV(IDIM),ZOBSLEV2(IDIM),ZTRIAL(IDIM)
      REAL*8 ZLAT,ZSTATE(JPNFLEV),ZVTR(IDIM),ZLON,ZTODEG
      REAL*8 ZPRESS(JPNFLEV),ZTEMP(JPNFLEV),ZALT(JPNFLEV)
      REAL*8 ZVTR2(IDIM),ZTRIAL2(IDIM),ZDUM(JPNFLEV)
 
      INTEGER ITRCODE
      INTEGER INUMS,INUM,IKERN
      INTEGER CH_KGETPOS
C
      EXTERNAL CH_KGETPOS
      CHARACTER*2 CLFAM

      INTEGER IPB,IPT,IK
      REAL*8 ZWB,ZWT
      REAL*8 ZLEV,ZPB,ZPT
C
      CLFAM='TR'
      ILMAX = NFLEV
      ZTODEG=180./RPI
C
      DO J = 1,NFILES
        IF (CFAMTYP(J).EQ.CLFAM.AND.NBEGINTYP(J).GT.0.AND.
     &    NENDTYP(J).GE.NBEGINTYP(J)) THEN
C
          IBEGIN=NBEGINTYP(J)
          ILAST=NENDTYP(J)
          IBEGIN1 = MOBDATA(NCMOBS,IBEGIN)
          ILAST1  = MOBDATA(NCMOBS,ILAST)
C
C         Loop over obs reports in a subfamily
C
          DO JOBS = IBEGIN1, ILAST1
C
C           Loop over obs (profiles) in a report.
C          
            INUM=MOBHDR(NCMNUM,JOBS)
            INUMS=MOBHDR(NCMNLV,JOBS)
C
            DO J1=1,INUM
C
C              Identify range of elements for an obs in the report
C
               IF (J1.EQ.1) THEN
                  IDATA   = MOBHDR(NCMRLN,JOBS)
                  IF (INUM.GT.1) INUMS=MOBDATA(NCMNUM1,IDATA)
                  IDATEND = INUMS + IDATA - 1
               ELSE
                  IDATA=IDATA+INUMS
                  IF (INUM.GT.1) INUMS=MOBDATA(NCMNUM1,IDATA) 
                  IDATEND=INUMS+IDATA-1
               END IF
C
C              Initialize std. dev. array. to PPMIS
C
               ROBDATA(NCMFGE,IDATA:IDATEND)=PPMIS
C
C              Check observation vertical coordinate and convert
C              to pressure when necessary.
C
               CALL CH_VOBS_TO_P(NULOUT,JOBS,ZOBSLEV,ZOBSLEV2,
     1                IDATA,IDATEND,IOBSLEV,IDIM,IIFLAG)
               IF (IIFLAG.NE.0.OR.IOBSLEV.NE.INUMS) THEN
                  write(nulout,*) 'CH_SETFGE: Level inconsistency.'
                  goto 150
               END IF
C
C              Obtain obs type to identify appropriate forward model (or TLM).  
C
               IOBSTYP  = MOBDATA(NCMCORD1,IDATA)
               IF (IOBSTYP.NE.1.AND.IOBSTYP.NE.2.AND.
     &             IOBSTYP.NE.3.AND.IOBSTYP.NE.4) GO TO 150
C
C              Obtain latitude and longitude of obs report
C
               ZLAT=ROBHDR(NCMLAT,JOBS)
               ILAT=MOBHDR(NCMTLA,JOBS)
               ZLON=ROBHDR(NCMLON,JOBS)
C
               IOBSNMB = MOBDATA(NCMVNM,IDATA)
               IOBS = MOBDATA(NCMOBS,IDATA)
               IPOS = MOBDATA(NCMPOS,IDATA)
               ITRCODE   = MOBDATA(NCMSPEC,IDATA)
C
               JLT = CH_KGETPOS(IOBSNMB, ITRCODE, CSTNID(JOBS))
               IF (JLT .LT. 0) THEN
                 write(nulout, *) 'CH_SETFGE: Species ', IOBSNMB,'  not processed!'               
                 go to 150
               END IF
C
C*             Identify background/increment arrays at obs lat/long location
C
               ZSTATE(1:ILMAX)=0.0
               IF (CNAMANAL(JLT).EQ.'HU'.OR.CNAMANAL(JLT).EQ.'LQ') THEN 
C                 
C                 Requires LQ trial field for variable transformation.
C                 
                  ZSTATE(1:ILMAX)=GOMQHR(1:ILMAX,IOBS)  ! Store LQ
               ELSE IF (NLOGTR.NE.0.AND.ITRCODE.NE.0) THEN
C                 
C                 Requires trial field for species variable transformation.
C
                  ZSTATE(1:ILMAX)=GOMOBSHR(1:ILMAX,IOBS) 
               END IF
               I1=1+IPOS*ILMAX
               I2=ILMAX+IPOS*ILMAX
c               zvtr(1:ILMAX) = GOMOBSHR(I1:I2,iobs)
               zvtr(1:ILMAX) = GOMOBS(I1:I2,iobs)
               if (iobsnmb.eq.nvnumb(58))  zvtr2(1:ILMAX) =
     &                   GOMOBS(I1+ILMAX:I2+ILMAX,iobs)
c     &                   GOMOBSHR(I1+ILMAX:I2+ILMAX,iobs)
               ztemp(1:ILMAX)=GOMTHR(1:ILMAX,IOBS)
               zpress(1:ILMAX)=RPPOBSHR(1:ILMAX,IOBS)
C
C*             Initialize ROBDATA8 to zero at obs location
C
               ROBDATA(NCMFGE,IDATA:IDATEND)=PPMIS
               ZTRIAL(1:INUMS)=0.0D0
               ZTRIAL2(1:INUMS)=0.0D0
C
               IREJECT=1
               IF (SUM(MOBDATA(NCMASS,IDATA:IDATEND)).NE.0) THEN
C             
                  IREJECT=0
C 
C                 Apply day/night/near-terminator criterion if requested
C                       For acceptance, point must be either under day or
C                       night condition for both the obs time and analysis
C                       time.
C
                  IF (daynightp(jlt).gt.0.0) THEN
C
                     IF (MOBDATA(NCMVCO,IDATA).NE.0) THEN
                        IF (MOBDATA(NCMVCO,IDATA).EQ.2) THEN
                           ZALT(:)=-1.0   ! Obs coord. not altitude
                        ELSE
C                          Obs vert. coord. is altitude (m)
                           ZALT(1:INUMS)=
     &                         ROBDATA8(NCMPPP,IDATA:IDATEND)
                        END IF
                        call ch_termcond(zlat*ztodeg,zlon*ztodeg,
     &                     MOBHDR(NCMDAT,NOBTOT),MOBHDR(NCMETM,NOBTOT),
     &                     INUMS,ZOBSLEV,ZALT,daynightp(jlt),
     &                     RPPOBS(1:ILMAX,IOBS),
     &                     GOMGZG(1:ILMAX,IOBS)/RG,
     &                     ILMAX,NULOUT,ICOND)
                        WHERE (ICOND(1:INUMS).EQ.0)  
                            MOBDATA(NCMASS,IDATA:IDATEND)=0
                            MOBDATA(NCMFLG,IDATA:IDATEND)=
     &                         MOBDATA(NCMFLG,IDATA:IDATEND)+131072+512
C                                  ! Same flag as for QCvar rejection
                        ENDWHERE
                        IF (SUM(MOBDATA(NCMASS,IDATA:IDATEND)).EQ.0)
     &                          IREJECT=1
                      END IF
                  END IF
C
C                 Set unit conversion factor ZVTR
C
                  IF (IREJECT.EQ.0) THEN
                     CALL CH_CONVERT(IOBSNMB,ITRCODE,speciesm(jlt),
     &                  CNAMANAL(JLT),ZVTR,ZSTATE,ZTEMP,ZPRESS,ILMAX,
     &                   'HR',1,NLOGTR,IREJECT)
                     IF (IREJECT.EQ.1) THEN
                        WRITE(NULOUT,*)
     &                     'CH_SETFGE: Obs rejected via CH_CONVERT: ',
     &                     CNAMANAL(JLT)
                         MOBDATA(NCMASS,IDATA:IDATEND)=0
                         MOBDATA(NCMFLG,IDATA:IDATEND)=
     &                         MOBDATA(NCMFLG,IDATA:IDATEND)+131072+512
C                                  ! Same flag as for QCvar rejection
                     END IF
                  END IF
               END IF
C
C*             If not rejected, select and apply forward model
C              "F(x)" (or TLM "Hx") for obs profile (with all
C               elements at same lat/long)
C
               IKERN=0
               IF (MOBHDR(NCMKER,JOBS).gt.0) IKERN=MOBHDR(NCMKER,JOBS)-INUM+J1
C
               IF (IREJECT.EQ.1) THEN
C                 
C                 Obs was rejected.
C
               ELSE IF (iobstyp.eq.1) then
C
C                 Point profiles.
C
                  if (iobsnmb.eq.nvnumb(58)) then  
C
C                    Doppler wind measurement
C                                  
                     CALL CH_DOPWIND(MOBDATA(NCMASS,IDATA:IDATEND),
     &                          MOBDATA(NCMXTR,IDATA:IDATEND),
     &                          ROBDATA(NCMLYR,IDATA:IDATEND),INUMS,
     &                          ILMAX,ZOBSLEV,ZPRESS,ZVTR,ZVTR2,
     &                          ROBDATA(NCMDWN,IDATA:IDATEND),
     &                          ZTRIAL,ZTRIAL2,0,IDIM)
C                 
                  else
C
                     CALL CH_VPROF(MOBDATA(NCMASS,IDATA:IDATEND),
     &                          MOBDATA(NCMXTR,IDATA:IDATEND),
     &                          ROBDATA(NCMLYR,IDATA:IDATEND),INUMS,
     &                          ILMAX,ZOBSLEV,ZPRESS,ZVTR,ZTRIAL,0,IDIM,IKERN)
                  end if
C
               ELSE IF (iobstyp.eq.2.or.iobstyp.eq.4) then
C
C                 Layer average observation elements.
C
                  MOBDATA(NCMXTR,IDATA:IDATEND)=0
                  CALL CH_VAVG(INUMS,MOBDATA(NCMASS,IDATA:IDATEND),
     &                         MOBDATA(NCMXTR,IDATA:IDATEND),
     &                         ZTRIAL,ZDUM,
     &                         'HR',ZVTR,zobslev,zobslev2,
     &                         ZPRESS,ilmax,zlat,ilat,zstate,
     &                         CNAMANAL(JLT),0,iobstyp)
C
               ELSE IF (iobstyp.eq.3) then
C
C                 Total or partial column amounts.
C
                  MOBDATA(NCMXTR,IDATA:IDATEND)=0
                  CALL CH_VCOLM(INUMS,MOBDATA(NCMASS,IDATA:IDATEND),
     &                          MOBDATA(NCMXTR,IDATA:IDATEND),
     &                          ZTRIAL,ZDUM,
     &                          'HR',ZVTR,zobslev,zobslev2,
     &                          ZPRESS,ilmax,zlat,ilat,zstate,
     &                          CSTNID(JOBS),CNAMANAL(JLT),0,IKERN)
C
               END IF
C
C              Save in ROBDAT(NCMFGE,*)
C
               DO JJ=1,INUMS
                  IF (MOBDATA(NCMASS,IDATA+JJ-1).EQ.1) THEN
                     IF (MOBDATA(NCMXTR,IDATA+JJ-1).EQ.2) THEN
                        ROBDATA(NCMFGE,IDATA+JJ-1)=ZTRIAL(INUMS)
                     ELSE IF (MOBDATA(NCMXTR,JJ).EQ.1) THEN
                        ROBDATA(NCMFGE,IDATA+JJ-1)=ZTRIAL(1)    
                     ELSE
                        ROBDATA(NCMFGE,IDATA+JJ-1)=ZTRIAL(JJ)
                     END IF
                  END IF
               END DO
C
 150           CONTINUE
            END DO
          END DO
        END IF
      END DO
C
      RETURN
      END