ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
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 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <boost/random/detail/polynomial.hpp>
9#include <compile_time_options.h>
10
11#include "discretization.h"
13
14#include <deal.II/base/quadrature_lib.h>
15#include <deal.II/fe/fe_dgq.h>
16#include <deal.II/fe/fe_nothing.h>
17#include <deal.II/fe/fe_q.h>
18#include <deal.II/fe/fe_simplex_p.h>
19#include <deal.II/fe/fe_tools.h>
20#include <deal.II/fe/mapping_fe.h>
21#if DEAL_II_VERSION_GTE(9, 7, 0)
22#include <deal.II/fe/mapping_p1.h>
23#endif
24#include <deal.II/fe/mapping_q.h>
25#include <deal.II/grid/grid_out.h>
26
27#include <random>
28
29namespace ryujin
30{
31 using namespace dealii;
32
33 template <int dim>
35 const std::string &subsection)
36 : ParameterAcceptor(subsection)
37 , mpi_ensemble_(mpi_ensemble)
38 {
39 /* Options: */
40
41 ansatz_ = Ansatz::cg_q1;
42 add_parameter("finite element ansatz",
43 ansatz_,
44 "The finite element ansatz used for discretization. Valid "
45 "choices are cG Q1, cG Q2, cG Q3.");
46
47 mesh_type_ =
49 add_parameter("mesh type",
50 mesh_type_,
51 "The triangulation class used. Valid choices are \"serial\", "
52 "\"parallel shared\", \"parallel distributed\", \"parallel "
53 "fullydistributed\".");
54
55 if constexpr (dim == 1) {
56 geometry_ = "rectangular domain";
57 } else {
58 geometry_ = "cylinder";
59 }
60 add_parameter("geometry",
61 geometry_,
62 "Name of the geometry used to create the mesh. Valid names "
63 "are given by any of the subsections defined below.");
64
65 refinement_ = 5;
66 add_parameter("mesh refinement",
67 refinement_,
68 "number of refinement of global refinement steps");
69
70 mesh_writeout_ = true;
71 add_parameter("mesh writeout",
72 mesh_writeout_,
73 "Write out shared coarse mesh to a GMSH *.msh file.");
74
75 mesh_distortion_ = 0.;
76 add_parameter(
77 "mesh distortion", mesh_distortion_, "Strength of mesh distortion");
78
79 Geometries::populate_geometry_list<dim>(geometry_list_, subsection);
80 }
81
82
83 template <int dim>
84 void Discretization<dim>::prepare(const std::string &base_name)
85 {
86#ifdef DEBUG_OUTPUT
87 std::cout << "Discretization<dim>::prepare()" << std::endl;
88#endif
89
90 /* Select geometry: */
91
92 {
93 bool initialized = false;
94 for (auto &it : geometry_list_)
95 if (it->name() == geometry_) {
96 selected_geometry_ = it;
97 initialized = true;
98 break;
99 }
100
101 AssertThrow(
102 initialized,
103 ExcMessage("Could not find a geometry description with name \"" +
104 geometry_ + "\""));
105 }
106
107 /* Set up Triangulation object: */
108
109 const auto smoothing =
110 dealii::Triangulation<dim>::limit_level_difference_at_vertices;
111
112 switch (mesh_type_) {
114 triangulation_ = std::make_unique<
115 dealii::parallel::fullydistributed::Triangulation<dim>>(
116 mpi_ensemble_.ensemble_communicator());
117 triangulation_->set_mesh_smoothing(smoothing);
118 } break;
119
121 const auto settings = dealii::parallel::distributed::Triangulation<
122 dim>::Settings::construct_multigrid_hierarchy;
123 triangulation_ =
124 std::make_unique<dealii::parallel::distributed::Triangulation<dim>>(
125 mpi_ensemble_.ensemble_communicator(), smoothing, settings);
126 } break;
127
129 const auto settings = static_cast<
130 typename dealii::parallel::shared::Triangulation<dim>::Settings>(
131 dealii::parallel::shared::Triangulation<dim>::partition_auto |
132 dealii::parallel::shared::Triangulation<
133 dim>::construct_multigrid_hierarchy);
134 /* Beware of the boolean: */
135 triangulation_ =
136 std::make_unique<dealii::parallel::shared::Triangulation<dim>>(
137 mpi_ensemble_.ensemble_communicator(),
138 smoothing,
139 /*artificial cells*/ true,
140 settings);
141 } break;
142
143 case MeshType::serial: {
144 AssertThrow(
145 mpi_ensemble_.n_ensemble_ranks() == 1,
146 ExcMessage(
147 "The serial triangulation can only be used for serial "
148 "computations. If you want to run simulations with more than one "
149 "rank per ensemble, then please set \"mesh type\" to one of the "
150 "parallel triangulations supported by deal.II"));
151
152 triangulation_ = std::make_unique<dealii::Triangulation<dim>>(smoothing);
153
154 } break;
155
156 default:
157 __builtin_trap();
158 }
159
160 /* Create and distribute mesh: */
161
162 auto &triangulation = *triangulation_;
163 selected_geometry_->create_coarse_triangulation(triangulation);
164
165 if (mesh_writeout_ && dealii::Utilities::MPI::this_mpi_process(
166 mpi_ensemble_.ensemble_communicator()) == 0) {
167#ifdef DEAL_II_GMSH_WITH_API
168 GridOut grid_out;
169 grid_out.write_msh(triangulation, base_name + "-coarse_grid.msh");
170#else
171 GridOut grid_out;
172 GridOutFlags::Msh flags(/* write faces */ true, /* write lines */ true);
173 grid_out.set_flags(flags);
174 std::ofstream file(base_name + "-coarse_grid.msh");
175 grid_out.write_msh(triangulation, file);
176#endif
177 }
178
179 triangulation.refine_global(refinement_);
180
181 if (std::abs(mesh_distortion_) > 1.0e-10)
182 GridTools::distort_random(
183 mesh_distortion_, triangulation, false, std::random_device()());
184
185 const auto fe_degree = polynomial_degree();
186 const auto mapping_degree = fe_degree;
187 const auto quadrature_degree = fe_degree + 1;
188
189 /*
190 * First, let the selected geometry populate our hp::*Collection
191 * objects. If the method returns standard_quarilaterls, or
192 * standard_simplices, however, we need to do the setup ourselves:
193 */
194
195 const auto collection_type =
196 selected_geometry_->populate_hp_collections(fe_degree, collection_);
197
198 switch (collection_type) {
200 /*
201 * The geometry already populated the hp::*Collections
202 */
203
204 Assert(collection_.mapping, dealii::ExcInternalError());
205 Assert(collection_.finite_element_cg, dealii::ExcInternalError());
206 Assert(collection_.finite_element_dg, dealii::ExcInternalError());
207 Assert(collection_.quadrature, dealii::ExcInternalError());
208 Assert(collection_.quadrature_high_order, dealii::ExcInternalError());
209 Assert(collection_.nodal_quadrature, dealii::ExcInternalError());
210 Assert(collection_.quadrature_1d, dealii::ExcInternalError());
211 Assert(collection_.nodal_quadrature_1d, dealii::ExcInternalError());
212 Assert(collection_.face_quadrature, dealii::ExcInternalError());
213 Assert(collection_.face_nodal_quadrature, dealii::ExcInternalError());
214 } break;
215
217 /*
218 * Populate all collections with appropriate objects for the cG Qk, dG
219 * Qk finite element on purely quadrilateral, or hexahedral meshes:
220 */
221
222 collection_.finite_element_cg =
223 std::make_unique<hp::FECollection<dim>>(FE_Q<dim>(fe_degree));
224 collection_.finite_element_dg =
225 std::make_unique<hp::FECollection<dim>>(FE_DGQ<dim>(fe_degree));
226
227 collection_.mapping =
228 std::make_unique<dealii::hp::MappingCollection<dim>>(
229 MappingQ<dim>(mapping_degree));
230
231 collection_.quadrature = std::make_unique<hp::QCollection<dim>>(
232 QGauss<dim>(quadrature_degree));
233 collection_.quadrature_high_order =
234 std::make_unique<hp::QCollection<dim>>(
235 QGauss<dim>(quadrature_degree + 1));
236 collection_.nodal_quadrature = std::make_unique<hp::QCollection<dim>>(
237 QGaussLobatto<dim>(quadrature_degree));
238 collection_.quadrature_1d =
239 std::make_unique<hp::QCollection<1>>(QGauss<1>(quadrature_degree));
240 collection_.nodal_quadrature_1d = std::make_unique<hp::QCollection<1>>(
241 QGaussLobatto<1>(quadrature_degree));
242 collection_.face_quadrature = std::make_unique<hp::QCollection<dim - 1>>(
243 QGauss<dim - 1>(quadrature_degree));
244 collection_.face_nodal_quadrature =
245 std::make_unique<hp::QCollection<dim - 1>>(
246 QGaussLobatto<dim - 1>(quadrature_degree));
247 } break;
248
250 /*
251 * Populate all collections with appropriate objects for the cG Pk, dG
252 * Pk finite element on purely quadrilateral, or hexahedral meshes:
253 */
254
255 collection_.finite_element_cg =
256 std::make_unique<hp::FECollection<dim>>(FE_SimplexP<dim>(fe_degree));
257 collection_.finite_element_dg = std::make_unique<hp::FECollection<dim>>(
258 FE_SimplexDGP<dim>(fe_degree));
259
260 if (mapping_degree == 1) {
261#if DEAL_II_VERSION_GTE(9, 7, 0)
262 collection_.mapping =
263 std::make_unique<hp::MappingCollection<dim>>(MappingP1<dim>());
264#else
265 collection_.mapping = std::make_unique<hp::MappingCollection<dim>>(
266 MappingFE<dim>(FE_SimplexP<dim>(fe_degree)));
267#endif
268 } else {
269 collection_.mapping = std::make_unique<hp::MappingCollection<dim>>(
270 MappingFE<dim>(FE_SimplexP<dim>(fe_degree)));
271 }
272
273 collection_.quadrature = std::make_unique<hp::QCollection<dim>>(
274 QGaussSimplex<dim>(quadrature_degree));
275 collection_.quadrature_high_order =
276 std::make_unique<hp::QCollection<dim>>(
277 QGaussSimplex<dim>(quadrature_degree + 1));
278#if DEAL_II_VERSION_GTE(9, 7, 0)
279 collection_.nodal_quadrature = std::make_unique<hp::QCollection<dim>>(
280 FETools::compute_nodal_quadrature(
281 FE_SimplexP<dim>(quadrature_degree)));
282#else
283 AssertThrow(false,
284 dealii::ExcMessage("Discretization: Simplex support requires "
285 "deal.II version 9.7.0 or newer"));
286
287#endif
288 collection_.quadrature_1d = std::make_unique<hp::QCollection<1>>(
289 QGaussSimplex<1>(quadrature_degree));
290#if DEAL_II_VERSION_GTE(9, 7, 0)
291 collection_.nodal_quadrature_1d = std::make_unique<hp::QCollection<1>>(
292 QGaussLobatto<1>(quadrature_degree));
293#endif
294 collection_.face_quadrature = std::make_unique<hp::QCollection<dim - 1>>(
295 QGaussSimplex<dim - 1>(quadrature_degree));
296 if constexpr (dim == 1) {
297 collection_.face_nodal_quadrature =
298 std::make_unique<hp::QCollection<dim - 1>>(
299 QGaussLobatto<dim - 1>(quadrature_degree));
300 } else {
301#if DEAL_II_VERSION_GTE(9, 7, 0)
302 collection_.face_nodal_quadrature =
303 std::make_unique<hp::QCollection<dim - 1>>(
304 FETools::compute_nodal_quadrature(
305 FE_SimplexP<dim - 1>(quadrature_degree)));
306#endif
307 }
308
309 return;
310 } break;
311 default:
312 __builtin_trap();
313 }
314 }
315
316} /* namespace ryujin */
Discretization(const MPIEnsemble &mpi_ensemble, const std::string &subsection="/Discretization")
void prepare(const std::string &base_name)