206 LOG_SCOPE (
"assign_global_indices()",
"MeshCommunication");
232 const Point bboxinv = invert_bbox(bbox);
236 std::vector<Parallel::DofObjectKey>
237 node_keys, elem_keys;
243 mesh.local_nodes_end());
244 node_keys.resize (nr.
size());
272 mesh.local_elements_end());
273 elem_keys.resize (er.
size());
315 const std::vector<Parallel::DofObjectKey> & my_node_bin =
322 const std::vector<Parallel::DofObjectKey> & my_elem_bin =
329 std::vector<Parallel::DofObjectKey>
330 node_upper_bounds(communicator.size()),
331 elem_upper_bounds(communicator.size());
334 std::vector<Parallel::DofObjectKey> recvbuf(2*communicator.size());
335 std::vector<unsigned short int>
336 empty_nodes (communicator.size()),
337 empty_elem (communicator.size());
338 std::vector<Parallel::DofObjectKey> my_max(2);
340 communicator.allgather (
static_cast<unsigned short int>(my_node_bin.empty()), empty_nodes);
341 communicator.allgather (
static_cast<unsigned short int>(my_elem_bin.empty()), empty_elem);
343 if (!my_node_bin.empty()) my_max[0] = my_node_bin.back();
344 if (!my_elem_bin.empty()) my_max[1] = my_elem_bin.back();
346 communicator.allgather (my_max,
true);
351 for (
auto p :
make_range(communicator.size()))
353 node_upper_bounds[p] = my_max[2*p+0];
354 elem_upper_bounds[p] = my_max[2*p+1];
358 if (empty_nodes[p]) node_upper_bounds[p] = node_upper_bounds[p-1];
359 if (empty_elem[p]) elem_upper_bounds[p] = elem_upper_bounds[p-1];
374 std::map<processor_id_type, std::vector<Parallel::DofObjectKey>>
378 std::map<dof_id_type, std::vector<dof_id_type>>
382 for (
const auto & node :
mesh.node_ptr_range())
386 get_dofobject_key (*node, bbox, bboxinv);
388 cast_int<processor_id_type>
389 (std::distance (node_upper_bounds.begin(),
390 std::lower_bound(node_upper_bounds.begin(),
391 node_upper_bounds.end(),
394 libmesh_assert_less (pid, communicator.size());
396 requested_ids[pid].push_back(hi);
400 std::vector<dof_id_type> node_bin_sizes(communicator.size());
401 communicator.allgather (
static_cast<dof_id_type>(my_node_bin.size()), node_bin_sizes);
405 for (
auto pid :
make_range(communicator.rank()))
406 my_offset += node_bin_sizes[pid];
408 auto gather_functor =
418 const std::vector<Parallel::DofObjectKey> & keys,
419 std::vector<dof_id_type> & global_ids)
422 const std::size_t keys_size = keys.size();
423 global_ids.reserve(keys_size);
424 for (std::size_t idx=0; idx != keys_size; idx++)
427 libmesh_assert_less_equal (hi, node_upper_bounds[communicator.rank()]);
430 std::vector<Parallel::DofObjectKey>::const_iterator pos =
431 std::lower_bound (my_node_bin.begin(), my_node_bin.end(), hi);
433 libmesh_assert_equal_to (*pos, hi);
437 global_ids.push_back(cast_int<dof_id_type>(std::distance(my_node_bin.begin(), pos) + my_offset));
441 auto action_functor =
444 const std::vector<Parallel::DofObjectKey> &,
445 const std::vector<dof_id_type> & global_ids)
447 filled_request[pid] = global_ids;
453 (communicator, requested_ids, gather_functor, action_functor, ex);
458 std::map<dof_id_type, std::vector<dof_id_type>::const_iterator>
460 for (
auto & p : filled_request)
461 next_obj_on_proc[p.first] = p.second.begin();
463 for (
auto & node :
mesh.node_ptr_range())
467 get_dofobject_key (*node, bbox, bboxinv);
469 cast_int<processor_id_type>
470 (std::distance (node_upper_bounds.begin(),
471 std::lower_bound(node_upper_bounds.begin(),
472 node_upper_bounds.end(),
475 libmesh_assert_less (pid, communicator.size());
476 libmesh_assert (next_obj_on_proc[pid] != filled_request[pid].end());
478 const dof_id_type global_index = *next_obj_on_proc[pid];
479 libmesh_assert_less (global_index,
mesh.
n_nodes());
480 node->set_id() = global_index;
482 ++next_obj_on_proc[pid];
491 std::map<processor_id_type, std::vector<Parallel::DofObjectKey>>
495 std::map<dof_id_type, std::vector<dof_id_type>>
498 for (
const auto & elem :
mesh.element_ptr_range())
502 get_dofobject_key (*elem, bbox, bboxinv);
504 cast_int<processor_id_type>
505 (std::distance (elem_upper_bounds.begin(),
506 std::lower_bound(elem_upper_bounds.begin(),
507 elem_upper_bounds.end(),
510 libmesh_assert_less (pid, communicator.size());
512 requested_ids[pid].push_back(hi);
516 std::vector<dof_id_type> elem_bin_sizes(communicator.size());
517 communicator.allgather (
static_cast<dof_id_type>(my_elem_bin.size()), elem_bin_sizes);
521 for (
auto pid :
make_range(communicator.rank()))
522 my_offset += elem_bin_sizes[pid];
524 auto gather_functor =
534 const std::vector<Parallel::DofObjectKey> & keys,
535 std::vector<dof_id_type> & global_ids)
538 const std::size_t keys_size = keys.size();
539 global_ids.reserve(keys_size);
540 for (std::size_t idx=0; idx != keys_size; idx++)
543 libmesh_assert_less_equal (hi, elem_upper_bounds[communicator.rank()]);
546 std::vector<Parallel::DofObjectKey>::const_iterator pos =
547 std::lower_bound (my_elem_bin.begin(), my_elem_bin.end(), hi);
549 libmesh_assert_equal_to (*pos, hi);
553 global_ids.push_back (cast_int<dof_id_type>(std::distance(my_elem_bin.begin(), pos) + my_offset));
557 auto action_functor =
560 const std::vector<Parallel::DofObjectKey> &,
561 const std::vector<dof_id_type> & global_ids)
563 filled_request[pid] = global_ids;
569 (communicator, requested_ids, gather_functor, action_functor, ex);
574 std::vector<std::vector<dof_id_type>::const_iterator>
575 next_obj_on_proc; next_obj_on_proc.reserve(communicator.size());
576 for (
auto pid :
make_range(communicator.size()))
577 next_obj_on_proc.push_back(filled_request[pid].begin());
579 for (
auto & elem :
mesh.element_ptr_range())
583 get_dofobject_key (*elem, bbox, bboxinv);
585 cast_int<processor_id_type>
586 (std::distance (elem_upper_bounds.begin(),
587 std::lower_bound(elem_upper_bounds.begin(),
588 elem_upper_bounds.end(),
591 libmesh_assert_less (pid, communicator.size());
592 libmesh_assert (next_obj_on_proc[pid] != filled_request[pid].end());
594 const dof_id_type global_index = *next_obj_on_proc[pid];
595 libmesh_assert_less (global_index,
mesh.
n_elem());
596 elem->set_id() = global_index;
598 ++next_obj_on_proc[pid];
614 LOG_SCOPE (
"check_for_duplicate_global_indices()",
"MeshCommunication");
622 const Point bboxinv = invert_bbox(bbox);
624 std::vector<Parallel::DofObjectKey>
625 node_keys, elem_keys;
631 mesh.local_nodes_end());
632 node_keys.resize (nr.
size());
638 for (std::size_t i = 0; i != node_keys.size(); ++i, ++nodei)
641 for (std::size_t j = 0; j != i; ++j, ++nodej)
643 if (node_keys[i] == node_keys[j])
645 CFixBitVec icoords[3], jcoords[3];
646 get_hilbert_coords(**nodej, bbox, bboxinv, jcoords);
648 "node " << (*nodej)->id() <<
", " <<
649 *(
const Point *)(*nodej) <<
" has HilbertIndices " <<
650 node_keys[j] << std::endl;
651 get_hilbert_coords(**nodei, bbox, bboxinv, icoords);
653 "node " << (*nodei)->id() <<
", " <<
654 *(
const Point *)(*nodei) <<
" has HilbertIndices " <<
655 node_keys[i] << std::endl;
656 libmesh_error_msg(
"Error: nodes with duplicate Hilbert keys!");
665 mesh.local_elements_end());
666 elem_keys.resize (er.
size());
673 for (std::size_t i = 0; i != elem_keys.size(); ++i, ++elemi)
676 for (std::size_t j = 0; j != i; ++j, ++elemj)
678 if ((elem_keys[i] == elem_keys[j]) &&
679 ((*elemi)->level() == (*elemj)->level()))
682 "level " << (*elemj)->level() <<
" elem\n" <<
683 (**elemj) <<
" vertex average " <<
684 (*elemj)->vertex_average() <<
" has HilbertIndices " <<
685 elem_keys[j] <<
" or " <<
686 get_dofobject_key((**elemj), bbox, bboxinv) <<
689 "level " << (*elemi)->level() <<
" elem\n" <<
690 (**elemi) <<
" vertex average " <<
691 (*elemi)->vertex_average() <<
" has HilbertIndices " <<
692 elem_keys[i] <<
" or " <<
693 get_dofobject_key((**elemi), bbox, bboxinv) <<
695 libmesh_error_msg(
"Error: level " << (*elemi)->level() <<
" elements with duplicate Hilbert keys!");
750 const ForwardIterator & begin,
751 const ForwardIterator & end,
752 std::vector<dof_id_type> & index_map)
const
754 LOG_SCOPE (
"find_global_indices()",
"MeshCommunication");
766 std::size_t n_objects = std::distance (begin, end);
767 index_map.reserve(n_objects);
769 const Point bboxinv = invert_bbox(bbox);
776 std::vector<Parallel::DofObjectKey>
779 sorted_hilbert_keys.reserve(n_objects);
780 hilbert_keys.reserve(n_objects);
782 LOG_SCOPE(
"compute_hilbert_indices()",
"MeshCommunication");
784 for (ForwardIterator it=begin; it!=end; ++it)
787 hilbert_keys.push_back(hi);
792 sorted_hilbert_keys.push_back(hi);
797 sorted_hilbert_keys.push_back(hi);
803 START_LOG (
"parallel_sort()",
"MeshCommunication");
805 sorted_hilbert_keys);
807 STOP_LOG (
"parallel_sort()",
"MeshCommunication");
808 const std::vector<Parallel::DofObjectKey> & my_bin = sorter.
bin();
811 std::vector<unsigned int> bin_sizes(communicator.size());
812 communicator.allgather (
static_cast<unsigned int>(my_bin.size()), bin_sizes);
815 unsigned int my_offset = 0;
816 for (
auto pid :
make_range(communicator.rank()))
817 my_offset += bin_sizes[pid];
821 std::vector<Parallel::DofObjectKey>
825 upper_bounds[0] = my_bin.back();
827 communicator.allgather (upper_bounds,
true);
833 if (!bin_sizes[p]) upper_bounds[p] = upper_bounds[p-1];
844 std::map<processor_id_type, std::vector<Parallel::DofObjectKey>>
847 std::map<processor_id_type, std::vector<dof_id_type>>
851 std::vector<Parallel::DofObjectKey>::const_iterator hi =
852 hilbert_keys.begin();
854 for (ForwardIterator it = begin; it != end; ++it)
858 std::vector<Parallel::DofObjectKey>::iterator lb =
859 std::lower_bound(upper_bounds.begin(), upper_bounds.end(),
863 cast_int<processor_id_type>
864 (std::distance (upper_bounds.begin(), lb));
866 libmesh_assert_less (pid, communicator.size());
868 requested_ids[pid].push_back(*hi);
873 index_map.push_back(pid);
876 auto gather_functor =
887 std::vector<dof_id_type> & global_ids)
893 const std::size_t keys_size = keys.size();
895 global_ids.reserve(keys_size);
896 for (std::size_t idx=0; idx != keys_size; idx++)
899 libmesh_assert_less_equal (hilbert_indices, upper_bounds[communicator.rank()]);
902 std::vector<Parallel::DofObjectKey>::const_iterator pos =
903 std::lower_bound (my_bin.begin(), my_bin.end(), hilbert_indices);
910 if (*pos != hilbert_indices)
915 Hilbert::BitVecType input;
916#ifdef LIBMESH_ENABLE_UNIQUE_ID
917 input = hilbert_indices.first;
919 input = hilbert_indices;
923 std::vector<CBigBitVec> output(3);
926 Hilbert::indexToCoords(output.data(), 8*
sizeof(Hilbert::inttype), 3, input);
932 const Real max_int_as_real =
933 static_cast<Real>(std::numeric_limits<Hilbert::inttype>::max());
938 Point p_hat(
static_cast<Real>(output[0].racks()[0]) / max_int_as_real,
939 static_cast<Real>(output[1].racks()[0]) / max_int_as_real,
940 static_cast<Real>(output[2].racks()[0]) / max_int_as_real);
944 xmin = bbox.first(0),
945 xmax = bbox.second(0),
946 ymin = bbox.first(1),
947 ymax = bbox.second(1),
948 zmin = bbox.first(2),
949 zmax = bbox.second(2);
952 Point p(xmin + (xmax-xmin)*p_hat(0),
953 ymin + (ymax-ymin)*p_hat(1),
954 zmin + (zmax-zmin)*p_hat(2));
956 libmesh_error_msg(
"Could not find hilbert indices: "
958 <<
" corresponding to point " << p);
964 global_ids.push_back (cast_int<dof_id_type>(std::distance(my_bin.begin(), pos) + my_offset));
968 auto action_functor =
971 const std::vector<Parallel::DofObjectKey> &,
972 const std::vector<dof_id_type> & global_ids)
974 filled_request[pid] = global_ids;
979 (communicator, requested_ids, gather_functor, action_functor, ex);
984 std::vector<std::vector<dof_id_type>::const_iterator>
985 next_obj_on_proc; next_obj_on_proc.reserve(communicator.size());
986 for (
auto pid :
make_range(communicator.size()))
987 next_obj_on_proc.push_back(filled_request[pid].begin());
990 for (ForwardIterator it = begin; it != end; ++it, cnt++)
995 libmesh_assert_less (pid, communicator.size());
996 libmesh_assert (next_obj_on_proc[pid] != filled_request[pid].end());
998 const dof_id_type global_index = *next_obj_on_proc[pid];
999 index_map[cnt] = global_index;
1001 ++next_obj_on_proc[pid];
1006 libmesh_assert_equal_to(index_map.size(), n_objects);