Influence3DGeoGaussianCart Subroutine

public subroutine Influence3DGeoGaussianCart(alpha, beta, Dalpha, Dbeta, P, x_rcvrMat, t_rcvr)

Geometrically-spreading beams with a Gaussian-shaped beam

!!!!!IF ( m_prime > BeamWindow * L_diag ) CYCLE Radials

! pre-calculate unit ray tangent

! rlen factor could be built into rayt

Arguments

Type IntentOptional Attributes Name
real(kind=8), intent(in) :: alpha
real(kind=8), intent(in) :: beta
real(kind=8), intent(in) :: Dalpha
real(kind=8), intent(in) :: Dbeta
complex, intent(out) :: P(Pos%Ntheta,Pos%Nrz,Pos%NRr)
real(kind=8), intent(in) :: x_rcvrMat(2,Pos%Ntheta,Pos%NRr)
real(kind=8), intent(in) :: t_rcvr(2,Pos%Ntheta)

Calls

proc~~influence3dgeogaussiancart~~CallsGraph proc~influence3dgeogaussiancart Influence3DGeoGaussianCart proc~applycontribution ApplyContribution proc~influence3dgeogaussiancart->proc~applycontribution proc~raynormal_unit RayNormal_unit proc~influence3dgeogaussiancart->proc~raynormal_unit proc~scalebeam ScaleBeam proc~influence3dgeogaussiancart->proc~scalebeam proc~addarr3d AddArr3D proc~applycontribution->proc~addarr3d proc~writeray3d WriteRay3D proc~applycontribution->proc~writeray3d sngl sngl proc~applycontribution->sngl proc~addarr3d->sngl

Called by

proc~~influence3dgeogaussiancart~~CalledByGraph proc~influence3dgeogaussiancart Influence3DGeoGaussianCart proc~bellhopcore BellhopCore proc~bellhopcore->proc~influence3dgeogaussiancart program~bellhop3d BELLHOP3D program~bellhop3d->proc~bellhopcore

