22#ifndef PRECONDITIONER_AMG
23#define PRECONDITIONER_AMG
25#include <deal.II/lac/la_parallel_vector.h>
26#include <deal.II/lac/petsc_precondition.h>
27#include <deal.II/lac/petsc_sparse_matrix.h>
28#include <deal.II/lac/trilinos_precondition.h>
29#include <deal.II/lac/trilinos_sparse_matrix.h>
31#include <exadg/solvers_and_preconditioners/multigrid/multigrid_parameters.h>
32#include <exadg/solvers_and_preconditioners/preconditioners/preconditioner_base.h>
33#include <exadg/solvers_and_preconditioners/utilities/petsc_operation.h>
34#include <exadg/utilities/print_functions.h>
38template<
int dim,
int spacedim>
39std::unique_ptr<MPI_Comm, void (*)(MPI_Comm *)>
40create_subcommunicator(dealii::DoFHandler<dim, spacedim>
const & dof_handler)
42 unsigned int n_locally_owned_cells = 0;
43 for(
auto const & cell : dof_handler.active_cell_iterators())
44 if(cell->is_locally_owned())
45 ++n_locally_owned_cells;
47 MPI_Comm
const mpi_comm = dof_handler.get_communicator();
55 if(dealii::Utilities::MPI::min(n_locally_owned_cells, mpi_comm) == 0)
57 std::unique_ptr<MPI_Comm, void (*)(MPI_Comm *)> subcommunicator(
new MPI_Comm,
62 MPI_Comm_split(mpi_comm,
63 n_locally_owned_cells > 0,
64 dealii::Utilities::MPI::this_mpi_process(mpi_comm),
65 subcommunicator.get());
67 return subcommunicator;
71 std::unique_ptr<MPI_Comm, void (*)(MPI_Comm *)> communicator(
new MPI_Comm, [](MPI_Comm * comm) {
74 *communicator = mpi_comm;
80#ifdef DEAL_II_WITH_TRILINOS
81template<
typename Operator,
typename Number>
82class PreconditionerML :
public PreconditionerBase<Number>
85 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
87 typedef dealii::TrilinosWrappers::PreconditionAMG::AdditionalData MLData;
91 dealii::TrilinosWrappers::SparseMatrix system_matrix;
94 dealii::TrilinosWrappers::PreconditionAMG amg;
97 PreconditionerML(Operator
const & op,
bool const initialize, MLData ml_data = MLData())
98 : pde_operator(op), ml_data(ml_data)
101 pde_operator.init_system_matrix(system_matrix,
102 op.get_matrix_free().get_dof_handler().get_communicator());
110 dealii::TrilinosWrappers::SparseMatrix
const &
113 return system_matrix;
117 vmult(VectorType & dst, VectorType
const & src)
const override
126 system_matrix *= 0.0;
129 pde_operator.calculate_system_matrix(system_matrix);
132 amg.initialize(system_matrix, ml_data);
134 this->update_needed =
false;
139 Operator
const & pde_operator;
145#ifdef DEAL_II_WITH_PETSC
149template<
typename Operator,
typename Number>
150class PreconditionerBoomerAMG :
public PreconditionerBase<Number>
153 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
155 typedef dealii::PETScWrappers::PreconditionBoomerAMG::AdditionalData BoomerData;
159 std::unique_ptr<MPI_Comm, void (*)(MPI_Comm *)> subcommunicator;
163 dealii::PETScWrappers::MPI::SparseMatrix system_matrix;
166 dealii::PETScWrappers::PreconditionBoomerAMG amg;
168 PreconditionerBoomerAMG(Operator
const & op,
169 bool const initialize,
170 BoomerData boomer_data = BoomerData())
172 create_subcommunicator(op.get_matrix_free().get_dof_handler(op.get_dof_index()))),
174 boomer_data(boomer_data)
177 pde_operator.init_system_matrix(system_matrix, *subcommunicator);
185 ~PreconditionerBoomerAMG()
187 if(system_matrix.m() > 0)
189 PetscErrorCode ierr = VecDestroy(&petsc_vector_dst);
190 AssertThrow(ierr == 0, dealii::ExcPETScError(ierr));
191 ierr = VecDestroy(&petsc_vector_src);
192 AssertThrow(ierr == 0, dealii::ExcPETScError(ierr));
196 dealii::PETScWrappers::MPI::SparseMatrix
const &
199 return system_matrix;
203 vmult(VectorType & dst, VectorType
const & src)
const override
205 if(system_matrix.m() > 0)
206 apply_petsc_operation(dst,
210 [&](dealii::PETScWrappers::VectorBase & petsc_dst,
211 dealii::PETScWrappers::VectorBase
const & petsc_src) {
212 amg.vmult(petsc_dst, petsc_src);
223 if(system_matrix.m() > 0)
226 calculate_preconditioner();
228 this->update_needed =
false;
233 calculate_preconditioner()
236 if(system_matrix.m() > 0)
238 pde_operator.calculate_system_matrix(system_matrix);
240 amg.initialize(system_matrix, boomer_data);
243 dealii::LinearAlgebra::distributed::Vector<typename Operator::value_type> vector;
244 pde_operator.initialize_dof_vector(vector);
245 VecCreateMPI(system_matrix.get_mpi_communicator(),
246 vector.get_partitioner()->locally_owned_size(),
249 VecCreateMPI(system_matrix.get_mpi_communicator(),
250 vector.get_partitioner()->locally_owned_size(),
257 Operator
const & pde_operator;
259 BoomerData boomer_data;
262 mutable VectorTypePETSc petsc_vector_src;
263 mutable VectorTypePETSc petsc_vector_dst;
270template<
typename Operator,
typename Number>
274 typedef double NumberAMG;
275 typedef typename PreconditionerBase<Number>::VectorType VectorType;
276 typedef dealii::LinearAlgebra::distributed::Vector<NumberAMG> VectorTypeAMG;
285 if(data.amg_type == AMGType::BoomerAMG)
287#ifdef DEAL_II_WITH_PETSC
289 std::make_shared<PreconditionerBoomerAMG<Operator, double>>(pde_operator,
293 AssertThrow(
false, dealii::ExcMessage(
"deal.II is not compiled with PETSc!"));
296 else if(data.amg_type == AMGType::ML)
298#ifdef DEAL_II_WITH_TRILINOS
299 preconditioner_amg = std::make_shared<PreconditionerML<Operator, double>>(pde_operator,
303 AssertThrow(
false, dealii::ExcMessage(
"deal.II is not compiled with Trilinos!"));
308 AssertThrow(
false, dealii::ExcNotImplemented());
313 vmult(VectorType & dst, VectorType
const & src)
const final
315 if constexpr(std::is_same_v<Number, NumberAMG>)
317 preconditioner_amg->vmult(dst, src);
322 VectorTypeAMG dst_amg;
323 dst_amg.reinit(dst,
false);
324 VectorTypeAMG src_amg;
325 src_amg.reinit(src,
true);
328 preconditioner_amg->vmult(dst_amg, src_amg);
331 dst.copy_locally_owned_data_from(dst_amg);
339 preconditioner_amg->update();
341 this->update_needed =
false;
344 std::shared_ptr<PreconditionerBase<NumberAMG>> preconditioner_amg;
Definition preconditioner_amg.h:272
Definition preconditioner_base.h:35
Definition multigrid_parameters.h:98