Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:34

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2022-2023 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 http://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 Portal::DetectorVolumeUpdaters& Portal::detectorVolumeUpdaters() const {
0037   return m_volumeUpdaters;
0038 }
0039 
0040 Portal::AttachedDetectorVolumes& Portal::attachedDetectorVolumes() {
0041   return m_attachedVolumes;
0042 }
0043 
0044 void Portal::assignGeometryId(const GeometryIdentifier& geometryId) {
0045   m_surface->assignGeometryId(geometryId);
0046 }
0047 
0048 std::shared_ptr<Portal> Portal::fuse(std::shared_ptr<Portal>& aPortal,
0049                                      std::shared_ptr<Portal>& bPortal) {
0050   if (aPortal == bPortal) {
0051     return aPortal;
0052   }
0053 
0054   auto bothConnected = [](const auto& p) {
0055     return p.m_volumeUpdaters[0u].connected() &&
0056            p.m_volumeUpdaters[1u].connected();
0057   };
0058 
0059   auto noneConnected = [](const auto& p) {
0060     return !p.m_volumeUpdaters[0u].connected() &&
0061            !p.m_volumeUpdaters[1u].connected();
0062   };
0063 
0064   if (bothConnected(*aPortal) || bothConnected(*bPortal)) {
0065     throw std::invalid_argument(
0066         "Portal: trying to fuse two portals where at least one has links on "
0067         "both sides.");
0068   }
0069 
0070   if (noneConnected(*aPortal) || noneConnected(*bPortal)) {
0071     throw std::invalid_argument(
0072         "Portal: trying to fuse two portals where at least one has no links.");
0073   }
0074 
0075   // @TODO: There's no safety against fusing portals with different surfaces
0076   // We model the fused portal after the aPortal
0077   std::shared_ptr<Portal> fused = std::make_shared<Portal>(aPortal->m_surface);
0078 
0079   // Get the connection directions
0080   Direction getA = (aPortal->m_volumeUpdaters[0].connected())
0081                        ? Direction::fromIndex(0)
0082                        : Direction::fromIndex(1);
0083   Direction getB = (bPortal->m_volumeUpdaters[0].connected())
0084                        ? Direction::fromIndex(0)
0085                        : Direction::fromIndex(1);
0086 
0087   // Modelling the fused portal after the aPortal, leaves B as inverted
0088   Direction setA = getA;
0089   Direction setB = setA.invert();
0090 
0091   // Check if material is associated
0092   const auto& aSurface = aPortal->surface();
0093   const auto& bSurface = bPortal->surface();
0094 
0095   if (aSurface.surfaceMaterial() != nullptr &&
0096       bSurface.surfaceMaterial() != nullptr) {
0097     throw std::runtime_error(
0098         "Portal: both surfaces have surface material, fusing will lead to "
0099         "information loss.");
0100   } else if (aSurface.surfaceMaterial() != nullptr) {
0101     // We keep the aPortal modelling
0102     fused->m_surface = aPortal->m_surface;
0103   } else if (bSurface.surfaceMaterial() != nullptr) {
0104     fused->m_surface = bPortal->m_surface;
0105     // Remodel after the bPortal
0106     setB = getB;
0107     setA = setB.invert();
0108   }
0109 
0110   fused->m_volumeUpdaters[setA.index()] =
0111       std::move(aPortal->m_volumeUpdaters[getA.index()]);
0112   fused->m_attachedVolumes[setA.index()] =
0113       std::move(aPortal->m_attachedVolumes[getA.index()]);
0114 
0115   fused->m_volumeUpdaters[setB.index()] =
0116       std::move(bPortal->m_volumeUpdaters[getB.index()]);
0117   fused->m_attachedVolumes[setB.index()] =
0118       std::move(bPortal->m_attachedVolumes[getB.index()]);
0119 
0120   return fused;
0121 }
0122 
0123 void Portal::assignDetectorVolumeUpdater(
0124     Direction dir, DetectorVolumeUpdater dVolumeUpdater,
0125     std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0126   auto idx = dir.index();
0127   m_volumeUpdaters[idx] = std::move(dVolumeUpdater);
0128   m_attachedVolumes[idx] = std::move(attachedVolumes);
0129 }
0130 
0131 void Portal::assignDetectorVolumeUpdater(
0132     DetectorVolumeUpdater dVolumeUpdater,
0133     std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0134   // Check and throw exceptions
0135   if (!m_volumeUpdaters[0u].connected() && !m_volumeUpdaters[1u].connected()) {
0136     throw std::runtime_error("Portal: portal has no link on either side.");
0137   }
0138   if (m_volumeUpdaters[0u].connected() && m_volumeUpdaters[1u].connected()) {
0139     throw std::runtime_error("Portal: portal already has links on both sides.");
0140   }
0141   std::size_t idx = m_volumeUpdaters[0u].connected() ? 1u : 0u;
0142   m_volumeUpdaters[idx] = std::move(dVolumeUpdater);
0143   m_attachedVolumes[idx] = std::move(attachedVolumes);
0144 }
0145 
0146 void Portal::updateDetectorVolume(const GeometryContext& gctx,
0147                                   NavigationState& nState) const {
0148   const auto& position = nState.position;
0149   const auto& direction = nState.direction;
0150   const Vector3 normal = surface().normal(gctx, position);
0151   Direction dir = Direction::fromScalar(normal.dot(direction));
0152   const auto& vUpdater = m_volumeUpdaters[dir.index()];
0153   if (vUpdater.connected()) {
0154     vUpdater(gctx, nState);
0155   } else {
0156     nState.currentVolume = nullptr;
0157   }
0158 }
0159 
0160 }  // namespace Acts::Experimental