ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
geometry_geotiff_profile.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2022 - 2025 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
9
11#include "geotiff_reader.h"
12
13namespace ryujin
14{
15 namespace Geometries
16 {
26 template <int dim, typename Callable>
27 class ProfileManifold : public dealii::ChartManifold<dim>
28 {
29 public:
30 ProfileManifold(const Callable &callable)
31 : callable_(callable)
32 {
33 }
34
35 dealii::Point<dim>
36 pull_back(const dealii::Point<dim> &space_point) const final
37 {
38 auto chart_point = space_point;
39
40 if constexpr (dim >= 2) {
41 /* transform y-direction (2D) or z-direction (3D): */
42 chart_point[dim - 1] -= callable_(space_point);
43 }
44
45 return chart_point;
46 }
47
48 dealii::Point<dim>
49 push_forward(const dealii::Point<dim> &chart_point) const final
50 {
51 auto space_point = chart_point;
52
53 if constexpr (dim >= 2) {
54 /* transform y-direction (2D) or z-direction (3D): */
55 space_point[dim - 1] += callable_(space_point);
56 }
57
58 return space_point;
59 }
60
61 std::unique_ptr<dealii::Manifold<dim, dim>> clone() const final
62 {
63 return std::make_unique<ProfileManifold<dim, Callable>>(callable_);
64 }
65
66 private:
67 const Callable callable_;
68 };
69
70
71 template <int dim, typename Callable>
72 ProfileManifold<dim, Callable>
73 make_profile_manifold(const Callable &callable)
74 {
75 return {callable};
76 }
77
78
82 template <int dim>
83 class GeoTIFFProfile : public Geometry<dim>
84 {
85 public:
86 GeoTIFFProfile(const std::string &subsection)
87 : Geometry<dim>("geotiff profile", subsection)
88 , geotiff_reader_(subsection + "/geotiff profile")
89 {
90 this->add_parameter("position bottom left",
91 point_left_,
92 "Position of bottom left corner");
93
94 for (unsigned int d = 0; d < dim; ++d)
95 point_right_[d] = 20.0;
96 this->add_parameter(
97 "position top right", point_right_, "Position of top right corner");
98
99 subdivisions_x_ = 1;
100 subdivisions_y_ = 1;
101 subdivisions_z_ = 1;
102 boundary_back_ = Boundary::dirichlet;
103 boundary_bottom_ = Boundary::dirichlet;
104 boundary_front_ = Boundary::dirichlet;
105 boundary_left_ = Boundary::dirichlet;
106 boundary_right_ = Boundary::dirichlet;
107 boundary_top_ = Boundary::dirichlet;
108
109 this->add_parameter("subdivisions x",
110 subdivisions_x_,
111 "number of subdivisions in x direction");
112 this->add_parameter(
113 "boundary condition left",
114 boundary_left_,
115 "Type of boundary condition enforced on the left side of the "
116 "domain (faces with normal in negative x direction)");
117 this->add_parameter(
118 "boundary condition right",
119 boundary_right_,
120 "Type of boundary condition enforced on the right side of the "
121 "domain (faces with normal in positive x direction)");
122
123 if constexpr (dim >= 2) {
124 this->add_parameter("subdivisions y",
125 subdivisions_y_,
126 "number of subdivisions in y direction");
127 this->add_parameter(
128 "boundary condition bottom",
129 boundary_bottom_,
130 "Type of boundary condition enforced on the bottom side of the "
131 "domain (faces with normal in negative y direction)");
132 this->add_parameter(
133 "boundary condition top",
134 boundary_top_,
135 "Type of boundary condition enforced on the top side of the "
136 "domain (faces with normal in positive y direction)");
137 }
138
139 if constexpr (dim == 2) {
140 reference_y_coordinate_ = 0.;
141 this->add_parameter(
142 "reference y coordinate",
143 reference_y_coordinate_,
144 "GeoTIFF: select the value for y-coordinate in 2D. That is, the "
145 "1D profile for the lower boundary is queried from the 2D "
146 "geotiff image at coordinates (x, y=constant)");
147 }
148
149 if constexpr (dim == 3) {
150 this->add_parameter("subdivisions z",
151 subdivisions_z_,
152 "number of subdivisions in z direction");
153 this->add_parameter(
154 "boundary condition back",
155 boundary_back_,
156 "Type of boundary condition enforced on the back side of the "
157 "domain (faces with normal in negative z direction)");
158 this->add_parameter(
159 "boundary condition front",
160 boundary_front_,
161 "Type of boundary condition enforced on the front side of the "
162 "domain (faces with normal in positive z direction)");
163 }
164 }
165
166
168 dealii::Triangulation<dim> &triangulation) const final
169 {
170 /* create mesh: */
171
172 dealii::Triangulation<dim, dim> tria1;
173 tria1.set_mesh_smoothing(triangulation.get_mesh_smoothing());
174
175 if constexpr (dim == 1) {
176 dealii::GridGenerator::subdivided_hyper_rectangle<dim, dim>(
177 tria1, {subdivisions_x_}, point_left_, point_right_);
178 } else if constexpr (dim == 2) {
179 dealii::GridGenerator::subdivided_hyper_rectangle(
180 tria1,
181 {subdivisions_x_, subdivisions_y_},
182 point_left_,
183 point_right_);
184 } else if constexpr (dim == 3) {
185 dealii::GridGenerator::subdivided_hyper_rectangle(
186 tria1,
187 {subdivisions_x_, subdivisions_y_, subdivisions_z_},
188 point_left_,
189 point_right_);
190 }
191
192 triangulation.copy_triangulation(tria1);
193 triangulation.reset_all_manifolds();
194 /* manifold id 0 for transfinite interpolation manifold */
195 triangulation.set_all_manifold_ids(0);
196
197 /* set boundary and manifold ids: */
198
199 for (auto cell : triangulation.active_cell_iterators()) {
200 for (auto f : cell->face_indices()) {
201 auto face = cell->face(f);
202 if (!face->at_boundary())
203 continue;
204 const auto position = face->center();
205
206 if (position[0] < point_left_[0] + 1.e-8) {
207 face->set_boundary_id(boundary_left_);
208 face->set_manifold_id(dealii::numbers::flat_manifold_id);
209 }
210
211 if (position[0] > point_right_[0] - 1.e-8) {
212 face->set_boundary_id(boundary_right_);
213 face->set_manifold_id(dealii::numbers::flat_manifold_id);
214 }
215
216
217 if constexpr (dim == 2) {
218 if (position[1] < point_left_[1] + 1.e-8) {
219 face->set_boundary_id(boundary_bottom_);
220 /* manifold id 1 for ProfileManifold: */
221 face->set_manifold_id(1);
222 }
223 if (position[1] > point_right_[1] - 1.e-8) {
224 face->set_boundary_id(boundary_top_);
225 face->set_manifold_id(dealii::numbers::flat_manifold_id);
226 }
227 }
228
229 if constexpr (dim == 3) {
230 if (position[1] < point_left_[1] + 1.e-8) {
231 face->set_boundary_id(boundary_bottom_);
232 face->set_manifold_id(dealii::numbers::flat_manifold_id);
233 }
234
235 if (position[1] > point_right_[1] - 1.e-8) {
236 face->set_boundary_id(boundary_top_);
237 face->set_manifold_id(dealii::numbers::flat_manifold_id);
238 }
239
240 /*
241 * The lower boundary at z = point_left_[2] is the profile
242 * manifold ant the upper boundary boundary at z =
243 * point_right_[2] is flat:
244 */
245
246 if (position[2] < point_left_[2] + 1.e-8) {
247 face->set_boundary_id(boundary_back_);
248 /* manifold id 1 for ProfileManifold: */
249 face->set_manifold_id(1);
250 }
251
252 if (position[2] > point_right_[2] - 1.e-8) {
253 face->set_boundary_id(boundary_front_);
254 face->set_manifold_id(dealii::numbers::flat_manifold_id);
255 }
256 }
257 } /*for*/
258 } /*for*/
259
260 const auto profile =
261 make_profile_manifold<dim>([&](dealii::Point<dim> point) {
262 /*
263 *
264 */
265 if constexpr (dim == 1) {
266 return 0.;
267 } else if constexpr (dim == 2) {
268 /*
269 * Set the second coordinate to a constant when querying
270 * height information in 2D.
271 */
272 point[1] = reference_y_coordinate_;
273 return geotiff_reader_.compute_height(point);
274 } else if constexpr (dim == 3) {
275 return geotiff_reader_.compute_height(point);
276 }
277 });
278 triangulation.set_manifold(1, profile);
279
280 dealii::TransfiniteInterpolationManifold<dim> transfinite_interpolation;
281 transfinite_interpolation.initialize(triangulation);
282 triangulation.set_manifold(0, transfinite_interpolation);
283 }
284
285 private:
286 GeoTIFFReader geotiff_reader_;
287
288 dealii::Point<dim> point_left_;
289 dealii::Point<dim> point_right_;
290
291 double reference_y_coordinate_;
292
293 unsigned int subdivisions_x_;
294 unsigned int subdivisions_y_;
295 unsigned int subdivisions_z_;
296
297 Boundary boundary_back_;
298 Boundary boundary_bottom_;
299 Boundary boundary_front_;
300 Boundary boundary_left_;
301 Boundary boundary_right_;
302 Boundary boundary_top_;
303 };
304 } /* namespace Geometries */
305} /* namespace ryujin */
DEAL_II_ALWAYS_INLINE double compute_height(const dealii::Point< dim > &point) const
void create_coarse_triangulation(dealii::Triangulation< dim > &triangulation) const final
GeoTIFFProfile(const std::string &subsection)
dealii::Point< dim > pull_back(const dealii::Point< dim > &space_point) const final
dealii::Point< dim > push_forward(const dealii::Point< dim > &chart_point) const final
std::unique_ptr< dealii::Manifold< dim, dim > > clone() const final
ProfileManifold< dim, Callable > make_profile_manifold(const Callable &callable)