SUBROUTINE CH_VERTINTG(pveta, ptop, pbtm, 10,2
1 qpeta, knflev, kfirst, pstate,
1 knulout,cvar,ktot,zh,zhp)
C
IMPLICIT NONE
C
C* Declaration of arguments
C
CHARACTER*(*) cvar
INTEGER knflev,knulout,kfirst,ktot
REAL*8 pveta(knflev),pstate(knflev),qpeta(knflev)
REAL*8 zh(knflev),zhp(knflev)
REAL*8 pbtm,ptop
C
*---------------------------------------------------------------------
#if defined (DOC)
*
***s/r CH_VERTINTG -- Vertical integration model to calculate partial (or total)
* column value of model state profile 'pveta' or used for
* adjoint calculations.
*
*Author : Y. Yang, based on Y. Rochon and S. Ren's program
*Revision:
* Yves J. Rochon, ARQX/MSC Nov 2004
* - Code strealining and changes for call and use
* of generalized innovation operator routine (ch_genoper)
* - Adapted for use with both the forward and adjoint models
* Yves J. Rochon, ARQX/MSC March 2007
* - Minor correction of text.
* Yves J. Rochon, ARQI Dec 2012
* - Reduced to setting of innovation operator terms
*
** Purpose: Calculate innovation operator terms required for vertical
* integration w.r.t. pressure to calculate partial (or total)
* column value of model state profile 'pveta' or used for adjoint calc..
* Layer boundaries are taken as mid-point between eta levels in lnP
* coordinate. Layer values are set to be the values interpolated
* to the mid-point in P within the various layers. Interpolation
* in P is done quadratically. (Some of above comments repeated below.)
*
*
*Arguments:
*
* Input pveta(nvlev) -- background values at eta levels when kmod=0
* knvlev -- # of vertical levels
* qpeta -- pressure at eta levels
* ptop -- obs top - level pressure (in Pascal)
* pbtm -- obs bottom -level pressure (in Pascal)
* kfirst -- Initialization flag.
* When jfirst=1, calc peta,pres, and vmid
* knulout -- Output unit index
* cvar -- Model variable name
* pstate(knflev) -- State profile for possible use in CH_GENOPER
*
* Output
* zh(knflev) -- Initial innovation model array
* (other than conversion constants)
* zhp(knflev) -- Part of innovation operator not
* related to resolution
*
* Local common block
* qpres -- pressures at analysis layer boundaries
* vh -- Storage array for elements contributing
* to the forward model.
*
*Comments:
*
* 1. VH is an intermediate work array used for setting the forward model array ZH.
*
* Description of i,j in vh(i,j):
*
* i: eta/analysis level index (index for eta, qpeta and pveta)
* j: layer index (index for layer between pressures qpres(j) & qpres(j+1))
*
* 2. Analysis layer boundaries set midpoint in alog(p) between analysis levels
*
* N.B.: exp(0.5*(alog(x)+alog(y)) = sqrt(x*y)
*
* 3. Since integration is in P (and not alog(P)), value of analysis variables
* are interpolated to middle of analysis layers in P.
*
*---------------------------------------------------------------------
#endif
C
C Common block used only in this routine
C
#include "pardim.cdk"
INTEGER ivh
PARAMETER (ivh=2)
REAL*8 vh(jpnflev,jpnflev)
REAL*8 qpres(jpnflev+1)
COMMON /VERTING/ qpres,vh
C
C* Declaration of local variables
C
INTEGER J,JK,ILMAX2,ILMIN2
INTEGER ILMIN, ILMAX
REAL*8 zet, zp, zp1, zp2, zp3, zr1, zr2, zr3,zsum,zhwhm
REAL*8 zdumeta,zwin
INTEGER ch_igetmodlev
C
EXTERNAL ch_igetmodlev
C
C* Determine P boundaries of analysis layers and save weights for
C use in setting innovation operator array.
C
C N.B.: Boundaries of layers set to mid-point
C
if (kfirst.eq.1) then
C
C Initialize innovation operator element array to zero
C
vh(:,:)=0.0D0
C
C Calculate layer boundaries
C
qpres(1)=qpeta(1)
qpres(knflev+1)= qpeta(knflev)
C
DO JK = 2, KNFLEV
qpres(jk)=sqrt(qpeta(jk-1)*qpeta(jk))
END DO
C
C Interpolation of pveta to mid-layer level in P using
C second degree Lagrangian interpolator.
C N.B.: Integration is w.r.t. P
C
C Calculating for jk=1
C
zp1= qpeta(1)
zp2= qpeta(2)
zp3= qpeta(3)
zp = (qpres(2)+qpres(1))/2.0
zr1=(zp-zp2)*(zp-zp3)/(zp1-zp2)/(zp1-zp3)
zr2=(zp-zp1)*(zp-zp3)/(zp2-zp1)/(zp2-zp3)
zr3=(zp-zp2)*(zp-zp1)/(zp3-zp2)/(zp3-zp1)
c vmid(1)=pveta(1)*zr1+pveta(2)*zr2
c + +pveta(3)*zr3
vh(1,1)=zr1
vh(2,1)=zr2
vh(3,1)=zr3
C
DO JK=2,knflev-1
zp1=qpeta(jk-1)
zp2=qpeta(jk)
zp3=qpeta(jk+1)
zp=(qpres(jk+1)+qpres(jk))/2.0
zr1=(zp-zp2)*(zp-zp3)/(zp1-zp2)/(zp1-zp3)
zr2=(zp-zp1)*(zp-zp3)/(zp2-zp1)/(zp2-zp3)
zr3=(zp-zp2)*(zp-zp1)/(zp3-zp2)/(zp3-zp1)
c vmid(jk)=pveta(jk-1)*zr1+pveta(jk)*zr2
c + +pveta(jk+1)*zr3
vh(jk-1,jk)=zr1
vh(jk,jk)=zr2
vh(jk+1,jk)=zr3
ENDDO
C
C Calculating for jk=knflev
C
zp1= qpeta(knflev-2)
zp2= qpeta(knflev-1)
zp3= qpeta(knflev)
zp = (qpres(knflev+1)+qpres(knflev))/2.0
zr1=(zp-zp2)*(zp-zp3)/(zp1-zp2)/(zp1-zp3)
zr2=(zp-zp1)*(zp-zp3)/(zp2-zp1)/(zp2-zp3)
zr3=(zp-zp2)*(zp-zp1)/(zp3-zp2)/(zp3-zp1)
c vmid(knflev)=pveta(knflev-2)*zr1+pveta(knflev-1)*zr2
c + +pveta(knflev)*zr3
vh(knflev-2,knflev)=zr1
vh(knflev-1,knflev)=zr2
vh(knflev,knflev)=zr3
C
end if
C
C* Initialize innovation operator arrays to zero
C
C ZH: Initial innovation model array (other than conversion constants)
C ZHP: Part of innovation operator not related to resolution
C
zh(:)=0.0D0
zhp(:)=0.0D0
C
C* Verify vertical range
C
ktot=1
C
if ((ptop.le.qpeta(1).and.pbtm.le.qpeta(1)).or.ptop.ge.pbtm*0.99.or.
& (ptop.ge.qpeta(knflev).and.pbtm.ge.qpeta(knflev))) then
ktot=0
return
end if
C
if (ptop.le.qpeta(1)*1.01) ptop=qpeta(1)*1.001
if (pbtm.gt.qpeta(knflev)*0.99) pbtm=qpeta(knflev)
C
C* Find the range of vertical levels over which to perform the integration
C and set innovation operator ZH over this range.
C
ilmin=1
ilmax=knflev
if (ptop.le.qpres(1)*1.01.and.pbtm.ge.qpeta(knflev)*0.99) then
C
C Total column integration part
C
do jk = 1,knflev
do j=max(1,jk-ivh),min(knflev,jk+ivh)
zh(jk)=zh(jk)+(qpres(j+1)-qpres(j))*vh(jk,j)
zhp(jk)=zhp(jk)+vh(jk,j)
end do
end do
C
else
C
C Partial column integration part (special treatment at boundaries)
C
C Identify analysis layer boundaries just within obs layer.
C
ilmin = CH_IGETMODLEV
(ptop, qpres, 'top', knflev+1)
ilmax = CH_IGETMODLEV
(pbtm, qpres, 'btm', knflev+1)
C
if (ilmin.eq.ilmax+1) then
C
C Entire obs layer within one analysis layer
C
j=ilmin
if (j.lt.3) j=3
if (j.gt.knflev) j=knflev
zp1=qpeta(j-2)
zp2=qpeta(j-1)
zp3=qpeta(j)
zp=(ptop+pbtm)/2.0
zr1=(zp-zp2)*(zp-zp3)/(zp1-zp2)/(zp1-zp3)
zr2=(zp-zp1)*(zp-zp3)/(zp2-zp1)/(zp2-zp3)
zr3=(zp-zp2)*(zp-zp1)/(zp3-zp2)/(zp3-zp1)
C
zh(j-2)=(pbtm-ptop)*zr1
zh(j-1)=(pbtm-ptop)*zr2
zh(j)=(pbtm-ptop)*zr3
zhp(j-2)=zr1
zhp(j-1)=zr2
zhp(j)=zr3
ilmin=j-2
ilmax=j
C
else
C
C Determine terms from the inner layers (excluding the lower and upper
C boundary layers when these layers not covering entire analyses layers)
C
if (pbtm.ge.qpeta(knflev)*0.99) then
ilmax2=knflev
else
ilmax2=ilmax-1
end if
if (ptop.le.qpres(1)*1.01) then
ilmin=1
ilmin2=ilmin
else
ilmin2=ilmin
end if
if (ilmin2.le.ilmax2) then
do jk = ilmin2,ilmax2
do j=max(1,jk-ivh),min(knflev,jk+ivh)
zh(jk)=zh(jk)+(qpres(j+1)-qpres(j))*vh(jk,j)
zhp(jk)=zhp(jk)+vh(jk,j)
end do
end do
end if
C
C Determine terms from the lower and upper boundary layers
C when these layers do not cover entire analyses layers.
C
if (pbtm.lt.qpeta(knflev)*0.99) then
C
j=ilmax+1
if (j.gt.knflev) j=knflev
if (j.lt.3) j=3
zp1=qpeta(j-2)
zp2=qpeta(j-1)
zp3=qpeta(j)
zp=(qpres(ilmax)+pbtm)/2.0
zr1=(zp-zp2)*(zp-zp3)/(zp1-zp2)/(zp1-zp3)
zr2=(zp-zp1)*(zp-zp3)/(zp2-zp1)/(zp2-zp3)
zr3=(zp-zp2)*(zp-zp1)/(zp3-zp2)/(zp3-zp1)
C
zh(j-2)=zh(j-2)+(pbtm - qpres(ilmax))*zr1
zh(j-1)=zh(j-1)+(pbtm - qpres(ilmax))*zr2
zh(j)=zh(j)+(pbtm - qpres(ilmax))*zr3
zhp(j-2)=zhp(j-2)+zr1
zhp(j-1)=zhp(j-1)+zr2
zhp(j)=zhp(j)+zr3
ilmax=j
C
end if
C
if (ptop.gt.qpres(1)*1.01) then
C
j=ilmin-1
if (j.lt.1) j=1
if (j.gt.knflev-2) j=knflev-2
zp1= qpeta(j)
zp2= qpeta(j+1)
zp3= qpeta(j+2)
zp = (qpres(ilmin)+ptop)/2.0
zr1=(zp-zp2)*(zp-zp3)/(zp1-zp2)/(zp1-zp3)
zr2=(zp-zp1)*(zp-zp3)/(zp2-zp1)/(zp2-zp3)
zr3=(zp-zp2)*(zp-zp1)/(zp3-zp2)/(zp3-zp1)
C
zh(j)=zh(j)+(qpres(ilmin)-ptop)*zr1
zh(j+1)=zh(j+1)+(qpres(ilmin)-ptop)*zr2
zh(j+2)=zh(j+2)+(qpres(ilmin)-ptop)*zr3
zhp(j)=zhp(j)+zr1
zhp(j+1)=zhp(j+1)+zr2
zhp(j+2)=zhp(j+2)+zr3
ilmin=j
if (ilmax.lt.j+2) ilmax=j+2
C
end if
if (ilmin.gt.ilmax-2) ilmin=ilmax-2
end if
end if
C
RETURN
END