22#ifndef EXADG_GRID_MAPPING_DOF_VECTOR_H_
23#define EXADG_GRID_MAPPING_DOF_VECTOR_H_
26#include <deal.II/base/conditional_ostream.h>
27#include <deal.II/base/mg_level_object.h>
28#include <deal.II/base/multithread_info.h>
29#include <deal.II/base/quadrature_lib.h>
30#include <deal.II/dofs/dof_tools.h>
31#include <deal.II/fe/fe_nothing.h>
32#include <deal.II/fe/fe_q.h>
33#include <deal.II/fe/fe_system.h>
34#include <deal.II/fe/fe_tools.h>
35#include <deal.II/fe/fe_values.h>
36#include <deal.II/fe/mapping_q_cache.h>
37#include <deal.II/lac/la_parallel_block_vector.h>
38#include <deal.II/multigrid/mg_transfer_matrix_free.h>
41#include <exadg/grid/grid_data.h>
42#include <exadg/solvers_and_preconditioners/multigrid/transfer.h>
53template<
int dim,
typename Number>
57 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
64 mapping_q_cache = std::make_shared<dealii::MappingQCache<dim>>(mapping_degree);
66 hierarchic_to_lexicographic_numbering =
67 dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(mapping_degree);
68 lexicographic_to_hierarchic_numbering =
69 dealii::Utilities::invert_permutation(hierarchic_to_lexicographic_numbering);
82 std::shared_ptr<dealii::Mapping<dim>
const>
85 AssertThrow(mapping_q_cache.get(),
86 dealii::ExcMessage(
"Mapping object mapping_q_cache is not initialized."));
88 return mapping_q_cache;
91 std::shared_ptr<dealii::MappingQCache<dim>>
92 get_mapping_q_cache()
const
94 AssertThrow(mapping_q_cache.get(),
95 dealii::ExcMessage(
"Mapping object mapping_q_cache is not initialized."));
97 return mapping_q_cache;
107 dealii::DoFHandler<dim>
const & dof_handler)
const
109 AssertThrow(mapping_q_cache.get(),
110 dealii::ExcMessage(
"Mapping object mapping_q_cache is not initialized."));
122 VectorType & grid_coordinates,
123 dealii::DoFHandler<dim>
const & dof_handler)
const
125 if(grid_coordinates.size() != dof_handler.n_dofs())
127 dealii::IndexSet
const relevant_dofs_grid =
128 dealii::DoFTools::extract_locally_relevant_dofs(dof_handler);
129 grid_coordinates.reinit(dof_handler.locally_owned_dofs(),
131 dof_handler.get_mpi_communicator());
135 grid_coordinates = 0;
138 AssertThrow(
get_element_type(dof_handler.get_triangulation()) == ElementType::Hypercube,
139 dealii::ExcMessage(
"Only implemented for hypercube elements."));
141 dealii::FiniteElement<dim>
const & fe = dof_handler.get_fe();
143 std::vector<std::array<unsigned int, dim>> component_to_system_index(
144 fe.base_element(0).dofs_per_cell);
146 if(fe.dofs_per_vertex > 0)
148 for(
unsigned int i = 0; i < fe.dofs_per_cell; ++i)
150 component_to_system_index
151 [hierarchic_to_lexicographic_numbering[fe.system_to_component_index(i).second]]
152 [fe.system_to_component_index(i).first] = i;
157 for(
unsigned int i = 0; i < fe.dofs_per_cell; ++i)
159 component_to_system_index[fe.system_to_component_index(i).second]
160 [fe.system_to_component_index(i).first] = i;
168 dealii::FE_Nothing<dim> fe_nothing;
169 dealii::FEValues<dim> fe_values(mapping,
171 dealii::QGaussLobatto<dim>(fe.degree + 1),
172 dealii::update_quadrature_points);
174 std::vector<dealii::types::global_dof_index> dof_indices(fe.dofs_per_cell);
176 for(
auto const & cell : dof_handler.active_cell_iterators())
178 if(not cell->is_artificial())
180 fe_values.reinit(
typename dealii::Triangulation<dim>::cell_iterator(cell));
181 cell->get_dof_indices(dof_indices);
182 for(
unsigned int i = 0; i < fe_values.n_quadrature_points; ++i)
184 dealii::Point<dim>
const point = fe_values.quadrature_point(i);
185 for(
unsigned int d = 0; d < dim; ++d)
187 if(grid_coordinates.get_partitioner()->in_local_range(
188 dof_indices[component_to_system_index[i][d]]))
190 grid_coordinates(dof_indices[component_to_system_index[i][d]]) = point[d];
197 grid_coordinates.update_ghost_values();
214 VectorType
const & displacement_vector,
215 dealii::DoFHandler<dim>
const & dof_handler)
217 AssertThrow(dealii::MultithreadInfo::n_threads() == 1, dealii::ExcNotImplemented());
219 AssertThrow(mapping_q_cache.get(),
220 dealii::ExcMessage(
"Mapping object mapping_q_cache is not initialized."));
222 VectorType displacement_vector_ghosted;
223 if(dof_handler.n_dofs() > 0 and displacement_vector.size() == dof_handler.n_dofs())
225 dealii::IndexSet
const locally_relevant_dofs =
226 dealii::DoFTools::extract_locally_relevant_dofs(dof_handler);
227 displacement_vector_ghosted.reinit(dof_handler.locally_owned_dofs(),
228 locally_relevant_dofs,
229 dof_handler.get_mpi_communicator());
230 displacement_vector_ghosted.copy_locally_owned_data_from(displacement_vector);
231 displacement_vector_ghosted.update_ghost_values();
234 AssertThrow(
get_element_type(dof_handler.get_triangulation()) == ElementType::Hypercube,
235 dealii::ExcMessage(
"Only implemented for hypercube elements."));
237 std::shared_ptr<dealii::FEValues<dim>> fe_values;
243 dealii::FE_Nothing<dim> fe_nothing;
245 if(mapping.get() != 0)
247 fe_values = std::make_shared<dealii::FEValues<dim>>(*mapping,
249 dealii::QGaussLobatto<dim>(
250 mapping_q_cache->get_degree() + 1),
251 dealii::update_quadrature_points);
256 mapping_q_cache->initialize(
257 dof_handler.get_triangulation(),
258 [&](
const typename dealii::Triangulation<dim>::cell_iterator & cell_tria)
259 -> std::vector<dealii::Point<dim>> {
260 unsigned int const scalar_dofs_per_cell =
261 dealii::Utilities::pow(mapping_q_cache->get_degree() + 1, dim);
263 std::vector<dealii::Point<dim>> grid_coordinates(scalar_dofs_per_cell);
265 if(mapping.get() != 0)
267 fe_values->reinit(cell_tria);
269 for(unsigned int i = 0; i < scalar_dofs_per_cell; ++i)
271 grid_coordinates[i] =
272 fe_values->quadrature_point(this->hierarchic_to_lexicographic_numbering[i]);
278 if(dof_handler.n_dofs() > 0 and displacement_vector.size() > 0 and
279 cell_tria->is_active() and not(cell_tria->is_artificial()))
281 typename dealii::DoFHandler<dim>::cell_iterator cell(&cell_tria->get_triangulation(),
286 dealii::FiniteElement<dim> const & fe = dof_handler.get_fe();
287 AssertThrow(fe.element_multiplicity(0) == dim,
288 dealii::ExcMessage(
"Expected finite element with dim components."));
290 std::vector<dealii::types::global_dof_index> dof_indices(fe.dofs_per_cell);
291 cell->get_dof_indices(dof_indices);
293 for(unsigned int i = 0; i < dof_indices.size(); ++i)
295 std::pair<unsigned int, unsigned int> const id = fe.system_to_component_index(i);
297 if(fe.dofs_per_vertex > 0)
299 grid_coordinates[id.second][id.first] += displacement_vector_ghosted(dof_indices[i]);
303 grid_coordinates[this->lexicographic_to_hierarchic_numbering[id.second]][id.first] +=
304 displacement_vector_ghosted(dof_indices[i]);
309 return grid_coordinates;
313 std::vector<unsigned int> hierarchic_to_lexicographic_numbering;
314 std::vector<unsigned int> lexicographic_to_hierarchic_numbering;
317 std::shared_ptr<dealii::MappingQCache<dim>> mapping_q_cache;
321namespace MappingTools
336template<
int dim,
typename Number>
338initialize_coarse_mappings_from_mapping_dof_vector(
339 std::vector<std::shared_ptr<MappingDoFVector<dim, Number>>> & coarse_mappings,
340 unsigned int const degree_coarse_mappings,
341 std::shared_ptr<MappingDoFVector<dim, Number>
const>
const & fine_mapping,
342 dealii::Triangulation<dim>
const & triangulation)
344 AssertThrow(dealii::MultithreadInfo::n_threads() == 1, dealii::ExcNotImplemented());
346 std::shared_ptr<dealii::MappingQCache<dim>> mapping_q_cache = fine_mapping->get_mapping_q_cache();
347 AssertThrow(mapping_q_cache.get(),
348 dealii::ExcMessage(
"Shared pointer mapping_q_cache is invalid."));
350 dealii::FESystem<dim> fe(dealii::FE_Q<dim>(degree_coarse_mappings), dim);
351 dealii::DoFHandler<dim> dof_handler(triangulation);
352 dof_handler.distribute_dofs(fe);
353 dof_handler.distribute_mg_dofs();
355 std::shared_ptr<MappingDoFVector<dim, Number>> mapping_dof_vector_all_levels =
356 std::make_shared<MappingDoFVector<dim, Number>>(degree_coarse_mappings);
359 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
360 VectorType grid_coordinates_fine_level;
363 mapping_dof_vector_all_levels->fill_grid_coordinates_vector(*fine_mapping->get_mapping(),
364 grid_coordinates_fine_level,
369 dealii::MGLevelObject<VectorType> grid_coordinates_all_levels,
370 grid_coordinates_all_levels_ghosted;
371 unsigned int const n_levels = triangulation.n_global_levels();
372 grid_coordinates_all_levels.resize(0, n_levels - 1);
373 grid_coordinates_all_levels_ghosted.resize(0, n_levels - 1);
375 dealii::MGTransferMatrixFree<dim, Number> transfer;
376 transfer.build(dof_handler);
377 transfer.interpolate_to_mg(dof_handler, grid_coordinates_all_levels, grid_coordinates_fine_level);
380 for(
unsigned int level = 0; level < n_levels; level++)
382 dealii::IndexSet
const relevant_dofs =
383 dealii::DoFTools::extract_locally_relevant_level_dofs(dof_handler, level);
385 grid_coordinates_all_levels_ghosted[level].reinit(
386 dof_handler.locally_owned_mg_dofs(level),
388 grid_coordinates_all_levels[level].get_mpi_communicator());
390 grid_coordinates_all_levels_ghosted[level].copy_locally_owned_data_from(
391 grid_coordinates_all_levels[level]);
393 grid_coordinates_all_levels_ghosted[level].update_ghost_values();
398 mapping_dof_vector_all_levels->get_mapping_q_cache()->initialize(
399 dof_handler.get_triangulation(),
400 [&](
const typename dealii::Triangulation<dim>::cell_iterator & cell_tria)
401 -> std::vector<dealii::Point<dim>> {
402 unsigned int const level = cell_tria->level();
404 typename dealii::DoFHandler<dim>::cell_iterator cell(&cell_tria->get_triangulation(),
409 AssertThrow(fe.element_multiplicity(0) == dim,
410 dealii::ExcMessage(
"Expected finite element with dim components."));
412 unsigned int const scalar_dofs_per_cell = dealii::Utilities::pow(fe.degree + 1, dim);
414 std::vector<dealii::Point<dim>> grid_coordinates(scalar_dofs_per_cell);
416 if(cell->level_subdomain_id() != dealii::numbers::artificial_subdomain_id)
418 std::vector<dealii::types::global_dof_index> dof_indices(fe.dofs_per_cell);
419 cell->get_mg_dof_indices(dof_indices);
421 for(unsigned int i = 0; i < dof_indices.size(); ++i)
423 std::pair<unsigned int, unsigned int> const id = fe.system_to_component_index(i);
425 if(fe.dofs_per_vertex > 0)
427 grid_coordinates[id.second][id.first] =
428 grid_coordinates_all_levels_ghosted[level](dof_indices[i]);
432 grid_coordinates[mapping_dof_vector_all_levels
433 ->lexicographic_to_hierarchic_numbering[id.second]][id.first] =
434 grid_coordinates_all_levels_ghosted[level](dof_indices[i]);
439 return grid_coordinates;
444 coarse_mappings.size() == n_levels - 1,
446 "coarse_mappings does not have correct size relative to the number of levels of the triangulation."));
452 for(
unsigned int h_level = 0; h_level < coarse_mappings.size(); ++h_level)
454 coarse_mappings[h_level] = mapping_dof_vector_all_levels;
473template<
int dim,
typename Number>
475initialize_coarse_mappings_from_mapping_dof_vector(
476 std::vector<std::shared_ptr<MappingDoFVector<dim, Number>>> & coarse_mappings,
477 unsigned int const degree_coarse_mappings,
478 std::shared_ptr<MappingDoFVector<dim, Number>
const>
const & fine_mapping,
479 std::shared_ptr<dealii::Triangulation<dim>
const>
const & fine_triangulation,
480 std::vector<std::shared_ptr<dealii::Triangulation<dim>
const>>
const & coarse_triangulations)
482 std::shared_ptr<dealii::MappingQCache<dim>> mapping_q_cache = fine_mapping->get_mapping_q_cache();
483 AssertThrow(mapping_q_cache.get(),
484 dealii::ExcMessage(
"Shared pointer mapping_q_cache is invalid."));
487 dealii::FESystem<dim> fe(dealii::FE_Q<dim>(degree_coarse_mappings), dim);
488 unsigned int const n_h_levels = coarse_triangulations.size() + 1;
489 std::vector<dealii::DoFHandler<dim>> dof_handlers_all_levels(n_h_levels);
490 std::vector<dealii::AffineConstraints<Number>> constraints_all_levels(n_h_levels);
491 for(
unsigned int h_level = 0; h_level < n_h_levels; ++h_level)
493 if(h_level == n_h_levels - 1)
494 dof_handlers_all_levels[h_level].reinit(*fine_triangulation);
496 dof_handlers_all_levels[h_level].reinit(*coarse_triangulations[h_level]);
497 dof_handlers_all_levels[h_level].distribute_dofs(fe);
499 constraints_all_levels[h_level].close();
503 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
504 VectorType grid_coordinates_fine_level;
507 std::shared_ptr<MappingDoFVector<dim, Number>> mapping_dof_vector_fine_level =
508 std::make_shared<MappingDoFVector<dim, Number>>(degree_coarse_mappings);
510 auto const & dof_handler_fine_level = dof_handlers_all_levels[n_h_levels - 1];
511 mapping_dof_vector_fine_level->fill_grid_coordinates_vector(*fine_mapping->get_mapping(),
512 grid_coordinates_fine_level,
513 dof_handler_fine_level);
517 dealii::MGLevelObject<dealii::MGTwoLevelTransfer<dim, VectorType>> transfers(0, n_h_levels - 1);
518 for(
unsigned int h_level = 1; h_level < n_h_levels; ++h_level)
520 transfers[h_level].reinit_geometric_transfer(dof_handlers_all_levels[h_level],
521 dof_handlers_all_levels[h_level - 1],
522 constraints_all_levels[h_level],
523 constraints_all_levels[h_level - 1]);
527 const std::function<void(
unsigned int const, VectorType &)> initialize_dof_vector =
528 [&](
unsigned int const h_level, VectorType & vector) {
529 dealii::IndexSet
const locally_relevant_dofs =
530 dealii::DoFTools::extract_locally_relevant_dofs(dof_handlers_all_levels[h_level]);
531 vector.reinit(dof_handlers_all_levels[h_level].locally_owned_dofs(),
532 locally_relevant_dofs,
533 dof_handlers_all_levels[h_level].get_mpi_communicator());
536 dealii::MGTransferGlobalCoarsening<dim, VectorType> mg_transfer_global_coarsening(
537 transfers, initialize_dof_vector);
541 dealii::DoFHandler<dim> dof_handler_dummy;
542 dealii::MGLevelObject<VectorType> grid_coordinates_all_levels(0, n_h_levels - 1);
543 mg_transfer_global_coarsening.interpolate_to_mg(dof_handler_dummy,
544 grid_coordinates_all_levels,
545 grid_coordinates_fine_level);
548 AssertThrow(coarse_mappings.size() == n_h_levels - 1,
550 "coarse_mappings does not have correct size relative to coarse_triangulations."));
552 for(
unsigned int h_level = 0; h_level < coarse_mappings.size(); ++h_level)
554 coarse_mappings[h_level] =
555 std::make_shared<MappingDoFVector<dim, Number>>(degree_coarse_mappings);
560 std::shared_ptr<dealii::Mapping<dim>
const> mapping_dummy;
561 coarse_mappings[h_level]->initialize_mapping_from_dof_vector(
562 mapping_dummy, grid_coordinates_all_levels[h_level], dof_handlers_all_levels[h_level]);
581template<
int dim,
typename Number>
583initialize_coarse_mappings(
584 std::vector<std::shared_ptr<MappingDoFVector<dim, Number>>> & coarse_mappings,
585 unsigned int const degree_coarse_mappings,
586 std::shared_ptr<MappingDoFVector<dim, Number>
const>
const & fine_mapping,
587 std::shared_ptr<dealii::Triangulation<dim>
const>
const & fine_triangulation,
588 std::vector<std::shared_ptr<dealii::Triangulation<dim>
const>>
const & coarse_triangulations)
590 if(fine_mapping.get())
592 if(coarse_triangulations.size() > 0)
594 MappingTools::initialize_coarse_mappings_from_mapping_dof_vector<dim, Number>(
596 degree_coarse_mappings,
599 coarse_triangulations);
603 MappingTools::initialize_coarse_mappings_from_mapping_dof_vector<dim, Number>(
604 coarse_mappings, degree_coarse_mappings, fine_mapping, *fine_triangulation);
MappingDoFVector(unsigned int const mapping_degree)
Definition mapping_dof_vector.h:62
void initialize_mapping_from_dof_vector(std::shared_ptr< dealii::Mapping< dim > const > mapping, VectorType const &displacement_vector, dealii::DoFHandler< dim > const &dof_handler)
Definition mapping_dof_vector.h:213
virtual ~MappingDoFVector()
Definition mapping_dof_vector.h:75
void fill_grid_coordinates_vector(dealii::Mapping< dim > const &mapping, VectorType &grid_coordinates, dealii::DoFHandler< dim > const &dof_handler) const
Definition mapping_dof_vector.h:121
void fill_grid_coordinates_vector(VectorType &grid_coordinates, dealii::DoFHandler< dim > const &dof_handler) const
Definition mapping_dof_vector.h:106
std::shared_ptr< dealii::Mapping< dim > const > get_mapping() const
Definition mapping_dof_vector.h:83
ElementType get_element_type(dealii::Triangulation< dim > const &tria)
Definition grid_data.h:70