Reference documentation for deal.II version Git 5a2787e538 2021-09-21 14:55:10 -0600
\(\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 - 2021 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 
667  template <class Archive>
668  void
669  save(Archive &ar, const unsigned int version) const;
670 
676  template <class Archive>
677  void
678  load(Archive &ar, const unsigned int version);
679 
680 #ifdef DOXYGEN
681 
686  template <class Archive>
687  void
688  serialize(Archive &archive, const unsigned int version);
689 #else
690  // This macro defines the serialize() method that is compatible with
691  // the templated save() and load() method that have been implemented.
692  BOOST_SERIALIZATION_SPLIT_MEMBER()
693 #endif
694 
695  // @}
696 
707  ExcNotCompressed,
708  "The operation you attempted is only allowed after the SparsityPattern "
709  "has been set up and compress() was called.");
710 
714  DeclException2(ExcNotEnoughSpace,
715  int,
716  int,
717  << "Upon entering a new entry to row " << arg1
718  << ": there was no free entry any more. " << std::endl
719  << "(Maximum number of entries for this row: " << arg2
720  << "; maybe the matrix is already compressed?)");
721 
727  ExcMatrixIsCompressed,
728  "The operation you attempted changes the structure of the SparsityPattern "
729  "and is not possible after compress() has been called.");
730 
731  // @}
732 
733 
734 protected:
743 
748 
753 
759  std::size_t max_vec_len;
760 
768  unsigned int max_row_length;
769 
783  std::unique_ptr<std::size_t[]> rowstart;
784 
807  std::unique_ptr<size_type[]> colnums;
808 
813 
814  // Make all sparse matrices friends of this class.
815  template <typename number>
816  friend class SparseMatrix;
817  template <typename number>
818  friend class SparseLUDecomposition;
819  template <typename number>
820  friend class SparseILU;
821  template <typename number>
822  friend class ChunkSparseMatrix;
823 
824  friend class ChunkSparsityPattern;
826 
827  // Also give access to internal details to the iterator/accessor classes.
831 };
832 
869 {
870 public:
875 
881 
890 
897 
904  // @{
910  SparsityPattern();
911 
928 
936  SparsityPattern(const size_type m,
937  const size_type n,
938  const unsigned int max_per_row);
939 
940 
949  SparsityPattern(const size_type m,
950  const size_type n,
951  const std::vector<unsigned int> &row_lengths);
952 
961  SparsityPattern(const size_type m, const unsigned int max_per_row);
962 
970  SparsityPattern(const size_type m,
971  const std::vector<unsigned int> &row_lengths);
972 
995  SparsityPattern(const SparsityPattern &original,
996  const unsigned int max_per_row,
997  const size_type extra_off_diagonals);
998 
1002  ~SparsityPattern() override = default;
1003 
1009  SparsityPattern &
1010  operator=(const SparsityPattern &);
1011 
1017  virtual void
1018  reinit(const size_type m,
1019  const size_type n,
1020  const ArrayView<const unsigned int> &row_lengths) override;
1021 
1034  void
1035  compress();
1036 
1037 
1114  template <typename ForwardIterator>
1115  void
1116  copy_from(const size_type n_rows,
1117  const size_type n_cols,
1118  const ForwardIterator begin,
1119  const ForwardIterator end);
1120 
1125  void
1126  copy_from(const DynamicSparsityPattern &dsp);
1127 
1132  void
1133  copy_from(const SparsityPattern &sp);
1134 
1149  template <typename number>
1150  void
1151  copy_from(const FullMatrix<number> &matrix);
1152 
1159  template <typename ForwardIterator>
1160  void
1161  add_entries(const size_type row,
1162  ForwardIterator begin,
1163  ForwardIterator end,
1164  const bool indices_are_sorted = false);
1165 
1166  // @}
1167 
1168 
1172  // @{
1176  bool
1177  operator==(const SparsityPattern &) const;
1178 
1191  bool
1192  stores_only_added_elements() const;
1193 
1198  std::size_t
1199  memory_consumption() const;
1200 
1201  // @}
1205  // @{
1228  size_type
1229  operator()(const size_type i, const size_type j) const;
1230 
1231  // @}
1235  // @{
1236 
1247  void
1248  block_write(std::ostream &out) const;
1249 
1263  void
1264  block_read(std::istream &in);
1265 
1270  template <class Archive>
1271  void
1272  save(Archive &ar, const unsigned int version) const;
1273 
1278  template <class Archive>
1279  void
1280  load(Archive &ar, const unsigned int version);
1281 
1282 #ifdef DOXYGEN
1283 
1287  template <class Archive>
1288  void
1289  serialize(Archive &archive, const unsigned int version);
1290 #else
1291  // This macro defines the serialize() method that is compatible with
1292  // the templated save() and load() method that have been implemented.
1293  BOOST_SERIALIZATION_SPLIT_MEMBER()
1294 #endif
1295 
1296  // @}
1297 
1305  DeclException2(ExcIteratorRange,
1306  int,
1307  int,
1308  << "The iterators denote a range of " << arg1
1309  << " elements, but the given number of rows was " << arg2);
1314  int,
1315  << "The number of partitions you gave is " << arg1
1316  << ", but must be greater than zero.");
1318 private:
1323 
1324  // Make all sparse matrices friends of this class.
1325  template <typename number>
1326  friend class SparseMatrix;
1327  template <typename number>
1329  template <typename number>
1330  friend class SparseILU;
1331  template <typename number>
1332  friend class ChunkSparseMatrix;
1333 
1334  friend class ChunkSparsityPattern;
1336 
1337  // Also give access to internal details to the iterator/accessor classes.
1341 };
1342 
1343 
1345 /*---------------------- Inline functions -----------------------------------*/
1346 
1347 #ifndef DOXYGEN
1348 
1349 
1350 namespace SparsityPatternIterators
1351 {
1352  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern,
1353  const std::size_t i)
1354  : container(sparsity_pattern)
1355  , linear_index(i)
1356  {}
1357 
1358 
1359 
1360  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern)
1361  : container(sparsity_pattern)
1362  , linear_index(container->rowstart[container->rows])
1363  {}
1364 
1365 
1366 
1367  inline Accessor::Accessor()
1368  : container(nullptr)
1369  , linear_index(numbers::invalid_size_type)
1370  {}
1371 
1372 
1373 
1374  inline bool
1375  Accessor::is_valid_entry() const
1376  {
1377  Assert(container != nullptr, DummyAccessor());
1378  return (linear_index < container->rowstart[container->rows] &&
1379  container->colnums[linear_index] != SparsityPattern::invalid_entry);
1380  }
1381 
1382 
1383 
1384  inline size_type
1385  Accessor::row() const
1386  {
1387  Assert(is_valid_entry() == true, ExcInvalidIterator());
1388 
1389  const std::size_t *insert_point =
1390  std::upper_bound(container->rowstart.get(),
1391  container->rowstart.get() + container->rows + 1,
1392  linear_index);
1393  return insert_point - container->rowstart.get() - 1;
1394  }
1395 
1396 
1397 
1398  inline size_type
1399  Accessor::column() const
1400  {
1401  Assert(is_valid_entry() == true, ExcInvalidIterator());
1402 
1403  return (container->colnums[linear_index]);
1404  }
1405 
1406 
1407 
1408  inline size_type
1409  Accessor::index() const
1410  {
1411  Assert(is_valid_entry() == true, ExcInvalidIterator());
1412 
1413  return linear_index - container->rowstart[row()];
1414  }
1415 
1416 
1417 
1418  inline size_type
1419  Accessor::global_index() const
1420  {
1421  Assert(is_valid_entry() == true, ExcInvalidIterator());
1422 
1423  return linear_index;
1424  }
1425 
1426 
1427 
1428  inline bool
1429  Accessor::operator==(const Accessor &other) const
1430  {
1431  return (container == other.container && linear_index == other.linear_index);
1432  }
1433 
1434 
1435 
1436  inline bool
1437  Accessor::operator<(const Accessor &other) const
1438  {
1439  Assert(container != nullptr, DummyAccessor());
1440  Assert(other.container != nullptr, DummyAccessor());
1441  Assert(container == other.container, ExcInternalError());
1442 
1443  return linear_index < other.linear_index;
1444  }
1445 
1446 
1447 
1448  inline void
1450  {
1451  Assert(container != nullptr, DummyAccessor());
1452  Assert(linear_index < container->rowstart[container->rows],
1453  ExcIteratorPastEnd());
1454  ++linear_index;
1455  }
1456 
1457 
1458  inline Iterator::Iterator(const SparsityPatternBase *sp,
1459  const std::size_t linear_index)
1460  : LinearIndexIterator<Iterator, Accessor>(Accessor(sp, linear_index))
1461  {}
1462 
1463 
1464  inline Iterator::Iterator(const Accessor &accessor)
1465  : LinearIndexIterator<Iterator, Accessor>(accessor)
1466  {}
1467 
1468 
1469 } // namespace SparsityPatternIterators
1470 
1471 
1472 
1475 {
1476  if (n_rows() > 0)
1477  return {this, rowstart[0]};
1478  else
1479  return end();
1480 }
1481 
1482 
1483 
1486 {
1487  if (n_rows() > 0)
1488  return {this, rowstart[rows]};
1489  else
1490  return {nullptr, 0};
1491 }
1492 
1493 
1494 
1497 {
1498  AssertIndexRange(r, n_rows());
1499 
1500  return {this, rowstart[r]};
1501 }
1502 
1503 
1504 
1506 SparsityPatternBase::end(const size_type r) const
1507 {
1508  AssertIndexRange(r, n_rows());
1509 
1510  return {this, rowstart[r + 1]};
1511 }
1512 
1513 
1514 
1517 {
1518  return rows;
1519 }
1520 
1521 
1522 
1525 {
1526  return cols;
1527 }
1528 
1529 
1530 
1531 inline bool
1533 {
1534  return compressed;
1535 }
1536 
1537 
1538 
1539 inline bool
1541 {
1542  return (store_diagonal_first_in_row == false);
1543 }
1544 
1545 
1546 
1547 inline unsigned int
1549 {
1550  AssertIndexRange(row, rows);
1551  return rowstart[row + 1] - rowstart[row];
1552 }
1553 
1554 
1555 
1558  const unsigned int index) const
1559 {
1560  AssertIndexRange(row, rows);
1561  AssertIndexRange(index, row_length(row));
1562 
1563  return colnums[rowstart[row] + index];
1564 }
1565 
1566 
1567 
1568 inline std::size_t
1570 {
1572 
1573  if ((rowstart != nullptr) && (colnums != nullptr))
1574  return rowstart[rows] - rowstart[0];
1575  else
1576  // the object is empty or has zero size
1577  return 0;
1578 }
1579 
1580 
1581 
1582 template <class Archive>
1583 inline void
1584 SparsityPatternBase::save(Archive &ar, const unsigned int) const
1585 {
1586  // forward to serialization function in the base class.
1587  ar &boost::serialization::base_object<const Subscriptor>(*this);
1588 
1590 
1591  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1592  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1593 }
1594 
1595 
1596 
1597 template <class Archive>
1598 inline void
1599 SparsityPatternBase::load(Archive &ar, const unsigned int)
1600 {
1601  // forward to serialization function in the base class.
1602  ar &boost::serialization::base_object<Subscriptor>(*this);
1603 
1605 
1606  rowstart = std::make_unique<std::size_t[]>(max_dim + 1);
1607  colnums = std::make_unique<size_type[]>(max_vec_len);
1608 
1609  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1610  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1611 }
1612 
1613 
1614 
1615 template <class Archive>
1616 inline void
1617 SparsityPattern::save(Archive &ar, const unsigned int) const
1618 {
1619  // forward to serialization function in the base class.
1620  ar &boost::serialization::base_object<const SparsityPatternBase>(*this);
1622 }
1623 
1624 
1625 
1626 template <class Archive>
1627 inline void
1628 SparsityPattern::load(Archive &ar, const unsigned int)
1629 {
1630  // forward to serialization function in the base class.
1631  ar &boost::serialization::base_object<SparsityPatternBase>(*this);
1633 }
1634 
1635 
1636 
1637 inline bool
1639 {
1640  // it isn't quite necessary to compare *all* member variables. by only
1641  // comparing the essential ones, we can say that two sparsity patterns are
1642  // equal even if one is compressed and the other is not (in which case some
1643  // of the member variables are not yet set correctly)
1644  if (rows != sp2.rows || cols != sp2.cols || compressed != sp2.compressed)
1645  return false;
1646 
1647  for (size_type i = 0; i < rows + 1; ++i)
1648  if (rowstart[i] != sp2.rowstart[i])
1649  return false;
1650 
1651  for (size_type i = 0; i < rowstart[rows]; ++i)
1652  if (colnums[i] != sp2.colnums[i])
1653  return false;
1654 
1655  return true;
1656 }
1657 
1658 
1659 
1660 inline bool
1662 {
1663  return (static_cast<const SparsityPatternBase &>(*this) == sp2) &&
1665 }
1666 
1667 
1668 
1669 namespace internal
1670 {
1671  namespace SparsityPatternTools
1672  {
1677 
1678  inline size_type
1680  {
1681  return i;
1682  }
1683 
1684 
1685 
1686  template <typename value>
1687  inline size_type
1688  get_column_index_from_iterator(const std::pair<size_type, value> &i)
1689  {
1690  return i.first;
1691  }
1692 
1693 
1694 
1695  template <typename value>
1696  inline size_type
1697  get_column_index_from_iterator(const std::pair<const size_type, value> &i)
1698  {
1699  return i.first;
1700  }
1701  } // namespace SparsityPatternTools
1702 } // namespace internal
1703 
1704 
1705 
1706 template <typename ForwardIterator>
1707 void
1709  const size_type n_cols,
1710  const ForwardIterator begin,
1711  const ForwardIterator end)
1712 {
1713  Assert(static_cast<size_type>(std::distance(begin, end)) == n_rows,
1714  ExcIteratorRange(std::distance(begin, end), n_rows));
1715 
1716  // first determine row lengths for each row. if the matrix is quadratic,
1717  // then we might have to add an additional entry for the diagonal, if that
1718  // is not yet present. as we have to call compress anyway later on, don't
1719  // bother to check whether that diagonal entry is in a certain row or not
1720  const bool is_square = (n_rows == n_cols);
1721  std::vector<unsigned int> row_lengths;
1722  row_lengths.reserve(n_rows);
1723  for (ForwardIterator i = begin; i != end; ++i)
1724  row_lengths.push_back(std::distance(i->begin(), i->end()) +
1725  (is_square ? 1 : 0));
1726  reinit(n_rows, n_cols, row_lengths);
1727 
1728  // now enter all the elements into the matrix. note that if the matrix is
1729  // quadratic, then we already have the diagonal element preallocated
1730  //
1731  // for use in the inner loop, we define an alias to the type of the inner
1732  // iterators
1733  size_type row = 0;
1734  using inner_iterator =
1735  typename std::iterator_traits<ForwardIterator>::value_type::const_iterator;
1736  for (ForwardIterator i = begin; i != end; ++i, ++row)
1737  {
1738  size_type * cols = &colnums[rowstart[row]] + (is_square ? 1 : 0);
1739  const inner_iterator end_of_row = i->end();
1740  for (inner_iterator j = i->begin(); j != end_of_row; ++j)
1741  {
1742  const size_type col =
1744  AssertIndexRange(col, n_cols);
1745 
1746  if ((col != row) || !is_square)
1747  *cols++ = col;
1748  }
1749  }
1750 
1751  // finally compress everything. this also sorts the entries within each row
1752  compress();
1753 }
1754 
1755 
1756 #endif // DOXYGEN
1757 
1759 
1760 #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:532
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:1718
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:509
Accessor(const ChunkSparsityPattern *matrix, const size_type row)
#define Assert(cond, exc)
Definition: exceptions.h:1461
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:487
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:401
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:400
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