TraceRay2D Subroutine

subroutine TraceRay2D(xs, alpha, Amp0)

Uses

  • proc~~traceray2d~2~~UsesGraph proc~traceray2d~2 TraceRay2D module~step Step proc~traceray2d~2->module~step module~writeray WriteRay proc~traceray2d~2->module~writeray module~bellhopmod bellhopMod module~step->module~bellhopmod module~sspmod sspmod module~step->module~sspmod module~writeray->module~bellhopmod module~writeray->module~sspmod module~mathconstants MathConstants module~bellhopmod->module~mathconstants module~fatalerror FatalError module~sspmod->module~fatalerror module~monotonicmod monotonicMod module~sspmod->module~monotonicmod module~splinec splinec module~sspmod->module~splinec

Traces the beam corresponding to a particular take-off angle

Arguments

Type IntentOptional Attributes Name
real(kind=8), intent(in) :: xs(2)
real(kind=8), intent(in) :: alpha
real(kind=8), intent(in) :: Amp0

Calls

proc~~traceray2d~2~~CallsGraph proc~traceray2d~2 TraceRay2D proc~distances2d Distances2D proc~traceray2d~2->proc~distances2d proc~evaluatessp EvaluateSSP proc~traceray2d~2->proc~evaluatessp proc~getbotseg GetBotSeg proc~traceray2d~2->proc~getbotseg proc~gettopseg GetTopSeg proc~traceray2d~2->proc~gettopseg proc~reflect2d~2 Reflect2D proc~traceray2d~2->proc~reflect2d~2 proc~step2d Step2D proc~traceray2d~2->proc~step2d 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~errout ERROUT proc~evaluatessp->proc~errout proc~hexahedral Hexahedral proc~evaluatessp->proc~hexahedral proc~n2linear n2Linear proc~evaluatessp->proc~n2linear proc~quad Quad proc~evaluatessp->proc~quad proc~getbotseg->proc~errout proc~gettopseg->proc~errout proc~reflect2d~2->proc~evaluatessp datan datan proc~reflect2d~2->datan dcos dcos proc~reflect2d~2->dcos dsin dsin proc~reflect2d~2->dsin proc~reflect2d~2->proc~errout proc~interpolatereflectioncoefficient InterpolateReflectionCoefficient proc~reflect2d~2->proc~interpolatereflectioncoefficient proc~step2d->proc~evaluatessp proc~reducestep2d ReduceStep2D proc~step2d->proc~reducestep2d proc~steptobdry2d StepToBdry2D proc~step2d->proc~steptobdry2d 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~~traceray2d~2~~CalledByGraph proc~traceray2d~2 TraceRay2D proc~bellhopcore~2 BellhopCore proc~bellhopcore~2->proc~traceray2d~2 program~bellhop BELLHOP program~bellhop->proc~bellhopcore~2

Source Code

