SUBROUTINE CH_CONVERT(KOBSNMB,KTRCODE,PTRMOLWT,CDCODE,PVTR,PSTATE, 5
     &           PTEMP,PRESS,KNLEV,CDBGTYP,KMODE,KLOGTR,KFLAG)
C
      IMPLICIT NONE
C
C*    Declaration of arguments
C
      INTEGER KOBSNMB,KTRCODE,KNLEV,KMODE,KLOGTR,KFLAG
      REAL*8 PTRMOLWT
      REAL*8 PVTR(KNLEV),PSTATE(KNLEV),PTEMP(KNLEV),PRESS(KNLEV)
      CHARACTER*(*) CDBGTYP
      CHARACTER*(*) CDCODE
C
*---------------------------------------------------------
#if defined (DOC)
*
***s/r CH_CONVERT - Set unit conversion factor and variable transformations
*                   to ensure consistency of Hx units with obs units.
*
*Author  : Y.J. Rochon ARQX/MSC June 2005
*          - From code initially written and modified by
*            Y. Yang (ARQI/MSC) and Y.J. Rochon  
*
**Revisions:
*          Y.J. Rochon ARQX/EC Feb 2007
*          - Completed updates for assimilation of water vapour obs
*            with analysis variable being LQ. Accounted for
*            background check & monitoring (CDBGTYP='HR' and KMODE=1) 
*            and assimilation (all other CDBGTYP and KMODE combinations).
*          - Made corrections to conversions
*          Y.J. Rochon ARQX/EC Apr 2009
*          - Updated for use with newly official constituent descriptors
*            (in addition to previous local descriptors).
*          Y.J. Rochon ARQX/EC Jan 2011
*          - Modified use of PSTATE considering changes in calling routines.
*           
*
*    -------------------
*
*Purpose: Set unit conversion factor and model variable transformations 
*         for consistency of Hx units with obs units. 
*
*Arguments:
*
*   INPUT
*
*     KOBSNMB:  BUFR descriptor element for obs units.
*     KTRCODE:  Code identifying constituent (and thus analysis variable).
*               0 for non-species.
*     CDCODE:   Corresponding model/analysis NOMVAR
*     KLOGTR:   State of species model/analysis variables.
*               0:  vmr (except for ln(q))
*               1:  ln(vmr)
*     PTRMOLWT: Molecular mass of constituent (g/mol).
*     KNLEV:    Dimension of PVTR and PSTATE
*     PVTR:     Increment field or trial field. 
*               (only relevant for KMODE=0)
*     PSTATE:   Analysis field on increment/analysis grid
*               (only relevant for CDBTYP.ne.'HR' & .ne.'hr')
*     PTEMP:    Temperature array (Kelvin)
*     PRESS:    Pressure array (Pascal; kg/(m s^2))
*     CDBGTYP:  'HR' for high resolution (trial field) grid (for gom*hr)
*               'BG' for low resolution (rebm) grid
*     KMODE:    0 when called by forward model or TLM (for ch_jocalc, ch_oda_htr)
*               1 when called by adjoint model (for ch_oda_httr)
*                 or CH_SETFGE (background check)
*     KLFAG     Initial flag value for obs rejection.
*
*   OUTPUT
*
*     PVTR:     Scaled or transformed increment field or trial field.
*     PSTATE:   Scaled or transformed analysis field on increment/analysis grid
*               (only relevant for CDBTYP.ne.'HR' & .ne.'hr' & KMODE .eq. 0)
*     KFLAG     Flag to indicate if obs is to be rejected. Set to 1 
*               for rejection, unchanged otherwise.
*
*Comments:
*
*     A. Standard model/analysis species field provided as volumetric mixing 
*        ratio (vmr). Conversion to vmr is applied when this is not the case. 
*        As this is hardcoded, any changes in analysis variable must
*        be reflected by correspondingly modifying this module.
*
*     B. Unit conversion factor is calculated in CH_CONVERT
*        from the following factors:
*          (1) physical constants: stored in comcst.cdk
*          (2) parameters related to a particular species such as molecular
*              mass previously read from BURP obs file and stored in CMA
*          (3) variables such as T and P from background field at each
*              iteration
*
*     Sample unit conversion factors:
*
*     Coefficients related to unit conversion
*
*        conv=1.E5              ! m to 1e-5m (=1DU)
*        rho_stp=1.293          ! air density at STP (kg/m^3)
*        ratio_oz_air = 1.657   ! ratio of mol. weigths ozone/air
*        rg=9.807               ! Acceleration due to gravity (m/s^2)
*
*      For background field provided in volume mixing ratio,
*      conversion factor from 'ozone volume mixing ratio'*Pascal to
*
*      (1) DU (e.g. ozone total column, GOME, TOMS) is
*
*              zcoef = 1.0/rg/rho_stp*conv
*
*      (2) kg/m^2 (e.g. ozone partial column, SBUV) is
*
*              zcoef = (molecular mass of species)
*                      /(molecular mass of air)/rg
*
*-----------------------------------------------------------
#endif
C
C*    Global variables
C
#include "comlun.cdk"
#include "comcst.cdk"
C
C*    Declaration of local variables
C
      REAL*8 CONV,ZCOEF
      INTEGER JL
