SUBROUTINE CH_GENOPER(PLAT,JLAT,KNULOUT,PRESS,KSTATE,PSTATE, 2 1 CDVAR,PWIN,PH,PHP,PG,KNFLEV) c IMPLICIT NONE c c* Declaration of arguments c CHARACTER*(*) CDVAR INTEGER KNULOUT,KNFLEV,KSTATE,JLAT REAL*8 PWIN,PH(KNFLEV),PHP(KNFLEV),PG(KNFLEV) REAL*8 PRESS(KNFLEV),PLAT,PSTATE(KNFLEV) C #if defined (DOC) *---------------------------------------------------------------------- * ***s/r CH_GENOPER * *Author : Y.J. Rochon *ARQX/MSC November 2004 *Revision: * Y.J. Rochon *ARQX/MSC Dec 2012 * - Corrections and simplications * * ------------------- * ** Purpose: Set generalized innovation operator for individual * integral obs. * *Arguments: * * INPUT: * * KNULOUT: Output unit index * CDVAR: Model variable name * PWIN: Fractional windowing/cutoff value applied to be applied * PHP. If <=0 or >=1, no windowing performed. * PRESS: Pressure levels (Pascal) * KNFLEV: Array dimension (must be >= NFLEV) * PLAT: Latitude of obs. (=ROBHDR(NMCLAT,obs index) * JLAT: Latitude index (=MOBHDR(NCMTLA,obs index) * PH(NFLEV): Complete TLM * PHP(NFLEV):Part of TLM with physics (excludes resolution dependence) * KSTATE: Flag indicating if the state profile will be part of the * generalized innovation operator (1 for yes, 0 for no) * PSTATE(NFLEV): * State profile provided when KSTATE=1 * * OUTPUT: * * PG(NFLEV): Final innovation operator. * *Comments: * * (1) Must only be applied when knflev=nflev. * * (2) This routine prepares an alternative operator g (PG), called * the generalized innovation operator, to take the place of the * innovation (TLM) operator h (row array; PH). The operator g is * specified as: * * g = a*w * * where a is a proportionality constant ensuring that the innovation * increment remains unchanged for the 1D case in the absence * of other obs., i.e., * * a^2 = (h*B*h^T)(w*B*w^T)^{-1}, * B is the initial physical space covariance matrix * (includes variances and vertical correlation matrix only), * w is a weigthing array (row array) specified below. * * The weighting array w is set as: * * w=h'*P*S^{-1} or w = h'*x*P*S^{-1} or w=h'*P*V*B^{-1} * or w=h'*x*P*V*B^{-1} * * where h' is the part of h which excludes resolution dependence * (only contains the physics part of h; PHP), * x is the state profile PSTATE (when KSTATE=1) * P is a diagonal window/cutoff matrix (see PWIN), and * V is an alternative vertical correlation matrix (PHWHM, VCOR) * B is the original covariance matrix (in 2D) * * Application of the state profile (KSTATE=1) is to make the * increment profile be more proportional to the state profile. * *----------------------------------------------------------------------- #endif c c* Global variables c #include "pardim.cdk"
#include "comdim.cdk"
#include "comlun.cdk"
#include "comcorr.cdk"
#include "comgem.cdk"
#include "comleg.cdk"
#include "comstate.cdk"
#include "comgdpar.cdk"
#include "rpnstd.cdk"
#include "comspg.cdk"
#include "comvarstd.cdk"
#include "comcorvert.cdk"
#include "comchem.cdk"
c integer istart common /istart/istart c c* Declaration of local variables c integer ivar,jk,j,ilev real*8 zsum,zg(nflev),zwbw,zhbh,za,zsum2 real*8 zstd(nflev),zvar(nflev),zc1,zc2,zmax c real*8 scaleh(nflev) istart=istart+1 scaleh(:)=1.0 c if (knflev.ne.nflev) then call abort3d(knulout, & 'CH_GENOPER: Dimension not compatible') end if c c* Identify index of variable according to ng* c in sustate.ftn, comstate.cdk, and comchem.cdk). 3D field assumed. c ivar=0 if (CDVAR.eq.'UU') then ivar=nguu else if (CDVAR.eq.'VV') then ivar=ngvv else if (CDVAR.eq.'GZ') then ivar=nggz else if (CDVAR.eq.'TT') then ivar=ngtt else if (CDVAR.eq.'HU') then ivar=ngq else do j=1,NGCMT if (CDVAR.eq.CGCMT(j)) then ivar=ngtr(J) if (CDVAR.EQ.'O3') then scaleh(1:6)=800. do jk=7,12 scaleh(jk)=800.-400*(jk-6)/(13.-6.) end do scaleh(13)=400. do jk=14,32 scaleh(jk)=400.-190*(jk-13)/(33.-13.) end do scaleh(33)=210. do jk=34,79 scaleh(jk)=210.-60*(jk-33)/(80.-33.) end do scaleh(80)=150. scaleh(1:79)=scaleh(1:79)/scaleh(80) scaleh(80)=1.0 end if go to 500 end if end do 500 continue end if if (ivar.eq.0) then write(knulout,2010) cdvar call abort3d(knulout, & 'CH_GENOPER: Field not found') end if 2010 FORMAT(//,'Variable: ',A2) c c* Apply cutoff to PHP (set h'*P) c if (pwin.gt.0.0.and.pwin.lt.1.0) then zmax=0.0D0 do j=1,nflev if (dabs(php(j)).gt.zmax) zmax=dabs(php(j)) end do zmax=pwin*zmax do j=1,nflev if (dabs(php(j)).lt.zmax) php(j)=0.0D0 end do end if c c* Apply state vector if requested c cc if (kstate.eq.1) php(1:nflev)=php(1:nflev)*pstate(1:nflev) cc zg(1:nflev)=php(1:nflev) if (kstate.eq.1) php(1:nflev)=php(1:nflev)*pstate(1:nflev) zg(1:nflev)=php(1:nflev) C C Identify background error std. dev. C zc1=(PLAT-RLATI(jlat+1))/(RLATI(jlat)-RLATI(jlat+1)) zc2=zc2*zc2 c ilev=nflev*(ivar-1) do j=1,nflev zvar(j)=rgsig(jlat,ilev+j)*rgsig(jlat,ilev+j)*zc2+ & rgsig(jlat+1,ilev+j)*rgsig(jlat+1,ilev+j)*zc1 zstd(j)=sqrt(zvar(j)) end do c c Finalize w c do jk=1,nflev zsum=dot_product(corvertt(jk,1:nflev,ivar),zstd(1:nflev)) zvar(jk)=zstd(jk)*zsum c3 zvar(jk)=zstd(jk)*zstd(jk) end do zvar(1:nflev)=zvar(1:nflev)*scaleh(1:nflev) pg(1:nflev)=zg(1:nflev)/zvar(1:nflev) c c* Determine proportionality factor 'a' c c First determine/estimate w*B*w^T and h*B*h^T c zwbw=0.0D0 zhbh=0.0D0 do jk=1,nflev zsum=0.0D0 zsum2=0.0D0 do j=1,nflev za=corvertt(jk,j,ivar)*zstd(j)*sqrt(scaleh(j)) zsum=zsum+za*pg(j) zsum2=zsum2+za*ph(j) end do za=zstd(jk)*sqrt(scaleh(jk)) zwbw=zwbw+pg(jk)*za*zsum zhbh=zhbh+ph(jk)*za*zsum2 end do c c1 zwbw=dot_product(pg(1:nflev)*pg(1:nflev),zvar(1:nflev)) c1 zhbh=dot_product(ph(1:nflev)*ph(1:nflev),zvar(1:nflev)) c c Set 'a' c za=sqrt(zhbh/zwbw) c c* Set innovation operator g c pg(1:nflev)=pg(1:nflev)*za c return end