Reference documentation for deal.II version 8.5.1
index_set.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2009 - 2017 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 
111 #ifdef DEAL_II_WITH_CXX11
112 
115  IndexSet (const IndexSet &) = default;
116 
120  IndexSet &operator= (const IndexSet &) = default;
121 
126  IndexSet (IndexSet &&is);
127 
133 #endif
134 
135 #ifdef DEAL_II_WITH_TRILINOS
136 
139  explicit IndexSet(const Epetra_Map &map);
140 #endif
141 
146  void clear ();
147 
154  void set_size (const size_type size);
155 
163  size_type size () const;
164 
171  void add_range (const size_type begin,
172  const size_type end);
173 
177  void add_index (const size_type index);
178 
188  template <typename ForwardIterator>
189  void add_indices (const ForwardIterator &begin,
190  const ForwardIterator &end);
191 
207  void add_indices(const IndexSet &other,
208  const unsigned int offset = 0);
209 
213  bool is_element (const size_type index) const;
214 
219  bool is_contiguous () const;
220 
225  bool is_empty () const;
226 
236  bool is_ascending_and_one_to_one(const MPI_Comm &communicator) const;
237 
241  size_type n_elements () const;
242 
248  size_type nth_index_in_set (const unsigned int local_index) const;
249 
256  size_type index_within_set (const size_type global_index) const;
257 
266  unsigned int n_intervals () const;
267 
272  unsigned int largest_range_starting_index() const;
273 
278  void compress () const;
279 
285  bool operator == (const IndexSet &is) const;
286 
292  bool operator != (const IndexSet &is) const;
293 
300  IndexSet operator & (const IndexSet &is) const;
301 
316  const size_type end) const;
317 
323  void subtract_set (const IndexSet &other);
324 
329  size_type pop_back ();
330 
335  size_type pop_front ();
336 
340  void fill_index_vector(std::vector<size_type> &indices) const;
341 
354  template <typename VectorType>
355  void fill_binary_vector (VectorType &vector) const;
356 
361  template <class StreamType>
362  void print(StreamType &out) const;
363 
368  void write(std::ostream &out) const;
369 
374  void read(std::istream &in);
375 
380  void block_write(std::ostream &out) const;
381 
386  void block_read(std::istream &in);
387 
388 #ifdef DEAL_II_WITH_TRILINOS
389 
417  Epetra_Map make_trilinos_map (const MPI_Comm &communicator = MPI_COMM_WORLD,
418  const bool overlapping = false) const;
419 #endif
420 
421 
426  std::size_t memory_consumption () const;
427 
429  << "The global index " << arg1
430  << " is not an element of this set.");
431 
436  template <class Archive>
437  void serialize (Archive &ar, const unsigned int version);
438 
439 
451  {
452  public:
457  IntervalAccessor(const IndexSet *idxset, const size_type range_idx);
458 
462  explicit IntervalAccessor(const IndexSet *idxset);
463 
467  size_type n_elements() const;
468 
472  bool is_valid() const;
473 
477  ElementIterator begin() const;
478 
483  ElementIterator end() const;
484 
488  size_type last() const;
489 
490  private:
494  IntervalAccessor(const IntervalAccessor &other);
499 
503  bool operator == (const IntervalAccessor &other) const;
507  bool operator < (const IntervalAccessor &other) const;
512  void advance ();
517 
523 
524  friend class IntervalIterator;
525  };
526 
531  class IntervalIterator : public std::iterator<std::forward_iterator_tag,IntervalAccessor>
532  {
533  public:
538  IntervalIterator(const IndexSet *idxset, const size_type range_idx);
539 
543  explicit IntervalIterator(const IndexSet *idxset);
544 
549 
553  IntervalIterator(const IntervalIterator &other);
554 
559 
564 
569 
573  const IntervalAccessor &operator* () const;
574 
578  const IntervalAccessor *operator-> () const;
579 
583  bool operator == (const IntervalIterator &) const;
584 
588  bool operator != (const IntervalIterator &) const;
589 
593  bool operator < (const IntervalIterator &) const;
594 
601  int operator - (const IntervalIterator &p) const;
602 
603  private:
608  };
609 
614  class ElementIterator : public std::iterator<std::forward_iterator_tag,size_type>
615  {
616  public:
621  ElementIterator(const IndexSet *idxset,
622  const size_type range_idx,
623  const size_type index);
624 
628  explicit ElementIterator(const IndexSet *idxset);
629 
634  size_type operator* () const;
635 
639  bool is_valid () const;
640 
645 
650 
654  bool operator == (const ElementIterator &) const;
655 
659  bool operator != (const ElementIterator &) const;
660 
664  bool operator < (const ElementIterator &) const;
665 
674  std::ptrdiff_t operator - (const ElementIterator &p) const;
675 
676  private:
680  void advance ();
681 
694  };
695 
700  ElementIterator begin() const;
701 
716  ElementIterator at(const size_type global_index) const;
717 
722  ElementIterator end() const;
723 
728 
734 
739 private:
748  struct Range
749  {
750  size_type begin;
751  size_type end;
752 
753  size_type nth_index_in_set;
754 
763  Range ();
764 
772  Range (const size_type i1,
773  const size_type i2);
774 
775  friend
776  inline bool operator< (const Range &range_1,
777  const Range &range_2)
778  {
779  return ((range_1.begin < range_2.begin)
780  ||
781  ((range_1.begin == range_2.begin)
782  &&
783  (range_1.end < range_2.end)));
784  }
785 
786  static bool end_compare(const IndexSet::Range &x, const IndexSet::Range &y)
787  {
788  return x.end < y.end;
789  }
790 
791  static bool nth_index_compare (const IndexSet::Range &x,
792  const IndexSet::Range &y)
793  {
794  return (x.nth_index_in_set+(x.end-x.begin) <
795  y.nth_index_in_set+(y.end-y.begin));
796  }
797 
798  friend
799  inline bool operator== (const Range &range_1,
800  const Range &range_2)
801  {
802  return ((range_1.begin == range_2.begin)
803  &&
804  (range_1.end == range_2.end));
805  }
806 
807  static std::size_t memory_consumption ()
808  {
809  return sizeof(Range);
810  }
811 
816  template <class Archive>
817  void serialize (Archive &ar, const unsigned int version);
818  };
819 
828  mutable std::vector<Range> ranges;
829 
838  mutable bool is_compressed;
839 
845 
856 
862 
866  void do_compress() const;
867 };
868 
869 
887 inline
888 IndexSet complete_index_set (const unsigned int N)
889 {
890  IndexSet is (N);
891  is.add_range(0, N);
892  return is;
893 }
894 
895 /* ------------------ inline functions ------------------ */
896 
897 
898 /* IntervalAccessor */
899 
900 inline
902  : index_set(idxset), range_idx(range_idx)
903 {
904  Assert(range_idx < idxset->n_intervals(), ExcInternalError("Invalid range index"));
905 }
906 
907 inline
909  : index_set(idxset), range_idx(numbers::invalid_dof_index)
910 {}
911 
912 inline
914 {
915  Assert(is_valid(), ExcMessage("invalid iterator"));
916  return index_set->ranges[range_idx].end - index_set->ranges[range_idx].begin;
917 }
918 
919 inline
921 {
922  return index_set != NULL && range_idx < index_set->n_intervals();
923 }
924 
925 inline
927 {
928  Assert(is_valid(), ExcMessage("invalid iterator"));
929  return IndexSet::ElementIterator(index_set, range_idx, index_set->ranges[range_idx].begin);
930 }
931 
932 inline
934 {
935  Assert(is_valid(), ExcMessage("invalid iterator"));
936 
937  // point to first index in next interval unless we are the last interval.
938  if (range_idx < index_set->ranges.size()-1)
939  return IndexSet::ElementIterator(index_set, range_idx+1, index_set->ranges[range_idx+1].begin);
940  else
941  return index_set->end();
942 }
943 
944 inline
947 {
948  Assert(is_valid(), ExcMessage("invalid iterator"));
949 
950  return index_set->ranges[range_idx].end-1;
951 }
952 
953 inline
955  : index_set (other.index_set), range_idx(other.range_idx)
956 {
957  Assert( range_idx == numbers::invalid_dof_index || is_valid(), ExcMessage("invalid iterator"));
958 }
959 
960 inline
963 {
964  index_set = other.index_set;
965  range_idx = other.range_idx;
966  Assert( range_idx == numbers::invalid_dof_index || is_valid(), ExcMessage("invalid iterator"));
967  return *this;
968 }
969 
970 inline
972 {
973  Assert (index_set == other.index_set, ExcMessage("Can not compare accessors pointing to different IndexSets"));
974  return range_idx == other.range_idx;
975 }
976 
977 inline
979 {
980  Assert (index_set == other.index_set, ExcMessage("Can not compare accessors pointing to different IndexSets"));
981  return range_idx < other.range_idx;
982 }
983 
984 inline
986 {
987  Assert(is_valid(), ExcMessage("Impossible to advance an IndexSet::IntervalIterator that is invalid"));
988  ++range_idx;
989 
990  // set ourselves to invalid if we walk off the end
991  if (range_idx>=index_set->ranges.size())
992  range_idx = numbers::invalid_dof_index;
993 }
994 
995 /* IntervalIterator */
996 
997 inline
999  : accessor(idxset, range_idx)
1000 {}
1001 
1002 inline
1004  : accessor(NULL)
1005 {}
1006 
1007 inline
1009  : accessor(idxset)
1010 {}
1011 
1012 inline
1014  : accessor(other.accessor)
1015 {}
1016 
1017 inline
1020 {
1021  accessor = other.accessor;
1022  return *this;
1023 }
1024 
1025 
1026 inline
1029 {
1030  accessor.advance();
1031  return *this;
1032 }
1033 
1034 inline
1037 {
1038  const IndexSet::IntervalIterator iter = *this;
1039  accessor.advance ();
1040  return iter;
1041 }
1042 
1043 inline
1046 {
1047  return accessor;
1048 }
1049 
1050 inline
1053 {
1054  return &accessor;
1055 }
1056 
1057 inline
1059 {
1060  return accessor == other.accessor;
1061 }
1062 
1063 inline
1065 {
1066  return !(*this == other);
1067 }
1068 
1069 inline
1071 {
1072  return accessor < other.accessor;
1073 }
1074 
1075 inline
1077 {
1078  Assert (accessor.index_set == other.accessor.index_set, ExcMessage("Can not compare iterators belonging to different IndexSets"));
1079 
1080  const size_type lhs = (accessor.range_idx == numbers::invalid_dof_index) ? accessor.index_set->ranges.size() : accessor.range_idx;
1081  const size_type rhs = (other.accessor.range_idx == numbers::invalid_dof_index) ? accessor.index_set->ranges.size() : other.accessor.range_idx;
1082 
1083  if (lhs > rhs)
1084  return static_cast<int>(lhs - rhs);
1085  else
1086  return -static_cast<int>(rhs - lhs);
1087 }
1088 
1089 
1090 /* ElementIterator */
1091 
1092 inline
1094 {
1095  Assert(
1097  ||
1098  (range_idx < index_set->ranges.size() && idx<index_set->ranges[range_idx].end)
1099  , ExcInternalError("Invalid ElementIterator state."));
1100 
1101  return range_idx < index_set->ranges.size() && idx<index_set->ranges[range_idx].end;
1102 }
1103 
1104 inline
1106  : index_set(idxset), range_idx(range_idx), idx(index)
1107 {
1108  Assert(range_idx < index_set->ranges.size(),
1109  ExcMessage("Invalid range index for IndexSet::ElementIterator constructor."));
1110  Assert(idx >= index_set->ranges[range_idx].begin
1111  &&
1112  idx < index_set->ranges[range_idx].end,
1113  ExcInternalError("Invalid index argument for IndexSet::ElementIterator constructor."));
1114 }
1115 
1116 inline
1118  : index_set(idxset), range_idx(numbers::invalid_dof_index), idx(numbers::invalid_dof_index)
1119 {}
1120 
1121 inline
1124 {
1125  Assert(is_valid(), ExcMessage("Impossible to dereference an IndexSet::ElementIterator that is invalid"));
1126  return idx;
1127 }
1128 
1129 inline
1131 {
1132  Assert (index_set == other.index_set, ExcMessage("Can not compare iterators belonging to different IndexSets"));
1133  return range_idx == other.range_idx && idx==other.idx;
1134 }
1135 
1136 inline
1138 {
1139  Assert(is_valid(), ExcMessage("Impossible to advance an IndexSet::ElementIterator that is invalid"));
1140  if (idx < index_set->ranges[range_idx].end)
1141  ++idx;
1142  // end of this range?
1143  if (idx == index_set->ranges[range_idx].end)
1144  {
1145  // point to first element in next interval if possible
1146  if (range_idx < index_set->ranges.size()-1)
1147  {
1148  ++range_idx;
1149  idx = index_set->ranges[range_idx].begin;
1150  }
1151  else
1152  {
1153  // we just fell off the end, set to invalid:
1154  range_idx = numbers::invalid_dof_index;
1156  }
1157  }
1158 }
1159 
1160 inline
1163 {
1164  advance();
1165  return *this;
1166 }
1167 
1168 inline
1171 {
1172  const IndexSet::ElementIterator it = *this;
1173  advance();
1174  return it;
1175 }
1176 
1177 inline
1179 {
1180  return !(*this == other);
1181 }
1182 
1183 inline
1185 {
1186  Assert (index_set == other.index_set, ExcMessage("Can not compare iterators belonging to different IndexSets"));
1187  return range_idx < other.range_idx || (range_idx == other.range_idx && idx<other.idx);
1188 }
1189 
1190 inline
1192 {
1193  Assert (index_set == other.index_set, ExcMessage("Can not compare iterators belonging to different IndexSets"));
1194  if (*this == other)
1195  return 0;
1196  if (!(*this < other))
1197  return -(other-*this);
1198 
1199  // only other can be equal to end() because of the checks above.
1200  Assert (is_valid(), ExcInternalError());
1201 
1202  // Note: we now compute how far advance *this in "*this < other" to get other, so we need to return -c at the end.
1203 
1204  // first finish the current range:
1205  std::ptrdiff_t c = index_set->ranges[range_idx].end-idx;
1206 
1207  // now walk in steps of ranges (need to start one behind our current one):
1208  for (size_type range=range_idx+1; range<index_set->ranges.size() && range<=other.range_idx; ++range)
1209  c += index_set->ranges[range].end-index_set->ranges[range].begin;
1210 
1211  Assert(other.range_idx < index_set->ranges.size() || other.range_idx == numbers::invalid_dof_index,
1212  ExcMessage("Inconsistent iterator state. Did you invalidate iterators by modifying the IndexSet?"));
1213 
1214  // We might have walked too far because we went until the end of other.range_idx, so walk backwards to other.idx:
1216  c -= index_set->ranges[other.range_idx].end - other.idx;
1217 
1218  return -c;
1219 }
1220 
1221 
1222 /* Range */
1223 
1224 inline
1226  :
1227  begin(numbers::invalid_dof_index),
1228  end(numbers::invalid_dof_index),
1229  nth_index_in_set(numbers::invalid_dof_index)
1230 {}
1231 
1232 
1233 inline
1235  const size_type i2)
1236  :
1237  begin(i1),
1238  end(i2),
1239  nth_index_in_set(numbers::invalid_dof_index)
1240 {}
1241 
1242 
1243 /* IndexSet itself */
1244 
1245 inline
1247 {
1248  compress();
1249  if (ranges.size()>0)
1250  return IndexSet::ElementIterator(this, 0, ranges[0].begin);
1251  else
1252  return end();
1253 }
1254 
1255 inline
1257 {
1258  compress();
1259  Assert (global_index < size(),
1260  ExcIndexRangeType<size_type> (global_index, 0, size()));
1261 
1262  if (ranges.empty())
1263  return end();
1264 
1265  std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1266 
1267  Range r (global_index, global_index+1);
1268  // This optimization makes the bounds for lower_bound smaller by checking
1269  // the largest range first.
1270  std::vector<Range>::const_iterator range_begin, range_end;
1271  if (global_index<main_range->begin)
1272  {
1273  range_begin = ranges.begin();
1274  range_end = main_range;
1275  }
1276  else
1277  {
1278  range_begin = main_range;
1279  range_end = ranges.end();
1280  }
1281 
1282  // This will give us the first range p=[a,b[ with b>=global_index using
1283  // a binary search
1284  const std::vector<Range>::const_iterator
1285  p = Utilities::lower_bound(range_begin, range_end, r, Range::end_compare);
1286 
1287  // We couldn't find a range, which means we have no range that contains
1288  // global_index and also no range behind it, meaning we need to return end().
1289  if (p == ranges.end())
1290  return end();
1291 
1292  // Finally, we can have two cases: Either global_index is not in [a,b[,
1293  // which means we need to return an iterator to a because global_index, ...,
1294  // a-1 is not in the IndexSet (if branch). Alternatively, global_index is in
1295  // [a,b[ and we will return an iterator pointing directly at global_index
1296  // (else branch).
1297  if (global_index < p->begin)
1298  return IndexSet::ElementIterator(this, p-ranges.begin(), p->begin);
1299  else
1300  return IndexSet::ElementIterator(this, p-ranges.begin(), global_index);
1301 }
1302 
1303 
1304 inline
1306 {
1307  compress();
1308  return IndexSet::ElementIterator(this);
1309 }
1310 
1311 
1312 inline
1314 {
1315  compress();
1316  if (ranges.size()>0)
1317  return IndexSet::IntervalIterator(this, 0);
1318  else
1319  return end_intervals();
1320 }
1321 
1322 inline
1324 {
1325  compress();
1326  return IndexSet::IntervalIterator(this);
1327 }
1328 
1329 
1330 
1331 inline
1333  :
1334  is_compressed (true),
1335  index_space_size (0),
1336  largest_range (numbers::invalid_unsigned_int)
1337 {}
1338 
1339 
1340 
1341 inline
1343  :
1344  is_compressed (true),
1345  index_space_size (size),
1346  largest_range (numbers::invalid_unsigned_int)
1347 {}
1348 
1349 
1350 
1351 #ifdef DEAL_II_WITH_CXX11
1352 
1353 inline
1355  :
1356  ranges (std::move(is.ranges)),
1357  is_compressed (is.is_compressed),
1358  index_space_size (is.index_space_size),
1359  largest_range (is.largest_range)
1360 {
1361  is.ranges.clear ();
1362  is.is_compressed = true;
1363  is.index_space_size = 0;
1364  is.largest_range = numbers::invalid_unsigned_int;
1365 
1366  compress ();
1367 }
1368 
1369 
1370 inline
1372 {
1373  ranges = std::move (is.ranges);
1374  is_compressed = is.is_compressed;
1375  index_space_size = is.index_space_size;
1376  largest_range = is.largest_range;
1377 
1378  is.ranges.clear ();
1379  is.is_compressed = true;
1380  is.index_space_size = 0;
1381  is.largest_range = numbers::invalid_unsigned_int;
1382 
1383  compress ();
1384 
1385  return *this;
1386 }
1387 
1388 #endif
1389 
1390 
1391 inline
1392 void
1394 {
1395  // reset so that there are no indices in the set any more; however,
1396  // as documented, the index set retains its size
1397  ranges.clear ();
1398  is_compressed = true;
1400 }
1401 
1402 
1403 
1404 inline
1405 void
1407 {
1408  Assert (ranges.empty(),
1409  ExcMessage ("This function can only be called if the current "
1410  "object does not yet contain any elements."));
1411  index_space_size = sz;
1412  is_compressed = true;
1413 }
1414 
1415 
1416 
1417 inline
1420 {
1421  return index_space_size;
1422 }
1423 
1424 
1425 
1426 inline
1427 void
1429 {
1430  if (is_compressed == true)
1431  return;
1432 
1433  do_compress();
1434 }
1435 
1436 
1437 
1438 inline
1439 void
1441 {
1442  Assert (index < index_space_size,
1443  ExcIndexRangeType<size_type> (index, 0, index_space_size));
1444 
1445  const Range new_range(index, index+1);
1446  if (ranges.size() == 0 || index > ranges.back().end)
1447  ranges.push_back(new_range);
1448  else if (index == ranges.back().end)
1449  ranges.back().end++;
1450  else
1451  ranges.insert (Utilities::lower_bound (ranges.begin(),
1452  ranges.end(),
1453  new_range),
1454  new_range);
1455  is_compressed = false;
1456 }
1457 
1458 
1459 
1460 template <typename ForwardIterator>
1461 inline
1462 void
1463 IndexSet::add_indices (const ForwardIterator &begin,
1464  const ForwardIterator &end)
1465 {
1466  // insert each element of the range. if some of them happen to be
1467  // consecutive, merge them to a range
1468  for (ForwardIterator p=begin; p!=end;)
1469  {
1470  const size_type begin_index = *p;
1471  size_type end_index = begin_index + 1;
1472  ForwardIterator q = p;
1473  ++q;
1474  while ((q != end) && (*q == end_index))
1475  {
1476  ++end_index;
1477  ++q;
1478  }
1479 
1480  add_range (begin_index, end_index);
1481  p = q;
1482  }
1483 }
1484 
1485 
1486 
1487 inline
1488 bool
1489 IndexSet::is_element (const size_type index) const
1490 {
1491  if (ranges.empty() == false)
1492  {
1493  compress ();
1494 
1495  // fast check whether the index is in the largest range
1497  if (index >= ranges[largest_range].begin &&
1498  index < ranges[largest_range].end)
1499  return true;
1500 
1501  // get the element after which we would have to insert a range that
1502  // consists of all elements from this element to the end of the index
1503  // range plus one. after this call we know that if p!=end() then
1504  // p->begin<=index unless there is no such range at all
1505  //
1506  // if the searched for element is an element of this range, then we're
1507  // done. otherwise, the element can't be in one of the following ranges
1508  // because otherwise p would be a different iterator
1509  //
1510  // since we already know the position relative to the largest range (we
1511  // called compress!), we can perform the binary search on ranges with
1512  // lower/higher number compared to the largest range
1513  std::vector<Range>::const_iterator
1514  p = std::upper_bound (ranges.begin() + (index<ranges[largest_range].begin?
1515  0 : largest_range+1),
1516  index<ranges[largest_range].begin ?
1517  ranges.begin() + largest_range:
1518  ranges.end(),
1519  Range (index, size()+1));
1520 
1521  if (p == ranges.begin())
1522  return ((index >= p->begin) && (index < p->end));
1523 
1524  Assert ((p == ranges.end()) || (p->begin > index),
1525  ExcInternalError());
1526 
1527  // now move to that previous range
1528  --p;
1529  Assert (p->begin <= index, ExcInternalError());
1530 
1531  return (p->end > index);
1532  }
1533 
1534  // didn't find this index, so it's not in the set
1535  return false;
1536 }
1537 
1538 
1539 
1540 inline
1541 bool
1543 {
1544  compress ();
1545  return (ranges.size() <= 1);
1546 }
1547 
1548 
1549 inline
1550 bool
1552 {
1553  return ranges.empty();
1554 }
1555 
1556 
1557 
1558 inline
1561 {
1562  // make sure we have non-overlapping ranges
1563  compress ();
1564 
1565  size_type v = 0;
1566  if (!ranges.empty())
1567  {
1568  Range &r = ranges.back();
1569  v = r.nth_index_in_set + r.end - r.begin;
1570  }
1571 
1572 #ifdef DEBUG
1573  size_type s = 0;
1574  for (std::vector<Range>::iterator range = ranges.begin();
1575  range != ranges.end();
1576  ++range)
1577  s += (range->end - range->begin);
1578  Assert(s==v, ExcInternalError());
1579 #endif
1580 
1581  return v;
1582 }
1583 
1584 
1585 
1586 inline
1587 unsigned int
1589 {
1590  compress ();
1591  return ranges.size();
1592 }
1593 
1594 
1595 
1596 inline
1597 unsigned int
1599 {
1600  Assert(ranges.empty()==false, ExcMessage("IndexSet cannot be empty."));
1601 
1602  compress();
1603  const std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1604 
1605  return main_range->nth_index_in_set;
1606 }
1607 
1608 
1609 
1610 inline
1612 IndexSet::nth_index_in_set (const unsigned int n) const
1613 {
1614  Assert (n < n_elements(), ExcIndexRangeType<size_type> (n, 0, n_elements()));
1615 
1616  compress ();
1617 
1618  // first check whether the index is in the largest range
1620  std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1621  if (n>=main_range->nth_index_in_set &&
1622  n<main_range->nth_index_in_set+(main_range->end-main_range->begin))
1623  return main_range->begin + (n-main_range->nth_index_in_set);
1624 
1625  // find out which chunk the local index n belongs to by using a binary
1626  // search. the comparator is based on the end of the ranges. Use the
1627  // position relative to main_range to subdivide the ranges
1628  Range r (n,n+1);
1629  r.nth_index_in_set = n;
1630  std::vector<Range>::const_iterator range_begin, range_end;
1631  if (n<main_range->nth_index_in_set)
1632  {
1633  range_begin = ranges.begin();
1634  range_end = main_range;
1635  }
1636  else
1637  {
1638  range_begin = main_range + 1;
1639  range_end = ranges.end();
1640  }
1641 
1642  const std::vector<Range>::const_iterator
1643  p = Utilities::lower_bound(range_begin, range_end, r,
1644  Range::nth_index_compare);
1645 
1646  Assert (p != ranges.end(), ExcInternalError());
1647  return p->begin + (n-p->nth_index_in_set);
1648 }
1649 
1650 
1651 inline
1654 {
1655  // to make this call thread-safe, compress() must not be called through this
1656  // function
1657  Assert (is_compressed == true, ExcMessage ("IndexSet must be compressed."));
1658  Assert (n < size(), ExcIndexRangeType<size_type> (n, 0, size()));
1659 
1660  // return immediately if the index set is empty
1661  if (is_empty())
1663 
1664  // check whether the index is in the largest range. use the result to
1665  // perform a one-sided binary search afterward
1667  std::vector<Range>::const_iterator main_range=ranges.begin()+largest_range;
1668  if (n >= main_range->begin && n < main_range->end)
1669  return (n-main_range->begin) + main_range->nth_index_in_set;
1670 
1671  Range r(n, n);
1672  std::vector<Range>::const_iterator range_begin, range_end;
1673  if (n<main_range->begin)
1674  {
1675  range_begin = ranges.begin();
1676  range_end = main_range;
1677  }
1678  else
1679  {
1680  range_begin = main_range + 1;
1681  range_end = ranges.end();
1682  }
1683 
1684  std::vector<Range>::const_iterator
1685  p = Utilities::lower_bound(range_begin, range_end, r,
1686  Range::end_compare);
1687 
1688  // if n is not in this set
1689  if (p==range_end || p->end == n || p->begin > n)
1691 
1692  Assert(p!=ranges.end(), ExcInternalError());
1693  Assert(p->begin<=n, ExcInternalError());
1694  Assert(n<p->end, ExcInternalError());
1695  return (n-p->begin) + p->nth_index_in_set;
1696 }
1697 
1698 
1699 
1700 inline
1701 bool
1703 {
1704  Assert (size() == is.size(),
1705  ExcDimensionMismatch (size(), is.size()));
1706 
1707  compress ();
1708  is.compress ();
1709 
1710  return ranges == is.ranges;
1711 }
1712 
1713 
1714 
1715 inline
1716 bool
1718 {
1719  Assert (size() == is.size(),
1720  ExcDimensionMismatch (size(), is.size()));
1721 
1722  compress ();
1723  is.compress ();
1724 
1725  return ranges != is.ranges;
1726 }
1727 
1728 
1729 
1730 template <typename Vector>
1731 void
1732 IndexSet::fill_binary_vector (Vector &vector) const
1733 {
1734  Assert (vector.size() == size(),
1735  ExcDimensionMismatch (vector.size(), size()));
1736 
1737  compress();
1738  // first fill all elements of the vector with zeroes.
1739  std::fill (vector.begin(), vector.end(), 0);
1740 
1741  // then write ones into the elements whose indices are contained in the
1742  // index set
1743  for (std::vector<Range>::iterator it = ranges.begin();
1744  it != ranges.end();
1745  ++it)
1746  for (size_type i=it->begin; i<it->end; ++i)
1747  vector[i] = 1;
1748 }
1749 
1750 
1751 
1752 template <class StreamType>
1753 inline
1754 void
1755 IndexSet::print (StreamType &out) const
1756 {
1757  compress();
1758  out << "{";
1759  std::vector<Range>::const_iterator p;
1760  for (p = ranges.begin(); p != ranges.end(); ++p)
1761  {
1762  if (p->end-p->begin==1)
1763  out << p->begin;
1764  else
1765  out << "[" << p->begin << "," << p->end-1 << "]";
1766 
1767  if (p != --ranges.end())
1768  out << ", ";
1769  }
1770  out << "}" << std::endl;
1771 }
1772 
1773 
1774 
1775 template <class Archive>
1776 inline
1777 void
1778 IndexSet::Range::serialize (Archive &ar, const unsigned int)
1779 {
1780  ar &begin &end &nth_index_in_set;
1781 }
1782 
1783 
1784 
1785 template <class Archive>
1786 inline
1787 void
1788 IndexSet::serialize (Archive &ar, const unsigned int)
1789 {
1791 }
1792 
1793 DEAL_II_NAMESPACE_CLOSE
1794 
1795 #endif
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:618
void fill_binary_vector(VectorType &vector) const
static const unsigned int invalid_unsigned_int
Definition: types.h:170
ElementIterator end() const
Definition: index_set.h:1305
void add_index(const size_type index)
Definition: index_set.h:1440
IndexSet operator&(const IndexSet &is) const
const IntervalAccessor * operator->() const
Definition: index_set.h:1052
const IntervalAccessor & operator*() const
Definition: index_set.h:1045
size_type nth_index_in_set(const unsigned int local_index) const
Definition: index_set.h:1612
const IndexSet * index_set
Definition: index_set.h:685
IndexSet & operator=(const IndexSet &)=default
void block_read(std::istream &in)
Definition: index_set.cc:493
signed int value_type
Definition: index_set.h:98
std::ptrdiff_t operator-(const ElementIterator &p) const
Definition: index_set.h:1191
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1463
STL namespace.
unsigned int largest_range_starting_index() const
Definition: index_set.h:1598
ElementIterator(const IndexSet *idxset, const size_type range_idx, const size_type index)
Definition: index_set.h:1105
bool operator<(const IntervalIterator &) const
Definition: index_set.h:1070
iterator end()
std::size_t memory_consumption() const
Definition: index_set.cc:674
size_type n_elements() const
Definition: index_set.h:913
size_type index_space_size
Definition: index_set.h:844
bool is_ascending_and_one_to_one(const MPI_Comm &communicator) const
Definition: index_set.cc:604
Epetra_Map make_trilinos_map(const MPI_Comm &communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition: index_set.cc:535
size_type size() const
Definition: index_set.h:1419
void print(StreamType &out) const
Definition: index_set.h:1755
void serialize(Archive &ar, const unsigned int version)
Definition: index_set.h:1778
IndexSet complete_index_set(const unsigned int N)
Definition: index_set.h:888
void clear()
Definition: index_set.h:1393
void serialize(Archive &ar, const unsigned int version)
Definition: index_set.h:1788
static ::ExceptionBase & ExcMessage(std::string arg1)
void block_write(std::ostream &out) const
Definition: index_set.cc:478
IntervalIterator & operator=(const IntervalIterator &other)
Definition: index_set.h:1019
std::vector< Range > ranges
Definition: index_set.h:828
static ::ExceptionBase & ExcIndexNotPresent(size_type arg1)
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:564
unsigned int global_dof_index
Definition: types.h:88
void subtract_set(const IndexSet &other)
Definition: index_set.cc:278
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
bool operator<(const ElementIterator &) const
Definition: index_set.h:1184
size_type index_within_set(const size_type global_index) const
Definition: index_set.h:1653
bool operator==(const IndexSet &is) const
Definition: index_set.h:1702
std::size_t size() const
IntervalAccessor accessor
Definition: index_set.h:607
void do_compress() const
Definition: index_set.cc:120
IntervalAccessor & operator=(const IntervalAccessor &other)
Definition: index_set.h:962
bool operator==(const IntervalIterator &) const
Definition: index_set.h:1058
iterator begin()
size_type last() const
Definition: index_set.h:946
const IndexSet * index_set
Definition: index_set.h:516
bool operator==(const IntervalAccessor &other) const
Definition: index_set.h:971
unsigned int n_intervals() const
Definition: index_set.h:1588
int operator-(const IntervalIterator &p) const
Definition: index_set.h:1076
bool operator!=(const IndexSet &is) const
Definition: index_set.h:1717
size_type pop_back()
Definition: index_set.cc:352
void fill_index_vector(std::vector< size_type > &indices) const
Definition: index_set.cc:512
void add_range(const size_type begin, const size_type end)
Definition: index_set.cc:88
void set_size(const size_type size)
Definition: index_set.h:1406
ElementIterator & operator++()
Definition: index_set.h:1162
IntervalAccessor(const IndexSet *idxset, const size_type range_idx)
Definition: index_set.h:901
IndexSet get_view(const size_type begin, const size_type end) const
Definition: index_set.cc:244
void compress() const
Definition: index_set.h:1428
ElementIterator end() const
Definition: index_set.h:933
IntervalIterator begin_intervals() const
Definition: index_set.h:1313
bool is_contiguous() const
Definition: index_set.h:1542
Threads::Mutex compress_mutex
Definition: index_set.h:861
size_type pop_front()
Definition: index_set.cc:369
IntervalIterator end_intervals() const
Definition: index_set.h:1323
bool is_compressed
Definition: index_set.h:838
bool operator<(const IntervalAccessor &other) const
Definition: index_set.h:978
bool operator!=(const ElementIterator &) const
Definition: index_set.h:1178
ElementIterator begin() const
Definition: index_set.h:926
void write(std::ostream &out) const
Definition: index_set.cc:445
bool is_element(const size_type index) const
Definition: index_set.h:1489
bool operator==(const ElementIterator &) const
Definition: index_set.h:1130
ElementIterator at(const size_type global_index) const
Definition: index_set.h:1256
const types::global_dof_index invalid_dof_index
Definition: types.h:184
types::global_dof_index size_type
Definition: index_set.h:73
ElementIterator begin() const
Definition: index_set.h:1246
void read(std::istream &in)
Definition: index_set.cc:460
size_type n_elements() const
Definition: index_set.h:1560
bool is_empty() const
Definition: index_set.h:1551
size_type largest_range
Definition: index_set.h:855
IntervalIterator & operator++()
Definition: index_set.h:1028
static ::ExceptionBase & ExcInternalError()
size_type operator*() const
Definition: index_set.h:1123
bool operator!=(const IntervalIterator &) const
Definition: index_set.h:1064