* result is always @p true. More information on the topic can be found in the
* @ref GlossFaceOrientation "glossary" article on this topic.
*
+ * In order to allow all kinds of meshes in 3d, including
+ * <em>Moebius</em>-loops, for example, a face might even be rotated looking
+ * from one cell, whereas it is according to the standard looking at it from the
+ * neighboring cell sharing that particular face. In order to cope with this,
+ * two flags <tt>face_flip</tt> and <tt>face_rotation</tt> are available, to
+ * represent rotations by 90 and 180 degree, respectively. Setting both flags
+ * accumulates to a rotation of 270 degrees (all counterclockwise). You can ask
+ * the cell for these flags like for the <tt>face_orientation</tt>. In order to
+ * enable rotated faces, even lines can deviate from their standard direction in
+ * 3d. This information is available as the <tt>line_orientation</tt> flag for
+ * cells and faces in 3d. Again, this is something that should be internal to
+ * the library and application program will probably never have to bother about
+ * it.
+ *
*
* <h4>Children</h4>
*
* Instantiations in the manual).
*
* @ingroup grid geomprimitives
- * @author Wolfgang Bangerth, 1998, Ralf Hartmann, 2005
+ * @author Wolfgang Bangerth, 1998, Ralf Hartmann, 2005, Tobias Leicht, 2007
*/
template <int dim>
struct GeometryInfo
* 2, on face 3 they are 2 and 3,
* etc.
*
- * For three spatial dimensions, the
- * exact order of the children is laid
- * down in the general documentation of
- * this class. Through the
- * <tt>face_orientation</tt> argument
- * this function handles faces oriented
- * in both, the standard and non-standard
- * orientation.
+ * For three spatial dimensions, the exact
+ * order of the children is laid down in
+ * the general documentation of this
+ * class.
+ *
+ * Through the <tt>face_orientation</tt>,
+ * <tt>face_flip</tt> and
+ * <tt>face_rotation</tt> arguments this
+ * function handles faces oriented in the
+ * standard and non-standard orientation.
* <tt>face_orientation</tt> defaults to
- * <tt>true</tt> (standard orientation)
- * and has no effect in 2d. The concept
- * of face orientations is explained in
- * this @ref GlossFaceOrientation "glossary"
+ * <tt>true</tt>, <tt>face_flip</tt> and
+ * <tt>face_rotation</tt> default to
+ * <tt>false</tt> (standard orientation)
+ * and has no effect in 2d. The concept of
+ * face orientations is explained in this
+ * @ref GlossFaceOrientation "glossary"
* entry.
*/
static unsigned int child_cell_on_face (const unsigned int face,
const unsigned int subface,
- const bool face_orientation = true);
+ const bool face_orientation = true,
+ const bool face_flip = false,
+ const bool face_rotation = false);
/**
* Map line vertex number to cell
* face <tt>face</tt>, e.g.
* <tt>GeometryInfo<2>::face_to_cell_vertices(3,0)=2</tt>.
*
- * Through the
- * <tt>face_orientation</tt>
- * argument this function handles
- * faces oriented in both, the
- * standard and non-standard
- * orientation.
- * <tt>face_orientation</tt>
- * defaults to <tt>true</tt>
- * (standard orientation) and has
- * no effect in 2d.
+ * Through the <tt>face_orientation</tt>,
+ * <tt>face_flip</tt> and
+ * <tt>face_rotation</tt> arguments this
+ * function handles faces oriented in the
+ * standard and non-standard orientation.
+ * <tt>face_orientation</tt> defaults to
+ * <tt>true</tt>, <tt>face_flip</tt> and
+ * <tt>face_rotation</tt> default to
+ * <tt>false</tt> (standard orientation)
+ * and has no effect in 2d.
*
* As the children of a cell are
* ordered according to the
*/
static unsigned int face_to_cell_vertices (const unsigned int face,
const unsigned int vertex,
- const bool face_orientation = true);
+ const bool face_orientation = true,
+ const bool face_flip = false,
+ const bool face_rotation = false);
/**
* Map face line number to cell
* <tt>face</tt>, e.g.
* <tt>GeometryInfo<3>::face_to_cell_lines(5,0)=4</tt>.
*
- * Through the
- * <tt>face_orientation</tt>
- * argument this function handles
- * faces oriented in both, the
- * standard and non-standard
- * orientation.
- * <tt>face_orientation</tt>
- * defaults to <tt>true</tt>
- * (standard orientation) and has
- * no effect in 2d.
+ * Through the <tt>face_orientation</tt>,
+ * <tt>face_flip</tt> and
+ * <tt>face_rotation</tt> arguments this
+ * function handles faces oriented in the
+ * standard and non-standard orientation.
+ * <tt>face_orientation</tt> defaults to
+ * <tt>true</tt>, <tt>face_flip</tt> and
+ * <tt>face_rotation</tt> default to
+ * <tt>false</tt> (standard orientation)
+ * and has no effect in 2d.
*/
static unsigned int face_to_cell_lines (const unsigned int face,
const unsigned int line,
- const bool face_orientation = true);
+ const bool face_orientation = true,
+ const bool face_flip = false,
+ const bool face_rotation = false);
+
+ /**
+ * Map the vertex index @p vertex of a face
+ * in standard orientation to one of a face
+ * with arbitrary @p face_orientation, @p
+ * face_flip and @p face_rotation. The
+ * values of these three flags default to
+ * <tt>true</tt>, <tt>false</tt> and
+ * <tt>false</tt>, respectively. this
+ * combination describes a face in standard
+ * orientation.
+ *
+ * This function is only implemented in 3D.
+ */
+ static unsigned int standard_to_real_face_vertex (const unsigned int vertex,
+ const bool face_orientation = true,
+ const bool face_flip = false,
+ const bool face_rotation = false);
+
+ /**
+ * Map the vertex index @p vertex of a face
+ * with arbitrary @p face_orientation, @p
+ * face_flip and @p face_rotation to a face
+ * in standard orientation. The values of
+ * these three flags default to
+ * <tt>true</tt>, <tt>false</tt> and
+ * <tt>false</tt>, respectively. this
+ * combination describes a face in standard
+ * orientation.
+ *
+ * This function is only implemented in 3D.
+ */
+ static unsigned int real_to_standard_face_vertex (const unsigned int vertex,
+ const bool face_orientation = true,
+ const bool face_flip = false,
+ const bool face_rotation = false);
+
+ /**
+ * Map the line index @p line of a face
+ * in standard orientation to one of a face
+ * with arbitrary @p face_orientation, @p
+ * face_flip and @p face_rotation. The
+ * values of these three flags default to
+ * <tt>true</tt>, <tt>false</tt> and
+ * <tt>false</tt>, respectively. this
+ * combination describes a face in standard
+ * orientation.
+ *
+ * This function is only implemented in 3D.
+ */
+ static unsigned int standard_to_real_face_line (const unsigned int line,
+ const bool face_orientation = true,
+ const bool face_flip = false,
+ const bool face_rotation = false);
+
+ /**
+ * Map the line index @p line of a face
+ * with arbitrary @p face_orientation, @p
+ * face_flip and @p face_rotation to a face
+ * in standard orientation. The values of
+ * these three flags default to
+ * <tt>true</tt>, <tt>false</tt> and
+ * <tt>false</tt>, respectively. this
+ * combination describes a face in standard
+ * orientation.
+ *
+ * This function is only implemented in 3D.
+ */
+ static unsigned int real_to_standard_face_line (const unsigned int line,
+ const bool face_orientation = true,
+ const bool face_flip = false,
+ const bool face_rotation = false);
/**
* Return the position of the @p ith
{ invalid_unsigned_int, invalid_unsigned_int, invalid_unsigned_int, invalid_unsigned_int },
{ invalid_unsigned_int, invalid_unsigned_int, invalid_unsigned_int, invalid_unsigned_int }};
+
+template <>
+unsigned int
+GeometryInfo<3>::standard_to_real_face_vertex(const unsigned int vertex,
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
+{
+ Assert(vertex<GeometryInfo<3>::vertices_per_face,
+ ExcIndexRange(vertex,0,GeometryInfo<3>::vertices_per_face));
+
+ // set up a table to make sure that
+ // we handle non-standard faces correctly
+ //
+ // so set up a table that for each vertex (of
+ // a quad in standard position) describes
+ // which vertex to take
+ //
+ // first index: four vertices 0...3
+ //
+ // second index: face_orientation; 0:
+ // opposite normal, 1: standard
+ //
+ // third index: face_flip; 0: standard, 1:
+ // face rotated by 180 degrees
+ //
+ // forth index: face_rotation: 0: standard,
+ // 1: face rotated by 90 degrees
+
+ static const unsigned int vertex_translation[4][2][2][2] =
+ { { { { 0, 2 }, // vertex 0, face_orientation=false, face_flip=false, face_rotation=false and true
+ { 3, 1 }}, // vertex 0, face_orientation=false, face_flip=true, face_rotation=false and true
+ { { 0, 2 }, // vertex 0, face_orientation=true, face_flip=false, face_rotation=false and true
+ { 3, 1 }}},// vertex 0, face_orientation=true, face_flip=true, face_rotation=false and true
+
+ { { { 2, 3 }, // vertex 1 ...
+ { 1, 0 }},
+ { { 1, 0 },
+ { 2, 3 }}},
+
+ { { { 1, 0 }, // vertex 2 ...
+ { 2, 3 }},
+ { { 2, 3 },
+ { 1, 0 }}},
+
+ { { { 3, 1 }, // vertex 3 ...
+ { 0, 2 }},
+ { { 3, 1 },
+ { 0, 2 }}}};
+
+ return vertex_translation[vertex][face_orientation][face_flip][face_rotation];
+}
+
+
+
+template <int dim>
+unsigned int
+GeometryInfo<dim>::standard_to_real_face_vertex(const unsigned int vertex,
+ const bool,
+ const bool,
+ const bool)
+{
+ Assert(false, ExcNotImplemented());
+ return vertex;
+
+}
+
+
+
+template <>
+unsigned int
+GeometryInfo<3>::real_to_standard_face_vertex(const unsigned int vertex,
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
+{
+ Assert(vertex<GeometryInfo<3>::vertices_per_face,
+ ExcIndexRange(vertex,0,GeometryInfo<3>::vertices_per_face));
+
+ // set up a table to make sure that
+ // we handle non-standard faces correctly
+ //
+ // so set up a table that for each vertex (of
+ // a quad in standard position) describes
+ // which vertex to take
+ //
+ // first index: four vertices 0...3
+ //
+ // second index: face_orientation; 0:
+ // opposite normal, 1: standard
+ //
+ // third index: face_flip; 0: standard, 1:
+ // face rotated by 180 degrees
+ //
+ // forth index: face_rotation: 0: standard,
+ // 1: face rotated by 90 degrees
+
+ static const unsigned int vertex_translation[4][2][2][2] =
+ { { { { 0, 2 }, // vertex 0, face_orientation=false, face_flip=false, face_rotation=false and true
+ { 3, 1 }}, // vertex 0, face_orientation=false, face_flip=true, face_rotation=false and true
+ { { 0, 1 }, // vertex 0, face_orientation=true, face_flip=false, face_rotation=false and true
+ { 3, 2 }}},// vertex 0, face_orientation=true, face_flip=true, face_rotation=false and true
+
+ { { { 2, 3 }, // vertex 1 ...
+ { 1, 0 }},
+ { { 1, 3 },
+ { 2, 0 }}},
+
+ { { { 1, 0 }, // vertex 2 ...
+ { 2, 3 }},
+ { { 2, 0 },
+ { 1, 3 }}},
+
+ { { { 3, 1 }, // vertex 3 ...
+ { 0, 2 }},
+ { { 3, 2 },
+ { 0, 1 }}}};
+
+ return vertex_translation[vertex][face_orientation][face_flip][face_rotation];
+}
+
+
+
+template <int dim>
+unsigned int
+GeometryInfo<dim>::real_to_standard_face_vertex(const unsigned int vertex,
+ const bool,
+ const bool,
+ const bool)
+{
+ Assert(false, ExcNotImplemented());
+ return vertex;
+
+}
+
+
+
+template <>
+unsigned int
+GeometryInfo<3>::standard_to_real_face_line(const unsigned int line,
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
+{
+ Assert(line<GeometryInfo<3>::lines_per_face,
+ ExcIndexRange(line,0,GeometryInfo<3>::lines_per_face));
+
+
+ // make sure we handle
+ // non-standard faces correctly
+ //
+ // so set up a table that for each line (of a
+ // quad) describes which line to take
+ //
+ // first index: four lines 0...3
+ //
+ // second index: face_orientation; 0:
+ // opposite normal, 1: standard
+ //
+ // third index: face_flip; 0: standard, 1:
+ // face rotated by 180 degrees
+ //
+ // forth index: face_rotation: 0: standard,
+ // 1: face rotated by 90 degrees
+
+ static const unsigned int line_translation[4][2][2][2] =
+ { { { { 2, 0 }, // line 0, face_orientation=false, face_flip=false, face_rotation=false and true
+ { 3, 1 }}, // line 0, face_orientation=false, face_flip=true, face_rotation=false and true
+ { { 0, 3 }, // line 0, face_orientation=true, face_flip=false, face_rotation=false and true
+ { 1, 2 }}},// line 0, face_orientation=true, face_flip=true, face_rotation=false and true
+
+ { { { 3, 1 }, // line 1 ...
+ { 2, 0 }},
+ { { 1, 2 },
+ { 0, 3 }}},
+
+ { { { 0, 3 }, // line 2 ...
+ { 1, 2 }},
+ { { 2, 0 },
+ { 3, 1 }}},
+
+ { { { 1, 2 }, // line 3 ...
+ { 0, 3 }},
+ { { 3, 1 },
+ { 2, 0 }}}};
+
+ return line_translation[line][face_orientation][face_flip][face_rotation];
+}
+
+
+
+template <int dim>
+unsigned int
+GeometryInfo<dim>::standard_to_real_face_line(const unsigned int line,
+ const bool,
+ const bool,
+ const bool)
+{
+ Assert(false, ExcNotImplemented());
+ return line;
+}
+
+
+
+template <>
+unsigned int
+GeometryInfo<3>::real_to_standard_face_line(const unsigned int line,
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
+{
+ Assert(line<GeometryInfo<3>::lines_per_face,
+ ExcIndexRange(line,0,GeometryInfo<3>::lines_per_face));
+
+
+ // make sure we handle
+ // non-standard faces correctly
+ //
+ // so set up a table that for each line (of a
+ // quad) describes which line to take
+ //
+ // first index: four lines 0...3
+ //
+ // second index: face_orientation; 0:
+ // opposite normal, 1: standard
+ //
+ // third index: face_flip; 0: standard, 1:
+ // face rotated by 180 degrees
+ //
+ // forth index: face_rotation: 0: standard,
+ // 1: face rotated by 90 degrees
+
+ static const unsigned int line_translation[4][2][2][2] =
+ { { { { 2, 0 }, // line 0, face_orientation=false, face_flip=false, face_rotation=false and true
+ { 3, 1 }}, // line 0, face_orientation=false, face_flip=true, face_rotation=false and true
+ { { 0, 2 }, // line 0, face_orientation=true, face_flip=false, face_rotation=false and true
+ { 1, 3 }}},// line 0, face_orientation=true, face_flip=true, face_rotation=false and true
+
+ { { { 3, 1 }, // line 1 ...
+ { 2, 0 }},
+ { { 1, 3 },
+ { 0, 2 }}},
+
+ { { { 0, 3 }, // line 2 ...
+ { 1, 2 }},
+ { { 2, 1 },
+ { 3, 0 }}},
+
+ { { { 1, 2 }, // line 3 ...
+ { 0, 3 }},
+ { { 3, 0 },
+ { 2, 1 }}}};
+
+ return line_translation[line][face_orientation][face_flip][face_rotation];
+}
+
+
+
+template <int dim>
+unsigned int
+GeometryInfo<dim>::real_to_standard_face_line(const unsigned int line,
+ const bool,
+ const bool,
+ const bool)
+{
+ Assert(false, ExcNotImplemented());
+ return line;
+}
+
+
+
template <>
unsigned int
GeometryInfo<1>::child_cell_on_face (const unsigned int face,
const unsigned int subface,
- const bool)
+ const bool, const bool, const bool)
{
Assert (face<faces_per_cell, ExcIndexRange(face, 0, faces_per_cell));
Assert (subface<subfaces_per_face,
unsigned int
GeometryInfo<2>::child_cell_on_face (const unsigned int face,
const unsigned int subface,
- const bool)
+ const bool, const bool, const bool)
{
Assert (face<faces_per_cell, ExcIndexRange(face, 0, faces_per_cell));
Assert (subface<subfaces_per_face, ExcIndexRange(subface, 0, subfaces_per_face));
unsigned int
GeometryInfo<3>::child_cell_on_face (const unsigned int face,
const unsigned int subface,
- const bool face_orientation)
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
{
Assert (face<faces_per_cell, ExcIndexRange(face, 0, faces_per_cell));
Assert (subface<subfaces_per_face, ExcIndexRange(subface, 0, subfaces_per_face));
- static const unsigned int flip[subfaces_per_face] = { 0, 2, 1, 3 };
-
static const unsigned
subcells[faces_per_cell][subfaces_per_face] = {{0, 2, 4, 6},
{1, 3, 5, 7},
{2, 6, 3, 7},
{0, 1, 2, 3},
{4, 5, 6, 7}};
- return face_orientation ? subcells[face][subface] : subcells[face][flip[subface]];
+ return subcells[face][real_to_standard_face_vertex(subface,
+ face_orientation,
+ face_flip,
+ face_rotation)];
}
template <>
unsigned int
GeometryInfo<4>::child_cell_on_face (const unsigned int,
- const unsigned int,
- const bool)
+ const unsigned int,
+ const bool, const bool, const bool)
{
Assert(false, ExcNotImplemented());
return invalid_unsigned_int;
unsigned int
GeometryInfo<1>::face_to_cell_lines (const unsigned int face,
const unsigned int line,
- const bool)
+ const bool, const bool, const bool)
{
Assert (face+1<faces_per_cell+1, ExcIndexRange(face, 0, faces_per_cell));
Assert (line+1<lines_per_face+1, ExcIndexRange(line, 0, lines_per_face));
unsigned int
GeometryInfo<2>::face_to_cell_lines (const unsigned int face,
const unsigned int line,
- const bool)
+ const bool, const bool, const bool)
{
Assert (face<faces_per_cell, ExcIndexRange(face, 0, faces_per_cell));
Assert (line<lines_per_face, ExcIndexRange(line, 0, lines_per_face));
unsigned int
GeometryInfo<3>::face_to_cell_lines (const unsigned int face,
const unsigned int line,
- const bool face_orientation)
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
{
Assert (face<faces_per_cell, ExcIndexRange(face, 0, faces_per_cell));
Assert (line<lines_per_face, ExcIndexRange(line, 0, lines_per_face));
- // also represented by (line+2)%4
- static const unsigned int flip[lines_per_face] = { 2, 3, 0, 1 };
-
static const unsigned
lines[faces_per_cell][lines_per_face] = {{8,10, 0, 4}, // left face
{9,11, 1, 5}, // right face
{3, 7,10,11}, // back face
{0, 1, 2, 3}, // bottom face
{4, 5, 6, 7}};// top face
- return face_orientation ? lines[face][line] : lines[face][flip[line]];
+ return lines[face][real_to_standard_face_line(line,
+ face_orientation,
+ face_flip,
+ face_rotation)];
}
unsigned int
GeometryInfo<dim>::face_to_cell_lines (const unsigned int,
const unsigned int,
- const bool)
+ const bool, const bool, const bool)
{
Assert(false, ExcNotImplemented());
return invalid_unsigned_int;
unsigned int
GeometryInfo<dim>::face_to_cell_vertices (const unsigned int face,
const unsigned int vertex,
- const bool face_orientation)
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
{
- return child_cell_on_face(face, vertex, face_orientation);
+ return child_cell_on_face(face, vertex,
+ face_orientation, face_flip, face_rotation);
}