@@ -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