C
C     Initialization
C
      zcoef=1.0
C
C     Do not apply transformations for winds and temperature variables
C 
      if (CDCODE.eq.'TT'.or.CDCODE.eq.'UU'.or.CDCODE.eq.'VV') RETURN
C
C     Assume species obs beyond this point.
C
C     Identify special obs - analysis variable combination requiring no
C     transformation.
C
C     - None at the moment -
C
C     Apply any required analysis variable transformations to vmr
C
      IF (KLOGTR.EQ.1.OR.CDCODE.EQ.'LQ'.OR.CDCODE.EQ.'HU') THEN
C
C        Assumes analysis variable is 'LQ' if humidity obs.
C        Convert from ln(analysis variable) or corresponding increment
C        to vmr.
C
C        First apply exponential or its TLM equivalent
C
         IF (CDBGTYP.ne.'HR'.and.CDBGTYP.ne.'hr') then
C
C             dx = x dlnx, with lnx = pstate(JL), dlnx=pvtr(JL)
C             Note: x=pstate(JL) for KMODE=1
C
              if (KMODE.eq.0) pstate=exp(pstate)
              pvtr = pstate*pvtr
         else
            IF (KMODE.eq.0) THEN
C
C              Converts LQ to HU or ln(x) to x
C
               pvtr=exp(pvtr)
            ELSE
C
C              Converts dLQ to dHU or dln(x) to dx 
C
Cx              dx = x dlnx, with lnx = pstate(JL), dlnx=pvtr(JL)
C              dx = x dlnx, with x = pstate(JL), dlnx=pvtr(JL)
C                 
Cx               pstate=exp(pstate) 
               pvtr= pstate*pvtr
            END IF
         end if
C
         IF (CDCODE.EQ.'LQ'.OR.CDCODE.EQ.'HU') THEN
C
C           Conversion from specific humidity to obs unit.
C
C           First convert to mass mixing ratio (or mass mixing ratio increment)
C
            IF (CDBGTYP.ne.'HR'.and.CDBGTYP.ne.'hr') then
               IF (KMODE.eq.0) THEN
C
C                 Apply tangent linear of r=q/(1-q):
C
C                           dr = dq/(1-q)^2
C
                  do JL=1,knlev
                    conv=pstate(JL)
                    if (conv.gt.0.8.or.conv.lt.-1.E-5) then
                       kflag=1
                       return
                    else
                       pvtr(JL)=pvtr(JL)/(1.0-conv)**2
                       pstate(JL) = pstate(JL)/(1.0E0-pstate(JL))
                    end if
                  end do
               ELSE
C
C                 pstate (and 1-conv) should be same as previously
C                 obtained with KMODE=0
C
                  do JL=1,knlev
                    conv=pstate(JL)
                    pvtr(JL)=pvtr(JL)/(1.0-conv)**2
                  end do
               END IF
            else
               IF (KMODE.eq.0) THEN
                  do JL=1,knlev
                     if (pvtr(JL).gt.0.8.or.pvtr(JL).lt.-1.E-5) then
                        kflag=1
                        return
                     else
                        pvtr(JL) = pvtr(JL)/(1.0E0-pvtr(JL))
                     end if
                  end do
               ELSE
                  do JL=1,knlev
                    conv=pstate(JL) ! HU
                    if (conv.gt.0.8.or.conv.lt.-1.E-5) then
                         kflag=1
                         return
                    else
                         pvtr(JL)=pvtr(JL)/(1.0-conv)**2
                    endif
                  end do
               end if
            end if
