StepToBdry3D Subroutine

public subroutine StepToBdry3D(x0, x2, urayt, iSegx0, iSegy0, iSegz0, h, topRefl, botRefl, snapDim)

Arguments

Type IntentOptional Attributes Name
real(kind=8), intent(in) :: x0(3)
real(kind=8), intent(inout) :: x2(3)
real(kind=8), intent(in) :: urayt(3)
integer, intent(in) :: iSegx0
integer, intent(in) :: iSegy0
integer, intent(in) :: iSegz0
real(kind=8), intent(inout) :: h
logical, intent(out) :: topRefl
logical, intent(out) :: botRefl
integer, intent(out) :: snapDim

Called by

proc~~steptobdry3d~~CalledByGraph proc~steptobdry3d StepToBdry3D proc~step2d~2 Step2D proc~step2d~2->proc~steptobdry3d proc~step3d Step3D proc~step3d->proc~steptobdry3d proc~traceray2d TraceRay2D proc~traceray2d->proc~step2d~2 proc~traceray3d TraceRay3D proc~traceray3d->proc~step3d proc~bellhopcore BellhopCore proc~bellhopcore->proc~traceray2d proc~bellhopcore->proc~traceray3d program~bellhop3d BELLHOP3D program~bellhop3d->proc~bellhopcore

