deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\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\}}\)
Loading...
Searching...
No Matches
sparse_matrix.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2002 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_sparse_matrix_h
14#define dealii_sparse_matrix_h
15
16#include <deal.II/base/config.h>
17
21
27
28#include <iterator>
29#include <memory>
30
31
33
34// Forward declarations
35#ifndef DOXYGEN
36template <typename number>
37class Vector;
38template <typename number>
39class FullMatrix;
40template <typename Matrix>
41class BlockMatrixBase;
42template <typename number>
43class SparseILU;
44# ifdef DEAL_II_WITH_MPI
45namespace Utilities
46{
47 namespace MPI
48 {
49 template <typename Number>
50 void
52 }
53} // namespace Utilities
54# endif
55#endif
56
67{
72
73 // forward declaration
74 template <typename number, bool Constness>
75 class Iterator;
76
87 template <typename number, bool Constness>
89 {
90 public:
94 number
95 value() const;
96
100 number &
102
108 get_matrix() const;
109 };
110
111
112
119 template <typename number>
120 class Accessor<number, true> : public SparsityPatternIterators::Accessor
121 {
122 public:
128
132 Accessor(MatrixType *matrix, const std::size_t index_within_matrix);
133
138
143
147 number
148 value() const;
149
154 const MatrixType &
155 get_matrix() const;
156
157 private:
162
167
168 // Make iterator class a friend.
169 template <typename, bool>
170 friend class Iterator;
171 };
172
173
180 template <typename number>
181 class Accessor<number, false> : public SparsityPatternIterators::Accessor
182 {
183 private:
208 class Reference
209 {
210 public:
215 Reference(const Accessor *accessor, const bool dummy);
216
220 operator number() const;
221
225 const Reference &
226 operator=(const number n) const;
227
231 const Reference &
232 operator+=(const number n) const;
233
237 const Reference &
238 operator-=(const number n) const;
239
243 const Reference &
244 operator*=(const number n) const;
245
249 const Reference &
250 operator/=(const number n) const;
251
252 private:
258 };
259
260 public:
266
270 Accessor(MatrixType *matrix, const std::size_t index);
271
276
280 Reference
281 value() const;
282
287 MatrixType &
288 get_matrix() const;
289
290 private:
295
300
301 // Make iterator class a friend.
302 template <typename, bool>
303 friend class Iterator;
304 };
305
306
307
337 template <typename number, bool Constness>
339 {
340 public:
345
351
357
362 Iterator(MatrixType *matrix, const std::size_t index_within_matrix);
363
368
374
380
384 Iterator &
386
392
397 operator*() const;
398
403 operator->() const;
404
408 bool
409 operator==(const Iterator &) const;
410
414 bool
415 operator!=(const Iterator &) const;
416
424 bool
425 operator<(const Iterator &) const;
426
431 bool
432 operator>(const Iterator &) const;
433
440 int
441 operator-(const Iterator &p) const;
442
447 operator+(const size_type n) const;
448
449 private:
454 };
455
456} // namespace SparseMatrixIterators
457
458DEAL_II_NAMESPACE_CLOSE // Do not convert for module purposes
459
460 namespace std
461{
462 template <typename number, bool Constness>
464 ::SparseMatrixIterators::Iterator<number, Constness>>
465 {
466 using iterator_category = forward_iterator_tag;
468 typename ::SparseMatrixIterators::Iterator<number,
469 Constness>::value_type;
470 using difference_type = typename ::SparseMatrixIterators::
471 Iterator<number, Constness>::difference_type;
472 };
473} // namespace std
474
475DEAL_II_NAMESPACE_OPEN // Do not convert for module purposes
476
482 // TODO: Add multithreading to the other vmult functions.
483
510 template <typename number>
511 class SparseMatrix : public virtual EnableObserverPointer
512{
513public:
518
523 using value_type = number;
524
535
541
549
556 struct Traits
557 {
562 static const bool zero_addition_can_be_elided = true;
563 };
564
580
590
599
613 explicit SparseMatrix(const SparsityPattern &sparsity);
614
621 SparseMatrix(const SparsityPattern &sparsity, const IdentityMatrix &id);
622
627 virtual ~SparseMatrix() override;
628
640
647
656
669 operator=(const double d);
670
684 virtual void
685 reinit(const SparsityPattern &sparsity);
686
693 template <typename number2>
694 void
695 reinit(const SparseMatrix<number2> &sparse_matrix);
696
702 virtual void
713 bool
714 empty() const;
715
721 m() const;
722
728 n() const;
729
734 get_row_length(const size_type row) const;
735
741 std::size_t
743
753 std::size_t
754 n_actually_nonzero_elements(const double threshold = 0.) const;
755
764 const SparsityPattern &
766
771 std::size_t
773
778
789 void
790 set(const size_type i, const size_type j, const number value);
791
807 template <typename number2>
808 void
809 set(const std::vector<size_type> &indices,
810 const FullMatrix<number2> &full_matrix,
811 const bool elide_zero_values = false);
812
818 template <typename number2>
819 void
820 set(const std::vector<size_type> &row_indices,
821 const std::vector<size_type> &col_indices,
822 const FullMatrix<number2> &full_matrix,
823 const bool elide_zero_values = false);
824
835 template <typename number2>
836 void
837 set(const size_type row,
838 const std::vector<size_type> &col_indices,
839 const std::vector<number2> &values,
840 const bool elide_zero_values = false);
841
851 template <typename number2>
852 void
853 set(const size_type row,
854 const size_type n_cols,
855 const size_type *col_indices,
856 const number2 *values,
857 const bool elide_zero_values = false);
858
864 void
865 add(const size_type i, const size_type j, const number value);
866
881 template <typename number2>
882 void
883 add(const std::vector<size_type> &indices,
884 const FullMatrix<number2> &full_matrix,
885 const bool elide_zero_values = true);
886
892 template <typename number2>
893 void
894 add(const std::vector<size_type> &row_indices,
895 const std::vector<size_type> &col_indices,
896 const FullMatrix<number2> &full_matrix,
897 const bool elide_zero_values = true);
898
908 template <typename number2>
909 void
910 add(const size_type row,
911 const std::vector<size_type> &col_indices,
912 const std::vector<number2> &values,
913 const bool elide_zero_values = true);
914
924 template <typename number2>
925 void
926 add(const size_type row,
927 const size_type n_cols,
928 const size_type *col_indices,
929 const number2 *values,
930 const bool elide_zero_values = true,
931 const bool col_indices_are_sorted = false);
932
937 operator*=(const number factor);
938
943 operator/=(const number factor);
944
957 void
959
976 template <typename somenumber>
979
996 template <typename ForwardIterator>
997 void
998 copy_from(const ForwardIterator begin, const ForwardIterator end);
999
1009 template <typename somenumber>
1010 void
1012
1013#ifdef DEAL_II_TRILINOS_WITH_EPETRA
1025#endif
1026
1038 template <typename somenumber>
1039 void
1040 add(const number factor, const SparseMatrix<somenumber> &matrix);
1041
1061 const number &
1062 operator()(const size_type i, const size_type j) const;
1063
1067 number &
1068 operator()(const size_type i, const size_type j);
1069
1082 number
1083 el(const size_type i, const size_type j) const;
1084
1094 number
1095 diag_element(const size_type i) const;
1096
1100 number &
1102
1124 template <class OutVector, class InVector>
1125 void
1126 vmult(OutVector &dst, const InVector &src) const;
1127
1143 template <class OutVector, class InVector>
1144 void
1145 Tvmult(OutVector &dst, const InVector &src) const;
1146
1163 template <class OutVector, class InVector>
1164 void
1165 vmult_add(OutVector &dst, const InVector &src) const;
1166
1182 template <class OutVector, class InVector>
1183 void
1184 Tvmult_add(OutVector &dst, const InVector &src) const;
1185
1203 template <typename somenumber>
1204 somenumber
1206
1212 template <typename somenumber>
1213 somenumber
1215 const Vector<somenumber> &v) const;
1216
1226 template <typename somenumber>
1227 somenumber
1229 const Vector<somenumber> &x,
1230 const Vector<somenumber> &b) const;
1231
1267 template <typename numberB, typename numberC>
1268 void
1270 const SparseMatrix<numberB> &B,
1271 const Vector<number> &V = Vector<number>(),
1272 const bool rebuild_sparsity_pattern = true) const;
1273
1298 template <typename numberB, typename numberC>
1299 void
1301 const SparseMatrix<numberB> &B,
1302 const Vector<number> &V = Vector<number>(),
1303 const bool rebuild_sparsity_pattern = true) const;
1304
1318 real_type
1319 l1_norm() const;
1320
1328 real_type
1330
1335 real_type
1348 template <typename somenumber>
1349 void
1351 const Vector<somenumber> &src,
1352 const number omega = 1.) const;
1353
1360 template <typename somenumber>
1361 void
1363 const Vector<somenumber> &src,
1364 const number omega = 1.,
1365 const std::vector<std::size_t> &pos_right_of_diagonal =
1366 std::vector<std::size_t>()) const;
1367
1371 template <typename somenumber>
1372 void
1374 const Vector<somenumber> &src,
1375 const number omega = 1.) const;
1376
1380 template <typename somenumber>
1381 void
1383 const Vector<somenumber> &src,
1384 const number omega = 1.) const;
1385
1391 template <typename somenumber>
1392 void
1393 SSOR(Vector<somenumber> &v, const number omega = 1.) const;
1394
1399 template <typename somenumber>
1400 void
1401 SOR(Vector<somenumber> &v, const number omega = 1.) const;
1402
1407 template <typename somenumber>
1408 void
1409 TSOR(Vector<somenumber> &v, const number omega = 1.) const;
1410
1421 template <typename somenumber>
1422 void
1424 const std::vector<size_type> &permutation,
1425 const std::vector<size_type> &inverse_permutation,
1426 const number omega = 1.) const;
1427
1438 template <typename somenumber>
1439 void
1441 const std::vector<size_type> &permutation,
1442 const std::vector<size_type> &inverse_permutation,
1443 const number omega = 1.) const;
1444
1450 template <typename somenumber>
1451 void
1453 const Vector<somenumber> &b,
1454 const number omega = 1.) const;
1455
1460 template <typename somenumber>
1461 void
1463 const Vector<somenumber> &b,
1464 const number omega = 1.) const;
1465
1470 template <typename somenumber>
1471 void
1473 const Vector<somenumber> &b,
1474 const number omega = 1.) const;
1475
1480 template <typename somenumber>
1481 void
1483 const Vector<somenumber> &b,
1484 const number omega = 1.) const;
1498 begin() const;
1499
1503 iterator
1505
1510 end() const;
1511
1515 iterator
1517
1528 begin(const size_type r) const;
1529
1533 iterator
1535
1546 end(const size_type r) const;
1547
1551 iterator
1552 end(const size_type r);
1570 template <typename StreamType>
1571 void
1572 print(StreamType &out,
1573 const bool across = false,
1574 const bool diagonal_first = true) const;
1575
1598 void
1599 print_formatted(std::ostream &out,
1600 const unsigned int precision = 3,
1601 const bool scientific = true,
1602 const unsigned int width = 0,
1603 const char *zero_string = " ",
1604 const double denominator = 1.,
1605 const char *separator = " ") const;
1606
1612 void
1613 print_pattern(std::ostream &out, const double threshold = 0.) const;
1614
1623 void
1624 print_as_numpy_arrays(std::ostream &out,
1625 const unsigned int precision = 9) const;
1626
1637 void
1638 block_write(std::ostream &out) const;
1639
1656 void
1657 block_read(std::istream &in);
1668 int,
1669 int,
1670 << "You are trying to access the matrix entry with index <"
1671 << arg1 << ',' << arg2
1672 << ">, but this entry does not exist in the sparsity pattern "
1673 "of this matrix."
1674 "\n\n"
1675 "The most common cause for this problem is that you used "
1676 "a method to build the sparsity pattern that did not "
1677 "(completely) take into account all of the entries you "
1678 "will later try to write into. An example would be "
1679 "building a sparsity pattern that does not include "
1680 "the entries you will write into due to constraints "
1681 "on degrees of freedom such as hanging nodes or periodic "
1682 "boundary conditions. In such cases, building the "
1683 "sparsity pattern will succeed, but you will get errors "
1684 "such as the current one at one point or other when "
1685 "trying to write into the entries of the matrix.");
1690 "When copying one sparse matrix into another, "
1691 "or when adding one sparse matrix to another, "
1692 "both matrices need to refer to the same "
1693 "sparsity pattern.");
1698 int,
1699 int,
1700 << "The iterators denote a range of " << arg1
1701 << " elements, but the given number of rows was " << arg2);
1706 "You are attempting an operation on two vectors that "
1707 "are the same object, but the operation requires that the "
1708 "two objects are in fact different.");
1711protected:
1722 void
1724
1729 void
1731
1732private:
1739
1747 std::unique_ptr<number[]> val;
1748
1755 std::size_t max_len;
1756
1757 // make all other sparse matrices friends
1758 template <typename somenumber>
1759 friend class SparseMatrix;
1760 template <typename somenumber>
1762 template <typename>
1763 friend class SparseILU;
1764
1765 // To allow it calling private prepare_add() and prepare_set().
1766 template <typename>
1767 friend class BlockMatrixBase;
1768
1769 // Also give access to internal details to the iterator/accessor classes.
1770 template <typename, bool>
1772 template <typename, bool>
1774
1775#ifdef DEAL_II_WITH_MPI
1776 // Give access to internal datastructures to perform MPI operations.
1777 template <typename Number>
1778 friend void
1780 const MPI_Comm,
1782#endif
1783};
1784
1785#ifndef DOXYGEN
1786/*---------------------- Inline functions -----------------------------------*/
1787
1788
1789
1790template <typename number>
1791template <typename number2>
1792void
1794{
1795 this->reinit(sparse_matrix.get_sparsity_pattern());
1796}
1797
1798
1799
1800template <typename number>
1801inline typename SparseMatrix<number>::size_type
1803{
1804 Assert(cols != nullptr, ExcNeedsSparsityPattern());
1805 return cols->rows;
1806}
1807
1808
1809
1810template <typename number>
1811inline typename SparseMatrix<number>::size_type
1813{
1814 Assert(cols != nullptr, ExcNeedsSparsityPattern());
1815 return cols->cols;
1816}
1817
1818
1819
1820template <typename number>
1821inline const SparsityPattern &
1823{
1824 Assert(cols != nullptr, ExcNeedsSparsityPattern());
1825 return *cols;
1826}
1827
1828
1829
1830// Inline the set() and add() functions, since they will be called frequently.
1831template <typename number>
1832inline void
1834 const size_type j,
1835 const number value)
1836{
1838
1839 const size_type index = cols->operator()(i, j);
1840
1841 // it is allowed to set elements of the matrix that are not part of the
1842 // sparsity pattern, if the value to which we set it is zero
1844 {
1845 Assert((index != SparsityPattern::invalid_entry) || (value == number()),
1846 ExcInvalidIndex(i, j));
1847 return;
1848 }
1849
1850 val[index] = value;
1851}
1852
1853
1854
1855template <typename number>
1856template <typename number2>
1857inline void
1858SparseMatrix<number>::set(const std::vector<size_type> &indices,
1859 const FullMatrix<number2> &values,
1860 const bool elide_zero_values)
1861{
1862 Assert(indices.size() == values.m(),
1863 ExcDimensionMismatch(indices.size(), values.m()));
1864 Assert(values.m() == values.n(), ExcNotQuadratic());
1865
1866 for (size_type i = 0; i < indices.size(); ++i)
1867 set(indices[i],
1868 indices.size(),
1869 indices.data(),
1870 &values(i, 0),
1871 elide_zero_values);
1872}
1873
1874
1875
1876template <typename number>
1877template <typename number2>
1878inline void
1879SparseMatrix<number>::set(const std::vector<size_type> &row_indices,
1880 const std::vector<size_type> &col_indices,
1881 const FullMatrix<number2> &values,
1882 const bool elide_zero_values)
1883{
1884 Assert(row_indices.size() == values.m(),
1885 ExcDimensionMismatch(row_indices.size(), values.m()));
1886 Assert(col_indices.size() == values.n(),
1887 ExcDimensionMismatch(col_indices.size(), values.n()));
1888
1889 for (size_type i = 0; i < row_indices.size(); ++i)
1890 set(row_indices[i],
1891 col_indices.size(),
1892 col_indices.data(),
1893 &values(i, 0),
1894 elide_zero_values);
1895}
1896
1897
1898
1899template <typename number>
1900template <typename number2>
1901inline void
1903 const std::vector<size_type> &col_indices,
1904 const std::vector<number2> &values,
1905 const bool elide_zero_values)
1906{
1907 Assert(col_indices.size() == values.size(),
1908 ExcDimensionMismatch(col_indices.size(), values.size()));
1909
1910 set(row,
1911 col_indices.size(),
1912 col_indices.data(),
1913 values.data(),
1914 elide_zero_values);
1915}
1916
1917
1918
1919template <typename number>
1920inline void
1922 const size_type j,
1923 const number value)
1924{
1926
1927 if (value == number())
1928 return;
1929
1930 const size_type index = cols->operator()(i, j);
1931
1932 // it is allowed to add elements to the matrix that are not part of the
1933 // sparsity pattern, if the value to which we set it is zero
1935 {
1936 Assert((index != SparsityPattern::invalid_entry) || (value == number()),
1937 ExcInvalidIndex(i, j));
1938 return;
1939 }
1940
1941 val[index] += value;
1942}
1943
1944
1945
1946template <typename number>
1947template <typename number2>
1948inline void
1949SparseMatrix<number>::add(const std::vector<size_type> &indices,
1950 const FullMatrix<number2> &values,
1951 const bool elide_zero_values)
1952{
1953 Assert(indices.size() == values.m(),
1954 ExcDimensionMismatch(indices.size(), values.m()));
1955 Assert(values.m() == values.n(), ExcNotQuadratic());
1956
1957 for (size_type i = 0; i < indices.size(); ++i)
1958 add(indices[i],
1959 indices.size(),
1960 indices.data(),
1961 &values(i, 0),
1962 elide_zero_values);
1963}
1964
1965
1966
1967template <typename number>
1968template <typename number2>
1969inline void
1970SparseMatrix<number>::add(const std::vector<size_type> &row_indices,
1971 const std::vector<size_type> &col_indices,
1972 const FullMatrix<number2> &values,
1973 const bool elide_zero_values)
1974{
1975 Assert(row_indices.size() == values.m(),
1976 ExcDimensionMismatch(row_indices.size(), values.m()));
1977 Assert(col_indices.size() == values.n(),
1978 ExcDimensionMismatch(col_indices.size(), values.n()));
1979
1980 for (size_type i = 0; i < row_indices.size(); ++i)
1981 add(row_indices[i],
1982 col_indices.size(),
1983 col_indices.data(),
1984 &values(i, 0),
1985 elide_zero_values);
1986}
1987
1988
1989
1990template <typename number>
1991template <typename number2>
1992inline void
1994 const std::vector<size_type> &col_indices,
1995 const std::vector<number2> &values,
1996 const bool elide_zero_values)
1997{
1998 Assert(col_indices.size() == values.size(),
1999 ExcDimensionMismatch(col_indices.size(), values.size()));
2000
2001 add(row,
2002 col_indices.size(),
2003 col_indices.data(),
2004 values.data(),
2005 elide_zero_values,
2006 std::is_sorted(col_indices.begin(), col_indices.end()));
2007}
2008
2009
2010
2011template <typename number>
2012inline SparseMatrix<number> &
2013SparseMatrix<number>::operator*=(const number factor)
2014{
2015 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2016 Assert(val != nullptr, ExcNotInitialized());
2017
2018 number *val_ptr = val.get();
2019 const number *const end_ptr = val.get() + cols->n_nonzero_elements();
2020
2021 while (val_ptr != end_ptr)
2022 *val_ptr++ *= factor;
2023
2024 return *this;
2025}
2026
2027
2028
2029template <typename number>
2030inline SparseMatrix<number> &
2031SparseMatrix<number>::operator/=(const number factor)
2032{
2033 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2034 Assert(val != nullptr, ExcNotInitialized());
2035 Assert(factor != number(), ExcDivideByZero());
2036
2037 const number factor_inv = number(1.) / factor;
2038
2039 number *val_ptr = val.get();
2040 const number *const end_ptr = val.get() + cols->n_nonzero_elements();
2041
2042 while (val_ptr != end_ptr)
2043 *val_ptr++ *= factor_inv;
2044
2045 return *this;
2046}
2047
2048
2049
2050template <typename number>
2051inline const number &
2053{
2054 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2055 Assert(cols->operator()(i, j) != SparsityPattern::invalid_entry,
2056 ExcInvalidIndex(i, j));
2057 return val[cols->operator()(i, j)];
2058}
2059
2060
2061
2062template <typename number>
2063inline number &
2065{
2066 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2067 Assert(cols->operator()(i, j) != SparsityPattern::invalid_entry,
2068 ExcInvalidIndex(i, j));
2069 return val[cols->operator()(i, j)];
2070}
2071
2072
2073
2074template <typename number>
2075inline number
2076SparseMatrix<number>::el(const size_type i, const size_type j) const
2077{
2078 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2079 const size_type index = cols->operator()(i, j);
2080
2082 return val[index];
2083 else
2084 return 0;
2085}
2086
2087
2088
2089template <typename number>
2090inline number
2092{
2093 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2094 Assert(m() == n(), ExcNotQuadratic());
2095 AssertIndexRange(i, m());
2096
2097 // Use that the first element in each row of a quadratic matrix is the main
2098 // diagonal
2099 return val[cols->rowstart[i]];
2100}
2101
2102
2103
2104template <typename number>
2105inline number &
2107{
2108 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2109 Assert(m() == n(), ExcNotQuadratic());
2110 AssertIndexRange(i, m());
2111
2112 // Use that the first element in each row of a quadratic matrix is the main
2113 // diagonal
2114 return val[cols->rowstart[i]];
2115}
2116
2117
2118
2119template <typename number>
2120template <typename ForwardIterator>
2121void
2122SparseMatrix<number>::copy_from(const ForwardIterator begin,
2123 const ForwardIterator end)
2124{
2125 Assert(static_cast<size_type>(std::distance(begin, end)) == m(),
2126 ExcIteratorRange(std::distance(begin, end), m()));
2127
2128 // for use in the inner loop, we define an alias to the type of the inner
2129 // iterators
2130 using inner_iterator =
2131 typename std::iterator_traits<ForwardIterator>::value_type::const_iterator;
2132 size_type row = 0;
2133 for (ForwardIterator i = begin; i != end; ++i, ++row)
2134 {
2135 const inner_iterator end_of_row = i->end();
2136 for (inner_iterator j = i->begin(); j != end_of_row; ++j)
2137 // write entries
2138 set(row, j->first, j->second);
2139 };
2140}
2141
2142
2143//---------------------------------------------------------------------------
2144
2145
2146namespace SparseMatrixIterators
2147{
2148 template <typename number>
2149 inline Accessor<number, true>::Accessor(const MatrixType *matrix,
2150 const std::size_t index_within_matrix)
2151 : SparsityPatternIterators::Accessor(&matrix->get_sparsity_pattern(),
2152 index_within_matrix)
2153 , matrix(matrix)
2154 {}
2155
2156
2157
2158 template <typename number>
2159 inline Accessor<number, true>::Accessor(const MatrixType *matrix)
2160 : SparsityPatternIterators::Accessor(&matrix->get_sparsity_pattern())
2161 , matrix(matrix)
2162 {}
2163
2164
2165
2166 template <typename number>
2167 inline Accessor<number, true>::Accessor(
2169 : SparsityPatternIterators::Accessor(a)
2170 , matrix(&a.get_matrix())
2171 {}
2172
2173
2174
2175 template <typename number>
2176 inline number
2177 Accessor<number, true>::value() const
2178 {
2179 AssertIndexRange(linear_index, matrix->n_nonzero_elements());
2180 return matrix->val[linear_index];
2181 }
2182
2183
2184
2185 template <typename number>
2186 inline const typename Accessor<number, true>::MatrixType &
2187 Accessor<number, true>::get_matrix() const
2188 {
2189 return *matrix;
2190 }
2191
2192
2193
2194 template <typename number>
2195 inline Accessor<number, false>::Reference::Reference(const Accessor *accessor,
2196 const bool)
2197 : accessor(accessor)
2198 {}
2199
2200
2201 template <typename number>
2202 inline Accessor<number, false>::Reference::operator number() const
2203 {
2204 AssertIndexRange(accessor->linear_index,
2205 accessor->matrix->n_nonzero_elements());
2206 return accessor->matrix->val[accessor->linear_index];
2207 }
2208
2209
2210
2211 template <typename number>
2212 inline const typename Accessor<number, false>::Reference &
2213 Accessor<number, false>::Reference::operator=(const number n) const
2214 {
2215 AssertIndexRange(accessor->linear_index,
2216 accessor->matrix->n_nonzero_elements());
2217 accessor->matrix->val[accessor->linear_index] = n;
2218 return *this;
2219 }
2220
2221
2222
2223 template <typename number>
2224 inline const typename Accessor<number, false>::Reference &
2225 Accessor<number, false>::Reference::operator+=(const number n) const
2226 {
2227 AssertIndexRange(accessor->linear_index,
2228 accessor->matrix->n_nonzero_elements());
2229 accessor->matrix->val[accessor->linear_index] += n;
2230 return *this;
2231 }
2232
2233
2234
2235 template <typename number>
2236 inline const typename Accessor<number, false>::Reference &
2237 Accessor<number, false>::Reference::operator-=(const number n) const
2238 {
2239 AssertIndexRange(accessor->linear_index,
2240 accessor->matrix->n_nonzero_elements());
2241 accessor->matrix->val[accessor->linear_index] -= n;
2242 return *this;
2243 }
2244
2245
2246
2247 template <typename number>
2248 inline const typename Accessor<number, false>::Reference &
2249 Accessor<number, false>::Reference::operator*=(const number n) const
2250 {
2251 AssertIndexRange(accessor->linear_index,
2252 accessor->matrix->n_nonzero_elements());
2253 accessor->matrix->val[accessor->linear_index] *= n;
2254 return *this;
2255 }
2256
2257
2258
2259 template <typename number>
2260 inline const typename Accessor<number, false>::Reference &
2261 Accessor<number, false>::Reference::operator/=(const number n) const
2262 {
2263 AssertIndexRange(accessor->linear_index,
2264 accessor->matrix->n_nonzero_elements());
2265 accessor->matrix->val[accessor->linear_index] /= n;
2266 return *this;
2267 }
2268
2269
2270
2271 template <typename number>
2272 inline Accessor<number, false>::Accessor(MatrixType *matrix,
2273 const std::size_t index)
2274 : SparsityPatternIterators::Accessor(&matrix->get_sparsity_pattern(), index)
2275 , matrix(matrix)
2276 {}
2277
2278
2279
2280 template <typename number>
2281 inline Accessor<number, false>::Accessor(MatrixType *matrix)
2282 : SparsityPatternIterators::Accessor(&matrix->get_sparsity_pattern())
2283 , matrix(matrix)
2284 {}
2285
2286
2287
2288 template <typename number>
2289 inline typename Accessor<number, false>::Reference
2290 Accessor<number, false>::value() const
2291 {
2292 return Reference(this, true);
2293 }
2294
2295
2296
2297 template <typename number>
2298 inline typename Accessor<number, false>::MatrixType &
2299 Accessor<number, false>::get_matrix() const
2300 {
2301 return *matrix;
2302 }
2303
2304
2305
2306 template <typename number, bool Constness>
2307 inline Iterator<number, Constness>::Iterator(MatrixType *matrix,
2308 const std::size_t index)
2309 : accessor(matrix, index)
2310 {}
2311
2312
2313
2314 template <typename number, bool Constness>
2315 inline Iterator<number, Constness>::Iterator(MatrixType *matrix)
2316 : accessor(matrix)
2317 {}
2318
2319
2320
2321 template <typename number, bool Constness>
2322 inline Iterator<number, Constness>::Iterator(
2324 : accessor(*i)
2325 {}
2326
2327
2328
2329 template <typename number, bool Constness>
2330 inline const Iterator<number, Constness> &
2331 Iterator<number, Constness>::operator=(
2333 {
2334 accessor = *i;
2335 return *this;
2336 }
2337
2338
2339
2340 template <typename number, bool Constness>
2341 inline Iterator<number, Constness> &
2342 Iterator<number, Constness>::operator++()
2343 {
2344 accessor.advance();
2345 return *this;
2346 }
2347
2348
2349 template <typename number, bool Constness>
2350 inline Iterator<number, Constness>
2351 Iterator<number, Constness>::operator++(int)
2352 {
2353 const Iterator iter = *this;
2354 accessor.advance();
2355 return iter;
2356 }
2357
2358
2359 template <typename number, bool Constness>
2360 inline const Accessor<number, Constness> &
2361 Iterator<number, Constness>::operator*() const
2362 {
2363 return accessor;
2364 }
2365
2366
2367 template <typename number, bool Constness>
2368 inline const Accessor<number, Constness> *
2369 Iterator<number, Constness>::operator->() const
2370 {
2371 return &accessor;
2372 }
2373
2374
2375 template <typename number, bool Constness>
2376 inline bool
2377 Iterator<number, Constness>::operator==(const Iterator &other) const
2378 {
2379 return (accessor == other.accessor);
2380 }
2381
2382
2383 template <typename number, bool Constness>
2384 inline bool
2385 Iterator<number, Constness>::operator!=(const Iterator &other) const
2386 {
2387 return !(*this == other);
2388 }
2389
2390
2391 template <typename number, bool Constness>
2392 inline bool
2393 Iterator<number, Constness>::operator<(const Iterator &other) const
2394 {
2395 Assert(&accessor.get_matrix() == &other.accessor.get_matrix(),
2397
2398 return (accessor < other.accessor);
2399 }
2400
2401
2402 template <typename number, bool Constness>
2403 inline bool
2404 Iterator<number, Constness>::operator>(const Iterator &other) const
2405 {
2406 return (other < *this);
2407 }
2408
2409
2410 template <typename number, bool Constness>
2411 inline int
2412 Iterator<number, Constness>::operator-(const Iterator &other) const
2413 {
2414 Assert(&accessor.get_matrix() == &other.accessor.get_matrix(),
2416
2417 return (*this)->linear_index - other->linear_index;
2418 }
2419
2420
2421
2422 template <typename number, bool Constness>
2423 inline Iterator<number, Constness>
2424 Iterator<number, Constness>::operator+(const size_type n) const
2425 {
2426 Iterator x = *this;
2427 for (size_type i = 0; i < n; ++i)
2428 ++x;
2429
2430 return x;
2431 }
2432
2433} // namespace SparseMatrixIterators
2434
2435
2436
2437template <typename number>
2440{
2441 return const_iterator(this, 0);
2442}
2443
2444
2445template <typename number>
2448{
2449 return const_iterator(this);
2450}
2451
2452
2453template <typename number>
2454inline typename SparseMatrix<number>::iterator
2456{
2457 return iterator(this, 0);
2458}
2459
2460
2461template <typename number>
2462inline typename SparseMatrix<number>::iterator
2464{
2465 return iterator(this, cols->rowstart[cols->rows]);
2466}
2467
2468
2469template <typename number>
2471SparseMatrix<number>::begin(const size_type r) const
2472{
2473 AssertIndexRange(r, m());
2474
2475 return const_iterator(this, cols->rowstart[r]);
2476}
2477
2478
2479
2480template <typename number>
2482SparseMatrix<number>::end(const size_type r) const
2483{
2484 AssertIndexRange(r, m());
2485
2486 return const_iterator(this, cols->rowstart[r + 1]);
2487}
2488
2489
2490
2491template <typename number>
2492inline typename SparseMatrix<number>::iterator
2493SparseMatrix<number>::begin(const size_type r)
2494{
2495 AssertIndexRange(r, m());
2496
2497 return iterator(this, cols->rowstart[r]);
2498}
2499
2500
2501
2502template <typename number>
2503inline typename SparseMatrix<number>::iterator
2504SparseMatrix<number>::end(const size_type r)
2505{
2506 AssertIndexRange(r, m());
2507
2508 return iterator(this, cols->rowstart[r + 1]);
2509}
2510
2511
2512
2513template <typename number>
2514template <typename StreamType>
2515inline void
2516SparseMatrix<number>::print(StreamType &out,
2517 const bool across,
2518 const bool diagonal_first) const
2519{
2520 Assert(cols != nullptr, ExcNeedsSparsityPattern());
2521 Assert(val != nullptr, ExcNotInitialized());
2522
2523 bool hanging_diagonal = false;
2524 number diagonal = number();
2525
2526 for (size_type i = 0; i < cols->rows; ++i)
2527 {
2528 for (size_type j = cols->rowstart[i]; j < cols->rowstart[i + 1]; ++j)
2529 {
2530 if (!diagonal_first && i == cols->colnums[j])
2531 {
2532 diagonal = val[j];
2533 hanging_diagonal = true;
2534 }
2535 else
2536 {
2537 if (hanging_diagonal && cols->colnums[j] > i)
2538 {
2539 if (across)
2540 out << ' ' << i << ',' << i << ':' << diagonal;
2541 else
2542 out << '(' << i << ',' << i << ") " << diagonal
2543 << std::endl;
2544 hanging_diagonal = false;
2545 }
2546 if (across)
2547 out << ' ' << i << ',' << cols->colnums[j] << ':' << val[j];
2548 else
2549 out << '(' << i << ',' << cols->colnums[j] << ") " << val[j]
2550 << std::endl;
2551 }
2552 }
2553 if (hanging_diagonal)
2554 {
2555 if (across)
2556 out << ' ' << i << ',' << i << ':' << diagonal;
2557 else
2558 out << '(' << i << ',' << i << ") " << diagonal << std::endl;
2559 hanging_diagonal = false;
2560 }
2561 }
2562 if (across)
2563 out << std::endl;
2564}
2565
2566
2567template <typename number>
2568inline void
2570{
2571 // nothing to do here
2572}
2573
2574
2575
2576template <typename number>
2577inline void
2579{
2580 // nothing to do here
2581}
2582
2583#endif // DOXYGEN
2584
2585
2587
2588#endif
*  iterator end()
*  *  iterator begin()
*  x_component_mask set(0, true)
*  *  const_iterator()=default
*  *  iterator()=default
const Reference & operator-=(const number n) const
Reference(const Accessor *accessor, const bool dummy)
const Reference & operator/=(const number n) const
const Reference & operator+=(const number n) const
const Reference & operator*=(const number n) const
const Reference & operator=(const number n) const
Accessor(MatrixType *matrix, const std::size_t index)
Accessor(const SparseMatrixIterators::Accessor< number, false > &a)
Accessor(MatrixType *matrix, const std::size_t index_within_matrix)
const SparseMatrix< number > & get_matrix() const
const Iterator< number, Constness > & operator=(const SparseMatrixIterators::Iterator< number, false > &i)
bool operator>(const Iterator &) const
bool operator==(const Iterator &) const
int operator-(const Iterator &p) const
bool operator<(const Iterator &) const
Iterator(MatrixType *matrix)
const Accessor< number, Constness > & value_type
Iterator operator+(const size_type n) const
const Accessor< number, Constness > & operator*() const
Accessor< number, Constness > accessor
Iterator(const SparseMatrixIterators::Iterator< number, false > &i)
Iterator(MatrixType *matrix, const std::size_t index_within_matrix)
const Accessor< number, Constness > * operator->() const
typename Accessor< number, Constness >::MatrixType MatrixType
bool operator!=(const Iterator &) const
void set(const size_type row, const std::vector< size_type > &col_indices, const std::vector< number2 > &values, const bool elide_zero_values=false)
somenumber matrix_scalar_product(const Vector< somenumber > &u, const Vector< somenumber > &v) const
void TSOR_step(Vector< somenumber > &v, const Vector< somenumber > &b, const number omega=1.) const
void precondition_Jacobi(Vector< somenumber > &dst, const Vector< somenumber > &src, const number omega=1.) const
SparseMatrix(const SparsityPattern &sparsity)
void add(const number factor, const SparseMatrix< somenumber > &matrix)
std::size_t n_nonzero_elements() const
size_type get_row_length(const size_type row) const
void SOR_step(Vector< somenumber > &v, const Vector< somenumber > &b, const number omega=1.) const
somenumber residual(Vector< somenumber > &dst, const Vector< somenumber > &x, const Vector< somenumber > &b) const
iterator end()
number & diag_element(const size_type i)
void prepare_add()
void Tmmult(SparseMatrix< numberC > &C, const SparseMatrix< numberB > &B, const Vector< number > &V=Vector< number >(), const bool rebuild_sparsity_pattern=true) const
void Tvmult(OutVector &dst, const InVector &src) const
const_iterator begin(const size_type r) const
SparseMatrix< number > & operator=(const SparseMatrix< number > &)
const_iterator end() const
void SSOR_step(Vector< somenumber > &v, const Vector< somenumber > &b, const number omega=1.) const
void set(const std::vector< size_type > &indices, const FullMatrix< number2 > &full_matrix, const bool elide_zero_values=false)
void print_as_numpy_arrays(std::ostream &out, const unsigned int precision=9) const
void mmult(SparseMatrix< numberC > &C, const SparseMatrix< numberB > &B, const Vector< number > &V=Vector< number >(), const bool rebuild_sparsity_pattern=true) const
ObserverPointer< const SparsityPattern, SparseMatrix< number > > cols
const SparsityPattern & get_sparsity_pattern() const
void set(const size_type i, const size_type j, const number value)
void print_formatted(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const unsigned int width=0, const char *zero_string=" ", const double denominator=1., const char *separator=" ") const
const_iterator begin() const
SparseMatrix< number > & copy_from(const SparseMatrix< somenumber > &source)
void precondition_TSOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number omega=1.) const
virtual void clear()
virtual ~SparseMatrix() override
void vmult_add(OutVector &dst, const InVector &src) const
number diag_element(const size_type i) const
void add(const std::vector< size_type > &row_indices, const std::vector< size_type > &col_indices, const FullMatrix< number2 > &full_matrix, const bool elide_zero_values=true)
void SSOR(Vector< somenumber > &v, const number omega=1.) const
somenumber matrix_norm_square(const Vector< somenumber > &v) const
SparseMatrix(SparseMatrix< number > &&m) noexcept
void TSOR(Vector< somenumber > &v, const number omega=1.) const
SparseMatrix< number > & copy_from(const TrilinosWrappers::SparseMatrix &matrix)
void symmetrize()
SparseMatrix(const SparsityPattern &sparsity, const IdentityMatrix &id)
void print_pattern(std::ostream &out, const double threshold=0.) const
void vmult(OutVector &dst, const InVector &src) const
std::size_t memory_consumption() const
void PSOR(Vector< somenumber > &v, const std::vector< size_type > &permutation, const std::vector< size_type > &inverse_permutation, const number omega=1.) const
void block_write(std::ostream &out) const
void copy_from(const ForwardIterator begin, const ForwardIterator end)
const number & operator()(const size_type i, const size_type j) const
number & operator()(const size_type i, const size_type j)
void block_read(std::istream &in)
void prepare_set()
number el(const size_type i, const size_type j) const
SparseMatrix< number > & operator=(SparseMatrix< number > &&m) noexcept
void precondition_SSOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number omega=1., const std::vector< std::size_t > &pos_right_of_diagonal=std::vector< std::size_t >()) const
void print(StreamType &out, const bool across=false, const bool diagonal_first=true) const
const_iterator end(const size_type r) const
iterator begin()
void SOR(Vector< somenumber > &v, const number omega=1.) const
SparseMatrix & operator/=(const number factor)
std::unique_ptr< number[]> val
iterator begin(const size_type r)
void precondition_SOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number omega=1.) const
typename numbers::NumberTraits< number >::real_type real_type
void reinit(const SparseMatrix< number2 > &sparse_matrix)
void add(const size_type row, const size_type n_cols, const size_type *col_indices, const number2 *values, const bool elide_zero_values=true, const bool col_indices_are_sorted=false)
void add(const size_type i, const size_type j, const number value)
size_type n() const
size_type m() const
void copy_from(const FullMatrix< somenumber > &matrix)
std::size_t max_len
iterator end(const size_type r)
SparseMatrix & operator*=(const number factor)
void compress(VectorOperation::values)
SparseMatrix(const SparseMatrix &)
SparseMatrix< number > & operator=(const IdentityMatrix &id)
SparseMatrix & operator=(const double d)
real_type frobenius_norm() const
void Tvmult_add(OutVector &dst, const InVector &src) const
real_type linfty_norm() const
void add(const size_type row, const std::vector< size_type > &col_indices, const std::vector< number2 > &values, const bool elide_zero_values=true)
void set(const std::vector< size_type > &row_indices, const std::vector< size_type > &col_indices, const FullMatrix< number2 > &full_matrix, const bool elide_zero_values=false)
real_type l1_norm() const
std::size_t n_actually_nonzero_elements(const double threshold=0.) const
bool empty() const
void add(const std::vector< size_type > &indices, const FullMatrix< number2 > &full_matrix, const bool elide_zero_values=true)
void TPSOR(Vector< somenumber > &v, const std::vector< size_type > &permutation, const std::vector< size_type > &inverse_permutation, const number omega=1.) const
virtual void reinit(const SparsityPattern &sparsity)
void set(const size_type row, const size_type n_cols, const size_type *col_indices, const number2 *values, const bool elide_zero_values=false)
void Jacobi_step(Vector< somenumber > &v, const Vector< somenumber > &b, const number omega=1.) const
friend class ChunkSparsityPatternIterators::Accessor
SparsityPatternIterators::size_type size_type
static constexpr size_type invalid_entry
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & ExcDifferentSparsityPatterns()
static ::ExceptionBase & ExcInvalidIndex(int arg1, int arg2)
#define Assert(cond, exc)
static ::ExceptionBase & ExcSourceEqualsDestination()
#define AssertIsFinite(number)
#define DeclException2(Exception2, type1, type2, outsequence)
static ::ExceptionBase & ExcNeedsSparsityPattern()
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDivideByZero()
static ::ExceptionBase & ExcIteratorRange(int arg1, int arg2)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcNotQuadratic()
@ matrix
Contents is actually a matrix.
@ diagonal
Matrix is diagonal.
types::global_dof_index size_type
T sum(const T &t, const MPI_Comm mpi_communicator)
STL namespace.
unsigned int global_dof_index
Definition types.h:92
static const bool zero_addition_can_be_elided
typename ::SparseMatrixIterators::Iterator< number, Constness >::difference_type difference_type
typename ::SparseMatrixIterators::Iterator< number, Constness >::value_type value_type