Reference documentation for deal.II version 8.4.2
trilinos_solver.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2014 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/lac/trilinos_solver.h>
17 
18 #ifdef DEAL_II_WITH_TRILINOS
19 
20 # include <deal.II/base/conditional_ostream.h>
21 # include <deal.II/lac/trilinos_sparse_matrix.h>
22 # include <deal.II/lac/trilinos_vector_base.h>
23 # include <deal.II/lac/trilinos_precondition.h>
24 
25 # include <cmath>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
29 namespace TrilinosWrappers
30 {
31 
32  SolverBase::AdditionalData::AdditionalData (const bool output_solver_details,
33  const unsigned int gmres_restart_parameter)
34  :
35  output_solver_details (output_solver_details),
36  gmres_restart_parameter (gmres_restart_parameter)
37  {}
38 
39 
40 
42  :
43  solver_name (gmres),
44  solver_control (cn)
45  {}
46 
47 
48 
50  SolverControl &cn)
51  :
52  solver_name (solver_name),
53  solver_control (cn)
54  {}
55 
56 
57 
59  {}
60 
61 
62 
65  {
66  return solver_control;
67  }
68 
69 
70 
71  void
73  VectorBase &x,
74  const VectorBase &b,
75  const PreconditionBase &preconditioner)
76  {
77  linear_problem.reset();
78 
79  // We need an Epetra_LinearProblem object to let the AztecOO solver know
80  // about the matrix and vectors.
81  linear_problem.reset
82  (new Epetra_LinearProblem(const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
83  &x.trilinos_vector(),
84  const_cast<Epetra_MultiVector *>(&b.trilinos_vector())));
85 
86  do_solve(preconditioner);
87  }
88 
89 
90 
91  void
92  SolverBase::solve (Epetra_Operator &A,
93  VectorBase &x,
94  const VectorBase &b,
95  const PreconditionBase &preconditioner)
96  {
97  linear_problem.reset();
98 
99  // We need an Epetra_LinearProblem object to let the AztecOO solver know
100  // about the matrix and vectors.
101  linear_problem.reset
102  (new Epetra_LinearProblem(&A,
103  &x.trilinos_vector(),
104  const_cast<Epetra_MultiVector *>(&b.trilinos_vector())));
105 
106  do_solve(preconditioner);
107  }
108 
109 
110 
111  void
113  ::Vector<double> &x,
114  const ::Vector<double> &b,
115  const PreconditionBase &preconditioner)
116  {
117  linear_problem.reset();
118 
119  // In case we call the solver with deal.II vectors, we create views of the
120  // vectors in Epetra format.
121  Assert (x.size() == A.n(),
122  ExcDimensionMismatch(x.size(), A.n()));
123  Assert (b.size() == A.m(),
124  ExcDimensionMismatch(b.size(), A.m()));
125  Assert (A.local_range ().second == A.m(),
126  ExcMessage ("Can only work in serial when using deal.II vectors."));
127  Assert (A.trilinos_matrix().Filled(),
128  ExcMessage ("Matrix is not compressed. Call compress() method."));
129 
130  Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
131  Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
132 
133  // We need an Epetra_LinearProblem object to let the AztecOO solver know
134  // about the matrix and vectors.
135  linear_problem.reset (new Epetra_LinearProblem
136  (const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
137  &ep_x, &ep_b));
138 
139  do_solve(preconditioner);
140  }
141 
142 
143 
144  void
145  SolverBase::solve (Epetra_Operator &A,
146  ::Vector<double> &x,
147  const ::Vector<double> &b,
148  const PreconditionBase &preconditioner)
149  {
150  linear_problem.reset();
151 
152  Epetra_Vector ep_x (View, A.OperatorDomainMap(), x.begin());
153  Epetra_Vector ep_b (View, A.OperatorRangeMap(), const_cast<double *>(b.begin()));
154 
155  // We need an Epetra_LinearProblem object to let the AztecOO solver know
156  // about the matrix and vectors.
157  linear_problem.reset (new Epetra_LinearProblem(&A,&ep_x, &ep_b));
158 
159  do_solve(preconditioner);
160  }
161 
162 
163 
164  void
167  const ::parallel::distributed::Vector<double> &b,
168  const PreconditionBase &preconditioner)
169  {
170  linear_problem.reset();
171 
172  // In case we call the solver with deal.II vectors, we create views of the
173  // vectors in Epetra format.
174  AssertDimension (static_cast<TrilinosWrappers::types::int_type>(x.local_size()),
175  A.domain_partitioner().NumMyElements());
176  AssertDimension (static_cast<TrilinosWrappers::types::int_type>(b.local_size()),
177  A.range_partitioner().NumMyElements());
178 
179  Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
180  Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
181 
182  // We need an Epetra_LinearProblem object to let the AztecOO solver know
183  // about the matrix and vectors.
184  linear_problem.reset (new Epetra_LinearProblem
185  (const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
186  &ep_x, &ep_b));
187 
188  do_solve(preconditioner);
189  }
190 
191 
192 
193  void
194  SolverBase::solve (Epetra_Operator &A,
196  const ::parallel::distributed::Vector<double> &b,
197  const PreconditionBase &preconditioner)
198  {
199  linear_problem.reset();
200 
201  AssertDimension (static_cast<TrilinosWrappers::types::int_type>(x.local_size()),
202  A.OperatorDomainMap().NumMyElements());
203  AssertDimension (static_cast<TrilinosWrappers::types::int_type>(b.local_size()),
204  A.OperatorRangeMap().NumMyElements());
205 
206  Epetra_Vector ep_x (View, A.OperatorDomainMap(), x.begin());
207  Epetra_Vector ep_b (View, A.OperatorRangeMap(), const_cast<double *>(b.begin()));
208 
209  // We need an Epetra_LinearProblem object to let the AztecOO solver know
210  // about the matrix and vectors.
211  linear_problem.reset (new Epetra_LinearProblem(&A,&ep_x, &ep_b));
212 
213  do_solve(preconditioner);
214  }
215 
216 
217 
218  void
219  SolverBase::do_solve(const PreconditionBase &preconditioner)
220  {
221  int ierr;
222 
223  // Next we can allocate the AztecOO solver...
224  solver.SetProblem(*linear_problem);
225 
226  // ... and we can specify the solver to be used.
227  switch (solver_name)
228  {
229  case cg:
230  solver.SetAztecOption(AZ_solver, AZ_cg);
231  break;
232  case cgs:
233  solver.SetAztecOption(AZ_solver, AZ_cgs);
234  break;
235  case gmres:
236  solver.SetAztecOption(AZ_solver, AZ_gmres);
237  solver.SetAztecOption(AZ_kspace, additional_data.gmres_restart_parameter);
238  break;
239  case bicgstab:
240  solver.SetAztecOption(AZ_solver, AZ_bicgstab);
241  break;
242  case tfqmr:
243  solver.SetAztecOption(AZ_solver, AZ_tfqmr);
244  break;
245  default:
246  Assert (false, ExcNotImplemented());
247  }
248 
249  // Introduce the preconditioner, if the identity preconditioner is used,
250  // the precondioner is set to none, ...
251  if (preconditioner.preconditioner.use_count()!=0)
252  {
253  ierr = solver.SetPrecOperator (const_cast<Epetra_Operator *>
254  (preconditioner.preconditioner.get()));
255  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
256  }
257  else
258  solver.SetAztecOption(AZ_precond,AZ_none);
259 
260  // ... set some options, ...
261  solver.SetAztecOption (AZ_output, additional_data.output_solver_details ?
262  AZ_all : AZ_none);
263  solver.SetAztecOption (AZ_conv, AZ_noscaled);
264 
265  // ... and then solve!
266  ierr = solver.Iterate (solver_control.max_steps(),
268 
269  // report errors in more detail than just by checking whether the return
270  // status is zero or greater. the error strings are taken from the
271  // implementation of the AztecOO::Iterate function
272  switch (ierr)
273  {
274  case -1:
275  AssertThrow (false, ExcMessage("AztecOO::Iterate error code -1: "
276  "option not implemented"));
277  case -2:
278  AssertThrow (false, ExcMessage("AztecOO::Iterate error code -2: "
279  "numerical breakdown"));
280  case -3:
281  AssertThrow (false, ExcMessage("AztecOO::Iterate error code -3: "
282  "loss of precision"));
283  case -4:
284  AssertThrow (false, ExcMessage("AztecOO::Iterate error code -4: "
285  "GMRES Hessenberg ill-conditioned"));
286  default:
287  AssertThrow (ierr >= 0, ExcTrilinosError(ierr));
288  }
289 
290  // Finally, let the deal.II SolverControl object know what has
291  // happened. If the solve succeeded, the status of the solver control will
292  // turn into SolverControl::success.
293  solver_control.check (solver.NumIters(), solver.TrueResidual());
294 
298  }
299 
300 
301 
302 
303 
304  /* ---------------------- SolverCG ------------------------ */
305 
307  AdditionalData (const bool output_solver_details)
308  :
309  output_solver_details (output_solver_details)
310  {}
311 
312 
313 
315  const AdditionalData &data)
316  :
317  SolverBase (cn),
319  {
320  solver_name = cg;
321  }
322 
323 
324  /* ---------------------- SolverGMRES ------------------------ */
325 
327  AdditionalData (const bool output_solver_details,
328  const unsigned int restart_parameter)
329  :
330  output_solver_details (output_solver_details),
331  restart_parameter (restart_parameter)
332  {}
333 
334 
335 
337  const AdditionalData &data)
338  :
339  SolverBase (cn),
341  data.restart_parameter)
342  {
343  solver_name = gmres;
344  }
345 
346 
347  /* ---------------------- SolverBicgstab ------------------------ */
348 
350  AdditionalData (const bool output_solver_details)
351  :
352  output_solver_details (output_solver_details)
353  {}
354 
355 
356 
357 
359  const AdditionalData &data)
360  :
361  SolverBase (cn),
363  {
364  solver_name = bicgstab;
365  }
366 
367 
368  /* ---------------------- SolverCGS ------------------------ */
369 
371  AdditionalData (const bool output_solver_details)
372  :
373  output_solver_details (output_solver_details)
374  {}
375 
376 
377 
378 
380  const AdditionalData &data)
381  :
382  SolverBase (cn),
384  {
385  solver_name = cgs;
386  }
387 
388 
389  /* ---------------------- SolverTFQMR ------------------------ */
390 
392  AdditionalData (const bool output_solver_details)
393  :
394  output_solver_details (output_solver_details)
395  {}
396 
397 
398 
400  const AdditionalData &data)
401  :
402  SolverBase (cn),
404  {
405  solver_name = tfqmr;
406  }
407 
408 
409 
410  /* ---------------------- SolverDirect ------------------------ */
411 
413  AdditionalData (const bool output_solver_details,
414  const std::string &solver_type)
415  :
416  output_solver_details (output_solver_details),
417  solver_type(solver_type)
418  {}
419 
420 
421 
422 
424  const AdditionalData &data)
425  :
426  solver_control (cn),
428  {}
429 
430 
431 
433  {}
434 
435 
436 
437  SolverControl &
439  {
440  return solver_control;
441  }
442 
443 
444 
445  void
447  {
448  // Fetch return value of Amesos Solver functions
449  int ierr;
450 
451  // First set whether we want to print the solver information to screen or
452  // not.
453  ConditionalOStream verbose_cout (std::cout,
455 
456  solver.reset();
457 
458  // Next allocate the Amesos solver, this is done in two steps, first we
459  // create a solver Factory and and generate with that the concrete Amesos
460  // solver, if possible.
461  Amesos Factory;
462 
463  AssertThrow(
464  Factory.Query(additional_data.solver_type.c_str()),
465  ExcMessage (std::string ("You tried to select the solver type <") +
467  "> but this solver is not supported by Trilinos either "
468  "because it does not exist, or because Trilinos was not "
469  "configured for its use.")
470  );
471 
472  solver.reset (
473  Factory.Create(additional_data.solver_type.c_str(), *linear_problem)
474  );
475 
476  verbose_cout << "Starting symbolic factorization" << std::endl;
477  ierr = solver->SymbolicFactorization();
478  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
479 
480  verbose_cout << "Starting numeric factorization" << std::endl;
481  ierr = solver->NumericFactorization();
482  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
483 
484  verbose_cout << "Starting solve" << std::endl;
485  ierr = solver->Solve();
486  AssertThrow (ierr == 0, ExcTrilinosError(ierr));
487 
488  // Finally, let the deal.II SolverControl object know what has
489  // happened. If the solve succeeded, the status of the solver control will
490  // turn into SolverControl::success.
491  solver_control.check (0, 0);
492 
496  }
497 
498 
499  void
501  VectorBase &x,
502  const VectorBase &b)
503  {
504  // We need an Epetra_LinearProblem object to let the Amesos solver know
505  // about the matrix and vectors.
506  linear_problem.reset
507  (new Epetra_LinearProblem(const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
508  &x.trilinos_vector(),
509  const_cast<Epetra_MultiVector *>(&b.trilinos_vector())));
510 
511  do_solve();
512  }
513 
514 
515 
516  void
518  ::Vector<double> &x,
519  const ::Vector<double> &b)
520  {
521 
522  // In case we call the solver with deal.II vectors, we create views of the
523  // vectors in Epetra format.
524  Assert (x.size() == A.n(),
525  ExcDimensionMismatch(x.size(), A.n()));
526  Assert (b.size() == A.m(),
527  ExcDimensionMismatch(b.size(), A.m()));
528  Assert (A.local_range ().second == A.m(),
529  ExcMessage ("Can only work in serial when using deal.II vectors."));
530  Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
531  Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
532 
533  // We need an Epetra_LinearProblem object to let the Amesos solver know
534  // about the matrix and vectors.
535  linear_problem.reset (new Epetra_LinearProblem
536  (const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
537  &ep_x, &ep_b));
538 
539  do_solve();
540  }
541 
542 
543 
544  void
547  const ::parallel::distributed::Vector<double> &b)
548  {
549  AssertDimension (static_cast<TrilinosWrappers::types::int_type>(x.local_size()),
550  A.domain_partitioner().NumMyElements());
551  AssertDimension (static_cast<TrilinosWrappers::types::int_type>(b.local_size()),
552  A.range_partitioner().NumMyElements());
553  Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
554  Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
555 
556  // We need an Epetra_LinearProblem object to let the Amesos solver know
557  // about the matrix and vectors.
558  linear_problem.reset (new Epetra_LinearProblem
559  (const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
560  &ep_x, &ep_b));
561 
562  do_solve();
563  }
564 
565 }
566 
567 DEAL_II_NAMESPACE_CLOSE
568 
569 #endif // DEAL_II_WITH_PETSC
SolverCG(SolverControl &cn, const AdditionalData &data=AdditionalData())
void do_solve(const PreconditionBase &preconditioner)
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1052
virtual State check(const unsigned int step, const double check_value)
std_cxx11::shared_ptr< Epetra_LinearProblem > linear_problem
void solve(const SparseMatrix &A, VectorBase &x, const VectorBase &b)
const AdditionalData additional_data
const AdditionalData additional_data
std_cxx11::shared_ptr< Epetra_LinearProblem > linear_problem
::ExceptionBase & ExcMessage(std::string arg1)
AdditionalData(const bool output_solver_details=false, const unsigned int restart_parameter=30)
const AdditionalData additional_data
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
const AdditionalData additional_data
void solve(const SparseMatrix &A, VectorBase &x, const VectorBase &b, const PreconditionBase &preconditioner)
std_cxx11::shared_ptr< Epetra_Operator > preconditioner
SolverCGS(SolverControl &cn, const AdditionalData &data=AdditionalData())
Stop iteration, goal reached.
SolverBase(SolverControl &cn)
#define Assert(cond, exc)
Definition: exceptions.h:294
AdditionalData(const bool output_solver_details=false)
SolverBicgstab(SolverControl &cn, const AdditionalData &data=AdditionalData())
std::size_t size() const
SolverControl & control() const
const Epetra_CrsMatrix & trilinos_matrix() const
iterator begin()
double last_value() const
SolverTFQMR(SolverControl &cn, const AdditionalData &data=AdditionalData())
AdditionalData(const bool output_solver_details=false)
double tolerance() const
unsigned int last_step() const
const AdditionalData additional_data
AdditionalData(const bool output_solver_details=false, const std::string &solver_type="Amesos_Klu")
SolverDirect(SolverControl &cn, const AdditionalData &data=AdditionalData())
State last_check() const
const AdditionalData additional_data
unsigned int max_steps() const
std_cxx11::shared_ptr< Amesos_BaseSolver > solver
std::pair< size_type, size_type > local_range() const
const Epetra_MultiVector & trilinos_vector() const
AdditionalData(const bool output_solver_details=false)
SolverControl & control() const
const Epetra_Map & domain_partitioner() const DEAL_II_DEPRECATED
AdditionalData(const bool output_solver_details=false, const unsigned int gmres_restart_parameter=30)
SolverGMRES(SolverControl &cn, const AdditionalData &data=AdditionalData())
const AdditionalData additional_data
size_type local_size() const
const Epetra_Map & range_partitioner() const DEAL_II_DEPRECATED
AdditionalData(const bool output_solver_details=false)