SUBROUTINE DOPPLSIM_TL(KDLEN,KDBDY,KLEN,KDCOUNT,KCOUNT,KPNLV,PUF,PVF,&
  &   PGEOPH5,KDPP,PXPP)

!***   DOPPLSIM_TL is the tangent linear model of the observation operator for
!      radar radial wind  

!      T. Montmerle 14/04/06 : Original
!      C. Faccani   06/02/08 : Read Beamwidth from odb base instead of constant value

!      ------------------------------------------------------------------------

USE PARKIND1,ONLY : JPIM,  JPRB
USE YOMCST  ,ONLY : RPI,RA,RG
USE YOMDIM  ,ONLY : NFLEVG
USE YOMHOOK ,ONLY : LHOOK, DR_HOOK
USE YOMLUN  ,ONLY : NULOUT
USE YOMANCS ,ONLY : RMDI,RDEGREES,RADIANS 
USE YOMDB

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN) :: KDLEN,KDBDY,KLEN,KDCOUNT
INTEGER(KIND=JPIM),INTENT(IN) :: KDPP
INTEGER(KIND=JPIM),INTENT(IN),DIMENSION(KDLEN) :: KCOUNT
INTEGER(KIND=JPIM),INTENT(IN),DIMENSION(KDLEN,KDBDY) :: KPNLV

REAL(KIND=JPRB),INTENT(IN),   DIMENSION(KDLEN,NFLEVG)     :: PUF,PVF
REAL(KIND=JPRB),INTENT(OUT),  DIMENSION(KDLEN,KDCOUNT,KDPP) :: PXPP
REAL(KIND=JPRB),INTENT(IN),   DIMENSION(KDLEN,0:NFLEVG)       :: PGEOPH5
REAL(KIND=JPRB)               :: ZHOOK_HANDLE

REAL(KIND=JPRB),DIMENSION(KDLEN,NFLEVG) :: ZDOPW  ! radial velocity
REAL(KIND=JPRB),DIMENSION(KDLEN)          :: ZAZIM  ! azimuth
REAL(KIND=JPRB) :: ZDTHETA ! beamwidth
REAL(KIND=JPRB) :: ZDLON,ZDLAT,ZDIST 
REAL(KIND=JPRB) :: ZTEMP1,ZTEMP2
REAL(KIND=JPRB),DIMENSION(NFLEVG) :: ZTHETA ! angle at each model level 
INTEGER(KIND=JPIM) :: JLEN,JCOUNT,JLEV,JI ! loop dummy counters for column, obs, level and working arrays
INTEGER(KIND=JPIM) :: ILEVTOP             ! Maximum model vertical level for radial wind computation
INTEGER(KIND=JPIM) :: IMIN,IMAX,IBODY ! min and max levels for vertical interpolation 
                                      ! (grosso modo beam vertical extension at column)
!!! constants
REAL(KIND=JPRB) :: ZRAE ! Earth's effective radius (4a/3)
REAL(KIND=JPRB),PARAMETER :: ZCOEF=1. ! width for vertical interpolation

REAL(KIND=JPRB), DIMENSION(KDLEN) :: ZSTALT,ZANTENHT ! radar station altitude and antena height
REAL(KIND=JPRB)  :: ZDISTANCE,ZELEV ! elevation en radians
REAL(KIND=JPRB)  :: ZALPHA          ! angle entre la verticale du radar
                                    ! et la verticale au pixel vent radar

#include "openmp_obs.h"

!      ------------------------------------------------------------------------

IF (LHOOK) CALL DR_HOOK('DOPPLSIM_TL',0,ZHOOK_HANDLE)

