Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylindricalContainerBuilderTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylindricalContainerBuilderTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 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 
9 #include <boost/test/unit_test.hpp>
10 
31 
32 #include <any>
33 #include <cmath>
34 #include <iterator>
35 #include <memory>
36 #include <stdexcept>
37 #include <string>
38 #include <utility>
39 #include <vector>
40 
41 using namespace Acts;
42 using namespace Acts::Experimental;
43 
45 
49 template <typename surface_type, typename surface_bounds_type>
51  public:
53  const CylinderVolumeBounds& vBounds,
54  const surface_bounds_type& sBounds,
55  const std::string& vName)
57  m_transform(transform),
58  m_volumeBounds(vBounds),
59  m_surfaceBounds(sBounds),
60  m_name(vName) {}
61 
62  DetectorComponent construct(
63  [[maybe_unused]] const GeometryContext& gctx) const final {
64  // The outgoing root volumes
65  std::vector<std::shared_ptr<DetectorVolume>> rootVolumes;
66 
67  // Ingredients
68  auto surface = Surface::makeShared<surface_type>(
69  (m_transform), std::make_shared<surface_bounds_type>(m_surfaceBounds));
70 
71  auto bounds = std::make_unique<CylinderVolumeBounds>(m_volumeBounds);
73  auto volume = DetectorVolumeFactory::construct(
74  portalGenerator, tContext, m_name, m_transform, std::move(bounds),
76 
77  // Add to the roots
78  rootVolumes.push_back(volume);
79 
81  for (auto [ip, p] : enumerate(volume->portalPtrs())) {
82  dContainer[ip] = p;
83  }
84  return DetectorComponent{
85  {volume},
86  dContainer,
87  RootDetectorVolumes{rootVolumes, tryRootVolumes()}};
88  }
89 
90  private:
93  surface_bounds_type m_surfaceBounds;
95 };
96 
98  public:
99  struct Cache {
100  unsigned int volumeCount = 0;
101  };
102 
104  return Cache{0};
105  }
106 
107  void assignGeometryId(IGeometryIdGenerator::GeoIdCache& cache,
108  DetectorVolume& dVolume) const final {
109  auto& ccache = std::any_cast<Cache&>(cache);
110  ccache.volumeCount += 1;
112  geoID.setVolume(ccache.volumeCount);
113  dVolume.assignGeometryId(geoID);
114  }
115 
116  void assignGeometryId(
118  Acts::Experimental::Portal& /*portal*/) const final {}
119 
120  void assignGeometryId(
122  Acts::Surface& /*surface*/) const final {}
123 };
124 
125 BOOST_AUTO_TEST_SUITE(Detector)
126 
127 BOOST_AUTO_TEST_CASE(CylindricaContainerBuilder_Misconfiguration) {
128  // misconfiruation: no builders
130  BOOST_CHECK_THROW(auto a = CylindricalContainerBuilder(misCfg),
131  std::invalid_argument);
132  // misconfiguration - 1D binning not in z, r, phi
133  misCfg.builders = {nullptr};
134  misCfg.binning = {Acts::binX};
135  BOOST_CHECK_THROW(auto b = CylindricalContainerBuilder(misCfg),
136  std::invalid_argument);
137 
138  // misconfiguration - 2D binning not in z, r,
139  misCfg.builders = {nullptr, nullptr};
140  misCfg.binning = {Acts::binZ, Acts::binPhi};
141  BOOST_CHECK_THROW(auto c = CylindricalContainerBuilder(misCfg),
142  std::invalid_argument);
143 
144  // misconfiguration - 2D binning in z, r, but not exactly 2 builders
145  misCfg.builders = {nullptr, nullptr, nullptr};
146  misCfg.binning = {Acts::binZ, Acts::binR};
147  BOOST_CHECK_THROW(auto d = CylindricalContainerBuilder(misCfg),
148  std::invalid_argument);
149 }
150 
151 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingZ) {
152  // Declare a negative disc builder
153  Transform3 negZ = Transform3::Identity();
154  negZ.pretranslate(Vector3(0., 0., -300.));
155  auto negDisc =
156  std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
157  negZ, CylinderVolumeBounds(50., 200., 100.), RadialBounds(60., 190.),
158  "NegativeDisc");
159 
160  // Declare a barrel builder
161  auto barrel = std::make_shared<
163  Transform3::Identity(), CylinderVolumeBounds(50., 200., 200.),
164  CylinderBounds(80., 190.), "Barrel");
165  // Declare a positive disc builder
166  Transform3 posZ = Transform3::Identity();
167  posZ.pretranslate(Vector3(0., 0., 300.));
168  auto posDisc =
169  std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
170  posZ, CylinderVolumeBounds(50., 200., 100.), RadialBounds(60., 190.),
171  "PositiveDisc");
172 
173  // Create the container builder
175  tripleZCfg.auxiliary = "*** Test 0 - Build triple in Z ***";
176  tripleZCfg.builders = {negDisc, barrel, posDisc};
177  tripleZCfg.binning = {binZ};
178  tripleZCfg.geoIdGenerator = std::make_shared<VolumeGeoIdGenerator>();
179  // Let's test the reverse generation
180  tripleZCfg.geoIdReverseGen = true;
181 
182  auto tripleZ = std::make_shared<CylindricalContainerBuilder>(
183  tripleZCfg, getDefaultLogger("TripleBuilderZ", Logging::VERBOSE));
184 
185  auto [volumes, portals, roots] = tripleZ->construct(tContext);
186 
187  BOOST_CHECK(portals.size() == 4u);
188  BOOST_CHECK(roots.volumes.size() == 3u);
189  BOOST_CHECK(roots.volumes[0]->geometryId().volume() == 3u);
190  BOOST_CHECK(roots.volumes[1]->geometryId().volume() == 2u);
191  BOOST_CHECK(roots.volumes[2]->geometryId().volume() == 1u);
192 }
193 
194 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingR) {
195  // Declare a barrel builder
196  auto barrel0 = std::make_shared<
198  Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
199  CylinderBounds(65., 190.), "Barrel0");
200 
201  // Declare a barrel builder
202  auto barrel1 = std::make_shared<
204  Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
205  CylinderBounds(95., 190.), "Barrel1");
206 
207  // Declare a barrel builder
208  auto barrel2 = std::make_shared<
210  Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
211  CylinderBounds(125., 190.), "Barrel2");
212 
213  // Create the container builder
215  barrelRCfg.auxiliary = "*** Test 1 - Build multilayer barrel ***";
216  barrelRCfg.builders = {barrel0, barrel1, barrel2};
217  barrelRCfg.binning = {binR};
218  barrelRCfg.geoIdGenerator = std::make_shared<VolumeGeoIdGenerator>();
219 
220  auto barrelR = std::make_shared<CylindricalContainerBuilder>(
221  barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::VERBOSE));
222 
223  auto [volumes, portals, roots] = barrelR->construct(tContext);
224 
225  BOOST_CHECK(portals.size() == 4u);
226  BOOST_CHECK(roots.volumes.size() == 3u);
227  BOOST_CHECK(roots.volumes[0]->geometryId().volume() == 1u);
228  BOOST_CHECK(roots.volumes[1]->geometryId().volume() == 2u);
229  BOOST_CHECK(roots.volumes[2]->geometryId().volume() == 3u);
230 }
231 
232 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingPhi) {
233  // Create the container builder
235  barrelPhiCfg.auxiliary = "*** Test 2 - Build segmented phi barrel ***";
236  barrelPhiCfg.binning = {binPhi};
237 
238  unsigned int phiSectors = 5;
239  Acts::ActsScalar phiHalfSector = M_PI / phiSectors;
240 
241  std::vector<std::shared_ptr<DetectorVolume>> phiVolumes = {};
242  for (unsigned int i = 0; i < phiSectors; ++i) {
243  // The volume bounds
244  Acts::CylinderVolumeBounds volumeBounds(
245  10., 100., 100., phiHalfSector, -M_PI + (2u * i + 1u) * phiHalfSector);
246  // The surface boudns
247  Acts::CylinderBounds surfaceBounds(50., 90., 0.99 * phiHalfSector,
248  -M_PI + (2u * i + 1u) * phiHalfSector);
249 
250  auto builder = std::make_shared<
252  Transform3::Identity(), volumeBounds, surfaceBounds,
253  std::string("Sector_") + std::to_string(i));
254  barrelPhiCfg.builders.push_back(builder);
255  }
256 
257  auto barrelPhi = std::make_shared<CylindricalContainerBuilder>(
258  barrelPhiCfg, getDefaultLogger("BarrelBuilderPhi", Logging::VERBOSE));
259 
260  auto [volumes, portals, roots] = barrelPhi->construct(tContext);
261 
262  BOOST_CHECK(portals.size() == 4u);
263  BOOST_CHECK(roots.volumes.size() == 5u);
264 }
265 
266 BOOST_AUTO_TEST_CASE(CylindricalContainerBuilderDetector) {
267  // Declare a barrel sub builder
268  auto beampipe = std::make_shared<
270  Transform3::Identity(), CylinderVolumeBounds(0., 50., 600.),
271  CylinderBounds(25., 590.), "BeamPipe");
272 
273  // Declare a negative disc builder
274  Transform3 negZ = Transform3::Identity();
275  negZ.pretranslate(Vector3(0., 0., -300.));
276  auto endcapN =
277  std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
278  negZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 130.),
279  "NegativeEndcap");
280 
281  // Declare a barrel sub builder
282  auto barrel0 = std::make_shared<
284  Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
285  CylinderBounds(65., 190.), "Barrel0");
286 
287  // Declare a barrel sub builder
288  auto barrel1 = std::make_shared<
290  Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
291  CylinderBounds(95., 190.), "Barrel1");
292 
293  // Declare a barrel sub builder
294  auto barrel2 = std::make_shared<
296  Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
297  CylinderBounds(125., 190.), "Barrel2");
298 
299  // Create the barrel container builder
301  barrelRCfg.builders = {barrel0, barrel1, barrel2};
302  barrelRCfg.binning = {binR};
303 
304  auto barrel = std::make_shared<CylindricalContainerBuilder>(
305  barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::VERBOSE));
306 
307  Transform3 posZ = Transform3::Identity();
308  posZ.pretranslate(Vector3(0., 0., 300.));
309  auto endcapP =
310  std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
311  posZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 130.),
312  "PositiveEndcap");
313 
314  // Create the barrel container builder
315  CylindricalContainerBuilder::Config barrelEndcapCfg;
316  barrelEndcapCfg.builders = {endcapN, barrel, endcapP};
317  barrelEndcapCfg.binning = {binZ};
318 
319  auto barrelEndcap = std::make_shared<CylindricalContainerBuilder>(
320  barrelEndcapCfg,
321  getDefaultLogger("BarrelEndcapBuilder", Logging::VERBOSE));
322 
323  // Create the barrel container builder
325  detectorCfg.builders = {beampipe, barrelEndcap};
326  detectorCfg.binning = {binR};
327 
328  auto detector = std::make_shared<CylindricalContainerBuilder>(
329  detectorCfg, getDefaultLogger("DetectorBuilder", Logging::VERBOSE));
330 
331  auto [volumes, portals, roots] = detector->construct(tContext);
332  BOOST_CHECK(portals.size() == 3u);
333  BOOST_CHECK(roots.volumes.size() == 6u);
334 }
335 
336 BOOST_AUTO_TEST_SUITE_END()