Source Code

  SUBROUTINE StepToBdry3D( x0, x2, urayt, iSegx0, iSegy0, iSegz0, h, &
    topRefl, botRefl, snapDim )

    INTEGER,       INTENT( IN    ) :: iSegx0, iSegy0, iSegz0
    REAL (KIND=8), INTENT( IN    ) :: x0( 3 ), urayt( 3 )  ! ray coordinate and tangent
    REAL (KIND=8), INTENT( INOUT ) :: x2( 3 ), h           ! output coord, reduced step size
    LOGICAL,       INTENT( OUT   ) :: topRefl, botRefl
    INTEGER,       INTENT( OUT   ) :: snapDim
    REAL (KIND=8) :: d( 3 ), d0( 3 ), tri_n( 3 )
    REAL (KIND=8) :: xSeg( 2 ), ySeg( 2 )                  ! boundary limits
    INTEGER                        :: k
    REAL (KIND=8) :: hnew, over_diag_amount
    LOGICAL       :: newSide, newOnEdge

    ! Original step due to maximum step size
    h = Beam%deltas
    x2 = x0 + h * urayt
    snapDim = -1

    ! interface crossing in depth
    IF ( ABS( urayt( 3 ) ) > EPSILON( h ) ) THEN
       IF      ( SSP%z( iSegz0     ) > x2( 3 ) .AND. iSegz0     > 1  ) THEN
          h  = ( SSP%z( iSegz0     ) - x0( 3 ) ) / urayt( 3 )
          x2 = x0 + h * urayt
          x2( 3 ) = SSP%z( iSegz0 )
          snapDim = 2
          IF ( STEP_DEBUGGING ) &
             WRITE( PRTFile, * ) 'StepToBdry3D shallower h to', h, x2
       ELSE IF ( SSP%z( iSegz0 + 1 ) < x2( 3 ) .AND. iSegz0 + 1 < SSP%Nz ) THEN
          h  = ( SSP%z( iSegz0 + 1 ) - x0( 3 ) ) / urayt( 3 )
          x2 = x0 + h * urayt
          x2( 3 ) = SSP%z( iSegz0 + 1 )
          snapDim = 2
          IF ( STEP_DEBUGGING ) &
             WRITE( PRTFile, * ) 'StepToBdry3D deeper h to', h, x2
       END IF
    END IF

    ! ray mask using a box centered at ( xs_3D( 1 ), xs_3D( 2 ), 0 )
    IF ( ABS( x2( 1 ) - xs_3D( 1 ) ) > Beam%Box%x ) THEN
       h = ( Beam%Box%x - ABS( ( x0( 1 ) - xs_3D( 1 ) ) ) ) / ABS( urayt( 1 ) )
       x2 = x0 + h * urayt
       x2( 1 ) = xs_3D( 1 ) + SIGN( Beam%Box%x, x0( 1 ) - xs_3D( 1 ) )
       snapDim = 0
       IF ( STEP_DEBUGGING ) &
          WRITE( PRTFile, * ) 'StepToBdry3D beam box crossing X h to', h, x2
    END IF
    IF ( ABS( x2( 2 ) - xs_3D( 2 ) ) > Beam%Box%y ) THEN
       h = ( Beam%Box%y - ABS( ( x0( 2 ) - xs_3D( 2 ) ) ) ) / ABS( urayt( 2 ) )
       x2 = x0 + h * urayt
       x2( 2 ) = xs_3D( 2 ) + SIGN( Beam%Box%y, x0( 2 ) - xs_3D( 2 ) )
       snapDim = 1
       IF ( STEP_DEBUGGING ) &
          WRITE( PRTFile, * ) 'StepToBdry3D beam box crossing Y h to', h, x2
    END IF
    IF ( ABS( x2( 3 )              ) > Beam%Box%z ) THEN
       h = ( Beam%Box%z - ABS(   x0( 3 )                ) ) / ABS( urayt( 3 ) )
       x2 = x0 + h * urayt
       x2( 3 ) =              SIGN( Beam%Box%z, x0( 3 )              )
       snapDim = 2
       IF ( STEP_DEBUGGING ) &
          WRITE( PRTFile, * ) 'StepToBdry3D beam box crossing Y h to', h, x2
    END IF

    ! top crossing
    d  = x2 - Topx ! vector from top to ray
    ! LP: Originally, this value had to be > a small positive number, meaning the
    ! new step really had to be outside the boundary, not just to the boundary.
    ! Also, this is not missing a normalization factor, Topn is normalized so
    ! this is actually the distance above the top in meters.
    IF ( DOT_PRODUCT( Topn, d )  > -INFINITESIMAL_STEP_SIZE ) THEN
       d0 = x0 - Topx   ! vector from top    node to ray origin
       h  = -DOT_PRODUCT( d0, Topn ) / DOT_PRODUCT( urayt, Topn )
       x2 = x0 + h * urayt
       ! Snap to exact top depth value if it's flat
       IF ( ABS( Topn( 1 ) ) < EPSILON( Topn( 1 ) ) .AND. ABS( Topn( 2 ) ) < EPSILON( Topn( 2 ) ) ) THEN
          x2( 3 ) = Topx( 3 )
       END IF
       snapDim = 2 ! Even if not flat, exactness in Z most important
       IF ( STEP_DEBUGGING ) &
          WRITE( PRTFile, * ) 'StepToBdry3D top crossing h to', h, x2
       topRefl = .TRUE.
    ELSE
       topRefl = .FALSE.
    END IF

    ! bottom crossing
    d  = x2 - Botx ! vector from bottom to ray
    ! LP: See comment above for top case.
    IF ( DOT_PRODUCT( Botn, d ) > -INFINITESIMAL_STEP_SIZE ) THEN
       d0 = x0 - Botx   ! vector from bottom node to ray origin
       h  = -DOT_PRODUCT( d0, Botn ) / DOT_PRODUCT( urayt, Botn )
       x2 = x0 + h * urayt
       ! Snap to exact bottom depth value if it's flat
       IF ( ABS( Botn( 1 ) ) < EPSILON( Botn( 1 ) ) .AND. ABS( Botn( 2 ) ) < EPSILON( Botn( 2 ) ) ) THEN
          x2( 3 ) = Botx( 3 )
       END IF
       snapDim = 2 ! Even if not flat, exactness in Z most important
       IF ( STEP_DEBUGGING ) &
          WRITE( PRTFile, * ) 'StepToBdry3D bottom crossing h to', h, x2
       botRefl = .TRUE.
       ! Should not ever be able to cross both, but in case it does, make sure
       ! only the crossing we exactly landed on is active
       topRefl = .FALSE.
    ELSE
       botRefl = .FALSE.
    END IF

    ! top/bottom segment crossing in x
    xSeg( 1 ) = MAX( xTopSeg( 1 ), xBotSeg( 1 ) ) ! LP: lower range bound (not an x value)
    xSeg( 2 ) = MIN( xTopSeg( 2 ), xBotSeg( 2 ) ) ! LP: upper range bound (not a y value)

    IF ( SSP%Type == 'H' ) THEN   ! ocean segment
       xSeg( 1 ) = MAX( xSeg( 1 ), SSP%Seg%x( iSegx0     ) )
       xSeg( 2 ) = MIN( xSeg( 2 ), SSP%Seg%x( iSegx0 + 1 ) )
    END IF

    IF ( ABS( urayt( 1 ) ) > EPSILON( h ) ) THEN
       IF       ( x2( 1 ) < xSeg( 1 ) ) THEN
          h  = -( x0( 1 ) - xSeg( 1 ) ) / urayt( 1 )
          x2 = x0 + h * urayt
          x2( 1 ) = xSeg( 1 )
          snapDim = 0
          topRefl = .FALSE.
          botRefl = .FALSE.
          IF ( STEP_DEBUGGING ) &
             WRITE( PRTFile, * ) 'StepToBdry3D X min bound h to', h, x2
       ELSE IF  ( x2( 1 ) > xSeg( 2 ) ) THEN
          h  = -( x0( 1 ) - xSeg( 2 ) ) / urayt( 1 )
          x2 = x0 + h * urayt
          x2( 1 ) = xSeg( 2 )
          snapDim = 0
          topRefl = .FALSE.
          botRefl = .FALSE.
          IF ( STEP_DEBUGGING ) &
             WRITE( PRTFile, * ) 'StepToBdry3D X max bound h to', h, x2
       END IF
    END IF

    ! top/bottom segment crossing in y
    ySeg( 1 ) = MAX( yTopSeg( 1 ), yBotSeg( 1 ) )
    ySeg( 2 ) = MIN( yTopSeg( 2 ), yBotSeg( 2 ) )

    IF ( SSP%Type == 'H' ) THEN   ! ocean segment
       ySeg( 1 ) = MAX( ySeg( 1 ), SSP%Seg%y( iSegy0     ) )
       ySeg( 2 ) = MIN( ySeg( 2 ), SSP%Seg%y( iSegy0 + 1 ) )
    END IF

    ! LP: removed 1000 * epsilon which mbp had comment questioning also
    IF ( ABS( urayt( 2 ) ) > EPSILON( h ) ) THEN
       IF       ( x2( 2 ) < ySeg( 1 ) ) THEN
          h  = -( x0( 2 ) - ySeg( 1 ) ) / urayt( 2 )
          x2 = x0 + h * urayt
          x2( 2 ) = ySeg( 1 )
          snapDim = 1
          topRefl = .FALSE.
          botRefl = .FALSE.
          IF ( STEP_DEBUGGING ) &
             WRITE( PRTFile, * ) 'StepToBdry3D Y min bound h to', h, x2
       ELSE IF  ( x2( 2 ) > ySeg( 2 ) ) THEN
          h  = -( x0( 2 ) - ySeg( 2 ) ) / urayt( 2 )
          x2 = x0 + h * urayt
          x2( 2 ) = ySeg( 2 )
          snapDim = 1
          topRefl = .FALSE.
          botRefl = .FALSE.
          IF ( STEP_DEBUGGING ) &
             WRITE( PRTFile, * ) 'StepToBdry3D Y max bound h to', h, x2
       END IF
    END IF

    ! triangle crossing within a top segment
    IF ( .NOT. Top_td_onEdge ) THEN
       d     = x2 - Topxmid   ! vector from top    center to ray end
       d0    = x0 - Topxmid   ! vector from top    center to ray origin
       tri_n = [ -( yTopSeg( 2 ) - yTopSeg( 1 ) ), xTopSeg( 2 ) - xTopSeg( 1 ), 0.0d0 ]
       tri_n = tri_n / NORM2( tri_n )
       over_diag_amount = DOT_PRODUCT( d, tri_n )
       newSide = ( over_diag_amount >= 0.0D0 )
       IF ( newSide .NEQV. Top_td_side ) THEN
          newOnEdge = ( ABS( over_diag_amount ) < TRIDIAG_THRESH )
          IF ( newOnEdge ) THEN
             IF ( STEP_DEBUGGING ) &
                WRITE( PRTFile, * ) 'StepToBdry3D Top naturally stepped to tri diag edge, h over_diag_amount', &
                   over_diag_amount
          ELSE
             hnew = -DOT_PRODUCT( d0, tri_n ) / DOT_PRODUCT( urayt, tri_n )
             IF ( hnew < 0.0D0 ) THEN
                WRITE( PRTFile, * ) 'StepToBdry3D Top BHC_WARN_TRIDIAG_H_NEGATIVE'
                h = 0.0D0
             ELSE
                IF ( hnew >= h ) &
                   WRITE( PRTFile, * ) 'StepToBdry3D Top BHC_WARN_TRIDIAG_H_GROWING'
                h = hnew
             END IF
             IF ( STEP_DEBUGGING ) &
                WRITE( PRTFile, * ) 'StepToBdry3D Top tri diag crossing hnew dot(n, d0) dot(n, d)', &
                   hnew, DOT_PRODUCT( tri_n, d0 ), over_diag_amount
             x2 = x0 + h * urayt
             Top_td_justSteppedTo = .TRUE.
             Top_td_outgoingSide = newSide
             snapDim = -2
             topRefl = .FALSE.
             botRefl = .FALSE.
          END IF
       END IF
    END IF

    ! triangle crossing within a bottom segment
    IF ( .NOT. Bot_td_onEdge ) THEN
       d     = x2 - Botxmid   ! vector from bottom center to ray end
       d0    = x0 - Botxmid   ! vector from bottom center to ray origin
       tri_n = [ -( yBotSeg( 2 ) - yBotSeg( 1 ) ), xBotSeg( 2 ) - xBotSeg( 1 ), 0.0d0 ]
       tri_n = tri_n / NORM2( tri_n )
       over_diag_amount = DOT_PRODUCT( d, tri_n )
       newSide = ( over_diag_amount >= 0.0D0 )
       IF ( newSide .NEQV. Bot_td_side ) THEN
          newOnEdge = ( ABS( over_diag_amount ) < TRIDIAG_THRESH )
          IF ( newOnEdge ) THEN
             IF ( STEP_DEBUGGING ) &
                WRITE( PRTFile, * ) 'StepToBdry3D Bot naturally stepped to tri diag edge, h over_diag_amount', &
                   over_diag_amount
          ELSE
             hnew = -DOT_PRODUCT( d0, tri_n ) / DOT_PRODUCT( urayt, tri_n )
             IF ( hnew < 0.0D0 ) THEN
                WRITE( PRTFile, * ) 'StepToBdry3D Bot BHC_WARN_TRIDIAG_H_NEGATIVE'
                h = 0.0D0
             ELSE
                IF ( hnew >= h ) &
                   WRITE( PRTFile, * ) 'StepToBdry3D Bot BHC_WARN_TRIDIAG_H_GROWING'
                h = hnew
             END IF
             IF ( STEP_DEBUGGING ) &
                WRITE( PRTFile, * ) 'StepToBdry3D Bot tri diag crossing hnew dot(n, d0) dot(n, d)', &
                   hnew, DOT_PRODUCT( tri_n, d0 ), over_diag_amount
             x2 = x0 + h * urayt
             Bot_td_justSteppedTo = .TRUE.
             Bot_td_outgoingSide = newSide
             snapDim = -2
             topRefl = .FALSE.
             botRefl = .FALSE.
          END IF
       END IF
    END IF

    IF ( h < INFINITESIMAL_STEP_SIZE * Beam%deltas ) THEN        ! is it taking an infinitesimal step?
       h = INFINITESIMAL_STEP_SIZE * Beam%deltas                 ! make sure we make some motion
       x2 = x0 + h * urayt
       snapDim = -1
       IF ( STEP_DEBUGGING ) &
          WRITE( PRTFile, * ) 'StepToBdry3D small step forced h to ', h, x2
       ! Recheck reflection conditions
       d = x2 - Topx ! vector from top to ray
       IF ( DOT_PRODUCT( Topn, d ) > EPSILON( d( 1 ) ) ) THEN
          topRefl = .TRUE.
          Top_td_justSteppedTo = .FALSE.
          Bot_td_justSteppedTo = .FALSE.
          snapDim = 2
       ELSE
          topRefl = .FALSE.
       END IF
       d = x2 - Botx ! vector from bottom to ray
       IF ( DOT_PRODUCT( Botn, d ) > EPSILON( d( 1 ) ) ) THEN
          botRefl = .TRUE.
          topRefl = .FALSE.
          Top_td_justSteppedTo = .FALSE.
          Bot_td_justSteppedTo = .FALSE.
          snapDim = 2
       ELSE
          botRefl = .FALSE.
       END IF
    ELSE
       IF ( STEP_DEBUGGING ) &
          WRITE( PRTFile, * ) 'StepToBdry3D regular h to ', h, x2
    END IF
  END SUBROUTINE StepToBdry3D