!-------------------------------------- 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 GD2MVOAD (cdvarname,klev) 10,10
*
#if defined (DOC)
*
***s/r GD2MVOAD - Adjoint of the horizontal interpolation of the model variables
* . in grid-point space to observation locations.
* . Simple multiplication by the weights of
* . the horizontal bilinear interpolation.
* . (adapted from BILINAD)
*
*
*Author : P. GAUTHIER *ARMA/MSC JULY 2002
*
*Revision:
* Bin He *ARMA/MRB JULY 2009
* -- MPI version , restore Global array GOMTGR,....
*
** Purpose: Update the estimate of GD from the gradient components
* at the observation points which have been stored in
* GOMOBS
*
* Arguments
* CDVARNAME: identificator of the variable to be treated
* KLEV : number of levels (typically 1 for 2D-fields and NFLEV for 3D-fields)
*
*
*
#endif
USE obstag
IMPLICIT NONE
*implicits
#include "pardim.cdk"
#include "comdim.cdk"
#include "comdimo.cdk"
#include "comleg.cdk"
#include "comgem.cdk"
#include "comgd0.cdk"
#include "comcst.cdk"
#include "comoahdr.cdk"
#include "comoabdy.cdk"
#include "comoba.cdk"
#include "commvo.cdk"
*
* Arguments
*
character*2 cdvarname
integer klev
*
* Local Variables
*
INTEGER JLEV, JGL, JLON, JOBS, IOBTYP
INTEGER ILON, ILOS, ILA, IMIDDLE, ISYM, IMAX
REAL*8 DLMEAN, DLMEAS, DLLAO, DLLOO, DLDLON, DLDLOS
REAL*8 DLDXN, DLDXS, DLDY, DLW1, DLW2, DLW3, DLW4
*
real*8 zfield(nibeg:niend,1:klev,njbeg:njend)
real*8,pointer,dimension(:,:) :: zprofil
*
* bhe =========
integer :: ierr
real*8 ,allocatable,dimension(:,:),target :: GOMARR
* bhe ============
* Transfer Grid point field into local array (for generecity)
*
zfield(:,:,:) = 0.0D0
*
*
allocate(gomarr(klev,nobtotp),stat=ierr )
SELECT CASE (CDVARNAME)
*
* 2D fields
*
CASE('TG')
CALL GetGomarr
(GOMARR,GOMTGR)
CASE('PS')
CALL GetGomarr
(GOMARR,GOMPS)
*
* 3D fields
*
CASE('TT')
CALL GetGomarr
(GOMARR,GOMT)
CASE('Q0')
CALL GetGomarr
(GOMARR,GOMQ)
CASE('O3')
CALL GetGomarr
(GOMARR,GOMOZ)
CASE('TR')
CALL GetGomarr
(GOMARR,GOMTR)
CASE('UU')
CALL GetGomarr
(GOMARR,GOMU)
CASE('VV')
CALL GetGomarr
(GOMARR,GOMV)
CASE('GZ')
CALL GetGomarr
(GOMARR,GOMGZ)
END SELECT
C* set array alian
ZPROFIL => GOMARR(1:KLEV,1:NOBTOTP)
C
C* 2. LOOP OVER ALL THE OBSERVATIONS
C ---------------------------------
C
200 CONTINUE
C
Observations: DO JOBS = 1, NOBTOTP
DLLAO = ROBHDR_G(NCMLAT,JOBS)
DLLOO = ROBHDR_G(NCMLON,JOBS)
IOBTYP = MOBHDR_G(NCMOTP,JOBS)
C
C * 2.1. LOCATE FIRST LATITUDE ROW NUMBER (ILA) TO THE NORTH
C * OF ZLAO, AND THE TWO LONGITUDE POINT NUMBERS IMMEDIATELY
C TO THE WEST (ILON AND ILOS)
C
ILA=MOBHDR_G(NCMTLA,JOBS)
C
IF(DLLOO.LT.0.) DLLOO = DLLOO + 2.*RPI
IF(DLLOO.GE.2.*RPI) DLLOO = DLLOO - 2.*RPI
DLDLON = 2.*RPI/NILON(ILA)
DLDLOS = 2.*RPI/NILON(ILA+1)
ILON = INT(DLLOO/DLDLON) + 1
ILOS = INT(DLLOO/DLDLOS) + 1
C
C * 2.2 COMPUTE THE 4 WEIGHTS OF THE BILINEAR INTERPOLATION
C
DLDXN = DLLOO/DLDLON + 1. - ILON
DLDXS = DLLOO/DLDLOS + 1. - ILOS
DLDY = (RLATI(ILA)-DLLAO)/(RLATI(ILA)-RLATI(ILA+1))
DLW1 = (1.-DLDXN)*(1.-DLDY)
DLW2 = DLDXN*(1.-DLDY)
DLW3 = (1.-DLDXS)*DLDY
DLW4 = DLDXS*DLDY
C
do jlev = 1, klev
ZFIELD(ILON,jlev,ILA) = ZFIELD(ILON,jlev,ILA)
+ + DLW1 * ZPROFIL(jlev,JOBS)
ZFIELD(ILON+1,jlev,ILA) = ZFIELD(ILON+1,jlev,ILA)
+ + DLW2 * ZPROFIL(jlev,JOBS)
ZFIELD(ILOS,jlev,ILA+1) = ZFIELD(ILOS,jlev,ILA+1)
+ + DLW3 * ZPROFIL(jlev,JOBS)
ZFIELD(ILOS+1,jlev,ILA+1) = ZFIELD(ILOS+1,jlev,ILA+1)
+ + DLW4 * ZPROFIL(jlev,JOBS)
C
end do
*
end do OBSERVATIONS
* release the memory
deallocate(gomarr)
C
C
C 1. REARRANGE GRID-POINTS ARRAYS GD0, BY CARRYING GRADIENTS
C . CONTRIBUTIONS OF MERIDIAN 0, NILON(JGL)+1 AND NILON(JGL+2)
C . INTO MERIDIANS NILON(JGL), 1, AND 2. SIMILAR TREATMENT NEAR POLES
C
C
C 1.2 EXTRA PARALLELS
C
C TREATMENT OF GRADIENTS FOR PARALLELS -1 AND NJ + 2 (WITH SYMETRIZATION)
C
LEVELS: DO JLEV = 1, KLEV
IMIDDLE = NILON(1) / 2
DO JLON = 0, IMIDDLE
ISYM = JLON + IMIDDLE
ZFIELD(ISYM,jlev,1) = ZFIELD(JLON,jlev,-1)
+ + ZFIELD(ISYM,jlev,1)
ZFIELD(ISYM,jlev,NJ) = ZFIELD(JLON,jlev,NJ+2)
+ + ZFIELD(ISYM,jlev,NJ)
END DO
*
IMAX = NILON(1)
DO JLON = IMIDDLE + 1, IMAX + 2
ISYM = JLON - IMIDDLE
ZFIELD(ISYM,JLEV,1) = ZFIELD(JLON,JLEV,-1)
+ + ZFIELD(ISYM,JLEV,1)
ZFIELD(ISYM,JLEV,NJ) = ZFIELD(JLON,JLEV,NJ+2)
+ + ZFIELD(ISYM,JLEV,NJ)
END DO
C
C TREATMENT OF THE GRADIENTS AT NORTH AND SOUTH POLES.
C
DLMEAN = 0.
DLMEAS = 0.
IMAX = NILON(0)
DO JLON = 0, IMAX + 2
DLMEAN = DLMEAN + ZFIELD(JLON,jlev,0)
DLMEAS = DLMEAS + ZFIELD(JLON,jlev,NJ+1)
end do
*
DLMEAN = DLMEAN/NILON(1)
DLMEAS = DLMEAS/NILON(NJ)
IMAX = NILON(1)
DO JLON = 1, IMAX
ZFIELD(JLON,jlev,1) = DLMEAN + ZFIELD(JLON,jlev,1)
ZFIELD(JLON,jlev,NJ) = DLMEAS + ZFIELD(JLON,jlev,NJ)
end do
*
END DO LEVELS
C
C
C 1.1 EXTRA MERIDIANS
C
DO JGL = 1, NJ
IMAX = NILON(JGL)
DO JLEV = 1, KLEV
ZFIELD(IMAX,JLEV,JGL) = ZFIELD(0,JLEV,JGL)
+ + ZFIELD(IMAX,JLEV,JGL)
ZFIELD(1,JLEV,JGL) = ZFIELD(IMAX+1,JLEV,JGL)
+ + ZFIELD(1,JLEV,JGL)
ZFIELD(2,JLEV,JGL) = ZFIELD(IMAX+2,JLEV,JGL)
+ + ZFIELD(2,JLEV,JGL)
END DO
END DO
*
* Adjoint of the identity (change of norm)
*
DO JGL = 1, NJ
IMAX = NILON(JGL)
DO JLEV = 1, KLEV
DO JLON = 1, IMAX
ZFIELD(JLON,JLEV,JGL) = ZFIELD(JLON,JLEV,JGL) *
+ NILON(JGL) / RWT(JGL)
END DO
END DO
END DO
C
C Transfer local results to global array
C
select case (cdvarname)
*
* 2D fields
*
case('TG')
gtg0(:,1:klev,:) = zfield(:,1:klev,:)
case('PS')
gps0(:,1:klev,:) = zfield(:,1:klev,:)
*
* 3D fields
*
case('TT')
tt0(:,1:klev,:) = zfield(:,1:klev,:)
case('Q0')
q0 (:,1:klev,:) = zfield(:,1:klev,:)
case('O3')
GOZ0(:,1:klev,:) = zfield(:,1:klev,:)
case('TR')
GTR0(:,1:klev,:) = zfield(:,1:klev,:)
case('UU')
UT0(:,1:klev,:) = zfield(:,1:klev,:)
case('VV')
VT0(:,1:klev,:) = zfield(:,1:klev,:)
case ('GZ')
GZ0(:,1:klev,:) = zfield(:,1:klev,:)
end select
CONTAINS
SUBROUTINE GetGOMARR(Arr_g,Arr_l) 18
REAL*8,DIMENSION(klev,nobtotp) :: arr_g
cping
REAL*8,DIMENSION(klev,nobtotp) :: arr_t
REAL*8,DIMENSION(nkgdimo,nobtot) :: arr_l
INTEGER :: i,j,iobs ,ierr
INTEGER :: ArrSize
arr_g(1:klev,1:nobtotp)=0.0D0
cping
arr_t(1:klev,1:nobtotp)=0.0D0
DO i=1,NOBTOT
iobs=locObsTag(i)
DO j=1,klev
ARR_g(j,iobs)=arr_l(j,i)
ENDDO
ENDDO
ArrSize=klev*nobtotp
cping CALL rpn_comm_allreduce(Arr_g,Arr_g,ArrSize,"MPI_DOUBLE_PRECISION","MPI_SUM","GRID",ierr)
CALL rpn_comm_allreduce(Arr_g,Arr_t,ArrSize,
& "MPI_DOUBLE_PRECISION","MPI_SUM","GRID",ierr)
Arr_g = Arr_t
END SUBROUTINE GetGOMARR
END SUBROUTINE GD2MVOAD