deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20: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 (void)reference_cell;
315
317
318 const unsigned int n_q_points = quadrature.size();
319
320 std::vector<Point<dim>> q_points(n_q_points);
321 for (unsigned int i = 0; i < n_q_points; ++i)
322 q_points[i] =
324 child_no);
325
326 // for the weights, things are
327 // equally simple: copy them and
328 // scale them
329 std::vector<double> weights = quadrature.get_weights();
330 for (unsigned int i = 0; i < n_q_points; ++i)
331 weights[i] *= (1. / GeometryInfo<dim>::max_children_per_cell);
332
333 return Quadrature<dim>(q_points, weights);
334}
335
336
337
338template <int dim>
341 const ReferenceCell<dim> &reference_cell,
342 const Quadrature<dim> &quadrature)
343{
344 Assert(reference_cell == ReferenceCells::get_hypercube<dim>(),
346 (void)reference_cell;
347
348 const unsigned int n_points = quadrature.size(),
350
351 std::vector<Point<dim>> q_points(n_points * n_children);
352 std::vector<double> weights(n_points * n_children);
353
354 // project to each child and copy
355 // results
356 for (unsigned int child = 0; child < n_children; ++child)
357 {
358 Quadrature<dim> help =
359 project_to_child(reference_cell, quadrature, child);
360 for (unsigned int i = 0; i < n_points; ++i)
361 {
362 q_points[child * n_points + i] = help.point(i);
363 weights[child * n_points + i] = help.weight(i);
364 }
365 }
366 return Quadrature<dim>(q_points, weights);
367}
368
369
370
371template <int dim>
374 const Quadrature<1> &quadrature,
375 const Point<dim> &p1,
376 const Point<dim> &p2)
377{
378 Assert(reference_cell == ReferenceCells::get_hypercube<dim>(),
380 (void)reference_cell;
381
382 const unsigned int n = quadrature.size();
383 std::vector<Point<dim>> points(n);
384 std::vector<double> weights(n);
385 const double length = p1.distance(p2);
386
387 for (unsigned int k = 0; k < n; ++k)
388 {
389 const double alpha = quadrature.point(k)[0];
390 points[k] = alpha * p2;
391 points[k] += (1. - alpha) * p1;
392 weights[k] = length * quadrature.weight(k);
393 }
394 return Quadrature<dim>(points, weights);
395}
396
397
398
399template <int dim>
402 const ReferenceCell<dim> &reference_cell,
403 const unsigned int face_no,
404 const types::geometric_orientation combined_orientation,
405 const unsigned int n_quadrature_points)
406{
407 AssertIndexRange(face_no, reference_cell.n_faces());
408 AssertIndexRange(combined_orientation,
409 reference_cell.n_face_orientations(face_no));
410 AssertDimension(reference_cell.get_dimension(), dim);
411
412
413 return {(reference_cell.n_face_orientations(face_no) * face_no +
414 combined_orientation) *
415 n_quadrature_points};
416}
417
418
419
420template <int dim>
423 const ReferenceCell<dim> &reference_cell,
424 const unsigned int face_no,
425 const types::geometric_orientation combined_orientation,
426 const hp::QCollection<dim - 1> &quadrature)
427{
428 AssertIndexRange(face_no, reference_cell.n_faces());
429 AssertIndexRange(combined_orientation,
430 reference_cell.n_face_orientations(face_no));
431 AssertDimension(reference_cell.get_dimension(), dim);
432
433 unsigned int offset = 0;
434 for (unsigned int i = 0; i < face_no; ++i)
435 offset += reference_cell.n_face_orientations(i) *
436 quadrature[quadrature.size() == 1 ? 0 : i].size();
437
438 return {offset + combined_orientation *
439 quadrature[quadrature.size() == 1 ? 0 : face_no].size()};
440}
441
442
443
444template <int dim>
447 const ReferenceCell<dim> &reference_cell,
448 const unsigned int face_no,
449 const unsigned int subface_no,
450 const types::geometric_orientation combined_orientation,
451 const unsigned int n_quadrature_points,
452 const internal::SubfaceCase<dim> ref_case)
453{
454 AssertDimension(reference_cell.get_dimension(), dim);
455 AssertIndexRange(face_no, reference_cell.n_faces());
456 AssertIndexRange(combined_orientation,
457 reference_cell.n_face_orientations(face_no));
458
459 const auto [final_subface_no, final_refinement_case] =
460 reference_cell.equivalent_refinement_case(combined_orientation,
461 ref_case,
462 subface_no);
463 if (dim > 1)
464 AssertIndexRange(final_subface_no,
465 reference_cell.face_reference_cell(face_no).n_children(
466 final_refinement_case));
467
468 // This function can't work with mixed elements since, in general, those may
469 // have a different number of quadrature points per face
470 Assert(reference_cell != ReferenceCells::Pyramid &&
471 reference_cell != ReferenceCells::Wedge,
473
474 // Calculate the total number of points per face:
475 const auto face_reference_cell = reference_cell.face_reference_cell(face_no);
476 const auto &refinement_cases = face_reference_cell.refinement_cases();
477 unsigned int points_per_face = 0;
478 for (const auto &refinement_case : refinement_cases)
479 {
480 const auto n_children =
481 dim > 1 ? face_reference_cell.n_children(refinement_case) : 1;
482 points_per_face += reference_cell.n_face_orientations(face_no) *
483 n_children * n_quadrature_points;
484 }
485
486 // Next, calculate where we are in the current face's enumeration of
487 // quadrature rules:
488 unsigned int index = points_per_face * face_no;
489 for (const auto &refinement_case : refinement_cases)
490 {
491 const auto n_children =
492 dim > 1 ? face_reference_cell.n_children(refinement_case) : 1;
493
494 if (refinement_case == final_refinement_case)
495 return index + (combined_orientation * n_children + final_subface_no) *
496 n_quadrature_points;
497 else
498 index += reference_cell.n_face_orientations(face_no) * n_children *
499 n_quadrature_points;
500 }
502
503 return index;
504}
505
506
507// explicit instantiations; note: we need them all for all dimensions
508template class QProjector<1>;
509template class QProjector<2>;
510template class QProjector<3>;
511
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