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