Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-13 08:19:32

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