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