Reflect2D Subroutine

subroutine Reflect2D(is, HS, BotTop, tBdry, nBdry, kappa, RefC, Npts)

Arguments

Type IntentOptional Attributes Name
integer, intent(inout) :: is
type(HSInfo), intent(in) :: HS
character(len=3), intent(in) :: BotTop
real(kind=8), intent(in) :: tBdry(2)
real(kind=8), intent(in) :: nBdry(2)
real(kind=8), intent(in) :: kappa
type(ReflectionCoef), intent(in) :: RefC(NPts)
integer, intent(in) :: Npts

Calls

proc~~reflect2d~2~~CallsGraph proc~reflect2d~2 Reflect2D datan datan proc~reflect2d~2->datan dcos dcos proc~reflect2d~2->dcos dsin dsin proc~reflect2d~2->dsin proc~errout ERROUT proc~reflect2d~2->proc~errout proc~evaluatessp EvaluateSSP proc~reflect2d~2->proc~evaluatessp proc~interpolatereflectioncoefficient InterpolateReflectionCoefficient proc~reflect2d~2->proc~interpolatereflectioncoefficient proc~evaluatessp->proc~errout proc~analytic Analytic proc~evaluatessp->proc~analytic proc~ccubic cCubic proc~evaluatessp->proc~ccubic proc~clinear cLinear proc~evaluatessp->proc~clinear proc~cpchip cPCHIP proc~evaluatessp->proc~cpchip proc~hexahedral Hexahedral proc~evaluatessp->proc~hexahedral proc~n2linear n2Linear proc~evaluatessp->proc~n2linear proc~quad Quad proc~evaluatessp->proc~quad proc~readssp ReadSSP proc~ccubic->proc~readssp proc~splineall SPLINEALL proc~ccubic->proc~splineall proc~updatedepthsegmentt UpdateDepthSegmentT proc~ccubic->proc~updatedepthsegmentt proc~clinear->proc~readssp proc~clinear->proc~updatedepthsegmentt proc~pchip PCHIP proc~cpchip->proc~pchip proc~cpchip->proc~readssp proc~cpchip->proc~updatedepthsegmentt proc~hexahedral->proc~errout interface~monotonic monotonic proc~hexahedral->interface~monotonic proc~hexahedral->proc~readssp proc~update3dxsegmentt Update3DXSegmentT proc~hexahedral->proc~update3dxsegmentt proc~update3dysegmentt Update3DYSegmentT proc~hexahedral->proc~update3dysegmentt proc~update3dzsegmentt Update3DZSegmentT proc~hexahedral->proc~update3dzsegmentt proc~n2linear->proc~readssp proc~n2linear->proc~updatedepthsegmentt proc~quad->proc~errout proc~quad->interface~monotonic proc~quad->proc~readssp proc~quad->proc~updatedepthsegmentt proc~updaterangesegmentt UpdateRangeSegmentT proc~quad->proc~updaterangesegmentt proc~monotonic_dble monotonic_dble interface~monotonic->proc~monotonic_dble proc~monotonic_sngl monotonic_sngl interface~monotonic->proc~monotonic_sngl proc~cspline CSPLINE proc~pchip->proc~cspline proc~fprime_interior_cmplx fprime_interior_Cmplx proc~pchip->proc~fprime_interior_cmplx proc~fprime_left_end_cmplx fprime_left_end_Cmplx proc~pchip->proc~fprime_left_end_cmplx proc~fprime_right_end_cmplx fprime_right_end_Cmplx proc~pchip->proc~fprime_right_end_cmplx proc~h_del h_del proc~pchip->proc~h_del proc~readssp->proc~errout proc~crci CRCI proc~readssp->proc~crci proc~crci->proc~errout proc~franc_garr Franc_Garr proc~crci->proc~franc_garr proc~fprime_interior fprime_interior proc~fprime_interior_cmplx->proc~fprime_interior proc~fprime_left_end fprime_left_end proc~fprime_left_end_cmplx->proc~fprime_left_end proc~fprime_right_end fprime_right_end proc~fprime_right_end_cmplx->proc~fprime_right_end

Called by

proc~~reflect2d~2~~CalledByGraph proc~reflect2d~2 Reflect2D proc~traceray2d~2 TraceRay2D proc~traceray2d~2->proc~reflect2d~2 proc~bellhopcore~2 BellhopCore proc~bellhopcore~2->proc~traceray2d~2 program~bellhop BELLHOP program~bellhop->proc~bellhopcore~2

Source Code

