deal.II version GIT relicensing-6809-ge913b9bb34 2026-09-25 17:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
index_set.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2009 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_index_set_h
14#define dealii_index_set_h
15
16#include <deal.II/base/config.h>
17
21#include <deal.II/base/mutex.h>
23#include <deal.II/base/types.h>
24
26
27#include <boost/container/small_vector.hpp>
28
29#include <algorithm>
30#include <vector>
31
32
33#ifdef DEAL_II_WITH_TRILINOS
34
36# ifdef DEAL_II_TRILINOS_WITH_EPETRA
37# include <Epetra_Map.h>
38# endif
39# ifdef DEAL_II_TRILINOS_WITH_TPETRA
40# include <Tpetra_Map.hpp>
41# endif
43
44#endif
45
46#ifdef DEAL_II_WITH_PETSC
47# include <petscis.h>
48#endif
49
51
75{
76public:
77 // forward declarations:
78 class ElementIterator;
79 class IntervalIterator;
80
86
104 using value_type = signed int;
105
106
110 IndexSet();
111
115 explicit IndexSet(const size_type size);
116
120 IndexSet(const IndexSet &) = default;
121
125 IndexSet &
126 operator=(const IndexSet &) = default;
127
132 IndexSet(IndexSet &&is) noexcept;
133
138 IndexSet &
139 operator=(IndexSet &&is) noexcept;
140
141#ifdef DEAL_II_TRILINOS_WITH_TPETRA
145 template <typename NodeType>
146 explicit IndexSet(
147 const Teuchos::RCP<
148 const Tpetra::Map<int, types::signed_global_dof_index, NodeType>> &map);
149#endif // DEAL_II_TRILINOS_WITH_TPETRA
150
151#ifdef DEAL_II_TRILINOS_WITH_EPETRA
155 explicit IndexSet(const Epetra_BlockMap &map);
156#endif // DEAL_II_WITH_TRILINOS
157
162 void
163 clear();
164
171 void
172 set_size(const size_type size);
173
182 size() const;
183
190 void
191 add_range(const size_type begin, const size_type end);
192
201 void
202 add_index(const size_type index);
203
228 template <typename ForwardIterator>
229 void
230 add_indices(const ForwardIterator &begin, const ForwardIterator &end);
231
247 void
248 add_indices(const IndexSet &other, const size_type offset = 0);
249
253 bool
254 is_element(const size_type index) const;
255
260 bool
261 is_contiguous() const;
262
272 bool
273 is_empty() const;
274
284 bool
285 is_ascending_and_one_to_one(const MPI_Comm communicator) const;
286
291 n_elements() const;
292
299 nth_index_in_set(const size_type local_index) const;
300
308 index_within_set(const size_type global_index) const;
309
318 unsigned int
319 n_intervals() const;
320
334
339 void
340 compress() const;
341
356 bool
357 operator==(const IndexSet &is) const;
358
373 bool
374 operator!=(const IndexSet &is) const;
375
383 operator&(const IndexSet &is) const;
384
402 get_view(const size_type begin, const size_type end) const;
403
450 get_view(const IndexSet &mask) const;
451
457 std::vector<IndexSet>
459 const std::vector<types::global_dof_index> &n_indices_per_block) const;
460
469 void
470 subtract_set(const IndexSet &other);
471
489 tensor_product(const IndexSet &other) const;
490
499 std::vector<size_type>
500 get_index_vector() const;
501
514 template <typename VectorType>
515 void
516 fill_binary_vector(VectorType &vector) const;
517
525 bool
526 is_subset_of(const IndexSet &other) const;
527
532 template <typename StreamType>
533 void
534 print(StreamType &out) const;
535
540 void
541 write(std::ostream &out) const;
542
547 void
548 read(std::istream &in);
549
554 void
555 block_write(std::ostream &out) const;
556
561 void
562 block_read(std::istream &in);
563
564#ifdef DEAL_II_TRILINOS_WITH_EPETRA
593 Epetra_Map
594 make_trilinos_map(const MPI_Comm communicator = MPI_COMM_WORLD,
595 const bool overlapping = false) const;
596#endif
597
598#ifdef DEAL_II_TRILINOS_WITH_TPETRA
599 template <
600 typename NodeType =
602 Tpetra::Map<int, types::signed_global_dof_index, NodeType>
603 make_tpetra_map(const MPI_Comm communicator = MPI_COMM_WORLD,
604 const bool overlapping = false) const;
605
606 template <
607 typename NodeType =
609 Teuchos::RCP<Tpetra::Map<int, types::signed_global_dof_index, NodeType>>
610 make_tpetra_map_rcp(const MPI_Comm communicator = MPI_COMM_WORLD,
611 const bool overlapping = false) const;
612#endif
613
614#ifdef DEAL_II_WITH_PETSC
615 IS
616 make_petsc_is(const MPI_Comm communicator = MPI_COMM_WORLD) const;
617#endif
618
619
624 std::size_t
625 memory_consumption() const;
626
628 size_type,
629 << "The global index " << arg1
630 << " is not an element of this set.");
631
637 template <class Archive>
638 void
639 serialize(Archive &ar, const unsigned int version);
640
641
653 {
654 public:
659 IntervalAccessor(const IndexSet *idxset, const size_type range_idx);
660
664 explicit IntervalAccessor(const IndexSet *idxset);
665
670 n_elements() const;
671
675 bool
676 is_valid() const;
677
682 begin() const;
683
689 end() const;
690
695 last() const;
696
697 private:
706 operator=(const IntervalAccessor &other);
707
711 bool
712 operator==(const IntervalAccessor &other) const;
716 bool
717 operator<(const IntervalAccessor &other) const;
722 void
723 advance();
728
734
735 friend class IntervalIterator;
736 };
737
743 {
744 public:
749 IntervalIterator(const IndexSet *idxset, const size_type range_idx);
750
754 explicit IntervalIterator(const IndexSet *idxset);
755
760
764 IntervalIterator(const IntervalIterator &other) = default;
765
770 operator=(const IntervalIterator &other) = default;
771
776 operator++();
777
782 operator++(int);
783
787 const IntervalAccessor &
788 operator*() const;
789
793 const IntervalAccessor *
794 operator->() const;
795
799 bool
800 operator==(const IntervalIterator &) const;
801
805 bool
806 operator!=(const IntervalIterator &) const;
807
811 bool
812 operator<(const IntervalIterator &) const;
813
820 int
821 operator-(const IntervalIterator &p) const;
822
828 using iterator_category = std::forward_iterator_tag;
830 using difference_type = std::ptrdiff_t;
833
834 private:
839 };
840
846 {
847 public:
852 ElementIterator(const IndexSet *idxset,
853 const size_type range_idx,
854 const size_type index);
855
859 explicit ElementIterator(const IndexSet *idxset);
860
866 operator*() const;
867
871 bool
872 is_valid() const;
873
878 operator++();
879
884 operator++(int);
885
889 bool
890 operator==(const ElementIterator &) const;
891
895 bool
896 operator!=(const ElementIterator &) const;
897
901 bool
902 operator<(const ElementIterator &) const;
903
912 std::ptrdiff_t
913 operator-(const ElementIterator &p) const;
914
920 using iterator_category = std::forward_iterator_tag;
922 using difference_type = std::ptrdiff_t;
925
926 private:
930 void
931 advance();
932
945 };
946
952 begin() const;
953
969 at(const size_type global_index) const;
970
976 end() const;
977
982 begin_intervals() const;
983
989 end_intervals() const;
990
995private:
1004 struct Range
1005 {
1008
1010
1019 Range();
1020
1028 Range(const size_type i1, const size_type i2);
1029
1030 friend inline bool
1031 operator<(const Range &range_1, const Range &range_2)
1032 {
1033 return (
1034 (range_1.begin < range_2.begin) ||
1035 ((range_1.begin == range_2.begin) && (range_1.end < range_2.end)));
1036 }
1037
1038 static bool
1040 {
1041 return x.end < y.end;
1042 }
1043
1044 static bool
1046 {
1047 return (x.nth_index_in_set + (x.end - x.begin) <
1048 y.nth_index_in_set + (y.end - y.begin));
1049 }
1050
1051 friend inline bool
1052 operator==(const Range &range_1, const Range &range_2)
1053 {
1054 return ((range_1.begin == range_2.begin) && (range_1.end == range_2.end));
1055 }
1056
1057 static std::size_t
1059 {
1060 return sizeof(Range);
1061 }
1062
1068 template <class Archive>
1069 void
1070 serialize(Archive &ar, const unsigned int version);
1071 };
1072
1081 mutable std::vector<Range> ranges;
1082
1091 mutable bool is_compressed;
1092
1098
1109
1115
1119 void
1120 do_compress() const;
1121
1128 bool
1129 is_element_binary_search(const size_type local_index) const;
1130
1137 size_type
1138 nth_index_in_set_binary_search(const size_type local_index) const;
1139
1146 size_type
1147 index_within_set_binary_search(const size_type global_index) const;
1148
1154 void
1155 add_range_lower_bound(const Range &range);
1156
1160 void
1162 boost::container::small_vector<std::pair<size_type, size_type>, 200>
1163 &tmp_ranges,
1164 const bool ranges_are_sorted);
1165};
1166
1167
1168
1186inline IndexSet
1188{
1189 IndexSet is(N);
1190 is.add_range(0, N);
1191 is.compress();
1192 return is;
1193}
1194
1195/* ------------------ inline functions ------------------ */
1196
1197
1198/* IntervalAccessor */
1199
1201 const IndexSet *idxset,
1202 const IndexSet::size_type range_idx)
1203 : index_set(idxset)
1204 , range_idx(range_idx)
1205{
1206 Assert(range_idx < idxset->n_intervals(),
1207 ExcInternalError("Invalid range index"));
1208}
1209
1210
1211
1213 : index_set(idxset)
1214 , range_idx(numbers::invalid_dof_index)
1215{}
1216
1217
1218
1220 const IndexSet::IntervalAccessor &other)
1221 : index_set(other.index_set)
1222 , range_idx(other.range_idx)
1223{
1225 ExcMessage("invalid iterator"));
1226}
1227
1228
1229
1232{
1233 Assert(is_valid(), ExcMessage("invalid iterator"));
1234 return index_set->ranges[range_idx].end - index_set->ranges[range_idx].begin;
1235}
1236
1237
1238
1239inline bool
1241{
1242 return index_set != nullptr && range_idx < index_set->n_intervals();
1243}
1244
1245
1246
1249{
1250 Assert(is_valid(), ExcMessage("invalid iterator"));
1251 return {index_set, range_idx, index_set->ranges[range_idx].begin};
1252}
1253
1254
1255
1258{
1259 Assert(is_valid(), ExcMessage("invalid iterator"));
1260
1261 // point to first index in next interval unless we are the last interval.
1262 if (range_idx < index_set->ranges.size() - 1)
1263 return {index_set, range_idx + 1, index_set->ranges[range_idx + 1].begin};
1264 else
1265 return index_set->end();
1266}
1267
1268
1269
1272{
1273 Assert(is_valid(), ExcMessage("invalid iterator"));
1274
1275 return index_set->ranges[range_idx].end - 1;
1276}
1277
1278
1279
1282{
1283 index_set = other.index_set;
1284 range_idx = other.range_idx;
1285 Assert(range_idx == numbers::invalid_dof_index || is_valid(),
1286 ExcMessage("invalid iterator"));
1287 return *this;
1288}
1289
1290
1291
1292inline bool
1294 const IndexSet::IntervalAccessor &other) const
1295{
1296 Assert(index_set == other.index_set,
1297 ExcMessage(
1298 "Can not compare accessors pointing to different IndexSets"));
1299 return range_idx == other.range_idx;
1300}
1301
1302
1303
1304inline bool
1306 const IndexSet::IntervalAccessor &other) const
1307{
1308 Assert(index_set == other.index_set,
1309 ExcMessage(
1310 "Can not compare accessors pointing to different IndexSets"));
1311 return range_idx < other.range_idx;
1312}
1313
1314
1315
1316inline void
1318{
1319 Assert(
1320 is_valid(),
1321 ExcMessage(
1322 "Impossible to advance an IndexSet::IntervalIterator that is invalid"));
1323 ++range_idx;
1324
1325 // set ourselves to invalid if we walk off the end
1326 if (range_idx >= index_set->ranges.size())
1327 range_idx = numbers::invalid_dof_index;
1328}
1329
1330
1331/* IntervalIterator */
1332
1334 const IndexSet *idxset,
1335 const IndexSet::size_type range_idx)
1336 : accessor(idxset, range_idx)
1337{}
1338
1339
1340
1342 : accessor(nullptr)
1343{}
1344
1345
1346
1348 : accessor(idxset)
1349{}
1350
1351
1352
1355{
1356 accessor.advance();
1357 return *this;
1358}
1359
1360
1361
1364{
1365 const IndexSet::IntervalIterator iter = *this;
1366 accessor.advance();
1367 return iter;
1368}
1369
1370
1371
1372inline const IndexSet::IntervalAccessor &
1374{
1375 return accessor;
1376}
1377
1378
1379
1380inline const IndexSet::IntervalAccessor *
1382{
1383 return &accessor;
1384}
1385
1386
1387
1388inline bool
1390 const IndexSet::IntervalIterator &other) const
1391{
1392 return accessor == other.accessor;
1393}
1394
1395
1396
1397inline bool
1399 const IndexSet::IntervalIterator &other) const
1400{
1401 return !(*this == other);
1402}
1403
1404
1405
1406inline bool
1408 const IndexSet::IntervalIterator &other) const
1409{
1410 return accessor < other.accessor;
1411}
1412
1413
1414
1415inline int
1417 const IndexSet::IntervalIterator &other) const
1418{
1419 Assert(accessor.index_set == other.accessor.index_set,
1420 ExcMessage(
1421 "Can not compare iterators belonging to different IndexSets"));
1422
1423 const size_type lhs = (accessor.range_idx == numbers::invalid_dof_index) ?
1424 accessor.index_set->ranges.size() :
1425 accessor.range_idx;
1426 const size_type rhs =
1428 accessor.index_set->ranges.size() :
1429 other.accessor.range_idx;
1430
1431 if (lhs > rhs)
1432 return static_cast<int>(lhs - rhs);
1433 else
1434 return -static_cast<int>(rhs - lhs);
1435}
1436
1437
1438
1439/* ElementIterator */
1440
1442 const IndexSet *idxset,
1443 const IndexSet::size_type range_idx,
1444 const IndexSet::size_type index)
1445 : index_set(idxset)
1446 , range_idx(range_idx)
1447 , idx(index)
1448{
1449 Assert(range_idx < index_set->ranges.size(),
1450 ExcMessage(
1451 "Invalid range index for IndexSet::ElementIterator constructor."));
1452 Assert(
1453 idx >= index_set->ranges[range_idx].begin &&
1454 idx < index_set->ranges[range_idx].end,
1456 "Invalid index argument for IndexSet::ElementIterator constructor."));
1457}
1458
1459
1460
1462 : index_set(idxset)
1463 , range_idx(numbers::invalid_dof_index)
1464 , idx(numbers::invalid_dof_index)
1465{}
1466
1467
1468
1469inline bool
1471{
1472 Assert((range_idx == numbers::invalid_dof_index &&
1474 (range_idx < index_set->ranges.size() &&
1475 idx < index_set->ranges[range_idx].end),
1476 ExcInternalError("Invalid ElementIterator state."));
1477
1478 return (range_idx < index_set->ranges.size() &&
1479 idx < index_set->ranges[range_idx].end);
1480}
1481
1482
1483
1486{
1487 Assert(
1488 is_valid(),
1489 ExcMessage(
1490 "Impossible to dereference an IndexSet::ElementIterator that is invalid"));
1491 return idx;
1492}
1493
1494
1495
1496inline bool
1498 const IndexSet::ElementIterator &other) const
1499{
1500 Assert(index_set == other.index_set,
1501 ExcMessage(
1502 "Can not compare iterators belonging to different IndexSets"));
1503 return range_idx == other.range_idx && idx == other.idx;
1504}
1505
1506
1507
1508inline void
1510{
1511 Assert(
1512 is_valid(),
1513 ExcMessage(
1514 "Impossible to advance an IndexSet::ElementIterator that is invalid"));
1515 if (idx < index_set->ranges[range_idx].end)
1516 ++idx;
1517 // end of this range?
1518 if (idx == index_set->ranges[range_idx].end)
1519 {
1520 // point to first element in next interval if possible
1521 if (range_idx < index_set->ranges.size() - 1)
1522 {
1523 ++range_idx;
1524 idx = index_set->ranges[range_idx].begin;
1525 }
1526 else
1527 {
1528 // we just fell off the end, set to invalid:
1529 range_idx = numbers::invalid_dof_index;
1531 }
1532 }
1533}
1534
1535
1536
1539{
1540 advance();
1541 return *this;
1542}
1543
1544
1545
1548{
1549 const IndexSet::ElementIterator it = *this;
1550 advance();
1551 return it;
1552}
1553
1554
1555
1556inline bool
1558 const IndexSet::ElementIterator &other) const
1559{
1560 return !(*this == other);
1561}
1562
1563
1564
1565inline bool
1567 const IndexSet::ElementIterator &other) const
1568{
1569 Assert(index_set == other.index_set,
1570 ExcMessage(
1571 "Can not compare iterators belonging to different IndexSets"));
1572 return range_idx < other.range_idx ||
1573 (range_idx == other.range_idx && idx < other.idx);
1574}
1575
1576
1577
1578inline std::ptrdiff_t
1580 const IndexSet::ElementIterator &other) const
1581{
1582 Assert(index_set == other.index_set,
1583 ExcMessage(
1584 "Can not compare iterators belonging to different IndexSets"));
1585 if (*this == other)
1586 return 0;
1587 if (!(*this < other))
1588 return -(other - *this);
1589
1590 // only other can be equal to end() because of the checks above.
1591 Assert(is_valid(), ExcInternalError());
1592
1593 // Note: we now compute how far advance *this in "*this < other" to get other,
1594 // so we need to return -c at the end.
1595
1596 // first finish the current range:
1597 std::ptrdiff_t c = index_set->ranges[range_idx].end - idx;
1598
1599 // now walk in steps of ranges (need to start one behind our current one):
1600 for (size_type range = range_idx + 1;
1601 range < index_set->ranges.size() && range <= other.range_idx;
1602 ++range)
1603 c += index_set->ranges[range].end - index_set->ranges[range].begin;
1604
1605 Assert(
1606 other.range_idx < index_set->ranges.size() ||
1608 ExcMessage(
1609 "Inconsistent iterator state. Did you invalidate iterators by modifying the IndexSet?"));
1610
1611 // We might have walked too far because we went until the end of
1612 // other.range_idx, so walk backwards to other.idx:
1614 c -= index_set->ranges[other.range_idx].end - other.idx;
1615
1616 return -c;
1617}
1618
1619
1620/* Range */
1621
1623 : begin(numbers::invalid_dof_index)
1624 , end(numbers::invalid_dof_index)
1625 , nth_index_in_set(numbers::invalid_dof_index)
1626{}
1627
1628
1629
1631 : begin(i1)
1632 , end(i2)
1633 , nth_index_in_set(numbers::invalid_dof_index)
1634{}
1635
1636
1637
1638/* IndexSet itself */
1639
1641 : is_compressed(true)
1642 , index_space_size(0)
1643 , largest_range(numbers::invalid_unsigned_int)
1644{}
1645
1646
1647
1649 : is_compressed(true)
1650 , index_space_size(size)
1651 , largest_range(numbers::invalid_unsigned_int)
1652{}
1653
1654
1655
1656inline IndexSet::IndexSet(IndexSet &&is) noexcept
1657 : ranges(std::move(is.ranges))
1658 , is_compressed(is.is_compressed)
1659 , index_space_size(is.index_space_size)
1660 , largest_range(is.largest_range)
1661{
1662 is.ranges.clear();
1663 is.is_compressed = true;
1664 is.index_space_size = 0;
1665 is.largest_range = numbers::invalid_unsigned_int;
1666
1667 compress();
1668}
1669
1670
1671
1672inline IndexSet &
1674{
1675 ranges = std::move(is.ranges);
1676 is_compressed = is.is_compressed;
1677 index_space_size = is.index_space_size;
1678 largest_range = is.largest_range;
1679
1680 is.ranges.clear();
1681 is.is_compressed = true;
1682 is.index_space_size = 0;
1683 is.largest_range = numbers::invalid_unsigned_int;
1684
1685 compress();
1686
1687 return *this;
1688}
1689
1690
1691
1694{
1695 compress();
1696 if (ranges.size() > 0)
1697 return {this, 0, ranges[0].begin};
1698 else
1699 return end();
1700}
1701
1702
1703
1706{
1707 compress();
1708 return IndexSet::ElementIterator(this);
1709}
1710
1711
1712
1715{
1716 compress();
1717 if (ranges.size() > 0)
1718 return IndexSet::IntervalIterator(this, 0);
1719 else
1720 return end_intervals();
1721}
1722
1723
1724
1727{
1728 compress();
1729 return IndexSet::IntervalIterator(this);
1730}
1731
1732
1733
1734inline void
1736{
1737 // reset so that there are no indices in the set any more; however,
1738 // as documented, the index set retains its size
1739 ranges.clear();
1740 is_compressed = true;
1742}
1743
1744
1745
1746inline void
1748{
1749 Assert(ranges.empty(),
1750 ExcMessage("This function can only be called if the current "
1751 "object does not yet contain any elements."));
1752 index_space_size = sz;
1753 is_compressed = true;
1754}
1755
1756
1757
1760{
1761 return index_space_size;
1762}
1763
1764
1765
1766inline void
1768{
1769 if (is_compressed == true)
1770 return;
1771
1772 do_compress();
1773}
1774
1775
1776
1777inline void
1779{
1780 add_range(index, index + 1);
1781}
1782
1783
1784
1785inline void
1787{
1790 ExcIndexRangeType<size_type>(begin, 0, index_space_size));
1792 ExcIndexRangeType<size_type>(end, 0, index_space_size + 1));
1794
1795 if (begin != end)
1796 {
1797 // the new index might be larger than the last index present in the
1798 // ranges. Then we can skip the binary search
1799 if (ranges.empty() || begin > ranges.back().end)
1800 ranges.emplace_back(begin, end);
1801 else if (begin == ranges.back().end)
1802 ranges.back().end = end;
1803 else
1805
1806 is_compressed = false;
1807 }
1808}
1809
1810
1811
1812template <typename ForwardIterator>
1813inline void
1814IndexSet::add_indices(const ForwardIterator &begin, const ForwardIterator &end)
1815{
1816 if (begin == end)
1817 return;
1818
1819 // identify ranges in the given iterator range by checking whether some
1820 // indices happen to be consecutive. to avoid quadratic complexity when
1821 // calling add_range many times (as add_range() going into the middle of an
1822 // already existing range must shift entries around), we first collect a
1823 // vector of ranges.
1824 boost::container::small_vector<std::pair<size_type, size_type>, 200>
1825 tmp_ranges;
1826 bool ranges_are_sorted = true;
1827 for (ForwardIterator p = begin; p != end;)
1828 {
1829 // Starting with the current iterator 'p', find an iterator
1830 // 'q' so that the indices pointed to by the iterators in
1831 // the range [p,q) are consecutive. These indices then form
1832 // a range that is contiguous, and that can be added all
1833 // at once.
1834 const size_type begin_index = *p;
1835 size_type end_index = begin_index + 1;
1836
1837 // Start looking at the position after 'p', and keep iterating while
1838 // 'q' points to a duplicate of 'p':
1839 ForwardIterator q = p;
1840 ++q;
1841 while ((q != end) && (*q == *p))
1842 ++q;
1843
1844 // Now we know that 'q' is either past the end, or points to a value
1845 // other than 'p'. If it points to 'end_index', we are still good with
1846 // a contiguous range; then increment the end index of that range, and
1847 // move to the next iterator that is not a duplicate of what
1848 // we were just looking at:
1849 while ((q != end) && (static_cast<size_type>(*q) == end_index))
1850 {
1851 ++q;
1852 while ((q != end) && (static_cast<size_type>(*q) == end_index))
1853 ++q;
1854
1855 ++end_index;
1856 }
1857
1858 // Add this range:
1859 tmp_ranges.emplace_back(begin_index, end_index);
1860
1861 // Then move on to the next element in the input range.
1862 // If the starting index of the next go-around of the for loop is less
1863 // than the end index of the one just identified, then we will have at
1864 // least one pair of ranges that are not sorted, and consequently the
1865 // whole collection of ranges is not sorted.
1866 p = q;
1867 if ((p != end) && (static_cast<size_type>(*p) < end_index))
1868 ranges_are_sorted = false;
1869 }
1870
1871 add_ranges_internal(tmp_ranges, ranges_are_sorted);
1872}
1873
1874
1875
1876inline bool
1878{
1879 if (ranges.empty() == false)
1880 {
1881 compress();
1882
1883 // fast check whether the index is in the largest range
1885 if (index >= ranges[largest_range].begin &&
1886 index < ranges[largest_range].end)
1887 return true;
1888 else if (ranges.size() > 1)
1889 return is_element_binary_search(index);
1890 else
1891 return false;
1892 }
1893 else
1894 return false;
1895}
1896
1897
1898
1899inline bool
1901{
1902 compress();
1903 return (ranges.size() <= 1);
1904}
1905
1906
1907
1908inline bool
1910{
1911 return ranges.empty();
1912}
1913
1914
1915
1918{
1919 // make sure we have non-overlapping ranges
1920 compress();
1921
1922 size_type v = 0;
1923 if (!ranges.empty())
1924 {
1925 const Range &r = ranges.back();
1926 v = r.nth_index_in_set + r.end - r.begin;
1927 }
1928
1929 return v;
1930}
1931
1932
1933
1934inline unsigned int
1936{
1937 compress();
1938 return ranges.size();
1939}
1940
1941
1942
1945{
1946 Assert(ranges.empty() == false, ExcMessage("IndexSet cannot be empty."));
1947
1948 compress();
1949 const std::vector<Range>::const_iterator main_range =
1950 ranges.begin() + largest_range;
1951
1952 return main_range->nth_index_in_set;
1953}
1954
1955
1956
1959{
1961
1962 compress();
1963
1964 // first check whether the index is in the largest range
1966 const auto main_range = ranges.begin() + largest_range;
1967 if (n >= main_range->nth_index_in_set &&
1968 n < main_range->nth_index_in_set + (main_range->end - main_range->begin))
1969 return main_range->begin + (n - main_range->nth_index_in_set);
1970 else
1972}
1973
1974
1975
1978{
1979 // to make this call thread-safe, compress() must not be called through this
1980 // function
1981 Assert(is_compressed == true, ExcMessage("IndexSet must be compressed."));
1982 AssertIndexRange(n, size());
1983
1984 // return immediately if the index set is empty
1985 if (is_empty())
1987
1988 // check whether the index is in the largest range. use the result to
1989 // perform a one-sided binary search afterward
1992 return (n - ranges[largest_range].begin) +
1993 ranges[largest_range].nth_index_in_set;
1994 else if (ranges.size() > 1)
1996 else
1998}
1999
2000
2001
2002inline bool
2004{
2005 // If one of the two index sets has size zero, the other one has to
2006 // have size zero as well:
2007 if (size() == 0)
2008 return (is.size() == 0);
2009 if (is.size() == 0)
2010 return (size() == 0);
2011
2012 // Otherwise, they must have the same size (see the documentation):
2013 Assert(size() == is.size(), ExcDimensionMismatch(size(), is.size()));
2014
2015 compress();
2016 is.compress();
2017
2018 return (ranges == is.ranges);
2019}
2020
2021
2022
2023inline bool
2025{
2026 // If one of the two index sets has size zero, the other one has to
2027 // have a non-zero size for inequality:
2028 if (size() == 0)
2029 return (is.size() != 0);
2030 if (is.size() == 0)
2031 return (size() != 0);
2032
2033 // Otherwise, they must have the same size (see the documentation):
2034 Assert(size() == is.size(), ExcDimensionMismatch(size(), is.size()));
2035
2036 compress();
2037 is.compress();
2038
2039 return (ranges != is.ranges);
2040}
2041
2042
2043
2044template <typename Vector>
2045void
2047{
2048 Assert(vector.size() == size(), ExcDimensionMismatch(vector.size(), size()));
2049
2050 compress();
2051 // first fill all elements of the vector with zeroes.
2052 std::fill(vector.begin(), vector.end(), 0);
2053
2054 // then write ones into the elements whose indices are contained in the
2055 // index set
2056 for (const auto &range : ranges)
2057 for (size_type i = range.begin; i < range.end; ++i)
2058 vector[i] = 1;
2059}
2060
2061
2062
2063template <typename StreamType>
2064inline void
2065IndexSet::print(StreamType &out) const
2066{
2067 compress();
2068 out << '{';
2069 std::vector<Range>::const_iterator p;
2070 for (p = ranges.begin(); p != ranges.end(); ++p)
2071 {
2072 if (p->end - p->begin == 1)
2073 out << p->begin;
2074 else
2075 out << '[' << p->begin << ',' << p->end - 1 << ']';
2076
2077 if (p != --ranges.end())
2078 out << ", ";
2079 }
2080 out << '}' << std::endl;
2081}
2082
2083
2084
2085template <class Archive>
2086inline void
2087IndexSet::Range::serialize(Archive &ar, const unsigned int)
2088{
2090}
2091
2092
2093
2094template <class Archive>
2095inline void
2096IndexSet::serialize(Archive &ar, const unsigned int)
2097{
2099}
2100
2102
2103#endif
*  iterator end()
*  *  iterator begin()
size_type operator*() const
Definition index_set.h:1485
bool operator==(const ElementIterator &) const
Definition index_set.h:1497
ElementIterator(const IndexSet *idxset, const size_type range_idx, const size_type index)
Definition index_set.h:1441
std::ptrdiff_t difference_type
Definition index_set.h:922
ElementIterator & operator++()
Definition index_set.h:1538
bool operator<(const ElementIterator &) const
Definition index_set.h:1566
bool operator!=(const ElementIterator &) const
Definition index_set.h:1557
std::ptrdiff_t operator-(const ElementIterator &p) const
Definition index_set.h:1579
std::forward_iterator_tag iterator_category
Definition index_set.h:920
const IndexSet * index_set
Definition index_set.h:936
size_type last() const
Definition index_set.h:1271
ElementIterator end() const
Definition index_set.h:1257
size_type n_elements() const
Definition index_set.h:1231
bool operator==(const IntervalAccessor &other) const
Definition index_set.h:1293
IntervalAccessor & operator=(const IntervalAccessor &other)
Definition index_set.h:1281
bool operator<(const IntervalAccessor &other) const
Definition index_set.h:1305
IntervalAccessor(const IndexSet *idxset, const size_type range_idx)
Definition index_set.h:1200
const IndexSet * index_set
Definition index_set.h:727
ElementIterator begin() const
Definition index_set.h:1248
std::ptrdiff_t difference_type
Definition index_set.h:830
const IntervalAccessor & operator*() const
Definition index_set.h:1373
IntervalIterator(const IntervalIterator &other)=default
bool operator==(const IntervalIterator &) const
Definition index_set.h:1389
int operator-(const IntervalIterator &p) const
Definition index_set.h:1416
bool operator<(const IntervalIterator &) const
Definition index_set.h:1407
std::forward_iterator_tag iterator_category
Definition index_set.h:828
IntervalIterator & operator=(const IntervalIterator &other)=default
IntervalIterator & operator++()
Definition index_set.h:1354
const IntervalAccessor * operator->() const
Definition index_set.h:1381
IntervalAccessor accessor
Definition index_set.h:838
bool operator!=(const IntervalIterator &) const
Definition index_set.h:1398
bool is_subset_of(const IndexSet &other) const
Definition index_set.cc:691
bool is_element_binary_search(const size_type local_index) const
Definition index_set.cc:786
size_type index_within_set_binary_search(const size_type global_index) const
Definition index_set.cc:839
size_type largest_range
Definition index_set.h:1108
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
Definition index_set.h:1900
unsigned int n_intervals() const
Definition index_set.h:1935
Tpetra::Map< int, types::signed_global_dof_index, NodeType > make_tpetra_map(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition index_set.cc:933
IndexSet(const IndexSet &)=default
IntervalIterator end_intervals() const
Definition index_set.h:1726
void do_compress() const
Definition index_set.cc:145
ElementIterator at(const size_type global_index) const
Definition index_set.cc:861
size_type size() const
Definition index_set.h:1759
bool is_empty() const
Definition index_set.h:1909
size_type index_within_set(const size_type global_index) const
Definition index_set.h:1977
std::vector< IndexSet > split_by_block(const std::vector< types::global_dof_index > &n_indices_per_block) const
Definition index_set.cc:466
size_type n_elements() const
Definition index_set.h:1917
bool operator==(const IndexSet &is) const
Definition index_set.h:2003
void add_range_lower_bound(const Range &range)
Definition index_set.cc:579
bool is_element(const size_type index) const
Definition index_set.h:1877
void serialize(Archive &ar, const unsigned int version)
Definition index_set.h:2096
ElementIterator begin() const
Definition index_set.h:1693
signed int value_type
Definition index_set.h:104
void set_size(const size_type size)
Definition index_set.h:1747
bool operator!=(const IndexSet &is) const
Definition index_set.h:2024
void read(std::istream &in)
Definition index_set.cc:730
Epetra_Map make_trilinos_map(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
void clear()
Definition index_set.h:1735
size_type largest_range_starting_index() const
Definition index_set.h:1944
void add_index(const size_type index)
Definition index_set.h:1778
void write(std::ostream &out) const
Definition index_set.cc:715
void block_read(std::istream &in)
Definition index_set.cc:766
bool is_compressed
Definition index_set.h:1091
void add_ranges_internal(boost::container::small_vector< std::pair< size_type, size_type >, 200 > &tmp_ranges, const bool ranges_are_sorted)
Definition index_set.cc:595
IntervalIterator begin_intervals() const
Definition index_set.h:1714
IndexSet & operator=(const IndexSet &)=default
void fill_binary_vector(VectorType &vector) const
std::vector< Range > ranges
Definition index_set.h:1081
void subtract_set(const IndexSet &other)
Definition index_set.cc:496
ElementIterator end() const
Definition index_set.h:1705
Threads::Mutex compress_mutex
Definition index_set.h:1114
IndexSet complete_index_set(const IndexSet::size_type N)
Definition index_set.h:1187
size_type index_space_size
Definition index_set.h:1097
void block_write(std::ostream &out) const
Definition index_set.cc:752
IndexSet get_view(const size_type begin, const size_type end) const
Definition index_set.cc:295
void add_range(const size_type begin, const size_type end)
Definition index_set.h:1786
size_type nth_index_in_set(const size_type local_index) const
Definition index_set.h:1958
std::size_t memory_consumption() const
void print(StreamType &out) const
Definition index_set.h:2065
size_type nth_index_in_set_binary_search(const size_type local_index) const
Definition index_set.cc:822
void compress() const
Definition index_set.h:1767
std::vector< size_type > get_index_vector() const
Definition index_set.cc:911
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
Definition index_set.cc:943
types::global_dof_index size_type
Definition index_set.h:85
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
IndexSet operator&(const IndexSet &is) const
virtual size_type size() const override
iterator end()
iterator begin()
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:636
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:680
#define Assert(cond, exc)
static ::ExceptionBase & ExcIndexNotPresent(size_type arg1)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::size_t size
Definition mpi.cc:733
Tpetra::KokkosCompat::KokkosDeviceWrapperNode< typename MemorySpace::kokkos_space::execution_space, typename MemorySpace::kokkos_space > NodeType
constexpr types::global_dof_index invalid_dof_index
Definition types.h:259
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
unsigned int global_dof_index
Definition types.h:92
static bool end_compare(const IndexSet::Range &x, const IndexSet::Range &y)
Definition index_set.h:1039
static bool nth_index_compare(const IndexSet::Range &x, const IndexSet::Range &y)
Definition index_set.h:1045
friend bool operator==(const Range &range_1, const Range &range_2)
Definition index_set.h:1052
size_type end
Definition index_set.h:1007
size_type nth_index_in_set
Definition index_set.h:1009
static std::size_t memory_consumption()
Definition index_set.h:1058
size_type begin
Definition index_set.h:1006
void serialize(Archive &ar, const unsigned int version)
Definition index_set.h:2087
friend bool operator<(const Range &range_1, const Range &range_2)
Definition index_set.h:1031
void advance(std::tuple< I1, I2 > &t, const unsigned int n)