Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:14:30

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/AxisDefinitions.hpp"
0014 #include "Acts/Utilities/VectorHelpers.hpp"
0015 
0016 #include <cmath>
0017 #include <limits>
0018 #include <numbers>
0019 
0020 using namespace Acts::VectorHelpers;
0021 
0022 BOOST_AUTO_TEST_SUITE(VectorHelpers)
0023 
0024 BOOST_AUTO_TEST_CASE(PhiFromVector) {
0025   // Test phi calculation for Eigen vectors
0026   CHECK_CLOSE_ABS(0.0, phi(Acts::Vector2{1, 0}), 1e-6);
0027   CHECK_CLOSE_ABS(std::numbers::pi / 2, phi(Acts::Vector2{0, 1}), 1e-6);
0028   CHECK_CLOSE_ABS(std::numbers::pi, phi(Acts::Vector2{-1, 0}), 1e-6);
0029   CHECK_CLOSE_ABS(-std::numbers::pi / 2, phi(Acts::Vector2{0, -1}), 1e-6);
0030   CHECK_CLOSE_ABS(std::numbers::pi / 4, phi(Acts::Vector2{1, 1}), 1e-6);
0031 
0032   // Test with 3D vectors
0033   CHECK_CLOSE_ABS(0.0, phi(Acts::Vector3{1, 0, 5}), 1e-6);
0034   CHECK_CLOSE_ABS(std::numbers::pi / 2, phi(Acts::Vector3{0, 1, -2}), 1e-6);
0035 
0036   // Test with dynamic vectors
0037   Acts::ActsDynamicVector dynVec2(2);
0038   dynVec2 << 1, 1;
0039   CHECK_CLOSE_ABS(std::numbers::pi / 4, phi(dynVec2), 1e-6);
0040 
0041   Acts::ActsDynamicVector dynVec3(3);
0042   dynVec3 << 0, 1, 5;
0043   CHECK_CLOSE_ABS(std::numbers::pi / 2, phi(dynVec3), 1e-6);
0044 }
0045 
0046 BOOST_AUTO_TEST_CASE(PhiFromObject) {
0047   // Test phi calculation for objects with phi() method
0048   struct MockObject {
0049     double phi() const { return 1.5; }
0050   };
0051 
0052   MockObject obj;
0053   CHECK_CLOSE_ABS(1.5, phi(obj), 1e-6);
0054 }
0055 
0056 BOOST_AUTO_TEST_CASE(PerpFromVector) {
0057   // Test transverse radius calculation
0058   CHECK_CLOSE_ABS(1.0, perp(Acts::Vector2{1, 0}), 1e-6);
0059   CHECK_CLOSE_ABS(1.0, perp(Acts::Vector2{0, 1}), 1e-6);
0060   CHECK_CLOSE_ABS(std::sqrt(2.0), perp(Acts::Vector2{1, 1}), 1e-6);
0061   CHECK_CLOSE_ABS(5.0, perp(Acts::Vector2{3, 4}), 1e-6);
0062 
0063   // Test with 3D vectors (should ignore z component)
0064   CHECK_CLOSE_ABS(1.0, perp(Acts::Vector3{1, 0, 10}), 1e-6);
0065   CHECK_CLOSE_ABS(5.0, perp(Acts::Vector3{3, 4, 100}), 1e-6);
0066 
0067   // Test with dynamic vectors
0068   Acts::ActsDynamicVector dynVec(3);
0069   dynVec << 3, 4, 5;
0070   CHECK_CLOSE_ABS(5.0, perp(dynVec), 1e-6);
0071 }
0072 
0073 BOOST_AUTO_TEST_CASE(ThetaFromVector) {
0074   // Test theta calculation
0075   CHECK_CLOSE_ABS(std::numbers::pi / 2, theta(Acts::Vector3{1, 0, 0}), 1e-6);
0076   CHECK_CLOSE_ABS(std::numbers::pi / 2, theta(Acts::Vector3{0, 1, 0}), 1e-6);
0077   CHECK_CLOSE_ABS(0.0, theta(Acts::Vector3{0, 0, 1}), 1e-6);
0078   CHECK_CLOSE_ABS(std::numbers::pi, theta(Acts::Vector3{0, 0, -1}), 1e-6);
0079   CHECK_CLOSE_ABS(std::numbers::pi / 4, theta(Acts::Vector3{1, 0, 1}), 1e-6);
0080   CHECK_CLOSE_ABS(3 * std::numbers::pi / 4, theta(Acts::Vector3{1, 0, -1}),
0081                   1e-6);
0082 
0083   // Test with dynamic vectors
0084   Acts::ActsDynamicVector dynVec(3);
0085   dynVec << 1, 0, 1;
0086   CHECK_CLOSE_ABS(std::numbers::pi / 4, theta(dynVec), 1e-6);
0087 
0088   dynVec << 0, 0, 1;
0089   CHECK_CLOSE_ABS(0.0, theta(dynVec), 1e-6);
0090 }
0091 
0092 BOOST_AUTO_TEST_CASE(EtaFromVector) {
0093   // Test pseudorapidity calculation
0094   CHECK_CLOSE_ABS(0.0, eta(Acts::Vector3{1, 0, 0}), 1e-6);
0095   CHECK_CLOSE_ABS(0.0, eta(Acts::Vector3{0, 1, 0}), 1e-6);
0096 
0097   // Test special case: vector parallel to z-axis
0098   BOOST_CHECK_EQUAL(eta(Acts::Vector3{0, 0, 1}),
0099                     std::numeric_limits<double>::infinity());
0100   BOOST_CHECK_EQUAL(eta(Acts::Vector3{0, 0, -1}),
0101                     -std::numeric_limits<double>::infinity());
0102 
0103   // Test finite values
0104   CHECK_CLOSE_ABS(std::asinh(1.0), eta(Acts::Vector3{1, 0, 1}), 1e-6);
0105   CHECK_CLOSE_ABS(std::asinh(-1.0), eta(Acts::Vector3{1, 0, -1}), 1e-6);
0106   CHECK_CLOSE_ABS(std::asinh(2.0), eta(Acts::Vector3{1, 1, 2 * std::sqrt(2)}),
0107                   1e-6);
0108 
0109   // Test with dynamic vectors
0110   Acts::ActsDynamicVector dynVec(3);
0111   dynVec << 1, 0, 1;
0112   CHECK_CLOSE_ABS(std::asinh(1.0), eta(dynVec), 1e-6);
0113 
0114   dynVec << 0, 0, 1;
0115   BOOST_CHECK_EQUAL(eta(dynVec), std::numeric_limits<double>::infinity());
0116 
0117   dynVec << 0, 0, -1;
0118   BOOST_CHECK_EQUAL(eta(dynVec), -std::numeric_limits<double>::infinity());
0119 }
0120 
0121 BOOST_AUTO_TEST_CASE(EvaluateTrigonomics) {
0122   // Test trigonometric evaluation
0123   Acts::Vector3 dir{1, 0, 0};  // pointing in x direction
0124   auto trig = evaluateTrigonomics(dir);
0125 
0126   CHECK_CLOSE_ABS(1.0, trig[0], 1e-6);  // cos(phi)
0127   CHECK_CLOSE_ABS(0.0, trig[1], 1e-6);  // sin(phi)
0128   CHECK_CLOSE_ABS(0.0, trig[2], 1e-6);  // cos(theta)
0129   CHECK_CLOSE_ABS(1.0, trig[3], 1e-6);  // sin(theta)
0130 
0131   // Test with y direction
0132   dir = Acts::Vector3{0, 1, 0};
0133   trig = evaluateTrigonomics(dir);
0134 
0135   CHECK_CLOSE_ABS(0.0, trig[0], 1e-6);  // cos(phi)
0136   CHECK_CLOSE_ABS(1.0, trig[1], 1e-6);  // sin(phi)
0137   CHECK_CLOSE_ABS(0.0, trig[2], 1e-6);  // cos(theta)
0138   CHECK_CLOSE_ABS(1.0, trig[3], 1e-6);  // sin(theta)
0139 
0140   // Test with diagonal direction (avoid z-axis singularity)
0141   dir = Acts::Vector3{1, 1, 1};
0142   dir.normalize();
0143   trig = evaluateTrigonomics(dir);
0144 
0145   // For normalized {1,1,1}, cos(theta) = 1/sqrt(3), sin(theta) = sqrt(2/3)
0146   // cos(phi) = sin(phi) = 1/sqrt(2) (45 degree angle in xy plane)
0147   CHECK_CLOSE_ABS(1.0 / std::sqrt(2), trig[0], 1e-6);    // cos(phi)
0148   CHECK_CLOSE_ABS(1.0 / std::sqrt(2), trig[1], 1e-6);    // sin(phi)
0149   CHECK_CLOSE_ABS(1.0 / std::sqrt(3), trig[2], 1e-6);    // cos(theta)
0150   CHECK_CLOSE_ABS(std::sqrt(2.0 / 3.0), trig[3], 1e-6);  // sin(theta)
0151 }
0152 
0153 BOOST_AUTO_TEST_CASE(CastAxisDirection) {
0154   using enum Acts::AxisDirection;
0155   Acts::Vector3 pos{3, 4, 5};
0156 
0157   // Test all axis directions
0158   CHECK_CLOSE_ABS(3.0, cast(pos, AxisX), 1e-6);
0159   CHECK_CLOSE_ABS(4.0, cast(pos, AxisY), 1e-6);
0160   CHECK_CLOSE_ABS(5.0, cast(pos, AxisZ), 1e-6);
0161   CHECK_CLOSE_ABS(5.0, cast(pos, AxisR), 1e-6);  // sqrt(3²+4²)
0162   CHECK_CLOSE_ABS(std::atan2(4, 3), cast(pos, AxisPhi), 1e-6);
0163   CHECK_CLOSE_ABS(5.0 * std::atan2(4, 3), cast(pos, AxisRPhi), 1e-6);
0164   CHECK_CLOSE_ABS(std::atan2(5, 5), cast(pos, AxisTheta), 1e-6);
0165   CHECK_CLOSE_ABS(std::asinh(1.0), cast(pos, AxisEta), 1e-6);
0166   CHECK_CLOSE_ABS(std::sqrt(50), cast(pos, AxisMag), 1e-6);
0167 }
0168 
0169 BOOST_AUTO_TEST_CASE(CrossProduct) {
0170   Acts::SquareMatrix3 m;
0171   m << 1, 0, 0, 0, 1, 0, 0, 0, 1;
0172 
0173   Acts::Vector3 v{1, 0, 0};
0174 
0175   Acts::SquareMatrix3 result = cross(m, v);
0176 
0177   // Check that each column is the cross product of the corresponding column of
0178   // m with v
0179   Acts::Vector3 expected_col0 =
0180       m.col(0).cross(v);  // [1,0,0] x [1,0,0] = [0,0,0]
0181   Acts::Vector3 expected_col1 =
0182       m.col(1).cross(v);  // [0,1,0] x [1,0,0] = [0,0,-1]
0183   Acts::Vector3 expected_col2 =
0184       m.col(2).cross(v);  // [0,0,1] x [1,0,0] = [0,1,0]
0185 
0186   CHECK_CLOSE_ABS(expected_col0[0], result.col(0)[0], 1e-6);
0187   CHECK_CLOSE_ABS(expected_col0[1], result.col(0)[1], 1e-6);
0188   CHECK_CLOSE_ABS(expected_col0[2], result.col(0)[2], 1e-6);
0189 
0190   CHECK_CLOSE_ABS(expected_col1[0], result.col(1)[0], 1e-6);
0191   CHECK_CLOSE_ABS(expected_col1[1], result.col(1)[1], 1e-6);
0192   CHECK_CLOSE_ABS(expected_col1[2], result.col(1)[2], 1e-6);
0193 
0194   CHECK_CLOSE_ABS(expected_col2[0], result.col(2)[0], 1e-6);
0195   CHECK_CLOSE_ABS(expected_col2[1], result.col(2)[1], 1e-6);
0196   CHECK_CLOSE_ABS(expected_col2[2], result.col(2)[2], 1e-6);
0197 }
0198 
0199 BOOST_AUTO_TEST_CASE(PositionFromVector4) {
0200   Acts::Vector4 pos4{1, 2, 3, 4};
0201   auto pos3 = position(pos4);
0202 
0203   CHECK_CLOSE_ABS(1.0, pos3[0], 1e-6);
0204   CHECK_CLOSE_ABS(2.0, pos3[1], 1e-6);
0205   CHECK_CLOSE_ABS(3.0, pos3[2], 1e-6);
0206 }
0207 
0208 BOOST_AUTO_TEST_CASE(PositionFromFreeVector) {
0209   Acts::FreeVector params = Acts::FreeVector::Zero();
0210   params[Acts::eFreePos0] = 1;
0211   params[Acts::eFreePos1] = 2;
0212   params[Acts::eFreePos2] = 3;
0213 
0214   auto pos3 = position(params);
0215 
0216   CHECK_CLOSE_ABS(1.0, pos3[0], 1e-6);
0217   CHECK_CLOSE_ABS(2.0, pos3[1], 1e-6);
0218   CHECK_CLOSE_ABS(3.0, pos3[2], 1e-6);
0219 }
0220 
0221 BOOST_AUTO_TEST_CASE(MakeVector4) {
0222   Acts::Vector3 vec3{1, 2, 3};
0223   double w = 4.0;
0224 
0225   auto vec4 = makeVector4(vec3, w);
0226 
0227   CHECK_CLOSE_ABS(1.0, vec4[Acts::ePos0], 1e-6);
0228   CHECK_CLOSE_ABS(2.0, vec4[Acts::ePos1], 1e-6);
0229   CHECK_CLOSE_ABS(3.0, vec4[Acts::ePos2], 1e-6);
0230   CHECK_CLOSE_ABS(4.0, vec4[Acts::eTime], 1e-6);
0231 }
0232 
0233 BOOST_AUTO_TEST_CASE(IncidentAngles) {
0234   Acts::Vector3 direction{1, 1, 1};
0235   direction.normalize();
0236 
0237   // Identity rotation (global == local)
0238   Acts::RotationMatrix3 globalToLocal = Acts::RotationMatrix3::Identity();
0239 
0240   auto angles = incidentAngles(direction, globalToLocal);
0241 
0242   // In local frame, direction is still {1,1,1}/sqrt(3)
0243   // phi = atan2(z, x) = atan2(1/sqrt(3), 1/sqrt(3)) = pi/4
0244   // theta = atan2(z, y) = atan2(1/sqrt(3), 1/sqrt(3)) = pi/4
0245   CHECK_CLOSE_ABS(std::numbers::pi / 4, angles.first, 1e-6);
0246   CHECK_CLOSE_ABS(std::numbers::pi / 4, angles.second, 1e-6);
0247 
0248   // Test with rotation around z-axis by 90 degrees
0249   Acts::RotationMatrix3 rotZ;
0250   rotZ << 0, 1, 0, -1, 0, 0, 0, 0, 1;
0251 
0252   angles = incidentAngles(Acts::Vector3{1, 0, 0}, rotZ);
0253   // After rotation: {1,0,0} -> {0,-1,0}
0254   // phi = atan2(0, 0) = 0, theta = atan2(0, -1) = pi (atan2 of 0,-1)
0255   CHECK_CLOSE_ABS(0.0, angles.first, 1e-6);
0256   CHECK_CLOSE_ABS(std::numbers::pi, angles.second, 1e-6);
0257 }
0258 
0259 BOOST_AUTO_TEST_SUITE_END()