Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 07:53:08

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/DetectorComponents.hpp"
0013 #include "Acts/Detector/DetectorVolume.hpp"
0014 #include "Acts/Detector/DetectorVolumeBuilder.hpp"
0015 #include "Acts/Detector/PortalGenerators.hpp"
0016 #include "Acts/Detector/interface/IExternalStructureBuilder.hpp"
0017 #include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
0018 #include "Acts/Detector/interface/IInternalStructureBuilder.hpp"
0019 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0020 #include "Acts/Geometry/GeometryContext.hpp"
0021 #include "Acts/Geometry/GeometryIdentifier.hpp"
0022 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0023 #include "Acts/Navigation/InternalNavigation.hpp"
0024 #include "Acts/Surfaces/CylinderBounds.hpp"
0025 #include "Acts/Surfaces/CylinderSurface.hpp"
0026 #include "Acts/Surfaces/Surface.hpp"
0027 #include "Acts/Utilities/Logger.hpp"
0028 #include "Acts/Utilities/ProtoAxis.hpp"
0029 
0030 #include <memory>
0031 #include <numbers>
0032 #include <stdexcept>
0033 #include <string>
0034 #include <utility>
0035 #include <vector>
0036 
0037 using namespace Acts;
0038 using namespace Acts::Experimental;
0039 
0040 GeometryContext tContext;
0041 
0042 /// @brief Mockup external structure builder
0043 /// @tparam bounds_type the volume bounds type that is constructed
0044 template <typename bounds_type>
0045 class ExternalsBuilder : public IExternalStructureBuilder {
0046  public:
0047   ExternalsBuilder(const Transform3& transform, const bounds_type& bounds)
0048       : IExternalStructureBuilder(),
0049         m_transform(transform),
0050         m_bounds(std::move(bounds)) {}
0051 
0052   ExternalStructure construct(
0053       [[maybe_unused]] const GeometryContext& gctx) const final {
0054     return {m_transform, std::make_unique<bounds_type>(m_bounds),
0055             defaultPortalGenerator()};
0056   }
0057 
0058  private:
0059   Transform3 m_transform = Transform3::Identity();
0060   bounds_type m_bounds;
0061 };
0062 
0063 /// @brief  Mockup internal surface builder
0064 /// @tparam surface_type the surface type to be constructed
0065 /// @tparam bounds_type the bounds type that is constructed
0066 template <typename surface_type, typename bounds_type>
0067 class InternalSurfaceBuilder : public IInternalStructureBuilder {
0068  public:
0069   InternalSurfaceBuilder(const Transform3& transform, const bounds_type& bounds)
0070       : IInternalStructureBuilder(),
0071         m_transform(transform),
0072         m_bounds(std::move(bounds)) {}
0073 
0074   InternalStructure construct(
0075       [[maybe_unused]] const GeometryContext& gctx) const final {
0076     auto surface = Surface::makeShared<surface_type>(
0077         m_transform, std::make_shared<bounds_type>(m_bounds));
0078     return {{surface}, {}, tryAllPortalsAndSurfaces(), tryNoVolumes()};
0079   }
0080 
0081  private:
0082   Transform3 m_transform = Transform3::Identity();
0083   bounds_type m_bounds;
0084 };
0085 
0086 class SurfaceGeoIdGenerator : public Acts::Experimental::IGeometryIdGenerator {
0087  public:
0088   Acts::Experimental::IGeometryIdGenerator::GeoIdCache generateCache()
0089       const final {
0090     return std::any();
0091   }
0092 
0093   void assignGeometryId(
0094       Acts::Experimental::IGeometryIdGenerator::GeoIdCache& /*cache*/,
0095       Acts::Experimental::DetectorVolume& dVolume) const final {
0096     for (auto [is, s] : Acts::enumerate(dVolume.surfacePtrs())) {
0097       s->assignGeometryId(GeometryIdentifier().withPassive(is + 1));
0098     }
0099   }
0100 
0101   void assignGeometryId(
0102       Acts::Experimental::IGeometryIdGenerator::GeoIdCache& /*cache*/,
0103       Acts::Experimental::Portal& /*portal*/) const final {}
0104 
0105   void assignGeometryId(
0106       Acts::Experimental::IGeometryIdGenerator::GeoIdCache& /*cache*/,
0107       Acts::Surface& /*surface*/) const final {}
0108 };
0109 
0110 /// @brief  Mockup internal surface builder
0111 /// @tparam surface_type the surface type to be constructed
0112 /// @tparam bounds_type the bounds type that is constructed
0113 template <typename bounds_type>
0114 class InternalVolumeBuilder : public IInternalStructureBuilder {
0115  public:
0116   InternalVolumeBuilder(const Transform3& transform, const bounds_type& bounds)
0117       : IInternalStructureBuilder(),
0118         m_transform(transform),
0119         m_bounds(std::move(bounds)) {}
0120 
0121   InternalStructure construct(
0122       [[maybe_unused]] const GeometryContext& gctx) const final {
0123     auto bounds = std::make_unique<bounds_type>(m_bounds);
0124     auto portalGenerator = defaultPortalGenerator();
0125     auto volume = DetectorVolumeFactory::construct(
0126         portalGenerator, tContext, "InternalVolume", m_transform,
0127         std::move(bounds), tryAllPortals());
0128     return {{}, {volume}, tryAllPortals(), tryRootVolumes()};
0129   }
0130 
0131  private:
0132   Transform3 m_transform = Transform3::Identity();
0133   bounds_type m_bounds;
0134 };
0135 
0136 BOOST_AUTO_TEST_SUITE(Detector)
0137 
0138 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_Misconfigured) {
0139   // Internal and external structure builder is empty
0140   DetectorVolumeBuilder::Config dvCfg;
0141   dvCfg.auxiliary = "*** Test X * Misconfigued ***";
0142   dvCfg.name = "EmptyCylinder";
0143   dvCfg.externalsBuilder = nullptr;
0144   dvCfg.internalsBuilder = nullptr;
0145 
0146   BOOST_CHECK_THROW(auto a = DetectorVolumeBuilder(dvCfg),
0147                     std::invalid_argument);
0148 }
0149 
0150 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_EmptyVolume) {
0151   CylinderVolumeBounds cBounds(10, 100, 200);
0152   auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0153       Transform3::Identity(), cBounds);
0154 
0155   DetectorVolumeBuilder::Config dvCfg;
0156   dvCfg.auxiliary = "*** Test 0 - Empty Cylinder ***";
0157   dvCfg.name = "EmptyCylinder";
0158   dvCfg.externalsBuilder = cBuilder;
0159   dvCfg.internalsBuilder = nullptr;
0160 
0161   // Assign proto material to
0162   dvCfg.portalMaterialBinning[2u] = {
0163       DirectedProtoAxis(AxisDirection::AxisZ, AxisBoundaryType::Bound, 50),
0164       DirectedProtoAxis(AxisDirection::AxisPhi, AxisBoundaryType::Closed,
0165                         -std::numbers::pi, std::numbers::pi, 12)};
0166 
0167   auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0168       dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0169 
0170   auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0171 
0172   BOOST_CHECK_EQUAL(volumes.size(), 1u);
0173   BOOST_CHECK(volumes.front()->surfaces().empty());
0174   BOOST_CHECK(volumes.front()->volumes().empty());
0175 
0176   BOOST_CHECK_EQUAL(portals.size(), 4u);
0177 
0178   BOOST_CHECK_EQUAL(roots.volumes.size(), 1u);
0179   BOOST_CHECK(roots.volumeFinder.connected());
0180 
0181   // Check that the outside portal has material
0182   BOOST_CHECK_NE(portals[2u]->surface().surfaceMaterial(), nullptr);
0183   // While all the others have none
0184   BOOST_CHECK_EQUAL(portals[0u]->surface().surfaceMaterial(), nullptr);
0185   BOOST_CHECK_EQUAL(portals[1u]->surface().surfaceMaterial(), nullptr);
0186   BOOST_CHECK_EQUAL(portals[3u]->surface().surfaceMaterial(), nullptr);
0187 }
0188 
0189 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_VolumeWithSurface) {
0190   CylinderVolumeBounds cvBounds(10, 100, 200);
0191   auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0192       Transform3::Identity(), cvBounds);
0193 
0194   CylinderBounds csBounds(55., 195.);
0195   auto sBuilder =
0196       std::make_shared<InternalSurfaceBuilder<CylinderSurface, CylinderBounds>>(
0197           Transform3::Identity(), csBounds);
0198 
0199   DetectorVolumeBuilder::Config dvCfg;
0200   dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0201   dvCfg.name = "CylinderWithSurface";
0202   dvCfg.externalsBuilder = cBuilder;
0203   dvCfg.internalsBuilder = sBuilder;
0204   dvCfg.geoIdGenerator = std::make_shared<SurfaceGeoIdGenerator>();
0205 
0206   auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0207       dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0208 
0209   auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0210 
0211   BOOST_CHECK_EQUAL(volumes.size(), 1u);
0212   BOOST_CHECK_EQUAL(volumes.front()->surfaces().size(), 1u);
0213 
0214   BOOST_CHECK_EQUAL(volumes.front()->surfaces().front()->geometryId().passive(),
0215                     1u);
0216   BOOST_CHECK(volumes.front()->volumes().empty());
0217 
0218   BOOST_CHECK_EQUAL(portals.size(), 4u);
0219 
0220   BOOST_CHECK_EQUAL(roots.volumes.size(), 1u);
0221   BOOST_CHECK(roots.volumeFinder.connected());
0222 }
0223 
0224 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_VolumeWithVolume) {
0225   CylinderVolumeBounds cvBounds(10, 100, 200);
0226   auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0227       Transform3::Identity(), cvBounds);
0228 
0229   CylinderVolumeBounds ciBounds(15., 95., 195.);
0230   auto iBuilder = std::make_shared<InternalVolumeBuilder<CylinderVolumeBounds>>(
0231       Transform3::Identity(), ciBounds);
0232 
0233   DetectorVolumeBuilder::Config dvCfg;
0234   dvCfg.auxiliary = "*** Test 2 - Cylinder with internal Volume ***";
0235   dvCfg.name = "CylinderWithVolume";
0236   dvCfg.externalsBuilder = cBuilder;
0237   dvCfg.internalsBuilder = iBuilder;
0238   dvCfg.addInternalsToRoot = false;
0239 
0240   auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0241       dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0242 
0243   auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0244 
0245   BOOST_CHECK_EQUAL(volumes.size(), 1u);
0246   BOOST_CHECK_EQUAL(portals.size(), 4u);
0247   BOOST_CHECK_EQUAL(roots.volumes.size(), 1u);
0248 }
0249 
0250 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_VolumeWithVolumeToRoot) {
0251   CylinderVolumeBounds cvBounds(10, 100, 200);
0252   auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0253       Transform3::Identity(), cvBounds);
0254 
0255   CylinderVolumeBounds ciBounds(15., 95., 195.);
0256   auto iBuilder = std::make_shared<InternalVolumeBuilder<CylinderVolumeBounds>>(
0257       Transform3::Identity(), ciBounds);
0258 
0259   DetectorVolumeBuilder::Config dvCfg;
0260   dvCfg.auxiliary =
0261       "*** Test 3 - Cylinder with internal Volume, adding to root ***";
0262   dvCfg.name = "CylinderWithVolume";
0263   dvCfg.externalsBuilder = cBuilder;
0264   dvCfg.internalsBuilder = iBuilder;
0265   dvCfg.addInternalsToRoot = true;
0266 
0267   auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0268       dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0269 
0270   auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0271 
0272   BOOST_CHECK_EQUAL(volumes.size(), 1u);
0273   BOOST_CHECK(volumes.front()->surfaces().empty());
0274   BOOST_CHECK_EQUAL(volumes.front()->volumes().size(), 1u);
0275 
0276   BOOST_CHECK_EQUAL(portals.size(), 4u);
0277 
0278   BOOST_CHECK_EQUAL(roots.volumes.size(), 2u);
0279   BOOST_CHECK(roots.volumeFinder.connected());
0280 }
0281 
0282 BOOST_AUTO_TEST_SUITE_END()