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_bicgstab.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) 1998 - 2024 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_bicgstab_h
14#define dealii_solver_bicgstab_h
15
16
17#include <deal.II/base/config.h>
18
23
24#include <deal.II/lac/solver.h>
26
27#include <cmath>
28#include <limits>
29
31
76template <typename VectorType = Vector<double>>
78class SolverBicgstab : public SolverBase<VectorType>
79{
80public:
92 {
101 const bool exact_residual = true,
102 const double breakdown =
103 std::numeric_limits<typename VectorType::value_type>::min())
104 : exact_residual(exact_residual)
105 , breakdown(breakdown)
106 {}
114 double breakdown;
115 };
116
123
130
134 virtual ~SolverBicgstab() override = default;
135
139 template <typename MatrixType, typename PreconditionerType>
143 void solve(const MatrixType &A,
144 VectorType &x,
145 const VectorType &b,
146 const PreconditionerType &preconditioner);
147
148protected:
152 template <typename MatrixType>
153 double
154 criterion(const MatrixType &A,
155 const VectorType &x,
156 const VectorType &b,
157 VectorType &t);
158
164 virtual void
165 print_vectors(const unsigned int step,
166 const VectorType &x,
167 const VectorType &r,
168 const VectorType &d) const;
169
173 AdditionalData additional_data;
174
175private:
181 {
184 unsigned int last_step;
186
187 IterationResult(const bool breakdown,
188 const SolverControl::State state,
189 const unsigned int last_step,
190 const double last_residual);
191 };
192
197 template <typename MatrixType, typename PreconditionerType>
199 iterate(const MatrixType &A,
200 VectorType &x,
201 const VectorType &b,
202 const PreconditionerType &preconditioner,
203 const unsigned int step);
204};
205
206
208/*-------------------------Inline functions -------------------------------*/
209
210#ifndef DOXYGEN
211
212
213template <typename VectorType>
216 const bool breakdown,
217 const SolverControl::State state,
218 const unsigned int last_step,
219 const double last_residual)
220 : breakdown(breakdown)
221 , state(state)
222 , last_step(last_step)
223 , last_residual(last_residual)
224{}
225
226
227
228template <typename VectorType>
232 const AdditionalData &data)
233 : SolverBase<VectorType>(cn, mem)
234 , additional_data(data)
235{}
236
237
238
239template <typename VectorType>
242 const AdditionalData &data)
244 , additional_data(data)
245{}
246
247
248
249template <typename VectorType>
251template <typename MatrixType>
252double SolverBicgstab<VectorType>::criterion(const MatrixType &A,
253 const VectorType &x,
254 const VectorType &b,
255 VectorType &t)
256{
257 A.vmult(t, x);
258 return std::sqrt(t.add_and_dot(-1.0, b, t));
259}
260
261
262
263template <typename VectorType>
265void SolverBicgstab<VectorType>::print_vectors(const unsigned int,
266 const VectorType &,
267 const VectorType &,
268 const VectorType &) const
269{}
270
271
272
273template <typename VectorType>
275template <typename MatrixType, typename PreconditionerType>
277 SolverBicgstab<VectorType>::iterate(const MatrixType &A,
278 VectorType &x,
279 const VectorType &b,
280 const PreconditionerType &preconditioner,
281 const unsigned int last_step)
282{
283 // Allocate temporary memory.
284 typename VectorMemory<VectorType>::Pointer Vr(this->memory);
285 typename VectorMemory<VectorType>::Pointer Vrbar(this->memory);
286 typename VectorMemory<VectorType>::Pointer Vp(this->memory);
287 typename VectorMemory<VectorType>::Pointer Vy(this->memory);
288 typename VectorMemory<VectorType>::Pointer Vz(this->memory);
289 typename VectorMemory<VectorType>::Pointer Vt(this->memory);
290 typename VectorMemory<VectorType>::Pointer Vv(this->memory);
291
292 // Define a few aliases for simpler use of the vectors
293 VectorType &r = *Vr;
294 VectorType &rbar = *Vrbar;
295 VectorType &p = *Vp;
296 VectorType &y = *Vy;
297 VectorType &z = *Vz;
298 VectorType &t = *Vt;
299 VectorType &v = *Vv;
300
301 r.reinit(x, true);
302 rbar.reinit(x, true);
303 p.reinit(x, true);
304 y.reinit(x, true);
305 z.reinit(x, true);
306 t.reinit(x, true);
307 v.reinit(x, true);
308
309 using value_type = typename VectorType::value_type;
310 using real_type = typename numbers::NumberTraits<value_type>::real_type;
311
312 A.vmult(r, x);
313 r.sadd(-1., 1., b);
314 value_type res = r.l2_norm();
315
316 unsigned int step = last_step;
317
318 SolverControl::State state = this->iteration_status(step, res, x);
320 return IterationResult(false, state, step, res);
321
322 rbar = r;
323
324 value_type alpha = 1.;
325 value_type rho = 1.;
326 value_type omega = 1.;
327
328 do
329 {
330 ++step;
331
332 const value_type rhobar = (step == 1 + last_step) ? res * res : r * rbar;
333
334 if (std::fabs(rhobar) < additional_data.breakdown)
335 {
336 return IterationResult(true, state, step, res);
337 }
338
339 const value_type beta = rhobar * alpha / (rho * omega);
340 rho = rhobar;
341 if (step == last_step + 1)
342 {
343 p = r;
344 }
345 else
346 {
347 p.sadd(beta, 1., r);
348 p.add(-beta * omega, v);
349 }
350
351 preconditioner.vmult(y, p);
352 A.vmult(v, y);
353 const value_type rbar_dot_v = rbar * v;
354 if (std::fabs(rbar_dot_v) < additional_data.breakdown)
355 {
356 return IterationResult(true, state, step, res);
357 }
358
359 alpha = rho / rbar_dot_v;
360
361 res = std::sqrt(real_type(r.add_and_dot(-alpha, v, r)));
362
363 // check for early success, see the lac/bicgstab_early testcase as to
364 // why this is necessary
365 //
366 // note: the vector *Vx we pass to the iteration_status signal here is
367 // only the current approximation, not the one we will return with, which
368 // will be x=*Vx + alpha*y
369 if (this->iteration_status(step, res, x) == SolverControl::success)
370 {
371 x.add(alpha, y);
372 print_vectors(step, x, r, y);
373 return IterationResult(false, SolverControl::success, step, res);
374 }
375
376 preconditioner.vmult(z, r);
377 A.vmult(t, z);
378 const value_type t_dot_r = t * r;
379 const real_type t_squared = t * t;
380 if (t_squared < additional_data.breakdown)
381 {
382 return IterationResult(true, state, step, res);
383 }
384 omega = t_dot_r / t_squared;
385 x.add(alpha, y, omega, z);
386
387 if (additional_data.exact_residual)
388 {
389 r.add(-omega, t);
390 res = criterion(A, x, b, t);
391 }
392 else
393 res = std::sqrt(real_type(r.add_and_dot(-omega, t, r)));
394
395 state = this->iteration_status(step, res, x);
396 print_vectors(step, x, r, y);
397 }
398 while (state == SolverControl::iterate);
399
400 return IterationResult(false, state, step, res);
401}
402
403
404
405template <typename VectorType>
407template <typename MatrixType, typename PreconditionerType>
411void SolverBicgstab<VectorType>::solve(const MatrixType &A,
412 VectorType &x,
413 const VectorType &b,
414 const PreconditionerType &preconditioner)
415{
416 LogStream::Prefix prefix("Bicgstab");
417
418 IterationResult state(false, SolverControl::failure, 0, 0);
419 do
420 {
421 state = iterate(A, x, b, preconditioner, state.last_step);
422 }
423 while (state.state == SolverControl::iterate);
424
425 // In case of failure: throw exception
426 AssertThrow(state.state == SolverControl::success,
427 SolverControl::NoConvergence(state.last_step,
428 state.last_residual));
429 // Otherwise exit as normal
430}
431
432#endif // DOXYGEN
433
435
436#endif
double criterion(const MatrixType &A, const VectorType &x, const VectorType &b, VectorType &t)
virtual void print_vectors(const unsigned int step, const VectorType &x, const VectorType &r, const VectorType &d) const
virtual ~SolverBicgstab() override=default
SolverBicgstab(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
SolverBicgstab(SolverControl &cn, const AdditionalData &data=AdditionalData())
IterationResult iterate(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner, const unsigned int step)
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
@ iterate
Continue iteration.
@ success
Stop iteration, goal reached.
@ failure
Stop iteration, goal not reached.
#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 AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:734
constexpr char A
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
AdditionalData(const bool exact_residual=true, const double breakdown=std::numeric_limits< typename VectorType::value_type >::min())
IterationResult(const bool breakdown, const SolverControl::State state, const unsigned int last_step, const double last_residual)