Source Code

  SUBROUTINE Influence3DGeoGaussianCart( alpha, beta, Dalpha, Dbeta, P, x_rcvrMat, t_rcvr )
    !! Geometrically-spreading beams with a Gaussian-shaped beam

    REAL, PARAMETER                :: BeamWindow = 4.0                   ! kills beams outside e**(-0.5 * BeamWindow**2 )
    REAL ( KIND=8 ), INTENT( IN  ) :: alpha, beta, Dalpha, Dbeta         ! ray take-off angle
    REAL ( KIND=8 ), INTENT( IN  ) :: x_rcvrMat( 2, Pos%Ntheta, Pos%NRr ), t_rcvr( 2, Pos%Ntheta ) ! rcvr coordinates and tangent
    COMPLEX        , INTENT( OUT ) :: P( Pos%Ntheta, Pos%Nrz, Pos%NRr )  ! complex pressure
    INTEGER            :: irT( 1 ), irTT
    REAL    ( KIND=8 ) :: rlen, a, b, x_ray( 3 ), n_ray_z( 3 ), n_ray_theta( 3 ), &
         e1( 3 ), e2( 3 ), x_rcvr( 3 ), x_rcvr_ray( 3 ), &
         L1_stent, L2_stent, L_z, L_diag, e_theta( 3 ), m_prime, zMin, zMax, &
         Det_Q, Det_Qold

    Ratio1 = SQRT( ABS( COS( alpha ) ) ) * SQRT( Dalpha * Dbeta ) / ray3D( 1 )%c / ( 2.0 * pi )
    CALL ScaleBeam( alpha, Dalpha, Dbeta )   ! scaling for geometric beams

    phase    = 0.0
    Det_QOld = ray3D( 1 )%DetQ   ! used to track phase changes at caustics (rotations of Det_Q)

    ! Compute nearest rcvr before normal
    ! LP: Same issues as hat cart.
    rA  = NORM2( ray3D( 1 )%x( 1 : 2 ) - xs_3D( 1 : 2 ) )         ! range of ray point
    irT = MINLOC( Pos%Rr( 1 : Pos%NRr ), MASK = Pos%Rr( 1 : Pos%NRr ) > rA )   ! index of receiver
    ir  = irT( 1 )

    Stepping: DO is = 2, Beam%Nsteps
       lambda = ray3D( is - 1 )%c / freq   ! local wavelength
       ! Compute nearest rcvr before normal
       rB  = NORM2( ray3D( is )%x( 1 : 2 ) - xs_3D( 1 : 2 ) )         ! range of ray point

       IF ( ABS( rB - rA ) > 1.0D3 * SPACING( rA ) ) THEN   ! jump to next step if duplicate point
          ! initialize the index of the receiver range
          IF ( is == 2 ) THEN
             IF ( rB > rA ) THEN   ! ray is moving outward in range
                ir = 1             ! index all the way in
             ELSE                  ! ray is moving inward in range
                ir = Pos%NRr       ! index all the way out
             END IF
          END IF

          x_ray = ray3D( is - 1 )%x

          ! compute normalized tangent (we need it to measure the step length)
          rayt = ray3D( is )%x - ray3D( is - 1 )%x
          rlen = NORM2( rayt )

          IF ( rlen > 1.0D3 * SPACING( ray3D( is )%x( 1 ) ) ) THEN  ! Make sure this is not a duplicate point
             rayt = rayt / rlen                                     ! unit tangent to ray
             CALL RayNormal_unit( rayt, ray3D( is )%phi, e1, e2 )   ! Get ray normals e1 and e2
             ! WRITE( PRTFile, * ) 'rayt phi', rayt, ray3D( is )%phi
             ! WRITE( PRTFile, * ) 'e1 e2', e1, e2

             ! phase shifts at caustics
             Det_Q  = ray3D( is - 1 )%DetQ
             IF ( Det_Q <= 0.0d0 .AND. Det_QOld > 0.0d0 .OR. Det_Q >= 0.0d0 .AND. Det_QOld < 0.0d0 ) phase = phase + pi / 2.
             Det_Qold = Det_Q

             L1 = MAX( NORM2( ray3D( is - 1 )%q_tilde ), NORM2( ray3D( is )%q_tilde ) ) ! beamwidths
             L2 = MAX( NORM2( ray3D( is - 1 )%q_hat   ), NORM2( ray3D( is )%q_hat   ) )

             L_diag = SQRT( L1 ** 2 + L2 ** 2 )   ! worst case is when rectangle is rotated to catch the hypotenuse

             n_ray_theta = [ -rayt( 2 ), rayt( 1 ), 0.D0 ]  ! normal to the ray in the horizontal receiver plane

             ! *** Compute contributions to bracketed receivers ***
             dq_tilde = ray3D( is )%q_tilde - ray3D( is - 1 )%q_tilde
             dq_hat   = ray3D( is )%q_hat   - ray3D( is - 1 )%q_hat
             dtau     = ray3D( is )%tau     - ray3D( is - 1 )%tau

             Ranges: DO
                ! is r( ir ) contained in [ rA, rB ]? Then compute beam influence
                IF ( Pos%Rr( ir ) >= MIN( rA, rB ) .AND. Pos%Rr( ir ) < MAX( rA, rB ) ) THEN

                   Radials: DO itheta = 1, Pos%Ntheta   ! Loop over radials of receiver line

                      x_rcvr( 1 : 2 ) = x_rcvrMat( 1 : 2, itheta, ir )
                      m_prime = ABS( DOT_PRODUCT( x_rcvr( 1 : 2 ) - x_ray( 1 : 2 ), n_ray_theta( 1 : 2 ) ) )
                      ! normal distance from rcvr to ray segment

!!!!!!!IF ( m_prime > BeamWindow * L_diag ) CYCLE Radials

                      ! The set of possible receivers is a ring
                      ! However, extrapolating the beam backwards produces contributions with s negative and large
                      ! We do not want to accept these contributions--- they have the proper range but are 180 degrees
                      ! away from this segment of the ray
