deal.II version 9.7.0
\(\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
householder.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: 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// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_householder_h
16#define dealii_householder_h
17
18
19#include <deal.II/base/config.h>
20
22
23#include <cmath>
24#include <vector>
25
27
28
29// forward declarations
30#ifndef DOXYGEN
31template <typename number>
32class Vector;
33#endif
34
39
40
77template <typename number>
79{
80public:
85
89 Householder() = default;
90
94 template <typename number2>
96
102 template <typename number2>
103 void
105
116 template <typename number2>
117 number2
119
123 template <typename number2>
124 double
126 const BlockVector<number2> &src) const;
127
132 template <typename VectorType>
133 void
134 vmult(VectorType &dst, const VectorType &src) const;
135
140 template <typename VectorType>
141 void
142 Tvmult(VectorType &dst, const VectorType &src) const;
143
144
145private:
150 std::vector<number> diagonal;
151
156};
157
159
160#ifndef DOXYGEN
161/*-------------------------Inline functions -------------------------------*/
162
163// QR-transformation cf. Stoer 1 4.8.2 (p. 191)
164
165template <typename number>
166template <typename number2>
167void
169{
170 const size_type m = M.n_rows(), n = M.n_cols();
171 storage.reinit(m, n);
172 storage.fill(M);
173 Assert(!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
174 diagonal.resize(m);
175
176 // m > n, src.n() = m
177 Assert(storage.n_cols() <= storage.n_rows(),
178 ExcDimensionMismatch(storage.n_cols(), storage.n_rows()));
179
180 for (size_type j = 0; j < n; ++j)
181 {
182 number2 sigma = 0;
183 size_type i;
184 // sigma = ||v||^2
185 for (i = j; i < m; ++i)
186 sigma += storage(i, j) * storage(i, j);
187 // We are ready if the column is
188 // empty. Are we?
189 if (std::abs(sigma) < 1.e-15)
190 return;
191
192 number2 s;
194 s = storage(j, j).real() < 0 ? std::sqrt(sigma) : -std::sqrt(sigma);
195 else
196 s = storage(j, j) < 0 ? std::sqrt(sigma) : -std::sqrt(sigma);
197 //
198 number2 beta = std::sqrt(1. / (sigma - s * storage(j, j)));
199
200 // Make column j the Householder
201 // vector, store first entry in
202 // diagonal
203 diagonal[j] = beta * (storage(j, j) - s);
204 storage(j, j) = s;
205
206 for (i = j + 1; i < m; ++i)
207 storage(i, j) *= beta;
208
209
210 // For all subsequent columns do
211 // the Householder reflection
212 for (size_type k = j + 1; k < n; ++k)
213 {
214 number2 sum = diagonal[j] * storage(j, k);
215 for (i = j + 1; i < m; ++i)
216 sum += storage(i, j) * storage(i, k);
217
218 storage(j, k) -= sum * this->diagonal[j];
219 for (i = j + 1; i < m; ++i)
220 storage(i, k) -= sum * storage(i, j);
221 }
222 }
223}
224
225
226
227template <typename number>
228template <typename number2>
230{
231 initialize(M);
232}
233
234
235
236template <typename number>
237template <typename number2>
238number2
240 const Vector<number2> &src) const
241{
242 Assert(!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
243 AssertDimension(dst.size(), storage.n());
244 AssertDimension(src.size(), storage.m());
245
246 const size_type m = storage.m(), n = storage.n();
247
248 Vector<number2> aux(src);
249 // m > n, m = src.n, n = dst.n
250
251 // Multiply Q_n ... Q_2 Q_1 src
252 // Where Q_i = I - v_i v_i^T
253 for (size_type j = 0; j < n; ++j)
254 {
255 // sum = v_i^T dst
256 number2 sum = diagonal[j] * aux(j);
257 for (size_type i = j + 1; i < m; ++i)
258 sum += static_cast<number2>(storage(i, j)) * aux(i);
259 // dst -= v * sum
260 aux(j) -= sum * diagonal[j];
261 for (size_type i = j + 1; i < m; ++i)
262 aux(i) -= sum * static_cast<number2>(storage(i, j));
263 }
264 // Compute norm of residual
265 number2 sum = 0.;
266 for (size_type i = n; i < m; ++i)
267 sum += aux(i) * aux(i);
268 AssertIsFinite(sum);
269
270 // Compute solution
271 storage.backward(dst, aux);
272
273 return std::sqrt(sum);
274}
275
276
277
278template <typename number>
279template <typename number2>
280double
282 const BlockVector<number2> &src) const
283{
284 Assert(!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
285 AssertDimension(dst.size(), storage.n());
286 AssertDimension(src.size(), storage.m());
287
288 const size_type m = storage.m(), n = storage.n();
289
291 aux.reinit(src, true);
292 aux = src;
293 // m > n, m = src.n, n = dst.n
294
295 // Multiply Q_n ... Q_2 Q_1 src
296 // Where Q_i = I-v_i v_i^T
297 for (size_type j = 0; j < n; ++j)
298 {
299 // sum = v_i^T dst
300 number2 sum = diagonal[j] * aux(j);
301 for (size_type i = j + 1; i < m; ++i)
302 sum += storage(i, j) * aux(i);
303 // dst -= v * sum
304 aux(j) -= sum * diagonal[j];
305 for (size_type i = j + 1; i < m; ++i)
306 aux(i) -= sum * storage(i, j);
307 }
308 // Compute norm of residual
309 number2 sum = 0.;
310 for (size_type i = n; i < m; ++i)
311 sum += *aux(i) * aux(i);
312 AssertIsFinite(sum);
313
314 // backward works for Vectors only, so copy them before
315 Vector<number2> v_dst, v_aux;
316 v_dst = dst;
317 v_aux = aux;
318 // Compute solution
319 storage.backward(v_dst, v_aux);
320 // copy the result back to the BlockVector
321 dst = v_dst;
322
323 return std::sqrt(sum);
324}
325
326
327template <typename number>
328template <typename VectorType>
329void
330Householder<number>::vmult(VectorType &dst, const VectorType &src) const
331{
332 least_squares(dst, src);
333}
334
335
336template <typename number>
337template <typename VectorType>
338void
339Householder<number>::Tvmult(VectorType &, const VectorType &) const
340{
342}
343
344
345
346#endif // DOXYGEN
347
349
350#endif
virtual size_type size() const override
void reinit(const unsigned int n_blocks, const size_type block_size=0, const bool omit_zeroing_entries=false)
void fill(const FullMatrix< number2 > &src, const size_type dst_offset_i=0, const size_type dst_offset_j=0, const size_type src_offset_i=0, const size_type src_offset_j=0)
void vmult(VectorType &dst, const VectorType &src) const
double least_squares(BlockVector< number2 > &dst, const BlockVector< number2 > &src) const
void Tvmult(VectorType &dst, const VectorType &src) const
std::vector< number > diagonal
FullMatrix< number > storage
types::global_dof_index size_type
Definition householder.h:84
Householder()=default
Householder(const FullMatrix< number2 > &A)
void initialize(const FullMatrix< number2 > &A)
number2 least_squares(Vector< number2 > &dst, const Vector< number2 > &src) const
virtual size_type size() const override
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcEmptyMatrix()
#define Assert(cond, exc)
#define AssertIsFinite(number)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
@ diagonal
Matrix is diagonal.
T sum(const T &t, const MPI_Comm mpi_communicator)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
Definition types.h:94
static constexpr bool is_complex
Definition numbers.h:404