Reference documentation for deal.II version 8.5.1
sparsity_pattern.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2016 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__sparsity_pattern_h
17 #define dealii__sparsity_pattern_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/subscriptor.h>
23 
24 // boost::serialization::make_array used to be in array.hpp, but was
25 // moved to a different file in BOOST 1.64
26 #include <boost/version.hpp>
27 #if BOOST_VERSION >= 106400
28 # include <boost/serialization/array_wrapper.hpp>
29 #else
30 # include <boost/serialization/array.hpp>
31 #endif
32 #include <boost/serialization/split_member.hpp>
33 
34 #include <vector>
35 #include <iostream>
36 #include <algorithm>
37 
38 DEAL_II_NAMESPACE_OPEN
39 
40 class SparsityPattern;
42 template <typename number> class FullMatrix;
43 template <typename number> class SparseMatrix;
44 template <typename number> class SparseLUDecomposition;
45 template <typename number> class SparseILU;
46 template <typename VectorType> class VectorSlice;
47 
49 {
50  class Accessor;
51 }
52 
53 
58 namespace internals
59 {
60  namespace SparsityPatternTools
61  {
66 
72  size_type
73  get_column_index_from_iterator (const size_type i);
74 
80  template <typename value>
81  size_type
82  get_column_index_from_iterator (const std::pair<size_type, value> &i);
83 
89  template <typename value>
90  size_type
91  get_column_index_from_iterator (const std::pair<const size_type, value> &i);
92 
93  }
94 }
95 
96 
101 {
102  // forward declaration
103  class Iterator;
104 
109 
123  class Accessor
124  {
125  public:
129  Accessor (const SparsityPattern *matrix,
130  const std::size_t index_within_sparsity);
131 
135  Accessor (const SparsityPattern *matrix);
136 
141  size_type row () const;
142 
148  size_type index () const;
149 
154  size_type column () const;
155 
165  bool is_valid_entry () const;
166 
170  bool operator == (const Accessor &) const;
171 
179  bool operator < (const Accessor &) const;
180 
181  protected:
186 
195 
199  void advance ();
200 
204  friend class Iterator;
205 
210  };
211 
212 
213 
238  class Iterator
239  {
240  public:
246  Iterator (const SparsityPattern *sp,
247  const std::size_t index_within_sparsity);
248 
253 
257  Iterator operator++ (int);
258 
262  const Accessor &operator* () const;
263 
267  const Accessor *operator-> () const;
268 
272  bool operator == (const Iterator &) const;
273 
277  bool operator != (const Iterator &) const;
278 
286  bool operator < (const Iterator &) const;
287 
294  int operator - (const Iterator &p) const;
295 
296  private:
301  };
302 }
303 
304 
305 
341 {
342 public:
347 
352  typedef
355 
363  typedef
366 
367 
383 
388 // @{
394  SparsityPattern ();
395 
412 
420  SparsityPattern (const size_type m,
421  const size_type n,
422  const unsigned int max_per_row);
423 
424 
433  SparsityPattern (const size_type m,
434  const size_type n,
435  const std::vector<unsigned int> &row_lengths);
436 
445  SparsityPattern (const size_type m,
446  const unsigned int max_per_row);
447 
455  SparsityPattern (const size_type m,
456  const std::vector<unsigned int> &row_lengths);
457 
480  SparsityPattern (const SparsityPattern &original,
481  const unsigned int max_per_row,
482  const size_type extra_off_diagonals);
483 
487  ~SparsityPattern ();
488 
495 
504  void reinit (const size_type m,
505  const size_type n,
506  const unsigned int max_per_row);
507 
508 
523  void reinit (const size_type m,
524  const size_type n,
525  const std::vector<unsigned int> &row_lengths);
526 
527 
531  void reinit (const size_type m,
532  const size_type n,
533  const VectorSlice<const std::vector<unsigned int> > &row_lengths);
534 
547  void compress ();
548 
549 
626  template <typename ForwardIterator>
627  void copy_from (const size_type n_rows,
628  const size_type n_cols,
629  const ForwardIterator begin,
630  const ForwardIterator end);
631 
639  template <typename SparsityPatternType>
640  void copy_from (const SparsityPatternType &dsp);
641 
642 
650  template <typename number>
651  void copy_from (const FullMatrix<number> &matrix);
652 
660  void symmetrize ();
661 
668  void add (const size_type i,
669  const size_type j);
670 
677  template <typename ForwardIterator>
678  void add_entries (const size_type row,
679  ForwardIterator begin,
680  ForwardIterator end,
681  const bool indices_are_sorted = false);
682 
683 // @}
684 
685 
686 
687 
691 // @{
692 
701  iterator begin () const;
702 
706  iterator end () const;
707 
719  iterator begin (const size_type r) const;
720 
729  iterator end (const size_type r) const;
730 
731 
732 // @}
736 // @{
740  bool operator == (const SparsityPattern &) const;
741 
746  bool empty () const;
747 
754 
764  size_type bandwidth () const;
765 
774  std::size_t n_nonzero_elements () const;
775 
779  bool is_compressed () const;
780 
785  size_type n_rows () const;
786 
791  size_type n_cols () const;
792 
796  unsigned int row_length (const size_type row) const;
797 
810  bool stores_only_added_elements () const;
811 
816  std::size_t memory_consumption () const;
817 
818 // @}
822 // @{
846  const size_type j) const;
847 
859  std::pair<size_type, size_type>
860  matrix_position (const std::size_t global_index) const;
861 
865  bool exists (const size_type i,
866  const size_type j) const;
867 
876  const size_type j) const;
877 
888  size_type column_number (const size_type row,
889  const unsigned int index) const;
890 
891 
892 // @}
896 // @{
907  void block_write (std::ostream &out) const;
908 
922  void block_read (std::istream &in);
923 
929  void print (std::ostream &out) const;
930 
944  void print_gnuplot (std::ostream &out) const;
945 
953  void print_svg (std::ostream &out) const;
954 
955 
960  template <class Archive>
961  void save (Archive &ar, const unsigned int version) const;
962 
967  template <class Archive>
968  void load (Archive &ar, const unsigned int version);
969 
970  BOOST_SERIALIZATION_SPLIT_MEMBER()
971 
972 // @}
973 
974 
982  int, int,
983  << "Upon entering a new entry to row " << arg1
984  << ": there was no free entry any more. " << std::endl
985  << "(Maximum number of entries for this row: "
986  << arg2 << "; maybe the matrix is already compressed?)");
992  "The operation you attempted is only allowed after the SparsityPattern "
993  "has been set up and compress() was called.");
999  "The operation you attempted changes the structure of the SparsityPattern "
1000  "and is not possible after compress() has been called.");
1005  int, int,
1006  << "The iterators denote a range of " << arg1
1007  << " elements, but the given number of rows was " << arg2);
1012  int,
1013  << "The number of partitions you gave is " << arg1
1014  << ", but must be greater than zero.");
1016 private:
1025 
1030 
1035 
1041  std::size_t max_vec_len;
1042 
1050  unsigned int max_row_length;
1051 
1065  std::size_t *rowstart;
1066 
1090 
1095 
1100 
1104  template <typename number> friend class SparseMatrix;
1105  template <typename number> friend class SparseLUDecomposition;
1106  template <typename number> friend class SparseILU;
1107  template <typename number> friend class ChunkSparseMatrix;
1108 
1109  friend class ChunkSparsityPattern;
1110 
1114  friend class SparsityPatternIterators::Iterator;
1115  friend class SparsityPatternIterators::Accessor;
1116  friend class ChunkSparsityPatternIterators::Accessor;
1117 };
1118 
1119 
1121 /*---------------------- Inline functions -----------------------------------*/
1122 
1123 #ifndef DOXYGEN
1124 
1125 
1126 namespace SparsityPatternIterators
1127 {
1128  inline
1129  Accessor::
1130  Accessor (const SparsityPattern *sparsity_pattern,
1131  const std::size_t i)
1132  :
1133  sparsity_pattern(sparsity_pattern),
1134  index_within_sparsity(i)
1135  {}
1136 
1137 
1138  inline
1139  Accessor::
1140  Accessor (const SparsityPattern *sparsity_pattern)
1141  :
1142  sparsity_pattern(sparsity_pattern),
1143  index_within_sparsity(sparsity_pattern->rowstart[sparsity_pattern->rows])
1144  {}
1145 
1146 
1147  inline
1148  bool
1149  Accessor::is_valid_entry () const
1150  {
1151  return (index_within_sparsity < sparsity_pattern->rowstart[sparsity_pattern->rows]
1152  &&
1153  sparsity_pattern->colnums[index_within_sparsity]
1155  }
1156 
1157 
1158  inline
1159  size_type
1160  Accessor::row() const
1161  {
1162  Assert (is_valid_entry() == true, ExcInvalidIterator());
1163 
1164  const std::size_t *insert_point =
1165  std::upper_bound(sparsity_pattern->rowstart,
1166  sparsity_pattern->rowstart + sparsity_pattern->rows + 1,
1167  index_within_sparsity);
1168  return insert_point - sparsity_pattern->rowstart - 1;
1169  }
1170 
1171 
1172  inline
1173  size_type
1174  Accessor::column() const
1175  {
1176  Assert (is_valid_entry() == true, ExcInvalidIterator());
1177 
1178  return (sparsity_pattern->colnums[index_within_sparsity]);
1179  }
1180 
1181 
1182  inline
1183  size_type
1184  Accessor::index() const
1185  {
1186  Assert (is_valid_entry() == true, ExcInvalidIterator());
1187 
1188  return index_within_sparsity - sparsity_pattern->rowstart[row()];
1189  }
1190 
1191 
1192 
1193 
1194  inline
1195  bool
1196  Accessor::operator == (const Accessor &other) const
1197  {
1198  return (sparsity_pattern == other.sparsity_pattern &&
1199  index_within_sparsity == other.index_within_sparsity);
1200  }
1201 
1202 
1203 
1204  inline
1205  bool
1206  Accessor::operator < (const Accessor &other) const
1207  {
1208  Assert (sparsity_pattern == other.sparsity_pattern,
1209  ExcInternalError());
1210 
1211  return index_within_sparsity < other.index_within_sparsity;
1212  }
1213 
1214 
1215  inline
1216  void
1217  Accessor::advance ()
1218  {
1219  Assert (index_within_sparsity < sparsity_pattern->rowstart[sparsity_pattern->rows],
1220  ExcIteratorPastEnd());
1221  ++index_within_sparsity;
1222  }
1223 
1224 
1225 
1226  inline
1227  Iterator::Iterator (const SparsityPattern *sparsity_pattern,
1228  const std::size_t i)
1229  :
1230  accessor(sparsity_pattern, i)
1231  {}
1232 
1233 
1234 
1235  inline
1236  Iterator &
1237  Iterator::operator++ ()
1238  {
1239  accessor.advance ();
1240  return *this;
1241  }
1242 
1243 
1244 
1245  inline
1246  Iterator
1247  Iterator::operator++ (int)
1248  {
1249  const Iterator iter = *this;
1250  accessor.advance ();
1251  return iter;
1252  }
1253 
1254 
1255 
1256  inline
1257  const Accessor &
1258  Iterator::operator* () const
1259  {
1260  return accessor;
1261  }
1262 
1263 
1264 
1265  inline
1266  const Accessor *
1267  Iterator::operator-> () const
1268  {
1269  return &accessor;
1270  }
1271 
1272 
1273  inline
1274  bool
1275  Iterator::operator == (const Iterator &other) const
1276  {
1277  return (accessor == other.accessor);
1278  }
1279 
1280 
1281 
1282  inline
1283  bool
1284  Iterator::operator != (const Iterator &other) const
1285  {
1286  return ! (*this == other);
1287  }
1288 
1289 
1290  inline
1291  bool
1292  Iterator::operator < (const Iterator &other) const
1293  {
1294  return accessor < other.accessor;
1295  }
1296 
1297 
1298  inline
1299  int
1300  Iterator::operator - (const Iterator &other) const
1301  {
1302  Assert (accessor.sparsity_pattern == other.accessor.sparsity_pattern,
1303  ExcInternalError());
1304 
1305  return (*this)->index_within_sparsity - other->index_within_sparsity;
1306  }
1307 }
1308 
1309 
1310 
1311 inline
1313 SparsityPattern::begin () const
1314 {
1315  return iterator(this, rowstart[0]);
1316 }
1317 
1318 
1319 inline
1321 SparsityPattern::end () const
1322 {
1323  return iterator(this, rowstart[rows]);
1324 }
1325 
1326 
1327 
1328 inline
1330 SparsityPattern::begin (const size_type r) const
1331 {
1332  Assert (r<n_rows(), ExcIndexRangeType<size_type>(r,0,n_rows()));
1333 
1334  return iterator(this, rowstart[r]);
1335 }
1336 
1337 
1338 
1339 inline
1341 SparsityPattern::end (const size_type r) const
1342 {
1343  Assert (r<n_rows(), ExcIndexRangeType<size_type>(r,0,n_rows()));
1344 
1345  return iterator(this, rowstart[r+1]);
1346 }
1347 
1348 
1349 
1350 inline
1352 SparsityPattern::n_rows () const
1353 {
1354  return rows;
1355 }
1356 
1357 
1358 inline
1360 SparsityPattern::n_cols () const
1361 {
1362  return cols;
1363 }
1364 
1365 
1366 inline
1367 bool
1369 {
1370  return compressed;
1371 }
1372 
1373 
1374 inline
1375 bool
1377 {
1378  return (store_diagonal_first_in_row == false);
1379 }
1380 
1381 
1382 
1383 inline
1384 unsigned int
1385 SparsityPattern::row_length (const size_type row) const
1386 {
1387  Assert(row<rows, ExcIndexRangeType<size_type>(row,0,rows));
1388  return rowstart[row+1]-rowstart[row];
1389 }
1390 
1391 
1392 
1393 inline
1396  const unsigned int index) const
1397 {
1398  Assert(row<rows, ExcIndexRangeType<size_type>(row,0,rows));
1399  Assert(index<row_length(row), ExcIndexRange(index,0,row_length(row)));
1400 
1401  return colnums[rowstart[row]+index];
1402 }
1403 
1404 
1405 inline
1406 std::size_t
1408 {
1409  Assert ((rowstart!=0) && (colnums!=0), ExcEmptyObject());
1411  return rowstart[rows]-rowstart[0];
1412 }
1413 
1414 
1415 
1416 template <class Archive>
1417 inline
1418 void
1419 SparsityPattern::save (Archive &ar, const unsigned int) const
1420 {
1421  // forward to serialization function in the base class.
1422  ar &static_cast<const Subscriptor &>(*this);
1423 
1425 
1426  ar &boost::serialization::make_array(rowstart, max_dim + 1);
1427  ar &boost::serialization::make_array(colnums, max_vec_len);
1428 }
1429 
1430 
1431 
1432 template <class Archive>
1433 inline
1434 void
1435 SparsityPattern::load (Archive &ar, const unsigned int)
1436 {
1437  // forward to serialization function in the base class.
1438  ar &static_cast<Subscriptor &>(*this);
1439 
1441 
1442  if (rowstart != 0)
1443  delete[] rowstart;
1444  rowstart = new std::size_t[max_dim + 1];
1445 
1446  if (colnums != 0)
1447  delete[] colnums;
1448  colnums = new size_type[max_vec_len];
1449 
1450  ar &boost::serialization::make_array(rowstart, max_dim + 1);
1451  ar &boost::serialization::make_array(colnums, max_vec_len);
1452 }
1453 
1454 
1455 
1456 inline
1457 bool
1459 {
1460  // it isn't quite necessary to compare *all* member variables. by only
1461  // comparing the essential ones, we can say that two sparsity patterns are
1462  // equal even if one is compressed and the other is not (in which case some
1463  // of the member variables are not yet set correctly)
1464  if (rows != sp2.rows ||
1465  cols != sp2.cols ||
1466  compressed != sp2.compressed ||
1468  return false;
1469 
1470  for (size_type i = 0; i < rows+1; ++i)
1471  if (rowstart[i] != sp2.rowstart[i])
1472  return false;
1473 
1474  for (size_type i = 0; i < rowstart[rows]; ++i)
1475  if (colnums[i] != sp2.colnums[i])
1476  return false;
1477 
1478  return true;
1479 }
1480 
1481 
1482 
1483 namespace internal
1484 {
1485  namespace SparsityPatternTools
1486  {
1491 
1492  inline
1493  size_type
1494  get_column_index_from_iterator (const size_type i)
1495  {
1496  return i;
1497  }
1498 
1499 
1500 
1501  template <typename value>
1502  inline
1503  size_type
1504  get_column_index_from_iterator (const std::pair<size_type, value> &i)
1505  {
1506  return i.first;
1507  }
1508 
1509 
1510 
1511  template <typename value>
1512  inline
1513  size_type
1514  get_column_index_from_iterator (const std::pair<const size_type, value> &i)
1515  {
1516  return i.first;
1517  }
1518  }
1519 }
1520 
1521 
1522 
1523 template <typename ForwardIterator>
1524 void
1526  const size_type n_cols,
1527  const ForwardIterator begin,
1528  const ForwardIterator end)
1529 {
1530  Assert (static_cast<size_type>(std::distance (begin, end)) == n_rows,
1531  ExcIteratorRange (std::distance (begin, end), n_rows));
1532 
1533  // first determine row lengths for each row. if the matrix is quadratic,
1534  // then we might have to add an additional entry for the diagonal, if that
1535  // is not yet present. as we have to call compress anyway later on, don't
1536  // bother to check whether that diagonal entry is in a certain row or not
1537  const bool is_square = (n_rows == n_cols);
1538  std::vector<unsigned int> row_lengths;
1539  row_lengths.reserve(n_rows);
1540  for (ForwardIterator i=begin; i!=end; ++i)
1541  row_lengths.push_back (std::distance (i->begin(), i->end())
1542  +
1543  (is_square ? 1 : 0));
1544  reinit (n_rows, n_cols, row_lengths);
1545 
1546  // now enter all the elements into the matrix. note that if the matrix is
1547  // quadratic, then we already have the diagonal element preallocated
1548  //
1549  // for use in the inner loop, we define a typedef to the type of the inner
1550  // iterators
1551  size_type row = 0;
1552  typedef typename std::iterator_traits<ForwardIterator>::value_type::const_iterator inner_iterator;
1553  for (ForwardIterator i=begin; i!=end; ++i, ++row)
1554  {
1555  size_type *cols = &colnums[rowstart[row]] + (is_square ? 1 : 0);
1556  const inner_iterator end_of_row = i->end();
1557  for (inner_iterator j=i->begin(); j!=end_of_row; ++j)
1558  {
1559  const size_type col
1560  = internal::SparsityPatternTools::get_column_index_from_iterator(*j);
1561  Assert (col < n_cols, ExcIndexRange(col,0,n_cols));
1562 
1563  if ((col!=row) || !is_square)
1564  *cols++ = col;
1565  }
1566  }
1567 
1568  // finally compress everything. this also sorts the entries within each row
1569  compress ();
1570 }
1571 
1572 
1573 #endif // DOXYGEN
1574 
1575 DEAL_II_NAMESPACE_CLOSE
1576 
1577 #endif
void block_write(std::ostream &out) const
const types::global_dof_index invalid_size_type
Definition: types.h:179
SparsityPatternIterators::Iterator iterator
void add_entries(const size_type row, ForwardIterator begin, ForwardIterator end, const bool indices_are_sorted=false)
static ::ExceptionBase & ExcMatrixIsCompressed()
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:576
std::size_t n_nonzero_elements() const
bool operator==(const Accessor &) const
size_type operator()(const size_type i, const size_type j) const
types::global_dof_index size_type
static const size_type invalid_entry
static ::ExceptionBase & ExcInvalidNumberOfPartitions(int arg1)
bool operator!=(const Iterator &) const
std::size_t memory_consumption() const
std::pair< size_type, size_type > matrix_position(const std::size_t global_index) const
void print_gnuplot(std::ostream &out) const
iterator end() const
STL namespace.
bool exists(const size_type i, const size_type j) const
bool empty() const
bool operator<(const Accessor &) const
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
size_type n_cols() const
bool is_compressed() const
bool operator<(const Iterator &) const
std::size_t max_vec_len
size_type n_rows() const
size_type bandwidth() const
static ::ExceptionBase & ExcInvalidIterator()
static ::ExceptionBase & ExcNotCompressed()
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:564
void add(const size_type i, const size_type j)
int operator-(const Iterator &p) const
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:313
void print_svg(std::ostream &out) const
size_type column_number(const size_type row, const unsigned int index) const
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:553
void print(std::ostream &out) const
SparsityPattern & operator=(const SparsityPattern &)
size_type max_entries_per_row() const
void load(Archive &ar, const unsigned int version)
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end)
bool operator==(const Iterator &) const
const Accessor & operator*() const
SparsityPatternIterators::Iterator const_iterator
static ::ExceptionBase & ExcIteratorPastEnd()
void reinit(const size_type m, const size_type n, const unsigned int max_per_row)
std::size_t * rowstart
unsigned int max_row_length
types::global_dof_index size_type
static ::ExceptionBase & ExcNotEnoughSpace(int arg1, int arg2)
bool operator==(const SparsityPattern &) const
bool stores_only_added_elements() const
const SparsityPattern * sparsity_pattern
static ::ExceptionBase & ExcEmptyObject()
Iterator(const SparsityPattern *sp, const std::size_t index_within_sparsity)
void block_read(std::istream &in)
Accessor(const SparsityPattern *matrix, const std::size_t index_within_sparsity)
static ::ExceptionBase & ExcIteratorRange(int arg1, int arg2)
iterator begin() const
const Accessor * operator->() const
void save(Archive &ar, const unsigned int version) const
unsigned int row_length(const size_type row) const
size_type row_position(const size_type i, const size_type j) const
static ::ExceptionBase & ExcInternalError()