deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\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: Apache-2.0 WITH LLVM-exception OR 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// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_householder_h
14#define dealii_householder_h
15
16
17#include <deal.II/base/config.h>
18
20
21#include <cmath>
22#include <vector>
23
25
26
27// forward declarations
28#ifndef DOXYGEN
29template <typename number>
30class Vector;
31#endif
32
75template <typename number>
77{
78public:
83
87 Householder() = default;
88
92 template <typename number2>
94
100 template <typename number2>
101 void
103
114 template <typename number2>
115 number2
117
121 template <typename number2>
122 double
124 const BlockVector<number2> &src) const;
125
130 template <typename VectorType>
131 void
132 vmult(VectorType &dst, const VectorType &src) const;
133
138 template <typename VectorType>
139 void
140 Tvmult(VectorType &dst, const VectorType &src) const;
141
142
143private:
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
163template <typename number>
164template <typename number2>
165void
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::abs(sigma) < 1.e-15)
188 return;
189
190 number2 s;
192 s = storage(j, j).real() < 0 ? std::sqrt(sigma) : -std::sqrt(sigma);
193 else
194 s = storage(j, j) < 0 ? std::sqrt(sigma) : -std::sqrt(sigma);
195 //
196 number2 beta = std::sqrt(1. / (sigma - s * storage(j, j)));
197
198 // Make column j the Householder
199 // vector, store first entry in
200 // diagonal
201 diagonal[j] = beta * (storage(j, j) - s);
202 storage(j, j) = s;
203
204 for (i = j + 1; i < m; ++i)
205 storage(i, j) *= beta;
206
207
208 // For all subsequent columns do
209 // the Householder reflection
210 for (size_type k = j + 1; k < n; ++k)
211 {
212 number2 sum = diagonal[j] * storage(j, k);
213 for (i = j + 1; i < m; ++i)
214 sum += storage(i, j) * storage(i, k);
215
216 storage(j, k) -= sum * this->diagonal[j];
217 for (i = j + 1; i < m; ++i)
218 storage(i, k) -= sum * storage(i, j);
219 }
220 }
221}
222
223
224
225template <typename number>
226template <typename number2>
228{
229 initialize(M);
230}
231
232
233
234template <typename number>
235template <typename number2>
236number2
238 const Vector<number2> &src) const
239{
240 Assert(!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
241 AssertDimension(dst.size(), storage.n());
242 AssertDimension(src.size(), storage.m());
243
244 const size_type m = storage.m(), n = storage.n();
245
246 Vector<number2> aux(src);
247 // m > n, m = src.n, n = dst.n
248
249 // Multiply Q_n ... Q_2 Q_1 src
250 // Where Q_i = I - v_i v_i^T
251 for (size_type j = 0; j < n; ++j)
252 {
253 // sum = v_i^T dst
254 number2 sum = diagonal[j] * aux(j);
255 for (size_type i = j + 1; i < m; ++i)
256 sum += static_cast<number2>(storage(i, j)) * aux(i);
257 // dst -= v * sum
258 aux(j) -= sum * diagonal[j];
259 for (size_type i = j + 1; i < m; ++i)
260 aux(i) -= sum * static_cast<number2>(storage(i, j));
261 }
262 // Compute norm of residual
263 number2 sum = 0.;
264 for (size_type i = n; i < m; ++i)
265 sum += aux(i) * aux(i);
266 AssertIsFinite(sum);
267
268 // Compute solution
269 storage.backward(dst, aux);
270
271 return std::sqrt(sum);
272}
273
274
275
276template <typename number>
277template <typename number2>
278double
280 const BlockVector<number2> &src) const
281{
282 Assert(!storage.empty(), typename FullMatrix<number2>::ExcEmptyMatrix());
283 AssertDimension(dst.size(), storage.n());
284 AssertDimension(src.size(), storage.m());
285
286 const size_type m = storage.m(), n = storage.n();
287
289 aux.reinit(src, true);
290 aux = src;
291 // m > n, m = src.n, n = dst.n
292
293 // Multiply Q_n ... Q_2 Q_1 src
294 // Where Q_i = I-v_i v_i^T
295 for (size_type j = 0; j < n; ++j)
296 {
297 // sum = v_i^T dst
298 number2 sum = diagonal[j] * aux(j);
299 for (size_type i = j + 1; i < m; ++i)
300 sum += storage(i, j) * aux(i);
301 // dst -= v * sum
302 aux(j) -= sum * diagonal[j];
303 for (size_type i = j + 1; i < m; ++i)
304 aux(i) -= sum * storage(i, j);
305 }
306 // Compute norm of residual
307 number2 sum = 0.;
308 for (size_type i = n; i < m; ++i)
309 sum += *aux(i) * aux(i);
310 AssertIsFinite(sum);
311
312 // backward works for Vectors only, so copy them before
313 Vector<number2> v_dst, v_aux;
314 v_dst = dst;
315 v_aux = aux;
316 // Compute solution
317 storage.backward(v_dst, v_aux);
318 // copy the result back to the BlockVector
319 dst = v_dst;
320
321 return std::sqrt(sum);
322}
323
324
325template <typename number>
326template <typename VectorType>
327void
328Householder<number>::vmult(VectorType &dst, const VectorType &src) const
329{
330 least_squares(dst, src);
331}
332
333
334template <typename number>
335template <typename VectorType>
336void
337Householder<number>::Tvmult(VectorType &, const VectorType &) const
338{
340}
341
342
343
344#endif // DOXYGEN
345
347
348#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
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:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
#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:92