Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NavigatorTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file NavigatorTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018-2020 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 
37 
38 #include <cstddef>
39 #include <iostream>
40 #include <map>
41 #include <memory>
42 #include <string>
43 #include <system_error>
44 #include <tuple>
45 #include <utility>
46 
47 namespace Acts {
48 class Layer;
49 struct FreeToBoundCorrection;
50 } // namespace Acts
51 
52 namespace bdata = boost::unit_test::data;
53 namespace tt = boost::test_tools;
54 using namespace Acts::UnitLiterals;
56 
57 namespace Acts {
58 namespace Test {
59 
60 // Create a test context
62 
65 struct PropagatorState {
67  struct Stepper {
68  // comply with concept
71  using BoundState = std::tuple<BoundTrackParameters, Jacobian, double>;
72  using CurvilinearState =
73  std::tuple<CurvilinearTrackParameters, Jacobian, double>;
74  using BField = int;
75 
76  template <typename, typename>
77  using return_parameter_type = void;
78 
81  struct State {
83  Vector4 pos4 = Vector4(0., 0., 0., 0.);
84 
86  Vector3 dir = Vector3(1., 0., 0.);
87 
89  double p = 0;
90 
92  double q = 0;
93 
96 
97  // accummulated path length cache
98  double pathAccumulated = 0.;
99 
100  // adaptive sep size of the runge-kutta integration
102 
103  // Previous step size for overstep estimation (ignored here)
104  double previousStepSize = 0.;
105 
108 
110  };
111 
113  void resetState(State& /*state*/, const BoundVector& /*boundParams*/,
114  const BoundSquareMatrix& /*cov*/,
115  const Surface& /*surface*/,
116  const double /*stepSize*/) const {}
117 
119  Vector3 position(const State& state) const {
120  return state.pos4.segment<3>(Acts::ePos0);
121  }
122 
124  double time(const State& state) const { return state.pos4[Acts::eTime]; }
125 
127  Vector3 direction(const State& state) const { return state.dir; }
128 
130  double qOverP(const State& state) const {
131  return (state.q == 0 ? 1 : state.q) / state.p;
132  }
133 
135  double absoluteMomentum(const State& state) const { return state.p; }
136 
138  Vector3 momentum(const State& state) const { return state.p * state.dir; }
139 
141  double charge(const State& state) const { return state.q; }
142 
144  double overstepLimit(const State& /*state*/) const {
145  return s_onSurfaceTolerance;
146  }
147 
148  Intersection3D::Status updateSurfaceStatus(State& state,
149  const Surface& surface,
151  const BoundaryCheck& bcheck,
152  ActsScalar surfaceTolerance,
153  const Logger& logger) const {
154  return detail::updateSingleSurfaceStatus<Stepper>(
155  *this, state, surface, navDir, bcheck, surfaceTolerance, logger);
156  }
157 
158  template <typename object_intersection_t>
159  void updateStepSize(State& state,
160  const object_intersection_t& oIntersection,
161  Direction /*direction*/, bool release = true) const {
162  detail::updateSingleStepSize<Stepper>(state, oIntersection, release);
163  }
164 
165  void setStepSize(State& state, double stepSize,
167  bool release = true) const {
168  state.previousStepSize = state.stepSize.value();
169  state.stepSize.update(stepSize, stype, release);
170  }
171 
172  double getStepSize(const State& state, ConstrainedStep::Type stype) const {
173  return state.stepSize.value(stype);
174  }
175 
176  void releaseStepSize(State& state) const {
178  }
179 
181  return state.stepSize.toString();
182  }
183 
185  State& state, const Surface& surface, bool /*transportCov*/,
186  const FreeToBoundCorrection& /*freeToBoundCorrection*/
187  ) const {
188  auto bound = BoundTrackParameters::create(
189  surface.getSharedPtr(), tgContext, state.pos4, state.dir,
190  state.q / state.p, std::nullopt, state.particleHypothesis);
191  if (!bound.ok()) {
192  return bound.error();
193  }
194  BoundState bState{std::move(*bound), Jacobian::Identity(),
195  state.pathAccumulated};
196  return bState;
197  }
198 
200  ) const {
202  state.q / state.p, std::nullopt,
203  state.particleHypothesis);
204  // Create the bound state
205  CurvilinearState curvState{std::move(parameters), Jacobian::Identity(),
206  state.pathAccumulated};
207  return curvState;
208  }
209 
210  void update(State& /*state*/, const FreeVector& /*freePars*/,
211  const BoundVector& /*boundPars*/, const Covariance& /*cov*/,
212  const Surface& /*surface*/) const {}
213 
214  void update(State& /*state*/, const Vector3& /*uposition*/,
215  const Vector3& /*udirection*/, double /*up*/,
216  double /*time*/) const {}
217 
218  void transportCovarianceToCurvilinear(State& /*state*/) const {}
219 
221  State& /*state*/, const Surface& /*surface*/,
222  const FreeToBoundCorrection& /*freeToBoundCorrection*/) const {}
223 
224  Result<Vector3> getField(State& /*state*/, const Vector3& /*pos*/) const {
225  // get the field from the cell
226  return Result<Vector3>::success({0., 0., 0.});
227  }
228  };
229 
230  static_assert(StepperConcept<Stepper>,
231  "Dummy stepper does not fulfill concept");
232 
234  struct Options {
237  bool debug = false;
238  std::string debugString = "";
240  size_t debugPfxWidth = 30;
241  size_t debugMsgWidth = 50;
242 
244 
246 
247  ActsScalar targetTolerance = s_onSurfaceTolerance;
248  };
249 
251  const Surface* startSurface = nullptr;
252 
254  const Surface* currentSurface = nullptr;
255 
257  const Surface* targetSurface = nullptr;
258  bool targetReached = false;
259 
262 
265 
268 
269  // The context cache for this propagation
271 };
272 
273 template <typename stepper_state_t>
274 void step(stepper_state_t& sstate) {
275  // update the cache position
276  sstate.pos4[Acts::ePos0] += sstate.stepSize.value() * sstate.dir[Acts::eMom0];
277  sstate.pos4[Acts::ePos1] += sstate.stepSize.value() * sstate.dir[Acts::eMom1];
278  sstate.pos4[Acts::ePos2] += sstate.stepSize.value() * sstate.dir[Acts::eMom2];
279  // create navigation parameters
280  return;
281 }
282 
291  size_t navLay, size_t navBound, size_t extSurf) {
292  return ((state.navSurfaces.size() == navSurf) &&
293  (state.navLayers.size() == navLay) &&
294  (state.navBoundaries.size() == navBound) &&
295  (state.externalSurfaces.size() == extSurf));
296 }
297 
311  Navigator::State& state, const TrackingVolume* worldVol,
312  const TrackingVolume* startVol, const Layer* startLay,
313  const Surface* startSurf, const Surface* currSurf,
314  const TrackingVolume* currVol, const TrackingVolume* targetVol,
315  const Layer* targetLay, const Surface* targetSurf) {
316  return (
317  (state.worldVolume == worldVol) && (state.startVolume == startVol) &&
318  (state.startLayer == startLay) && (state.startSurface == startSurf) &&
319  (state.currentSurface == currSurf) && (state.currentVolume == currVol) &&
320  (state.targetVolume == targetVol) && (state.targetLayer == targetLay) &&
321  (state.targetSurface == targetSurf));
322 }
323 // the surface cache & the creation of the geometry
324 
325 CylindricalTrackingGeometry cGeometry(tgContext);
326 auto tGeometry = cGeometry();
327 
328 // the debug boolean
329 bool debug = true;
330 
331 BOOST_AUTO_TEST_CASE(Navigator_status_methods) {
332  // position and direction vector
333  Vector4 position4(0., 0., 0, 0);
334  Vector3 momentum(1., 1., 0);
335 
336  // the propagator cache
338  state.options.debug = debug;
339 
340  // the stepper cache
341  state.stepping.pos4 = position4;
342  state.stepping.dir = momentum.normalized();
343 
344  // Stepper
346 
347  //
348  // (1) Test for inactivity
349  //
350  // Run without anything present
351  {
352  Navigator::Config navCfg;
353  navCfg.resolveSensitive = false;
354  navCfg.resolveMaterial = false;
355  navCfg.resolvePassive = false;
356  Navigator navigator{navCfg};
357 
358  navigator.postStep(state, stepper);
359  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
360  BOOST_CHECK(testNavigatorStatePointers(state.navigation, nullptr, nullptr,
361  nullptr, nullptr, nullptr, nullptr,
362  nullptr, nullptr, nullptr));
363  }
364 
365  // Run with geometry but without resolving
366  {
367  Navigator::Config navCfg;
368  navCfg.resolveSensitive = false;
369  navCfg.resolveMaterial = false;
370  navCfg.resolvePassive = false;
371  navCfg.trackingGeometry = tGeometry;
372  Navigator navigator{navCfg};
373 
374  navigator.postStep(state, stepper);
375  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
376  BOOST_CHECK(testNavigatorStatePointers(state.navigation, nullptr, nullptr,
377  nullptr, nullptr, nullptr, nullptr,
378  nullptr, nullptr, nullptr));
379  }
380 
381  // Run with geometry and resolving but broken navigation for various reasons
382  {
383  Navigator::Config navCfg;
384  navCfg.resolveSensitive = true;
385  navCfg.resolveMaterial = true;
386  navCfg.resolvePassive = true;
387  navCfg.trackingGeometry = tGeometry;
388  Navigator navigator{navCfg};
389 
390  state.navigation.navigationBreak = true;
391  // a) Because target is reached
392  state.navigation.targetReached = true;
393  navigator.postStep(state, stepper);
394  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
395  BOOST_CHECK(testNavigatorStatePointers(state.navigation, nullptr, nullptr,
396  nullptr, nullptr, nullptr, nullptr,
397  nullptr, nullptr, nullptr));
398 
399  // b) Because of no target surface
400  state.navigation.targetReached = false;
401  state.navigation.targetSurface = nullptr;
402  navigator.postStep(state, stepper);
403  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
404  BOOST_CHECK(testNavigatorStatePointers(state.navigation, nullptr, nullptr,
405  nullptr, nullptr, nullptr, nullptr,
406  nullptr, nullptr, nullptr));
407  // c) Because the target surface is reached
408  const Surface* startSurf = tGeometry->getBeamline();
409  state.stepping.pos4.segment<3>(Acts::ePos0) =
410  startSurf->center(state.geoContext);
411  const Surface* targetSurf = startSurf;
412  state.navigation.targetSurface = targetSurf;
413  navigator.postStep(state, stepper);
414  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
415  BOOST_CHECK(testNavigatorStatePointers(
416  state.navigation, nullptr, nullptr, nullptr, nullptr, targetSurf,
417  nullptr, nullptr, nullptr, targetSurf));
418 
419  //
420  // (2) Test the initialisation
421  //
422  // a) Initialise without additional information
423  state.navigation = Navigator::State();
424  state.stepping.pos4 << 0., 0., 0., 0.;
425  const TrackingVolume* worldVol = tGeometry->highestTrackingVolume();
426  const TrackingVolume* startVol = tGeometry->lowestTrackingVolume(
427  state.geoContext, stepper.position(state.stepping));
428  const Layer* startLay = startVol->associatedLayer(
429  state.geoContext, stepper.position(state.stepping));
430  navigator.initialize(state, stepper);
431  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
432  BOOST_CHECK(testNavigatorStatePointers(state.navigation, worldVol, startVol,
433  startLay, nullptr, nullptr, startVol,
434  nullptr, nullptr, nullptr));
435 
436  // b) Initialise having a start surface
437  state.navigation = Navigator::State();
438  state.navigation.startSurface = startSurf;
439  navigator.initialize(state, stepper);
440  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
441  BOOST_CHECK(testNavigatorStatePointers(
442  state.navigation, worldVol, startVol, startLay, startSurf, startSurf,
443  startVol, nullptr, nullptr, nullptr));
444 
445  // c) Initialise having a start volume
446  state.navigation = Navigator::State();
447  state.navigation.startVolume = startVol;
448  navigator.initialize(state, stepper);
449  BOOST_CHECK(testNavigatorStateVectors(state.navigation, 0u, 0u, 0u, 0u));
450  BOOST_CHECK(testNavigatorStatePointers(state.navigation, worldVol, startVol,
451  startLay, nullptr, nullptr, startVol,
452  nullptr, nullptr, nullptr));
453  }
454 }
455 
456 BOOST_AUTO_TEST_CASE(Navigator_target_methods) {
457  // create a navigator
458  Navigator::Config navCfg;
459  navCfg.trackingGeometry = tGeometry;
460  navCfg.resolveSensitive = true;
461  navCfg.resolveMaterial = true;
462  navCfg.resolvePassive = false;
463  Navigator navigator{navCfg};
464 
465  // create a navigator for the Bounding Volume Hierarchy test
466  CubicBVHTrackingGeometry grid(20, 1000, 5);
467  Navigator::Config bvhNavCfg;
468  bvhNavCfg.trackingGeometry = grid.trackingGeometry;
469  bvhNavCfg.resolveSensitive = true;
470  bvhNavCfg.resolveMaterial = true;
471  bvhNavCfg.resolvePassive = false;
472  Navigator BVHNavigator{bvhNavCfg};
473 
474  // position and direction vector
475  Vector4 position4(0., 0., 0, 0);
476  Vector3 momentum(1., 1., 0);
477 
478  // the propagator cache
480  state.options.debug = debug;
481 
482  // the stepper cache
483  state.stepping.pos4 = position4;
484  state.stepping.dir = momentum.normalized();
485 
486  // forward navigation ----------------------------------------------
487  if (debug) {
488  std::cout << "<<<<<<<<<<<<<<<<<<<<< FORWARD NAVIGATION >>>>>>>>>>>>>>>>>>"
489  << std::endl;
490  }
491 
492  // Stepper
494 
495  // (1) Initialization navigation from start point
496  // - this will call resolveLayers() as well
497  // - and thus should call a return to the stepper
498  navigator.initialize(state, stepper);
499  // Check that the currentVolume is set
500  BOOST_CHECK_NE(state.navigation.currentVolume, nullptr);
501  // Check that the currentVolume is the startVolume
502  BOOST_CHECK_EQUAL(state.navigation.currentVolume,
503  state.navigation.startVolume);
504  // Check that the currentSurface is reset to:
505  BOOST_CHECK_EQUAL(state.navigation.currentSurface, nullptr);
506  // No layer has been found
507  BOOST_CHECK_EQUAL(state.navigation.navLayers.size(), 0u);
508  // ACTORS-ABORTERS-TARGET
509  navigator.preStep(state, stepper);
510  // A layer has been found
511  BOOST_CHECK_EQUAL(state.navigation.navLayers.size(), 1u);
512  // The index should points to the begin
513  BOOST_CHECK(state.navigation.navLayerIndex == 0);
514  // Cache the beam pipe radius
515  double beamPipeR = perp(state.navigation.navLayer().position());
516  // step size has been updated
517  CHECK_CLOSE_ABS(state.stepping.stepSize.value(), beamPipeR,
519  if (debug) {
520  std::cout << "<<< Test 1a >>> initialize at "
521  << toString(state.stepping.pos4) << std::endl;
522  std::cout << state.options.debugString << std::endl;
523  // Clear the debug string for the next test
524  state.options.debugString = "";
525  }
526 
527  // Do the step towards the beam pipe
528  step(state.stepping);
529 
530  // (2) re-entering navigator:
531  // POST STEP
532  navigator.postStep(state, stepper);
533  // Check that the currentVolume is the still startVolume
534  BOOST_CHECK_EQUAL(state.navigation.currentVolume,
535  state.navigation.startVolume);
536  // The layer number has not changed
537  BOOST_CHECK_EQUAL(state.navigation.navLayers.size(), 1u);
538  // The index still points to the begin
539  BOOST_CHECK(state.navigation.navLayerIndex == 0);
540  // ACTORS - ABORTERS - PRE STEP
541  navigator.preStep(state, stepper);
542 
543  if (debug) {
544  std::cout << "<<< Test 1b >>> step to the BeamPipe at "
545  << toString(state.stepping.pos4) << std::endl;
546  std::cout << state.options.debugString << std::endl;
547  state.options.debugString = "";
548  }
549 
550  // Do the step towards the boundary
551  step(state.stepping);
552 
553  // (3) re-entering navigator:
554  // POST STEP
555  navigator.postStep(state, stepper);
556  // ACTORS - ABORTERS - PRE STEP
557  navigator.preStep(state, stepper);
558 
559  if (debug) {
560  std::cout << "<<< Test 1c >>> step to the Boundary at "
561  << toString(state.stepping.pos4) << std::endl;
562  std::cout << state.options.debugString << std::endl;
563  state.options.debugString = "";
564  }
565 
566  // positive return: do the step
567  step(state.stepping);
568  // (4) re-entering navigator:
569  // POST STEP
570  navigator.postStep(state, stepper);
571  // ACTORS - ABORTERS - PRE STEP
572  navigator.preStep(state, stepper);
573 
574  if (debug) {
575  std::cout << "<<< Test 1d >>> step to 1st layer at "
576  << toString(state.stepping.pos4) << std::endl;
577  std::cout << state.options.debugString << std::endl;
578  state.options.debugString = "";
579  }
580 
581  // Step through the surfaces on first layer
582  for (size_t isf = 0; isf < 5; ++isf) {
583  step(state.stepping);
584  // (5-9) re-entering navigator:
585  // POST STEP
586  navigator.postStep(state, stepper);
587  // ACTORS - ABORTERS - PRE STEP
588  navigator.preStep(state, stepper);
589 
590  if (debug) {
591  std::cout << "<<< Test 1e-1i >>> step within 1st layer at "
592  << toString(state.stepping.pos4) << std::endl;
593  std::cout << state.options.debugString << std::endl;
594  state.options.debugString = "";
595  }
596  }
597 
598  // positive return: do the step
599  step(state.stepping);
600  // (10) re-entering navigator:
601  // POST STEP
602  navigator.postStep(state, stepper);
603  // ACTORS - ABORTERS - PRE STEP
604  navigator.preStep(state, stepper);
605 
606  if (debug) {
607  std::cout << "<<< Test 1j >>> step to 2nd layer at "
608  << toString(state.stepping.pos4) << std::endl;
609  std::cout << state.options.debugString << std::endl;
610  state.options.debugString = "";
611  }
612 
613  // Step through the surfaces on second layer
614  for (size_t isf = 0; isf < 5; ++isf) {
615  step(state.stepping);
616  // (11-15) re-entering navigator:
617  // POST STEP
618  navigator.postStep(state, stepper);
619  // ACTORS - ABORTERS - PRE STEP
620  navigator.preStep(state, stepper);
621 
622  if (debug) {
623  std::cout << "<<< Test 1k-1o >>> step within 2nd layer at "
624  << toString(state.stepping.pos4) << std::endl;
625  std::cout << state.options.debugString << std::endl;
626  state.options.debugString = "";
627  }
628  }
629 
630  // positive return: do the step
631  step(state.stepping);
632  // (16) re-entering navigator:
633  // POST STEP
634  navigator.postStep(state, stepper);
635  // ACTORS - ABORTERS - PRE STEP
636  navigator.preStep(state, stepper);
637 
638  if (debug) {
639  std::cout << "<<< Test 1p >>> step to 3rd layer at "
640  << toString(state.stepping.pos4) << std::endl;
641  std::cout << state.options.debugString << std::endl;
642  state.options.debugString = "";
643  }
644 
645  // Step through the surfaces on third layer
646  for (size_t isf = 0; isf < 3; ++isf) {
647  step(state.stepping);
648  // (17-19) re-entering navigator:
649  // POST STEP
650  navigator.postStep(state, stepper);
651  // ACTORS - ABORTERS - PRE STEP
652  navigator.preStep(state, stepper);
653 
654  if (debug) {
655  std::cout << "<<< Test 1q-1s >>> step within 3rd layer at "
656  << toString(state.stepping.pos4) << std::endl;
657  std::cout << state.options.debugString << std::endl;
658  state.options.debugString = "";
659  }
660  }
661 
662  // positive return: do the step
663  step(state.stepping);
664  // (20) re-entering navigator:
665  // POST STEP
666  navigator.postStep(state, stepper);
667  // ACTORS - ABORTERS - PRE STEP
668  navigator.preStep(state, stepper);
669 
670  if (debug) {
671  std::cout << "<<< Test 1t >>> step to 4th layer at "
672  << toString(state.stepping.pos4) << std::endl;
673  std::cout << state.options.debugString << std::endl;
674  state.options.debugString = "";
675  }
676 
677  // Step through the surfaces on second layer
678  for (size_t isf = 0; isf < 3; ++isf) {
679  step(state.stepping);
680  // (21-23) re-entering navigator:
681  // POST STEP
682  navigator.postStep(state, stepper);
683  // ACTORS - ABORTERS - PRE STEP
684  navigator.preStep(state, stepper);
685 
686  if (debug) {
687  std::cout << "<<< Test 1t-1v >>> step within 4th layer at "
688  << toString(state.stepping.pos4) << std::endl;
689  std::cout << state.options.debugString << std::endl;
690  state.options.debugString = "";
691  }
692  }
693 
694  // positive return: do the step
695  step(state.stepping);
696  // (24) re-entering navigator:
697  // POST STEP
698  navigator.postStep(state, stepper);
699  // ACTORS - ABORTERS - PRE STEP
700  navigator.preStep(state, stepper);
701 
702  if (debug) {
703  std::cout << "<<< Test 1w >>> step to boundary at "
704  << toString(state.stepping.pos4) << std::endl;
705  std::cout << state.options.debugString << std::endl;
706  state.options.debugString = "";
707  }
708 
709  // test the navigation in a bounding volume hierarchy
710  // ----------------------------------------------
711  if (debug) {
712  std::cout << "<<<<<<<<<<<<<<<<<<<<< BVH Navigation >>>>>>>>>>>>>>>>>>"
713  << std::endl;
714  }
715 
716  // position and direction vector
717  Vector4 BVHPosition4(0., 0., 0, 0);
718  Vector3 BVHMomentum(1., 1., 0.);
719 
720  // the propagator cache
721  PropagatorState BVHState;
722  BVHState.options.debug = debug;
723 
724  // the stepper cache
725  BVHState.stepping.pos4 = BVHPosition4;
726  BVHState.stepping.dir = BVHMomentum.normalized();
727 
728  // Stepper
729  PropagatorState::Stepper BVHStepper;
730 
731  BVHNavigator.initialize(BVHState, BVHStepper);
732 
733  // Check that the currentVolume is set
734  BOOST_CHECK_NE(BVHState.navigation.currentVolume, nullptr);
735  // Check that the currentVolume is the startVolume
736  BOOST_CHECK_EQUAL(BVHState.navigation.currentVolume,
737  BVHState.navigation.startVolume);
738  // Check that the currentSurface is reset to:
739  BOOST_CHECK_EQUAL(BVHState.navigation.currentSurface, nullptr);
740  // No layer has been found
741  BOOST_CHECK_EQUAL(BVHState.navigation.navLayers.size(), 0u);
742  // ACTORS-ABORTERS-TARGET
743  navigator.preStep(BVHState, BVHStepper);
744  // Still no layer
745  BOOST_CHECK_EQUAL(BVHState.navigation.navLayers.size(), 0u);
746  // Surfaces have been found
747  BOOST_CHECK_EQUAL(BVHState.navigation.navSurfaces.size(), 42u);
748 }
749 
750 } // namespace Test
751 } // namespace Acts