Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:00

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 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 https://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 #include <numbers>
0019 
0020 using Acts::Vector3;
0021 
0022 namespace {
0023 constexpr auto eps = std::numeric_limits<double>::epsilon();
0024 }
0025 
0026 BOOST_AUTO_TEST_SUITE(UnitVectors)
0027 
0028 BOOST_AUTO_TEST_CASE(DirectionPhiEta) {
0029   using Acts::makeDirectionFromPhiEta;
0030 
0031   // along positive x
0032   const auto xPos1 = makeDirectionFromPhiEta(0.0, 0.0);
0033   CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
0034   CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
0035   const auto xPos2 = makeDirectionFromPhiEta(2 * std::numbers::pi, 0.);
0036   CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
0037   CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
0038   // along negative x
0039   const auto xNeg1 = makeDirectionFromPhiEta(std::numbers::pi, 0.);
0040   CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
0041   CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
0042   const auto xNeg2 = makeDirectionFromPhiEta(-std::numbers::pi, 0.);
0043   CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
0044   CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
0045   // along positive y
0046   const auto yPos1 = makeDirectionFromPhiEta(std::numbers::pi / 2., 0.);
0047   CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
0048   CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
0049   const auto yPos2 = makeDirectionFromPhiEta(-3 * std::numbers::pi / 2., 0.);
0050   CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
0051   CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
0052   // along negative y
0053   const auto yNeg1 = makeDirectionFromPhiEta(-std::numbers::pi / 2., 0.);
0054   CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
0055   CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
0056   const auto yNeg2 = makeDirectionFromPhiEta(3 * std::numbers::pi / 2., 0.);
0057   CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
0058   CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
0059 
0060   const auto inf = std::numeric_limits<double>::infinity();
0061   // along positive z
0062   const auto zPos1 = makeDirectionFromPhiEta(0.0, inf);
0063   CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
0064   CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
0065   const auto zPos2 = makeDirectionFromPhiEta(std::numbers::pi / 2., inf);
0066   CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
0067   CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
0068   // along negative z
0069   const auto zNeg1 = makeDirectionFromPhiEta(0.0, -inf);
0070   CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
0071   CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
0072   const auto zNeg2 = makeDirectionFromPhiEta(std::numbers::pi / 2., -inf);
0073   CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
0074   CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
0075 
0076   // mixed direction
0077   const auto mixed1 = makeDirectionFromPhiEta(std::numbers::pi / 4., 1.);
0078   CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
0079   CHECK_CLOSE_REL(
0080       mixed1.dot(
0081           Vector3(1, 1, std::numbers::sqrt2 * std::sinh(1.0)).normalized()),
0082       1, eps);
0083   const auto mixed2 = makeDirectionFromPhiEta(std::numbers::pi / 4., -1.);
0084   CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
0085   CHECK_CLOSE_REL(
0086       mixed2.dot(
0087           Vector3(1, 1, std::numbers::sqrt2 * std::sinh(-1.0)).normalized()),
0088       1, eps);
0089   const auto mixed3 = makeDirectionFromPhiEta(-std::numbers::pi / 4., -1.);
0090   CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
0091   CHECK_CLOSE_REL(
0092       mixed3.dot(
0093           Vector3(1, -1, std::numbers::sqrt2 * std::sinh(-1.)).normalized()),
0094       1, eps);
0095 }
0096 
0097 BOOST_AUTO_TEST_CASE(DirectionPhiTheta) {
0098   using Acts::makeDirectionFromPhiTheta;
0099 
0100   // along positive x
0101   const auto xPos1 = makeDirectionFromPhiTheta(0., std::numbers::pi / 2.);
0102   CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
0103   CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
0104   const auto xPos2 =
0105       makeDirectionFromPhiTheta(2 * std::numbers::pi, std::numbers::pi / 2.);
0106   CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
0107   CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
0108   // along negative x
0109   const auto xNeg1 =
0110       makeDirectionFromPhiTheta(std::numbers::pi, std::numbers::pi / 2.);
0111   CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
0112   CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
0113   const auto xNeg2 =
0114       makeDirectionFromPhiTheta(-std::numbers::pi, std::numbers::pi / 2.);
0115   CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
0116   CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
0117   // along positive y
0118   const auto yPos1 =
0119       makeDirectionFromPhiTheta(std::numbers::pi / 2., std::numbers::pi / 2.);
0120   CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
0121   CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
0122   const auto yPos2 = makeDirectionFromPhiTheta(-3 * std::numbers::pi / 2.,
0123                                                std::numbers::pi / 2.);
0124   CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
0125   CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
0126   // along negative y
0127   const auto yNeg1 =
0128       makeDirectionFromPhiTheta(-std::numbers::pi / 2., std::numbers::pi / 2.);
0129   CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
0130   CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
0131   const auto yNeg2 = makeDirectionFromPhiTheta(3 * std::numbers::pi / 2.,
0132                                                std::numbers::pi / 2.);
0133   CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
0134   CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
0135 
0136   // along positive z
0137   const auto zPos1 = makeDirectionFromPhiTheta(0.0, 0.0);
0138   CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
0139   CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
0140   const auto zPos2 = makeDirectionFromPhiTheta(std::numbers::pi / 2., 0.);
0141   CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
0142   CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
0143   // along negative z
0144   const auto zNeg1 = makeDirectionFromPhiTheta(0., std::numbers::pi);
0145   CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
0146   CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
0147   const auto zNeg2 =
0148       makeDirectionFromPhiTheta(std::numbers::pi / 2., std::numbers::pi);
0149   CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
0150   CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
0151 
0152   // mixed direction
0153   const auto mixed1 =
0154       makeDirectionFromPhiTheta(std::numbers::pi / 4., std::numbers::pi / 4.);
0155   CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
0156   CHECK_CLOSE_REL(mixed1.dot(Vector3(1, 1, std::numbers::sqrt2).normalized()),
0157                   1, eps);
0158   const auto mixed2 = makeDirectionFromPhiTheta(std::numbers::pi / 4.,
0159                                                 3 * std::numbers::pi / 4.);
0160   CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
0161   CHECK_CLOSE_REL(mixed2.dot(Vector3(1, 1, -std::numbers::sqrt2).normalized()),
0162                   1, eps);
0163   const auto mixed3 = makeDirectionFromPhiTheta(-std::numbers::pi / 4.,
0164                                                 3 * std::numbers::pi / 4.);
0165   CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
0166   CHECK_CLOSE_REL(mixed3.dot(Vector3(1, -1, -std::numbers::sqrt2).normalized()),
0167                   1, eps);
0168 }
0169 
0170 namespace {
0171 template <typename Direction, typename RefUnitU, typename RefUnitV>
0172 void testCurvilinear(const Eigen::MatrixBase<Direction>& direction,
0173                      const Eigen::MatrixBase<RefUnitU>& refU,
0174                      const Eigen::MatrixBase<RefUnitV>& refV) {
0175   const auto u = Acts::makeCurvilinearUnitU(direction);
0176   const auto uv = Acts::makeCurvilinearUnitVectors(direction);
0177   // verify normalization
0178   CHECK_CLOSE_ABS(u.norm(), 1, eps);
0179   CHECK_CLOSE_ABS(uv.first.norm(), 1, eps);
0180   CHECK_CLOSE_ABS(uv.second.norm(), 1, eps);
0181   // verify orthonormality
0182   CHECK_SMALL(u.dot(direction), eps);
0183   CHECK_SMALL(uv.first.dot(direction), eps);
0184   CHECK_SMALL(uv.second.dot(direction), eps);
0185   CHECK_SMALL(uv.first.dot(uv.second), eps);
0186   // verify u is in the x-y plane
0187   CHECK_SMALL(u[2], eps);
0188   CHECK_SMALL(uv.first[2], eps);
0189   // verify references. do not use element-wise comparison to avoid issues with
0190   // small, epsilon-like differences.
0191   CHECK_CLOSE_ABS(u.dot(refU), 1, eps);
0192   CHECK_CLOSE_ABS(uv.first.dot(refU), 1, eps);
0193   CHECK_CLOSE_ABS(uv.second.dot(refV), 1, eps);
0194 }
0195 }  // namespace
0196 
0197 BOOST_AUTO_TEST_CASE(CurvilinearTransverse) {
0198   // curvilinear system w/ direction in the transverse plane
0199   testCurvilinear(Vector3(1, 1, 0), Vector3(-1, 1, 0).normalized(),
0200                   Vector3(0, 0, 1).normalized());
0201 }
0202 
0203 BOOST_AUTO_TEST_CASE(CurvilinearPositiveZ) {
0204   // curvilinear system w/ direction along z
0205   testCurvilinear(Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0));
0206 }
0207 
0208 BOOST_AUTO_TEST_CASE(CurvilinearNegativeZ) {
0209   // curvilinear system w/ direction along z
0210   testCurvilinear(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0));
0211 }
0212 
0213 BOOST_AUTO_TEST_CASE(CurvilinearCloseToZ) {
0214   // curvilinear system w/ direction close to z
0215   testCurvilinear(Vector3(0, 32 * eps, 1 - 32 * eps), Vector3(-1, 0, 0),
0216                   Vector3(0, -1, 32 * eps));
0217 }
0218 
0219 BOOST_AUTO_TEST_SUITE_END()