!-------------------------------------- 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 sugomobs(columng,columnhr,lobsSpaceData,indexAnalysis) 4,124
!
! s/r sumgomobs
!
! Author : S. Pellerin ARMA/AES Nov. 1999
!
! Purpose: Fill in COLUMNG and COLUMNHR with trial profiles
!
!Arguments: COLUMNG, COLUMNHR
!
use EarthConstants_mod
use MathPhysConstants_mod
use mpivar_mod
use horizontalCoord_mod
use timeCoord_mod
use columnData_mod
use obsSpaceData_mod
use gridStateVector_mod
use timeCoord_mod
, only: tim_getDatestamp
use WindRotation_mod
implicit none
type(struct_columnData) :: columng,columnhr
type(struct_obs) :: lobsSpaceData
integer :: indexAnalysis
type(struct_vco), pointer :: vco_anl, vco_trl
type(struct_hco), pointer :: hco_anl
integer ezgprm,fnom,fclos,fstouv,fstfrm
integer ezsetopt,gdxyfll,vezgdef, gdllfxy
integer jlev,jobs,ierr,iset,jstep,jlatlontile
integer ini, inj,ink,iig1,iig2,iig3,iig4,jvar
integer itrlnlev
integer idata,idatend,jdata
character*1 clgrtyp
character*2 cltypvar
character*12 cletiket
real*8, allocatable :: varInterphr_T(:,:),varInterphr_M(:,:),varInterphr_VV(:,:)
integer ip1_pak_trl,ip1_vco_trl
integer nlv_T,nlv_M
integer, parameter :: jpnflev = 200
integer itrlgid,iip1s(jpnflev),iip2,iip3
integer, allocatable :: idate(:),itime(:)
integer :: newdate,nstepanltime
integer, allocatable :: nobsgid(:) ! (nstepobs) grid id for ezscint corresponding to stepobs bin
integer, allocatable :: notag(:,:) ! (nobtot,nstepobs) obs tag associated to observations of each bin
integer, allocatable :: nobs(:),nobs_maxmpiglobal(:) ! number of headers for each stepobs bin
integer, allocatable :: nobsgid_mpiglobal(:,:),nobs_mpiglobal(:,:)
integer, allocatable :: datestamplist(:)
integer :: numColumn_maxmpiglobal
real :: lat_r4, lon_r4, lat_deg_r4, lon_deg_r4, xpos_r4, ypos_r4, xposLowerBoundAnl_r4, xposUpperBoundAnl_r4
real*8 :: lat_r8,lon_r8, ypos_r8, xpos_r8, lat_rot, lon_rot
character(len=2) :: flnum
character(len=5) :: flnum2
character(len=128) :: trialfile
integer, allocatable :: nultrl(:)
integer :: nultrl2
logical :: trialExists
real*8 :: zig1,zig2,zig3,zig4,stepObsIndex
real*8, allocatable :: dlonfld(:), dlatfld(:)
real*8, allocatable :: dlonfld_mpiglobal(:,:), dlatfld_mpiglobal(:,:)
integer :: ig1obs,ig2obs,ig3obs,ig4obs
integer :: status,Vcode_trl,Vcode_anl
real*8, pointer :: column_ptr(:) => null()
write(*,*) ' '
write(*,*) '-------- ENTERING SUGOMOBS ---------'
write(*,*) ' '
if(mpi_myid.eq.0) write(*,*) 'nstepobs=',tim_nstepobs
call tmg_start(10,'SUGOMOBS')
!
! Ensure that all trial field files exist and
! open all trial field files (assume 1 file per time step)
!
allocate(nultrl(tim_nStepObs))
nultrl(:)=0
if(indexAnalysis.gt.0) then
write(flnum2,'(I4.4)') (indexAnalysis-1)
flnum2='_' // trim(flnum2)
else
flnum2=''
endif
do jstep = 1, tim_nStepObs
write(flnum,'(I2.2)') jstep
trialfile='./trlm_'//trim(flnum)//trim(flnum2)
inquire(file=trim(trialfile),exist=trialExists)
if(.not.trialExists) then
write(*,*) 'File missing=',trialfile
call abort3d
('SUGOMOBS:DID NOT FIND A TRIAL FIELD FILE')
else
ierr=fnom(nultrl(jstep),trim(trialfile),'RND+OLD+R/O',0)
ierr=fstouv(nultrl(jstep),'RND+OLD')
write(*,*) 'ITRIAL - File :', trialfile
write(*,*) ' opened as unit file ',nultrl(jstep)
end if
enddo
!
! Vertical coordinate parameters
!
vco_anl => col_getVco
(columng)
vco_trl => col_getVco
(columnhr)
nlv_M = vco_getNumLev
(vco_trl,'MM')
nlv_T = vco_getNumLev
(vco_trl,'TH')
if(mpi_myid.eq.0) write(*,*)'sugomobs:niv thermo:',nlv_T,' momentum',nlv_M
if(mpi_myid.eq.0) write(*,*)'sugomobs:zptophr,zprefhr,zrcoefhr ', &
vco_trl%dpt_T,vco_trl%dprf_T,vco_trl%drcf1
status = vgd_get(vco_trl%vgrid,key='ig_1 - vertical coord code',value=Vcode_trl)
status = vgd_get(vco_anl%vgrid,key='ig_1 - vertical coord code',value=Vcode_anl)
if(mpi_myid.eq.0) write(*,*) 'sugomobs: Vcode_trl= ',Vcode_trl, &
' Vcode_anl= ',Vcode_anl
if(Vcode_trl.ne.5001.and.Vcode_trl.ne.5002) call abort3d
('sugomobs: invalid vertical coord for background state!')
if(Vcode_anl.ne.5001.and.Vcode_anl.ne.5002) call abort3d
('sugomobs: invalid vertical coord for analysis grid!')
!
! Compute the maximum number of columns over all processors (lat-lon tiles)
!
call rpn_comm_allreduce(col_getNumCol
(columng),numColumn_maxmpiglobal,1, &
"MPI_INTEGER","MPI_MAX","GRID",ierr)
!
! Allocate trial field column object and other local arrays
!
if(col_getNumCol
(columng).gt.0) then
allocate(notag(col_getNumCol
(columng),tim_nStepObs))
allocate(varInterphr_T(nlv_T,col_getNumCol
(columng)))
allocate(varInterphr_M(nlv_M,col_getNumCol
(columng)))
allocate(varInterphr_VV(nlv_M,col_getNumCol
(columng)))
varInterphr_T(:,:)=0.0d0
varInterphr_M(:,:)=0.0d0
varInterphr_VV(:,:)=0.0d0
endif
allocate(dlonfld(numColumn_maxmpiglobal))
allocate(dlatfld(numColumn_maxmpiglobal))
allocate(dlonfld_mpiglobal(numColumn_maxmpiglobal,mpi_nprocs))
allocate(dlatfld_mpiglobal(numColumn_maxmpiglobal,mpi_nprocs))
allocate(nobsgid(tim_nStepObs))
allocate(nobs(tim_nStepObs))
allocate(nobs_maxmpiglobal(tim_nStepObs))
allocate(datestamplist(tim_nStepObs))
allocate(idate(tim_nStepObs))
allocate(itime(tim_nStepObs))
allocate(nobsgid_mpiglobal(tim_nStepObs,mpi_nprocs))
allocate(nobs_mpiglobal(tim_nStepObs,mpi_nprocs))
!
! Computing date and time of step obs for error message
!
call getstamplist
(datestamplist,tim_nStepObs,tim_getDatestamp
())
do jstep = 1,tim_nStepObs
ierr = newdate(datestamplist(jstep),idate(jstep),itime(jstep),-3)
if(mpi_myid.eq.0) write(*,*) 'sugomobs: datestamplist=',jstep,datestamplist(jstep)
if(datestamplist(jstep) == tim_getDatestamp
()) nstepanltime = jstep
end do
!
! Setting degree of horizontal interpolations
!
ierr = ezsetopt('INTERP_DEGREE', 'LINEAR')
!ierr = ezsetopt('INTERP_DEGREE', 'NEAREST')
!
!- Get the Analysis Grid structure
!
hco_anl => hco_Get
('Analysis')
if ( hco_anl % global ) then
xposLowerBoundAnl_r4 = - huge(1.0) ! no limit since grid is global (periodic)
xposUpperBoundAnl_r4 = + huge(1.0) ! no limit since grid is global (periodic)
else
xposLowerBoundAnl_r4 = 1.0
xposUpperBoundAnl_r4 = real(hco_anl % ni)
end if
!
! The following code replaces the subroutine suobsgid
!
nobs(:) = 0
do jvar=1,vnl_numvarmax2D
if(gsv_varExist
(vnl_varNameList2D(jvar))) exit
end do
if(mpi_myid.eq.0) write(*,*) 'sugomobs: first 2d variable=',vnl_varNameList2D(jvar),jvar
do jstep = 1,tim_nStepObs
!
!- Get horizontal grid parameters to be used to test grid bounds
!
call getfldprm2
(IIP1S,IIP2,IIP3,ITRLNLEV,CLETIKET,CLTYPVAR, &
ITRLGID,vnl_varNameList2D(jvar),datestamplist(jstep),jpnflev, &
nultrl(:),ip1_pak_trl,ip1_vco_trl,tim_nStepObs, &
nultrl2)
if (itrlnlev <= 0 ) then
call abort3d
('SUGOMOBS:Problem with background file')
end if
ierr = ezgprm(itrlgid,clgrtyp,ini,inj,iig1,iig2,iig3,iig4)
dlonfld(:)=0.0d0
dlatfld(:)=0.0d0
do jobs=1, obs_numheader
(lobsSpaceData)
call getStepObsIndex
(stepObsIndex,tim_getDatestamp
(), &
obs_headElem_i
(lobsSpaceData,OBS_DAT,jobs), &
obs_headElem_i
(lobsSpaceData,OBS_ETM,jobs),tim_nstepobs)
! check if obs is outside of assimilation window when jstep = 1
if(jstep.eq.1 .and. &
(stepobsIndex.lt.1.0 .or. stepObsIndex.gt.real(tim_nstepobs,8)) ) then
write(*,*) 'sugomobs: Observation time outside assimilation window: ', &
obs_headElem_i
(lobsSpaceData,OBS_DAT,jobs),obs_headElem_i
(lobsSpaceData,OBS_ETM,jobs)
! put the obs in the first time bin (it has to go somewhere!)
stepObsIndex=1.0d0
! flag it as out of time domain and turn off its assimilation flag
idata = obs_headElem_i
(lobsSpaceData,OBS_RLN,jobs)
idatend = obs_headElem_i
(lobsSpaceData,OBS_NLV,jobs) + idata -1
do jdata = idata, idatend
call obs_bodySet_i
(lobsSpaceData,OBS_ASS,JDATA, 0)
end do
call obs_headSet_i
(lobsSpaceData,OBS_ST1,jobs, &
ibset( obs_headElem_i
(lobsSpaceData,OBS_ST1,jobs), 05))
end if
if ( nint(stepObsIndex) == jstep ) then
nobs(jstep) = nobs(jstep) + 1
notag(nobs(jstep),jstep) = jobs
!- Get LatLon of observation location
lat_r8=obs_headElem_r
(lobsSpaceData,OBS_LAT,jobs)
lon_r8=obs_headElem_r
(lobsSpaceData,OBS_LON,jobs)
lat_r4=real(lat_r8)
lon_r4=real(lon_r8)
if (lon_r4.lt.0.0 ) lon_r4 = lon_r4 + 2.0*MPC_PI_R4
if (lon_r4.ge.2.*MPC_PI_R4) lon_r4 = lon_r4 - 2.0*MPC_PI_R4
lat_deg_r4=lat_r4 * MPC_DEGREES_PER_RADIAN_R4 ! Radian To Degree
lon_deg_r4=lon_r4 * MPC_DEGREES_PER_RADIAN_R4
!
!- Find the position in the analysis grid
!
ierr = gdxyfll( hco_anl % EZscintID, xpos_r4, ypos_r4, &
lat_deg_r4, lon_deg_r4, 1)
if ( trim(hco_anl % grtyp) == 'G' .and. hco_anl % ig2 == 1 ) then
! Revert latitudes since gdxyfll does not handle properly this grid type
ypos_r4 = real(hco_anl % nj,4) - ypos_r4 + 1.0
end if
!- Test if the obs is outside the analysis grid
if ( xpos_r4 < xposLowerBoundAnl_r4 .or. &
xpos_r4 > xposUpperBoundAnl_r4 .or. &
ypos_r4 < 1.0 .or. &
ypos_r4 > real(hco_anl % nj) ) then
if ( hco_anl % global ) then
! Modify latitude if we have an observation at or near the poles
write(*,*) ''
write(*,*) 'sugomobs: Moving OBS inside the GLOBAL ANALYSIS grid, ', jobs
write(*,*) ' true position : ', lat_deg_r4, lon_deg_r4, ypos_r4, xpos_r4
!- Move the observation to the nearest grid point
if ( ypos_r4 < 1.0 ) ypos_r4 = 1.0
if ( ypos_r4 > real(hco_anl % nj) ) ypos_r4 = real(hco_anl % nj)
ierr = gdllfxy( hco_anl % EZscintID, & ! IN
lat_deg_r4, lon_deg_r4, & ! OUT
xpos_r4, ypos_r4, 1) ! IN
if ( trim(hco_anl % grtyp) == 'G' .and. hco_anl % ig2 == 1 ) then
! Revert latitudes since gdllfxy does not handle properly this grid type
lat_deg_r4 = -1.0 * lat_deg_r4
end if
write(*,*) ' new position : ', lat_deg_r4, lon_deg_r4, ypos_r4, xpos_r4
lat_r8 = real(lat_deg_r4,8) * MPC_RADIANS_PER_DEGREE_R8
lon_r8 = real(lon_deg_r4,8) * MPC_RADIANS_PER_DEGREE_R8
call obs_headSet_r
(lobsSpaceData,OBS_LAT,jobs, lat_r8) ! IN
call obs_headSet_r
(lobsSpaceData,OBS_LON,jobs, lon_r8) ! IN
! Recompute position to make sure it is consistent with modified lat/lon
! lat_deg_r4=real(lat_r8) * MPC_DEGREES_PER_RADIAN_R4 ! Radian To Degree
! lon_deg_r4=real(lon_r8) * MPC_DEGREES_PER_RADIAN_R4
! ierr = gdxyfll( hco_anl % EZscintID, xpos_r4, ypos_r4, &
! lat_deg_r4, lon_deg_r4, 1)
! if ( trim(hco_anl % grtyp) == 'G' .and. hco_anl % ig2 == 1 ) then
! ! Revert latitudes since gdxyfll does not handle properly this grid type
! ypos_r4 = real(hco_anl % nj,4) - ypos_r4 + 1.0
! end if
else
! The observation is outside the domain
! In LAM Analysis mode we must discard this observation
write(*,*) 'sugomobs: Rejecting OBS outside the LAM ANALYSIS grid domain, ', jobs
write(*,*) ' position : ', lat_deg_r4, lon_deg_r4, ypos_r4, xpos_r4
idata = obs_headElem_i
(lobsSpaceData,OBS_RLN,jobs)
idatend = obs_headElem_i
(lobsSpaceData,OBS_NLV,jobs) + idata -1
do jdata = idata, idatend
call obs_bodySet_i
(lobsSpaceData,OBS_ASS,JDATA, 0)
end do
call obs_headSet_i
(lobsSpaceData,OBS_ST1,jobs, &
ibset( obs_headElem_i
(lobsSpaceData,OBS_ST1,jobs), 05))
end if
end if
!- Convert to rotated grid if needed
if (hco_anl % rotated) then
call uvr_RotateLatLon
( lat_rot, lon_rot, & ! OUT (radians)
lat_r8, & ! IN (radians)
lon_r8, & ! IN (radians)
'ToLatLonRot') ! IN
else
lat_rot = lat_r8
lon_rot = lon_r8
end if
!- Store the above 3 pairs of values in column structure
ypos_r8 = real(ypos_r4,8)
xpos_r8 = real(xpos_r4,8)
call col_setLatLon
( columng , jobs, lat_r8, lon_r8, & ! IN
ypos_r8, xpos_r8, lat_rot, lon_rot ) ! IN
call col_setLatLon
( columnhr, jobs, lat_r8, lon_r8, & ! IN
ypos_r8, xpos_r8, lat_rot, lon_rot ) ! IN
!
!- Find the position in the trial field grid
!
ierr=gdxyfll(itrlgid, xpos_r4, ypos_r4, lat_deg_r4, lon_deg_r4, 1)
if ( xpos_r4 >= 1.0 .and. xpos_r4 <= real(ini) .and. &
ypos_r4 >= 1.0 .and. ypos_r4 <= real(inj) ) then
dlonfld(nobs(jstep)) = lon_r8
dlatfld(nobs(jstep)) = lat_r8
if(dlonfld(nobs(jstep)).lt.0.0d0) &
dlonfld(nobs(jstep)) = dlonfld(nobs(jstep)) + &
2*MPC_PI_R8
if(dlonfld(nobs(jstep)).ge.2.0d0*MPC_PI_R8) &
dlonfld(nobs(jstep)) =dlonfld(nobs(jstep)) - &
2*MPC_PI_R8
dlonfld(nobs(jstep))=dlonfld(nobs(jstep))*MPC_DEGREES_PER_RADIAN_R8
dlatfld(nobs(jstep))=dlatfld(nobs(jstep))*MPC_DEGREES_PER_RADIAN_R8
else
! The observation is outside the domain
! With a LAM trial field we must discard this observation
write(*,*) 'sugomobs: Rejecting OBS outside the TRIAL field domain, ', jobs
write(*,*) ' position : ', lat_deg_r4, lon_deg_r4, ypos_r4, xpos_r4
idata = obs_headElem_i
(lobsSpaceData,OBS_RLN,jobs)
idatend = obs_headElem_i
(lobsSpaceData,OBS_NLV,jobs) + idata -1
do jdata = idata, idatend
call obs_bodySet_i
(lobsSpaceData,OBS_ASS,JDATA, 0)
end do
call obs_headSet_i
(lobsSpaceData,OBS_ST1,jobs, &
ibset( obs_headElem_i
(lobsSpaceData,OBS_ST1,jobs), 05))
! However, we must assigned a realistic lat-lon to this point
! to avoid problem later in Hx computation.
ierr=gdllfxy(itrlgid, lat_deg_r4, lon_deg_r4, real(ini)/2.0, &
real(inj)/2.0, 1) ! Middle of the domain
dlonfld(nobs(jstep)) = real(lon_deg_r4,8)
dlatfld(nobs(jstep)) = real(lat_deg_r4,8)
end if
end if
end do ! jobs
! gather and compute the max number of obs over all processors for each timestep
call rpn_comm_allreduce(nobs(jstep),nobs_maxmpiglobal(jstep),1, &
"MPI_INTEGER","MPI_MAX","GRID",ierr)
call rpn_comm_allgather(nobs(jstep),1,"mpi_integer", &
nobs_mpiglobal(jstep,:),1,"mpi_integer", &
"GRID",ierr)
! gather lon-lat of observations from all processors
call rpn_comm_allgather(dlonfld,numColumn_maxmpiglobal,"mpi_double_precision", &
dlonfld_mpiglobal,numColumn_maxmpiglobal,"mpi_double_precision", &
"GRID",ierr)
call rpn_comm_allgather(dlatfld,numColumn_maxmpiglobal,"mpi_double_precision", &
dlatfld_mpiglobal,numColumn_maxmpiglobal,"mpi_double_precision", &
"GRID",ierr)
zig1 = 0.0D0
zig2 = 0.0D0
zig3 = 1.0D0
zig4 = 1.0D0
call vcxgaig
('L',ig1obs,ig2obs,ig3obs,ig4obs,zig1,zig2,zig3,zig4)
do jlatlontile = 1,mpi_nprocs
if (nobs_mpiglobal(jstep,jlatlontile).gt.0) then
nobsgid_mpiglobal(jstep,jlatlontile) = vezgdef
(nobs_mpiglobal(jstep,jlatlontile), &
1,'Y','L',ig1obs,ig2obs,ig3obs,ig4obs, &
dlonfld_mpiglobal(1:nobs_mpiglobal(jstep,jlatlontile),jlatlontile), &
dlatfld_mpiglobal(1:nobs_mpiglobal(jstep,jlatlontile),jlatlontile))
else
!write(*,*) 'sugomobs: NO OBS found for this time/lat bin =',jstep,jlatlontile
nobsgid_mpiglobal(jstep,jlatlontile) = -999
end if
end do
end do ! jstep
!
! reading 2D fields
!
do jvar=1,vnl_numvarmax2D
if(.not.gsv_varExist(vnl_varNameList2D(jvar))) cycle
call readTrialField4
(varInterphr_M,varInterphr_VV,vnl_varNameList2D(jvar),'SF')
if(col_getNumCol
(columng).gt.0) then
if(vnl_varNameList2D(jvar).eq.'P0 ') then
varInterphr_M(:,:)=varInterphr_M(:,:)*MPC_PA_PER_MBAR_R8
endif
call col_fillmvo
(columng ,varInterphr_M,vnl_varNameList2D(jvar))
call col_fillmvo
(columnhr,varInterphr_M,vnl_varNameList2D(jvar))
endif
enddo
!
! Derive the pressure fields at observation points from the hybrid
! levels(vco_anl%dhyb_m), the hybrid coordinate parameters of the
! analysis increment and the surface pressure of the trial field
!
if(col_getNumCol
(columng).gt.0) then
call col_calcPressure
(columng)
do jlev = 1,col_getNumLev
(columng,'MM')
if(mpi_myid.eq.0) write(*,*) 'sugomobs: jlev, vco_anl%dhyb_m(jlev), col_getPressure
(COLUMNG,jlev,1,MM) = ', &
jlev,vco_anl%dhyb_m(jlev),col_getPressure
(COLUMNG,jlev,1,'MM')
end do
! Calculate profiles of pressure values at station location
! Compute Pressure fields at desired trial field levels
call col_calcPressure
(columnhr)
do jlev = 1,col_getNumLev
(columnhr,'MM')
if(mpi_myid.eq.0) write(*,*) 'sugomobs: jlev, vco_trl%dhyb_m(jlev), col_getPressure
(COLUMNHR,jlev,1,MM) = ', &
jlev,vco_trl%dhyb_m(jlev),col_getPressure
(columnhr,jlev,1,'MM')
end do
do jlev = 1,col_getNumLev
(columnhr,'TH')
if(mpi_myid.eq.0) write(*,*) 'sugomobs: jlev, vco_trl%dhyb_t(jlev), col_getPressure
(COLUMNHR,jlev,1,TH) = ', &
jlev,vco_trl%dhyb_t(jlev),col_getPressure
(columnhr,jlev,1,'TH')
end do
if(mpi_myid.eq.0) write(*,*) 'sugomobs: surface Pressure=',col_getElem
(columnhr,1,1,'P0')
end if
!
! Variable GZ qui se trouve sur les niveaux momentum et thermodynamiques
!
write(*,*)' ----- Initializing GZ ----'
!
! Lire les GZ des niveaux Momentum
!
call readTrialField4
(varInterphr_M,varInterphr_VV,'GZ','MM')
if(col_getNumCol
(columng).gt.0) then
varInterphr_M(:,:)=varInterphr_M(:,:)*10.0d0*RG
call col_fillmvo
(columnhr,varInterphr_M,'GZ ','MM')
if(mpi_myid.eq.0) write(*,*) 'sugomobs:GZ_M'
do jlev = 1,nlv_M
if(mpi_myid.eq.0) write(*,*) 'GZ,',jlev,varInterphr_M(jlev,1)
enddo
endif
!
! Lire les GZ des niveaux Thermodynamique
!
call readTrialField4
(varInterphr_T,varInterphr_VV,'GZ','TH')
if(col_getNumCol
(columng).gt.0) then
varInterphr_T(:,:)=varInterphr_T(:,:)*10.0d0*RG
call col_fillmvo
(columnhr,varInterphr_T,'GZ ','TH')
if(mpi_myid.eq.0) write(*,*) 'sugomobs:GZ_TH'
do jlev = 1,nlv_T
if(mpi_myid.eq.0) write(*,*)'GZ,',jlev,varInterphr_T(jlev,1)
enddo
endif
!
! Now all of the other 3D variables
!
do jvar=1, vnl_numvarmax3D
if(.not.gsv_varExist(vnl_varNameList3D(jvar))) cycle
select case ( vnl_varNameList3D(jvar) )
!
! Variables sur les niveaux momentum
!
case ('UU')
write(*,*)' ----- Initializing UU and VV ----'
call readTrialField4
(varInterphr_M,varInterphr_VV,'UV','MM')
if(col_getNumCol
(columng).gt.0) then
if(mpi_myid.eq.0) write(*,*) 'sugomobs: UU ,nlev= ',nlv_M
do jlev = 1,nlv_M
if(mpi_myid.eq.0) write(*,*) 'UU',jvar,jlev,varInterphr_M(jlev,1)
enddo
if(mpi_myid.eq.0) write(*,*) 'sugomobs: VV ,nlev= ',nlv_M
do jlev = 1,nlv_M
if(mpi_myid.eq.0) write(*,*) 'VV',jvar,jlev,varInterphr_VV(jlev,1)
enddo
call col_fillmvo
(columnhr,varInterphr_M,'UU ')
call col_fillmvo
(columnhr,varInterphr_VV,'VV ')
call col_vintprof
(columnhr,columng,'UU')
call col_vintprof
(columnhr,columng,'VV')
! conversion from knots to m/s
do jobs=1,col_getNumCol
(columng)
column_ptr => col_getColumn
(columnhr,jobs,'UU')
do jlev=1,col_getNumLev
(columnhr,'MM')
column_ptr(jlev)=column_ptr(jlev)*MPC_M_PER_S_PER_KNOT_R8
enddo
column_ptr => col_getColumn
(columnhr,jobs,'VV')
do jlev=1,col_getNumLev
(columnhr,'MM')
column_ptr(jlev)=column_ptr(jlev)*MPC_M_PER_S_PER_KNOT_R8
enddo
column_ptr => col_getColumn
(columng,jobs,'UU')
do jlev=1,col_getNumLev
(columng,'MM')
column_ptr(jlev)=column_ptr(jlev)*MPC_M_PER_S_PER_KNOT_R8
enddo
column_ptr => col_getColumn
(columng,jobs,'VV')
do jlev=1,col_getNumLev
(columng,'MM')
column_ptr(jlev)=column_ptr(jlev)*MPC_M_PER_S_PER_KNOT_R8
enddo
enddo
endif
!
! Variable sur les niveaux thermodynamiques
!
case ('TT','HU')
write(*,*)' ----- Initializing ',vnl_varNameList3D(jvar),' ----'
call readTrialField4
(varInterphr_T,varInterphr_VV,vnl_varNameList3D(jvar),'TH')
if(col_getNumCol
(columng).gt.0) then
if(mpi_myid.eq.0) write(*,*) 'sugomobs:',vnl_varNameList3D(jvar)
do jlev = 1,nlv_T
if(mpi_myid.eq.0) write(*,*) trim(vnl_varNameList3D(jvar)),',',jlev,varInterphr_T(jlev,1)
enddo
call col_fillmvo
(columnhr,varInterphr_T,vnl_varNameList3D(jvar))
call col_vintprof
(columnhr,columng,vnl_varNameList3D(jvar))
if(vnl_varNameList3D(jvar).eq.'TT ') then
! conversion from Celcius to Kelvin
do jobs=1,col_getNumCol
(columng)
column_ptr => col_getColumn
(columnhr,jobs,'TT')
do jlev=1,col_getNumLev
(columnhr,'TH')
column_ptr(jlev)=column_ptr(jlev)+MPC_K_C_DEGREE_OFFSET_R8
enddo
column_ptr => col_getColumn
(columng,jobs,'TT')
do jlev=1,col_getNumLev
(columng,'TH')
column_ptr(jlev)=column_ptr(jlev)+MPC_K_C_DEGREE_OFFSET_R8
enddo
enddo
elseif(vnl_varNameList3D(jvar).eq.'HU ') then
! conversion from specific humidity to log(humidity)
do jobs=1,col_getNumCol
(columng)
column_ptr => col_getColumn
(columnhr,jobs,'HU')
do jlev=1,col_getNumLev
(columnhr,'TH')
column_ptr(jlev)=log(max(column_ptr(jlev),rhumin))
enddo
column_ptr => col_getColumn
(columng,jobs,'HU')
do jlev=1,col_getNumLev
(columng,'TH')
column_ptr(jlev)=log(max(column_ptr(jlev),rhumin))
enddo
enddo
endif
endif
end select
enddo
!
!- Initialisation of TLM operators
!
if(Vcode_anl .eq. 5001) then
! initialize virtual temperature and GZ operators
call subasic_obs
(columng)
elseif(Vcode_anl .eq. 5002) then
! only initialize virtual temperature operator
call subasic_obs_gem4
(columng)
else
call abort3d
('sugomobs: invalid vertical coord for analysis increment grid!')
endif
!
!- Using T, q and PS to compute GZ for columng
!
do jobs = 1, col_getNumCol
(columng)
call col_setMountain
(columng ,jobs,col_getMountain
(columnhr,jobs))
enddo
if(Vcode_anl .eq. 5001) then
call tt2phi
(columng)
elseif(Vcode_anl .eq. 5002) then
call tt2phi_gem4
(columng)
else
call abort3d
('sugomobs: invalid vertical coord for analysis increment grid!')
endif
!
!- Using T, q and PS to compute GZ for columnhr
!
if(Vcode_trl .eq. 5001 ) then ! only in non-staggered mode
call tt2phi
(columnhr)
else
! test out the staggered GZ calculation, recomputing GZ for columnhr
!call tt2phi_gem4(columnhr)
endif
!
!- Close the files
!
do jstep=1,tim_nStepObs
ierr=fstfrm(nultrl(jstep))
ierr=fclos(nultrl(jstep))
enddo
!
!- Deallocate the local arrays
!
if(col_getNumCol
(columng).gt.0) then
deallocate(notag)
deallocate(varInterphr_T)
deallocate(varInterphr_M)
deallocate(varInterphr_VV)
endif
deallocate(datestamplist)
deallocate(nobsgid)
deallocate(nobs,nobs_maxmpiglobal)
deallocate(nultrl)
deallocate(idate)
deallocate(itime)
deallocate(dlonfld)
deallocate(dlatfld)
deallocate(dlonfld_mpiglobal)
deallocate(dlatfld_mpiglobal)
deallocate(nobsgid_mpiglobal)
deallocate(nobs_mpiglobal)
write(*,*) ' '
write(*,*) '-------- Leaving SUGOMOBS ---------'
write(*,*) ' '
call tmg_stop(10)
return
!--------------------------------------------------------------------------------
CONTAINS
subroutine readTrialField4(varInterphr_MT,varInterphr_VV,varName_in,varType_in) 5,5
!
! s/r readTrialField
!
! Author : M. Buehner, Dec 2012
!
! Purpose: Read and interpolate all levels/time steps for a single variable of trial field
!
implicit none
character(len=*) :: varName_in
character(len=*),optional :: varType_in
character(len=2) :: varType,varName
real*8 :: varInterphr_MT(:,:),varInterphr_VV(:,:)
real*4, allocatable :: varTrial_r4(:,:),varTrial_VV_r4(:,:)
real*4, allocatable :: varTrial_zero_r4(:,:)
real*8, allocatable :: varInterp(:,:,:),varInterp_VV(:,:,:)
real*8, allocatable :: varInterp2(:),varInterp2_VV(:)
real*8, allocatable :: varInterp_recv(:,:),varInterp_recv_VV(:,:)
integer :: nlevel,nsize,iip1,pe_send,pe_recv,tag,tag2
integer :: fstlir,vezuvint2,vezsint2,ezdefset
integer :: key, fstinf, fstprm, EZscintID, ezqkdef
integer :: ni, nj, nk
integer :: dateo, deet, npas, nbits, datyp
integer :: ip1, ip2, ip3, swa, lng, dltf, ubc
integer :: extra1, extra2, extra3
integer :: ig1, ig2, ig3, ig4
!
! Determine the type and number of vertical levels
!
if(trim(varName_in).eq.'UV') then
varName='UU'
else
varName=varName_in
endif
if(present(varType_in)) then
varType = varType_in
else
varType = vnl_vartypeFromVarname
(varName)
endif
nlevel = col_getNumLev
(columnhr,varType)
!
! Determine grid size and EZSCINT ID
!
dateo = -1
cletiket = ' '
ip1 = -1
ip2 = -1
ip3 = -1
cltypvar = ' '
key = fstinf( nultrl(1), & ! IN
ni, nj, nk, & ! OUT
dateo, cletiket, ip1, ip2, ip3, cltypvar, varName )! IN
if (key < 0) then
write(6,*)
write(6,*) 'SUGOMOBS: Unable to find trial field = ',varName
stop
end if
ierr = fstprm( key, & ! IN
dateo, deet, npas, ni, nj, nk, nbits, & ! OUT
datyp, ip1, ip2, ip3, cltypvar, varName, cletiket, & ! OUT
clgrtyp, ig1, ig2, ig3, & ! OUT
ig4, swa, lng, dltf, ubc, extra1, extra2, extra3 ) ! OUT
EZscintID = ezqkdef( ni, nj, clgrtyp, ig1, ig2, ig3, ig4, nultrl(1) ) ! IN
!
allocate(varTrial_r4(ni,nj))
allocate(varTrial_VV_r4(ni,nj))
allocate(varTrial_zero_r4(ni,nj))
allocate(varInterp(maxval(nobs_mpiglobal),nlevel,mpi_nprocs))
allocate(varInterp_VV(maxval(nobs_mpiglobal),nlevel,mpi_nprocs))
allocate(varInterp2(maxval(nobs_mpiglobal)))
allocate(varInterp2_VV(maxval(nobs_mpiglobal)))
allocate(varInterp_recv(maxval(nobs_mpiglobal),nlevel))
allocate(varInterp_recv_VV(maxval(nobs_mpiglobal),nlevel))
varTrial_zero_r4(:,:) = 0.0
! in the case that not all variable have the same etiket or typvar
! (this is necessary for extra 3d-var done before gen_coeff)
cletiket=' '
cltypvar=' '
do jstep = 1,tim_nStepObs
if(nobs_maxmpiglobal(jstep) > 0) then
call rpn_comm_barrier("GRID",ierr)
do jlev = (1+mpi_myid),nlevel,mpi_nprocs
if(varType.eq.'MM') then
IIP1 = vco_trl%ip1_M(jlev)
elseif(varType.eq.'TH') then
IIP1 = vco_trl%ip1_T(jlev)
elseif(varType.eq.'SF') then
IIP1 = -1
else
call abort3d
('SUGOMOBS: unknown varType')
endif
ierr=fstlir(varTrial_r4(:,:),nultrl(jstep),ni,nj,ink, &
datestamplist(jstep) ,cletiket,iip1,-1,-1, &
cltypvar,varName)
if(ierr.lt.0)then
write(*,2001) varName,iip1,idate(jstep),itime(jstep)
call abort3d
('SUGOMOBS:Problem with background file')
end if
if(varName.eq.'UU') then
ierr=fstlir(varTrial_VV_r4(:,:),nultrl(jstep),ni,nj,ink, &
datestamplist(jstep) ,cletiket,iip1,-1,-1, &
cltypvar,'VV')
if(ierr.lt.0)then
write(*,2001) 'VV',iip1,idate(jstep),itime(jstep)
call abort3d
('SUGOMOBS:Problem with background file')
end if
endif
! Interpolate to mpiglobal set of columns for a subset of levels
do jlatlontile = 1,mpi_nprocs
if (nobs_mpiglobal(jstep,jlatlontile).gt.0) then
iset = ezdefset(nobsgid_mpiglobal(jstep,jlatlontile),EZscintID)
if(trim(varName).eq.'UU') then
ierr = vezuvint2(varInterp(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile), &
varInterp_VV(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile), &
varTrial_r4,varTrial_zero_r4, &
nobs_mpiglobal(jstep,jlatlontile),ni*nj)
ierr = vezuvint2(varInterp2(1:nobs_mpiglobal(jstep,jlatlontile)), &
varInterp2_VV(1:nobs_mpiglobal(jstep,jlatlontile)), &
varTrial_zero_r4,varTrial_VV_r4, &
nobs_mpiglobal(jstep,jlatlontile),ni*nj)
varInterp(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile) = &
varInterp(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile) + &
varInterp2(1:nobs_mpiglobal(jstep,jlatlontile))
varInterp_VV(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile) = &
varInterp_VV(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile) + &
varInterp2_VV(1:nobs_mpiglobal(jstep,jlatlontile))
else
ierr = vezsint2(varInterp(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile), &
varTrial_r4, &
nobs_mpiglobal(jstep,jlatlontile),1,1,ni,nj,1)
endif
endif
enddo
enddo
do jlatlontile = 1,mpi_nprocs
if (nobs_mpiglobal(jstep,jlatlontile).gt.0) then
do jlev = 1,nlevel
pe_send = mod(jlev-1,mpi_nprocs)
pe_recv = jlatlontile-1
tag = pe_recv*500 + pe_send
tag2 = pe_recv*500 + pe_send + 1000000
if(pe_send.eq.pe_recv) then
if(mpi_myid.eq.pe_send) then
varInterp_recv(1:nobs_mpiglobal(jstep,jlatlontile),jlev) = &
varInterp(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile)
if(trim(varName).eq.'UU') then
varInterp_recv_VV(1:nobs_mpiglobal(jstep,jlatlontile),jlev) = &
varInterp_VV(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile)
endif
endif
else
if(mpi_myid.eq.pe_send) then
nsize=nobs_mpiglobal(jstep,jlatlontile)
call rpn_comm_send(varInterp(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile), &
nsize,"mpi_double_precision",pe_recv,tag,"GRID",ierr)
if(trim(varName).eq.'UU') then
call rpn_comm_send(varInterp_VV(1:nobs_mpiglobal(jstep,jlatlontile),jlev,jlatlontile), &
nsize,"mpi_double_precision",pe_recv,tag2,"GRID",ierr)
endif
endif
if(mpi_myid.eq.pe_recv) then
nsize=nobs_mpiglobal(jstep,jlatlontile)
call rpn_comm_recv(varInterp_recv(1:nobs_mpiglobal(jstep,jlatlontile),jlev), &
nsize,"mpi_double_precision",pe_send,tag,"GRID",status,ierr)
if(trim(varName).eq.'UU') then
call rpn_comm_recv(varInterp_recv_VV(1:nobs_mpiglobal(jstep,jlatlontile),jlev), &
nsize,"mpi_double_precision",pe_send,tag2,"GRID",status,ierr)
endif
endif
endif
enddo
endif
enddo
do jlev = 1,nlevel
do jobs = 1, nobs(jstep)
varInterphr_MT(jlev,notag(jobs,jstep)) = varInterp_recv(jobs,jlev)
if(trim(varName).eq.'UU') then
varInterphr_VV(jlev,notag(jobs,jstep)) = varInterp_recv_VV(jobs,jlev)
endif
enddo
enddo
endif !nobs>0
enddo !jstep
deallocate(varTrial_r4,varTrial_VV_r4)
deallocate(varTrial_zero_r4)
deallocate(varInterp,varInterp_VV)
deallocate(varInterp_recv,varInterp_recv_VV)
deallocate(varInterp2,varInterp2_VV)
2001 format(1x,'SUGOMOBS: Problem finding variable',1x,a4,1x,'at level', &
i10,1x,', on',1x,i8,1x,'at',1x,i8.8,1x,'HHMMSSss')
end subroutine readTrialField4
end subroutine sugomobs