ASPECT
block_stokes_preconditioner.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2025 by the authors of the ASPECT code.
3 
4  This file is part of ASPECT.
5 
6  ASPECT is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2, or (at your option)
9  any later version.
10 
11  ASPECT is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with ASPECT; see the file LICENSE. If not see
18  <http://www.gnu.org/licenses/>.
19 */
20 #ifndef aspect_block_stokes_preconditioner_h
21 #define aspect_block_stokes_preconditioner_h
22 
23 #include <deal.II/lac/solver_bicgstab.h>
24 
25 namespace aspect
26 {
27 
28  namespace internal
29  {
36  template <class PreconditionerA, class VectorType, class ABlockType>
38  {
39  public:
50  InverseVelocityBlock(const ABlockType &matrix,
51  const PreconditionerA &preconditioner,
52  const bool do_solve_A,
53  const bool A_block_is_symmetric,
54  const double solver_tolerance);
55 
56  void vmult(VectorType &dst,
57  const VectorType &src) const;
58 
59  unsigned int n_iterations() const;
60 
61  private:
62  mutable unsigned int n_iterations_;
63  const ABlockType &matrix;
64  const PreconditionerA &preconditioner;
65  const bool do_solve_A;
67  const double solver_tolerance;
68  };
69 
70 
71 
72  template <class PreconditionerA,class VectorType, class ABlockType>
74  const ABlockType &matrix,
75  const PreconditionerA &preconditioner,
76  const bool do_solve_A,
77  const bool A_block_is_symmetric,
78  const double solver_tolerance)
79  : n_iterations_ (0),
80  matrix (matrix),
81  preconditioner (preconditioner),
82  do_solve_A (do_solve_A),
83  A_block_is_symmetric (A_block_is_symmetric),
84  solver_tolerance (solver_tolerance)
85  {}
86 
87 
88 
93  template <class PreconditionerA, class VectorType, class ABlockType>
95  const VectorType &src) const
96  {
97 
98  // Either solve with the top left block
99  // or just apply one preconditioner sweep (for the first few
100  // iterations of our two-stage outer GMRES iteration)
101  if (do_solve_A == true)
102  {
103  SolverControl solver_control(10000, src.l2_norm() * solver_tolerance);
104  PrimitiveVectorMemory<VectorType> mem;
105 
106  try
107  {
108  dst = 0.0;
109 
111  {
112  SolverCG<VectorType> solver(solver_control, mem);
113  solver.solve(matrix, dst, src, preconditioner);
114  }
115  else
116  {
117  // Use BiCGStab for non-symmetric matrices.
118  // BiCGStab can also solve indefinite systems if necessary.
119  // Do not compute the exact residual, as this
120  // is more expensive, and we only need an approximate solution.
121  SolverBicgstab<VectorType>
122  solver(solver_control,
123  mem,
124  typename SolverBicgstab<VectorType>::AdditionalData(/*exact_residual=*/ false));
125  solver.solve(matrix, dst, src, preconditioner);
126  }
127  n_iterations_ += solver_control.last_step();
128  }
129  catch (const std::exception &exc)
130  {
131  // if the solver fails, report the error from processor 0 with some additional
132  // information about its location, and throw a quiet exception on all other
133  // processors
134  Utilities::throw_linear_solver_failure_exception("iterative (top left) solver",
135  "BlockSchurPreconditioner::vmult",
136  std::vector<SolverControl> {solver_control},
137  exc,
138  src.get_mpi_communicator());
139  }
140  }
141  else
142  {
143  preconditioner.vmult (dst, src);
144  n_iterations_ += 1;
145  }
146  }
147 
148 
149 
150  template <class PreconditionerA, class VectorType, class ABlockType>
152  {
153  return n_iterations_;
154  }
155 
160  template <class AInvOperator, class SInvOperator, class BTOperator, class VectorType>
162 #if DEAL_II_VERSION_GTE(9,7,0)
163  EnableObserverPointer
164 #else
166 #endif
167 
168  {
169  public:
177  const AInvOperator &A_inverse_operator,
178  const SInvOperator &S_inverse_operator,
179  const BTOperator &BT_operator);
180 
184  void vmult (VectorType &dst,
185  const VectorType &src) const;
186 
187  private:
192  const AInvOperator &A_inverse_operator;
193  const SInvOperator &S_inverse_operator;
194  const BTOperator &BT_operator;
195  };
196 
197 
198  template <class AInvOperator, class SInvOperator, class BTOperator, class VectorType>
201  const AInvOperator &A_inverse_operator,
202  const SInvOperator &S_inverse_operator,
203  const BTOperator &BT_operator)
204  :
205  A_inverse_operator (A_inverse_operator),
206  S_inverse_operator (S_inverse_operator),
207  BT_operator (BT_operator)
208  {}
209 
210 
211 
212  template <class AInvOperator, class SInvOperator, class BTOperator, class VectorType>
213  void
215  vmult (VectorType &dst,
216  const VectorType &src) const
217  {
218  typename VectorType::BlockType utmp(src.block(0));
219 
220  // first apply the Schur Complement inverse operator.
221  {
222  S_inverse_operator.vmult(dst.block(1),src.block(1));
223  dst.block(1) *= -1.0;
224  }
225 
226  // apply the top right block
227  {
228  BT_operator.vmult(utmp, dst.block(1)); // B^T or J^{up}
229  utmp *= -1.0;
230  utmp += src.block(0);
231  }
232 
233  A_inverse_operator.vmult(dst.block(0), utmp);
234  }
235  }
236 }
237 
238 #endif
InverseVelocityBlock(const ABlockType &matrix, const PreconditionerA &preconditioner, const bool do_solve_A, const bool A_block_is_symmetric, const double solver_tolerance)
void throw_linear_solver_failure_exception(const std::string &solver_name, const std::string &function_name, const std::vector< SolverControl > &solver_controls, const std::exception &exc, const MPI_Comm mpi_communicator, const std::string &output_filename="")
void vmult(VectorType &dst, const VectorType &src) const
BlockSchurPreconditioner(const AInvOperator &A_inverse_operator, const SInvOperator &S_inverse_operator, const BTOperator &BT_operator)
Constructor.
void vmult(VectorType &dst, const VectorType &src) const