Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LayerStructureBuilder.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file LayerStructureBuilder.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
16 #include "Acts/Geometry/Extent.hpp"
25 
26 #include <cmath>
27 #include <cstddef>
28 #include <ostream>
29 #include <set>
30 #include <stdexcept>
31 #include <utility>
32 
33 namespace Acts {
34 namespace Experimental {
35 class DetectorVolume;
36 } // namespace Experimental
37 } // namespace Acts
38 
39 namespace {
40 
51 template <Acts::detail::AxisBoundaryType aType>
54  std::vector<std::shared_ptr<Acts::Surface>> lSurfaces,
55  std::vector<size_t> assignToAll,
56  const Acts::Experimental::ProtoBinning& binning) {
57  // The surface candidate updator & a generator for polyhedrons
60  // Indexed Surface generator for this case
62  decltype(lSurfaces), Acts::Experimental::IndexedSurfacesImpl>
63  isg{std::move(lSurfaces),
64  std::move(assignToAll),
65  {binning.binValue},
66  {binning.expansion}};
67  if (binning.axisType == Acts::detail::AxisType::Equidistant) {
68  // Equidistant
70  {binning.edges.front(), binning.edges.back()}, binning.bins()};
71  sfCandidates = isg(gctx, aGenerator, rGenerator);
72  } else {
73  // Variable
75  binning.edges};
76  sfCandidates = isg(gctx, aGenerator, rGenerator);
77  }
78  return sfCandidates;
79 }
80 
93 template <Acts::detail::AxisBoundaryType aType,
96  const Acts::GeometryContext& gctx,
97  const std::vector<std::shared_ptr<Acts::Surface>>& lSurfaces,
98  const std::vector<size_t>& assignToAll,
99  const Acts::Experimental::ProtoBinning& aBinning,
100  const Acts::Experimental::ProtoBinning& bBinning) {
101  // The surface candidate updator & a generator for polyhedrons
104  // Indexed Surface generator for this case
106  decltype(lSurfaces), Acts::Experimental::IndexedSurfacesImpl>
107  isg{lSurfaces,
108  assignToAll,
109  {aBinning.binValue, bBinning.binValue},
110  {aBinning.expansion, bBinning.expansion}};
111  // Run through the cases
112  if (aBinning.axisType == Acts::detail::AxisType::Equidistant and
113  bBinning.axisType == Acts::detail::AxisType::Equidistant) {
114  // Equidistant-Equidistant
116  aGenerator{{aBinning.edges.front(), aBinning.edges.back()},
117  aBinning.bins(),
118  {bBinning.edges.front(), bBinning.edges.back()},
119  bBinning.bins()};
120  sfCandidates = isg(gctx, aGenerator, rGenerator);
121  } else if (bBinning.axisType == Acts::detail::AxisType::Equidistant) {
122  // Variable-Equidistant
124  aGenerator{aBinning.edges,
125  {bBinning.edges.front(), bBinning.edges.back()},
126  bBinning.bins()};
127  sfCandidates = isg(gctx, aGenerator, rGenerator);
128  } else if (aBinning.axisType == Acts::detail::AxisType::Equidistant) {
129  // Equidistant-Variable
131  aGenerator{{aBinning.edges.front(), aBinning.edges.back()},
132  aBinning.bins(),
133  bBinning.edges};
134  sfCandidates = isg(gctx, aGenerator, rGenerator);
135  } else {
136  // Variable-Variable
138  aGenerator{aBinning.edges, bBinning.edges};
139  sfCandidates = isg(gctx, aGenerator, rGenerator);
140  }
141  // Return the candidates
142  return sfCandidates;
143 }
144 
145 } // namespace
146 
149  std::unique_ptr<const Acts::Logger> logger)
150  : IInternalStructureBuilder(), m_cfg(cfg), m_logger(std::move(logger)) {
151  if (m_cfg.surfacesProvider == nullptr) {
152  throw std::invalid_argument(
153  "LayerStructureBuilder: surfaces provider is nullptr.");
154  }
155 }
156 
159  const Acts::GeometryContext& gctx) const {
160  // Trivialities first: internal volumes
161  std::vector<std::shared_ptr<DetectorVolume>> internalVolumes = {};
162  DetectorVolumeUpdator internalVolumeUpdator = tryNoVolumes();
163 
164  // Print the auxiliary information
165  if (not m_cfg.auxiliary.empty()) {
166  ACTS_DEBUG(m_cfg.auxiliary);
167  }
168 
169  // Retrieve the layer surfaces
170  SurfaceCandidatesUpdator internalCandidatesUpdator =
172  auto internalSurfaces = m_cfg.surfacesProvider->surfaces(gctx);
173  ACTS_DEBUG("Building internal layer structure from "
174  << internalSurfaces.size() << " provided surfaces.");
175 
176  // Check whether support structure is scheduled to be built, and if so
177  // collect those that should be assigned to all bins
178  std::vector<size_t> assignToAll = {};
179  if (not m_cfg.supports.empty()) {
180  ACTS_DEBUG("Adding " << m_cfg.supports.size() << " support structures.")
181  // The surface candidate updator
182  for (const auto& support : m_cfg.supports) {
183  // Check if the supportsurface has already been built
184  if (support.surface != nullptr) {
185  ACTS_VERBOSE("- Use provided support surface directly.");
186  if (support.assignToAll) {
187  assignToAll.push_back(internalSurfaces.size());
188  ACTS_VERBOSE(" Support surface is assigned to all bins.");
189  }
190  internalSurfaces.push_back(support.surface);
191  continue;
192  }
193 
194  // Throw an exception is misconfigured
195  if (support.type == Surface::SurfaceType::Other) {
196  throw std::invalid_argument(
197  "LayerStructureBuilder: support surface type not specified.");
198  }
199  ACTS_VERBOSE("- Build support of type '"
200  << Acts::Surface::s_surfaceTypeNames[support.type] << "'.");
201  if (support.splits > 1u) {
202  ACTS_VERBOSE(" Support surface is modelled with " << support.splits
203  << " planes.");
204  }
205  // To correctly attach the support structures, estimate the extent
206  Extent internalExtent;
207  for (const auto& s : internalSurfaces) {
208  auto sPolyhedron = s->polyhedronRepresentation(gctx, m_cfg.nSegments);
209  internalExtent.extend(sPolyhedron.extent(), support.constraints);
210  }
211  // Use the support bulder helper to add support surfaces
213  internalSurfaces, assignToAll, internalExtent, support.type,
214  support.values, support.transform, support.splits);
215  }
216  }
217  if (m_cfg.binnings.empty()) {
218  ACTS_DEBUG(
219  "No surface binning provided, navigation will be 'tryAll' (potentially "
220  "slow).");
221  } else if (m_cfg.binnings.size() == 1u) {
222  ACTS_DEBUG("- 1-dimensional surface binning detected.");
223  // Capture the binning
224  auto binning = m_cfg.binnings[0u];
225  if (binning.boundaryType == Acts::detail::AxisBoundaryType::Closed) {
226  ACTS_VERBOSE("-- closed binning option.");
227  internalCandidatesUpdator =
228  createUpdator<Acts::detail::AxisBoundaryType::Closed>(
229  gctx, internalSurfaces, assignToAll, binning);
230  } else {
231  ACTS_VERBOSE("-- closed binning option.");
232  internalCandidatesUpdator =
233  createUpdator<Acts::detail::AxisBoundaryType::Bound>(
234  gctx, internalSurfaces, assignToAll, binning);
235  }
236  } else if (m_cfg.binnings.size() == 2u) {
237  ACTS_DEBUG("- 2-dimensional surface binning detected.");
238  // Capture the binnings
239  const auto& binning0 = m_cfg.binnings[0u];
240  const auto& binning1 = m_cfg.binnings[1u];
241 
242  if (binning0.boundaryType == Acts::detail::AxisBoundaryType::Closed) {
243  ACTS_VERBOSE("-- closed/bound binning option.");
244  internalCandidatesUpdator =
245  createUpdator<Acts::detail::AxisBoundaryType::Closed,
246  Acts::detail::AxisBoundaryType::Bound>(
247  gctx, internalSurfaces, assignToAll, binning0, binning1);
248  } else if (binning1.boundaryType ==
249  Acts::detail::AxisBoundaryType::Closed) {
250  ACTS_VERBOSE("-- bound/closed binning option.");
251  internalCandidatesUpdator =
252  createUpdator<Acts::detail::AxisBoundaryType::Bound,
253  Acts::detail::AxisBoundaryType::Closed>(
254  gctx, internalSurfaces, assignToAll, binning0, binning1);
255  } else {
256  ACTS_VERBOSE("-- closed/closed binning option.");
257  internalCandidatesUpdator =
258  createUpdator<Acts::detail::AxisBoundaryType::Bound,
259  Acts::detail::AxisBoundaryType::Bound>(
260  gctx, internalSurfaces, assignToAll, binning0, binning1);
261  }
262  }
263  // Check if everything went ok
264  if (not internalCandidatesUpdator.connected()) {
265  throw std::runtime_error(
266  "LayerStructureBuilder: could not connect surface candidate updator.");
267  }
268 
269  // Return the internal structure
270  return InternalStructure{internalSurfaces, internalVolumes,
271  std::move(internalCandidatesUpdator),
272  std::move(internalVolumeUpdator)};
273 }