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