Reference documentation for deal.II version 9.0.0
householder.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2005 - 2018 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 
77 template <typename number>
79 {
80 public:
85 
89  Householder () = default;
90 
94  template <typename number2>
96 
102  template <typename number2>
103  void
104  initialize (const FullMatrix<number2> &A);
105 
116  template <typename number2>
117  double least_squares (Vector<number2> &dst,
118  const Vector<number2> &src) const;
119 
123  template <typename number2>
124  double least_squares (BlockVector<number2> &dst,
125  const BlockVector<number2> &src) const;
126 
131  template <class VectorType>
132  void vmult (VectorType &dst,
133  const VectorType &src) const;
134 
139  template <class VectorType>
140  void Tvmult (VectorType &dst, const VectorType &src) const;
141 
142 
143 private:
148  std::vector<number> diagonal;
149 
154 };
155 
158 #ifndef DOXYGEN
159 /*-------------------------Inline functions -------------------------------*/
160 
161 // QR-transformation cf. Stoer 1 4.8.2 (p. 191)
162 
163 template <typename number>
164 template <typename number2>
165 void
167 {
168  const size_type m = M.n_rows(), n = M.n_cols();
169  storage.reinit(m, n);
170  storage.fill(M);
171  Assert (!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
172  diagonal.resize(m);
173 
174  // m > n, src.n() = m
175  Assert (storage.n_cols() <= storage.n_rows(),
176  ExcDimensionMismatch(storage.n_cols(), storage.n_rows()));
177 
178  for (size_type j=0 ; j<n ; ++j)
179  {
180  number2 sigma = 0;
181  size_type i;
182  // sigma = ||v||^2
183  for (i=j ; i<m ; ++i)
184  sigma += storage(i,j)*storage(i,j);
185  // We are ready if the column is
186  // empty. Are we?
187  if (std::fabs(sigma) < 1.e-15) return;
188 
189  number2 s = (storage(j,j) < 0) ? std::sqrt(sigma) : -std::sqrt(sigma);
190  //
191  number2 beta = std::sqrt(1./(sigma-s*storage(j,j)));
192 
193  // Make column j the Householder
194  // vector, store first entry in
195  // diagonal
196  diagonal[j] = beta*(storage(j,j) - s);
197  storage(j,j) = s;
198 
199  for (i=j+1 ; i<m ; ++i)
200  storage(i,j) *= beta;
201 
202 
203  // For all subsequent columns do
204  // the Householder reflection
205  for (size_type k=j+1 ; k<n ; ++k)
206  {
207  number2 sum = diagonal[j]*storage(j,k);
208  for (i=j+1 ; i<m ; ++i)
209  sum += storage(i,j)*storage(i,k);
210 
211  storage(j,k) -= sum*this->diagonal[j];
212  for (i=j+1 ; i<m ; ++i)
213  storage(i,k) -= sum*storage(i,j);
214  }
215  }
216 }
217 
218 
219 
220 template <typename number>
221 template <typename number2>
223 {
224  initialize(M);
225 }
226 
227 
228 
229 template <typename number>
230 template <typename number2>
231 double
232 Householder<number>::least_squares (Vector<number2> &dst,
233  const Vector<number2> &src) const
234 {
235  Assert (!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
236  AssertDimension(dst.size(), storage.n());
237  AssertDimension(src.size(), storage.m());
238 
239  const size_type m = storage.m(), n = storage.n();
240 
242  typename VectorMemory<Vector<number2> >::Pointer aux (mem);
243  aux->reinit(src, true);
244  *aux = src;
245  // m > n, m = src.n, n = dst.n
246 
247  // Multiply Q_n ... Q_2 Q_1 src
248  // Where Q_i = I - v_i v_i^T
249  for (size_type j=0; j<n; ++j)
250  {
251  // sum = v_i^T dst
252  number2 sum = diagonal[j]* (*aux)(j);
253  for (size_type i=j+1 ; i<m ; ++i)
254  sum += static_cast<number2>(storage(i,j))*(*aux)(i);
255  // dst -= v * sum
256  (*aux)(j) -= sum*diagonal[j];
257  for (size_type i=j+1 ; i<m ; ++i)
258  (*aux)(i) -= sum*static_cast<number2>(storage(i,j));
259  }
260  // Compute norm of residual
261  number2 sum = 0.;
262  for (size_type i=n ; i<m ; ++i)
263  sum += (*aux)(i) * (*aux)(i);
265 
266  // Compute solution
267  storage.backward(dst, *aux);
268 
269  return std::sqrt(sum);
270 }
271 
272 
273 
274 template <typename number>
275 template <typename number2>
276 double
278  const BlockVector<number2> &src) const
279 {
280  Assert (!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
281  AssertDimension(dst.size(), storage.n());
282  AssertDimension(src.size(), storage.m());
283 
284  const size_type m = storage.m(), n = storage.n();
285 
287  typename VectorMemory<BlockVector<number2> >::Pointer aux (mem);
288  aux->reinit(src, true);
289  *aux = src;
290  // m > n, m = src.n, n = dst.n
291 
292  // Multiply Q_n ... Q_2 Q_1 src
293  // Where Q_i = I-v_i v_i^T
294  for (size_type j=0; j<n; ++j)
295  {
296  // sum = v_i^T dst
297  number2 sum = diagonal[j]* (*aux)(j);
298  for (size_type i=j+1 ; i<m ; ++i)
299  sum += storage(i,j)*(*aux)(i);
300  // dst -= v * sum
301  (*aux)(j) -= sum*diagonal[j];
302  for (size_type i=j+1 ; i<m ; ++i)
303  (*aux)(i) -= sum*storage(i,j);
304  }
305  // Compute norm of residual
306  number2 sum = 0.;
307  for (size_type i=n ; i<m ; ++i)
308  sum += (*aux)(i) * (*aux)(i);
310 
311  //backward works for
312  //Vectors only, so copy
313  //them before
314  Vector<number2> v_dst, v_aux;
315  v_dst = dst;
316  v_aux = *aux;
317  // Compute solution
318  storage.backward(v_dst, v_aux);
319  //copy the result back
320  //to the BlockVector
321  dst = v_dst;
322 
323  return std::sqrt(sum);
324 }
325 
326 
327 template <typename number>
328 template <class VectorType>
329 void
330 Householder<number>::vmult (VectorType &dst, const VectorType &src) const
331 {
332  least_squares (dst, src);
333 }
334 
335 
336 template <typename number>
337 template <class VectorType>
338 void
339 Householder<number>::Tvmult (VectorType &, const VectorType &) const
340 {
341  Assert(false, ExcNotImplemented());
342 }
343 
344 
345 
346 #endif // DOXYGEN
347 
348 DEAL_II_NAMESPACE_CLOSE
349 
350 #endif
static ::ExceptionBase & ExcEmptyMatrix()
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
void Tvmult(VectorType &dst, const VectorType &src) const
Matrix is diagonal.
types::global_dof_index size_type
Definition: householder.h:84
unsigned int global_dof_index
Definition: types.h:88
void reinit(const TableIndices< N > &new_size, const bool omit_default_initialization=false)
#define Assert(cond, exc)
Definition: exceptions.h:1142
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void vmult(VectorType &dst, const VectorType &src) const
FullMatrix< double > storage
Definition: householder.h:153
SymmetricTensor< rank, dim, Number > sum(const SymmetricTensor< rank, dim, Number > &local, const MPI_Comm &mpi_communicator)
std::vector< number > diagonal
Definition: householder.h:148
void initialize(const FullMatrix< number2 > &A)
double least_squares(Vector< number2 > &dst, const Vector< number2 > &src) const
static ::ExceptionBase & ExcNotImplemented()
#define AssertIsFinite(number)
Definition: exceptions.h:1299
Householder()=default