22 template <
int dim,
typename Callable>
32 pull_back(
const dealii::Point<dim> &space_point)
const final
34 auto chart_point = space_point;
36 if constexpr (dim >= 2) {
38 chart_point[dim - 1] -= callable_(space_point);
47 auto space_point = chart_point;
49 if constexpr (dim >= 2) {
51 space_point[dim - 1] += callable_(space_point);
57 std::unique_ptr<dealii::Manifold<dim, dim>>
clone() const final
59 return std::make_unique<ProfileManifold<dim, Callable>>(callable_);
63 const Callable callable_;
67 template <
int dim,
typename Callable>
68 ProfileManifold<dim, Callable>
83 :
Geometry<dim>(
"geotiff profile", subsection)
84 , geotiff_reader_(subsection +
"/geotiff profile")
86 this->add_parameter(
"position bottom left",
88 "Position of bottom left corner");
90 for (
unsigned int d = 0; d < dim; ++d)
91 point_right_[d] = 20.0;
93 "position top right", point_right_,
"Position of top right corner");
105 this->add_parameter(
"subdivisions x",
107 "number of subdivisions in x direction");
109 "boundary condition left",
111 "Type of boundary condition enforced on the left side of the "
112 "domain (faces with normal in negative x direction)");
114 "boundary condition right",
116 "Type of boundary condition enforced on the right side of the "
117 "domain (faces with normal in positive x direction)");
119 if constexpr (dim >= 2) {
120 this->add_parameter(
"subdivisions y",
122 "number of subdivisions in y direction");
124 "boundary condition bottom",
126 "Type of boundary condition enforced on the bottom side of the "
127 "domain (faces with normal in negative y direction)");
129 "boundary condition top",
131 "Type of boundary condition enforced on the top side of the "
132 "domain (faces with normal in positive y direction)");
135 if constexpr (dim == 2) {
136 reference_y_coordinate_ = 0.;
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)");
145 if constexpr (dim == 3) {
146 this->add_parameter(
"subdivisions z",
148 "number of subdivisions in z direction");
150 "boundary condition back",
152 "Type of boundary condition enforced on the back side of the "
153 "domain (faces with normal in negative z direction)");
155 "boundary condition front",
157 "Type of boundary condition enforced on the front side of the "
158 "domain (faces with normal in positive z direction)");
168 dealii::Triangulation<dim, dim> tria1;
169 tria1.set_mesh_smoothing(triangulation.get_mesh_smoothing());
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(
177 {subdivisions_x_, subdivisions_y_},
180 }
else if constexpr (dim == 3) {
181 dealii::GridGenerator::subdivided_hyper_rectangle(
183 {subdivisions_x_, subdivisions_y_, subdivisions_z_},
188 triangulation.copy_triangulation(tria1);
189 triangulation.reset_all_manifolds();
191 triangulation.set_all_manifold_ids(0);
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())
200 const auto position = face->center();
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);
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);
213 if constexpr (dim == 2) {
214 if (position[1] < point_left_[1] + 1.e-8) {
215 face->set_boundary_id(boundary_bottom_);
217 face->set_manifold_id(1);
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);
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);
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);
242 if (position[2] < point_left_[2] + 1.e-8) {
243 face->set_boundary_id(boundary_back_);
245 face->set_manifold_id(1);
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);
257 make_profile_manifold<dim>([&](dealii::Point<dim> point) {
261 if constexpr (dim == 1) {
263 }
else if constexpr (dim == 2) {
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);
274 triangulation.set_manifold(1, profile);
276 dealii::TransfiniteInterpolationManifold<dim> transfinite_interpolation;
277 transfinite_interpolation.initialize(triangulation);
278 triangulation.set_manifold(0, transfinite_interpolation);
284 dealii::Point<dim> point_left_;
285 dealii::Point<dim> point_right_;
287 double reference_y_coordinate_;
289 unsigned int subdivisions_x_;
290 unsigned int subdivisions_y_;
291 unsigned int subdivisions_z_;
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
ProfileManifold(const Callable &callable)
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
ProfileManifold< dim, Callable > make_profile_manifold(const Callable &callable)