72 typedef double NumberAMG;
74 typedef typename Operator::value_type MultigridNumber;
76 typedef dealii::LinearAlgebra::distributed::Vector<MultigridNumber> VectorType;
78 typedef dealii::LinearAlgebra::distributed::Vector<NumberAMG> VectorTypeAMG;
86 : solver_type(KrylovSolverType::CG),
87 solver_data(
SolverData(1e4, 1.e-12, 1.e-3, 100)),
88 operator_is_singular(false),
89 preconditioner(MultigridCoarseGridPreconditioner::None),
95 KrylovSolverType solver_type;
103 bool operator_is_singular;
106 MultigridCoarseGridPreconditioner preconditioner;
113 bool const initialize,
114 AdditionalData
const & additional_data,
115 MPI_Comm
const & comm)
116 : pde_operator(pde_operator_in), additional_data(additional_data), mpi_comm(comm)
118 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi)
120 preconditioner = std::make_shared<JacobiPreconditioner<Operator>>(pde_operator, initialize);
122 std::shared_ptr<JacobiPreconditioner<Operator>> jacobi =
123 std::dynamic_pointer_cast<JacobiPreconditioner<Operator>>(preconditioner);
124 AssertDimension(jacobi->get_size_of_diagonal(), pde_operator.m());
126 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
129 std::make_shared<BlockJacobiPreconditioner<Operator>>(pde_operator, initialize);
131 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG)
133 if(additional_data.amg_data.amg_type == AMGType::ML)
135#ifdef DEAL_II_WITH_TRILINOS
137 std::make_shared<PreconditionerML<Operator, NumberAMG>>(pde_operator,
139 additional_data.amg_data.ml_data);
141 AssertThrow(
false, dealii::ExcMessage(
"deal.II is not compiled with Trilinos!"));
144 else if(additional_data.amg_data.amg_type == AMGType::BoomerAMG)
146#ifdef DEAL_II_WITH_PETSC
147 preconditioner_amg = std::make_shared<PreconditionerBoomerAMG<Operator, NumberAMG>>(
148 pde_operator, initialize, additional_data.amg_data.boomer_data);
150 AssertThrow(
false, dealii::ExcMessage(
"deal.II is not compiled with PETSc!"));
155 AssertThrow(
false, dealii::ExcNotImplemented());
161 additional_data.preconditioner == MultigridCoarseGridPreconditioner::None or
162 additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
163 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi or
164 additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG,
165 dealii::ExcMessage(
"Specified preconditioner for PCG coarse grid solver not implemented."));
172 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::None)
176 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
177 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
179 preconditioner->update();
181 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG)
183 preconditioner_amg->update();
187 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
192 operator()(
unsigned int const, VectorType & dst, VectorType
const & src)
const final
195 if(additional_data.operator_is_singular)
196 dealii::VectorTools::subtract_mean_value(r);
198 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG)
200 if(additional_data.amg_data.amg_type == AMGType::ML)
202#ifdef DEAL_II_WITH_TRILINOS
204 VectorTypeAMG dst_tri;
205 dst_tri.reinit(dst,
false);
206 VectorTypeAMG src_tri;
207 src_tri.reinit(r,
true);
208 src_tri.copy_locally_owned_data_from(r);
210 std::shared_ptr<PreconditionerML<Operator, NumberAMG>> coarse_operator =
211 std::dynamic_pointer_cast<PreconditionerML<Operator, NumberAMG>>(preconditioner_amg);
213 dealii::ReductionControl solver_control(additional_data.solver_data.max_iter,
214 additional_data.solver_data.abs_tol,
215 additional_data.solver_data.rel_tol);
217 if(additional_data.solver_type == KrylovSolverType::CG)
219 dealii::SolverCG<VectorTypeAMG> solver(solver_control);
220 solver.solve(coarse_operator->system_matrix, dst_tri, src_tri, *preconditioner_amg);
222 else if(additional_data.solver_type == KrylovSolverType::GMRES)
224 typename dealii::SolverGMRES<VectorTypeAMG>::AdditionalData gmres_data;
225 gmres_data.max_n_tmp_vectors = additional_data.solver_data.max_krylov_size;
226 gmres_data.right_preconditioning =
true;
228 dealii::SolverGMRES<VectorTypeAMG> solver(solver_control, gmres_data);
229 solver.solve(coarse_operator->system_matrix, dst_tri, src_tri, *preconditioner_amg);
233 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
237 dst.copy_locally_owned_data_from(dst_tri);
240 else if(additional_data.amg_data.amg_type == AMGType::BoomerAMG)
242#ifdef DEAL_II_WITH_PETSC
243 apply_petsc_operation(
246 std::dynamic_pointer_cast<PreconditionerBoomerAMG<Operator, NumberAMG>>(
248 ->system_matrix.get_mpi_communicator(),
249 [&](dealii::PETScWrappers::VectorBase & petsc_dst,
250 dealii::PETScWrappers::VectorBase
const & petsc_src) {
251 std::shared_ptr<PreconditionerBoomerAMG<Operator, NumberAMG>> coarse_operator =
252 std::dynamic_pointer_cast<PreconditionerBoomerAMG<Operator, NumberAMG>>(
255 dealii::ReductionControl solver_control(additional_data.solver_data.max_iter,
256 additional_data.solver_data.abs_tol,
257 additional_data.solver_data.rel_tol);
259 if(additional_data.solver_type == KrylovSolverType::CG)
261 dealii::PETScWrappers::SolverCG solver(solver_control);
262 solver.solve(coarse_operator->system_matrix,
265 coarse_operator->amg);
267 else if(additional_data.solver_type == KrylovSolverType::GMRES)
269 dealii::PETScWrappers::SolverGMRES solver(solver_control);
270 solver.solve(coarse_operator->system_matrix,
273 coarse_operator->amg);
277 AssertThrow(false, dealii::ExcMessage(
"Not implemented."));
284 AssertThrow(
false, dealii::ExcNotImplemented());
289 std::shared_ptr<Krylov::SolverBase<VectorType>> solver;
291 if(additional_data.solver_type == KrylovSolverType::CG)
293 Krylov::SolverDataCG solver_data;
294 solver_data.max_iter = additional_data.solver_data.max_iter;
295 solver_data.solver_tolerance_abs = additional_data.solver_data.abs_tol;
296 solver_data.solver_tolerance_rel = additional_data.solver_data.rel_tol;
298 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::None)
300 solver_data.use_preconditioner =
false;
302 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
303 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
305 solver_data.use_preconditioner =
true;
309 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
313 new Krylov::SolverCG<Operator, PreconditionerBase<MultigridNumber>, VectorType>(
314 pde_operator, *preconditioner, solver_data));
316 else if(additional_data.solver_type == KrylovSolverType::GMRES)
318 Krylov::SolverDataGMRES solver_data;
320 solver_data.max_iter = additional_data.solver_data.max_iter;
321 solver_data.solver_tolerance_abs = additional_data.solver_data.abs_tol;
322 solver_data.solver_tolerance_rel = additional_data.solver_data.rel_tol;
323 solver_data.max_n_tmp_vectors = additional_data.solver_data.max_krylov_size;
325 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::None)
327 solver_data.use_preconditioner =
false;
329 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
330 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
332 solver_data.use_preconditioner =
true;
336 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
340 new Krylov::SolverGMRES<Operator, PreconditionerBase<MultigridNumber>, VectorType>(
341 pde_operator, *preconditioner, solver_data, mpi_comm));
345 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
349 solver->solve(dst, src);
354 const Operator & pde_operator;
356 std::shared_ptr<PreconditionerBase<MultigridNumber>> preconditioner;
359 std::shared_ptr<PreconditionerBase<NumberAMG>> preconditioner_amg;
361 AdditionalData additional_data;
363 MPI_Comm
const mpi_comm;
371 typedef typename Operator::value_type MultigridNumber;
373 typedef dealii::LinearAlgebra::distributed::Vector<MultigridNumber> VectorType;
375 typedef dealii::PreconditionChebyshev<Operator, VectorType, dealii::DiagonalMatrix<VectorType>>
379 bool const initialize_preconditioner_in,
380 double const relative_tolerance_in,
381 MultigridCoarseGridPreconditioner
const & preconditioner,
382 bool const operator_is_singular_in)
383 : coarse_operator(coarse_operator_in),
384 relative_tolerance(relative_tolerance_in),
385 operator_is_singular(operator_is_singular_in)
387 AssertThrow(preconditioner == MultigridCoarseGridPreconditioner::PointJacobi,
389 "Only PointJacobi preconditioner implemented for Chebyshev coarse-grid solver."));
391 if(initialize_preconditioner_in)
401 typename DealiiChebyshev::AdditionalData dealii_additional_data;
403 std::shared_ptr<dealii::DiagonalMatrix<VectorType>> diagonal_matrix =
404 std::make_shared<dealii::DiagonalMatrix<VectorType>>();
405 VectorType & diagonal_vector = diagonal_matrix->get_vector();
407 coarse_operator.initialize_dof_vector(diagonal_vector);
408 coarse_operator.calculate_inverse_diagonal(diagonal_vector);
410 std::pair<double, double> eigenvalues =
411 compute_eigenvalues(coarse_operator, diagonal_vector, operator_is_singular);
413 double const factor = 1.1;
415 dealii_additional_data.preconditioner = diagonal_matrix;
416 dealii_additional_data.max_eigenvalue = factor * eigenvalues.second;
417 dealii_additional_data.smoothing_range = eigenvalues.second / eigenvalues.first * factor;
419 double sigma = (1. - std::sqrt(1. / dealii_additional_data.smoothing_range)) /
420 (1. + std::sqrt(1. / dealii_additional_data.smoothing_range));
424 double const eps = relative_tolerance;
426 dealii_additional_data.degree =
static_cast<unsigned int>(
427 std::log(1. / eps + std::sqrt(1. / eps / eps - 1.)) / std::log(1. / sigma));
428 dealii_additional_data.eig_cg_n_iterations = 0;
430 chebyshev_smoother = std::make_shared<DealiiChebyshev>();
431 chebyshev_smoother->initialize(coarse_operator, dealii_additional_data);
435 operator()(
unsigned int const level, VectorType & dst,
const VectorType & src)
const final
437 AssertThrow(chebyshev_smoother.get() != 0,
438 dealii::ExcMessage(
"MGCoarseChebyshev: chebyshev_smoother is not initialized."));
440 AssertThrow(level == 0, dealii::ExcNotImplemented());
442 chebyshev_smoother->vmult(dst, src);
446 Operator
const & coarse_operator;
447 double const relative_tolerance;
448 bool const operator_is_singular;
450 std::shared_ptr<DealiiChebyshev> chebyshev_smoother;