ExaDG
Loading...
Searching...
No Matches
grid_utilities.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef EXADG_GRID_GRID_UTILITIES_H_
23#define EXADG_GRID_GRID_UTILITIES_H_
24
25// deal.II
26#include <deal.II/fe/fe_simplex_p.h>
27#include <deal.II/fe/mapping_fe.h>
28#include <deal.II/fe/mapping_q.h>
29#include <deal.II/grid/grid_in.h>
30#include <deal.II/grid/grid_tools.h>
31#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
32
33// ExaDG
34#include <exadg/grid/balanced_granularity_partition_policy.h>
35#include <exadg/grid/grid.h>
36#include <exadg/grid/grid_data.h>
37#include <exadg/grid/perform_local_refinements.h>
38
39namespace ExaDG
40{
41namespace GridUtilities
42{
43template<int dim>
44using PeriodicFacePairs = std::vector<
45 dealii::GridTools::PeriodicFacePair<typename dealii::Triangulation<dim>::cell_iterator>>;
46
50template<int dim>
51void
52create_mapping(std::shared_ptr<dealii::Mapping<dim>> & mapping,
53 ElementType const & element_type,
54 unsigned int const & mapping_degree)
55{
56 if(element_type == ElementType::Hypercube)
57 {
58 mapping = std::make_shared<dealii::MappingQ<dim>>(mapping_degree);
59 }
60 else if(element_type == ElementType::Simplex)
61 {
62 mapping = std::make_shared<dealii::MappingFE<dim>>(dealii::FE_SimplexP<dim>(mapping_degree));
63 }
64 else
65 {
66 AssertThrow(false, dealii::ExcMessage("Invalid parameter element_type."));
67 }
68}
69
76template<int dim, typename Number>
77void
78create_mapping_with_multigrid(std::shared_ptr<dealii::Mapping<dim>> & mapping,
79 std::shared_ptr<MultigridMappings<dim, Number>> & multigrid_mappings,
80 ElementType const & element_type,
81 unsigned int const & mapping_degree_fine,
82 unsigned int const & mapping_degree_coarse,
83 bool const involves_h_multigrid)
84{
85 // create fine mapping
86 create_mapping(mapping, element_type, mapping_degree_fine);
87
88 // create coarse mappings if needed
89 std::shared_ptr<dealii::Mapping<dim>> coarse_mapping;
90 if(involves_h_multigrid and (mapping_degree_coarse != mapping_degree_fine))
91 {
92 create_mapping(coarse_mapping, element_type, mapping_degree_coarse);
93 }
94 multigrid_mappings = std::make_shared<MultigridMappings<dim, Number>>(mapping, coarse_mapping);
95}
96
102template<int dim>
103std::vector<dealii::GridTools::PeriodicFacePair<typename dealii::DoFHandler<dim>::cell_iterator>>
104transform_periodic_face_pairs_to_dof_cell_iterator(
105 std::vector<dealii::GridTools::PeriodicFacePair<
106 typename dealii::Triangulation<dim>::cell_iterator>> const & periodic_faces,
107 dealii::DoFHandler<dim> const & dof_handler)
108{
109 typedef typename std::vector<
110 dealii::GridTools::PeriodicFacePair<typename dealii::DoFHandler<dim>::cell_iterator>>
111 PeriodicFacesDoF;
112
113 PeriodicFacesDoF periodic_faces_dof;
114
115 for(auto it : periodic_faces)
116 {
117 dealii::GridTools::PeriodicFacePair<typename dealii::DoFHandler<dim>::cell_iterator>
118 face_pair_dof_hander;
119
120 face_pair_dof_hander.cell[0] = it.cell[0]->as_dof_handler_iterator(dof_handler);
121 face_pair_dof_hander.cell[1] = it.cell[1]->as_dof_handler_iterator(dof_handler);
122
123 face_pair_dof_hander.face_idx[0] = it.face_idx[0];
124 face_pair_dof_hander.face_idx[1] = it.face_idx[1];
125
126 face_pair_dof_hander.orientation = it.orientation;
127 face_pair_dof_hander.matrix = it.matrix;
128
129 periodic_faces_dof.push_back(face_pair_dof_hander);
130 }
131
132 return periodic_faces_dof;
133}
134
142
143template<int dim>
144inline void
145create_triangulation(
146 std::shared_ptr<dealii::Triangulation<dim>> & triangulation,
147 PeriodicFacePairs<dim> & periodic_face_pairs,
148 MPI_Comm const & mpi_comm,
149 GridData const & data,
150 bool const construct_multigrid_hierarchy,
151 std::function<void(dealii::Triangulation<dim> &,
152 PeriodicFacePairs<dim> &,
153 unsigned int const,
154 std::vector<unsigned int> const &)> const & lambda_create_triangulation,
155 unsigned int const global_refinements,
156 std::vector<unsigned int> const & vector_local_refinements)
157{
158 if(vector_local_refinements.size() != 0)
159 {
160 AssertThrow(
161 data.element_type == ElementType::Hypercube,
162 dealii::ExcMessage(
163 "Local refinements are currently only supported for meshes composed of hypercube elements."));
164 }
165
166 // mesh smoothing
167 auto mesh_smoothing = dealii::Triangulation<dim>::none;
168
169 // the mesh used for a simulation should not depend on the preconditioner used to solve the
170 // problem (like whether multigrid is used or not). Hence, we always set this parameter for
171 // ElementType::Hypercube. It is not posible to set this parameter for ElementType::Simplex due to
172 // the implementation in deal.II.
173 if(data.element_type == ElementType::Hypercube)
174 {
175 mesh_smoothing = dealii::Triangulation<dim>::limit_level_difference_at_vertices;
176 }
177
178 if(data.triangulation_type == TriangulationType::Serial)
179 {
180 AssertDimension(dealii::Utilities::MPI::n_mpi_processes(mpi_comm), 1);
181 triangulation = std::make_shared<dealii::Triangulation<dim>>(mesh_smoothing);
182
183 lambda_create_triangulation(*triangulation,
184 periodic_face_pairs,
185 global_refinements,
186 vector_local_refinements);
187 }
188 else if(data.triangulation_type == TriangulationType::Distributed)
189 {
190 typename dealii::parallel::distributed::Triangulation<dim>::Settings distributed_settings;
191
192 if(construct_multigrid_hierarchy)
193 {
194 distributed_settings =
195 dealii::parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy;
196 }
197
198 triangulation =
199 std::make_shared<dealii::parallel::distributed::Triangulation<dim>>(mpi_comm,
200 mesh_smoothing,
201 distributed_settings);
202
203 lambda_create_triangulation(*triangulation,
204 periodic_face_pairs,
205 global_refinements,
206 vector_local_refinements);
207 }
208 else if(data.triangulation_type == TriangulationType::FullyDistributed)
209 {
210 auto const serial_grid_generator = [&](dealii::Triangulation<dim, dim> & tria_serial) {
211 lambda_create_triangulation(tria_serial,
212 periodic_face_pairs,
213 global_refinements,
214 vector_local_refinements);
215 };
216
217 auto const serial_grid_partitioner = [&](dealii::Triangulation<dim, dim> & tria_serial,
218 MPI_Comm const comm,
219 unsigned int const group_size) {
220 (void)group_size;
221 if(data.partitioning_type == PartitioningType::Metis)
222 {
223 dealii::GridTools::partition_triangulation(dealii::Utilities::MPI::n_mpi_processes(comm),
224 tria_serial);
225 }
226 else if(data.partitioning_type == PartitioningType::z_order)
227 {
228 dealii::GridTools::partition_triangulation_zorder(
229 dealii::Utilities::MPI::n_mpi_processes(comm), tria_serial);
230 }
231 else
232 {
233 AssertThrow(false, dealii::ExcNotImplemented());
234 }
235 };
236
237 unsigned int const group_size = 1;
238
239 typename dealii::TriangulationDescription::Settings triangulation_description_setting =
240 dealii::TriangulationDescription::default_setting;
241
242 if(construct_multigrid_hierarchy)
243 {
244 triangulation_description_setting =
245 dealii::TriangulationDescription::construct_multigrid_hierarchy;
246 }
247
248 triangulation =
249 std::make_shared<dealii::parallel::fullydistributed::Triangulation<dim>>(mpi_comm);
250
251 auto const description = dealii::TriangulationDescription::Utilities::
252 create_description_from_triangulation_in_groups<dim, dim>(
253 serial_grid_generator,
254 serial_grid_partitioner,
255 triangulation->get_mpi_communicator(),
256 group_size,
257 mesh_smoothing,
258 triangulation_description_setting);
259
260 triangulation->create_triangulation(description);
261 }
262 else
263 {
264 AssertThrow(false, dealii::ExcMessage("Invalid parameter triangulation_type."));
265 }
266}
267
279template<int dim>
280inline void
281create_coarse_triangulations_automatically_from_fine_triangulation(
282 dealii::Triangulation<dim> const & fine_triangulation,
283 PeriodicFacePairs<dim> const & fine_periodic_face_pairs,
284 std::vector<std::shared_ptr<dealii::Triangulation<dim> const>> & coarse_triangulations_const,
285 std::vector<PeriodicFacePairs<dim>> & coarse_periodic_face_pairs,
286 GridData const & data)
287{
288 // In case of a serial or distributed triangulation, deal.II can automatically generate the
289 // coarse triangulations.
290 AssertThrow(data.triangulation_type == TriangulationType::Serial or
291 data.triangulation_type == TriangulationType::Distributed,
292 dealii::ExcMessage("Invalid parameter triangulation_type."));
293
294 if(data.triangulation_type == TriangulationType::Serial)
295 {
296 AssertThrow(
297 fine_triangulation.all_reference_cells_are_hyper_cube(),
298 dealii::ExcMessage(
299 "The create_geometric_coarsening_sequence function of dealii does currently not support "
300 "simplicial elements."));
301
302 coarse_triangulations_const =
303 dealii::MGTransferGlobalCoarseningTools::create_geometric_coarsening_sequence(
304 fine_triangulation);
305 }
306 else if(data.triangulation_type == TriangulationType::Distributed)
307 {
308 AssertThrow(
309 fine_triangulation.all_reference_cells_are_hyper_cube(),
310 dealii::ExcMessage(
311 "dealii::parallel::distributed::Triangulation does not support simplicial elements."));
312
313 coarse_triangulations_const =
314 dealii::MGTransferGlobalCoarseningTools::create_geometric_coarsening_sequence(
315 fine_triangulation,
316 BalancedGranularityPartitionPolicy<dim>(
317 dealii::Utilities::MPI::n_mpi_processes(fine_triangulation.get_mpi_communicator())));
318 }
319 else
320 {
321 AssertThrow(false, dealii::ExcMessage("Invalid parameter triangulation_type."));
322 }
323
324 // deal.II adds the fine triangulation as the last entry of the vector. According to our
325 // convention in ExaDG, we only include the triangulations coarser than the fine level. Hence,
326 // we remove the last entry of the vector.
327 coarse_triangulations_const.pop_back();
328
329 coarse_periodic_face_pairs.resize(coarse_triangulations_const.size());
330 for(unsigned int level = 0; level < coarse_periodic_face_pairs.size(); ++level)
331 {
332 coarse_periodic_face_pairs[level] = fine_periodic_face_pairs;
333 }
334}
335
336template<int dim>
337inline void
338create_coarse_triangulations_for_fully_distributed_triangulation(
339 dealii::Triangulation<dim> const & fine_triangulation,
340 std::vector<std::shared_ptr<dealii::Triangulation<dim> const>> & coarse_triangulations_const,
341 std::vector<PeriodicFacePairs<dim>> & coarse_periodic_face_pairs,
342 GridData const & data,
343 std::function<void(dealii::Triangulation<dim> &,
344 PeriodicFacePairs<dim> &,
345 unsigned int const,
346 std::vector<unsigned int> const &)> const & lambda_create_triangulation,
347 std::vector<unsigned int> const vector_local_refinements)
348{
349 // In case of a fully distributed triangulation, deal.II cannot automatically generate the
350 // coarse triangulations. Create the coarse traingulations using the lambda function and
351 // the vector of local refinements.
352 AssertThrow(data.triangulation_type == TriangulationType::FullyDistributed,
353 dealii::ExcMessage("Invalid parameter triangulation_type."));
354
355 if(fine_triangulation.n_global_levels() >= 2)
356 {
357 // Resize the empty coarse_triangulations and coarse_periodic_face_pairs vectors.
358 std::vector<std::shared_ptr<dealii::Triangulation<dim>>> coarse_triangulations =
359 std::vector<std::shared_ptr<dealii::Triangulation<dim>>>(
360 fine_triangulation.n_global_levels() - 1);
361
362 coarse_periodic_face_pairs = std::vector<PeriodicFacePairs<dim>>(coarse_triangulations.size());
363
364 // Start one level below the fine triangulation.
365 unsigned int level = fine_triangulation.n_global_levels() - 2;
366 std::vector<unsigned int> refine_local = vector_local_refinements;
367
368 // Undo global refinements.
369 if(data.n_refine_global >= 1)
370 {
371 unsigned int const n_refine_global_start = (unsigned int)(data.n_refine_global - 1);
372 for(int refine_global = n_refine_global_start; refine_global >= 0; --refine_global)
373 {
374 GridUtilities::create_triangulation<dim>(coarse_triangulations[level],
375 coarse_periodic_face_pairs[level],
376 fine_triangulation.get_mpi_communicator(),
377 data,
378 false /*construct_multigrid_hierarchy */,
379 lambda_create_triangulation,
380 refine_global,
382
383 if(level > 0)
384 {
385 level--;
386 }
387 }
388 }
389
390 // Undo local refinements.
391 if(refine_local.size() > 0)
392 {
393 while(*std::max_element(refine_local.begin(), refine_local.end()) != 0)
394 {
395 for(size_t material_id = 0; material_id < refine_local.size(); material_id++)
396 {
397 if(refine_local[material_id] > 0)
398 {
399 refine_local[material_id]--;
400 }
401 }
402
403 GridUtilities::create_triangulation<dim>(coarse_triangulations[level],
404 coarse_periodic_face_pairs[level],
405 fine_triangulation.get_mpi_communicator(),
406 data,
407 false /*construct_multigrid_hierarchy */,
408 lambda_create_triangulation,
409 0 /*refine_global*/,
411
412 if(level > 0)
413 {
414 level--;
415 }
416 }
417 }
418
419 AssertThrow(
420 level == 0,
421 dealii::ExcMessage(
422 "There occurred a logical error when creating the geometric coarsening sequence."));
423
424 // Make all entries in the vector of shared pointers const.
425 for(auto const & it : coarse_triangulations)
426 {
427 coarse_triangulations_const.push_back(it);
428 }
429 }
430}
431
432template<int dim>
433inline void
434create_coarse_triangulations(
435 dealii::Triangulation<dim> const & fine_triangulation,
436 PeriodicFacePairs<dim> const & fine_periodic_face_pairs,
437 std::vector<std::shared_ptr<dealii::Triangulation<dim> const>> & coarse_triangulations_const,
438 std::vector<PeriodicFacePairs<dim>> & coarse_periodic_face_pairs,
439 GridData const & data,
440 std::function<void(dealii::Triangulation<dim> &,
441 PeriodicFacePairs<dim> &,
442 unsigned int const,
443 std::vector<unsigned int> const &)> const & lambda_create_triangulation,
444 std::vector<unsigned int> const vector_local_refinements)
445{
446 // In case of a serial or distributed triangulation, deal.II can automatically generate the
447 // coarse triangulations, otherwise, the coarse triangulations have to be explicitily created
448 // using the provided lambda function and the vector of local refinements.
449 if(data.triangulation_type == TriangulationType::Serial or
450 data.triangulation_type == TriangulationType::Distributed)
451 {
452 create_coarse_triangulations_automatically_from_fine_triangulation(fine_triangulation,
453 fine_periodic_face_pairs,
454 coarse_triangulations_const,
455 coarse_periodic_face_pairs,
456 data);
457 }
458 else if(data.triangulation_type == TriangulationType::FullyDistributed)
459 {
460 create_coarse_triangulations_for_fully_distributed_triangulation(fine_triangulation,
461 coarse_triangulations_const,
462 coarse_periodic_face_pairs,
463 data,
464 lambda_create_triangulation,
465 vector_local_refinements);
466 }
467 else
468 {
469 AssertThrow(false, dealii::ExcMessage("Invalid parameter triangulation_type."));
470 }
471}
472
479template<int dim>
480inline void
481create_triangulation(
482 Grid<dim> & grid,
483 MPI_Comm const & mpi_comm,
484 GridData const & data,
485 std::function<void(dealii::Triangulation<dim> &,
486 PeriodicFacePairs<dim> &,
487 unsigned int const,
488 std::vector<unsigned int> const &)> const & lambda_create_triangulation,
489 std::vector<unsigned int> const vector_local_refinements)
490{
491 GridUtilities::create_triangulation(grid.triangulation,
492 grid.periodic_face_pairs,
493 mpi_comm,
494 data,
495 false /*construct_multigrid_hierarchy */,
496 lambda_create_triangulation,
497 data.n_refine_global,
498 vector_local_refinements);
499}
500
506template<int dim>
507inline void
508create_triangulation_with_multigrid(
509 Grid<dim> & grid,
510 MPI_Comm const & mpi_comm,
511 GridData const & data,
512 bool const involves_h_multigrid,
513 std::function<void(dealii::Triangulation<dim> &,
514 PeriodicFacePairs<dim> &,
515 unsigned int const,
516 std::vector<unsigned int> const &)> const & lambda_create_triangulation,
517 std::vector<unsigned int> const vector_local_refinements)
518{
519 if(involves_h_multigrid)
520 {
521 // Make sure that we create coarse triangulations in case of simplex meshes.
522 if(data.element_type == ElementType::Simplex)
523 {
524 AssertThrow(data.create_coarse_triangulations == true,
525 dealii::ExcMessage(
526 "You need to set GridData::create_coarse_triangulations = true "
527 "in order to use h-multigrid for simplex meshes."));
528 }
529
530 // create fine triangulation
531 GridUtilities::create_triangulation(grid.triangulation,
532 grid.periodic_face_pairs,
533 mpi_comm,
534 data,
535 not data.create_coarse_triangulations,
536 lambda_create_triangulation,
537 data.n_refine_global,
538 vector_local_refinements);
539
540 // Make sure that we create coarse triangulations in case of meshes with hanging nodes.
541 if(grid.triangulation->has_hanging_nodes())
542 {
543 AssertThrow(data.create_coarse_triangulations == true,
544 dealii::ExcMessage(
545 "You need to set GridData::create_coarse_triangulations = true "
546 "in order to use h-multigrid for meshes with hanging nodes."));
547 }
548
549 // create coarse triangulations
550 if(data.create_coarse_triangulations)
551 {
552 GridUtilities::create_coarse_triangulations(*grid.triangulation,
553 grid.periodic_face_pairs,
554 grid.coarse_triangulations,
555 grid.coarse_periodic_face_pairs,
556 data,
557 lambda_create_triangulation,
558 vector_local_refinements);
559 }
560 }
561 else
562 {
563 // If no h-multigrid is involved, simply re-direct to the other function that creates the fine
564 // triangulation only.
565 GridUtilities::create_triangulation<dim>(
566 grid, mpi_comm, data, lambda_create_triangulation, vector_local_refinements);
567 }
568}
569
574template<int dim>
575inline void
576create_coarse_triangulations_after_coarsening_and_refinement(
577 dealii::Triangulation<dim> const & fine_triangulation,
578 PeriodicFacePairs<dim> const & fine_periodic_face_pairs,
579 std::vector<std::shared_ptr<dealii::Triangulation<dim> const>> & coarse_triangulations_const,
580 std::vector<PeriodicFacePairs<dim>> & coarse_periodic_face_pairs,
581 GridData const & data,
582 bool const amr_preserves_boundary_cells)
583{
584 if(data.triangulation_type == TriangulationType::Serial or
585 data.triangulation_type == TriangulationType::Distributed)
586 {
587 // Update periodic face pairs if existent.
588 if(fine_periodic_face_pairs.size() > 0)
589 {
590 AssertThrow(amr_preserves_boundary_cells,
591 dealii::ExcMessage(
592 "Combination of adaptive mesh refinement and periodic face pairs"
593 " requires boundary cells to be preserved."));
594 }
595
596 create_coarse_triangulations_automatically_from_fine_triangulation(fine_triangulation,
597 fine_periodic_face_pairs,
598 coarse_triangulations_const,
599 coarse_periodic_face_pairs,
600 data);
601 }
602 else if(data.triangulation_type == TriangulationType::FullyDistributed)
603 {
604 AssertThrow(false,
605 dealii::ExcMessage("Combination of adaptive mesh refinement and "
606 "TriangulationType::FullyDistributed not implemented."));
607 }
608 else
609 {
610 AssertThrow(false, dealii::ExcMessage("Invalid parameter triangulation_type."));
611 }
612}
613
618template<int dim>
619inline void
620read_external_triangulation(dealii::Triangulation<dim, dim> & tria, GridData const & data)
621{
622 AssertThrow(not data.file_name.empty(),
623 dealii::ExcMessage(
624 "You are trying to read a grid file, but the string, which is supposed to contain"
625 " the file name, is empty."));
626
627 dealii::GridIn<dim> grid_in;
628
629 grid_in.attach_triangulation(tria);
630
631 // find the file extension from the file name
632 std::string extension = data.file_name.substr(data.file_name.find_last_of('.') + 1);
633
634 AssertThrow(not extension.empty(),
635 dealii::ExcMessage("You are trying to read a grid file, but the file extension is"
636 " empty."));
637
638 // decide the file format
639 typename dealii::GridIn<dim>::Format format;
640 if(extension == "e" || extension == "exo")
641 format = dealii::GridIn<dim>::Format::exodusii;
642 else
643 format = grid_in.parse_format(extension);
644
645 // TODO: check if the exodusIIData is needed
646 // typename dealii::GridIn<dim>::ExodusIIData exodusIIData;
647
648 grid_in.read(data.file_name, format);
649
650 AssertThrow(get_element_type(tria) == data.element_type,
651 dealii::ExcMessage("You are trying to read a grid file, but the element type of the"
652 " external grid file and the element type specified in GridData"
653 " don't match. Most likely, you forgot to change the element_type"
654 " parameter of GridData to the desired element type."));
655}
656
657} // namespace GridUtilities
658} // namespace ExaDG
659
660#endif /* EXADG_GRID_GRID_UTILITIES_H_ */
Definition driver.cpp:33
ElementType get_element_type(dealii::Triangulation< dim > const &tria)
Definition grid_data.h:70
void refine_local(dealii::Triangulation< dim > &tria, std::vector< unsigned int > const &vector_local_refinements)
Definition perform_local_refinements.h:43