!--------------------------------------- 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 --------------------------------------
program diag_bmatrix,23
!
! program: diag_bmatrix - Program to compute diagnostics of the B matrix
!
! Author : M. Buehner March, 2013
!
use mpivar_mod
use MathPhysConstants_mod
use controlVector_mod
use gridStateVector_mod
use gaussGrid_mod
use bmatrix_mod
use verticalCoord_mod
IMPLICIT NONE
#include "comct0.cdk"
#include "comfilt.cdk"
type(struct_gsv) :: statevector
type(struct_vco), pointer :: vco_anl => null()
real*8, pointer :: field(:,:,:)
real*4, allocatable :: ensemble(:,:,:,:)
real*8, allocatable :: gdmean(:,:,:)
real*8, allocatable :: gdstddev(:,:,:)
real*8, allocatable :: zes(:,:,:)
real*8, allocatable :: ztv(:,:,:)
real*8, allocatable :: zgz(:,:,:)
real*8, allocatable :: zhu(:,:,:)
integer fclos,fnom,fstouv,fstfrm,fstopc,nulfile,newdate,nstamp
integer ierr,iseed
integer jmem,jj,jni,jnj,jnk,nkgdim
integer idate,itime,nulnam
real*8 gasdev,zdum,rwtinv
character*128 filename
character(len=10) :: datestr
character(len=4) :: varnames(10)
integer :: nlons,nlats,nlevs,ilon,ilat,ilev,iloc,nvarnames,ivar
integer :: numperturbations,nrandseed,diagdate
integer :: oneobs_levs(100),oneobs_lons(100),oneobs_lats(100)
namelist /namdiag/numperturbations,nrandseed,diagdate,oneobs_levs,oneobs_lons,oneobs_lats
write(*,*) " -------------------------------------------"
write(*,*) " --- START OF MAIN PROGRAM DIAG_BMATRIX: ---"
write(*,*) " --- Diagnositcs of the B matrix ---"
write(*,*) " --- Part of VARGLB Revision number ",crevision
write(*,*) " -------------------------------------------"
! MPI, tmg initialization
call mpi_init
call tmg_init(mpi_myid, 'TMG_DIAG-BMATRIX' )
ierr = fstopc('MSGLVL','ERRORS',0)
! Set some global variables
nstepobsinc=1
nstepobs=1
! Set default values for namelist NAMDIAG parameters
diagdate = 2011020100
numperturbations = -1
nrandseed = 1
oneobs_levs(:)=-1
oneobs_lons(:)=-1
oneobs_lats(:)=-1
! Read the parameters from NAMDIAG
nulnam=0
ierr=fnom(nulnam,'./flnml','FTN+SEQ+R/O',0)
read(nulnam,nml=namdiag,iostat=ierr)
if(ierr.ne.0) call abort3d
('diag_bmatrix: Error reading namelist')
write(*,nml=namdiag)
ierr=fclos(nulnam)
nlevs=0
do jj=1,size(oneobs_levs)
if(oneobs_levs(jj).ge.1) nlevs=nlevs+1
enddo
nlons=0
do jj=1,size(oneobs_lons)
if(oneobs_lons(jj).ge.1) nlons=nlons+1
enddo
nlats=0
do jj=1,size(oneobs_lats)
if(oneobs_lats(jj).ge.1) nlats=nlats+1
enddo
! Decompose diagdate(yyyymmddhh) into idate(YYYYMMDD) itime(HHMMSShh)
! and calculate date-time stamp
idate = diagdate/100
itime = (diagdate-idate*100)*1000000
ierr = newdate(nstamp,idate,itime,3)
write(datestr,'(i10.10)') diagdate
write(*,*)' idate= ',idate,' time= ',itime
write(*,*)' date= ',diagdate,' stamp= ',nstamp
! Initialize variables of the model states
call gsv_setup
! Initialize dimensions of the gaussian grid (analysis grid)
call gaus_setup
! Initialize the vertical coordinate from the statistics file
call vco_SetupFromFile(vco_anl,'./glbcov',.true.)
! Allocate the statevector
call gsv_setVco(statevector,vco_anl)
call gsv_allocate(statevector,gaus_ni,gaus_nj,1,dateStamp=nstamp,mpi_local=.true.)
nkgdim = statevector%nk
! Setup the B matrix
call bmat_setup(vco_anl,nstamp)
! Allocate auxillary variables
allocate(zes(gaus_ni,vco_anl%nlev_M,gaus_nj))
allocate(ztv(gaus_ni,vco_anl%nlev_M,gaus_nj))
allocate(zgz(gaus_ni,vco_anl%nlev_M,gaus_nj))
allocate(zhu(gaus_ni,vco_anl%nlev_M,gaus_nj))
zes(:,:,:)=0.0d0
ztv(:,:,:)=0.0d0
zgz(:,:,:)=0.0d0
zhu(:,:,:)=0.0d0
if(nlevs.ge.1.and.nlons.ge.1.and.nlats.ge.1) then
write(*,*) '********************************************'
write(*,*) 'Compute columns of B matrix'
write(*,*) '********************************************'
write(*,*) 'number of levels =',nlevs
write(*,*) 'number of longitudes =',nlons
write(*,*) 'number of latitudes =',nlats
nvarnames=4
varnames(1)='TT '
varnames(2)='HU '
varnames(3)='UU '
varnames(4)='VV '
do ivar=1,nvarnames
if(mpi_myid.eq.0) then
filename = 'columnB_' // trim(varnames(ivar)) // '_' // datestr // '.fst'
nulfile = 0
ierr = fnom(nulfile,trim(filename),'RND',0)
if(ierr.ge.0)then
write(*,*)' fstouv nulfile= ',nulfile
ierr = fstouv(nulfile,'RND')
else
call abort3d
('diag_bmatrix: problem with file= ' // trim(filename))
endif
endif
iloc=0
do ilev=1,nlevs
do ilon=1,nlons
do ilat=1,nlats
iloc=iloc+1
call gsv_zero
(statevector)
field => gsv_getField3d
(statevector,varnames(ivar))
if(oneobs_lats(ilat).ge.statevector%myLatBeg.and.oneobs_lats(ilat).le.statevector%myLatEnd) then
field(oneobs_lons(ilon),oneobs_levs(ilev),oneobs_lats(ilat))=1.0d0
endif
cvm_vazx(:)=0.0d0
do jnj = statevector%myLatBeg,statevector%myLatEnd
rwtinv = real(statevector%ni,8)/gaus_rwt(jnj)
do jnk = 1,statevector%nlev_m
do jni = 1, statevector%ni
field(jni,jnk,jnj) = field(jni,jnk,jnj)*rwtinv
enddo
enddo
enddo
call bmat_sqrtBT
(cvm_vazx,cvm_nvadim,statevector)
call bmat_sqrtB
(cvm_vazx,cvm_nvadim,statevector)
write(*,*)'DIAG_BMATRIX: writing out the column of B, ilev,ilon,ilat=',ilev,ilon,ilat
call gsv_commMPIGlobal
(statevector)
if(mpi_myid.eq.0) call varout(nulfile,statevector,zes,ztv,zgz,zhu,iloc)
call gsv_deallocate
(statevector)
call gsv_allocate
(statevector,gaus_ni,gaus_nj,1,dateStamp=nstamp,mpi_local=.true.)
enddo
enddo
enddo
if(mpi_myid.eq.0) then
ierr = fstfrm(nulfile)
ierr = fclos(nulfile)
endif
enddo
endif ! if oneobs_????(1).ge.1
if(numperturbations.gt.1) then
write(*,*) '********************************************'
write(*,*) 'Compute the stddev from random perturbations'
write(*,*) '********************************************'
! Allocate the ensemble, mean and stddev
allocate(ensemble(gaus_ni,statevector%nk,statevector%myLatBeg:statevector%myLatEnd,numperturbations))
allocate(gdmean(gaus_ni,nkgdim,statevector%myLatBeg:statevector%myLatEnd))
allocate(gdstddev(gaus_ni,nkgdim,statevector%myLatBeg:statevector%myLatEnd))
iseed = abs(nrandseed)
zdum = gasdev
(-iseed)
gdmean(:,:,:) = 0.0d0
gdstddev(:,:,:) = 0.0d0
field => gsv_getField3d
(statevector)
do jmem = 1,numperturbations
write(*,*) ' computing member number= ',jmem
do jj = 1,cvm_nvadim
cvm_vazx(jj)=gasdev
(1)
enddo
call bmat_sqrtB
(cvm_vazx,cvm_nvadim,statevector)
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = 1,gaus_ni
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
ensemble(jni,jnk,jnj,jmem)=field(jni,jnk,jnj)
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
enddo
! Compute the ensemble mean
do jmem = 1,numperturbations
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = 1,gaus_ni
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
gdmean(jni,jnk,jnj) = gdmean(jni,jnk,jnj)+ensemble(jni,jnk,jnj,jmem)
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
enddo
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = 1,gaus_ni
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
gdmean(jni,jnk,jnj) = gdmean(jni,jnk,jnj)/real(numperturbations,8)
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
! Remove the ensemble mean from the ensemble
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jmem,jnj,jnk)
do jni = 1,gaus_ni
do jmem = 1,numperturbations
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
ensemble(jni,jnk,jnj,jmem)=ensemble(jni,jnk,jnj,jmem)-gdmean(jni,jnk,jnj)
enddo
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
! Compute the ensemble stddev
do jmem = 1,numperturbations
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = 1,gaus_ni
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
gdstddev(jni,jnk,jnj) = gdstddev(jni,jnk,jnj)+(ensemble(jni,jnk,jnj,jmem)**2)/real(numperturbations,8)
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
enddo
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = 1,gaus_ni
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
gdstddev(jni,jnk,jnj)=sqrt(gdstddev(jni,jnk,jnj))
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
if(mpi_myid.eq.0) then
filename = 'stddev_' // datestr // '.fst'
write(*,*)'DIAG_BMATRIX: writing out the stddev'
nulfile = 0
ierr = fnom(nulfile,trim(filename),'RND',0)
if(ierr.ge.0)then
write(*,*)' fstouv nulfile= ',nulfile
ierr = fstouv(nulfile,'RND')
else
call abort3d
('diag_bmatrix: problem with file= ' // trim(filename))
endif
endif
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = 1,gaus_ni
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
field(jni,jnk,jnj) = gdstddev(jni,jnk,jnj)
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
call gsv_commMPIGlobal(statevector)
if(mpi_myid.eq.0) then
call varout(nulfile,statevector,zes,ztv,zgz,zhu,0)
ierr = fstfrm(nulfile)
ierr = fclos(nulfile)
endif
call gsv_deallocate(statevector)
call gsv_allocate(statevector,gaus_ni,gaus_nj,1,dateStamp=nstamp,mpi_local=.true.)
if(mpi_myid.eq.0) then
filename = 'stddev_zonavg_' // datestr // '.fst'
write(*,*)'DIAG_BMATRIX: writing out the stddev_zonavg'
nulfile = 0
ierr = fnom(nulfile,trim(filename),'RND',0)
if(ierr.ge.0)then
write(*,*)' fstouv nulfile= ',nulfile
ierr = fstouv(nulfile,'RND')
else
call abort3d
('diag_bmatrix: problem with file= ' // trim(filename))
endif
endif
field => gsv_getField3d
(statevector)
field(:,:,:) = 0.0d0
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jni = 1,gaus_ni
do jnk = 1,nkgdim
field(1,jnk,jnj) = field(1,jnk,jnj) + (gdstddev(jni,jnk,jnj)**2)/real(gaus_ni,8)
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jnj = statevector%myLatBeg,statevector%myLatEnd
do jnk = 1,nkgdim
do jni = 2,gaus_ni
field(jni,jnk,jnj) = sqrt(field(1,jnk,jnj))
enddo
field(1,jnk,jnj) = sqrt(field(1,jnk,jnj))
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL
call gsv_commMPIGlobal(statevector)
if(mpi_myid.eq.0) then
call varout(nulfile,statevector,zes,ztv,zgz,zhu,0)
ierr = fstfrm(nulfile)
ierr = fclos(nulfile)
endif
call gsv_deallocate(statevector)
call gsv_allocate(statevector,gaus_ni,gaus_nj,1,dateStamp=nstamp,mpi_local=.true.)
deallocate(ensemble)
deallocate(gdmean)
deallocate(gdstddev)
endif ! if numperturbations.gt.1
! Deallocate arrays
call gsv_deallocate(statevector)
deallocate(zes)
deallocate(ztv)
deallocate(zgz)
deallocate(zhu)
! MPI, tmg finalize
call tmg_terminate(mpi_myid, 'TMG_DIAG-BMATRIX' )
CALL RPN_COMM_FINALIZE(ierr)
write(*,*) ' --------------------------------'
write(*,*) ' DIAG_BMATRIX ENDS'
write(*,*) ' --------------------------------'
end program diag_bmatrix