Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-18 08:22:25

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/Detector/detail/SupportSurfacesHelper.hpp"
0013 #include "Acts/Geometry/Extent.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Surfaces/SurfaceBounds.hpp"
0017 #include "Acts/Utilities/BinningType.hpp"
0018 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0019 
0020 #include <array>
0021 #include <cmath>
0022 #include <cstddef>
0023 #include <memory>
0024 #include <numbers>
0025 #include <optional>
0026 #include <stdexcept>
0027 #include <vector>
0028 
0029 using namespace Acts;
0030 
0031 using namespace Acts::Experimental::detail::SupportSurfacesHelper;
0032 
0033 GeometryContext tContext;
0034 
0035 namespace ActsTests {
0036 
0037 BOOST_AUTO_TEST_SUITE(DetectorSuite)
0038 
0039 BOOST_AUTO_TEST_CASE(CylindricalSupportCase) {
0040   // This tests the basic functionally to add a cylindrical support structure
0041   // and then split it into planar sectors
0042 
0043   // As a single cylinder
0044   // radius = 100
0045   // half length = 400
0046   // phi min = 0
0047   // phi max = 2pi
0048 
0049   Extent lExtent;
0050   lExtent.set(AxisDirection::AxisR, 100., 110.);
0051   lExtent.set(AxisDirection::AxisZ, -400., 400.);
0052 
0053   // Test creation of surface components
0054   CylindricalSupport csCreator{10., {1., 1.}};
0055   auto csComponents = csCreator(lExtent);
0056   auto& [csType, csValues, csTransform] = csComponents;
0057 
0058   BOOST_CHECK_EQUAL(csType, Surface::SurfaceType::Cylinder);
0059   BOOST_CHECK_EQUAL(csValues.size(), 6u);
0060   BOOST_CHECK_EQUAL(csValues[0u], 120.);
0061   BOOST_CHECK_EQUAL(csValues[1u], 399.);
0062   BOOST_CHECK(csTransform.isApprox(Transform3::Identity()));
0063 
0064   // Test a single support from Extent generation
0065   auto singleSupport = cylindricalSupport(csComponents);
0066   BOOST_CHECK_EQUAL(singleSupport.size(), 1u);
0067   BOOST_CHECK_EQUAL(singleSupport[0u]->type(), Surface::SurfaceType::Cylinder);
0068 
0069   // Test a split cylinder into 32 sectors
0070   auto splitSupport = cylindricalSupport(csComponents, 32u);
0071   BOOST_CHECK_EQUAL(splitSupport.size(), 32u);
0072   for (const auto& ss : splitSupport) {
0073     BOOST_CHECK_EQUAL(ss->type(), Surface::SurfaceType::Plane);
0074   }
0075 
0076   // As a split cylinder - sectoral start cylinder
0077   auto splitSectoralSupport =
0078       Experimental::detail::SupportSurfacesHelper::cylindricalSupport(
0079           csComponents, 128u);
0080   BOOST_CHECK_EQUAL(splitSectoralSupport.size(), 128u);
0081   for (const auto& ss : splitSectoralSupport) {
0082     BOOST_CHECK_EQUAL(ss->type(), Surface::SurfaceType::Plane);
0083   }
0084 
0085   // Invalid / runtime checks
0086   Extent invalid;
0087   BOOST_CHECK_THROW(csCreator(invalid), std::invalid_argument);
0088 
0089   csValues = {120., 399.};
0090   BOOST_CHECK_THROW(cylindricalSupport(csComponents), std::invalid_argument);
0091 
0092   csValues = {120., 399., 0., 0., 0., 0.};
0093   csType = Surface::SurfaceType::Disc;
0094   BOOST_CHECK_THROW(cylindricalSupport(csComponents), std::invalid_argument);
0095 }
0096 
0097 BOOST_AUTO_TEST_CASE(DiscSupportCase) {
0098   // This tests the basic functionality to add a disc support structure
0099   // and then split it into planar sectors
0100 
0101   // As a single disc
0102   // rmin = 100
0103   // rmax = 400
0104   // phi min = 0
0105   // phi max = 2pi
0106   Extent lExtent;
0107   lExtent.set(AxisDirection::AxisR, 100., 400.);
0108   lExtent.set(AxisDirection::AxisZ, -405., -395.);
0109 
0110   // Test creation of surface components
0111   DiscSupport dsCreator{0., {1., 1.}};
0112   auto dsComponents = dsCreator(lExtent);
0113   auto& [dsType, dsValues, dsTransform] = dsComponents;
0114 
0115   BOOST_CHECK_EQUAL(dsType, Surface::SurfaceType::Disc);
0116   BOOST_CHECK_EQUAL(dsValues.size(), 4u);
0117   BOOST_CHECK_EQUAL(dsValues[0u], 101.);
0118   BOOST_CHECK_EQUAL(dsValues[1u], 399.);
0119   BOOST_CHECK(dsTransform.translation().isApprox(Vector3(0., 0., -400.)));
0120 
0121   // Test as a single support surface
0122   auto singleSupport =
0123       Experimental::detail::SupportSurfacesHelper::discSupport(dsComponents);
0124   BOOST_CHECK_EQUAL(singleSupport.size(), 1u);
0125   BOOST_CHECK_EQUAL(singleSupport[0u]->type(), Surface::SurfaceType::Disc);
0126 
0127   // As a split disc into 32 sectors
0128   auto splitSupport = Experimental::detail::SupportSurfacesHelper::discSupport(
0129       dsComponents, 32u);
0130   BOOST_CHECK_EQUAL(splitSupport.size(), 32u);
0131   for (const auto& ss : splitSupport) {
0132     BOOST_CHECK_EQUAL(ss->type(), Surface::SurfaceType::Plane);
0133   }
0134 
0135   // As a split disc - sectoral start disc
0136   auto splitSectoralSupport =
0137       Experimental::detail::SupportSurfacesHelper::discSupport(dsComponents,
0138                                                                16u);
0139   BOOST_CHECK_EQUAL(splitSectoralSupport.size(), 16u);
0140   for (const auto& ss : splitSectoralSupport) {
0141     BOOST_CHECK_EQUAL(ss->type(), Surface::SurfaceType::Plane);
0142   }
0143 
0144   // Invalid / runtime checks
0145   Extent invalid;
0146   BOOST_CHECK_THROW(dsCreator(invalid), std::invalid_argument);
0147 
0148   dsValues = {120., 399.};
0149   BOOST_CHECK_THROW(cylindricalSupport(dsComponents), std::invalid_argument);
0150 
0151   dsValues = {120., 399., std::numbers::pi, 0.};
0152   dsType = Surface::SurfaceType::Cylinder;
0153   BOOST_CHECK_THROW(cylindricalSupport(dsComponents), std::invalid_argument);
0154 }
0155 
0156 BOOST_AUTO_TEST_CASE(RectangularSupportCase) {
0157   // This tests the basic functionality to add a planar, rectangular support
0158   // structure
0159 
0160   // As a plane extent in z
0161   // dx = [-100,100]
0162   // dy = [-200,200]
0163   // dz = [-50, -60]
0164   Extent lExtent;
0165   lExtent.set(AxisDirection::AxisX, -100., 100.);
0166   lExtent.set(AxisDirection::AxisY, -200., 200.);
0167   lExtent.set(AxisDirection::AxisZ, -60., -50.);
0168 
0169   // place in Z with offset 2_mm
0170   // Asymmetric clearances in x an y for testing
0171   RectangularSupport rsCreator{AxisDirection::AxisZ, 2., {1., 2.}, {3., 4.}};
0172   auto rsComponents = rsCreator(lExtent);
0173   auto& [rsType, rsValues, rsTransform] = rsComponents;
0174 
0175   BOOST_CHECK_EQUAL(rsType, Surface::SurfaceType::Plane);
0176   BOOST_CHECK_EQUAL(rsValues.size(), 4u);
0177   BOOST_CHECK_EQUAL(rsValues[0u], -99.);
0178   BOOST_CHECK_EQUAL(rsValues[1u], -197.);
0179   BOOST_CHECK_EQUAL(rsValues[2u], 98.);
0180   BOOST_CHECK_EQUAL(rsValues[3u], 196.);
0181 
0182   BOOST_CHECK(rsTransform.translation().isApprox(Vector3(0., 0., -53.)));
0183 
0184   // Test the support surface creation
0185   auto singleSupport =
0186       Experimental::detail::SupportSurfacesHelper::rectangularSupport(
0187           rsComponents);
0188   BOOST_CHECK_EQUAL(singleSupport.size(), 1u);
0189   BOOST_CHECK_EQUAL(singleSupport[0u]->type(), Surface::SurfaceType::Plane);
0190 
0191   // Invalid / runtime checks
0192   Extent invalid;
0193   invalid.set(AxisDirection::AxisX, -100., 100.);
0194   invalid.set(AxisDirection::AxisY, -200., 200.);
0195   BOOST_CHECK_THROW(rsCreator(invalid), std::invalid_argument);
0196 }
0197 
0198 BOOST_AUTO_TEST_CASE(addCylinderSupportCase) {
0199   // This tests the functionally to take the surfaces from a cylinder layer,
0200   // estimate their extend and use this to construct a support structure
0201   // with some given additional instructuions
0202   std::vector<std::shared_ptr<Surface>> lSurfaces;
0203   std::vector<std::size_t> assignToAll;
0204 
0205   // The Extent - estimated by surfaces and other constraints
0206   // In this example we assume that e.g. the surfaces were parsed
0207   // -> did yield and extend of 100 < r 110
0208   // The volume would give an extend of -400 < z < 400
0209   Extent lExtent;
0210   lExtent.set(AxisDirection::AxisR, 100., 110.);
0211   lExtent.set(AxisDirection::AxisZ, -400., 400.);
0212 
0213   // Cylinder support
0214   CylindricalSupport csCreator{10., {1., 1.}};
0215 
0216   // Add a single support cylinder
0217   Experimental::detail::SupportSurfacesHelper::addSupport(
0218       lSurfaces, assignToAll, lExtent, csCreator, 1u);
0219 
0220   BOOST_CHECK_EQUAL(lSurfaces.size(), 1u);
0221   BOOST_CHECK_EQUAL(lSurfaces[0u]->type(), Surface::SurfaceType::Cylinder);
0222   BOOST_CHECK_EQUAL(assignToAll.size(), 1u);
0223   BOOST_CHECK_EQUAL(assignToAll[0u], 0u);
0224 
0225   // The radius of the support surface should be 10 out of the maximum
0226   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[0u], 120, 1e-3);
0227   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[1u], 399, 1e-3);
0228 
0229   // Clear up for the next test
0230   lSurfaces.clear();
0231   assignToAll.clear();
0232 
0233   // Add split surfaces as support to already existing surfaces
0234   Experimental::detail::SupportSurfacesHelper::addSupport(
0235       lSurfaces, assignToAll, lExtent, csCreator, 16u);
0236   BOOST_CHECK_EQUAL(lSurfaces.size(), 16u);
0237   BOOST_CHECK(assignToAll.empty());
0238 }
0239 
0240 BOOST_AUTO_TEST_CASE(addDiscSupportCase) {
0241   // This tests the functionally to take the surfaces from a disc layer,
0242   // estimate their extend and use this to construct a support structure
0243   // with some given additional instructuions
0244   std::vector<std::shared_ptr<Surface>> lSurfaces;
0245   std::vector<std::size_t> assignToAll;
0246 
0247   // The Extent
0248   Extent lExtent;
0249   lExtent.set(AxisDirection::AxisR, 100., 400.);
0250   lExtent.set(AxisDirection::AxisZ, -110., -100.);
0251 
0252   // Disc support: this would set the disc at the center
0253   DiscSupport dsCreator{0., {1., 1.}};
0254 
0255   // Add a single disc as a support surface
0256   Experimental::detail::SupportSurfacesHelper::addSupport(
0257       lSurfaces, assignToAll, lExtent, dsCreator, 1u);
0258   BOOST_CHECK_EQUAL(lSurfaces.size(), 1u);
0259   BOOST_CHECK_EQUAL(lSurfaces[0u]->type(), Surface::SurfaceType::Disc);
0260   BOOST_CHECK_EQUAL(assignToAll.size(), 1u);
0261   BOOST_CHECK_EQUAL(assignToAll[0u], 0u);
0262 
0263   // The position of the support surface should be at zenter z
0264   CHECK_CLOSE_ABS(lSurfaces[0u]->transform(tContext).translation().z(), -105,
0265                   1e-3);
0266   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[0u], 101, 1e-3);
0267   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[1u], 399, 1e-3);
0268 
0269   // Clear up for the next test
0270   lSurfaces.clear();
0271   assignToAll.clear();
0272   // Add split surfaces as support disc
0273   Experimental::detail::SupportSurfacesHelper::addSupport(
0274       lSurfaces, assignToAll, lExtent, dsCreator, 16u);
0275   BOOST_CHECK_EQUAL(lSurfaces.size(), 16u);
0276   BOOST_CHECK(assignToAll.empty());
0277 }
0278 
0279 BOOST_AUTO_TEST_CASE(addRectangularSupportCase) {
0280   // This tests the functionally to take the surfaces from a plane layer,
0281   // estimate their extend and use this to construct a support structure
0282   // with some given additional instructuions
0283   std::vector<std::shared_ptr<Surface>> lSurfaces;
0284   std::vector<std::size_t> assignToAll;
0285 
0286   // As a plane extent in z
0287   // dx = [-100,100]
0288   // dy = [-200,200]
0289   // dz = [-50, -60]
0290   Extent lExtent;
0291   lExtent.set(AxisDirection::AxisX, -100., 100.);
0292   lExtent.set(AxisDirection::AxisY, -200., 200.);
0293   lExtent.set(AxisDirection::AxisZ, -60., -50.);
0294 
0295   // place in Z with offset 2_mm
0296   // Asymmetric clearances in x an y for testing
0297   RectangularSupport rsCreator{AxisDirection::AxisZ, 2., {1., 2.}, {3., 4.}};
0298 
0299   // Add a single disc as a support surface
0300   Experimental::detail::SupportSurfacesHelper::addSupport(
0301       lSurfaces, assignToAll, lExtent, rsCreator);
0302 
0303   BOOST_CHECK_EQUAL(lSurfaces.size(), 1u);
0304   BOOST_CHECK_EQUAL(lSurfaces[0u]->type(), Surface::SurfaceType::Plane);
0305   BOOST_CHECK_EQUAL(assignToAll.size(), 1u);
0306   BOOST_CHECK_EQUAL(assignToAll[0u], 0u);
0307 
0308   // The position of the support surface should be z with offset
0309   CHECK_CLOSE_ABS(lSurfaces[0u]->transform(tContext).translation().z(), -53,
0310                   1e-3);
0311   // The bounds should be as given (including clearances)
0312   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[0u], -99, 1e-3);
0313   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[1u], -197, 1e-3);
0314   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[2u], 98, 1e-3);
0315   CHECK_CLOSE_ABS(lSurfaces[0u]->bounds().values()[3u], 196, 1e-3);
0316 }
0317 
0318 BOOST_AUTO_TEST_CASE(addMisconfiguredSupportCase) {
0319   std::vector<std::shared_ptr<Surface>> lSurfaces;
0320   std::vector<std::size_t> assignToAll;
0321 
0322   // Unconstrainted extent
0323   Extent lExtent;
0324 
0325   // Cylinder support
0326   CylindricalSupport csCreator{10., {1., 1.}};
0327 
0328   // R - Z are not constrained
0329   // Add a single disc as a support cylinder
0330   BOOST_CHECK_THROW(Experimental::detail::SupportSurfacesHelper::addSupport(
0331                         lSurfaces, assignToAll, lExtent, csCreator, 1u),
0332                     std::invalid_argument);
0333 
0334   // The Extent
0335   lExtent.set(AxisDirection::AxisR, 100., 400.);
0336   lExtent.set(AxisDirection::AxisZ, -110., -100.);
0337 
0338   // Wrong surface type
0339   struct InvalidCreator {
0340     auto operator()(const Extent& /*e*/) const {
0341       return std::make_tuple(Surface::SurfaceType::Perigee,
0342                              std::vector<double>{}, Transform3::Identity());
0343     }
0344   };
0345 
0346   // Add a single disc as a support cylinder
0347   BOOST_CHECK_THROW(Experimental::detail::SupportSurfacesHelper::addSupport(
0348                         lSurfaces, assignToAll, lExtent, InvalidCreator{}, 1u),
0349                     std::invalid_argument);
0350 }
0351 
0352 BOOST_AUTO_TEST_SUITE_END()
0353 
0354 }  // namespace ActsTests