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