Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-10 09:29:31

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/Geometry/BlueprintOptions.hpp"
0012 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0013 #include "Acts/Geometry/GeometryContext.hpp"
0014 #include "Acts/Geometry/StaticBlueprintNode.hpp"
0015 #include "Acts/Geometry/Volume.hpp"
0016 #include "Acts/Utilities/Logger.hpp"
0017 #include "ActsPlugins/Root/BlueprintBuilder.hpp"
0018 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0019 
0020 #include <stdexcept>
0021 #include <string>
0022 
0023 #include "TGeoManager.h"
0024 #include "TGeoMaterial.h"
0025 #include "TGeoMatrix.h"
0026 #include "TGeoMedium.h"
0027 #include "TGeoVolume.h"
0028 
0029 using namespace Acts;
0030 using namespace ActsPlugins;
0031 
0032 namespace ActsTests {
0033 
0034 static_assert(detail::HasPassiveVolume<TGeoBlueprintBuilderBackend>);
0035 
0036 namespace {
0037 
0038 /// Builds a small TGeo world (in cm) with a support tube, an endplate disc
0039 /// and a box.
0040 void buildPassiveGeometry() {
0041   new TGeoManager("passive", "passive elements");
0042   auto* mat = new TGeoMaterial("Al", 26.98, 13, 2.7);
0043   auto* med = new TGeoMedium("MED", 1, mat);
0044   TGeoVolume* top = gGeoManager->MakeBox("World", med, 500., 500., 500.);
0045   gGeoManager->SetTopVolume(top);
0046 
0047   // Tube-like: radial thickness 0.4 cm, z half-length 100 cm.
0048   TGeoVolume* tube = gGeoManager->MakeTube("SupportTube", med, 20., 20.4, 100.);
0049   top->AddNode(tube, 1);
0050 
0051   // Disc-like: radial extent 10 cm, z half-length 0.5 cm, shifted to z=150 cm.
0052   TGeoVolume* disc = gGeoManager->MakeTube("Endplate", med, 5., 15., 0.5);
0053   top->AddNode(disc, 1, new TGeoTranslation(0., 0., 150.));
0054 
0055   // Neither tube- nor disc-like.
0056   TGeoVolume* box = gGeoManager->MakeBox("Box", med, 1., 1., 1.);
0057   top->AddNode(box, 1);
0058 
0059   gGeoManager->CloseGeometry();
0060 }
0061 
0062 }  // namespace
0063 
0064 BOOST_AUTO_TEST_SUITE(RootSuite)
0065 
0066 BOOST_AUTO_TEST_CASE(TGeoBlueprintBuilderPassiveElement) {
0067   buildPassiveGeometry();
0068 
0069   TGeoBlueprintBuilderBackend::Config cfg;
0070   cfg.root = gGeoManager->GetTopNode();
0071   cfg.lengthScale = 10.;  // cm -> mm
0072   ActsPlugins::BlueprintBuilder builder{cfg};
0073 
0074   auto gctx = GeometryContext::dangerouslyDefaultConstruct();
0075 
0076   // Tube-like element becomes a cylinder shell around the beam axis.
0077   auto tubeElement = builder.findDetElementByName("SupportTube");
0078   BOOST_REQUIRE(tubeElement.has_value());
0079   auto tubeNode = builder.makePassiveElement(*tubeElement);
0080   BOOST_CHECK_EQUAL(tubeNode->name(), "SupportTube");
0081   const Volume& tubeVolume = tubeNode->build(BlueprintOptions{}, gctx);
0082   const auto* tubeBounds =
0083       dynamic_cast<const CylinderVolumeBounds*>(&tubeVolume.volumeBounds());
0084   BOOST_REQUIRE(tubeBounds != nullptr);
0085   CHECK_CLOSE_ABS(tubeBounds->get(CylinderVolumeBounds::eMinR), 200., 1e-9);
0086   CHECK_CLOSE_ABS(tubeBounds->get(CylinderVolumeBounds::eMaxR), 204., 1e-9);
0087   CHECK_CLOSE_ABS(tubeBounds->get(CylinderVolumeBounds::eHalfLengthZ), 1000.,
0088                   1e-9);
0089   CHECK_CLOSE_ABS(tubeVolume.localToGlobalTransform(gctx).translation().z(), 0.,
0090                   1e-9);
0091 
0092   // Disc-like element becomes an annular disc at its placement, with an
0093   // explicit volume name.
0094   auto discElement = builder.findDetElementByName("Endplate");
0095   BOOST_REQUIRE(discElement.has_value());
0096   auto discNode = builder.makePassiveElement(*discElement, "PositiveEndplate");
0097   BOOST_CHECK_EQUAL(discNode->name(), "PositiveEndplate");
0098   const Volume& discVolume = discNode->build(BlueprintOptions{}, gctx);
0099   const auto* discBounds =
0100       dynamic_cast<const CylinderVolumeBounds*>(&discVolume.volumeBounds());
0101   BOOST_REQUIRE(discBounds != nullptr);
0102   CHECK_CLOSE_ABS(discBounds->get(CylinderVolumeBounds::eMinR), 50., 1e-9);
0103   CHECK_CLOSE_ABS(discBounds->get(CylinderVolumeBounds::eMaxR), 150., 1e-9);
0104   CHECK_CLOSE_ABS(discBounds->get(CylinderVolumeBounds::eHalfLengthZ), 5.,
0105                   1e-9);
0106   CHECK_CLOSE_ABS(discVolume.localToGlobalTransform(gctx).translation().z(),
0107                   1500., 1e-9);
0108 
0109   // A shape that is neither tube- nor disc-like is rejected.
0110   auto boxElement = builder.findDetElementByName("Box");
0111   BOOST_REQUIRE(boxElement.has_value());
0112   BOOST_CHECK_THROW(builder.makePassiveElement(*boxElement),
0113                     std::runtime_error);
0114 }
0115 
0116 BOOST_AUTO_TEST_SUITE_END()
0117 
0118 }  // namespace ActsTests