!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer,
! version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer
!version 3 or (at your option) any later version that should be found at:
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software;
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec),
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
!
subroutine ptotla_1(kulstat,koutfile,ldhelm,ldfplane,ldtb_psi,ldcoriol_one) 2,18
#if defined (DOC)
*
***s/r ptotla_1 - Statistical Estimation of A where:
* vec(T Ps) = A vec(P_b) + vec(T' Ps')
* Identical setup as correlation calculations
*
*Author : Luc Fillion - ARAM/MSC - 7 Apr 2005 Limited-Area version.
*Revision:
* Luc Fillion - ARAM/EC - Jun 2008 - Adapt with GD1 for initgdla.ftn call.
* Luc Fillion - ARAM/EC - 28 May 2010 - Introduce argument ldfilt into initgdla.ftn
*
*Arguments: KULSTAT logical unit number for error sample forecast files.
*
#endif
IMPLICIT NONE
*implicits
#include "taglam4d.cdk"
#include "pardim.cdk"
#include "comdim.cdk"
#include "comlun.cdk"
#include "comcst.cdk"
#include "comgem.cdk"
#include "comgemla.cdk"
#include "comcorr.cdk"
#include "comsp.cdk"
#include "comgd0.cdk"
#include "comsp1.cdk"
#include "comgd1.cdk"
#include "comgdpar.cdk"
#include "comcse1.cdk"
#include "comgrd_param.cdk"
#include "comgrd.cdk"
*
logical ldhelm,ldfplane,ldtb_psi,ldcoriol_one
INTEGER KULSTAT,koutfile
!
integer ji,jj,ifois,icase
! integer isave_ihh,isave_ifstrun
data ifois/0/
INTEGER JENS, IENS, inbens, JK1, JK2, JLA
INTEGER IERR, JFILE, JK, ILON, ILEN, JB, NLATBAND
!
INTEGER FNOM, FSTOUV, FSTFRM, FCLOS, FSTPRM, FSTINF, FSTINL
!
! RPN Standard files parameters
!
INTEGER INI, INJ, INK, INPAS, INBITS, IDATYP, IDEET,
+ IP1, IP2, IP3, IG1, IG2, IG3, IG4, ISWA, ILENGTH, IDLTF,
+ IUBC, IEXTR1, IEXTR2, IEXTR3
INTEGER ILISTE(100), IDATE(100), IDATV(100), IDIMAX, INFON, IFSTRUN, IHH
!
INTEGER IBND1,IBND2,JPNLATBND
!
REAL*8 DHEURES
CHARACTER*1 CLTYPVAR, CLGRTYP, clflt,clgrid
CHARACTER*2 CLNOMVAR
CHARACTER*8 CLETIKET
!
logical ldopc,llfilt
REAL*8 ZFACT,ZMAXI,ZWT
real*8 zpb(ni,nflev,nj),zgdpsi(ni,nflev,nj),zgdchi(ni,nflev,nj)
real*8 z2d(ni,nj)
real*8 z2d_in(mni_in,mnj_in)
real*8 zgdes(ni,nflev,nj),zgdgz(ni,nflev,nj)
real*8 zvort(ni,nflev,nj),zdiv(ni,nflev,nj)
REAL*8 ZM1(NFLEV+1,NFLEV,nj), ZM2(NFLEV,NFLEV,nj)
REAL*8 ZPTOT(NFLEV,NFLEV)
REAL*8 ZM2INV(NFLEV,NFLEV), ZWORK(NFLEV*NFLEV), ZDET, ZEPS
REAL*8 ZCHIPSI(NFLEV,NJ), ZPSIPSI(NFLEV,NJ)
!
real*8 zmeangdpsi(ni,nflev,nj)
real*8 zsavut0(ni,nflev,nj)
real*8 zwork2d(ni,nj)
real*8 zwrksp(nla,2,nflev)
integer inip1,injp1
integer vfstlir,vfstecr,IPAK, IDATEO,IULPTOT
real*8 zx8(ni),zy8(nj)
!
EXTERNAL FNOM, FSTOUV, FSTFRM, FCLOS, FSTPRM, FSTINF,FSTINL
!
!!
write(nulout,*) 'ptotla_1: BEGIN'
!
llfilt = .false.
if(lflt_low) then
llfilt = .true.
clflt = 'L'
else if(lflt_high) then
llfilt = .true.
clflt = 'H'
endif
!
WRITE(NULOUT,FMT=9000)
9000 FORMAT(3(/,3x,80('.')),//
S ,4x,' ptotla_1- Estimation of P_to_T Operator for LAM4D',//)
!
! Initialize a few constants
!
inip1 = ni+1
injp1 = nj+1
!
!*1. Initialize Arrays
! -----------------
!
zm1(:,:,:) = 0.0
zm2(:,:,:) = 0.0
zptot(:,:) = 0.0
ZCHIPSI(:,:) = 0.0
ZPSIPSI(:,:) = 0.0
THETA(:,:) = 0.0
!
! allocate space for accumulators
!
! call stddall
!
!*2. Access the increments of PSI and (T,lnPs) from a set of files
! (loop on the files)
! -------------------------------------------------------------
!
IDIMAX = 100
!
! call getmeangdla(nulbgst) ! read from file: precomputed mean of fields
!
DO 201 JFILE = 1, NFLSTAT
!
call openinc
(kulstat,jfile)
!
!* 2.1 Find how many cases there are to be treated
!
IP1 = -1
IP2 = -1
IP3 = -1
CLNOMVAR = CFSTVAR(1)
IF (CLNOMVAR.EQ.'P0') THEN
IP1 =0
ELSE
IP1 =12000
ENDIF
WRITE(NULOUT,*)
IERR = FSTINL (KULSTAT,INI,INJ,INK
S ,-1,CETIKETN,IP1,IP2,IP3,' '
S ,CLNOMVAR,ILISTE,INFON,IDIMAX)
WRITE(NULOUT,9210)INFON
9210 FORMAT(//,4X,"ENSEMBLE OF ",I4," DIFFERENT INCREMENTS TYPES")
IF(INFON.EQ.0) THEN
WRITE(NULOUT,*)' THIS FILE IS EMPTY.
$ CHECK THE SELECTION CRITERIA'
CALL ABORT3D
(NULOUT,'ptotla_1: PROBLEM WITH FSTINL')
END IF
IENS = INFON
!
!* 2.2 Get all the dates at which increments are available
!
inbens = 0
DO JENS = 1, IENS
IERR = FSTPRM(ILISTE(JENS),IDATE(JENS),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)
!
DHEURES = DBLE(INPAS*IDEET/3600)
CALL INCDATR(IDATV(JENS),IDATE(JENS),SNGL(DHEURES))
CALL NEWDATE(IDATV(JENS),IFSTRUN,IHH,-3)
! if(jens.eq.1) then
! isave_IFSTRUN = IFSTRUN
! isave_IHH = IHH
! end
! if(IFSTRUN.eq.isave_IFSTRUN.and.IHH.eq.isave_IHH) inbens=inbens+1
WRITE(NULOUT,9320)JENS, IFSTRUN,IHH
END DO
9320 FORMAT(5X,"Case No. ",I3,5x,"Date and time: ",I10,5x,I8)
!
! iens = inbens
!ping WRITE(NULOUT,9210)iens
!ping 9210 FORMAT(//,4X,"ENSEMBLE OF ",I4," INCREMENTS")
WRITE(NULOUT,9310)iens
9310 FORMAT(//,4X,"ENSEMBLE OF ",I4," INCREMENTS")
!
IF(NENSEMBLE.EQ.0) THEN
NDATESTAT = IDATE(1)
END IF
!
CTYPVARN = ' '
CETIKETN = CLETIKET
!
!* 2.3 Loop on the ensemble
!
DO 231 JENS = 1, IENS
!
! Get the increment in grid-point form
!
if(lmcstats) then
NSTAMPN = -1
icase=jens ! i.e. will use IP3 as a search parameter and ignore the date in current file since all same
else
NSTAMPN = IDATE(JENS) ! i.e. will use the current date of validity of the current error sample in standard file.
icase = -1 ! ignore IP3 as a search parameter in vfstlir
endif
!
call geterr
(kulstat,'G','N',icase)
!
! Estimation of P_to_T matrix (A)
!
call transfer
('GD01')
ldopc = .true.
if(lpsifromglb.or.lpsifromlam) ldopc=.false.
call initgdla
(zvort,zdiv,zgdpsi,zgdchi,'U',ldopc,.false.)
call transfer
('GD10')
!
if(lpsifromlam) then ! get PSI from input file kulstat
do jk=1,nflev
ierr = vfstlir
(z2d,kulstat,ni,nj,1,NSTAMPN,
& 'PSI_LAM ',NIP1(JK),-1,-1,'E','PP')
if(ierr.lt.0) then
call abort3d
(nulout,'ptotla_1: Problem reading PSI field')
endif
do jj=1,nj
do ji=1,ni
zgdpsi(ji,jk,jj) = z2d(ji,jj)
enddo
enddo
ierr = vfstlir
(z2d,kulstat,ni,nj,1,NSTAMPN,
& 'CHI_LAM ',NIP1(JK),-1,-1,'E','CC')
if(ierr.lt.0) then
call abort3d
(nulout,'ptotla_1: Problem reading CHI field')
endif
do jj=1,nj
do ji=1,ni
zgdchi(ji,jk,jj) = z2d(ji,jj)
enddo
enddo
enddo
else if(lpsifromglb) then ! get PSI from input file kulstat
do jk=1,nflev
ierr = vfstlir
(z2d_in,kulstat,mni_in,mnj_in,1,NSTAMPN,
& 'LAM4D ',NIP1(JK),-1,-1,'E','PP')
if(ierr.lt.0) then
call abort3d
(nulout,'ptotla_1: Problem reading PSI field')
endif
do jj=1,mnj_in
do ji=1,mni_in
zgdpsi(ji,jk,jj) = z2d_in(ji,jj)
enddo
enddo
enddo
call mach3
(zgdpsi,ni,nj,nflev,inip1,injp1)
call setmean
(zgdpsi,0.0,nflev)
endif
!
if(llfilt) then
write(nulout,*) 'ptotla_1: **************************************'
write(nulout,*) 'ptotla_1: PP error sample is spectrally filtered'
write(nulout,*) 'ptotla_1: **************************************'
call gdtruncr
(zgdpsi,zwrksp,'T',mflt_trunc,clflt,.false.,nflev)
else
write(nulout,*) 'ptotla_1: NO FILTER applied to PP error sample'
endif
!
if(ldtb_psi) then
clgrid = 'S'
if(lpsifromglb) clgrid = 'S'
call linbal_la
(zpb,zgdpsi,ldfplane,ldcoriol_one,clgrid)
else
do jk=1,nflev
do jj=1,nj
do ji=1,ni
zpb(ji,jk,jj)=zvort(ji,jk,jj)
enddo
enddo
enddo
endif
!
DO jj = 1, nj
ZFACT = 1.0
DO ji = 1, ni
DO JK1 = 1, NFLEV+1
DO JK2 = 1, NFLEV
IF(JK1.LE.NFLEV) THEN
ZM1(JK1,JK2,jj) = ZM1(JK1,JK2,jj) +
& ZFACT * TT0(ji,JK1,jj) * zpb(ji,JK2,jj)
ELSE
ZM1(JK1,JK2,jj) = ZM1(JK1,JK2,jj) +
& ZFACT * GPS0(ji,1,jj) * zpb(ji,JK2,jj)
endif
enddo ! jk2 loop
enddo ! jk1 loop
enddo ! ji loop
enddo ! jj loop
!
! update ZM2 = sum_over_t_x_y[vec(P_b) vec(P_b)^T]
!
DO jj = 1, nj
ZFACT = 1.0
DO ji = 1, ni
DO JK1 = 1, NFLEV
DO JK2 = 1, NFLEV
ZM2(JK1,JK2,jj) = ZM2(JK1,JK2,jj) +
+ ZFACT * zpb(ji,JK1,jj) * zpb(ji,JK2,jj)
enddo ! jk2 loop
enddo ! jk1 loop
enddo ! ji loop
enddo ! jj loop
231 continue ! loop on jens
!
NENSEMBLE = NENSEMBLE + IENS
WRITE(NULOUT,9370) IENS, NENSEMBLE
9370 FORMAT(5X,I4," cases have been processed",
S 5x,"Current size of the ensemble: ",I4)
!
998 continue
IERR = FSTFRM (KULSTAT)
IERR = FCLOS (KULSTAT)
!
201 continue ! loop on jfile
!
!*3. Compute A = ZM1*inv(ZM2)
! ------------------------
!
! seem to need to scale ZM2 before calling MINV (otherwise overflow error)
! scale by maximum value (zmaxi) - rescale in final calculation
!
do jj = 1, nj
ZMAXI = 0.0
DO JK1 = 1, NFLEV
DO JK2 = 1, NFLEV
IF(ZM2(JK1,JK2,jj).GT.ZMAXI) ZMAXI = ZM2(JK1,JK2,jj)
ENDDO
ENDDO
!
DO JK1 = 1, NFLEV
DO JK2 = 1, NFLEV
ZM2INV(JK1,JK2) = ZM2(JK1,JK2,jj)/ZMAXI
ENDDO
ENDDO
!
ZEPS = RZERO
CALL MINV
(ZM2INV,NFLEV,NFLEV,ZWORK,ZDET,ZEPS,0,1)
!
call zero
(nflev*nflev,zptot)
!
DO JK1 = 1, NFLEV+1
DO JK2 = 1, NFLEV
DO JK = 1, NFLEV
PTOT(JK1,JK2,jj) = PTOT(JK1,JK2,jj) +
$ ZM1(JK1,JK,jj) * ZM2INV(JK,JK2) / ZMAXI
IF(JK1.LE.NFLEV) THEN
ZPTOT(JK1,JK2) = ZPTOT(JK1,JK2) +
$ ZM1(JK1,JK,jj) * ZM2INV(JK,JK2) / ZMAXI
endif
ENDDO
ENDDO
ENDDO
enddo ! end loop on jj
!
DO JK2 = 1, NFLEV
write(nulout,*) 'ptotla_1: jk2, PTOT(nflev+1,JK2,1)=',
& jk2, PTOT(nflev+1,JK2,1)
enddo
!
! call outhoriz2d(zptot,'ptot.od ','PT',1,
! & 1,nflev,1,nflev,nflev,nflev,1)
!
write(nulout,*) 'ptotla_1: END'
!
RETURN
END