SUBROUTINE CH_RDSPLITOPER(poper, knstatlev,jvar,SPLITOPER, SPLITOPERD) 1,6
#if defined (DOC)
*
**s/r ch_rdsplitoper -Read in splitting operator spectral coefficients
* .
* Purpose
* . Read in coefficients for splitting operator for use in updating the
* unobserved species, i.e. Pux(Pxx)^-1
* . Vertical interpolation of operators
*
*Author : Y. Yang, based on S. Pellerin's subroutine rdspptot
*Revision:
*Arguments:
* in:
* poper : operator for vertical interpolation
* knstatlev : number of vertical levels of statistics array read in
* jvar : index of the correlation pairs
#endif
IMPLICIT NONE
*implicits
*
* Global variables
*
#include "comdim.cdk"
#include "comlun.cdk"
#include "comleg.cdk"
#include "comcorr.cdk"
#include "rpnstd.cdk"
#include "cominterp.cdk"
#include "comsplit.cdk"
#include "pardim.cdk"
*
* Local variables
*
integer knstatlev
real*8 poper(nflev,knstatlev)
integer jvar
c REAL*8 SPLITOPER(NFLEV, NFLEV, NJ)
c REAL*8 SPLITOPERD(NFLEV, NJ)
*
integer jn, jk1, jk2, ikey, ilen,jlat,jcol
character*4 clnomvar4
real*8 zopersrc,zspoper,zgroper,zoperecr
& ,zopermix, zspoperd, zgroperd
real*8 zopersrcd
real*8 zleg,zwork
real*8 hsqrt2
pointer (pxzspoper,zspoper(0:ntrunc,nflev,nflev))
pointer (pxzspoperd,zspoperd(0:ntrunc,nflev))
pointer (pxzgroper,zgroper(nj,nflev,nflev))
pointer (pxzgroperd,zgroperd(nj,nflev))
pointer (pxzleg,zleg(0:ntrunc,nj))
pointer (pxzoperecr,zoperecr(nflev,nflev,nj))
*
pointer (pxzopermix,zopermix(nflev,knstatlev))
*
pointer (pxzopersrc,zopersrc(knstatlev,knstatlev))
pointer (pxzopersrcd,zopersrcd(knstatlev))
real z4lev_trl(jpnflev)
integer ip1_all
integer iip1,iip2, iip3,iip1s_trl(jpnflev)
real*8 zlev_trl(jpnflev)
integer itrlnlev,ITRLGID
integer ip1_pak_trl,ip1_vco_trl
real*8 zmean_glb(nflev)
integer ii, jj, jlev, ikind, imode, ibrpstamp
real*8 zvhvar2d(1)
real*8, allocatable :: zmean_trial(:,:)
pointer (pxvhvar2d,zvhvar2d)
c pointer (pxmean_trial,zmean_trial)
character*1 clstring
integer vfstluk
character*4 cnomvar
c logical LSCAL_OPER
C ------------------------------------------------------
write(nulout,*) 'CH_RDSPLITOPER - Begin'
*
* Allocating local arrays
*
ilen = (ntrunc+1) * nflev * nflev
call hpalloc(pxzspoper,max(1,ilen),ierr,8)
ilen = nj * nflev * nflev
call hpalloc(pxzgroper,max(1,ilen),ierr,8)
ilen = nj * nflev
call hpalloc(pxzgroperd,max(1,ilen),ierr,8)
ilen = (ntrunc + 1) * nj
call hpalloc(pxzleg,max(1,ilen),ierr,8)
ilen = nj * nflev * nflev
call hpalloc(pxzoperecr,max(1,ilen),ierr,8)
*
ilen = nflev * knstatlev
call hpalloc(pxzopermix,max(1,ilen),ierr,8)
*
ilen = knstatlev * knstatlev
call hpalloc(pxzopersrc,max(1,ilen),ierr,8)
*
* for diagno operator
*
ilen = (ntrunc+1) * nflev
call hpalloc(pxzspoperd,max(1,ilen),ierr,8)
ilen = knstatlev
call hpalloc(pxzopersrcd,max(1,ilen),ierr,8)
*
* set up simple spectral transforms
*
C for transformation constant
C
hsqrt2=sqrt(2.0D0)/2.0D0
write(nulout,*) 'CH_RDSPLITOPER: set up simple spectral transforms'
call zlegpol(zleg,rmu,nj,ntrunc,ntrunc,nj)
*
if (LDIAGNO) then
*
* diagno-like operator, i.e. without cross-level correlations
*
ip1 = -1
ip3 = -1
idateo = -1
cletiket = 'S_SPLITD'//cvaranal(jvar)
cltypvar = 'X'
clnomvar4 = cvarunobs(jvar)
C
c read of spectral coefficients for theta
c
write(nulout,*) 'CH_RDSPLITOPER: Start reading in diagno operator from unit:'
& ,nulbgst
do jn = 0,ntrunc
ip2 = jn
ikey = vfstlir
(zopersrcd,nulsplitoper,ini,inj,ink
& ,idateo,cletiket,ip1,ip2,ip3,cltypvar,clnomvar4)
c
IF(IKEY .LT.0 ) THEN
CALL ABORT3D(NULOUT
& ,'CH_RDSPLITOPER: Problem with diagno stat file')
ENDIF
c
if (ini .ne. knstatlev) then
CALL ABORT3D(NULOUT
& ,'CH_RDSPLITOPER: diagno BG stat levels inconsitencies')
endif
c
c for spectral transform constant
c
zopersrcd(:)=zopersrcd(:)/hsqrt2
if(lvintbgstat) then
c
c Vertical interpolation O'm = Vmn On
c
call mxmaop1(poper,1,nflev,zopersrcd,1,knstatlev,zspoperd(jn,1)
& ,ntrunc+1,1,nflev,knstatlev,1)
else
do jk1 = 1,nflev
zspoperd(jn,jk1) = zopersrcd(jk1)
enddo
endif
*
enddo
*
c converting diagno operator in physical space
c
write(nulout,*) 'CH_RDSPLITOPER: converting diagno operator in physical space'
call zleginv2
(zgroperd,zspoperd,zleg,ntrunc,nj,nflev,nj,nflev
& ,ntrunc)
*
do jlat = 1, nj
do jk1 = 1, nflev
splitoperd(jk1,jlat) = zgroperd(jlat,jk1)
end do
end do
c
if ( kulsplitgd .gt. 0 ) then
ierr = fstprm(ikey,idateo,ideet,inpas,ini,inj,ink, inbits,
& idatyp,ip1,ip2,ip3,cltypvar,clnomvar,cletiket,clgrtyp,ig1
& ,ig2,ig3,ig4,iswa,ilength,idltf,iubc,iextr1,iextr2,iextr3)
c
ini = nflev
inj = nj
ink = 1
ip1 = 0
ip2 = 0
cletiket = 'G_SPLITD'//cvaranal(jvar)
c
ierr = vfstecr
(splitoperd, zwork, -inbits, kulsplitgd, idateo, ideet,
& inpas, ini, inj, ink, ip1, ip2, ip3, cltypvar, clnomvar4,
& cletiket,clgrtyp,ig1, ig2, ig3, ig4, idatyp, .true.)
c
endif
else !(LDIAGNO)
*
* non-diagno operator, i.e. like the P-TO-T operator with vertical
* correlations
*
write(nulout,*) 'CH_RDSPLITOPER: Start Reading in S_SPLITN from unit:'
& ,nulbgst
write(nulout,*) 'clnomvar4= ' ,clnomvar4, ' cletiket = ' , cletiket
ip1 = -1
ip2 = -1
ip3 = -1
idateo = -1
cletiket = 'S_SPLITN'//cvaranal(jvar)
cltypvar = 'X'
clnomvar4 = cvarunobs(jvar)
C
c read of spectral coefficients for splitting operator
c
do jn = 0,ntrunc
ip2 = jn
ikey = vfstlir
(zopersrc,nulsplitoper,ini,inj,ink
s ,idateo,cletiket,ip1,ip2,ip3,cltypvar,clnomvar4)
c
IF(IKEY .LT.0 ) THEN
CALL ABORT3D(NULOUT
& ,'CH_RDSPLITOPER: Problem with non-diagno operator stat file')
ENDIF
c
if (ini .ne. knstatlev .or. inj .ne. knstatlev) then
call abort3d(nulout
& ,'CH_RDSPLITOPER: non-diagno Operator stat levels inconsitencies')
endif
c
c for spectral transform constant
c
zopersrc(:,:)=zopersrc(:,:)/hsqrt2
c
if(lvintbgstat) then
c
c Vertical interpolation of splitting operator
c First Vertical interpolation: P'mn = Vmn Pnn
c
call mxmaop1(poper,1,nflev,zopersrc,1,knstatlev,zopermix,1
& ,nflev,nflev,knstatlev,knstatlev)
c
c Second Vertical interpolation: P''mm = P'mn (Vnm)
c
call mxmaop1(zopermix,1,nflev+1,poper,knstatlev,1,zspoper(jn,1
& ,1),ntrunc+1,(ntrunc+1)*(nflev+1),nflev+1,knstatlev,nflev
& )
c
else
do jk2 = 1,nflev
do jk1 = 1,nflev
zspoper(jn,jk1,jk2) = zopersrc(jk1,jk2)
enddo
enddo
endif
enddo
c
write(nulout,*) 'CH_RDSPLITOPER: converting operator into physical space'
ilen = nflev*nflev
call zleginv2
(zgroper,zspoper,zleg,ntrunc,nj,ilen,nj,ilen
& ,ntrunc)
c
do jlat = 1, nj
do jk2 = 1,nflev
do jk1 = 1, nflev
splitoper(jk1,jk2,jlat) = zgroper(jlat,jk1,jk2)
end do
end do
enddo
c
c store diagno elements for plotting
c
do jlat = 1, nj
do jk2 = 1,nflev
splitoperd(jk2,jlat)= splitoper(jk2,jk2,jlat)
end do
enddo
c ---------------------------------------------------
if ( kulsplitgd .gt. 0 ) then
ierr = fstprm(ikey,idateo,ideet,inpas,ini,inj,ink, inbits,
& idatyp,ip1,ip2,ip3,cltypvar,clnomvar4,cletiket,clgrtyp,ig1
& ,ig2,ig3,ig4,iswa,ilength,idltf,iubc,iextr1,iextr2,iextr3)
c
do jlat = 1, nj
do jk2 = 1,nflev
do jk1 = 1, nflev
zoperecr(jk1,jk2,jlat) = splitoper(jk1,jk2,nj-jlat+1)
end do
end do
enddo
c
ini = nflev
inj = nflev
ink = nj
ip1 = 0
ip2 = 0
cletiket = 'G_SPLITN'//cvaranal(jvar)
c
ierr = vfstecr
(zoperecr, zwork, -inbits, kulsplitgd, idateo,
& ideet, inpas, ini, inj, ink, ip1, ip2, ip3, cltypvar,
& clnomvar4, cletiket,clgrtyp,ig1, ig2, ig3, ig4, idatyp,
& .true.)
c
endif
endif !(LDIAGNO)
c
c scale the operator by the ratio of zonal mean of concentration to
C the global mean of unobserved variable
c
if (LSCAL_OPER) then
c
C Field parameters associated with unobserved variables
C
cletiket=''
clgrtyp=''
cltypvar=''
iip2=-1
iip3=-1
ibrpstamp=-1
call getfldprm(IIP1S_TRL,IIP2,IIP3,ITRLNLEV,CLETIKET,CLTYPVAR
& ,ITRLGID,cvarunobs(jvar),ibrpstamp,jpnflev,ninmpg_unobs
& ,nulout,ip1_pak_trl,ip1_vco_trl)
c
c Sort the levels encoded in IIP1S_TRL
c
c Decode the levels
C
imode = -1
ikind = ip1_vco_trl
do jlev = 1,itrlnlev
call VCONVIP( iip1s_trl(jlev), zlev_trl(jlev), ikind, imode,
& clstring,.false. )
enddo
c
call vsort(zlev_trl,itrlnlev)
c
c Encode iip1s_trl to match the sorted zlev_trl
C
imode = ip1_pak_trl
ikind = ip1_vco_trl
do jlev = 1,itrlnlev
z4lev_trl(jlev) = zlev_trl(jlev)
call VCONVIP( iip1s_trl(jlev), zlev_trl(jlev), ikind, imode,
& clstring,.false. )
enddo
c
c read trial field of unobserved to calculate zonal mean
c
cletiket=''
clgrtyp=''
cltypvar=''
iip2=-1
iip3=-1
cnomvar=cvarunobs(jvar)
ibrpstamp= -1
c
c get field information
c
ikey = FSTINF(ninmpg_unobs, INI, INJ, INK, ibrpstamp, cletiket,
& ip1_all(z4lev_trl(1),ip1_vco_trl), iip2, iip3
& ,cltypvar,cnomvar)
write(nulout,*) 'in ch_rdsplitoper, after first fstinf, reading trial fld unobserved, var = ', cvarunobs(jvar)
& , ' ikey= ' , ikey, ' ibrpstamp= ' , ibrpstamp , ' ip1= ' , ip1_all(z4lev_trl(1),ip1_vco_trl)
if (ikey.lt.0) then
write(nulout,*) 'problem in reading trial field for unobserved !!'
endif
c
c allocate space
c
call hpalloc(pxvhvar2d,ini*inj,ierr,8)
C call hpalloc(pxmean_trial, inj*nflev, ierr, 8)
allocate(zmean_trial(inj,nflev))
do jlev = 1,itrlnlev
ikey = FSTINF(ninmpg_unobs, INI, INJ, INK, ibrpstamp, cletiket,
& ip1_all(z4lev_trl(jlev),ip1_vco_trl), iip2, iip3
& ,cltypvar,cnomvar)
c write(nulout,*) 'in ch_rdsplitoper, after fstinf, reading trial fld unobserved, var = ', cvarunobs(jvar)
c & , ' ikey= ' , ikey, ' ibrpstamp= ' , ibrpstamp
if (ikey.ge.0) then
ikey = VFSTLUK(zvhvar2d,ikey, INI, INJ, INK)
zmean_trial(1:inj, jlev)=0.
do jj = 1, inj
do ii = 1, ini
zmean_trial(jj, jlev)= zmean_trial(jj, jlev)+zvhvar2d(ii+ (jj-1)*ini)
enddo
enddo
endif
c write(nulout,*) 'zmean_trial, jlev= ' , jlev
c write(nulout,*) (zmean_trial(jj, jlev), jj=1, inj,4)
enddo !jlev
do jlev = 1,itrlnlev
zmean_glb(jlev)= 0.
do jj = 1, inj
zmean_trial(jj, jlev) = zmean_trial(jj, jlev)/float(ini)
c zmean_glb(jlev)=zmean_glb(jlev)+ zmean_trial(jj, jlev)
zmean_glb(jlev)=zmean_glb(jlev)+ zmean_trial(jj, jlev)*zmean_trial(jj, jlev)
enddo
c zmean_glb(jlev)= zmean_glb(jlev)/ float(nflev)
zmean_glb(jlev)= sqrt (zmean_glb(jlev)/ float(nflev))
enddo
write(nulout,*) 'zmean_glb'
write(nulout,*) (zmean_glb(jlev), jlev=1,itrlnlev, 2)
if (LDIAGNO) then
c do jk1 = 1, nflev,2
c write(nulout,*) 'before scaling, splitoperd, jk1= ' ,jk1
c write(nulout,*) (splitoperd(jk1,jlat), jlat = 1, nj,4)
c end do
c write(nulout,*)'*********************************************************'
c write(nulout,*)'*********************************************************'
c do jk1 = 1, nflev,2
cc write(nulout,*) 'before scaling, zmean_trial, jk1= ' ,jk1
cc write(nulout,*) (zmean_trial(jlat, jk1), jlat = 1, nj,4)
c end do
do jlat = 1, nj
do jk1 = 1, nflev
splitoperd(jk1,jlat) = splitoperd(jk1,jlat)*zmean_trial(jlat, jk1)/zmean_glb(jk1)
cc splitoperd(jk1,jlat) = splitoperd(jk1,jlat)*zmean_trial(jlat, jk1)
end do
end do
c write(nulout,*)'*********************************************************'
c write(nulout,*)'*********************************************************'
c do jk1 = 1, nflev,2
c write(nulout,*) 'after scaling, splitoperd, jk1= ' ,jk1
c write(nulout,*) (splitoperd(jk1,jlat), jlat = 1, nj,4)
c end do
else
do jlat = 1, nj
do jk2 = 1,nflev
do jk1 = 1, nflev
splitoper(jk1,jk2,jlat) = splitoper(jk1,jk2,jlat)*zmean_trial(jlat, jk1)/zmean_glb(jk1)
end do
end do
enddo
endif
deallocate(zmean_trial)
call hpdeallc(pxvhvar2d,ierr,1)
endif ! LSCAL_OPER
c
c write out splitting operator into ascii file
c
open(unit=666,form='formatted',
+ file='./split_operator.asc')
write(666, *) cvaranal(jvar),'--', cvarunobs(jvar)
write(666, *) ' LSCAL_OPER= ' , LSCAL_OPER
write(666, *) '**********************************************'
write(666, *) 'splitting operator'
write(666, *) '**********************************************'
do jk1=1, nflev
write(666, 400)(splitoperd(jk1,jlat), jlat= nj, 1 ,-1)
enddo
400 format(2x, 7(g11.5, 3x))
c
* 9. Deallocate local arrays
c
call hpdeallc(pxzspoper,ierr,1)
call hpdeallc(pxzgroper,ierr,1)
call hpdeallc(pxzgroperd,ierr,1)
call hpdeallc(pxzleg,ierr,1)
call hpdeallc(pxzoperecr,ierr,1)
call hpdeallc(pxzopermix,ierr,1)
call hpdeallc(pxzopersrc,ierr,1)
call hpdeallc(pxzspoperd,ierr,1)
call hpdeallc(pxzopersrcd,ierr,1)
c call hpdeallc(pxmean_trial,ierr,1)
*
ierr=fstfrm(kulsplitgd)
close(666)
write(nulout,*)'DONE in CH_RDSPLITOPER'
c
return
end