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  {
163  public:
171  const AInvOperator &A_inverse_operator,
172  const SInvOperator &S_inverse_operator,
173  const BTOperator &BT_operator);
174 
178  void vmult (VectorType &dst,
179  const VectorType &src) const;
180 
181  private:
186  const AInvOperator &A_inverse_operator;
187  const SInvOperator &S_inverse_operator;
188  const BTOperator &BT_operator;
189  };
190 
191 
192  template <class AInvOperator, class SInvOperator, class BTOperator, class VectorType>
195  const AInvOperator &A_inverse_operator,
196  const SInvOperator &S_inverse_operator,
197  const BTOperator &BT_operator)
198  :
199  A_inverse_operator (A_inverse_operator),
200  S_inverse_operator (S_inverse_operator),
201  BT_operator (BT_operator)
202  {}
203 
204 
205 
206  template <class AInvOperator, class SInvOperator, class BTOperator, class VectorType>
207  void
209  vmult (VectorType &dst,
210  const VectorType &src) const
211  {
212  typename VectorType::BlockType utmp(src.block(0));
213 
214  // first apply the Schur Complement inverse operator.
215  {
216  S_inverse_operator.vmult(dst.block(1),src.block(1));
217  dst.block(1) *= -1.0;
218  }
219 
220  // apply the top right block
221  {
222  BT_operator.vmult(utmp, dst.block(1)); // B^T or J^{up}
223  utmp *= -1.0;
224  utmp += src.block(0);
225  }
226 
227  A_inverse_operator.vmult(dst.block(0), utmp);
228  }
229  }
230 }
231 
232 #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