C
C           Account for mass mixing ratio to volume mixing ratio conversion
C
            pvtr(:)=pvtr(:)*RMD/PTRMOLWT
C
         END IF
C
      END IF
C
C     Identify unit conversion factor (pcoef) and variable conversion
C     assuming variable is a vmr. 
C
      if (KOBSNMB.eq.15001.or.KOBSNMB.eq.15005) then
C
C        For conversion of vmr*dP integral to DU
C        rg:  Accelaration due to gravity. 9.8607 m/s^2
C        rho_stp: Air density at STP. 1.293 kg/m^3
C
         conv=1.E5              ! m to 1e-5m (=1DU)
         zcoef = zcoef/rg/rho_stp*conv
         pvtr(:)=pvtr(:)*zcoef
C
      else if (KOBSNMB.eq.15198.or.KOBSNMB.eq.15009) then
C
C        For conversion of vmr*dP integral to molecules/m^2
C        RAV: Avogadro's number. 6.023E23 molecules/mole
C        RMD: Dry air molecular mass. 28.9644 g/mole         
C        rg:  Accelaration due to gravity. 9.8607 m/s^2
C
         conv=1.E3         ! 1.E3 g/kg
C                          ! required for conversion of RMD from g/mol
C                          ! to kg/mol
         zcoef = zcoef*RAV*conv/RMD/rg
         pvtr(:)=pvtr(:)*zcoef
C
      else if (KOBSNMB.eq.15020.or.KOBSNMB.eq.15021.or.KOBSNMB.eq.15200) then
C
C        For conversion of vmr*dP integral to kg/m^2
C        RMD: Dry air molecular mass. 28.9644 g/mole
C        rg:  Accelaration due to gravity. 9.8607 m/s^2 
C
         zcoef = zcoef*PTRMOLWT/RMD/rg
         pvtr(:)=pvtr(:)*zcoef
C
      ELSE IF (KOBSNMB.eq.15027.or.KOBSNMB.eq.15223.or.KOBSNMB.eq.15007) THEN  
C
C        For conversion from vmr to kg/m^3
C        RDCJ: Dry air constant. 8.341 J/mole/K (J=kg m^2/s^2)
C       
         zcoef = zcoef*PTRMOLWT/RDCJ
C
C        Apply temperature and pressure at observation level.
C
         pvtr = pvtr*PRESS/PTEMP*zcoef
         if (CDBGTYP.ne.'HR'.and.CDBGTYP.ne.'hr'.and.KMODE.EQ.0) then
               pstate = pstate*PRESS/PTEMP*zcoef
         end if
C
      ELSE IF (KOBSNMB.eq.15010.or.KOBSNMB.eq.15199.or.KOBSNMB.eq.15003) THEN
C       
C        For conversion from vmr to partial pressure (PA)
C
         pvtr = pvtr*PRESS*zcoef
         if (CDBGTYP.ne.'HR'.and.CDBGTYP.ne.'hr'.and.KMODE.EQ.0) then
               pstate = pstate*PRESS*zcoef
         end if   
C
      ELSE IF (KOBSNMB.eq.15230.or.KOBSNMB.eq.15022) then
C
C        For conversion from vmr to molecules/m^3
C        RAV:  Avogadro's number. 6.023E23 molecules/mole
C        RDCJ: Dry air constant. 8.341 J/mole/K  (J=kg m^2/s^2)
C
         zcoef = zcoef*RAV/RDCJ
C
C        Apply temperature and pressure at observation level.
C
         pvtr = pvtr*PRESS/PTEMP*zcoef
         if (CDBGTYP.ne.'HR'.and.CDBGTYP.ne.'hr'.and.KMODE.EQ.0) then
               pstate = pstate*PRESS/PTEMP*zcoef
         end if
C
      ELSE IF (KOBSNMB.eq.15026.or.KOBSNMB.eq.15008.or.KOBSNMB.eq.15197) then
C
C        Observation in molecules/molecules by volume (vmr).
C        No conversion needed.
C        
c         zcoef = zcoef*1.0D0
c         pvtr = pvtr*zcoef
C
      ELSE IF (KOBSNMB.eq.15024) then
C
C        Do nothing
C
      else 
         write(nulout,*) 'CH_CONVERT: Unknown obs type ',KOBSNMB
         call abort3d(nulout,'CH_CONVERT')
      END IF
C
      RETURN
      END