ryujin 2.5.0 revision c64172211cf21344cb9b9b0f3a1266aa6400d392
Loading...
Searching...
No Matches
geometry_two_tanks.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2025 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <ryujin/base/compile_time_options.h>
10
11namespace ryujin
12{
13 namespace GridGenerator
14 {
33 template <int dim, int spacedim, template <int, int> class Triangulation>
34 void twotanks(Triangulation<dim, spacedim> &,
35 const double /*tank_length*/,
36 const double /*tank_width*/,
37 const double /*tunnel_length*/,
38 const double /*tunnel_width*/,
39 const unsigned int /*subdivisions_factor*/)
40 {
41 AssertThrow(false, dealii::ExcNotImplemented());
42 __builtin_trap();
43 }
44
45
46#ifndef DOXYGEN
47 template <template <int, int> class Triangulation>
48 void twotanks(Triangulation<2, 2> &triangulation,
49 const double tank_length,
50 const double tank_width,
51 const double tunnel_length,
52 const double tunnel_width,
53 const unsigned int subdivisions_factor)
54 {
55 using namespace dealii;
56
57 dealii::Triangulation<2, 2> res1, res2, res3, tank1, tank2, tunnel, final;
58
59 const double tolerance = 1.e-8;
60
61 Assert(
62 tank_width - tunnel_width > tolerance,
63 dealii::ExcMessage(
64 " !!! The tank width must be larger than the tunnel width !!!"));
65
66 /* We split the tank into three triangulations and subdivide to
67 * get somewhat close to uniform refinement */
68
69 const double diff = (tank_width - tunnel_width) / 2.;
70 unsigned int sub_x =
71 static_cast<int>(std::round(tank_length * subdivisions_factor));
72 unsigned int sub_y =
73 static_cast<int>(std::round(diff * subdivisions_factor));
74
75 GridGenerator::subdivided_hyper_rectangle(
76 res1,
77 {sub_x, sub_y},
78 Point<2>(-tank_length, -tank_width / 2.),
79 Point<2>(0, -tunnel_width / 2.));
80
81 GridGenerator::subdivided_hyper_rectangle(
82 res3,
83 {sub_x, sub_y},
84 Point<2>(-tank_length, tunnel_width / 2.),
85 Point<2>(0, tank_width / 2.));
86
87 sub_y = static_cast<int>(std::round(tunnel_width * subdivisions_factor));
88
89 GridGenerator::subdivided_hyper_rectangle(
90 res2,
91 {sub_x, sub_y},
92 Point<2>(-tank_length, -tunnel_width / 2.),
93 Point<2>(0, tunnel_width / 2.));
94
95 // We create tank1 by merging the three triangulations above
96 tank1.set_mesh_smoothing(triangulation.get_mesh_smoothing());
97 GridGenerator::merge_triangulations(
98 {&res1, &res2, &res3}, tank1, tolerance);
99
100 // We now create the second tank (tank2) by copying the above and shifting
101 tank2.copy_triangulation(tank1);
102 dealii::Point<2> shift_vector(tunnel_length + tank_length, 0.);
103 dealii::GridTools::shift(shift_vector, tank2);
104
105 // We now create the tunnel
106 sub_x = static_cast<int>(std::round(tunnel_length * subdivisions_factor));
107
108 GridGenerator::subdivided_hyper_rectangle(
109 tunnel,
110 {sub_x, sub_y},
111 Point<2>(0., -tunnel_width / 2.),
112 Point<2>(tunnel_length, tunnel_width / 2.));
113
114
115 // We now merge the two tanks and the tunnel
116 final.set_mesh_smoothing(triangulation.get_mesh_smoothing());
117 GridGenerator::merge_triangulations(
118 {&tank1, &tunnel, &tank2}, final, tolerance);
119
120
121 // Finally, copy the "final" triangulation to "triangulation"
122 triangulation.copy_triangulation(final);
123
124 /*
125 * Set boundary ids:
126 */
127
128 for (auto cell : triangulation.active_cell_iterators()) {
129 for (auto f : cell->face_indices()) {
130 const auto face = cell->face(f);
131
132 if (!face->at_boundary())
133 continue;
134
135 /*
136 * We want slip everywhere except the left/right edges of tanks.
137 */
138
139 face->set_boundary_id(Boundary::slip);
140
141 const auto center = face->center();
142 if (center[0] > tank_length + tunnel_length - tolerance)
143 face->set_boundary_id(Boundary::dynamic);
144
145 if (center[0] < -tank_length + tolerance)
146 face->set_boundary_id(Boundary::dynamic);
147
148 } /*f*/
149 } /*cell*/
150 }
151#endif
152 } // namespace GridGenerator
153
154
155 namespace Geometries
156 {
162 template <int dim>
163 class TwoTanks : public Geometry<dim>
164 {
165 public:
166 TwoTanks(const std::string &subsection)
167 : Geometry<dim>("two tanks", subsection)
168 {
169 tank_length_ = 100.;
170 this->add_parameter(
171 "tank length", tank_length_, "length of tanks [units]");
172
173 tank_width_ = 100.;
174 this->add_parameter("tank width", tank_width_, "width of tank [units]");
175
176 tunnel_length_ = 10.;
177 this->add_parameter(
178 "tunnel length", tunnel_length_, "length of tunnel [units]");
179
180 tunnel_width_ = 50.;
181 this->add_parameter(
182 "tunnel width", tunnel_width_, "width of tunnel [units]");
183
184 // if you divide the default values by 100, make this number 100
185 subdivisions_factor_ = 1;
186 this->add_parameter("subdivisions factor",
187 subdivisions_factor_,
188 "A number used for introducing subdivions in both "
189 "x-y direction. Useful when dealing with "
190 "measurements that are less than 1. ");
191 }
192
194 dealii::Triangulation<dim> &triangulation) const final
195 {
196 GridGenerator::twotanks(triangulation,
197 tank_length_,
198 tank_width_,
199 tunnel_length_,
200 tunnel_width_,
201 subdivisions_factor_);
202 }
203
204 private:
205 double tank_length_;
206 double tank_width_;
207 double tunnel_length_;
208 double tunnel_width_;
209
210 unsigned int subdivisions_factor_;
211 };
212 } // namespace Geometries
213} // namespace ryujin
TwoTanks(const std::string &subsection)
void create_coarse_triangulation(dealii::Triangulation< dim > &triangulation) const final
void twotanks(Triangulation< dim, spacedim > &, const double, const double, const double, const double, const unsigned int)