Reference documentation for deal.II version Git f982bbb689 2019-09-17 15:49:08 -0400
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
sparsity_pattern.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2019 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 
22 #include <deal.II/base/array_view.h>
23 #include <deal.II/base/exceptions.h>
24 #include <deal.II/base/linear_index_iterator.h>
25 #include <deal.II/base/std_cxx14/memory.h>
26 #include <deal.II/base/subscriptor.h>
27 
28 // boost::serialization::make_array used to be in array.hpp, but was
29 // moved to a different file in BOOST 1.64
30 #include <boost/version.hpp>
31 #if BOOST_VERSION >= 106400
32 # include <boost/serialization/array_wrapper.hpp>
33 #else
34 # include <boost/serialization/array.hpp>
35 #endif
36 #include <boost/serialization/split_member.hpp>
37 
38 #include <algorithm>
39 #include <iostream>
40 #include <vector>
41 
42 DEAL_II_NAMESPACE_OPEN
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  {
76  using size_type = types::global_dof_index;
77 
83  size_type
84  get_column_index_from_iterator(const size_type i);
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 
134  class Accessor
135  {
136  public:
141 
145  Accessor(const SparsityPatternBase *matrix, const std::size_t linear_index);
146 
150  Accessor(const SparsityPatternBase *matrix);
151 
157  Accessor();
158 
163  size_type
164  row() const;
165 
171  size_type
172  index() const;
173 
183  size_type
184  global_index() const;
185 
190  size_type
191  column() const;
192 
202  bool
203  is_valid_entry() const;
204 
208  bool
209  operator==(const Accessor &) const;
210 
218  bool
219  operator<(const Accessor &) const;
220 
221  protected:
222  DeclExceptionMsg(DummyAccessor,
223  "The instance of this class was initialized"
224  " without SparsityPattern object, which"
225  " means that it is a dummy accessor that can"
226  " not do any operations.");
227 
232 
240  std::size_t linear_index;
241 
245  void
246  advance();
247 
248  // Grant access to iterator class.
249  friend class LinearIndexIterator<Iterator, Accessor>;
250 
251  // Grant access to accessor class of ChunkSparsityPattern.
253  };
254 
255 
256 
281  class Iterator : public LinearIndexIterator<Iterator, Accessor>
282  {
283  public:
288 
293 
299  Iterator(const SparsityPatternBase *sp, const std::size_t linear_index);
300 
305  Iterator(const Accessor &accessor);
306  };
307 } // namespace SparsityPatternIterators
308 
309 
310 
330 {
331 public:
336 
342 
351 
366  static const size_type invalid_entry = numbers::invalid_size_type;
367 
374  // @{
381 
385  ~SparsityPatternBase() override = default;
386 
395  void
396  reinit(const size_type m, const size_type n, const unsigned int max_per_row);
397 
408  void
409  reinit(const size_type m,
410  const size_type n,
411  const std::vector<unsigned int> &row_lengths);
412 
418  virtual void
419  reinit(const size_type m,
420  const size_type n,
421  const ArrayView<const unsigned int> &row_lengths) = 0;
422 
430  void
431  symmetrize();
432 
439  void
440  add(const size_type i, const size_type j);
441 
442  // @}
443 
447  // @{
448 
457  iterator
458  begin() const;
459 
463  iterator
464  end() const;
465 
477  iterator
478  begin(const size_type r) const;
479 
488  iterator
489  end(const size_type r) const;
490 
491 
492  // @}
493 
497  // @{
498 
502  bool
503  operator==(const SparsityPatternBase &) const;
504 
509  bool
510  empty() const;
511 
515  bool
516  exists(const size_type i, const size_type j) const;
517 
523  size_type
524  max_entries_per_row() const;
525 
535  size_type
536  bandwidth() const;
537 
546  std::size_t
547  n_nonzero_elements() const;
548 
552  bool
553  is_compressed() const;
554 
559  size_type
560  n_rows() const;
561 
566  size_type
567  n_cols() const;
568 
572  unsigned int
573  row_length(const size_type row) const;
574 
579  std::size_t
580  memory_consumption() const;
581 
582  // @}
583 
587  // @{
588 
599  size_type
600  column_number(const size_type row, const unsigned int index) const;
601 
609  size_type
610  row_position(const size_type i, const size_type j) const;
611 
623  std::pair<size_type, size_type>
624  matrix_position(const std::size_t global_index) const;
625 
626  // @}
627 
631  // @{
632 
638  void
639  print(std::ostream &out) const;
640 
654  void
655  print_gnuplot(std::ostream &out) const;
656 
664  void
665  print_svg(std::ostream &out) const;
666 
671  template <class Archive>
672  void
673  save(Archive &ar, const unsigned int version) const;
674 
679  template <class Archive>
680  void
681  load(Archive &ar, const unsigned int version);
682 
683  BOOST_SERIALIZATION_SPLIT_MEMBER()
684 
685  // @}
686 
687 
697  ExcNotCompressed,
698  "The operation you attempted is only allowed after the SparsityPattern "
699  "has been set up and compress() was called.");
700 
704  DeclException2(ExcNotEnoughSpace,
705  int,
706  int,
707  << "Upon entering a new entry to row " << arg1
708  << ": there was no free entry any more. " << std::endl
709  << "(Maximum number of entries for this row: " << arg2
710  << "; maybe the matrix is already compressed?)");
711 
717  ExcMatrixIsCompressed,
718  "The operation you attempted changes the structure of the SparsityPattern "
719  "and is not possible after compress() has been called.");
720 
721  // @}
722 
723 
724 protected:
732  size_type max_dim;
733 
737  size_type rows;
738 
742  size_type cols;
743 
749  std::size_t max_vec_len;
750 
758  unsigned int max_row_length;
759 
773  std::unique_ptr<std::size_t[]> rowstart;
774 
797  std::unique_ptr<size_type[]> colnums;
798 
802  bool compressed;
803 
804  // Make all sparse matrices friends of this class.
805  template <typename number>
806  friend class SparseMatrix;
807  template <typename number>
808  friend class SparseLUDecomposition;
809  template <typename number>
810  friend class SparseILU;
811  template <typename number>
812  friend class ChunkSparseMatrix;
813 
814  friend class ChunkSparsityPattern;
815  friend class DynamicSparsityPattern;
816 
817  // Also give access to internal details to the iterator/accessor classes.
818  friend class SparsityPatternIterators::Iterator;
819  friend class SparsityPatternIterators::Accessor;
820  friend class ChunkSparsityPatternIterators::Accessor;
821 };
822 
854 {
855 public:
860 
866 
875 
882 
889  // @{
895  SparsityPattern();
896 
913 
921  SparsityPattern(const size_type m,
922  const size_type n,
923  const unsigned int max_per_row);
924 
925 
934  SparsityPattern(const size_type m,
935  const size_type n,
936  const std::vector<unsigned int> &row_lengths);
937 
946  SparsityPattern(const size_type m, const unsigned int max_per_row);
947 
955  SparsityPattern(const size_type m,
956  const std::vector<unsigned int> &row_lengths);
957 
980  SparsityPattern(const SparsityPattern &original,
981  const unsigned int max_per_row,
982  const size_type extra_off_diagonals);
983 
987  ~SparsityPattern() override = default;
988 
995  operator=(const SparsityPattern &);
996 
1002  virtual void
1003  reinit(const size_type m,
1004  const size_type n,
1005  const ArrayView<const unsigned int> &row_lengths) override;
1006 
1019  void
1020  compress();
1021 
1022 
1099  template <typename ForwardIterator>
1100  void
1101  copy_from(const size_type n_rows,
1102  const size_type n_cols,
1103  const ForwardIterator begin,
1104  const ForwardIterator end);
1105 
1110  void
1111  copy_from(const DynamicSparsityPattern &dsp);
1112 
1117  void
1118  copy_from(const SparsityPattern &sp);
1119 
1127  template <typename number>
1128  void
1129  copy_from(const FullMatrix<number> &matrix);
1130 
1137  template <typename ForwardIterator>
1138  void
1139  add_entries(const size_type row,
1140  ForwardIterator begin,
1141  ForwardIterator end,
1142  const bool indices_are_sorted = false);
1143 
1144  // @}
1145 
1146 
1150  // @{
1154  bool
1155  operator==(const SparsityPattern &) const;
1156 
1169  bool
1170  stores_only_added_elements() const;
1171 
1176  std::size_t
1177  memory_consumption() const;
1178 
1179  // @}
1183  // @{
1206  size_type
1207  operator()(const size_type i, const size_type j) const;
1208 
1209  // @}
1213  // @{
1214 
1225  void
1226  block_write(std::ostream &out) const;
1227 
1241  void
1242  block_read(std::istream &in);
1243 
1248  template <class Archive>
1249  void
1250  save(Archive &ar, const unsigned int version) const;
1251 
1256  template <class Archive>
1257  void
1258  load(Archive &ar, const unsigned int version);
1259 
1260  BOOST_SERIALIZATION_SPLIT_MEMBER()
1261 
1262  // @}
1263 
1264 
1271  DeclException2(ExcIteratorRange,
1272  int,
1273  int,
1274  << "The iterators denote a range of " << arg1
1275  << " elements, but the given number of rows was " << arg2);
1280  int,
1281  << "The number of partitions you gave is " << arg1
1282  << ", but must be greater than zero.");
1284 private:
1288  bool store_diagonal_first_in_row;
1289 
1290  // Make all sparse matrices friends of this class.
1291  template <typename number>
1292  friend class SparseMatrix;
1293  template <typename number>
1294  friend class SparseLUDecomposition;
1295  template <typename number>
1296  friend class SparseILU;
1297  template <typename number>
1298  friend class ChunkSparseMatrix;
1299 
1300  friend class ChunkSparsityPattern;
1301  friend class DynamicSparsityPattern;
1302 
1303  // Also give access to internal details to the iterator/accessor classes.
1304  friend class SparsityPatternIterators::Iterator;
1305  friend class SparsityPatternIterators::Accessor;
1306  friend class ChunkSparsityPatternIterators::Accessor;
1307 };
1308 
1309 
1311 /*---------------------- Inline functions -----------------------------------*/
1312 
1313 #ifndef DOXYGEN
1314 
1315 
1316 namespace SparsityPatternIterators
1317 {
1318  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern,
1319  const std::size_t i)
1320  : container(sparsity_pattern)
1321  , linear_index(i)
1322  {}
1323 
1324 
1325 
1326  inline Accessor::Accessor(const SparsityPatternBase *sparsity_pattern)
1327  : container(sparsity_pattern)
1328  , linear_index(container->rowstart[container->rows])
1329  {}
1330 
1331 
1332 
1333  inline Accessor::Accessor()
1334  : container(nullptr)
1335  , linear_index(numbers::invalid_size_type)
1336  {}
1337 
1338 
1339 
1340  inline bool
1341  Accessor::is_valid_entry() const
1342  {
1343  Assert(container != nullptr, DummyAccessor());
1344  return (linear_index < container->rowstart[container->rows] &&
1345  container->colnums[linear_index] != SparsityPattern::invalid_entry);
1346  }
1347 
1348 
1349 
1350  inline size_type
1351  Accessor::row() const
1352  {
1353  Assert(is_valid_entry() == true, ExcInvalidIterator());
1354 
1355  const std::size_t *insert_point =
1356  std::upper_bound(container->rowstart.get(),
1357  container->rowstart.get() + container->rows + 1,
1358  linear_index);
1359  return insert_point - container->rowstart.get() - 1;
1360  }
1361 
1362 
1363 
1364  inline size_type
1365  Accessor::column() const
1366  {
1367  Assert(is_valid_entry() == true, ExcInvalidIterator());
1368 
1369  return (container->colnums[linear_index]);
1370  }
1371 
1372 
1373 
1374  inline size_type
1375  Accessor::index() const
1376  {
1377  Assert(is_valid_entry() == true, ExcInvalidIterator());
1378 
1379  return linear_index - container->rowstart[row()];
1380  }
1381 
1382 
1383 
1384  inline size_type
1385  Accessor::global_index() const
1386  {
1387  Assert(is_valid_entry() == true, ExcInvalidIterator());
1388 
1389  return linear_index;
1390  }
1391 
1392 
1393 
1394  inline bool
1395  Accessor::operator==(const Accessor &other) const
1396  {
1397  Assert(container != nullptr, DummyAccessor());
1398  Assert(other.container != nullptr, DummyAccessor());
1399  return (container == other.container && linear_index == other.linear_index);
1400  }
1401 
1402 
1403 
1404  inline bool
1405  Accessor::operator<(const Accessor &other) const
1406  {
1407  Assert(container != nullptr, DummyAccessor());
1408  Assert(other.container != nullptr, DummyAccessor());
1409  Assert(container == other.container, ExcInternalError());
1410 
1411  return linear_index < other.linear_index;
1412  }
1413 
1414 
1415 
1416  inline void
1418  {
1419  Assert(container != nullptr, DummyAccessor());
1420  Assert(linear_index < container->rowstart[container->rows],
1421  ExcIteratorPastEnd());
1422  ++linear_index;
1423  }
1424 
1425 
1426  inline Iterator::Iterator(const SparsityPatternBase *sp,
1427  const std::size_t linear_index)
1428  : LinearIndexIterator<Iterator, Accessor>(Accessor(sp, linear_index))
1429  {}
1430 
1431 
1432  inline Iterator::Iterator(const Accessor &accessor)
1434  {}
1435 
1436 
1437 } // namespace SparsityPatternIterators
1438 
1439 
1440 
1443 {
1444  if (n_rows() > 0)
1445  return {this, rowstart[0]};
1446  else
1447  return end();
1448 }
1449 
1450 
1451 
1454 {
1455  if (n_rows() > 0)
1456  return {this, rowstart[rows]};
1457  else
1458  return {nullptr, 0};
1459 }
1460 
1461 
1462 
1465 {
1466  Assert(r < n_rows(), ExcIndexRangeType<size_type>(r, 0, n_rows()));
1467 
1468  return {this, rowstart[r]};
1469 }
1470 
1471 
1472 
1474 SparsityPatternBase::end(const size_type r) const
1475 {
1476  Assert(r < n_rows(), ExcIndexRangeType<size_type>(r, 0, n_rows()));
1477 
1478  return {this, rowstart[r + 1]};
1479 }
1480 
1481 
1482 
1485 {
1486  return rows;
1487 }
1488 
1489 
1490 
1493 {
1494  return cols;
1495 }
1496 
1497 
1498 
1499 inline bool
1501 {
1502  return compressed;
1503 }
1504 
1505 
1506 
1507 inline bool
1509 {
1510  return (store_diagonal_first_in_row == false);
1511 }
1512 
1513 
1514 
1515 inline unsigned int
1517 {
1518  Assert(row < rows, ExcIndexRangeType<size_type>(row, 0, rows));
1519  return rowstart[row + 1] - rowstart[row];
1520 }
1521 
1522 
1523 
1526  const unsigned int index) const
1527 {
1528  Assert(row < rows, ExcIndexRangeType<size_type>(row, 0, rows));
1529  Assert(index < row_length(row), ExcIndexRange(index, 0, row_length(row)));
1530 
1531  return colnums[rowstart[row] + index];
1532 }
1533 
1534 
1535 
1536 inline std::size_t
1538 {
1539  Assert(compressed, ExcNotCompressed());
1540 
1541  if ((rowstart != nullptr) && (colnums != nullptr))
1542  return rowstart[rows] - rowstart[0];
1543  else
1544  // the object is empty or has zero size
1545  return 0;
1546 }
1547 
1548 
1549 
1550 template <class Archive>
1551 inline void
1552 SparsityPatternBase::save(Archive &ar, const unsigned int) const
1553 {
1554  // forward to serialization function in the base class.
1555  ar &boost::serialization::base_object<const Subscriptor>(*this);
1556 
1557  ar &max_dim &rows &cols &max_vec_len &max_row_length &compressed;
1558 
1559  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1560  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1561 }
1562 
1563 
1564 
1565 template <class Archive>
1566 inline void
1567 SparsityPatternBase::load(Archive &ar, const unsigned int)
1568 {
1569  // forward to serialization function in the base class.
1570  ar &boost::serialization::base_object<Subscriptor>(*this);
1571 
1572  ar &max_dim &rows &cols &max_vec_len &max_row_length &compressed;
1573 
1574  rowstart = std_cxx14::make_unique<std::size_t[]>(max_dim + 1);
1575  colnums = std_cxx14::make_unique<size_type[]>(max_vec_len);
1576 
1577  ar &boost::serialization::make_array(rowstart.get(), max_dim + 1);
1578  ar &boost::serialization::make_array(colnums.get(), max_vec_len);
1579 }
1580 
1581 
1582 
1583 template <class Archive>
1584 inline void
1585 SparsityPattern::save(Archive &ar, const unsigned int) const
1586 {
1587  // forward to serialization function in the base class.
1588  ar &boost::serialization::base_object<const SparsityPatternBase>(*this);
1589  ar &store_diagonal_first_in_row;
1590 }
1591 
1592 
1593 
1594 template <class Archive>
1595 inline void
1596 SparsityPattern::load(Archive &ar, const unsigned int)
1597 {
1598  // forward to serialization function in the base class.
1599  ar &boost::serialization::base_object<SparsityPatternBase>(*this);
1600  ar &store_diagonal_first_in_row;
1601 }
1602 
1603 
1604 
1605 inline bool
1606 SparsityPatternBase::operator==(const SparsityPatternBase &sp2) const
1607 {
1608  // it isn't quite necessary to compare *all* member variables. by only
1609  // comparing the essential ones, we can say that two sparsity patterns are
1610  // equal even if one is compressed and the other is not (in which case some
1611  // of the member variables are not yet set correctly)
1612  if (rows != sp2.rows || cols != sp2.cols || compressed != sp2.compressed)
1613  return false;
1614 
1615  for (size_type i = 0; i < rows + 1; ++i)
1616  if (rowstart[i] != sp2.rowstart[i])
1617  return false;
1618 
1619  for (size_type i = 0; i < rowstart[rows]; ++i)
1620  if (colnums[i] != sp2.colnums[i])
1621  return false;
1622 
1623  return true;
1624 }
1625 
1626 
1627 
1628 inline bool
1630 {
1631  return (static_cast<const SparsityPatternBase &>(*this) == sp2) &&
1632  (store_diagonal_first_in_row == sp2.store_diagonal_first_in_row);
1633 }
1634 
1635 
1636 
1637 namespace internal
1638 {
1639  namespace SparsityPatternTools
1640  {
1645 
1646  inline size_type
1647  get_column_index_from_iterator(const size_type i)
1648  {
1649  return i;
1650  }
1651 
1652 
1653 
1654  template <typename value>
1655  inline size_type
1656  get_column_index_from_iterator(const std::pair<size_type, value> &i)
1657  {
1658  return i.first;
1659  }
1660 
1661 
1662 
1663  template <typename value>
1664  inline size_type
1665  get_column_index_from_iterator(const std::pair<const size_type, value> &i)
1666  {
1667  return i.first;
1668  }
1669  } // namespace SparsityPatternTools
1670 } // namespace internal
1671 
1672 
1673 
1674 template <typename ForwardIterator>
1675 void
1677  const size_type n_cols,
1678  const ForwardIterator begin,
1679  const ForwardIterator end)
1680 {
1681  Assert(static_cast<size_type>(std::distance(begin, end)) == n_rows,
1682  ExcIteratorRange(std::distance(begin, end), n_rows));
1683 
1684  // first determine row lengths for each row. if the matrix is quadratic,
1685  // then we might have to add an additional entry for the diagonal, if that
1686  // is not yet present. as we have to call compress anyway later on, don't
1687  // bother to check whether that diagonal entry is in a certain row or not
1688  const bool is_square = (n_rows == n_cols);
1689  std::vector<unsigned int> row_lengths;
1690  row_lengths.reserve(n_rows);
1691  for (ForwardIterator i = begin; i != end; ++i)
1692  row_lengths.push_back(std::distance(i->begin(), i->end()) +
1693  (is_square ? 1 : 0));
1694  reinit(n_rows, n_cols, row_lengths);
1695 
1696  // now enter all the elements into the matrix. note that if the matrix is
1697  // quadratic, then we already have the diagonal element preallocated
1698  //
1699  // for use in the inner loop, we define an alias to the type of the inner
1700  // iterators
1701  size_type row = 0;
1702  using inner_iterator =
1703  typename std::iterator_traits<ForwardIterator>::value_type::const_iterator;
1704  for (ForwardIterator i = begin; i != end; ++i, ++row)
1705  {
1706  size_type * cols = &colnums[rowstart[row]] + (is_square ? 1 : 0);
1707  const inner_iterator end_of_row = i->end();
1708  for (inner_iterator j = i->begin(); j != end_of_row; ++j)
1709  {
1710  const size_type col =
1711  internal::SparsityPatternTools::get_column_index_from_iterator(*j);
1712  Assert(col < n_cols, ExcIndexRange(col, 0, n_cols));
1713 
1714  if ((col != row) || !is_square)
1715  *cols++ = col;
1716  }
1717  }
1718 
1719  // finally compress everything. this also sorts the entries within each row
1720  compress();
1721 }
1722 
1723 
1724 #endif // DOXYGEN
1725 
1726 DEAL_II_NAMESPACE_CLOSE
1727 
1728 #endif
SparsityPatternIterators::size_type size_type
const types::global_dof_index invalid_size_type
Definition: types.h:196
iterator end() const
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:541
iterator begin() const
void load(Archive &ar, const unsigned int version)
types::global_dof_index size_type
Iterator(const ChunkSparsityPattern *sp, const size_type row)
STL namespace.
bool operator==(const SparsityPatternBase &) const
types::global_dof_index size_type
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
void reinit(const size_type m, const size_type n, const unsigned int max_per_row)
std::unique_ptr< std::size_t[]> rowstart
static ::ExceptionBase & ExcInvalidIterator()
static ::ExceptionBase & ExcInvalidNumberOfPartitions(int arg1)
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:518
Accessor(const ChunkSparsityPattern *matrix, const size_type row)
SparsityPatternBase::size_type size_type
#define Assert(cond, exc)
Definition: exceptions.h:1407
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:496
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:89
__global__ void set(Number *val, const Number s, const size_type 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
static const size_type invalid_entry
types::global_dof_index size_type
bool operator<(const Accessor &) const
DEAL_II_CONSTEXPR SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
size_type column_number(const size_type row, const unsigned int index) const
void save(Archive &ar, const unsigned int version) const
unsigned int row_length(const size_type row) const
size_type n_rows() const
bool operator==(const Accessor &) const
const SparsityPatternBase * container
static ::ExceptionBase & ExcInternalError()
SparsityPatternIterators::Iterator iterator
size_type n_cols() const