Reference documentation for deal.II version 9.0.0
sparsity_pattern.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 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_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/std_cxx14/memory.h>
23 #include <deal.II/base/subscriptor.h>
24 
25 // boost::serialization::make_array used to be in array.hpp, but was
26 // moved to a different file in BOOST 1.64
27 #include <boost/version.hpp>
28 #if BOOST_VERSION >= 106400
29 # include <boost/serialization/array_wrapper.hpp>
30 #else
31 # include <boost/serialization/array.hpp>
32 #endif
33 #include <boost/serialization/split_member.hpp>
34 
35 #include <vector>
36 #include <iostream>
37 #include <algorithm>
38 
39 DEAL_II_NAMESPACE_OPEN
40 
41 class SparsityPattern;
44 template <typename number> class FullMatrix;
45 template <typename number> class SparseMatrix;
46 template <typename number> class SparseLUDecomposition;
47 template <typename number> class SparseILU;
48 template <typename VectorType> class VectorSlice;
49 
51 {
52  class Accessor;
53 }
54 
55 
60 namespace internals
61 {
62  namespace SparsityPatternTools
63  {
68 
74  size_type
75  get_column_index_from_iterator (const size_type i);
76 
82  template <typename value>
83  size_type
84  get_column_index_from_iterator (const std::pair<size_type, value> &i);
85 
91  template <typename value>
92  size_type
93  get_column_index_from_iterator (const std::pair<const size_type, value> &i);
94 
95  }
96 }
97 
98 
103 {
104  // forward declaration
105  class Iterator;
106 
111 
125  class Accessor
126  {
127  public:
131  Accessor (const SparsityPattern *matrix,
132  const std::size_t index_within_sparsity);
133 
137  Accessor (const SparsityPattern *matrix);
138 
143  size_type row () const;
144 
150  size_type index () const;
151 
156  size_type column () const;
157 
167  bool is_valid_entry () const;
168 
172  bool operator == (const Accessor &) const;
173 
181  bool operator < (const Accessor &) const;
182 
183  protected:
188 
197 
201  void advance ();
202 
206  friend class Iterator;
207 
212  };
213 
214 
215 
240  class Iterator
241  {
242  public:
248  Iterator (const SparsityPattern *sp,
249  const std::size_t index_within_sparsity);
250 
255 
259  Iterator operator++ (int);
260 
264  const Accessor &operator* () const;
265 
269  const Accessor *operator-> () const;
270 
274  bool operator == (const Iterator &) const;
275 
279  bool operator != (const Iterator &) const;
280 
288  bool operator < (const Iterator &) const;
289 
296  int operator - (const Iterator &p) const;
297 
298  private:
303  };
304 }
305 
306 
307 
343 {
344 public:
349 
354  typedef
357 
365  typedef
368 
369 
385 
390 // @{
396  SparsityPattern ();
397 
414 
422  SparsityPattern (const size_type m,
423  const size_type n,
424  const unsigned int max_per_row);
425 
426 
435  SparsityPattern (const size_type m,
436  const size_type n,
437  const std::vector<unsigned int> &row_lengths);
438 
447  SparsityPattern (const size_type m,
448  const unsigned int max_per_row);
449 
457  SparsityPattern (const size_type m,
458  const std::vector<unsigned int> &row_lengths);
459 
482  SparsityPattern (const SparsityPattern &original,
483  const unsigned int max_per_row,
484  const size_type extra_off_diagonals);
485 
489  ~SparsityPattern () = default;
490 
497 
506  void reinit (const size_type m,
507  const size_type n,
508  const unsigned int max_per_row);
509 
510 
525  void reinit (const size_type m,
526  const size_type n,
527  const std::vector<unsigned int> &row_lengths);
528 
529 
533  void reinit (const size_type m,
534  const size_type n,
535  const VectorSlice<const std::vector<unsigned int> > &row_lengths);
536 
549  void compress ();
550 
551 
628  template <typename ForwardIterator>
629  void copy_from (const size_type n_rows,
630  const size_type n_cols,
631  const ForwardIterator begin,
632  const ForwardIterator end);
633 
638  void copy_from (const DynamicSparsityPattern &dsp);
639 
644  void copy_from (const SparsityPattern &sp);
645 
653  template <typename number>
654  void copy_from (const FullMatrix<number> &matrix);
655 
663  void symmetrize ();
664 
671  void add (const size_type i,
672  const size_type j);
673 
680  template <typename ForwardIterator>
681  void add_entries (const size_type row,
682  ForwardIterator begin,
683  ForwardIterator end,
684  const bool indices_are_sorted = false);
685 
686 // @}
687 
688 
689 
690 
694 // @{
695 
704  iterator begin () const;
705 
709  iterator end () const;
710 
722  iterator begin (const size_type r) const;
723 
732  iterator end (const size_type r) const;
733 
734 
735 // @}
739 // @{
743  bool operator == (const SparsityPattern &) const;
744 
749  bool empty () const;
750 
757 
767  size_type bandwidth () const;
768 
777  std::size_t n_nonzero_elements () const;
778 
782  bool is_compressed () const;
783 
788  size_type n_rows () const;
789 
794  size_type n_cols () const;
795 
799  unsigned int row_length (const size_type row) const;
800 
813  bool stores_only_added_elements () const;
814 
819  std::size_t memory_consumption () const;
820 
821 // @}
825 // @{
849  const size_type j) const;
850 
862  std::pair<size_type, size_type>
863  matrix_position (const std::size_t global_index) const;
864 
868  bool exists (const size_type i,
869  const size_type j) const;
870 
879  const size_type j) const;
880 
891  size_type column_number (const size_type row,
892  const unsigned int index) const;
893 
894 
895 // @}
899 // @{
910  void block_write (std::ostream &out) const;
911 
925  void block_read (std::istream &in);
926 
932  void print (std::ostream &out) const;
933 
947  void print_gnuplot (std::ostream &out) const;
948 
956  void print_svg (std::ostream &out) const;
957 
958 
963  template <class Archive>
964  void save (Archive &ar, const unsigned int version) const;
965 
970  template <class Archive>
971  void load (Archive &ar, const unsigned int version);
972 
973  BOOST_SERIALIZATION_SPLIT_MEMBER()
974 
975 // @}
976 
977 
985  int, int,
986  << "Upon entering a new entry to row " << arg1
987  << ": there was no free entry any more. " << std::endl
988  << "(Maximum number of entries for this row: "
989  << arg2 << "; maybe the matrix is already compressed?)");
995  "The operation you attempted is only allowed after the SparsityPattern "
996  "has been set up and compress() was called.");
1002  "The operation you attempted changes the structure of the SparsityPattern "
1003  "and is not possible after compress() has been called.");
1008  int, int,
1009  << "The iterators denote a range of " << arg1
1010  << " elements, but the given number of rows was " << arg2);
1015  int,
1016  << "The number of partitions you gave is " << arg1
1017  << ", but must be greater than zero.");
1019 private:
1028 
1033 
1038 
1044  std::size_t max_vec_len;
1045 
1053  unsigned int max_row_length;
1054 
1068  std::unique_ptr<std::size_t[]> rowstart;
1069 
1092  std::unique_ptr<size_type[]> colnums;
1093 
1098 
1103 
1107  template <typename number> friend class SparseMatrix;
1108  template <typename number> friend class SparseLUDecomposition;
1109  template <typename number> friend class SparseILU;
1110  template <typename number> friend class ChunkSparseMatrix;
1111 
1112  friend class ChunkSparsityPattern;
1113 
1117  friend class SparsityPatternIterators::Iterator;
1118  friend class SparsityPatternIterators::Accessor;
1119  friend class ChunkSparsityPatternIterators::Accessor;
1120 };
1121 
1122 
1124 /*---------------------- Inline functions -----------------------------------*/
1125 
1126 #ifndef DOXYGEN
1127 
1128 
1129 namespace SparsityPatternIterators
1130 {
1131  inline
1132  Accessor::
1133  Accessor (const SparsityPattern *sparsity_pattern,
1134  const std::size_t i)
1135  :
1136  sparsity_pattern(sparsity_pattern),
1137  index_within_sparsity(i)
1138  {}
1139 
1140 
1141  inline
1142  Accessor::
1143  Accessor (const SparsityPattern *sparsity_pattern)
1144  :
1145  sparsity_pattern(sparsity_pattern),
1146  index_within_sparsity(sparsity_pattern->rowstart[sparsity_pattern->rows])
1147  {}
1148 
1149 
1150  inline
1151  bool
1152  Accessor::is_valid_entry () const
1153  {
1154  return (index_within_sparsity < sparsity_pattern->rowstart[sparsity_pattern->rows]
1155  &&
1156  sparsity_pattern->colnums[index_within_sparsity]
1158  }
1159 
1160 
1161  inline
1162  size_type
1163  Accessor::row() const
1164  {
1165  Assert (is_valid_entry() == true, ExcInvalidIterator());
1166 
1167  const std::size_t *insert_point =
1168  std::upper_bound(sparsity_pattern->rowstart.get(),
1169  sparsity_pattern->rowstart.get() + sparsity_pattern->rows + 1,
1170  index_within_sparsity);
1171  return insert_point - sparsity_pattern->rowstart.get() - 1;
1172  }
1173 
1174 
1175  inline
1176  size_type
1177  Accessor::column() const
1178  {
1179  Assert (is_valid_entry() == true, ExcInvalidIterator());
1180 
1181  return (sparsity_pattern->colnums[index_within_sparsity]);
1182  }
1183 
1184 
1185  inline
1186  size_type
1187  Accessor::index() const
1188  {
1189  Assert (is_valid_entry() == true, ExcInvalidIterator());
1190 
1191  return index_within_sparsity - sparsity_pattern->rowstart[row()];
1192  }
1193 
1194 
1195 
1196 
1197  inline
1198  bool
1199  Accessor::operator == (const Accessor &other) const
1200  {
1201  return (sparsity_pattern == other.sparsity_pattern &&
1202  index_within_sparsity == other.index_within_sparsity);
1203  }
1204 
1205 
1206 
1207  inline
1208  bool
1209  Accessor::operator < (const Accessor &other) const
1210  {
1211  Assert (sparsity_pattern == other.sparsity_pattern,
1212  ExcInternalError());
1213 
1214  return index_within_sparsity < other.index_within_sparsity;
1215  }
1216 
1217 
1218  inline
1219  void
1220  Accessor::advance ()
1221  {
1222  Assert (index_within_sparsity < sparsity_pattern->rowstart[sparsity_pattern->rows],
1223  ExcIteratorPastEnd());
1224  ++index_within_sparsity;
1225  }
1226 
1227 
1228 
1229  inline
1230  Iterator::Iterator (const SparsityPattern *sparsity_pattern,
1231  const std::size_t i)
1232  :
1233  accessor(sparsity_pattern, i)
1234  {}
1235 
1236 
1237 
1238  inline
1239  Iterator &
1240  Iterator::operator++ ()
1241  {
1242  accessor.advance ();
1243  return *this;
1244  }
1245 
1246 
1247 
1248  inline
1249  Iterator
1250  Iterator::operator++ (int)
1251  {
1252  const Iterator iter = *this;
1253  accessor.advance ();
1254  return iter;
1255  }
1256 
1257 
1258 
1259  inline
1260  const Accessor &
1261  Iterator::operator* () const
1262  {
1263  return accessor;
1264  }
1265 
1266 
1267 
1268  inline
1269  const Accessor *
1270  Iterator::operator-> () const
1271  {
1272  return &accessor;
1273  }
1274 
1275 
1276  inline
1277  bool
1278  Iterator::operator == (const Iterator &other) const
1279  {
1280  return (accessor == other.accessor);
1281  }
1282 
1283 
1284 
1285  inline
1286  bool
1287  Iterator::operator != (const Iterator &other) const
1288  {
1289  return ! (*this == other);
1290  }
1291 
1292 
1293  inline
1294  bool
1295  Iterator::operator < (const Iterator &other) const
1296  {
1297  return accessor < other.accessor;
1298  }
1299 
1300 
1301  inline
1302  int
1303  Iterator::operator - (const Iterator &other) const
1304  {
1305  Assert (accessor.sparsity_pattern == other.accessor.sparsity_pattern,
1306  ExcInternalError());
1307 
1308  return (*this)->index_within_sparsity - other->index_within_sparsity;
1309  }
1310 }
1311 
1312 
1313 
1314 inline
1316 SparsityPattern::begin () const
1317 {
1318  return iterator(this, rowstart[0]);
1319 }
1320 
1321 
1322 inline
1324 SparsityPattern::end () const
1325 {
1326  return iterator(this, rowstart[rows]);
1327 }
1328 
1329 
1330 
1331 inline
1333 SparsityPattern::begin (const size_type r) const
1334 {
1335  Assert (r<n_rows(), ExcIndexRangeType<size_type>(r,0,n_rows()));
1336 
1337  return iterator(this, rowstart[r]);
1338 }
1339 
1340 
1341 
1342 inline
1344 SparsityPattern::end (const size_type r) const
1345 {
1346  Assert (r<n_rows(), ExcIndexRangeType<size_type>(r,0,n_rows()));
1347 
1348  return iterator(this, rowstart[r+1]);
1349 }
1350 
1351 
1352 
1353 inline
1355 SparsityPattern::n_rows () const
1356 {
1357  return rows;
1358 }
1359 
1360 
1361 inline
1363 SparsityPattern::n_cols () const
1364 {
1365  return cols;
1366 }
1367 
1368 
1369 inline
1370 bool
1372 {
1373  return compressed;
1374 }
1375 
1376 
1377 inline
1378 bool
1380 {
1381  return (store_diagonal_first_in_row == false);
1382 }
1383 
1384 
1385 
1386 inline
1387 unsigned int
1388 SparsityPattern::row_length (const size_type row) const
1389 {
1390  Assert(row<rows, ExcIndexRangeType<size_type>(row,0,rows));
1391  return rowstart[row+1]-rowstart[row];
1392 }
1393 
1394 
1395 
1396 inline
1399  const unsigned int index) const
1400 {
1401  Assert(row<rows, ExcIndexRangeType<size_type>(row,0,rows));
1402  Assert(index<row_length(row), ExcIndexRange(index,0,row_length(row)));
1403 
1404  return colnums[rowstart[row]+index];
1405 }
1406 
1407 
1408 inline
1409 std::size_t
1411 {
1413 
1414  if ((rowstart!=nullptr) && (colnums!=nullptr))
1415  return rowstart[rows]-rowstart[0];
1416  else
1417  // the object is empty or has zero size
1418  return 0;
1419 }
1420 
1421 
1422 
1423 template <class Archive>
1424 inline
1425 void
1426 SparsityPattern::save (Archive &ar, const unsigned int) const
1427 {
1428  // forward to serialization function in the base class.
1429  ar &static_cast<const Subscriptor &>(*this);
1430 
1432 
1433  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1434  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1435 }
1436 
1437 
1438 
1439 template <class Archive>
1440 inline
1441 void
1442 SparsityPattern::load (Archive &ar, const unsigned int)
1443 {
1444  // forward to serialization function in the base class.
1445  ar &static_cast<Subscriptor &>(*this);
1446 
1448 
1449  rowstart = std_cxx14::make_unique<std::size_t[]>(max_dim + 1);
1450  colnums = std_cxx14::make_unique<size_type[]>(max_vec_len);
1451 
1452  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1453  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1454 }
1455 
1456 
1457 
1458 inline
1459 bool
1461 {
1462  // it isn't quite necessary to compare *all* member variables. by only
1463  // comparing the essential ones, we can say that two sparsity patterns are
1464  // equal even if one is compressed and the other is not (in which case some
1465  // of the member variables are not yet set correctly)
1466  if (rows != sp2.rows ||
1467  cols != sp2.cols ||
1468  compressed != sp2.compressed ||
1470  return false;
1471 
1472  for (size_type i = 0; i < rows+1; ++i)
1473  if (rowstart[i] != sp2.rowstart[i])
1474  return false;
1475 
1476  for (size_type i = 0; i < rowstart[rows]; ++i)
1477  if (colnums[i] != sp2.colnums[i])
1478  return false;
1479 
1480  return true;
1481 }
1482 
1483 
1484 
1485 namespace internal
1486 {
1487  namespace SparsityPatternTools
1488  {
1493 
1494  inline
1495  size_type
1496  get_column_index_from_iterator (const size_type i)
1497  {
1498  return i;
1499  }
1500 
1501 
1502 
1503  template <typename value>
1504  inline
1505  size_type
1506  get_column_index_from_iterator (const std::pair<size_type, value> &i)
1507  {
1508  return i.first;
1509  }
1510 
1511 
1512 
1513  template <typename value>
1514  inline
1515  size_type
1516  get_column_index_from_iterator (const std::pair<const size_type, value> &i)
1517  {
1518  return i.first;
1519  }
1520  }
1521 }
1522 
1523 
1524 
1525 template <typename ForwardIterator>
1526 void
1528  const size_type n_cols,
1529  const ForwardIterator begin,
1530  const ForwardIterator end)
1531 {
1532  Assert (static_cast<size_type>(std::distance (begin, end)) == n_rows,
1533  ExcIteratorRange (std::distance (begin, end), n_rows));
1534 
1535  // first determine row lengths for each row. if the matrix is quadratic,
1536  // then we might have to add an additional entry for the diagonal, if that
1537  // is not yet present. as we have to call compress anyway later on, don't
1538  // bother to check whether that diagonal entry is in a certain row or not
1539  const bool is_square = (n_rows == n_cols);
1540  std::vector<unsigned int> row_lengths;
1541  row_lengths.reserve(n_rows);
1542  for (ForwardIterator i=begin; i!=end; ++i)
1543  row_lengths.push_back (std::distance (i->begin(), i->end())
1544  +
1545  (is_square ? 1 : 0));
1546  reinit (n_rows, n_cols, row_lengths);
1547 
1548  // now enter all the elements into the matrix. note that if the matrix is
1549  // quadratic, then we already have the diagonal element preallocated
1550  //
1551  // for use in the inner loop, we define a typedef to the type of the inner
1552  // iterators
1553  size_type row = 0;
1554  typedef typename std::iterator_traits<ForwardIterator>::value_type::const_iterator inner_iterator;
1555  for (ForwardIterator i=begin; i!=end; ++i, ++row)
1556  {
1557  size_type *cols = &colnums[rowstart[row]] + (is_square ? 1 : 0);
1558  const inner_iterator end_of_row = i->end();
1559  for (inner_iterator j=i->begin(); j!=end_of_row; ++j)
1560  {
1561  const size_type col
1562  = internal::SparsityPatternTools::get_column_index_from_iterator(*j);
1563  Assert (col < n_cols, ExcIndexRange(col,0,n_cols));
1564 
1565  if ((col!=row) || !is_square)
1566  *cols++ = col;
1567  }
1568  }
1569 
1570  // finally compress everything. this also sorts the entries within each row
1571  compress ();
1572 }
1573 
1574 
1575 #endif // DOXYGEN
1576 
1577 DEAL_II_NAMESPACE_CLOSE
1578 
1579 #endif
void block_write(std::ostream &out) const
const types::global_dof_index invalid_size_type
Definition: types.h:182
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:358
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)
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
~SparsityPattern()=default
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
std::unique_ptr< size_type[]> colnums
static ::ExceptionBase & ExcInvalidIterator()
static ::ExceptionBase & ExcNotCompressed()
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:346
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:1142
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:335
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)
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
std::unique_ptr< std::size_t[]> rowstart
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
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
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()