svMultiPhysics
Loading...
Searching...
No Matches
BasisTraits.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the University of California, and others.
2// SPDX-License-Identifier: BSD-3-Clause
3
4#ifndef SVMP_FE_BASIS_BASISTRAITS_H
5#define SVMP_FE_BASIS_BASISTRAITS_H
6
7/**
8 * @file BasisTraits.h
9 * @brief Reference-topology vocabulary (BasisTopology) and the internal
10 * ElementType/topology/order maps.
11 */
12
13#include "Types.h"
14
15#include <cstddef>
16
17namespace svmp::FE::basis {
18
19/**
20 * @brief Reference-cell topology of a basis (the shape, independent of order).
21 * @ingroup FE_Basis
22 *
23 * @details Together with a polynomial order this is the order-agnostic identity a
24 * basis is built from: the arbitrary-order constructors take a BasisTopology and an
25 * order, and BasisRequest::topology selects that path. A named ElementType maps to
26 * one of these through topology().
27 */
28enum class BasisTopology {
29 Unknown, ///< Unrecognized or uninitialized topology.
30 Point, ///< 0D point.
31 Line, ///< 1D line segment.
32 Triangle, ///< 2D triangle (simplex).
33 Quadrilateral, ///< 2D quadrilateral (tensor product).
34 Tetrahedron, ///< 3D tetrahedron (simplex).
35 Hexahedron, ///< 3D hexahedron (tensor product).
36 Wedge, ///< 3D triangular prism.
37};
38
39// The maps below are internal to the Basis module (used to build the basis classes
40// and the factory); they are excluded from the public Doxygen output.
41/** @cond INTERNAL */
42
43// ---------------------------------------------------------------------------
44// ElementType / BasisTopology / order mapping helpers.
45//
46// A basis identity is expressed three ways -- a named ElementType, a
47// (BasisTopology, order) pair, and a reference dimension -- and the constexpr
48// maps below convert between them. They are grouped here so the relationships
49// stay in one place:
50//
51// ElementType -> BasisTopology topology()
52// ElementType -> ElementType canonical_lagrange_type() (alias -> linear representative)
53// ElementType -> order complete_lagrange_alias_order(), named_lagrange_order()
54// BasisTopology -> int (dimension) topology_dimension()
55// BasisTopology -> ElementType lagrange_topology_representative() (lowest-order representative)
56// (BasisTopology, order, family) -> ElementType named_element_for() (inverse of topology() + order())
57//
58// The two ElementType -> order maps differ only at Point1:
59// complete_lagrange_alias_order() returns -1 (a point is not a complete-Lagrange
60// alias) while named_lagrange_order() returns 0 (the point layout's order).
61// named_lagrange_order() is defined in terms of complete_lagrange_alias_order(),
62// so the order-1 / order-2 alias values have a single source of truth.
63// ---------------------------------------------------------------------------
64
65// Reference-cell topology is derived from the single mesh cell-family
66// classification (to_mesh_family) so the basis layer never maintains a parallel
67// ElementType->shape switch; adding an ElementType updates only to_mesh_family.
68// ElementType::Unknown must stay Unknown here: CellFamily has no "unknown"
69// member, so to_mesh_family() falls back to Point for unrecognized types.
70[[nodiscard]] constexpr BasisTopology topology(ElementType type) noexcept {
71 if (type == ElementType::Unknown) {
73 }
74 switch (to_mesh_family(type)) {
75 case CellFamily::Point: return BasisTopology::Point;
76 case CellFamily::Line: return BasisTopology::Line;
77 case CellFamily::Triangle: return BasisTopology::Triangle;
78 case CellFamily::Quad: return BasisTopology::Quadrilateral;
79 case CellFamily::Tetra: return BasisTopology::Tetrahedron;
80 case CellFamily::Hex: return BasisTopology::Hexahedron;
81 case CellFamily::Wedge: return BasisTopology::Wedge;
82 // Pyramid/Polygon/Polyhedron are outside the current basis scope.
83 // BasisTopology::Unknown is a sentinel the basis constructors validate
84 // and convert into a BasisElementCompatibilityException at the call site,
85 // not an error raised from this constexpr noexcept classifier.
86 default: return BasisTopology::Unknown;
87 }
88}
89
90[[nodiscard]] constexpr ElementType canonical_lagrange_type(ElementType type) noexcept {
91 switch (type) {
94 return ElementType::Line2;
100 return ElementType::Quad4;
103 return ElementType::Tetra4;
106 return ElementType::Hex8;
109 return ElementType::Wedge6;
110 default:
111 return type;
112 }
113}
114
115[[nodiscard]] constexpr int complete_lagrange_alias_order(ElementType type) noexcept {
116 switch (type) {
123 return 1;
130 return 2;
131 default:
132 // -1 is a sentinel for "not a complete-Lagrange alias" (serendipity
133 // layouts, pyramids, Unknown), not an error: the LagrangeBasis
134 // (ElementType, order) constructor compares the requested order
135 // against named_lagrange_order() and raises BasisConfigurationException
136 // on mismatch. These classifiers are constexpr noexcept and so cannot
137 // throw themselves.
138 return -1;
139 }
140}
141
142// Reference-space dimension of a basis topology: 0 for points up to 3 for
143// volume topologies; -1 for Unknown.
144[[nodiscard]] constexpr int topology_dimension(BasisTopology top) noexcept {
145 switch (top) {
146 case BasisTopology::Point: return 0;
147 case BasisTopology::Line: return 1;
149 case BasisTopology::Quadrilateral: return 2;
152 case BasisTopology::Wedge: return 3;
153 default: return -1;
154 }
155}
156
157// Lowest-order named element that represents a topology. Used internally to
158// drive the reference-node generators, which key on a canonical ElementType
159// (and re-canonicalize it). This is the inverse of topology() for the linear
160// elements and is purely an implementation detail: the node-count name never
161// leaks into the public basis identity.
162[[nodiscard]] constexpr ElementType lagrange_topology_representative(BasisTopology top) noexcept {
163 switch (top) {
171 default: return ElementType::Unknown;
172 }
173}
174
175// Polynomial order baked into a named Lagrange element layout: 0 for the point,
176// 1 for the linear elements, 2 for the complete-quadratic aliases; -1 for types
177// with no complete-Lagrange order (serendipity, pyramid, Unknown). Unlike
178// complete_lagrange_alias_order this also maps Point1 -> 0, so it is the single
179// source of truth the (ElementType, order) constructor validates against.
180[[nodiscard]] constexpr int named_lagrange_order(ElementType type) noexcept {
181 if (type == ElementType::Point1) {
182 return 0;
183 }
184 return complete_lagrange_alias_order(type);
185}
186
187/** @endcond */
188
189/**
190 * @brief Named ElementType denoted by a (topology, order, family) triple.
191 * @ingroup FE_Basis
192 *
193 * @details Inverse of topology() + order() for the named layouts: returns the
194 * ElementType a basis identity denotes, or ElementType::Unknown when no named
195 * layout exists (order 0 on a non-point topology, any order >= 3, or a reduced
196 * family at an unsupported order). topology() + order() remain the authoritative
197 * identity; callers that want a named ElementType for a basis pass its topology(),
198 * order(), and basis_type() here.
199 *
200 * @param top Reference topology.
201 * @param order Polynomial order.
202 * @param family Basis family; only Serendipity is distinguished from nodal/Lagrange naming.
203 * @return Named ElementType, or ElementType::Unknown when none applies.
204 */
205[[nodiscard]] constexpr ElementType named_element_for(BasisTopology top, int order,
206 BasisType family) noexcept {
207 if (family == BasisType::Serendipity) {
208 switch (top) {
210 return order == 2 ? ElementType::Quad8 : ElementType::Unknown;
212 if (order == 1) { return ElementType::Hex8; }
213 if (order == 2) { return ElementType::Hex20; }
216 return order == 2 ? ElementType::Wedge15 : ElementType::Unknown;
217 default:
219 }
220 }
221
222 // Lagrange (and any nodal family built on the complete layouts).
223 if (top == BasisTopology::Point) {
224 return order == 0 ? ElementType::Point1 : ElementType::Unknown;
225 }
226 switch (order) {
227 case 1:
228 switch (top) {
235 default: return ElementType::Unknown;
236 }
237 case 2:
238 switch (top) {
245 default: return ElementType::Unknown;
246 }
247 default:
249 }
250}
251
252} // namespace svmp::FE::basis
253
254#endif // SVMP_FE_BASIS_BASISTRAITS_H
Fundamental type definitions for the finite element library.
BasisTopology
Reference-cell topology of a basis (the shape, independent of order).
Definition BasisTraits.h:28
constexpr ElementType named_element_for(BasisTopology top, int order, BasisType family) noexcept
Named ElementType denoted by a (topology, order, family) triple.
Definition BasisTraits.h:205
@ Wedge
3D triangular prism.
@ Triangle
2D triangle (simplex).
@ Unknown
Unrecognized or uninitialized topology.
@ Hexahedron
3D hexahedron (tensor product).
@ Quadrilateral
2D quadrilateral (tensor product).
@ Tetrahedron
3D tetrahedron (simplex).
BasisType
Basis function families.
Definition Types.h:247
constexpr svmp::CellFamily to_mesh_family(ElementType elem) noexcept
Convert FE ElementType to Mesh CellFamily.
Definition Types.h:468
ElementType
Reference element types supported by the FE library.
Definition Types.h:215
@ Serendipity
Serendipity elements.
@ Triangle3
3-node triangle
@ Quad9
9-node quadrilateral (bi-quadratic)
@ Wedge6
6-node wedge/prism
@ Wedge15
15-node wedge
@ Quad4
4-node quadrilateral
@ Quad8
8-node quadrilateral (serendipity)
@ Unknown
Unrecognized or uninitialized element type.
@ Wedge18
18-node wedge (complete quadratic)
@ Hex27
27-node hexahedron (tri-quadratic)
@ Point1
1-node point element
@ Triangle6
6-node triangle
@ Hex20
20-node hexahedron (serendipity)
@ Tetra10
10-node tetrahedron
@ Hex8
8-node hexahedron
@ Tetra4
4-node tetrahedron