deal.II version 9.7.0
\(\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
fe_raviart_thomas.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2003 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
21#include <deal.II/base/table.h>
23
25
26#include <deal.II/fe/fe.h>
28#include <deal.II/fe/fe_tools.h>
30#include <deal.II/fe/mapping.h>
31
32#include <deal.II/grid/tria.h>
34
35#include <iostream>
36#include <memory>
37#include <sstream>
38
39
41
42
43template <int dim>
45 : FE_PolyTensor<dim>(
47 deg,
50 dim,
51 deg + 1,
53 std::vector<bool>(
54 PolynomialsVectorAnisotropic<dim>::n_polynomials(deg + 1, deg),
55 true),
56 std::vector<ComponentMask>(
57 PolynomialsVectorAnisotropic<dim>::n_polynomials(deg + 1, deg),
58 ComponentMask(std::vector<bool>(dim, true))))
59{
60 Assert(dim >= 2, ExcImpossibleInDim(dim));
61 const unsigned int n_dofs = this->n_dofs_per_cell();
62
64 // First, initialize the
65 // generalized support points and
66 // quadrature weights, since they
67 // are required for interpolation.
69
70 // Now compute the inverse node matrix, generating the correct
71 // basis functions from the raw ones. For a discussion of what
72 // exactly happens here, see FETools::compute_node_matrix.
74 this->inverse_node_matrix.reinit(n_dofs, n_dofs);
75 this->inverse_node_matrix.invert(M);
76 // From now on, the shape functions provided by FiniteElement::shape_value
77 // and similar functions will be the correct ones, not
78 // the raw shape functions from the polynomial space anymore.
79
80 // Reinit the vectors of
81 // restriction and prolongation
82 // matrices to the right sizes.
83 // Restriction only for isotropic
84 // refinement
86 // Fill prolongation matrices with embedding operators
89
90 // TODO: the implementation makes the assumption that all faces have the
91 // same number of dofs
93 const unsigned int face_no = 0;
94
95 // TODO[TL]: for anisotropic refinement we will probably need a table of
96 // submatrices with an array for each refine case
97 std::vector<FullMatrix<double>> face_embeddings(
98 this->reference_cell().face_reference_cell(0).template n_children<dim - 1>(
100 for (auto &face_embedding : face_embeddings)
101 face_embedding.reinit(this->n_dofs_per_face(face_no),
102 this->n_dofs_per_face(face_no));
104 make_array_view(face_embeddings),
105 0,
106 0);
107 this->interface_constraints.reinit((1 << (dim - 1)) *
108 this->n_dofs_per_face(face_no),
109 this->n_dofs_per_face(face_no));
110 unsigned int target_row = 0;
111 for (const auto &face_embedding : face_embeddings)
112 for (unsigned int i = 0; i < face_embedding.m(); ++i)
113 {
114 for (unsigned int j = 0; j < face_embedding.n(); ++j)
115 this->interface_constraints(target_row, j) = face_embedding(i, j);
116 ++target_row;
117 }
118
119 // We need to initialize the dof permutation table and the one for the sign
120 // change.
122}
123
124
125
126template <int dim>
127std::string
129{
130 // note that the
131 // FETools::get_fe_by_name
132 // function depends on the
133 // particular format of the string
134 // this function returns, so they
135 // have to be kept in synch
136
137 // note that this->degree is the maximal
138 // polynomial degree and is thus one higher
139 // than the argument given to the
140 // constructor
141 std::ostringstream namebuf;
142 namebuf << "FE_RaviartThomas<" << dim << ">(" << this->degree - 1 << ")";
143
144 return namebuf.str();
145}
146
147
148template <int dim>
149std::unique_ptr<FiniteElement<dim, dim>>
151{
152 return std::make_unique<FE_RaviartThomas<dim>>(*this);
153}
154
155
156//---------------------------------------------------------------------------
157// Auxiliary and internal functions
158//---------------------------------------------------------------------------
159
160
161template <int dim>
162void
164{
165 const QGauss<dim> cell_quadrature(deg + 1);
166 const unsigned int n_interior_points = (deg > 0) ? cell_quadrature.size() : 0;
167
168 // TODO: the implementation makes the assumption that all faces have the
169 // same number of dofs
171 const unsigned int face_no = 0;
172
173 unsigned int n_face_points = (dim > 1) ? 1 : 0;
174 // compute (deg+1)^(dim-1)
175 for (unsigned int d = 1; d < dim; ++d)
176 n_face_points *= deg + 1;
177
178
179 this->generalized_support_points.resize(
180 this->reference_cell().n_faces() * n_face_points + n_interior_points);
181 this->generalized_face_support_points[face_no].resize(n_face_points);
182
183 // Number of the point being entered
184 unsigned int current = 0;
185
186 if (dim > 1)
187 {
188 const QGauss<dim - 1> face_points(deg + 1);
189 TensorProductPolynomials<dim - 1> legendre =
191
192 boundary_weights.reinit(n_face_points, legendre.n());
193
194 for (unsigned int k = 0; k < n_face_points; ++k)
195 {
196 this->generalized_face_support_points[face_no][k] =
197 face_points.point(k);
198 // Compute its quadrature
199 // contribution for each
200 // moment.
201 for (unsigned int i = 0; i < legendre.n(); ++i)
202 {
203 boundary_weights(k, i) =
204 face_points.weight(k) *
205 legendre.compute_value(i, face_points.point(k));
206 }
207 }
208
209 const Quadrature<dim> faces =
211 face_points);
212
213 for (unsigned int face_no = 0;
214 face_no < GeometryInfo<dim>::faces_per_cell;
215 ++face_no)
216 {
218 this->reference_cell(),
219 face_no,
221 n_face_points);
222 for (unsigned int face_point = 0; face_point < n_face_points;
223 ++face_point)
224 {
225 // Enter the support point into the vector
226 this->generalized_support_points[current] =
227 faces.point(offset + face_point);
228 ++current;
229 }
230 }
231 }
232
233 if (deg == 0)
234 return;
235
236 // Create Legendre basis for the space D_xi Q_k
237 std::unique_ptr<AnisotropicPolynomials<dim>> polynomials[dim];
238 for (unsigned int dd = 0; dd < dim; ++dd)
239 {
240 std::vector<std::vector<Polynomials::Polynomial<double>>> poly(dim);
241 for (unsigned int d = 0; d < dim; ++d)
244
245 polynomials[dd] = std::make_unique<AnisotropicPolynomials<dim>>(poly);
246 }
247
248 interior_weights.reinit(
249 TableIndices<3>(n_interior_points, polynomials[0]->n(), dim));
250
251 for (unsigned int k = 0; k < cell_quadrature.size(); ++k)
252 {
253 this->generalized_support_points[current++] = cell_quadrature.point(k);
254 for (unsigned int i = 0; i < polynomials[0]->n(); ++i)
255 for (unsigned int d = 0; d < dim; ++d)
256 interior_weights(k, i, d) =
257 cell_quadrature.weight(k) *
258 polynomials[d]->compute_value(i, cell_quadrature.point(k));
259 }
260
261 Assert(current == this->generalized_support_points.size(),
263}
264
265
266template <int dim>
267void
269{
270 // For 1d do nothing.
271 //
272 // TODO: For 2d we simply keep the legacy behavior for now. This should be
273 // changed in the future and can be taken care of by similar means as the 3d
274 // case below. The legacy behavior can be found in fe_poly_tensor.cc in the
275 // function internal::FE_PolyTensor::get_dof_sign_change_h_div(...)
276 if (dim < 3)
277 return;
278
279 // TODO: the implementation makes the assumption that all faces have the
280 // same number of dofs
282 const unsigned int face_no = 0;
283
284 Assert(
286 this->reference_cell().n_face_orientations(face_no) *
287 this->n_dofs_per_quad(face_no),
289
290 // The 3d RaviartThomas space has tensor_degree*tensor_degree face dofs
291 const unsigned int n = this->tensor_degree();
292 Assert(n * n == this->n_dofs_per_quad(face_no), ExcInternalError());
293
294 // The vector of tables adjust_quad_dof_index_for_face_orientation_table
295 // contains offsets for local face_dofs and is being filled with zeros in
296 // fe.cc. We need to fill it with the correct values in case of non-standard,
297 // flipped (rotated by +180 degrees) or rotated (rotated by +90 degrees) faces
298
299 // The dofs on a face are connected to a n x n matrix. for example, for
300 // tensor_degree==3 we have the following dofs on a quad:
301
302 // ___________
303 // | |
304 // | 6 7 8 |
305 // | |
306 // | 3 4 5 |
307 // | |
308 // | 0 1 2 |
309 // |___________|
310 //
311 // We have dof_index=i+n*j with index i in x-direction and index j in
312 // y-direction running from 0 to n-1. to extract i and j we can use
313 // i=dof_index%n and j=dof_index/n. The indices i and j can then be used to
314 // compute the offset.
315
316 // Example: if the switches are (true | true | true) that means we rotate the
317 // face first by + 90 degree(counterclockwise) then by another +180
318 // degrees but we do not flip it since the face has standard
319 // orientation. The flip axis is the diagonal from the lower left to the upper
320 // right corner of the face. With these flags the configuration above becomes:
321 // ___________
322 // | |
323 // | 2 5 8 |
324 // | |
325 // | 1 4 7 |
326 // | |
327 // | 0 3 6 |
328 // |___________|
329 //
330 // This is exactly what is realized by the formulas implemented below. Note
331 // that the necessity of a permuattion depends on the three flags.
332
333 // There is also a pattern for the sign change of the mapped face_dofs
334 // depending on the switches. In the above example it would be
335 // ___________
336 // | |
337 // | + - + |
338 // | |
339 // | + - + |
340 // | |
341 // | + - + |
342 // |___________|
343 //
344
345 for (unsigned int local_face_dof = 0;
346 local_face_dof < this->n_dofs_per_quad(face_no);
347 ++local_face_dof)
348 {
349 // Row and column
350 unsigned int i = local_face_dof % n;
351 unsigned int j = local_face_dof / n;
352
353 // We have 8 cases that are all treated the same way. Note that the
354 // corresponding case to case_no is just its binary representation.
355 // The above example of (false | true | true) would be case_no=3
356 for (const bool face_orientation : {false, true})
357 for (const bool face_flip : {false, true})
358 for (const bool face_rotation : {false, true})
359 {
360 const auto case_no =
362 face_rotation,
363 face_flip);
364
365 if (((!face_orientation) && (!face_rotation)) ||
366 ((face_orientation) && (face_rotation)))
367 {
368 // We flip across the diagonal
369 // This is the local face dof offset
370 this
371 ->adjust_quad_dof_index_for_face_orientation_table[face_no](
372 local_face_dof, case_no) = j + i * n - local_face_dof;
373 }
374 else
375 {
376 // Offset is zero
377 this
378 ->adjust_quad_dof_index_for_face_orientation_table[face_no](
379 local_face_dof, case_no) = 0;
380 } // if face needs dof permutation
381
382 // Get new local face_dof by adding offset
383 const unsigned int new_local_face_dof =
384 local_face_dof +
386 local_face_dof, case_no);
387 // compute new row and column index
388 i = new_local_face_dof % n;
389 j = new_local_face_dof / n;
390
391 /*
392 * Now compute if a sign change is necessary. This is done for the
393 * case of face_orientation==true
394 */
395 // flip = false, rotation=true
396 if (!face_flip && face_rotation)
397 {
398 this
399 ->adjust_quad_dof_sign_for_face_orientation_table[face_no](
400 local_face_dof, case_no) = ((j % 2) == 1);
401 }
402 // flip = true, rotation=false
403 else if (face_flip && !face_rotation)
404 {
405 // This case is symmetric (although row and column may be
406 // switched)
407 this
408 ->adjust_quad_dof_sign_for_face_orientation_table[face_no](
409 local_face_dof, case_no) =
410 ((j % 2) == 1) != ((i % 2) == 1);
411 }
412 // flip = true, rotation=true
413 else if (face_flip && face_rotation)
414 {
415 this
416 ->adjust_quad_dof_sign_for_face_orientation_table[face_no](
417 local_face_dof, case_no) = ((i % 2) == 1);
418 }
419 /*
420 * flip = false, rotation=false => nothing to do
421 */
422
423 /*
424 * If face_orientation==false the sign flip is exactly the
425 * opposite.
426 */
427 if (!face_orientation)
429 local_face_dof, case_no) =
430 !this
432 local_face_dof, case_no);
433 } // case_no
434 } // local_face_dof
435}
436
437
438template <>
439void
441{
442 // there is only one refinement case in 1d,
443 // which is the isotropic one (first index of
444 // the matrix array has to be 0)
445 for (auto &restriction_matrix : this->restriction[0])
446 restriction_matrix.reinit(0, 0);
447}
448
449
450
451// This function is the same Raviart-Thomas interpolation performed by
452// interpolate. Still, we cannot use interpolate, since it was written
453// for smooth functions. The functions interpolated here are not
454// smooth, maybe even not continuous. Therefore, we must double the
455// number of quadrature points in each direction in order to integrate
456// only smooth functions.
457
458// Then again, the interpolated function is chosen such that the
459// moments coincide with the function to be interpolated.
460
461template <int dim>
462void
464{
465 const unsigned int iso = RefinementCase<dim>::isotropic_refinement - 1;
466
467 const QGauss<dim - 1> q_base(this->degree);
468 const unsigned int n_face_points = q_base.size();
469 // First, compute interpolation on
470 // subfaces
471 for (const unsigned int face : this->reference_cell().face_indices())
472 {
473 // The shape functions of the
474 // child cell are evaluated
475 // in the quadrature points
476 // of a full face.
478 this->reference_cell(),
479 q_base,
480 face,
482 // Store shape values, since the
483 // evaluation suffers if not
484 // ordered by point
485 Table<2, double> cached_values_on_face(this->n_dofs_per_cell(),
486 q_face.size());
487 for (unsigned int k = 0; k < q_face.size(); ++k)
488 for (unsigned int i = 0; i < this->n_dofs_per_cell(); ++i)
489 cached_values_on_face(i, k) = this->shape_value_component(
491
492 for (unsigned int sub = 0; sub < this->reference_cell()
493 .face_reference_cell(face)
494 .template n_children<dim - 1>();
495 ++sub)
496 {
497 // The weight functions for
498 // the coarse face are
499 // evaluated on the subface
500 // only.
502 this->reference_cell(),
503 q_base,
504 face,
505 sub,
508 const unsigned int child = GeometryInfo<dim>::child_cell_on_face(
510
511 // On a certain face, we must
512 // compute the moments of ALL
513 // fine level functions with
514 // the coarse level weight
515 // functions belonging to
516 // that face. Due to the
517 // orthogonalization process
518 // when building the shape
519 // functions, these weights
520 // are equal to the
521 // corresponding shape
522 // functions.
523 for (unsigned int k = 0; k < n_face_points; ++k)
524 for (unsigned int i_child = 0; i_child < this->n_dofs_per_cell();
525 ++i_child)
526 for (unsigned int i_face = 0;
527 i_face < this->n_dofs_per_face(face);
528 ++i_face)
529 {
530 // The quadrature
531 // weights on the
532 // subcell are NOT
533 // transformed, so we
534 // have to do it here.
535 this->restriction[iso][child](
536 face * this->n_dofs_per_face(face) + i_face, i_child) +=
538 cached_values_on_face(i_child, k) *
540 face * this->n_dofs_per_face(face) + i_face,
541 q_sub.point(k),
543 }
544 }
545 }
546
547 if (this->degree == 1)
548 return;
549
550 // Create Legendre basis for the space D_xi Q_k. Here, we cannot
551 // use the shape functions
552 std::unique_ptr<AnisotropicPolynomials<dim>> polynomials[dim];
553 for (unsigned int dd = 0; dd < dim; ++dd)
554 {
555 std::vector<std::vector<Polynomials::Polynomial<double>>> poly(dim);
556 for (unsigned int d = 0; d < dim; ++d)
557 poly[d] =
559 poly[dd] =
561
562 polynomials[dd] = std::make_unique<AnisotropicPolynomials<dim>>(poly);
563 }
564
565 // TODO: the implementation makes the assumption that all faces have the
566 // same number of dofs
568 const unsigned int face_no = 0;
569
570 const QGauss<dim> q_cell(this->degree);
571 const unsigned int start_cell_dofs =
572 this->reference_cell().n_faces() * this->n_dofs_per_face(face_no);
573
574 // Store shape values, since the
575 // evaluation suffers if not
576 // ordered by point
577 Table<3, double> cached_values_on_cell(this->n_dofs_per_cell(),
578 q_cell.size(),
579 dim);
580 for (unsigned int k = 0; k < q_cell.size(); ++k)
581 for (unsigned int i = 0; i < this->n_dofs_per_cell(); ++i)
582 for (unsigned int d = 0; d < dim; ++d)
583 cached_values_on_cell(i, k, d) =
584 this->shape_value_component(i, q_cell.point(k), d);
585
586 for (unsigned int child = 0;
587 child < this->reference_cell().template n_children<dim>();
588 ++child)
589 {
590 Quadrature<dim> q_sub =
592 q_cell,
593 child);
594
595 for (unsigned int k = 0; k < q_sub.size(); ++k)
596 for (unsigned int i_child = 0; i_child < this->n_dofs_per_cell();
597 ++i_child)
598 for (unsigned int d = 0; d < dim; ++d)
599 for (unsigned int i_weight = 0; i_weight < polynomials[d]->n();
600 ++i_weight)
601 {
602 this->restriction[iso][child](start_cell_dofs + i_weight * dim +
603 d,
604 i_child) +=
605 q_sub.weight(k) * cached_values_on_cell(i_child, k, d) *
606 polynomials[d]->compute_value(i_weight, q_sub.point(k));
607 }
608 }
609}
610
611
612
613template <int dim>
614std::vector<unsigned int>
616{
617 // the element is face-based and we have
618 // (deg+1)^(dim-1) DoFs per face
619 unsigned int dofs_per_face = 1;
620 for (unsigned int d = 1; d < dim; ++d)
621 dofs_per_face *= deg + 1;
622
623 // and then there are interior dofs
624 const unsigned int interior_dofs = dim * deg * dofs_per_face;
625
626 std::vector<unsigned int> dpo(dim + 1);
627 dpo[dim - 1] = dofs_per_face;
628 dpo[dim] = interior_dofs;
629
630 return dpo;
631}
632
633
634
635template <int dim>
636std::pair<Table<2, bool>, std::vector<unsigned int>>
638{
639 Table<2, bool> constant_modes(dim, this->n_dofs_per_cell());
640 for (unsigned int d = 0; d < dim; ++d)
641 for (unsigned int i = 0; i < this->n_dofs_per_cell(); ++i)
642 constant_modes(d, i) = true;
643 std::vector<unsigned int> components;
644 components.reserve(dim);
645 for (unsigned int d = 0; d < dim; ++d)
646 components.push_back(d);
647 return std::pair<Table<2, bool>, std::vector<unsigned int>>(constant_modes,
648 components);
649}
650
651
652
653//---------------------------------------------------------------------------
654// Data field initialization
655//---------------------------------------------------------------------------
656
657
658template <int dim>
659bool
660FE_RaviartThomas<dim>::has_support_on_face(const unsigned int shape_index,
661 const unsigned int face_index) const
662{
663 AssertIndexRange(shape_index, this->n_dofs_per_cell());
664 AssertIndexRange(face_index, this->reference_cell().n_faces());
665
666 // Return computed values if we
667 // know them easily. Otherwise, it
668 // is always safe to return true.
669 switch (this->degree)
670 {
671 case 1:
672 {
673 switch (dim)
674 {
675 case 2:
676 {
677 // only on the one
678 // non-adjacent face
679 // are the values
680 // actually zero. list
681 // these in a table
682 return (face_index !=
684 }
685
686 default:
687 return true;
688 }
689 }
690
691 default: // other rt_order
692 return true;
693 }
694
695 return true;
696}
697
698
699
700template <int dim>
701std::vector<unsigned int>
703{
704 const unsigned int n_dofs_face = Utilities::pow(degree + 1, dim - 1);
705 std::vector<unsigned int> lexicographic_numbering;
706 // component 1
707 for (unsigned int j = 0; j < n_dofs_face; ++j)
708 {
709 lexicographic_numbering.push_back(j);
710 for (unsigned int i = n_dofs_face * 2 * dim;
711 i < n_dofs_face * 2 * dim + degree;
712 ++i)
713 lexicographic_numbering.push_back(i + j * degree);
714 lexicographic_numbering.push_back(n_dofs_face + j);
715 }
716
717 // component 2
718 unsigned int layers = (dim == 3) ? degree + 1 : 1;
719 for (unsigned int k = 0; k < layers; ++k)
720 {
721 unsigned int k_add = k * (degree + 1);
722 for (unsigned int j = n_dofs_face * 2; j < n_dofs_face * 2 + degree + 1;
723 ++j)
724 lexicographic_numbering.push_back(j + k_add);
725
726 for (unsigned int i = n_dofs_face * (2 * dim + degree);
727 i < n_dofs_face * (2 * dim + degree) + degree * (degree + 1);
728 ++i)
729 {
730 lexicographic_numbering.push_back(i + k_add * degree);
731 }
732 for (unsigned int j = n_dofs_face * 3; j < n_dofs_face * 3 + degree + 1;
733 ++j)
734 lexicographic_numbering.push_back(j + k_add);
735 }
736
737 // component 3
738 if (dim == 3)
739 {
740 for (unsigned int i = 4 * n_dofs_face; i < 5 * n_dofs_face; ++i)
741 lexicographic_numbering.push_back(i);
742 for (unsigned int i = 6 * n_dofs_face + n_dofs_face * 2 * degree;
743 i < 6 * n_dofs_face + n_dofs_face * 3 * degree;
744 ++i)
745 lexicographic_numbering.push_back(i);
746 for (unsigned int i = 5 * n_dofs_face; i < 6 * n_dofs_face; ++i)
747 lexicographic_numbering.push_back(i);
748 }
749
750 return lexicographic_numbering;
751}
752
753
754
755template <int dim>
756void
758 const std::vector<Vector<double>> &support_point_values,
759 std::vector<double> &nodal_values) const
760{
761 Assert(support_point_values.size() == this->generalized_support_points.size(),
762 ExcDimensionMismatch(support_point_values.size(),
763 this->generalized_support_points.size()));
764 Assert(nodal_values.size() == this->n_dofs_per_cell(),
765 ExcDimensionMismatch(nodal_values.size(), this->n_dofs_per_cell()));
766 Assert(support_point_values[0].size() == this->n_components(),
767 ExcDimensionMismatch(support_point_values[0].size(),
768 this->n_components()));
769
770 std::fill(nodal_values.begin(), nodal_values.end(), 0.);
771
772 const unsigned int n_face_points = boundary_weights.size(0);
773 for (const unsigned int face : this->reference_cell().face_indices())
774 for (unsigned int k = 0; k < n_face_points; ++k)
775 for (unsigned int i = 0; i < boundary_weights.size(1); ++i)
776 {
777 nodal_values[i + face * this->n_dofs_per_face(face)] +=
778 boundary_weights(k, i) *
779 support_point_values[face * n_face_points + k](
781 }
782
783 // TODO: the implementation makes the assumption that all faces have the
784 // same number of dofs
786 const unsigned int face_no = 0;
787
788 const unsigned int start_cell_dofs =
789 this->reference_cell().n_faces() * this->n_dofs_per_face(face_no);
790 const unsigned int start_cell_points =
791 this->reference_cell().n_faces() * n_face_points;
792
793 for (unsigned int k = 0; k < interior_weights.size(0); ++k)
794 for (unsigned int i = 0; i < interior_weights.size(1); ++i)
795 for (unsigned int d = 0; d < dim; ++d)
796 nodal_values[start_cell_dofs + i * dim + d] +=
797 interior_weights(k, i, d) *
798 support_point_values[k + start_cell_points](d);
799}
800
801
802
803template <int dim>
804std::size_t
810
811
812
813// explicit instantiations
814#include "fe/fe_raviart_thomas.inst"
815
816
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition array_view.h:954
std::vector< Table< 2, bool > > adjust_quad_dof_sign_for_face_orientation_table
FullMatrix< double > inverse_node_matrix
virtual double shape_value_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
std::vector< MappingKind > mapping_kind
FE_PolyTensor(const TensorPolynomialsBase< dim > &polynomials, const FiniteElementData< dim > &fe_data, const std::vector< bool > &restriction_is_additive_flags, const std::vector< ComponentMask > &nonzero_components)
virtual std::size_t memory_consumption() const override
virtual void convert_generalized_support_point_values_to_dof_values(const std::vector< Vector< double > > &support_point_values, std::vector< double > &nodal_values) const override
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const override
Table< 3, double > interior_weights
virtual std::pair< Table< 2, bool >, std::vector< unsigned int > > get_constant_modes() const override
Table< 2, double > boundary_weights
void initialize_quad_dof_index_permutation_and_sign_change()
virtual std::unique_ptr< FiniteElement< dim, dim > > clone() const override
friend class FE_RaviartThomas
void initialize_support_points(const unsigned int rt_degree)
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
virtual std::string get_name() const override
static std::vector< unsigned int > get_lexicographic_numbering(const unsigned int degree)
const unsigned int components
Definition fe_data.h:446
const unsigned int degree
Definition fe_data.h:452
unsigned int n_dofs_per_cell() const
const unsigned int dofs_per_face
Definition fe_data.h:422
unsigned int n_dofs_per_face(unsigned int face_no=0, unsigned int child=0) const
unsigned int tensor_degree() const
unsigned int n_components() const
ReferenceCell reference_cell() const
unsigned int n_unique_faces() const
unsigned int n_dofs_per_quad(unsigned int face_no=0) const
FiniteElementData(const std::vector< unsigned int > &dofs_per_object, const unsigned int n_components, const unsigned int degree, const Conformity conformity=unknown, const BlockIndices &block_indices=BlockIndices())
Definition fe_data.cc:114
std::vector< std::vector< FullMatrix< double > > > restriction
Definition fe.h:2524
std::vector< Table< 2, int > > adjust_quad_dof_index_for_face_orientation_table
Definition fe.h:2598
void reinit_restriction_and_prolongation_matrices(const bool isotropic_restriction_only=false, const bool isotropic_prolongation_only=false)
std::vector< std::vector< Point< dim - 1 > > > generalized_face_support_points
Definition fe.h:2581
FullMatrix< double > interface_constraints
Definition fe.h:2550
std::vector< Point< dim > > generalized_support_points
Definition fe.h:2575
std::vector< std::vector< FullMatrix< double > > > prolongation
Definition fe.h:2538
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
static DataSetDescriptor face(const ReferenceCell &reference_cell, const unsigned int face_no, const bool face_orientation, const bool face_flip, const bool face_rotation, const unsigned int n_quadrature_points)
static Quadrature< dim > project_to_all_faces(const ReferenceCell &reference_cell, const hp::QCollection< dim - 1 > &quadrature)
static Quadrature< dim > project_to_child(const ReferenceCell &reference_cell, const Quadrature< dim > &quadrature, const unsigned int child_no)
static void project_to_subface(const ReferenceCell &reference_cell, const SubQuadrature &quadrature, const unsigned int face_no, const unsigned int subface_no, std::vector< Point< dim > > &q_points, const RefinementCase< dim - 1 > &ref_case=RefinementCase< dim - 1 >::isotropic_refinement)
static void project_to_face(const ReferenceCell &reference_cell, const SubQuadrature &quadrature, const unsigned int face_no, std::vector< Point< dim > > &q_points)
const Point< dim > & point(const unsigned int i) const
double weight(const unsigned int i) const
unsigned int size() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
#define DEAL_II_NOT_IMPLEMENTED()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
@ mapping_raviart_thomas
Definition mapping.h:136
void compute_embedding_matrices(const FiniteElement< dim, spacedim > &fe, std::vector< std::vector< FullMatrix< number > > > &matrices, const bool isotropic_only=false, const double threshold=1.e-12)
void compute_face_embedding_matrices(const FiniteElement< dim, spacedim > &fe, const ArrayView< FullMatrix< number > > &matrices, const unsigned int face_coarse, const unsigned int face_fine, const double threshold=1.e-12)
FullMatrix< double > compute_node_matrix(const FiniteElement< dim, spacedim > &fe)
constexpr T fixed_power(const T t)
Definition utilities.h:943
constexpr T pow(const T base, const int iexp)
Definition utilities.h:967
types::geometric_orientation combined_face_orientation(const bool face_orientation, const bool face_rotation, const bool face_flip)
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:352
STL namespace.
static unsigned int child_cell_on_face(const RefinementCase< dim > &ref_case, const unsigned int face, const unsigned int subface, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement)
static constexpr std::array< unsigned int, faces_per_cell > unit_normal_direction
static constexpr std::array< unsigned int, faces_per_cell > opposite_face