!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer,
!                     version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer
!version 3 or (at your option) any later version that should be found at:
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software;
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec),
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
!

      SUBROUTINE oda_qcv(lobsSpaceData) 1,33
      use obsSpaceData_mod
      use columnData_mod
      use bufr
      use rmatrix_mod ,only : rmat_lnondiagr
      IMPLICIT NONE
*
*Purpose : 1) Modify Jo [OBS_JOBS] according to
*             Andersson and Jarvinen 1999, Variational quality control,
*             Q.J.R., 125, pp. 697-722.
*          2) Save the values of (1-Wqc) in OBS_QCV
*             for gradient factorization and postalt flag criterion.
*
*Author  : S. Pellerin, ARMA, January 2009
*          Generalisation of QCVAR originally embeded in observation
*          operators from P. Koclas, J. Halle and J. St-James
*
      type(struct_obs) :: lobsSpaceData
      integer :: index_body,istyp,jj,index_header,ityp,index_body_start,ierr,index_family
      real*8 :: zgami,zjon,zqcarg,zppost,zlev,zslev
      logical :: lluv
      logical :: includeFlag
C
      BODY: do index_body = 1, obs_numbody(lobsSpaceData)
        includeFlag = (obs_bodyElem_i(lobsSpaceData,OBS_ASS,index_body).eq.1) 
     +          .and. (obs_getFamily(lobsSpaceData,bodyIndex=index_body).ne.'RO')
C pas de qcvar pour  les radiances en mode matrice R non diagonale
        if (rmat_lnondiagr) includeFlag = 
     +    includeFlag .and. 
     +    (obs_getFamily(lobsSpaceData,bodyIndex=index_body).ne.'TO') 

        if (includeFlag) then
          index_header = obs_bodyElem_i(lobsSpaceData,OBS_HIND,index_body)
          index_body_start = obs_headElem_i(lobsSpaceData,OBS_RLN,INDEX_HEADER)
          ZLEV = obs_bodyElem_r(lobsSpaceData,OBS_PPP,INDEX_BODY)
          zgami = obs_bodyElem_r(lobsSpaceData,OBS_POB,index_body)
          ITYP = obs_bodyElem_i(lobsSpaceData,OBS_VNM,INDEX_BODY)
          LLUV = ((ITYP .EQ. BUFR_NEUU .OR. ITYP .EQ. BUFR_NEUS) .AND.
     &         col_varExist('UU')) .OR. ((ITYP .EQ. BUFR_NEVV .OR.
     &         ITYP .EQ. BUFR_NEVS).AND.col_varExist('VV'))
          IF (LLUV) THEN
            IF (ITYP .EQ. BUFR_NEUU .OR. ITYP .EQ. BUFR_NEUS)THEN
C
C  In order to calculate the contribution to Jo from a wind, the o-a
C  must be available for both u and v components. Hence, loop over only
C  data for which o-a has already been calculated
C
              DO JJ=INDEX_BODY_START, INDEX_BODY
                ISTYP = obs_bodyElem_i(lobsSpaceData,OBS_VNM,JJ)
                ZSLEV = obs_bodyElem_r(lobsSpaceData,OBS_PPP,JJ)
                IF ((ISTYP .EQ. BUFR_NEVV
     1               .OR. ISTYP .EQ. BUFR_NEVS) .AND.
     2               ZSLEV .EQ. ZLEV) THEN
                  ZJON=obs_bodyElem_r(lobsSpaceData,OBS_JOBS,INDEX_BODY)+
     &                 obs_bodyElem_r(lobsSpaceData,OBS_JOBS,JJ)
                  ZQCARG = ZGAMI + EXP(-1.0D0*ZJON)
                  ZPPOST = ZGAMI/ZQCARG
C
C     Store the value of o-a multiplied by one minus the posterior
C     probability of gross error (needed for the adjoint calculations)
C
                  call obs_bodySet_r(lobsSpaceData,OBS_QCV,INDEX_BODY, ZPPOST)
                  call obs_bodySet_r(lobsSpaceData,OBS_QCV,JJ, ZPPOST)

                  call obs_bodySet_r(lobsSpaceData,OBS_JOBS,INDEX_BODY,-LOG(ZQCARG/(ZGAMI+1.D0))
     &                 /2.D0)
                  call obs_bodySet_r(lobsSpaceData,OBS_JOBS,JJ, -LOG(ZQCARG/(ZGAMI+1.D0))
     &                 /2.D0)
C
C     Contribution of both u and v added to the cost function at the
C     same time (see tech. note by Andersson and Jarvinen)
C
                ENDIF
              ENDDO
            ELSE ! ITYP
              DO JJ=INDEX_BODY_START, INDEX_BODY
                ISTYP = obs_bodyElem_i(lobsSpaceData,OBS_VNM,JJ)
                ZSLEV = obs_bodyElem_r(lobsSpaceData,OBS_PPP,JJ)
                IF ((ISTYP .EQ. BUFR_NEUU .OR.
     1               ISTYP .EQ. BUFR_NEUS) .AND.
     2               ZSLEV .EQ. ZLEV) THEN
                  ZJON=obs_bodyElem_r(lobsSpaceData,OBS_JOBS,INDEX_BODY)+
     &                 obs_bodyElem_r(lobsSpaceData,OBS_JOBS,JJ)
                  ZQCARG = ZGAMI + EXP(-1.0D0*ZJON)
                  ZPPOST = ZGAMI/ZQCARG
                  call obs_bodySet_r(lobsSpaceData,OBS_QCV,INDEX_BODY, ZPPOST)
                  call obs_bodySet_r(lobsSpaceData,OBS_QCV,JJ, ZPPOST)
                  call obs_bodySet_r(lobsSpaceData,OBS_JOBS,INDEX_BODY,-LOG(ZQCARG/(ZGAMI+1.D0))
     &                 /2.D0)
                  call obs_bodySet_r(lobsSpaceData,OBS_JOBS,JJ, -LOG(ZQCARG/(ZGAMI+1.D0))
     &                 /2.D0)
                ENDIF
              enddo
            endif !ITYP
          else ! LLUV
            zjon = obs_bodyElem_r(lobsSpaceData,OBS_JOBS,index_body)
            zqcarg = zgami + exp(-1.0D0*zjon)
            zppost = zgami/zqcarg
            call obs_bodySet_r(lobsSpaceData,OBS_QCV,index_body, zppost)
            call obs_bodySet_r(lobsSpaceData,OBS_JOBS,INDEX_BODY, - log(zqcarg/(zgami+1.D0)))
          endif ! LLUV

        endif ! includeFlag

      enddo BODY

      END subroutine oda_qcv