Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GridTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GridTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
18 
19 #include <algorithm>
20 #include <array>
21 #include <cstddef>
22 #include <set>
23 #include <tuple>
24 #include <utility>
25 #include <vector>
26 
27 namespace Acts {
28 
29 using namespace detail;
30 
31 namespace Test {
32 
33 BOOST_AUTO_TEST_CASE(grid_test_1d_equidistant) {
34  using Point = std::array<double, 1>;
35  using indices = std::array<size_t, 1>;
36  EquidistantAxis a(0.0, 4.0, 4u);
38 
39  // test general properties
40  BOOST_CHECK_EQUAL(g.size(), 6u);
41  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
42 
43  // global bin index
44  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-0.3}})), 0u);
45  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-0.}})), 1u);
46  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.}})), 1u);
47  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.7}})), 1u);
48  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1}})), 2u);
49  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2}})), 2u);
50  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.}})), 3u);
51  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.7}})), 3u);
52  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.}})), 4u);
53  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.9999}})), 4u);
54  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.}})), 5u);
55  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.98}})), 5u);
56 
57  // global bin index -> local bin indices
58  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0}}));
59  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{1}}));
60  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{2}}));
61  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{3}}));
62  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{4}}));
63  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{5}}));
64 
65  // local bin indices -> global bin index
66  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0}}), 0u);
67  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1}}), 1u);
68  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2}}), 2u);
69  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3}}), 3u);
70  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4}}), 4u);
71  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5}}), 5u);
72 
73  BOOST_CHECK(g.localBinsFromGlobalBin(
74  g.globalBinFromPosition(Point({{2.7}}))) == indices({{3}}));
75 
76  // inside checks
77  BOOST_CHECK(not g.isInside(Point({{-2.}})));
78  BOOST_CHECK(g.isInside(Point({{0.}})));
79  BOOST_CHECK(g.isInside(Point({{2.5}})));
80  BOOST_CHECK(not g.isInside(Point({{4.}})));
81  BOOST_CHECK(not g.isInside(Point({{6.}})));
82 
83  // test some bin centers
84  CHECK_CLOSE_ABS(g.binCenter({{1}}), Point({{0.5}}), 1e-6);
85  CHECK_CLOSE_ABS(g.binCenter({{2}}), Point({{1.5}}), 1e-6);
86  CHECK_CLOSE_ABS(g.binCenter({{3}}), Point({{2.5}}), 1e-6);
87  CHECK_CLOSE_ABS(g.binCenter({{4}}), Point({{3.5}}), 1e-6);
88 
89  // test some lower-left bin edges
90  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1}}), Point({{0.}}), 1e-6);
91  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2}}), Point({{1.}}), 1e-6);
92  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3}}), Point({{2.}}), 1e-6);
93  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4}}), Point({{3.}}), 1e-6);
94 
95  // test some upper right-bin edges
96  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1}}), Point({{1.}}), 1e-6);
97  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2}}), Point({{2.}}), 1e-6);
98  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3}}), Point({{3.}}), 1e-6);
99  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4}}), Point({{4.}}), 1e-6);
100 
101  // initialize grid
102  for (size_t bin = 0; bin < g.size(); ++bin) {
103  g.at(bin) = bin;
104  }
105 
106  // consistency of access
107  const auto& point = Point({{0.7}});
108  size_t globalBin = g.globalBinFromPosition(point);
109  indices localBins = g.localBinsFromGlobalBin(globalBin);
110 
111  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
112  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
113 }
114 
115 BOOST_AUTO_TEST_CASE(grid_test_2d_equidistant) {
116  using Point = std::array<double, 2>;
117  using indices = std::array<size_t, 2>;
118  EquidistantAxis a(0.0, 4.0, 4u);
119  EquidistantAxis b(0.0, 3.0, 3u);
122 
123  // test general properties
124  BOOST_CHECK_EQUAL(g.size(), 30u);
125  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
126  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 3u);
127 
128  // global bin index
129  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, -1}})), 0u);
130  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 0}})), 1u);
131  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 1}})), 2u);
132  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 2}})), 3u);
133  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 3}})), 4u);
134  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, -1}})), 5u);
135  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0}})), 6u);
136  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1}})), 7u);
137  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2}})), 8u);
138  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3}})), 9u);
139  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, -1}})), 10u);
140  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0}})), 11u);
141  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1}})), 12u);
142  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2}})), 13u);
143  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3}})), 14u);
144  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, -1}})), 15u);
145  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0}})), 16u);
146  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1}})), 17u);
147  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2}})), 18u);
148  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3}})), 19u);
149  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, -1}})), 20u);
150  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 0}})), 21u);
151  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 1}})), 22u);
152  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 2}})), 23u);
153  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 3}})), 24u);
154  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, -1}})), 25u);
155  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 0}})), 26u);
156  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 1}})), 27u);
157  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 2}})), 28u);
158  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 3}})), 29u);
159 
160  // test some arbitrary points
161  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2, 0.3}})), 11u);
162  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.2, 3.3}})), 19u);
163  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.9, 1.8}})), 7u);
164  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.7, 3.1}})), 24u);
165  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.4, 2.3}})), 13u);
166  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, 3}})), 4u);
167  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{8, 1}})), 27u);
168  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, -3}})), 10u);
169  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 11}})), 24u);
170  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, -3}})), 0u);
171  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, 7}})), 04u);
172  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, -1}})), 25u);
173  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, 11}})), 29u);
174 
175  // global bin index -> local bin indices
176  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0}}));
177  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 1}}));
178  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 2}}));
179  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 3}}));
180  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{0, 4}}));
181  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{1, 0}}));
182  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{1, 1}}));
183  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{1, 2}}));
184  BOOST_CHECK(g.localBinsFromGlobalBin(8) == indices({{1, 3}}));
185  BOOST_CHECK(g.localBinsFromGlobalBin(9) == indices({{1, 4}}));
186  BOOST_CHECK(g.localBinsFromGlobalBin(10) == indices({{2, 0}}));
187  BOOST_CHECK(g.localBinsFromGlobalBin(11) == indices({{2, 1}}));
188  BOOST_CHECK(g.localBinsFromGlobalBin(12) == indices({{2, 2}}));
189  BOOST_CHECK(g.localBinsFromGlobalBin(13) == indices({{2, 3}}));
190  BOOST_CHECK(g.localBinsFromGlobalBin(14) == indices({{2, 4}}));
191  BOOST_CHECK(g.localBinsFromGlobalBin(15) == indices({{3, 0}}));
192  BOOST_CHECK(g.localBinsFromGlobalBin(16) == indices({{3, 1}}));
193  BOOST_CHECK(g.localBinsFromGlobalBin(17) == indices({{3, 2}}));
194  BOOST_CHECK(g.localBinsFromGlobalBin(18) == indices({{3, 3}}));
195  BOOST_CHECK(g.localBinsFromGlobalBin(19) == indices({{3, 4}}));
196  BOOST_CHECK(g.localBinsFromGlobalBin(20) == indices({{4, 0}}));
197  BOOST_CHECK(g.localBinsFromGlobalBin(21) == indices({{4, 1}}));
198  BOOST_CHECK(g.localBinsFromGlobalBin(22) == indices({{4, 2}}));
199  BOOST_CHECK(g.localBinsFromGlobalBin(23) == indices({{4, 3}}));
200  BOOST_CHECK(g.localBinsFromGlobalBin(24) == indices({{4, 4}}));
201  BOOST_CHECK(g.localBinsFromGlobalBin(25) == indices({{5, 0}}));
202  BOOST_CHECK(g.localBinsFromGlobalBin(26) == indices({{5, 1}}));
203  BOOST_CHECK(g.localBinsFromGlobalBin(27) == indices({{5, 2}}));
204  BOOST_CHECK(g.localBinsFromGlobalBin(28) == indices({{5, 3}}));
205  BOOST_CHECK(g.localBinsFromGlobalBin(29) == indices({{5, 4}}));
206 
207  // local bin indices -> global bin index
208  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0}}), 0u);
209  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1}}), 1u);
210  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 2}}), 2u);
211  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3}}), 3u);
212  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 4}}), 4u);
213  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0}}), 5u);
214  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1}}), 6u);
215  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 2}}), 7u);
216  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3}}), 8u);
217  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 4}}), 9u);
218  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0}}), 10u);
219  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1}}), 11u);
220  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 2}}), 12u);
221  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3}}), 13u);
222  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 4}}), 14u);
223  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0}}), 15u);
224  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 1}}), 16u);
225  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 2}}), 17u);
226  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 3}}), 18u);
227  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4}}), 19u);
228  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 0}}), 20u);
229  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 1}}), 21u);
230  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 2}}), 22u);
231  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 3}}), 23u);
232  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 4}}), 24u);
233  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 0}}), 25u);
234  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 1}}), 26u);
235  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 2}}), 27u);
236  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 3}}), 28u);
237  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 4}}), 29u);
238 
239  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
240  Point({{1.2, 0.7}}))) == indices({{2, 1}}));
241 
242  // inside checks
243  BOOST_CHECK(not g.isInside(Point({{-2., -1}})));
244  BOOST_CHECK(not g.isInside(Point({{-2., 1.}})));
245  BOOST_CHECK(not g.isInside(Point({{-2., 5.}})));
246  BOOST_CHECK(not g.isInside(Point({{1., -1.}})));
247  BOOST_CHECK(not g.isInside(Point({{6., -1.}})));
248  BOOST_CHECK(g.isInside(Point({{0.5, 1.3}})));
249  BOOST_CHECK(not g.isInside(Point({{4., -1.}})));
250  BOOST_CHECK(not g.isInside(Point({{4., 0.3}})));
251  BOOST_CHECK(not g.isInside(Point({{4., 3.}})));
252  BOOST_CHECK(not g.isInside(Point({{-1., 3.}})));
253  BOOST_CHECK(not g.isInside(Point({{2., 3.}})));
254  BOOST_CHECK(not g.isInside(Point({{5., 3.}})));
255 
256  // test some bin centers
257  CHECK_CLOSE_ABS(g.binCenter({{1, 1}}), Point({{0.5, 0.5}}), 1e-6);
258  CHECK_CLOSE_ABS(g.binCenter({{2, 3}}), Point({{1.5, 2.5}}), 1e-6);
259  CHECK_CLOSE_ABS(g.binCenter({{3, 1}}), Point({{2.5, 0.5}}), 1e-6);
260  CHECK_CLOSE_ABS(g.binCenter({{4, 2}}), Point({{3.5, 1.5}}), 1e-6);
261 
262  // test some lower-left bin edges
263  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1}}), Point({{0., 0.}}), 1e-6);
264  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 3}}), Point({{1., 2.}}), 1e-6);
265  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3, 1}}), Point({{2., 0.}}), 1e-6);
266  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4, 2}}), Point({{3., 1.}}), 1e-6);
267 
268  // test some upper right-bin edges
269  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1}}), Point({{1., 1.}}), 1e-6);
270  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 3}}), Point({{2., 3.}}), 1e-6);
271  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3, 1}}), Point({{3., 1.}}), 1e-6);
272  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4, 2}}), Point({{4., 2.}}), 1e-6);
273 
274  // initialize grid
275  for (size_t bin = 0; bin < g.size(); ++bin) {
276  g.at(bin) = bin;
277  }
278 
279  // consistency of access
280  const auto& point = Point({{0.7, 1.3}});
281  size_t globalBin = g.globalBinFromPosition(point);
282  indices localBins = g.localBinsFromGlobalBin(globalBin);
283 
284  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
285  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
286 }
287 
288 BOOST_AUTO_TEST_CASE(grid_test_3d_equidistant) {
289  using Point = std::array<double, 3>;
290  using indices = std::array<size_t, 3>;
291  EquidistantAxis a(0.0, 2.0, 2u);
292  EquidistantAxis b(0.0, 3.0, 3u);
293  EquidistantAxis c(0.0, 2.0, 2u);
296 
297  // test general properties
298  BOOST_CHECK_EQUAL(g.size(), 80u);
299  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
300  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 3u);
301  BOOST_CHECK_EQUAL(g.numLocalBins().at(2), 2u);
302 
303  // test grid points
304  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 0}})), 25u);
305  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 1}})), 26u);
306  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 2}})), 27u);
307  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1, 0}})), 29u);
308  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1, 1}})), 30u);
309  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1, 2}})), 31u);
310  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2, 0}})), 33u);
311  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2, 1}})), 34u);
312  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2, 2}})), 35u);
313  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 0}})), 37u);
314  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 1}})), 38u);
315  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 2}})), 39u);
316  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 0}})), 45u);
317  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 1}})), 46u);
318  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 2}})), 47u);
319  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1, 0}})), 49u);
320  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1, 1}})), 50u);
321  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1, 2}})), 51u);
322  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2, 0}})), 53u);
323  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2, 1}})), 54u);
324  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2, 2}})), 55u);
325  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 0}})), 57u);
326  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 1}})), 58u);
327  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 2}})), 59u);
328  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0, 0}})), 65u);
329  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0, 1}})), 66u);
330  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0, 2}})), 67u);
331  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1, 0}})), 69u);
332  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1, 1}})), 70u);
333  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1, 2}})), 71u);
334  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2, 0}})), 73u);
335  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2, 1}})), 74u);
336  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2, 2}})), 75u);
337  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3, 0}})), 77u);
338  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3, 1}})), 78u);
339  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3, 2}})), 79u);
340 
341  // global bin index -> local bin indices
342  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0, 0}}));
343  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 0, 1}}));
344  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 0, 2}}));
345  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 0, 3}}));
346  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{0, 1, 0}}));
347  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{0, 1, 1}}));
348  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{0, 1, 2}}));
349  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{0, 1, 3}}));
350  BOOST_CHECK(g.localBinsFromGlobalBin(24) == indices({{1, 1, 0}}));
351  BOOST_CHECK(g.localBinsFromGlobalBin(25) == indices({{1, 1, 1}}));
352  BOOST_CHECK(g.localBinsFromGlobalBin(26) == indices({{1, 1, 2}}));
353  BOOST_CHECK(g.localBinsFromGlobalBin(27) == indices({{1, 1, 3}}));
354  BOOST_CHECK(g.localBinsFromGlobalBin(52) == indices({{2, 3, 0}}));
355  BOOST_CHECK(g.localBinsFromGlobalBin(53) == indices({{2, 3, 1}}));
356  BOOST_CHECK(g.localBinsFromGlobalBin(54) == indices({{2, 3, 2}}));
357  BOOST_CHECK(g.localBinsFromGlobalBin(55) == indices({{2, 3, 3}}));
358  BOOST_CHECK(g.localBinsFromGlobalBin(60) == indices({{3, 0, 0}}));
359  BOOST_CHECK(g.localBinsFromGlobalBin(61) == indices({{3, 0, 1}}));
360  BOOST_CHECK(g.localBinsFromGlobalBin(62) == indices({{3, 0, 2}}));
361  BOOST_CHECK(g.localBinsFromGlobalBin(63) == indices({{3, 0, 3}}));
362  BOOST_CHECK(g.localBinsFromGlobalBin(76) == indices({{3, 4, 0}}));
363  BOOST_CHECK(g.localBinsFromGlobalBin(77) == indices({{3, 4, 1}}));
364  BOOST_CHECK(g.localBinsFromGlobalBin(78) == indices({{3, 4, 2}}));
365  BOOST_CHECK(g.localBinsFromGlobalBin(79) == indices({{3, 4, 3}}));
366 
367  // local bin indices -> global bin index
368  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 0}}), 0u);
369  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 1}}), 1u);
370  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 2}}), 2u);
371  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 3}}), 3u);
372  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 0}}), 4u);
373  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 1}}), 5u);
374  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 2}}), 6u);
375  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 3}}), 7u);
376  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 0}}), 24u);
377  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 1}}), 25u);
378  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 2}}), 26u);
379  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 3}}), 27u);
380  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 0}}), 52u);
381  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 1}}), 53u);
382  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 2}}), 54u);
383  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 3}}), 55u);
384  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 0}}), 60u);
385  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 1}}), 61u);
386  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 2}}), 62u);
387  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 3}}), 63u);
388  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 0}}), 76u);
389  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 1}}), 77u);
390  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 2}}), 78u);
391  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 3}}), 79u);
392 
393  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
394  Point({{1.2, 0.7, 1.4}}))) == indices({{2, 1, 2}}));
395 
396  // inside checks
397  BOOST_CHECK(not g.isInside(Point({{-2., -1, -2}})));
398  BOOST_CHECK(not g.isInside(Point({{-2., 1., 0.}})));
399  BOOST_CHECK(not g.isInside(Point({{-2., 5., -1}})));
400  BOOST_CHECK(not g.isInside(Point({{1., -1., 1.}})));
401  BOOST_CHECK(not g.isInside(Point({{6., -1., 4.}})));
402  BOOST_CHECK(g.isInside(Point({{0.5, 1.3, 1.7}})));
403  BOOST_CHECK(not g.isInside(Point({{2., -1., -0.4}})));
404  BOOST_CHECK(not g.isInside(Point({{2., 0.3, 3.4}})));
405  BOOST_CHECK(not g.isInside(Point({{2., 3., 0.8}})));
406  BOOST_CHECK(not g.isInside(Point({{-1., 3., 5.}})));
407  BOOST_CHECK(not g.isInside(Point({{2., 3., -1.}})));
408  BOOST_CHECK(not g.isInside(Point({{5., 3., 0.5}})));
409 
410  // test some bin centers
411  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 1}}), Point({{0.5, 0.5, 0.5}}), 1e-6);
412  CHECK_CLOSE_ABS(g.binCenter({{2, 3, 2}}), Point({{1.5, 2.5, 1.5}}), 1e-6);
413  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 2}}), Point({{0.5, 0.5, 1.5}}), 1e-6);
414  CHECK_CLOSE_ABS(g.binCenter({{2, 2, 1}}), Point({{1.5, 1.5, 0.5}}), 1e-6);
415 
416  // test some lower-left bin edges
417  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 1}}), Point({{0., 0., 0.}}), 1e-6);
418  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 3, 2}}), Point({{1., 2., 1.}}), 1e-6);
419  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 2}}), Point({{0., 0., 1.}}), 1e-6);
420  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 2, 1}}), Point({{1., 1., 0.}}), 1e-6);
421 
422  // test some upper right-bin edges
423  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 1}}), Point({{1., 1., 1.}}),
424  1e-6);
425  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 3, 2}}), Point({{2., 3., 2.}}),
426  1e-6);
427  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 2}}), Point({{1., 1., 2.}}),
428  1e-6);
429  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 2, 1}}), Point({{2., 2., 1.}}),
430  1e-6);
431 
432  // initialize grid
433  for (size_t bin = 0; bin < g.size(); ++bin) {
434  g.at(bin) = bin;
435  }
436 
437  // consistency of access
438  const auto& point = Point({{0.7, 2.3, 1.3}});
439  size_t globalBin = g.globalBinFromPosition(point);
440  indices localBins = g.localBinsFromGlobalBin(globalBin);
441 
442  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
443  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
444 }
445 
446 BOOST_AUTO_TEST_CASE(grid_test_1d_variable) {
447  using Point = std::array<double, 1>;
448  using indices = std::array<size_t, 1>;
449  VariableAxis a({0.0, 1.0, 4.0});
451 
452  // test general properties
453  BOOST_CHECK_EQUAL(g.size(), 4u);
454  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
455 
456  // global bin index
457  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-0.3}})), 0u);
458  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.}})), 1u);
459  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.7}})), 1u);
460  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1}})), 2u);
461  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2}})), 2u);
462  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.7}})), 2u);
463  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.}})), 3u);
464  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.98}})), 3u);
465 
466  // global bin index -> local bin indices
467  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0}}));
468  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{1}}));
469  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{2}}));
470  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{3}}));
471 
472  // local bin indices -> global bin index
473  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0}}), 0u);
474  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1}}), 1u);
475  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2}}), 2u);
476  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3}}), 3u);
477 
478  BOOST_CHECK(g.localBinsFromGlobalBin(
479  g.globalBinFromPosition(Point({{0.8}}))) == indices({{1}}));
480 
481  // inside checks
482  BOOST_CHECK(not g.isInside(Point({{-2.}})));
483  BOOST_CHECK(g.isInside(Point({{0.}})));
484  BOOST_CHECK(g.isInside(Point({{2.5}})));
485  BOOST_CHECK(not g.isInside(Point({{4.}})));
486  BOOST_CHECK(not g.isInside(Point({{6.}})));
487 
488  // test some bin centers
489  CHECK_CLOSE_ABS(g.binCenter({{1}}), Point({{0.5}}), 1e-6);
490  CHECK_CLOSE_ABS(g.binCenter({{2}}), Point({{2.5}}), 1e-6);
491 
492  // test some lower-left bin edges
493  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1}}), Point({{0.}}), 1e-6);
494  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2}}), Point({{1.}}), 1e-6);
495 
496  // test some upper right-bin edges
497  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1}}), Point({{1.}}), 1e-6);
498  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2}}), Point({{4.}}), 1e-6);
499 
500  // initialize grid
501  for (size_t bin = 0; bin < g.size(); ++bin) {
502  g.at(bin) = bin;
503  }
504 
505  // consistency of access
506  const auto& point = Point({{0.7}});
507  size_t globalBin = g.globalBinFromPosition(point);
508  indices localBins = g.localBinsFromGlobalBin(globalBin);
509 
510  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
511  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
512 }
513 
514 BOOST_AUTO_TEST_CASE(grid_test_2d_variable) {
515  using Point = std::array<double, 2>;
516  using indices = std::array<size_t, 2>;
517  VariableAxis a({0.0, 0.5, 3.0});
518  VariableAxis b({0.0, 1.0, 4.0});
521 
522  // test general properties
523  BOOST_CHECK_EQUAL(g.size(), 16u);
524  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
525  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
526 
527  // test grid points
528  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0}})), 5u);
529  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1}})), 6u);
530  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 4}})), 7u);
531  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 0}})), 9u);
532  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 1}})), 10u);
533  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 4}})), 11u);
534  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 0}})), 13u);
535  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 1}})), 14u);
536  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 4}})), 15u);
537 
538  // test some arbitrary points
539  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.3, 1.2}})), 6u);
540  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.3, 2.2}})), 14u);
541  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.8, 0.9}})), 9u);
542  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.1, 0.7}})), 13u);
543  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.3, 1.4}})), 10u);
544  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, -3}})), 8u);
545  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 8}})), 11u);
546  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, 1}})), 2u);
547  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{11, 3}})), 14u);
548  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, -2}})), 0u);
549  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{7, -2}})), 12u);
550  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 12}})), 3u);
551  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{11, 12}})), 15u);
552 
553  // global bin index -> local bin indices
554  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0}}));
555  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 1}}));
556  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 2}}));
557  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 3}}));
558  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{1, 0}}));
559  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{1, 1}}));
560  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{1, 2}}));
561  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{1, 3}}));
562  BOOST_CHECK(g.localBinsFromGlobalBin(8) == indices({{2, 0}}));
563  BOOST_CHECK(g.localBinsFromGlobalBin(9) == indices({{2, 1}}));
564  BOOST_CHECK(g.localBinsFromGlobalBin(10) == indices({{2, 2}}));
565  BOOST_CHECK(g.localBinsFromGlobalBin(11) == indices({{2, 3}}));
566  BOOST_CHECK(g.localBinsFromGlobalBin(12) == indices({{3, 0}}));
567  BOOST_CHECK(g.localBinsFromGlobalBin(13) == indices({{3, 1}}));
568  BOOST_CHECK(g.localBinsFromGlobalBin(14) == indices({{3, 2}}));
569  BOOST_CHECK(g.localBinsFromGlobalBin(15) == indices({{3, 3}}));
570 
571  // local bin indices -> global bin index
572  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0}}), 0u);
573  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1}}), 1u);
574  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 2}}), 2u);
575  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3}}), 3u);
576  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0}}), 4u);
577  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1}}), 5u);
578  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 2}}), 6u);
579  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3}}), 7u);
580  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0}}), 8u);
581  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1}}), 9u);
582  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 2}}), 10u);
583  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3}}), 11u);
584  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0}}), 12u);
585  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 1}}), 13u);
586  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 2}}), 14u);
587  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 3}}), 15u);
588 
589  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
590  Point({{3.2, 1.8}}))) == indices({{3, 2}}));
591 
592  // inside checks
593  BOOST_CHECK(not g.isInside(Point({{-2., -1}})));
594  BOOST_CHECK(not g.isInside(Point({{-2., 1.}})));
595  BOOST_CHECK(not g.isInside(Point({{-2., 5.}})));
596  BOOST_CHECK(not g.isInside(Point({{1., -1.}})));
597  BOOST_CHECK(not g.isInside(Point({{6., -1.}})));
598  BOOST_CHECK(g.isInside(Point({{0.5, 1.3}})));
599  BOOST_CHECK(not g.isInside(Point({{3., -1.}})));
600  BOOST_CHECK(not g.isInside(Point({{3., 0.3}})));
601  BOOST_CHECK(not g.isInside(Point({{3., 4.}})));
602  BOOST_CHECK(not g.isInside(Point({{-1., 4.}})));
603  BOOST_CHECK(not g.isInside(Point({{2., 4.}})));
604  BOOST_CHECK(not g.isInside(Point({{5., 4.}})));
605 
606  // test some bin centers
607  CHECK_CLOSE_ABS(g.binCenter({{1, 1}}), Point({{0.25, 0.5}}), 1e-6);
608  CHECK_CLOSE_ABS(g.binCenter({{2, 1}}), Point({{1.75, 0.5}}), 1e-6);
609  CHECK_CLOSE_ABS(g.binCenter({{1, 2}}), Point({{0.25, 2.5}}), 1e-6);
610  CHECK_CLOSE_ABS(g.binCenter({{2, 2}}), Point({{1.75, 2.5}}), 1e-6);
611 
612  // test some lower-left bin edges
613  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1}}), Point({{0., 0.}}), 1e-6);
614  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 1}}), Point({{0.5, 0.}}), 1e-6);
615  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2}}), Point({{0., 1.}}), 1e-6);
616  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 2}}), Point({{0.5, 1.}}), 1e-6);
617 
618  // test some upper right-bin edges
619  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1}}), Point({{0.5, 1.}}), 1e-6);
620  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 1}}), Point({{3., 1.}}), 1e-6);
621  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2}}), Point({{0.5, 4.}}), 1e-6);
622  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 2}}), Point({{3., 4.}}), 1e-6);
623 
624  // initialize grid
625  for (size_t bin = 0; bin < g.size(); ++bin) {
626  g.at(bin) = bin;
627  }
628 
629  // consistency of access
630  const auto& point = Point({{0.7, 1.3}});
631  size_t globalBin = g.globalBinFromPosition(point);
632  indices localBins = g.localBinsFromGlobalBin(globalBin);
633 
634  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
635  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
636 }
637 
638 BOOST_AUTO_TEST_CASE(grid_test_3d_variable) {
639  using Point = std::array<double, 3>;
640  using indices = std::array<size_t, 3>;
641  VariableAxis a({0.0, 1.0});
642  VariableAxis b({0.0, 0.5, 3.0});
643  VariableAxis c({0.0, 0.5, 3.0, 3.3});
646 
647  // test general properties
648  BOOST_CHECK_EQUAL(g.size(), 60u);
649  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 1u);
650  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
651  BOOST_CHECK_EQUAL(g.numLocalBins().at(2), 3u);
652 
653  // test grid points
654  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 0}})), 26u);
655  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 0}})), 46u);
656  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 0}})), 31u);
657  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 0}})), 51u);
658  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 0}})), 36u);
659  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 0}})), 56u);
660  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 0.5}})), 27u);
661  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 0.5}})), 47u);
662  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 0.5}})), 32u);
663  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 0.5}})), 52u);
664  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 0.5}})), 37u);
665  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 0.5}})), 57u);
666  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 3}})), 28u);
667  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 3}})), 48u);
668  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 3}})), 33u);
669  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 3}})), 53u);
670  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 3}})), 38u);
671  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 3}})), 58u);
672  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 3.3}})), 29u);
673  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 3.3}})), 49u);
674  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 3.3}})), 34u);
675  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 3.3}})), 54u);
676  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 3.3}})), 39u);
677  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 3.3}})), 59u);
678 
679  // global bin index -> local bin indices
680  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0, 0}}));
681  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 0, 1}}));
682  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 0, 2}}));
683  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 0, 3}}));
684  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{0, 0, 4}}));
685  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{0, 1, 0}}));
686  BOOST_CHECK(g.localBinsFromGlobalBin(21) == indices({{1, 0, 1}}));
687  BOOST_CHECK(g.localBinsFromGlobalBin(22) == indices({{1, 0, 2}}));
688  BOOST_CHECK(g.localBinsFromGlobalBin(23) == indices({{1, 0, 3}}));
689  BOOST_CHECK(g.localBinsFromGlobalBin(24) == indices({{1, 0, 4}}));
690  BOOST_CHECK(g.localBinsFromGlobalBin(25) == indices({{1, 1, 0}}));
691  BOOST_CHECK(g.localBinsFromGlobalBin(26) == indices({{1, 1, 1}}));
692  BOOST_CHECK(g.localBinsFromGlobalBin(57) == indices({{2, 3, 2}}));
693  BOOST_CHECK(g.localBinsFromGlobalBin(58) == indices({{2, 3, 3}}));
694  BOOST_CHECK(g.localBinsFromGlobalBin(59) == indices({{2, 3, 4}}));
695 
696  // local bin indices -> global bin index
697  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 0}}), 0u);
698  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0, 0}}), 20u);
699  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0, 0}}), 40u);
700  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 0}}), 5u);
701  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 0}}), 25u);
702  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1, 0}}), 45u);
703  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3, 1}}), 16u);
704  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3, 1}}), 36u);
705  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 1}}), 56u);
706  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 2}}), 2u);
707  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0, 2}}), 22u);
708  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0, 2}}), 42u);
709  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3, 4}}), 19u);
710  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3, 4}}), 39u);
711  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 4}}), 59u);
712 
713  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
714  Point({{1.8, 0.7, 3.2}}))) == indices({{2, 2, 3}}));
715 
716  // inside checks
717  BOOST_CHECK(not g.isInside(Point({{-2., -1, -2}})));
718  BOOST_CHECK(not g.isInside(Point({{-2., 1., 0.}})));
719  BOOST_CHECK(not g.isInside(Point({{-2., 5., -1}})));
720  BOOST_CHECK(not g.isInside(Point({{1., -1., 1.}})));
721  BOOST_CHECK(not g.isInside(Point({{6., -1., 4.}})));
722  BOOST_CHECK(g.isInside(Point({{0.5, 1.3, 1.7}})));
723  BOOST_CHECK(not g.isInside(Point({{1., -1., -0.4}})));
724  BOOST_CHECK(not g.isInside(Point({{1., 0.3, 3.4}})));
725  BOOST_CHECK(not g.isInside(Point({{1., 3., 0.8}})));
726  BOOST_CHECK(not g.isInside(Point({{-1., 3., 5.}})));
727  BOOST_CHECK(not g.isInside(Point({{2., 3., -1.}})));
728  BOOST_CHECK(not g.isInside(Point({{5., 3., 0.5}})));
729 
730  // test some bin centers
731  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 1}}), Point({{0.5, 0.25, 0.25}}), 1e-6);
732  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 2}}), Point({{0.5, 0.25, 1.75}}), 1e-6);
733  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 3}}), Point({{0.5, 0.25, 3.15}}), 1e-6);
734  CHECK_CLOSE_ABS(g.binCenter({{1, 2, 1}}), Point({{0.5, 1.75, 0.25}}), 1e-6);
735  CHECK_CLOSE_ABS(g.binCenter({{1, 2, 2}}), Point({{0.5, 1.75, 1.75}}), 1e-6);
736  CHECK_CLOSE_ABS(g.binCenter({{1, 2, 3}}), Point({{0.5, 1.75, 3.15}}), 1e-6);
737 
738  // test some lower-left bin edges
739  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 1}}), Point({{0., 0., 0.}}), 1e-6);
740  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 2}}), Point({{0., 0., 0.5}}),
741  1e-6);
742  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 3}}), Point({{0., 0., 3.}}), 1e-6);
743  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2, 1}}), Point({{0., 0.5, 0.}}),
744  1e-6);
745  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2, 2}}), Point({{0., 0.5, 0.5}}),
746  1e-6);
747  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2, 3}}), Point({{0., 0.5, 3.}}),
748  1e-6);
749 
750  // test some upper right-bin edges
751  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 1}}), Point({{1., 0.5, 0.5}}),
752  1e-6);
753  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 2}}), Point({{1., 0.5, 3.}}),
754  1e-6);
755  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 3}}), Point({{1., 0.5, 3.3}}),
756  1e-6);
757  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2, 1}}), Point({{1., 3., 0.5}}),
758  1e-6);
759  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2, 2}}), Point({{1., 3., 3.}}),
760  1e-6);
761  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2, 3}}), Point({{1., 3., 3.3}}),
762  1e-6);
763 
764  // initialize grid
765  for (size_t bin = 0; bin < g.size(); ++bin) {
766  g.at(bin) = bin;
767  }
768 
769  // consistency of access
770  const auto& point = Point({{0.7, 1.3, 3.7}});
771  size_t globalBin = g.globalBinFromPosition(point);
772  indices localBins = g.localBinsFromGlobalBin(globalBin);
773 
774  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
775  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
776 }
777 
778 BOOST_AUTO_TEST_CASE(grid_test_2d_mixed) {
779  using Point = std::array<double, 2>;
780  using indices = std::array<size_t, 2>;
781  EquidistantAxis a(0.0, 1.0, 4u);
782  VariableAxis b({0.0, 0.5, 3.0});
785 
786  // test general properties
787  BOOST_CHECK_EQUAL(g.size(), 24u);
788  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
789  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
790 
791  // test grid points
792  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0}})), 5u);
793  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.25, 0}})), 9u);
794  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 0}})), 13u);
795  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.75, 0}})), 17u);
796  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0}})), 21u);
797  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5}})), 6u);
798  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.25, 0.5}})), 10u);
799  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 0.5}})), 14u);
800  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.75, 0.5}})), 18u);
801  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5}})), 22u);
802  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3}})), 7u);
803  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.25, 3}})), 11u);
804  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 3}})), 15u);
805  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.75, 3}})), 19u);
806  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3}})), 23u);
807 
808  // test some arbitrary points
809  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2, 0.3}})), 21u);
810  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.2, 1.3}})), 6u);
811  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.9, 1.8}})), 18u);
812  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.7, 2.1}})), 14u);
813  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.4, 0.3}})), 9u);
814  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, 2}})), 2u);
815  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{8, 1}})), 22u);
816  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.1, -3}})), 4u);
817  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.8, 11}})), 19u);
818  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, -3}})), 0u);
819  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, 7}})), 3u);
820  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, -1}})), 20u);
821  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, 11}})), 23u);
822 
823  // global bin index -> local bin indices
824  using indices = std::array<size_t, 2>;
825  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0}}));
826  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 1}}));
827  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 2}}));
828  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 3}}));
829  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{1, 0}}));
830  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{1, 1}}));
831  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{1, 2}}));
832  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{1, 3}}));
833  BOOST_CHECK(g.localBinsFromGlobalBin(8) == indices({{2, 0}}));
834  BOOST_CHECK(g.localBinsFromGlobalBin(9) == indices({{2, 1}}));
835  BOOST_CHECK(g.localBinsFromGlobalBin(10) == indices({{2, 2}}));
836  BOOST_CHECK(g.localBinsFromGlobalBin(11) == indices({{2, 3}}));
837  BOOST_CHECK(g.localBinsFromGlobalBin(12) == indices({{3, 0}}));
838  BOOST_CHECK(g.localBinsFromGlobalBin(13) == indices({{3, 1}}));
839  BOOST_CHECK(g.localBinsFromGlobalBin(14) == indices({{3, 2}}));
840  BOOST_CHECK(g.localBinsFromGlobalBin(15) == indices({{3, 3}}));
841  BOOST_CHECK(g.localBinsFromGlobalBin(16) == indices({{4, 0}}));
842  BOOST_CHECK(g.localBinsFromGlobalBin(17) == indices({{4, 1}}));
843  BOOST_CHECK(g.localBinsFromGlobalBin(18) == indices({{4, 2}}));
844  BOOST_CHECK(g.localBinsFromGlobalBin(19) == indices({{4, 3}}));
845  BOOST_CHECK(g.localBinsFromGlobalBin(20) == indices({{5, 0}}));
846  BOOST_CHECK(g.localBinsFromGlobalBin(21) == indices({{5, 1}}));
847  BOOST_CHECK(g.localBinsFromGlobalBin(22) == indices({{5, 2}}));
848  BOOST_CHECK(g.localBinsFromGlobalBin(23) == indices({{5, 3}}));
849 
850  // local bin indices -> global bin index
851  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0}}), 0u);
852  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1}}), 1u);
853  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 2}}), 2u);
854  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3}}), 3u);
855  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0}}), 4u);
856  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1}}), 5u);
857  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 2}}), 6u);
858  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3}}), 7u);
859  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0}}), 8u);
860  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1}}), 9u);
861  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 2}}), 10u);
862  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3}}), 11u);
863  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0}}), 12u);
864  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 1}}), 13u);
865  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 2}}), 14u);
866  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 3}}), 15u);
867  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 0}}), 16u);
868  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 1}}), 17u);
869  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 2}}), 18u);
870  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 3}}), 19u);
871  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 0}}), 20u);
872  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 1}}), 21u);
873  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 2}}), 22u);
874  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 3}}), 23u);
875 
876  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
877  Point({{1.1, 1.7}}))) == indices({{5, 2}}));
878 
879  // inside checks
880  BOOST_CHECK(not g.isInside(Point({{-2., -1}})));
881  BOOST_CHECK(not g.isInside(Point({{-2., 1.}})));
882  BOOST_CHECK(not g.isInside(Point({{-2., 5.}})));
883  BOOST_CHECK(not g.isInside(Point({{0.1, -1.}})));
884  BOOST_CHECK(not g.isInside(Point({{6., -1.}})));
885  BOOST_CHECK(g.isInside(Point({{0.5, 1.3}})));
886  BOOST_CHECK(not g.isInside(Point({{1., -1.}})));
887  BOOST_CHECK(not g.isInside(Point({{1., 0.3}})));
888  BOOST_CHECK(not g.isInside(Point({{1., 3.}})));
889  BOOST_CHECK(not g.isInside(Point({{-1., 3.}})));
890  BOOST_CHECK(not g.isInside(Point({{0.2, 3.}})));
891  BOOST_CHECK(not g.isInside(Point({{5., 3.}})));
892 
893  // test some bin centers
894  CHECK_CLOSE_ABS(g.binCenter({{1, 1}}), Point({{0.125, 0.25}}), 1e-6);
895  CHECK_CLOSE_ABS(g.binCenter({{1, 2}}), Point({{0.125, 1.75}}), 1e-6);
896  CHECK_CLOSE_ABS(g.binCenter({{2, 1}}), Point({{0.375, 0.25}}), 1e-6);
897  CHECK_CLOSE_ABS(g.binCenter({{2, 2}}), Point({{0.375, 1.75}}), 1e-6);
898  CHECK_CLOSE_ABS(g.binCenter({{3, 1}}), Point({{0.625, 0.25}}), 1e-6);
899  CHECK_CLOSE_ABS(g.binCenter({{3, 2}}), Point({{0.625, 1.75}}), 1e-6);
900  CHECK_CLOSE_ABS(g.binCenter({{4, 1}}), Point({{0.875, 0.25}}), 1e-6);
901  CHECK_CLOSE_ABS(g.binCenter({{4, 2}}), Point({{0.875, 1.75}}), 1e-6);
902 
903  // test some lower-left bin edges
904  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1}}), Point({{0., 0.}}), 1e-6);
905  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2}}), Point({{0., 0.5}}), 1e-6);
906  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 1}}), Point({{0.25, 0.}}), 1e-6);
907  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 2}}), Point({{0.25, 0.5}}), 1e-6);
908  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3, 1}}), Point({{0.5, 0.}}), 1e-6);
909  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3, 2}}), Point({{0.5, 0.5}}), 1e-6);
910  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4, 1}}), Point({{0.75, 0.}}), 1e-6);
911  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4, 2}}), Point({{0.75, 0.5}}), 1e-6);
912 
913  // test some upper-right bin edges
914  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1}}), Point({{0.25, 0.5}}), 1e-6);
915  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2}}), Point({{0.25, 3.}}), 1e-6);
916  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 1}}), Point({{0.5, 0.5}}), 1e-6);
917  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 2}}), Point({{0.5, 3.}}), 1e-6);
918  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3, 1}}), Point({{0.75, 0.5}}), 1e-6);
919  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3, 2}}), Point({{0.75, 3.}}), 1e-6);
920  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4, 1}}), Point({{1., 0.5}}), 1e-6);
921  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4, 2}}), Point({{1., 3.}}), 1e-6);
922 
923  // initialize grid
924  for (size_t bin = 0; bin < g.size(); ++bin) {
925  g.at(bin) = bin;
926  }
927 
928  // consistency of access
929  const auto& point = Point({{1.3, 3.7}});
930  size_t globalBin = g.globalBinFromPosition(point);
931  indices localBins = g.localBinsFromGlobalBin(globalBin);
932 
933  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
934  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
935 }
936 
937 BOOST_AUTO_TEST_CASE(grid_test_2d_mixed_at) {
938  EquidistantAxis a(0.0, 6.0, 4u);
939  VariableAxis b({0.0, 1.5, 3.0});
942 
943  // initialize the grid
944  using Point = std::array<double, 2>;
945  g.atPosition(Point({{0, 0}})) = 0.;
946  g.atPosition(Point({{1.5, 0}})) = 1.;
947  g.atPosition(Point({{3, 0}})) = 2.;
948  g.atPosition(Point({{4.5, 0}})) = 3.;
949  g.atPosition(Point({{6, 0}})) = 4.;
950  g.atPosition(Point({{0, 1.5}})) = 5.;
951  g.atPosition(Point({{1.5, 1.5}})) = 6.;
952  g.atPosition(Point({{3, 1.5}})) = 7.;
953  g.atPosition(Point({{4.5, 1.5}})) = 8.;
954  g.atPosition(Point({{6, 1.5}})) = 9.;
955  g.atPosition(Point({{0, 3}})) = 10.;
956  g.atPosition(Point({{1.5, 3}})) = 11.;
957  g.atPosition(Point({{3, 3}})) = 12.;
958  g.atPosition(Point({{4.5, 3}})) = 13.;
959  g.atPosition(Point({{6, 3}})) = 14.;
960 
961  // test general properties
962  BOOST_CHECK_EQUAL(g.size(), 24u);
963 
964  // test some arbitrary points
965  BOOST_CHECK_EQUAL(g.atPosition(Point({{1.2, 0.3}})), 0.);
966  BOOST_CHECK_EQUAL(g.atPosition(Point({{2.2, 1.3}})), 1.);
967  BOOST_CHECK_EQUAL(g.atPosition(Point({{4.9, 1.8}})), 8.);
968  BOOST_CHECK_EQUAL(g.atPosition(Point({{3.7, 2.1}})), 7.);
969  BOOST_CHECK_EQUAL(g.atPosition(Point({{0.4, 2.3}})), 5.);
970 }
971 
972 BOOST_AUTO_TEST_CASE(grid_interpolation) {
973  using Point = std::array<double, 3>;
974  EquidistantAxis a(1.0, 3.0, 2u);
975  EquidistantAxis b(1.0, 5.0, 2u);
976  EquidistantAxis c(1.0, 7.0, 2u);
979 
980  g.atPosition(Point({{1., 1., 1.}})) = 10.;
981  g.atPosition(Point({{2., 1., 1.}})) = 20.;
982  g.atPosition(Point({{1., 3., 1.}})) = 30.;
983  g.atPosition(Point({{2., 3., 1.}})) = 40.;
984  g.atPosition(Point({{1., 1., 4.}})) = 50.;
985  g.atPosition(Point({{2., 1., 4.}})) = 60.;
986  g.atPosition(Point({{1., 3., 4.}})) = 70.;
987  g.atPosition(Point({{2., 3., 4.}})) = 80.;
988 
989  CHECK_CLOSE_REL(g.interpolate(Point({{1., 1., 1.}})), 10., 1e-6);
990  CHECK_CLOSE_REL(g.interpolate(Point({{2., 1., 1.}})), 20., 1e-6);
991  CHECK_CLOSE_REL(g.interpolate(Point({{1., 3., 1.}})), 30., 1e-6);
992  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 1.}})), 40., 1e-6);
993  CHECK_CLOSE_REL(g.interpolate(Point({{1., 1., 4.}})), 50., 1e-6);
994  CHECK_CLOSE_REL(g.interpolate(Point({{2., 1., 4.}})), 60., 1e-6);
995  CHECK_CLOSE_REL(g.interpolate(Point({{1., 3., 4.}})), 70., 1e-6);
996  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 4.}})), 80., 1e-6);
997  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 1., 1.}})), 15., 1e-6);
998  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 3., 1.}})), 35., 1e-6);
999  CHECK_CLOSE_REL(g.interpolate(Point({{1., 2., 1.}})), 20., 1e-6);
1000  CHECK_CLOSE_REL(g.interpolate(Point({{2., 2., 1.}})), 30., 1e-6);
1001  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 1., 4.}})), 55., 1e-6);
1002  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 3., 4.}})), 75., 1e-6);
1003  CHECK_CLOSE_REL(g.interpolate(Point({{1., 2., 4.}})), 60., 1e-6);
1004  CHECK_CLOSE_REL(g.interpolate(Point({{2., 2., 4.}})), 70., 1e-6);
1005  CHECK_CLOSE_REL(g.interpolate(Point({{1., 1., 2.5}})), 30., 1e-6);
1006  CHECK_CLOSE_REL(g.interpolate(Point({{1., 3., 2.5}})), 50., 1e-6);
1007  CHECK_CLOSE_REL(g.interpolate(Point({{2., 1., 2.5}})), 40., 1e-6);
1008  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 2.5}})), 60., 1e-6);
1009  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 2., 2.5}})), 360. / 8, 1e-6);
1010  CHECK_CLOSE_REL(g.interpolate(Point({{1.3, 2.1, 1.6}})), 32., 1e-6);
1011  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 4.}})), 80., 1e-6);
1012 }
1013 
1014 BOOST_AUTO_TEST_CASE(neighborhood) {
1015  using bins_t = std::vector<size_t>;
1016  using EAxis = EquidistantAxis;
1017  using Grid1_t = Grid<double, EAxis>;
1018  using Grid2_t = Grid<double, EAxis, EAxis>;
1019  using Grid3_t = Grid<double, EAxis, EAxis, EAxis>;
1020 
1021  EAxis a(0.0, 1.0, 10u);
1022  EAxis b(0.0, 1.0, 10u);
1023  EAxis c(0.0, 1.0, 10u);
1024  Grid1_t g1(std::make_tuple(a));
1025  Grid2_t g2(std::make_tuple(a, b));
1026  Grid3_t g3(std::make_tuple(std::move(a), std::move(b), std::move(c)));
1027 
1028  // clang-format off
1029  // 1D case
1030  BOOST_CHECK(g1.neighborHoodIndices({{0}}, 1).collectVector()
1031  == bins_t({0, 1}));
1032  BOOST_CHECK(g1.neighborHoodIndices({{0}}, 2).collectVector()
1033  == bins_t({0, 1, 2}));
1034  BOOST_CHECK(g1.neighborHoodIndices({{1}}, 1).collectVector()
1035  == bins_t({0, 1, 2}));
1036  BOOST_CHECK(g1.neighborHoodIndices({{1}}, 3).collectVector()
1037  == bins_t({0, 1, 2, 3, 4}));
1038  BOOST_CHECK(g1.neighborHoodIndices({{4}}, 2).collectVector()
1039  == bins_t({2, 3, 4, 5, 6}));
1040  BOOST_CHECK(g1.neighborHoodIndices({{9}}, 2).collectVector()
1041  == bins_t({7, 8, 9, 10, 11}));
1042  BOOST_CHECK(g1.neighborHoodIndices({{10}}, 2).collectVector()
1043  == bins_t({8, 9, 10, 11}));
1044  BOOST_CHECK(g1.neighborHoodIndices({{11}}, 2).collectVector()
1045  == bins_t({9, 10, 11}));
1046 
1047  // 2D case
1048  BOOST_CHECK(g2.neighborHoodIndices({{0, 0}}, 1).collectVector()
1049  == bins_t({0, 1, 12, 13}));
1050  BOOST_CHECK(g2.neighborHoodIndices({{0, 1}}, 1).collectVector()
1051  == bins_t({0, 1, 2, 12, 13, 14}));
1052  BOOST_CHECK(g2.neighborHoodIndices({{1, 0}}, 1).collectVector()
1053  == bins_t({0, 1, 12, 13, 24, 25}));
1054  BOOST_CHECK(g2.neighborHoodIndices({{1, 1}}, 1).collectVector()
1055  == bins_t({0, 1, 2, 12, 13, 14, 24, 25, 26}));
1056  BOOST_CHECK(g2.neighborHoodIndices({{5, 5}}, 1).collectVector()
1057  == bins_t({52, 53, 54, 64, 65, 66, 76, 77, 78}));
1058  BOOST_CHECK(g2.neighborHoodIndices({{9, 10}}, 2).collectVector()
1059  == bins_t({92, 93, 94, 95, 104, 105, 106, 107, 116, 117, 118,
1060  119, 128, 129, 130, 131, 140, 141, 142, 143}));
1061 
1062  // 3D case
1063  BOOST_CHECK(g3.neighborHoodIndices({{0, 0, 0}}, 1).collectVector()
1064  == bins_t({0, 1, 12, 13, 144, 145, 156, 157}));
1065  BOOST_CHECK(g3.neighborHoodIndices({{0, 0, 1}}, 1).collectVector()
1066  == bins_t({0, 1, 2, 12, 13, 14, 144, 145, 146, 156, 157, 158}));
1067  BOOST_CHECK(g3.neighborHoodIndices({{0, 1, 0}}, 1).collectVector()
1068  == bins_t({0, 1, 12, 13, 24, 25, 144, 145, 156, 157, 168, 169}));
1069  BOOST_CHECK(g3.neighborHoodIndices({{1, 0, 0}}, 1).collectVector()
1070  == bins_t({0, 1, 12, 13, 144, 145, 156, 157, 288, 289, 300, 301}));
1071  BOOST_CHECK(g3.neighborHoodIndices({{0, 1, 1}}, 1).collectVector()
1072  == bins_t({0, 1, 2, 12, 13, 14, 24, 25, 26, 144, 145, 146,
1073  156, 157, 158, 168, 169, 170}));
1074  BOOST_CHECK(g3.neighborHoodIndices({{1, 1, 1}}, 1).collectVector()
1075  == bins_t({0, 1, 2, 12, 13, 14, 24, 25, 26, 144, 145, 146,
1076  156, 157, 158, 168, 169, 170, 288, 289, 290, 300,
1077  301, 302, 312, 313, 314}));
1078  BOOST_CHECK(g3.neighborHoodIndices({{11, 10, 9}}, 1).collectVector()
1079  == bins_t({1556, 1557, 1558, 1568, 1569, 1570, 1580, 1581,
1080  1582, 1700, 1701, 1702, 1712, 1713, 1714, 1724,
1081  1725, 1726}));
1082 
1083  // Neighbors array
1084  std::array<std::pair<int,int>,1> a1;
1085  a1.at(0) = std::make_pair<int,int>(-1,1);
1086  BOOST_CHECK(g1.neighborHoodIndices({{0}}, a1).collectVector()
1087  == bins_t({0,1}));
1088  BOOST_CHECK(g1.neighborHoodIndices({{2}}, a1).collectVector()
1089  == bins_t({1,2,3}));
1090 
1091  a1.at(0) = std::make_pair<int,int>(2,3);
1092  BOOST_CHECK(g1.neighborHoodIndices({{2}}, a1).collectVector()
1093  == bins_t({4,5}));
1094 
1095  a1.at(0) = std::make_pair<int,int>(-2,-1);
1096  BOOST_CHECK(g1.neighborHoodIndices({{2}}, a1).collectVector()
1097  == bins_t({0,1}));
1098 
1099  a1.at(0) = std::make_pair<int,int>(-3,-1);
1100  BOOST_CHECK(g1.neighborHoodIndices({{2}}, a1).collectVector()
1101  == bins_t({0,1}));
1102  // clang-format on
1103 
1105  using Grid1Closed_t = Grid<double, EAxisClosed>;
1106  EAxisClosed d(0.0, 1.0, 10u);
1107 
1108  Grid1Closed_t g1Cl(std::make_tuple(std::move(d)));
1109  BOOST_CHECK(g1Cl.neighborHoodIndices({{0}}, 1).collectVector() ==
1110  bins_t({})); // underflow, makes no sense
1111  BOOST_CHECK(g1Cl.neighborHoodIndices({{11}}, 1).collectVector() ==
1112  bins_t({})); // overflow, makes no sense
1113  BOOST_CHECK(g1Cl.neighborHoodIndices({{1}}, 1).collectVector() ==
1114  bins_t({10, 1, 2})); // overflow, makes no sense
1115  BOOST_CHECK(g1Cl.neighborHoodIndices({{5}}, 1).collectVector() ==
1116  bins_t({4, 5, 6})); // overflow, makes no sense
1117 
1118  using Grid2Closed_t = Grid<double, EAxisClosed, EAxisClosed>;
1119  // typedef Grid<double, EAxisClosed, EAxisClosed, EAxisClosed>
1120  // Grid3Closed_t;
1121  EAxisClosed e(0.0, 1.0, 5u);
1122  EAxisClosed f(0.0, 1.0, 5u);
1123  Grid2Closed_t g2Cl(std::make_tuple(std::move(e), std::move(f)));
1124  BOOST_CHECK(g2Cl.neighborHoodIndices({{3, 3}}, 1).collectVector() ==
1125  bins_t({16, 17, 18, 23, 24, 25, 30, 31, 32}));
1126  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 1}}, 1).collectVector() ==
1127  bins_t({40, 36, 37, 12, 8, 9, 19, 15, 16}));
1128  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 5}}, 1).collectVector() ==
1129  bins_t({39, 40, 36, 11, 12, 8, 18, 19, 15}));
1130  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 1}}, 1).collectVector() ==
1131  bins_t({33, 29, 30, 40, 36, 37, 12, 8, 9}));
1132  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 5}}, 1).collectVector() ==
1133  bins_t({32, 33, 29, 39, 40, 36, 11, 12, 8}));
1134 
1135  BOOST_CHECK(g2Cl.neighborHoodIndices({{3, 3}}, 2).collectVector() ==
1136  bins_t({8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 22, 23, 24,
1137  25, 26, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40}));
1138  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 1}}, 2).collectVector() ==
1139  bins_t({32, 33, 29, 30, 31, 39, 40, 36, 37, 38, 11, 12, 8,
1140  9, 10, 18, 19, 15, 16, 17, 25, 26, 22, 23, 24}));
1141  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 5}}, 2).collectVector() ==
1142  bins_t({31, 32, 33, 29, 30, 38, 39, 40, 36, 37, 10, 11, 12,
1143  8, 9, 17, 18, 19, 15, 16, 24, 25, 26, 22, 23}));
1144  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 1}}, 2).collectVector() ==
1145  bins_t({25, 26, 22, 23, 24, 32, 33, 29, 30, 31, 39, 40, 36,
1146  37, 38, 11, 12, 8, 9, 10, 18, 19, 15, 16, 17}));
1147  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 5}}, 2).collectVector() ==
1148  bins_t({24, 25, 26, 22, 23, 31, 32, 33, 29, 30, 38, 39, 40,
1149  36, 37, 10, 11, 12, 8, 9, 17, 18, 19, 15, 16}));
1150 
1151  std::array<std::pair<int, int>, 2> a2;
1152  a2.at(0) =
1153  std::make_pair<int, int>(-2, -1); // only 2 bins left of requested bin
1154  // (not including the requested bin)
1155  a2.at(1) = std::make_pair<int, int>(
1156  -1, 2); // one bin left of requested bin, the requested bin itself and 2
1157  // bins right of requested bin
1158  std::set<size_t> returnedBins;
1159 
1160  auto returnedBinsVec = g2Cl.neighborHoodIndices({{3, 2}}, a2).collectVector();
1161  returnedBins.insert(returnedBinsVec.begin(), returnedBinsVec.end());
1162  std::set<size_t> expectedBins{{8, 9, 10, 11, 15, 16, 17, 18}};
1163  BOOST_CHECK(returnedBins == expectedBins);
1164 
1165  returnedBinsVec = g2Cl.neighborHoodIndices({{1, 5}}, a2).collectVector();
1166  returnedBins.clear();
1167  returnedBins.insert(returnedBinsVec.begin(), returnedBinsVec.end());
1168  expectedBins = {{29, 30, 32, 33, 36, 37, 39, 40}};
1169  BOOST_CHECK(returnedBins == expectedBins);
1170 
1171  a2.at(0) = {-6, 7};
1172  a2.at(1) = {0, 0};
1173  returnedBinsVec = g2Cl.neighborHoodIndices({{1, 5}}, a2).collectVector();
1174  returnedBins.clear();
1175  returnedBins.insert(returnedBinsVec.begin(), returnedBinsVec.end());
1176  expectedBins = {{12, 19, 26, 33, 40}};
1177  BOOST_CHECK(returnedBins == expectedBins);
1178 
1179  // @TODO 3D test would be nice, but should essentially not be a problem if
1180  // 2D works.
1181 
1182  // clang-format off
1183  /*
1184  * 1 2 3 4 5
1185  * |------------------------|
1186  * 1 | 8 | 9 | 10 | 11 | 12 |
1187  * |----|----|----|----|----|
1188  * 2 | 15 | 16 | 17 | 18 | 19 |
1189  * |----|----|----|----|----|
1190  * 3 | 22 | 23 | 24 | 25 | 26 |
1191  * |----|----|----|----|----|
1192  * 4 | 29 | 30 | 31 | 32 | 33 |
1193  * |----|----|----|----|----|
1194  * 5 | 36 | 37 | 38 | 39 | 40 |
1195  * |------------------------|
1196  */
1197  // clang-format on
1198 }
1199 
1200 BOOST_AUTO_TEST_CASE(closestPoints) {
1201  using Point = std::array<double, 3>;
1202  using bins_t = std::vector<size_t>;
1203  using EAxis = EquidistantAxis;
1204  using Grid1_t = Grid<double, EAxis>;
1205  using Grid2_t = Grid<double, EAxis, EAxis>;
1206  using Grid3_t = Grid<double, EAxis, EAxis, EAxis>;
1207 
1208  EAxis a(0.0, 1.0, 10u);
1209  EAxis b(0.0, 1.0, 5u);
1210  EAxis c(0.0, 1.0, 3u);
1211  Grid1_t g1(std::make_tuple(a));
1212  Grid2_t g2(std::make_tuple(a, b));
1213  Grid3_t g3(std::make_tuple(std::move(a), std::move(b), std::move(c)));
1214 
1215  // clang-format off
1216  // 1D case
1217  BOOST_CHECK(g1.closestPointsIndices(Point({{0.52}})).collectVector()
1218  == bins_t({6, 7}));
1219  BOOST_CHECK(g1.closestPointsIndices(Point({{0.98}})).collectVector()
1220  == bins_t({10, 11}));
1221 
1222  // 2D case
1223  BOOST_CHECK(g2.closestPointsIndices(Point({{0.52, 0.08}})).collectVector()
1224  == bins_t({43, 44, 50, 51}));
1225  BOOST_CHECK(g2.closestPointsIndices(Point({{0.05, 0.08}})).collectVector()
1226  == bins_t({8, 9, 15, 16}));
1227 
1228  // 3D case
1229  BOOST_CHECK(g3.closestPointsIndices(Point({{0.23, 0.13, 0.61}})).collectVector()
1230  == bins_t({112, 113, 117, 118, 147, 148, 152, 153}));
1231  BOOST_CHECK(g3.closestPointsIndices(Point({{0.52, 0.35, 0.71}})).collectVector()
1232  == bins_t({223, 224, 228, 229, 258, 259, 263, 264}));
1233 
1235  using Grid1Cl_t = Grid<double, EAxisClosed>;
1236  using Grid2Cl_t = Grid<double, EAxisClosed, EAxisClosed>;
1237  //using Grid3Cl_t = Grid<double, EAxisClosed, EAxisClosed, EAxisClosed>;
1238  EAxisClosed aCl(0.0, 1.0, 10u);
1239  EAxisClosed bCl(0.0, 1.0, 5u);
1240  EAxisClosed cCl(0.0, 1.0, 3u);
1241  Grid1Cl_t g1Cl(std::make_tuple(aCl));
1242  Grid2Cl_t g2Cl(std::make_tuple(std::move(aCl), std::move(bCl)));
1243 
1244  // 1D case
1245  BOOST_CHECK(g1Cl.closestPointsIndices(Point({{0.52}})).collectVector()
1246  == bins_t({6, 7}));
1247  BOOST_CHECK(g1Cl.closestPointsIndices(Point({{0.98}})).collectVector()
1248  == bins_t({10, 1}));
1249 
1250  // 2D case
1251  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.52, 0.08}})).collectVector()
1252  == bins_t({43, 44, 50, 51}));
1253  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.52, 0.68}})).collectVector()
1254  == bins_t({46, 47, 53, 54}));
1255  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.52, 0.88}})).collectVector()
1256  == bins_t({47, 43, 54, 50}));
1257  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.05, 0.08}})).collectVector()
1258  == bins_t({8, 9, 15, 16}));
1259  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.9, 0.95}})).collectVector()
1260  == bins_t({75, 71, 12, 8}));
1261 
1262  // @TODO: 3D checks would also be nice
1263 
1265  using Grid1Op_t = Grid<double, EAxisOpen>;
1266  using Grid2Op_t = Grid<double, EAxisOpen, EAxisOpen>;
1267  //using Grid3Op_t = Grid<double, EAxisOpen, EAxisOpen, EAxisOpen>;
1268 
1269  EAxisOpen aOp(0.0, 1.0, 10u);
1270  EAxisOpen bOp(0.0, 1.0, 5u);
1271  EAxisOpen cOp(0.0, 1.0, 3u);
1272  Grid1Op_t g1Op(std::make_tuple(aOp));
1273  Grid2Op_t g2Op(std::make_tuple(std::move(aOp), std::move(bOp)));
1274 
1275  // 1D case
1276  BOOST_CHECK(g1Op.closestPointsIndices(Point({{0.52}})).collectVector()
1277  == bins_t({6, 7}));
1278  BOOST_CHECK(g1Op.closestPointsIndices(Point({{0.98}})).collectVector()
1279  == bins_t({10}));
1280  BOOST_CHECK(g1Op.closestPointsIndices(Point({{0.88}})).collectVector()
1281  == bins_t({9, 10}));
1282 
1283  // 2D case
1284  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.52, 0.08}})).collectVector()
1285  == bins_t({43, 44, 50, 51}));
1286  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.52, 0.68}})).collectVector()
1287  == bins_t({46, 47, 53, 54}));
1288  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.52, 0.88}})).collectVector()
1289  == bins_t({47, 54}));
1290  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.05, 0.1}})).collectVector()
1291  == bins_t({8, 9, 15, 16}));
1292  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.95, 0.95}})).collectVector()
1293  == bins_t({75}));
1294 
1295  // @TODO: 3D checks would also be nice
1296 
1297  /*
1298  * 1 2 3 4 5
1299  * |------------------------|
1300  * 1 | 8 | 9 | 10 | 11 | 12 |
1301  * |----|----|----|----|----|
1302  * 2 | 15 | 16 | 17 | 18 | 19 |
1303  * |----|----|----|----|----|
1304  * 3 | 22 | 23 | 24 | 25 | 26 |
1305  * |----|----|----|----|----|
1306  * 4 | 29 | 30 | 31 | 32 | 33 |
1307  * |----|----|----|----|----|
1308  * 5 | 36 | 37 | 38 | 39 | 40 |
1309  * |------------------------|
1310  * 6 | 43 | 44 | 45 | 46 | 47 |
1311  * |------------------------|
1312  * 7 | 50 | 51 | 52 | 53 | 54 |
1313  * |------------------------|
1314  * 8 | 57 | 58 | 59 | 60 | 61 |
1315  * |------------------------|
1316  * 9 | 64 | 65 | 66 | 67 | 68 |
1317  * |------------------------|
1318  * 10 | 71 | 72 | 73 | 74 | 75 |
1319  * |------------------------|
1320  * 77 78 79 80 81 82 83
1321  */
1322 
1323  // clang-format on
1324 }
1325 
1326 } // namespace Test
1327 
1328 } // namespace Acts