Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExtrapolatorTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ExtrapolatorTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018-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/data/test_case.hpp>
10 #include <boost/test/tools/output_test_stream.hpp>
11 #include <boost/test/unit_test.hpp>
12 
33 
34 #include <algorithm>
35 #include <array>
36 #include <cmath>
37 #include <map>
38 #include <memory>
39 #include <optional>
40 #include <random>
41 #include <tuple>
42 #include <utility>
43 #include <vector>
44 
45 namespace bdata = boost::unit_test::data;
46 namespace tt = boost::test_tools;
47 using namespace Acts::UnitLiterals;
48 
49 namespace Acts {
50 namespace Test {
51 
52 // Create a test context
55 
56 // Global definitions
57 // The path limit abort
59 
60 std::vector<std::unique_ptr<const Surface>> stepState;
61 
63 auto tGeometry = cGeometry();
64 
65 // Get the navigator and provide the TrackingGeometry
67 
72 
73 auto bField = std::make_shared<BFieldType>(Vector3{0, 0, 2_T});
76 
77 const int ntests = 100;
78 
79 // A plane selector for the SurfaceCollector
80 struct PlaneSelector {
83  bool operator()(const Surface& sf) const {
84  return (sf.type() == Surface::Plane);
85  }
86 };
87 
88 // This test case checks that no segmentation fault appears
89 // - simple extrapolation test
91  test_extrapolation_,
92  bdata::random((bdata::seed = 0,
93  bdata::distribution =
94  std::uniform_real_distribution<>(0.4_GeV, 10_GeV))) ^
95  bdata::random((bdata::seed = 1,
96  bdata::distribution =
97  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
98  bdata::random((bdata::seed = 2,
99  bdata::distribution =
100  std::uniform_real_distribution<>(1.0, M_PI - 1.0))) ^
101  bdata::random(
102  (bdata::seed = 3,
103  bdata::distribution = std::uniform_int_distribution<>(0, 1))) ^
104  bdata::random(
105  (bdata::seed = 4,
106  bdata::distribution = std::uniform_int_distribution<>(0, 100))) ^
107  bdata::xrange(ntests),
108  pT, phi, theta, charge, time, index) {
109  double p = pT / sin(theta);
110  double q = -1 + 2 * charge;
111  (void)index;
112 
113  // define start parameters
115  Covariance cov;
116  // take some major correlations (off-diagonals)
117  cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
118  0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
119  0, 0;
121  cov, ParticleHypothesis::pion());
122 
124  options.maxStepSize = 10_cm;
125  options.pathLimit = 25_cm;
126 
127  BOOST_CHECK(
128  epropagator.propagate(start, options).value().endParameters.has_value());
129 }
130 
131 // This test case checks that no segmentation fault appears
132 // - this tests the collection of surfaces
134  test_surface_collection_,
135  bdata::random((bdata::seed = 10,
136  bdata::distribution =
137  std::uniform_real_distribution<>(0.4_GeV, 10_GeV))) ^
138  bdata::random((bdata::seed = 11,
139  bdata::distribution =
140  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
141  bdata::random((bdata::seed = 12,
142  bdata::distribution =
143  std::uniform_real_distribution<>(1.0, M_PI - 1.0))) ^
144  bdata::random(
145  (bdata::seed = 13,
146  bdata::distribution = std::uniform_int_distribution<>(0, 1))) ^
147  bdata::random(
148  (bdata::seed = 14,
149  bdata::distribution = std::uniform_int_distribution<>(0, 100))) ^
150  bdata::xrange(ntests),
151  pT, phi, theta, charge, time, index) {
152  double p = pT / sin(theta);
153  double q = -1 + 2 * charge;
154  (void)index;
155 
156  // define start parameters
158  Covariance cov;
159  // take some major correlations (off-diagonals)
160  cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
161  0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
162  0, 0;
164  cov, ParticleHypothesis::pion());
165 
166  // A PlaneSelector for the SurfaceCollector
167  using PlaneCollector = SurfaceCollector<PlaneSelector>;
168 
170 
171  options.maxStepSize = 10_cm;
172  options.pathLimit = 25_cm;
173 
174  const auto& result = epropagator.propagate(start, options).value();
175  auto collector_result = result.get<PlaneCollector::result_type>();
176 
177  // step through the surfaces and go step by step
178  PropagatorOptions<> optionsEmpty(tgContext, mfContext);
179 
180  optionsEmpty.maxStepSize = 25_cm;
181  // Try propagation from start to each surface
182  for (const auto& colsf : collector_result.collected) {
183  const auto& csurface = colsf.surface;
184  // Avoid going to the same surface
185  // @todo: decide on strategy and write unit test for this
186  if (csurface == &start.referenceSurface()) {
187  continue;
188  }
189  // Extrapolate & check
190  const auto& cresult = epropagator.propagate(start, *csurface, optionsEmpty)
191  .value()
192  .endParameters;
193  BOOST_CHECK(cresult.has_value());
194  }
195 }
196 
197 // This test case checks that no segmentation fault appears
198 // - this tests the collection of surfaces
200  test_material_interactor_,
201  bdata::random((bdata::seed = 20,
202  bdata::distribution =
203  std::uniform_real_distribution<>(0.4_GeV, 10_GeV))) ^
204  bdata::random((bdata::seed = 21,
205  bdata::distribution =
206  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
207  bdata::random((bdata::seed = 22,
208  bdata::distribution =
209  std::uniform_real_distribution<>(1.0, M_PI - 1.0))) ^
210  bdata::random(
211  (bdata::seed = 23,
212  bdata::distribution = std::uniform_int_distribution<>(0, 1))) ^
213  bdata::random(
214  (bdata::seed = 24,
215  bdata::distribution = std::uniform_int_distribution<>(0, 100))) ^
216  bdata::xrange(ntests),
217  pT, phi, theta, charge, time, index) {
218  double p = pT / sin(theta);
219  double q = -1 + 2 * charge;
220  (void)index;
221 
222  // define start parameters
224  Covariance cov;
225  // take some major correlations (off-diagonals)
226  cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
227  0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
228  0, 0;
230  cov, ParticleHypothesis::pion());
231 
233  mfContext);
234  options.maxStepSize = 25_cm;
235  options.pathLimit = 25_cm;
236 
237  const auto& result = epropagator.propagate(start, options).value();
238  if (result.endParameters) {
239  // test that you actually lost some energy
240  BOOST_CHECK_LT(result.endParameters->absoluteMomentum(),
241  start.absoluteMomentum());
242  }
243 }
244 
245 // This test case checks that no segmentation fault appears
246 // - this tests the loop protection
248  loop_protection_test,
249  bdata::random((bdata::seed = 20,
250  bdata::distribution =
251  std::uniform_real_distribution<>(0.1_GeV, 0.5_GeV))) ^
252  bdata::random((bdata::seed = 21,
253  bdata::distribution =
254  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
255  bdata::random((bdata::seed = 22,
256  bdata::distribution =
257  std::uniform_real_distribution<>(1.0, M_PI - 1.0))) ^
258  bdata::random(
259  (bdata::seed = 23,
260  bdata::distribution = std::uniform_int_distribution<>(0, 1))) ^
261  bdata::random(
262  (bdata::seed = 24,
263  bdata::distribution = std::uniform_int_distribution<>(0, 100))) ^
264  bdata::xrange(ntests),
265  pT, phi, theta, charge, time, index) {
266  double p = pT / sin(theta);
267  double q = -1 + 2 * charge;
268  (void)index;
269 
270  // define start parameters
272  Covariance cov;
273  // take some major correlations (off-diagonals)
274  cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
275  0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
276  0, 0;
278  cov, ParticleHypothesis::pion());
279 
280  // Action list and abort list
282  mfContext);
283  options.maxStepSize = 25_cm;
284  options.pathLimit = 1500_mm;
285 
286  const auto& status = epropagator.propagate(start, options).value();
287  // this test assumes state.options.loopFraction = 0.5
288  // maximum momentum allowed
289  auto bCache = bField->makeCache(mfContext);
290  double pmax =
291  options.pathLimit *
292  bField->getField(start.position(tgContext), bCache).value().norm() / M_PI;
293  if (p < pmax) {
294  BOOST_CHECK_LT(status.pathLength, options.pathLimit);
295  } else {
296  CHECK_CLOSE_REL(status.pathLength, options.pathLimit, 1e-3);
297  }
298 }
299 
300 } // namespace Test
301 } // namespace Acts