I am trying to implement a test program using the matrix-free method, combined with a geometric multigrid preconditioner. In my case my vmult/apply_add-function needs access to the solution from the last step. Thus I added a vector
LinearAlgebra::distributed::Vector<number> old_solution;
which is filled using
template <int dim, int fe_degree, typename number>
void LaplaceOperator<dim, fe_degree, number>::update_old_solution(const LinearAlgebra::distributed::Vector<number> &solution){
this->old_solution = LinearAlgebra::distributed::Vector<number>(solution);
}
For each level of grids I need to fill this vector with the current solution, interpolated onto the correct mesh. Thus, I added the following code:
const unsigned int nlevels = triangulation.n_global_levels();
mg_matrices.resize(0, nlevels - 1);
std::set<types::boundary_id> dirichlet_boundary;
dirichlet_boundary.insert(0);
mg_constrained_dofs.initialize(dof_handler);
mg_constrained_dofs.make_zero_boundary_constraints(dof_handler,
dirichlet_boundary);
MGTransferMatrixFree<dim, float> mg_transfer(mg_constrained_dofs);
const unsigned int max_level =
dof_handler.get_triangulation().n_global_levels() - 1;
const unsigned int min_level = 0;
MGLevelObject<LinearAlgebra::distributed::Vector<float>>
level_projection(min_level, max_level);
pcout << "Interpolate to mg\n";
mg_transfer.interpolate_to_mg(dof_handler, level_projection, solution);
pcout << "Interpolated to mg\n";
for (unsigned int level = 0; level < nlevels; ++level)
{
pcout << "Level: " << level << '\n';
IndexSet relevant_dofs;
DoFTools::extract_locally_relevant_level_dofs(dof_handler,
level,
relevant_dofs);
AffineConstraints<double> level_constraints;
level_constraints.reinit(relevant_dofs);
level_constraints.add_lines(
mg_constrained_dofs.get_boundary_indices(level));
level_constraints.close();
typename MatrixFree<dim, float>::AdditionalData additional_data;
additional_data.tasks_parallel_scheme =
MatrixFree<dim, float>::AdditionalData::partition_partition;
additional_data.mapping_update_flags =
(update_gradients | update_JxW_values | update_quadrature_points);
additional_data.level_mg_handler = level;
std::shared_ptr<MatrixFree<dim, float>> mg_mf_storage_level(
new MatrixFree<dim, float>());
mg_mf_storage_level->reinit(dof_handler,
level_constraints,
QGauss<1>(fe.degree + 1),
additional_data);
mg_matrices[level].initialize(mg_mf_storage_level,
mg_constrained_dofs,
level);
mg_matrices[level].set_time_step(time_step);
mg_matrices[level].update_old_solution(level_projection[level]);
}
My program works without crash (even though I get wrong results, but that is another problem) when compiling it in debug mode, but crashes immediately after pcout << "Interpolate to mg\n" with a segfault; when running in release mode. Why is that? Or are there other methods I could use for interpolation?
Thanks!