]> https://gitweb.dealii.org/ - dealii.git/commitdiff
FE_SimplexP: generalize some line orientation code.
authorDavid Wells <drwells@email.unc.edu>
Sat, 26 Apr 2025 21:54:43 +0000 (17:54 -0400)
committerDavid Wells <drwells@email.unc.edu>
Wed, 28 May 2025 19:18:53 +0000 (15:18 -0400)
include/deal.II/fe/fe_simplex_p.h
source/fe/fe_simplex_p.cc

index 7ce1999318e1f4c180fdc8e22ab0debcc47262ef..e463240c38423d9a4c7b69090f4f98ebe66d0c18 100644 (file)
@@ -68,13 +68,6 @@ public:
 
   /**
    * @see FiniteElement::face_to_cell_index()
-   *
-   * @note This function has some limitations in 3D. If @p dim is 3, this
-   * function works if either:
-   * 1. @p combined_orientation is the default orientation.
-   * 2. @p combined_orientation is `(false, false, false)` and the triangular
-   * face has no more than one degree of freedom in its interior.
-   * Otherwise this function throws an error.
    */
   virtual unsigned int
   face_to_cell_index(const unsigned int                 face_dof_index,
index 55732e1175daadc2f574b9370509fed0f47b2f04..4259fbde5507fee33ab575cb52e20292e6449fed 100644 (file)
@@ -501,38 +501,45 @@ FE_SimplexPoly<dim, spacedim>::face_to_cell_index(
             break;
 
           case 3:
-            // in 3d, things are difficult. someone will have to think
-            // about how this code here should look like, by drawing a bunch
-            // of pictures of how all the faces can look like with the various
-            // flips and rotations.
-            //
-            // that said, we can implement a couple other situations easily:
-            // if the face orientation is
-            // numbers::default_combined_face_orientation then things are
-            // simple. Likewise if the face orientation is
-            // internal::combined_face_orientation(false,false,false) then we
-            // just know we need to reverse the DoF order on each line.
-            //
-            // this at least allows for tetrahedral meshes where periodic face
-            // pairs are each in one of the two above configurations. Doing so
-            // may turn out to be always possible or it may not, but at least
-            // this is less restrictive.
-            Assert((this->n_dofs_per_line() <= 1) ||
-                     combined_orientation ==
-                       numbers::default_geometric_orientation ||
-                     combined_orientation ==
-                       internal::combined_face_orientation(false, false, false),
-                   ExcNotImplemented());
-
-            if (combined_orientation == numbers::default_geometric_orientation)
-              {
+            {
+              // Line orientations are not consistent between faces of
+              // tetrahedra: e.g., the cell's first line is (0, 1) on face 0 and
+              // (1, 0) on face 1. Hence we have to determine the relative line
+              // orientation to determine how to index dofs along lines.
+              //
+              // face_to_cell_line_orientation() may only be called with
+              // canonical (face, line) pairs. Extract that information and then
+              // also the new canonical face_line_index.
+              const auto cell_line_index =
+                this->reference_cell().face_to_cell_lines(face,
+                                                          face_line,
+                                                          combined_orientation);
+              const auto [canonical_face, canonical_line] =
+                this->reference_cell().standard_line_to_face_and_line_index(
+                  cell_line_index);
+              // Here we don't take into account what the actual orientation of
+              // the line is: that's usually handled inside, e.g.,
+              // face->get_dof_indices().
+              const auto face_line_orientation =
+                this->reference_cell().face_to_cell_line_orientation(
+                  canonical_line,
+                  canonical_face,
+                  combined_orientation,
+                  /*combined_line_orientation =*/
+                  numbers::default_geometric_orientation);
+
+              if (face_line_orientation ==
+                  numbers::default_geometric_orientation)
                 adjusted_dof_index_on_line = dof_index_on_line;
-              }
-            else
-              {
-                adjusted_dof_index_on_line =
-                  this->n_dofs_per_line() - dof_index_on_line - 1;
-              }
+              else
+                {
+                  Assert(face_line_orientation ==
+                           numbers::reverse_line_orientation,
+                         ExcInternalError());
+                  adjusted_dof_index_on_line =
+                    this->n_dofs_per_line() - dof_index_on_line - 1;
+                }
+            }
             break;
 
           default:
@@ -555,9 +562,15 @@ FE_SimplexPoly<dim, spacedim>::face_to_cell_index(
       const unsigned int index =
         face_dof_index - this->get_first_face_quad_index(face);
 
-      // the same is true here as above for the 3d case -- someone will
-      // just have to draw a bunch of pictures. in the meantime,
-      // we can implement the degree <= 3 case in which it is simple
+      // Since polynomials on simplices are typically defined in barycentric
+      // coordinates, handling higher degree elements is not that hard: if the
+      // DoFs come in triples then they simply need to be rotated in the correct
+      // way (as though they were the vertices). However, we don't implement
+      // higher than cubic elements, so that is not yet done here. For example,
+      // for a P4 element a quad will have 3 DoFs, and each of those DoFs will
+      // be on its corresponding vertex's bisector. Hence they can be rotated by
+      // simply calling
+      // ReferenceCells::Triangle::permute_by_combined_orientation().
       Assert((this->n_dofs_per_quad(face) <= 1) ||
                combined_orientation == numbers::default_geometric_orientation,
              ExcNotImplemented());

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.