1 #include <libmesh/elem.h> 2 #include <libmesh/enum_quadrature_type.h> 3 #include <libmesh/quadrature.h> 4 #include <libmesh/string_to_enum.h> 5 #include <libmesh/utility.h> 18 #define TEST_ONE_ORDER(qtype, order, maxorder) \ 19 CPPUNIT_TEST( testBuild<qtype MACROCOMMA order> ); \ 20 CPPUNIT_TEST( test1DWeights<qtype MACROCOMMA order MACROCOMMA maxorder> ); \ 21 CPPUNIT_TEST( test2DWeights<qtype MACROCOMMA order MACROCOMMA maxorder> ); \ 22 CPPUNIT_TEST( test3DWeights<qtype MACROCOMMA order MACROCOMMA maxorder> ); 24 #define TEST_ONE_ORDER(qtype, order, maxorder) \ 25 CPPUNIT_TEST( testBuild<qtype MACROCOMMA order> ); \ 26 CPPUNIT_TEST( test1DWeights<qtype MACROCOMMA order MACROCOMMA maxorder> ); \ 27 CPPUNIT_TEST( test2DWeights<qtype MACROCOMMA order MACROCOMMA maxorder> ); 29 #define TEST_ONE_ORDER(qtype, order, maxorder) \ 30 CPPUNIT_TEST( testBuild<qtype MACROCOMMA order> ); \ 31 CPPUNIT_TEST( test1DWeights<qtype MACROCOMMA order MACROCOMMA maxorder> ); 35 #define mymin(a, b) (a < b ? a : b) 37 #define TEST_NINTH_ORDER(qtype, maxorder) \ 38 TEST_ONE_ORDER(qtype, FIRST, mymin(1,maxorder)); \ 39 TEST_ONE_ORDER(qtype, SECOND, mymin(2,maxorder)); \ 40 TEST_ONE_ORDER(qtype, THIRD, mymin(3,maxorder)); \ 41 TEST_ONE_ORDER(qtype, FOURTH, mymin(4,maxorder)); \ 42 TEST_ONE_ORDER(qtype, FIFTH, mymin(5,maxorder)); \ 43 TEST_ONE_ORDER(qtype, SIXTH, mymin(6,maxorder)); \ 44 TEST_ONE_ORDER(qtype, SEVENTH, mymin(7,maxorder)); \ 45 TEST_ONE_ORDER(qtype, EIGHTH, mymin(8,maxorder)); \ 46 TEST_ONE_ORDER(qtype, NINTH, mymin(9,maxorder)); 48 #define TEST_TWENTIETH_ORDER(qtype, maxorder) \ 49 TEST_NINTH_ORDER(qtype, maxorder) \ 50 TEST_ONE_ORDER(qtype, TENTH, mymin(10,maxorder)); \ 51 TEST_ONE_ORDER(qtype, ELEVENTH, mymin(11,maxorder)); \ 52 TEST_ONE_ORDER(qtype, TWELFTH, mymin(12,maxorder)); \ 53 TEST_ONE_ORDER(qtype, THIRTEENTH, mymin(13,maxorder));\ 54 TEST_ONE_ORDER(qtype, FOURTEENTH, mymin(14,maxorder));\ 55 TEST_ONE_ORDER(qtype, FIFTEENTH, mymin(15,maxorder)); \ 56 TEST_ONE_ORDER(qtype, SIXTEENTH, mymin(16,maxorder)); \ 57 TEST_ONE_ORDER(qtype, SEVENTEENTH, mymin(17,maxorder));\ 58 TEST_ONE_ORDER(qtype, EIGHTEENTH, mymin(18,maxorder));\ 59 TEST_ONE_ORDER(qtype, NINETEENTH, mymin(19,maxorder));\ 60 TEST_ONE_ORDER(qtype, TWENTIETH, mymin(20,maxorder)); 62 #define LIBMESH_ASSERT_REALS_EQUAL(first, second, tolerance) \ 63 if (std::abs(first-second) >= tolerance) \ 65 std::cerr << "first = " << first << std::endl; \ 66 std::cerr << "second = " << second << std::endl; \ 67 std::cerr << "error = " << std::abs(first-second) << std::endl; \ 68 std::cerr << "tolerance = " << tolerance << std::endl; \ 70 CPPUNIT_ASSERT (std::abs(first-second) < tolerance) 76 TEST_TWENTIETH_ORDER(
QGAUSS, 9999);
81 TEST_NINTH_ORDER(
QGRID, 1);
113 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA TWENTYFIRST MACROCOMMA 21> );
114 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA TWENTYFIFTH MACROCOMMA 25> );
115 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA TWENTYSEVENTH MACROCOMMA 27> );
116 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA TWENTYNINTH MACROCOMMA 29> );
117 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA THIRTYFIRST MACROCOMMA 31> );
118 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA THIRTYTHIRD MACROCOMMA 33> );
119 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA THIRTYFIFTH MACROCOMMA 35> );
120 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA THIRTYSEVENTH MACROCOMMA 37> );
121 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA THIRTYNINTH MACROCOMMA 39> );
122 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA FORTYFIRST MACROCOMMA 41> );
123 CPPUNIT_TEST( test1DWeights<QGAUSS MACROCOMMA FORTYTHIRD MACROCOMMA 43> );
126 CPPUNIT_TEST( testMonomialQuadrature );
129 CPPUNIT_TEST( testNodalQuadrature );
133 CPPUNIT_TEST( testTriQuadrature );
138 CPPUNIT_TEST( testTetQuadrature );
142 CPPUNIT_TEST( testJacobi );
144 CPPUNIT_TEST_SUITE_END();
151 int xp,
int yp,
int zp,
155 for (
unsigned int qp=0; qp<qrule.
n_points(); qp++)
168 LIBMESH_ASSERT_REALS_EQUAL(true_value, sum, quadrature_tolerance);
173 const std::function<
Real(
int,
int,
int)> & true_value,
177 unsigned int dim = elem->dim();
178 std::unique_ptr<QBase> qrule =
186 qrule->allow_nodal_pyramid_quadrature =
true;
190 const int max_y_order =
dim>1 ? 0 : exactorder;
191 const int max_z_order =
dim>2 ? 0 : exactorder;
193 for (
int xp=0; xp <= exactorder; ++xp)
194 for (
int yp=0; yp <= max_y_order; ++yp)
195 for (
int zp=0; zp <= max_z_order; ++zp)
198 if (xp + yp + zp > exactorder)
201 const Real exact = true_value(xp, yp, zp);
202 testPolynomial(*qrule, xp, yp, zp, exact);
206 const std::function<Real(int,int,int)> edge_integrals =
208 return (mode % 2) ? 0 : (
Real(2.0) / (mode+1));
211 const std::function<Real(int,int,int)> quad_integrals =
212 [](
int modex,
int modey,
int) {
213 const Real exactx = (modex % 2) ?
214 0 : (
Real(2.0) / (modex+1));
216 const Real exacty = (modey % 2) ?
217 0 : (
Real(2.0) / (modey+1));
219 return exactx*exacty;
222 const std::function<Real(int,int,int)> tri_integrals =
223 [](
int x_power,
int y_power,
int) {
225 Real analytical = 1.0;
228 larger_power = std::max(x_power, y_power),
229 smaller_power = std::min(x_power, y_power);
233 std::vector<unsigned>
234 numerator(smaller_power > 1 ? smaller_power-1 : 0),
235 denominator(2+smaller_power);
238 std::iota(numerator.begin(), numerator.end(), 2);
239 std::iota(denominator.begin(), denominator.end(), larger_power+1);
242 for (std::size_t i=0; i<denominator.size(); ++i)
244 if (i < numerator.size())
245 analytical *= numerator[i];
246 analytical /= denominator[i];
251 const std::function<Real(int,int,int)> hex_integrals =
252 [](
int modex,
int modey,
int modez) {
253 const Real exactx = (modex % 2) ?
254 0 : (
Real(2.0) / (modex+1));
256 const Real exacty = (modey % 2) ?
257 0 : (
Real(2.0) / (modey+1));
259 const Real exactz = (modez % 2) ?
260 0 : (
Real(2.0) / (modez+1));
262 return exactx*exacty*exactz;
265 const std::function<Real(int,int,int)> tet_integrals =
266 [](
int x_power,
int y_power,
int z_power) {
268 Real analytical = 1.0;
271 int sorted_powers[3] = {x_power, y_power, z_power};
272 std::sort(sorted_powers, sorted_powers+3);
277 numerator_1(sorted_powers[0] > 1 ? sorted_powers[0]-1 : 0),
278 numerator_2(sorted_powers[1] > 1 ? sorted_powers[1]-1 : 0),
279 denominator(3 + sorted_powers[0] + sorted_powers[1]);
282 std::iota(numerator_1.begin(), numerator_1.end(), 2);
283 std::iota(numerator_2.begin(), numerator_2.end(), 2);
284 std::iota(denominator.begin(), denominator.end(), sorted_powers[2]+1);
287 for (std::size_t i=0; i<denominator.size(); ++i)
289 if (i < numerator_1.size())
290 analytical *= numerator_1[i];
292 if (i < numerator_2.size())
293 analytical *= numerator_2[i];
295 analytical /= denominator[i];
300 const std::function<Real(int,int,int)> prism_integrals =
301 [
this](
int modex,
int modey,
int modez) {
302 const Real exactz = (modez % 2) ?
303 0 : (
Real(2.0) / (modez+1));
305 return exactz * tri_integrals(modex, modey, 0);
308 const std::function<Real(int,int,int)> pyramid_integrals =
309 [](
int modex,
int modey,
int modez) {
313 if (modex%2 || modey%2)
316 return Real(4)/((modex+1)*(modey+1)*binom*(modex+modey+modez+3));
331 const std::vector<std::vector<ElemType>> all_types =
340 const std::function<Real(int,int,int)> true_values[] =
350 for (
ElemType elem_type : all_types[i])
352 const unsigned int order =
Elem::build(elem_type)->default_order();
354 unsigned int exactorder = order;
361 if (elem_type ==
TRI6 || elem_type ==
QUAD8 ||
375 if ((
sizeof(
Real) >
sizeof(
double)) && elem_type ==
PRISM20)
380 testPolynomials(
QNODAL, order, elem_type, true_values[i], exactorder);
389 const std::vector<std::vector<ElemType>> all_types =
391 const std::vector<std::vector<std::function<Real(int,int,int)>>>
394 {quad_integrals, tri_integrals},
395 {hex_integrals, tet_integrals, prism_integrals, pyramid_integrals}};
399 for (
int order=0; order<17; ++order)
400 testPolynomials(
QMONOMIAL, order, all_types[i][j], true_values[i][j], order);
412 for (
int qt=0; qt<3; ++qt)
413 for (
int order=0; order<end_order; ++order)
417 if ((
sizeof(
Real) >
sizeof(
double)) && order > 2)
419 testPolynomials(qtype[qt], order,
TET4, tet_integrals, order);
429 for (
int qt=0; qt<4; ++qt)
430 for (
int order=0; order<10; ++order)
431 testPolynomials(qtype[qt], order,
TRI3, tri_integrals, order);
438 constexpr
int max_order = 43;
447 Real initial_sum_weights[2] = {.5, 1./3.};
457 std::vector<std::vector<Real>> true_integrals(2);
461 true_integrals[0].resize(max_order);
462 for (std::size_t p=0; p<true_integrals[0].size(); ++p)
463 true_integrals[0][p] = 1. / (p*p + 3.*p + 2.);
467 true_integrals[1].resize(max_order);
468 for (std::size_t p=0; p<true_integrals[1].size(); ++p)
469 true_integrals[1][p] = 2. / (p*p*p + 6.*p*p + 11.*p + 6.);
472 for (
int qt=0; qt<2; ++qt)
474 for (
int order=0; order<max_order; ++order)
478 static_cast<Order>(order));
481 qrule->init (
EDGE2, 0,
true);
485 for (
unsigned int qp=0; qp<qrule->n_points(); qp++)
486 sumw += qrule->w(qp);
489 LIBMESH_ASSERT_REALS_EQUAL(initial_sum_weights[qt], sumw, quadrature_tolerance);
492 for (
int testpower=0; testpower<=order; ++testpower)
499 for (
unsigned int qp=0; qp<qrule->n_points(); qp++)
500 sumq += qrule->w(qp) *
std::pow(qrule->qp(qp)(0), testpower);
503 LIBMESH_ASSERT_REALS_EQUAL(true_integrals[qt][testpower], sumq, quadrature_tolerance);
511 template <QuadratureType qtype, Order order>
516 std::unique_ptr<QBase> qrule1D =
QBase::build (qtype, 1, order);
517 std::unique_ptr<QBase> qrule2D =
QBase::build (qtype, 2, order);
518 std::unique_ptr<QBase> qrule3D =
QBase::build (qtype, 3, order);
520 CPPUNIT_ASSERT_EQUAL ( qtype, qrule1D->type() );
521 CPPUNIT_ASSERT_EQUAL ( qtype, qrule2D->type() );
522 CPPUNIT_ASSERT_EQUAL ( qtype, qrule3D->type() );
527 CPPUNIT_ASSERT_EQUAL ( order, qrule1D->get_base_order() );
528 CPPUNIT_ASSERT_EQUAL ( order, qrule2D->get_base_order() );
529 CPPUNIT_ASSERT_EQUAL ( order, qrule3D->get_base_order() );
532 CPPUNIT_ASSERT_EQUAL ( static_cast<unsigned int>(1) , qrule1D->get_dim() );
533 CPPUNIT_ASSERT_EQUAL ( static_cast<unsigned int>(2) , qrule2D->get_dim() );
534 CPPUNIT_ASSERT_EQUAL ( static_cast<unsigned int>(3) , qrule3D->get_dim() );
545 template <QuadratureType qtype, Order order,
unsigned int exactorder>
550 testPolynomials(qtype, order,
EDGE3, edge_integrals, exactorder);
557 template <QuadratureType qtype, Order order,
unsigned int exactorder>
562 testPolynomials(qtype, order,
QUAD8, quad_integrals, exactorder);
571 testPolynomials(qtype, order,
TRI6, tri_integrals, 0);
574 testPolynomials(qtype, order,
TRI6, tri_integrals, std::min(1u,exactorder));
579 if ((
sizeof(
Real) >
sizeof(
double)) && (order > 17))
582 testPolynomials(qtype, order,
TRI6, tri_integrals, exactorder);
590 template <QuadratureType qtype, Order order,
unsigned int exactorder>
595 testPolynomials(qtype, order,
HEX20, hex_integrals, exactorder);
606 testPolynomials(qtype, order,
TET10, tet_integrals, 0);
607 testPolynomials(qtype, order,
PYRAMID14, pyramid_integrals, 0);
612 testPolynomials(qtype, order,
TET10, tet_integrals, std::min(1u,exactorder));
613 testPolynomials(qtype, order,
PRISM15, prism_integrals, std::min(1u,exactorder));
616 testPolynomials(qtype, order,
PYRAMID14, pyramid_integrals, std::min(1u,exactorder));
620 testPolynomials(qtype, order,
TET10, tet_integrals, exactorder);
621 testPolynomials(qtype, order,
PYRAMID14, pyramid_integrals, exactorder);
626 if ((
sizeof(
Real) >
sizeof(
double)) && (order > 17))
629 testPolynomials(qtype, order,
PRISM15, prism_integrals, exactorder);
void testPolynomial(QBase &qrule, int xp, int yp, int zp, Real true_value)
ElemType
Defines an enum for geometric element types.
void testNodalQuadrature()
Point qp(const unsigned int i) const
static constexpr Real TOLERANCE
QuadratureType
Defines an enum for currently available quadrature rules.
The libMesh namespace provides an interface to certain functionality in the library.
void iota(ForwardIter first, ForwardIter last, T value)
Utility::iota was created back when std::iota was just an SGI STL extension.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
void testMonomialQuadrature()
unsigned int get_dim() const
unsigned int n_points() const
Real quadrature_tolerance
std::string enum_to_string(const T e)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
CPPUNIT_TEST_SUITE_REGISTRATION(QuadratureTest)
static std::unique_ptr< QBase > build(std::string_view name, const unsigned int dim, const Order order=INVALID_ORDER)
Builds a specific quadrature rule based on the name string.
void testPolynomials(QuadratureType qtype, int order, ElemType elem_type, const std::function< Real(int, int, int)> &true_value, int exactorder)
Real w(const unsigned int i) const
A Point defines a location in LIBMESH_DIM dimensional Real space.
The QBase class provides the basic functionality from which various quadrature rules can be derived...
void ErrorVector unsigned int
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...