Reference documentation for deal.II version Git 040c6ad7d4 2020-09-26 18:01:03 +0200
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
sparsity_pattern.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2020 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.md at
12 // the top level directory of deal.II.
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 
26 
27 // boost::serialization::make_array used to be in array.hpp, but was
28 // moved to a different file in BOOST 1.64
29 #include <boost/version.hpp>
30 #if BOOST_VERSION >= 106400
31 # include <boost/serialization/array_wrapper.hpp>
32 #else
33 # include <boost/serialization/array.hpp>
34 #endif
35 #include <boost/serialization/split_member.hpp>
36 
37 #include <algorithm>
38 #include <iostream>
39 #include <memory>
40 #include <vector>
41 
43 
44 // Forward declarations
45 #ifndef DOXYGEN
46 class SparsityPattern;
50 template <typename number>
51 class FullMatrix;
52 template <typename number>
53 class SparseMatrix;
54 template <typename number>
56 template <typename number>
57 class SparseILU;
58 
60 {
61  class Accessor;
62 }
63 #endif
64 
69 namespace internals
70 {
71  namespace SparsityPatternTools
72  {
77 
83  size_type
85 
91  template <typename value>
92  size_type
93  get_column_index_from_iterator(const std::pair<size_type, value> &i);
94 
100  template <typename value>
101  size_type
102  get_column_index_from_iterator(const std::pair<const size_type, value> &i);
103 
104  } // namespace SparsityPatternTools
105 } // namespace internals
106 
107 
112 {
113  // forward declaration
114  class Iterator;
115 
120 
131  class Accessor
132  {
133  public:
138 
142  Accessor(const SparsityPatternBase *matrix, const std::size_t linear_index);
143 
148 
154  Accessor();
155 
160  size_type
161  row() const;
162 
168  size_type
169  index() const;
170 
180  size_type
181  global_index() const;
182 
187  size_type
188  column() const;
189 
199  bool
200  is_valid_entry() const;
201 
205  bool
206  operator==(const Accessor &) const;
207 
215  bool
216  operator<(const Accessor &) const;
217 
218  protected:
219  DeclExceptionMsg(DummyAccessor,
220  "The instance of this class was initialized"
221  " without SparsityPattern object, which"
222  " means that it is a dummy accessor that can"
223  " not do any operations.");
224 
229 
237  std::size_t linear_index;
238 
242  void
243  advance();
244 
245  // Grant access to iterator class.
247 
248  // Grant access to accessor class of ChunkSparsityPattern.
250  };
251 
252 
253 
278  class Iterator : public LinearIndexIterator<Iterator, Accessor>
279  {
280  public:
285 
290 
296  Iterator(const SparsityPatternBase *sp, const std::size_t linear_index);
297 
302  Iterator(const Accessor &accessor);
303  };
304 } // namespace SparsityPatternIterators
305 
306 
307 
325 {
326 public:
331 
337 
346 
361  static const size_type invalid_entry = numbers::invalid_size_type;
362 
369  // @{
376 
380  ~SparsityPatternBase() override = default;
381 
390  void
391  reinit(const size_type m, const size_type n, const unsigned int max_per_row);
392 
403  void
404  reinit(const size_type m,
405  const size_type n,
406  const std::vector<unsigned int> &row_lengths);
407 
413  virtual void
414  reinit(const size_type m,
415  const size_type n,
416  const ArrayView<const unsigned int> &row_lengths) = 0;
417 
425  void
426  symmetrize();
427 
434  void
435  add(const size_type i, const size_type j);
436 
437  // @}
438 
442  // @{
443 
452  iterator
453  begin() const;
454 
458  iterator
459  end() const;
460 
472  iterator
473  begin(const size_type r) const;
474 
483  iterator
484  end(const size_type r) const;
485 
486 
487  // @}
488 
492  // @{
493 
497  bool
498  operator==(const SparsityPatternBase &) const;
499 
504  bool
505  empty() const;
506 
510  bool
511  exists(const size_type i, const size_type j) const;
512 
518  size_type
519  max_entries_per_row() const;
520 
530  size_type
531  bandwidth() const;
532 
541  std::size_t
542  n_nonzero_elements() const;
543 
547  bool
548  is_compressed() const;
549 
554  size_type
555  n_rows() const;
556 
561  size_type
562  n_cols() const;
563 
567  unsigned int
568  row_length(const size_type row) const;
569 
574  std::size_t
575  memory_consumption() const;
576 
577  // @}
578 
582  // @{
583 
594  size_type
595  column_number(const size_type row, const unsigned int index) const;
596 
604  size_type
605  row_position(const size_type i, const size_type j) const;
606 
618  std::pair<size_type, size_type>
619  matrix_position(const std::size_t global_index) const;
620 
621  // @}
622 
626  // @{
627 
633  void
634  print(std::ostream &out) const;
635 
649  void
650  print_gnuplot(std::ostream &out) const;
651 
659  void
660  print_svg(std::ostream &out) const;
661 
666  template <class Archive>
667  void
668  save(Archive &ar, const unsigned int version) const;
669 
674  template <class Archive>
675  void
676  load(Archive &ar, const unsigned int version);
677 
678 #ifdef DOXYGEN
679 
683  template <class Archive>
684  void
685  serialize(Archive &archive, const unsigned int version);
686 #else
687  // This macro defines the serialize() method that is compatible with
688  // the templated save() and load() method that have been implemented.
689  BOOST_SERIALIZATION_SPLIT_MEMBER()
690 #endif
691 
692  // @}
693 
704  ExcNotCompressed,
705  "The operation you attempted is only allowed after the SparsityPattern "
706  "has been set up and compress() was called.");
707 
711  DeclException2(ExcNotEnoughSpace,
712  int,
713  int,
714  << "Upon entering a new entry to row " << arg1
715  << ": there was no free entry any more. " << std::endl
716  << "(Maximum number of entries for this row: " << arg2
717  << "; maybe the matrix is already compressed?)");
718 
724  ExcMatrixIsCompressed,
725  "The operation you attempted changes the structure of the SparsityPattern "
726  "and is not possible after compress() has been called.");
727 
728  // @}
729 
730 
731 protected:
740 
745 
750 
756  std::size_t max_vec_len;
757 
765  unsigned int max_row_length;
766 
780  std::unique_ptr<std::size_t[]> rowstart;
781 
804  std::unique_ptr<size_type[]> colnums;
805 
810 
811  // Make all sparse matrices friends of this class.
812  template <typename number>
813  friend class SparseMatrix;
814  template <typename number>
815  friend class SparseLUDecomposition;
816  template <typename number>
817  friend class SparseILU;
818  template <typename number>
819  friend class ChunkSparseMatrix;
820 
821  friend class ChunkSparsityPattern;
823 
824  // Also give access to internal details to the iterator/accessor classes.
828 };
829 
866 {
867 public:
872 
878 
887 
894 
901  // @{
907  SparsityPattern();
908 
925 
933  SparsityPattern(const size_type m,
934  const size_type n,
935  const unsigned int max_per_row);
936 
937 
946  SparsityPattern(const size_type m,
947  const size_type n,
948  const std::vector<unsigned int> &row_lengths);
949 
958  SparsityPattern(const size_type m, const unsigned int max_per_row);
959 
967  SparsityPattern(const size_type m,
968  const std::vector<unsigned int> &row_lengths);
969 
992  SparsityPattern(const SparsityPattern &original,
993  const unsigned int max_per_row,
994  const size_type extra_off_diagonals);
995 
999  ~SparsityPattern() override = default;
1000 
1006  SparsityPattern &
1007  operator=(const SparsityPattern &);
1008 
1014  virtual void
1015  reinit(const size_type m,
1016  const size_type n,
1017  const ArrayView<const unsigned int> &row_lengths) override;
1018 
1031  void
1032  compress();
1033 
1034 
1111  template <typename ForwardIterator>
1112  void
1113  copy_from(const size_type n_rows,
1114  const size_type n_cols,
1115  const ForwardIterator begin,
1116  const ForwardIterator end);
1117 
1122  void
1123  copy_from(const DynamicSparsityPattern &dsp);
1124 
1129  void
1130  copy_from(const SparsityPattern &sp);
1131 
1139  template <typename number>
1140  void
1141  copy_from(const FullMatrix<number> &matrix);
1142 
1149  template <typename ForwardIterator>
1150  void
1151  add_entries(const size_type row,
1152  ForwardIterator begin,
1153  ForwardIterator end,
1154  const bool indices_are_sorted = false);
1155 
1156  // @}
1157 
1158 
1162  // @{
1166  bool
1167  operator==(const SparsityPattern &) const;
1168 
1181  bool
1182  stores_only_added_elements() const;
1183 
1188  std::size_t
1189  memory_consumption() const;
1190 
1191  // @}
1195  // @{
1218  size_type
1219  operator()(const size_type i, const size_type j) const;
1220 
1221  // @}
1225  // @{
1226 
1237  void
1238  block_write(std::ostream &out) const;
1239 
1253  void
1254  block_read(std::istream &in);
1255 
1260  template <class Archive>
1261  void
1262  save(Archive &ar, const unsigned int version) const;
1263 
1268  template <class Archive>
1269  void
1270  load(Archive &ar, const unsigned int version);
1271 
1272 #ifdef DOXYGEN
1273 
1277  template <class Archive>
1278  void
1279  serialize(Archive &archive, const unsigned int version);
1280 #else
1281  // This macro defines the serialize() method that is compatible with
1282  // the templated save() and load() method that have been implemented.
1283  BOOST_SERIALIZATION_SPLIT_MEMBER()
1284 #endif
1285 
1286  // @}
1287 
1295  DeclException2(ExcIteratorRange,
1296  int,
1297  int,
1298  << "The iterators denote a range of " << arg1
1299  << " elements, but the given number of rows was " << arg2);
1304  int,
1305  << "The number of partitions you gave is " << arg1
1306  << ", but must be greater than zero.");
1308 private:
1313 
1314  // Make all sparse matrices friends of this class.
1315  template <typename number>
1316  friend class SparseMatrix;
1317  template <typename number>
1319  template <typename number>
1320  friend class SparseILU;
1321  template <typename number>
1322  friend class ChunkSparseMatrix;
1323 
1324  friend class ChunkSparsityPattern;
1326 
1327  // Also give access to internal details to the iterator/accessor classes.
1331 };
1332 
1333 
1335 /*---------------------- Inline functions -----------------------------------*/
1336 
1337 #ifndef DOXYGEN
1338 
1339 
1340 namespace SparsityPatternIterators
1341 {
1342  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern,
1343  const std::size_t i)
1344  : container(sparsity_pattern)
1345  , linear_index(i)
1346  {}
1347 
1348 
1349 
1350  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern)
1351  : container(sparsity_pattern)
1352  , linear_index(container->rowstart[container->rows])
1353  {}
1354 
1355 
1356 
1357  inline Accessor::Accessor()
1358  : container(nullptr)
1359  , linear_index(numbers::invalid_size_type)
1360  {}
1361 
1362 
1363 
1364  inline bool
1365  Accessor::is_valid_entry() const
1366  {
1367  Assert(container != nullptr, DummyAccessor());
1368  return (linear_index < container->rowstart[container->rows] &&
1369  container->colnums[linear_index] != SparsityPattern::invalid_entry);
1370  }
1371 
1372 
1373 
1374  inline size_type
1375  Accessor::row() const
1376  {
1377  Assert(is_valid_entry() == true, ExcInvalidIterator());
1378 
1379  const std::size_t *insert_point =
1380  std::upper_bound(container->rowstart.get(),
1381  container->rowstart.get() + container->rows + 1,
1382  linear_index);
1383  return insert_point - container->rowstart.get() - 1;
1384  }
1385 
1386 
1387 
1388  inline size_type
1389  Accessor::column() const
1390  {
1391  Assert(is_valid_entry() == true, ExcInvalidIterator());
1392 
1393  return (container->colnums[linear_index]);
1394  }
1395 
1396 
1397 
1398  inline size_type
1399  Accessor::index() const
1400  {
1401  Assert(is_valid_entry() == true, ExcInvalidIterator());
1402 
1403  return linear_index - container->rowstart[row()];
1404  }
1405 
1406 
1407 
1408  inline size_type
1409  Accessor::global_index() const
1410  {
1411  Assert(is_valid_entry() == true, ExcInvalidIterator());
1412 
1413  return linear_index;
1414  }
1415 
1416 
1417 
1418  inline bool
1419  Accessor::operator==(const Accessor &other) const
1420  {
1421  return (container == other.container && linear_index == other.linear_index);
1422  }
1423 
1424 
1425 
1426  inline bool
1427  Accessor::operator<(const Accessor &other) const
1428  {
1429  Assert(container != nullptr, DummyAccessor());
1430  Assert(other.container != nullptr, DummyAccessor());
1431  Assert(container == other.container, ExcInternalError());
1432 
1433  return linear_index < other.linear_index;
1434  }
1435 
1436 
1437 
1438  inline void
1440  {
1441  Assert(container != nullptr, DummyAccessor());
1442  Assert(linear_index < container->rowstart[container->rows],
1443  ExcIteratorPastEnd());
1444  ++linear_index;
1445  }
1446 
1447 
1448  inline Iterator::Iterator(const SparsityPatternBase *sp,
1449  const std::size_t linear_index)
1450  : LinearIndexIterator<Iterator, Accessor>(Accessor(sp, linear_index))
1451  {}
1452 
1453 
1454  inline Iterator::Iterator(const Accessor &accessor)
1455  : LinearIndexIterator<Iterator, Accessor>(accessor)
1456  {}
1457 
1458 
1459 } // namespace SparsityPatternIterators
1460 
1461 
1462 
1465 {
1466  if (n_rows() > 0)
1467  return {this, rowstart[0]};
1468  else
1469  return end();
1470 }
1471 
1472 
1473 
1476 {
1477  if (n_rows() > 0)
1478  return {this, rowstart[rows]};
1479  else
1480  return {nullptr, 0};
1481 }
1482 
1483 
1484 
1487 {
1488  AssertIndexRange(r, n_rows());
1489 
1490  return {this, rowstart[r]};
1491 }
1492 
1493 
1494 
1496 SparsityPatternBase::end(const size_type r) const
1497 {
1498  AssertIndexRange(r, n_rows());
1499 
1500  return {this, rowstart[r + 1]};
1501 }
1502 
1503 
1504 
1507 {
1508  return rows;
1509 }
1510 
1511 
1512 
1515 {
1516  return cols;
1517 }
1518 
1519 
1520 
1521 inline bool
1523 {
1524  return compressed;
1525 }
1526 
1527 
1528 
1529 inline bool
1531 {
1532  return (store_diagonal_first_in_row == false);
1533 }
1534 
1535 
1536 
1537 inline unsigned int
1539 {
1540  AssertIndexRange(row, rows);
1541  return rowstart[row + 1] - rowstart[row];
1542 }
1543 
1544 
1545 
1548  const unsigned int index) const
1549 {
1550  AssertIndexRange(row, rows);
1551  AssertIndexRange(index, row_length(row));
1552 
1553  return colnums[rowstart[row] + index];
1554 }
1555 
1556 
1557 
1558 inline std::size_t
1560 {
1562 
1563  if ((rowstart != nullptr) && (colnums != nullptr))
1564  return rowstart[rows] - rowstart[0];
1565  else
1566  // the object is empty or has zero size
1567  return 0;
1568 }
1569 
1570 
1571 
1572 template <class Archive>
1573 inline void
1574 SparsityPatternBase::save(Archive &ar, const unsigned int) const
1575 {
1576  // forward to serialization function in the base class.
1577  ar &boost::serialization::base_object<const Subscriptor>(*this);
1578 
1580 
1581  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1582  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1583 }
1584 
1585 
1586 
1587 template <class Archive>
1588 inline void
1589 SparsityPatternBase::load(Archive &ar, const unsigned int)
1590 {
1591  // forward to serialization function in the base class.
1592  ar &boost::serialization::base_object<Subscriptor>(*this);
1593 
1595 
1596  rowstart = std::make_unique<std::size_t[]>(max_dim + 1);
1597  colnums = std::make_unique<size_type[]>(max_vec_len);
1598 
1599  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1600  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1601 }
1602 
1603 
1604 
1605 template <class Archive>
1606 inline void
1607 SparsityPattern::save(Archive &ar, const unsigned int) const
1608 {
1609  // forward to serialization function in the base class.
1610  ar &boost::serialization::base_object<const SparsityPatternBase>(*this);
1612 }
1613 
1614 
1615 
1616 template <class Archive>
1617 inline void
1618 SparsityPattern::load(Archive &ar, const unsigned int)
1619 {
1620  // forward to serialization function in the base class.
1621  ar &boost::serialization::base_object<SparsityPatternBase>(*this);
1623 }
1624 
1625 
1626 
1627 inline bool
1629 {
1630  // it isn't quite necessary to compare *all* member variables. by only
1631  // comparing the essential ones, we can say that two sparsity patterns are
1632  // equal even if one is compressed and the other is not (in which case some
1633  // of the member variables are not yet set correctly)
1634  if (rows != sp2.rows || cols != sp2.cols || compressed != sp2.compressed)
1635  return false;
1636 
1637  for (size_type i = 0; i < rows + 1; ++i)
1638  if (rowstart[i] != sp2.rowstart[i])
1639  return false;
1640 
1641  for (size_type i = 0; i < rowstart[rows]; ++i)
1642  if (colnums[i] != sp2.colnums[i])
1643  return false;
1644 
1645  return true;
1646 }
1647 
1648 
1649 
1650 inline bool
1652 {
1653  return (static_cast<const SparsityPatternBase &>(*this) == sp2) &&
1655 }
1656 
1657 
1658 
1659 namespace internal
1660 {
1661  namespace SparsityPatternTools
1662  {
1667 
1668  inline size_type
1670  {
1671  return i;
1672  }
1673 
1674 
1675 
1676  template <typename value>
1677  inline size_type
1678  get_column_index_from_iterator(const std::pair<size_type, value> &i)
1679  {
1680  return i.first;
1681  }
1682 
1683 
1684 
1685  template <typename value>
1686  inline size_type
1687  get_column_index_from_iterator(const std::pair<const size_type, value> &i)
1688  {
1689  return i.first;
1690  }
1691  } // namespace SparsityPatternTools
1692 } // namespace internal
1693 
1694 
1695 
1696 template <typename ForwardIterator>
1697 void
1699  const size_type n_cols,
1700  const ForwardIterator begin,
1701  const ForwardIterator end)
1702 {
1703  Assert(static_cast<size_type>(std::distance(begin, end)) == n_rows,
1704  ExcIteratorRange(std::distance(begin, end), n_rows));
1705 
1706  // first determine row lengths for each row. if the matrix is quadratic,
1707  // then we might have to add an additional entry for the diagonal, if that
1708  // is not yet present. as we have to call compress anyway later on, don't
1709  // bother to check whether that diagonal entry is in a certain row or not
1710  const bool is_square = (n_rows == n_cols);
1711  std::vector<unsigned int> row_lengths;
1712  row_lengths.reserve(n_rows);
1713  for (ForwardIterator i = begin; i != end; ++i)
1714  row_lengths.push_back(std::distance(i->begin(), i->end()) +
1715  (is_square ? 1 : 0));
1716  reinit(n_rows, n_cols, row_lengths);
1717 
1718  // now enter all the elements into the matrix. note that if the matrix is
1719  // quadratic, then we already have the diagonal element preallocated
1720  //
1721  // for use in the inner loop, we define an alias to the type of the inner
1722  // iterators
1723  size_type row = 0;
1724  using inner_iterator =
1725  typename std::iterator_traits<ForwardIterator>::value_type::const_iterator;
1726  for (ForwardIterator i = begin; i != end; ++i, ++row)
1727  {
1728  size_type * cols = &colnums[rowstart[row]] + (is_square ? 1 : 0);
1729  const inner_iterator end_of_row = i->end();
1730  for (inner_iterator j = i->begin(); j != end_of_row; ++j)
1731  {
1732  const size_type col =
1734  AssertIndexRange(col, n_cols);
1735 
1736  if ((col != row) || !is_square)
1737  *cols++ = col;
1738  }
1739  }
1740 
1741  // finally compress everything. this also sorts the entries within each row
1742  compress();
1743 }
1744 
1745 
1746 #endif // DOXYGEN
1747 
1749 
1750 #endif
const types::global_dof_index invalid_size_type
Definition: types.h:205
iterator end() const
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
Definition: matrix_block.h:618
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:538
unsigned int max_row_length
iterator begin() const
Contents is actually a matrix.
constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
void load(Archive &ar, const unsigned int version)
#define AssertIndexRange(index, range)
Definition: exceptions.h:1636
types::global_dof_index size_type
bool operator<(const SynchronousIterators< Iterators > &a, const SynchronousIterators< Iterators > &b)
bool operator==(const SparsityPatternBase &) const
bool operator==(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
void reinit(const size_type m, const size_type n, const unsigned int max_per_row)
types::global_dof_index size_type
std::unique_ptr< std::size_t[]> rowstart
static ::ExceptionBase & ExcNotCompressed()
static ::ExceptionBase & ExcInvalidIterator()
static ::ExceptionBase & ExcInvalidNumberOfPartitions(int arg1)
virtual void reinit(const size_type m, const size_type n, const ArrayView< const unsigned int > &row_lengths) override
std::string compress(const std::string &input)
Definition: utilities.cc:392
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:515
Accessor(const ChunkSparsityPattern *matrix, const size_type row)
#define Assert(cond, exc)
Definition: exceptions.h:1411
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:493
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:363
VectorType::value_type * end(VectorType &V)
SparsityPatternIterators::Iterator const_iterator
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)
std::size_t n_nonzero_elements() const
static ::ExceptionBase & ExcIteratorPastEnd()
std::unique_ptr< size_type[]> colnums
unsigned int global_dof_index
Definition: types.h:76
void advance(std::tuple< I1, I2 > &t, const unsigned int n)
bool is_compressed() const
bool operator==(const SparsityPattern &) const
bool stores_only_added_elements() const
void save(Archive &ar, const unsigned int version) const
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:362
VectorType::value_type * begin(VectorType &V)
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
static const size_type invalid_entry
types::global_dof_index size_type
static ::ExceptionBase & ExcIteratorRange(int arg1, int arg2)
size_type column_number(const size_type row, const unsigned int index) const
void save(Archive &ar, const unsigned int version) const
size_type get_column_index_from_iterator(const std::pair< const size_type, value > &i)
unsigned int row_length(const size_type row) const
size_type n_rows() const
const SparsityPatternBase * container
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static ::ExceptionBase & ExcInternalError()
SparsityPatternIterators::Iterator iterator
size_type n_cols() const