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