Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UnitVectorsTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file UnitVectorsTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 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 
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <limits>
18 
19 using Acts::Vector3;
20 
21 namespace {
22 constexpr auto eps = std::numeric_limits<double>::epsilon();
23 }
24 
25 BOOST_AUTO_TEST_SUITE(UnitVectors)
26 
27 BOOST_AUTO_TEST_CASE(DirectionPhiEta) {
29 
30  // along positive x
31  const auto xPos1 = makeDirectionFromPhiEta(0.0, 0.0);
32  CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
33  CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
34  const auto xPos2 = makeDirectionFromPhiEta(2 * M_PI, 0.0);
35  CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
36  CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
37  // along negative x
38  const auto xNeg1 = makeDirectionFromPhiEta(M_PI, 0.0);
39  CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
40  CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
41  const auto xNeg2 = makeDirectionFromPhiEta(-M_PI, 0.0);
42  CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
43  CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
44  // along positive y
45  const auto yPos1 = makeDirectionFromPhiEta(M_PI_2, 0.0);
46  CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
47  CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
48  const auto yPos2 = makeDirectionFromPhiEta(-3 * M_PI_2, 0.0);
49  CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
50  CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
51  // along negative y
52  const auto yNeg1 = makeDirectionFromPhiEta(-M_PI_2, 0.0);
53  CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
54  CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
55  const auto yNeg2 = makeDirectionFromPhiEta(3 * M_PI_2, 0.0);
56  CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
57  CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
58 
59  const auto inf = std::numeric_limits<double>::infinity();
60  // along positive z
61  const auto zPos1 = makeDirectionFromPhiEta(0.0, inf);
62  CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
63  CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
64  const auto zPos2 = makeDirectionFromPhiEta(M_PI_2, inf);
65  CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
66  CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
67  // along negative z
68  const auto zNeg1 = makeDirectionFromPhiEta(0.0, -inf);
69  CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
70  CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
71  const auto zNeg2 = makeDirectionFromPhiEta(M_PI_2, -inf);
72  CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
73  CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
74 
75  // mixed direction
76  const auto mixed1 = makeDirectionFromPhiEta(M_PI_4, 1.0);
77  CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
79  mixed1.dot(Vector3(1, 1, M_SQRT2 * std::sinh(1.0)).normalized()), 1, eps);
80  const auto mixed2 = makeDirectionFromPhiEta(M_PI_4, -1.0);
81  CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
83  mixed2.dot(Vector3(1, 1, M_SQRT2 * std::sinh(-1.0)).normalized()), 1,
84  eps);
85  const auto mixed3 = makeDirectionFromPhiEta(-M_PI_4, -1.0);
86  CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
88  mixed3.dot(Vector3(1, -1, M_SQRT2 * std::sinh(-1.0)).normalized()), 1,
89  eps);
90 }
91 
92 BOOST_AUTO_TEST_CASE(DirectionPhiTheta) {
94 
95  // along positive x
96  const auto xPos1 = makeDirectionFromPhiTheta(0.0, M_PI_2);
97  CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
98  CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
99  const auto xPos2 = makeDirectionFromPhiTheta(2 * M_PI, M_PI_2);
100  CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
101  CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
102  // along negative x
103  const auto xNeg1 = makeDirectionFromPhiTheta(M_PI, M_PI_2);
104  CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
105  CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
106  const auto xNeg2 = makeDirectionFromPhiTheta(-M_PI, M_PI_2);
107  CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
108  CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
109  // along positive y
110  const auto yPos1 = makeDirectionFromPhiTheta(M_PI_2, M_PI_2);
111  CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
112  CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
113  const auto yPos2 = makeDirectionFromPhiTheta(-3 * M_PI_2, M_PI_2);
114  CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
115  CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
116  // along negative y
117  const auto yNeg1 = makeDirectionFromPhiTheta(-M_PI_2, M_PI_2);
118  CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
119  CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
120  const auto yNeg2 = makeDirectionFromPhiTheta(3 * M_PI_2, M_PI_2);
121  CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
122  CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
123 
124  // along positive z
125  const auto zPos1 = makeDirectionFromPhiTheta(0.0, 0.0);
126  CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
127  CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
128  const auto zPos2 = makeDirectionFromPhiTheta(M_PI_2, 0.0);
129  CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
130  CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
131  // along negative z
132  const auto zNeg1 = makeDirectionFromPhiTheta(0.0, M_PI);
133  CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
134  CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
135  const auto zNeg2 = makeDirectionFromPhiTheta(M_PI_2, M_PI);
136  CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
137  CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
138 
139  // mixed direction
140  const auto mixed1 = makeDirectionFromPhiTheta(M_PI_4, M_PI_4);
141  CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
142  CHECK_CLOSE_REL(mixed1.dot(Vector3(1, 1, M_SQRT2).normalized()), 1, eps);
143  const auto mixed2 = makeDirectionFromPhiTheta(M_PI_4, 3 * M_PI_4);
144  CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
145  CHECK_CLOSE_REL(mixed2.dot(Vector3(1, 1, -M_SQRT2).normalized()), 1, eps);
146  const auto mixed3 = makeDirectionFromPhiTheta(-M_PI_4, 3 * M_PI_4);
147  CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
148  CHECK_CLOSE_REL(mixed3.dot(Vector3(1, -1, -M_SQRT2).normalized()), 1, eps);
149 }
150 
151 namespace {
152 template <typename Direction, typename RefUnitU, typename RefUnitV>
153 void testCurvilinear(const Eigen::MatrixBase<Direction>& direction,
154  const Eigen::MatrixBase<RefUnitU>& refU,
155  const Eigen::MatrixBase<RefUnitV>& refV) {
156  const auto u = Acts::makeCurvilinearUnitU(direction);
157  const auto uv = Acts::makeCurvilinearUnitVectors(direction);
158  // verify normalization
159  CHECK_CLOSE_ABS(u.norm(), 1, eps);
160  CHECK_CLOSE_ABS(uv.first.norm(), 1, eps);
161  CHECK_CLOSE_ABS(uv.second.norm(), 1, eps);
162  // verify orthonormality
163  CHECK_SMALL(u.dot(direction), eps);
164  CHECK_SMALL(uv.first.dot(direction), eps);
165  CHECK_SMALL(uv.second.dot(direction), eps);
166  CHECK_SMALL(uv.first.dot(uv.second), eps);
167  // verify u is in the x-y plane
168  CHECK_SMALL(u[2], eps);
169  CHECK_SMALL(uv.first[2], eps);
170  // verify references. do not use element-wise comparison to avoid issues with
171  // small, epsilon-like differences.
172  CHECK_CLOSE_ABS(u.dot(refU), 1, eps);
173  CHECK_CLOSE_ABS(uv.first.dot(refU), 1, eps);
174  CHECK_CLOSE_ABS(uv.second.dot(refV), 1, eps);
175 }
176 } // namespace
177 
178 BOOST_AUTO_TEST_CASE(CurvilinearTransverse) {
179  // curvilinear system w/ direction in the transverse plane
180  testCurvilinear(Vector3(1, 1, 0), Vector3(-1, 1, 0).normalized(),
181  Vector3(0, 0, 1).normalized());
182 }
183 
184 BOOST_AUTO_TEST_CASE(CurvilinearPositiveZ) {
185  // curvilinear system w/ direction along z
186  testCurvilinear(Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0));
187 }
188 
189 BOOST_AUTO_TEST_CASE(CurvilinearNegativeZ) {
190  // curvilinear system w/ direction along z
191  testCurvilinear(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0));
192 }
193 
194 BOOST_AUTO_TEST_CASE(CurvilinearCloseToZ) {
195  // curvilinear system w/ direction close to z
196  testCurvilinear(Vector3(0, 32 * eps, 1 - 32 * eps), Vector3(-1, 0, 0),
197  Vector3(0, -1, 32 * eps));
198 }
199 
200 BOOST_AUTO_TEST_SUITE_END()