Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VolumeMaterialMapperTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file VolumeMaterialMapperTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 
41 
42 #include <functional>
43 #include <map>
44 #include <memory>
45 #include <random>
46 #include <string>
47 #include <tuple>
48 #include <utility>
49 #include <vector>
50 
51 namespace Acts {
52 
54 struct MaterialCollector {
55  struct this_result {
56  std::vector<Material> matTrue;
57  std::vector<Vector3> position;
58  };
60 
61  template <typename propagator_state_t, typename stepper_t,
62  typename navigator_t>
63  void operator()(propagator_state_t& state, const stepper_t& stepper,
64  const navigator_t& navigator, result_type& result,
65  const Logger& /*logger*/) const {
66  if (navigator.currentVolume(state.navigation) != nullptr) {
67  auto position = stepper.position(state.stepping);
68  result.matTrue.push_back(
69  (navigator.currentVolume(state.navigation)->volumeMaterial() !=
70  nullptr)
71  ? navigator.currentVolume(state.navigation)
72  ->volumeMaterial()
73  ->material(position)
74  : Material());
75 
76  result.position.push_back(position);
77  }
78  }
79 };
80 
81 namespace Test {
82 
84 BOOST_AUTO_TEST_CASE(SurfaceMaterialMapper_tests) {
85  using namespace Acts::UnitLiterals;
86 
87  BinUtility bu1(4, 0_m, 1_m, open, binX);
88  bu1 += BinUtility(2, -0.5_m, 0.5_m, open, binY);
89  bu1 += BinUtility(2, -0.5_m, 0.5_m, open, binZ);
90 
91  BinUtility bu2(4, 1_m, 2_m, open, binX);
92  bu2 += BinUtility(2, -0.5_m, 0.5_m, open, binY);
93  bu2 += BinUtility(2, -0.5_m, 0.5_m, open, binZ);
94 
95  BinUtility bu3(4, 2_m, 3_m, open, binX);
96  bu3 += BinUtility(2, -0.5_m, 0.5_m, open, binY);
97  bu3 += BinUtility(2, -0.5_m, 0.5_m, open, binZ);
98 
99  // Build a vacuum volume
100  CuboidVolumeBuilder::VolumeConfig vCfg1;
101  vCfg1.position = Vector3(0.5_m, 0., 0.);
102  vCfg1.length = Vector3(1_m, 1_m, 1_m);
103  vCfg1.name = "Vacuum volume";
104  vCfg1.volumeMaterial = std::make_shared<const ProtoVolumeMaterial>(bu1);
105 
106  // Build a material volume
107  CuboidVolumeBuilder::VolumeConfig vCfg2;
108  vCfg2.position = Vector3(1.5_m, 0., 0.);
109  vCfg2.length = Vector3(1_m, 1_m, 1_m);
110  vCfg2.name = "First material volume";
111  vCfg2.volumeMaterial = std::make_shared<const ProtoVolumeMaterial>(bu2);
112 
113  // Build another material volume with different material
114  CuboidVolumeBuilder::VolumeConfig vCfg3;
115  vCfg3.position = Vector3(2.5_m, 0., 0.);
116  vCfg3.length = Vector3(1_m, 1_m, 1_m);
117  vCfg3.name = "Second material volume";
118  vCfg3.volumeMaterial = std::make_shared<const ProtoVolumeMaterial>(bu3);
119 
120  // Configure world
122  cfg.position = Vector3(1.5_m, 0., 0.);
123  cfg.length = Vector3(3_m, 1_m, 1_m);
124  cfg.volumeCfg = {vCfg1, vCfg2, vCfg3};
125 
126  GeometryContext gc;
127 
128  // Build a detector
129  CuboidVolumeBuilder cvb(cfg);
131  tgbCfg.trackingVolumeBuilders.push_back(
132  [=](const auto& context, const auto& inner, const auto&) {
133  return cvb.trackingVolume(context, inner, nullptr);
134  });
135  TrackingGeometryBuilder tgb(tgbCfg);
136  std::shared_ptr<const TrackingGeometry> tGeometry = tgb.trackingGeometry(gc);
137 
139  Navigator navigator({tGeometry});
140  StraightLineStepper stepper;
143 
147  vmmConfig, std::move(propagator),
148  getDefaultLogger("VolumeMaterialMapper", Logging::VERBOSE));
149 
151  GeometryContext gCtx;
152  MagneticFieldContext mfCtx;
153 
155  auto mState = vmMapper.createState(gCtx, mfCtx, *tGeometry);
156 
158  BOOST_CHECK_EQUAL(mState.materialBin.size(), 3u);
159 }
160 
163 BOOST_AUTO_TEST_CASE(VolumeMaterialMapper_comparison_tests) {
164  using namespace Acts::UnitLiterals;
165 
166  // Build a vacuum volume
168  vCfg1.position = Vector3(0.5_m, 0., 0.);
169  vCfg1.length = Vector3(1_m, 1_m, 1_m);
170  vCfg1.name = "Vacuum volume";
171  vCfg1.volumeMaterial =
172  std::make_shared<const HomogeneousVolumeMaterial>(Material());
173 
174  // Build a material volume
176  vCfg2.position = Vector3(1.5_m, 0., 0.);
177  vCfg2.length = Vector3(1_m, 1_m, 1_m);
178  vCfg2.name = "First material volume";
179  vCfg2.volumeMaterial =
180  std::make_shared<HomogeneousVolumeMaterial>(makeSilicon());
181 
182  // Build another material volume with different material
184  vCfg3.position = Vector3(2.5_m, 0., 0.);
185  vCfg3.length = Vector3(1_m, 1_m, 1_m);
186  vCfg3.name = "Second material volume";
187  vCfg3.volumeMaterial =
188  std::make_shared<const HomogeneousVolumeMaterial>(Material());
189 
190  // Configure world
192  cfg.position = Vector3(1.5_m, 0., 0.);
193  cfg.length = Vector3(3_m, 1_m, 1_m);
194  cfg.volumeCfg = {vCfg1, vCfg2, vCfg3};
195 
196  GeometryContext gc;
197 
198  // Build a detector
201  tgbCfg.trackingVolumeBuilders.push_back(
202  [=](const auto& context, const auto& inner, const auto&) {
203  return cvb.trackingVolume(context, inner, nullptr);
204  });
205  TrackingGeometryBuilder tgb(tgbCfg);
206  std::unique_ptr<const TrackingGeometry> detector = tgb.trackingGeometry(gc);
207 
208  // Set up the grid axes
209  Acts::MaterialGridAxisData xAxis{0_m, 3_m, 7};
210  Acts::MaterialGridAxisData yAxis{-0.5_m, 0.5_m, 7};
211  Acts::MaterialGridAxisData zAxis{-0.5_m, 0.5_m, 7};
212 
213  // Set up a random engine for sampling material
214  std::random_device rd;
215  std::mt19937 gen(42);
216  std::uniform_real_distribution<> disX(0., 3_m);
217  std::uniform_real_distribution<> disYZ(-0.5_m, 0.5_m);
218 
219  // Sample the Material in the detector
220  RecordedMaterialVolumePoint matRecord;
221  for (unsigned int i = 0; i < 1e4; i++) {
222  Vector3 pos(disX(gen), disYZ(gen), disYZ(gen));
223  std::vector<Vector3> volPos;
224  volPos.push_back(pos);
225  Material tv =
226  (detector->lowestTrackingVolume(gc, pos)->volumeMaterial() != nullptr)
227  ? (detector->lowestTrackingVolume(gc, pos)->volumeMaterial())
228  ->material(pos)
229  : Material();
230  MaterialSlab matProp(tv, 1);
231  matRecord.push_back(std::make_pair(matProp, volPos));
232  }
233 
234  // Build the material grid
235  Grid3D Grid = createGrid(xAxis, yAxis, zAxis);
236  std::function<Vector3(Vector3)> transfoGlobalToLocal =
237  [](Vector3 pos) -> Vector3 {
238  return {pos.x(), pos.y(), pos.z()};
239  };
240 
241  // Walk over each property
242  for (const auto& rm : matRecord) {
243  // Walk over each point associated with the properties
244  for (const auto& point : rm.second) {
245  // Search for fitting grid point and accumulate
247  Grid.localBinsFromLowerLeftEdge(transfoGlobalToLocal(point));
248  Grid.atLocalBins(index).accumulate(rm.first);
249  }
250  }
251 
253 
254  // Construct a simple propagation through the detector
256  Navigator::Config navCfg;
258  Navigator nav(navCfg);
260 
261  // Set some start parameters
262  Vector4 pos4(0., 0., 0., 42_ns);
263  Vector3 dir(1., 0., 0.);
264  CurvilinearTrackParameters sctp(pos4, dir, 1 / 1_GeV, std::nullopt,
266 
268  // Launch propagation and gather result
269  PropagatorOptions<ActionList<MaterialCollector>, AbortList<EndOfWorldReached>>
270  po(gc, mc);
271  po.maxStepSize = 1._mm;
272  po.maxSteps = 1e6;
273 
274  const auto& result = prop.propagate(sctp, po).value();
275  const MaterialCollector::this_result& stepResult =
276  result.get<typename MaterialCollector::result_type>();
277 
278  // Collect the material as given by the grid and test it
279  std::vector<Material> matvector;
280  double gridX0 = 0., gridL0 = 0., trueX0 = 0., trueL0 = 0.;
281  for (unsigned int i = 0; i < stepResult.position.size(); i++) {
282  matvector.push_back(matGrid.atPosition(stepResult.position[i]));
283  gridX0 += 1 / matvector[i].X0();
284  gridL0 += 1 / matvector[i].L0();
285  trueX0 += 1 / stepResult.matTrue[i].X0();
286  trueL0 += 1 / stepResult.matTrue[i].L0();
287  }
288  CHECK_CLOSE_REL(gridX0, trueX0, 1e-1);
289  CHECK_CLOSE_REL(gridL0, trueL0, 1e-1);
290 }
291 
292 } // namespace Test
293 } // namespace Acts