Back to home page

EIC code displayed by LXR

 
 

    


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

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/DetectorVolume.hpp"
0010 
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Detector/Portal.hpp"
0013 #include "Acts/Geometry/Polyhedron.hpp"
0014 #include "Acts/Geometry/VolumeBounds.hpp"
0015 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0016 #include "Acts/Navigation/NavigationState.hpp"
0017 #include "Acts/Navigation/PortalNavigation.hpp"
0018 #include "Acts/Surfaces/Surface.hpp"
0019 #include "Acts/Utilities/Delegate.hpp"
0020 #include "Acts/Utilities/Enumerate.hpp"
0021 
0022 #include <cassert>
0023 #include <iterator>
0024 
0025 namespace Acts {
0026 class IVolumeMaterial;
0027 }  // namespace Acts
0028 
0029 Acts::Experimental::DetectorVolume::DetectorVolume(
0030     const GeometryContext& gctx, std::string name, const Transform3& transform,
0031     std::shared_ptr<VolumeBounds> bounds,
0032     std::vector<std::shared_ptr<Surface>> surfaces,
0033     std::vector<std::shared_ptr<DetectorVolume>> volumes,
0034     ExternalNavigationDelegate externalNavigation,
0035     InternalNavigationDelegate internalNavigation)
0036     : m_name(std::move(name)),
0037       m_transform(transform),
0038       m_bounds(std::move(bounds)),
0039       m_surfaces(std::move(surfaces)),
0040       m_volumes(std::move(volumes)),
0041       m_externalNavigation(std::move(externalNavigation)),
0042       m_internalNavigation(std::move(internalNavigation)),
0043       m_volumeMaterial(nullptr) {
0044   if (m_bounds == nullptr) {
0045     throw std::invalid_argument(
0046         "DetectorVolume: construction with nullptr bounds.");
0047   }
0048   if (!m_externalNavigation.connected()) {
0049     throw std::invalid_argument(
0050         "DetectorVolume: external navigation delegate is not connected.");
0051   }
0052   if (!m_internalNavigation.connected()) {
0053     throw std::invalid_argument(
0054         "DetectorVolume: internal navigaiton delegate is not connected.");
0055   }
0056 
0057   [[maybe_unused]] const auto& gctx_ref = gctx;
0058 }
0059 
0060 Acts::Experimental::DetectorVolume::DetectorVolume(
0061     const GeometryContext& gctx, std::string name, const Transform3& transform,
0062     std::shared_ptr<VolumeBounds> bounds,
0063     InternalNavigationDelegate internalNavigation)
0064     : DetectorVolume(gctx, std::move(name), transform, std::move(bounds), {},
0065                      {}, tryNoVolumes(), std::move(internalNavigation)) {}
0066 
0067 std::shared_ptr<Acts::Experimental::DetectorVolume>
0068 Acts::Experimental::DetectorVolume::makeShared(
0069     const GeometryContext& gctx, std::string name, const Transform3& transform,
0070     std::shared_ptr<VolumeBounds> bounds,
0071     std::vector<std::shared_ptr<Surface>> surfaces,
0072     std::vector<std::shared_ptr<DetectorVolume>> volumes,
0073     ExternalNavigationDelegate externalNavigation,
0074     InternalNavigationDelegate internalNavigation) {
0075   return std::shared_ptr<DetectorVolume>(new DetectorVolume(
0076       gctx, std::move(name), transform, std::move(bounds), std::move(surfaces),
0077       std::move(volumes), std::move(externalNavigation),
0078       std::move(internalNavigation)));
0079 }
0080 
0081 std::shared_ptr<Acts::Experimental::DetectorVolume>
0082 Acts::Experimental::DetectorVolume::makeShared(
0083     const GeometryContext& gctx, std::string name, const Transform3& transform,
0084     std::shared_ptr<VolumeBounds> bounds,
0085     InternalNavigationDelegate internalNavigation) {
0086   return std::shared_ptr<DetectorVolume>(
0087       new DetectorVolume(gctx, std::move(name), transform, std::move(bounds),
0088                          std::move(internalNavigation)));
0089 }
0090 
0091 const Acts::Transform3& Acts::Experimental::DetectorVolume::transform(
0092     const GeometryContext& /*gctx*/) const {
0093   return m_transform;
0094 }
0095 
0096 Acts::Vector3 Acts::Experimental::DetectorVolume::center(
0097     const GeometryContext& gctx) const {
0098   return transform(gctx).translation();
0099 }
0100 
0101 const Acts::VolumeBounds& Acts::Experimental::DetectorVolume::volumeBounds()
0102     const {
0103   return (*m_bounds.get());
0104 }
0105 
0106 std::vector<std::shared_ptr<Acts::Experimental::Portal>>&
0107 Acts::Experimental::DetectorVolume::portalPtrs() {
0108   return m_portals.internal;
0109 }
0110 
0111 std::vector<std::shared_ptr<Acts::Surface>>&
0112 Acts::Experimental::DetectorVolume::surfacePtrs() {
0113   return m_surfaces.internal;
0114 }
0115 
0116 std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>>&
0117 Acts::Experimental::DetectorVolume::volumePtrs() {
0118   return m_volumes.internal;
0119 }
0120 
0121 const std::vector<const Acts::Experimental::Portal*>&
0122 Acts::Experimental::DetectorVolume::portals() const {
0123   return m_portals.external;
0124 }
0125 
0126 const std::vector<const Acts::Surface*>&
0127 Acts::Experimental::DetectorVolume::surfaces() const {
0128   return m_surfaces.external;
0129 }
0130 
0131 const std::vector<const Acts::Experimental::DetectorVolume*>&
0132 Acts::Experimental::DetectorVolume::volumes() const {
0133   return m_volumes.external;
0134 }
0135 
0136 const Acts::Experimental::ExternalNavigationDelegate&
0137 Acts::Experimental::DetectorVolume::externalNavigation() const {
0138   return m_externalNavigation;
0139 }
0140 
0141 const Acts::Experimental::InternalNavigationDelegate&
0142 Acts::Experimental::DetectorVolume::internalNavigation() const {
0143   return m_internalNavigation;
0144 }
0145 
0146 void Acts::Experimental::DetectorVolume::assignVolumeMaterial(
0147     std::shared_ptr<const IVolumeMaterial> material) {
0148   m_volumeMaterial = std::move(material);
0149 }
0150 
0151 const Acts::IVolumeMaterial*
0152 Acts::Experimental::DetectorVolume::volumeMaterial() const {
0153   return m_volumeMaterial.get();
0154 }
0155 
0156 const Acts::GeometryIdentifier& Acts::Experimental::DetectorVolume::geometryId()
0157     const {
0158   return m_geometryId;
0159 }
0160 
0161 void Acts::Experimental::DetectorVolume::assignGeometryId(
0162     const GeometryIdentifier& geoID) {
0163   m_geometryId = geoID;
0164 }
0165 
0166 const std::string& Acts::Experimental::DetectorVolume::name() const {
0167   return m_name;
0168 }
0169 
0170 void Acts::Experimental::DetectorVolume::assignDetector(
0171     const Detector& detector) {
0172   m_detector = &detector;
0173 
0174   for (auto& v : m_volumes.internal) {
0175     v->assignDetector(detector);
0176   }
0177 }
0178 
0179 const Acts::Experimental::Detector*
0180 Acts::Experimental::DetectorVolume::detector() const {
0181   return m_detector;
0182 }
0183 
0184 void Acts::Experimental::DetectorVolume::updatePortal(
0185     std::shared_ptr<Portal> portal, unsigned int pIndex) {
0186   if (pIndex >= m_portals.internal.size()) {
0187     throw std::invalid_argument(
0188         "DetectorVolume: trying to update a portal that does not exist.");
0189   }
0190   m_portals.internal[pIndex] = std::move(portal);
0191   m_portals = ObjectStore<std::shared_ptr<Portal>>(m_portals.internal);
0192 }
0193 
0194 void Acts::Experimental::DetectorVolume::construct(
0195     const GeometryContext& gctx, const PortalGenerator& portalGenerator) {
0196   // Create portals with the given generator
0197   auto portalSurfaces =
0198       portalGenerator(transform(gctx), *(m_bounds.get()), getSharedPtr());
0199   m_portals = ObjectStore<std::shared_ptr<Portal>>(portalSurfaces);
0200   createBoundingBox(gctx);
0201 }
0202 
0203 std::shared_ptr<Acts::Experimental::DetectorVolume>
0204 Acts::Experimental::DetectorVolume::getSharedPtr() {
0205   return shared_from_this();
0206 }
0207 
0208 std::shared_ptr<const Acts::Experimental::DetectorVolume>
0209 Acts::Experimental::DetectorVolume::getSharedPtr() const {
0210   return shared_from_this();
0211 }
0212 
0213 bool Acts::Experimental::DetectorVolume::inside(const GeometryContext& gctx,
0214                                                 const Vector3& position) const {
0215   Vector3 posInVolFrame(transform(gctx).inverse() * position);
0216   return volumeBounds().inside(posInVolFrame);
0217 }
0218 
0219 bool Acts::Experimental::DetectorVolume::exclusivelyInside(
0220     const GeometryContext& gctx, const Vector3& position) const {
0221   if (!inside(gctx, position)) {
0222     return false;
0223   }
0224   // Check exclusion through subvolume
0225   for (const auto& v : volumes()) {
0226     if (v->inside(gctx, position)) {
0227       return false;
0228     }
0229   }
0230   return true;
0231 }
0232 
0233 void Acts::Experimental::DetectorVolume::updateNavigationState(
0234     const GeometryContext& gctx, NavigationState& nState) const {
0235   nState.currentVolume = this;
0236   m_internalNavigation(gctx, nState);
0237   nState.surfaceCandidateIndex = 0;
0238 }
0239 
0240 void Acts::Experimental::DetectorVolume::assignInternalNavigation(
0241     InternalNavigationDelegate internalNavigation,
0242     const std::vector<std::shared_ptr<Surface>>& surfaces,
0243     const std::vector<std::shared_ptr<DetectorVolume>>& volumes) {
0244   m_internalNavigation = std::move(internalNavigation);
0245   m_surfaces = ObjectStore<std::shared_ptr<Surface>>(surfaces);
0246   m_volumes = ObjectStore<std::shared_ptr<DetectorVolume>>(volumes);
0247 }
0248 
0249 Acts::Extent Acts::Experimental::DetectorVolume::extent(
0250     const GeometryContext& gctx, std::size_t nseg) const {
0251   Extent volumeExtent;
0252   for (const auto* p : portals()) {
0253     volumeExtent.extend(
0254         p->surface().polyhedronRepresentation(gctx, nseg).extent());
0255   }
0256   return volumeExtent;
0257 }
0258 
0259 bool Acts::Experimental::DetectorVolume::checkContainment(
0260     const GeometryContext& gctx, std::size_t nseg) const {
0261   // We don't have a logging instance here
0262   // so can't throw a warning for shapes that are
0263   // using the bounding box
0264   auto binningValues = volumeBounds().canonicalAxes();
0265 
0266   // Create the volume extent
0267   auto volumeExtent = extent(gctx, nseg);
0268   // Check surfaces
0269   for (auto b : binningValues) {
0270     for (const auto* s : surfaces()) {
0271       auto sExtent = s->polyhedronRepresentation(gctx, nseg).extent();
0272       if (!volumeExtent.contains(sExtent, b)) {
0273         return false;
0274       }
0275     }
0276     // Check volumes
0277     for (const auto* v : volumes()) {
0278       auto vExtent = v->extent(gctx, nseg);
0279       if (!volumeExtent.contains(vExtent, b)) {
0280         return false;
0281       }
0282     }
0283   }
0284   // All contained
0285   return true;
0286 }
0287 
0288 void Acts::Experimental::DetectorVolume::closePortals() {
0289   for (auto& p : m_portals.internal) {
0290     // Create a null link
0291     for (auto [ivu, vu] : enumerate(p->portalNavigation())) {
0292       if (!vu.connected()) {
0293         auto eowDir = Direction::fromIndex(ivu);
0294         auto eow = std::make_unique<const EndOfWorld>();
0295         Acts::Experimental::ExternalNavigationDelegate eowLink;
0296         eowLink.connect<&EndOfWorld::update>(std::move(eow));
0297         p->assignPortalNavigation(eowDir, std::move(eowLink), {});
0298       }
0299     }
0300   }
0301 
0302   for (auto& v : m_volumes.internal) {
0303     v->closePortals();
0304   }
0305 }
0306 
0307 void Acts::Experimental::DetectorVolume::createBoundingBox(
0308     const GeometryContext& gctx) {
0309   std::vector<Vector3> vertices;
0310   for (auto p : m_portals.external) {
0311     auto surface = p->surface().polyhedronRepresentation(gctx, 1);
0312     auto pVertices = surface.vertices;
0313     for (const auto& v : pVertices) {
0314       vertices.push_back(v);
0315     }
0316   }
0317   Acts::Vector3 vmin = Acts::Vector3::Zero();
0318   Acts::Vector3 vmax = Acts::Vector3::Zero();
0319   for (const auto& v : vertices) {
0320     vmin = vmin.cwiseMin(v);
0321     vmax = vmax.cwiseMax(v);
0322   }
0323   std::shared_ptr<Acts::Experimental::DetectorVolume::BoundingBox> box =
0324       std::make_shared<Acts::Experimental::DetectorVolume::BoundingBox>(
0325           this, vmin, vmax);
0326   m_boundingBox = box;
0327 }
0328 
0329 const Acts::Experimental::DetectorVolume::BoundingBox&
0330 Acts::Experimental::DetectorVolume::getBoundingBox() const {
0331   return *m_boundingBox;
0332 }