libMesh
Loading...
Searching...
No Matches
fe_gll_lagrange_agreement_test.C
Go to the documentation of this file.
1// At orders one and two on the tensor product element types, LAGRANGE and the Gauss-Lobatto
2// nodal families have the same shape functions, because the Gauss-Lobatto points of those
3// orders, {-1,1} and {-1,0,1}, are the element nodes. The implementations are independent:
4// LAGRANGE evaluates a closed form for each order, and the Gauss-Lobatto basis evaluates
5// the barycentric formula on its point table. This test pairs each Gauss-Lobatto shape
6// function with the LAGRANGE shape function of the node at the same reference point and
7// checks that their values agree.
8//
9// It catches errors in the point table, the barycentric evaluation, and the tensor index
10// map.
11
12#include <libmesh/elem.h>
13#include <libmesh/enum_fe_family.h>
14#include <libmesh/enum_order.h>
15#include <libmesh/fe_interface.h>
16#include <libmesh/fe_type.h>
17#include <libmesh/int_range.h>
18#include <libmesh/mesh.h>
19#include <libmesh/mesh_generation.h>
20#include <libmesh/parallel_implementation.h>
21#include <libmesh/quadrature_gauss_lobatto.h>
22
23#include "test_comm.h"
24#include "libmesh_cppunit.h"
25
26#include <memory>
27#include <vector>
28
29using namespace libMesh;
30
31template <ElemType elem_type, Order order>
32class FEGLLLagrangeAgreementTest : public CppUnit::TestCase
33{
34protected:
35 std::unique_ptr<Mesh> _mesh;
36 std::string libmesh_suite_name;
37
38public:
39 void setUp()
40 {
41 _mesh = std::make_unique<Mesh>(*TestCommWorld);
42
43 const unsigned int dim = Elem::type_to_dim_map[elem_type];
44
45 if (dim == 1)
46 MeshTools::Generation::build_line(*_mesh, 1, 0., 1., elem_type);
47 else if (dim == 2)
48 MeshTools::Generation::build_square(*_mesh, 1, 1, 0., 1., 0., 1., elem_type);
49 else
50 MeshTools::Generation::build_cube(*_mesh, 1, 1, 1, 0., 1., 0., 1., 0., 1., elem_type);
51 }
52
53 void tearDown() { _mesh.reset(); }
54
56 Point gll_point(const unsigned int i, const unsigned int dim)
57 {
58 const unsigned int n = static_cast<unsigned int>(order) + 1;
59
60 // QGaussLobatto chooses n points for order 2n-3
61 QGaussLobatto rule(1, static_cast<Order>(2*n - 3));
62 rule.init(EDGE2);
63
64 Point q;
65 unsigned int stride = 1;
66
67 for (const auto d : make_range(dim))
68 {
69 q(d) = rule.qp((i / stride) % n)(0);
70 stride *= n;
71 }
72
73 return q;
74 }
75
77 unsigned int node_at(const Elem & elem, const Point & q)
78 {
79 unsigned int found = invalid_uint;
80
81 for (const auto n : elem.node_index_range())
83 {
84 // Each shape function must pair with exactly one node
85 CPPUNIT_ASSERT_EQUAL(invalid_uint, found);
86 found = n;
87 }
88
89 return found;
90 }
91
93 {
94 LOG_UNIT_TEST;
95
96 const unsigned int dim = Elem::type_to_dim_map[elem_type];
97
98 const FEType gll_type(order, L2_LAGRANGE_GLL);
99 const FEType lagrange_type(order, LAGRANGE);
100
101 // Sample on a grid spread over the reference element, so that most points lie between
102 // the interpolation points
103 std::vector<Point> samples;
104 for (const auto a : make_range(-3, 4))
105 for (const auto b : make_range(-3, 4))
106 for (const auto c : make_range(-3, 4))
107 samples.emplace_back(a/7., (dim > 1) ? b/7. : 0., (dim > 2) ? c/7. : 0.);
108
109 unsigned int n_paired = 0;
110
111 for (const auto * elem : _mesh->active_local_element_ptr_range())
112 {
113 const unsigned int n_gll = FEInterface::n_shape_functions(gll_type, elem);
114 const unsigned int n_lag = FEInterface::n_shape_functions(lagrange_type, elem);
115
116 // The two bases span the same space here, so their sizes match
117 CPPUNIT_ASSERT_EQUAL(n_lag, n_gll);
118
119 for (const auto i : make_range(n_gll))
120 {
121 const unsigned int n = node_at(*elem, gll_point(i, dim));
122 CPPUNIT_ASSERT(n != invalid_uint);
123
124 for (const Point & q : samples)
125 LIBMESH_ASSERT_FP_EQUAL(FEInterface::shape(lagrange_type, elem, n, q),
126 FEInterface::shape(gll_type, elem, i, q),
128
129 ++n_paired;
130 }
131 }
132
133 _mesh->comm().sum(n_paired);
134 CPPUNIT_ASSERT(n_paired > 0);
135 }
136};
137
138#define INSTANTIATE_FEGLLAGREEMENTTEST(elemtype, order) \
139 class FEGLLLagrangeAgreementTest_##order##_##elemtype : \
140 public FEGLLLagrangeAgreementTest<elemtype, order> { \
141 public: \
142 FEGLLLagrangeAgreementTest_##order##_##elemtype() : \
143 FEGLLLagrangeAgreementTest<elemtype, order>() { \
144 if (unitlog->summarized_logs_enabled()) \
145 this->libmesh_suite_name = "FEGLLLagrangeAgreementTest"; \
146 else \
147 this->libmesh_suite_name = \
148 "FEGLLLagrangeAgreementTest_" #order "_" #elemtype; \
149 } \
150 CPPUNIT_TEST_SUITE( FEGLLLagrangeAgreementTest_##order##_##elemtype ); \
151 CPPUNIT_TEST( testAgreesWithLagrange ); \
152 CPPUNIT_TEST_SUITE_END(); \
153 }; \
154 \
155 CPPUNIT_TEST_SUITE_REGISTRATION( FEGLLLagrangeAgreementTest_##order##_##elemtype )
156
157// Element types whose nodes are the Gauss-Lobatto points of the given order. QUAD8 and
158// HEX20 are excluded because LAGRANGE on those serendipity types spans a smaller space than
159// the tensor product basis.
162
163#if LIBMESH_DIM > 1
166#endif
167
168#if LIBMESH_DIM > 2
171#endif
unsigned int dim
unsigned int node_at(const Elem &elem, const Point &q)
The node of elem whose reference position is q, or invalid_uint if it has none.
Point gll_point(const unsigned int i, const unsigned int dim)
The interpolation point of Gauss-Lobatto shape function i.
This is the base class from which all geometric element types are derived.
Definition elem.h:96
static const unsigned int type_to_dim_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the geometric dimension of the ele...
Definition elem.h:649
IntRange< unsigned short > node_index_range() const
Definition elem.h:2821
virtual Point master_point(const unsigned int i) const =0
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
static unsigned int n_shape_functions(const unsigned int dim, const FEType &fe_t, const ElemType t)
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition fe_type.h:197
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:41
Point qp(const unsigned int i) const
Definition quadrature.h:179
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
Initializes the data structures for a quadrature rule for the element e.
Definition quadrature.C:65
This class implements Gauss-Lobatto quadrature for 1D elements and 2D/3D tensor product elements.
bool relative_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
static const Real b
Communicator * TestCommWorld
INSTANTIATE_FEGLLAGREEMENTTEST(EDGE2, FIRST)
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
The libMesh namespace provides an interface to certain functionality in the library.
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition libmesh.h:303
static constexpr Real TOLERANCE
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176