Reference documentation for deal.II version 9.1.0-pre
trilinos_solver.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2018 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.md at
12 // the top level directory of deal.II.
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/base/std_cxx14/memory.h>
22 
23 # include <deal.II/lac/trilinos_precondition.h>
24 # include <deal.II/lac/trilinos_sparse_matrix.h>
25 # include <deal.II/lac/trilinos_vector.h>
26 
27 # include <AztecOO_StatusTest.h>
28 # include <AztecOO_StatusTestCombo.h>
29 # include <AztecOO_StatusTestMaxIters.h>
30 # include <AztecOO_StatusTestResNorm.h>
31 # include <AztecOO_StatusType.h>
32 
33 # include <cmath>
34 # include <limits>
35 
36 DEAL_II_NAMESPACE_OPEN
37 
38 namespace TrilinosWrappers
39 {
41  const bool output_solver_details,
42  const unsigned int gmres_restart_parameter)
43  : output_solver_details(output_solver_details)
44  , gmres_restart_parameter(gmres_restart_parameter)
45  {}
46 
47 
48 
50  : solver_name(gmres)
51  , solver_control(cn)
52  , additional_data(data)
53  {}
54 
55 
56 
58  SolverControl & cn,
59  const AdditionalData & data)
60  : solver_name(solver_name)
61  , solver_control(cn)
62  , additional_data(data)
63  {}
64 
65 
66 
69  {
70  return solver_control;
71  }
72 
73 
74 
75  void
77  MPI::Vector & x,
78  const MPI::Vector & b,
79  const PreconditionBase &preconditioner)
80  {
81  // We need an Epetra_LinearProblem object to let the AztecOO solver know
82  // about the matrix and vectors.
83  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
84  const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
85  &x.trilinos_vector(),
86  const_cast<Epetra_MultiVector *>(&b.trilinos_vector()));
87 
88  do_solve(preconditioner);
89  }
90 
91 
92 
93  // Note: "A" is set as a constant reference so that all patterns for ::solve
94  // can be used by the inverse_operator of LinearOperator
95  void
96  SolverBase::solve(const Epetra_Operator & A,
97  MPI::Vector & x,
98  const MPI::Vector & b,
99  const PreconditionBase &preconditioner)
100  {
101  // We need an Epetra_LinearProblem object to let the AztecOO solver know
102  // about the matrix and vectors.
103  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
104  const_cast<Epetra_Operator *>(&A),
105  &x.trilinos_vector(),
106  const_cast<Epetra_MultiVector *>(&b.trilinos_vector()));
107 
108  do_solve(preconditioner);
109  }
110 
111 
112 
113  // Note: "A" is set as a constant reference so that all patterns for ::solve
114  // can be used by the inverse_operator of LinearOperator
115  void
116  SolverBase::solve(const Epetra_Operator &A,
117  MPI::Vector & x,
118  const MPI::Vector & b,
119  const Epetra_Operator &preconditioner)
120  {
121  // We need an Epetra_LinearProblem object to let the AztecOO solver know
122  // about the matrix and vectors.
123  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
124  const_cast<Epetra_Operator *>(&A),
125  &x.trilinos_vector(),
126  const_cast<Epetra_MultiVector *>(&b.trilinos_vector()));
127 
128  do_solve(preconditioner);
129  }
130 
131 
132 
133  // Note: "A" is set as a constant reference so that all patterns for ::solve
134  // can be used by the inverse_operator of LinearOperator
135  void
136  SolverBase::solve(const Epetra_Operator & A,
137  Epetra_MultiVector & x,
138  const Epetra_MultiVector &b,
139  const PreconditionBase & preconditioner)
140  {
141  // We need an Epetra_LinearProblem object to let the AztecOO solver know
142  // about the matrix and vectors.
143  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
144  const_cast<Epetra_Operator *>(&A),
145  &x,
146  const_cast<Epetra_MultiVector *>(&b));
147 
148  do_solve(preconditioner);
149  }
150 
151 
152 
153  // Note: "A" is set as a constant reference so that all patterns for ::solve
154  // can be used by the inverse_operator of LinearOperator
155  void
156  SolverBase::solve(const Epetra_Operator & A,
157  Epetra_MultiVector & x,
158  const Epetra_MultiVector &b,
159  const Epetra_Operator & preconditioner)
160  {
161  // We need an Epetra_LinearProblem object to let the AztecOO solver know
162  // about the matrix and vectors.
163  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
164  const_cast<Epetra_Operator *>(&A),
165  &x,
166  const_cast<Epetra_MultiVector *>(&b));
167 
168  do_solve(preconditioner);
169  }
170 
171 
172 
173  void
175  ::Vector<double> & x,
176  const ::Vector<double> &b,
177  const PreconditionBase & preconditioner)
178  {
179  // In case we call the solver with deal.II vectors, we create views of the
180  // vectors in Epetra format.
181  Assert(x.size() == A.n(), ExcDimensionMismatch(x.size(), A.n()));
182  Assert(b.size() == A.m(), ExcDimensionMismatch(b.size(), A.m()));
183  Assert(A.local_range().second == A.m(),
184  ExcMessage("Can only work in serial when using deal.II vectors."));
185  Assert(A.trilinos_matrix().Filled(),
186  ExcMessage("Matrix is not compressed. Call compress() method."));
187 
188  Epetra_Vector ep_x(View, A.domain_partitioner(), x.begin());
189  Epetra_Vector ep_b(View,
190  A.range_partitioner(),
191  const_cast<double *>(b.begin()));
192 
193  // We need an Epetra_LinearProblem object to let the AztecOO solver know
194  // about the matrix and vectors.
195  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
196  const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()), &ep_x, &ep_b);
197 
198  do_solve(preconditioner);
199  }
200 
201 
202 
203  void
204  SolverBase::solve(Epetra_Operator & A,
205  ::Vector<double> & x,
206  const ::Vector<double> &b,
207  const PreconditionBase & preconditioner)
208  {
209  Epetra_Vector ep_x(View, A.OperatorDomainMap(), x.begin());
210  Epetra_Vector ep_b(View,
211  A.OperatorRangeMap(),
212  const_cast<double *>(b.begin()));
213 
214  // We need an Epetra_LinearProblem object to let the AztecOO solver know
215  // about the matrix and vectors.
217  std_cxx14::make_unique<Epetra_LinearProblem>(&A, &ep_x, &ep_b);
218 
219  do_solve(preconditioner);
220  }
221 
222 
223 
224  void
227  const ::LinearAlgebra::distributed::Vector<double> &b,
228  const PreconditionBase &preconditioner)
229  {
230  // In case we call the solver with deal.II vectors, we create views of the
231  // vectors in Epetra format.
232  AssertDimension(static_cast<TrilinosWrappers::types::int_type>(
233  x.local_size()),
234  A.domain_partitioner().NumMyElements());
235  AssertDimension(static_cast<TrilinosWrappers::types::int_type>(
236  b.local_size()),
237  A.range_partitioner().NumMyElements());
238 
239  Epetra_Vector ep_x(View, A.domain_partitioner(), x.begin());
240  Epetra_Vector ep_b(View,
241  A.range_partitioner(),
242  const_cast<double *>(b.begin()));
243 
244  // We need an Epetra_LinearProblem object to let the AztecOO solver know
245  // about the matrix and vectors.
246  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
247  const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()), &ep_x, &ep_b);
248 
249  do_solve(preconditioner);
250  }
251 
252 
253 
254  void
255  SolverBase::solve(Epetra_Operator & A,
257  const ::LinearAlgebra::distributed::Vector<double> &b,
258  const PreconditionBase &preconditioner)
259  {
260  AssertDimension(static_cast<TrilinosWrappers::types::int_type>(
261  x.local_size()),
262  A.OperatorDomainMap().NumMyElements());
263  AssertDimension(static_cast<TrilinosWrappers::types::int_type>(
264  b.local_size()),
265  A.OperatorRangeMap().NumMyElements());
266 
267  Epetra_Vector ep_x(View, A.OperatorDomainMap(), x.begin());
268  Epetra_Vector ep_b(View,
269  A.OperatorRangeMap(),
270  const_cast<double *>(b.begin()));
271 
272  // We need an Epetra_LinearProblem object to let the AztecOO solver know
273  // about the matrix and vectors.
275  std_cxx14::make_unique<Epetra_LinearProblem>(&A, &ep_x, &ep_b);
276 
277  do_solve(preconditioner);
278  }
279 
280 
281  namespace internal
282  {
283  namespace
284  {
285  double
286  compute_residual(const Epetra_MultiVector *const residual_vector)
287  {
288  Assert(residual_vector->NumVectors() == 1,
289  ExcMessage("Residual multivector holds more than one vector"));
290  TrilinosScalar res_l2_norm = 0.0;
291  const int ierr = residual_vector->Norm2(&res_l2_norm);
292  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
293  return res_l2_norm;
294  }
295 
296  class TrilinosReductionControl : public AztecOO_StatusTest
297  {
298  public:
299  TrilinosReductionControl(const int & max_steps,
300  const double & tolerance,
301  const double & reduction,
302  const Epetra_LinearProblem &linear_problem);
303 
304  virtual ~TrilinosReductionControl() override = default;
305 
306  virtual bool
307  ResidualVectorRequired() const override
308  {
309  return status_test_collection->ResidualVectorRequired();
310  }
311 
312  virtual AztecOO_StatusType
313  CheckStatus(int CurrentIter,
314  Epetra_MultiVector *CurrentResVector,
315  double CurrentResNormEst,
316  bool SolutionUpdated) override
317  {
318  // Note: CurrentResNormEst is set to -1.0 if no estimate of the
319  // residual value is available
320  current_residual =
321  (CurrentResNormEst < 0.0 ? compute_residual(CurrentResVector) :
322  CurrentResNormEst);
323  if (CurrentIter == 0)
324  initial_residual = current_residual;
325 
326  return status_test_collection->CheckStatus(CurrentIter,
327  CurrentResVector,
328  CurrentResNormEst,
329  SolutionUpdated);
330  }
331 
332  virtual AztecOO_StatusType
333  GetStatus() const override
334  {
335  return status_test_collection->GetStatus();
336  }
337 
338  virtual std::ostream &
339  Print(std::ostream &stream, int indent = 0) const override
340  {
341  return status_test_collection->Print(stream, indent);
342  }
343 
344  double
345  get_initial_residual() const
346  {
347  return initial_residual;
348  }
349 
350  double
351  get_current_residual() const
352  {
353  return current_residual;
354  }
355 
356  private:
357  double initial_residual;
358  double current_residual;
359  std::unique_ptr<AztecOO_StatusTestCombo> status_test_collection;
360  std::unique_ptr<AztecOO_StatusTestMaxIters> status_test_max_steps;
361  std::unique_ptr<AztecOO_StatusTestResNorm> status_test_abs_tol;
362  std::unique_ptr<AztecOO_StatusTestResNorm> status_test_rel_tol;
363  };
364 
365 
366  TrilinosReductionControl::TrilinosReductionControl(
367  const int & max_steps,
368  const double & tolerance,
369  const double & reduction,
370  const Epetra_LinearProblem &linear_problem)
371  : initial_residual(std::numeric_limits<double>::max())
372  , current_residual(std::numeric_limits<double>::max())
373  {
374  // Consider linear problem converged if any of the collection
375  // of criterion are met
376  status_test_collection =
377  std_cxx14::make_unique<AztecOO_StatusTestCombo>(
378  AztecOO_StatusTestCombo::OR);
379 
380  // Maximum number of iterations
381  Assert(max_steps >= 0, ExcInternalError());
382  status_test_max_steps =
383  std_cxx14::make_unique<AztecOO_StatusTestMaxIters>(max_steps);
384  status_test_collection->AddStatusTest(*status_test_max_steps);
385 
386  Assert(linear_problem.GetRHS()->NumVectors() == 1,
387  ExcMessage("RHS multivector holds more than one vector"));
388 
389  // Residual norm is below some absolute value
390  status_test_abs_tol = std_cxx14::make_unique<AztecOO_StatusTestResNorm>(
391  *linear_problem.GetOperator(),
392  *(linear_problem.GetLHS()->operator()(0)),
393  *(linear_problem.GetRHS()->operator()(0)),
394  tolerance);
395  status_test_abs_tol->DefineResForm(AztecOO_StatusTestResNorm::Explicit,
396  AztecOO_StatusTestResNorm::TwoNorm);
397  status_test_abs_tol->DefineScaleForm(
398  AztecOO_StatusTestResNorm::None, AztecOO_StatusTestResNorm::TwoNorm);
399  status_test_collection->AddStatusTest(*status_test_abs_tol);
400 
401  // Residual norm, scaled by some initial value, is below some threshold
402  status_test_rel_tol = std_cxx14::make_unique<AztecOO_StatusTestResNorm>(
403  *linear_problem.GetOperator(),
404  *(linear_problem.GetLHS()->operator()(0)),
405  *(linear_problem.GetRHS()->operator()(0)),
406  reduction);
407  status_test_rel_tol->DefineResForm(AztecOO_StatusTestResNorm::Explicit,
408  AztecOO_StatusTestResNorm::TwoNorm);
409  status_test_rel_tol->DefineScaleForm(
410  AztecOO_StatusTestResNorm::NormOfInitRes,
411  AztecOO_StatusTestResNorm::TwoNorm);
412  status_test_collection->AddStatusTest(*status_test_rel_tol);
413  }
414 
415  } // namespace
416  } // namespace internal
417 
418 
419  template <typename Preconditioner>
420  void
421  SolverBase::do_solve(const Preconditioner &preconditioner)
422  {
423  int ierr;
424 
425  // Next we can allocate the AztecOO solver...
426  solver.SetProblem(*linear_problem);
427 
428  // ... and we can specify the solver to be used.
429  switch (solver_name)
430  {
431  case cg:
432  solver.SetAztecOption(AZ_solver, AZ_cg);
433  break;
434  case cgs:
435  solver.SetAztecOption(AZ_solver, AZ_cgs);
436  break;
437  case gmres:
438  solver.SetAztecOption(AZ_solver, AZ_gmres);
439  solver.SetAztecOption(AZ_kspace,
441  break;
442  case bicgstab:
443  solver.SetAztecOption(AZ_solver, AZ_bicgstab);
444  break;
445  case tfqmr:
446  solver.SetAztecOption(AZ_solver, AZ_tfqmr);
447  break;
448  default:
449  Assert(false, ExcNotImplemented());
450  }
451 
452  // Set the preconditioner
453  set_preconditioner(solver, preconditioner);
454 
455  // ... set some options, ...
456  solver.SetAztecOption(AZ_output,
458  AZ_none);
459  solver.SetAztecOption(AZ_conv, AZ_noscaled);
460 
461  // By default, the Trilinos solver chooses convergence criterion based on
462  // the number of iterations made and an absolute tolerance.
463  // This implies that the use of the standard Trilinos convergence test
464  // actually coincides with ::IterationNumberControl because the
465  // solver, unless explicitly told otherwise, will Iterate() until a number
466  // of max_steps() are taken or an absolute tolerance() is attained.
467  // It is therefore suitable for use with both SolverControl or
468  // IterationNumberControl. The final check at the end will determine whether
469  // failure to converge to the defined residual norm constitutes failure
470  // (SolverControl) or is alright (IterationNumberControl).
471  // In the case that the SolverControl wants to perform ReductionControl,
472  // then we have to do a little extra something by prescribing a custom
473  // status test.
474  if (!status_test)
475  {
476  if (const ReductionControl *const reduction_control =
477  dynamic_cast<const ReductionControl *const>(&solver_control))
478  {
479  status_test =
480  std_cxx14::make_unique<internal::TrilinosReductionControl>(
481  reduction_control->max_steps(),
482  reduction_control->tolerance(),
483  reduction_control->reduction(),
484  *linear_problem);
485  solver.SetStatusTest(status_test.get());
486  }
487  }
488 
489  // ... and then solve!
490  ierr =
492 
493  // report errors in more detail than just by checking whether the return
494  // status is zero or greater. the error strings are taken from the
495  // implementation of the AztecOO::Iterate function
496  switch (ierr)
497  {
498  case -1:
499  AssertThrow(false,
500  ExcMessage("AztecOO::Iterate error code -1: "
501  "option not implemented"));
502  break;
503  case -2:
504  AssertThrow(false,
505  ExcMessage("AztecOO::Iterate error code -2: "
506  "numerical breakdown"));
507  break;
508  case -3:
509  AssertThrow(false,
510  ExcMessage("AztecOO::Iterate error code -3: "
511  "loss of precision"));
512  break;
513  case -4:
514  AssertThrow(false,
515  ExcMessage("AztecOO::Iterate error code -4: "
516  "GMRES Hessenberg ill-conditioned"));
517  break;
518  default:
519  AssertThrow(ierr >= 0, ExcTrilinosError(ierr));
520  }
521 
522  // Finally, let the deal.II SolverControl object know what has
523  // happened. If the solve succeeded, the status of the solver control will
524  // turn into SolverControl::success.
525  // If the residual is not computed/stored by the solver, as can happen for
526  // certain choices of solver or if a custom status test is set, then the
527  // result returned by TrueResidual() is equal to -1. In this case we must
528  // compute it ourself.
529  if (const internal::TrilinosReductionControl
530  *const reduction_control_status =
531  dynamic_cast<const internal::TrilinosReductionControl *const>(
532  status_test.get()))
533  {
534  Assert(dynamic_cast<const ReductionControl *const>(&solver_control),
535  ExcInternalError());
536 
537  // Check to see if solver converged in one step
538  // This can happen if the matrix is diagonal and a non-trivial
539  // preconditioner is used.
540  if (solver.NumIters() > 0)
541  {
542  // For ReductionControl, we must first register the initial residual
543  // value. This is the basis from which it will determine whether the
544  // current residual corresponds to a converged state.
546  0, reduction_control_status->get_initial_residual());
548  solver.NumIters(),
549  reduction_control_status->get_current_residual());
550  }
551  else
553  solver.NumIters(),
554  reduction_control_status->get_current_residual());
555  }
556  else
557  {
558  Assert(solver.TrueResidual() >= 0.0, ExcInternalError());
559  solver_control.check(solver.NumIters(), solver.TrueResidual());
560  }
561 
563  AssertThrow(false,
566  }
567 
568 
569 
570  template <>
571  void
573  const PreconditionBase &preconditioner)
574  {
575  // Introduce the preconditioner, if the identity preconditioner is used,
576  // the precondioner is set to none, ...
577  if (preconditioner.preconditioner.use_count() != 0)
578  {
579  const int ierr = solver.SetPrecOperator(
580  const_cast<Epetra_Operator *>(preconditioner.preconditioner.get()));
581  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
582  }
583  else
584  solver.SetAztecOption(AZ_precond, AZ_none);
585  }
586 
587 
588  template <>
589  void
590  SolverBase::set_preconditioner(AztecOO & solver,
591  const Epetra_Operator &preconditioner)
592  {
593  const int ierr =
594  solver.SetPrecOperator(const_cast<Epetra_Operator *>(&preconditioner));
595  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
596  }
597 
598 
599  /* ---------------------- SolverCG ------------------------ */
600 
601  SolverCG::AdditionalData::AdditionalData(const bool output_solver_details)
602  : SolverBase::AdditionalData(output_solver_details)
603  {}
604 
605 
606 
608  : SolverBase(cn, data)
609  , additional_data(data)
610  {
611  solver_name = cg;
612  }
613 
614 
615  /* ---------------------- SolverGMRES ------------------------ */
616 
618  const bool output_solver_details,
619  const unsigned int restart_parameter)
620  : SolverBase::AdditionalData(output_solver_details, restart_parameter)
621  {}
622 
623 
624 
626  : SolverBase(cn, data)
627  , additional_data(data)
628  {
629  solver_name = gmres;
630  }
631 
632 
633  /* ---------------------- SolverBicgstab ------------------------ */
634 
636  const bool output_solver_details)
637  : SolverBase::AdditionalData(output_solver_details)
638  {}
639 
640 
641 
643  : SolverBase(cn, data)
644  , additional_data(data)
645  {
646  solver_name = bicgstab;
647  }
648 
649 
650  /* ---------------------- SolverCGS ------------------------ */
651 
652  SolverCGS::AdditionalData::AdditionalData(const bool output_solver_details)
653  : SolverBase::AdditionalData(output_solver_details)
654  {}
655 
656 
657 
659  : SolverBase(cn, data)
660  , additional_data(data)
661  {
662  solver_name = cgs;
663  }
664 
665 
666  /* ---------------------- SolverTFQMR ------------------------ */
667 
668  SolverTFQMR::AdditionalData::AdditionalData(const bool output_solver_details)
669  : SolverBase::AdditionalData(output_solver_details)
670  {}
671 
672 
673 
675  : SolverBase(cn, data)
676  , additional_data(data)
677  {
678  solver_name = tfqmr;
679  }
680 
681 
682 
683  /* ---------------------- SolverDirect ------------------------ */
684 
685  SolverDirect::AdditionalData::AdditionalData(const bool output_solver_details,
686  const std::string &solver_type)
687  : output_solver_details(output_solver_details)
688  , solver_type(solver_type)
689  {}
690 
691 
692 
694  : solver_control(cn)
696  {}
697 
698 
699 
700  SolverControl &
702  {
703  return solver_control;
704  }
705 
706 
707 
708  void
710  {
711  // We need an Epetra_LinearProblem object to let the Amesos solver know
712  // about the matrix and vectors.
713  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>();
714 
715  // Assign the matrix operator to the Epetra_LinearProblem object
716  linear_problem->SetOperator(
717  const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()));
718 
719  // Fetch return value of Amesos Solver functions
720  int ierr;
721 
722  // First set whether we want to print the solver information to screen or
723  // not.
724  ConditionalOStream verbose_cout(std::cout,
726 
727  // Next allocate the Amesos solver, this is done in two steps, first we
728  // create a solver Factory and and generate with that the concrete Amesos
729  // solver, if possible.
730  Amesos Factory;
731 
732  AssertThrow(Factory.Query(additional_data.solver_type.c_str()),
733  ExcMessage(
734  std::string("You tried to select the solver type <") +
736  "> but this solver is not supported by Trilinos either "
737  "because it does not exist, or because Trilinos was not "
738  "configured for its use."));
739 
740  solver.reset(
741  Factory.Create(additional_data.solver_type.c_str(), *linear_problem));
742 
743  verbose_cout << "Starting symbolic factorization" << std::endl;
744  ierr = solver->SymbolicFactorization();
745  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
746 
747  verbose_cout << "Starting numeric factorization" << std::endl;
748  ierr = solver->NumericFactorization();
749  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
750  }
751 
752 
753  void
755  {
756  // Assign the empty LHS vector to the Epetra_LinearProblem object
757  linear_problem->SetLHS(&x.trilinos_vector());
758 
759  // Assign the RHS vector to the Epetra_LinearProblem object
760  linear_problem->SetRHS(
761  const_cast<Epetra_MultiVector *>(&b.trilinos_vector()));
762 
763  // First set whether we want to print the solver information to screen or
764  // not.
765  ConditionalOStream verbose_cout(std::cout,
767 
768 
769  verbose_cout << "Starting solve" << std::endl;
770 
771  // Fetch return value of Amesos Solver functions
772  int ierr = solver->Solve();
773  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
774 
775  // Finally, force the SolverControl object to report convergence
776  solver_control.check(0, 0);
777  }
778 
779 
780 
781  void
784  const ::LinearAlgebra::distributed::Vector<double> &b)
785  {
786  Epetra_Vector ep_x(View,
787  linear_problem->GetOperator()->OperatorDomainMap(),
788  x.begin());
789  Epetra_Vector ep_b(View,
790  linear_problem->GetOperator()->OperatorRangeMap(),
791  const_cast<double *>(b.begin()));
792 
793  // Assign the empty LHS vector to the Epetra_LinearProblem object
794  linear_problem->SetLHS(&ep_x);
795 
796  // Assign the RHS vector to the Epetra_LinearProblem object
797  linear_problem->SetRHS(&ep_b);
798 
799  // First set whether we want to print the solver information to screen or
800  // not.
801  ConditionalOStream verbose_cout(std::cout,
803 
804  verbose_cout << "Starting solve" << std::endl;
805 
806  // Fetch return value of Amesos Solver functions
807  int ierr = solver->Solve();
808  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
809 
810  // Finally, force the SolverControl object to report convergence
811  solver_control.check(0, 0);
812  }
813 
814 
815 
816  void
818  {
819  // Fetch return value of Amesos Solver functions
820  int ierr;
821 
822  // First set whether we want to print the solver information to screen or
823  // not.
824  ConditionalOStream verbose_cout(std::cout,
826 
827  // Next allocate the Amesos solver, this is done in two steps, first we
828  // create a solver Factory and and generate with that the concrete Amesos
829  // solver, if possible.
830  Amesos Factory;
831 
832  AssertThrow(Factory.Query(additional_data.solver_type.c_str()),
833  ExcMessage(
834  std::string("You tried to select the solver type <") +
836  "> but this solver is not supported by Trilinos either "
837  "because it does not exist, or because Trilinos was not "
838  "configured for its use."));
839 
840  solver.reset(
841  Factory.Create(additional_data.solver_type.c_str(), *linear_problem));
842 
843  verbose_cout << "Starting symbolic factorization" << std::endl;
844  ierr = solver->SymbolicFactorization();
845  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
846 
847  verbose_cout << "Starting numeric factorization" << std::endl;
848  ierr = solver->NumericFactorization();
849  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
850 
851  verbose_cout << "Starting solve" << std::endl;
852  ierr = solver->Solve();
853  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
854 
855  // Finally, let the deal.II SolverControl object know what has
856  // happened. If the solve succeeded, the status of the solver control will
857  // turn into SolverControl::success.
858  solver_control.check(0, 0);
859 
861  AssertThrow(false,
864  }
865 
866 
867  void
869  MPI::Vector & x,
870  const MPI::Vector & b)
871  {
872  // We need an Epetra_LinearProblem object to let the Amesos solver know
873  // about the matrix and vectors.
874  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
875  const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
876  &x.trilinos_vector(),
877  const_cast<Epetra_MultiVector *>(&b.trilinos_vector()));
878 
879  do_solve();
880  }
881 
882 
883 
884  void
886  ::Vector<double> & x,
887  const ::Vector<double> &b)
888  {
889  // In case we call the solver with deal.II vectors, we create views of the
890  // vectors in Epetra format.
891  Assert(x.size() == A.n(), ExcDimensionMismatch(x.size(), A.n()));
892  Assert(b.size() == A.m(), ExcDimensionMismatch(b.size(), A.m()));
893  Assert(A.local_range().second == A.m(),
894  ExcMessage("Can only work in serial when using deal.II vectors."));
895  Epetra_Vector ep_x(View, A.domain_partitioner(), x.begin());
896  Epetra_Vector ep_b(View,
897  A.range_partitioner(),
898  const_cast<double *>(b.begin()));
899 
900  // We need an Epetra_LinearProblem object to let the Amesos solver know
901  // about the matrix and vectors.
902  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
903  const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()), &ep_x, &ep_b);
904 
905  do_solve();
906  }
907 
908 
909 
910  void
912  const SparseMatrix & A,
914  const ::LinearAlgebra::distributed::Vector<double> &b)
915  {
916  AssertDimension(static_cast<TrilinosWrappers::types::int_type>(
917  x.local_size()),
918  A.domain_partitioner().NumMyElements());
919  AssertDimension(static_cast<TrilinosWrappers::types::int_type>(
920  b.local_size()),
921  A.range_partitioner().NumMyElements());
922  Epetra_Vector ep_x(View, A.domain_partitioner(), x.begin());
923  Epetra_Vector ep_b(View,
924  A.range_partitioner(),
925  const_cast<double *>(b.begin()));
926 
927  // We need an Epetra_LinearProblem object to let the Amesos solver know
928  // about the matrix and vectors.
929  linear_problem = std_cxx14::make_unique<Epetra_LinearProblem>(
930  const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()), &ep_x, &ep_b);
931 
932  do_solve();
933  }
934 } // namespace TrilinosWrappers
935 
936 
937 // explicit instantiations
938 // TODO: put these instantiations into generic file
939 namespace TrilinosWrappers
940 {
941  template void
942  SolverBase::do_solve(const PreconditionBase &preconditioner);
943 
944  template void
945  SolverBase::do_solve(const Epetra_Operator &preconditioner);
946 } // namespace TrilinosWrappers
947 
948 DEAL_II_NAMESPACE_CLOSE
949 
950 #endif // DEAL_II_WITH_PETSC
void set_preconditioner(AztecOO &solver, const Preconditioner &preconditioner)
SolverCG(SolverControl &cn, const AdditionalData &data=AdditionalData())
const Epetra_Map & domain_partitioner() const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
virtual State check(const unsigned int step, const double check_value)
const Epetra_CrsMatrix & trilinos_matrix() const
const AdditionalData additional_data
std::unique_ptr< AztecOO_StatusTest > status_test
const AdditionalData additional_data
size_type size() const
AdditionalData(const bool output_solver_details=false, const unsigned int restart_parameter=30)
const AdditionalData additional_data
void initialize(const SparseMatrix &A)
static::ExceptionBase & ExcTrilinosError(int arg1)
double tolerance() const
void solve(MPI::Vector &x, const MPI::Vector &b)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
const AdditionalData additional_data
void do_solve(const Preconditioner &preconditioner)
static::ExceptionBase & ExcMessage(std::string arg1)
double last_value() const
SolverCGS(SolverControl &cn, const AdditionalData &data=AdditionalData())
Stop iteration, goal reached.
unsigned int max_steps() const
SolverControl & control() const
#define Assert(cond, exc)
Definition: exceptions.h:1227
AdditionalData(const bool output_solver_details=false)
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
SolverBicgstab(SolverControl &cn, const AdditionalData &data=AdditionalData())
std::unique_ptr< Epetra_LinearProblem > linear_problem
void solve(const SparseMatrix &A, MPI::Vector &x, const MPI::Vector &b, const PreconditionBase &preconditioner)
std::unique_ptr< Epetra_LinearProblem > linear_problem
iterator begin()
unsigned int last_step() const
SolverTFQMR(SolverControl &cn, const AdditionalData &data=AdditionalData())
AdditionalData(const bool output_solver_details=false)
SolverBase(SolverControl &cn, const AdditionalData &data=AdditionalData())
const Epetra_Map & range_partitioner() 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
SolverControl & control() const
AdditionalData(const bool output_solver_details=false)
static::ExceptionBase & ExcNotImplemented()
AdditionalData(const bool output_solver_details=false, const unsigned int gmres_restart_parameter=30)
std::shared_ptr< Epetra_Operator > preconditioner
SolverGMRES(SolverControl &cn, const AdditionalData &data=AdditionalData())
const AdditionalData additional_data
std::pair< size_type, size_type > local_range() const
const Epetra_MultiVector & trilinos_vector() const
static::ExceptionBase & ExcInternalError()
static::ExceptionBase & ExcTrilinosError(int arg1)
AdditionalData(const bool output_solver_details=false)