SUBROUTINE Reflect2D( is, HS, BotTop, tBdry, nBdry, kappa, RefC, Npts )

  INTEGER,              INTENT( IN ) :: Npts
  REAL     (KIND=8),    INTENT( IN ) :: tBdry( 2 ), nBdry( 2 )  ! Tangent and normal to the boundary
  REAL     (KIND=8),    INTENT( IN ) :: kappa                   ! Boundary curvature
  CHARACTER (LEN=3),    INTENT( IN ) :: BotTop                  ! Flag indicating bottom or top reflection
  TYPE( HSInfo ),       INTENT( IN ) :: HS                      ! half-space properties
  TYPE(ReflectionCoef), INTENT( IN ) :: RefC( NPts )            ! reflection coefficient
  INTEGER,              INTENT( INOUT ) :: is
  INTEGER           :: is1
  REAL     (KIND=8) :: c, cimag, gradc( 2 ), crr, crz, czz, rho                  ! derivatives of sound speed
  REAL     (KIND=8) :: RM, RN, Tg, Th, rayt( 2 ), rayn( 2 ), rayt_tilde( 2 ), rayn_tilde( 2 ), cnjump, csjump  ! for curvature change
  REAL     (KIND=8) :: ck, co, si, cco, ssi, pdelta, rddelta, sddelta, theta_bot ! for beam shift
  COMPLEX  (KIND=8) :: kx, kz, kzP, kzS, kzP2, kzS2, mu, f, g, y2, y4, Refl      ! for tabulated reflection coef.
  COMPLEX  (KIND=8) :: ch, a, b, d, sb, delta, ddelta                            ! for beam shift
  TYPE(ReflectionCoef) :: RInt

  is  = is + 1
  is1 = is + 1

  Tg = DOT_PRODUCT( ray2D( is )%t, tBdry )  ! component of ray tangent, along boundary
  Th = DOT_PRODUCT( ray2D( is )%t, nBdry )  ! component of ray tangent, normal to boundary

  ray2D( is1 )%NumTopBnc = ray2D( is )%NumTopBnc
  ray2D( is1 )%NumBotBnc = ray2D( is )%NumBotBnc
  ray2D( is1 )%x         = ray2D( is )%x
  ray2D( is1 )%t         = ray2D( is )%t - 2.0 * Th * nBdry  ! changing the ray direction

  ! Calculate the change in curvature
  ! Based on formulas given by Muller, Geoph. J. R.A.S., 79 (1984).

  CALL EvaluateSSP( ray2D( is )%x, ray2D( is )%t, c, cimag, gradc, crr, crz, czz, rho, freq, 'TAB' )   ! just to get c

  ! incident unit ray tangent and normal
  rayt = c * ray2D( is )%t                              ! unit tangent to ray
  rayn = [ -rayt( 2 ), rayt( 1 ) ]                      ! unit normal  to ray

  ! reflected unit ray tangent and normal (the reflected tangent, normal system has a different orientation)
  rayt_tilde = c * ray2D( is1 )%t                       ! unit tangent to ray
  rayn_tilde = -[ -rayt_tilde( 2 ), rayt_tilde( 1 ) ]   ! unit normal  to ray

  RN = 2 * kappa / c ** 2 / Th    ! boundary curvature correction

  ! get the jumps (this could be simplified, e.g. jump in rayt is roughly 2 * Th * nbdry
  cnjump = -DOT_PRODUCT( gradc, rayn_tilde - rayn )
  csjump = -DOT_PRODUCT( gradc, rayt_tilde - rayt )

  IF ( BotTop == 'TOP' ) THEN
     cnjump = -cnjump   ! this is because the (t,n) system of the top boundary has a different sense to the bottom boundary
     RN     = -RN
  END IF

  RM = Tg / Th   ! this is tan( alpha ) where alpha is the angle of incidence
  RN = RN + RM * ( 2 * cnjump - RM * csjump ) / c ** 2

  SELECT CASE ( Beam%Type( 3 : 3 ) )
  CASE ( 'D' )
     RN = 2.0 * RN
  CASE ( 'Z' )
     RN = 0.0
  END SELECT

  ray2D( is1 )%c   = c
  ray2D( is1 )%tau = ray2D( is )%tau
  ray2D( is1 )%p   = ray2D( is )%p + ray2D( is )%q * RN
  ray2D( is1 )%q   = ray2D( is )%q

  ! account for phase change

  SELECT CASE ( HS%BC )
  CASE ( 'R' )                 ! rigid
     ray2D( is1 )%Amp   = ray2D( is )%Amp
     ray2D( is1 )%Phase = ray2D( is )%Phase
  CASE ( 'V' )                 ! vacuum
     ray2D( is1 )%Amp   = ray2D( is )%Amp
     ray2D( is1 )%Phase = ray2D( is )%Phase + pi
  CASE ( 'F' )                 ! file
     RInt%theta = RadDeg * ABS( ATAN2( Th, Tg ) )           ! angle of incidence (relative to normal to bathymetry)
     IF ( RInt%theta > 90 ) RInt%theta = 180. - RInt%theta  ! reflection coefficient is symmetric about 90 degrees
     CALL InterpolateReflectionCoefficient( RInt, RefC, Npts, PRTFile )
     ray2D( is1 )%Amp   = ray2D( is )%Amp * RInt%R
     ray2D( is1 )%Phase = ray2D( is )%Phase + RInt%phi
  CASE ( 'A', 'G' )            ! half-space
     kx = omega * Tg     ! wavenumber in direction parallel      to bathymetry
     kz = omega * Th     ! wavenumber in direction perpendicular to bathymetry (in ocean)

     ! notation below is a bit misleading
     ! kzS, kzP is really what I called gamma in other codes, and differs by a factor of +/- i
     IF ( REAL( HS%cS ) > 0.0 ) THEN
        kzS2 = kx ** 2 - ( omega / HS%cS ) ** 2
        kzP2 = kx ** 2 - ( omega / HS%cP ) ** 2
        kzS  = SQRT( kzS2 )
        kzP  = SQRT( kzP2 )
        mu   = HS%rho * HS%cS ** 2

        y2 = ( ( kzS2 + kx ** 2 ) ** 2 - 4.0D0 * kzS * kzP * kx ** 2 ) * mu
        y4 = kzP * ( kx ** 2 - kzS2 )

        f = omega ** 2 * y4
        g = y2
     ELSE
        kzP = SQRT( kx ** 2 - ( omega / HS%cP ) ** 2 )

        ! Intel and GFortran compilers return different branches of the SQRT for negative reals
        IF ( REAL( kzP ) == 0.0D0 .AND. AIMAG( kzP ) < 0.0D0 ) kzP = -kzP
        f   = kzP
        g   = HS%rho
     ENDIF

     Refl =  - ( rho * f - i * kz * g ) / ( rho * f + i * kz * g )   ! complex reflection coef.

     IF ( ABS( Refl ) < 1.0E-5 ) THEN   ! kill a ray that has lost its energy in reflection
        ray2D( is1 )%Amp   = 0.0
        ray2D( is1 )%Phase = ray2D( is )%Phase
     ELSE
        ray2D( is1 )%Amp   = ABS( Refl ) * ray2D(  is )%Amp
        ray2D( is1 )%Phase = ray2D( is )%Phase + ATAN2( AIMAG( Refl ), REAL( Refl ) )

        ! compute beam-displacement Tindle, Eq. (14)
        ! needs a correction to beam-width as well ...
        !  IF ( REAL( kz2Sq ) < 0.0 ) THEN
        !     rhoW   = 1.0   ! density of water
        !     rhoWSq  = rhoW  * rhoW
        !     rhoHSSq = rhoHS * rhoHS
        !     DELTA = 2 * GK * rhoW * rhoHS * ( kz1Sq - kz2Sq ) /
        ! &( kz1 * i * kz2 *
        ! &( -rhoWSq * kz2Sq + rhoHSSq * kz1Sq ) )
        !     RV( is + 1 ) = RV( is + 1 ) + DELTA
        !  END IF

        if ( Beam%Type( 4 : 4 ) == 'S' ) then   ! beam displacement & width change (Seongil's version)
           ch = ray2D( is )%c / conjg( HS%cP )
           co = ray2D( is )%t( 1 ) * ray2D( is )%c
           si = ray2D( is )%t( 2 ) * ray2D( is )%c
           ck = omega / ray2D( is )%c

           a   = 2 * HS%rho * ( 1 - ch * ch )
           b   = co * co - ch * ch
           d   = HS%rho * HS%rho * si * si + b
           sb  = sqrt( b )
           cco = co * co
           ssi = si * si

           IF ( si /= 0.0 ) THEN
              delta = a * co / si / ( ck * sb * d )   ! Do we need an abs() on this???
           ELSE
              delta = 0.0
           END IF

           pdelta  = real( delta ) / ( ray2D( is )%c / co)
           ddelta  = -a / ( ck*sb*d ) - a*cco / ssi / (ck*sb*d) + a*cco / (ck*b*sb*d) &
                     -a*co / si / (ck*sb*d*d) * (2* HS%rho * HS%rho *si*co-2*co*si)
           rddelta = -real( ddelta )
           sddelta = rddelta / abs( rddelta )

           ! next 3 lines have an update by Diana McCammon to allow a sloping bottom
           ! I think the formulas are good, but this won't be reliable because it doesn't have the logic
           ! that tracks crossing into new segments after the ray displacement.

           theta_bot = datan( tBdry( 2 ) / tBdry( 1 ))  ! bottom angle
           ray2D( is1 )%x( 1 ) = ray2D( is1 )%x( 1 ) + real( delta ) * dcos( theta_bot )       ! range displacement
           ray2D( is1 )%x( 2 ) = ray2D( is1 )%x( 2 ) + real( delta ) * dsin( theta_bot )       ! depth displacement
           ray2D( is1 )%tau    = ray2D( is1 )%tau + pdelta                                     ! phase change
           ray2D( is1 )%q      = ray2D( is1 )%q + sddelta * rddelta * si * c * ray2D( is )%p   ! beam-width change
        endif

     ENDIF
  CASE DEFAULT
     WRITE( PRTFile, * ) 'HS%BC = ', HS%BC
     CALL ERROUT( 'Reflect2D', 'Unknown boundary condition type' )
  END SELECT

END SUBROUTINE Reflect2D