OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
TestLinearSpline.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025, Jon Thompson
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice,
7 * this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice,
9 * this list of conditions and the following disclaimer in the documentation
10 * and/or other materials provided with the distribution.
11 * 3. Neither the name of STFC nor the names of its contributors may be used to
12 * endorse or promote products derived from this software without specific
13 * prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <gtest/gtest.h>
29#include <vector>
31
32class LinearSplineTest : public testing::Test {
33protected:
34 void SetUp() override {
35 // Test data: y = x^2
36 x_data = {0.0, 1.0, 2.0, 3.0, 4.0};
37 y_data = {0.0, 1.0, 4.0, 9.0, 16.0};
38 }
39
40 std::vector<double> x_data;
41 std::vector<double> y_data;
42};
43
44TEST_F(LinearSplineTest, BasicInterpolation) {
45 const LinearSpline spline(x_data, y_data);
47 // Test interpolation at data points
48 EXPECT_NEAR(spline.eval(0.0, acc), 0.0, 1e-10);
49 EXPECT_NEAR(spline.eval(1.0, acc), 1.0, 1e-10);
50 EXPECT_NEAR(spline.eval(2.0, acc), 4.0, 1e-10);
51 EXPECT_NEAR(spline.eval(3.0, acc), 9.0, 1e-10);
52 EXPECT_NEAR(spline.eval(4.0, acc), 16.0, 1e-10);
53
54 // Test interpolation between points
55 EXPECT_NEAR(spline.eval(1.5, acc), 2.5, 1e-10);
56}
57
58TEST_F(LinearSplineTest, Uninitialised) {
59 // Uninitialised
61 LinearSpline spline_uninit;
62 EXPECT_THROW(spline_uninit.eval(0.0, accel), std::runtime_error);
63}
64
65TEST_F(LinearSplineTest, Extrapolation) {
66 const LinearSpline spline(x_data, y_data);
68
69 // Test left extrapolation
70 EXPECT_NEAR(spline.eval(-1.0, acc), -1.0, 1e-10);
71 EXPECT_NEAR(spline.eval(-0.5, acc), -0.5, 1e-10);
72
73 // Test right extrapolation
74 EXPECT_NEAR(spline.eval(5.0, acc), 23.0, 1e-10);
75 EXPECT_NEAR(spline.eval(5.5, acc), 26.5, 1e-10);
76}
77
78TEST_F(LinearSplineTest, Accelerator) {
79 const LinearSpline spline(x_data, y_data);
81
82 // First evaluation
83 EXPECT_NEAR(spline.eval(1.5, acc), 2.5, 1e-10);
84
85 // Second evaluation in the same interval (should use cached index)
86 EXPECT_NEAR(spline.eval(1.5, acc), 2.5, 1e-10);
87
88 // Evaluation in a different interval
89 EXPECT_NEAR(spline.eval(2.5, acc), 6.5, 1e-10);
90}
91
92TEST_F(LinearSplineTest, InvalidInput) {
93 // Too few points
94 EXPECT_THROW(LinearSpline spline({0.0}, {0.0}), std::invalid_argument);
95 // Differing lengths
96 EXPECT_THROW(LinearSpline spline({0.0}, {0.0, 1.0}), std::invalid_argument);
97 // Non-increasing x
98 EXPECT_THROW(
99 LinearSpline spline({0.0, 1.0, 0.5, 2.0}, {0.0, 1.0, 2.0, 3.0}), std::invalid_argument);
100}
101
103 LinearSpline spline(x_data, y_data);
105
106 // Whole pre-computed intervals
107 EXPECT_NEAR(spline.evalIntegral(0, 1, accel), 0.5, 1e-10);
108 EXPECT_NEAR(spline.evalIntegral(1, 2, accel), 2.5, 1e-10);
109 EXPECT_NEAR(spline.evalIntegral(2, 3, accel), 6.5, 1e-10);
110 EXPECT_NEAR(spline.evalIntegral(3, 4, accel), 12.5, 1e-10);
111 EXPECT_NEAR(spline.evalIntegral(0, 4, accel), 22.0, 1e-10);
112
113 // Partial first and last intervals
114 EXPECT_NEAR(spline.evalIntegral(0.6, 3.2, accel), 11.26, 1e-10);
115
116 // Asking again should use the cache
117 EXPECT_NEAR(spline.evalIntegral(0.6, 3.2, accel), 11.26, 1e-10);
118
119 // Extrapolation below the first interval
120 EXPECT_NEAR(spline.evalIntegral(-1, 1.5, accel), 0.875, 1e-10);
121
122 // Extrapolation above the last interval
123 EXPECT_NEAR(spline.evalIntegral(3, 4.5, accel), 21.375, 1e-10);
124
125 // Swapping integral bounds
126 EXPECT_NEAR(spline.evalIntegral(2, 1, accel), 2.5, 1e-10);
127
128 // Uninitialised spline
129 LinearSpline spline_uninit;
130 EXPECT_THROW(spline_uninit.evalIntegral(2, 1, accel), std::runtime_error);
131
132 // Re-initialise the spline to something different
133 spline.init({0.0, 1.0, 2.0, 3.0, 4.0}, {0.0, 2.0, 4.0, 6.0, 8.0});
134 EXPECT_NEAR(spline.evalIntegral(0, 4, accel), 16.0, 1e-10);
135}
TEST_F(LinearSplineTest, BasicInterpolation)
Accelerator caching last interval indices.
void SetUp() override
std::vector< double > x_data
std::vector< double > y_data
double evalIntegral(double xa, double xb, Accelerator &accel) const override
Evaluate the integral of the spline at x.
void init(const std::vector< double > &x, const std::vector< double > &y) override
Initialize from tabulated data (natural spline).
double eval(double x, Accelerator &accel) const override
Evaluate the spline at x using an accelerator.