15 #include "../config/config.hpp" 17 #ifdef MFEM_USE_GINKGO 19 #include "operator.hpp" 23 #include <ginkgo/ginkgo.hpp> 32 #define MFEM_GINKGO_VERSION \ 33 ((GKO_VERSION_MAJOR*100 + GKO_VERSION_MINOR)*100 + GKO_VERSION_PATCH) 42 #if MFEM_GINKGO_VERSION < 10500 43 template <
typename T>
using gko_array = gko::Array<T>;
45 template <
typename T>
using gko_array = gko::array<T>;
76 gko::size_type size,
Vector *mfem_vec,
77 bool ownership =
false)
78 : gko::matrix::Dense<double>(
80 gko::
dim<2> {size, 1},
84 exec != exec->get_master() ? true :
false)),
95 wrapped_vec = std::unique_ptr<
Vector,
96 std::function<void(Vector *)>>(
101 using deleter = gko::null_deleter<Vector>;
102 wrapped_vec = std::unique_ptr<Vector,
103 std::function<void(Vector *)>>(
104 mfem_vec, deleter{});
108 static std::unique_ptr<VectorWrapper>
create(
109 std::shared_ptr<const gko::Executor> exec,
112 bool ownership =
false)
114 return std::unique_ptr<VectorWrapper>(
126 virtual std::unique_ptr<gko::matrix::Dense<double>>
131 this->wrapped_vec.get()->GetMemory().GetMemoryType());
133 mfem_vec->
UseDevice(this->wrapped_vec.get()->UseDevice());
149 std::shared_ptr<const gko::Executor> exec,
150 const gko::dim<2> &size,
151 gko::size_type stride)
const override 158 "VectorWrapper cannot be created with stride > 1");
161 gko::size_type total_size = size[0]*size[1];
164 this->wrapped_vec.get()->GetMemory().GetMemoryType());
166 mfem_vec->
UseDevice(this->wrapped_vec.get()->UseDevice());
172 this->get_executor(), total_size, mfem_vec,
179 const gko::span &rows,
180 const gko::span &columns,
181 const gko::size_type stride)
override 184 gko::size_type num_rows = rows.end - rows.begin;
185 gko::size_type num_cols = columns.end - columns.begin;
189 if (num_cols > 1 || stride > 1)
191 throw gko::BadDimension(
192 __FILE__, __LINE__, __func__,
"new_submatrix", num_rows,
194 "VectorWrapper submatrix must have one column and stride = 1");
196 int data_size =
static_cast<int>(num_rows * num_cols);
197 int start =
static_cast<int>(rows.begin);
200 mfem_vec->
MakeRef(*(this->wrapped_vec.get()), start, data_size);
201 mfem_vec->
UseDevice(this->wrapped_vec.get()->UseDevice());
208 this->get_executor(), data_size, mfem_vec,
213 std::unique_ptr<Vector, std::function<void(Vector *)>> wrapped_vec;
225 :
public gko::EnableLinOp<OperatorWrapper>,
226 public gko::EnableCreateMethod<OperatorWrapper>
230 gko::size_type size = 0,
233 gko::EnableCreateMethod<OperatorWrapper>()
235 this->wrapped_oper = oper;
239 void apply_impl(
const gko::LinOp *
b, gko::LinOp *x)
const override;
241 const gko::LinOp *
beta, gko::LinOp *x)
const override;
249 template <
typename ValueType=
double>
250 double get_norm(
const gko::matrix::Dense<ValueType> *norm)
253 auto cpu_norm = clone(norm->get_executor()->get_master(), norm);
255 return cpu_norm->at(0, 0);
260 template <
typename ValueType=
double>
264 auto exec =
b->get_executor();
266 auto b_norm = gko::initialize<gko::matrix::Dense<ValueType>>({0.0}, exec);
268 b->compute_norm2(lend(b_norm));
270 return std::pow(
get_norm(lend(b_norm)),2);
284 template <
typename ValueType=
double>
291 if (compute_real_residual)
293 mfem::out <<
"Iteration log with real residual norms:" << std::endl;
297 mfem::out <<
"Iteration log with residual norms:" << std::endl;
299 mfem::out <<
'|' << std::setw(10) <<
"Iteration" <<
'|' << std::setw(25)
300 <<
"Residual Norm" <<
'|' << std::endl;
303 mfem::out <<
'|' << std::setfill(
'-') << std::setw(11) <<
'|' <<
304 std::setw(26) <<
'|' << std::setfill(
' ') << std::endl;
307 for (std::size_t i = 0; i < iterations.size(); i++)
309 mfem::out <<
'|' << std::setw(10) << iterations[i] <<
'|' 310 << std::setw(25) << residual_norms[i] <<
'|' << std::endl;
314 mfem::out.unsetf(std::ios_base::floatfield);
316 mfem::out <<
'|' << std::setfill(
'-') << std::setw(11) <<
'|' <<
317 std::setw(26) <<
'|' << std::setfill(
' ') << std::endl;
325 const gko::size_type &iteration,
326 const gko::LinOp *residual,
327 const gko::LinOp *solution,
328 const gko::LinOp *residual_norm,
329 const gko::LinOp *implicit_sq_residual_norm)
const override 333 if (solution && compute_real_residual)
336 auto exec = matrix->get_executor();
339 matrix->apply(gko::lend(solution), gko::lend(res));
342 if (dynamic_cast<const VectorWrapper*>(b))
344 const VectorWrapper *b_cast = gko::as<const VectorWrapper>(b);
352 auto neg_one = gko::initialize<gko_dense>({-1.0}, exec);
353 res->add_scaled(gko::lend(neg_one), gko::lend(b));
363 if (implicit_sq_residual_norm)
365 auto dense_norm = gko::as<gko_dense>(implicit_sq_residual_norm);
367 residual_norms.push_back(
get_norm(dense_norm));
370 else if (residual_norm)
372 auto dense_norm = gko::as<gko_dense>(residual_norm);
374 residual_norms.push_back(
get_norm(dense_norm));
379 auto dense_residual = gko::as<gko_dense>(residual);
383 residual_norms.push_back(norm);
387 iterations.push_back(iteration);
392 const gko::size_type &iteration,
393 const gko::LinOp *residual,
394 const gko::LinOp *solution,
395 const gko::LinOp *residual_norm)
const override 403 const gko::LinOp *matrix,
const gko_dense *b,
404 bool compute_real_residual=
false)
406 #if MFEM_GINKGO_VERSION < 10500
407 gko::log::Logger(exec,
408 gko::log::Logger::iteration_complete_mask),
410 gko::log::Logger(gko::log::Logger::iteration_complete_mask),
414 compute_real_residual{compute_real_residual}
416 if (compute_real_residual ==
true)
418 if (dynamic_cast<const VectorWrapper*>(b))
420 const VectorWrapper *b_cast = gko::as<const VectorWrapper>(b);
421 res = std::move(gko_dense::create_with_config_of(b_cast).release());
425 res = std::move(gko::clone(b).release());
432 const gko::LinOp *matrix;
438 mutable std::vector<ValueType> residual_norms{};
440 mutable std::vector<std::size_t> iterations{};
443 const bool compute_real_residual;
491 return this->executor;
495 std::shared_ptr<gko::Executor> executor;
698 std::shared_ptr<gko::stop::ResidualNorm<>::Factory>
705 std::shared_ptr<gko::stop::ResidualNorm<>::Factory>
712 std::shared_ptr<gko::stop::ImplicitResidualNorm<>::Factory>
719 std::shared_ptr<gko::stop::ImplicitResidualNorm<>::Factory>
770 initialize_ginkgo_log(gko::matrix::Dense<double>*
b)
const;
776 std::shared_ptr<gko::LinOp> system_oper;
786 template<
typename SolverType>
797 gko::as<typename SolverType::Factory>(
solver_gen)->get_parameters().criteria =
809 gko::as<typename SolverType::Factory>(
solver_gen)->get_parameters().criteria =
821 gko::as<typename SolverType::Factory>(
solver_gen)->get_parameters().criteria =
985 using gko::solver::cb_gmres::storage_precision;
1015 storage_precision prec = storage_precision::reduce1);
1034 storage_precision prec = storage_precision::reduce1);
1095 const std::string &storage_opt =
"none",
1096 const double accuracy = 1.e-1,
1097 const int max_block_size = 32
1129 const std::string &factorization_type =
"exact",
1130 const int sweeps = 0,
1131 const bool skip_sort =
false 1171 const std::string &factorization_type =
"exact",
1172 const int sweeps = 0,
1173 const int sparsity_power = 1,
1174 const bool skip_sort =
false 1206 const std::string &factorization_type =
"exact",
1207 const int sweeps = 0,
1208 const bool skip_sort =
false 1248 const std::string &factorization_type =
"exact",
1249 const int sweeps = 0,
1250 const int sparsity_power = 1,
1251 const bool skip_sort =
false 1271 const Solver &mfem_precond
1281 MFEM_ABORT(
"Ginkgo::MFEMPreconditioner must be constructed " 1282 "with the MFEM Operator that it will wrap as an argument;\n" 1283 "calling SetOperator() is not allowed.");
1290 #endif // MFEM_USE_GINKGO 1292 #endif // MFEM_GINKGO bool use_implicit_res_norm
std::shared_ptr< gko::log::Convergence<> > convergence_logger
bool UsesVectorWrappers() const
void SetRelTol(double rtol)
std::shared_ptr< ResidualLogger<> > residual_logger
virtual ~GinkgoExecutor()=default
virtual void SetOperator(const Operator &op)
std::shared_ptr< gko::stop::ResidualNorm<>::Factory > abs_criterion
GinkgoIterativeSolver(GinkgoExecutor &exec, bool use_implicit_res_norm)
CBGMRESSolver(GinkgoExecutor &exec, int dim=0, storage_precision prec=storage_precision::reduce1)
const std::shared_ptr< gko::LinOp > GetGeneratedPreconditioner() const
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
std::shared_ptr< gko::LinOpFactory > precond_gen
CGSSolver(GinkgoExecutor &exec)
virtual std::unique_ptr< gko::matrix::Dense< double > > create_with_same_config() const override
MFEMPreconditioner(GinkgoExecutor &exec, const Solver &mfem_precond)
static std::unique_ptr< VectorWrapper > create(std::shared_ptr< const gko::Executor > exec, gko::size_type size, Vector *mfem_vec, bool ownership=false)
JacobiPreconditioner(GinkgoExecutor &exec, const std::string &storage_opt="none", const double accuracy=1.e-1, const int max_block_size=32)
std::shared_ptr< gko::Executor > executor
GinkgoExecutor(ExecType exec_type)
virtual void SetOperator(const Operator &op)
void SetMaxIter(int max_it)
gko::matrix::Dense< ValueType > gko_dense
int GetNumIterations() const
virtual void Mult(const Vector &x, Vector &y) const
BICGSTABSolver(GinkgoExecutor &exec)
bool HasGeneratedPreconditioner() const
std::shared_ptr< gko::stop::ImplicitResidualNorm<>::Factory > imp_rel_criterion
IluPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const bool skip_sort=false)
virtual std::unique_ptr< gko::matrix::Dense< double > > create_submatrix_impl(const gko::span &rows, const gko::span &columns, const gko::size_type stride) override
Vector & get_mfem_vec_ref()
const std::shared_ptr< gko::LinOpFactory > GetFactory() const
std::shared_ptr< gko::Executor > executor
void on_iteration_complete(const gko::LinOp *op, const gko::size_type &iteration, const gko::LinOp *residual, const gko::LinOp *solution, const gko::LinOp *residual_norm) const override
bool sub_op_needs_wrapped_vecs
void update_stop_factory()
CGSolver(GinkgoExecutor &exec)
virtual void Mult(const Vector &x, Vector &y) const
void SetPrintLevel(int print_lvl)
virtual std::unique_ptr< gko::matrix::Dense< double > > create_with_type_of_impl(std::shared_ptr< const gko::Executor > exec, const gko::dim< 2 > &size, gko::size_type stride) const override
ResidualLogger(std::shared_ptr< const gko::Executor > exec, const gko::LinOp *matrix, const gko_dense *b, bool compute_real_residual=false)
VectorWrapper(std::shared_ptr< const gko::Executor > exec, gko::size_type size, Vector *mfem_vec, bool ownership=false)
GMRESSolver(GinkgoExecutor &exec, int dim=0)
virtual ~GinkgoPreconditioner()=default
double compute_norm(const gko::matrix::Dense< ValueType > *b)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
std::shared_ptr< gko::Executor > GetExecutor() const
std::shared_ptr< gko::stop::ResidualNorm<>::Factory > rel_criterion
double get_norm(const gko::matrix::Dense< ValueType > *norm)
IRSolver(GinkgoExecutor &exec)
const Vector & get_mfem_vec_const_ref() const
IcPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const bool skip_sort=false)
std::shared_ptr< gko::stop::Combined::Factory > combined_factory
std::shared_ptr< gko::LinOpFactory > solver_gen
bool has_generated_precond
const std::shared_ptr< gko::LinOpFactory > GetFactory() const
FCGSolver(GinkgoExecutor &exec)
IcIsaiPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const int sparsity_power=1, const bool skip_sort=false)
void on_iteration_complete(const gko::LinOp *, const gko::size_type &iteration, const gko::LinOp *residual, const gko::LinOp *solution, const gko::LinOp *residual_norm, const gko::LinOp *implicit_sq_residual_norm) const override
IluIsaiPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const int sparsity_power=1, const bool skip_sort=false)
void SetAbsTol(double atol)
GinkgoPreconditioner(GinkgoExecutor &exec)
OperatorWrapper(std::shared_ptr< const gko::Executor > exec, gko::size_type size=0, const Operator *oper=NULL)
virtual ~GinkgoIterativeSolver()=default
std::shared_ptr< gko::LinOp > generated_precond
EnableGinkgoSolver(GinkgoExecutor &exec, bool use_implicit_res_norm)
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
std::shared_ptr< gko::stop::ImplicitResidualNorm<>::Factory > imp_abs_criterion
virtual void SetOperator(const Operator &op)
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
gko::Array< T > gko_array
double GetFinalNorm() const
void apply_impl(const gko::LinOp *b, gko::LinOp *x) const override
std::shared_ptr< gko::LinOp > solver
void operator()(pointer ptr) const noexcept