Reference documentation for deal.II version 8.5.1
householder.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2005 - 2015 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 #ifndef dealii__householder_h
17 #define dealii__householder_h
18 
19 
20 #include <cmath>
21 #include <deal.II/base/config.h>
22 #include <deal.II/lac/full_matrix.h>
23 #include <deal.II/lac/vector_memory.h>
24 
25 #include <vector>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
29 
30 // forward declarations
31 template<typename number> class Vector;
32 
33 
55 template<typename number>
56 class Householder : private FullMatrix<number>
57 {
58 public:
63 
67  Householder ();
68 
72  template<typename number2>
74 
78  template<typename number2>
79  void
81 
92  template<typename number2>
93  double least_squares (Vector<number2> &dst,
94  const Vector<number2> &src) const;
95 
99  template<typename number2>
100  double least_squares (BlockVector<number2> &dst,
101  const BlockVector<number2> &src) const;
102 
107  template<class VectorType>
108  void vmult (VectorType &dst, const VectorType &src) const;
109 
110  template<class VectorType>
111  void Tvmult (VectorType &dst, const VectorType &src) const;
112 
113 
114 private:
118  std::vector<number> diagonal;
119 };
120 
123 #ifndef DOXYGEN
124 /*-------------------------Inline functions -------------------------------*/
125 
126 // QR-transformation cf. Stoer 1 4.8.2 (p. 191)
127 
128 template <typename number>
130 {}
131 
132 
133 
134 template <typename number>
135 template <typename number2>
136 void
138 {
139  const size_type m = M.n_rows(), n = M.n_cols();
140  this->reinit(m, n);
141  this->fill(M);
142  Assert (!this->empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
143  diagonal.resize(m);
144 
145  // m > n, src.n() = m
146  Assert (this->n_cols() <= this->n_rows(),
147  ExcDimensionMismatch(this->n_cols(), this->n_rows()));
148 
149  for (size_type j=0 ; j<n ; ++j)
150  {
151  number2 sigma = 0;
152  size_type i;
153  // sigma = ||v||^2
154  for (i=j ; i<m ; ++i)
155  sigma += this->el(i,j)*this->el(i,j);
156  // We are ready if the column is
157  // empty. Are we?
158  if (std::fabs(sigma) < 1.e-15) return;
159 
160  number2 s = (this->el(j,j) < 0) ? std::sqrt(sigma) : -std::sqrt(sigma);
161  //
162  number2 beta = std::sqrt(1./(sigma-s*this->el(j,j)));
163 
164  // Make column j the Householder
165  // vector, store first entry in
166  // diagonal
167  diagonal[j] = beta*(this->el(j,j) - s);
168  this->el(j,j) = s;
169 
170  for (i=j+1 ; i<m ; ++i)
171  this->el(i,j) *= beta;
172 
173 
174  // For all subsequent columns do
175  // the Householder reflection
176  for (size_type k=j+1 ; k<n ; ++k)
177  {
178  number2 sum = diagonal[j]*this->el(j,k);
179  for (i=j+1 ; i<m ; ++i)
180  sum += this->el(i,j)*this->el(i,k);
181 
182  this->el(j,k) -= sum*this->diagonal[j];
183  for (i=j+1 ; i<m ; ++i)
184  this->el(i,k) -= sum*this->el(i,j);
185  }
186  }
187 }
188 
189 
190 template <typename number>
191 template <typename number2>
193 {
194  initialize(M);
195 }
196 
197 
198 template <typename number>
199 template <typename number2>
200 double
202  const Vector<number2> &src) const
203 {
204  Assert (!this->empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
205  AssertDimension(dst.size(), this->n());
206  AssertDimension(src.size(), this->m());
207 
208  const size_type m = this->m(), n = this->n();
209 
211  Vector<number2> *aux = mem.alloc();
212  aux->reinit(src, true);
213  *aux = src;
214  // m > n, m = src.n, n = dst.n
215 
216  // Multiply Q_n ... Q_2 Q_1 src
217  // Where Q_i = I-v_i v_i^T
218  for (size_type j=0; j<n; ++j)
219  {
220  // sum = v_i^T dst
221  number2 sum = diagonal[j]* (*aux)(j);
222  for (size_type i=j+1 ; i<m ; ++i)
223  sum += static_cast<number2>(this->el(i,j))*(*aux)(i);
224  // dst -= v * sum
225  (*aux)(j) -= sum*diagonal[j];
226  for (size_type i=j+1 ; i<m ; ++i)
227  (*aux)(i) -= sum*static_cast<number2>(this->el(i,j));
228  }
229  // Compute norm of residual
230  number2 sum = 0.;
231  for (size_type i=n ; i<m ; ++i)
232  sum += (*aux)(i) * (*aux)(i);
234 
235  // Compute solution
236  this->backward(dst, *aux);
237 
238  mem.free(aux);
239 
240  return std::sqrt(sum);
241 }
242 
243 template <typename number>
244 template <typename number2>
245 double
247  const BlockVector<number2> &src) const
248 {
249  Assert (!this->empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
250  AssertDimension(dst.size(), this->n());
251  AssertDimension(src.size(), this->m());
252 
253  const size_type m = this->m(), n = this->n();
254 
256  BlockVector<number2> *aux = mem.alloc();
257  aux->reinit(src, true);
258  *aux = src;
259  // m > n, m = src.n, n = dst.n
260 
261  // Multiply Q_n ... Q_2 Q_1 src
262  // Where Q_i = I-v_i v_i^T
263  for (size_type j=0; j<n; ++j)
264  {
265  // sum = v_i^T dst
266  number2 sum = diagonal[j]* (*aux)(j);
267  for (size_type i=j+1 ; i<m ; ++i)
268  sum += this->el(i,j)*(*aux)(i);
269  // dst -= v * sum
270  (*aux)(j) -= sum*diagonal[j];
271  for (size_type i=j+1 ; i<m ; ++i)
272  (*aux)(i) -= sum*this->el(i,j);
273  }
274  // Compute norm of residual
275  number2 sum = 0.;
276  for (size_type i=n ; i<m ; ++i)
277  sum += (*aux)(i) * (*aux)(i);
279 
280  //backward works for
281  //Vectors only, so copy
282  //them before
283  Vector<number2> v_dst, v_aux;
284  v_dst = dst;
285  v_aux = *aux;
286  // Compute solution
287  this->backward(v_dst, v_aux);
288  //copy the result back
289  //to the BlockVector
290  dst = v_dst;
291 
292  mem.free(aux);
293 
294  return std::sqrt(sum);
295 }
296 
297 
298 template <typename number>
299 template <class VectorType>
300 void
301 Householder<number>::vmult (VectorType &dst, const VectorType &src) const
302 {
303  least_squares (dst, src);
304 }
305 
306 
307 template <typename number>
308 template <class VectorType>
309 void
310 Householder<number>::Tvmult (VectorType &, const VectorType &) const
311 {
312  Assert(false, ExcNotImplemented());
313 }
314 
315 
316 
317 #endif // DOXYGEN
318 
319 DEAL_II_NAMESPACE_CLOSE
320 
321 #endif
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
types::global_dof_index size_type
Definition: householder.h:62
unsigned int global_dof_index
Definition: types.h:88
virtual VectorType * alloc()
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
std::size_t size() const
void vmult(VectorType &dst, const VectorType &src) const
virtual void free(const VectorType *const)
void reinit(const unsigned int n_blocks, const size_type block_size=0, const bool omit_zeroing_entries=false)
SymmetricTensor< rank, dim, Number > sum(const SymmetricTensor< rank, dim, Number > &local, const MPI_Comm &mpi_communicator)
std::vector< number > diagonal
Definition: householder.h:118
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
double least_squares(Vector< number2 > &dst, const Vector< number2 > &src) const
static ::ExceptionBase & ExcNotImplemented()
void initialize(const FullMatrix< number2 > &)
#define AssertIsFinite(number)
Definition: exceptions.h:1197