libMesh
trilinos_aztec_linear_solver.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #include "libmesh/libmesh_common.h"
21 
22 #ifdef LIBMESH_TRILINOS_HAVE_AZTECOO
23 
24 
25 // Local Includes
26 #include "libmesh/libmesh_logging.h"
27 #include "libmesh/enum_to_string.h"
28 #include "libmesh/trilinos_aztec_linear_solver.h"
29 #include "libmesh/trilinos_epetra_matrix.h"
30 #include "libmesh/trilinos_epetra_vector.h"
31 #include "libmesh/enum_preconditioner_type.h"
32 #include "libmesh/enum_solver_type.h"
33 #include "libmesh/enum_convergence_flags.h"
34 
35 namespace libMesh
36 {
37 
38 
39 /*----------------------- functions ----------------------------------*/
40 template <typename T>
42  LinearSolver<T>(comm)
43 {
44  if (this->n_processors() == 1)
46  else
48 }
49 
50 
51 
52 template <typename T>
54 {
55  if (this->initialized())
56  {
57  this->_is_initialized = false;
58 
59  // Mimic PETSc default solver and preconditioner
60  this->_solver_type = GMRES;
61 
62  if (this->n_processors() == 1)
63  this->_preconditioner_type = ILU_PRECOND;
64  else
65  this->_preconditioner_type = BLOCK_JACOBI_PRECOND;
66  }
67 }
68 
69 
70 
71 template <typename T>
72 void AztecLinearSolver<T>::init (const char * /*name*/)
73 {
74  // Initialize the data structures if not done so already.
75  if (!this->initialized())
76  {
77  this->_is_initialized = true;
78 
79  _linear_solver = new AztecOO();
80 
81  set_solver_type();
82 
83  switch(this->_preconditioner_type)
84  {
85  case ILU_PRECOND:
86  _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp);
87  _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_ilu);
88  break;
89 
91  _linear_solver->SetAztecOption(AZ_precond,AZ_Jacobi);
92  break;
93 
94  case ICC_PRECOND:
95  _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp);
96  _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_icc);
97  break;
98 
99  case LU_PRECOND:
100  _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp);
101  _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_lu);
102  break;
103 
104  default:
105  _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp);
106  _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_ilu);
107  }
108  }
109 }
110 
111 
112 
113 
114 template <typename T>
115 std::pair<unsigned int, Real>
117  SparseMatrix<T> & precond_in,
118  NumericVector<T> & solution_in,
119  NumericVector<T> & rhs_in,
120  const std::optional<double> tol,
121  const std::optional<unsigned int> m_its)
122 {
123  LOG_SCOPE("solve()", "AztecLinearSolver");
124 
125  // Make sure the data passed in are really of Epetra types
126  EpetraMatrix<T> * matrix = cast_ptr<EpetraMatrix<T> *>(&matrix_in);
127  EpetraMatrix<T> * precond = cast_ptr<EpetraMatrix<T> *>(&precond_in);
128  EpetraVector<T> * solution = cast_ptr<EpetraVector<T> *>(&solution_in);
129  EpetraVector<T> * rhs = cast_ptr<EpetraVector<T> *>(&rhs_in);
130 
131  this->init();
132 
133  // Close the matrices and vectors in case this wasn't already done.
134  matrix->close ();
135  precond->close ();
136  solution->close ();
137  rhs->close ();
138 
139  const int max_its = this->get_int_solver_setting("max_its", m_its);
140  const double rel_tol = this->get_real_solver_setting("rel_tol", tol);
141 
142  _linear_solver->SetAztecOption(AZ_max_iter,max_its);
143  _linear_solver->SetAztecParam(AZ_tol,rel_tol);
144 
145  Epetra_FECrsMatrix * emat = matrix->mat();
146  Epetra_Vector * esol = solution->vec();
147  Epetra_Vector * erhs = rhs->vec();
148 
149  _linear_solver->Iterate(emat, esol, erhs, max_its, rel_tol);
150 
151  // return the # of its. and the final residual norm.
152  return std::make_pair(_linear_solver->NumIters(), _linear_solver->TrueResidual());
153 }
154 
155 
156 
157 template <typename T>
158 std::pair<unsigned int, Real>
162  const std::optional<double>,
163  const std::optional<unsigned int>)
164 {
165  libmesh_not_implemented();
166 }
167 
168 
169 
170 template <typename T>
171 std::pair<unsigned int, Real>
173  const SparseMatrix<T> &,
176  const std::optional<double>,
177  const std::optional<unsigned int>)
178 {
179  libmesh_not_implemented();
180 }
181 
182 
183 
184 template <typename T>
185 void AztecLinearSolver<T>::get_residual_history(std::vector<double> & /* hist */)
186 {
187  libmesh_not_implemented();
188 }
189 
190 
191 
192 
193 template <typename T>
195 {
196  return _linear_solver->TrueResidual();
197 }
198 
199 
200 
201 template <typename T>
203 {
204  const double *status = _linear_solver->GetAztecStatus();
205 
206  switch (static_cast<int>(status[AZ_why]))
207  {
208  case AZ_normal :
209  libMesh::out << "AztecOO converged.\n";
210  break;
211  case AZ_maxits :
212  libMesh::out << "AztecOO failed to converge within maximum iterations.\n";
213  break;
214  case AZ_param :
215  libMesh::out << "AztecOO failed to support a user-requested parameter.\n";
216  break;
217  case AZ_breakdown :
218  libMesh::out << "AztecOO encountered numerical breakdown.\n";
219  break;
220  case AZ_loss :
221  libMesh::out << "AztecOO encountered numerical loss of precision.\n";
222  break;
223  case AZ_ill_cond :
224  libMesh::out << "AztecOO encountered an ill-conditioned GMRES Hessian.\n";
225  break;
226  default:
227  libMesh::out << "AztecOO reported an unrecognized condition.\n";
228  break;
229  }
230 }
231 
232 
233 
234 template <typename T>
236 {
237  const double *status = _linear_solver->GetAztecStatus();
238 
239  switch (static_cast<int>(status[AZ_why]))
240  {
241  case AZ_normal :
242  return CONVERGED_RTOL_NORMAL;
243  case AZ_maxits :
244  return DIVERGED_ITS;
245  default :
246  break;
247  }
248  return DIVERGED_NULL;
249 }
250 
251 
252 
253 template <typename T>
255 {
256  switch (this->_solver_type)
257  {
258  case CG:
259  _linear_solver->SetAztecOption(AZ_solver, AZ_cg); return;
260 
261  case CGS:
262  _linear_solver->SetAztecOption(AZ_solver, AZ_cgs); return;
263 
264  case TFQMR:
265  _linear_solver->SetAztecOption(AZ_solver, AZ_tfqmr); return;
266 
267  case BICGSTAB:
268  _linear_solver->SetAztecOption(AZ_solver, AZ_bicgstab); return;
269 
270  case GMRES:
271  _linear_solver->SetAztecOption(AZ_solver, AZ_gmres); return;
272 
273  default:
274  libMesh::err << "ERROR: Unsupported AztecOO Solver: "
275  << Utility::enum_to_string(this->_solver_type) << std::endl
276  << "Continuing with AztecOO defaults" << std::endl;
277  }
278 }
279 
280 //------------------------------------------------------------------
281 // Explicit instantiations
282 template class LIBMESH_EXPORT AztecLinearSolver<Number>;
283 
284 } // namespace libMesh
285 
286 
287 
288 #endif // #ifdef LIBMESH_TRILINOS_HAVE_AZTECOO
OStreamProxy err
This class provides a nice interface to the Trilinos Epetra_Vector object.
void get_residual_history(std::vector< double > &hist)
Fills the input vector with the sequence of residual norms from the latest iterative solve...
LinearConvergenceReason
Linear solver convergence flags (taken from the PETSc flags).
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
Definition: vector_fe_ex5.C:43
The libMesh namespace provides an interface to certain functionality in the library.
Generic sparse matrix.
Definition: vector_fe_ex5.C:45
MPI_Status status
This base class can be inherited from to provide interfaces to linear solvers from different packages...
Definition: linear_solver.h:59
processor_id_type n_processors() const
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:247
virtual void clear() override
Release all memory and clear data structures.
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
AztecLinearSolver(const libMesh::Parallel::Communicator &comm)
Constructor.
virtual std::pair< unsigned int, Real > solve(SparseMatrix< T > &matrix_in, NumericVector< T > &solution_in, NumericVector< T > &rhs_in, const std::optional< double > tol=std::nullopt, const std::optional< unsigned int > m_its=std::nullopt) override
Call the Aztec solver.
virtual void init(const char *name=nullptr) override
Initialize data structures if not done so already.
virtual void close() override
Calls the SparseMatrix&#39;s internal assembly routines, ensuring that the values are consistent across p...
std::string enum_to_string(const T e)
This class provides an interface to AztecOO iterative solvers that is compatible with the libMesh Lin...
void set_solver_type()
Tells AztecOO to use the user-specified solver stored in _solver_type.
virtual void print_converged_reason() const override
Prints a useful message about why the latest linear solve con(di)verged.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
OStreamProxy out
PreconditionerType _preconditioner_type
Enum stating with type of preconditioner to use.
virtual LinearConvergenceReason get_converged_reason() const override
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:266
Epetra_FECrsMatrix * mat()
Generic shell matrix, i.e.
This class provides a nice interface to the Epetra data structures for parallel, sparse matrices...