EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PropagatorTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PropagatorTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-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 
25 #include "Acts/Utilities/Units.hpp"
26 
27 namespace bdata = boost::unit_test::data;
28 namespace tt = boost::test_tools;
29 using namespace Acts::UnitLiterals;
32 
33 namespace Acts {
34 namespace Test {
35 
36 // Create a test context
39 
41 
45  struct this_result {
46  double distance = std::numeric_limits<double>::max();
47  };
48 
50 
51  PerpendicularMeasure() = default;
52 
53  template <typename propagator_state_t, typename stepper_t>
54  void operator()(propagator_state_t& state, const stepper_t& stepper,
55  result_type& result) const {
56  result.distance = perp(stepper.position(state.stepping));
57  }
58 
59  template <typename propagator_state_t, typename stepper_t>
60  void operator()(propagator_state_t& /*unused*/,
61  const stepper_t& /*unused*/) const {}
62 };
63 
65 template <typename Surface>
67  // the surface to be intersected
68  const Surface* surface = nullptr;
69  // the tolerance for intersection
70  double tolerance = 1.e-5;
71 
73  struct this_result {
74  size_t surfaces_passed = 0;
75  double surface_passed_r = std::numeric_limits<double>::max();
76  };
77 
79 
80  SurfaceObserver() = default;
81 
82  template <typename propagator_state_t, typename stepper_t>
83  void operator()(propagator_state_t& state, const stepper_t& stepper,
84  result_type& result) const {
85  if (surface && !result.surfaces_passed) {
86  // calculate the distance to the surface
87  const double distance =
88  surface
89  ->intersect(state.geoContext, stepper.position(state.stepping),
90  stepper.direction(state.stepping), true)
91  .intersection.pathLength;
92  // Adjust the step size so that we cannot cross the target surface
93  state.stepping.stepSize.update(distance, ConstrainedStep::actor);
94  // return true if you fall below tolerance
95  if (std::abs(distance) <= tolerance) {
96  ++result.surfaces_passed;
97  result.surface_passed_r = perp(stepper.position(state.stepping));
98  // release the step size, will be re-adjusted
99  state.stepping.stepSize.release(ConstrainedStep::actor);
100  }
101  }
102  }
103 
104  template <typename propagator_state_t, typename stepper_t>
105  void operator()(propagator_state_t& /*unused*/,
106  const stepper_t& /*unused*/) const {}
107 };
108 
109 // Global definitions
110 // The path limit abort
112 
113 using BFieldType = ConstantBField;
116 
117 const double Bz = 2_T;
118 BFieldType bField(0, 0, Bz);
121 
122 auto mCylinder = std::make_shared<CylinderBounds>(10_mm, 1000_mm);
123 auto mSurface =
124  Surface::makeShared<CylinderSurface>(Transform3D::Identity(), mCylinder);
125 auto cCylinder = std::make_shared<CylinderBounds>(150_mm, 1000_mm);
126 auto cSurface =
127  Surface::makeShared<CylinderSurface>(Transform3D::Identity(), cCylinder);
128 
129 const int ntests = 5;
130 
131 // This tests the Options
132 BOOST_AUTO_TEST_CASE(PropagatorOptions_) {
133  using null_optionsType = PropagatorOptions<>;
134  null_optionsType null_options(tgContext, mfContext, getDummyLogger());
135  // todo write null options test
136 
137  using ActionListType = ActionList<PerpendicularMeasure>;
138  using AbortConditionsType = AbortList<>;
139 
141 
142  optionsType options(tgContext, mfContext, getDummyLogger());
143 }
144 
146  cylinder_passage_observer_,
147  bdata::random((bdata::seed = 0,
148  bdata::distribution =
149  std::uniform_real_distribution<>(0.4_GeV, 10_GeV))) ^
150  bdata::random((bdata::seed = 1,
151  bdata::distribution =
152  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
153  bdata::random((bdata::seed = 2,
154  bdata::distribution =
155  std::uniform_real_distribution<>(1.0, M_PI - 1.0))) ^
156  bdata::random(
157  (bdata::seed = 3,
158  bdata::distribution = std::uniform_int_distribution<>(0, 1))) ^
159  bdata::random(
160  (bdata::seed = 4,
161  bdata::distribution = std::uniform_int_distribution<>(0, 100))) ^
163  pT, phi, theta, charge, time, index) {
164  double dcharge = -1 + 2 * charge;
165  (void)index;
166 
167  using CylinderObserver = SurfaceObserver<CylinderSurface>;
168  using ActionListType = ActionList<CylinderObserver>;
169  using AbortConditionsType = AbortList<>;
170 
171  // setup propagation options
174 
175  options.pathLimit = 20_m;
176  options.maxStepSize = 1_cm;
177 
178  // set the surface to be passed by
179  options.actionList.get<CylinderObserver>().surface = mSurface.get();
180 
181  using so_result = typename CylinderObserver::result_type;
182 
183  // define start parameters
184  double x = 0;
185  double y = 0;
186  double z = 0;
187  double px = pT * cos(phi);
188  double py = pT * sin(phi);
189  double pz = pT / tan(theta);
190  double q = dcharge;
191  Vector3D pos(x, y, z);
192  Vector3D mom(px, py, pz);
193  CurvilinearTrackParameters start(makeVector4(pos, time), mom, mom.norm(), q);
194  // propagate to the cylinder surface
195  const auto& result = epropagator.propagate(start, *cSurface, options).value();
196  auto& sor = result.get<so_result>();
197 
198  BOOST_CHECK_EQUAL(sor.surfaces_passed, 1u);
199  CHECK_CLOSE_ABS(sor.surface_passed_r, 10., 1e-5);
200 }
201 
203  curvilinear_additive_,
204  bdata::random((bdata::seed = 0,
205  bdata::distribution =
206  std::uniform_real_distribution<>(0.4_GeV, 10_GeV))) ^
207  bdata::random((bdata::seed = 1,
208  bdata::distribution =
209  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
210  bdata::random((bdata::seed = 2,
211  bdata::distribution =
212  std::uniform_real_distribution<>(1.0, M_PI - 1.0))) ^
213  bdata::random(
214  (bdata::seed = 3,
215  bdata::distribution = std::uniform_int_distribution<>(0, 1))) ^
216  bdata::random(
217  (bdata::seed = 4,
218  bdata::distribution = std::uniform_int_distribution<>(0, 100))) ^
220  pT, phi, theta, charge, time, index) {
221  double dcharge = -1 + 2 * charge;
222  (void)index;
223 
224  // setup propagation options - the tow step options
226  options_2s.pathLimit = 50_cm;
227  options_2s.maxStepSize = 1_cm;
228 
229  // define start parameters
230  double x = 0;
231  double y = 0;
232  double z = 0;
233  double px = pT * cos(phi);
234  double py = pT * sin(phi);
235  double pz = pT / tan(theta);
236  double q = dcharge;
237  Vector3D pos(x, y, z);
238  Vector3D mom(px, py, pz);
240  Covariance cov;
241  // take some major correlations (off-diagonals)
242  cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
243  0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
244  0, 0;
245  CurvilinearTrackParameters start(makeVector4(pos, time), mom, mom.norm(), q,
246  cov);
247  // propagate to a path length of 100 with two steps of 50
248  const auto& mid_parameters =
249  epropagator.propagate(start, options_2s).value().endParameters;
250  const auto& end_parameters_2s =
251  epropagator.propagate(*mid_parameters, options_2s).value().endParameters;
252 
253  // setup propagation options - the one step options
255  options_1s.pathLimit = 100_cm;
256  options_1s.maxStepSize = 1_cm;
257  // propagate to a path length of 100 in one step
258  const auto& end_parameters_1s =
259  epropagator.propagate(start, options_1s).value().endParameters;
260 
261  // test that the propagation is additive
262  CHECK_CLOSE_REL(end_parameters_1s->position(tgContext),
263  end_parameters_2s->position(tgContext), 0.001);
264 
265  const auto& cov_1s = *(end_parameters_1s->covariance());
266  const auto& cov_2s = *(end_parameters_2s->covariance());
267 
268  // CHECK_CLOSE_COVARIANCE(cov_1s, cov_2s, 0.001);
269  for (unsigned int i = 0; i < cov_1s.rows(); i++) {
270  for (unsigned int j = 0; j < cov_1s.cols(); j++) {
271  CHECK_CLOSE_OR_SMALL(cov_1s(i, j), cov_2s(i, j), 0.001, 1e-6);
272  }
273  }
274 }
275 
277  cylinder_additive_,
278  bdata::random((bdata::seed = 0,
279  bdata::distribution =
280  std::uniform_real_distribution<>(0.4_GeV, 10_GeV))) ^
281  bdata::random((bdata::seed = 1,
282  bdata::distribution =
283  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
284  bdata::random((bdata::seed = 2,
285  bdata::distribution =
286  std::uniform_real_distribution<>(1.0, M_PI - 1.0))) ^
287  bdata::random(
288  (bdata::seed = 3,
289  bdata::distribution = std::uniform_int_distribution<>(0, 1))) ^
290  bdata::random(
291  (bdata::seed = 4,
292  bdata::distribution = std::uniform_int_distribution<>(0, 100))) ^
294  pT, phi, theta, charge, time, index) {
295  double dcharge = -1 + 2 * charge;
296  (void)index;
297 
298  // setup propagation options - 2 setp options
300  options_2s.pathLimit = 10_m;
301  options_2s.maxStepSize = 1_cm;
302 
303  // define start parameters
304  double x = 0;
305  double y = 0;
306  double z = 0;
307  double px = pT * cos(phi);
308  double py = pT * sin(phi);
309  double pz = pT / tan(theta);
310  double q = dcharge;
311  Vector3D pos(x, y, z);
312  Vector3D mom(px, py, pz);
314  Covariance cov;
315  // take some major correlations (off-diagonals)
316  cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
317  0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
318  0, 0;
319  CurvilinearTrackParameters start(makeVector4(pos, time), mom, mom.norm(), q,
320  cov);
321  // propagate to a final surface with one stop in between
322  const auto& mid_parameters =
323  epropagator.propagate(start, *mSurface, options_2s).value().endParameters;
324 
325  const auto& end_parameters_2s =
326  epropagator.propagate(*mid_parameters, *cSurface, options_2s)
327  .value()
328  .endParameters;
329 
330  // setup propagation options - one step options
332  options_1s.pathLimit = 10_m;
333  options_1s.maxStepSize = 1_cm;
334  // propagate to a final surface in one stop
335  const auto& end_parameters_1s =
336  epropagator.propagate(start, *cSurface, options_1s).value().endParameters;
337 
338  // test that the propagation is additive
339  CHECK_CLOSE_REL(end_parameters_1s->position(tgContext),
340  end_parameters_2s->position(tgContext), 0.001);
341 
342  const auto& cov_1s = (*(end_parameters_1s->covariance()));
343  const auto& cov_2s = (*(end_parameters_2s->covariance()));
344 
345  // CHECK_CLOSE_COVARIANCE(cov_1s, cov_2s, 0.001);
346  for (unsigned int i = 0; i < cov_1s.rows(); i++) {
347  for (unsigned int j = 0; j < cov_1s.cols(); j++) {
348  CHECK_CLOSE_OR_SMALL(cov_1s(i, j), cov_2s(i, j), 0.001, 1e-6);
349  }
350  }
351 }
352 
353 } // namespace Test
354 } // namespace Acts