ryujin 2.1.1 revision feb53359f0c9a08baf43c3dfe847d8a9f7d6893a
discretization.template.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2023 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
9
10#include "discretization.h"
11#include "geometry_library.h"
12
13#include <deal.II/base/quadrature_lib.h>
14#include <deal.II/fe/fe_q.h>
15#include <deal.II/fe/mapping_q.h>
16
17#include <fstream>
18#include <random>
19
20namespace ryujin
21{
22 using namespace dealii;
23
24 template <int dim>
25 Discretization<dim>::Discretization(const MPI_Comm &mpi_communicator,
26 const std::string &subsection)
27 : ParameterAcceptor(subsection)
28 , mpi_communicator_(mpi_communicator)
29 {
30 const auto smoothing =
31 dealii::Triangulation<dim>::limit_level_difference_at_vertices;
32
33 if constexpr (have_distributed_triangulation<dim>) {
34 const auto settings =
35 Triangulation::Settings::construct_multigrid_hierarchy;
36 triangulation_ = std::make_unique<Triangulation>(
37 mpi_communicator_, smoothing, settings);
38
39 } else {
40 const auto settings = static_cast<typename Triangulation::Settings>(
41 Triangulation::partition_auto |
42 Triangulation::construct_multigrid_hierarchy);
43 /* Beware of the boolean: */
44 triangulation_ = std::make_unique<Triangulation>(
45 mpi_communicator_, smoothing, /*artificial cells*/ true, settings);
46 }
47
48
49 /* Options: */
50
51 geometry_ = "cylinder";
52 add_parameter("geometry",
53 geometry_,
54 "Name of the geometry used to create the mesh. Valid names "
55 "are given by any of the subsections defined below.");
56
57 refinement_ = 5;
58 add_parameter("mesh refinement",
59 refinement_,
60 "number of refinement of global refinement steps");
61
62 mesh_distortion_ = 0.;
63 add_parameter(
64 "mesh distortion", mesh_distortion_, "Strength of mesh distortion");
65
66 repartitioning_ = false;
67 add_parameter("mesh repartitioning",
68 repartitioning_,
69 "try to equalize workload by repartitioning the mesh");
70
71 Geometries::populate_geometry_list<dim>(geometry_list_, subsection);
72 }
73
74
75 template <int dim>
77 {
78#ifdef DEBUG_OUTPUT
79 std::cout << "Discretization<dim>::prepare()" << std::endl;
80#endif
81
82 auto &triangulation = *triangulation_;
83 triangulation.clear();
84
85 {
86 bool initialized = false;
87 for (auto &it : geometry_list_)
88 if (it->name() == geometry_) {
89 it->create_triangulation(triangulation);
90 initialized = true;
91 break;
92 }
93
94 AssertThrow(
95 initialized,
96 ExcMessage("Could not find a geometry description with name \"" +
97 geometry_ + "\""));
98 }
99
100 if constexpr (have_distributed_triangulation<dim>) {
101 if (repartitioning_) {
102 /*
103 * Try to partition the mesh equilibrating the workload. The usual mesh
104 * partitioning heuristic that tries to partition the mesh such that
105 * every MPI rank has roughly the same number of locally owned degrees
106 * of freedom does not work well in our case due to the fact that
107 * boundary dofs are not SIMD parallelized. (In fact, every dof with
108 * "non-standard connectivity" is not SIMD parallelized. Those are
109 * however exceedingly rare (point irregularities in 2D, line
110 * irregularities in 3D) and we simply ignore them.)
111 *
112 * For the mesh partitioning scheme we have to supply an additional
113 * weight that gets added to the default weight of a cell which is
114 * 1000. Asymptotically we have one boundary dof per boundary cell (in
115 * any dimension). A rough benchmark reveals that the speedup due to
116 * SIMD vectorization is typically less than VectorizedArray::size() /
117 * 2. Boundary dofs are more expensive due to certain special treatment
118 * (additional symmetrization of d_ij, boundary fixup) so it should be
119 * safe to assume that the cost incurred is at least
120 * VectorizedArray::size() / 2.
121 */
122 constexpr auto speedup = dealii::VectorizedArray<NUMBER>::size() / 2u;
123 constexpr unsigned int weight = 1000u;
124
125#if DEAL_II_VERSION_GTE(9, 5, 0)
126 triangulation.signals.weight.connect(
127#else
128 triangulation.signals.cell_weight.connect(
129#endif
130 [](const auto &cell, const auto /*status*/) -> unsigned int {
131 if (cell->at_boundary())
132 return weight * (speedup == 0u ? 0u : speedup - 1u);
133 else
134 return 0u;
135 });
136
137 triangulation.repartition();
138 }
139 }
140
141 triangulation.refine_global(refinement_);
142
143 if (std::abs(mesh_distortion_) > 1.0e-10)
144 GridTools::distort_random(
145 mesh_distortion_, triangulation, std::random_device()());
146
147 mapping_ = std::make_unique<MappingQ<dim>>(order_mapping);
148 finite_element_ = std::make_unique<FE_Q<dim>>(order_finite_element);
149 quadrature_ = std::make_unique<QGauss<dim>>(order_quadrature);
150 quadrature_1d_ = std::make_unique<QGauss<1>>(order_quadrature);
151 }
152
153} /* namespace ryujin */
std::unique_ptr< Triangulation > triangulation_
Discretization(const MPI_Comm &mpi_communicator, const std::string &subsection="/Discretization")
const MPI_Comm & mpi_communicator_