Nektar++
TestPolylib.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: TestPolylib.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Unit tests for the Polylib library.
32//
33///////////////////////////////////////////////////////////////////////////////
34
36
37#include <boost/test/tools/floating_point_comparison.hpp>
38#include <boost/test/unit_test.hpp>
39
40#include <iostream>
41#include <tuple>
42#include <vector>
43
44namespace Nektar
45{
46namespace UnitTests
47{
48
49/// Lower range of number of quadrature points to use for unit tests.
50#define NPLOWER 5
51/// Upper range of number of quadrature points to use for unit tests.
52#define NPUPPER 15
53/// Tolerance to be used for floating point comparisons.
54#define EPS 1e-11
55
56/// Dot product two vectors.
57double ddot(int n, double *x, int incx, double *y, int incy)
58{
59 double sum = 0.0;
60
61 while (n--)
62 {
63 sum += (*x) * (*y);
64 x += incx;
65 y += incy;
66 }
67
68 return sum;
69}
70
71// Storage
72std::vector<double> z(NPUPPER), w(NPUPPER), p(NPUPPER);
73std::vector<double> d(NPUPPER *NPUPPER), q(NPUPPER *NPUPPER);
74
75/**
76 * @brief Test integrals of Jacobi polynomials.
77 *
78 * This routine evaluates the integral \f[ \int_{-1}^1 (1-x)^\alpha (1+x)^\beta
79 * P_n^{\alpha,\beta} dx = 0 \f] using \f$ -0.5 \leq \alpha,\beta \leq 5 \f$ and
80 * using \f$ N \f$ points where \f$ N \f$ lies between #NPLOWER and #NPUPPER.
81 * Tolerance is taken using the #EPS value.
82 */
83inline void TestIntegral(
84 std::function<void(double *, double *, int, double, double)> func, int o)
85{
86 double alpha = -0.5;
87 while (alpha <= 5.0)
88 {
89 double beta = -0.5;
90 while (beta <= 5.0)
91 {
92 for (int np = NPLOWER; np <= NPUPPER; ++np)
93 {
94 func(&z[0], &w[0], np, alpha, beta);
95 for (int n = 2; n < 2 * np - 1 - o; ++n)
96 {
97 Polylib::jacobfd(np, &z[0], &p[0], NULL, n, alpha, beta);
98 double sum = ddot(np, &w[0], 1, &p[0], 1);
99 BOOST_CHECK_SMALL(sum, EPS);
100 }
101 }
102
103 beta += 0.5;
104 }
105
106 alpha += 0.5;
107 }
108}
109
110/**
111 * @brief Test derivatives using Gaussian quadrature.
112 *
113 * This routine evaluates the deriatives \f[ \frac{d}{dx}(x^n) = nx^{n-1} \f]
114 * using \f$ -0.5 \leq \alpha,\beta \leq 5 \f$ and using \f$ N \f$ points where
115 * \f$ N \f$ lies between #NPLOWER and #NPUPPER. Tolerance is taken using the
116 * #EPS value.
117 */
119 std::function<void(double *, double *, int, double, double)> func,
120 std::function<void(double *, double *, int, double, double)> funcD)
121{
122 double alpha = -0.5;
123 while (alpha <= 5.0)
124 {
125 double beta = -0.5;
126 while (beta <= 5.0)
127 {
128 for (int np = NPLOWER; np <= NPUPPER; ++np)
129 {
130 func(&z[0], &w[0], np, alpha, beta);
131 funcD(&d[0], &z[0], np, alpha, beta);
132 for (int n = 2; n < np - 1; ++n)
133 {
134 for (int i = 0; i < np; ++i)
135 {
136 p[i] = pow(z[i], n);
137 }
138
139 double sum = 0.0;
140
141 for (int i = 0; i < np; ++i)
142 {
143 sum += fabs(ddot(np, &d[0] + i, np, &p[0], 1) -
144 n * pow(z[i], n - 1));
145 }
146 sum /= np;
147
148 BOOST_CHECK_SMALL(sum, EPS);
149 }
150 }
151 beta += 0.5;
152 }
153 alpha += 0.5;
154 }
155}
156
157/**
158 * @brief Evaluate interpolation using Gaussian quadrature.
159 *
160 * This routine evaluates the interpolation of \f$ z^n \f$ to \f$ x^n \f$, where
161 * \f$ z \f$ are the quadrature zeros and \f$ x \f$ are the equispaced points
162 * \f[ x_n = \frac{2n}{N-1} - 1, \quad 0\leq n\leq N, \f] using \f$ -0.5 \leq
163 * \alpha,\beta \leq 5 \f$ and using \f$ N \f$ points where \f$ N \f$ lies
164 * between #NPLOWER and #NPUPPER. Tolerance is taken using the
165 * #EPS value.
166 */
168 std::function<void(double *, double *, int, double, double)> func,
169 std::function<void(double *, double *, double *, int, int, double, double)>
170 funcI)
171{
172 double alpha = -0.5;
173 while (alpha <= 5.0)
174 {
175 double beta = -0.5;
176 while (beta <= 5.0)
177 {
178 for (int np = NPLOWER; np <= NPUPPER; ++np)
179 {
180 func(&z[0], &w[0], np, alpha, beta);
181 for (int n = 2; n < np - 1; ++n)
182 {
183 for (int i = 0; i < np; ++i)
184 {
185 w[i] = 2.0 * i / (double)(np - 1) - 1.0;
186 p[i] = pow(z[i], n);
187 }
188 funcI(&d[0], &z[0], &w[0], np, np, alpha, beta);
189
190 double sum = 0.0;
191 for (int i = 0; i < np; ++i)
192 {
193 sum += fabs(ddot(np, &d[0] + i, np, &p[0], 1) -
194 pow(w[i], n));
195 }
196 sum /= np;
197
198 BOOST_CHECK_SMALL(sum, EPS);
199 }
200 }
201 beta += 0.5;
202 }
203 alpha += 0.5;
204 }
205}
206
208 std::function<void(double *, double *, int, double, double)> func,
209 std::function<void(double *, double *, int)> funcQ)
210{
211 double alpha = -0.5;
212 while (alpha <= 5.0)
213 {
214 double beta = -0.5;
215 while (beta <= 5.0)
216 {
217 for (int np = NPLOWER; np <= NPUPPER; ++np)
218 {
219 func(&z[0], &w[0], np, alpha, beta);
220 funcQ(&q[0], &z[0], np);
221 for (int n = 2; n < np - 1; ++n)
222 {
223 for (int i = 0; i < np; ++i)
224 {
225 p[i] = pow(z[i], n);
226 }
227
228 double sum = 0.0;
229
230 for (int i = 0; i < np; ++i)
231 {
232 sum += fabs(ddot(np, &q[0] + i * np, 1, &p[0], 1) -
233 pow(z[i], n + 1) / (n + 1));
234 }
235 sum /= np;
236
237 BOOST_CHECK_SMALL(sum, EPS);
238 }
239 }
240 beta += 0.5;
241 }
242 alpha += 0.5;
243 }
244}
245
247{
249}
250
251BOOST_AUTO_TEST_CASE(TestGaussRadauM)
252{
254}
255
256BOOST_AUTO_TEST_CASE(TestGaussRadauP)
257{
259}
260
261BOOST_AUTO_TEST_CASE(TestGaussLobatto)
262{
264}
265
267{
269}
270
271BOOST_AUTO_TEST_CASE(TestGaussRadauMDiff)
272{
274}
275
276BOOST_AUTO_TEST_CASE(TestGaussRadauPDiff)
277{
279}
280
281BOOST_AUTO_TEST_CASE(TestGaussLobattoDiff)
282{
284}
285
286BOOST_AUTO_TEST_CASE(TestGaussInterp)
287{
289}
290
291BOOST_AUTO_TEST_CASE(TestGaussRadauMInterp)
292{
294}
295
296BOOST_AUTO_TEST_CASE(TestGaussRadauPInterp)
297{
299}
300
301BOOST_AUTO_TEST_CASE(TestGaussLobattoInterp)
302{
304}
305
306BOOST_AUTO_TEST_CASE(TestGaussIntMatrix)
307{
309}
310
311BOOST_AUTO_TEST_CASE(TestGaussRadauMIntMatrix)
312{
314}
315
316BOOST_AUTO_TEST_CASE(TestGaussRadauPIntMatrix)
317{
319}
320
321BOOST_AUTO_TEST_CASE(TestGaussLobattoIntMatrix)
322{
324}
325
326BOOST_AUTO_TEST_CASE(TestGammaFraction)
327{
328 double a, c;
329
330 using arrT = std::tuple<int, double, int, double>;
331 std::vector<std::tuple<double, arrT, arrT>> ac = {
332 {362880.0, std::make_tuple(10, 0.0, 0, 1.0),
333 std::make_tuple(1, 0.0, 12, -2.0)},
334 {30.0, std::make_tuple(4, 3., 5, 0.), std::make_tuple(5, 0., 7, 0.)},
335 {21651.09375, std::make_tuple(7, 3.5, 5, 0.5),
336 std::make_tuple(5, 0.5, 10, 0.5)},
337 {97429.921875, std::make_tuple(10, 0.5, 5, -0.5),
338 std::make_tuple(5, -0.5, 11, -0.5)},
339 {2279.0625, std::make_tuple(10, -0.5, 5, 0.5),
340 std::make_tuple(5, 0.5, 10, -0.5)},
341 {639383.8623046875, std::make_tuple(10, 0.5, 0, 0.5),
342 std::make_tuple(0, 0.5, 10, 0.5)},
343 {5967498288235982848., std::make_tuple(100, 0., 90, 0.5),
344 std::make_tuple(90, 0.5, 100, 0.)},
345 {5618641603777298169856., std::make_tuple(200, 0., 191, -0.5),
346 std::make_tuple(190, 0.5, 200, 0.)},
347 {77396694214720029196288., std::make_tuple(200, 0., 190, 0.),
348 std::make_tuple(190, 0., 200, 0.)}};
349
350 for (auto &test : ac)
351 {
352 double a = std::get<0>(test);
353 arrT c1 = std::get<1>(test);
354 arrT c2 = std::get<2>(test);
355 double c1e = Polylib::gammaFracGammaF(std::get<0>(c1), std::get<1>(c1),
356 std::get<2>(c1), std::get<3>(c1));
357 double c2e = Polylib::gammaFracGammaF(std::get<0>(c2), std::get<1>(c2),
358 std::get<2>(c2), std::get<3>(c2));
359
360 BOOST_CHECK_SMALL(c1e / a - 1.0, EPS);
361 BOOST_CHECK_SMALL(c2e * a - 1.0, EPS);
362 }
363
364 int Q = 2;
365 for (double alpha = -0.5; alpha <= 150.; alpha += 0.5)
366 {
367 for (double beta = -0.5; beta <= 150.; beta += 0.5)
368 {
369 a = Polylib::gammaF(Q + alpha) / Polylib::gammaF(Q + beta);
370 c = Polylib::gammaFracGammaF(Q, alpha, Q, beta) / a - 1.;
371 BOOST_CHECK_SMALL(c, EPS);
372 }
373 }
374}
375
376} // namespace UnitTests
377} // namespace Nektar
#define NPUPPER
Upper range of number of quadrature points to use for unit tests.
Definition: TestPolylib.cpp:52
#define EPS
Tolerance to be used for floating point comparisons.
Definition: TestPolylib.cpp:54
#define NPLOWER
Lower range of number of quadrature points to use for unit tests.
Definition: TestPolylib.cpp:50
@ beta
Gauss Radau pinned at x=-1,.
Definition: PointsType.h:61
std::vector< double > w(NPUPPER)
std::vector< double > p(NPUPPER)
std::vector< double > z(NPUPPER)
void TestInterpolation(std::function< void(double *, double *, int, double, double)> func, std::function< void(double *, double *, double *, int, int, double, double)> funcI)
Evaluate interpolation using Gaussian quadrature.
std::vector< double > d(NPUPPER *NPUPPER)
double ddot(int n, double *x, int incx, double *y, int incy)
Dot product two vectors.
Definition: TestPolylib.cpp:57
void TestIntegral(std::function< void(double *, double *, int, double, double)> func, int o)
Test integrals of Jacobi polynomials.
Definition: TestPolylib.cpp:83
std::vector< double > q(NPUPPER *NPUPPER)
void TestIntegralMatrix(std::function< void(double *, double *, int, double, double)> func, std::function< void(double *, double *, int)> funcQ)
void TestDifferentiation(std::function< void(double *, double *, int, double, double)> func, std::function< void(double *, double *, int, double, double)> funcD)
Test derivatives using Gaussian quadrature.
BOOST_AUTO_TEST_CASE(TestGaussInt)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double gammaF(const double x)
Calculate the Gamma function , , for integer values and halves.
Definition: Polylib.cpp:1347
void Dgj(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix and its transpose associated with the Gauss-Jacobi zeros.
Definition: Polylib.cpp:647
void zwgrjm(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Radau-Jacobi zeros and weights with end point at z=-1.
Definition: Polylib.cpp:182
void zwgrjp(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Radau-Jacobi zeros and weights with end point at z=1.
Definition: Polylib.cpp:223
void Dglj(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix associated with the Gauss-Lobatto-Jacobi zeros.
Definition: Polylib.cpp:807
void Imgrjp(double *im, const double *zgrj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Radau-Jacobi points (including z=1) to an arbitrary distrubtion at ...
Definition: Polylib.cpp:1074
void zwglj(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Lobatto-Jacobi zeros and weights with end point at z=-1,1.
Definition: Polylib.cpp:262
void zwgj(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Jacobi zeros and weights.
Definition: Polylib.cpp:154
void Imgj(double *im, const double *zgj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Jacobi points to an arbitrary distribution at points zm.
Definition: Polylib.cpp:1012
void Qg(double *Q, const double *z, const int np)
Compute the Integration Matrix.
Definition: Polylib.cpp:605
double gammaFracGammaF(const int x, const double alpha, const int y, const double beta)
Calculate fraction of two Gamma functions, , for integer values and halves.
Definition: Polylib.cpp:1396
void Imgrjm(double *im, const double *zgrj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Radau-Jacobi points (including z=-1) to an arbitrary distrubtion at...
Definition: Polylib.cpp:1043
void Dgrjm(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix and its transpose associated with the Gauss-Radau-Jacobi zeros with a z...
Definition: Polylib.cpp:694
void Dgrjp(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix associated with the Gauss-Radau-Jacobi zeros with a zero at z=1.
Definition: Polylib.cpp:750
void Imglj(double *im, const double *zglj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Lobatto-Jacobi points to an arbitrary distrubtion at points zm.
Definition: Polylib.cpp:1105
void jacobfd(const int np, const double *z, double *poly_in, double *polyd, const int n, const double alpha, const double beta)
Routine to calculate Jacobi polynomials, , and their first derivative, .
Definition: Polylib.cpp:1206