!-------------------------------------- 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 enkf_pturb,41
!
!** s/r enkf_pturb - Routine to prepare random perturbations for ENKF
!
use topLevelControl_mod
use mpi_mod
use mpivar_mod
use MathPhysConstants_mod
use controlVector_mod
use gridStateVector_mod
use gaussGrid_mod
use bmatrix_mod
use verticalCoord_mod
use horizontalCoord_mod
use LamAnalysisGrid_mod
use writeIncrement_mod
IMPLICIT NONE
type(struct_gsv) :: statevector
type(struct_vco), pointer :: vco_anl => null()
type(struct_hco), pointer :: hco_anl => null()
real(8), pointer :: field(:,:,:)
integer :: fclos,fnom,newdate,nstamp
integer :: ierr,iseed,status
integer :: ji,jj,jmem,jni,jnj,jnk,nkgdim,nlev_T
integer :: idate,itime,ndate,nulnam,cvDim_local
integer :: get_max_rss
integer :: LatPerPE, myLatBeg, myLatEnd
integer :: LonPerPE, myLonBeg, myLonEnd
real(8) :: gasdev,zdum
real(8), allocatable :: cvm_vazx_global(:)
real(8), allocatable :: gdmean(:,:,:)
real(8), allocatable :: zes_global(:,:,:)
real(8), allocatable :: ztv_global(:,:,:)
real(8), allocatable :: zgz_global(:,:,:)
real(8), allocatable :: zhu_global(:,:,:)
real(4), allocatable :: ensemble_r4(:,:,:,:)
character(len=10) :: cldate
character(len=3) :: clmember
character(len=25) :: clfiname
LOGICAL :: LREMOVE_MEAN
INTEGER :: NENKFMEM,NRANDSEED,NDATE_PTURB
NAMELIST /NAMENKF/NENKFMEM,NRANDSEED,NDATE_PTURB,LREMOVE_MEAN
write(*,'(/,' // &
'3(" *****************"),/,' // &
'14x,"-- START OF MAIN ENKF_PTURB --",/,' // &
'14x,"-- Generation of the isotropic perturbations --",/, ' // &
'14x,"-- VARGLB Revision number ",a," --",/,' // &
'3(" *****************"))') top_crevision
!
!- 0. MPI, tmg initialization
!
call mpi_initialize
call tmg_init(mpi_myid, 'TMG_ENKF-PTURB' )
!
!- 1. Set/Read values for the namelist NAMENKF
!
!- 1.1 Setting default values
NENKFMEM = 10
NRANDSEED = 1
NDATE_PTURB = 1900120100
LREMOVE_MEAN = .true.
!- 1.2 Read the namelist
nulnam=0
ierr=fnom(nulnam,'./flnml','FTN+SEQ+R/O',0)
read(nulnam,nml=namenkf,iostat=ierr)
if(ierr.ne.0) call abort3d
('enkf_pturb: Error reading namelist')
write(*,nml=namenkf)
ierr=fclos(nulnam)
ndate = NDATE_PTURB
write(cldate,'(I10)') ndate
!
!- 2. Initialization
!
!- 2.1 Decompose ndate(yyyymmddhh) into date(YYYYMMDD) time(HHMMSShh)
! calculate date-time stamp for postproc.ftn
idate = ndate/100
itime = (ndate-idate*100)*1000000
ierr = newdate(nstamp,idate,itime,3)
write(*,*)' idate= ',idate,' time= ',itime
write(*,*)' date= ',ndate,' stamp= ',nstamp
!- 2.2 Initialize variables of the model states
call gsv_setup
!- 2.3 Initialize the Analysis grid
if (mpi_myid == 0) write(*,*)''
if (mpi_myid == 0) write(*,*)' preproc: Set hco parameters for analysis grid'
call hco_SetupFromFile
( './analysisgrid', 'ANALYSIS', 'Analysis' ) ! IN
hco_anl => hco_Get
('Analysis')
if ( hco_anl % global ) then
!- Setup the global analysis grid metrics
call gaus_SetupFromHCO
(hco_anl) ! IN
else
!- Iniatilized the core (Non-Exteded) analysis grid
call hco_SetupFromFile
( './analysisgrid', 'COREGRID', 'AnalysisNonExt' ) ! IN
!- Setup the LAM analysis grid metrics
call lag_SetupFromHCO
( 'Analysis', 'AnalysisNonExt' ) ! IN
end if
call mpivar_setup_latbands
(hco_anl % nj, & ! IN
latPerPE, myLatBeg, myLatEnd ) ! OUT
call mpivar_setup_lonbands
(hco_anl % ni, & ! IN
lonPerPE, myLonBeg, myLonEnd ) ! OUT
!- 2.4 Initialize the vertical coordinate from the statistics file
call vco_SetupFromFile
( vco_anl,'./bgcov',.true.)
!- 2.5 Initialize the B_hi matrix
call bmat_setup
(hco_anl,vco_anl)
!
!- 3. Memory allocations
!
!- 3.1 Allocate the statevector
call gsv_setHco
(statevector,hco_anl)
call gsv_setVco
(statevector,vco_anl)
call gsv_allocate
(statevector,1,dateStamp=nstamp,mpi_local=.true.)
nkgdim = statevector%nk
allocate(ensemble_r4(myLonBeg:myLonEnd,statevector%nk,myLatBeg:myLatEnd,nenkfmem))
!- 3.2 Allocate auxillary variables
nlev_T = vco_getNumLev
(vco_anl,'TH')
allocate(zes_global(hco_anl%ni,nlev_T,hco_anl % nj))
allocate(ztv_global(hco_anl % ni,nlev_T,hco_anl % nj))
allocate(zgz_global(hco_anl % ni,nlev_T,hco_anl % nj))
allocate(zhu_global(hco_anl % ni,nlev_T,hco_anl % nj))
zes_global(:,:,:)=0.0d0
ztv_global(:,:,:)=0.0d0
zgz_global(:,:,:)=0.0d0
zhu_global(:,:,:)=0.0d0
allocate(gdmean(myLonBeg:myLonEnd,nkgdim,myLatBeg:myLatEnd),STAT=status)
if ( status /= 0 ) then
call abort3d
('enkf_pturb: PROBLEM WITH ALLOCATING OF GDMEAN')
endif
allocate(cvm_vazx_global(cvm_nvadim_mpiglobal))
!
!- 4. Compute an ensemble of random perturbations
!
write(*,*) '******************'
write(*,*) 'COMPUTE the mean of the random perturbations' &
,' of all the members'
iseed = ABS(nrandseed)
zdum = gasdev
(-iseed)
gdmean(:,:,:) = 0.0D0
field => gsv_getField3d
(statevector)
!- 4.1 Generate a (potentially) biased ensemble
do jmem = 1,NENKFMEM
write(*,*) ' computing member number= ',jmem
!- 4.1.1 Create a random control vector in spectral space
!- Global vector (same for each processors)
do jj = 1, cvm_nvadim_mpiglobal
cvm_vazx_global(jj) = gasdev
(1)
enddo
!- Extract only the subvector for this processor
call bmat_reduceToMPILocal
(cvm_vazx, & ! OUT
cvm_vazx_global, & ! IN
cvDim_local ) ! OUT
!- 4.1.2 Transform to control variables in physical space
call bmat_sqrtB
(cvm_vazx, cvm_nvadim, & ! IN
statevector ) ! OUT
!- 4.1.3 Running ensemble sum
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = myLonBeg, myLonEnd
do jnj = myLatBeg, myLatEnd
do jnk = 1, nkgdim
ensemble_r4(jni,jnk,jnj,jmem) = real(field(jni,jnk,jnj),4)
gdmean(jni,jnk,jnj) = gdmean(jni,jnk,jnj) + field(jni,jnk,jnj)
end do
end do
end do
!$OMP END DO
!$OMP END PARALLEL
end do
call gsv_deallocate
(statevector)
!- 4.2 Remove the ensemble mean
if ( LREMOVE_MEAN ) then
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = myLonBeg, myLonEnd
do jnj = myLatBeg, myLatEnd
do jnk = 1, nkgdim
gdmean(jni,jnk,jnj) = gdmean(jni,jnk,jnj) / real(NENKFMEM,8)
end do
end do
end do
!$OMP END DO
!$OMP END PARALLEL
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jmem,jnj,jnk)
do jni = myLonBeg, myLonEnd
do jmem = 1, NENKFMEM
do jnj = myLatBeg, myLatEnd
do jnk = 1, nkgdim
ensemble_r4(jni,jnk,jnj,jmem) = ensemble_r4(jni,jnk,jnj,jmem) - &
real(gdmean(jni,jnk,jnj),4)
end do
end do
end do
end do
!$OMP END DO
!$OMP END PARALLEL
end if
!- 4.3 Write the perturbations
do jmem = 1,NENKFMEM
write(*,*)
write(*,*) ' pre-processing for writing member number= ',jmem
call gsv_allocate
(statevector,1,dateStamp=nstamp,mpi_local=.true.)
field => gsv_getField3d
(statevector)
!$OMP PARALLEL
!$OMP DO PRIVATE (jni,jnj,jnk)
do jni = myLonBeg, myLonEnd
do jnj = myLatBeg, myLatEnd
do jnk = 1, nkgdim
field(jni,jnk,jnj) = ensemble_r4(jni,jnk,jnj,jmem)
end do
end do
end do
!$OMP END DO
!$OMP END PARALLEL
! mpiglobal result for 3D increment only on myid=0
call gsv_commMPIGlobal3D
(statevector)
write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
if (mpi_myid == 0) then
write(clmember,'(I3.3)') jmem
clfiname = './ptbm_'//trim(cldate)//'_'//trim(clmember)
write(*,*)'ENKF_PTURB: PROCESSING clfiname= ',clfiname
call writeIncrement
(clfiname,statevector,zes_global,ztv_global, & ! IN
zgz_global,zhu_global,nstamp) ! IN
write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
end if
call gsv_deallocate
(statevector)
end do
!
!- 5. Memory deallocations
!
deallocate(gdmean,STAT=status)
if ( status /= 0 ) then
call abort3d
('enkf_pturb: PROBLEM WITH DEALLOCATE OF GDMEAN')
endif
deallocate(zes_global)
deallocate(ztv_global)
deallocate(zgz_global)
deallocate(zhu_global)
deallocate(ensemble_r4)
deallocate(cvm_vazx_global)
!
!- 6. MPI, tmg finalize
!
call tmg_terminate(mpi_myid, 'TMG_ENKF-PTURB' )
CALL RPN_COMM_FINALIZE(ierr)
!
!- 7. Ending
!
write(*,*) ' --------------------------------'
write(*,*) ' ENKF_PTURB ENDS'
write(*,*) ' --------------------------------'
end program enkf_pturb