# include <Epetra_Operator.h>
// for Belos solvers
+# include <BelosBlockCGSolMgr.hpp>
# include <BelosBlockGmresSolMgr.hpp>
# include <BelosEpetraAdapter.hpp>
# include <BelosIteration.hpp>
class SolverBelos
{
public:
+ /**
+ * Enumeration object that Trilinos which solver to use.
+ * Currently enabled options are:
+ */
+ enum SolverName
+ {
+ /**
+ * Use the conjugate gradient (CG) algorithm.
+ */
+ cg,
+ /**
+ * Use the generalized minimum residual (GMRES) algorithm.
+ */
+ gmres,
+ } solver_name;
+
/**
* Struct that helps to configure SolverBelos. More advanced
* parameters are passed to the constructor SolverBelos
/**
* Constructor.
*/
- AdditionalData(const bool right_preconditioning = false)
+ AdditionalData(const SolverName &solver_name = SolverName::cg,
+ const bool right_preconditioning = false)
: right_preconditioning(right_preconditioning)
{}
+ /**
+ * Solver type;
+ */
+ SolverName solver_name;
+
/**
* Flag for right preconditioning.
*/
for (unsigned int i = 0; i < index.size(); ++i)
{
- new_multi_vec->vectors[i] = std::make_shared<VectorType>();
- *new_multi_vec->vectors[i] = *this->vectors[i];
+ AssertThrow(static_cast<unsigned int>(index[i]) <
+ this->vectors.size(),
+ ExcInternalError());
+
+ new_multi_vec->vectors[i] = std::make_shared<VectorType>();
+
+ AssertIndexRange(index[i], this->vectors.size());
+ *new_multi_vec->vectors[i] = *this->vectors[index[i]];
}
return new_multi_vec;
new_multi_vec->vectors.resize(index.size());
for (unsigned int i = 0; i < index.size(); ++i)
- new_multi_vec->vectors[i].reset(
- this->vectors[index[i]].get(),
- [](auto
- *) { /*Nothing to do, since we are creating only a view.*/ });
+ {
+ AssertThrow(static_cast<unsigned int>(index[i]) <
+ this->vectors.size(),
+ ExcInternalError());
+
+ new_multi_vec->vectors[i].reset(
+ this->vectors[index[i]].get(),
+ [](
+ auto
+ *) { /*Nothing to do, since we are creating only a view.*/ });
+ }
return new_multi_vec;
}
GetGlobalLength() const
{
AssertThrow(this->vectors.size() > 0, ExcInternalError());
+
+ for (unsigned int i = 1; i < this->vectors.size(); ++i)
+ AssertDimension(this->vectors[0]->size(), this->vectors[i]->size());
+
return this->vectors[0]->size();
}
const Teuchos::SerialDenseMatrix<int, value_type> &B,
const value_type beta)
{
- const auto &A = cast(A_);
+ const auto &A = try_to_get_underlying_vector(A_);
const unsigned int n_rows = B.numRows();
const unsigned int n_cols = B.numCols();
const value_type beta,
const Belos::MultiVec<value_type> &B_)
{
- const auto &A = cast(A_);
- const auto &B = cast(B_);
+ const auto &A = try_to_get_underlying_vector(A_);
+ const auto &B = try_to_get_underlying_vector(B_);
AssertThrow(this->vectors.size() == A.vectors.size(),
ExcInternalError());
const Belos::MultiVec<value_type> & A_,
Teuchos::SerialDenseMatrix<int, value_type> &B) const
{
- const auto &A = cast(A_);
+ const auto &A = try_to_get_underlying_vector(A_);
const unsigned int n_rows = B.numRows();
const unsigned int n_cols = B.numCols();
ExcInternalError());
for (unsigned int i = 0; i < n_rows; ++i)
- {
- for (unsigned int j = 0; j < n_cols; ++j)
- {
- AssertThrow(A.vectors[i], ExcNotImplemented());
- AssertThrow(this->vectors[j], ExcNotImplemented());
-
- B(i, j) = alpha * ((*A.vectors[i]) * (*this->vectors[j]));
- }
- }
+ for (unsigned int j = 0; j < n_cols; ++j)
+ B(i, j) = alpha * ((*A.vectors[i]) * (*this->vectors[j]));
}
/**
MvDot(const Belos::MultiVec<value_type> &A_,
std::vector<value_type> & b) const
{
- const auto &A = cast(A_);
+ const auto &A = try_to_get_underlying_vector(A_);
AssertThrow(this->vectors.size() == A.vectors.size(),
ExcInternalError());
* Cast Belos::MultiVec to MultiVecWrapper.
*/
static MultiVecWrapper<VectorType> &
- cast(Belos::MultiVec<value_type> &vec_in)
+ try_to_get_underlying_vector(Belos::MultiVec<value_type> &vec_in)
{
auto vec = dynamic_cast<MultiVecWrapper<VectorType> *>(&vec_in);
* Cast Belos::MultiVec to MultiVecWrapper (const version).
*/
const static MultiVecWrapper<VectorType> &
- cast(const Belos::MultiVec<value_type> &vec_in)
+ try_to_get_underlying_vector(const Belos::MultiVec<value_type> &vec_in)
{
auto vec = dynamic_cast<const MultiVecWrapper<VectorType> *>(&vec_in);
# ifdef HAVE_BELOS_TSQR
virtual void
- factorExplicit(Belos::MultiVec<value_type> & Q,
- Teuchos::SerialDenseMatrix<int, value_type> &R,
- const bool forceNonnegativeDiagonal = false)
+ factorExplicit(Belos::MultiVec<value_type> &,
+ Teuchos::SerialDenseMatrix<int, value_type> &,
+ const bool = false)
{
- TEUCHOS_TEST_FOR_EXCEPTION(
- true,
- std::logic_error,
- "The Belos::MultiVec<"
- << Teuchos::TypeNameTraits<value_type>::name()
- << "> subclass which you "
- "are using does not implement the TSQR-related method factorExplicit().");
+ Asser(false, ExcNotImplemented());
}
virtual int
revealRank(
- Teuchos::SerialDenseMatrix<int, value_type> & R,
- const typename Teuchos::ScalarTraits<value_type>::magnitudeType &tol)
+ Teuchos::SerialDenseMatrix<int, value_type> &,
+ const typename Teuchos::ScalarTraits<value_type>::magnitudeType &)
{
- TEUCHOS_TEST_FOR_EXCEPTION(
- true,
- std::logic_error,
- "The Belos::MultiVec<"
- << Teuchos::TypeNameTraits<value_type>::name()
- << "> subclass which you "
- "are using does not implement the TSQR-related method revealRank().");
+ Asser(false, ExcNotImplemented());
}
# endif
* Constructor.
*/
OperatorWrapper(const OperatorType &op)
- : op(op){};
+ : op(op)
+ {}
/**
* Destructor.
// TODO: check for Tvmult
AssertThrow(trans == Belos::NOTRANS, ExcNotImplemented());
- op.vmult(MultiVecWrapper<VectorType>::cast(y).genericVector(),
- MultiVecWrapper<VectorType>::cast(x).genericVector());
+ op.vmult(MultiVecWrapper<VectorType>::try_to_get_underlying_vector(y)
+ .genericVector(),
+ MultiVecWrapper<VectorType>::try_to_get_underlying_vector(x)
+ .genericVector());
}
/**
template <typename VectorType>
template <typename OperatorType, typename PreconditionerType>
void
- SolverBelos<VectorType>::solve(const OperatorType & a,
- VectorType & x,
- const VectorType & b,
- const PreconditionerType &p)
+ SolverBelos<VectorType>::solve(const OperatorType & A_dealii,
+ VectorType & x_dealii,
+ const VectorType & b_dealii,
+ const PreconditionerType &P_dealii)
{
using value_type = typename VectorType::value_type;
using MV = Belos::MultiVec<value_type>;
using OP = Belos::Operator<value_type>;
- Teuchos::RCP<OP> A =
- Teuchos::rcp(new internal::OperatorWrapper<OperatorType, VectorType>(a));
+ Teuchos::RCP<OP> A = Teuchos::rcp(
+ new internal::OperatorWrapper<OperatorType, VectorType>(A_dealii));
Teuchos::RCP<OP> P = Teuchos::rcp(
- new internal::OperatorWrapper<PreconditionerType, VectorType>(p));
+ new internal::OperatorWrapper<PreconditionerType, VectorType>(P_dealii));
Teuchos::RCP<MV> X =
- Teuchos::rcp(new internal::MultiVecWrapper<VectorType>(x));
+ Teuchos::rcp(new internal::MultiVecWrapper<VectorType>(x_dealii));
Teuchos::RCP<MV> B =
- Teuchos::rcp(new internal::MultiVecWrapper<VectorType>(b));
+ Teuchos::rcp(new internal::MultiVecWrapper<VectorType>(b_dealii));
Teuchos::RCP<Belos::LinearProblem<value_type, MV, OP>> problem =
Teuchos::rcp(new Belos::LinearProblem<value_type, MV, OP>(A, X, B));
// compute initial residal
VectorType r;
- r.reinit(x, true);
- a.vmult(r, x);
- r.sadd(-1., 1., b);
+ r.reinit(x_dealii, true);
+ A_dealii.vmult(r, x_dealii);
+ r.sadd(-1., 1., b_dealii);
const auto norm_0 = r.l2_norm();
if (solver_control.check(0, norm_0) != SolverControl::iterate)
double relative_tolerance_to_be_achieved =
solver_control.tolerance() / norm_0;
- const int max_steps = solver_control.max_steps();
+ const unsigned int max_steps = solver_control.max_steps();
if (const auto *reduction_control =
dynamic_cast<ReductionControl *>(&solver_control))
belos_parameters_copy->set("Convergence Tolerance",
relative_tolerance_to_be_achieved);
- belos_parameters_copy->set("Maximum Iterations", max_steps);
+ belos_parameters_copy->set("Maximum Iterations",
+ static_cast<int>(max_steps));
- Teuchos::RCP<Belos::SolverManager<value_type, MV, OP>> solver =
- Teuchos::rcp(
+ Teuchos::RCP<Belos::SolverManager<value_type, MV, OP>> solver;
+
+ if (additional_data.solver_name == SolverName::cg)
+ solver = Teuchos::rcp(
+ new Belos::BlockCGSolMgr<value_type, MV, OP>(problem,
+ belos_parameters_copy));
+ else if (additional_data.solver_name == SolverName::gmres)
+ solver = Teuchos::rcp(
new Belos::BlockGmresSolMgr<value_type, MV, OP>(problem,
belos_parameters_copy));
+ else
+ AssertThrow(false, ExcNotImplemented());
const auto flag = solver->solve();