ryujin 2.5.0 revision c64172211cf21344cb9b9b0f3a1266aa6400d392
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 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <ryujin/base/compile_time_options.h>
12
13#include <deal.II/base/quadrature_lib.h>
14#include <deal.II/distributed/fully_distributed_tria.h>
15#include <deal.II/distributed/tria.h>
16#include <deal.II/fe/fe_dgq.h>
17#include <deal.II/fe/fe_q.h>
18#include <deal.II/fe/fe_simplex_p.h>
19#include <deal.II/fe/fe_tools.h>
20#include <deal.II/fe/mapping_fe.h>
21#include <deal.II/fe/mapping_q.h>
22
23namespace ryujin
24{
25 namespace Geometries
26 {
40 template <int dim>
42 {
43 public:
44 GeoTIFFProfile(const std::string &subsection)
45 : RectangularDomain<dim>("geotiff profile", subsection)
46 , geotiff_reader_(subsection + "/geotiff profile/geotiff")
47 , mesh_alignment_(subsection + "/geotiff profile/mesh alignment")
48 {
49 reference_y_coordinate_ = 0.;
50 this->add_parameter(
51 "reference y coordinate",
52 reference_y_coordinate_,
53 "GeoTIFF: select the value for y-coordinate in 2D. That is, the "
54 "1D profile for the lower boundary is queried from the 2D "
55 "geotiff image at coordinates (x, y=constant)");
56
57 refinement_ = 0;
58 this->add_parameter("refinement",
59 refinement_,
60 "number of global refinement steps applied to the "
61 "coarse mesh before aligning it with the elevation "
62 "profile");
63 }
64
65
67 dealii::Triangulation<dim> &triangulation) const final
68 {
69 AssertThrow(
70 dim == 2,
71 dealii::ExcMessage(
72 "The geotiff profile ng geometry is only implemented in 2D."));
73
74 /*
75 * The mesh is refined and aligned on a temporary triangulation (a
76 * parallel::distributed one for a fully distributed triangulation)
77 * from which the cut cell decomposition creates the triangulation:
78 */
79 using Base = dealii::parallel::TriangulationBase<dim>;
80 using FD = dealii::parallel::fullydistributed::Triangulation<dim>;
81 const auto distributed = dynamic_cast<const Base *>(&triangulation);
82 const auto fully_distributed = dynamic_cast<const FD *>(&triangulation);
83 AssertThrow(
84 fully_distributed != nullptr || distributed == nullptr,
85 dealii::ExcMessage("The geotiff profile ng geometry only supports "
86 "serial and fully distributed triangulations."));
87
88 if constexpr (dim == 2) {
89 std::unique_ptr<dealii::Triangulation<dim>> temporary;
90 if (fully_distributed != nullptr)
91#if DEAL_II_VERSION_GTE(9, 7, 0)
92 temporary =
93 std::make_unique<FD>(triangulation.get_mpi_communicator());
94#else
95 temporary = std::make_unique<FD>(triangulation.get_communicator());
96#endif
97 else
98 temporary = std::make_unique<dealii::Triangulation<dim>>();
99
101 temporary->refine_global(refinement_);
102
103 /*
104 * The 1D profile is extracted from the geotiff image along the
105 * line y = reference_y_coordinate_:
106 */
107
108 const auto height = [&](const dealii::Point<dim> &vertex) {
109 return geotiff_reader_.compute_height(
110 dealii::Point<2>(vertex[0], reference_y_coordinate_));
111 };
112
113 mesh_alignment_.align_with_elevation_profile(*temporary, height);
114
115 cut_cell_decomposition_.create_triangulation(
116 triangulation, *temporary, height, this->boundary_bottom_);
117
118 } else {
119
120 __builtin_trap();
121 }
122 }
123
124
125 void update_dof_handler(dealii::DoFHandler<dim> &dof_handler) const final
126 {
127 /* Select the simplex finite element (index 1) on all triangles: */
128 for (const auto &cell : dof_handler.active_cell_iterators())
129 if (cell->is_locally_owned() && cell->reference_cell().is_simplex())
130 cell->set_active_fe_index(1);
131 }
132
133
135 populate_hp_collections(const unsigned int fe_degree,
137 &collection) const final
138 {
139 using namespace dealii;
140
141 /*
142 * Every collection has the cG Qk / dG Qk finite element for
143 * quadrilaterals at index 0 and the cG Pk / dG Pk finite element
144 * for the triangles created by the cut cell decomposition at index
145 * 1:
146 */
147
148 if constexpr (dim == 2) {
149 const auto mapping_degree = fe_degree;
150 const auto quadrature_degree = fe_degree + 1;
151
152 const auto make = [](auto collection,
153 const auto &quadrilateral,
154 const auto &triangle) {
155 collection.push_back(quadrilateral);
156 collection.push_back(triangle);
157 return std::make_unique<decltype(collection)>(
158 std::move(collection));
159 };
160
161 collection.finite_element_cg = make(hp::FECollection<dim>(),
162 FE_Q<dim>(fe_degree),
163 FE_SimplexP<dim>(fe_degree));
164 collection.finite_element_dg = make(hp::FECollection<dim>(),
165 FE_DGQ<dim>(fe_degree),
166 FE_SimplexDGP<dim>(fe_degree));
167
168 collection.mapping =
169 make(hp::MappingCollection<dim>(),
170 MappingQ<dim>(mapping_degree),
171 MappingFE<dim>(FE_SimplexP<dim>(mapping_degree)));
172
173 collection.quadrature = make(hp::QCollection<dim>(),
174 QGauss<dim>(quadrature_degree),
175 QGaussSimplex<dim>(quadrature_degree));
176 collection.quadrature_high_order =
177 make(hp::QCollection<dim>(),
178 QGauss<dim>(quadrature_degree + 1),
179 QGaussSimplex<dim>(quadrature_degree + 1));
180 collection.nodal_quadrature =
181 make(hp::QCollection<dim>(),
182 QGaussLobatto<dim>(quadrature_degree),
183 FETools::compute_nodal_quadrature(
184 FE_SimplexP<dim>(quadrature_degree)));
185
186 collection.quadrature_1d = make(hp::QCollection<1>(),
187 QGauss<1>(quadrature_degree),
188 QGaussSimplex<1>(quadrature_degree));
189 collection.nodal_quadrature_1d =
190 make(hp::QCollection<1>(),
191 QGaussLobatto<1>(quadrature_degree),
192 QGaussLobatto<1>(quadrature_degree));
193
194 /* One face quadrature collection per finite element: */
195 using QCF = hp::QCollection<dim - 1>;
196 collection.face_quadrature =
197 make(std::vector<QCF>(),
198 QCF(QGauss<dim - 1>(quadrature_degree)),
199 QCF(QGaussSimplex<dim - 1>(quadrature_degree)));
200 collection.face_nodal_quadrature =
201 make(std::vector<QCF>(),
202 QCF(QGaussLobatto<dim - 1>(quadrature_degree)),
203 QCF(QGaussLobatto<dim - 1>(quadrature_degree)));
204
205 } else {
206
207 __builtin_trap();
208 }
209
211 }
212
213 private:
214 GeoTIFFReader geotiff_reader_;
215 MeshAlignment<dim> mesh_alignment_;
216 CutCellDecomposition<dim> cut_cell_decomposition_;
217
218 double reference_y_coordinate_;
219 unsigned int refinement_;
220 };
221
222 } // namespace Geometries
223} // namespace ryujin
DEAL_II_ALWAYS_INLINE double compute_height(const dealii::Point< dim > &point) const
Geometry< dim >::HP_Collection populate_hp_collections(const unsigned int fe_degree, typename ryujin::Discretization< dim >::Collection &collection) const final
void update_dof_handler(dealii::DoFHandler< dim > &dof_handler) const final
void create_coarse_triangulation(dealii::Triangulation< dim > &triangulation) const final
GeoTIFFProfile(const std::string &subsection)
void create_coarse_triangulation(dealii::Triangulation< dim > &triangulation) const override