Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:35

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2020 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0013 #include "Acts/Utilities/UnitVectors.hpp"
0014 
0015 #include <algorithm>
0016 #include <cmath>
0017 #include <limits>
0018 
0019 using Acts::Vector3;
0020 
0021 namespace {
0022 constexpr auto eps = std::numeric_limits<double>::epsilon();
0023 }
0024 
0025 BOOST_AUTO_TEST_SUITE(UnitVectors)
0026 
0027 BOOST_AUTO_TEST_CASE(DirectionPhiEta) {
0028   using Acts::makeDirectionFromPhiEta;
0029 
0030   // along positive x
0031   const auto xPos1 = makeDirectionFromPhiEta(0.0, 0.0);
0032   CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
0033   CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
0034   const auto xPos2 = makeDirectionFromPhiEta(2 * M_PI, 0.0);
0035   CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
0036   CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
0037   // along negative x
0038   const auto xNeg1 = makeDirectionFromPhiEta(M_PI, 0.0);
0039   CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
0040   CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
0041   const auto xNeg2 = makeDirectionFromPhiEta(-M_PI, 0.0);
0042   CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
0043   CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
0044   // along positive y
0045   const auto yPos1 = makeDirectionFromPhiEta(M_PI_2, 0.0);
0046   CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
0047   CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
0048   const auto yPos2 = makeDirectionFromPhiEta(-3 * M_PI_2, 0.0);
0049   CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
0050   CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
0051   // along negative y
0052   const auto yNeg1 = makeDirectionFromPhiEta(-M_PI_2, 0.0);
0053   CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
0054   CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
0055   const auto yNeg2 = makeDirectionFromPhiEta(3 * M_PI_2, 0.0);
0056   CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
0057   CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
0058 
0059   const auto inf = std::numeric_limits<double>::infinity();
0060   // along positive z
0061   const auto zPos1 = makeDirectionFromPhiEta(0.0, inf);
0062   CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
0063   CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
0064   const auto zPos2 = makeDirectionFromPhiEta(M_PI_2, inf);
0065   CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
0066   CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
0067   // along negative z
0068   const auto zNeg1 = makeDirectionFromPhiEta(0.0, -inf);
0069   CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
0070   CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
0071   const auto zNeg2 = makeDirectionFromPhiEta(M_PI_2, -inf);
0072   CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
0073   CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
0074 
0075   // mixed direction
0076   const auto mixed1 = makeDirectionFromPhiEta(M_PI_4, 1.0);
0077   CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
0078   CHECK_CLOSE_REL(
0079       mixed1.dot(Vector3(1, 1, M_SQRT2 * std::sinh(1.0)).normalized()), 1, eps);
0080   const auto mixed2 = makeDirectionFromPhiEta(M_PI_4, -1.0);
0081   CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
0082   CHECK_CLOSE_REL(
0083       mixed2.dot(Vector3(1, 1, M_SQRT2 * std::sinh(-1.0)).normalized()), 1,
0084       eps);
0085   const auto mixed3 = makeDirectionFromPhiEta(-M_PI_4, -1.0);
0086   CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
0087   CHECK_CLOSE_REL(
0088       mixed3.dot(Vector3(1, -1, M_SQRT2 * std::sinh(-1.0)).normalized()), 1,
0089       eps);
0090 }
0091 
0092 BOOST_AUTO_TEST_CASE(DirectionPhiTheta) {
0093   using Acts::makeDirectionFromPhiTheta;
0094 
0095   // along positive x
0096   const auto xPos1 = makeDirectionFromPhiTheta(0.0, M_PI_2);
0097   CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
0098   CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
0099   const auto xPos2 = makeDirectionFromPhiTheta(2 * M_PI, M_PI_2);
0100   CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
0101   CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
0102   // along negative x
0103   const auto xNeg1 = makeDirectionFromPhiTheta(M_PI, M_PI_2);
0104   CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
0105   CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
0106   const auto xNeg2 = makeDirectionFromPhiTheta(-M_PI, M_PI_2);
0107   CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
0108   CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
0109   // along positive y
0110   const auto yPos1 = makeDirectionFromPhiTheta(M_PI_2, M_PI_2);
0111   CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
0112   CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
0113   const auto yPos2 = makeDirectionFromPhiTheta(-3 * M_PI_2, M_PI_2);
0114   CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
0115   CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
0116   // along negative y
0117   const auto yNeg1 = makeDirectionFromPhiTheta(-M_PI_2, M_PI_2);
0118   CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
0119   CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
0120   const auto yNeg2 = makeDirectionFromPhiTheta(3 * M_PI_2, M_PI_2);
0121   CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
0122   CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
0123 
0124   // along positive z
0125   const auto zPos1 = makeDirectionFromPhiTheta(0.0, 0.0);
0126   CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
0127   CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
0128   const auto zPos2 = makeDirectionFromPhiTheta(M_PI_2, 0.0);
0129   CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
0130   CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
0131   // along negative z
0132   const auto zNeg1 = makeDirectionFromPhiTheta(0.0, M_PI);
0133   CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
0134   CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
0135   const auto zNeg2 = makeDirectionFromPhiTheta(M_PI_2, M_PI);
0136   CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
0137   CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
0138 
0139   // mixed direction
0140   const auto mixed1 = makeDirectionFromPhiTheta(M_PI_4, M_PI_4);
0141   CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
0142   CHECK_CLOSE_REL(mixed1.dot(Vector3(1, 1, M_SQRT2).normalized()), 1, eps);
0143   const auto mixed2 = makeDirectionFromPhiTheta(M_PI_4, 3 * M_PI_4);
0144   CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
0145   CHECK_CLOSE_REL(mixed2.dot(Vector3(1, 1, -M_SQRT2).normalized()), 1, eps);
0146   const auto mixed3 = makeDirectionFromPhiTheta(-M_PI_4, 3 * M_PI_4);
0147   CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
0148   CHECK_CLOSE_REL(mixed3.dot(Vector3(1, -1, -M_SQRT2).normalized()), 1, eps);
0149 }
0150 
0151 namespace {
0152 template <typename Direction, typename RefUnitU, typename RefUnitV>
0153 void testCurvilinear(const Eigen::MatrixBase<Direction>& direction,
0154                      const Eigen::MatrixBase<RefUnitU>& refU,
0155                      const Eigen::MatrixBase<RefUnitV>& refV) {
0156   const auto u = Acts::makeCurvilinearUnitU(direction);
0157   const auto uv = Acts::makeCurvilinearUnitVectors(direction);
0158   // verify normalization
0159   CHECK_CLOSE_ABS(u.norm(), 1, eps);
0160   CHECK_CLOSE_ABS(uv.first.norm(), 1, eps);
0161   CHECK_CLOSE_ABS(uv.second.norm(), 1, eps);
0162   // verify orthonormality
0163   CHECK_SMALL(u.dot(direction), eps);
0164   CHECK_SMALL(uv.first.dot(direction), eps);
0165   CHECK_SMALL(uv.second.dot(direction), eps);
0166   CHECK_SMALL(uv.first.dot(uv.second), eps);
0167   // verify u is in the x-y plane
0168   CHECK_SMALL(u[2], eps);
0169   CHECK_SMALL(uv.first[2], eps);
0170   // verify references. do not use element-wise comparison to avoid issues with
0171   // small, epsilon-like differences.
0172   CHECK_CLOSE_ABS(u.dot(refU), 1, eps);
0173   CHECK_CLOSE_ABS(uv.first.dot(refU), 1, eps);
0174   CHECK_CLOSE_ABS(uv.second.dot(refV), 1, eps);
0175 }
0176 }  // namespace
0177 
0178 BOOST_AUTO_TEST_CASE(CurvilinearTransverse) {
0179   // curvilinear system w/ direction in the transverse plane
0180   testCurvilinear(Vector3(1, 1, 0), Vector3(-1, 1, 0).normalized(),
0181                   Vector3(0, 0, 1).normalized());
0182 }
0183 
0184 BOOST_AUTO_TEST_CASE(CurvilinearPositiveZ) {
0185   // curvilinear system w/ direction along z
0186   testCurvilinear(Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0));
0187 }
0188 
0189 BOOST_AUTO_TEST_CASE(CurvilinearNegativeZ) {
0190   // curvilinear system w/ direction along z
0191   testCurvilinear(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0));
0192 }
0193 
0194 BOOST_AUTO_TEST_CASE(CurvilinearCloseToZ) {
0195   // curvilinear system w/ direction close to z
0196   testCurvilinear(Vector3(0, 32 * eps, 1 - 32 * eps), Vector3(-1, 0, 0),
0197                   Vector3(0, -1, 32 * eps));
0198 }
0199 
0200 BOOST_AUTO_TEST_SUITE_END()