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