65 typedef typename Operator::value_type Number;
67 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
75 : solver_type(MultigridCoarseGridSolver::CG),
76 solver_data(
SolverData(1e4, 1.e-12, 1.e-3, LinearSolver::Undefined, 100)),
77 operator_is_singular(false),
78 preconditioner(MultigridCoarseGridPreconditioner::None),
84 MultigridCoarseGridSolver solver_type;
92 bool operator_is_singular;
95 MultigridCoarseGridPreconditioner preconditioner;
102 bool const initialize,
103 AdditionalData
const & additional_data,
104 MPI_Comm
const & comm)
105 : pde_operator(pde_operator_in), additional_data(additional_data), mpi_comm(comm)
107 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi)
109 preconditioner = std::make_shared<JacobiPreconditioner<Operator>>(pde_operator, initialize);
111 std::shared_ptr<JacobiPreconditioner<Operator>> jacobi =
112 std::dynamic_pointer_cast<JacobiPreconditioner<Operator>>(preconditioner);
113 AssertDimension(jacobi->get_size_of_diagonal(), pde_operator.m());
115 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
118 std::make_shared<BlockJacobiPreconditioner<Operator>>(pde_operator, initialize);
120 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG)
123 std::make_shared<PreconditionerAMG<Operator, Number>>(pde_operator,
125 additional_data.amg_data);
130 additional_data.preconditioner == MultigridCoarseGridPreconditioner::None or
131 additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
132 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi or
133 additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG,
134 dealii::ExcMessage(
"Specified preconditioner for PCG coarse grid solver not implemented."));
141 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::None)
145 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
146 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi or
147 additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG)
149 preconditioner->update();
153 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
158 operator()(
unsigned int const, VectorType & dst, VectorType
const & src)
const final
161 if(additional_data.operator_is_singular)
162 dealii::VectorTools::subtract_mean_value(r);
164 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::AMG)
166 std::shared_ptr<PreconditionerAMG<Operator, Number>> preconditioner_amg =
167 std::dynamic_pointer_cast<PreconditionerAMG<Operator, Number>>(preconditioner);
169 AssertThrow(preconditioner_amg !=
nullptr,
170 dealii::ExcMessage(
"Constructed preconditioner is not of type "
171 "PreconditionerAMG<Operator, Number>."));
173 preconditioner_amg->apply_krylov_solver_with_amg_preconditioner(dst,
175 additional_data.solver_type,
176 additional_data.solver_data);
181 SolverData solver_data = additional_data.solver_data;
182 if(additional_data.solver_type == MultigridCoarseGridSolver::CG)
184 solver_data.linear_solver = LinearSolver::CG;
186 else if(additional_data.solver_type == MultigridCoarseGridSolver::GMRES)
188 solver_data.linear_solver = LinearSolver::GMRES;
192 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
195 bool constexpr compute_performance_metrics =
false;
196 bool constexpr compute_eigenvalues =
false;
197 bool use_preconditioner;
198 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::None)
200 use_preconditioner =
false;
202 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
203 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
205 use_preconditioner =
true;
209 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
212 typedef Krylov::KrylovSolver<Operator, PreconditionerBase<Number>, VectorType> SolverType;
214 SolverType solver(pde_operator,
218 compute_performance_metrics,
219 compute_eigenvalues);
222 solver.solve(dst, r);
227 Operator
const & pde_operator;
229 std::shared_ptr<PreconditionerBase<Number>> preconditioner;
233 MPI_Comm
const mpi_comm;
241 typedef typename Operator::value_type MultigridNumber;
243 typedef dealii::LinearAlgebra::distributed::Vector<MultigridNumber> VectorType;
245 typedef dealii::PreconditionChebyshev<Operator, VectorType, dealii::DiagonalMatrix<VectorType>>
248 MGCoarseChebyshev(Operator
const & coarse_operator_in,
249 bool const initialize_preconditioner_in,
250 double const relative_tolerance_in,
251 MultigridCoarseGridPreconditioner
const & preconditioner,
252 bool const operator_is_singular_in)
253 : coarse_operator(coarse_operator_in),
254 relative_tolerance(relative_tolerance_in),
255 operator_is_singular(operator_is_singular_in)
257 AssertThrow(preconditioner == MultigridCoarseGridPreconditioner::PointJacobi,
259 "Only PointJacobi preconditioner implemented for Chebyshev coarse-grid solver."));
261 if(initialize_preconditioner_in)
271 typename DealiiChebyshev::AdditionalData dealii_additional_data;
273 std::shared_ptr<dealii::DiagonalMatrix<VectorType>> diagonal_matrix =
274 std::make_shared<dealii::DiagonalMatrix<VectorType>>();
275 VectorType & diagonal_vector = diagonal_matrix->get_vector();
277 coarse_operator.initialize_dof_vector(diagonal_vector);
278 coarse_operator.calculate_inverse_diagonal(diagonal_vector);
280 std::pair<double, double> eigenvalues =
281 estimate_eigenvalues_cg(coarse_operator, diagonal_vector, operator_is_singular);
283 double const factor = 1.1;
285 dealii_additional_data.preconditioner = diagonal_matrix;
286 dealii_additional_data.max_eigenvalue = factor * eigenvalues.second;
287 dealii_additional_data.smoothing_range = eigenvalues.second / eigenvalues.first * factor;
289 double sigma = (1. - std::sqrt(1. / dealii_additional_data.smoothing_range)) /
290 (1. + std::sqrt(1. / dealii_additional_data.smoothing_range));
294 double const eps = relative_tolerance;
296 dealii_additional_data.degree =
static_cast<unsigned int>(
297 std::log(1. / eps + std::sqrt(1. / eps / eps - 1.)) / std::log(1. / sigma));
298 dealii_additional_data.eig_cg_n_iterations = 0;
300 chebyshev_smoother = std::make_shared<DealiiChebyshev>();
301 chebyshev_smoother->initialize(coarse_operator, dealii_additional_data);
305 operator()(
unsigned int const level, VectorType & dst,
const VectorType & src)
const final
307 AssertThrow(chebyshev_smoother.get() != 0,
308 dealii::ExcMessage(
"MGCoarseChebyshev: chebyshev_smoother is not initialized."));
310 AssertThrow(level == 0, dealii::ExcNotImplemented());
312 chebyshev_smoother->vmult(dst, src);
316 Operator
const & coarse_operator;
317 double const relative_tolerance;
318 bool const operator_is_singular;
320 std::shared_ptr<DealiiChebyshev> chebyshev_smoother;
331 typedef typename Operator::value_type Number;
333 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
336 MGCoarseAMG(Operator
const & op,
bool const initialize,
AMGData data =
AMGData())
339 std::make_shared<PreconditionerAMG<Operator, Number>>(op, initialize, data);
345 amg_preconditioner->update();
349 operator()(
unsigned int const , VectorType & dst, VectorType
const & src)
const final
351 amg_preconditioner->vmult(dst, src);
355 std::shared_ptr<PreconditionerAMG<Operator, Number>> amg_preconditioner;