SUBROUTINE TraceRay2D( xs, alpha, Amp0 )
!! Traces the beam corresponding to a particular take-off angle

  USE Step
  USE WriteRay

  REAL     (KIND=8), INTENT( IN ) :: xs( 2 )      ! x-y coordinate of the source
  REAL     (KIND=8), INTENT( IN ) :: alpha, Amp0  ! initial angle, amplitude
  INTEGER           :: is, is1                    ! index for a step along the ray
  REAL     (KIND=8) :: c, cimag, gradc( 2 ), crr, crz, czz, rho
  REAL     (KIND=8) :: dEndTop( 2 ), dEndBot( 2 ), TopnInt( 2 ), BotnInt( 2 ), ToptInt( 2 ), BottInt( 2 )
  REAL     (KIND=8) :: DistBegTop, DistEndTop, DistBegBot, DistEndBot ! Distances from ray beginning, end to top and bottom
  REAL     (KIND=8) :: sss
  REAL     (KIND=8) :: tinit( 2 )
  LOGICAL           :: topRefl, botRefl

  ! Initial conditions

  ! LP: This initialization was missing (only done once globally). In some cases
  ! (a source on a boundary), in conjunction with other subtle issues, the
  ! missing initialization caused the initial state of one ray to be dependent
  ! on the final state of the previous ray, which is obviously non-physical.
  iSegz = 1
  iSegr = 1

  iSmallStepCtr = 0
  tinit = [ COS( alpha ), SIN( alpha ) ]
  CALL EvaluateSSP( xs, tinit, c, cimag, gradc, crr, crz, czz, rho, freq, 'TAB' )
  ray2D( 1 )%c         = c
  ray2D( 1 )%x         = xs
  ray2D( 1 )%t         = tinit / c
  ray2D( 1 )%p         = [ 1.0, 0.0 ]
  ray2D( 1 )%q         = [ 0.0, 1.0 ]
  ray2D( 1 )%tau       = 0.0
  ray2D( 1 )%Amp       = Amp0
  ray2D( 1 )%Phase     = 0.0
  ray2D( 1 )%NumTopBnc = 0
  ray2D( 1 )%NumBotBnc = 0

  ! second component of qv is not used in geometric beam tracing
  ! set I.C. to 0 in hopes of saving run time
  IF ( Beam%RunType( 2 : 2 ) == 'G' ) ray2D( 1 )%q = [ 0.0, 0.0 ]

  CALL GetTopSeg( xs( 1 ), ray2D( 1 )%t( 1 ) )   ! identify the top    segment above the source
  CALL GetBotSeg( xs( 1 ), ray2D( 1 )%t( 1 ) )   ! identify the bottom segment below the source

  ! convert range-dependent geoacoustic parameters from user to program units
  ! compiler is not accepting the copy of the whole structure at once ...
  IF ( atiType( 2 : 2 ) == 'L' ) THEN
     Bdry%Top%HS%cp  = Top( IsegTop )%HS%cp   ! grab the geoacoustic info for the new segment
     Bdry%Top%HS%cs  = Top( IsegTop )%HS%cs
     Bdry%Top%HS%rho = Top( IsegTop )%HS%rho
  END IF

  IF ( btyType( 2 : 2 ) == 'L' ) THEN
     Bdry%Bot%HS%cp  = Bot( IsegBot )%HS%cp
     Bdry%Bot%HS%cs  = Bot( IsegBot )%HS%cs
     Bdry%Bot%HS%rho = Bot( IsegBot )%HS%rho
  END IF

  ! Trace the beam (note that Reflect alters the step index, is)
  is = 0
  CALL Distances2D( ray2D( 1 )%x, Top( IsegTop )%x, Bot( IsegBot )%x, dEndTop,    dEndBot,  &
       Top( IsegTop )%n, Bot( IsegBot )%n, DistBegTop, DistBegBot )

  IF ( DistBegTop <= 0 .OR. DistBegBot <= 0 ) THEN
     Beam%Nsteps = 1
     WRITE( PRTFile, * ) 'Terminating the ray trace because the source is on or outside the boundaries'
     RETURN       ! source must be within the medium
  END IF

  ! LP: Changed from loop istep to MaxN-1, as is will hit MaxN-3 first.
  Stepping: DO WHILE ( .TRUE. )
     is  = is + 1
     is1 = is + 1

     CALL Step2D( ray2D( is ), ray2D( is1 ),  &
          topRefl, botRefl, &
          Top( IsegTop )%x, Top( IsegTop )%n, &
          Bot( IsegBot )%x, Bot( IsegBot )%n )

     ! New altimetry segment?
     IF (        ray2D( is1 )%x( 1 )  < rTopSeg( 1 ) &
          .OR. ( ray2D( is1 )%x( 1 ) == rTopSeg( 1 ) .AND. ray2D( is1 )%t( 1 ) <  0.0 ) &
          .OR.   ray2D( is1 )%x( 1 )  > rTopSeg( 2 ) &
          .OR. ( ray2D( is1 )%x( 1 ) == rTopSeg( 2 ) .AND. ray2D( is1 )%t( 1 ) >= 0.0 )) THEN
        CALL GetTopSeg( ray2D( is1 )%x( 1 ), ray2D( is1 )%t( 1 ) )
        IF ( atiType( 2 : 2 ) == 'L' ) THEN
           Bdry%Top%HS%cp  = Top( IsegTop )%HS%cp   ! grab the geoacoustic info for the new segment
           Bdry%Top%HS%cs  = Top( IsegTop )%HS%cs
           Bdry%Top%HS%rho = Top( IsegTop )%HS%rho
        END IF
     END IF

     ! New bathymetry segment?
     IF (        ray2D( is1 )%x( 1 )  < rBotSeg( 1 ) &
          .OR. ( ray2D( is1 )%x( 1 ) == rBotSeg( 1 ) .AND. ray2D( is1 )%t( 1 ) <  0.0 ) &
          .OR.   ray2D( is1 )%x( 1 )  > rBotSeg( 2 ) &
          .OR. ( ray2D( is1 )%x( 1 ) == rBotSeg( 2 ) .AND. ray2D( is1 )%t( 1 ) >= 0.0 )) THEN
        CALL GetBotSeg( ray2D( is1 )%x( 1 ), ray2D( is1 )%t( 1 ) )
        IF ( btyType( 2 : 2 ) == 'L' ) THEN
           Bdry%Bot%HS%cp  = Bot( IsegBot )%HS%cp   ! grab the geoacoustic info for the new segment
           Bdry%Bot%HS%cs  = Bot( IsegBot )%HS%cs
           Bdry%Bot%HS%rho = Bot( IsegBot )%HS%rho
        END IF
     END IF

     ! Reflections?
     ! Tests that ray at step is is inside, and ray at step is+1 is outside
     ! to detect only a crossing from inside to outside
     ! DistBeg is the distance at step is,   which is saved
     ! DistEnd is the distance at step is+1, which needs to be calculated

     CALL Distances2D( ray2D( is1 )%x, Top( IsegTop )%x, Bot( IsegBot )%x, dEndTop,    dEndBot,  &
          Top( IsegTop )%n, Bot( IsegBot )%n, DistEndTop, DistEndBot )

     IF      ( topRefl ) THEN
        ! WRITE( PRTFile, * ) 'Top reflecting'
        IF ( atiType == 'C' ) THEN
           sss     = DOT_PRODUCT( dEndTop, Top( IsegTop )%t ) / Top( IsegTop )%Len   ! proportional distance along segment
           TopnInt = ( 1 - sss ) * Top( IsegTop )%Noden + sss * Top( 1 + IsegTop )%Noden
           ToptInt = ( 1 - sss ) * Top( IsegTop )%Nodet + sss * Top( 1 + IsegTop )%Nodet
        ELSE
           TopnInt = Top( IsegTop )%n   ! normal is constant in a segment
           ToptInt = Top( IsegTop )%t
        END IF

        CALL Reflect2D( is, Bdry%Top%HS, 'TOP', ToptInt, TopnInt, Top( IsegTop )%kappa, RTop, NTopPTS )
        ray2D( is + 1 )%NumTopBnc = ray2D( is )%NumTopBnc + 1

        CALL Distances2D( ray2D( is + 1 )%x, Top( IsegTop )%x, Bot( IsegBot )%x, dEndTop,    dEndBot,  &
             Top( IsegTop )%n, Bot( IsegBot )%n, DistEndTop, DistEndBot )

     ELSE IF ( botRefl ) THEN
        ! WRITE( PRTFile, * ) 'Bottom reflecting'
        IF ( btyType == 'C' ) THEN
           sss     = DOT_PRODUCT( dEndBot, Bot( IsegBot )%t ) / Bot( IsegBot )%Len   ! proportional distance along segment
           BotnInt = ( 1 - sss ) * Bot( IsegBot )%Noden + sss * Bot( 1 + IsegBot )%Noden
           BottInt = ( 1 - sss ) * Bot( IsegBot )%Nodet + sss * Bot( 1 + IsegBot )%Nodet
        ELSE
           BotnInt = Bot( IsegBot )%n   ! normal is constant in a segment
           BottInt = Bot( IsegBot )%t
        END IF

        CALL Reflect2D( is, Bdry%Bot%HS, 'BOT', BottInt, BotnInt, Bot( IsegBot )%kappa, RBot, NBotPTS )
        ray2D( is + 1 )%NumBotBnc = ray2D( is )%NumBotBnc + 1
        CALL Distances2D( ray2D( is + 1 )%x, Top( IsegTop )%x, Bot( IsegBot )%x, dEndTop,    dEndBot, &
             Top( IsegTop )%n, Bot( IsegBot )%n, DistEndTop, DistEndBot )

     END IF

     ! Has the ray left the box, lost its energy, escaped the boundaries, or exceeded storage limit?
     ! There is a test here for when two adjacent ray points are outside the boundaries
     ! BELLHOP3D handles this differently using a counter-limit for really small steps.
     IF ( ABS( ray2D( is + 1 )%x( 1 ) ) >= Beam%Box%r .OR. &
          ABS( ray2D( is + 1 )%x( 2 ) ) >= Beam%Box%z .OR. ray2D( is + 1 )%Amp < 0.005 .OR. &
          ( DistBegTop < 0.0 .AND. DistEndTop < 0.0 ) .OR. &
          ( DistBegBot < 0.0 .AND. DistEndBot < 0.0 ) ) THEN
          ! ray2D( is + 1 )%t( 1 ) < 0 ) THEN ! this last test kills off a backward traveling ray
        Beam%Nsteps = is + 1
        EXIT Stepping
     ELSE IF ( is >= MaxN - 3 ) THEN
        WRITE( PRTFile, * ) 'Warning in TraceRay2D : Insufficient storage for ray trajectory'
        Beam%Nsteps = is
        EXIT Stepping
     END IF

     DistBegTop = DistEndTop
     DistBegBot = DistEndBot

  END DO Stepping
END SUBROUTINE TraceRay2D