GetTopSeg3D Subroutine

public subroutine GetTopSeg3D(x, t, isInit)

Gets the Top segment info

Arguments

Type IntentOptional Attributes Name
real(kind=8), intent(in) :: x(3)
real(kind=8), intent(in) :: t(3)
logical, intent(in) :: isInit

Calls

proc~~gettopseg3d~~CallsGraph proc~gettopseg3d GetTopSeg3D proc~errout ERROUT proc~gettopseg3d->proc~errout

Called by

proc~~gettopseg3d~~CalledByGraph proc~gettopseg3d GetTopSeg3D proc~traceray2d TraceRay2D proc~traceray2d->proc~gettopseg3d proc~traceray3d TraceRay3D proc~traceray3d->proc~gettopseg3d proc~bellhopcore BellhopCore proc~bellhopcore->proc~traceray2d proc~bellhopcore->proc~traceray3d program~bellhop3d BELLHOP3D program~bellhop3d->proc~bellhopcore

Source Code

  SUBROUTINE GetTopSeg3D( x, t, isInit )
!! Gets the Top segment info

    ! Get the Top segment info (index and range interval) for XY position, x
    ! sets Topx and Topn
    ! LP: See discussion of changes in README.md.

    INTEGER, PARAMETER :: PRTFile = 6
    REAL (KIND=8), INTENT( IN ) :: x( 3 ), t( 3 )
    LOGICAL,       INTENT( IN ) :: isInit
    INTEGER :: nx, ny
    REAL (KIND=8) :: Top_tri_n( 2 )   ! triangle normals
    REAL (KIND=8) :: over_diag_amount

    nx = NatiPts( 1 )
    ny = NatiPts( 2 )

    IsegTopx = MIN( MAX( IsegTopx, 1 ), nx - 1 )
    IsegTopy = MIN( MAX( IsegTopy, 1 ), ny - 1 )

    IF ( t( 1 ) >= 0.0 ) THEN
       DO WHILE ( IsegTopx >= 1 .AND. Top( IsegTopx, 1 )%x( 1 ) > x( 1 ) )
          IsegTopx = IsegTopx - 1
       END DO
       DO WHILE ( IsegTopx >= 1 .AND. IsegTopx < nx .AND. Top( IsegTopx + 1, 1 )%x( 1 ) <= x( 1 ) )
          IsegTopx = IsegTopx + 1
       END DO
    ELSE
      DO WHILE ( IsegTopx < nx .AND. Top( IsegTopx + 1, 1 )%x( 1 ) < x( 1 ) )
         IsegTopx = IsegTopx + 1
      END DO
      DO WHILE ( IsegTopx >= 1 .AND. IsegTopx < nx .AND. Top( IsegTopx, 1 )%x( 1 ) >= x( 1 ) )
         IsegTopx = IsegTopx - 1
      END DO
    END IF
    IF ( t( 2 ) >= 0.0 ) THEN
      DO WHILE ( IsegTopy >= 1 .AND. Top( 1, IsegTopy )%x( 2 ) > x( 2 ) )
         IsegTopy = IsegTopy - 1
      END DO
      DO WHILE ( IsegTopy >= 1 .AND. IsegTopy < ny .AND. Top( 1, IsegTopy + 1 )%x( 2 ) <= x( 2 ) )
         IsegTopy = IsegTopy + 1
      END DO
    ELSE
      DO WHILE ( IsegTopy < ny .AND. Top( 1, IsegTopy + 1 )%x( 2 ) < x( 2 ) )
         IsegTopy = IsegTopy + 1
      END DO
      DO WHILE ( IsegTopy >= 1 .AND. IsegTopy < ny .AND. Top( 1, IsegTopy )%x( 2 ) >= x( 2 ) )
         IsegTopy = IsegTopy - 1
      END DO
    END IF

    IF ( IsegTopx ==  0 .AND. Top(  1,  1 )%x( 1 ) == x( 1 ) ) IsegTopx = 1
    IF ( IsegTopx == nx .AND. Top( nx,  1 )%x( 1 ) == x( 1 ) ) IsegTopx = nx - 1
    IF ( IsegTopy ==  0 .AND. Top(  1,  1 )%x( 2 ) == x( 2 ) ) IsegTopy = 1
    IF ( IsegTopy == ny .AND. Top(  1, ny )%x( 2 ) == x( 2 ) ) IsegTopy = ny - 1

    IF ( IsegTopx <= 0 .OR. IsegTopx >= nx .OR. IsegTopy <= 0 .OR. IsegTopy >= ny ) THEN
       WRITE( PRTFile, * ) 'Warning: GetTopSeg3D: Top altimetry undefined above the ray, x', x
       IsegTopx = MIN( MAX( IsegTopx, 1 ), nx - 1 )
       IsegTopy = MIN( MAX( IsegTopy, 1 ), ny - 1 )
    END IF


    xTopSeg  = [ Top( IsegTopx, 1 )%x( 1 ), Top( IsegTopx + 1, 1 )%x( 1 ) ]   ! segment limits in range
    yTopSeg  = [ Top( 1, IsegTopy )%x( 2 ), Top( 1, IsegTopy + 1 )%x( 2 ) ]   ! segment limits in range

    Topx = Top( IsegTopx, IsegTopy )%x
    Topxmid = ( Topx + Top( IsegTopx + 1, IsegTopy + 1 )%x ) * 0.5D0

    ! WRITE( PRTFile, * ) 'IsegTop', IsegTopx, IsegTopy
    ! WRITE( PRTFile, * ) 'Topx x', Topx, x

    ! identify the normal based on the active triangle of a pair
    ! normal of triangle side pointing up and to the left
    Top_tri_n = [ -( yTopSeg( 2 ) - yTopSeg( 1 ) ), xTopSeg( 2 ) - xTopSeg( 1 ) ]
    Top_tri_n = Top_tri_n / NORM2( Top_tri_n )
    over_diag_amount = DOT_PRODUCT( x( 1 : 2 ) - Topxmid( 1 : 2 ), Top_tri_n )
    Top_td_onEdge = ( ABS( over_diag_amount ) < TRIDIAG_THRESH )
    ! WRITE( PRTFile, * ) 'Top_tri_n over_diag_amount', Top_tri_n, over_diag_amount
    IF ( .NOT. isInit .AND. Top_td_justSteppedTo ) THEN
       Top_td_side = Top_td_outgoingSide
    ELSE IF ( .NOT. isInit .AND. Top_td_onEdge ) THEN
       Top_td_side = ( DOT_PRODUCT( t( 1 : 2 ), Top_tri_n ) >= 0.0D0 )
    ELSE
       Top_td_side = ( over_diag_amount >= 0.0D0 )
    END IF
    Top_td_justSteppedTo = .FALSE.
    IF ( .NOT. Top_td_side ) THEN
       Topn = Top( IsegTopx, IsegTopy )%n1
    ELSE
       Topn = Top( IsegTopx, IsegTopy )%n2
    END IF

    ! if the Bot depth is bad (a NaN) then error out
    ! LP: Originally set segment to invalid and relied on later code to catch this.
    IF ( ISNAN( Topx( 3 ) ) .OR. ANY( ISNAN( Topn ) ) ) THEN
       WRITE( PRTFile, * ) 'Error: Boundary segment contains NaN!'
       CALL ERROUT( 'BELLHOP: GetTopSeg3D', 'Boundary segment contains NaN' )
    END IF
  END SUBROUTINE GetTopSeg3D