!!! pre-calculate unit ray tangent
                      ! s = DOT_PRODUCT( x_rcvr( 1 : 2 ) - x_ray( 1 : 2 ), rayt( 1 : 2 ) / NORM2( rayt( 1 : 2 ) ) )   ! a distance along ray    (in x-y plane)
                      ! s = DOT_PRODUCT( x_rcvr( 1 : 2 ) - xs_3D( 1 : 2 ), t_rcvr( 1 : 2, itheta ) ) ! a distance along radial (in x-y plane)
                      s = DOT_PRODUCT( x_rcvr( 1 : 2 ) - xs_3D( 1 : 2 ), x_ray( 1 : 2 ) - xs_3D( 1 : 2 ) ) ! vector to rcvr dotted into vector to ray point

                      ! The real receivers have an s-value in [0, R_len]
                      ! IF ( s < 0D0 .OR. s > NORM2( ray3D( is )%x( 1 : 2 ) - ray3D( is - 1 )%x( 1 : 2 ) ) ) THEN
                      ! IF ( ABS( s ) > NORM2( ray3D( is )%x( 1 : 2 ) - ray3D( is - 1 )%x( 1 : 2 ) ) ) THEN

                      IF ( s < 0D0 ) CYCLE Radials

                      ! calculate z-limits for the beam (could be pre-cacluated for each itheta)
                      e_theta      = [ -t_rcvr( 2, itheta ), t_rcvr( 1, itheta ), 0.0D0 ]  ! normal to the vertical receiver plane
                      ! n_ray_z    = CROSS_PRODUCT( rayt, e_theta )                        ! normal to the ray in the vertical receiver plane
                      n_ray_z( 3 ) = rayt( 1 ) * e_theta( 2 ) - rayt( 2 ) * e_theta( 1 )   ! normal to the ray in the vertical receiver plane

                      IF ( ABS( n_ray_z( 3 ) ) < 1D-9 ) CYCLE Radials   ! avoid divide by zero
                      L_z          = BeamWindow * L_diag / ABS( n_ray_z( 3 ) )

                      zmin = MIN( ray3D( is - 1 )%x( 3 ), ray3D( is )%x( 3 ) ) - L_z  ! min depth of ray segment
                      zmax = MAX( ray3D( is - 1 )%x( 3 ), ray3D( is )%x( 3 ) ) + L_z  ! max depth of ray segment

                      ! WRITE( PRTFile, * ) 'step ir itheta', is-2, ir-1, itheta-1

                      ReceiverDepths: DO iz = 1, Pos%Nrz
                         x_rcvr( 3 ) = DBLE( Pos%rz( iz ) )   ! z coordinate of the receiver
                         IF ( x_rcvr( 3 ) < zmin .OR. x_rcvr( 3 ) > zmax ) CYCLE ReceiverDepths

                         x_rcvr_ray = x_rcvr - x_ray
                         ! IF ( ir-1 == 7 .AND. itheta-1 == 59 ) THEN
                         !    WRITE( PRTFile, * ) 'x_rcvr_ray e1, e2', x_rcvr_ray, e1, e2
                         ! END IF

