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/Detector/VolumeStructureBuilder.hpp"
0010 
0011 #include "Acts/Detector/PortalGenerators.hpp"
0012 #include "Acts/Geometry/ConeVolumeBounds.hpp"
0013 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0014 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0016 #include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
0017 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0018 #include "Acts/Utilities/Enumerate.hpp"
0019 #include "Acts/Utilities/Helpers.hpp"
0020 #include "Acts/Utilities/StringHelpers.hpp"
0021 
0022 #include <numbers>
0023 
0024 Acts::Experimental::VolumeStructureBuilder::VolumeStructureBuilder(
0025     const Acts::Experimental::VolumeStructureBuilder::Config& cfg,
0026     std::unique_ptr<const Acts::Logger> mlogger)
0027     : IExternalStructureBuilder(), m_cfg(cfg), m_logger(std::move(mlogger)) {
0028   // Sanity cross-checks
0029   if (m_cfg.boundValues.empty() && !m_cfg.extent.has_value()) {
0030     throw std::invalid_argument(
0031         "VolumeStructureBuilder: no extent nor boundary values given");
0032   }
0033   // Check for the bounds type
0034   if (m_cfg.boundsType == VolumeBounds::BoundsType::eOther) {
0035     throw std::invalid_argument(
0036         "VolumeStructureBuilder: no known volume bounds type provided.");
0037   }
0038 }
0039 
0040 Acts::Experimental::ExternalStructure
0041 Acts::Experimental::VolumeStructureBuilder::construct(
0042     [[maybe_unused]] const Acts::GeometryContext& gctx) const {
0043   // Print out the auxiliary information
0044   if (!m_cfg.auxiliary.empty()) {
0045     ACTS_DEBUG(m_cfg.auxiliary);
0046   }
0047 
0048   // The volume bounds to be constructed
0049   std::unique_ptr<VolumeBounds> volumeBounds = nullptr;
0050 
0051   // The transform from the extent
0052   auto eTransform = Transform3::Identity();
0053   std::vector<double> boundValues = m_cfg.boundValues;
0054 
0055   // This code dispatches into the dedicated volume types
0056   switch (m_cfg.boundsType) {
0057     case VolumeBounds::BoundsType::eCone: {
0058       ACTS_VERBOSE("Building conical volume bounds.");
0059       // Cone translation - only pre-defined values
0060       if (boundValues.size() < 5u) {
0061         throw std::runtime_error(
0062             "VolumeStructureBuilder: parameters for cone volume bounds need to "
0063             "be fully provided, they can not be estimated from an Extent "
0064             "object. It needs at least 5 parameters, while " +
0065             std::to_string(boundValues.size()) + " where given");
0066       }
0067       auto bArray =
0068           toArray<ConeVolumeBounds::BoundValues::eSize, double>(boundValues);
0069       volumeBounds = std::make_unique<ConeVolumeBounds>(bArray);
0070     } break;
0071     case VolumeBounds::BoundsType::eCuboid: {
0072       ACTS_VERBOSE("Building cuboid volume bounds.");
0073       // Cuboid translation - either parameters / or extent
0074       if (boundValues.empty() && m_cfg.extent.has_value()) {
0075         ACTS_VERBOSE("Cuboid: estimate parameters from Extent.");
0076         const auto& vExtent = m_cfg.extent.value();
0077         if (vExtent.constrains(AxisDirection::AxisX) &&
0078             vExtent.constrains(AxisDirection::AxisY) &&
0079             vExtent.constrains(AxisDirection::AxisZ)) {
0080           eTransform.pretranslate(
0081               Vector3(vExtent.medium(AxisDirection::AxisX),
0082                       vExtent.medium(AxisDirection::AxisY),
0083                       vExtent.medium(AxisDirection::AxisZ)));
0084           boundValues = {0.5 * vExtent.interval(AxisDirection::AxisX),
0085                          0.5 * vExtent.interval(AxisDirection::AxisY),
0086                          0.5 * vExtent.interval(AxisDirection::AxisZ)};
0087 
0088         } else {
0089           throw std::runtime_error(
0090               "VolumeStructureBuilder: translation to cuboid does not work as "
0091               "the extent does not constrain all necessary value.");
0092         }
0093       } else if (boundValues.size() < 3u) {
0094         throw std::runtime_error(
0095             "VolumeStructureBuilder: parameters for cuboid volume bounds need "
0096             "to be fully provided, it needs exactly 3 parameters, while " +
0097             std::to_string(boundValues.size()) + " where given");
0098       }
0099       auto bArray =
0100           toArray<CuboidVolumeBounds::BoundValues::eSize>(boundValues);
0101       volumeBounds = std::make_unique<CuboidVolumeBounds>(bArray);
0102     } break;
0103     case VolumeBounds::BoundsType::eCutoutCylinder: {
0104       ACTS_VERBOSE("Building cutout cylindrical volume bounds.");
0105       // Cutout cylinder translation - only parameters
0106       if (boundValues.size() < 5u) {
0107         throw std::runtime_error(
0108             "VolumeStructureBuilder: parameters for cutout cylinder volume "
0109             "bounds need to be fully provided, they can not be estimated from "
0110             "an Extent object. It needs exactly 3 parameters, while " +
0111             std::to_string(boundValues.size()) + " where given");
0112       }
0113       auto bArray =
0114           toArray<CutoutCylinderVolumeBounds::BoundValues::eSize>(boundValues);
0115       volumeBounds = std::make_unique<CutoutCylinderVolumeBounds>(bArray);
0116     } break;
0117     case VolumeBounds::BoundsType::eCylinder: {
0118       ACTS_VERBOSE("Building cylindrical volume bounds.");
0119       // Cylinder translation - either parameters / or extent
0120       if (boundValues.empty() && m_cfg.extent.has_value()) {
0121         ACTS_VERBOSE("Cylinder: estimate parameters from Extent.");
0122         const auto& vExtent = m_cfg.extent.value();
0123         if (vExtent.constrains(AxisDirection::AxisR) &&
0124             vExtent.constrains(AxisDirection::AxisZ)) {
0125           eTransform.pretranslate(
0126               Vector3(0., 0., vExtent.medium(AxisDirection::AxisZ)));
0127           boundValues = {vExtent.min(AxisDirection::AxisR),
0128                          vExtent.max(AxisDirection::AxisR),
0129                          0.5 * vExtent.interval(AxisDirection::AxisZ)};
0130           if (vExtent.constrains(AxisDirection::AxisPhi)) {
0131             boundValues.push_back(0.5 *
0132                                   vExtent.interval(AxisDirection::AxisPhi));
0133             boundValues.push_back(vExtent.medium(AxisDirection::AxisPhi));
0134           }
0135         } else {
0136           throw std::runtime_error(
0137               "VolumeStructureBuilder: translation to cuboid does not work as "
0138               "the extent does not constrain all necessary values.");
0139         }
0140       } else if (boundValues.size() < 3u) {
0141         throw std::runtime_error(
0142             "VolumeStructureBuilder: parameters for cylinder volume "
0143             "bounds need to be fully provided, it needs at least 3 parameters, "
0144             "while " +
0145             std::to_string(boundValues.size()) + " where given");
0146       }
0147       // Check if phi has been constraint, otherwise fill it with full coverage
0148       if (boundValues.size() == 3u) {
0149         boundValues.push_back(std::numbers::pi);
0150         boundValues.push_back(0.);
0151       }
0152       ACTS_VERBOSE(" - cylindrical shape with [iR, oR, hZ, sPhi, mPhi] = "
0153                    << boundValues[0] << ", " << boundValues[1] << ", "
0154                    << boundValues[2] << ", " << boundValues[3] << ", "
0155                    << boundValues[4]);
0156       auto bArray =
0157           toArray<CylinderVolumeBounds::BoundValues::eSize>(boundValues);
0158       volumeBounds = std::make_unique<CylinderVolumeBounds>(bArray);
0159     } break;
0160     case VolumeBounds::BoundsType::eGenericCuboid: {
0161       ACTS_VERBOSE("Building generic cuboid volume bounds.");
0162       // Generic cuboid translation - parameters only
0163       if (boundValues.size() < GenericCuboidVolumeBounds::BoundValues::eSize) {
0164         throw std::runtime_error(
0165             "VolumeStructureBuilder: parameters for generic cuboid volume "
0166             "bounds need to be provided, they can not be estimated from an "
0167             "Extent object. It needs exactly 24 parameters, while " +
0168             std::to_string(boundValues.size()) + " where given");
0169       }
0170       auto bArray =
0171           toArray<GenericCuboidVolumeBounds::BoundValues::eSize>(boundValues);
0172       volumeBounds = std::make_unique<GenericCuboidVolumeBounds>(bArray);
0173     } break;
0174     case VolumeBounds::BoundsType::eTrapezoid: {
0175       ACTS_VERBOSE("Building trapezoid volume bounds.");
0176       // Trapezoid translation - parameters only
0177       if (boundValues.size() < 4u) {
0178         throw std::runtime_error(
0179             "VolumeStructureBuilder: parameters for trapezoid volume bounds "
0180             "need to be provided, they can not be estimated from an Extent "
0181             "object. It needs at least 4 parameters, while " +
0182             std::to_string(boundValues.size()) + " where given");
0183       }
0184       auto bArray =
0185           toArray<TrapezoidVolumeBounds::BoundValues::eSize>(boundValues);
0186       volumeBounds = std::make_unique<TrapezoidVolumeBounds>(bArray);
0187     } break;
0188     default:
0189       break;
0190   }
0191 
0192   Transform3 fTransform = m_cfg.transform * eTransform;
0193   ACTS_VERBOSE(" - translation: " << Acts::toString(fTransform.translation()));
0194   if (!fTransform.rotation().isApprox(
0195           Acts::Transform3::Identity().rotation())) {
0196     ACTS_VERBOSE(" - rotation: " << Acts::toString(fTransform.rotation()));
0197   }
0198   // Return the transform, the volume bounds, and some default portal
0199   // generators
0200   return {fTransform, std::move(volumeBounds), defaultPortalGenerator()};
0201 }