Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12: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/Detector/DetectorVolume.hpp"
0013 #include "Acts/Detector/Portal.hpp"
0014 #include "Acts/Detector/PortalGenerators.hpp"
0015 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0016 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0017 #include "Acts/Geometry/Extent.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0020 #include "Acts/Material/HomogeneousVolumeMaterial.hpp"
0021 #include "Acts/Material/Material.hpp"
0022 #include "Acts/Material/MaterialSlab.hpp"
0023 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0024 #include "Acts/Navigation/InternalNavigation.hpp"
0025 #include "Acts/Navigation/NavigationState.hpp"
0026 #include "Acts/Surfaces/CylinderBounds.hpp"
0027 #include "Acts/Surfaces/CylinderSurface.hpp"
0028 #include "Acts/Surfaces/PlaneSurface.hpp"
0029 #include "Acts/Surfaces/RectangleBounds.hpp"
0030 #include "Acts/Surfaces/Surface.hpp"
0031 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0032 #include "Acts/Utilities/BinningType.hpp"
0033 
0034 #include <cstddef>
0035 #include <memory>
0036 #include <stdexcept>
0037 #include <utility>
0038 #include <vector>
0039 
0040 /// Unpack to shared - simply to test the getSharedPtr mechanism
0041 ///
0042 /// @tparam referenced_type is the type of the referenced object
0043 ///
0044 /// @param rt is the referenced object
0045 ///
0046 /// @returns a shared pointer
0047 template <typename referenced_type>
0048 std::shared_ptr<referenced_type> unpackToShared(referenced_type& rt) {
0049   return rt.getSharedPtr();
0050 }
0051 
0052 using namespace Acts::Experimental;
0053 
0054 Acts::GeometryContext tContext;
0055 
0056 BOOST_AUTO_TEST_SUITE(Detector)
0057 
0058 BOOST_AUTO_TEST_CASE(SurfaceVolumeContainment) {
0059   // Create a surface that is placed way off
0060   auto surfaceOutOfBounds = Acts::Surface::makeShared<Acts::CylinderSurface>(
0061       Acts::Transform3::Identity() * Acts::Translation3(-1000, 0., 0.),
0062       std::make_shared<Acts::CylinderBounds>(1, 1));
0063 
0064   auto vBounds = Acts::CuboidVolumeBounds(10.0, 10.0, 10.0);
0065   auto portalGenerator =
0066       Acts::Experimental::defaultPortalAndSubPortalGenerator();
0067   BOOST_CHECK_THROW(
0068       Acts::Experimental::DetectorVolumeFactory::construct(
0069           portalGenerator, Acts::GeometryContext(),
0070           "CubeWithOutofBoundsSurface", Acts::Transform3::Identity(),
0071           std::make_shared<Acts::CuboidVolumeBounds>(vBounds),
0072           {surfaceOutOfBounds}, {}, Acts::Experimental::tryAllSubVolumes(),
0073           Acts::Experimental::tryAllPortalsAndSurfaces(), 1000),
0074       std::invalid_argument);
0075 
0076   // Create a surface that is too big
0077   auto surfaceTooBig = Acts::Surface::makeShared<Acts::PlaneSurface>(
0078       Acts::Transform3::Identity() * Acts::Translation3(0, 0., 0.),
0079       std::make_shared<Acts::RectangleBounds>(1, 100));
0080 
0081   BOOST_CHECK_THROW(
0082       Acts::Experimental::DetectorVolumeFactory::construct(
0083           portalGenerator, Acts::GeometryContext(), "CubeWithSurfaceTooBig",
0084           Acts::Transform3::Identity(),
0085           std::make_shared<Acts::CuboidVolumeBounds>(vBounds), {surfaceTooBig},
0086           {}, Acts::Experimental::tryAllSubVolumes(),
0087           Acts::Experimental::tryAllPortalsAndSurfaces(), 1000),
0088       std::invalid_argument);
0089 
0090   // Envelope a bigger volume into a smaller one
0091   auto bigVolume = Acts::Experimental::DetectorVolumeFactory::construct(
0092       portalGenerator, Acts::GeometryContext(), "BigCube",
0093       Acts::Transform3::Identity(),
0094       std::make_shared<Acts::CuboidVolumeBounds>(vBounds), {}, {},
0095       Acts::Experimental::tryAllSubVolumes(),
0096       Acts::Experimental::tryAllPortalsAndSurfaces(), 1000);
0097 
0098   auto smallBounds = Acts::CuboidVolumeBounds(1.0, 1.0, 1.0);
0099   BOOST_CHECK_THROW(
0100       Acts::Experimental::DetectorVolumeFactory::construct(
0101           portalGenerator, Acts::GeometryContext(),
0102           "SmallCubeWithBigCubeInside", Acts::Transform3::Identity(),
0103           std::make_shared<Acts::CuboidVolumeBounds>(smallBounds), {},
0104           {bigVolume}, Acts::Experimental::tryAllSubVolumes(),
0105           Acts::Experimental::tryAllPortalsAndSurfaces(), 1000),
0106       std::invalid_argument);
0107 
0108   // Envelope a misaligned subvolume
0109   auto smallVolumeMisaligned =
0110       Acts::Experimental::DetectorVolumeFactory::construct(
0111           portalGenerator, Acts::GeometryContext(), "SmallCubeMisaligned",
0112           Acts::Transform3::Identity() * Acts::Translation3(9.5, 0., 0.),
0113           std::make_shared<Acts::CuboidVolumeBounds>(smallBounds), {}, {},
0114           Acts::Experimental::tryAllSubVolumes(),
0115           Acts::Experimental::tryAllPortalsAndSurfaces(), 1000);
0116 
0117   BOOST_CHECK_THROW(
0118       Acts::Experimental::DetectorVolumeFactory::construct(
0119           portalGenerator, Acts::GeometryContext(), "CubeWithMisalignedVolume",
0120           Acts::Transform3::Identity(),
0121           std::make_shared<Acts::CuboidVolumeBounds>(vBounds), {},
0122           {smallVolumeMisaligned}, Acts::Experimental::tryAllSubVolumes(),
0123           Acts::Experimental::tryAllPortalsAndSurfaces(), 1000),
0124       std::invalid_argument);
0125 }
0126 
0127 BOOST_AUTO_TEST_CASE(CylindricalDetectorVolumePortals) {
0128   double rInner = 10.;
0129   double rOuter = 100.;
0130   double zHalfL = 200.;
0131 
0132   Acts::Transform3 nominal = Acts::Transform3::Identity();
0133 
0134   auto fullCylinderBounds =
0135       std::make_unique<Acts::CylinderVolumeBounds>(0., rOuter, zHalfL);
0136 
0137   auto portalGenerator = defaultPortalGenerator();
0138 
0139   // Misconfigured - null pointer for bounds
0140   BOOST_CHECK_THROW(
0141       DetectorVolumeFactory::construct(portalGenerator, tContext,
0142                                        "MisconfiguredFullCylinderVolume",
0143                                        nominal, nullptr, tryAllPortals()),
0144       std::invalid_argument);
0145 
0146   // Misconfigured - portal generator not connected
0147   PortalGenerator unconnected;
0148   BOOST_CHECK_THROW(
0149       DetectorVolumeFactory::construct(unconnected, tContext,
0150                                        "MisconfiguredFullCylinderVolume",
0151                                        nominal, nullptr, tryAllPortals()),
0152       std::invalid_argument);
0153 
0154   // A full cylinder
0155   auto fullCylinderVolume = DetectorVolumeFactory::construct(
0156       portalGenerator, tContext, "FullCylinderVolume", nominal,
0157       std::move(fullCylinderBounds), tryAllPortals());
0158 
0159   BOOST_CHECK_EQUAL(fullCylinderVolume,
0160                     unpackToShared<DetectorVolume>(*fullCylinderVolume));
0161   BOOST_CHECK_EQUAL(fullCylinderVolume,
0162                     unpackToShared<const DetectorVolume>(*fullCylinderVolume));
0163 
0164   BOOST_CHECK(fullCylinderVolume->surfaces().empty());
0165   BOOST_CHECK(fullCylinderVolume->volumes().empty());
0166   BOOST_CHECK_EQUAL(fullCylinderVolume->portals().size(), 3u);
0167 
0168   // A tube cylinder
0169   auto tubeCylinderBounds =
0170       std::make_unique<Acts::CylinderVolumeBounds>(rInner, rOuter, zHalfL);
0171 
0172   auto tubeCylinderVolume = DetectorVolumeFactory::construct(
0173       portalGenerator, tContext, "TubeCylinderVolume", nominal,
0174       std::move(tubeCylinderBounds), tryAllPortals());
0175 
0176   BOOST_CHECK(tubeCylinderVolume->surfaces().empty());
0177   BOOST_CHECK(tubeCylinderVolume->volumes().empty());
0178   BOOST_CHECK_EQUAL(tubeCylinderVolume->portals().size(), 4u);
0179 
0180   // Let's test the resizing, first inside test: OK
0181   BOOST_CHECK(tubeCylinderVolume->inside(tContext, Acts::Vector3(50., 0., 0.)));
0182   // Outside
0183   BOOST_CHECK(
0184       !tubeCylinderVolume->inside(tContext, Acts::Vector3(150., 0., 0.)));
0185 
0186   // Check the extent
0187   auto volumeExtent = tubeCylinderVolume->extent(tContext, 1);
0188   CHECK_CLOSE_ABS(volumeExtent.min(Acts::AxisDirection::AxisR), 10., 10e-5);
0189   CHECK_CLOSE_ABS(volumeExtent.max(Acts::AxisDirection::AxisR), 100., 10e-5);
0190   CHECK_CLOSE_ABS(volumeExtent.min(Acts::AxisDirection::AxisZ), -200., 10e-5);
0191   CHECK_CLOSE_ABS(volumeExtent.max(Acts::AxisDirection::AxisZ), 200., 10e-5);
0192 }
0193 
0194 BOOST_AUTO_TEST_CASE(UpdatePortal) {
0195   Acts::Transform3 nominal = Acts::Transform3::Identity();
0196 
0197   auto fullCylinderBounds =
0198       std::make_unique<Acts::CylinderVolumeBounds>(0., 10., 100.);
0199 
0200   auto portalGenerator = defaultPortalGenerator();
0201 
0202   auto fullCylinderVolume = DetectorVolumeFactory::construct(
0203       portalGenerator, tContext, "FullCylinderVolume", nominal,
0204       std::move(fullCylinderBounds), tryAllPortals());
0205 
0206   auto cylinderSurface =
0207       Acts::Surface::makeShared<Acts::CylinderSurface>(nominal, 10., 100.);
0208 
0209   auto cylinderPortal =
0210       std::make_shared<Acts::Experimental::Portal>(cylinderSurface);
0211 
0212   fullCylinderVolume->updatePortal(cylinderPortal, 2u);
0213 
0214   BOOST_CHECK_EQUAL(fullCylinderVolume->portals()[2u], cylinderPortal.get());
0215 }
0216 
0217 BOOST_AUTO_TEST_CASE(CuboidWithCuboid) {
0218   double bigBox = 100.;
0219   double smallBox = 10.;
0220 
0221   Acts::Transform3 nominal = Acts::Transform3::Identity();
0222 
0223   auto bigBoxBounds =
0224       std::make_unique<Acts::CuboidVolumeBounds>(bigBox, bigBox, bigBox);
0225 
0226   auto smallBoxBounds =
0227       std::make_unique<Acts::CuboidVolumeBounds>(smallBox, smallBox, smallBox);
0228 
0229   auto portals = defaultPortalGenerator();
0230   auto generatePortalsUpdateInternals = defaultPortalAndSubPortalGenerator();
0231 
0232   // Create the inner box
0233   auto innerBox = DetectorVolumeFactory::construct(
0234       portals, tContext, "InnerBox", nominal, std::move(smallBoxBounds),
0235       tryAllPortals());
0236 
0237   std::vector<std::shared_ptr<Acts::Surface>> surfaces = {};
0238   std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>> volumes = {
0239       innerBox};
0240 
0241   // Create the outer box and insert the inner box, use a portal generator
0242   // with sub portal registration
0243   auto outerBox = DetectorVolumeFactory::construct(
0244       generatePortalsUpdateInternals, tContext, "OuterBox", nominal,
0245       std::move(bigBoxBounds), surfaces, volumes, tryAllSubVolumes(),
0246       tryAllPortals());
0247 
0248   // Check that we are within the outer box
0249   Acts::Experimental::NavigationState nState;
0250   nState.position = Acts::Vector3(-50., 5., 0.);
0251   nState.direction = Acts::Vector3(1., 0., 0.);
0252 
0253   BOOST_CHECK(outerBox->inside(tContext, nState.position));
0254   nState.currentVolume = outerBox.get();
0255 
0256   outerBox->updateNavigationState(tContext, nState);
0257 
0258   // We should have 12 candidates, 6 inner, 6 outer portals but only 3 are
0259   // reachable
0260   BOOST_CHECK_EQUAL(nState.surfaceCandidates.size(), 3u);
0261 
0262   // Check surface visiting - const access
0263   // Test the visitor pattern for surfaces
0264   std::size_t nSurfaces = 0;
0265   outerBox->visitSurfaces([&nSurfaces](const auto* s) {
0266     if (s != nullptr) {
0267       nSurfaces++;
0268     }
0269   });
0270   // 6 portlas outer box, 6 portals inner box
0271   BOOST_CHECK_EQUAL(nSurfaces, 12u);
0272 
0273   // Check volume visiting - const access
0274   std::size_t nVolumes = 0;
0275   outerBox->visitVolumes([&nVolumes](const auto* v) {
0276     if (v != nullptr) {
0277       nVolumes++;
0278     }
0279   });
0280   BOOST_CHECK_EQUAL(nVolumes, 2u);
0281 
0282   // Check surface visiting - non-const access
0283   // Test visitor pattern - non-const access
0284   struct SetMaterial {
0285     /// The material to set
0286     std::shared_ptr<const Acts::HomogeneousSurfaceMaterial> surfaceMaterial =
0287         std::make_shared<Acts::HomogeneousSurfaceMaterial>(Acts::MaterialSlab(
0288             Acts::Material::fromMolarDensity(1., 2., 3., 4., 5.), 1.));
0289 
0290     std::shared_ptr<Acts::HomogeneousVolumeMaterial> volumeMaterial =
0291         std::make_shared<Acts::HomogeneousVolumeMaterial>(
0292             Acts::Material::fromMolarDensity(1., 2., 3., 4., 5.));
0293 
0294     /// The visitor call: set surface material
0295     void operator()(Acts::Surface* s) {
0296       if (s != nullptr) {
0297         s->assignSurfaceMaterial(surfaceMaterial);
0298       }
0299     }
0300 
0301     /// The visitor call : set volume material
0302     void operator()(DetectorVolume* v) {
0303       if (v != nullptr) {
0304         v->assignVolumeMaterial(volumeMaterial);
0305       }
0306     }
0307   };
0308 
0309   SetMaterial setMaterial;
0310   outerBox->visitMutableSurfaces(setMaterial);
0311   outerBox->visitMutableVolumes(setMaterial);
0312 
0313   // Count surfaces with material
0314   std::size_t nSurfacesWithMaterial = 0;
0315   outerBox->visitSurfaces([&nSurfacesWithMaterial](const auto* s) {
0316     if (s != nullptr && s->surfaceMaterial() != nullptr) {
0317       nSurfacesWithMaterial++;
0318     }
0319   });
0320   BOOST_CHECK_EQUAL(nSurfacesWithMaterial, 12u);
0321 
0322   // Count volumes with material
0323   std::size_t nVolumesWithMaterial = 0;
0324   outerBox->visitVolumes([&nVolumesWithMaterial](const auto* v) {
0325     if (v != nullptr && v->volumeMaterial() != nullptr) {
0326       nVolumesWithMaterial++;
0327     }
0328   });
0329   BOOST_CHECK_EQUAL(nVolumesWithMaterial, 2u);
0330 }
0331 
0332 BOOST_AUTO_TEST_CASE(CylinderWithSurfacesTestExtractors) {
0333   auto portalGenerator = defaultPortalGenerator();
0334 
0335   std::vector<double> radii = {100, 102, 104, 106, 108, 110};
0336   auto cylinderVoumeBounds =
0337       std::make_unique<Acts::CylinderVolumeBounds>(80, 130, 200);
0338   std::vector<std::shared_ptr<Acts::Surface>> surfaces = {};
0339   for (const auto& r : radii) {
0340     surfaces.push_back(Acts::Surface::makeShared<Acts::CylinderSurface>(
0341         Acts::Transform3::Identity(),
0342         std::make_shared<Acts::CylinderBounds>(r, 190)));
0343   }
0344 
0345   // A full cylinder
0346   auto cylinderVolume = DetectorVolumeFactory::construct(
0347       portalGenerator, tContext, "CylinderVolume", Acts::Transform3::Identity(),
0348       std::move(cylinderVoumeBounds), surfaces, {}, tryNoVolumes(),
0349       tryAllPortalsAndSurfaces());
0350 
0351   // The navigation state
0352   NavigationState nState;
0353   AllPortalsExtractor allPortals;
0354   AllSurfacesExtractor allSurfaces;
0355   IndexedSurfacesExtractor indexedSurfaces;
0356 
0357   // First check exception behaviour
0358   BOOST_CHECK_THROW(allPortals.extract(tContext, nState), std::runtime_error);
0359   BOOST_CHECK_THROW(allSurfaces.extract(tContext, nState), std::runtime_error);
0360   BOOST_CHECK_THROW(indexedSurfaces.extract(tContext, nState, {0u, 1u}),
0361                     std::runtime_error);
0362 
0363   // A volume needs to be set
0364   nState.currentVolume = cylinderVolume.get();
0365 
0366   // This extracts all portals as candidates
0367   auto eportals = allPortals.extract(tContext, nState);
0368   BOOST_CHECK_EQUAL(eportals.size(), 4u);
0369 
0370   auto esurfaces = allSurfaces.extract(tContext, nState);
0371   BOOST_CHECK_EQUAL(esurfaces.size(), 6u);
0372 
0373   esurfaces = indexedSurfaces.extract(tContext, nState, {2u, 4u});
0374   BOOST_CHECK_EQUAL(esurfaces.size(), 2u);
0375   BOOST_CHECK_EQUAL(esurfaces[0u], surfaces[2u].get());
0376   BOOST_CHECK_EQUAL(esurfaces[1u], surfaces[4u].get());
0377 
0378   // Test the visitor pattern for surfaces
0379   struct CountSurfaces {
0380     unsigned int counter = 0;
0381 
0382     void operator()(const Acts::Surface* s) {
0383       if (s != nullptr) {
0384         counter++;
0385       }
0386     }
0387   };
0388 
0389   CountSurfaces countSurfaces;
0390   cylinderVolume->visitSurfaces(countSurfaces);
0391 
0392   // 6 internal surfaces, 4 portals -> 10 surfaces counted
0393   BOOST_CHECK_EQUAL(countSurfaces.counter, 10u);
0394 }
0395 
0396 BOOST_AUTO_TEST_SUITE_END()