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