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