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
solver_minres.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) 2000 - 2026 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_solver_minres_h
14#define dealii_solver_minres_h
15
16
17#include <deal.II/base/config.h>
18
23
24#include <deal.II/lac/solver.h>
26
27#include <cmath>
28
30
67template <typename VectorType = Vector<double>>
69class SolverMinRes : public SolverBase<VectorType>
70{
71public:
77 {};
78
85
92
96 virtual ~SolverMinRes() override = default;
97
101 template <typename MatrixType, typename PreconditionerType>
105 void solve(const MatrixType &A,
106 VectorType &x,
107 const VectorType &b,
108 const PreconditionerType &preconditioner);
109
118 DeclExceptionMsg(ExcPreconditionerNotDefinite,
119 "The preconditioner for MinRes must be a symmetric and "
120 "definite operator, even though MinRes can solve linear "
121 "systems with symmetric and *indefinite* operators. "
122 "During iterations, MinRes has detected that the "
123 "preconditioner is apparently not definite.");
126protected:
130 virtual double
131 criterion();
132
138 virtual void
139 print_vectors(const unsigned int step,
140 const VectorType &x,
141 const VectorType &r,
142 const VectorType &d) const;
143
150 double res2;
151};
152
154/*------------------------- Implementation ----------------------------*/
155
156#ifndef DOXYGEN
157
158template <typename VectorType>
162 const AdditionalData &)
163 : SolverBase<VectorType>(cn, mem)
164 , res2(numbers::signaling_nan<double>())
165{}
166
167
168
169template <typename VectorType>
172 const AdditionalData &)
173 : SolverBase<VectorType>(cn)
174 , res2(numbers::signaling_nan<double>())
175{}
176
177
178
179template <typename VectorType>
182{
183 return res2;
184}
185
186
187template <typename VectorType>
189void SolverMinRes<VectorType>::print_vectors(const unsigned int,
190 const VectorType &,
191 const VectorType &,
192 const VectorType &) const
193{}
194
195
196
197template <typename VectorType>
199template <typename MatrixType, typename PreconditionerType>
203void SolverMinRes<VectorType>::solve(const MatrixType &A,
204 VectorType &x,
205 const VectorType &b,
206 const PreconditionerType &preconditioner)
207{
208 LogStream::Prefix prefix("minres");
209
210 // Memory allocation
211 typename VectorMemory<VectorType>::Pointer Vu0(this->memory);
212 typename VectorMemory<VectorType>::Pointer Vu1(this->memory);
213 typename VectorMemory<VectorType>::Pointer Vu2(this->memory);
214
215 typename VectorMemory<VectorType>::Pointer Vm0(this->memory);
216 typename VectorMemory<VectorType>::Pointer Vm1(this->memory);
217 typename VectorMemory<VectorType>::Pointer Vm2(this->memory);
218
219 typename VectorMemory<VectorType>::Pointer Vv(this->memory);
220
221 // define some aliases for simpler access
222 using vecptr = VectorType *;
223 vecptr u[3] = {Vu0.get(), Vu1.get(), Vu2.get()};
224 vecptr m[3] = {Vm0.get(), Vm1.get(), Vm2.get()};
225 VectorType &v = *Vv;
226
227 // resize the vectors, but do not set the values since they'd be overwritten
228 // soon anyway.
229 u[0]->reinit(b, true);
230 u[1]->reinit(b, true);
231 u[2]->reinit(b, true);
232 m[0]->reinit(b, true);
233 m[1]->reinit(b, true);
234 m[2]->reinit(b, true);
235 v.reinit(b, true);
236
237 // some values needed
238 double delta[3] = {0, 0, 0};
239 double f[2] = {0, 0};
240 double e[2] = {0, 0};
241
242 double r_l2 = 0;
243 double r0 = 0;
244 double tau = 0;
245 double c = 0;
246 double s = 0;
247 double d_ = 0;
248
249 // The iteration step.
250 unsigned int j = 1;
251
252
253 // Start of the solution process
254 A.vmult(*m[0], x);
255 *u[1] = b;
256 *u[1] -= *m[0];
257 // Precondition is applied.
258 // The preconditioner has to be
259 // positive definite and symmetric
260
261 // M v = u[1]
262 preconditioner.vmult(v, *u[1]);
263
264 delta[1] = v * (*u[1]);
265 // Preconditioner positive
266 Assert(delta[1] >= 0, ExcPreconditionerNotDefinite());
267
268 r0 = std::sqrt(delta[1]);
269 r_l2 = r0;
270
271
272 u[0]->reinit(b);
273 delta[0] = 1.;
274 m[0]->reinit(b);
275 m[1]->reinit(b);
276 m[2]->reinit(b);
277
278 SolverControl::State conv = this->iteration_status(0, r_l2, x);
279 while (conv == SolverControl::iterate)
280 {
281 const double beta = std::sqrt(delta[1]);
282 const double inv_beta = 1.0 / beta; // Compute inverse once
283 if (delta[1] != 0)
284 v *= inv_beta;
285 else
286 v.reinit(b);
287
288 A.vmult(*u[2], v);
289 u[2]->add(-beta / std::sqrt(delta[0]), *u[0]);
290
291 const double gamma = *u[2] * v;
292 u[2]->add(-gamma * inv_beta, *u[1]);
293 *m[0] = v;
294
295 // precondition: solve M v = u[2]
296 // Preconditioner has to be positive
297 // definite and symmetric.
298 preconditioner.vmult(v, *u[2]);
299
300 delta[2] = v * (*u[2]);
301
302 Assert(delta[2] >= 0, ExcPreconditionerNotDefinite());
303
304 if (j == 1)
305 {
306 d_ = gamma;
307 e[1] = std::sqrt(delta[2]);
308 }
309 if (j > 1)
310 {
311 d_ = s * e[0] - c * gamma;
312 e[0] = c * e[0] + s * gamma;
313 f[1] = s * std::sqrt(delta[2]);
314 e[1] = -c * std::sqrt(delta[2]);
315 }
316
317 const double d = std::sqrt(d_ * d_ + delta[2]);
318 const double inv_d = 1.0 / d; // Compute inverse once
319
320 if (j > 1)
321 tau *= s / c;
322 c = d_ * inv_d;
323 tau *= c;
324
325 s = std::sqrt(delta[2]) * inv_d;
326
327 if (j == 1)
328 tau = r0 * c;
329
330 m[0]->add(-e[0], *m[1]);
331 if (j > 1)
332 m[0]->add(-f[0], *m[2]);
333 *m[0] *= inv_d;
334 x.add(tau, *m[0]);
335 r_l2 *= std::fabs(s);
336
337 conv = this->iteration_status(j, r_l2, x);
338
339 // next iteration step
340 ++j;
341 // All vectors have to be shifted
342 // one iteration step.
343 // This should be changed one time.
344 swap(*m[2], *m[1]);
345 swap(*m[1], *m[0]);
346
347 // likewise, but reverse direction:
348 // u[0] = u[1];
349 // u[1] = u[2];
350 swap(*u[0], *u[1]);
351 swap(*u[1], *u[2]);
352
353 // these are scalars, so need
354 // to bother
355 f[0] = f[1];
356 e[0] = e[1];
357 delta[0] = delta[1];
358 delta[1] = delta[2];
359 }
360
361 // in case of failure: throw exception
364
365 // otherwise exit as normal
366}
367
368#endif // DOXYGEN
369
371
372#endif
*  *  for(const auto &cell :triangulation.active_cell_iterators())
@ iterate
Continue iteration.
@ success
Stop iteration, goal reached.
virtual ~SolverMinRes() override=default
SolverMinRes(SolverControl &cn, const AdditionalData &data=AdditionalData())
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
virtual void print_vectors(const unsigned int step, const VectorType &x, const VectorType &r, const VectorType &d) const
virtual double criterion()
SolverMinRes(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:249
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
#define DeclExceptionMsg(Exception, defaulttext)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:734
constexpr char A
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
long double gamma(const unsigned int n)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
void swap(ObserverPointer< T, P > &t1, ObserverPointer< T, Q > &t2)