ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CuboidVolumeBuilderTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CuboidVolumeBuilderTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018 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 
11 #include <vector>
12 
14 #include "Acts/Geometry/Layer.hpp"
28 #include "Acts/Utilities/Units.hpp"
29 
33 
34 using namespace Acts::UnitLiterals;
35 
36 namespace Acts {
37 namespace Test {
38 
43  struct this_result {
44  // Position of the propagator after each step
45  std::vector<Vector3D> position;
46  // Volume of the propagator after each step
47  std::vector<TrackingVolume const*> volume;
48  };
49 
51 
52  template <typename propagator_state_t, typename stepper_t>
53  void operator()(propagator_state_t& state, const stepper_t& stepper,
54  result_type& result) const {
55  result.position.push_back(stepper.position(state.stepping));
56  result.volume.push_back(state.navigation.currentVolume);
57  }
58 };
59 
60 BOOST_AUTO_TEST_CASE(CuboidVolumeBuilderTest) {
61  // Construct builder
63 
64  // Create a test context
66 
67  // Create configurations for surfaces
68  std::vector<CuboidVolumeBuilder::SurfaceConfig> surfaceConfig;
69  for (unsigned int i = 1; i < 5; i++) {
70  // Position of the surfaces
72  cfg.position = {i * UnitConstants::m, 0., 0.};
73 
74  // Rotation of the surfaces
75  double rotationAngle = M_PI * 0.5;
76  Vector3D xPos(cos(rotationAngle), 0., sin(rotationAngle));
77  Vector3D yPos(0., 1., 0.);
78  Vector3D zPos(-sin(rotationAngle), 0., cos(rotationAngle));
79  cfg.rotation.col(0) = xPos;
80  cfg.rotation.col(1) = yPos;
81  cfg.rotation.col(2) = zPos;
82 
83  // Boundaries of the surfaces
84  cfg.rBounds =
85  std::make_shared<const RectangleBounds>(RectangleBounds(0.5_m, 0.5_m));
86 
87  // Material of the surfaces
88  MaterialProperties matProp(makeBeryllium(), 0.5_mm);
89  cfg.surMat = std::make_shared<HomogeneousSurfaceMaterial>(matProp);
90 
91  // Thickness of the detector element
92  cfg.thickness = 1_um;
93 
95  [](std::shared_ptr<const Transform3D> trans,
96  std::shared_ptr<const RectangleBounds> bounds, double thickness) {
97  return new DetectorElementStub(trans, bounds, thickness);
98  };
99  surfaceConfig.push_back(cfg);
100  }
101 
102  // Test that there are actually 4 surface configurations
103  BOOST_CHECK_EQUAL(surfaceConfig.size(), 4u);
104 
105  // Test that 4 surfaces can be built
106  for (const auto& cfg : surfaceConfig) {
107  std::shared_ptr<const PlaneSurface> pSur = cvb.buildSurface(tgContext, cfg);
108  BOOST_CHECK_NE(pSur, nullptr);
109  CHECK_CLOSE_ABS(pSur->center(tgContext), cfg.position, 1e-9);
110  BOOST_CHECK_NE(pSur->surfaceMaterial(), nullptr);
111  BOOST_CHECK_NE(pSur->associatedDetectorElement(), nullptr);
112  }
113 
115  // Build layer configurations
116  std::vector<CuboidVolumeBuilder::LayerConfig> layerConfig;
117  for (auto& sCfg : surfaceConfig) {
119  cfg.surfaceCfg = sCfg;
120  layerConfig.push_back(cfg);
121  }
122 
123  // Test that there are actually 4 layer configurations
124  BOOST_CHECK_EQUAL(layerConfig.size(), 4u);
125 
126  // Test that 4 layers with surfaces can be built
127  for (auto& cfg : layerConfig) {
128  LayerPtr layer = cvb.buildLayer(tgContext, cfg);
129  BOOST_CHECK_NE(layer, nullptr);
130  BOOST_CHECK_NE(cfg.surface, nullptr);
131  BOOST_CHECK_EQUAL(layer->surfaceArray()->surfaces().size(), 1u);
132  BOOST_CHECK_EQUAL(layer->layerType(), LayerType::active);
133  }
134 
135  for (auto& cfg : layerConfig) {
136  cfg.surface = nullptr;
137  }
138 
139  // Build volume configuration
141  volumeConfig.position = {2.5_m, 0., 0.};
142  volumeConfig.length = {5_m, 1_m, 1_m};
143  volumeConfig.layerCfg = layerConfig;
144  volumeConfig.name = "Test volume";
145  volumeConfig.volumeMaterial =
146  std::make_shared<HomogeneousVolumeMaterial>(makeBeryllium());
147 
148  // Test the building
149  std::shared_ptr<TrackingVolume> trVol =
150  cvb.buildVolume(tgContext, volumeConfig);
151  BOOST_CHECK_EQUAL(volumeConfig.layers.size(), 4u);
152  BOOST_CHECK_EQUAL(trVol->confinedLayers()->arrayObjects().size(),
153  volumeConfig.layers.size() * 2 +
154  1u); // #layers = navigation + material layers
155  BOOST_CHECK_EQUAL(trVol->volumeName(), volumeConfig.name);
156  BOOST_CHECK_NE(trVol->volumeMaterial(), nullptr);
157 
158  // Test the building
159  volumeConfig.layers.clear();
160  trVol = cvb.buildVolume(tgContext, volumeConfig);
161  BOOST_CHECK_EQUAL(volumeConfig.layers.size(), 4u);
162  BOOST_CHECK_EQUAL(trVol->confinedLayers()->arrayObjects().size(),
163  volumeConfig.layers.size() * 2 +
164  1u); // #layers = navigation + material layers
165  BOOST_CHECK_EQUAL(trVol->volumeName(), volumeConfig.name);
166 
167  volumeConfig.layers.clear();
168  for (auto& lay : volumeConfig.layerCfg) {
169  lay.surface = nullptr;
170  lay.active = true;
171  }
172  trVol = cvb.buildVolume(tgContext, volumeConfig);
173  BOOST_CHECK_EQUAL(volumeConfig.layers.size(), 4u);
174  for (auto& lay : volumeConfig.layers) {
175  BOOST_CHECK_EQUAL(lay->layerType(), LayerType::active);
176  }
177 
178  volumeConfig.layers.clear();
179  for (auto& lay : volumeConfig.layerCfg) {
180  lay.active = true;
181  }
182  trVol = cvb.buildVolume(tgContext, volumeConfig);
183  BOOST_CHECK_EQUAL(volumeConfig.layers.size(), 4u);
184  for (auto& lay : volumeConfig.layers) {
185  BOOST_CHECK_EQUAL(lay->layerType(), LayerType::active);
186  }
187 
189  // Build TrackingGeometry configuration
190 
191  // Build second volume
192  std::vector<CuboidVolumeBuilder::SurfaceConfig> surfaceConfig2;
193  for (int i = 1; i < 5; i++) {
194  // Position of the surfaces
196  cfg.position = {-i * UnitConstants::m, 0., 0.};
197 
198  // Rotation of the surfaces
199  double rotationAngle = M_PI * 0.5;
200  Vector3D xPos(cos(rotationAngle), 0., sin(rotationAngle));
201  Vector3D yPos(0., 1., 0.);
202  Vector3D zPos(-sin(rotationAngle), 0., cos(rotationAngle));
203  cfg.rotation.col(0) = xPos;
204  cfg.rotation.col(1) = yPos;
205  cfg.rotation.col(2) = zPos;
206 
207  // Boundaries of the surfaces
208  cfg.rBounds =
209  std::make_shared<const RectangleBounds>(RectangleBounds(0.5_m, 0.5_m));
210 
211  // Material of the surfaces
212  MaterialProperties matProp(makeBeryllium(), 0.5_mm);
213  cfg.surMat = std::make_shared<HomogeneousSurfaceMaterial>(matProp);
214 
215  // Thickness of the detector element
216  cfg.thickness = 1_um;
217  surfaceConfig2.push_back(cfg);
218  }
219 
220  std::vector<CuboidVolumeBuilder::LayerConfig> layerConfig2;
221  for (auto& sCfg : surfaceConfig2) {
223  cfg.surfaceCfg = sCfg;
224  layerConfig2.push_back(cfg);
225  }
226  CuboidVolumeBuilder::VolumeConfig volumeConfig2;
227  volumeConfig2.position = {-2.5_m, 0., 0.};
228  volumeConfig2.length = {5_m, 1_m, 1_m};
229  volumeConfig2.layerCfg = layerConfig2;
230  volumeConfig2.name = "Test volume2";
231 
233  config.position = {0., 0., 0.};
234  config.length = {10_m, 1_m, 1_m};
235  config.volumeCfg = {volumeConfig2, volumeConfig};
236 
237  cvb.setConfig(config);
239  tgbCfg.trackingVolumeBuilders.push_back(
240  [=](const auto& context, const auto& inner, const auto&) {
241  return cvb.trackingVolume(context, inner, nullptr);
242  });
243  TrackingGeometryBuilder tgb(tgbCfg);
244 
245  std::unique_ptr<const TrackingGeometry> detector =
246  tgb.trackingGeometry(tgContext);
247  BOOST_CHECK_EQUAL(
248  detector->lowestTrackingVolume(tgContext, Vector3D(1., 0., 0.))
249  ->volumeName(),
250  volumeConfig.name);
251  BOOST_CHECK_EQUAL(
252  detector->lowestTrackingVolume(tgContext, Vector3D(-1., 0., 0.))
253  ->volumeName(),
254  volumeConfig2.name);
255 }
256 
257 /*
258 BOOST_AUTO_TEST_CASE(CuboidVolumeBuilderTest_confinedVolumes) {
259  // Production factory
260  CuboidVolumeBuilder cvb;
261 
262  // Create a test context
263  GeometryContext tgContext = GeometryContext();
264  MagneticFieldContext mfContext = MagneticFieldContext();
265 
266  // Build a volume that confines another volume
267  CuboidVolumeBuilder::VolumeConfig vCfg;
268  vCfg.position = {1. * units::_m, 0., 0.};
269  vCfg.length = {2. * units::_m, 1. * units::_m, 1. * units::_m};
270  vCfg.name = "Test volume";
271  // Build and add 2 confined volumes
272  CuboidVolumeBuilder::VolumeConfig cvCfg1;
273  cvCfg1.position = {1.1 * units::_m, 0., 0.};
274  cvCfg1.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm};
275  cvCfg1.name = "Confined volume1";
276  cvCfg1.volumeMaterial =
277  std::shared_ptr<const IVolumeMaterial>(new HomogeneousVolumeMaterial(
278  Material(352.8, 407., 9.012, 4., 1.848e-3)));
279  CuboidVolumeBuilder::VolumeConfig cvCfg2;
280  cvCfg2.position = {0.9 * units::_m, 0., 0.};
281  cvCfg2.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm};
282  cvCfg2.name = "Confined volume2";
283  vCfg.volumeCfg = {cvCfg1, cvCfg2};
284 
285  // Build detector
286  CuboidVolumeBuilder::Config config;
287  config.position = {1. * units::_m, 0., 0.};
288  config.length = {2. * units::_m, 1. * units::_m, 1. * units::_m};
289  config.volumeCfg = {vCfg};
290 
291  cvb.setConfig(config);
292  TrackingGeometryBuilder::Config tgbCfg;
293  tgbCfg.trackingVolumeBuilders.push_back(
294  [=](const auto& context, const auto& inner, const auto& vb) {
295  return cvb.trackingVolume(context, inner, vb);
296  });
297  TrackingGeometryBuilder tgb(tgbCfg);
298  std::shared_ptr<const TrackingGeometry> detector =
299  tgb.trackingGeometry(tgContext);
300 
301  // Test that the right volume is selected
302  BOOST_TEST(detector->lowestTrackingVolume(tgContext, {1. * units::_m, 0., 0.})
303  ->volumeName() == vCfg.name);
304  BOOST_TEST(
305  detector->lowestTrackingVolume(tgContext, {1.1 * units::_m, 0., 0.})
306  ->volumeName() == cvCfg1.name);
307  BOOST_TEST(
308  detector->lowestTrackingVolume(tgContext, {0.9 * units::_m, 0., 0.})
309  ->volumeName() == cvCfg2.name);
310 
311  // Set propagator and navigator
312  PropagatorOptions<ActionList<StepVolumeCollector>> propOpts(tgContext,
313  mfContext);
314  propOpts.maxStepSize = 10. * units::_mm;
315  StraightLineStepper sls;
316  Navigator navi(detector);
317  navi.resolvePassive = true;
318  navi.resolveMaterial = true;
319  navi.resolveSensitive = true;
320 
321  Propagator<StraightLineStepper, Navigator> prop(sls, navi);
322 
323  // Set initial parameters for the particle track
324  Vector3D startParams(0., 0., 0.), startMom(1. * units::_GeV, 0., 0.);
325  SingleCurvilinearTrackParameters<ChargedPolicy> sbtp(
326  std::nullopt, startParams, startMom, 1., 0.);
327 
328  // Launch and collect results
329  const auto& result = prop.propagate(sbtp, propOpts).value();
330  const StepVolumeCollector::this_result& stepResult =
331  result.get<typename StepVolumeCollector::result_type>();
332 
333  // Check the identified volumes
334  for (unsigned int i = 0; i < stepResult.position.size(); i++) {
335  if (i > 0) {
336  BOOST_TEST(stepResult.position[i].x() > 0.);
337  }
338  if (stepResult.position[i].x() >= 0.85 * units::_m &&
339  stepResult.position[i].x() < 0.95 * units::_m) {
340  BOOST_TEST(stepResult.volume[i]->volumeName() == cvCfg2.name);
341  BOOST_TEST(stepResult.volume[i]->volumeMaterial() == nullptr);
342  } else {
343  if (stepResult.position[i].x() >= 1.05 * units::_m &&
344  stepResult.position[i].x() < 1.15 * units::_m) {
345  BOOST_TEST(stepResult.volume[i]->volumeName() == cvCfg1.name);
346  BOOST_TEST(stepResult.volume[i]->volumeMaterial() != nullptr);
347  } else {
348  if (stepResult.position[i].x() < 2. * units::_m) {
349  BOOST_TEST(stepResult.volume[i]->volumeName() == vCfg.name);
350  BOOST_TEST(stepResult.volume[i]->volumeMaterial() == nullptr);
351  }
352  }
353  }
354  }
355 }
356 */
483 } // namespace Test
484 } // namespace Acts