LifeV
SolverAztecOO.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  @file
29  @brief SolverAztecOO
30 
31  @author Simone Deparis <simone.deparis@epfl.ch>
32  @author Gilles Fourestey <gilles.fourestey@epfl.ch>
33  @contributor Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
34  @maintainer Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
35 
36  @date 08-11-2006
37  */
38 
39 #include <lifev/core/LifeV.hpp>
40 #include <lifev/core/algorithm/SolverAztecOO.hpp>
41 
42 namespace LifeV
43 {
44 
45 // ===================================================
46 // Constructors & Destructor
47 // ===================================================
48 SolverAztecOO::SolverAztecOO() :
50  M_solver (),
51  M_TrilinosParameterList(),
52  M_displayer ( new Displayer() ),
53  M_tolerance ( 0. ),
54  M_maxIter ( 0 ),
55  M_maxIterForReuse ( 0 ),
56  M_reusePreconditioner (false)
57 {
58  if ( M_displayer->isLeader() )
59  {
60  std::cerr << "Warning: SolverAztecOO is deprecated!" << std::endl
61  << " You should use LinearSolver instead!" << std::endl;
62  }
63 }
64 
65 SolverAztecOO::SolverAztecOO ( const std::shared_ptr<Epetra_Comm>& comm ) :
67  M_solver (),
68  M_TrilinosParameterList(),
69  M_displayer ( new Displayer (comm) ),
70  M_tolerance ( 0. ),
71  M_maxIter ( 0 ),
72  M_maxIterForReuse ( 0 ),
73  M_reusePreconditioner (false)
74 {
75  if ( M_displayer->isLeader() )
76  {
77  std::cerr << "Warning: SolverAztecOO is deprecated!" << std::endl
78  << " You should use LinearSolver instead!" << std::endl;
79  }
80 }
81 
82 // ===================================================
83 // Methods
84 // ===================================================
85 Int
86 SolverAztecOO::solve ( vector_type& solution, const vector_type& rhs )
87 {
88  M_solver.SetLHS ( &solution.epetraVector() );
89  // The Solver from Aztecoo takes a non const (because of rescaling?)
90  // We should be careful if you use scaling
91  Epetra_FEVector* rhsVectorPtr ( const_cast<Epetra_FEVector*> (&rhs.epetraVector() ) );
92  M_solver.SetRHS ( rhsVectorPtr );
93 
94  Int maxiter (M_maxIter);
95  Real mytol (M_tolerance);
96  Int status;
97 
98  if ( isPreconditionerSet() && M_preconditioner->preconditionerType().compare ("AztecOO") )
99  {
100  M_solver.SetPrecOperator (M_preconditioner->preconditioner() );
101  }
102 
103  status = M_solver.Iterate (maxiter, mytol);
104 
105 #ifdef HAVE_LIFEV_DEBUG
106  M_displayer->comm()->Barrier();
107  M_displayer->leaderPrint ( " o- Number of iterations = ", M_solver.NumIters() );
108  M_displayer->leaderPrint ( " o- Norm of the true residual = ", M_solver.TrueResidual() );
109  M_displayer->leaderPrint ( " o- Norm of the true ratio = ", M_solver.ScaledResidual() );
110 #endif
111 
112  /* try to solve again (reason may be:
113  -2 "Aztec status AZ_breakdown: numerical breakdown"
114  -3 "Aztec status AZ_loss: loss of precision"
115  -4 "Aztec status AZ_ill_cond: GMRES hessenberg ill-conditioned"
116  */
117  if ( status <= -2 )
118  {
119  maxiter = M_maxIter;
120  mytol = M_tolerance;
121  Int oldIter = M_solver.NumIters();
122  status = M_solver.Iterate (maxiter, mytol);
123 
124 #ifdef HAVE_LIFEV_DEBUG
125  M_displayer->comm()->Barrier();
126  M_displayer->leaderPrint ( " o- Second run: number of iterations = ", M_solver.NumIters() );
127  M_displayer->leaderPrint ( " o- Norm of the true residual = ", M_solver.TrueResidual() );
128  M_displayer->leaderPrint ( " o- Norm of the true ratio = ", M_solver.ScaledResidual() );
129 #endif
130  return ( M_solver.NumIters() + oldIter );
131  }
132 
133  return ( M_solver.NumIters() );
134 }
135 
136 Real
138 {
139  vector_type Ax ( solution.map() );
140  vector_type res ( rhs );
141 
142  M_solver.GetUserMatrix()->Apply ( solution.epetraVector(), Ax.epetraVector() );
143 
144  res.epetraVector().Update ( 1, Ax.epetraVector(), -1 );
145 
146  Real residual;
147 
148  res.norm2 ( &residual );
149 
150  return residual;
151 }
152 
153 std::string
155 {
156 
157  std::ostringstream stat;
158  std::string str;
159 
160  Real status[AZ_STATUS_SIZE];
161  aztecStatus ( status );
162 
163  if ( status[AZ_why] == AZ_normal )
164  {
165  stat << "Normal Convergence ";
166  }
167  else if ( status[AZ_why] == AZ_maxits )
168  {
169  stat << "Maximum iters reached ";
170  }
171  else if ( status[AZ_why] == AZ_loss )
172  {
173  stat << "Accuracy loss ";
174  }
175  else if ( status[AZ_why] == AZ_ill_cond )
176  {
177  stat << "Ill-conditioned ";
178  }
179  else if ( status[AZ_why] == AZ_breakdown )
180  {
181  stat << "Breakdown ";
182  }
183 
184  stat << std::setw (12) << "res = " << status[AZ_scaled_r];
185  stat << std::setw (4) << " " << (Int) status[AZ_its] << " iters. ";
186  stat << std::endl;
187 
188  str = stat.str();
189  return str;
190 }
191 
193  vector_type& solution,
194  matrix_ptrtype& baseMatrixForPreconditioner )
195 
196 {
197 
198  bool retry ( true );
199 
200  LifeChrono chrono;
201 
202  M_displayer->leaderPrint ( "SLV- Setting up the solver ... \n" );
203 
204  if ( baseMatrixForPreconditioner.get() == 0 )
205  {
206  M_displayer->leaderPrint ( "SLV- Warning: baseMatrixForPreconditioner is empty \n" );
207  }
208 
210  {
211  buildPreconditioner ( baseMatrixForPreconditioner );
212  // do not retry if I am recomputing the preconditioner
213  retry = false;
214  }
215  else
216  {
217  M_displayer->leaderPrint ( "SLV- Reusing precond ... \n" );
218  }
219 
220  Int numIter = solveSystem ( rhsFull, solution, M_preconditioner );
221 
222  // If we do not want to retry, return now.
223  // otherwise rebuild the preconditioner and solve again:
224  if ( numIter < 0 && retry )
225  {
226  chrono.start();
227 
228  M_displayer->leaderPrint ( "SLV- Iterative solver failed, numiter = " , - numIter );
229  M_displayer->leaderPrint ( "SLV- maxIterSolver = " , M_maxIter );
230  M_displayer->leaderPrint ( "SLV- retrying: " );
231 
232  buildPreconditioner ( baseMatrixForPreconditioner );
233 
234  chrono.stop();
235  M_displayer->leaderPrintMax ( "done in " , chrono.diff() );
236  // Solving again, but only once (retry = false)
237  numIter = solveSystem ( rhsFull, solution, M_preconditioner );
238 
239  if ( numIter < 0 )
240  {
241  M_displayer->leaderPrint ( " ERROR: Iterative solver failed again.\n" );
242  }
243  }
244 
245  if ( std::abs (numIter) > M_maxIterForReuse )
246  {
248  }
249 
250  return numIter;
251 }
252 
253 void SolverAztecOO::setupPreconditioner ( const GetPot& dataFile, const std::string& section )
254 {
255  std::string precType = dataFile ( (section + "/prectype").data(), "Ifpack" );
256  M_preconditioner.reset ( PRECFactory::instance().createObject ( precType ) );
257 
258  ASSERT ( M_preconditioner.get() != 0, " Preconditioner not set" );
259  M_preconditioner->setSolver ( *this );
260  M_preconditioner->setDataFromGetPot ( dataFile, section );
261 }
262 
264 {
265  LifeChrono chrono;
266  Real condest (-1);
267 
268  chrono.start();
269 
270  M_displayer->leaderPrint ( "SLV- Computing the precond ... " );
271 
272  M_preconditioner->buildPreconditioner ( preconditioner );
273 
274  condest = M_preconditioner->condest();
275  chrono.stop();
276 
277  M_displayer->leaderPrintMax ( "done in " , chrono.diff() );
278  M_displayer->leaderPrint ( "SLV- Estimated condition number " , condest, "\n" );
279 }
280 
282 {
283  M_preconditioner->resetPreconditioner();
284 }
285 
286 bool
288 {
289  return ( M_preconditioner.get() != 0 && M_preconditioner->preconditionerCreated() );
290 }
291 
292 void
293 SolverAztecOO::showMe ( std::ostream& output ) const
294 {
295  output << "showMe must be implemented for the SolverAztecOO class" << std::endl;
296 }
297 
298 // ===================================================
299 // Set Methods
300 // ===================================================
301 void
302 SolverAztecOO::setCommunicator ( const std::shared_ptr<Epetra_Comm>& comm )
303 {
304  M_displayer->setCommunicator ( comm );
305 }
306 
308 {
309  M_matrix = matrix.matrixPtr();
310  M_solver.SetUserMatrix ( M_matrix.get() );
311 }
312 
313 void
314 SolverAztecOO::setOperator ( Epetra_Operator& oper )
315 {
316  M_solver.SetUserOperator ( &oper );
317 }
318 
319 void
321 {
322  M_preconditioner = preconditioner;
323 }
324 
325 void
327 {
328  M_solver.SetPrecOperator ( preconditioner.get() );
329 }
330 
331 void
332 SolverAztecOO::setDataFromGetPot ( const GetPot& dataFile, const std::string& section )
333 {
334  // SOLVER PARAMETERS
335 
336  // Solver type
337  M_TrilinosParameterList.set ( "solver", dataFile ( ( section + "/solver" ).data(), "gmres" ) );
338 
339  // Residual expression
340  M_TrilinosParameterList.set ( "conv", dataFile ( ( section + "/conv" ).data(), "rhs" ) );
341 
342  // Scaling
343  M_TrilinosParameterList.set ( "scaling", dataFile ( ( section + "/scaling" ).data(), "none" ) );
344 
345  // Output
346  M_TrilinosParameterList.set ( "output", dataFile ( ( section + "/output" ).data(), "all" ) );
347 
348  // Tolerance
349  M_tolerance = dataFile ( ( section + "/tol" ).data(), 1.e-6 );
350  M_TrilinosParameterList.set ( "tol", M_tolerance );
351 
352  // Maximum Number of iterations
353  M_maxIter = dataFile ( ( section + "/max_iter" ).data(), 200 );
354  M_maxIterForReuse = dataFile ( ( section + "/max_iter_reuse").data(), static_cast<Int> ( M_maxIter * 8. / 10.) );
355  M_reusePreconditioner = dataFile ( (section + "/reuse").data(), M_reusePreconditioner );
356 
357  M_TrilinosParameterList.set ( "max_iter", M_maxIter );
358 
359  // GMRES PARAMETERS
360 
361  // Krylov space dimension
362  M_TrilinosParameterList.set ( "kspace", dataFile ( ( section + "/kspace" ).data(), M_maxIter ) );
363 
364  // Gram-Schmidt algorithm
365  M_TrilinosParameterList.set ( "orthog", dataFile ( ( section + "/orthog" ).data(), AZ_classic ) );
366 
367  // r-vector
368  M_TrilinosParameterList.set ( "aux_vec", dataFile ( ( section + "/aux_vec" ).data(), AZ_resid ) );
369 
370 
371  // SET PARAMETERS
372  setParameters ( false );
373 }
374 
375 void
376 SolverAztecOO::setParameters ( bool cerrWarningIfUnused )
377 {
378  M_solver.SetParameters ( M_TrilinosParameterList, cerrWarningIfUnused );
379 }
380 
381 void
382 SolverAztecOO::setTolerance ( const Real tolerance )
383 {
384  if ( tolerance > 0 )
385  {
386  M_tolerance = tolerance;
387  M_TrilinosParameterList.set ( "tol", M_tolerance );
388  }
389 }
390 
391 void
393 {
394  if ( maxIter >= 0 )
395  {
396  M_maxIter = maxIter;
397  M_TrilinosParameterList.set ( "max_iter", M_maxIter );
398  }
399 }
400 
401 void
402 SolverAztecOO::setReusePreconditioner ( const bool reusePreconditioner )
403 {
404  M_reusePreconditioner = reusePreconditioner;
405 }
406 
409 {
410  return M_displayer;
411 }
412 
413 // ===================================================
414 // Get Methods
415 // ===================================================
416 Int
418 {
419  return M_solver.NumIters();
420 }
421 
422 Int
424 {
425  return M_maxIter;
426 }
427 
428 
429 Real
431 {
432  return M_solver.TrueResidual();
433 }
434 
437 {
438  return M_preconditioner;
439 }
440 
441 void
443 {
444  M_solver.GetAllAztecStatus ( status );
445 }
446 
449 {
450  return M_TrilinosParameterList;
451 }
452 
453 AztecOO&
455 {
456  return M_solver;
457 }
458 
459 } // namespace LifeV
Real computeResidual(vector_type &solution, vector_type &rhs)
Compute the residual.
std::string printStatus()
return the Aztec status
void start()
Start the timer.
Definition: LifeChrono.hpp:93
std::shared_ptr< prec_raw_type > prec_type
Real trueResidual()
Return the true residual.
SolverAztecOO - Class to wrap linear solver.
Int numIterations() const
Return the total number of iterations.
void setMaxNumIterations(const Int maxIter=-1)
Set the tolerance and the maximum number of iterations.
Int solve(vector_type &solution, const vector_type &rhs)
Solve the problem .
VectorEpetra vector_type
void showMe(std::ostream &output=std::cout) const
Print informations about the solver.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
void aztecStatus(Real status[AZ_STATUS_SIZE])
Return the AztecStatus.
VectorEpetra(const MapEpetra &map, const MapEpetraType &mapType=Unique, const combineMode_Type combineMode=Add)
Constructor - Using Maps.
void updateInverseJacobian(const UInt &iQuadPt)
void setOperator(Epetra_Operator &oper)
Method to set a general linear operator (of class derived from Epetra_Operator) defining the linear s...
void setReusePreconditioner(const bool reusePreconditioner)
Specify if the preconditioner should be reuse or not.
void norm2(Real *result) const
Compute and store the norm 2 in the given pointed variable.
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
Teuchos::ParameterList & getParametersList()
Return a Teuchos parameters list.
void setCommunicator(const std::shared_ptr< Epetra_Comm > &comm)
Method to set communicator for Displayer (for empty constructor)
std::shared_ptr< Epetra_Operator > comp_prec_type
const MapEpetra & map() const
Return the MapEpetra of the vector.
AztecOO & solver()
Return a reference on the AztecOO solver.
bool isPreconditionerSet() const
Return true if preconditioner has been setted.
prec_type & preconditioner()
Method to get a shared pointer to the preconditioner (of type derived from Preconditioner)*/.
void buildPreconditioner(matrix_ptrtype &baseMatrixForPreconditioner)
Builds the preconditioner starting from the matrix "baseMatrixForPreconditioner". ...
double Real
Generic real data.
Definition: LifeV.hpp:175
Int maxNumIterations() const
Return the maximum total number of iterations.
void stop()
Stop the timer.
Definition: LifeChrono.hpp:100
std::shared_ptr< matrix_type > matrix_ptrtype
void setParameters(bool cerrWarningIfUnused=false)
Set the current parameters with the internal parameters list.
void resetPreconditioner()
Delete the stored preconditioner.
VectorEpetra(const VectorEpetra &vector)
Copy constructor.
std::shared_ptr< Displayer > displayer()
Return the displayer.
void setTolerance(const Real tolerance)
Set the tolerance of the solver.
MatrixEpetra< Real > matrix_type
void setMatrix(matrix_type &matrix)
Method to set matrix from MatrixEpetra.
Int solveSystem(const vector_type &rhsFull, vector_type &solution, matrix_ptrtype &baseMatrixForPreconditioner)
Solves the system and returns the number of iterations.
void setPreconditioner(comp_prec_type &preconditioner)
Method to set a general Epetra_Operator as preconditioner.