WRITE(NULOUT,*) "====>> DOPPLSIM_TL"
!WRITE(NULOUT,*) "  KDLEN:",KDLEN," KLEN:",KLEN," KDCOUNT:",KDCOUNT,"KDBDY:",KDBDY
!WRITE(NULOUT,*) "  KCOUNT:",KCOUNT(:)
!WRITE(NULOUT,*) "SIZE SATHDR:",SIZE(SATHDR,1),SIZE(SATHDR,2)
!WRITE(NULOUT,*) "SIZE SATBODY:",SIZE(SATBODY,1),SIZE(SATBODY,2)
!WRITE(NULOUT,*) "SIZE ROBHDR:",SIZE(ROBHDR,1),SIZE(ROBHDR,2)
!WRITE(NULOUT,*) "SIZE PUF:",SIZE(PUF,1),SIZE(PUF,2)
!WRITE(NULOUT,*) "SIZE PGEOPH5:",SIZE(PGEOPH5,1),SIZE(PGEOPH5,2)
!WRITE(NULOUT,*) "SIZE KPNLV:",SIZE(KPNLV,1),SIZE(KPNLV,2)
!WRITE(NULOUT,*) "SIZE MLNKH2B:",SIZE(MLNKH2B,1)
CALL FLUSH(NULOUT)

!      ------------------------------------------------------------------------
!*
!         1. Initialization of constants 
!         ------------------------------

ZRAE=4._JPRB/3._JPRB*RA    ! Earth's effective radius
ILEVTOP=17

ZDOPW(:,:)=0._JPRB
PXPP(:,:,:) = RMDI
ZAZIM(:)=0._JPRB
ZTHETA(:)=RPI/2._JPRB
ZELEV=0._JPRB
ZDISTANCE=0._JPRB
ZSTALT(:)=0._JPRB
ZANTENHT(:)=0._JPRB

!      ------------------------------------------------------------------------
!*
!         2. Compute radial winds on each model vertical level 
!         ----------------------------------------------------

DO JLEN=1,KLEN
  ZSTALT(JLEN)=SATHDR(JLEN,MDB_STALT_AT_RADAR_STATION)
  ZANTENHT(JLEN)=SATHDR(JLEN,MDB_ANTENHT_AT_RADAR_STATION)
  ZDLON=ROBHDR(JLEN,MDBLON)-SATHDR(JLEN,MDB_LON_AT_RADAR_STATION)*RADIANS
  ZDLAT=ROBHDR(JLEN,MDBLAT)-SATHDR(JLEN,MDB_LAT_AT_RADAR_STATION)*RADIANS
  ZDTHETA=SATHDR(JLEN,MDB_BEAMWIDTH_AT_RADAR_STATION)

!* Azimuth computation
  ZDIST=SQRT(ZDLON**2+ZDLAT**2)
  IF(ZDIST > 0.) THEN
     IF(ZDLAT >= 0.) ZAZIM(JLEN)=ASIN(ZDLON/ZDIST)
     IF(ZDLAT < 0.)  ZAZIM(JLEN)=RPI-ASIN(ZDLON/ZDIST)
  ELSE
     ZAZIM(JLEN) = 0.
  ENDIF

!* Horizontal radial wind 
  DO JLEV=1,NFLEVG
        ZDOPW(JLEN,JLEV) = PUF(JLEN,JLEV)*SIN(ZAZIM(JLEN))+PVF(JLEN,JLEV)&
   &    *COS(ZAZIM(JLEN))
  ENDDO
ENDDO

!      ------------------------------------------------------------------------
!*
!         3. Weight doppler radial winds over the vertical (Gaussian)
!         -----------------------------------------------------------

DO JLEN=1,KLEN ! loop over model columns of observations
   IF (KCOUNT(JLEN) >= 1) THEN
      DO JCOUNT=1,KCOUNT(JLEN) ! loop over each observation data

         IBODY = MLNKH2B(JLEN) + KPNLV(JLEN,JCOUNT) -1

         ZDISTANCE=SATBODY(IBODY,MDB_DISTANCE_AT_RADAR_BODY)
         ZELEV=SATBODY(IBODY,MDB_ELEVATION_AT_RADAR_BODY)*RADIANS

         !WRITE(NULOUT,*) '--------------------'
         !WRITE(NULOUT,*) '#WAG:',ROBODY(IBODY,MDBESQN)," VARNO:",ROBODY(IBODY,MDBVNM)
         !WRITE(NULOUT,*) 'ELEVATION:',ZELEV*RDEGREES

!* Angle of the horizontal radial wind with the ray path + earth curvature
         ZALPHA=ATAN(ZDISTANCE*COS(ZELEV)/&
    &       (ZDISTANCE*SIN(ZELEV)+ZRAE+ZSTALT(JLEN)+ZANTENHT(JLEN)))

