Back to home page

EIC code displayed by LXR

 
 

    


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

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/Layer.hpp"
0010 
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Definitions/Tolerance.hpp"
0013 #include "Acts/Material/IMaterialDecorator.hpp"
0014 #include "Acts/Propagator/Navigator.hpp"
0015 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0016 #include "Acts/Surfaces/Surface.hpp"
0017 #include "Acts/Utilities/Helpers.hpp"
0018 #include "Acts/Utilities/Intersection.hpp"
0019 
0020 #include <algorithm>
0021 #include <functional>
0022 #include <iterator>
0023 #include <vector>
0024 
0025 Acts::Layer::Layer(std::unique_ptr<SurfaceArray> surfaceArray, double thickness,
0026                    std::unique_ptr<ApproachDescriptor> ades, LayerType laytyp)
0027     : m_nextLayers(NextLayers(nullptr, nullptr)),
0028       m_surfaceArray(surfaceArray.release()),
0029       m_layerThickness(thickness),
0030       m_approachDescriptor(nullptr),
0031       m_representingVolume(nullptr),
0032       m_layerType(laytyp),
0033       m_ssRepresentingSurface(1) {
0034   if (ades) {
0035     ades->registerLayer(*this);
0036     m_approachDescriptor = std::move(ades);
0037     m_ssApproachSurfaces = 1;  // indicates existence
0038   }
0039   // indicates existence of sensitive surfaces
0040   if (m_surfaceArray) {
0041     m_ssSensitiveSurfaces = 1;
0042   }
0043 }
0044 
0045 const Acts::ApproachDescriptor* Acts::Layer::approachDescriptor() const {
0046   return m_approachDescriptor.get();
0047 }
0048 
0049 Acts::ApproachDescriptor* Acts::Layer::approachDescriptor() {
0050   return const_cast<ApproachDescriptor*>(m_approachDescriptor.get());
0051 }
0052 
0053 void Acts::Layer::closeGeometry(const IMaterialDecorator* materialDecorator,
0054                                 const GeometryIdentifier& layerID,
0055                                 const GeometryIdentifierHook& hook,
0056                                 const Logger& logger) {
0057   // set the volumeID of this
0058   assignGeometryId(layerID);
0059   // assign to the representing surface
0060   Surface* rSurface = const_cast<Surface*>(&surfaceRepresentation());
0061   if (materialDecorator != nullptr) {
0062     materialDecorator->decorate(*rSurface);
0063   }
0064   ACTS_DEBUG("layerID: " << layerID);
0065 
0066   rSurface->assignGeometryId(layerID);
0067 
0068   // also find out how the sub structure is defined
0069   if (surfaceRepresentation().surfaceMaterial() != nullptr) {
0070     m_ssRepresentingSurface = 2;
0071   }
0072   // loop over the approach surfaces
0073   if (m_approachDescriptor) {
0074     // indicates the existence of approach surfaces
0075     m_ssApproachSurfaces = 1;
0076     // loop through the approachSurfaces and assign unique GeomeryID
0077     GeometryIdentifier::Value iasurface = 0;
0078     for (auto& aSurface : m_approachDescriptor->containedSurfaces()) {
0079       auto asurfaceID = GeometryIdentifier(layerID).setApproach(++iasurface);
0080       auto mutableASurface = const_cast<Surface*>(aSurface);
0081       mutableASurface->assignGeometryId(asurfaceID);
0082       if (materialDecorator != nullptr) {
0083         materialDecorator->decorate(*mutableASurface);
0084       }
0085       // if any of the approach surfaces has material
0086       if (aSurface->surfaceMaterial() != nullptr) {
0087         m_ssApproachSurfaces = 2;
0088       }
0089     }
0090   }
0091   // check if you have sensitive surfaces
0092   if (m_surfaceArray) {
0093     // indicates the existence of sensitive surfaces
0094     m_ssSensitiveSurfaces = 1;
0095     // loop sensitive surfaces and assign unique GeometryIdentifier
0096     GeometryIdentifier::Value issurface = 0;
0097     for (auto& sSurface : m_surfaceArray->surfaces()) {
0098       auto ssurfaceID = GeometryIdentifier(layerID).setSensitive(++issurface);
0099       ssurfaceID = hook.decorateIdentifier(ssurfaceID, *sSurface);
0100       auto mutableSSurface = const_cast<Surface*>(sSurface);
0101       mutableSSurface->assignGeometryId(ssurfaceID);
0102       if (materialDecorator != nullptr) {
0103         materialDecorator->decorate(*mutableSSurface);
0104       }
0105       // if any of the sensitive surfaces has material
0106       if (sSurface->surfaceMaterial() != nullptr) {
0107         m_ssSensitiveSurfaces = 2;
0108       }
0109     }
0110   }
0111 }
0112 
0113 boost::container::small_vector<Acts::SurfaceIntersection, 10>
0114 Acts::Layer::compatibleSurfaces(
0115     const GeometryContext& gctx, const Vector3& position,
0116     const Vector3& direction, const NavigationOptions<Surface>& options) const {
0117   // the list of valid intersection
0118   boost::container::small_vector<SurfaceIntersection, 10> sIntersections;
0119 
0120   // fast exit - there is nothing to
0121   if (!m_surfaceArray || !m_approachDescriptor) {
0122     return sIntersections;
0123   }
0124 
0125   double nearLimit = options.nearLimit;
0126   double farLimit = options.farLimit;
0127 
0128   auto isUnique = [&](const SurfaceIntersection& b) {
0129     return std::ranges::none_of(sIntersections, [&b](const auto& a) {
0130       return a.object() == b.object() && a.index() == b.index();
0131     });
0132   };
0133 
0134   // lemma 0 : accept the surface
0135   auto acceptSurface = [&options](const Surface& sf,
0136                                   bool sensitive = false) -> bool {
0137     // surface is sensitive and you're asked to resolve
0138     if (sensitive && options.resolveSensitive) {
0139       return true;
0140     }
0141     // next option: it's a material surface, and you want to have it
0142     if (options.resolveMaterial && sf.surfaceMaterial() != nullptr) {
0143       return true;
0144     }
0145     // last option: resolve all
0146     return options.resolvePassive;
0147   };
0148 
0149   // lemma 1 : check and fill the surface
0150   // [&sIntersections, &options, &parameters
0151   auto processSurface = [&](const Surface& sf, bool sensitive = false) {
0152     // veto if it's start surface
0153     if (options.startObject == &sf) {
0154       return;
0155     }
0156     // veto if it doesn't fit the prescription
0157     if (!acceptSurface(sf, sensitive)) {
0158       return;
0159     }
0160     BoundaryTolerance boundaryTolerance = options.boundaryTolerance;
0161     if (rangeContainsValue(options.externalSurfaces, sf.geometryId())) {
0162       boundaryTolerance = BoundaryTolerance::Infinite();
0163     }
0164     // the surface intersection
0165     SurfaceIntersection sfi =
0166         sf.intersect(gctx, position, direction, boundaryTolerance).closest();
0167     if (sfi.isValid() &&
0168         detail::checkPathLength(sfi.pathLength(), nearLimit, farLimit) &&
0169         isUnique(sfi)) {
0170       sIntersections.push_back(sfi);
0171     }
0172   };
0173 
0174   // (A) approach descriptor section
0175   //
0176   // the approach surfaces are in principle always testSurfaces
0177   // - the surface on approach is excluded via the veto
0178   // - the surfaces are only collected if needed
0179   if (m_approachDescriptor &&
0180       (options.resolveMaterial || options.resolvePassive)) {
0181     // the approach surfaces
0182     const std::vector<const Surface*>& approachSurfaces =
0183         m_approachDescriptor->containedSurfaces();
0184     // we loop through and veto
0185     // - if the approach surface is the parameter surface
0186     // - if the surface is not compatible with the collect
0187     for (auto& aSurface : approachSurfaces) {
0188       processSurface(*aSurface);
0189     }
0190   }
0191 
0192   // (B) sensitive surface section
0193   //
0194   // check the sensitive surfaces if you have some
0195   if (m_surfaceArray && (options.resolveMaterial || options.resolvePassive ||
0196                          options.resolveSensitive)) {
0197     // get the candidates
0198     const std::vector<const Surface*>& sensitiveSurfaces =
0199         m_surfaceArray->neighbors(position);
0200     // loop through and veto
0201     // - if the approach surface is the parameter surface
0202     // - if the surface is not compatible with the type(s) that are collected
0203     for (auto& sSurface : sensitiveSurfaces) {
0204       processSurface(*sSurface, true);
0205     }
0206   }
0207 
0208   // (C) representing surface section
0209   //
0210   // the layer surface itself is a testSurface
0211   const Surface* layerSurface = &surfaceRepresentation();
0212   processSurface(*layerSurface);
0213 
0214   return sIntersections;
0215 }
0216 
0217 Acts::SurfaceIntersection Acts::Layer::surfaceOnApproach(
0218     const GeometryContext& gctx, const Vector3& position,
0219     const Vector3& direction, const NavigationOptions<Layer>& options) const {
0220   // resolve directive based by options
0221   // - options.resolvePassive is on -> always
0222   // - options.resolveSensitive is on -> always
0223   // - options.resolveMaterial is on
0224   //   && either sensitive or approach surfaces have material
0225   bool resolvePS = options.resolveSensitive || options.resolvePassive;
0226   bool resolveMS = options.resolveMaterial &&
0227                    (m_ssSensitiveSurfaces > 1 || m_ssApproachSurfaces > 1 ||
0228                     (surfaceRepresentation().surfaceMaterial() != nullptr));
0229 
0230   // The Limits
0231   double nearLimit = options.nearLimit;
0232   double farLimit = options.farLimit;
0233 
0234   // Helper function to find valid intersection
0235   auto findValidIntersection =
0236       [&](const SurfaceMultiIntersection& sfmi) -> SurfaceIntersection {
0237     for (const auto& sfi : sfmi.split()) {
0238       if (sfi.isValid() &&
0239           detail::checkPathLength(sfi.pathLength(), nearLimit, farLimit)) {
0240         return sfi;
0241       }
0242     }
0243 
0244     // Return an invalid one
0245     return SurfaceIntersection::invalid();
0246   };
0247 
0248   // Approach descriptor present and resolving is necessary
0249   if (m_approachDescriptor && (resolvePS || resolveMS)) {
0250     SurfaceIntersection aSurface = m_approachDescriptor->approachSurface(
0251         gctx, position, direction, options.boundaryTolerance, nearLimit,
0252         farLimit);
0253     return aSurface;
0254   }
0255 
0256   // Intersect and check the representing surface
0257   const Surface& rSurface = surfaceRepresentation();
0258   auto sIntersection =
0259       rSurface.intersect(gctx, position, direction, options.boundaryTolerance);
0260   return findValidIntersection(sIntersection);
0261 }