186 min_level = triangulation_handler.get_mg_min_level();
187 max_level = triangulation_handler.get_mg_max_level();
191 std::make_unique<dealii::MGLevelObject<LevelMatrixType>>(min_level,
195 this->subset_attributes);
196 mg_transfer_operators.resize(min_level, max_level);
199 mg_matrix_free_handler.resize(min_level, max_level, this->user_inputs);
202 mg_newton_update_src.resize(min_level, max_level);
203 for (
unsigned int level = min_level; level <= max_level; ++level)
207 mg_matrix_free_handler[level].
reinit(
209 dof_handler.get_mg_dof_handler(this->field_index, level),
210 this->constraint_handler.get_mg_constraint(this->field_index, level),
211 dealii::QGaussLobatto<1>(degree + 1));
213 (*mg_operators)[level].initialize(mg_matrix_free_handler[level].get_matrix_free());
215 (*mg_operators)[level].add_global_to_local_mapping(
216 this->newton_update_global_to_local_solution);
219 mg_newton_update_src[level].resize(this->newton_update_src.size());
220 for (
const auto &[pair, local_index] : this->newton_update_global_to_local_solution)
222 mg_newton_update_src[level][local_index] =
new MGVectorType();
223 (*mg_operators)[level]
224 .initialize_dof_vector(*mg_newton_update_src[level][local_index], pair.first);
230 Assert((*mg_operators)[level]
232 ->get_vector_partitioner(this->field_index)
233 ->is_compatible(*(mg_newton_update_src[level][0]->get_partitioner())),
234 dealii::ExcMessage(
"Incompatabile vector partitioners"));
236 (*mg_operators)[level].add_src_solution_subset(mg_newton_update_src[level]);
238 mg_matrix = std::make_shared<dealii::mg::Matrix<MGVectorType>>(*mg_operators);
241 for (
unsigned int level = min_level; level < max_level; ++level)
243 mg_transfer_operators[level + 1].reinit(
244 dof_handler.get_mg_dof_handler(this->field_index, level + 1),
245 dof_handler.get_mg_dof_handler(this->field_index, level),
246 this->constraint_handler.get_mg_constraint(this->field_index, level + 1),
247 this->constraint_handler.get_mg_constraint(this->field_index, level));
249 mg_transfer = std::make_shared<dealii::MGTransferGlobalCoarsening<dim, MGVectorType>>(
250 mg_transfer_operators);
252 this->system_matrix->clear();
253 this->system_matrix->initialize(this->matrix_free_handler.get_matrix_free());
254 this->update_system_matrix->clear();
255 this->update_system_matrix->initialize(this->matrix_free_handler.get_matrix_free());
257 this->system_matrix->add_global_to_local_mapping(
258 this->residual_global_to_local_solution);
259 this->system_matrix->add_src_solution_subset(this->residual_src);
261 this->update_system_matrix->add_global_to_local_mapping(
262 this->newton_update_global_to_local_solution);
263 this->update_system_matrix->add_src_solution_subset(this->newton_update_src);
266 this->constraint_handler.get_constraint(this->field_index)
267 .distribute(*(this->solution_handler.solution_set.at(
268 std::make_pair(this->field_index, dependencyType::NORMAL))));
273 <<
"\nMultigrid Setup Information for index " << this->field_index <<
":\n"
274 <<
" Min level: " << min_level <<
"\n"
275 <<
" Max level: " << max_level <<
"\n";
276 for (
unsigned int level = min_level; level <= max_level; ++level)
279 <<
" Level: " << level <<
"\n"
281 << triangulation_handler.get_mg_triangulation(level).n_global_active_cells()
284 << dof_handler.get_mg_dof_handler(this->field_index, level).n_dofs() <<
"\n"
285 <<
" Constrained DoFs: "
286 << this->constraint_handler.get_mg_constraint(this->field_index, level)
291 <<
" MG vertical communication efficiency: "
292 << dealii::MGTools::vertical_communication_efficiency(
293 triangulation_handler.get_mg_triangulation())
295 <<
" MG workload imbalance: "
296 << dealii::MGTools::workload_imbalance(triangulation_handler.get_mg_triangulation())
311 const auto *current_dof_handler = dof_handler.get_dof_handlers().at(this->field_index);
312 auto *solution = this->solution_handler.solution_set.at(
313 std::make_pair(this->field_index, dependencyType::NORMAL));
316 this->system_matrix->compute_residual(*this->residual, *solution);
318 <<
" field: " << this->field_index
319 <<
" Initial residual: " << this->residual->l2_norm() << std::flush;
322 this->compute_solver_tolerance();
325 this->solver_control.set_tolerance(this->tolerance);
326 dealii::SolverCG<VectorType> cg(this->solver_control);
329 for (
unsigned int local_index = 0; local_index < this->newton_update_src.size();
333 dealii::MGLevelObject<MGVectorType> mg_src_subset(min_level, max_level);
334 for (
unsigned int level = min_level; level < max_level; ++level)
336 mg_src_subset[level] = *mg_newton_update_src[level][local_index];
340 mg_transfer->interpolate_to_mg(*current_dof_handler,
342 *this->newton_update_src[local_index]);
346 using SmootherType = dealii::PreconditionChebyshev<LevelMatrixType, MGVectorType>;
347 dealii::MGSmootherPrecondition<LevelMatrixType, SmootherType, MGVectorType> mg_smoother;
348 dealii::MGLevelObject<typename SmootherType::AdditionalData> smoother_data(min_level,
350 for (
unsigned int level = min_level; level <= max_level; ++level)
352 smoother_data[level].smoothing_range =
353 this->user_inputs.linear_solve_parameters.linear_solve.at(this->field_index)
355 smoother_data[level].degree =
356 this->user_inputs.linear_solve_parameters.linear_solve.at(this->field_index)
358 smoother_data[level].eig_cg_n_iterations =
359 this->user_inputs.linear_solve_parameters.linear_solve.at(this->field_index)
360 .eig_cg_n_iterations;
361 (*mg_operators)[level].compute_diagonal(this->field_index);
362 smoother_data[level].preconditioner =
363 (*mg_operators)[level].get_matrix_diagonal_inverse();
364 smoother_data[level].constraints.copy_from(
365 this->constraint_handler.get_mg_constraint(this->field_index, level));
367 mg_smoother.initialize(*mg_operators, smoother_data);
369 dealii::MGCoarseGridApplySmoother<MGVectorType> mg_coarse;
370 mg_coarse.initialize(mg_smoother);
373 dealii::Multigrid<MGVectorType> mg(*mg_matrix,
380 dealii::Multigrid<MGVectorType>::Cycle::v_cycle);
383 dealii::PreconditionMG<dim,
385 dealii::MGTransferGlobalCoarsening<dim, MGVectorType>>
386 preconditioner(*current_dof_handler, mg, *mg_transfer);
390 *this->newton_update = 0.0;
391 cg.solve(*(this->update_system_matrix),
392 *this->newton_update,
399 <<
"Warning: linear solver did not converge as per set tolerances.\n";
401 this->constraint_handler.get_constraint(this->field_index)
402 .set_zero(*this->newton_update);
405 <<
" Final residual: " << this->solver_control.last_value()
406 <<
" Steps: " << this->solver_control.last_step() <<
"\n"
410 (*solution).add(step_length, *this->newton_update);
411 this->solution_handler.update(fieldSolveType::NONEXPLICIT_LINEAR, this->field_index);
415 this->constraint_handler.get_constraint(this->field_index).distribute(*solution);
GMGSolver(const userInputParameters< dim > &_user_inputs, const variableAttributes &_variable_attributes, const matrixfreeHandler< dim > &_matrix_free_handler, const constraintHandler< dim > &_constraint_handler, const triangulationHandler< dim > &_triangulation_handler, const dofHandler< dim > &_dof_handler, dealii::MGLevelObject< matrixfreeHandler< dim, float > > &_mg_matrix_free_handler, solutionHandler< dim > &_solution_handler)
Constructor.
Definition linear_solver_gmg.h:146