35#if defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP)
36 gko::version_info gko_version = gko::version_info::get();
37 bool gko_with_omp_support = (strcmp(gko_version.omp_version.tag,
38 "not compiled") != 0);
44 executor = gko::ReferenceExecutor::create();
49 executor = gko::OmpExecutor::create();
54 if (gko::CudaExecutor::get_num_devices() > 0)
57 int current_device = 0;
58 MFEM_GPU_CHECK(cudaGetDevice(¤t_device));
60 if (gko_with_omp_support)
62 executor = gko::CudaExecutor::create(current_device,
63 gko::OmpExecutor::create());
68 executor = gko::CudaExecutor::create(current_device,
69 gko::ReferenceExecutor::create());
75 MFEM_ABORT(
"gko::CudaExecutor::get_num_devices() did not report "
76 "any valid devices.");
82 if (gko::HipExecutor::get_num_devices() > 0)
85 int current_device = 0;
86 MFEM_GPU_CHECK(hipGetDevice(¤t_device));
88 if (gko_with_omp_support)
90 executor = gko::HipExecutor::create(current_device,
91 gko::OmpExecutor::create());
96 executor = gko::HipExecutor::create(current_device,
97 gko::ReferenceExecutor::create());
103 MFEM_ABORT(
"gko::HipExecutor::get_num_devices() did not report "
104 "any valid devices.");
109 MFEM_ABORT(
"Invalid ExecType specified");
121 MFEM_WARNING(
"Parameter host_exec_type ignored for CPU GinkgoExecutor.");
122 executor = gko::ReferenceExecutor::create();
127 MFEM_WARNING(
"Parameter host_exec_type ignored for CPU GinkgoExecutor.");
128 executor = gko::OmpExecutor::create();
133 if (gko::CudaExecutor::get_num_devices() > 0)
136 int current_device = 0;
137 MFEM_GPU_CHECK(cudaGetDevice(¤t_device));
140 executor = gko::CudaExecutor::create(current_device,
141 gko::OmpExecutor::create());
145 executor = gko::CudaExecutor::create(current_device,
146 gko::ReferenceExecutor::create());
152 MFEM_ABORT(
"gko::CudaExecutor::get_num_devices() did not report "
153 "any valid devices.");
159 if (gko::HipExecutor::get_num_devices() > 0)
162 int current_device = 0;
163 MFEM_GPU_CHECK(hipGetDevice(¤t_device));
166 executor = gko::HipExecutor::create(current_device,
167 gko::OmpExecutor::create());
171 executor = gko::HipExecutor::create(current_device,
172 gko::ReferenceExecutor::create());
178 MFEM_ABORT(
"gko::HipExecutor::get_num_devices() did not report "
179 "any valid devices.");
184 MFEM_ABORT(
"Invalid ExecType specified");
191 gko::version_info gko_version = gko::version_info::get();
192 bool gko_with_omp_support = (strcmp(gko_version.omp_version.tag,
193 "not compiled") != 0);
196 if (gko::CudaExecutor::get_num_devices() > 0)
199 int current_device = 0;
200 MFEM_GPU_CHECK(cudaGetDevice(¤t_device));
202 if (gko_with_omp_support)
204 executor = gko::CudaExecutor::create(current_device,
205 gko::OmpExecutor::create());
210 executor = gko::CudaExecutor::create(current_device,
211 gko::ReferenceExecutor::create());
217 MFEM_ABORT(
"gko::CudaExecutor::get_num_devices() did not report "
218 "any valid devices.");
223 if (gko::HipExecutor::get_num_devices() > 0)
226 int current_device = 0;
227 MFEM_GPU_CHECK(hipGetDevice(¤t_device));
229 if (gko_with_omp_support)
231 executor = gko::HipExecutor::create(current_device,
232 gko::OmpExecutor::create());
237 executor = gko::HipExecutor::create(current_device,
238 gko::ReferenceExecutor::create());
244 MFEM_ABORT(
"gko::HipExecutor::get_num_devices() did not report "
245 "any valid devices.");
253 if (gko_with_omp_support)
255 executor = gko::OmpExecutor::create();
259 executor = gko::ReferenceExecutor::create();
264 executor = gko::ReferenceExecutor::create();
277 if (gko::CudaExecutor::get_num_devices() > 0)
280 int current_device = 0;
281 MFEM_GPU_CHECK(cudaGetDevice(¤t_device));
284 executor = gko::CudaExecutor::create(current_device,
285 gko::OmpExecutor::create());
289 executor = gko::CudaExecutor::create(current_device,
290 gko::ReferenceExecutor::create());
296 MFEM_ABORT(
"gko::CudaExecutor::get_num_devices() did not report "
297 "any valid devices.");
302 if (gko::HipExecutor::get_num_devices() > 0)
305 int current_device = 0;
306 MFEM_GPU_CHECK(hipGetDevice(¤t_device));
309 executor = gko::HipExecutor::create(current_device,
310 gko::OmpExecutor::create());
314 executor = gko::HipExecutor::create(current_device,
315 gko::ReferenceExecutor::create());
321 MFEM_ABORT(
"gko::HipExecutor::get_num_devices() did not report "
322 "any valid devices.");
327 MFEM_WARNING(
"Parameter host_exec_type ignored for CPU GinkgoExecutor.");
331 gko::version_info gko_version = gko::version_info::get();
332 bool gko_with_omp_support = (strcmp(gko_version.omp_version.tag,
333 "not compiled") != 0);
334 if (gko_with_omp_support)
336 executor = gko::OmpExecutor::create();
340 executor = gko::ReferenceExecutor::create();
345 executor = gko::ReferenceExecutor::create();
351 bool use_implicit_res_norm)
353#
if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
356 use_implicit_res_norm(use_implicit_res_norm)
371#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
374 bool use_implicit_res_norm)
376 use_implicit_res_norm(use_implicit_res_norm),
377 needs_sorted_diagonal_mat(false)
380 gko_comm = std::shared_ptr<gko::experimental::mpi::communicator>(
381 new gko::experimental::mpi::communicator(comm));
398 using ResidualCriterionFactory = gko::stop::ResidualNorm<real_t>;
399 using ImplicitResidualCriterionFactory =
400 gko::stop::ImplicitResidualNorm<real_t>;
405 .with_reduction_factor(
rel_tol)
406 .with_baseline(gko::stop::mode::initial_resnorm)
409 .with_reduction_factor(
abs_tol)
410 .with_baseline(gko::stop::mode::absolute)
413 gko::stop::Combined::build()
416 gko::stop::Iteration::build()
417 .with_max_iters(
static_cast<unsigned long>(
max_iter))
424 .with_reduction_factor(
rel_tol)
425 .with_baseline(gko::stop::mode::initial_resnorm)
428 .with_reduction_factor(
abs_tol)
429 .with_baseline(gko::stop::mode::absolute)
432 gko::stop::Combined::build()
435 gko::stop::Iteration::build()
436 .with_max_iters(
static_cast<unsigned long>(
max_iter))
443GinkgoIterativeSolver::initialize_ginkgo_log(gko::matrix::Dense<real_t>*
b)
449 std::make_shared<EnableConvergenceLogger<gko::matrix::Dense<real_t>>>
451 system_oper.get(),
b);
453 std::make_shared<EnableResidualLogger<gko::matrix::Dense<real_t>>>
455 system_oper.get(),
b);
459#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
461GinkgoIterativeSolver::initialize_ginkgo_log(ParallelVectorWrapper*
b)
467 std::make_shared<EnableConvergenceLogger<gko::experimental::distributed::Vector<real_t>>>
469 system_oper.get(),
b);
471 std::make_shared<EnableResidualLogger<gko::experimental::distributed::Vector<real_t>>>
473 system_oper.get(),
b);
489 const gko::LinOp *beta,
498 if (
alpha->get_size()[0] > 1 ||
alpha->get_size()[1] > 1)
500 throw gko::BadDimension(
501 __FILE__, __LINE__, __func__,
"alpha",
alpha->get_size()[0],
502 alpha->get_size()[1],
503 "Expected an object of size [1 x 1] for scaling "
504 " in this operator's apply_impl");
506 if (beta->get_size()[0] > 1 || beta->get_size()[1] > 1)
508 throw gko::BadDimension(
509 __FILE__, __LINE__, __func__,
"beta", beta->get_size()[0],
511 "Expected an object of size [1 x 1] for scaling "
512 " in this operator's apply_impl");
517 if (
alpha->get_executor() ==
alpha->get_executor()->get_master())
520 alpha_f = gko::as<gko::matrix::Dense<real_t>>(
alpha)->at(0, 0);
525 this->get_executor()->get_master().get()->copy_from(
526 this->get_executor().get(),
527 1, gko::as<gko::matrix::Dense<real_t>>(
alpha)->get_const_values(),
530 if (beta->get_executor() == beta->get_executor()->get_master())
533 beta_f = gko::as<gko::matrix::Dense<real_t>>(beta)->at(0, 0);
538 this->get_executor()->get_master().get()->copy_from(
539 this->get_executor().get(),
540 1, gko::as<gko::matrix::Dense<real_t>>(beta)->get_const_values(),
561#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
567 gko::as<const mfem::Ginkgo::VectorWrapper>(
568 (gko::as<const ParallelVectorWrapper>(
b))->get_local_wrapped_vec_const());
570 (gko::as<ParallelVectorWrapper>(x))->get_local_wrapped_vec());
577 const gko::LinOp *beta,
583 gko::as<const mfem::Ginkgo::VectorWrapper>(
584 (gko::as<const ParallelVectorWrapper>(
b))->get_local_wrapped_vec_const());
586 (gko::as<ParallelVectorWrapper>(x))->get_local_wrapped_vec());
589 if (
alpha->get_size()[0] > 1 ||
alpha->get_size()[1] > 1)
591 throw gko::BadDimension(
592 __FILE__, __LINE__, __func__,
"alpha",
alpha->get_size()[0],
593 alpha->get_size()[1],
594 "Expected an object of size [1 x 1] for scaling "
595 " in this operator's apply_impl");
597 if (beta->get_size()[0] > 1 || beta->get_size()[1] > 1)
599 throw gko::BadDimension(
600 __FILE__, __LINE__, __func__,
"beta", beta->get_size()[0],
602 "Expected an object of size [1 x 1] for scaling "
603 " in this operator's apply_impl");
607 if (
alpha->get_executor() ==
alpha->get_executor()->get_master())
610 alpha_f = gko::as<gko::matrix::Dense<double>>(
alpha)->at(0, 0);
615 this->get_executor()->get_master().get()->copy_from(
616 this->get_executor().get(),
617 1, gko::as<gko::matrix::Dense<double>>(
alpha)->get_const_values(),
620 if (beta->get_executor() == beta->get_executor()->get_master())
623 beta_f = gko::as<gko::matrix::Dense<double>>(beta)->at(0, 0);
628 this->get_executor()->get_master().get()->copy_from(
629 this->get_executor().get(),
630 1, gko::as<gko::matrix::Dense<double>>(beta)->get_const_values(),
656 MFEM_VERIFY(system_oper,
"System matrix or operator not initialized");
657 MFEM_VERIFY(
executor,
"executor is not initialized");
659 "Mismatching sizes for rhs and solution");
661 using vec = gko::matrix::Dense<real_t>;
669 bool on_device =
false;
674 std::unique_ptr<gko::LinOp> gko_x;
675 std::unique_ptr<gko::LinOp> gko_y;
685 x.
Read(on_device))), 1);
690 initialize_ginkgo_log(gko::as<vec>(gko_x.get()));
694#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
697 using par_vec = gko::experimental::distributed::Vector<real_t>;
699 const_cast<Vector *
>(&x),
false);
702 gko_x = std::unique_ptr<ParallelVectorWrapper>(
705 system_oper->get_size()[0], 1));
706 gko_y = std::unique_ptr<ParallelVectorWrapper>(
709 system_oper->get_size()[0], 1));
712 initialize_ginkgo_log(gko::as<ParallelVectorWrapper>(gko_x.get()));
717 gko_x = std::unique_ptr<vec>(
719 const_cast<Vector *
>(&x),
false));
720 gko_y = std::unique_ptr<vec>(
723 initialize_ginkgo_log(gko::as<vec>(gko_x.get()));
738 solver->apply(gko_x, gko_y);
741 real_t final_res_norm = 0.0;
750#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
765 " iterations with final residual norm "
766 << final_res_norm <<
'\n';
768#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
773#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
774std::unique_ptr<gko::experimental::distributed::Matrix<real_t, gko_hypre_int, gko_hypre_bigint>>
776 std::shared_ptr<gko::Executor> executor,
777 std::shared_ptr<gko::experimental::mpi::communicator> gko_comm,
bool sort_diag)
781 "System matrix is not square");
784 if (executor != executor->get_master())
789 using local_mtx = gko::matrix::Csr<real_t, gko_hypre_int>;
791 gko::experimental::distributed::Matrix<real_t, gko_hypre_int, gko_hypre_bigint>;
792 using gko_partition =
793 gko::experimental::distributed::Partition<gko_hypre_int, gko_hypre_bigint>;
795 gko::experimental::distributed::index_map<gko_hypre_int, gko_hypre_bigint>;
798 auto mpi_exec = executor->get_master();
799 gko::array<gko_hypre_bigint> col_ranges(mpi_exec, gko_comm->size() + 1);
800 col_ranges.fill(gko::zero<gko_hypre_bigint>());
803 gko_comm->all_gather(mpi_exec, par_mat->
GetColStarts() + 1, 1,
804 col_ranges.get_data() + 1, 1);
806 col_ranges.set_executor(executor);
807 auto col_part = gko::share(gko_partition::build_from_contiguous(executor,
811 HYPRE_Int num_offd_cols;
818 recv_indices.set_executor(executor);
819 idx_map imap(executor, col_part, gko_comm->rank(), recv_indices);
823 std::shared_ptr<local_mtx> diag_mat = local_mtx::create(
834 if (sort_diag ==
true)
836 diag_mat->sort_by_column_index();
839 std::shared_ptr<local_mtx> off_diag_mat = local_mtx::create(
840 executor, gko::dim<2>(par_mat->
GetNumRows(), num_offd_cols),
851 return global_mtx::create(executor, *(gko_comm.get()), imap, diag_mat,
877 "System operator is not square");
879#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
883 if (par_op_mat != NULL)
901 bool on_device =
false;
907 using mtx = gko::matrix::Csr<real_t, int>;
909 system_oper = mtx::create(
924#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
928 auto mpi_exec =
executor->get_master();
929 gko_comm->all_reduce(mpi_exec, &global_size, 1, MPI_SUM);
930 system_oper = std::shared_ptr<ParallelOperatorWrapper>(
936 system_oper = std::shared_ptr<OperatorWrapper>(
954 using cg = gko::solver::Cg<real_t>;
959#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
963 using cg = gko::solver::Cg<real_t>;
973 using cg = gko::solver::Cg<real_t>;
979 .with_generated_preconditioner(
983 GetGeneratedPreconditioner().get()))
993 .with_preconditioner(preconditioner.
GetFactory())
998#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1004 using cg = gko::solver::Cg<real_t>;
1011 .with_generated_preconditioner(
1013 .on(this->executor);
1019 .with_preconditioner(preconditioner.
GetFactory())
1020 .on(this->executor);
1030 using bicgstab = gko::solver::Bicgstab<real_t>;
1033 .on(this->executor);
1036#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1040 using bicgstab = gko::solver::Bicgstab<real_t>;
1043 .on(this->executor);
1051 using bicgstab = gko::solver::Bicgstab<real_t>;
1056 .with_generated_preconditioner(
1058 .on(this->executor);
1060 GetGeneratedPreconditioner().get()))
1070 .with_preconditioner(preconditioner.
GetFactory())
1071 .on(this->executor);
1075#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1081 using bicgstab = gko::solver::Bicgstab<real_t>;
1086 .with_generated_preconditioner(
1088 .on(this->executor);
1094 .with_preconditioner(preconditioner.
GetFactory())
1095 .on(this->executor);
1105 using cgs = gko::solver::Cgs<real_t>;
1110#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1114 using cgs = gko::solver::Cgs<real_t>;
1124 using cgs = gko::solver::Cgs<real_t>;
1129 .with_generated_preconditioner(
1131 .on(this->executor);
1133 GetGeneratedPreconditioner().get()))
1143 .with_preconditioner(preconditioner.
GetFactory())
1144 .on(this->executor);
1148#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1153 using cgs = gko::solver::Cgs<real_t>;
1158 .with_generated_preconditioner(
1160 .on(this->executor);
1166 .with_preconditioner(preconditioner.
GetFactory())
1167 .on(this->executor);
1177 using fcg = gko::solver::Fcg<real_t>;
1182#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1186 using fcg = gko::solver::Fcg<real_t>;
1196 using fcg = gko::solver::Fcg<real_t>;
1201 .with_generated_preconditioner(
1203 .on(this->executor);
1205 GetGeneratedPreconditioner().get()))
1215 .with_preconditioner(preconditioner.
GetFactory())
1216 .on(this->executor);
1220#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1225 using fcg = gko::solver::Fcg<real_t>;
1230 .with_generated_preconditioner(
1232 .on(this->executor);
1238 .with_preconditioner(preconditioner.
GetFactory())
1239 .on(this->executor);
1250 using gmres = gko::solver::Gmres<real_t>;
1255 .on(this->executor);
1260 .with_krylov_dim(
static_cast<unsigned long>(
m))
1262 .on(this->executor);
1266#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1271 using gmres = gko::solver::Gmres<real_t>;
1277 .on(this->executor);
1282 .with_krylov_dim(
static_cast<unsigned long>(
m))
1284 .on(this->executor);
1294 using gmres = gko::solver::Gmres<real_t>;
1302 .with_generated_preconditioner(
1304 .on(this->executor);
1306 GetGeneratedPreconditioner().get()))
1316 .with_preconditioner(preconditioner.
GetFactory())
1317 .on(this->executor);
1325 .with_krylov_dim(
static_cast<unsigned long>(
m))
1327 .with_generated_preconditioner(
1329 .on(this->executor);
1331 GetGeneratedPreconditioner().get()))
1340 .with_krylov_dim(
static_cast<unsigned long>(
m))
1342 .with_preconditioner(preconditioner.
GetFactory())
1343 .on(this->executor);
1348#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1354 using gmres = gko::solver::Gmres<real_t>;
1363 .with_generated_preconditioner(
1365 .on(this->executor);
1371 .with_preconditioner(preconditioner.
GetFactory())
1372 .on(this->executor);
1380 .with_krylov_dim(
static_cast<unsigned long>(
m))
1382 .with_generated_preconditioner(
1384 .on(this->executor);
1389 .with_krylov_dim(
static_cast<unsigned long>(
m))
1391 .with_preconditioner(preconditioner.
GetFactory())
1392 .on(this->executor);
1402 using gmres = gko::solver::Gmres<real_t>;
1404 auto current_params = gko::as<gmres::Factory>(
solver_gen)->get_parameters();
1405 this->
solver_gen = current_params.with_krylov_dim(
static_cast<unsigned long>(
m))
1406 .on(this->executor);
1409 gko::as<gmres>(
solver)->set_krylov_dim(
static_cast<unsigned long>(
m));
1415 storage_precision prec)
1419 using gmres = gko::solver::CbGmres<real_t>;
1424 .with_storage_precision(prec)
1425 .on(this->executor);
1430 .with_krylov_dim(
static_cast<unsigned long>(
m))
1432 .with_storage_precision(prec)
1433 .on(this->executor);
1439 int dim, storage_precision prec)
1443 using gmres = gko::solver::CbGmres<real_t>;
1451 .with_storage_precision(prec)
1452 .with_generated_preconditioner(
1454 .on(this->executor);
1456 GetGeneratedPreconditioner().get()))
1466 .with_storage_precision(prec)
1467 .with_preconditioner(preconditioner.
GetFactory())
1468 .on(this->executor);
1476 .with_krylov_dim(
static_cast<unsigned long>(
m))
1478 .with_storage_precision(prec)
1479 .with_generated_preconditioner(
1481 .on(this->executor);
1483 GetGeneratedPreconditioner().get()))
1492 .with_krylov_dim(
static_cast<unsigned long>(
m))
1494 .with_storage_precision(prec)
1495 .with_preconditioner(preconditioner.
GetFactory())
1496 .on(this->executor);
1504 using gmres = gko::solver::CbGmres<real_t>;
1506 auto current_params = gko::as<gmres::Factory>(
solver_gen)->get_parameters();
1507 this->
solver_gen = current_params.with_krylov_dim(
static_cast<unsigned long>(
m))
1508 .on(this->executor);
1511 gko::as<gmres>(
solver)->set_krylov_dim(
static_cast<unsigned long>(
m));
1519 using ir = gko::solver::Ir<real_t>;
1524#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1528 using ir = gko::solver::Ir<real_t>;
1538 using ir = gko::solver::Ir<real_t>;
1542 .on(this->executor);
1550#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1555 using ir = gko::solver::Ir<real_t>;
1559 .on(this->executor);
1568#
if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1571 has_generated_precond(false)
1576#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1581 has_generated_precond(false)
1584 gko_comm = std::shared_ptr<gko::experimental::mpi::communicator>(
1585 new gko::experimental::mpi::communicator(comm));
1594 MFEM_VERIFY(
executor,
"executor is not initialized");
1596 using vec = gko::matrix::Dense<real_t>;
1602 std::unique_ptr<gko::LinOp> gko_x;
1603 std::unique_ptr<gko::LinOp> gko_y;
1605#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1608 using par_vec = gko::experimental::distributed::Vector<real_t>;
1610 const_cast<Vector *
>(&x),
false);
1613 gko_x = std::unique_ptr<ParallelVectorWrapper>(
1617 gko_y = std::unique_ptr<ParallelVectorWrapper>(
1627 bool on_device =
false;
1632 gko_x = vec::create(
executor, gko::dim<2>(x.
Size(), 1),
1635 x.
Read(on_device))), 1);
1636 gko_y = vec::create(
executor, gko::dim<2>(y.
Size(), 1),
1655 "System operator is not square");
1656#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1660 if (par_op_mat != NULL)
1678 MFEM_VERIFY(op_mat != NULL,
1679 "GinkgoPreconditioner::SetOperator : not a SparseMatrix or HypreParMatrix!");
1681 bool on_device =
false;
1687 using mtx = gko::matrix::Csr<real_t, int>;
1689 auto gko_matrix = mtx::create(
1713 const std::string &storage_opt,
1715 const int max_block_size
1720 if (storage_opt ==
"auto")
1722 precond_gen = gko::preconditioner::Jacobi<real_t, int>::build()
1723 .with_storage_optimization(
1724 gko::precision_reduction::autodetect())
1725 .with_accuracy(accuracy)
1726 .with_max_block_size(
static_cast<unsigned int>(max_block_size))
1731 precond_gen = gko::preconditioner::Jacobi<real_t, int>::build()
1732 .with_storage_optimization(
1733 gko::precision_reduction(0, 0))
1734 .with_accuracy(accuracy)
1735 .with_max_block_size(
static_cast<unsigned int>(max_block_size))
1744 const std::string &factorization_type,
1746 const bool skip_sort
1750 if (factorization_type ==
"exact")
1752 using ilu_fact_type = gko::factorization::Ilu<real_t, int>;
1753 std::shared_ptr<ilu_fact_type::Factory> fact_factory =
1754 ilu_fact_type::build()
1755 .with_skip_sorting(skip_sort)
1758 .with_factorization(fact_factory)
1763 using ilu_fact_type = gko::factorization::ParIlu<real_t, int>;
1764 std::shared_ptr<ilu_fact_type::Factory> fact_factory =
1765 ilu_fact_type::build()
1766 .with_iterations(
static_cast<unsigned long>(sweeps))
1767 .with_skip_sorting(skip_sort)
1770 .with_factorization(fact_factory)
1778 const std::string &factorization_type,
1780 const int sparsity_power,
1781 const bool skip_sort
1785 using l_solver_type = gko::preconditioner::LowerIsai<>;
1786 using u_solver_type = gko::preconditioner::UpperIsai<>;
1788 std::shared_ptr<l_solver_type::Factory> l_solver_factory =
1789 l_solver_type::build()
1790 .with_sparsity_power(sparsity_power)
1792 std::shared_ptr<u_solver_type::Factory> u_solver_factory =
1793 u_solver_type::build()
1794 .with_sparsity_power(sparsity_power)
1799 if (factorization_type ==
"exact")
1801 using ilu_fact_type = gko::factorization::Ilu<real_t, int>;
1802 std::shared_ptr<ilu_fact_type::Factory> fact_factory =
1803 ilu_fact_type::build()
1804 .with_skip_sorting(skip_sort)
1806 precond_gen = gko::preconditioner::Ilu<l_solver_type,
1807 u_solver_type>::build()
1808 .with_factorization(fact_factory)
1809 .with_l_solver(l_solver_factory)
1810 .with_u_solver(u_solver_factory)
1816 using ilu_fact_type = gko::factorization::ParIlu<real_t, int>;
1817 std::shared_ptr<ilu_fact_type::Factory> fact_factory =
1818 ilu_fact_type::build()
1819 .with_iterations(
static_cast<unsigned long>(sweeps))
1820 .with_skip_sorting(skip_sort)
1822 precond_gen = gko::preconditioner::Ilu<l_solver_type,
1823 u_solver_type>::build()
1824 .with_factorization(fact_factory)
1825 .with_l_solver(l_solver_factory)
1826 .with_u_solver(u_solver_factory)
1835 const std::string &factorization_type,
1837 const bool skip_sort
1842 if (factorization_type ==
"exact")
1844 using ic_fact_type = gko::factorization::Ic<real_t, int>;
1845 std::shared_ptr<ic_fact_type::Factory> fact_factory =
1846 ic_fact_type::build()
1847 .with_both_factors(
false)
1848 .with_skip_sorting(skip_sort)
1851 .with_factorization(fact_factory)
1856 using ic_fact_type = gko::factorization::ParIc<real_t, int>;
1857 std::shared_ptr<ic_fact_type::Factory> fact_factory =
1858 ic_fact_type::build()
1859 .with_both_factors(
false)
1860 .with_iterations(
static_cast<unsigned long>(sweeps))
1861 .with_skip_sorting(skip_sort)
1864 .with_factorization(fact_factory)
1871 const std::string &factorization_type,
1873 const int sparsity_power,
1874 const bool skip_sort
1879 using l_solver_type = gko::preconditioner::LowerIsai<>;
1880 std::shared_ptr<l_solver_type::Factory> l_solver_factory =
1881 l_solver_type::build()
1882 .with_sparsity_power(sparsity_power)
1884 if (factorization_type ==
"exact")
1886 using ic_fact_type = gko::factorization::Ic<real_t, int>;
1887 std::shared_ptr<ic_fact_type::Factory> fact_factory =
1888 ic_fact_type::build()
1889 .with_both_factors(
false)
1890 .with_skip_sorting(skip_sort)
1892 precond_gen = gko::preconditioner::Ic<l_solver_type>::build()
1893 .with_factorization(fact_factory)
1894 .with_l_solver(l_solver_factory)
1899 using ic_fact_type = gko::factorization::ParIc<real_t, int>;
1900 std::shared_ptr<ic_fact_type::Factory> fact_factory =
1901 ic_fact_type::build()
1902 .with_both_factors(
false)
1903 .with_iterations(
static_cast<unsigned long>(sweeps))
1904 .with_skip_sorting(skip_sort)
1906 precond_gen = gko::preconditioner::Ic<l_solver_type>::build()
1907 .with_factorization(fact_factory)
1908 .with_l_solver(l_solver_factory)
1914#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
1919 const bool l1_smoother
1924 gko::experimental::distributed::preconditioner::Schwarz<real_t, int, gko_hypre_bigint>;
1927 if (local_gko_solver != NULL)
1930 .with_local_solver(local_gko_solver->
GetFactory())
1931 .with_l1_smoother(l1_smoother)
1938 MFEM_VERIFY(local_mfem_precond == NULL,
1939 "Ginkgo::SchwarzPreconditioner cannot use an MFEMPreconditioner "
1940 "for the local solver.");
1944 if (local_gko_precond != NULL)
1948 MFEM_VERIFY(l1_smoother ==
false,
1949 "L1 smoother not available for pre-generated local solvers");
1957 .with_local_solver(local_gko_precond->
GetFactory())
1958 .with_l1_smoother(l1_smoother)
1964 MFEM_ABORT(
"Ginkgo::SchwarzPreconditioner must take a GinkgoIterativeSolver or GinkgoPreconditioner object "
1965 "for the local solver.");
1982 "System operator is not square");
1987 MFEM_VERIFY(par_op_mat != NULL,
1988 "GinkgoPreconditioner::SetOperator : not a HypreParMatrix!");
1991 MFEM_VERIFY(par_op_mat->
Height() == par_op_mat->
Width(),
1992 "System matrix is not square");
1995 gko::experimental::distributed::preconditioner::Schwarz<real_t, int, gko_hypre_bigint>;
1996 auto factory_params = gko::as<typename schwarz::Factory>
1998 bool sort_diag =
false;
1999 if (factory_params.l1_smoother ==
true)
2017 const Solver &mfem_precond
2023 mfem_precond.
Height(), &mfem_precond));
2027#if defined(MFEM_USE_MPI) && GINKGO_BUILD_MPI
2030 const Solver &mfem_precond,
2036 auto mpi_exec =
executor->get_master();
2038 gko_comm->all_reduce(mpi_exec, &global_size, 1, MPI_SUM);
2041 global_size, &mfem_precond));
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
BICGSTABSolver(GinkgoExecutor &exec)
CBGMRESSolver(GinkgoExecutor &exec, int dim=0, storage_precision prec=storage_precision::reduce1)
CGSSolver(GinkgoExecutor &exec)
bool check_needs_sorted_diagonal_mat()
FCGSolver(GinkgoExecutor &exec)
std::shared_ptr< gko::Executor > GetExecutor() const
GinkgoExecutor(ExecType exec_type)
@ REFERENCE
Reference CPU Executor.
@ OMP
OpenMP CPU Executor.
void SetOperator(const Operator &op) override
bool sub_op_needs_wrapped_vecs
bool UsesVectorWrappers() const
void Mult(const Vector &x, Vector &y) const override
void update_stop_factory()
bool use_implicit_res_norm
std::shared_ptr< gko::stop::Combined::Factory > combined_factory
std::shared_ptr< gko::experimental::mpi::communicator > gko_comm
std::shared_ptr< gko::stop::ResidualNorm< real_t >::Factory > abs_criterion
std::shared_ptr< gko::stop::ImplicitResidualNorm< real_t >::Factory > imp_abs_criterion
std::shared_ptr< ConvergenceLogger > convergence_logger
std::shared_ptr< gko::stop::ResidualNorm< real_t >::Factory > rel_criterion
bool needs_sorted_diagonal_mat
const std::shared_ptr< gko::LinOpFactory > GetFactory() const
std::shared_ptr< ResidualLogger > residual_logger
GinkgoIterativeSolver(GinkgoExecutor &exec, bool use_implicit_res_norm)
std::shared_ptr< gko::stop::ImplicitResidualNorm< real_t >::Factory > imp_rel_criterion
std::shared_ptr< gko::LinOpFactory > solver_gen
std::shared_ptr< gko::Executor > executor
std::shared_ptr< gko::LinOp > solver
void SetOperator(const Operator &op) override
std::shared_ptr< gko::Executor > executor
const std::shared_ptr< gko::LinOpFactory > GetFactory() const
void Mult(const Vector &x, Vector &y) const override
std::shared_ptr< gko::LinOp > generated_precond
bool HasGeneratedPreconditioner() const
std::shared_ptr< gko::experimental::mpi::communicator > gko_comm
bool has_generated_precond
GinkgoPreconditioner(GinkgoExecutor &exec)
std::shared_ptr< gko::LinOpFactory > precond_gen
const std::shared_ptr< gko::LinOp > GetGeneratedPreconditioner() const
IRSolver(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)
IcPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const bool skip_sort=false)
IluIsaiPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const int sparsity_power=1, const bool skip_sort=false)
IluPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const bool skip_sort=false)
JacobiPreconditioner(GinkgoExecutor &exec, const std::string &storage_opt="none", const real_t accuracy=1.e-1, const int max_block_size=32)
MFEMPreconditioner(GinkgoExecutor &exec, const Solver &mfem_precond)
void apply_impl(const gko::LinOp *b, gko::LinOp *x) const override
void apply_impl(const gko::LinOp *b, gko::LinOp *x) const override
void SetOperator(const Operator &op) override
SchwarzPreconditioner(GinkgoExecutor &exec, MPI_Comm comm, Solver &local_solver, const bool l1_smoother=false)
Vector & get_mfem_vec_ref()
const Vector & get_mfem_vec_const_ref() const
Wrapper for hypre's ParCSR matrix class.
Memory< HYPRE_Int > & GetOffdMemoryI()
Memory< HYPRE_Int > & GetDiagMemoryI()
int GetNumCols() const
Returns the number of columns in the diagonal block of the ParCSRMatrix.
int GetNumRows() const
Returns the number of rows in the diagonal block of the ParCSRMatrix.
Memory< HYPRE_Int > & GetDiagMemoryJ()
Memory< HYPRE_Int > & GetOffdMemoryJ()
Memory< real_t > & GetOffdMemoryData()
Memory< real_t > & GetDiagMemoryData()
HYPRE_BigInt * GetColStarts() const
Return the parallel column partitioning array.
void GetOffdColMap(HYPRE_BigInt *&cmap, HYPRE_Int &num_cols) const
Get the global column mapping for the local off-diagonal block.
int Capacity() const
Return the size of the allocated memory.
T * ReadWrite(MemoryClass mc, int size)
Get read-write access to the memory with the given MemoryClass.
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...
int width
Dimension of the input / number of columns in the matrix.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int height
Dimension of the output / number of rows in the matrix.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
int * ReadWriteI(bool on_dev=true)
real_t * ReadWriteData(bool on_dev=true)
int * ReadWriteJ(bool on_dev=true)
Memory< real_t > & GetMemoryData()
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Memory< real_t > & GetMemory()
Return a reference to the Memory object used by the Vector.
void Destroy()
Destroy a vector.
int Size() const
Returns the size of the vector.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Vector & Add(const real_t a, const Vector &Va)
(*this) += a * Va
std::conditional_t< sizeof(HYPRE_BigInt)==sizeof(std::int32_t), std::int32_t, std::conditional_t< sizeof(HYPRE_BigInt)==sizeof(std::int64_t), std::int64_t, void > > gko_hypre_bigint
std::conditional_t< sizeof(HYPRE_Int)==sizeof(std::int32_t), std::int32_t, std::conditional_t< sizeof(HYPRE_Int)==sizeof(std::int64_t), std::int64_t, void > > gko_hypre_int
gko::array< T > gko_array
std::unique_ptr< gko::experimental::distributed::Matrix< real_t, gko_hypre_int, gko_hypre_bigint > > GinkgoWrapHypreParMatrix(HypreParMatrix *par_mat, std::shared_ptr< gko::Executor > executor, std::shared_ptr< gko::experimental::mpi::communicator > gko_comm, bool sort_diag)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
MemoryClass
Memory classes identify sets of memory types.
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
struct schwarz_common schwarz
@ HIP_MASK
Biwise-OR of all HIP backends.
@ CUDA_MASK
Biwise-OR of all CUDA backends.
@ OMP_MASK
Biwise-OR of all OpenMP backends.