libMesh
Loading...
Searching...
No Matches
fe_hdiv_grad_test.C
Go to the documentation of this file.
1// libmesh includes
2#include "libmesh/elem.h"
3#include "libmesh/fe.h"
4#include "libmesh/fe_map.h"
5#include "libmesh/mesh.h"
6#include "libmesh/mesh_generation.h"
7#include "libmesh/node.h"
8#include "libmesh/quadrature_gauss.h"
9#include "libmesh/tensor_value.h"
10
11// unit test includes
12#include "test_comm.h"
13
14#include "libmesh_cppunit.h"
15
16using namespace libMesh;
17
25class HDivGradTest : public CppUnit::TestCase
26{
27public:
29
30#if LIBMESH_DIM > 1
33#if LIBMESH_ENABLE_SECOND_DERIVATIVES
36#endif
37#endif
38#if LIBMESH_DIM > 2
41#if LIBMESH_ENABLE_SECOND_DERIVATIVES
44#endif
45#endif
46
48
49public:
50 void setUp() {}
51 void tearDown() {}
52
53#if LIBMESH_DIM > 1
54 // RAVIART_THOMAS dof placement piggybacks on the second-order edge/face
55 // nodes, so the geometric element types must be the second-order ones
56 // (QUAD8, TRI6, ...) even though the RT approximation order used here
57 // is FIRST.
62#endif
63
64#if LIBMESH_DIM > 2
69#endif
70
71private:
72 // Builds a single-element mesh of the given type, optionally distorting
73 // one node so the element's map is non-affine, then checks the HDiv
74 // shape function gradients returned by fe->get_dphi() at every
75 // quadrature point and coordinate direction.
76 void testGradByFiniteDifference(const ElemType elem_type, const bool distort)
77 {
78 LOG_UNIT_TEST;
79
81 unsigned int dim = 0;
82
83 switch (elem_type)
84 {
85 case QUAD8:
86 case TRI6:
87 dim = 2;
89 (mesh, 1, 1, 0., 1., 0., 1., elem_type);
90 break;
91 case HEX27:
92 case TET14:
93 dim = 3;
95 (mesh, 1, 1, 1, 0., 1., 0., 1., 0., 1., elem_type);
96 break;
97 default:
98 libmesh_error_msg("Unsupported element type " << elem_type);
99 }
100
101 auto elem_range = mesh.active_local_element_ptr_range();
102 if (elem_range.begin() == elem_range.end())
103 return;
104 const Elem * elem = *(elem_range.begin());
105
106 if (distort)
107 {
108 // Move one of this element's own vertices partway toward the
109 // element's own vertex average, without touching the associated
110 // edge/face nodes -- this turns the element's boundary curved and
111 // gives the map nonzero second derivatives, exercising the terms
112 // in map_dphi (A and B in the derivation) that vanish identically
113 // on an affine element. For a straight-sided simplex, the signed
114 // volume is an affine function of any single vertex's position,
115 // and moving that vertex to the vertex average reduces the signed
116 // volume to a positive fraction (1/n_vertices) of the original;
117 // moving only partway there is therefore guaranteed to keep the
118 // element non-degenerate, regardless of the element's own size or
119 // shape, unlike a fixed or size-scaled absolute displacement.
120 Node & node = mesh.node_ref(elem->node_id(0));
121 const Point target = elem->vertex_average();
122 for (auto d : make_range(dim))
123 node(d) += Real(0.3) * (target(d) - node(d));
124 }
125
126 const FEType fe_type(FIRST, RAVIART_THOMAS);
127 std::unique_ptr<FEVectorBase> fe(FEVectorBase::build(dim, fe_type));
128
129 const std::vector<std::vector<RealTensor>> & dphi = fe->get_dphi();
130 const std::vector<std::vector<RealGradient>> & phi = fe->get_phi();
131 const std::vector<Point> & xyz = fe->get_xyz();
132
133 QGauss qrule(dim, fe_type.default_quadrature_order());
134 fe->attach_quadrature_rule(&qrule);
135
136 fe->reinit(elem);
137
138 // Copy out what we need before the perturbed reinit() calls below
139 // overwrite fe's internal state.
140 const std::vector<std::vector<RealTensor>> dphi_base = dphi;
141 const std::vector<Point> qpoints = xyz;
142
143 const Real h = 1e-6;
144 const Real tol = 5e-4;
145
146 for (auto qp : index_range(qpoints))
147 {
148 const Point x0 = qpoints[qp];
149
150 for (auto l : make_range(dim))
151 {
152 Point x_plus = x0;
153 x_plus(l) += h;
154 Point x_minus = x0;
155 x_minus(l) -= h;
156
157 std::vector<Point> pts_plus
158 (1, FEMap::inverse_map(dim, elem, x_plus));
159 fe->reinit(elem, &pts_plus);
160 const std::vector<std::vector<RealGradient>> phi_plus = phi;
161
162 std::vector<Point> pts_minus
163 (1, FEMap::inverse_map(dim, elem, x_minus));
164 fe->reinit(elem, &pts_minus);
165 const std::vector<std::vector<RealGradient>> phi_minus = phi;
166
167 for (auto i : index_range(dphi_base))
168 for (auto k : make_range(LIBMESH_DIM))
169 {
170 const Real fd =
171 (phi_plus[i][0](k) - phi_minus[i][0](k)) / (2*h);
172
173 LIBMESH_ASSERT_FP_EQUAL(fd, dphi_base[i][qp](k, l), tol);
174 }
175 }
176 }
177 }
178};
179
unsigned int dim
Verifies HDivFETransformation::map_dphi (the physical-space gradients of H(div)-conforming Raviart-Th...
CPPUNIT_TEST(testHex27Affine)
CPPUNIT_TEST(testTri6NonAffine)
LIBMESH_CPPUNIT_TEST_SUITE(HDivGradTest)
void testTet14NonAffine()
CPPUNIT_TEST(testTet14NonAffine)
CPPUNIT_TEST_SUITE_END()
void testGradByFiniteDifference(const ElemType elem_type, const bool distort)
CPPUNIT_TEST(testTet14Affine)
CPPUNIT_TEST(testHex27NonAffine)
void testQuad8NonAffine()
CPPUNIT_TEST(testQuad8Affine)
void testHex27NonAffine()
CPPUNIT_TEST(testQuad8NonAffine)
CPPUNIT_TEST(testTri6Affine)
This is the base class from which all geometric element types are derived.
Definition elem.h:96
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2605
Point vertex_average() const
Definition elem.C:609
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
Definition fe_map.C:1512
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition fe_type.h:197
Order default_quadrature_order() const
Definition fe_type.h:415
virtual const Node & node_ref(const dof_id_type i) const
Definition mesh_base.h:742
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
A Node is like a Point, but with more information.
Definition node.h:55
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:41
This class implements specific orders of Gauss quadrature.
Communicator * TestCommWorld
CPPUNIT_TEST_SUITE_REGISTRATION(HDivGradTest)
MeshBase & mesh
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_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.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
ElemType
Defines an enum for geometric element types.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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