Skip to content

Commit 54d6e15

Browse files
committed
updates point search in neighbor elements
1 parent 9916735 commit 54d6e15

File tree

1 file changed

+70
-20
lines changed

1 file changed

+70
-20
lines changed

src/specfem3D/locate_point.f90

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,9 @@ end subroutine find_local_coordinates
534534
!-------------------------------------------------------------------------------------------------
535535
!
536536

537-
subroutine find_best_neighbor(x_target,y_target,z_target,xi,eta,gamma,x,y,z,ispec_selected,distmin_squared,POINT_CAN_BE_BURIED)
537+
subroutine find_best_neighbor(x_target,y_target,z_target, &
538+
xi_found,eta_found,gamma_found,x_found,y_found,z_found, &
539+
ispec_selected,final_distmin_squared,POINT_CAN_BE_BURIED)
538540

539541
use constants_solver, only: &
540542
NGLLX,NGLLY,NGLLZ,MIDX,MIDY,MIDZ
@@ -557,11 +559,11 @@ subroutine find_best_neighbor(x_target,y_target,z_target,xi,eta,gamma,x,y,z,ispe
557559
implicit none
558560

559561
double precision,intent(in) :: x_target,y_target,z_target
560-
double precision,intent(inout) :: xi,eta,gamma
561-
double precision,intent(inout) :: x,y,z
562+
double precision,intent(inout) :: xi_found,eta_found,gamma_found
563+
double precision,intent(inout) :: x_found,y_found,z_found
562564

563565
integer,intent(inout) :: ispec_selected
564-
double precision,intent(inout) :: distmin_squared
566+
double precision,intent(inout) :: final_distmin_squared
565567
logical,intent(in) :: POINT_CAN_BE_BURIED
566568

567569
! local parameters
@@ -582,17 +584,25 @@ subroutine find_best_neighbor(x_target,y_target,z_target,xi,eta,gamma,x,y,z,ispe
582584

583585
integer :: ii,jj,i_n,ientry,ispec_ref
584586
logical :: do_neighbor
587+
logical :: is_better_location
588+
589+
! for close points
590+
double precision, parameter :: TOL_POINT_DISTANCE = 1.d-10
591+
! for close points relative to each other
592+
double precision, parameter :: TOL_RELATIVE_POINT_DISTANCE = 1.d-15
585593

586594
! verbose output
587595
logical,parameter :: DEBUG = .false.
588596

589597
! best distance to target .. so far
590-
distmin_squared = (x_target - x)*(x_target - x) &
591-
+ (y_target - y)*(y_target - y) &
592-
+ (z_target - z)*(z_target - z)
598+
dx = x_target - x_found
599+
dy = y_target - y_found
600+
dz = z_target - z_found
601+
final_distmin_squared = dx*dx + dy*dy + dz*dz
593602

594603
!debug
595-
if (DEBUG) print *,'neighbors: best guess ',ispec_selected,xi,eta,gamma,'distance',sngl(sqrt(distmin_squared)*R_PLANET_KM)
604+
if (DEBUG) print *,'neighbors: best guess ',ispec_selected,xi_found,eta_found,gamma_found, &
605+
'distance',sngl(sqrt(final_distmin_squared)*R_PLANET_KM)
596606

597607
! fill neighbors arrays
598608
!
@@ -704,29 +714,69 @@ subroutine find_best_neighbor(x_target,y_target,z_target,xi,eta,gamma,x,y,z,ispe
704714

705715
! debug
706716
if (DEBUG) print *,' neighbor ',ispec,i_n,ientry,'ispec = ',ispec_selected,sngl(xi_n),sngl(eta_n),sngl(gamma_n), &
707-
'distance',sngl(sqrt(dist_squared)*R_PLANET_KM),sngl(sqrt(distmin_squared)*R_PLANET_KM)
717+
'distance',sngl(sqrt(dist_squared)*R_PLANET_KM),sngl(sqrt(final_distmin_squared)*R_PLANET_KM)
718+
719+
! flag to determine if taking new position
720+
is_better_location = .false.
721+
722+
! if we found a close point
723+
if (dist_squared < TOL_POINT_DISTANCE) then
724+
! checks if position within element
725+
if (abs(xi_n) <= 1.d0 .and. abs(eta_n) <= 1.d0 .and. abs(gamma_n) <= 1.d0) then
726+
! takes position if old position has xi/eta/gamma outside of element
727+
if (abs(xi_found) > 1.d0 .or. abs(eta_found) > 1.d0 .or. abs(gamma_found) > 1.d0) then
728+
! old position is out of element, new inside an element; let's take the new one
729+
is_better_location = .true.
730+
endif
731+
endif
732+
endif
708733

709-
! takes this point if it is closer to the receiver
734+
! if we have found an element that gives a shorter distance
710735
! (we compare squared distances instead of distances themselves to significantly speed up calculations)
711-
if (dist_squared < distmin_squared) then
712-
distmin_squared = dist_squared
736+
if (dist_squared < final_distmin_squared) then
737+
! check if location is better in case almost similar distances
738+
! since we allow xi/eta/gamma to go a bit outside of the element range [-1.01,1.01],
739+
! we keep the element where xi/eta/gamma is still within element
740+
!
741+
! note: this can avoid problems when points on interfaces, say between acoustic/elastic, have been choosen.
742+
! the point search takes whatever element comes last with a best position, even if the point
743+
! has been located slightly away from the element. thus, we try to check if the previous location
744+
! was accurate enough with coordinates still within an element.
745+
is_better_location = .true.
746+
if (abs(dist_squared - final_distmin_squared) < TOL_RELATIVE_POINT_DISTANCE) then
747+
if (abs(xi_n) > 1.d0 .or. abs(eta_n) > 1.d0 .or. abs(gamma_n) > 1.d0) then
748+
if (abs(xi_found) > 1.d0 .or. abs(eta_found) > 1.d0 .or. abs(gamma_found) > 1.d0) then
749+
! old position is also out of element, let's take the new one
750+
is_better_location = .true.
751+
else
752+
! old position is still within element and new distance has only little improved, so keep old one
753+
is_better_location = .false.
754+
endif
755+
endif
756+
endif
757+
endif
758+
759+
! takes this point if it is better
760+
if (is_better_location) then
761+
final_distmin_squared = dist_squared
713762
! uses this as new location
714763
ispec_selected = ispec
715-
xi = xi_n
716-
eta = eta_n
717-
gamma = gamma_n
718-
x = x_n
719-
y = y_n
720-
z = z_n
764+
xi_found = xi_n
765+
eta_found = eta_n
766+
gamma_found = gamma_n
767+
x_found = x_n
768+
y_found = y_n
769+
z_found = z_n
721770
endif
722771

723772
! checks if position lies inside element (which usually means that located position is accurate)
724-
if (abs(xi) <= 1.d0 .and. abs(eta) <= 1.d0 .and. abs(gamma) <= 1.d0) exit
773+
if (abs(xi_found) <= 1.d0 .and. abs(eta_found) <= 1.d0 .and. abs(gamma_found) <= 1.d0) exit
725774

726775
enddo ! num_neighbors
727776

728777
!debug
729-
if (DEBUG) print *,'neighbors: final ',ispec_selected,xi,eta,gamma,'distance',sqrt(distmin_squared)*R_PLANET_KM
778+
if (DEBUG) print *,'neighbors: final ',ispec_selected,xi_found,eta_found,gamma_found, &
779+
'distance',sqrt(final_distmin_squared)*R_PLANET_KM
730780

731781
end subroutine find_best_neighbor
732782

0 commit comments

Comments
 (0)