!!! rlen factor could be built into rayt
                         ! linear interpolation of q's
                         s       = DOT_PRODUCT( x_rcvr_ray, rayt ) / rlen  ! proportional distance along ray
                         q_tilde = ray3D( is - 1 )%q_tilde + s * dq_tilde
                         q_hat   = ray3D( is - 1 )%q_hat   + s * dq_hat

                         L1 = NORM2( q_tilde )  ! beamwidth is length of the vector
                         L2 = NORM2( q_hat   )  ! beamwidth

                         IF ( L1 == 0 .OR. L2 == 0 ) THEN
                            ! IF ( ir-1 == 7 .AND. itheta-1 == 59 ) THEN
                            !    WRITE( PRTFile, * ) 'Skipping z b/c L1/L2', iz
                            ! END IF
                            CYCLE ReceiverDepths
                         END IF

                         n  = ABS( DOT_PRODUCT( x_rcvr_ray, e1 ) )         ! normal distance to ray
                         m  = ABS( DOT_PRODUCT( x_rcvr_ray, e2 ) )         ! normal distance to ray

                         ! represent (m, n) as a linear combination a q + b q
                         DetQint = q_tilde( 1 ) * q_hat( 2 ) - q_hat( 1 ) * q_tilde( 2 )   ! area of parallelogram formed by ray tube
                         IF ( DetQint == 0.0 ) THEN
                            ! IF ( ir-1 == 7 .AND. itheta-1 == 59 ) THEN
                            !    WRITE( PRTFile, * ) 'Skipping z b/c DetQint', iz
                            ! END IF
                            CYCLE ReceiverDepths
                         END IF

                         a = ABS( ( -q_hat(   1 ) * m + q_hat(   2 ) * n ) / DetQint )
                         b = ABS( (  q_tilde( 1 ) * m - q_tilde( 2 ) * n ) / DetQint )

                         IF ( a + b > BeamWindow ) THEN
                            ! IF ( ir-1 == 7 .AND. itheta-1 == 59 ) THEN
                            !    WRITE( PRTFile, * ) 'Skipping z b/c outside beam (a+b) BeamWindow', &
                            !      iz, a+b, BeamWindow
                            ! END IF
                            CYCLE ReceiverDepths   ! receiver is outside the beam
                         END IF
                         ! IF ( ir-1 == 7 .AND. itheta-1 == 59 ) THEN
                         !   WRITE( PRTFile, * ) 'q_tilde', q_tilde
                         !   WRITE( PRTFile, * ) 'q_hat  ', q_hat
                         !   WRITE( PRTFile, * ) 'DetQint m n', DetQint, n, m
                         !   WRITE( PRTFile, * ) 'a b', a, b
                         ! END IF

                         delay = ray3D( is - 1 )%tau + s * dtau

                         ! phase shift at caustics
                         phaseInt = ray3D( is - 1 )%Phase + phase
                         IF ( DetQint <= 0.0d0 .AND. Det_QOld > 0.0d0 .OR. &
                              DetQint >= 0.0d0 .AND. Det_QOld < 0.0d0 ) phaseInt = phaseInt + pi / 2.

                         const = ray3D( is )%Amp / SQRT( ABS( DetQint ) )

                         ! calculate the beamwidth (must be at least lambda, except in the nearfield)
                         ! comment out the following 2 lines to turn the stent off
                         !L1_stent  = MAX( L1, MIN( 0.2 * freq * REAL( ray3D( is )%tau ), pi * lambda ) )
                         !L2_stent  = MAX( L2, MIN( 0.2 * freq * REAL( ray3D( is )%tau ), pi * lambda ) )

                         ! Beam shape function (Gaussian)
                         ! The factor involving L1, L2 compensates for the change in intensity when widening the beam

                         !W   = EXP( -.5 * ( n ** 2 + m ** 2 ) ) * L1 / L1_stent * L2 / L2_stent
                         W   = EXP( -.5 * ( a ** 2 + b ** 2 ) )   ! Gaussian
                         Amp = const * W

                         ! IF ( ir-1 == 7 .AND. itheta-1 == 59 ) THEN
                         !    WRITE( PRTFile, * ) 'iz const W delay phaseInt', iz, const, W, delay, phaseInt
                         ! END IF

                         CALL ApplyContribution( alpha, beta, P( itheta, iz, ir ) )
                      END DO ReceiverDepths
                   END DO Radials

                END IF
                ! bump receiver index, ir, towards rB
                IF ( Pos%Rr( ir ) < rB ) THEN
                   IF ( ir >= Pos%NRr ) EXIT Ranges  ! jump out of the search and go to next step on ray
                   irTT = ir + 1                     ! bump right
                   IF ( Pos%Rr( irTT ) >= rB ) EXIT Ranges
                ELSE
                   IF ( ir <= 1  ) EXIT Ranges       ! jump out of the search and go to next step on ray
                   irTT = ir - 1                     ! bump left
                   IF ( Pos%Rr( irTT ) <= rB ) EXIT Ranges
                END IF
                ir = irTT
             END DO Ranges
          END IF
       END IF
       rA = rB
    END DO Stepping

  END SUBROUTINE Influence3DGeoGaussianCart