Reference documentation for deal.II version 9.0.0
index_set.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2009 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_index_set_h
17 #define dealii_index_set_h
18 
19 #include <deal.II/base/config.h>
20 #include <deal.II/base/utilities.h>
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/thread_management.h>
23 #include <boost/serialization/vector.hpp>
24 #include <vector>
25 #include <algorithm>
26 #include <iterator>
27 
28 
29 #ifdef DEAL_II_WITH_TRILINOS
30 # include <Epetra_Map.h>
31 #endif
32 
33 #if defined(DEAL_II_WITH_MPI) || defined(DEAL_II_WITH_PETSC)
34 #include <mpi.h>
35 #else
36 typedef int MPI_Comm;
37 # ifndef MPI_COMM_WORLD
38 # define MPI_COMM_WORLD 0
39 # endif
40 #endif
41 
42 DEAL_II_NAMESPACE_OPEN
43 
68 class IndexSet
69 {
70 public:
71  // forward declarations:
72  class ElementIterator;
74 
80 
98  typedef signed int value_type;
99 
100 
104  IndexSet ();
105 
109  explicit IndexSet (const size_type size);
110 
114  IndexSet (const IndexSet &) = default;
115 
119  IndexSet &operator= (const IndexSet &) = default;
120 
125  IndexSet (IndexSet &&is) noexcept;
126 
131  IndexSet &operator= (IndexSet &&is) noexcept;
132 
133 #ifdef DEAL_II_WITH_TRILINOS
134 
137  explicit IndexSet(const Epetra_Map &map);
138 #endif
139 
144  void clear ();
145 
152  void set_size (const size_type size);
153 
161  size_type size () const;
162 
169  void add_range (const size_type begin,
170  const size_type end);
171 
175  void add_index (const size_type index);
176 
186  template <typename ForwardIterator>
187  void add_indices (const ForwardIterator &begin,
188  const ForwardIterator &end);
189 
205  void add_indices(const IndexSet &other,
206  const unsigned int offset = 0);
207 
211  bool is_element (const size_type index) const;
212 
217  bool is_contiguous () const;
218 
223  bool is_empty () const;
224 
234  bool is_ascending_and_one_to_one(const MPI_Comm &communicator) const;
235 
239  size_type n_elements () const;
240 
246  size_type nth_index_in_set (const unsigned int local_index) const;
247 
254  size_type index_within_set (const size_type global_index) const;
255 
264  unsigned int n_intervals () const;
265 
270  unsigned int largest_range_starting_index() const;
271 
276  void compress () const;
277 
283  bool operator == (const IndexSet &is) const;
284 
290  bool operator != (const IndexSet &is) const;
291 
298  IndexSet operator & (const IndexSet &is) const;
299 
314  const size_type end) const;
315 
321  void subtract_set (const IndexSet &other);
322 
327  size_type pop_back ();
328 
333  size_type pop_front ();
334 
338  void fill_index_vector(std::vector<size_type> &indices) const;
339 
352  template <typename VectorType>
353  void fill_binary_vector (VectorType &vector) const;
354 
359  template <class StreamType>
360  void print(StreamType &out) const;
361 
366  void write(std::ostream &out) const;
367 
372  void read(std::istream &in);
373 
378  void block_write(std::ostream &out) const;
379 
384  void block_read(std::istream &in);
385 
386 #ifdef DEAL_II_WITH_TRILINOS
387 
415  Epetra_Map make_trilinos_map (const MPI_Comm &communicator = MPI_COMM_WORLD,
416  const bool overlapping = false) const;
417 #endif
418 
419 
424  std::size_t memory_consumption () const;
425 
427  << "The global index " << arg1
428  << " is not an element of this set.");
429 
434  template <class Archive>
435  void serialize (Archive &ar, const unsigned int version);
436 
437 
449  {
450  public:
455  IntervalAccessor(const IndexSet *idxset, const size_type range_idx);
456 
460  explicit IntervalAccessor(const IndexSet *idxset);
461 
465  size_type n_elements() const;
466 
470  bool is_valid() const;
471 
475  ElementIterator begin() const;
476 
481  ElementIterator end() const;
482 
486  size_type last() const;
487 
488  private:
492  IntervalAccessor(const IntervalAccessor &other);
497 
501  bool operator == (const IntervalAccessor &other) const;
505  bool operator < (const IntervalAccessor &other) const;
510  void advance ();
515 
521 
522  friend class IntervalIterator;
523  };
524 
530  {
531  public:
536  IntervalIterator(const IndexSet *idxset, const size_type range_idx);
537 
541  explicit IntervalIterator(const IndexSet *idxset);
542 
547 
551  IntervalIterator(const IntervalIterator &other);
552 
557 
562 
567 
571  const IntervalAccessor &operator* () const;
572 
576  const IntervalAccessor *operator-> () const;
577 
581  bool operator == (const IntervalIterator &) const;
582 
586  bool operator != (const IntervalIterator &) const;
587 
591  bool operator < (const IntervalIterator &) const;
592 
599  int operator - (const IntervalIterator &p) const;
600 
606  typedef std::forward_iterator_tag iterator_category;
608  typedef std::ptrdiff_t difference_type;
609  typedef IntervalAccessor *pointer;
610  typedef IntervalAccessor &reference;
611 
612  private:
617  };
618 
624  {
625  public:
630  ElementIterator(const IndexSet *idxset,
631  const size_type range_idx,
632  const size_type index);
633 
637  explicit ElementIterator(const IndexSet *idxset);
638 
643  size_type operator* () const;
644 
648  bool is_valid () const;
649 
654 
659 
663  bool operator == (const ElementIterator &) const;
664 
668  bool operator != (const ElementIterator &) const;
669 
673  bool operator < (const ElementIterator &) const;
674 
683  std::ptrdiff_t operator - (const ElementIterator &p) const;
684 
690  typedef std::forward_iterator_tag iterator_category;
691  typedef size_type value_type;
692  typedef std::ptrdiff_t difference_type;
693  typedef size_type *pointer;
694  typedef size_type &reference;
695 
696  private:
700  void advance ();
701 
714  };
715 
720  ElementIterator begin() const;
721 
736  ElementIterator at(const size_type global_index) const;
737 
742  ElementIterator end() const;
743 
748 
754 
759 private:
768  struct Range
769  {
770  size_type begin;
771  size_type end;
772 
773  size_type nth_index_in_set;
774 
783  Range ();
784 
792  Range (const size_type i1,
793  const size_type i2);
794 
795  friend
796  inline bool operator< (const Range &range_1,
797  const Range &range_2)
798  {
799  return ((range_1.begin < range_2.begin)
800  ||
801  ((range_1.begin == range_2.begin)
802  &&
803  (range_1.end < range_2.end)));
804  }
805 
806  static bool end_compare(const IndexSet::Range &x, const IndexSet::Range &y)
807  {
808  return x.end < y.end;
809  }
810 
811  static bool nth_index_compare (const IndexSet::Range &x,
812  const IndexSet::Range &y)
813  {
814  return (x.nth_index_in_set+(x.end-x.begin) <
815  y.nth_index_in_set+(y.end-y.begin));
816  }
817 
818  friend
819  inline bool operator== (const Range &range_1,
820  const Range &range_2)
821  {
822  return ((range_1.begin == range_2.begin)
823  &&
824  (range_1.end == range_2.end));
825  }
826 
827  static std::size_t memory_consumption ()
828  {
829  return sizeof(Range);
830  }
831 
836  template <class Archive>
837  void serialize (Archive &ar, const unsigned int version);
838  };
839 
848  mutable std::vector<Range> ranges;
849 
858  mutable bool is_compressed;
859 
865 
876 
882 
886  void do_compress() const;
887 };
888 
889 
907 inline
908 IndexSet complete_index_set (const unsigned int N)
909 {
910  IndexSet is (N);
911  is.add_range(0, N);
912  is.compress();
913  return is;
914 }
915 
916 /* ------------------ inline functions ------------------ */
917 
918 
919 /* IntervalAccessor */
920 
921 inline
924  const IndexSet::size_type range_idx)
925  :
926  index_set(idxset),
927  range_idx(range_idx)
928 {
929  Assert(range_idx < idxset->n_intervals(), ExcInternalError("Invalid range index"));
930 }
931 
932 
933 
934 inline
937  :
938  index_set(idxset),
939  range_idx(numbers::invalid_dof_index)
940 {}
941 
942 
943 
944 inline
947  :
948  index_set (other.index_set),
949  range_idx(other.range_idx)
950 {
952  ExcMessage("invalid iterator"));
953 }
954 
955 
956 
957 inline
960 {
961  Assert(is_valid(), ExcMessage("invalid iterator"));
962  return index_set->ranges[range_idx].end - index_set->ranges[range_idx].begin;
963 }
964 
965 
966 
967 inline
968 bool
970 {
971  return index_set != nullptr && range_idx < index_set->n_intervals();
972 }
973 
974 
975 
976 inline
979 {
980  Assert(is_valid(), ExcMessage("invalid iterator"));
981  return IndexSet::ElementIterator(index_set, range_idx,
982  index_set->ranges[range_idx].begin);
983 }
984 
985 
986 
987 inline
990 {
991  Assert(is_valid(), ExcMessage("invalid iterator"));
992 
993  // point to first index in next interval unless we are the last interval.
994  if (range_idx < index_set->ranges.size()-1)
995  return IndexSet::ElementIterator(index_set, range_idx+1, index_set->ranges[range_idx+1].begin);
996  else
997  return index_set->end();
998 }
999 
1000 
1001 
1002 inline
1005 {
1006  Assert(is_valid(), ExcMessage("invalid iterator"));
1007 
1008  return index_set->ranges[range_idx].end-1;
1009 }
1010 
1011 
1012 
1013 inline
1016 {
1017  index_set = other.index_set;
1018  range_idx = other.range_idx;
1019  Assert( range_idx == numbers::invalid_dof_index || is_valid(),
1020  ExcMessage("invalid iterator"));
1021  return *this;
1022 }
1023 
1024 
1025 
1026 inline
1027 bool
1029 {
1030  Assert (index_set == other.index_set,
1031  ExcMessage("Can not compare accessors pointing to different IndexSets"));
1032  return range_idx == other.range_idx;
1033 }
1034 
1035 
1036 
1037 inline
1038 bool
1040 {
1041  Assert (index_set == other.index_set,
1042  ExcMessage("Can not compare accessors pointing to different IndexSets"));
1043  return range_idx < other.range_idx;
1044 }
1045 
1046 
1047 
1048 inline
1050 {
1051  Assert (is_valid(),
1052  ExcMessage("Impossible to advance an IndexSet::IntervalIterator that is invalid"));
1053  ++range_idx;
1054 
1055  // set ourselves to invalid if we walk off the end
1056  if (range_idx>=index_set->ranges.size())
1057  range_idx = numbers::invalid_dof_index;
1058 }
1059 
1060 
1061 /* IntervalIterator */
1062 
1063 inline
1065  const IndexSet::size_type range_idx)
1066  :
1067  accessor(idxset, range_idx)
1068 {}
1069 
1070 
1071 
1072 inline
1074  :
1075  accessor(nullptr)
1076 {}
1077 
1078 
1079 
1080 inline
1082  :
1083  accessor(idxset)
1084 {}
1085 
1086 
1087 
1088 inline
1090  :
1091  accessor(other.accessor)
1092 {}
1093 
1094 
1095 
1096 inline
1099 {
1100  accessor = other.accessor;
1101  return *this;
1102 }
1103 
1104 
1105 
1106 inline
1109 {
1110  accessor.advance();
1111  return *this;
1112 }
1113 
1114 
1115 
1116 inline
1119 {
1120  const IndexSet::IntervalIterator iter = *this;
1121  accessor.advance ();
1122  return iter;
1123 }
1124 
1125 
1126 
1127 inline
1130 {
1131  return accessor;
1132 }
1133 
1134 
1135 
1136 inline
1139 {
1140  return &accessor;
1141 }
1142 
1143 
1144 
1145 inline
1146 bool
1148 {
1149  return accessor == other.accessor;
1150 }
1151 
1152 
1153 
1154 inline
1155 bool
1157 {
1158  return !(*this == other);
1159 }
1160 
1161 
1162 
1163 inline
1164 bool
1166 {
1167  return accessor < other.accessor;
1168 }
1169 
1170 
1171 
1172 inline
1173 int
1175 {
1176  Assert (accessor.index_set == other.accessor.index_set,
1177  ExcMessage("Can not compare iterators belonging to different IndexSets"));
1178 
1179  const size_type lhs = (accessor.range_idx == numbers::invalid_dof_index)
1180  ?
1181  accessor.index_set->ranges.size()
1182  :
1183  accessor.range_idx;
1185  ?
1186  accessor.index_set->ranges.size()
1187  :
1188  other.accessor.range_idx;
1189 
1190  if (lhs > rhs)
1191  return static_cast<int>(lhs - rhs);
1192  else
1193  return -static_cast<int>(rhs - lhs);
1194 }
1195 
1196 
1197 
1198 /* ElementIterator */
1199 
1200 inline
1203  const IndexSet::size_type range_idx,
1204  const IndexSet::size_type index)
1205  :
1206  index_set(idxset),
1207  range_idx(range_idx),
1208  idx(index)
1209 {
1210  Assert(range_idx < index_set->ranges.size(),
1211  ExcMessage("Invalid range index for IndexSet::ElementIterator constructor."));
1212  Assert(idx >= index_set->ranges[range_idx].begin
1213  &&
1214  idx < index_set->ranges[range_idx].end,
1215  ExcInternalError("Invalid index argument for IndexSet::ElementIterator constructor."));
1216 }
1217 
1218 
1219 
1220 inline
1222  :
1223  index_set(idxset),
1224  range_idx(numbers::invalid_dof_index),
1225  idx(numbers::invalid_dof_index)
1226 {}
1227 
1228 
1229 
1230 inline
1231 bool
1233 {
1235  ||
1236  (range_idx < index_set->ranges.size() && idx<index_set->ranges[range_idx].end),
1237  ExcInternalError("Invalid ElementIterator state."));
1238 
1239  return (range_idx < index_set->ranges.size() &&
1240  idx<index_set->ranges[range_idx].end);
1241 }
1242 
1243 
1244 
1245 
1246 inline
1249 {
1250  Assert (is_valid(),
1251  ExcMessage("Impossible to dereference an IndexSet::ElementIterator that is invalid"));
1252  return idx;
1253 }
1254 
1255 
1256 
1257 inline
1258 bool
1260 {
1261  Assert (index_set == other.index_set,
1262  ExcMessage("Can not compare iterators belonging to different IndexSets"));
1263  return range_idx == other.range_idx && idx==other.idx;
1264 }
1265 
1266 
1267 
1268 inline
1269 void
1271 {
1272  Assert (is_valid(),
1273  ExcMessage("Impossible to advance an IndexSet::ElementIterator that is invalid"));
1274  if (idx < index_set->ranges[range_idx].end)
1275  ++idx;
1276  // end of this range?
1277  if (idx == index_set->ranges[range_idx].end)
1278  {
1279  // point to first element in next interval if possible
1280  if (range_idx < index_set->ranges.size()-1)
1281  {
1282  ++range_idx;
1283  idx = index_set->ranges[range_idx].begin;
1284  }
1285  else
1286  {
1287  // we just fell off the end, set to invalid:
1288  range_idx = numbers::invalid_dof_index;
1290  }
1291  }
1292 }
1293 
1294 
1295 
1296 inline
1299 {
1300  advance();
1301  return *this;
1302 }
1303 
1304 
1305 
1306 inline
1309 {
1310  const IndexSet::ElementIterator it = *this;
1311  advance();
1312  return it;
1313 }
1314 
1315 
1316 
1317 inline
1319 {
1320  return !(*this == other);
1321 }
1322 
1323 
1324 
1325 inline
1327 {
1328  Assert (index_set == other.index_set,
1329  ExcMessage("Can not compare iterators belonging to different IndexSets"));
1330  return range_idx < other.range_idx || (range_idx == other.range_idx && idx<other.idx);
1331 }
1332 
1333 
1334 
1335 inline
1336 std::ptrdiff_t
1338 {
1339  Assert (index_set == other.index_set,
1340  ExcMessage("Can not compare iterators belonging to different IndexSets"));
1341  if (*this == other)
1342  return 0;
1343  if (!(*this < other))
1344  return -(other-*this);
1345 
1346  // only other can be equal to end() because of the checks above.
1347  Assert (is_valid(), ExcInternalError());
1348 
1349  // Note: we now compute how far advance *this in "*this < other" to get other, so we need to return -c at the end.
1350 
1351  // first finish the current range:
1352  std::ptrdiff_t c = index_set->ranges[range_idx].end-idx;
1353 
1354  // now walk in steps of ranges (need to start one behind our current one):
1355  for (size_type range=range_idx+1; range<index_set->ranges.size() && range<=other.range_idx; ++range)
1356  c += index_set->ranges[range].end-index_set->ranges[range].begin;
1357 
1358  Assert(other.range_idx < index_set->ranges.size() || other.range_idx == numbers::invalid_dof_index,
1359  ExcMessage("Inconsistent iterator state. Did you invalidate iterators by modifying the IndexSet?"));
1360 
1361  // We might have walked too far because we went until the end of other.range_idx, so walk backwards to other.idx:
1363  c -= index_set->ranges[other.range_idx].end - other.idx;
1364 
1365  return -c;
1366 }
1367 
1368 
1369 /* Range */
1370 
1371 inline
1373  :
1374  begin(numbers::invalid_dof_index),
1375  end(numbers::invalid_dof_index),
1376  nth_index_in_set(numbers::invalid_dof_index)
1377 {}
1378 
1379 
1380 
1381 inline
1383  const size_type i2)
1384  :
1385  begin(i1),
1386  end(i2),
1387  nth_index_in_set(numbers::invalid_dof_index)
1388 {}
1389 
1390 
1391 
1392 /* IndexSet itself */
1393 
1394 inline
1396  :
1397  is_compressed (true),
1398  index_space_size (0),
1399  largest_range (numbers::invalid_unsigned_int)
1400 {}
1401 
1402 
1403 
1404 inline
1406  :
1407  is_compressed (true),
1408  index_space_size (size),
1409  largest_range (numbers::invalid_unsigned_int)
1410 {}
1411 
1412 
1413 
1414 inline
1416 :
1417 ranges (std::move(is.ranges)),
1418  is_compressed (is.is_compressed),
1419  index_space_size (is.index_space_size),
1420  largest_range (is.largest_range)
1421 {
1422  is.ranges.clear ();
1423  is.is_compressed = true;
1424  is.index_space_size = 0;
1425  is.largest_range = numbers::invalid_unsigned_int;
1426 
1427  compress ();
1428 }
1429 
1430 
1431 
1432 inline
1434 {
1435  ranges = std::move (is.ranges);
1436  is_compressed = is.is_compressed;
1437  index_space_size = is.index_space_size;
1438  largest_range = is.largest_range;
1439 
1440  is.ranges.clear ();
1441  is.is_compressed = true;
1442  is.index_space_size = 0;
1443  is.largest_range = numbers::invalid_unsigned_int;
1444 
1445  compress ();
1446 
1447  return *this;
1448 }
1449 
1450 
1451 
1452 inline
1454 {
1455  compress();
1456  if (ranges.size()>0)
1457  return IndexSet::ElementIterator(this, 0, ranges[0].begin);
1458  else
1459  return end();
1460 }
1461 
1462 
1463 
1464 inline
1466 {
1467  compress();
1468  Assert (global_index < size(),
1469  ExcIndexRangeType<size_type> (global_index, 0, size()));
1470 
1471  if (ranges.empty())
1472  return end();
1473 
1474  std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1475 
1476  Range r (global_index, global_index+1);
1477  // This optimization makes the bounds for lower_bound smaller by checking
1478  // the largest range first.
1479  std::vector<Range>::const_iterator range_begin, range_end;
1480  if (global_index<main_range->begin)
1481  {
1482  range_begin = ranges.begin();
1483  range_end = main_range;
1484  }
1485  else
1486  {
1487  range_begin = main_range;
1488  range_end = ranges.end();
1489  }
1490 
1491  // This will give us the first range p=[a,b[ with b>=global_index using
1492  // a binary search
1493  const std::vector<Range>::const_iterator
1494  p = Utilities::lower_bound(range_begin, range_end, r, Range::end_compare);
1495 
1496  // We couldn't find a range, which means we have no range that contains
1497  // global_index and also no range behind it, meaning we need to return end().
1498  if (p == ranges.end())
1499  return end();
1500 
1501  // Finally, we can have two cases: Either global_index is not in [a,b[,
1502  // which means we need to return an iterator to a because global_index, ...,
1503  // a-1 is not in the IndexSet (if branch). Alternatively, global_index is in
1504  // [a,b[ and we will return an iterator pointing directly at global_index
1505  // (else branch).
1506  if (global_index < p->begin)
1507  return IndexSet::ElementIterator(this, p-ranges.begin(), p->begin);
1508  else
1509  return IndexSet::ElementIterator(this, p-ranges.begin(), global_index);
1510 }
1511 
1512 
1513 
1514 inline
1517 {
1518  compress();
1519  return IndexSet::ElementIterator(this);
1520 }
1521 
1522 
1523 
1524 inline
1527 {
1528  compress();
1529  if (ranges.size()>0)
1530  return IndexSet::IntervalIterator(this, 0);
1531  else
1532  return end_intervals();
1533 }
1534 
1535 
1536 
1537 inline
1540 {
1541  compress();
1542  return IndexSet::IntervalIterator(this);
1543 }
1544 
1545 
1546 
1547 inline
1548 void
1550 {
1551  // reset so that there are no indices in the set any more; however,
1552  // as documented, the index set retains its size
1553  ranges.clear ();
1554  is_compressed = true;
1556 }
1557 
1558 
1559 
1560 inline
1561 void
1563 {
1564  Assert (ranges.empty(),
1565  ExcMessage ("This function can only be called if the current "
1566  "object does not yet contain any elements."));
1567  index_space_size = sz;
1568  is_compressed = true;
1569 }
1570 
1571 
1572 
1573 inline
1576 {
1577  return index_space_size;
1578 }
1579 
1580 
1581 
1582 inline
1583 void
1585 {
1586  if (is_compressed == true)
1587  return;
1588 
1589  do_compress();
1590 }
1591 
1592 
1593 
1594 inline
1595 void
1597 {
1598  Assert (index < index_space_size,
1599  ExcIndexRangeType<size_type> (index, 0, index_space_size));
1600 
1601  const Range new_range(index, index+1);
1602  if (ranges.size() == 0 || index > ranges.back().end)
1603  ranges.push_back(new_range);
1604  else if (index == ranges.back().end)
1605  ranges.back().end++;
1606  else
1607  ranges.insert (Utilities::lower_bound (ranges.begin(),
1608  ranges.end(),
1609  new_range),
1610  new_range);
1611  is_compressed = false;
1612 }
1613 
1614 
1615 
1616 template <typename ForwardIterator>
1617 inline
1618 void
1619 IndexSet::add_indices (const ForwardIterator &begin,
1620  const ForwardIterator &end)
1621 {
1622  // insert each element of the range. if some of them happen to be
1623  // consecutive, merge them to a range
1624  for (ForwardIterator p=begin; p!=end;)
1625  {
1626  const size_type begin_index = *p;
1627  size_type end_index = begin_index + 1;
1628  ForwardIterator q = p;
1629  ++q;
1630  while ((q != end) && (*q == end_index))
1631  {
1632  ++end_index;
1633  ++q;
1634  }
1635 
1636  add_range (begin_index, end_index);
1637  p = q;
1638  }
1639 }
1640 
1641 
1642 
1643 inline
1644 bool
1645 IndexSet::is_element (const size_type index) const
1646 {
1647  if (ranges.empty() == false)
1648  {
1649  compress ();
1650 
1651  // fast check whether the index is in the largest range
1653  if (index >= ranges[largest_range].begin &&
1654  index < ranges[largest_range].end)
1655  return true;
1656 
1657  // get the element after which we would have to insert a range that
1658  // consists of all elements from this element to the end of the index
1659  // range plus one. after this call we know that if p!=end() then
1660  // p->begin<=index unless there is no such range at all
1661  //
1662  // if the searched for element is an element of this range, then we're
1663  // done. otherwise, the element can't be in one of the following ranges
1664  // because otherwise p would be a different iterator
1665  //
1666  // since we already know the position relative to the largest range (we
1667  // called compress!), we can perform the binary search on ranges with
1668  // lower/higher number compared to the largest range
1669  std::vector<Range>::const_iterator
1670  p = std::upper_bound (ranges.begin() + (index<ranges[largest_range].begin?
1671  0 : largest_range+1),
1672  index<ranges[largest_range].begin ?
1673  ranges.begin() + largest_range:
1674  ranges.end(),
1675  Range (index, size()+1));
1676 
1677  if (p == ranges.begin())
1678  return ((index >= p->begin) && (index < p->end));
1679 
1680  Assert ((p == ranges.end()) || (p->begin > index),
1681  ExcInternalError());
1682 
1683  // now move to that previous range
1684  --p;
1685  Assert (p->begin <= index, ExcInternalError());
1686 
1687  return (p->end > index);
1688  }
1689 
1690  // didn't find this index, so it's not in the set
1691  return false;
1692 }
1693 
1694 
1695 
1696 inline
1697 bool
1699 {
1700  compress ();
1701  return (ranges.size() <= 1);
1702 }
1703 
1704 
1705 
1706 inline
1707 bool
1709 {
1710  return ranges.empty();
1711 }
1712 
1713 
1714 
1715 inline
1718 {
1719  // make sure we have non-overlapping ranges
1720  compress ();
1721 
1722  size_type v = 0;
1723  if (!ranges.empty())
1724  {
1725  Range &r = ranges.back();
1726  v = r.nth_index_in_set + r.end - r.begin;
1727  }
1728 
1729 #ifdef DEBUG
1730  size_type s = 0;
1731  for (std::vector<Range>::iterator range = ranges.begin();
1732  range != ranges.end();
1733  ++range)
1734  s += (range->end - range->begin);
1735  Assert(s==v, ExcInternalError());
1736 #endif
1737 
1738  return v;
1739 }
1740 
1741 
1742 
1743 inline
1744 unsigned int
1746 {
1747  compress ();
1748  return ranges.size();
1749 }
1750 
1751 
1752 
1753 inline
1754 unsigned int
1756 {
1757  Assert(ranges.empty()==false, ExcMessage("IndexSet cannot be empty."));
1758 
1759  compress();
1760  const std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1761 
1762  return main_range->nth_index_in_set;
1763 }
1764 
1765 
1766 
1767 inline
1769 IndexSet::nth_index_in_set (const unsigned int n) const
1770 {
1771  Assert (n < n_elements(), ExcIndexRangeType<size_type> (n, 0, n_elements()));
1772 
1773  compress ();
1774 
1775  // first check whether the index is in the largest range
1777  std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1778  if (n>=main_range->nth_index_in_set &&
1779  n<main_range->nth_index_in_set+(main_range->end-main_range->begin))
1780  return main_range->begin + (n-main_range->nth_index_in_set);
1781 
1782  // find out which chunk the local index n belongs to by using a binary
1783  // search. the comparator is based on the end of the ranges. Use the
1784  // position relative to main_range to subdivide the ranges
1785  Range r (n,n+1);
1786  r.nth_index_in_set = n;
1787  std::vector<Range>::const_iterator range_begin, range_end;
1788  if (n<main_range->nth_index_in_set)
1789  {
1790  range_begin = ranges.begin();
1791  range_end = main_range;
1792  }
1793  else
1794  {
1795  range_begin = main_range + 1;
1796  range_end = ranges.end();
1797  }
1798 
1799  const std::vector<Range>::const_iterator
1800  p = Utilities::lower_bound(range_begin, range_end, r,
1801  Range::nth_index_compare);
1802 
1803  Assert (p != ranges.end(), ExcInternalError());
1804  return p->begin + (n-p->nth_index_in_set);
1805 }
1806 
1807 
1808 
1809 inline
1812 {
1813  // to make this call thread-safe, compress() must not be called through this
1814  // function
1815  Assert (is_compressed == true, ExcMessage ("IndexSet must be compressed."));
1816  Assert (n < size(), ExcIndexRangeType<size_type> (n, 0, size()));
1817 
1818  // return immediately if the index set is empty
1819  if (is_empty())
1821 
1822  // check whether the index is in the largest range. use the result to
1823  // perform a one-sided binary search afterward
1825  std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1826  if (n >= main_range->begin && n < main_range->end)
1827  return (n-main_range->begin) + main_range->nth_index_in_set;
1828 
1829  Range r(n, n);
1830  std::vector<Range>::const_iterator range_begin, range_end;
1831  if (n<main_range->begin)
1832  {
1833  range_begin = ranges.begin();
1834  range_end = main_range;
1835  }
1836  else
1837  {
1838  range_begin = main_range + 1;
1839  range_end = ranges.end();
1840  }
1841 
1842  std::vector<Range>::const_iterator
1843  p = Utilities::lower_bound(range_begin, range_end, r,
1844  Range::end_compare);
1845 
1846  // if n is not in this set
1847  if (p==range_end || p->end == n || p->begin > n)
1849 
1850  Assert(p!=ranges.end(), ExcInternalError());
1851  Assert(p->begin<=n, ExcInternalError());
1852  Assert(n<p->end, ExcInternalError());
1853  return (n-p->begin) + p->nth_index_in_set;
1854 }
1855 
1856 
1857 
1858 inline
1859 bool
1861 {
1862  Assert (size() == is.size(),
1863  ExcDimensionMismatch (size(), is.size()));
1864 
1865  compress ();
1866  is.compress ();
1867 
1868  return ranges == is.ranges;
1869 }
1870 
1871 
1872 
1873 inline
1874 bool
1876 {
1877  Assert (size() == is.size(),
1878  ExcDimensionMismatch (size(), is.size()));
1879 
1880  compress ();
1881  is.compress ();
1882 
1883  return ranges != is.ranges;
1884 }
1885 
1886 
1887 
1888 template <typename Vector>
1889 void
1890 IndexSet::fill_binary_vector (Vector &vector) const
1891 {
1892  Assert (vector.size() == size(),
1893  ExcDimensionMismatch (vector.size(), size()));
1894 
1895  compress();
1896  // first fill all elements of the vector with zeroes.
1897  std::fill (vector.begin(), vector.end(), 0);
1898 
1899  // then write ones into the elements whose indices are contained in the
1900  // index set
1901  for (std::vector<Range>::iterator it = ranges.begin();
1902  it != ranges.end();
1903  ++it)
1904  for (size_type i=it->begin; i<it->end; ++i)
1905  vector[i] = 1;
1906 }
1907 
1908 
1909 
1910 template <class StreamType>
1911 inline
1912 void
1913 IndexSet::print (StreamType &out) const
1914 {
1915  compress();
1916  out << "{";
1917  std::vector<Range>::const_iterator p;
1918  for (p = ranges.begin(); p != ranges.end(); ++p)
1919  {
1920  if (p->end-p->begin==1)
1921  out << p->begin;
1922  else
1923  out << "[" << p->begin << "," << p->end-1 << "]";
1924 
1925  if (p != --ranges.end())
1926  out << ", ";
1927  }
1928  out << "}" << std::endl;
1929 }
1930 
1931 
1932 
1933 template <class Archive>
1934 inline
1935 void
1936 IndexSet::Range::serialize (Archive &ar, const unsigned int)
1937 {
1938  ar &begin &end &nth_index_in_set;
1939 }
1940 
1941 
1942 
1943 template <class Archive>
1944 inline
1945 void
1946 IndexSet::serialize (Archive &ar, const unsigned int)
1947 {
1949 }
1950 
1951 DEAL_II_NAMESPACE_CLOSE
1952 
1953 #endif
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:891
void fill_binary_vector(VectorType &vector) const
static const unsigned int invalid_unsigned_int
Definition: types.h:173
ElementIterator end() const
Definition: index_set.h:1516
void add_index(const size_type index)
Definition: index_set.h:1596
IndexSet operator&(const IndexSet &is) const
const IntervalAccessor * operator->() const
Definition: index_set.h:1138
const IntervalAccessor & operator*() const
Definition: index_set.h:1129
size_type nth_index_in_set(const unsigned int local_index) const
Definition: index_set.h:1769
const IndexSet * index_set
Definition: index_set.h:705
IndexSet & operator=(const IndexSet &)=default
void block_read(std::istream &in)
Definition: index_set.cc:507
signed int value_type
Definition: index_set.h:98
std::ptrdiff_t operator-(const ElementIterator &p) const
Definition: index_set.h:1337
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1619
unsigned int largest_range_starting_index() const
Definition: index_set.h:1755
ElementIterator(const IndexSet *idxset, const size_type range_idx, const size_type index)
Definition: index_set.h:1202
bool operator<(const IntervalIterator &) const
Definition: index_set.h:1165
std::size_t memory_consumption() const
Definition: index_set.cc:679
size_type n_elements() const
Definition: index_set.h:959
size_type index_space_size
Definition: index_set.h:864
bool is_ascending_and_one_to_one(const MPI_Comm &communicator) const
Definition: index_set.cc:618
Epetra_Map make_trilinos_map(const MPI_Comm &communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition: index_set.cc:549
size_type size() const
Definition: index_set.h:1575
void print(StreamType &out) const
Definition: index_set.h:1913
void serialize(Archive &ar, const unsigned int version)
Definition: index_set.h:1936
IndexSet complete_index_set(const unsigned int N)
Definition: index_set.h:908
void clear()
Definition: index_set.h:1549
void serialize(Archive &ar, const unsigned int version)
Definition: index_set.h:1946
static ::ExceptionBase & ExcMessage(std::string arg1)
void block_write(std::ostream &out) const
Definition: index_set.cc:492
IntervalIterator & operator=(const IntervalIterator &other)
Definition: index_set.h:1098
std::vector< Range > ranges
Definition: index_set.h:848
static ::ExceptionBase & ExcIndexNotPresent(size_type arg1)
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:346
unsigned int global_dof_index
Definition: types.h:88
void subtract_set(const IndexSet &other)
Definition: index_set.cc:288
#define Assert(cond, exc)
Definition: exceptions.h:1142
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
bool operator<(const ElementIterator &) const
Definition: index_set.h:1326
size_type index_within_set(const size_type global_index) const
Definition: index_set.h:1811
bool operator==(const IndexSet &is) const
Definition: index_set.h:1860
IntervalAccessor accessor
Definition: index_set.h:616
void do_compress() const
Definition: index_set.cc:130
IntervalAccessor & operator=(const IntervalAccessor &other)
Definition: index_set.h:1015
bool operator==(const IntervalIterator &) const
Definition: index_set.h:1147
size_type last() const
Definition: index_set.h:1004
const IndexSet * index_set
Definition: index_set.h:514
bool operator==(const IntervalAccessor &other) const
Definition: index_set.h:1028
unsigned int n_intervals() const
Definition: index_set.h:1745
int operator-(const IntervalIterator &p) const
Definition: index_set.h:1174
bool operator!=(const IndexSet &is) const
Definition: index_set.h:1875
size_type pop_back()
Definition: index_set.cc:362
void fill_index_vector(std::vector< size_type > &indices) const
Definition: index_set.cc:526
void add_range(const size_type begin, const size_type end)
Definition: index_set.cc:98
void set_size(const size_type size)
Definition: index_set.h:1562
std::forward_iterator_tag iterator_category
Definition: index_set.h:690
ElementIterator & operator++()
Definition: index_set.h:1298
IntervalAccessor(const IndexSet *idxset, const size_type range_idx)
Definition: index_set.h:923
IndexSet get_view(const size_type begin, const size_type end) const
Definition: index_set.cc:254
void compress() const
Definition: index_set.h:1584
ElementIterator end() const
Definition: index_set.h:989
IntervalIterator begin_intervals() const
Definition: index_set.h:1526
bool is_contiguous() const
Definition: index_set.h:1698
Threads::Mutex compress_mutex
Definition: index_set.h:881
size_type pop_front()
Definition: index_set.cc:379
IntervalIterator end_intervals() const
Definition: index_set.h:1539
bool is_compressed
Definition: index_set.h:858
bool operator<(const IntervalAccessor &other) const
Definition: index_set.h:1039
bool operator!=(const ElementIterator &) const
Definition: index_set.h:1318
ElementIterator begin() const
Definition: index_set.h:978
void write(std::ostream &out) const
Definition: index_set.cc:455
bool is_element(const size_type index) const
Definition: index_set.h:1645
bool operator==(const ElementIterator &) const
Definition: index_set.h:1259
ElementIterator at(const size_type global_index) const
Definition: index_set.h:1465
const types::global_dof_index invalid_dof_index
Definition: types.h:187
types::global_dof_index size_type
Definition: index_set.h:73
ElementIterator begin() const
Definition: index_set.h:1453
void read(std::istream &in)
Definition: index_set.cc:470
size_type n_elements() const
Definition: index_set.h:1717
bool is_empty() const
Definition: index_set.h:1708
size_type largest_range
Definition: index_set.h:875
IntervalIterator & operator++()
Definition: index_set.h:1108
std::forward_iterator_tag iterator_category
Definition: index_set.h:606
static ::ExceptionBase & ExcInternalError()
size_type operator*() const
Definition: index_set.h:1248
bool operator!=(const IntervalIterator &) const
Definition: index_set.h:1156