16 #include <deal.II/lac/trilinos_solver.h> 18 #ifdef DEAL_II_WITH_TRILINOS 20 # include <deal.II/base/conditional_ostream.h> 21 # include <deal.II/base/std_cxx14/memory.h> 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> 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> 36 DEAL_II_NAMESPACE_OPEN
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)
60 : solver_name(solver_name)
62 , additional_data(data)
86 const_cast<Epetra_MultiVector *
>(&b.trilinos_vector()));
104 const_cast<Epetra_Operator *
>(&A),
106 const_cast<Epetra_MultiVector *
>(&b.trilinos_vector()));
119 const Epetra_Operator &preconditioner)
124 const_cast<Epetra_Operator *
>(&A),
126 const_cast<Epetra_MultiVector *
>(&b.trilinos_vector()));
137 Epetra_MultiVector & x,
138 const Epetra_MultiVector &b,
144 const_cast<Epetra_Operator *
>(&A),
146 const_cast<Epetra_MultiVector *>(&b));
157 Epetra_MultiVector & x,
158 const Epetra_MultiVector &b,
159 const Epetra_Operator & preconditioner)
164 const_cast<Epetra_Operator *
>(&A),
166 const_cast<Epetra_MultiVector *>(&b));
176 const ::Vector<double> &b,
184 ExcMessage(
"Can only work in serial when using deal.II vectors."));
186 ExcMessage(
"Matrix is not compressed. Call compress() method."));
189 Epetra_Vector ep_b(View,
191 const_cast<double *
>(b.begin()));
206 const ::Vector<double> &b,
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()));
217 std_cxx14::make_unique<Epetra_LinearProblem>(&A, &ep_x, &ep_b);
227 const ::LinearAlgebra::distributed::Vector<double> &b,
236 Epetra_Vector ep_b(View,
238 const_cast<double *
>(b.begin()));
253 const ::LinearAlgebra::distributed::Vector<double> &b,
259 Epetra_Vector ep_x(View, A.OperatorDomainMap(), x.
begin());
260 Epetra_Vector ep_b(View,
261 A.OperatorRangeMap(),
262 const_cast<double *
>(b.begin()));
267 std_cxx14::make_unique<Epetra_LinearProblem>(&A, &ep_x, &ep_b);
278 compute_residual(
const Epetra_MultiVector *
const residual_vector)
280 Assert(residual_vector->NumVectors() == 1,
281 ExcMessage(
"Residual multivector holds more than one vector"));
282 TrilinosScalar res_l2_norm = 0.0;
283 const int ierr = residual_vector->Norm2(&res_l2_norm);
288 class TrilinosReductionControl :
public AztecOO_StatusTest
291 TrilinosReductionControl(
const int max_steps,
292 const double tolerance,
294 const Epetra_LinearProblem &linear_problem);
296 virtual ~TrilinosReductionControl()
override =
default;
299 ResidualVectorRequired()
const override 301 return status_test_collection->ResidualVectorRequired();
304 virtual AztecOO_StatusType
305 CheckStatus(
int CurrentIter,
306 Epetra_MultiVector *CurrentResVector,
307 double CurrentResNormEst,
308 bool SolutionUpdated)
override 313 (CurrentResNormEst < 0.0 ? compute_residual(CurrentResVector) :
315 if (CurrentIter == 0)
316 initial_residual = current_residual;
318 return status_test_collection->CheckStatus(CurrentIter,
324 virtual AztecOO_StatusType
325 GetStatus()
const override 327 return status_test_collection->GetStatus();
330 virtual std::ostream &
331 Print(std::ostream &stream,
int indent = 0)
const override 333 return status_test_collection->Print(stream, indent);
337 get_initial_residual()
const 339 return initial_residual;
343 get_current_residual()
const 345 return current_residual;
349 double initial_residual;
350 double current_residual;
351 std::unique_ptr<AztecOO_StatusTestCombo> status_test_collection;
352 std::unique_ptr<AztecOO_StatusTestMaxIters> status_test_max_steps;
353 std::unique_ptr<AztecOO_StatusTestResNorm> status_test_abs_tol;
354 std::unique_ptr<AztecOO_StatusTestResNorm> status_test_rel_tol;
358 TrilinosReductionControl::TrilinosReductionControl(
360 const double tolerance,
362 const Epetra_LinearProblem &linear_problem)
363 : initial_residual(
std::numeric_limits<double>::
max())
364 , current_residual(
std::numeric_limits<double>::
max())
367 , status_test_collection(
368 std_cxx14::make_unique<AztecOO_StatusTestCombo>(
369 AztecOO_StatusTestCombo::OR))
373 status_test_max_steps =
374 std_cxx14::make_unique<AztecOO_StatusTestMaxIters>(max_steps);
375 status_test_collection->AddStatusTest(*status_test_max_steps);
378 ExcMessage(
"RHS multivector holds more than one vector"));
381 status_test_abs_tol = std_cxx14::make_unique<AztecOO_StatusTestResNorm>(
386 status_test_abs_tol->DefineResForm(AztecOO_StatusTestResNorm::Explicit,
387 AztecOO_StatusTestResNorm::TwoNorm);
388 status_test_abs_tol->DefineScaleForm(
389 AztecOO_StatusTestResNorm::None, AztecOO_StatusTestResNorm::TwoNorm);
390 status_test_collection->AddStatusTest(*status_test_abs_tol);
393 status_test_rel_tol = std_cxx14::make_unique<AztecOO_StatusTestResNorm>(
398 status_test_rel_tol->DefineResForm(AztecOO_StatusTestResNorm::Explicit,
399 AztecOO_StatusTestResNorm::TwoNorm);
400 status_test_rel_tol->DefineScaleForm(
401 AztecOO_StatusTestResNorm::NormOfInitRes,
402 AztecOO_StatusTestResNorm::TwoNorm);
403 status_test_collection->AddStatusTest(*status_test_rel_tol);
410 template <
typename Preconditioner>
412 SolverBase::do_solve(
const Preconditioner &preconditioner)
417 solver.SetProblem(*linear_problem);
423 solver.SetAztecOption(AZ_solver, AZ_cg);
426 solver.SetAztecOption(AZ_solver, AZ_cgs);
429 solver.SetAztecOption(AZ_solver, AZ_gmres);
430 solver.SetAztecOption(AZ_kspace,
431 additional_data.gmres_restart_parameter);
434 solver.SetAztecOption(AZ_solver, AZ_bicgstab);
437 solver.SetAztecOption(AZ_solver, AZ_tfqmr);
444 set_preconditioner(solver, preconditioner);
447 solver.SetAztecOption(AZ_output,
448 additional_data.output_solver_details ? AZ_all :
450 solver.SetAztecOption(AZ_conv, AZ_noscaled);
468 dynamic_cast<const ReductionControl *const>(&solver_control))
471 std_cxx14::make_unique<internal::TrilinosReductionControl>(
472 reduction_control->max_steps(),
473 reduction_control->tolerance(),
474 reduction_control->reduction(),
476 solver.SetStatusTest(status_test.get());
482 solver.Iterate(solver_control.max_steps(), solver_control.tolerance());
492 "option not implemented"));
497 "numerical breakdown"));
502 "loss of precision"));
507 "GMRES Hessenberg ill-conditioned"));
520 if (
const internal::TrilinosReductionControl
521 *
const reduction_control_status =
522 dynamic_cast<const internal::TrilinosReductionControl *const>(
525 Assert(dynamic_cast<const ReductionControl *const>(&solver_control),
531 if (solver.NumIters() > 0)
536 solver_control.check(
537 0, reduction_control_status->get_initial_residual());
538 solver_control.check(
540 reduction_control_status->get_current_residual());
543 solver_control.check(
545 reduction_control_status->get_current_residual());
550 solver_control.check(solver.NumIters(), solver.TrueResidual());
556 solver_control.last_value()));
563 SolverBase::set_preconditioner(AztecOO & solver,
570 const int ierr = solver.SetPrecOperator(
571 const_cast<Epetra_Operator *>(preconditioner.
preconditioner.get()));
575 solver.SetAztecOption(AZ_precond, AZ_none);
581 SolverBase::set_preconditioner(AztecOO & solver,
582 const Epetra_Operator &preconditioner)
585 solver.SetPrecOperator(const_cast<Epetra_Operator *>(&preconditioner));
592 SolverCG::AdditionalData::AdditionalData(
const bool output_solver_details)
609 const bool output_solver_details,
610 const unsigned int restart_parameter)
627 const bool output_solver_details)
677 const std::string &solver_type)
678 : output_solver_details(output_solver_details)
679 , solver_type(solver_type)
725 std::string(
"You tried to select the solver type <") +
727 "> but this solver is not supported by Trilinos either " 728 "because it does not exist, or because Trilinos was not " 729 "configured for its use."));
734 verbose_cout <<
"Starting symbolic factorization" << std::endl;
735 ierr =
solver->SymbolicFactorization();
738 verbose_cout <<
"Starting numeric factorization" << std::endl;
739 ierr =
solver->NumericFactorization();
752 const_cast<Epetra_MultiVector *>(&b.trilinos_vector()));
760 verbose_cout <<
"Starting solve" << std::endl;
763 int ierr =
solver->Solve();
775 const ::LinearAlgebra::distributed::Vector<double> &b)
777 Epetra_Vector ep_x(View,
780 Epetra_Vector ep_b(View,
782 const_cast<double *
>(b.begin()));
795 verbose_cout <<
"Starting solve" << std::endl;
798 int ierr =
solver->Solve();
825 std::string(
"You tried to select the solver type <") +
827 "> but this solver is not supported by Trilinos either " 828 "because it does not exist, or because Trilinos was not " 829 "configured for its use."));
834 verbose_cout <<
"Starting symbolic factorization" << std::endl;
835 ierr =
solver->SymbolicFactorization();
838 verbose_cout <<
"Starting numeric factorization" << std::endl;
839 ierr =
solver->NumericFactorization();
842 verbose_cout <<
"Starting solve" << std::endl;
868 const_cast<Epetra_MultiVector *
>(&b.trilinos_vector()));
878 const ::Vector<double> &b)
885 ExcMessage(
"Can only work in serial when using deal.II vectors."));
887 Epetra_Vector ep_b(View,
889 const_cast<double *
>(b.begin()));
905 const ::LinearAlgebra::distributed::Vector<double> &b)
910 Epetra_Vector ep_b(View,
912 const_cast<double *
>(b.begin()));
935 DEAL_II_NAMESPACE_CLOSE
937 #endif // DEAL_II_WITH_PETSC static ::ExceptionBase & ExcTrilinosError(int arg1)
SolverCG(SolverControl &cn, const AdditionalData &data=AdditionalData())
size_type local_size() const
__global__ void reduction(Number *result, const Number *v, const size_type N)
#define AssertDimension(dim1, dim2)
virtual State check(const unsigned int step, const double check_value)
SolverBase(SolverControl &cn, const AdditionalData &data=AdditionalData())
std::unique_ptr< Amesos_BaseSolver > solver
const Epetra_Map & range_partitioner() const
const AdditionalData additional_data
const AdditionalData additional_data
AdditionalData(const bool output_solver_details=false, const unsigned int restart_parameter=30)
const AdditionalData additional_data
void initialize(const SparseMatrix &A)
void solve(MPI::Vector &x, const MPI::Vector &b)
void solve(const SparseMatrix &A, MPI::Vector &x, const MPI::Vector &b, const PreconditionBase &preconditioner)
#define AssertThrow(cond, exc)
const AdditionalData additional_data
SolverControl & solver_control
static ::ExceptionBase & ExcMessage(std::string arg1)
SolverCGS(SolverControl &cn, const AdditionalData &data=AdditionalData())
Stop iteration, goal reached.
#define Assert(cond, exc)
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())
SolverControl & solver_control
std::unique_ptr< Epetra_LinearProblem > linear_problem
SolverControl & control() const
const Epetra_CrsMatrix & trilinos_matrix() const
std::unique_ptr< Epetra_LinearProblem > linear_problem
double last_value() const
SolverTFQMR(SolverControl &cn, const AdditionalData &data=AdditionalData())
AdditionalData(const bool output_solver_details=false)
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())
const Epetra_Map & domain_partitioner() const
const AdditionalData additional_data
bool output_solver_details
std::pair< size_type, size_type > local_range() const
AdditionalData(const bool output_solver_details=false)
SolverControl & control() const
void do_solve(const Preconditioner &preconditioner)
static ::ExceptionBase & ExcNotImplemented()
AdditionalData(const bool output_solver_details=false, const unsigned int gmres_restart_parameter=30)
const Epetra_MultiVector & trilinos_vector() const
SolverGMRES(SolverControl &cn, const AdditionalData &data=AdditionalData())
const AdditionalData additional_data
T max(const T &t, const MPI_Comm &mpi_communicator)
Teuchos::RCP< Epetra_Operator > preconditioner
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcTrilinosError(int arg1)