Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-22 08:25:22

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/data/test_case.hpp>
0010 #include <boost/test/tools/output_test_stream.hpp>
0011 #include <boost/test/unit_test.hpp>
0012 
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Definitions/Tolerance.hpp"
0015 #include "Acts/Geometry/Extent.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/Geometry/Polyhedron.hpp"
0018 #include "Acts/Material/BinnedSurfaceMaterial.hpp"
0019 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0020 #include "Acts/Material/Material.hpp"
0021 #include "Acts/Material/MaterialSlab.hpp"
0022 #include "Acts/Surfaces/ConeBounds.hpp"
0023 #include "Acts/Surfaces/ConeSurface.hpp"
0024 #include "Acts/Surfaces/Surface.hpp"
0025 #include "Acts/Surfaces/SurfaceBounds.hpp"
0026 #include "Acts/Utilities/AxisDefinitions.hpp"
0027 #include "Acts/Utilities/BinUtility.hpp"
0028 #include "Acts/Utilities/BinningType.hpp"
0029 #include "Acts/Utilities/Result.hpp"
0030 #include "Acts/Utilities/ThrowAssert.hpp"
0031 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0032 
0033 #include <cmath>
0034 #include <memory>
0035 #include <numbers>
0036 #include <string>
0037 
0038 using namespace Acts;
0039 namespace ActsTests {
0040 
0041 // Create a test context
0042 GeometryContext tgContext = GeometryContext::dangerouslyDefaultConstruct();
0043 
0044 BOOST_AUTO_TEST_SUITE(SurfacesSuite)
0045 
0046 /// Unit test for creating compliant/non-compliant ConeSurface object
0047 BOOST_AUTO_TEST_CASE(ConeSurfaceConstruction) {
0048   /// Test default construction
0049   // default construction is deleted
0050 
0051   /// Constructor with transform, alpha and symmetry indicator
0052   const double alpha = std::numbers::pi / 8.;
0053   const double halfPhiSector = std::numbers::pi / 16.;
0054   const double zMin = 1.;
0055   const double zMax = 10.;
0056   const bool symmetric = false;
0057   const Translation3 translation{0., 1., 2.};
0058 
0059   auto pTransform = Transform3(translation);
0060   BOOST_CHECK_EQUAL(
0061       Surface::makeShared<ConeSurface>(Transform3::Identity(), alpha, symmetric)
0062           ->type(),
0063       Surface::Cone);
0064   BOOST_CHECK_EQUAL(
0065       Surface::makeShared<ConeSurface>(pTransform, alpha, symmetric)->type(),
0066       Surface::Cone);
0067 
0068   /// Constructor with transform pointer, alpha,z min and max, halfPhiSector
0069   BOOST_CHECK_EQUAL(Surface::makeShared<ConeSurface>(pTransform, alpha, zMin,
0070                                                      zMax, halfPhiSector)
0071                         ->type(),
0072                     Surface::Cone);
0073 
0074   /// Constructor with transform and ConeBounds pointer
0075   auto pConeBounds =
0076       std::make_shared<const ConeBounds>(alpha, zMin, zMax, halfPhiSector, 0.);
0077   BOOST_CHECK_EQUAL(
0078       Surface::makeShared<ConeSurface>(pTransform, pConeBounds)->type(),
0079       Surface::Cone);
0080 
0081   /// Copy constructor
0082   auto coneSurfaceObject =
0083       Surface::makeShared<ConeSurface>(pTransform, alpha, symmetric);
0084   auto copiedConeSurface = Surface::makeShared<ConeSurface>(*coneSurfaceObject);
0085   BOOST_CHECK_EQUAL(copiedConeSurface->type(), Surface::Cone);
0086   BOOST_CHECK(*copiedConeSurface == *coneSurfaceObject);
0087 
0088   /// Copied and transformed
0089   auto copiedTransformedConeSurface = Surface::makeShared<ConeSurface>(
0090       tgContext, *coneSurfaceObject, pTransform);
0091   BOOST_CHECK_EQUAL(copiedTransformedConeSurface->type(), Surface::Cone);
0092 
0093   /// Construct with nullptr bounds
0094   BOOST_CHECK_THROW(auto nullBounds = Surface::makeShared<ConeSurface>(
0095                         Transform3::Identity(), nullptr),
0096                     AssertionFailureException);
0097 }
0098 
0099 /// Unit test for testing ConeSurface properties
0100 BOOST_AUTO_TEST_CASE(ConeSurfaceProperties) {
0101   /// Test clone method
0102   const double alpha = std::numbers::pi / 8.;
0103   const bool symmetric = false;
0104   const Translation3 translation{0., 1., 2.};
0105 
0106   auto pTransform = Transform3(translation);
0107   auto coneSurfaceObject =
0108       Surface::makeShared<ConeSurface>(pTransform, alpha, symmetric);
0109 
0110   /// Test type (redundant)
0111   BOOST_CHECK_EQUAL(coneSurfaceObject->type(), Surface::Cone);
0112 
0113   /// Test referencePosition
0114   Vector3 referencePosition{0., 1., 2.};
0115   CHECK_CLOSE_ABS(
0116       coneSurfaceObject->referencePosition(tgContext, AxisDirection::AxisPhi),
0117       referencePosition, 1e-6);
0118 
0119   /// Test referenceFrame
0120   Vector3 globalPosition{2., 2., 2.};
0121   Vector3 momentum{1.e6, 1.e6, 1.e6};
0122   double rootHalf = std::sqrt(0.5);
0123   RotationMatrix3 expectedFrame;
0124   expectedFrame << -rootHalf, 0., rootHalf, rootHalf, 0., rootHalf, 0., 1., 0.;
0125   CHECK_CLOSE_OR_SMALL(
0126       coneSurfaceObject->referenceFrame(tgContext, globalPosition, momentum),
0127       expectedFrame, 1e-6, 1e-9);
0128 
0129   /// Test normal, given 3D position
0130   Vector3 origin{0., 0., 0.};
0131   Vector3 normal3D = {0., -1., 0.};
0132   CHECK_CLOSE_ABS(coneSurfaceObject->normal(tgContext, origin), normal3D, 1e-6);
0133 
0134   /// Test normal given 2D rphi position
0135   Vector2 positionPiBy2(1., std::numbers::pi / 2.);
0136   Vector3 normalAtPiBy2{0.0312768, 0.92335, -0.382683};
0137 
0138   CHECK_CLOSE_OR_SMALL(coneSurfaceObject->normal(tgContext, positionPiBy2),
0139                        normalAtPiBy2, 1e-2, 1e-9);
0140 
0141   /// Test rotational symmetry axis
0142   Vector3 symmetryAxis{0., 0., 1.};
0143   CHECK_CLOSE_ABS(coneSurfaceObject->rotSymmetryAxis(tgContext), symmetryAxis,
0144                   1e-6);
0145 
0146   /// Test bounds
0147   BOOST_CHECK_EQUAL(coneSurfaceObject->bounds().type(), SurfaceBounds::eCone);
0148 
0149   /// Test localToGlobal
0150   Vector2 localPosition{1., std::numbers::pi / 2.};
0151   globalPosition =
0152       coneSurfaceObject->localToGlobal(tgContext, localPosition, momentum);
0153   Vector3 expectedPosition{0.0220268, 1.65027, 3.5708};
0154 
0155   CHECK_CLOSE_REL(globalPosition, expectedPosition, 1e-2);
0156 
0157   /// Testing globalToLocal
0158   localPosition =
0159       coneSurfaceObject->globalToLocal(tgContext, globalPosition, momentum)
0160           .value();
0161   Vector2 expectedLocalPosition{1., std::numbers::pi / 2.};
0162 
0163   CHECK_CLOSE_REL(localPosition, expectedLocalPosition, 1e-6);
0164 
0165   /// Test isOnSurface
0166   Vector3 offSurface{100, 1, 2};
0167   BOOST_CHECK(coneSurfaceObject->isOnSurface(
0168       tgContext, globalPosition, momentum, BoundaryTolerance::None()));
0169   BOOST_CHECK(!coneSurfaceObject->isOnSurface(tgContext, offSurface, momentum,
0170                                               BoundaryTolerance::None()));
0171 
0172   /// Test pathCorrection
0173   CHECK_CLOSE_REL(coneSurfaceObject->pathCorrection(tgContext, offSurface,
0174                                                     momentum.normalized()),
0175                   3.20041, 0.01);
0176 
0177   /// Test name
0178   BOOST_CHECK_EQUAL(coneSurfaceObject->name(),
0179                     std::string("Acts::ConeSurface"));
0180 
0181   /// Test dump
0182   boost::test_tools::output_test_stream dumpOutput;
0183   dumpOutput << coneSurfaceObject->toStream(tgContext);
0184   BOOST_CHECK(dumpOutput.is_equal(
0185       "Acts::ConeSurface\n"
0186       "     Center position  (x, y, z) = (0.0000, 1.0000, 2.0000)\n"
0187       "     Rotation:             colX = (1.000000, 0.000000, 0.000000)\n"
0188       "                           colY = (0.000000, 1.000000, 0.000000)\n"
0189       "                           colZ = (0.000000, 0.000000, 1.000000)\n"
0190       "     Bounds  : Acts::ConeBounds: (tanAlpha, minZ, maxZ, halfPhiSector, "
0191       "averagePhi) = (0.4142136, 0.0000000, inf, 3.1415927, 0.0000000)"
0192 
0193       ));
0194 }
0195 
0196 BOOST_AUTO_TEST_CASE(ConeSurfaceEqualityOperators) {
0197   const double alpha = std::numbers::pi / 8.;
0198   const bool symmetric = false;
0199   const Translation3 translation{0., 1., 2.};
0200 
0201   auto pTransform = Transform3(translation);
0202   auto coneSurfaceObject =
0203       Surface::makeShared<ConeSurface>(pTransform, alpha, symmetric);
0204 
0205   auto coneSurfaceObject2 =
0206       Surface::makeShared<ConeSurface>(pTransform, alpha, symmetric);
0207 
0208   /// Test equality operator
0209   BOOST_CHECK(*coneSurfaceObject == *coneSurfaceObject2);
0210 
0211   BOOST_TEST_CHECKPOINT(
0212       "Create and then assign a ConeSurface object to the existing one");
0213   /// Test assignment
0214   auto assignedConeSurface =
0215       Surface::makeShared<ConeSurface>(Transform3::Identity(), 0.1, true);
0216   *assignedConeSurface = *coneSurfaceObject;
0217   /// Test equality of assigned to original
0218   BOOST_CHECK(*assignedConeSurface == *coneSurfaceObject);
0219 }
0220 
0221 BOOST_AUTO_TEST_CASE(ConeSurfaceExtent) {
0222   const double alpha = std::numbers::pi / 8.;
0223   const double halfPhiSector = std::numbers::pi / 8.;  // != pi/16
0224   const double zMin = 0.;                              // != 1.
0225   const double zMax = 10.;
0226   const Translation3 translation{0., 0., 0.};  // != {0., 1., 2.}
0227 
0228   /// Testing a Full cone
0229   auto pTransform = Transform3(translation);
0230   auto pConeBounds = std::make_shared<const ConeBounds>(alpha, zMin, zMax);
0231   auto pCone = Surface::makeShared<ConeSurface>(pTransform, pConeBounds);
0232   auto pConeExtent = pCone->polyhedronRepresentation(tgContext, 1).extent();
0233 
0234   double rMax = zMax * std::tan(alpha);
0235   CHECK_CLOSE_ABS(zMin, pConeExtent.min(AxisDirection::AxisZ),
0236                   s_onSurfaceTolerance);
0237   CHECK_CLOSE_ABS(zMax, pConeExtent.max(AxisDirection::AxisZ),
0238                   s_onSurfaceTolerance);
0239   CHECK_CLOSE_ABS(0., pConeExtent.min(AxisDirection::AxisR),
0240                   s_onSurfaceTolerance);
0241   CHECK_CLOSE_ABS(rMax, pConeExtent.max(AxisDirection::AxisR),
0242                   s_onSurfaceTolerance);
0243   CHECK_CLOSE_ABS(-rMax, pConeExtent.min(AxisDirection::AxisX),
0244                   s_onSurfaceTolerance);
0245   CHECK_CLOSE_ABS(rMax, pConeExtent.max(AxisDirection::AxisX),
0246                   s_onSurfaceTolerance);
0247   CHECK_CLOSE_ABS(-rMax, pConeExtent.min(AxisDirection::AxisY),
0248                   s_onSurfaceTolerance);
0249   CHECK_CLOSE_ABS(rMax, pConeExtent.max(AxisDirection::AxisY),
0250                   s_onSurfaceTolerance);
0251 
0252   /// Now a sector
0253   pConeBounds =
0254       std::make_shared<const ConeBounds>(alpha, zMin, zMax, halfPhiSector, 0.);
0255   pCone = Surface::makeShared<ConeSurface>(pTransform, pConeBounds);
0256   pConeExtent = pCone->polyhedronRepresentation(tgContext, 1).extent();
0257 
0258   CHECK_CLOSE_ABS(zMin, pConeExtent.min(AxisDirection::AxisZ),
0259                   s_onSurfaceTolerance);
0260   CHECK_CLOSE_ABS(zMax, pConeExtent.max(AxisDirection::AxisZ),
0261                   s_onSurfaceTolerance);
0262   CHECK_CLOSE_ABS(0., pConeExtent.min(AxisDirection::AxisR),
0263                   s_onSurfaceTolerance);
0264   CHECK_CLOSE_ABS(rMax, pConeExtent.max(AxisDirection::AxisR),
0265                   s_onSurfaceTolerance);
0266 }
0267 
0268 /// Unit test for testing ConeSurface alignment derivatives
0269 BOOST_AUTO_TEST_CASE(ConeSurfaceAlignment) {
0270   const double alpha = std::numbers::pi / 8.;
0271   const bool symmetric = false;
0272   const Translation3 translation{0., 1., 2.};
0273 
0274   auto pTransform = Transform3(translation);
0275   auto coneSurfaceObject =
0276       Surface::makeShared<ConeSurface>(pTransform, alpha, symmetric);
0277 
0278   const auto& rotation = pTransform.rotation();
0279   // The local frame z axis
0280   const Vector3 localZAxis = rotation.col(2);
0281   // Check the local z axis is aligned to global z axis
0282   CHECK_CLOSE_ABS(localZAxis, Vector3(0., 0., 1.), 1e-15);
0283 
0284   /// Define the track (global) position and direction
0285   Vector3 globalPosition{0, 1. + std::tan(alpha), 3};
0286 
0287   // Test the derivative of bound track parameters local position w.r.t.
0288   // position in local 3D Cartesian coordinates
0289   const auto& loc3DToLocBound =
0290       coneSurfaceObject->localCartesianToBoundLocalDerivative(tgContext,
0291                                                               globalPosition);
0292   // Check if the result is as expected
0293   Matrix<2, 3> expLoc3DToLocBound = Matrix<2, 3>::Zero();
0294   expLoc3DToLocBound << -1, 0, std::numbers::pi / 2. * std::tan(alpha), 0, 0, 1;
0295   CHECK_CLOSE_ABS(loc3DToLocBound, expLoc3DToLocBound, 1e-10);
0296 }
0297 
0298 BOOST_AUTO_TEST_CASE(ConeSurfaceMaterialAssignment) {
0299   const double alpha = 0.3;
0300   auto surface = Surface::makeShared<ConeSurface>(Transform3::Identity(), alpha,
0301                                                   true /*symmetric*/);
0302   MaterialSlab slab(Material::fromMolarDensity(1., 2., 3., 4., 5.), 0.1);
0303 
0304   // HomogeneousSurfaceMaterial is always valid
0305   auto homMat = std::make_shared<HomogeneousSurfaceMaterial>(slab);
0306   BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(homMat));
0307   BOOST_CHECK_NE(surface->surfaceMaterial(), nullptr);
0308 
0309   // nullptr clears the material
0310   BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(nullptr));
0311   BOOST_CHECK_EQUAL(surface->surfaceMaterial(), nullptr);
0312 
0313   // 1D AxisZ - valid for cone
0314   BinUtility buZ(10, -100.f, 100.f, Acts::open, AxisDirection::AxisZ);
0315   auto matZ = std::make_shared<BinnedSurfaceMaterial>(
0316       buZ, MaterialSlabVector(10, slab));
0317   BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(matZ));
0318 
0319   // Wrong axis directions - should throw
0320   for (auto badDir : {AxisDirection::AxisR, AxisDirection::AxisPhi,
0321                       AxisDirection::AxisX, AxisDirection::AxisY}) {
0322     BinUtility buBad(10, 0.f, 10.f, Acts::open, badDir);
0323     auto matBad = std::make_shared<BinnedSurfaceMaterial>(
0324         buBad, MaterialSlabVector(10, slab));
0325     BOOST_CHECK_THROW(surface->assignSurfaceMaterial(matBad),
0326                       std::invalid_argument);
0327   }
0328 }
0329 
0330 BOOST_AUTO_TEST_SUITE_END()
0331 }  // namespace ActsTests