Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:19

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 "Acts/Geometry/Blueprint.hpp"
0010 
0011 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0012 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0013 #include "Acts/Geometry/Extent.hpp"
0014 #include "Acts/Geometry/PortalShell.hpp"
0015 #include "Acts/Geometry/VolumeBounds.hpp"
0016 #include "Acts/Navigation/INavigationPolicy.hpp"
0017 #include "Acts/Utilities/GraphViz.hpp"
0018 
0019 namespace {
0020 const std::string s_rootName = "Root";
0021 }
0022 
0023 namespace Acts {
0024 
0025 Blueprint::Blueprint(const Config &config) : m_cfg(config) {}
0026 
0027 const std::string &Blueprint::name() const {
0028   return s_rootName;
0029 }
0030 
0031 Volume &Blueprint::build(const BlueprintOptions & /*options*/,
0032                          const GeometryContext & /*gctx*/,
0033                          const Logger & /*logger*/) {
0034   throw std::logic_error("Root node cannot be built");
0035 }
0036 
0037 PortalShellBase &Blueprint::connect(const BlueprintOptions & /*options*/,
0038                                     const GeometryContext & /*gctx*/,
0039                                     const Logger & /*logger*/) {
0040   throw std::logic_error("Root node cannot be connected");
0041 }
0042 
0043 void Blueprint::finalize(const BlueprintOptions & /*options*/,
0044                          const GeometryContext & /*gctx*/,
0045                          TrackingVolume & /*parent*/,
0046                          const Logger & /*logger*/) {
0047   throw std::logic_error("Root node cannot be finalized");
0048 }
0049 
0050 void Blueprint::addToGraphviz(std::ostream &os) const {
0051   GraphViz::Node node{
0052       .id = name(), .label = "World", .shape = GraphViz::Shape::House};
0053 
0054   os << node;
0055   BlueprintNode::addToGraphviz(os);
0056 }
0057 
0058 std::unique_ptr<TrackingGeometry> Blueprint::construct(
0059     const BlueprintOptions &options, const GeometryContext &gctx,
0060     const Logger &logger) {
0061   using enum AxisDirection;
0062 
0063   ACTS_INFO(prefix() << "Building tracking geometry from blueprint tree");
0064 
0065   options.validate();
0066 
0067   if (m_cfg.envelope == ExtentEnvelope::Zero()) {
0068     ACTS_WARNING(prefix() << "Root node is configured with zero envelope. This "
0069                              "might lead to navigation issues");
0070   }
0071 
0072   if (children().size() != 1) {
0073     ACTS_ERROR(prefix() << "Root node must have exactly one child");
0074     throw std::logic_error("Root node must have exactly one child");
0075   }
0076 
0077   auto &child = children().at(0);
0078 
0079   ACTS_DEBUG(prefix() << "Executing building on tree");
0080   Volume &topVolume = child.build(options, gctx, logger);
0081   const auto &bounds = topVolume.volumeBounds();
0082 
0083   std::stringstream ss;
0084   bounds.toStream(ss);
0085   ACTS_DEBUG(prefix() << "have top volume: " << ss.str() << "\n"
0086                       << topVolume.transform().matrix());
0087 
0088   std::shared_ptr<VolumeBounds> worldBounds;
0089 
0090   if (const auto *cyl = dynamic_cast<const CylinderVolumeBounds *>(&bounds);
0091       cyl != nullptr) {
0092     using enum CylinderVolumeBounds::BoundValues;
0093 
0094     // Make a copy that we'll modify
0095     auto newBounds = std::make_shared<CylinderVolumeBounds>(*cyl);
0096 
0097     const auto &zEnv = m_cfg.envelope[AxisZ];
0098     if (zEnv[0] != zEnv[1]) {
0099       ACTS_ERROR(
0100           prefix() << "Root node cylinder envelope for z must be symmetric");
0101       throw std::logic_error(
0102           "Root node cylinder envelope for z must be "
0103           "symmetric");
0104     }
0105 
0106     const auto &rEnv = m_cfg.envelope[AxisR];
0107 
0108     newBounds->set({
0109         {eHalfLengthZ, newBounds->get(eHalfLengthZ) + zEnv[0]},
0110         {eMinR, std::max(0.0, newBounds->get(eMinR) - rEnv[0])},
0111         {eMaxR, newBounds->get(eMaxR) + rEnv[1]},
0112     });
0113 
0114     worldBounds = std::move(newBounds);
0115 
0116   } else if (const auto *box =
0117                  dynamic_cast<const CuboidVolumeBounds *>(&bounds);
0118              box != nullptr) {
0119     throw std::logic_error{"Not implemented"};
0120   } else {
0121     throw std::logic_error{"Unsupported volume bounds type"};
0122   }
0123 
0124   ACTS_DEBUG(prefix() << "New root volume bounds are: " << *worldBounds);
0125 
0126   auto world = std::make_unique<TrackingVolume>(
0127       topVolume.transform(), std::move(worldBounds), "World");
0128 
0129   // @TODO: This needs to become configurable
0130   world->setNavigationPolicy(
0131       options.defaultNavigationPolicyFactory->build(gctx, *world, logger));
0132 
0133   // Need one-sided portal shell that connects outwards to nullptr
0134   SingleCylinderPortalShell worldShell{*world};
0135   worldShell.applyToVolume();
0136 
0137   auto &shell = child.connect(options, gctx, logger);
0138 
0139   shell.fill(*world);
0140 
0141   child.finalize(options, gctx, *world, logger);
0142 
0143   std::set<std::string, std::less<>> names;
0144 
0145   world->visitVolumes([&names, &logger, this](const auto *volume) {
0146     if (names.contains(volume->volumeName())) {
0147       ACTS_ERROR(prefix() << "Duplicate volume name: " << volume->volumeName());
0148       throw std::logic_error("Duplicate volume name");
0149     }
0150     names.insert(volume->volumeName());
0151   });
0152 
0153   return std::make_unique<TrackingGeometry>(
0154       std::move(world), nullptr, m_cfg.geometryIdentifierHook, logger);
0155 }
0156 
0157 }  // namespace Acts