13#ifndef dealii_trilinos_solver_h
14#define dealii_trilinos_solver_h
19#ifndef DEAL_II_TRILINOS_WITH_EPETRA
27#ifdef DEAL_II_WITH_TRILINOS
38# ifdef DEAL_II_TRILINOS_WITH_EPETRA
41# include <Epetra_LinearProblem.h>
42# include <Epetra_Operator.h>
46# ifdef DEAL_II_TRILINOS_WITH_BELOS
47# include <BelosBlockCGSolMgr.hpp>
48# include <BelosBlockGmresSolMgr.hpp>
49# ifdef DEAL_II_TRILINOS_WITH_EPETRA
50# include <BelosEpetraAdapter.hpp>
52# include <BelosIteration.hpp>
53# include <BelosMultiVec.hpp>
54# include <BelosOperator.hpp>
55# include <BelosSolverManager.hpp>
67#ifdef DEAL_II_WITH_TRILINOS
70# ifdef DEAL_II_TRILINOS_WITH_EPETRA
223 Epetra_MultiVector &x,
224 const Epetra_MultiVector &b,
239 Epetra_MultiVector &x,
240 const Epetra_MultiVector &b,
258 const ::Vector<double> &b,
275 const ::Vector<double> &b,
287 const ::LinearAlgebra::distributed::Vector<double> &b,
300 const ::LinearAlgebra::distributed::Vector<double> &b,
315 <<
"An error with error number " << arg1
316 <<
" occurred while calling a Trilinos function");
332 template <
typename Preconditioner>
334 do_solve(
const Preconditioner &preconditioner);
339 template <
typename Preconditioner>
589 const ::LinearAlgebra::distributed::Vector<double> &b);
606 const ::LinearAlgebra::distributed::Vector<double> &b)
const;
627 const ::Vector<double> &b);
638 const ::LinearAlgebra::distributed::Vector<double> &b);
648 Epetra_MultiVector &x,
649 const Epetra_MultiVector &b);
673 <<
"An error with error number " << arg1
674 <<
" occurred while calling a Trilinos function");
708 std::unique_ptr<Amesos_BaseSolver>
solver;
737# ifdef DEAL_II_TRILINOS_WITH_BELOS
744 template <
typename VectorType>
776 const bool right_preconditioning =
false)
777 : solver_name(solver_name)
778 , right_preconditioning(right_preconditioning)
797 const Teuchos::RCP<Teuchos::ParameterList> &belos_parameters);
802 template <
typename OperatorType,
typename PreconditionerType>
807 const PreconditionerType &p);
822# ifdef DEAL_II_TRILINOS_WITH_BELOS
833 template <
typename VectorType>
835 class MultiVecWrapper
836 :
public Belos::MultiVec<typename VectorType::value_type>
842 using value_type =
typename VectorType::value_type;
848 this_type_is_missing_a_specialization()
856 MultiVecWrapper(VectorType &vector)
858 this->vectors.resize(1);
859 this->vectors[0].reset(
867 MultiVecWrapper(
const VectorType &vector)
869 this->vectors.resize(1);
870 this->vectors[0].reset(
871 &
const_cast<VectorType &
>(vector),
878 virtual ~MultiVecWrapper() =
default;
883 virtual Belos::MultiVec<value_type> *
884 Clone(
const int numvecs)
const
886 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
888 new_multi_vec->vectors.resize(numvecs);
890 for (
auto &vec : new_multi_vec->vectors)
892 vec = std::make_shared<VectorType>();
895 vec->reinit(*this->vectors[0]);
898 return new_multi_vec;
904 virtual Belos::MultiVec<value_type> *
915 virtual Belos::MultiVec<value_type> *
916 CloneCopy(
const std::vector<int> &index)
const
918 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
920 new_multi_vec->vectors.resize(index.size());
922 for (
unsigned int i = 0; i < index.size(); ++i)
925 this->vectors.size(),
928 new_multi_vec->vectors[i] = std::make_shared<VectorType>();
931 *new_multi_vec->vectors[i] = *this->vectors[index[i]];
934 return new_multi_vec;
942 virtual Belos::MultiVec<value_type> *
943 CloneViewNonConst(
const std::vector<int> &index)
945 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
947 new_multi_vec->vectors.resize(index.size());
949 for (
unsigned int i = 0; i < index.size(); ++i)
952 this->vectors.size(),
955 new_multi_vec->vectors[i].reset(
956 this->vectors[index[i]].get(),
962 return new_multi_vec;
970 virtual const Belos::MultiVec<value_type> *
971 CloneView(
const std::vector<int> &index)
const
973 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
975 new_multi_vec->vectors.resize(index.size());
977 for (
unsigned int i = 0; i < index.size(); ++i)
980 this->vectors.size(),
983 new_multi_vec->vectors[i].reset(
984 this->vectors[index[i]].get(),
990 return new_multi_vec;
996 virtual std::ptrdiff_t
997 GetGlobalLength()
const
1001 for (
unsigned int i = 1; i < this->vectors.size(); ++i)
1004 return this->vectors[0]->size();
1011 GetNumberVecs()
const
1013 return vectors.size();
1021 const Belos::MultiVec<value_type> &A_,
1022 const Teuchos::SerialDenseMatrix<int, value_type> &B,
1025 const auto &A = try_to_get_underlying_vector(A_);
1027 const unsigned int n_rows = B.numRows();
1028 const unsigned int n_cols = B.numCols();
1030 AssertThrow(n_rows ==
static_cast<unsigned int>(A.GetNumberVecs()),
1032 AssertThrow(n_cols ==
static_cast<unsigned int>(this->GetNumberVecs()),
1035 for (
unsigned int i = 0; i < n_cols; ++i)
1036 (*this->vectors[i]) *= beta;
1038 for (
unsigned int i = 0; i < n_cols; ++i)
1039 for (
unsigned int j = 0; j < n_rows; ++j)
1040 this->vectors[i]->add(alpha * B(j, i), *A.vectors[j]);
1048 const Belos::MultiVec<value_type> &A_,
1050 const Belos::MultiVec<value_type> &B_)
1052 const auto &A = try_to_get_underlying_vector(A_);
1053 const auto &B = try_to_get_underlying_vector(B_);
1055 AssertThrow(this->vectors.size() == A.vectors.size(),
1057 AssertThrow(this->vectors.size() == B.vectors.size(),
1060 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
1062 this->vectors[i]->equ(alpha, *A.vectors[i]);
1063 this->vectors[i]->add(beta, *B.vectors[i]);
1073 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
1074 (*this->vectors[i]) *= alpha;
1081 MvScale(
const std::vector<value_type> & )
1092 const Belos::MultiVec<value_type> &A_,
1093 Teuchos::SerialDenseMatrix<int, value_type> &B)
const
1095 const auto &A = try_to_get_underlying_vector(A_);
1097 const unsigned int n_rows = B.numRows();
1098 const unsigned int n_cols = B.numCols();
1100 AssertThrow(n_rows ==
static_cast<unsigned int>(A.GetNumberVecs()),
1102 AssertThrow(n_cols ==
static_cast<unsigned int>(this->GetNumberVecs()),
1105 for (
unsigned int i = 0; i < n_rows; ++i)
1106 for (
unsigned int j = 0; j < n_cols; ++j)
1107 B(i, j) = alpha * ((*A.vectors[i]) * (*this->vectors[j]));
1115 MvDot(
const Belos::MultiVec<value_type> &A_,
1116 std::vector<value_type> &b)
const
1118 const auto &A = try_to_get_underlying_vector(A_);
1120 AssertThrow(this->vectors.size() == A.vectors.size(),
1124 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
1125 b[i] = (*this->vectors[i]) * (*A.vectors[i]);
1133 std::vector<
typename Teuchos::ScalarTraits<value_type>::magnitudeType>
1135 Belos::NormType type = Belos::TwoNorm)
const
1140 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
1141 normvec[i] = this->vectors[i]->l2_norm();
1148 SetBlock(
const Belos::MultiVec<value_type> & ,
1149 const std::vector<int> & )
1176 MvPrint(std::ostream & )
const
1196 genericVector()
const
1206 static MultiVecWrapper<VectorType> &
1207 try_to_get_underlying_vector(Belos::MultiVec<value_type> &vec_in)
1209 auto vec =
dynamic_cast<MultiVecWrapper<VectorType> *
>(&vec_in);
1219 const static MultiVecWrapper<VectorType> &
1220 try_to_get_underlying_vector(
const Belos::MultiVec<value_type> &vec_in)
1222 auto vec =
dynamic_cast<const MultiVecWrapper<VectorType> *
>(&vec_in);
1230# ifdef HAVE_BELOS_TSQR
1232 factorExplicit(Belos::MultiVec<value_type> &,
1233 Teuchos::SerialDenseMatrix<int, value_type> &,
1241 Teuchos::SerialDenseMatrix<int, value_type> &,
1242 const typename Teuchos::ScalarTraits<value_type>::magnitudeType &)
1253 std::vector<std::shared_ptr<VectorType>> vectors;
1259 MultiVecWrapper() =
default;
1268 template <
typename OperatorType,
typename VectorType>
1270 class OperatorWrapper
1271 :
public Belos::Operator<typename VectorType::value_type>
1277 using value_type =
typename VectorType::value_type;
1283 this_type_is_missing_a_specialization()
1291 OperatorWrapper(
const OperatorType &op)
1298 virtual ~OperatorWrapper() =
default;
1304 Apply(
const Belos::MultiVec<value_type> &x,
1305 Belos::MultiVec<value_type> &y,
1306 Belos::ETrans trans = Belos::NOTRANS)
const
1311 op.vmult(MultiVecWrapper<VectorType>::try_to_get_underlying_vector(y)
1313 MultiVecWrapper<VectorType>::try_to_get_underlying_vector(x)
1321 HasApplyTranspose()
const
1331 const OperatorType &op;
1338 template <
typename VectorType>
1342 const AdditionalData &additional_data,
1343 const Teuchos::RCP<Teuchos::ParameterList> &belos_parameters)
1344 : solver_control(solver_control)
1345 , additional_data(additional_data)
1346 , belos_parameters(belos_parameters)
1351 template <
typename VectorType>
1353 template <
typename OperatorType,
typename PreconditionerType>
1355 VectorType &x_dealii,
1356 const VectorType &b_dealii,
1357 const PreconditionerType &P_dealii)
1359 using value_type =
typename VectorType::value_type;
1361 using MV = Belos::MultiVec<value_type>;
1362 using OP = Belos::Operator<value_type>;
1364 Teuchos::RCP<OP>
A = Teuchos::rcp(
1365 new internal::OperatorWrapper<OperatorType, VectorType>(A_dealii));
1366 Teuchos::RCP<OP> P = Teuchos::rcp(
1367 new internal::OperatorWrapper<PreconditionerType, VectorType>(P_dealii));
1368 Teuchos::RCP<MV> X =
1369 Teuchos::rcp(
new internal::MultiVecWrapper<VectorType>(x_dealii));
1370 Teuchos::RCP<MV> B =
1371 Teuchos::rcp(
new internal::MultiVecWrapper<VectorType>(b_dealii));
1373 Teuchos::RCP<Belos::LinearProblem<value_type, MV, OP>> problem =
1374 Teuchos::rcp(
new Belos::LinearProblem<value_type, MV, OP>(A, X, B));
1376 if (additional_data.right_preconditioning ==
false)
1377 problem->setLeftPrec(P);
1379 problem->setRightPrec(P);
1381 const bool problem_set = problem->setProblem();
1386 r.reinit(x_dealii,
true);
1387 A_dealii.vmult(r, x_dealii);
1388 r.sadd(-1., 1., b_dealii);
1389 const auto norm_0 = r.l2_norm();
1394 double relative_tolerance_to_be_achieved =
1395 solver_control.tolerance() / norm_0;
1396 const unsigned int max_steps = solver_control.max_steps();
1398 if (
const auto *reduction_control =
1400 relative_tolerance_to_be_achieved =
1401 std::max(relative_tolerance_to_be_achieved,
1402 reduction_control->reduction());
1404 Teuchos::RCP<Teuchos::ParameterList> belos_parameters_copy(
1405 Teuchos::rcp(
new Teuchos::ParameterList(*belos_parameters)));
1407 belos_parameters_copy->set(
"Convergence Tolerance",
1408 relative_tolerance_to_be_achieved);
1409 belos_parameters_copy->set(
"Maximum Iterations",
1410 static_cast<int>(max_steps));
1412 Teuchos::RCP<Belos::SolverManager<value_type, MV, OP>> solver;
1414 if (additional_data.solver_name == SolverName::cg)
1415 solver = Teuchos::rcp(
1416 new Belos::BlockCGSolMgr<value_type, MV, OP>(problem,
1417 belos_parameters_copy));
1418 else if (additional_data.solver_name == SolverName::gmres)
1419 solver = Teuchos::rcp(
1420 new Belos::BlockGmresSolMgr<value_type, MV, OP>(problem,
1421 belos_parameters_copy));
1425 const auto flag = solver->solve();
1427 solver_control.check(solver->getNumIters(), solver->achievedTol() * norm_0);
1429 AssertThrow(flag == Belos::ReturnType::Converged ||
1432 (solver_control.last_step() == max_steps)),
1434 solver_control.last_value()));
@ iterate
Continue iteration.
virtual ~SolverBase()=default
SolverControl & control() const
void solve(const SparseMatrix &A, MPI::Vector &x, const MPI::Vector &b, const PreconditionBase &preconditioner)
const AdditionalData additional_data
std::unique_ptr< AztecOO_StatusTest > status_test
void set_preconditioner(AztecOO &solver, const Preconditioner &preconditioner)
SolverControl & solver_control
void do_solve(const Preconditioner &preconditioner)
void solve(Epetra_Operator &A, ::LinearAlgebra::distributed::Vector< double > &x, const ::LinearAlgebra::distributed::Vector< double > &b, const PreconditionBase &preconditioner)
std::unique_ptr< Epetra_LinearProblem > linear_problem
enum TrilinosWrappers::SolverBase::SolverName solver_name
void solve(const SparseMatrix &A, ::LinearAlgebra::distributed::Vector< double > &x, const ::LinearAlgebra::distributed::Vector< double > &b, const PreconditionBase &preconditioner)
SolverBelos(SolverControl &solver_control, const AdditionalData &additional_data, const Teuchos::RCP< Teuchos::ParameterList > &belos_parameters)
const AdditionalData additional_data
void solve(const OperatorType &a, VectorType &x, const VectorType &b, const PreconditionerType &p)
SolverControl & solver_control
const Teuchos::RCP< Teuchos::ParameterList > & belos_parameters
void solve(const SparseMatrix &A, ::LinearAlgebra::distributed::Vector< double > &x, const ::LinearAlgebra::distributed::Vector< double > &b)
virtual ~SolverDirect()=default
void initialize(const SparseMatrix &A)
void vmult(MPI::Vector &x, const MPI::Vector &b) const
std::unique_ptr< Amesos_BaseSolver > solver
SolverControl & solver_control
void solve(MPI::Vector &x, const MPI::Vector &b)
std::unique_ptr< Epetra_LinearProblem > linear_problem
AdditionalData additional_data
SolverControl solver_control_own
SolverControl & control() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcNotImplemented()
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
#define DeclException1(Exception1, type1, outsequence)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
const unsigned int gmres_restart_parameter
const bool output_solver_details
AdditionalData(const SolverName solver_name=SolverName::cg, const bool right_preconditioning=false)
bool right_preconditioning
bool output_solver_details