deal.II version GIT relicensing-6960-g70e9c5b7be 2026-10-22 20:10:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
qprojector.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2020 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
17
20
21#include <boost/container/small_vector.hpp>
22
23
25
26
27namespace internal
28{
29 namespace QProjector
30 {
31 namespace
32 {
59 template <int dim>
60 void
61 append_subobject_rule(
62 const ReferenceCell<dim - 1> &face_reference_cell,
63 const Quadrature<dim - 1> &quadrature,
66 ReferenceCells::max_n_vertices<dim - 1>()> &vertices,
67 const double measure,
68 const types::geometric_orientation combined_orientation,
69 std::vector<Point<dim>> &points,
70 std::vector<double> &weights)
71 {
72 AssertDimension(points.size(), weights.size());
73 points.reserve(points.size() + quadrature.size());
74 weights.reserve(weights.size() + quadrature.size());
75
76 const auto support_points =
77 face_reference_cell.permute_by_combined_orientation(
78 ArrayView<const Point<dim>>(vertices),
79 face_reference_cell.get_inverse_combined_orientation(
80 combined_orientation));
81 for (unsigned int j = 0; j < quadrature.size(); ++j)
82 {
83 Point<dim> mapped_point;
84
85 // map reference quadrature point
86 for (const unsigned int vertex_no :
87 face_reference_cell.vertex_indices())
88 mapped_point +=
89 support_points[vertex_no] *
90 face_reference_cell.d_linear_shape_function(quadrature.point(j),
91 vertex_no);
92
93 points.push_back(mapped_point);
94
95 // rescale quadrature weights so that the sum of the weights on
96 // each face equals the measure of that face.
97 weights.push_back(quadrature.weight(j) * measure /
98 face_reference_cell.volume());
99 }
100 }
101 } // namespace
102 } // namespace QProjector
103} // namespace internal
104
105
106
107template <int dim>
110 const ReferenceCell<dim> &reference_cell,
111 const Quadrature<dim - 1> &quadrature,
112 const unsigned int face_no,
113 const types::geometric_orientation combined_orientation)
114{
115 AssertIndexRange(face_no, reference_cell.n_faces());
116 AssertIndexRange(combined_orientation,
117 reference_cell.n_face_orientations(face_no));
118 AssertDimension(reference_cell.get_dimension(), dim);
119
120 std::vector<Point<dim>> points;
121 std::vector<double> weights;
122
123 const ReferenceCell face_reference_cell =
124 reference_cell.face_reference_cell(face_no);
127 face_vertices(face_reference_cell.n_vertices());
128 for (const unsigned int vertex_no : face_reference_cell.vertex_indices())
129 face_vertices[vertex_no] =
130 reference_cell.face_vertex_location(face_no, vertex_no);
131 internal::QProjector::append_subobject_rule(face_reference_cell,
132 quadrature,
133 face_vertices,
134 reference_cell.face_measure(
135 face_no),
136 combined_orientation,
137 points,
138 weights);
139
140 return Quadrature<dim>(std::move(points), std::move(weights));
141}
142
143
144
145template <int dim>
148 const ReferenceCell<dim> &reference_cell,
149 const SubQuadrature &quadrature,
150 const unsigned int face_no,
151 const unsigned int subface_no,
152 const types::geometric_orientation combined_orientation,
153 const RefinementCase<dim - 1> &ref_case)
154{
155 AssertIndexRange(face_no, reference_cell.n_faces());
156 AssertIndexRange(combined_orientation,
157 reference_cell.n_face_orientations(face_no));
158 AssertDimension(reference_cell.get_dimension(), dim);
159 if (dim > 1)
160 AssertIndexRange(subface_no,
161 reference_cell.face_reference_cell(face_no).n_children(
162 ref_case));
163 if (dim == 1)
164 AssertDimension(quadrature.size(), 1);
165
166 std::vector<Point<dim>> points;
167 std::vector<double> weights;
170 vertices;
171 for (const unsigned int subface_vertex_no :
172 reference_cell.face_reference_cell(face_no).vertex_indices())
173 vertices.push_back(reference_cell.subface_vertex_location(
174 face_no, subface_no, subface_vertex_no, ref_case));
175 internal::QProjector::append_subobject_rule(
176 reference_cell.face_reference_cell(face_no),
177 quadrature,
178 vertices,
179 reference_cell.face_measure(face_no),
180 combined_orientation,
181 points,
182 weights);
183
184 return Quadrature<dim>(std::move(points), std::move(weights));
185}
186
187
188
189template <int dim>
192 const ReferenceCell<dim> &reference_cell,
193 const hp::QCollection<dim - 1> &quadrature)
194{
195 std::size_t n_points = 0;
196 for (const unsigned int face_no : reference_cell.face_indices())
197 n_points += quadrature[quadrature.size() == 1 ? 0 : face_no].size() *
198 reference_cell.n_face_orientations(face_no);
199
200 std::vector<Point<dim>> points;
201 std::vector<double> weights;
202 points.reserve(n_points);
203 weights.reserve(n_points);
204
205 for (const unsigned int face_no : reference_cell.face_indices())
206 {
207 const ReferenceCell face_reference_cell =
208 reference_cell.face_reference_cell(face_no);
211 face_vertices(face_reference_cell.n_vertices());
212 for (const unsigned int vertex_no : face_reference_cell.vertex_indices())
213 face_vertices[vertex_no] =
214 reference_cell.face_vertex_location(face_no, vertex_no);
215
216 for (types::geometric_orientation combined_orientation = 0;
217 combined_orientation < reference_cell.n_face_orientations(face_no);
218 ++combined_orientation)
219 internal::QProjector::append_subobject_rule(
220 face_reference_cell,
221 quadrature[quadrature.size() == 1 ? 0 : face_no],
222 face_vertices,
223 reference_cell.face_measure(face_no),
224 combined_orientation,
225 points,
226 weights);
227 }
228
229 return Quadrature<dim>(std::move(points), std::move(weights));
230}
231
232
233
234template <int dim>
237 const ReferenceCell<dim> &reference_cell,
238 const Quadrature<dim - 1> &quadrature)
239{
240 AssertDimension(reference_cell.get_dimension(), dim);
241 if (dim == 1)
242 AssertDimension(quadrature.size(), 1);
243
244 std::size_t n_points = 0;
245 for (const unsigned int face_no : reference_cell.face_indices())
246 {
247 const auto n_orientations = reference_cell.n_face_orientations(face_no);
248 const auto face_reference_cell =
249 reference_cell.face_reference_cell(face_no);
250 for (const auto &refinement_case : face_reference_cell.refinement_cases())
251 {
252 const auto n_children =
253 dim > 1 ? face_reference_cell.n_children(refinement_case) : 1;
254 n_points += n_children * n_orientations * quadrature.size();
255 }
256 }
257
258 std::vector<Point<dim>> points;
259 std::vector<double> weights;
260 points.reserve(n_points);
261 weights.reserve(n_points);
262
263 // project to each face and copy results
264 for (unsigned int face_no = 0; face_no < reference_cell.n_faces(); ++face_no)
265 {
266 const auto face_reference_cell =
267 reference_cell.face_reference_cell(face_no);
268 const auto &refinement_cases = face_reference_cell.refinement_cases();
269 for (const auto &refinement_case : refinement_cases)
270 {
271 const auto n_children =
272 dim > 1 ? face_reference_cell.n_children(refinement_case) : 1;
273 for (types::geometric_orientation combined_orientation = 0;
274 combined_orientation <
275 reference_cell.n_face_orientations(face_no);
276 ++combined_orientation)
277 for (unsigned int subface_no = 0; subface_no < n_children;
278 ++subface_no)
279 {
283 vertices;
284 for (const unsigned int subface_vertex_no :
285 reference_cell.face_reference_cell(face_no)
286 .vertex_indices())
287 vertices.push_back(reference_cell.subface_vertex_location(
288 face_no, subface_no, subface_vertex_no, refinement_case));
289 internal::QProjector::append_subobject_rule(
290 reference_cell.face_reference_cell(face_no),
291 quadrature,
292 vertices,
293 reference_cell.face_measure(face_no),
294 combined_orientation,
295 points,
296 weights);
297 }
298 }
299 }
300
301 return Quadrature<dim>(std::move(points), std::move(weights));
302}
303
304
305
306template <int dim>
309 const Quadrature<dim> &quadrature,
310 const unsigned int child_no)
311{
312 Assert(reference_cell == ReferenceCells::get_hypercube<dim>(),
314
316
317 const unsigned int n_q_points = quadrature.size();
318
319 std::vector<Point<dim>> q_points(n_q_points);
320 for (unsigned int i = 0; i < n_q_points; ++i)
321 q_points[i] =
323 child_no);
324
325 // for the weights, things are
326 // equally simple: copy them and
327 // scale them
328 std::vector<double> weights = quadrature.get_weights();
329 for (unsigned int i = 0; i < n_q_points; ++i)
330 weights[i] *= (1. / GeometryInfo<dim>::max_children_per_cell);
331
332 return Quadrature<dim>(q_points, weights);
333}
334
335
336
337template <int dim>
340 const ReferenceCell<dim> &reference_cell,
341 const Quadrature<dim> &quadrature)
342{
343 Assert(reference_cell == ReferenceCells::get_hypercube<dim>(),
345
346 const unsigned int n_points = quadrature.size(),
348
349 std::vector<Point<dim>> q_points(n_points * n_children);
350 std::vector<double> weights(n_points * n_children);
351
352 // project to each child and copy
353 // results
354 for (unsigned int child = 0; child < n_children; ++child)
355 {
356 Quadrature<dim> help =
357 project_to_child(reference_cell, quadrature, child);
358 for (unsigned int i = 0; i < n_points; ++i)
359 {
360 q_points[child * n_points + i] = help.point(i);
361 weights[child * n_points + i] = help.weight(i);
362 }
363 }
364 return Quadrature<dim>(q_points, weights);
365}
366
367
368
369template <int dim>
372 const Quadrature<1> &quadrature,
373 const Point<dim> &p1,
374 const Point<dim> &p2)
375{
376 Assert(reference_cell == ReferenceCells::get_hypercube<dim>(),
378
379 const unsigned int n = quadrature.size();
380 std::vector<Point<dim>> points(n);
381 std::vector<double> weights(n);
382 const double length = p1.distance(p2);
383
384 for (unsigned int k = 0; k < n; ++k)
385 {
386 const double alpha = quadrature.point(k)[0];
387 points[k] = alpha * p2;
388 points[k] += (1. - alpha) * p1;
389 weights[k] = length * quadrature.weight(k);
390 }
391 return Quadrature<dim>(points, weights);
392}
393
394
395
396template <int dim>
399 const ReferenceCell<dim> &reference_cell,
400 const unsigned int face_no,
401 const types::geometric_orientation combined_orientation,
402 const unsigned int n_quadrature_points)
403{
404 AssertIndexRange(face_no, reference_cell.n_faces());
405 AssertIndexRange(combined_orientation,
406 reference_cell.n_face_orientations(face_no));
407 AssertDimension(reference_cell.get_dimension(), dim);
408
409
410 return {(reference_cell.n_face_orientations(face_no) * face_no +
411 combined_orientation) *
412 n_quadrature_points};
413}
414
415
416
417template <int dim>
420 const ReferenceCell<dim> &reference_cell,
421 const unsigned int face_no,
422 const types::geometric_orientation combined_orientation,
423 const hp::QCollection<dim - 1> &quadrature)
424{
425 AssertIndexRange(face_no, reference_cell.n_faces());
426 AssertIndexRange(combined_orientation,
427 reference_cell.n_face_orientations(face_no));
428 AssertDimension(reference_cell.get_dimension(), dim);
429
430 unsigned int offset = 0;
431 for (unsigned int i = 0; i < face_no; ++i)
432 offset += reference_cell.n_face_orientations(i) *
433 quadrature[quadrature.size() == 1 ? 0 : i].size();
434
435 return {offset + combined_orientation *
436 quadrature[quadrature.size() == 1 ? 0 : face_no].size()};
437}
438
439
440
441template <int dim>
444 const ReferenceCell<dim> &reference_cell,
445 const unsigned int face_no,
446 const unsigned int subface_no,
447 const types::geometric_orientation combined_orientation,
448 const unsigned int n_quadrature_points,
449 const internal::SubfaceCase<dim> ref_case)
450{
451 AssertDimension(reference_cell.get_dimension(), dim);
452 AssertIndexRange(face_no, reference_cell.n_faces());
453 AssertIndexRange(combined_orientation,
454 reference_cell.n_face_orientations(face_no));
455
456 const auto [final_subface_no, final_refinement_case] =
457 reference_cell.equivalent_refinement_case(combined_orientation,
458 ref_case,
459 subface_no);
460 if (dim > 1)
461 AssertIndexRange(final_subface_no,
462 reference_cell.face_reference_cell(face_no).n_children(
463 final_refinement_case));
464
465 // This function can't work with mixed elements since, in general, those may
466 // have a different number of quadrature points per face
467 Assert(reference_cell != ReferenceCells::Pyramid &&
468 reference_cell != ReferenceCells::Wedge,
470
471 // Calculate the total number of points per face:
472 const auto face_reference_cell = reference_cell.face_reference_cell(face_no);
473 const auto &refinement_cases = face_reference_cell.refinement_cases();
474 unsigned int points_per_face = 0;
475 for (const auto &refinement_case : refinement_cases)
476 {
477 const auto n_children =
478 dim > 1 ? face_reference_cell.n_children(refinement_case) : 1;
479 points_per_face += reference_cell.n_face_orientations(face_no) *
480 n_children * n_quadrature_points;
481 }
482
483 // Next, calculate where we are in the current face's enumeration of
484 // quadrature rules:
485 unsigned int index = points_per_face * face_no;
486 for (const auto &refinement_case : refinement_cases)
487 {
488 const auto n_children =
489 dim > 1 ? face_reference_cell.n_children(refinement_case) : 1;
490
491 if (refinement_case == final_refinement_case)
492 return index + (combined_orientation * n_children + final_subface_no) *
493 n_quadrature_points;
494 else
495 index += reference_cell.n_face_orientations(face_no) * n_children *
496 n_quadrature_points;
497 }
499
500 return index;
501}
502
503
504// explicit instantiations; note: we need them all for all dimensions
505template class QProjector<1>;
506template class QProjector<2>;
507template class QProjector<3>;
508
Definition point.h:111
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
Class storing the offset index into a Quadrature rule created by project_to_all_faces() or project_to...
Definition qprojector.h:204
static DataSetDescriptor face(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const types::geometric_orientation combined_orientation, const unsigned int n_quadrature_points)
static DataSetDescriptor subface(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const unsigned int subface_no, const types::geometric_orientation combined_orientation, const unsigned int n_quadrature_points, const internal::SubfaceCase< dim > ref_case=internal::SubfaceCase< dim >::case_isotropic)
Class which transforms dim - 1-dimensional quadrature rules to dim-dimensional face quadratures.
Definition qprojector.h:68
static Quadrature< dim > project_to_all_faces(const ReferenceCell< dim > &reference_cell, const hp::QCollection< dim - 1 > &quadrature)
static Quadrature< dim > project_to_all_subfaces(const ReferenceCell< dim > &reference_cell, const SubQuadrature &quadrature)
static Quadrature< dim > project_to_all_children(const ReferenceCell< dim > &reference_cell, const Quadrature< dim > &quadrature)
static Quadrature< dim > project_to_line(const ReferenceCell< dim > &reference_cell, const Quadrature< 1 > &quadrature, const Point< dim > &p1, const Point< dim > &p2)
static Quadrature< dim > project_to_face(const ReferenceCell< dim > &reference_cell, const SubQuadrature &quadrature, const unsigned int face_no, const types::geometric_orientation combined_orientation)
static Quadrature< dim > project_to_subface(const ReferenceCell< dim > &reference_cell, const SubQuadrature &quadrature, const unsigned int face_no, const unsigned int subface_no, const types::geometric_orientation combined_orientation, const RefinementCase< dim - 1 > &ref_case)
static Quadrature< dim > project_to_child(const ReferenceCell< dim > &reference_cell, const Quadrature< dim > &quadrature, const unsigned int child_no)
const Point< dim > & point(const unsigned int i) const
double weight(const unsigned int i) const
const std::vector< double > & get_weights() const
unsigned int size() const
double volume() const
constexpr unsigned int n_vertices() const
double d_linear_shape_function(const Point< dim > &xi, const unsigned int i) const
std_cxx20::ranges::iota_view< unsigned int, unsigned int > vertex_indices() const
boost::container::small_vector< T, 8 > permute_by_combined_orientation(const ArrayView< const T > &vertices, const types::geometric_orientation orientation) const
types::geometric_orientation get_inverse_combined_orientation(const types::geometric_orientation orientation) const
unsigned int size() const
Definition collection.h:314
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
constexpr unsigned int max_n_vertices()
constexpr ReferenceCell< 3 > Pyramid
constexpr ReferenceCell< 3 > Wedge
std::uint8_t geometric_orientation
Definition types.h:38