241 neighbor_lists_view_type neighbor_lists, epsilons_view_type epsilons,
242 const double uniform_radius = 0.0,
double max_search_radius = 0.0) {
246 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename trg_view_type::memory_space>::accessible==1) &&
247 "Target coordinates view passed to generate2DNeighborListsFromRadiusSearch should be accessible from the host.");
249 "Target coordinates view passed to generate2DNeighborListsFromRadiusSearch must have \
250 second dimension as large as _dim.");
251 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename neighbor_lists_view_type::memory_space>::accessible==1) &&
252 "Views passed to generate2DNeighborListsFromRadiusSearch should be accessible from the host.");
253 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename epsilons_view_type::memory_space>::accessible==1) &&
254 "Views passed to generate2DNeighborListsFromRadiusSearch should be accessible from the host.");
257 const int num_target_sites = trg_pts_view.extent(0);
265 && neighbor_lists.extent(1)>=1)
266 &&
"neighbor lists View does not have large enough dimensions");
270 &&
"epsilons View does not have the correct dimension");
272 typedef Kokkos::View<double*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
275 typedef Kokkos::View<size_t*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
279 int team_scratch_size = 0;
280 team_scratch_size += scratch_double_view::shmem_size(neighbor_lists.extent(1));
281 team_scratch_size += scratch_int_view::shmem_size(neighbor_lists.extent(1));
282 team_scratch_size += scratch_double_view::shmem_size(
_dim);
286 size_t max_num_neighbors = 0;
289 auto scratch_level = (team_scratch_size > 32000) ? 1 : 0;
293 .set_scratch_size(scratch_level , Kokkos::PerTeam(team_scratch_size));
294 auto radius_search = [=,*
this](
const host_member_type& teamMember,
size_t& t_max_num_neighbors) {
297 scratch_double_view neighbor_distances(teamMember.team_scratch(scratch_level ), neighbor_lists.extent(1));
298 scratch_int_view neighbor_indices(teamMember.team_scratch(scratch_level ), neighbor_lists.extent(1));
299 scratch_double_view this_target_coord(teamMember.team_scratch(scratch_level ), dim);
301 size_t neighbors_found = 0;
303 const int i = teamMember.league_rank();
306 if (uniform_radius > 0) epsilons(i) = uniform_radius;
309 compadre_kernel_assert_release((epsilons(i)<=max_search_radius || max_search_radius==0) &&
"max_search_radius given (generally derived from the size of a halo region), and search radius needed would exceed this max_search_radius.");
311 Kokkos::parallel_for(Kokkos::TeamThreadRange(teamMember, neighbor_lists.extent(1)), [&](
const int j) {
312 neighbor_indices(j) = 0;
313 neighbor_distances(j) = -1.0;
315 teamMember.team_barrier();
317 Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
321 for (
int j=0; j<dim; ++j) {
322 this_target_coord(j) = trg_pts_view(i,j);
325 nanoflann::SearchParams sp;
328 neighbors_found =
_tree_1d->template radiusSearchCustomCallback<Compadre::RadiusResultSet<double> >(this_target_coord.data(), rrs, sp) ;
330 neighbors_found =
_tree_2d->template radiusSearchCustomCallback<Compadre::RadiusResultSet<double> >(this_target_coord.data(), rrs, sp) ;
332 neighbors_found =
_tree_3d->template radiusSearchCustomCallback<Compadre::RadiusResultSet<double> >(this_target_coord.data(), rrs, sp) ;
335 t_max_num_neighbors = (neighbors_found > t_max_num_neighbors) ? neighbors_found : t_max_num_neighbors;
338 neighbor_lists(i,0) = neighbors_found;
342 teamMember.team_barrier();
345 int loop_bound = (neighbors_found < neighbor_lists.extent(1)-1) ? neighbors_found : neighbor_lists.extent(1)-1;
348 Kokkos::parallel_for(Kokkos::TeamThreadRange(teamMember, loop_bound), [&](
const int j) {
350 neighbor_lists(i,j+1) =
static_cast<typename std::remove_pointer<typename std::remove_pointer<typename neighbor_lists_view_type::data_type>::type
>::type>(neighbor_indices(j));
352 teamMember.team_barrier();
356 Kokkos::parallel_reduce(
"radius search 2D", policy, radius_search, Kokkos::Max<size_t>(max_num_neighbors));
361 &&
"neighbor_lists does not contain enough columns for the maximum number of neighbors needing to be stored.");
363 return max_num_neighbors;
380 neighbor_lists_view_type neighbor_lists, neighbor_lists_view_type number_of_neighbors_list,
381 epsilons_view_type epsilons,
const double uniform_radius = 0.0,
double max_search_radius = 0.0) {
385 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename trg_view_type::memory_space>::accessible==1) &&
386 "Target coordinates view passed to generateCRNeighborListsFromRadiusSearch should be accessible from the host.");
388 "Target coordinates view passed to generateCRNeighborListsFromRadiusSearch must have \
389 second dimension as large as _dim.");
390 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename neighbor_lists_view_type::memory_space>::accessible==1) &&
391 "Views passed to generateCRNeighborListsFromRadiusSearch should be accessible from the host.");
392 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename epsilons_view_type::memory_space>::accessible==1) &&
393 "Views passed to generateCRNeighborListsFromRadiusSearch should be accessible from the host.");
396 const int num_target_sites = trg_pts_view.extent(0);
403 &&
"number_of_neighbors_list or neighbor lists View does not have large enough dimensions");
406 typedef Kokkos::View<
global_index_type*,
typename neighbor_lists_view_type::array_layout,
407 typename neighbor_lists_view_type::memory_space,
typename neighbor_lists_view_type::memory_traits> row_offsets_view_type;
408 row_offsets_view_type row_offsets;
409 int max_neighbor_list_row_storage_size = 1;
412 max_neighbor_list_row_storage_size = nla.getMaxNumNeighbors();
413 Kokkos::resize(row_offsets, num_target_sites);
415 Kokkos::parallel_for(Kokkos::RangePolicy<host_execution_space>(0,num_target_sites), [&](
const int i) {
416 row_offsets(i) = nla.getRowOffsetHost(i);
422 &&
"epsilons View does not have the correct dimension");
424 typedef Kokkos::View<double*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
427 typedef Kokkos::View<size_t*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
431 int team_scratch_size = 0;
432 team_scratch_size += scratch_double_view::shmem_size(max_neighbor_list_row_storage_size);
433 team_scratch_size += scratch_int_view::shmem_size(max_neighbor_list_row_storage_size);
434 team_scratch_size += scratch_double_view::shmem_size(
_dim);
439 auto scratch_level = (team_scratch_size > 32000) ? 1 : 0;
443 .set_scratch_size(scratch_level , Kokkos::PerTeam(team_scratch_size));
447 scratch_double_view neighbor_distances(teamMember.team_scratch(scratch_level ), max_neighbor_list_row_storage_size);
448 scratch_int_view neighbor_indices(teamMember.team_scratch(scratch_level ), max_neighbor_list_row_storage_size);
449 scratch_double_view this_target_coord(teamMember.team_scratch(scratch_level ), dim);
451 size_t neighbors_found = 0;
453 const int i = teamMember.league_rank();
456 if (uniform_radius > 0) epsilons(i) = uniform_radius;
459 compadre_kernel_assert_release((epsilons(i)<=max_search_radius || max_search_radius==0) &&
"max_search_radius given (generally derived from the size of a halo region), and search radius needed would exceed this max_search_radius.");
461 Kokkos::parallel_for(Kokkos::TeamThreadRange(teamMember, max_neighbor_list_row_storage_size), [&](
const int j) {
462 neighbor_indices(j) = 0;
463 neighbor_distances(j) = -1.0;
465 teamMember.team_barrier();
467 Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
471 for (
int j=0; j<dim; ++j) {
472 this_target_coord(j) = trg_pts_view(i,j);
475 nanoflann::SearchParams sp;
478 neighbors_found =
_tree_1d->template radiusSearchCustomCallback<Compadre::RadiusResultSet<double> >(this_target_coord.data(), rrs, sp) ;
480 neighbors_found =
_tree_2d->template radiusSearchCustomCallback<Compadre::RadiusResultSet<double> >(this_target_coord.data(), rrs, sp) ;
482 neighbors_found =
_tree_3d->template radiusSearchCustomCallback<Compadre::RadiusResultSet<double> >(this_target_coord.data(), rrs, sp) ;
487 if (is_dry_run || uniform_radius!=0.0) {
488 number_of_neighbors_list(i) = neighbors_found;
491 &&
"Number of neighbors found changed since dry-run.");
496 teamMember.team_barrier();
499 int loop_bound = neighbors_found;
502 Kokkos::parallel_for(Kokkos::TeamThreadRange(teamMember, loop_bound), [&](
const int j) {
504 neighbor_lists(row_offsets(i)+j) =
static_cast<typename std::remove_pointer<typename std::remove_pointer<typename neighbor_lists_view_type::data_type>::type
>::type>(neighbor_indices(j));
506 teamMember.team_barrier();
510 Kokkos::parallel_for(
"radius search CR", policy, radius_search);
513 return nla.getTotalNeighborsOverAllListsHost();
530 neighbor_lists_view_type neighbor_lists, epsilons_view_type epsilons,
531 const int neighbors_needed,
const double epsilon_multiplier = 1.6,
532 double max_search_radius = 0.0,
const bool verify_unisolvency =
true) {
536 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename trg_view_type::memory_space>::accessible==1) &&
537 "Target coordinates view passed to generate2DNeighborListsFromKNNSearch should be accessible from the host.");
539 "Target coordinates view passed to generate2DNeighborListsFromRadiusSearch must have \
540 second dimension as large as _dim.");
541 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename neighbor_lists_view_type::memory_space>::accessible==1) &&
542 "Views passed to generate2DNeighborListsFromKNNSearch should be accessible from the host.");
543 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename epsilons_view_type::memory_space>::accessible==1) &&
544 "Views passed to generate2DNeighborListsFromKNNSearch should be accessible from the host.");
547 const int num_target_sites = trg_pts_view.extent(0);
555 (neighbor_lists.extent(0)==(
size_t)num_target_sites
556 && neighbor_lists.extent(1)>=(
size_t)(neighbors_needed+1)))
557 &&
"neighbor lists View does not have large enough dimensions");
561 &&
"epsilons View does not have the correct dimension");
563 typedef Kokkos::View<double*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
566 typedef Kokkos::View<size_t*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
570 int team_scratch_size = 0;
571 team_scratch_size += scratch_double_view::shmem_size(neighbor_lists.extent(1));
572 team_scratch_size += scratch_int_view::shmem_size(neighbor_lists.extent(1));
573 team_scratch_size += scratch_double_view::shmem_size(
_dim);
577 size_t min_num_neighbors = 0;
585 auto scratch_level = (team_scratch_size > 32000) ? 1 : 0;
589 .set_scratch_size(scratch_level , Kokkos::PerTeam(team_scratch_size));
590 auto knn_search = [=,*
this](
const host_member_type& teamMember,
size_t& t_min_num_neighbors) {
593 scratch_double_view neighbor_distances(teamMember.team_scratch(scratch_level ), neighbor_lists.extent(1));
594 scratch_int_view neighbor_indices(teamMember.team_scratch(scratch_level ), neighbor_lists.extent(1));
595 scratch_double_view this_target_coord(teamMember.team_scratch(scratch_level ), dim);
597 size_t neighbors_found = 0;
599 const int i = teamMember.league_rank();
601 Kokkos::parallel_for(Kokkos::TeamThreadRange(teamMember, neighbor_lists.extent(1)), [=](
const int j) {
602 neighbor_indices(j) = 0;
603 neighbor_distances(j) = -1.0;
606 teamMember.team_barrier();
607 Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
611 for (
int j=0; j<dim; ++j) {
612 this_target_coord(j) = trg_pts_view(i,j);
616 neighbors_found =
_tree_1d->knnSearch(this_target_coord.data(), neighbors_needed,
617 neighbor_indices.data(), neighbor_distances.data()) ;
619 neighbors_found =
_tree_2d->knnSearch(this_target_coord.data(), neighbors_needed,
620 neighbor_indices.data(), neighbor_distances.data()) ;
622 neighbors_found =
_tree_3d->knnSearch(this_target_coord.data(), neighbors_needed,
623 neighbor_indices.data(), neighbor_distances.data()) ;
627 t_min_num_neighbors = (neighbors_found < t_min_num_neighbors) ? neighbors_found : t_min_num_neighbors;
630 epsilons(i) = (neighbor_distances(neighbors_found-1) > 0) ?
631 std::sqrt(neighbor_distances(neighbors_found-1))*epsilon_multiplier : 1e-14*epsilon_multiplier;
639 &&
"Neighbors found exceeded storage capacity in neighbor list.");
641 &&
"max_search_radius given (generally derived from the size of a halo region), \
642 and search radius needed would exceed this max_search_radius.");
646 Kokkos::parallel_reduce(
"knn search 2D", policy, knn_search, Kokkos::Min<size_t>(min_num_neighbors));
650 if (num_target_sites==0) min_num_neighbors = neighbors_needed;
652 if (verify_unisolvency) {
655 &&
"Neighbor search failed to find number of neighbors needed for unisolvency.");
660 epsilons, 0.0 , max_search_radius);
662 return max_num_neighbors;
679 neighbor_lists_view_type neighbor_lists, neighbor_lists_view_type number_of_neighbors_list,
680 epsilons_view_type epsilons,
const int neighbors_needed,
const double epsilon_multiplier = 1.6,
681 double max_search_radius = 0.0,
const bool verify_unisolvency =
true) {
685 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename trg_view_type::memory_space>::accessible==1) &&
686 "Target coordinates view passed to generateCRNeighborListsFromKNNSearch should be accessible from the host.");
688 "Target coordinates view passed to generateCRNeighborListsFromRadiusSearch must have \
689 second dimension as large as _dim.");
690 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename neighbor_lists_view_type::memory_space>::accessible==1) &&
691 "Views passed to generateCRNeighborListsFromKNNSearch should be accessible from the host.");
692 compadre_assert_release((Kokkos::SpaceAccessibility<host_execution_space, typename epsilons_view_type::memory_space>::accessible==1) &&
693 "Views passed to generateCRNeighborListsFromKNNSearch should be accessible from the host.");
696 const int num_target_sites = trg_pts_view.extent(0);
704 &&
"number_of_neighbors_list or neighbor lists View does not have large enough dimensions");
708 int max_neighbor_list_row_storage_size = neighbors_needed;
711 max_neighbor_list_row_storage_size = nla.getMaxNumNeighbors();
715 &&
"epsilons View does not have the correct dimension");
717 typedef Kokkos::View<double*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
720 typedef Kokkos::View<size_t*, host_scratch, Kokkos::MemoryTraits<Kokkos::Unmanaged> >
724 int team_scratch_size = 0;
725 team_scratch_size += scratch_double_view::shmem_size(max_neighbor_list_row_storage_size);
726 team_scratch_size += scratch_int_view::shmem_size(max_neighbor_list_row_storage_size);
727 team_scratch_size += scratch_double_view::shmem_size(
_dim);
731 size_t min_num_neighbors = 0;
739 auto scratch_level = (team_scratch_size > 32000) ? 1 : 0;
743 .set_scratch_size(scratch_level , Kokkos::PerTeam(team_scratch_size));
744 auto knn_search = [=,*
this](
const host_member_type& teamMember,
size_t& t_min_num_neighbors) {
747 scratch_double_view neighbor_distances(teamMember.team_scratch(scratch_level ), max_neighbor_list_row_storage_size);
748 scratch_int_view neighbor_indices(teamMember.team_scratch(scratch_level ), max_neighbor_list_row_storage_size);
749 scratch_double_view this_target_coord(teamMember.team_scratch(scratch_level ), dim);
751 size_t neighbors_found = 0;
753 const int i = teamMember.league_rank();
755 Kokkos::parallel_for(Kokkos::TeamThreadRange(teamMember, max_neighbor_list_row_storage_size), [=](
const int j) {
756 neighbor_indices(j) = 0;
757 neighbor_distances(j) = -1.0;
760 teamMember.team_barrier();
761 Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
765 for (
int j=0; j<dim; ++j) {
766 this_target_coord(j) = trg_pts_view(i,j);
770 neighbors_found =
_tree_1d->knnSearch(this_target_coord.data(), neighbors_needed,
771 neighbor_indices.data(), neighbor_distances.data()) ;
773 neighbors_found =
_tree_2d->knnSearch(this_target_coord.data(), neighbors_needed,
774 neighbor_indices.data(), neighbor_distances.data()) ;
776 neighbors_found =
_tree_3d->knnSearch(this_target_coord.data(), neighbors_needed,
777 neighbor_indices.data(), neighbor_distances.data()) ;
781 t_min_num_neighbors = (neighbors_found < t_min_num_neighbors) ? neighbors_found : t_min_num_neighbors;
784 epsilons(i) = (neighbor_distances(neighbors_found-1) > 0) ?
785 std::sqrt(neighbor_distances(neighbors_found-1))*epsilon_multiplier : 1e-14*epsilon_multiplier;
792 &&
"max_search_radius given (generally derived from the size of a halo region), \
793 and search radius needed would exceed this max_search_radius.");
797 Kokkos::parallel_reduce(
"knn search CR", policy, knn_search, Kokkos::Min<size_t>(min_num_neighbors));
801 if (num_target_sites==0) min_num_neighbors = neighbors_needed;
803 if (verify_unisolvency) {
806 &&
"Neighbor search failed to find number of neighbors needed for unisolvency.");
811 number_of_neighbors_list, epsilons, 0.0 , max_search_radius);
814 return nla.getTotalNeighborsOverAllListsHost();