!* Vertical Weighting of the radial wind supposed constant during minimization
         IMIN=1
         IMAX=1
         DO JLEV=ILEVTOP,NFLEVG
            ZDOPW(JLEN,JLEV)=ZDOPW(JLEN,JLEV)*COS(ZELEV + ZALPHA)
            IF(ZDISTANCE > 0.) THEN

            IF ( (( (PGEOPH5(JLEN,JLEV)/RG-ZSTALT(JLEN)-ZANTENHT(JLEN)+ZRAE)**2 &
                &  - ZDISTANCE**2-ZRAE**2)/2._JPRB/ZDISTANCE/ZRAE) < 1._JPRB) then

            ZTHETA(JLEV)=ASIN(((PGEOPH5(JLEN,JLEV)/RG-ZSTALT(JLEN)-ZANTENHT(JLEN)+ZRAE)**2 &
               &  - ZDISTANCE**2-ZRAE**2)/2._JPRB/ZDISTANCE/ZRAE) - ZELEV

                ELSE
! Level outside the beamwidth. Angle > 1. ---> CYCLE
                  !WRITE(NULOUT,*)"----  Level outside the beamwidth:",JLEV
                  CYCLE
                ENDIF
            ELSE
               ZTHETA(JLEV)=0.
            ENDIF
            IF((ZTHETA(JLEV)*RDEGREES) >= .5_JPRB*ZCOEF*ZDTHETA) IMIN=JLEV
            IF((ZTHETA(JLEV)*RDEGREES) >= (-0.5_JPRB)*ZCOEF*ZDTHETA) IMAX=JLEV
         ENDDO
         !WRITE(NULOUT,*)'LAT:',ROBHDR(JLEN,MDBLAT)*RDEGREES," LON:",ROBHDR(JLEN,MDBLON)*RDEGREES
         !WRITE(NULOUT,*)'DIST:',ZDISTANCE
         !WRITE(NULOUT,*)'IMIN=',IMIN, 'IMAX=',IMAX
         CALL FLUSH(NULOUT)

         IF (IMIN < IMAX) THEN 

!* Approximation of integrals by trapezoidal summations
            ZTEMP1=0.0_JPRB
            ZTEMP2=0.0_JPRB
            DO JI=IMIN,IMAX-1
               ZTEMP1 = ZTEMP1 &
                 & + 0.5_JPRB*(PGEOPH5(JLEN,JI+1)-PGEOPH5(JLEN,JI))/RG &
                 & * (ZDOPW(JLEN,JI+1)*EXP(-8._JPRB*LOG(2._JPRB)*(ZTHETA(JI+1) &
                 & / ZDTHETA*RDEGREES)**2)  &
                 & + ZDOPW(JLEN,JI)*EXP(-8._JPRB*LOG(2._JPRB)*(ZTHETA(JI) &
                 & / ZDTHETA*RDEGREES)**2)) 
   
               ZTEMP2 = ZTEMP2 &
                 & + 0.5_JPRB*(PGEOPH5(JLEN,JI+1)-PGEOPH5(JLEN,JI))/RG &
                 & * (EXP(-8._JPRB*LOG(2._JPRB)*(ZTHETA(JI+1) &
                 & / ZDTHETA*RDEGREES)**2) &
                 & + EXP(-8._JPRB*LOG(2._JPRB)*(ZTHETA(JI) &
                 & / ZDTHETA*RDEGREES)**2)) 
            ENDDO
   
!* Final radial wind
            PXPP(JLEN,JCOUNT,1)= - ZTEMP1/ZTEMP2
            !WRITE(NULOUT,*) "dVr:",PXPP(JLEN,JCOUNT,1)
         ELSE
            WRITE(NULOUT,*)"!!!! Pb dans la ponderation verticale !!!!!"
            WRITE(NULOUT,*)"IMIN=",IMIN, "IMAX=",IMAX
            WRITE(NULOUT,*)"JLEN:",JLEN,"JCOUNT:",JCOUNT,"ZTEMP1=",ZTEMP1, "ZTEMP2=",ZTEMP2
         ENDIF
      ENDDO
   ENDIF
ENDDO

IF (LHOOK) CALL DR_HOOK('DOPPLSIM_TL',1,ZHOOK_HANDLE)

END SUBROUTINE DOPPLSIM_TL 
