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, 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);
180 std::shared_ptr<Krylov::SolverBase<VectorType>> solver;
182 if(additional_data.solver_type == MultigridCoarseGridSolver::CG)
184 Krylov::SolverDataCG solver_data;
185 solver_data.max_iter = additional_data.solver_data.max_iter;
186 solver_data.solver_tolerance_abs = additional_data.solver_data.abs_tol;
187 solver_data.solver_tolerance_rel = additional_data.solver_data.rel_tol;
189 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::None)
191 solver_data.use_preconditioner =
false;
193 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
194 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
196 solver_data.use_preconditioner =
true;
200 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
203 solver.reset(
new Krylov::SolverCG<Operator, PreconditionerBase<Number>, VectorType>(
204 pde_operator, *preconditioner, solver_data));
206 else if(additional_data.solver_type == MultigridCoarseGridSolver::GMRES)
208 Krylov::SolverDataGMRES solver_data;
210 solver_data.max_iter = additional_data.solver_data.max_iter;
211 solver_data.solver_tolerance_abs = additional_data.solver_data.abs_tol;
212 solver_data.solver_tolerance_rel = additional_data.solver_data.rel_tol;
213 solver_data.max_n_tmp_vectors = additional_data.solver_data.max_krylov_size;
215 if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::None)
217 solver_data.use_preconditioner =
false;
219 else if(additional_data.preconditioner == MultigridCoarseGridPreconditioner::PointJacobi or
220 additional_data.preconditioner == MultigridCoarseGridPreconditioner::BlockJacobi)
222 solver_data.use_preconditioner =
true;
226 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
229 solver.reset(
new Krylov::SolverGMRES<Operator, PreconditionerBase<Number>, VectorType>(
230 pde_operator, *preconditioner, solver_data, mpi_comm));
234 AssertThrow(
false, dealii::ExcMessage(
"Not implemented."));
238 solver->solve(dst, r);
243 Operator
const & pde_operator;
245 std::shared_ptr<PreconditionerBase<Number>> preconditioner;
249 MPI_Comm
const mpi_comm;
257 typedef typename Operator::value_type MultigridNumber;
259 typedef dealii::LinearAlgebra::distributed::Vector<MultigridNumber> VectorType;
261 typedef dealii::PreconditionChebyshev<Operator, VectorType, dealii::DiagonalMatrix<VectorType>>
264 MGCoarseChebyshev(Operator
const & coarse_operator_in,
265 bool const initialize_preconditioner_in,
266 double const relative_tolerance_in,
267 MultigridCoarseGridPreconditioner
const & preconditioner,
268 bool const operator_is_singular_in)
269 : coarse_operator(coarse_operator_in),
270 relative_tolerance(relative_tolerance_in),
271 operator_is_singular(operator_is_singular_in)
273 AssertThrow(preconditioner == MultigridCoarseGridPreconditioner::PointJacobi,
275 "Only PointJacobi preconditioner implemented for Chebyshev coarse-grid solver."));
277 if(initialize_preconditioner_in)
287 typename DealiiChebyshev::AdditionalData dealii_additional_data;
289 std::shared_ptr<dealii::DiagonalMatrix<VectorType>> diagonal_matrix =
290 std::make_shared<dealii::DiagonalMatrix<VectorType>>();
291 VectorType & diagonal_vector = diagonal_matrix->get_vector();
293 coarse_operator.initialize_dof_vector(diagonal_vector);
294 coarse_operator.calculate_inverse_diagonal(diagonal_vector);
296 std::pair<double, double> eigenvalues =
297 compute_eigenvalues(coarse_operator, diagonal_vector, operator_is_singular);
299 double const factor = 1.1;
301 dealii_additional_data.preconditioner = diagonal_matrix;
302 dealii_additional_data.max_eigenvalue = factor * eigenvalues.second;
303 dealii_additional_data.smoothing_range = eigenvalues.second / eigenvalues.first * factor;
305 double sigma = (1. - std::sqrt(1. / dealii_additional_data.smoothing_range)) /
306 (1. + std::sqrt(1. / dealii_additional_data.smoothing_range));
310 double const eps = relative_tolerance;
312 dealii_additional_data.degree =
static_cast<unsigned int>(
313 std::log(1. / eps + std::sqrt(1. / eps / eps - 1.)) / std::log(1. / sigma));
314 dealii_additional_data.eig_cg_n_iterations = 0;
316 chebyshev_smoother = std::make_shared<DealiiChebyshev>();
317 chebyshev_smoother->initialize(coarse_operator, dealii_additional_data);
321 operator()(
unsigned int const level, VectorType & dst,
const VectorType & src)
const final
323 AssertThrow(chebyshev_smoother.get() != 0,
324 dealii::ExcMessage(
"MGCoarseChebyshev: chebyshev_smoother is not initialized."));
326 AssertThrow(level == 0, dealii::ExcNotImplemented());
328 chebyshev_smoother->vmult(dst, src);
332 Operator
const & coarse_operator;
333 double const relative_tolerance;
334 bool const operator_is_singular;
336 std::shared_ptr<DealiiChebyshev> chebyshev_smoother;