deal.II version 9.8.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: 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
501 pop_back();
502
513 pop_front();
514
523 std::vector<size_type>
524 get_index_vector() const;
525
538 template <typename VectorType>
539 void
540 fill_binary_vector(VectorType &vector) const;
541
549 bool
550 is_subset_of(const IndexSet &other) const;
551
556 template <typename StreamType>
557 void
558 print(StreamType &out) const;
559
564 void
565 write(std::ostream &out) const;
566
571 void
572 read(std::istream &in);
573
578 void
579 block_write(std::ostream &out) const;
580
585 void
586 block_read(std::istream &in);
587
588#ifdef DEAL_II_TRILINOS_WITH_EPETRA
617 Epetra_Map
618 make_trilinos_map(const MPI_Comm communicator = MPI_COMM_WORLD,
619 const bool overlapping = false) const;
620#endif
621
622#ifdef DEAL_II_TRILINOS_WITH_TPETRA
623 template <
624 typename NodeType =
626 Tpetra::Map<int, types::signed_global_dof_index, NodeType>
627 make_tpetra_map(const MPI_Comm communicator = MPI_COMM_WORLD,
628 const bool overlapping = false) const;
629
630 template <
631 typename NodeType =
633 Teuchos::RCP<Tpetra::Map<int, types::signed_global_dof_index, NodeType>>
634 make_tpetra_map_rcp(const MPI_Comm communicator = MPI_COMM_WORLD,
635 const bool overlapping = false) const;
636#endif
637
638#ifdef DEAL_II_WITH_PETSC
639 IS
640 make_petsc_is(const MPI_Comm communicator = MPI_COMM_WORLD) const;
641#endif
642
643
648 std::size_t
649 memory_consumption() const;
650
652 size_type,
653 << "The global index " << arg1
654 << " is not an element of this set.");
655
661 template <class Archive>
662 void
663 serialize(Archive &ar, const unsigned int version);
664
665
670
677 {
678 public:
683 IntervalAccessor(const IndexSet *idxset, const size_type range_idx);
684
688 explicit IntervalAccessor(const IndexSet *idxset);
689
694 n_elements() const;
695
699 bool
700 is_valid() const;
701
706 begin() const;
707
713 end() const;
714
719 last() const;
720
721 private:
730 operator=(const IntervalAccessor &other);
731
735 bool
736 operator==(const IntervalAccessor &other) const;
740 bool
741 operator<(const IntervalAccessor &other) const;
746 void
747 advance();
752
758
759 friend class IntervalIterator;
760 };
761
767 {
768 public:
773 IntervalIterator(const IndexSet *idxset, const size_type range_idx);
774
778 explicit IntervalIterator(const IndexSet *idxset);
779
784
788 IntervalIterator(const IntervalIterator &other) = default;
789
794 operator=(const IntervalIterator &other) = default;
795
800 operator++();
801
806 operator++(int);
807
811 const IntervalAccessor &
812 operator*() const;
813
817 const IntervalAccessor *
818 operator->() const;
819
823 bool
824 operator==(const IntervalIterator &) const;
825
829 bool
830 operator!=(const IntervalIterator &) const;
831
835 bool
836 operator<(const IntervalIterator &) const;
837
844 int
845 operator-(const IntervalIterator &p) const;
846
852 using iterator_category = std::forward_iterator_tag;
854 using difference_type = std::ptrdiff_t;
857
858 private:
863 };
864
870 {
871 public:
876 ElementIterator(const IndexSet *idxset,
877 const size_type range_idx,
878 const size_type index);
879
883 explicit ElementIterator(const IndexSet *idxset);
884
890 operator*() const;
891
895 bool
896 is_valid() const;
897
902 operator++();
903
908 operator++(int);
909
913 bool
914 operator==(const ElementIterator &) const;
915
919 bool
920 operator!=(const ElementIterator &) const;
921
925 bool
926 operator<(const ElementIterator &) const;
927
936 std::ptrdiff_t
937 operator-(const ElementIterator &p) const;
938
944 using iterator_category = std::forward_iterator_tag;
946 using difference_type = std::ptrdiff_t;
949
950 private:
954 void
955 advance();
956
969 };
970
976 begin() const;
977
993 at(const size_type global_index) const;
994
1000 end() const;
1001
1006 begin_intervals() const;
1007
1013 end_intervals() const;
1014
1018
1019private:
1028 struct Range
1029 {
1032
1034
1043 Range();
1044
1052 Range(const size_type i1, const size_type i2);
1053
1054 friend inline bool
1055 operator<(const Range &range_1, const Range &range_2)
1056 {
1057 return (
1058 (range_1.begin < range_2.begin) ||
1059 ((range_1.begin == range_2.begin) && (range_1.end < range_2.end)));
1060 }
1061
1062 static bool
1064 {
1065 return x.end < y.end;
1066 }
1067
1068 static bool
1070 {
1071 return (x.nth_index_in_set + (x.end - x.begin) <
1072 y.nth_index_in_set + (y.end - y.begin));
1073 }
1074
1075 friend inline bool
1076 operator==(const Range &range_1, const Range &range_2)
1077 {
1078 return ((range_1.begin == range_2.begin) && (range_1.end == range_2.end));
1079 }
1080
1081 static std::size_t
1083 {
1084 return sizeof(Range);
1085 }
1086
1092 template <class Archive>
1093 void
1094 serialize(Archive &ar, const unsigned int version);
1095 };
1096
1105 mutable std::vector<Range> ranges;
1106
1115 mutable bool is_compressed;
1116
1122
1133
1139
1143 void
1144 do_compress() const;
1145
1152 bool
1153 is_element_binary_search(const size_type local_index) const;
1154
1161 size_type
1162 nth_index_in_set_binary_search(const size_type local_index) const;
1163
1170 size_type
1171 index_within_set_binary_search(const size_type global_index) const;
1172
1178 void
1179 add_range_lower_bound(const Range &range);
1180
1184 void
1186 boost::container::small_vector<std::pair<size_type, size_type>, 200>
1187 &tmp_ranges,
1188 const bool ranges_are_sorted);
1189};
1190
1191
1192
1210inline IndexSet
1212{
1213 IndexSet is(N);
1214 is.add_range(0, N);
1215 is.compress();
1216 return is;
1217}
1218
1219/* ------------------ inline functions ------------------ */
1220
1221
1222/* IntervalAccessor */
1223
1225 const IndexSet *idxset,
1227 : index_set(idxset)
1229{
1231 ExcInternalError("Invalid range index"));
1232}
1233
1234
1235
1237 : index_set(idxset)
1238 , range_idx(numbers::invalid_dof_index)
1239{}
1240
1241
1242
1244 const IndexSet::IntervalAccessor &other)
1245 : index_set(other.index_set)
1246 , range_idx(other.range_idx)
1247{
1249 ExcMessage("invalid iterator"));
1250}
1251
1252
1253
1256{
1257 Assert(is_valid(), ExcMessage("invalid iterator"));
1258 return index_set->ranges[range_idx].end - index_set->ranges[range_idx].begin;
1259}
1260
1261
1262
1263inline bool
1265{
1266 return index_set != nullptr && range_idx < index_set->n_intervals();
1267}
1268
1269
1270
1273{
1274 Assert(is_valid(), ExcMessage("invalid iterator"));
1275 return {index_set, range_idx, index_set->ranges[range_idx].begin};
1276}
1277
1278
1279
1282{
1283 Assert(is_valid(), ExcMessage("invalid iterator"));
1284
1285 // point to first index in next interval unless we are the last interval.
1286 if (range_idx < index_set->ranges.size() - 1)
1287 return {index_set, range_idx + 1, index_set->ranges[range_idx + 1].begin};
1288 else
1289 return index_set->end();
1290}
1291
1292
1293
1296{
1297 Assert(is_valid(), ExcMessage("invalid iterator"));
1298
1299 return index_set->ranges[range_idx].end - 1;
1300}
1301
1302
1303
1306{
1307 index_set = other.index_set;
1308 range_idx = other.range_idx;
1310 ExcMessage("invalid iterator"));
1311 return *this;
1312}
1313
1314
1315
1316inline bool
1318 const IndexSet::IntervalAccessor &other) const
1319{
1320 Assert(index_set == other.index_set,
1321 ExcMessage(
1322 "Can not compare accessors pointing to different IndexSets"));
1323 return range_idx == other.range_idx;
1324}
1325
1326
1327
1328inline bool
1330 const IndexSet::IntervalAccessor &other) const
1331{
1332 Assert(index_set == other.index_set,
1333 ExcMessage(
1334 "Can not compare accessors pointing to different IndexSets"));
1335 return range_idx < other.range_idx;
1336}
1337
1338
1339
1340inline void
1342{
1343 Assert(
1344 is_valid(),
1345 ExcMessage(
1346 "Impossible to advance an IndexSet::IntervalIterator that is invalid"));
1347 ++range_idx;
1348
1349 // set ourselves to invalid if we walk off the end
1350 if (range_idx >= index_set->ranges.size())
1352}
1353
1354
1355/* IntervalIterator */
1356
1358 const IndexSet *idxset,
1359 const IndexSet::size_type range_idx)
1360 : accessor(idxset, range_idx)
1361{}
1362
1363
1364
1368
1369
1370
1372 : accessor(idxset)
1373{}
1374
1375
1376
1379{
1380 accessor.advance();
1381 return *this;
1382}
1383
1384
1385
1388{
1389 const IndexSet::IntervalIterator iter = *this;
1390 accessor.advance();
1391 return iter;
1392}
1393
1394
1395
1396inline const IndexSet::IntervalAccessor &
1398{
1399 return accessor;
1400}
1401
1402
1403
1404inline const IndexSet::IntervalAccessor *
1406{
1407 return &accessor;
1408}
1409
1410
1411
1412inline bool
1414 const IndexSet::IntervalIterator &other) const
1415{
1416 return accessor == other.accessor;
1417}
1418
1419
1420
1421inline bool
1423 const IndexSet::IntervalIterator &other) const
1424{
1425 return !(*this == other);
1426}
1427
1428
1429
1430inline bool
1432 const IndexSet::IntervalIterator &other) const
1433{
1434 return accessor < other.accessor;
1435}
1436
1437
1438
1439inline int
1441 const IndexSet::IntervalIterator &other) const
1442{
1443 Assert(accessor.index_set == other.accessor.index_set,
1444 ExcMessage(
1445 "Can not compare iterators belonging to different IndexSets"));
1446
1447 const size_type lhs = (accessor.range_idx == numbers::invalid_dof_index) ?
1448 accessor.index_set->ranges.size() :
1449 accessor.range_idx;
1450 const size_type rhs =
1452 accessor.index_set->ranges.size() :
1453 other.accessor.range_idx;
1454
1455 if (lhs > rhs)
1456 return static_cast<int>(lhs - rhs);
1457 else
1458 return -static_cast<int>(rhs - lhs);
1459}
1460
1461
1462
1463/* ElementIterator */
1464
1466 const IndexSet *idxset,
1468 const IndexSet::size_type index)
1469 : index_set(idxset)
1471 , idx(index)
1472{
1474 ExcMessage(
1475 "Invalid range index for IndexSet::ElementIterator constructor."));
1476 Assert(
1477 idx >= index_set->ranges[range_idx].begin &&
1480 "Invalid index argument for IndexSet::ElementIterator constructor."));
1481}
1482
1483
1484
1486 : index_set(idxset)
1487 , range_idx(numbers::invalid_dof_index)
1488 , idx(numbers::invalid_dof_index)
1489{}
1490
1491
1492
1493inline bool
1495{
1498 (range_idx < index_set->ranges.size() &&
1499 idx < index_set->ranges[range_idx].end),
1500 ExcInternalError("Invalid ElementIterator state."));
1501
1502 return (range_idx < index_set->ranges.size() &&
1503 idx < index_set->ranges[range_idx].end);
1504}
1505
1506
1507
1510{
1511 Assert(
1512 is_valid(),
1513 ExcMessage(
1514 "Impossible to dereference an IndexSet::ElementIterator that is invalid"));
1515 return idx;
1516}
1517
1518
1519
1520inline bool
1522 const IndexSet::ElementIterator &other) const
1523{
1524 Assert(index_set == other.index_set,
1525 ExcMessage(
1526 "Can not compare iterators belonging to different IndexSets"));
1527 return range_idx == other.range_idx && idx == other.idx;
1528}
1529
1530
1531
1532inline void
1534{
1535 Assert(
1536 is_valid(),
1537 ExcMessage(
1538 "Impossible to advance an IndexSet::ElementIterator that is invalid"));
1539 if (idx < index_set->ranges[range_idx].end)
1540 ++idx;
1541 // end of this range?
1542 if (idx == index_set->ranges[range_idx].end)
1543 {
1544 // point to first element in next interval if possible
1545 if (range_idx < index_set->ranges.size() - 1)
1546 {
1547 ++range_idx;
1548 idx = index_set->ranges[range_idx].begin;
1549 }
1550 else
1551 {
1552 // we just fell off the end, set to invalid:
1555 }
1556 }
1557}
1558
1559
1560
1563{
1564 advance();
1565 return *this;
1566}
1567
1568
1569
1572{
1573 const IndexSet::ElementIterator it = *this;
1574 advance();
1575 return it;
1576}
1577
1578
1579
1580inline bool
1582 const IndexSet::ElementIterator &other) const
1583{
1584 return !(*this == other);
1585}
1586
1587
1588
1589inline bool
1591 const IndexSet::ElementIterator &other) const
1592{
1593 Assert(index_set == other.index_set,
1594 ExcMessage(
1595 "Can not compare iterators belonging to different IndexSets"));
1596 return range_idx < other.range_idx ||
1597 (range_idx == other.range_idx && idx < other.idx);
1598}
1599
1600
1601
1602inline std::ptrdiff_t
1604 const IndexSet::ElementIterator &other) const
1605{
1606 Assert(index_set == other.index_set,
1607 ExcMessage(
1608 "Can not compare iterators belonging to different IndexSets"));
1609 if (*this == other)
1610 return 0;
1611 if (!(*this < other))
1612 return -(other - *this);
1613
1614 // only other can be equal to end() because of the checks above.
1616
1617 // Note: we now compute how far advance *this in "*this < other" to get other,
1618 // so we need to return -c at the end.
1619
1620 // first finish the current range:
1621 std::ptrdiff_t c = index_set->ranges[range_idx].end - idx;
1622
1623 // now walk in steps of ranges (need to start one behind our current one):
1624 for (size_type range = range_idx + 1;
1625 range < index_set->ranges.size() && range <= other.range_idx;
1626 ++range)
1627 c += index_set->ranges[range].end - index_set->ranges[range].begin;
1628
1629 Assert(
1630 other.range_idx < index_set->ranges.size() ||
1632 ExcMessage(
1633 "Inconsistent iterator state. Did you invalidate iterators by modifying the IndexSet?"));
1634
1635 // We might have walked too far because we went until the end of
1636 // other.range_idx, so walk backwards to other.idx:
1638 c -= index_set->ranges[other.range_idx].end - other.idx;
1639
1640 return -c;
1641}
1642
1643
1644/* Range */
1645
1647 : begin(numbers::invalid_dof_index)
1648 , end(numbers::invalid_dof_index)
1649 , nth_index_in_set(numbers::invalid_dof_index)
1650{}
1651
1652
1653
1655 : begin(i1)
1656 , end(i2)
1657 , nth_index_in_set(numbers::invalid_dof_index)
1658{}
1659
1660
1661
1662/* IndexSet itself */
1663
1665 : is_compressed(true)
1666 , index_space_size(0)
1667 , largest_range(numbers::invalid_unsigned_int)
1668{}
1669
1670
1671
1673 : is_compressed(true)
1675 , largest_range(numbers::invalid_unsigned_int)
1676{}
1677
1678
1679
1680inline IndexSet::IndexSet(IndexSet &&is) noexcept
1681 : ranges(std::move(is.ranges))
1682 , is_compressed(is.is_compressed)
1683 , index_space_size(is.index_space_size)
1684 , largest_range(is.largest_range)
1685{
1686 is.ranges.clear();
1687 is.is_compressed = true;
1688 is.index_space_size = 0;
1689 is.largest_range = numbers::invalid_unsigned_int;
1690
1691 compress();
1692}
1693
1694
1695
1696inline IndexSet &
1698{
1699 ranges = std::move(is.ranges);
1700 is_compressed = is.is_compressed;
1701 index_space_size = is.index_space_size;
1702 largest_range = is.largest_range;
1703
1704 is.ranges.clear();
1705 is.is_compressed = true;
1706 is.index_space_size = 0;
1707 is.largest_range = numbers::invalid_unsigned_int;
1708
1709 compress();
1710
1711 return *this;
1712}
1713
1714
1715
1718{
1719 compress();
1720 if (ranges.size() > 0)
1721 return {this, 0, ranges[0].begin};
1722 else
1723 return end();
1724}
1725
1726
1727
1730{
1731 compress();
1732 return IndexSet::ElementIterator(this);
1733}
1734
1735
1736
1739{
1740 compress();
1741 if (ranges.size() > 0)
1742 return IndexSet::IntervalIterator(this, 0);
1743 else
1744 return end_intervals();
1745}
1746
1747
1748
1751{
1752 compress();
1753 return IndexSet::IntervalIterator(this);
1754}
1755
1756
1757
1758inline void
1760{
1761 // reset so that there are no indices in the set any more; however,
1762 // as documented, the index set retains its size
1763 ranges.clear();
1764 is_compressed = true;
1766}
1767
1768
1769
1770inline void
1772{
1773 Assert(ranges.empty(),
1774 ExcMessage("This function can only be called if the current "
1775 "object does not yet contain any elements."));
1776 index_space_size = sz;
1777 is_compressed = true;
1778}
1779
1780
1781
1784{
1785 return index_space_size;
1786}
1787
1788
1789
1790inline void
1792{
1793 if (is_compressed == true)
1794 return;
1795
1796 do_compress();
1797}
1798
1799
1800
1801inline void
1803{
1804 add_range(index, index + 1);
1805}
1806
1807
1808
1809inline void
1811{
1818
1819 if (begin != end)
1820 {
1821 // the new index might be larger than the last index present in the
1822 // ranges. Then we can skip the binary search
1823 if (ranges.empty() || begin > ranges.back().end)
1824 ranges.emplace_back(begin, end);
1825 else if (begin == ranges.back().end)
1826 ranges.back().end = end;
1827 else
1829
1830 is_compressed = false;
1831 }
1832}
1833
1834
1835
1836template <typename ForwardIterator>
1837inline void
1838IndexSet::add_indices(const ForwardIterator &begin, const ForwardIterator &end)
1839{
1840 if (begin == end)
1841 return;
1842
1843 // identify ranges in the given iterator range by checking whether some
1844 // indices happen to be consecutive. to avoid quadratic complexity when
1845 // calling add_range many times (as add_range() going into the middle of an
1846 // already existing range must shift entries around), we first collect a
1847 // vector of ranges.
1848 boost::container::small_vector<std::pair<size_type, size_type>, 200>
1849 tmp_ranges;
1850 bool ranges_are_sorted = true;
1851 for (ForwardIterator p = begin; p != end;)
1852 {
1853 // Starting with the current iterator 'p', find an iterator
1854 // 'q' so that the indices pointed to by the iterators in
1855 // the range [p,q) are consecutive. These indices then form
1856 // a range that is contiguous, and that can be added all
1857 // at once.
1858 const size_type begin_index = *p;
1859 size_type end_index = begin_index + 1;
1860
1861 // Start looking at the position after 'p', and keep iterating while
1862 // 'q' points to a duplicate of 'p':
1863 ForwardIterator q = p;
1864 ++q;
1865 while ((q != end) && (*q == *p))
1866 ++q;
1867
1868 // Now we know that 'q' is either past the end, or points to a value
1869 // other than 'p'. If it points to 'end_index', we are still good with
1870 // a contiguous range; then increment the end index of that range, and
1871 // move to the next iterator that is not a duplicate of what
1872 // we were just looking at:
1873 while ((q != end) && (static_cast<size_type>(*q) == end_index))
1874 {
1875 ++q;
1876 while ((q != end) && (static_cast<size_type>(*q) == end_index))
1877 ++q;
1878
1879 ++end_index;
1880 }
1881
1882 // Add this range:
1883 tmp_ranges.emplace_back(begin_index, end_index);
1884
1885 // Then move on to the next element in the input range.
1886 // If the starting index of the next go-around of the for loop is less
1887 // than the end index of the one just identified, then we will have at
1888 // least one pair of ranges that are not sorted, and consequently the
1889 // whole collection of ranges is not sorted.
1890 p = q;
1891 if ((p != end) && (static_cast<size_type>(*p) < end_index))
1892 ranges_are_sorted = false;
1893 }
1894
1895 add_ranges_internal(tmp_ranges, ranges_are_sorted);
1896}
1897
1898
1899
1900inline bool
1902{
1903 if (ranges.empty() == false)
1904 {
1905 compress();
1906
1907 // fast check whether the index is in the largest range
1909 if (index >= ranges[largest_range].begin &&
1910 index < ranges[largest_range].end)
1911 return true;
1912 else if (ranges.size() > 1)
1913 return is_element_binary_search(index);
1914 else
1915 return false;
1916 }
1917 else
1918 return false;
1919}
1920
1921
1922
1923inline bool
1925{
1926 compress();
1927 return (ranges.size() <= 1);
1928}
1929
1930
1931
1932inline bool
1934{
1935 return ranges.empty();
1936}
1937
1938
1939
1942{
1943 // make sure we have non-overlapping ranges
1944 compress();
1945
1946 size_type v = 0;
1947 if (!ranges.empty())
1948 {
1949 const Range &r = ranges.back();
1950 v = r.nth_index_in_set + r.end - r.begin;
1951 }
1952
1953 return v;
1954}
1955
1956
1957
1958inline unsigned int
1960{
1961 compress();
1962 return ranges.size();
1963}
1964
1965
1966
1969{
1970 Assert(ranges.empty() == false, ExcMessage("IndexSet cannot be empty."));
1971
1972 compress();
1973 const std::vector<Range>::const_iterator main_range =
1974 ranges.begin() + largest_range;
1975
1976 return main_range->nth_index_in_set;
1977}
1978
1979
1980
1983{
1985
1986 compress();
1987
1988 // first check whether the index is in the largest range
1990 const auto main_range = ranges.begin() + largest_range;
1991 if (n >= main_range->nth_index_in_set &&
1992 n < main_range->nth_index_in_set + (main_range->end - main_range->begin))
1993 return main_range->begin + (n - main_range->nth_index_in_set);
1994 else
1996}
1997
1998
1999
2002{
2003 // to make this call thread-safe, compress() must not be called through this
2004 // function
2005 Assert(is_compressed == true, ExcMessage("IndexSet must be compressed."));
2006 AssertIndexRange(n, size());
2007
2008 // return immediately if the index set is empty
2009 if (is_empty())
2011
2012 // check whether the index is in the largest range. use the result to
2013 // perform a one-sided binary search afterward
2016 return (n - ranges[largest_range].begin) +
2017 ranges[largest_range].nth_index_in_set;
2018 else if (ranges.size() > 1)
2020 else
2022}
2023
2024
2025
2026inline bool
2028{
2029 // If one of the two index sets has size zero, the other one has to
2030 // have size zero as well:
2031 if (size() == 0)
2032 return (is.size() == 0);
2033 if (is.size() == 0)
2034 return (size() == 0);
2035
2036 // Otherwise, they must have the same size (see the documentation):
2037 Assert(size() == is.size(), ExcDimensionMismatch(size(), is.size()));
2038
2039 compress();
2040 is.compress();
2041
2042 return (ranges == is.ranges);
2043}
2044
2045
2046
2047inline bool
2049{
2050 // If one of the two index sets has size zero, the other one has to
2051 // have a non-zero size for inequality:
2052 if (size() == 0)
2053 return (is.size() != 0);
2054 if (is.size() == 0)
2055 return (size() != 0);
2056
2057 // Otherwise, they must have the same size (see the documentation):
2058 Assert(size() == is.size(), ExcDimensionMismatch(size(), is.size()));
2059
2060 compress();
2061 is.compress();
2062
2063 return (ranges != is.ranges);
2064}
2065
2066
2067
2068template <typename Vector>
2069void
2071{
2072 Assert(vector.size() == size(), ExcDimensionMismatch(vector.size(), size()));
2073
2074 compress();
2075 // first fill all elements of the vector with zeroes.
2076 std::fill(vector.begin(), vector.end(), 0);
2077
2078 // then write ones into the elements whose indices are contained in the
2079 // index set
2080 for (const auto &range : ranges)
2081 for (size_type i = range.begin; i < range.end; ++i)
2082 vector[i] = 1;
2083}
2084
2085
2086
2087template <typename StreamType>
2088inline void
2089IndexSet::print(StreamType &out) const
2090{
2091 compress();
2092 out << '{';
2093 std::vector<Range>::const_iterator p;
2094 for (p = ranges.begin(); p != ranges.end(); ++p)
2095 {
2096 if (p->end - p->begin == 1)
2097 out << p->begin;
2098 else
2099 out << '[' << p->begin << ',' << p->end - 1 << ']';
2100
2101 if (p != --ranges.end())
2102 out << ", ";
2103 }
2104 out << '}' << std::endl;
2105}
2106
2107
2108
2109template <class Archive>
2110inline void
2111IndexSet::Range::serialize(Archive &ar, const unsigned int)
2112{
2114}
2115
2116
2117
2118template <class Archive>
2119inline void
2120IndexSet::serialize(Archive &ar, const unsigned int)
2121{
2123}
2124
2126
2127#endif
size_type operator*() const
Definition index_set.h:1509
bool operator==(const ElementIterator &) const
Definition index_set.h:1521
ElementIterator(const IndexSet *idxset, const size_type range_idx, const size_type index)
Definition index_set.h:1465
std::ptrdiff_t difference_type
Definition index_set.h:946
ElementIterator & operator++()
Definition index_set.h:1562
bool operator<(const ElementIterator &) const
Definition index_set.h:1590
bool operator!=(const ElementIterator &) const
Definition index_set.h:1581
std::ptrdiff_t operator-(const ElementIterator &p) const
Definition index_set.h:1603
std::forward_iterator_tag iterator_category
Definition index_set.h:944
const IndexSet * index_set
Definition index_set.h:960
size_type last() const
Definition index_set.h:1295
ElementIterator end() const
Definition index_set.h:1281
friend class IntervalIterator
Definition index_set.h:759
size_type n_elements() const
Definition index_set.h:1255
bool operator==(const IntervalAccessor &other) const
Definition index_set.h:1317
IntervalAccessor & operator=(const IntervalAccessor &other)
Definition index_set.h:1305
bool operator<(const IntervalAccessor &other) const
Definition index_set.h:1329
IntervalAccessor(const IndexSet *idxset, const size_type range_idx)
Definition index_set.h:1224
const IndexSet * index_set
Definition index_set.h:751
ElementIterator begin() const
Definition index_set.h:1272
IntervalAccessor & reference
Definition index_set.h:856
std::ptrdiff_t difference_type
Definition index_set.h:854
const IntervalAccessor & operator*() const
Definition index_set.h:1397
IntervalIterator(const IntervalIterator &other)=default
bool operator==(const IntervalIterator &) const
Definition index_set.h:1413
int operator-(const IntervalIterator &p) const
Definition index_set.h:1440
bool operator<(const IntervalIterator &) const
Definition index_set.h:1431
std::forward_iterator_tag iterator_category
Definition index_set.h:852
IntervalIterator & operator=(const IntervalIterator &other)=default
IntervalAccessor value_type
Definition index_set.h:853
IntervalIterator & operator++()
Definition index_set.h:1378
const IntervalAccessor * operator->() const
Definition index_set.h:1405
IntervalIterator(const IndexSet *idxset, const size_type range_idx)
Definition index_set.h:1357
IntervalAccessor * pointer
Definition index_set.h:855
IntervalAccessor accessor
Definition index_set.h:862
bool operator!=(const IntervalIterator &) const
Definition index_set.h:1422
bool is_subset_of(const IndexSet &other) const
Definition index_set.cc:731
bool is_element_binary_search(const size_type local_index) const
Definition index_set.cc:826
size_type index_within_set_binary_search(const size_type global_index) const
Definition index_set.cc:879
size_type largest_range
Definition index_set.h:1132
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:1924
unsigned int n_intervals() const
Definition index_set.h:1959
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:973
IndexSet(const IndexSet &)=default
IntervalIterator end_intervals() const
Definition index_set.h:1750
void do_compress() const
Definition index_set.cc:145
ElementIterator at(const size_type global_index) const
Definition index_set.cc:901
size_type size() const
Definition index_set.h:1783
bool is_empty() const
Definition index_set.h:1933
size_type index_within_set(const size_type global_index) const
Definition index_set.h:2001
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:1941
bool operator==(const IndexSet &is) const
Definition index_set.h:2027
void add_range_lower_bound(const Range &range)
Definition index_set.cc:619
bool is_element(const size_type index) const
Definition index_set.h:1901
void serialize(Archive &ar, const unsigned int version)
Definition index_set.h:2120
ElementIterator begin() const
Definition index_set.h:1717
size_type pop_front()
Definition index_set.cc:597
signed int value_type
Definition index_set.h:104
void set_size(const size_type size)
Definition index_set.h:1771
bool operator!=(const IndexSet &is) const
Definition index_set.h:2048
void read(std::istream &in)
Definition index_set.cc:770
Epetra_Map make_trilinos_map(const MPI_Comm communicator=MPI_COMM_WORLD, const bool overlapping=false) const
void clear()
Definition index_set.h:1759
size_type largest_range_starting_index() const
Definition index_set.h:1968
IndexSet tensor_product(const IndexSet &other) const
Definition index_set.cc:567
void add_index(const size_type index)
Definition index_set.h:1802
void write(std::ostream &out) const
Definition index_set.cc:755
void block_read(std::istream &in)
Definition index_set.cc:806
bool is_compressed
Definition index_set.h:1115
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:635
IntervalIterator begin_intervals() const
Definition index_set.h:1738
IndexSet & operator=(const IndexSet &)=default
void fill_binary_vector(VectorType &vector) const
std::vector< Range > ranges
Definition index_set.h:1105
void subtract_set(const IndexSet &other)
Definition index_set.cc:496
ElementIterator end() const
Definition index_set.h:1729
Threads::Mutex compress_mutex
Definition index_set.h:1138
IndexSet complete_index_set(const IndexSet::size_type N)
Definition index_set.h:1211
size_type index_space_size
Definition index_set.h:1121
void block_write(std::ostream &out) const
Definition index_set.cc:792
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:1810
size_type nth_index_in_set(const size_type local_index) const
Definition index_set.h:1982
std::size_t memory_consumption() const
void print(StreamType &out) const
Definition index_set.h:2089
size_type nth_index_in_set_binary_search(const size_type local_index) const
Definition index_set.cc:862
void compress() const
Definition index_set.h:1791
size_type pop_back()
Definition index_set.cc:579
std::vector< size_type > get_index_vector() const
Definition index_set.cc:951
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:983
types::global_dof_index size_type
Definition index_set.h:85
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1838
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:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:628
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:672
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:267
constexpr unsigned int invalid_unsigned_int
Definition types.h:236
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:1063
static bool nth_index_compare(const IndexSet::Range &x, const IndexSet::Range &y)
Definition index_set.h:1069
friend bool operator==(const Range &range_1, const Range &range_2)
Definition index_set.h:1076
size_type end
Definition index_set.h:1031
size_type nth_index_in_set
Definition index_set.h:1033
static std::size_t memory_consumption()
Definition index_set.h:1082
size_type begin
Definition index_set.h:1030
void serialize(Archive &ar, const unsigned int version)
Definition index_set.h:2111
friend bool operator<(const Range &range_1, const Range &range_2)
Definition index_set.h:1055
void advance(std::tuple< I1, I2 > &t, const unsigned int n)