Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-23 08:24:02

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/Detector.hpp"
0013 #include "Acts/Detector/DetectorVolume.hpp"
0014 #include "Acts/Detector/GeometryIdGenerator.hpp"
0015 #include "Acts/Detector/PortalGenerators.hpp"
0016 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
0019 #include "Acts/Geometry/GeometryIdentifier.hpp"
0020 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0021 #include "Acts/Material/HomogeneousVolumeMaterial.hpp"
0022 #include "Acts/Material/Material.hpp"
0023 #include "Acts/Material/MaterialSlab.hpp"
0024 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0025 #include "Acts/Navigation/InternalNavigation.hpp"
0026 #include "Acts/Navigation/NavigationDelegates.hpp"
0027 #include "Acts/Navigation/NavigationState.hpp"
0028 #include "Acts/Surfaces/CylinderBounds.hpp"
0029 #include "ActsTests/CommonHelpers/DetectorElementStub.hpp"
0030 
0031 #include <memory>
0032 #include <stdexcept>
0033 #include <string>
0034 #include <utility>
0035 #include <vector>
0036 
0037 using namespace Acts;
0038 
0039 namespace ActsTests {
0040 
0041 /// Unpack to shared - simply to test the getSharedPtr mechanism
0042 ///
0043 /// @tparam referenced_type is the type of the referenced object
0044 ///
0045 /// @param rt is the referenced object
0046 ///
0047 /// @returns a shared pointer
0048 template <typename referenced_type>
0049 std::shared_ptr<referenced_type> unpackToShared(referenced_type& rt) {
0050   return rt.getSharedPtr();
0051 }
0052 
0053 GeometryContext tContext;
0054 
0055 BOOST_AUTO_TEST_SUITE(DetectorSuite)
0056 
0057 BOOST_AUTO_TEST_CASE(DetectorConstruction) {
0058   double r0 = 0.;
0059   double r1 = 10.;
0060   double r2 = 100.;
0061   double r3 = 200.;
0062   double zHalfL = 200.;
0063 
0064   Transform3 nominal = Transform3::Identity();
0065 
0066   // Create a bunch of volumes
0067   auto cyl0Bounds = std::make_unique<CylinderVolumeBounds>(r0, r1, zHalfL);
0068 
0069   auto cyl0BoundsCopy = std::make_unique<CylinderVolumeBounds>(r0, r1, zHalfL);
0070 
0071   auto cyl1Bounds = std::make_unique<CylinderVolumeBounds>(r1, r2, zHalfL);
0072 
0073   auto cyl2Bounds = std::make_unique<CylinderVolumeBounds>(r2, r3, zHalfL);
0074 
0075   auto portalGenerator = Experimental::defaultPortalGenerator();
0076 
0077   auto cyl0 = Experimental::DetectorVolumeFactory::construct(
0078       portalGenerator, tContext, "Cyl0", nominal, std::move(cyl0Bounds),
0079       Experimental::tryAllPortals());
0080 
0081   auto cyl0nameDup = Experimental::DetectorVolumeFactory::construct(
0082       portalGenerator, tContext, "Cyl0", nominal, std::move(cyl0BoundsCopy),
0083       Experimental::tryAllPortals());
0084 
0085   auto cyl1 = Experimental::DetectorVolumeFactory::construct(
0086       portalGenerator, tContext, "Cyl1", nominal, std::move(cyl1Bounds),
0087       Experimental::tryAllPortals());
0088 
0089   auto cyl2 = Experimental::DetectorVolumeFactory::construct(
0090       portalGenerator, tContext, "Cyl2", nominal, std::move(cyl2Bounds),
0091       Experimental::tryAllPortals());
0092 
0093   std::vector<std::shared_ptr<Experimental::DetectorVolume>> volumes012 = {
0094       cyl0, cyl1, cyl2};
0095 
0096   Experimental::GeometryIdGenerator::Config generatorConfig;
0097   Experimental::GeometryIdGenerator generator(
0098       generatorConfig,
0099       getDefaultLogger("SequentialIdGenerator", Logging::VERBOSE));
0100   auto cache = generator.generateCache();
0101   for (auto& vol : volumes012) {
0102     generator.assignGeometryId(cache, *vol);
0103   }
0104 
0105   auto det012 = Experimental::Detector::makeShared(
0106       "Det012", volumes012, Experimental::tryRootVolumes());
0107 
0108   // Check the basic return functions
0109   BOOST_CHECK_EQUAL(det012->name(), "Det012");
0110   BOOST_CHECK_EQUAL(det012->volumes().size(), 3u);
0111   BOOST_CHECK_EQUAL(det012->volumePtrs().size(), 3u);
0112 
0113   // Check the shared pointer mechanism
0114   BOOST_CHECK_EQUAL(det012, unpackToShared<Experimental::Detector>(*det012));
0115   BOOST_CHECK_EQUAL(det012,
0116                     unpackToShared<const Experimental::Detector>(*det012));
0117 
0118   // Check surface visiting
0119   // Test the visitor pattern for surfaces
0120   std::size_t nSurfaces = 0;
0121   det012->visitSurfaces([&nSurfaces](const auto* s) {
0122     if (s != nullptr) {
0123       nSurfaces++;
0124     }
0125   });
0126   BOOST_CHECK_EQUAL(nSurfaces, 11u);
0127 
0128   // Check the volume visiting
0129   std::size_t nVolumes = 0;
0130   det012->visitVolumes([&nVolumes](const auto* v) {
0131     if (v != nullptr) {
0132       nVolumes++;
0133     }
0134   });
0135   BOOST_CHECK_EQUAL(nVolumes, 3u);
0136 
0137   // Check surface visiting - non-const access
0138   // Test visitor pattern - non-const access
0139   struct SetMaterial {
0140     /// The material to set
0141     std::shared_ptr<const HomogeneousSurfaceMaterial> surfaceMaterial =
0142         std::make_shared<HomogeneousSurfaceMaterial>(
0143             MaterialSlab(Material::fromMolarDensity(1., 2., 3., 4., 5.), 1.));
0144 
0145     std::shared_ptr<HomogeneousVolumeMaterial> volumeMaterial =
0146         std::make_shared<HomogeneousVolumeMaterial>(
0147             Material::fromMolarDensity(1., 2., 3., 4., 5.));
0148 
0149     /// The visitor call: set surface material
0150     void operator()(Surface* s) {
0151       if (s != nullptr) {
0152         s->assignSurfaceMaterial(surfaceMaterial);
0153       }
0154     }
0155 
0156     /// The visitor call : set volume material
0157     void operator()(Experimental::DetectorVolume* v) {
0158       if (v != nullptr) {
0159         v->assignVolumeMaterial(volumeMaterial);
0160       }
0161     }
0162   };
0163 
0164   SetMaterial setMaterial;
0165   det012->visitMutableSurfaces(setMaterial);
0166   det012->visitMutableVolumes(setMaterial);
0167 
0168   // Count surfaces with material
0169   std::size_t nSurfacesWithMaterial = 0;
0170   det012->visitSurfaces([&nSurfacesWithMaterial](const auto* s) {
0171     if (s != nullptr && s->surfaceMaterial() != nullptr) {
0172       nSurfacesWithMaterial++;
0173     }
0174   });
0175   BOOST_CHECK_EQUAL(nSurfacesWithMaterial, 11u);
0176 
0177   // Count volumes with material
0178   std::size_t nVolumesWithMaterial = 0;
0179 
0180   det012->visitVolumes([&nVolumesWithMaterial](const auto* v) {
0181     if (v != nullptr && v->volumeMaterial() != nullptr) {
0182       nVolumesWithMaterial++;
0183     }
0184   });
0185   BOOST_CHECK_EQUAL(nVolumesWithMaterial, 3u);
0186 
0187   // Check the inside function with positions
0188   Experimental::NavigationState nState;
0189   nState.position = Vector3(5., 0., 0.);
0190   nState.currentDetector = det012.get();
0191   det012->updateDetectorVolume(tContext, nState);
0192   BOOST_CHECK_EQUAL(nState.currentVolume, cyl0.get());
0193 
0194   auto find1 = det012->findDetectorVolume(tContext, Vector3(15., 0., 0.));
0195   BOOST_CHECK_EQUAL(find1, cyl1.get());
0196 
0197   auto find2 = det012->findDetectorVolume(tContext, Vector3(150., 0., 0.));
0198   BOOST_CHECK_EQUAL(find2, cyl2.get());
0199 
0200   auto findNull = det012->findDetectorVolume(tContext, Vector3(1500., 0., 0.));
0201   BOOST_CHECK_EQUAL(findNull, nullptr);
0202 
0203   /// Find by name
0204   auto find0 = det012->findDetectorVolume("Cyl0");
0205   BOOST_CHECK_EQUAL(find0, cyl0.get());
0206 
0207   findNull = det012->findDetectorVolume("Null");
0208   BOOST_CHECK_EQUAL(findNull, nullptr);
0209 
0210   // Misconfigured - unkonnected finder
0211   Experimental::ExternalNavigationDelegate unconnected;
0212   BOOST_CHECK_THROW(
0213       Experimental::Detector::makeShared("Det012_unconnected", volumes012,
0214                                          std::move(unconnected)),
0215       std::invalid_argument);
0216 
0217   generator.assignGeometryId(cache, *cyl0nameDup);
0218 
0219   // Misconfigured - duplicate name
0220   std::vector<std::shared_ptr<Experimental::DetectorVolume>> volumes002 = {
0221       cyl0, cyl0nameDup, cyl2};
0222   BOOST_CHECK_THROW(
0223       Experimental::Detector::makeShared("Det002_name_duplicate", volumes002,
0224                                          Experimental::tryRootVolumes()),
0225       std::invalid_argument);
0226 }
0227 
0228 BOOST_AUTO_TEST_CASE(DetectorConstructionWithHierarchyMap) {
0229   auto portalGenerator = Experimental::defaultPortalGenerator();
0230 
0231   std::vector<std::unique_ptr<DetectorElementStub>> detStore;
0232   std::vector<double> radii = {100, 102, 104, 106, 108, 110};
0233   auto cylinderVoumeBounds =
0234       std::make_unique<CylinderVolumeBounds>(80, 130, 200);
0235   std::vector<std::shared_ptr<Surface>> surfaces = {};
0236   for (auto [ir, r] : enumerate(radii)) {
0237     auto detElement = std::make_unique<DetectorElementStub>(
0238         Transform3::Identity(), std::make_shared<CylinderBounds>(r, 190.), 0.1);
0239     auto surface = detElement->surface().getSharedPtr();
0240     surface->assignGeometryId(GeometryIdentifier{}.withSensitive(ir + 1));
0241     surfaces.push_back(std::move(surface));
0242     detStore.push_back(std::move(detElement));
0243   }
0244 
0245   auto cylVolume = Experimental::DetectorVolumeFactory::construct(
0246       portalGenerator, tContext, "CylinderVolume", Transform3::Identity(),
0247       std::move(cylinderVoumeBounds), surfaces, {},
0248       Experimental::tryNoVolumes(), Experimental::tryAllPortalsAndSurfaces());
0249 
0250   Experimental::GeometryIdGenerator::Config generatorConfig;
0251   Experimental::GeometryIdGenerator generator(
0252       generatorConfig,
0253       getDefaultLogger("SequentialIdGenerator", Logging::VERBOSE));
0254 
0255   auto cache = generator.generateCache();
0256   generator.assignGeometryId(cache, *cylVolume);
0257 
0258   auto det = Experimental::Detector::makeShared("DetWithSurfaces", {cylVolume},
0259                                                 Experimental::tryRootVolumes());
0260 
0261   const auto& sensitiveHierarchyMap = det->sensitiveHierarchyMap();
0262 
0263   const Surface* surface0 =
0264       det->findSurface(GeometryIdentifier{}.withSensitive(1));
0265 
0266   BOOST_CHECK_EQUAL(sensitiveHierarchyMap.size(), 6u);
0267   BOOST_CHECK_NE(surface0, nullptr);
0268 }
0269 
0270 BOOST_AUTO_TEST_SUITE_END()
0271 
0272 }  // namespace ActsTests