Reference documentation for deal.II version Git d63a52b21e 2020-07-11 21:58:20 -0400
\(\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 
859 {
860 public:
865 
871 
880 
887 
894  // @{
900  SparsityPattern();
901 
918 
926  SparsityPattern(const size_type m,
927  const size_type n,
928  const unsigned int max_per_row);
929 
930 
939  SparsityPattern(const size_type m,
940  const size_type n,
941  const std::vector<unsigned int> &row_lengths);
942 
951  SparsityPattern(const size_type m, const unsigned int max_per_row);
952 
960  SparsityPattern(const size_type m,
961  const std::vector<unsigned int> &row_lengths);
962 
985  SparsityPattern(const SparsityPattern &original,
986  const unsigned int max_per_row,
987  const size_type extra_off_diagonals);
988 
992  ~SparsityPattern() override = default;
993 
1000  operator=(const SparsityPattern &);
1001 
1007  virtual void
1008  reinit(const size_type m,
1009  const size_type n,
1010  const ArrayView<const unsigned int> &row_lengths) override;
1011 
1024  void
1025  compress();
1026 
1027 
1104  template <typename ForwardIterator>
1105  void
1106  copy_from(const size_type n_rows,
1107  const size_type n_cols,
1108  const ForwardIterator begin,
1109  const ForwardIterator end);
1110 
1115  void
1116  copy_from(const DynamicSparsityPattern &dsp);
1117 
1122  void
1123  copy_from(const SparsityPattern &sp);
1124 
1132  template <typename number>
1133  void
1134  copy_from(const FullMatrix<number> &matrix);
1135 
1142  template <typename ForwardIterator>
1143  void
1144  add_entries(const size_type row,
1145  ForwardIterator begin,
1146  ForwardIterator end,
1147  const bool indices_are_sorted = false);
1148 
1149  // @}
1150 
1151 
1155  // @{
1159  bool
1160  operator==(const SparsityPattern &) const;
1161 
1174  bool
1175  stores_only_added_elements() const;
1176 
1181  std::size_t
1182  memory_consumption() const;
1183 
1184  // @}
1188  // @{
1211  size_type
1212  operator()(const size_type i, const size_type j) const;
1213 
1214  // @}
1218  // @{
1219 
1230  void
1231  block_write(std::ostream &out) const;
1232 
1246  void
1247  block_read(std::istream &in);
1248 
1253  template <class Archive>
1254  void
1255  save(Archive &ar, const unsigned int version) const;
1256 
1261  template <class Archive>
1262  void
1263  load(Archive &ar, const unsigned int version);
1264 
1265 #ifdef DOXYGEN
1266 
1270  template <class Archive>
1271  void
1272  serialize(Archive &archive, const unsigned int version);
1273 #else
1274  // This macro defines the serialize() method that is compatible with
1275  // the templated save() and load() method that have been implemented.
1276  BOOST_SERIALIZATION_SPLIT_MEMBER()
1277 #endif
1278 
1279  // @}
1280 
1288  DeclException2(ExcIteratorRange,
1289  int,
1290  int,
1291  << "The iterators denote a range of " << arg1
1292  << " elements, but the given number of rows was " << arg2);
1297  int,
1298  << "The number of partitions you gave is " << arg1
1299  << ", but must be greater than zero.");
1301 private:
1306 
1307  // Make all sparse matrices friends of this class.
1308  template <typename number>
1309  friend class SparseMatrix;
1310  template <typename number>
1312  template <typename number>
1313  friend class SparseILU;
1314  template <typename number>
1315  friend class ChunkSparseMatrix;
1316 
1317  friend class ChunkSparsityPattern;
1319 
1320  // Also give access to internal details to the iterator/accessor classes.
1324 };
1325 
1326 
1328 /*---------------------- Inline functions -----------------------------------*/
1329 
1330 #ifndef DOXYGEN
1331 
1332 
1333 namespace SparsityPatternIterators
1334 {
1335  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern,
1336  const std::size_t i)
1337  : container(sparsity_pattern)
1338  , linear_index(i)
1339  {}
1340 
1341 
1342 
1343  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern)
1344  : container(sparsity_pattern)
1345  , linear_index(container->rowstart[container->rows])
1346  {}
1347 
1348 
1349 
1350  inline Accessor::Accessor()
1351  : container(nullptr)
1352  , linear_index(numbers::invalid_size_type)
1353  {}
1354 
1355 
1356 
1357  inline bool
1358  Accessor::is_valid_entry() const
1359  {
1360  Assert(container != nullptr, DummyAccessor());
1361  return (linear_index < container->rowstart[container->rows] &&
1362  container->colnums[linear_index] != SparsityPattern::invalid_entry);
1363  }
1364 
1365 
1366 
1367  inline size_type
1368  Accessor::row() const
1369  {
1370  Assert(is_valid_entry() == true, ExcInvalidIterator());
1371 
1372  const std::size_t *insert_point =
1373  std::upper_bound(container->rowstart.get(),
1374  container->rowstart.get() + container->rows + 1,
1375  linear_index);
1376  return insert_point - container->rowstart.get() - 1;
1377  }
1378 
1379 
1380 
1381  inline size_type
1382  Accessor::column() const
1383  {
1384  Assert(is_valid_entry() == true, ExcInvalidIterator());
1385 
1386  return (container->colnums[linear_index]);
1387  }
1388 
1389 
1390 
1391  inline size_type
1392  Accessor::index() const
1393  {
1394  Assert(is_valid_entry() == true, ExcInvalidIterator());
1395 
1396  return linear_index - container->rowstart[row()];
1397  }
1398 
1399 
1400 
1401  inline size_type
1402  Accessor::global_index() const
1403  {
1404  Assert(is_valid_entry() == true, ExcInvalidIterator());
1405 
1406  return linear_index;
1407  }
1408 
1409 
1410 
1411  inline bool
1412  Accessor::operator==(const Accessor &other) const
1413  {
1414  return (container == other.container && linear_index == other.linear_index);
1415  }
1416 
1417 
1418 
1419  inline bool
1420  Accessor::operator<(const Accessor &other) const
1421  {
1422  Assert(container != nullptr, DummyAccessor());
1423  Assert(other.container != nullptr, DummyAccessor());
1424  Assert(container == other.container, ExcInternalError());
1425 
1426  return linear_index < other.linear_index;
1427  }
1428 
1429 
1430 
1431  inline void
1433  {
1434  Assert(container != nullptr, DummyAccessor());
1435  Assert(linear_index < container->rowstart[container->rows],
1436  ExcIteratorPastEnd());
1437  ++linear_index;
1438  }
1439 
1440 
1441  inline Iterator::Iterator(const SparsityPatternBase *sp,
1442  const std::size_t linear_index)
1443  : LinearIndexIterator<Iterator, Accessor>(Accessor(sp, linear_index))
1444  {}
1445 
1446 
1447  inline Iterator::Iterator(const Accessor &accessor)
1448  : LinearIndexIterator<Iterator, Accessor>(accessor)
1449  {}
1450 
1451 
1452 } // namespace SparsityPatternIterators
1453 
1454 
1455 
1458 {
1459  if (n_rows() > 0)
1460  return {this, rowstart[0]};
1461  else
1462  return end();
1463 }
1464 
1465 
1466 
1469 {
1470  if (n_rows() > 0)
1471  return {this, rowstart[rows]};
1472  else
1473  return {nullptr, 0};
1474 }
1475 
1476 
1477 
1480 {
1481  AssertIndexRange(r, n_rows());
1482 
1483  return {this, rowstart[r]};
1484 }
1485 
1486 
1487 
1489 SparsityPatternBase::end(const size_type r) const
1490 {
1491  AssertIndexRange(r, n_rows());
1492 
1493  return {this, rowstart[r + 1]};
1494 }
1495 
1496 
1497 
1500 {
1501  return rows;
1502 }
1503 
1504 
1505 
1508 {
1509  return cols;
1510 }
1511 
1512 
1513 
1514 inline bool
1516 {
1517  return compressed;
1518 }
1519 
1520 
1521 
1522 inline bool
1524 {
1525  return (store_diagonal_first_in_row == false);
1526 }
1527 
1528 
1529 
1530 inline unsigned int
1532 {
1533  AssertIndexRange(row, rows);
1534  return rowstart[row + 1] - rowstart[row];
1535 }
1536 
1537 
1538 
1541  const unsigned int index) const
1542 {
1543  AssertIndexRange(row, rows);
1544  AssertIndexRange(index, row_length(row));
1545 
1546  return colnums[rowstart[row] + index];
1547 }
1548 
1549 
1550 
1551 inline std::size_t
1553 {
1555 
1556  if ((rowstart != nullptr) && (colnums != nullptr))
1557  return rowstart[rows] - rowstart[0];
1558  else
1559  // the object is empty or has zero size
1560  return 0;
1561 }
1562 
1563 
1564 
1565 template <class Archive>
1566 inline void
1567 SparsityPatternBase::save(Archive &ar, const unsigned int) const
1568 {
1569  // forward to serialization function in the base class.
1570  ar &boost::serialization::base_object<const Subscriptor>(*this);
1571 
1573 
1574  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1575  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1576 }
1577 
1578 
1579 
1580 template <class Archive>
1581 inline void
1582 SparsityPatternBase::load(Archive &ar, const unsigned int)
1583 {
1584  // forward to serialization function in the base class.
1585  ar &boost::serialization::base_object<Subscriptor>(*this);
1586 
1588 
1589  rowstart = std::make_unique<std::size_t[]>(max_dim + 1);
1590  colnums = std::make_unique<size_type[]>(max_vec_len);
1591 
1592  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1593  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1594 }
1595 
1596 
1597 
1598 template <class Archive>
1599 inline void
1600 SparsityPattern::save(Archive &ar, const unsigned int) const
1601 {
1602  // forward to serialization function in the base class.
1603  ar &boost::serialization::base_object<const SparsityPatternBase>(*this);
1605 }
1606 
1607 
1608 
1609 template <class Archive>
1610 inline void
1611 SparsityPattern::load(Archive &ar, const unsigned int)
1612 {
1613  // forward to serialization function in the base class.
1614  ar &boost::serialization::base_object<SparsityPatternBase>(*this);
1616 }
1617 
1618 
1619 
1620 inline bool
1622 {
1623  // it isn't quite necessary to compare *all* member variables. by only
1624  // comparing the essential ones, we can say that two sparsity patterns are
1625  // equal even if one is compressed and the other is not (in which case some
1626  // of the member variables are not yet set correctly)
1627  if (rows != sp2.rows || cols != sp2.cols || compressed != sp2.compressed)
1628  return false;
1629 
1630  for (size_type i = 0; i < rows + 1; ++i)
1631  if (rowstart[i] != sp2.rowstart[i])
1632  return false;
1633 
1634  for (size_type i = 0; i < rowstart[rows]; ++i)
1635  if (colnums[i] != sp2.colnums[i])
1636  return false;
1637 
1638  return true;
1639 }
1640 
1641 
1642 
1643 inline bool
1645 {
1646  return (static_cast<const SparsityPatternBase &>(*this) == sp2) &&
1648 }
1649 
1650 
1651 
1652 namespace internal
1653 {
1654  namespace SparsityPatternTools
1655  {
1660 
1661  inline size_type
1663  {
1664  return i;
1665  }
1666 
1667 
1668 
1669  template <typename value>
1670  inline size_type
1671  get_column_index_from_iterator(const std::pair<size_type, value> &i)
1672  {
1673  return i.first;
1674  }
1675 
1676 
1677 
1678  template <typename value>
1679  inline size_type
1680  get_column_index_from_iterator(const std::pair<const size_type, value> &i)
1681  {
1682  return i.first;
1683  }
1684  } // namespace SparsityPatternTools
1685 } // namespace internal
1686 
1687 
1688 
1689 template <typename ForwardIterator>
1690 void
1692  const size_type n_cols,
1693  const ForwardIterator begin,
1694  const ForwardIterator end)
1695 {
1696  Assert(static_cast<size_type>(std::distance(begin, end)) == n_rows,
1697  ExcIteratorRange(std::distance(begin, end), n_rows));
1698 
1699  // first determine row lengths for each row. if the matrix is quadratic,
1700  // then we might have to add an additional entry for the diagonal, if that
1701  // is not yet present. as we have to call compress anyway later on, don't
1702  // bother to check whether that diagonal entry is in a certain row or not
1703  const bool is_square = (n_rows == n_cols);
1704  std::vector<unsigned int> row_lengths;
1705  row_lengths.reserve(n_rows);
1706  for (ForwardIterator i = begin; i != end; ++i)
1707  row_lengths.push_back(std::distance(i->begin(), i->end()) +
1708  (is_square ? 1 : 0));
1709  reinit(n_rows, n_cols, row_lengths);
1710 
1711  // now enter all the elements into the matrix. note that if the matrix is
1712  // quadratic, then we already have the diagonal element preallocated
1713  //
1714  // for use in the inner loop, we define an alias to the type of the inner
1715  // iterators
1716  size_type row = 0;
1717  using inner_iterator =
1718  typename std::iterator_traits<ForwardIterator>::value_type::const_iterator;
1719  for (ForwardIterator i = begin; i != end; ++i, ++row)
1720  {
1721  size_type * cols = &colnums[rowstart[row]] + (is_square ? 1 : 0);
1722  const inner_iterator end_of_row = i->end();
1723  for (inner_iterator j = i->begin(); j != end_of_row; ++j)
1724  {
1725  const size_type col =
1727  AssertIndexRange(col, n_cols);
1728 
1729  if ((col != row) || !is_square)
1730  *cols++ = col;
1731  }
1732  }
1733 
1734  // finally compress everything. this also sorts the entries within each row
1735  compress();
1736 }
1737 
1738 
1739 #endif // DOXYGEN
1740 
1742 
1743 #endif
const types::global_dof_index invalid_size_type
Definition: types.h:200
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:1628
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:1403
#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