16#ifndef dealii_trilinos_solver_h
17#define dealii_trilinos_solver_h
22#ifdef DEAL_II_WITH_TRILINOS
32# include <Epetra_LinearProblem.h>
33# include <Epetra_Operator.h>
36# ifdef DEAL_II_TRILINOS_WITH_BELOS
37# include <BelosBlockCGSolMgr.hpp>
38# include <BelosBlockGmresSolMgr.hpp>
39# include <BelosEpetraAdapter.hpp>
40# include <BelosIteration.hpp>
41# include <BelosMultiVec.hpp>
42# include <BelosOperator.hpp>
43# include <BelosSolverManager.hpp>
56 class PreconditionBase;
210 Epetra_MultiVector & x,
211 const Epetra_MultiVector &b,
226 Epetra_MultiVector & x,
227 const Epetra_MultiVector &b,
245 const ::Vector<double> &b,
262 const ::Vector<double> &b,
274 const ::LinearAlgebra::distributed::Vector<double> &b,
287 const ::LinearAlgebra::distributed::Vector<double> &b,
302 <<
"An error with error number " << arg1
303 <<
" occurred while calling a Trilinos function");
319 template <
typename Preconditioner>
321 do_solve(
const Preconditioner &preconditioner);
326 template <
typename Preconditioner>
561 const ::LinearAlgebra::distributed::Vector<double> &b);
582 const ::Vector<double> &b);
593 const ::LinearAlgebra::distributed::Vector<double> &b);
606 <<
"An error with error number " << arg1
607 <<
" occurred while calling a Trilinos function");
636 std::unique_ptr<Amesos_BaseSolver>
solver;
646# ifdef DEAL_II_TRILINOS_WITH_BELOS
653 template <
typename VectorType>
678 struct AdditionalData
683 AdditionalData(
const SolverName solver_name = SolverName::cg,
684 const bool right_preconditioning =
false)
685 : solver_name(solver_name)
686 , right_preconditioning(right_preconditioning)
692 SolverName solver_name;
697 bool right_preconditioning;
704 const AdditionalData & additional_data,
705 const Teuchos::RCP<Teuchos::ParameterList> &belos_parameters);
710 template <
typename OperatorType,
typename PreconditionerType>
712 solve(
const OperatorType & a,
714 const VectorType & b,
715 const PreconditionerType &p);
719 const AdditionalData additional_data;
720 const Teuchos::RCP<Teuchos::ParameterList> &belos_parameters;
730# ifdef DEAL_II_TRILINOS_WITH_BELOS
741 template <
class VectorType>
742 class MultiVecWrapper
743 :
public Belos::MultiVec<typename VectorType::value_type>
749 using value_type =
typename VectorType::value_type;
755 this_type_is_missing_a_specialization()
763 MultiVecWrapper(VectorType &vector)
765 this->vectors.resize(1);
766 this->vectors[0].reset(
774 MultiVecWrapper(
const VectorType &vector)
776 this->vectors.resize(1);
777 this->vectors[0].reset(
778 &
const_cast<VectorType &
>(vector),
785 virtual ~MultiVecWrapper() =
default;
790 virtual Belos::MultiVec<value_type> *
791 Clone(
const int numvecs)
const
793 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
795 new_multi_vec->vectors.resize(numvecs);
797 for (
auto &vec : new_multi_vec->vectors)
799 vec = std::make_shared<VectorType>();
802 vec->reinit(*this->vectors[0]);
805 return new_multi_vec;
811 virtual Belos::MultiVec<value_type> *
822 virtual Belos::MultiVec<value_type> *
823 CloneCopy(
const std::vector<int> &index)
const
825 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
827 new_multi_vec->vectors.resize(
index.size());
829 for (
unsigned int i = 0; i <
index.size(); ++i)
832 this->vectors.size(),
835 new_multi_vec->vectors[i] = std::make_shared<VectorType>();
838 *new_multi_vec->vectors[i] = *this->vectors[
index[i]];
841 return new_multi_vec;
849 virtual Belos::MultiVec<value_type> *
850 CloneViewNonConst(
const std::vector<int> &index)
852 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
854 new_multi_vec->vectors.resize(
index.size());
856 for (
unsigned int i = 0; i <
index.size(); ++i)
859 this->vectors.size(),
862 new_multi_vec->vectors[i].reset(
863 this->vectors[index[i]].get(),
869 return new_multi_vec;
877 virtual const Belos::MultiVec<value_type> *
878 CloneView(
const std::vector<int> &index)
const
880 auto new_multi_vec =
new MultiVecWrapper<VectorType>;
882 new_multi_vec->vectors.resize(
index.size());
884 for (
unsigned int i = 0; i <
index.size(); ++i)
887 this->vectors.size(),
890 new_multi_vec->vectors[i].reset(
891 this->vectors[index[i]].get(),
897 return new_multi_vec;
904 GetGlobalLength()
const
908 for (
unsigned int i = 1; i < this->vectors.size(); ++i)
911 return this->vectors[0]->size();
918 GetNumberVecs()
const
920 return vectors.size();
927 MvTimesMatAddMv(
const value_type alpha,
928 const Belos::MultiVec<value_type> & A_,
929 const Teuchos::SerialDenseMatrix<int, value_type> &B,
930 const value_type beta)
932 const auto &A = try_to_get_underlying_vector(A_);
934 const unsigned int n_rows = B.numRows();
935 const unsigned int n_cols = B.numCols();
937 AssertThrow(n_rows ==
static_cast<unsigned int>(A.GetNumberVecs()),
939 AssertThrow(n_cols ==
static_cast<unsigned int>(this->GetNumberVecs()),
942 for (
unsigned int i = 0; i < n_cols; ++i)
943 (*this->vectors[i]) *= beta;
945 for (
unsigned int i = 0; i < n_cols; ++i)
946 for (
unsigned int j = 0; j < n_rows; ++j)
947 this->vectors[i]->add(alpha * B(j, i), *A.vectors[j]);
954 MvAddMv(
const value_type alpha,
955 const Belos::MultiVec<value_type> &A_,
956 const value_type beta,
957 const Belos::MultiVec<value_type> &B_)
959 const auto &A = try_to_get_underlying_vector(A_);
960 const auto &B = try_to_get_underlying_vector(B_);
962 AssertThrow(this->vectors.size() == A.vectors.size(),
964 AssertThrow(this->vectors.size() == B.vectors.size(),
967 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
969 this->vectors[i]->equ(alpha, *A.vectors[i]);
970 this->vectors[i]->add(beta, *B.vectors[i]);
978 MvScale(
const value_type alpha)
980 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
981 (*this->vectors[i]) *= alpha;
988 MvScale(
const std::vector<value_type> &alpha)
999 MvTransMv(
const value_type alpha,
1000 const Belos::MultiVec<value_type> & A_,
1001 Teuchos::SerialDenseMatrix<int, value_type> &B)
const
1003 const auto &A = try_to_get_underlying_vector(A_);
1005 const unsigned int n_rows = B.numRows();
1006 const unsigned int n_cols = B.numCols();
1008 AssertThrow(n_rows ==
static_cast<unsigned int>(A.GetNumberVecs()),
1010 AssertThrow(n_cols ==
static_cast<unsigned int>(this->GetNumberVecs()),
1013 for (
unsigned int i = 0; i < n_rows; ++i)
1014 for (
unsigned int j = 0; j < n_cols; ++j)
1015 B(i, j) = alpha * ((*A.vectors[i]) * (*this->vectors[j]));
1023 MvDot(
const Belos::MultiVec<value_type> &A_,
1024 std::vector<value_type> & b)
const
1026 const auto &A = try_to_get_underlying_vector(A_);
1028 AssertThrow(this->vectors.size() == A.vectors.size(),
1032 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
1033 b[i] = (*this->vectors[i]) * (*A.vectors[i]);
1041 std::vector<
typename Teuchos::ScalarTraits<value_type>::magnitudeType>
1043 Belos::NormType type = Belos::TwoNorm)
const
1048 for (
unsigned int i = 0; i < this->vectors.size(); ++i)
1049 normvec[i] = this->vectors[i]->
l2_norm();
1056 SetBlock(
const Belos::MultiVec<value_type> &A,
1057 const std::vector<int> & index)
1077 MvInit(
const value_type alpha)
1087 MvPrint(std::ostream &os)
const
1108 genericVector()
const
1118 static MultiVecWrapper<VectorType> &
1119 try_to_get_underlying_vector(Belos::MultiVec<value_type> &vec_in)
1121 auto vec =
dynamic_cast<MultiVecWrapper<VectorType> *
>(&vec_in);
1131 const static MultiVecWrapper<VectorType> &
1132 try_to_get_underlying_vector(
const Belos::MultiVec<value_type> &vec_in)
1134 auto vec =
dynamic_cast<const MultiVecWrapper<VectorType> *
>(&vec_in);
1142# ifdef HAVE_BELOS_TSQR
1144 factorExplicit(Belos::MultiVec<value_type> &,
1145 Teuchos::SerialDenseMatrix<int, value_type> &,
1153 Teuchos::SerialDenseMatrix<int, value_type> &,
1154 const typename Teuchos::ScalarTraits<value_type>::magnitudeType &)
1165 std::vector<std::shared_ptr<VectorType>> vectors;
1171 MultiVecWrapper() =
default;
1180 template <
class OperatorType,
class VectorType>
1181 class OperatorWrapper
1182 :
public Belos::Operator<typename VectorType::value_type>
1188 using value_type =
typename VectorType::value_type;
1194 this_type_is_missing_a_specialization()
1202 OperatorWrapper(
const OperatorType &op)
1209 virtual ~OperatorWrapper() =
default;
1215 Apply(
const Belos::MultiVec<value_type> &x,
1216 Belos::MultiVec<value_type> & y,
1217 Belos::ETrans trans = Belos::NOTRANS)
const
1222 op.vmult(MultiVecWrapper<VectorType>::try_to_get_underlying_vector(y)
1224 MultiVecWrapper<VectorType>::try_to_get_underlying_vector(x)
1232 HasApplyTranspose()
const
1242 const OperatorType &op;
1249 template <
typename VectorType>
1250 SolverBelos<VectorType>::SolverBelos(
1252 const AdditionalData & additional_data,
1253 const Teuchos::RCP<Teuchos::ParameterList> &belos_parameters)
1254 : solver_control(solver_control)
1255 , additional_data(additional_data)
1256 , belos_parameters(belos_parameters)
1261 template <
typename VectorType>
1262 template <
typename OperatorType,
typename PreconditionerType>
1264 SolverBelos<VectorType>::solve(
const OperatorType & A_dealii,
1265 VectorType & x_dealii,
1266 const VectorType & b_dealii,
1267 const PreconditionerType &P_dealii)
1269 using value_type =
typename VectorType::value_type;
1271 using MV = Belos::MultiVec<value_type>;
1272 using OP = Belos::Operator<value_type>;
1274 Teuchos::RCP<OP> A = Teuchos::rcp(
1275 new internal::OperatorWrapper<OperatorType, VectorType>(A_dealii));
1276 Teuchos::RCP<OP> P = Teuchos::rcp(
1277 new internal::OperatorWrapper<PreconditionerType, VectorType>(P_dealii));
1278 Teuchos::RCP<MV> X =
1279 Teuchos::rcp(
new internal::MultiVecWrapper<VectorType>(x_dealii));
1280 Teuchos::RCP<MV> B =
1281 Teuchos::rcp(
new internal::MultiVecWrapper<VectorType>(b_dealii));
1283 Teuchos::RCP<Belos::LinearProblem<value_type, MV, OP>> problem =
1284 Teuchos::rcp(
new Belos::LinearProblem<value_type, MV, OP>(A, X, B));
1286 if (additional_data.right_preconditioning ==
false)
1287 problem->setLeftPrec(P);
1289 problem->setRightPrec(P);
1291 const bool problem_set = problem->setProblem();
1296 r.reinit(x_dealii,
true);
1297 A_dealii.vmult(r, x_dealii);
1298 r.sadd(-1., 1., b_dealii);
1299 const auto norm_0 = r.l2_norm();
1304 double relative_tolerance_to_be_achieved =
1305 solver_control.tolerance() / norm_0;
1306 const unsigned int max_steps = solver_control.max_steps();
1308 if (
const auto *reduction_control =
1310 relative_tolerance_to_be_achieved =
1311 std::max(relative_tolerance_to_be_achieved,
1312 reduction_control->reduction());
1314 Teuchos::RCP<Teuchos::ParameterList> belos_parameters_copy(
1315 Teuchos::rcp(
new Teuchos::ParameterList(*belos_parameters)));
1317 belos_parameters_copy->set(
"Convergence Tolerance",
1318 relative_tolerance_to_be_achieved);
1319 belos_parameters_copy->set(
"Maximum Iterations",
1320 static_cast<int>(max_steps));
1322 Teuchos::RCP<Belos::SolverManager<value_type, MV, OP>> solver;
1324 if (additional_data.solver_name == SolverName::cg)
1325 solver = Teuchos::rcp(
1326 new Belos::BlockCGSolMgr<value_type, MV, OP>(problem,
1327 belos_parameters_copy));
1328 else if (additional_data.solver_name == SolverName::gmres)
1329 solver = Teuchos::rcp(
1330 new Belos::BlockGmresSolMgr<value_type, MV, OP>(problem,
1331 belos_parameters_copy));
1335 const auto flag = solver->solve();
1337 solver_control.check(solver->getNumIters(), solver->achievedTol() * norm_0);
1339 AssertThrow(flag == Belos::ReturnType::Converged ||
1342 (solver_control.last_step() == max_steps)),
1344 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)
void solve(const SparseMatrix &A, ::LinearAlgebra::distributed::Vector< double > &x, const ::LinearAlgebra::distributed::Vector< double > &b)
const AdditionalData additional_data
virtual ~SolverDirect()=default
void initialize(const SparseMatrix &A)
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
SolverControl & control() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcTrilinosError(int arg1)
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
#define DeclException1(Exception1, type1, outsequence)
#define AssertThrow(cond, exc)
std::vector< value_type > l2_norm(const typename ::Triangulation< dim, spacedim >::cell_iterator &parent, const value_type parent_value)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
const unsigned int gmres_restart_parameter
const bool output_solver_details
bool output_solver_details