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
tridiagonal_matrix.cc
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) 2005 - 2025 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
16#include <deal.II/lac/vector.h>
17
18#include <complex>
19
21
22using namespace LAPACKSupport;
23
24template <typename number>
26 : diagonal(size, 0.)
27 , left((symmetric ? 0 : size), 0.)
28 , right(size, 0.)
29 , is_symmetric(symmetric)
30 , state(matrix)
31{}
32
33
34
35template <typename number>
36void
38{
39 is_symmetric = symmetric;
40 diagonal.resize(size);
41 right.resize(size);
42 left.resize(symmetric ? 0 : size);
43 state = matrix;
44}
45
46
47
48template <typename number>
49bool
51{
52 Assert(state == matrix, ExcState(state));
53
54 return std::all_of(left.begin(),
55 left.end(),
56 numbers::value_is_zero<number>) &&
57 std::all_of(diagonal.begin(),
58 diagonal.end(),
59 numbers::value_is_zero<number>) &&
60 std::all_of(right.begin(),
61 right.end(),
62 numbers::value_is_zero<number>);
63}
64
65
66
67template <typename number>
68void
70 const Vector<number> &v,
71 const bool adding) const
72{
73 Assert(state == matrix, ExcState(state));
74
75 Assert(w.size() == n(), ExcDimensionMismatch(w.size(), n()));
76 Assert(v.size() == n(), ExcDimensionMismatch(v.size(), n()));
77
78 if (n() == 0)
79 return;
80
81 // The actual loop skips the first and last row
82 const size_type e = n() - 1;
83 // Let iterators point to the first entry of each diagonal
84 typename std::vector<number>::const_iterator d = diagonal.begin();
85 typename std::vector<number>::const_iterator r = right.begin();
86 // The left diagonal starts one later or is equal to the right
87 // one for symmetric storage
88 typename std::vector<number>::const_iterator l = left.begin();
89 if (is_symmetric)
90 l = r;
91 else
92 ++l;
93
94 if (adding)
95 {
96 // Treat first row separately
97 w(0) += (*d) * v(0) + (*r) * v(1);
98 ++d;
99 ++r;
100 // All rows with three entries
101 for (size_type i = 1; i < e; ++i, ++d, ++r, ++l)
102 w(i) += (*l) * v(i - 1) + (*d) * v(i) + (*r) * v(i + 1);
103 // Last row is special again
104 w(e) += (*l) * v(e - 1) + (*d) * v(e);
105 }
106 else
107 {
108 w(0) = (*d) * v(0) + (*r) * v(1);
109 ++d;
110 ++r;
111 for (size_type i = 1; i < e; ++i, ++d, ++r, ++l)
112 w(i) = (*l) * v(i - 1) + (*d) * v(i) + (*r) * v(i + 1);
113 w(e) = (*l) * v(e - 1) + (*d) * v(e);
114 }
115}
116
117
118template <typename number>
119void
121 const Vector<number> &v) const
122{
123 vmult(w, v, /*adding = */ true);
124}
125
126
127
128template <typename number>
129void
131 const Vector<number> &v,
132 const bool adding) const
133{
134 Assert(state == matrix, ExcState(state));
135
136 Assert(w.size() == n(), ExcDimensionMismatch(w.size(), n()));
137 Assert(v.size() == n(), ExcDimensionMismatch(v.size(), n()));
138
139 if (n() == 0)
140 return;
141
142 const size_type e = n() - 1;
143 typename std::vector<number>::const_iterator d = diagonal.begin();
144 typename std::vector<number>::const_iterator r = right.begin();
145 typename std::vector<number>::const_iterator l = left.begin();
146 if (is_symmetric)
147 l = r;
148 else
149 ++l;
150
151 if (adding)
152 {
153 w(0) += (*d) * v(0) + (*l) * v(1);
154 ++d;
155 ++l;
156 for (size_type i = 1; i < e; ++i, ++d, ++r, ++l)
157 w(i) += (*l) * v(i + 1) + (*d) * v(i) + (*r) * v(i - 1);
158 w(e) += (*d) * v(e) + (*r) * v(e - 1);
159 }
160 else
161 {
162 w(0) = (*d) * v(0) + (*l) * v(1);
163 ++d;
164 ++l;
165 for (size_type i = 1; i < e; ++i, ++d, ++r, ++l)
166 w(i) = (*l) * v(i + 1) + (*d) * v(i) + (*r) * v(i - 1);
167 w(e) = (*d) * v(e) + (*r) * v(e - 1);
168 }
169}
170
171
172
173template <typename number>
174void
176 const Vector<number> &v) const
177{
178 Tvmult(w, v, true);
179}
180
181
182
183template <typename number>
184number
186 const Vector<number> &v) const
187{
188 Assert(state == matrix, ExcState(state));
189
190 const size_type e = n() - 1;
191 typename std::vector<number>::const_iterator d = diagonal.begin();
192 typename std::vector<number>::const_iterator r = right.begin();
193 typename std::vector<number>::const_iterator l = left.begin();
194 if (is_symmetric)
195 l = r;
196 else
197 ++l;
198
199 number result = w(0) * ((*d) * v(0) + (*r) * v(1));
200 ++d;
201 ++r;
202 for (size_type i = 1; i < e; ++i, ++d, ++r, ++l)
203 result += w(i) * ((*l) * v(i - 1) + (*d) * v(i) + (*r) * v(i + 1));
204 result += w(e) * ((*l) * v(e - 1) + (*d) * v(e));
205 return result;
206}
207
208
209
210template <typename number>
211number
213{
214 return matrix_scalar_product(v, v);
215}
216
217
218
219template <typename number>
220void
222{
223#ifdef DEAL_II_WITH_LAPACK
224 Assert(state == matrix, ExcState(state));
225 Assert(is_symmetric, ExcNotImplemented());
226
227 const types::blas_int nn = n();
228 types::blas_int info;
229 stev(&N,
230 &nn,
231 diagonal.data(),
232 right.data(),
233 static_cast<number *>(nullptr),
234 &one,
235 static_cast<number *>(nullptr),
236 &info);
237 Assert(info == 0, ExcInternalError());
238
240#else
241 AssertThrow(false, ExcNeedsLAPACK());
242#endif
243}
244
245
246
247template <typename number>
248number
250{
252 AssertIndexRange(i, n());
253 return diagonal[i];
254}
255
256
257
258template class TridiagonalMatrix<float>;
259template class TridiagonalMatrix<double>;
260#ifdef DEAL_II_WITH_COMPLEX_VALUES
263#endif
264
void Tvmult_add(Vector< number > &w, const Vector< number > &v) const
void vmult(Vector< number > &w, const Vector< number > &v, const bool adding=false) const
number matrix_norm_square(const Vector< number > &v) const
void reinit(size_type n, bool symmetric=false)
void vmult_add(Vector< number > &w, const Vector< number > &v) const
void Tvmult(Vector< number > &w, const Vector< number > &v, const bool adding=false) const
number eigenvalue(const size_type i) const
TridiagonalMatrix(size_type n=0, bool symmetric=false)
number matrix_scalar_product(const Vector< number > &u, const Vector< number > &v) const
virtual size_type size() const override
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNeedsLAPACK()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcState(State arg1)
#define AssertThrow(cond, exc)
void stev(const char *, const ::types::blas_int *, number1 *, number2 *, number3 *, const ::types::blas_int *, number4 *, ::types::blas_int *)
std::size_t size
Definition mpi.cc:733
@ matrix
Contents is actually a matrix.
@ eigenvalues
Eigenvalue vector is filled.
@ symmetric
Matrix is symmetric.
@ diagonal
Matrix is diagonal.
constexpr char N
constexpr types::blas_int one