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/Portal.hpp"
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Navigation/NavigationState.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 #include "Acts/Utilities/Delegate.hpp"
0015 #include "Acts/Utilities/ThrowAssert.hpp"
0016 
0017 #include <cstddef>
0018 #include <stdexcept>
0019 #include <utility>
0020 
0021 namespace Acts::Experimental {
0022 
0023 Portal::Portal(std::shared_ptr<RegularSurface> surface)
0024     : m_surface(std::move(surface)) {
0025   throw_assert(m_surface, "Portal surface is nullptr");
0026 }
0027 
0028 const Acts::RegularSurface& Portal::surface() const {
0029   return *m_surface.get();
0030 }
0031 
0032 Acts::RegularSurface& Portal::surface() {
0033   return *m_surface.get();
0034 }
0035 
0036 const std::array<Acts::Experimental::ExternalNavigationDelegate, 2u>&
0037 Portal::portalNavigation() const {
0038   return m_portalNavigation;
0039 }
0040 
0041 Portal::AttachedDetectorVolumes& Portal::attachedDetectorVolumes() {
0042   return m_attachedVolumes;
0043 }
0044 
0045 void Portal::assignGeometryId(const GeometryIdentifier& geometryId) {
0046   m_surface->assignGeometryId(geometryId);
0047 }
0048 
0049 std::shared_ptr<Portal> Portal::fuse(std::shared_ptr<Portal>& aPortal,
0050                                      std::shared_ptr<Portal>& bPortal) {
0051   if (aPortal == bPortal) {
0052     return aPortal;
0053   }
0054 
0055   auto bothConnected = [](const auto& p) {
0056     return p.m_portalNavigation[0u].connected() &&
0057            p.m_portalNavigation[1u].connected();
0058   };
0059 
0060   auto noneConnected = [](const auto& p) {
0061     return !p.m_portalNavigation[0u].connected() &&
0062            !p.m_portalNavigation[1u].connected();
0063   };
0064 
0065   if (bothConnected(*aPortal) || bothConnected(*bPortal)) {
0066     throw std::invalid_argument(
0067         "Portal: trying to fuse two portals where at least one has links on "
0068         "both sides.");
0069   }
0070 
0071   if (noneConnected(*aPortal) || noneConnected(*bPortal)) {
0072     throw std::invalid_argument(
0073         "Portal: trying to fuse two portals where at least one has no links.");
0074   }
0075 
0076   // @TODO: There's no safety against fusing portals with different surfaces
0077   // We model the fused portal after the aPortal
0078   std::shared_ptr<Portal> fused = std::make_shared<Portal>(aPortal->m_surface);
0079 
0080   // Get the connection directions
0081   Direction getA = (aPortal->m_portalNavigation[0].connected())
0082                        ? Direction::fromIndex(0)
0083                        : Direction::fromIndex(1);
0084   Direction getB = (bPortal->m_portalNavigation[0].connected())
0085                        ? Direction::fromIndex(0)
0086                        : Direction::fromIndex(1);
0087 
0088   // Modelling the fused portal after the aPortal, leaves B as inverted
0089   Direction setA = getA;
0090   Direction setB = setA.invert();
0091 
0092   // Check if material is associated
0093   const auto& aSurface = aPortal->surface();
0094   const auto& bSurface = bPortal->surface();
0095 
0096   if (aSurface.surfaceMaterial() != nullptr &&
0097       bSurface.surfaceMaterial() != nullptr) {
0098     throw std::runtime_error(
0099         "Portal: both surfaces have surface material, fusing will lead to "
0100         "information loss.");
0101   } else if (aSurface.surfaceMaterial() != nullptr) {
0102     // We keep the aPortal modelling
0103     fused->m_surface = aPortal->m_surface;
0104   } else if (bSurface.surfaceMaterial() != nullptr) {
0105     fused->m_surface = bPortal->m_surface;
0106     // Remodel after the bPortal
0107     setB = getB;
0108     setA = setB.invert();
0109   }
0110 
0111   fused->m_portalNavigation[setA.index()] =
0112       std::move(aPortal->m_portalNavigation[getA.index()]);
0113   fused->m_attachedVolumes[setA.index()] =
0114       std::move(aPortal->m_attachedVolumes[getA.index()]);
0115 
0116   fused->m_portalNavigation[setB.index()] =
0117       std::move(bPortal->m_portalNavigation[getB.index()]);
0118   fused->m_attachedVolumes[setB.index()] =
0119       std::move(bPortal->m_attachedVolumes[getB.index()]);
0120 
0121   return fused;
0122 }
0123 
0124 void Portal::assignPortalNavigation(
0125     Direction dir, ExternalNavigationDelegate portalNavigation,
0126     std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0127   auto idx = dir.index();
0128   m_portalNavigation[idx] = std::move(portalNavigation);
0129   m_attachedVolumes[idx] = std::move(attachedVolumes);
0130 }
0131 
0132 void Portal::assignPortalNavigation(
0133     ExternalNavigationDelegate portalNavigation,
0134     std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0135   // Check and throw exceptions
0136   if (!m_portalNavigation[0u].connected() &&
0137       !m_portalNavigation[1u].connected()) {
0138     throw std::runtime_error("Portal: portal has no link on either side.");
0139   }
0140   if (m_portalNavigation[0u].connected() &&
0141       m_portalNavigation[1u].connected()) {
0142     throw std::runtime_error("Portal: portal already has links on both sides.");
0143   }
0144   std::size_t idx = m_portalNavigation[0u].connected() ? 1u : 0u;
0145   m_portalNavigation[idx] = std::move(portalNavigation);
0146   m_attachedVolumes[idx] = std::move(attachedVolumes);
0147 }
0148 
0149 void Portal::updateDetectorVolume(const GeometryContext& gctx,
0150                                   NavigationState& nState) const {
0151   const auto& position = nState.position;
0152   const auto& direction = nState.direction;
0153   const Vector3 normal = surface().normal(gctx, position);
0154   Direction dir = Direction::fromScalar(normal.dot(direction));
0155   const auto& vUpdater = m_portalNavigation[dir.index()];
0156   if (vUpdater.connected()) {
0157     vUpdater(gctx, nState);
0158   } else {
0159     nState.currentVolume = nullptr;
0160   }
0161 }
0162 
0163 }  // namespace Acts::Experimental