ryujin 2.5.0 revision c64172211cf21344cb9b9b0f3a1266aa6400d392
Loading...
Searching...
No Matches
geometry_rectangular_domain.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2022 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <ryujin/base/compile_time_options.h>
10
11#include <deal.II/base/function_parser.h>
12
13namespace ryujin
14{
15 namespace Geometries
16 {
42 template <int dim>
43 class RectangularDomain : public Geometry<dim>
44 {
45 public:
46 RectangularDomain(const std::string &name, const std::string &subsection)
47 : Geometry<dim>(name, subsection)
48 {
49 this->add_parameter("position bottom left",
51 "Position of bottom left corner");
52
53 for (unsigned int d = 0; d < dim; ++d)
54 point_right_[d] = 20.0;
55 this->add_parameter(
56 "position top right", point_right_, "Position of top right corner");
57
58 grading_push_forward_ = dim == 1 ? "x" : (dim == 2 ? "x;y" : "x;y;z;");
59 this->add_parameter("grading push forward",
61 "push forward of grading manifold");
62
64 this->add_parameter("grading pull back",
66 "pull back of grading manifold");
67
68 this->add_parameter(
69 "transformation",
71 "Optional forward transformation of the rectangular domain given "
72 "as a semicolon separated list of dim expressions in x, y, z. If "
73 "empty, no transformation is applied.");
74
84
85 this->add_parameter("subdivisions x",
87 "number of subdivisions in x direction");
88 this->add_parameter(
89 "boundary condition left",
91 "Type of boundary condition enforced on the left side of the "
92 "domain (faces with normal in negative x direction)");
93 this->add_parameter(
94 "boundary condition right",
96 "Type of boundary condition enforced on the right side of the "
97 "domain (faces with normal in positive x direction)");
98
99 if constexpr (dim >= 2) {
100 this->add_parameter("subdivisions y",
102 "number of subdivisions in y direction");
103 this->add_parameter(
104 "boundary condition bottom",
106 "Type of boundary condition enforced on the bottom side of the "
107 "domain (faces with normal in negative y direction)");
108 this->add_parameter(
109 "boundary condition top",
111 "Type of boundary condition enforced on the top side of the "
112 "domain (faces with normal in positive y direction)");
113 }
114
115 if constexpr (dim == 3) {
116 this->add_parameter("subdivisions z",
118 "number of subdivisions in z direction");
119 this->add_parameter(
120 "boundary condition back",
122 "Type of boundary condition enforced on the back side of the "
123 "domain (faces with normal in negative z direction)");
124 this->add_parameter(
125 "boundary condition front",
127 "Type of boundary condition enforced on the front side of the "
128 "domain (faces with normal in positive z direction)");
129 }
130
131 use_simplices_ = false;
132 this->add_parameter("simplex mesh",
134 "If set to true, the triangulation uses simplices "
135 "instead of quadrangles.");
136 }
137
138
139 RectangularDomain(const std::string subsection)
140 : RectangularDomain("rectangular domain", subsection)
141 {
142 }
143
144
146 dealii::Triangulation<dim> &triangulation) const override
147 {
148 /* create mesh: */
149
150 dealii::Triangulation<dim, dim> tria1;
151 tria1.set_mesh_smoothing(triangulation.get_mesh_smoothing());
152
153 if (use_simplices_) {
154 /* Mesh with simplices: */
155
156 if constexpr (dim == 1) {
157 dealii::GridGenerator::
158 subdivided_hyper_rectangle_with_simplices<dim, dim>(
160 } else if constexpr (dim == 2) {
161 dealii::GridGenerator::subdivided_hyper_rectangle_with_simplices(
162 tria1,
166 } else if constexpr (dim == 3) {
167 dealii::GridGenerator::subdivided_hyper_rectangle_with_simplices(
168 tria1,
172 }
173
174 } else {
175 /* Regular mesh with quadrilaterals/hexahedra: */
176
177 if constexpr (dim == 1) {
178 dealii::GridGenerator::subdivided_hyper_rectangle<dim, dim>(
180 } else if constexpr (dim == 2) {
181 dealii::GridGenerator::subdivided_hyper_rectangle(
182 tria1,
186 } else if constexpr (dim == 3) {
187 dealii::GridGenerator::subdivided_hyper_rectangle(
188 tria1,
192 }
193 }
194
195 triangulation.copy_triangulation(tria1);
196
197 /* create transformation: */
198
199 if (!transformation_expression_.empty()) {
200 AssertThrow(!use_simplices_,
201 dealii::ExcMessage(
202 "A transformation can only be used with a mesh "
203 "consisting of quadrilaterals or hexahedra."));
204
205 const auto transformation =
206 std::make_shared<dealii::FunctionParser<dim>>(
208 AssertThrow(transformation->n_components == dim,
209 dealii::ExcMessage(
210 "The transformation must consist of exactly dim "
211 "semicolon separated expressions."));
212
213 this->transformation_ =
214 [transformation](
215 const typename dealii::Triangulation<dim>::cell_iterator &,
216 const dealii::Point<dim> &point) {
217 dealii::Point<dim> result;
218 for (unsigned int d = 0; d < dim; ++d)
219 result[d] = transformation->value(point, d);
220 return result;
221 };
222 }
223
224 /* create grading: */
225
226 // FIXME: We should ideally check the push forward and pull back
227 // for compatiblity.
229 dealii::FunctionManifold<dim> grading(grading_push_forward_,
231 triangulation.set_all_manifold_ids(1);
232 triangulation.set_manifold(1, grading);
233 }
234
235 /* set boundary ids: */
236
237 for (auto cell : triangulation.active_cell_iterators()) {
238 for (auto f : cell->face_indices()) {
239 auto face = cell->face(f);
240 if (!face->at_boundary())
241 continue;
242 const auto position = face->center();
243
244 if (position[0] < point_left_[0] + 1.e-8)
245 face->set_boundary_id(boundary_left_);
246 if (position[0] > point_right_[0] - 1.e-8)
247 face->set_boundary_id(boundary_right_);
248
249 if constexpr (dim >= 2) {
250 if (position[1] < point_left_[1] + 1.e-8)
251 face->set_boundary_id(boundary_bottom_);
252 if (position[1] > point_right_[1] - 1.e-8)
253 face->set_boundary_id(boundary_top_);
254 }
255
256 if constexpr (dim == 3) {
257 if (position[2] < point_left_[2] + 1.e-8)
258 face->set_boundary_id(boundary_back_);
259 if (position[2] > point_right_[2] - 1.e-8)
260 face->set_boundary_id(boundary_front_);
261 }
262 } /*for*/
263 } /*for*/
264
265 std::vector<int> directions;
266
269 AssertThrow(boundary_left_ == boundary_right_,
270 dealii::ExcMessage(
271 "For prescribing periodic boundaries in x-direction, "
272 "both, the left and right boundary conditions must "
273 "be set to periodic"));
274 directions.push_back(0);
275 }
276
277 if (dim >= 2 && (boundary_bottom_ == Boundary::periodic ||
279 AssertThrow(boundary_bottom_ == boundary_top_,
280 dealii::ExcMessage(
281 "For prescribing periodic boundaries in y-direction, "
282 "both, the bottom and top boundary conditions must "
283 "be set to periodic"));
284 directions.push_back(1);
285 }
286
287 if (dim == 3 && (boundary_back_ == Boundary::periodic ||
289 AssertThrow(boundary_back_ == boundary_front_,
290 dealii::ExcMessage(
291 "For prescribing periodic boundaries in z-direction, "
292 "both, the back and front boundary conditions must "
293 "be set to periodic"));
294 directions.push_back(2);
295 }
296
297#ifndef BUG_COLLECT_PERIODIC_FACES_INSTANTIATION
298 if (!directions.empty()) {
299 std::vector<dealii::GridTools::PeriodicFacePair<
300 typename dealii::Triangulation<dim>::cell_iterator>>
301 periodic_faces;
302
303 for (const auto direction : directions)
304 dealii::GridTools::collect_periodic_faces(
305 triangulation,
306 /*b_id */ Boundary::periodic,
307 /*direction*/ direction,
308 periodic_faces);
309
310 triangulation.add_periodicity(periodic_faces);
311 }
312#endif
313 }
314
315
317 populate_hp_collections(const unsigned int /*fe_degree*/,
319 & /*collection*/) const override
320 {
321 if (use_simplices_) {
323 } else {
325 }
326 }
327
328
329 protected:
330 dealii::Point<dim> point_left_;
331 dealii::Point<dim> point_right_;
332
333 unsigned int subdivisions_x_;
334 unsigned int subdivisions_y_;
335 unsigned int subdivisions_z_;
336
339
341
348
350 };
351 } // namespace Geometries
352} // namespace ryujin
Geometry< dim >::HP_Collection populate_hp_collections(const unsigned int, typename ryujin::Discretization< dim >::Collection &) const override
RectangularDomain(const std::string &name, const std::string &subsection)
void create_coarse_triangulation(dealii::Triangulation< dim > &triangulation) const override
std::function< dealii::Point< dim >(const typename dealii::Triangulation< dim >::cell_iterator &, const dealii::Point< dim > &)> transformation_
Definition geometry.h:136