20#include <boost/container/small_vector.hpp>
24#ifdef DEAL_II_WITH_TRILINOS
26# ifdef DEAL_II_TRILINOS_WITH_EPETRA
27# ifdef DEAL_II_WITH_MPI
28# include <Epetra_MpiComm.h>
30# include <Epetra_Map.h>
31# include <Epetra_SerialComm.h>
33# ifdef DEAL_II_TRILINOS_WITH_TPETRA
34# include <Tpetra_Map.hpp>
43#ifdef DEAL_II_WITH_TRILINOS
45# ifdef DEAL_II_TRILINOS_WITH_TPETRA
47template <
typename NodeType>
50 const Tpetra::Map<int, types::signed_global_dof_index, NodeType>> &map)
52 , index_space_size(1 + map->getMaxAllGlobalIndex())
53 , largest_range(
numbers::invalid_unsigned_int)
55 Assert(map->getMinAllGlobalIndex() == 0,
57 "The Tpetra::Map does not contain the global index 0, "
58 "which means some entries are not present on any processor."));
61 if (map->isContiguous())
66# if DEAL_II_TRILINOS_VERSION_GTE(13, 4, 0)
67 const size_type n_indices = map->getLocalNumElements();
69 const size_type n_indices = map->getNodeNumElements();
72 map->getMyGlobalIndices().data();
84# ifdef DEAL_II_TRILINOS_WITH_EPETRA
85# ifdef DEAL_II_WITH_64BIT_INDICES
89 , index_space_size(1 + map.MaxAllGID64())
90 , largest_range(
numbers::invalid_unsigned_int)
92 Assert(map.MinAllGID64() == 0,
94 "The Epetra_BlockMap does not contain the global index 0, "
95 "which means some entries are not present on any processor."));
102 const size_type n_indices = map.NumMyElements();
104 reinterpret_cast<size_type *
>(map.MyGlobalElements64());
115 : is_compressed(true)
116 , index_space_size(1 + map.MaxAllGID())
117 , largest_range(
numbers::invalid_unsigned_int)
119 Assert(map.MinAllGID() == 0,
121 "The Epetra_BlockMap does not contain the global index 0, "
122 "which means some entries are not present on any processor."));
129 const size_type n_indices = map.NumMyElements();
130 unsigned int *indices =
131 reinterpret_cast<unsigned int *
>(map.MyGlobalElements());
159 std::vector<Range>::iterator store =
ranges.begin();
160 for (std::vector<Range>::iterator i =
ranges.begin(); i !=
ranges.end();)
162 std::vector<Range>::iterator next = i;
169 while (next !=
ranges.end() && (next->begin <= last_index))
171 last_index =
std::max(last_index, next->end);
177 *store =
Range(first_index, last_index);
181 if (store !=
ranges.end())
183 std::vector<Range> new_ranges(
ranges.begin(), store);
188 size_type next_index = 0, largest_range_size = 0;
189 for (std::vector<Range>::iterator i =
ranges.begin(); i !=
ranges.end();
194 i->nth_index_in_set = next_index;
195 next_index += (i->end - i->begin);
196 if (i->end - i->begin > largest_range_size)
198 largest_range_size = i->end - i->begin;
219 for (
const auto &range :
ranges)
223 ExcMessage(
"In the process of creating the current IndexSet "
224 "object, you added indices beyond the size of the index "
225 "space. Specifically, you added elements that form the "
227 std::to_string(range.begin) +
"," +
228 std::to_string(range.end) +
229 "), but the size of the index space is only " +
231 n_owned_elements += (range.end - range.begin);
254 std::vector<Range>::const_iterator r1 =
ranges.begin(),
262 if (r1->end <= r2->begin)
264 else if (r2->end <= r1->begin)
269 Assert(((r1->begin <= r2->begin) && (r1->end > r2->begin)) ||
270 ((r2->begin <= r1->begin) && (r2->end > r1->begin)),
274 result.add_range(
std::max(r1->begin, r2->begin),
280 if (r1->end <= r2->end)
298 ExcMessage(
"End index needs to be larger or equal to begin index!"));
300 ExcMessage(
"You are asking for a view into an IndexSet object "
301 "that would cover the sub-range [" +
302 std::to_string(
begin) +
',' + std::to_string(
end) +
303 "). But this is not a subset of the range "
304 "of the current object, which is [0," +
305 std::to_string(
size()) +
")."));
308 std::vector<Range>::const_iterator r1 =
ranges.begin();
310 while (r1 !=
ranges.end())
312 if ((r1->end >
begin) && (r1->begin <
end))
317 else if (r1->begin >=
end)
333 ExcMessage(
"The mask must have the same size index space "
334 "as the index set it is applied to."));
346 if (mask.ranges.size() == 1)
347 return get_view(mask.ranges[0].begin, mask.ranges[0].end);
356 std::vector<Range> new_ranges;
358 std::vector<Range>::iterator own_it =
ranges.begin();
359 std::vector<Range>::iterator mask_it = mask.ranges.begin();
361 while ((own_it !=
ranges.end()) && (mask_it != mask.ranges.end()))
367 if (own_it->end <= mask_it->begin)
375 if (mask_it->end <= own_it->begin)
394 if ((own_it->begin <= mask_it->begin) && (own_it->end <= mask_it->end))
396 new_ranges.emplace_back(mask_it->begin - mask_it->nth_index_in_set,
397 own_it->end - mask_it->nth_index_in_set);
401 if ((mask_it->begin <= own_it->begin) && (mask_it->end <= own_it->end))
403 const size_type offset_within_mask_interval =
404 own_it->begin - mask_it->begin;
405 new_ranges.emplace_back(mask_it->nth_index_in_set +
406 offset_within_mask_interval,
407 mask_it->nth_index_in_set +
408 (mask_it->end - mask_it->begin));
412 if ((own_it->begin <= mask_it->begin) &&
413 (own_it->end >= mask_it->end))
415 new_ranges.emplace_back(mask_it->begin -
416 mask_it->nth_index_in_set,
417 mask_it->end - mask_it->nth_index_in_set);
421 if ((mask_it->begin <= own_it->begin) &&
422 (mask_it->end >= own_it->end))
424 const size_type offset_within_mask_interval =
425 own_it->begin - mask_it->begin;
426 new_ranges.emplace_back(mask_it->nth_index_in_set +
427 offset_within_mask_interval,
428 mask_it->nth_index_in_set +
429 offset_within_mask_interval +
430 (own_it->end - own_it->begin));
439 if (own_it->end < mask_it->end)
441 else if (mask_it->end < own_it->end)
456 for (
const auto &range : new_ranges)
457 result.
add_range(range.begin, range.end);
467 const std::vector<types::global_dof_index> &n_indices_per_block)
const
469 std::vector<IndexSet> partitioned;
470 const unsigned int n_blocks = n_indices_per_block.size();
472 partitioned.reserve(n_blocks);
474 for (
const auto n_block_indices : n_indices_per_block)
476 partitioned.push_back(this->
get_view(start, start + n_block_indices));
477 start += n_block_indices;
483 for (
const auto &partition : partitioned)
485 sum += partition.size();
507 std::vector<Range> new_ranges;
509 std::vector<Range>::iterator own_it =
ranges.begin();
510 std::vector<Range>::iterator other_it = other.
ranges.begin();
512 while (own_it !=
ranges.end() && other_it != other.
ranges.end())
515 if (own_it->end <= other_it->begin)
517 new_ranges.push_back(*own_it);
522 if (own_it->begin >= other_it->end)
530 if (own_it->begin < other_it->begin)
532 Range r(own_it->begin, other_it->begin);
534 new_ranges.push_back(r);
539 own_it->begin = other_it->end;
540 if (own_it->begin > own_it->end)
542 own_it->begin = own_it->end;
551 for (; own_it !=
ranges.end(); ++own_it)
552 new_ranges.push_back(*own_it);
557 const std::vector<Range>::iterator
end = new_ranges.end();
558 for (std::vector<Range>::iterator it = new_ranges.begin(); it !=
end; ++it)
570 for (
const auto el : *
this)
571 set.add_indices(other, el * other.
size());
584 const auto insert_position =
586 if (insert_position ==
ranges.end() ||
587 insert_position->begin > new_range.
begin ||
588 insert_position->end < new_range.
end)
589 ranges.insert(insert_position, new_range);
596 boost::container::small_vector<std::pair<size_type, size_type>, 200>
598 const bool ranges_are_sorted)
600 if (!ranges_are_sorted)
601 std::sort(tmp_ranges.begin(), tmp_ranges.end());
611 if (tmp_ranges.size() > 9)
614 tmp_set.
ranges.reserve(tmp_ranges.size());
615 for (
const auto &i : tmp_ranges)
620 if (this->
ranges.size() <= 1)
622 if (this->
ranges.size() == 1)
624 std::swap(*
this, tmp_set);
630 for (
const auto &i : tmp_ranges)
639 if ((
this == &other) && (offset == 0))
642 if (other.
ranges.size() != 0)
650 std::vector<Range>::const_iterator r1 =
ranges.begin(),
651 r2 = other.
ranges.begin();
653 std::vector<Range> new_ranges;
660 if (r2 == other.
ranges.end() ||
661 (r1 !=
ranges.end() && r1->end < (r2->begin + offset)))
663 new_ranges.push_back(*r1);
666 else if (r1 ==
ranges.end() || (r2->end + offset) < r1->begin)
668 new_ranges.emplace_back(r2->begin + offset, r2->end + offset);
676 std::max(r1->end, r2->end + offset));
677 new_ranges.push_back(next);
694 ExcMessage(
"One index set can only be a subset of another if they "
695 "describe index spaces of the same size. The ones in "
696 "question here have sizes " +
697 std::to_string(
size()) +
" and " +
698 std::to_string(other.
size()) +
"."));
718 out <<
size() <<
" ";
719 out <<
ranges.size() << std::endl;
720 std::vector<Range>::const_iterator r =
ranges.begin();
721 for (; r !=
ranges.end(); ++r)
723 out << r->begin <<
" " << r->end << std::endl;
735 unsigned int n_ranges;
740 for (
unsigned int i = 0; i < n_ranges; ++i)
757 std::size_t n_ranges =
ranges.size();
758 out.write(
reinterpret_cast<const char *
>(&n_ranges),
sizeof(n_ranges));
759 if (
ranges.empty() ==
false)
760 out.write(
reinterpret_cast<const char *
>(&*
ranges.begin()),
769 std::size_t n_ranges;
770 in.read(
reinterpret_cast<char *
>(&
size),
sizeof(
size));
771 in.read(
reinterpret_cast<char *
>(&n_ranges),
sizeof(n_ranges));
777 in.read(
reinterpret_cast<char *
>(&*
ranges.begin()),
800 std::vector<Range>::const_iterator p = std::upper_bound(
808 return ((index >= p->begin) && (index < p->end));
816 return (p->end > index);
833 return p->begin + (n - p->nth_index_in_set);
845 std::vector<Range>::const_iterator p =
849 if (p ==
ranges.end() || p->end == n || p->begin > n)
855 return (n - p->begin) + p->nth_index_in_set;
869 std::vector<Range>::const_iterator main_range =
872 Range r(global_index, global_index + 1);
875 std::vector<Range>::const_iterator range_begin, range_end;
876 if (global_index < main_range->
begin)
878 range_begin =
ranges.begin();
879 range_end = main_range;
883 range_begin = main_range;
889 const std::vector<Range>::const_iterator p =
902 if (global_index < p->
begin)
905 return {
this,
static_cast<size_type>(p -
ranges.begin()), global_index};
910std::vector<IndexSet::size_type>
915 std::vector<size_type> indices;
918 for (
const auto &range :
ranges)
919 for (
size_type entry = range.begin; entry < range.end; ++entry)
920 indices.push_back(entry);
929#ifdef DEAL_II_TRILINOS_WITH_TPETRA
931template <
typename NodeType>
932Tpetra::Map<int, types::signed_global_dof_index, NodeType>
936 return *make_tpetra_map_rcp<NodeType>(communicator,
overlapping);
941template <
typename NodeType>
942Teuchos::RCP<Tpetra::Map<int, types::signed_global_dof_index, NodeType>>
956 ExcMessage(
"You are trying to create an Tpetra::Map object "
957 "that partitions elements of an index set "
958 "between processors. However, the union of the "
959 "index sets on different processors does not "
960 "contain all indices exactly once: the sum of "
961 "the number of entries the various processors "
962 "want to store locally is " +
963 std::to_string(n_global_elements) +
964 " whereas the total size of the object to be "
966 std::to_string(
size()) +
967 ". In other words, there are "
968 "either indices that are not spoken for "
969 "by any processor, or there are indices that are "
970 "claimed by multiple processors."));
980 Tpetra::Map<int, types::signed_global_dof_index, NodeType>>(
984# ifdef DEAL_II_WITH_MPI
985 Utilities::Trilinos::internal::make_rcp<Teuchos::MpiComm<int>>(
994 std::vector<types::signed_global_dof_index> int_indices(indices.size());
995 std::copy(indices.begin(), indices.end(), int_indices.begin());
996 const Teuchos::ArrayView<types::signed_global_dof_index> arr_view(
1000 Tpetra::Map<int, types::signed_global_dof_index, NodeType>>(
1004# ifdef DEAL_II_WITH_MPI
1005 Utilities::Trilinos::internal::make_rcp<Teuchos::MpiComm<int>>(
1017#ifdef DEAL_II_TRILINOS_WITH_EPETRA
1032 ExcMessage(
"You are trying to create an Epetra_Map object "
1033 "that partitions elements of an index set "
1034 "between processors. However, the union of the "
1035 "index sets on different processors does not "
1036 "contain all indices exactly once: the sum of "
1037 "the number of entries the various processors "
1038 "want to store locally is " +
1039 std::to_string(n_global_elements) +
1040 " whereas the total size of the object to be "
1042 std::to_string(
size()) +
1043 ". In other words, there are "
1044 "either indices that are not spoken for "
1045 "by any processor, or there are indices that are "
1046 "claimed by multiple processors."));
1059# ifdef DEAL_II_WITH_MPI
1060 Epetra_MpiComm(communicator)
1076# ifdef DEAL_II_WITH_MPI
1077 Epetra_MpiComm(communicator)
1087#ifdef DEAL_II_WITH_PETSC
1096 const auto local_size =
static_cast<PetscInt
>(
n_elements());
1100 std::vector<PetscInt> petsc_indices(
n_elements());
1101 for (
const auto &index : *
this)
1103 const auto petsc_index =
static_cast<PetscInt
>(index);
1105 petsc_indices[i] = petsc_index;
1110 PetscErrorCode ierr = ISCreateGeneral(
1111 communicator, local_size, petsc_indices.data(), PETSC_COPY_VALUES, &is);
1127 if (n_global_elements !=
size())
1130 if (n_global_elements == 0)
1133#ifdef DEAL_II_WITH_MPI
1135 const bool all_contiguous =
1137 if (!all_contiguous)
1140 bool is_globally_ascending =
true;
1147 const std::vector<types::global_dof_index> global_dofs =
1157 for (; index < global_dofs.size(); ++index)
1162 if (new_dof <= old_dof)
1164 is_globally_ascending =
false;
1174 int is_ascending = is_globally_ascending ? 1 : 0;
1175 int ierr = MPI_Bcast(&is_ascending, 1, MPI_INT, 0, communicator);
1178 return (is_ascending == 1);
1198# ifdef DEAL_II_WITH_TRILINOS
1199# ifdef DEAL_II_TRILINOS_WITH_TPETRA
1202 const Teuchos::RCP<
const Tpetra::Map<
1208# if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP) || \
1209 defined(KOKKOS_ENABLE_SYCL)
1211 const Teuchos::RCP<
const Tpetra::Map<
1224# if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP) || \
1225 defined(KOKKOS_ENABLE_SYCL)
1234template Teuchos::RCP<
1241# if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP) || \
1242 defined(KOKKOS_ENABLE_SYCL)
1243template Teuchos::RCP<
* x_component_mask set(0, true)
ElementIterator begin() const
bool is_subset_of(const IndexSet &other) const
bool is_element_binary_search(const size_type local_index) const
size_type index_within_set_binary_search(const size_type global_index) const
IS make_petsc_is(const MPI_Comm communicator=MPI_COMM_WORLD) const
bool is_ascending_and_one_to_one(const MPI_Comm communicator) const
bool is_contiguous() const
Tpetra::Map< int, types::signed_global_dof_index, NodeType > make_tpetra_map(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
ElementIterator at(const size_type global_index) const
std::vector< IndexSet > split_by_block(const std::vector< types::global_dof_index > &n_indices_per_block) const
size_type n_elements() const
void add_range_lower_bound(const Range &range)
ElementIterator begin() const
void set_size(const size_type size)
void read(std::istream &in)
Epetra_Map make_trilinos_map(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
IndexSet tensor_product(const IndexSet &other) const
void write(std::ostream &out) const
void block_read(std::istream &in)
void add_ranges_internal(boost::container::small_vector< std::pair< size_type, size_type >, 200 > &tmp_ranges, const bool ranges_are_sorted)
IntervalIterator begin_intervals() const
std::vector< Range > ranges
void subtract_set(const IndexSet &other)
ElementIterator end() const
Threads::Mutex compress_mutex
size_type index_space_size
void block_write(std::ostream &out) const
IndexSet get_view(const size_type begin, const size_type end) const
void add_range(const size_type begin, const size_type end)
std::size_t memory_consumption() const
size_type nth_index_in_set_binary_search(const size_type local_index) const
std::vector< size_type > get_index_vector() const
Teuchos::RCP< Tpetra::Map< int, types::signed_global_dof_index, NodeType > > make_tpetra_map_rcp(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
types::global_dof_index size_type
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
IndexSet operator&(const IndexSet &is) const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
#define AssertIntegerConversion(index1, index2)
#define DEAL_II_ASSERT_UNREACHABLE()
#define AssertThrowIntegerConversion(index1, index2)
static ::ExceptionBase & ExcIO()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
const unsigned int my_rank
Tpetra::KokkosCompat::KokkosDeviceWrapperNode< typename MemorySpace::kokkos_space::execution_space, typename MemorySpace::kokkos_space > NodeType
Tpetra::Map< LO, GO, NodeType< MemorySpace > > MapType
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
T sum(const T &t, const MPI_Comm mpi_communicator)
bool logical_and(const bool t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
std::vector< T > gather(const MPI_Comm comm, const T &object_to_send, const unsigned int root_process=0)
Teuchos::RCP< T > make_rcp(Args &&...args)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
constexpr types::global_dof_index invalid_dof_index
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
static bool end_compare(const IndexSet::Range &x, const IndexSet::Range &y)
static bool nth_index_compare(const IndexSet::Range &x, const IndexSet::Range &y)
size_type nth_index_in_set