deal.II version 9.7.0
\(\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: LGPL-2.1-or-later
4// Copyright (C) 2009 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_index_set_h
16#define dealii_index_set_h
17
18#include <deal.II/base/config.h>
19
23#include <deal.II/base/mutex.h>
25#include <deal.II/base/types.h>
26
28
29#include <boost/container/small_vector.hpp>
30
31#include <algorithm>
32#include <vector>
33
34
35#ifdef DEAL_II_WITH_TRILINOS
36
38# include <Epetra_Map.h>
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_WITH_TRILINOS
142
143# ifdef DEAL_II_TRILINOS_WITH_TPETRA
147 template <typename NodeType>
148 explicit IndexSet(
149 const Teuchos::RCP<
150 const Tpetra::Map<int, types::signed_global_dof_index, NodeType>> &map);
151# endif // DEAL_II_TRILINOS_WITH_TPETRA
152
156 explicit IndexSet(const Epetra_BlockMap &map);
157#endif // DEAL_II_WITH_TRILINOS
158
163 void
164 clear();
165
172 void
173 set_size(const size_type size);
174
183 size() const;
184
191 void
192 add_range(const size_type begin, const size_type end);
193
202 void
203 add_index(const size_type index);
204
229 template <typename ForwardIterator>
230 void
231 add_indices(const ForwardIterator &begin, const ForwardIterator &end);
232
248 void
249 add_indices(const IndexSet &other, const size_type offset = 0);
250
254 bool
255 is_element(const size_type index) const;
256
261 bool
262 is_contiguous() const;
263
273 bool
274 is_empty() const;
275
285 bool
286 is_ascending_and_one_to_one(const MPI_Comm communicator) const;
287
292 n_elements() const;
293
300 nth_index_in_set(const size_type local_index) const;
301
309 index_within_set(const size_type global_index) const;
310
319 unsigned int
320 n_intervals() const;
321
335
340 void
341 compress() const;
342
357 bool
358 operator==(const IndexSet &is) const;
359
374 bool
375 operator!=(const IndexSet &is) const;
376
384 operator&(const IndexSet &is) const;
385
403 get_view(const size_type begin, const size_type end) const;
404
451 get_view(const IndexSet &mask) const;
452
458 std::vector<IndexSet>
460 const std::vector<types::global_dof_index> &n_indices_per_block) const;
461
467 void
468 subtract_set(const IndexSet &other);
469
487 tensor_product(const IndexSet &other) const;
488
497 DEAL_II_DEPRECATED_EARLY
499 pop_back();
500
509 DEAL_II_DEPRECATED_EARLY
511 pop_front();
512
521 std::vector<size_type>
522 get_index_vector() const;
523
531 void
532 fill_index_vector(std::vector<size_type> &indices) const;
533
546 template <typename VectorType>
547 void
548 fill_binary_vector(VectorType &vector) const;
549
557 bool
558 is_subset_of(const IndexSet &other) const;
559
564 template <typename StreamType>
565 void
566 print(StreamType &out) const;
567
572 void
573 write(std::ostream &out) const;
574
579 void
580 read(std::istream &in);
581
586 void
587 block_write(std::ostream &out) const;
588
593 void
594 block_read(std::istream &in);
595
596#ifdef DEAL_II_WITH_TRILINOS
625 Epetra_Map
626 make_trilinos_map(const MPI_Comm communicator = MPI_COMM_WORLD,
627 const bool overlapping = false) const;
628
629# ifdef DEAL_II_TRILINOS_WITH_TPETRA
630 template <
631 typename NodeType =
633 Tpetra::Map<int, types::signed_global_dof_index, NodeType>
634 make_tpetra_map(const MPI_Comm communicator = MPI_COMM_WORLD,
635 const bool overlapping = false) const;
636
637 template <
638 typename NodeType =
640 Teuchos::RCP<Tpetra::Map<int, types::signed_global_dof_index, NodeType>>
641 make_tpetra_map_rcp(const MPI_Comm communicator = MPI_COMM_WORLD,
642 const bool overlapping = false) const;
643# endif
644#endif
645
646#ifdef DEAL_II_WITH_PETSC
647 IS
648 make_petsc_is(const MPI_Comm communicator = MPI_COMM_WORLD) const;
649#endif
650
651
656 std::size_t
657 memory_consumption() const;
658
660 size_type,
661 << "The global index " << arg1
662 << " is not an element of this set.");
663
669 template <class Archive>
670 void
671 serialize(Archive &ar, const unsigned int version);
672
673
678
685 {
686 public:
691 IntervalAccessor(const IndexSet *idxset, const size_type range_idx);
692
696 explicit IntervalAccessor(const IndexSet *idxset);
697
702 n_elements() const;
703
707 bool
708 is_valid() const;
709
714 begin() const;
715
721 end() const;
722
727 last() const;
728
729 private:
738 operator=(const IntervalAccessor &other);
739
743 bool
744 operator==(const IntervalAccessor &other) const;
748 bool
749 operator<(const IntervalAccessor &other) const;
754 void
755 advance();
760
766
767 friend class IntervalIterator;
768 };
769
775 {
776 public:
781 IntervalIterator(const IndexSet *idxset, const size_type range_idx);
782
786 explicit IntervalIterator(const IndexSet *idxset);
787
792
796 IntervalIterator(const IntervalIterator &other) = default;
797
802 operator=(const IntervalIterator &other) = default;
803
808 operator++();
809
814 operator++(int);
815
819 const IntervalAccessor &
820 operator*() const;
821
825 const IntervalAccessor *
826 operator->() const;
827
831 bool
832 operator==(const IntervalIterator &) const;
833
837 bool
838 operator!=(const IntervalIterator &) const;
839
843 bool
844 operator<(const IntervalIterator &) const;
845
852 int
853 operator-(const IntervalIterator &p) const;
854
860 using iterator_category = std::forward_iterator_tag;
862 using difference_type = std::ptrdiff_t;
865
866 private:
871 };
872
878 {
879 public:
884 ElementIterator(const IndexSet *idxset,
885 const size_type range_idx,
886 const size_type index);
887
891 explicit ElementIterator(const IndexSet *idxset);
892
898 operator*() const;
899
903 bool
904 is_valid() const;
905
910 operator++();
911
916 operator++(int);
917
921 bool
922 operator==(const ElementIterator &) const;
923
927 bool
928 operator!=(const ElementIterator &) const;
929
933 bool
934 operator<(const ElementIterator &) const;
935
944 std::ptrdiff_t
945 operator-(const ElementIterator &p) const;
946
952 using iterator_category = std::forward_iterator_tag;
954 using difference_type = std::ptrdiff_t;
957
958 private:
962 void
963 advance();
964
977 };
978
984 begin() const;
985
1001 at(const size_type global_index) const;
1002
1008 end() const;
1009
1014 begin_intervals() const;
1015
1021 end_intervals() const;
1022
1026
1027private:
1036 struct Range
1037 {
1040
1042
1051 Range();
1052
1060 Range(const size_type i1, const size_type i2);
1061
1062 friend inline bool
1063 operator<(const Range &range_1, const Range &range_2)
1064 {
1065 return (
1066 (range_1.begin < range_2.begin) ||
1067 ((range_1.begin == range_2.begin) && (range_1.end < range_2.end)));
1068 }
1069
1070 static bool
1072 {
1073 return x.end < y.end;
1074 }
1075
1076 static bool
1078 {
1079 return (x.nth_index_in_set + (x.end - x.begin) <
1080 y.nth_index_in_set + (y.end - y.begin));
1081 }
1082
1083 friend inline bool
1084 operator==(const Range &range_1, const Range &range_2)
1085 {
1086 return ((range_1.begin == range_2.begin) && (range_1.end == range_2.end));
1087 }
1088
1089 static std::size_t
1091 {
1092 return sizeof(Range);
1093 }
1094
1100 template <class Archive>
1101 void
1102 serialize(Archive &ar, const unsigned int version);
1103 };
1104
1113 mutable std::vector<Range> ranges;
1114
1123 mutable bool is_compressed;
1124
1130
1141
1147
1151 void
1152 do_compress() const;
1153
1160 bool
1161 is_element_binary_search(const size_type local_index) const;
1162
1169 size_type
1170 nth_index_in_set_binary_search(const size_type local_index) const;
1171
1178 size_type
1179 index_within_set_binary_search(const size_type global_index) const;
1180
1186 void
1187 add_range_lower_bound(const Range &range);
1188
1192 void
1194 boost::container::small_vector<std::pair<size_type, size_type>, 200>
1195 &tmp_ranges,
1196 const bool ranges_are_sorted);
1197};
1198
1199
1200
1218inline IndexSet
1220{
1221 IndexSet is(N);
1222 is.add_range(0, N);
1223 is.compress();
1224 return is;
1225}
1226
1227/* ------------------ inline functions ------------------ */
1228
1229
1230/* IntervalAccessor */
1231
1233 const IndexSet *idxset,
1235 : index_set(idxset)
1237{
1239 ExcInternalError("Invalid range index"));
1240}
1241
1242
1243
1245 : index_set(idxset)
1246 , range_idx(numbers::invalid_dof_index)
1247{}
1248
1249
1250
1252 const IndexSet::IntervalAccessor &other)
1253 : index_set(other.index_set)
1254 , range_idx(other.range_idx)
1255{
1257 ExcMessage("invalid iterator"));
1258}
1259
1260
1261
1264{
1265 Assert(is_valid(), ExcMessage("invalid iterator"));
1266 return index_set->ranges[range_idx].end - index_set->ranges[range_idx].begin;
1267}
1268
1269
1270
1271inline bool
1273{
1274 return index_set != nullptr && range_idx < index_set->n_intervals();
1275}
1276
1277
1278
1281{
1282 Assert(is_valid(), ExcMessage("invalid iterator"));
1283 return {index_set, range_idx, index_set->ranges[range_idx].begin};
1284}
1285
1286
1287
1290{
1291 Assert(is_valid(), ExcMessage("invalid iterator"));
1292
1293 // point to first index in next interval unless we are the last interval.
1294 if (range_idx < index_set->ranges.size() - 1)
1295 return {index_set, range_idx + 1, index_set->ranges[range_idx + 1].begin};
1296 else
1297 return index_set->end();
1298}
1299
1300
1301
1304{
1305 Assert(is_valid(), ExcMessage("invalid iterator"));
1306
1307 return index_set->ranges[range_idx].end - 1;
1308}
1309
1310
1311
1314{
1315 index_set = other.index_set;
1316 range_idx = other.range_idx;
1318 ExcMessage("invalid iterator"));
1319 return *this;
1320}
1321
1322
1323
1324inline bool
1326 const IndexSet::IntervalAccessor &other) const
1327{
1328 Assert(index_set == other.index_set,
1329 ExcMessage(
1330 "Can not compare accessors pointing to different IndexSets"));
1331 return range_idx == other.range_idx;
1332}
1333
1334
1335
1336inline bool
1338 const IndexSet::IntervalAccessor &other) const
1339{
1340 Assert(index_set == other.index_set,
1341 ExcMessage(
1342 "Can not compare accessors pointing to different IndexSets"));
1343 return range_idx < other.range_idx;
1344}
1345
1346
1347
1348inline void
1350{
1351 Assert(
1352 is_valid(),
1353 ExcMessage(
1354 "Impossible to advance an IndexSet::IntervalIterator that is invalid"));
1355 ++range_idx;
1356
1357 // set ourselves to invalid if we walk off the end
1358 if (range_idx >= index_set->ranges.size())
1360}
1361
1362
1363/* IntervalIterator */
1364
1366 const IndexSet *idxset,
1367 const IndexSet::size_type range_idx)
1368 : accessor(idxset, range_idx)
1369{}
1370
1371
1372
1376
1377
1378
1380 : accessor(idxset)
1381{}
1382
1383
1384
1387{
1388 accessor.advance();
1389 return *this;
1390}
1391
1392
1393
1396{
1397 const IndexSet::IntervalIterator iter = *this;
1398 accessor.advance();
1399 return iter;
1400}
1401
1402
1403
1404inline const IndexSet::IntervalAccessor &
1406{
1407 return accessor;
1408}
1409
1410
1411
1412inline const IndexSet::IntervalAccessor *
1414{
1415 return &accessor;
1416}
1417
1418
1419
1420inline bool
1422 const IndexSet::IntervalIterator &other) const
1423{
1424 return accessor == other.accessor;
1425}
1426
1427
1428
1429inline bool
1431 const IndexSet::IntervalIterator &other) const
1432{
1433 return !(*this == other);
1434}
1435
1436
1437
1438inline bool
1440 const IndexSet::IntervalIterator &other) const
1441{
1442 return accessor < other.accessor;
1443}
1444
1445
1446
1447inline int
1449 const IndexSet::IntervalIterator &other) const
1450{
1451 Assert(accessor.index_set == other.accessor.index_set,
1452 ExcMessage(
1453 "Can not compare iterators belonging to different IndexSets"));
1454
1455 const size_type lhs = (accessor.range_idx == numbers::invalid_dof_index) ?
1456 accessor.index_set->ranges.size() :
1457 accessor.range_idx;
1458 const size_type rhs =
1460 accessor.index_set->ranges.size() :
1461 other.accessor.range_idx;
1462
1463 if (lhs > rhs)
1464 return static_cast<int>(lhs - rhs);
1465 else
1466 return -static_cast<int>(rhs - lhs);
1467}
1468
1469
1470
1471/* ElementIterator */
1472
1474 const IndexSet *idxset,
1476 const IndexSet::size_type index)
1477 : index_set(idxset)
1479 , idx(index)
1480{
1482 ExcMessage(
1483 "Invalid range index for IndexSet::ElementIterator constructor."));
1484 Assert(
1485 idx >= index_set->ranges[range_idx].begin &&
1488 "Invalid index argument for IndexSet::ElementIterator constructor."));
1489}
1490
1491
1492
1494 : index_set(idxset)
1495 , range_idx(numbers::invalid_dof_index)
1496 , idx(numbers::invalid_dof_index)
1497{}
1498
1499
1500
1501inline bool
1503{
1506 (range_idx < index_set->ranges.size() &&
1507 idx < index_set->ranges[range_idx].end),
1508 ExcInternalError("Invalid ElementIterator state."));
1509
1510 return (range_idx < index_set->ranges.size() &&
1511 idx < index_set->ranges[range_idx].end);
1512}
1513
1514
1515
1518{
1519 Assert(
1520 is_valid(),
1521 ExcMessage(
1522 "Impossible to dereference an IndexSet::ElementIterator that is invalid"));
1523 return idx;
1524}
1525
1526
1527
1528inline bool
1530 const IndexSet::ElementIterator &other) const
1531{
1532 Assert(index_set == other.index_set,
1533 ExcMessage(
1534 "Can not compare iterators belonging to different IndexSets"));
1535 return range_idx == other.range_idx && idx == other.idx;
1536}
1537
1538
1539
1540inline void
1542{
1543 Assert(
1544 is_valid(),
1545 ExcMessage(
1546 "Impossible to advance an IndexSet::ElementIterator that is invalid"));
1547 if (idx < index_set->ranges[range_idx].end)
1548 ++idx;
1549 // end of this range?
1550 if (idx == index_set->ranges[range_idx].end)
1551 {
1552 // point to first element in next interval if possible
1553 if (range_idx < index_set->ranges.size() - 1)
1554 {
1555 ++range_idx;
1556 idx = index_set->ranges[range_idx].begin;
1557 }
1558 else
1559 {
1560 // we just fell off the end, set to invalid:
1563 }
1564 }
1565}
1566
1567
1568
1571{
1572 advance();
1573 return *this;
1574}
1575
1576
1577
1580{
1581 const IndexSet::ElementIterator it = *this;
1582 advance();
1583 return it;
1584}
1585
1586
1587
1588inline bool
1590 const IndexSet::ElementIterator &other) const
1591{
1592 return !(*this == other);
1593}
1594
1595
1596
1597inline bool
1599 const IndexSet::ElementIterator &other) const
1600{
1601 Assert(index_set == other.index_set,
1602 ExcMessage(
1603 "Can not compare iterators belonging to different IndexSets"));
1604 return range_idx < other.range_idx ||
1605 (range_idx == other.range_idx && idx < other.idx);
1606}
1607
1608
1609
1610inline std::ptrdiff_t
1612 const IndexSet::ElementIterator &other) const
1613{
1614 Assert(index_set == other.index_set,
1615 ExcMessage(
1616 "Can not compare iterators belonging to different IndexSets"));
1617 if (*this == other)
1618 return 0;
1619 if (!(*this < other))
1620 return -(other - *this);
1621
1622 // only other can be equal to end() because of the checks above.
1624
1625 // Note: we now compute how far advance *this in "*this < other" to get other,
1626 // so we need to return -c at the end.
1627
1628 // first finish the current range:
1629 std::ptrdiff_t c = index_set->ranges[range_idx].end - idx;
1630
1631 // now walk in steps of ranges (need to start one behind our current one):
1632 for (size_type range = range_idx + 1;
1633 range < index_set->ranges.size() && range <= other.range_idx;
1634 ++range)
1635 c += index_set->ranges[range].end - index_set->ranges[range].begin;
1636
1637 Assert(
1638 other.range_idx < index_set->ranges.size() ||
1640 ExcMessage(
1641 "Inconsistent iterator state. Did you invalidate iterators by modifying the IndexSet?"));
1642
1643 // We might have walked too far because we went until the end of
1644 // other.range_idx, so walk backwards to other.idx:
1646 c -= index_set->ranges[other.range_idx].end - other.idx;
1647
1648 return -c;
1649}
1650
1651
1652/* Range */
1653
1655 : begin(numbers::invalid_dof_index)
1656 , end(numbers::invalid_dof_index)
1657 , nth_index_in_set(numbers::invalid_dof_index)
1658{}
1659
1660
1661
1663 : begin(i1)
1664 , end(i2)
1665 , nth_index_in_set(numbers::invalid_dof_index)
1666{}
1667
1668
1669
1670/* IndexSet itself */
1671
1673 : is_compressed(true)
1674 , index_space_size(0)
1675 , largest_range(numbers::invalid_unsigned_int)
1676{}
1677
1678
1679
1681 : is_compressed(true)
1683 , largest_range(numbers::invalid_unsigned_int)
1684{}
1685
1686
1687
1688inline IndexSet::IndexSet(IndexSet &&is) noexcept
1689 : ranges(std::move(is.ranges))
1690 , is_compressed(is.is_compressed)
1691 , index_space_size(is.index_space_size)
1692 , largest_range(is.largest_range)
1693{
1694 is.ranges.clear();
1695 is.is_compressed = true;
1696 is.index_space_size = 0;
1697 is.largest_range = numbers::invalid_unsigned_int;
1698
1699 compress();
1700}
1701
1702
1703
1704inline IndexSet &
1706{
1707 ranges = std::move(is.ranges);
1708 is_compressed = is.is_compressed;
1709 index_space_size = is.index_space_size;
1710 largest_range = is.largest_range;
1711
1712 is.ranges.clear();
1713 is.is_compressed = true;
1714 is.index_space_size = 0;
1715 is.largest_range = numbers::invalid_unsigned_int;
1716
1717 compress();
1718
1719 return *this;
1720}
1721
1722
1723
1726{
1727 compress();
1728 if (ranges.size() > 0)
1729 return {this, 0, ranges[0].begin};
1730 else
1731 return end();
1732}
1733
1734
1735
1738{
1739 compress();
1740 return IndexSet::ElementIterator(this);
1741}
1742
1743
1744
1747{
1748 compress();
1749 if (ranges.size() > 0)
1750 return IndexSet::IntervalIterator(this, 0);
1751 else
1752 return end_intervals();
1753}
1754
1755
1756
1759{
1760 compress();
1761 return IndexSet::IntervalIterator(this);
1762}
1763
1764
1765
1766inline void
1768{
1769 // reset so that there are no indices in the set any more; however,
1770 // as documented, the index set retains its size
1771 ranges.clear();
1772 is_compressed = true;
1774}
1775
1776
1777
1778inline void
1780{
1781 Assert(ranges.empty(),
1782 ExcMessage("This function can only be called if the current "
1783 "object does not yet contain any elements."));
1784 index_space_size = sz;
1785 is_compressed = true;
1786}
1787
1788
1789
1792{
1793 return index_space_size;
1794}
1795
1796
1797
1798inline void
1800{
1801 if (is_compressed == true)
1802 return;
1803
1804 do_compress();
1805}
1806
1807
1808
1809inline void
1811{
1812 add_range(index, index + 1);
1813}
1814
1815
1816
1817inline void
1819{
1826
1827 if (begin != end)
1828 {
1829 // the new index might be larger than the last index present in the
1830 // ranges. Then we can skip the binary search
1831 if (ranges.empty() || begin > ranges.back().end)
1832 ranges.emplace_back(begin, end);
1833 else if (begin == ranges.back().end)
1834 ranges.back().end = end;
1835 else
1837
1838 is_compressed = false;
1839 }
1840}
1841
1842
1843
1844template <typename ForwardIterator>
1845inline void
1846IndexSet::add_indices(const ForwardIterator &begin, const ForwardIterator &end)
1847{
1848 if (begin == end)
1849 return;
1850
1851 // identify ranges in the given iterator range by checking whether some
1852 // indices happen to be consecutive. to avoid quadratic complexity when
1853 // calling add_range many times (as add_range() going into the middle of an
1854 // already existing range must shift entries around), we first collect a
1855 // vector of ranges.
1856 boost::container::small_vector<std::pair<size_type, size_type>, 200>
1857 tmp_ranges;
1858 bool ranges_are_sorted = true;
1859 for (ForwardIterator p = begin; p != end;)
1860 {
1861 // Starting with the current iterator 'p', find an iterator
1862 // 'q' so that the indices pointed to by the iterators in
1863 // the range [p,q) are consecutive. These indices then form
1864 // a range that is contiguous, and that can be added all
1865 // at once.
1866 const size_type begin_index = *p;
1867 size_type end_index = begin_index + 1;
1868
1869 // Start looking at the position after 'p', and keep iterating while
1870 // 'q' points to a duplicate of 'p':
1871 ForwardIterator q = p;
1872 ++q;
1873 while ((q != end) && (*q == *p))
1874 ++q;
1875
1876 // Now we know that 'q' is either past the end, or points to a value
1877 // other than 'p'. If it points to 'end_index', we are still good with
1878 // a contiguous range; then increment the end index of that range, and
1879 // move to the next iterator that is not a duplicate of what
1880 // we were just looking at:
1881 while ((q != end) && (static_cast<size_type>(*q) == end_index))
1882 {
1883 ++q;
1884 while ((q != end) && (static_cast<size_type>(*q) == end_index))
1885 ++q;
1886
1887 ++end_index;
1888 }
1889
1890 // Add this range:
1891 tmp_ranges.emplace_back(begin_index, end_index);
1892
1893 // Then move on to the next element in the input range.
1894 // If the starting index of the next go-around of the for loop is less
1895 // than the end index of the one just identified, then we will have at
1896 // least one pair of ranges that are not sorted, and consequently the
1897 // whole collection of ranges is not sorted.
1898 p = q;
1899 if ((p != end) && (static_cast<size_type>(*p) < end_index))
1900 ranges_are_sorted = false;
1901 }
1902
1903 add_ranges_internal(tmp_ranges, ranges_are_sorted);
1904}
1905
1906
1907
1908inline bool
1910{
1911 if (ranges.empty() == false)
1912 {
1913 compress();
1914
1915 // fast check whether the index is in the largest range
1917 if (index >= ranges[largest_range].begin &&
1918 index < ranges[largest_range].end)
1919 return true;
1920 else if (ranges.size() > 1)
1921 return is_element_binary_search(index);
1922 else
1923 return false;
1924 }
1925 else
1926 return false;
1927}
1928
1929
1930
1931inline bool
1933{
1934 compress();
1935 return (ranges.size() <= 1);
1936}
1937
1938
1939
1940inline bool
1942{
1943 return ranges.empty();
1944}
1945
1946
1947
1950{
1951 // make sure we have non-overlapping ranges
1952 compress();
1953
1954 size_type v = 0;
1955 if (!ranges.empty())
1956 {
1957 const Range &r = ranges.back();
1958 v = r.nth_index_in_set + r.end - r.begin;
1959 }
1960
1961 if constexpr (running_in_debug_mode())
1962 {
1963 size_type s = 0;
1964 for (const auto &range : ranges)
1965 s += (range.end - range.begin);
1966 Assert(s == v, ExcInternalError());
1967 }
1968
1969 return v;
1970}
1971
1972
1973
1974inline unsigned int
1976{
1977 compress();
1978 return ranges.size();
1979}
1980
1981
1982
1985{
1986 Assert(ranges.empty() == false, ExcMessage("IndexSet cannot be empty."));
1987
1988 compress();
1989 const std::vector<Range>::const_iterator main_range =
1990 ranges.begin() + largest_range;
1991
1992 return main_range->nth_index_in_set;
1993}
1994
1995
1996
1999{
2001
2002 compress();
2003
2004 // first check whether the index is in the largest range
2006 const auto main_range = ranges.begin() + largest_range;
2007 if (n >= main_range->nth_index_in_set &&
2008 n < main_range->nth_index_in_set + (main_range->end - main_range->begin))
2009 return main_range->begin + (n - main_range->nth_index_in_set);
2010 else
2012}
2013
2014
2015
2018{
2019 // to make this call thread-safe, compress() must not be called through this
2020 // function
2021 Assert(is_compressed == true, ExcMessage("IndexSet must be compressed."));
2022 AssertIndexRange(n, size());
2023
2024 // return immediately if the index set is empty
2025 if (is_empty())
2027
2028 // check whether the index is in the largest range. use the result to
2029 // perform a one-sided binary search afterward
2032 return (n - ranges[largest_range].begin) +
2033 ranges[largest_range].nth_index_in_set;
2034 else if (ranges.size() > 1)
2036 else
2038}
2039
2040
2041
2042inline bool
2044{
2045 // If one of the two index sets has size zero, the other one has to
2046 // have size zero as well:
2047 if (size() == 0)
2048 return (is.size() == 0);
2049 if (is.size() == 0)
2050 return (size() == 0);
2051
2052 // Otherwise, they must have the same size (see the documentation):
2053 Assert(size() == is.size(), ExcDimensionMismatch(size(), is.size()));
2054
2055 compress();
2056 is.compress();
2057
2058 return (ranges == is.ranges);
2059}
2060
2061
2062
2063inline bool
2065{
2066 // If one of the two index sets has size zero, the other one has to
2067 // have a non-zero size for inequality:
2068 if (size() == 0)
2069 return (is.size() != 0);
2070 if (is.size() == 0)
2071 return (size() != 0);
2072
2073 // Otherwise, they must have the same size (see the documentation):
2074 Assert(size() == is.size(), ExcDimensionMismatch(size(), is.size()));
2075
2076 compress();
2077 is.compress();
2078
2079 return (ranges != is.ranges);
2080}
2081
2082
2083
2084template <typename Vector>
2085void
2087{
2088 Assert(vector.size() == size(), ExcDimensionMismatch(vector.size(), size()));
2089
2090 compress();
2091 // first fill all elements of the vector with zeroes.
2092 std::fill(vector.begin(), vector.end(), 0);
2093
2094 // then write ones into the elements whose indices are contained in the
2095 // index set
2096 for (const auto &range : ranges)
2097 for (size_type i = range.begin; i < range.end; ++i)
2098 vector[i] = 1;
2099}
2100
2101
2102
2103template <typename StreamType>
2104inline void
2105IndexSet::print(StreamType &out) const
2106{
2107 compress();
2108 out << '{';
2109 std::vector<Range>::const_iterator p;
2110 for (p = ranges.begin(); p != ranges.end(); ++p)
2111 {
2112 if (p->end - p->begin == 1)
2113 out << p->begin;
2114 else
2115 out << '[' << p->begin << ',' << p->end - 1 << ']';
2116
2117 if (p != --ranges.end())
2118 out << ", ";
2119 }
2120 out << '}' << std::endl;
2121}
2122
2123
2124
2125template <class Archive>
2126inline void
2127IndexSet::Range::serialize(Archive &ar, const unsigned int)
2128{
2130}
2131
2132
2133
2134template <class Archive>
2135inline void
2136IndexSet::serialize(Archive &ar, const unsigned int)
2137{
2139}
2140
2142
2143#endif
size_type operator*() const
Definition index_set.h:1517
bool operator==(const ElementIterator &) const
Definition index_set.h:1529
ElementIterator(const IndexSet *idxset, const size_type range_idx, const size_type index)
Definition index_set.h:1473
std::ptrdiff_t difference_type
Definition index_set.h:954
ElementIterator & operator++()
Definition index_set.h:1570
bool operator<(const ElementIterator &) const
Definition index_set.h:1598
bool operator!=(const ElementIterator &) const
Definition index_set.h:1589
std::ptrdiff_t operator-(const ElementIterator &p) const
Definition index_set.h:1611
std::forward_iterator_tag iterator_category
Definition index_set.h:952
const IndexSet * index_set
Definition index_set.h:968
size_type last() const
Definition index_set.h:1303
ElementIterator end() const
Definition index_set.h:1289
friend class IntervalIterator
Definition index_set.h:767
size_type n_elements() const
Definition index_set.h:1263
bool operator==(const IntervalAccessor &other) const
Definition index_set.h:1325
IntervalAccessor & operator=(const IntervalAccessor &other)
Definition index_set.h:1313
bool operator<(const IntervalAccessor &other) const
Definition index_set.h:1337
IntervalAccessor(const IndexSet *idxset, const size_type range_idx)
Definition index_set.h:1232
const IndexSet * index_set
Definition index_set.h:759
ElementIterator begin() const
Definition index_set.h:1280
IntervalAccessor & reference
Definition index_set.h:864
std::ptrdiff_t difference_type
Definition index_set.h:862
const IntervalAccessor & operator*() const
Definition index_set.h:1405
IntervalIterator(const IntervalIterator &other)=default
bool operator==(const IntervalIterator &) const
Definition index_set.h:1421
int operator-(const IntervalIterator &p) const
Definition index_set.h:1448
bool operator<(const IntervalIterator &) const
Definition index_set.h:1439
std::forward_iterator_tag iterator_category
Definition index_set.h:860
IntervalIterator & operator=(const IntervalIterator &other)=default
IntervalAccessor value_type
Definition index_set.h:861
IntervalIterator & operator++()
Definition index_set.h:1386
const IntervalAccessor * operator->() const
Definition index_set.h:1413
IntervalIterator(const IndexSet *idxset, const size_type range_idx)
Definition index_set.h:1365
IntervalAccessor * pointer
Definition index_set.h:863
IntervalAccessor accessor
Definition index_set.h:870
bool operator!=(const IntervalIterator &) const
Definition index_set.h:1430
bool is_subset_of(const IndexSet &other) const
Definition index_set.cc:713
bool is_element_binary_search(const size_type local_index) const
Definition index_set.cc:808
size_type index_within_set_binary_search(const size_type global_index) const
Definition index_set.cc:861
size_type largest_range
Definition index_set.h:1140
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:1932
unsigned int n_intervals() const
Definition index_set.h:1975
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:964
IndexSet(const IndexSet &)=default
IntervalIterator end_intervals() const
Definition index_set.h:1758
void do_compress() const
Definition index_set.cc:143
ElementIterator at(const size_type global_index) const
Definition index_set.cc:883
size_type size() const
Definition index_set.h:1791
void fill_index_vector(std::vector< size_type > &indices) const
Definition index_set.cc:952
bool is_empty() const
Definition index_set.h:1941
size_type index_within_set(const size_type global_index) const
Definition index_set.h:2017
std::vector< IndexSet > split_by_block(const std::vector< types::global_dof_index > &n_indices_per_block) const
Definition index_set.cc:450
size_type n_elements() const
Definition index_set.h:1949
bool operator==(const IndexSet &is) const
Definition index_set.h:2043
void add_range_lower_bound(const Range &range)
Definition index_set.cc:601
bool is_element(const size_type index) const
Definition index_set.h:1909
void serialize(Archive &ar, const unsigned int version)
Definition index_set.h:2136
ElementIterator begin() const
Definition index_set.h:1725
size_type pop_front()
Definition index_set.cc:579
signed int value_type
Definition index_set.h:104
void set_size(const size_type size)
Definition index_set.h:1779
bool operator!=(const IndexSet &is) const
Definition index_set.h:2064
void read(std::istream &in)
Definition index_set.cc:752
Epetra_Map make_trilinos_map(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
void clear()
Definition index_set.h:1767
size_type largest_range_starting_index() const
Definition index_set.h:1984
void add_index(const size_type index)
Definition index_set.h:1810
void write(std::ostream &out) const
Definition index_set.cc:737
void block_read(std::istream &in)
Definition index_set.cc:788
bool is_compressed
Definition index_set.h:1123
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:617
IntervalIterator begin_intervals() const
Definition index_set.h:1746
IndexSet & operator=(const IndexSet &)=default
void fill_binary_vector(VectorType &vector) const
std::vector< Range > ranges
Definition index_set.h:1113
void subtract_set(const IndexSet &other)
Definition index_set.cc:480
ElementIterator end() const
Definition index_set.h:1737
Threads::Mutex compress_mutex
Definition index_set.h:1146
IndexSet complete_index_set(const IndexSet::size_type N)
Definition index_set.h:1219
size_type index_space_size
Definition index_set.h:1129
void block_write(std::ostream &out) const
Definition index_set.cc:774
IndexSet get_view(const size_type begin, const size_type end) const
Definition index_set.cc:279
void add_range(const size_type begin, const size_type end)
Definition index_set.h:1818
size_type nth_index_in_set(const size_type local_index) const
Definition index_set.h:1998
std::size_t memory_consumption() const
void print(StreamType &out) const
Definition index_set.h:2105
size_type nth_index_in_set_binary_search(const size_type local_index) const
Definition index_set.cc:844
void compress() const
Definition index_set.h:1799
size_type pop_back()
Definition index_set.cc:561
std::vector< size_type > get_index_vector() const
Definition index_set.cc:933
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:974
types::global_dof_index size_type
Definition index_set.h:85
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1846
IndexSet operator&(const IndexSet &is) const
virtual size_type size() const override
iterator end()
iterator begin()
#define DEAL_II_DEPRECATED
Definition config.h:286
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:603
constexpr bool running_in_debug_mode()
Definition config.h:78
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:647
static ::ExceptionBase & ExcIndexRangeType(T arg1, T arg2, T arg3)
#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)
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:269
constexpr unsigned int invalid_unsigned_int
Definition types.h:238
unsigned int global_dof_index
Definition types.h:94
static bool end_compare(const IndexSet::Range &x, const IndexSet::Range &y)
Definition index_set.h:1071
static bool nth_index_compare(const IndexSet::Range &x, const IndexSet::Range &y)
Definition index_set.h:1077
friend bool operator==(const Range &range_1, const Range &range_2)
Definition index_set.h:1084
size_type end
Definition index_set.h:1039
size_type nth_index_in_set
Definition index_set.h:1041
static std::size_t memory_consumption()
Definition index_set.h:1090
size_type begin
Definition index_set.h:1038
void serialize(Archive &ar, const unsigned int version)
Definition index_set.h:2127
friend bool operator<(const Range &range_1, const Range &range_2)
Definition index_set.h:1063
void advance(std::tuple< I1, I2 > &t, const unsigned int n)