9 #include <boost/test/unit_test.hpp>
65 #include <type_traits>
70 class ISurfaceMaterial;
74 namespace tt = boost::test_tools;
75 using namespace Acts::UnitLiterals;
83 static constexpr
auto eps = 3 * std::numeric_limits<double>::epsilon();
90 template <
typename stepper_state_t>
94 : stepping(std::
move(sState)) {
102 double stepSizeCutOff = 0.;
103 unsigned int maxRungeKuttaStepTrials = 10000;
108 struct MockNavigator {};
133 template <
typename propagator_state_t,
typename stepper_t,
134 typename navigator_t>
138 const double tolerance = state.options.targetTolerance;
139 if (maxX - std::abs(stepper.position(state.stepping).x()) <= tolerance ||
140 std::abs(stepper.position(state.stepping).y()) >= 0.5_m ||
141 std::abs(stepper.position(state.stepping).z()) >= 0.5_m) {
175 template <
typename propagator_state_t,
typename stepper_t,
176 typename navigator_t>
180 result.
position.push_back(stepper.position(state.stepping));
181 result.
momentum.push_back(stepper.momentum(state.stepping));
189 auto bField = std::make_shared<ConstantBField>(
Vector3(1., 2.5, 33.33));
206 BOOST_CHECK_EQUAL(esState.jacToGlobal, BoundToFreeMatrix::Zero());
207 BOOST_CHECK_EQUAL(esState.jacTransport, FreeMatrix::Identity());
208 BOOST_CHECK_EQUAL(esState.derivative, FreeVector::Zero());
209 BOOST_CHECK(!esState.covTransport);
210 BOOST_CHECK_EQUAL(esState.cov, Covariance::Zero());
211 BOOST_CHECK_EQUAL(esState.pathAccumulated, 0.);
212 BOOST_CHECK_EQUAL(esState.stepSize.value(),
stepSize);
213 BOOST_CHECK_EQUAL(esState.previousStepSize, 0.);
220 BOOST_CHECK_EQUAL(es.
charge(esState), 0.);
228 BOOST_CHECK_NE(esState.jacToGlobal, BoundToFreeMatrix::Zero());
229 BOOST_CHECK(esState.covTransport);
230 BOOST_CHECK_EQUAL(esState.cov, cov);
239 auto bField = std::make_shared<ConstantBField>(
Vector3(1., 2.5, 33.33));
263 BOOST_CHECK_EQUAL(es.
getField(esState, pos).value(),
264 bField->getField(pos, bCache).value());
267 const std::string originalStepSize = esState.stepSize.toString();
270 BOOST_CHECK_EQUAL(esState.previousStepSize, stepSize);
271 BOOST_CHECK_EQUAL(esState.stepSize.value(), -1337.);
274 BOOST_CHECK_EQUAL(esState.stepSize.value(),
stepSize);
279 auto curvPars = std::get<0>(curvState);
284 BOOST_CHECK(curvPars.covariance().has_value());
285 BOOST_CHECK_NE(*curvPars.covariance(),
cov);
293 double newTime(321.);
294 es.
update(esState, newPos, newMom.normalized(), charge / newMom.norm(),
296 BOOST_CHECK_EQUAL(es.
position(esState), newPos);
297 BOOST_CHECK_EQUAL(es.
direction(esState), newMom.normalized());
300 BOOST_CHECK_EQUAL(es.
time(esState), newTime);
305 BOOST_CHECK_NE(esState.cov, cov);
306 BOOST_CHECK_NE(esState.jacToGlobal, BoundToFreeMatrix::Zero());
307 BOOST_CHECK_EQUAL(esState.jacTransport, FreeMatrix::Identity());
308 BOOST_CHECK_EQUAL(esState.derivative, FreeVector::Zero());
321 BOOST_CHECK_EQUAL(ps.
stepping.derivative, FreeVector::Zero());
322 BOOST_CHECK_EQUAL(ps.
stepping.jacTransport, FreeMatrix::Identity());
331 BOOST_CHECK_NE(ps.
stepping.derivative, FreeVector::Zero());
332 BOOST_CHECK_NE(ps.
stepping.jacTransport, FreeMatrix::Identity());
339 double absMom2 = 8.5;
343 charge2 / absMom2, cov2,
350 auto copyState = [&](
auto&
field,
const auto&
state) {
351 using field_t = std::decay_t<decltype(field)>;
354 copy.pars =
state.pars;
355 copy.covTransport =
state.covTransport;
356 copy.cov =
state.cov;
357 copy.jacobian =
state.jacobian;
358 copy.jacToGlobal =
state.jacToGlobal;
359 copy.jacTransport =
state.jacTransport;
360 copy.derivative =
state.derivative;
361 copy.pathAccumulated =
state.pathAccumulated;
362 copy.stepSize =
state.stepSize;
363 copy.previousStepSize =
state.previousStepSize;
366 MagneticFieldProvider::Cache::make<typename field_t::Cache>(
367 state.fieldCache.template get<typename field_t::Cache>());
369 copy.geoContext =
state.geoContext;
370 copy.extension =
state.extension;
371 copy.auctioneer =
state.auctioneer;
372 copy.stepData =
state.stepData;
383 BOOST_CHECK_NE(esStateCopy.
jacToGlobal, BoundToFreeMatrix::Zero());
385 BOOST_CHECK_EQUAL(esStateCopy.
jacTransport, FreeMatrix::Identity());
386 BOOST_CHECK_EQUAL(esStateCopy.
derivative, FreeVector::Zero());
388 BOOST_CHECK_EQUAL(esStateCopy.
cov, cov2);
389 BOOST_CHECK_EQUAL(es.
position(esStateCopy),
390 freeParams.template segment<3>(
eFreePos0));
391 BOOST_CHECK_EQUAL(es.
direction(esStateCopy),
392 freeParams.template segment<3>(
eFreeDir0).normalized());
396 BOOST_CHECK_EQUAL(es.
time(esStateCopy), freeParams[
eFreeTime]);
398 BOOST_CHECK_EQUAL(esStateCopy.
stepSize.
value(), navDir * stepSize2);
406 BOOST_CHECK_NE(esStateCopy.
jacToGlobal, BoundToFreeMatrix::Zero());
408 BOOST_CHECK_EQUAL(esStateCopy.
jacTransport, FreeMatrix::Identity());
409 BOOST_CHECK_EQUAL(esStateCopy.
derivative, FreeVector::Zero());
411 BOOST_CHECK_EQUAL(esStateCopy.
cov, cov2);
412 BOOST_CHECK_EQUAL(es.
position(esStateCopy),
413 freeParams.template segment<3>(
eFreePos0));
414 BOOST_CHECK_EQUAL(es.
direction(esStateCopy),
415 freeParams.template segment<3>(
eFreeDir0).normalized());
417 std::abs(1. / freeParams[eFreeQOverP]));
419 BOOST_CHECK_EQUAL(es.
time(esStateCopy), freeParams[
eFreeTime]);
422 std::numeric_limits<double>::max());
430 BOOST_CHECK_NE(esStateCopy.
jacToGlobal, BoundToFreeMatrix::Zero());
432 BOOST_CHECK_EQUAL(esStateCopy.
jacTransport, FreeMatrix::Identity());
433 BOOST_CHECK_EQUAL(esStateCopy.
derivative, FreeVector::Zero());
435 BOOST_CHECK_EQUAL(esStateCopy.
cov, cov2);
436 BOOST_CHECK_EQUAL(es.
position(esStateCopy),
437 freeParams.template segment<3>(
eFreePos0));
438 BOOST_CHECK_EQUAL(es.
direction(esStateCopy),
439 freeParams.template segment<3>(
eFreeDir0).normalized());
441 std::abs(1. / freeParams[eFreeQOverP]));
443 BOOST_CHECK_EQUAL(es.
time(esStateCopy), freeParams[
eFreeTime]);
446 std::numeric_limits<double>::max());
450 auto plane = Surface::makeShared<PlaneSurface>(
pos, dir.normalized());
460 Surface::makeShared<PlaneSurface>(pos + navDir * 2. * dir, dir);
473 esState.stepSize.setUser(navDir * stepSize);
489 BOOST_CHECK(boundPars.covariance().has_value());
490 BOOST_CHECK_NE(*boundPars.covariance(),
cov);
497 BOOST_CHECK_NE(esState.cov, cov);
498 BOOST_CHECK_NE(esState.jacToGlobal, BoundToFreeMatrix::Zero());
499 BOOST_CHECK_EQUAL(esState.jacTransport, FreeMatrix::Identity());
500 BOOST_CHECK_EQUAL(esState.derivative, FreeVector::Zero());
504 bp.referenceSurface(),
tgContext, bp.parameters());
509 es.
update(esState, freeParams, bp.parameters(), 2 * (*bp.covariance()),
520 double h0 = esState.stepSize.value();
525 auto nBfield = std::make_shared<NullBField>();
529 PropState nps(navDir, copyState(*nBfield, nesState));
531 nps.options.tolerance = 1
e-21;
532 nps.options.stepSizeCutOff = 1e20;
534 BOOST_CHECK(!res.ok());
535 BOOST_CHECK_EQUAL(res.error(), EigenStepperError::StepSizeStalled);
538 nps.options.stepSizeCutOff = 0.;
539 nps.options.maxRungeKuttaStepTrials = 0.;
541 BOOST_CHECK(!res.ok());
542 BOOST_CHECK_EQUAL(res.error(), EigenStepperError::StepSizeAdjustmentFailed);
560 vConf.
length = {1_m, 1_m, 1_m};
564 conf.
length = {1_m, 1_m, 1_m};
570 [=](
const auto& context,
const auto& inner,
const auto& vb) {
574 std::shared_ptr<const TrackingGeometry> vacuum =
578 Navigator naviVac({vacuum,
true,
true,
true});
583 const Vector3 startMom = 1_GeV * startDir;
588 ActionList<StepCollector> aList;
589 AbortList<EndOfWorld> abortList;
593 AbortList<EndOfWorld>>
601 auto bField = std::make_shared<ConstantBField>(
Vector3(0., 0., 0.));
613 const auto& result = prop.propagate(sbtp, propOpts).value();
625 for (
const auto& mom : stepResult.
momentum) {
630 ActionList<StepCollector> aListDef;
642 propDef(esDef, naviVac);
645 const auto& resultDef = propDef.
propagate(sbtp, propOptsDef).value();
651 BOOST_CHECK_EQUAL(stepResult.
position.size(), stepResultDef.
position.size());
652 for (
unsigned int i = 0;
i < stepResult.
position.size();
i++) {
655 BOOST_CHECK_EQUAL(stepResult.
momentum.size(), stepResultDef.
momentum.size());
656 for (
unsigned int i = 0;
i < stepResult.
momentum.size();
i++) {
665 vConf.
length = {1_m, 1_m, 1_m};
667 std::make_shared<HomogeneousVolumeMaterial>(
makeBeryllium());
670 conf.position = {0.5_m, 0., 0.};
671 conf.length = {1_m, 1_m, 1_m};
677 [=](
const auto& context,
const auto& inner,
const auto& vb) {
681 std::shared_ptr<const TrackingGeometry>
material =
690 const Vector3 startMom = 5_GeV * startDir;
695 ActionList<StepCollector> aList;
696 AbortList<EndOfWorld> abortList;
700 AbortList<EndOfWorld>>
708 auto bField = std::make_shared<ConstantBField>(
Vector3(0., 0., 0.));
720 const auto& result = prop.propagate(sbtp, propOpts).value();
731 BOOST_CHECK_GT(std::abs(
pos.x()), 1_um);
734 for (
const auto& mom : stepResult.
momentum) {
737 if (mom == stepResult.
momentum.front()) {
740 BOOST_CHECK_LT(mom.x(), 5_GeV);
747 AbortList<EndOfWorld>>
758 propDense(esDense, naviMat);
761 const auto& resultDense = propDense.
propagate(sbtp, propOptsDense).value();
767 BOOST_CHECK_EQUAL(stepResult.
position.size(),
769 for (
unsigned int i = 0;
i < stepResult.
position.size();
i++) {
772 BOOST_CHECK_EQUAL(stepResult.
momentum.size(),
774 for (
unsigned int i = 0;
i < stepResult.
momentum.size();
i++) {
783 StepperExtensionList<DefaultExtension, DenseEnvironmentExtension>,
784 detail::HighestValidAuctioneer>
787 DenseEnvironmentExtension>,
788 detail::HighestValidAuctioneer>,
792 const auto& resultB = propB.propagate(sbtp, propOptsDense).value();
801 BOOST_CHECK_GT(std::abs(
pos.x()), 1_um);
803 BOOST_CHECK_GT(std::abs(
pos.z()), 0.125_um);
806 for (
const auto& mom : stepResultB.
momentum) {
807 if (mom == stepResultB.
momentum.front()) {
810 BOOST_CHECK_NE(mom.x(), 5_GeV);
812 BOOST_CHECK_NE(mom.z(), 0.);
820 vConfVac1.
position = {0.5_m, 0., 0.};
821 vConfVac1.
length = {1_m, 1_m, 1_m};
822 vConfVac1.
name =
"First vacuum volume";
824 vConfMat.
position = {1.5_m, 0., 0.};
825 vConfMat.
length = {1_m, 1_m, 1_m};
827 std::make_shared<const HomogeneousVolumeMaterial>(
makeBeryllium());
828 vConfMat.
name =
"Material volume";
830 vConfVac2.
position = {2.5_m, 0., 0.};
831 vConfVac2.
length = {1_m, 1_m, 1_m};
832 vConfVac2.
name =
"Second vacuum volume";
834 conf.
volumeCfg = {vConfVac1, vConfMat, vConfVac2};
836 conf.
length = {3_m, 1_m, 1_m};
842 [=](
const auto& context,
const auto& inner,
const auto& vb) {
849 Navigator naviDet({det,
true,
true,
true});
853 1_e / 5_GeV, Covariance::Identity(),
857 AbortList<EndOfWorld> abortList;
862 AbortList<EndOfWorld>>
864 propOpts.abortList = abortList;
865 propOpts.maxSteps = 1000;
866 propOpts.maxStepSize = 1.5_m;
869 auto bField = std::make_shared<ConstantBField>(
Vector3(0., 1_T, 0.));
881 const auto& result = prop.propagate(sbtp, propOpts).value();
888 std::vector<Surface const*> surs;
889 std::vector<std::shared_ptr<const BoundarySurfaceT<TrackingVolume>>>
890 boundaries = det->lowestTrackingVolume(
tgContext, {0.5_m, 0., 0.})
891 ->boundarySurfaces();
892 for (
auto&
b : boundaries) {
893 if (
b->surfaceRepresentation().center(
tgContext).x() == 1_m) {
894 surs.push_back(&(
b->surfaceRepresentation()));
899 det->lowestTrackingVolume(
tgContext, {1.5_m, 0., 0.})->boundarySurfaces();
900 for (
auto&
b : boundaries) {
901 if (
b->surfaceRepresentation().center(
tgContext).x() == 2_m) {
902 surs.push_back(&(
b->surfaceRepresentation()));
907 det->lowestTrackingVolume(
tgContext, {2.5_m, 0., 0.})->boundarySurfaces();
908 for (
auto&
b : boundaries) {
909 if (
b->surfaceRepresentation().center(
tgContext).x() == 3_m) {
910 surs.push_back(&(
b->surfaceRepresentation()));
928 propDef(esDef, naviDet);
931 const auto& resultDef =
932 propDef.
propagate(sbtp, *(surs[0]), propOptsDef).value();
937 std::pair<Vector3, Vector3> endParams, endParamsControl;
938 for (
unsigned int i = 0;
i < stepResultDef.
position.size();
i++) {
939 if (1_m - stepResultDef.
position[
i].x() < 1
e-4) {
945 for (
unsigned int i = 0;
i < stepResult.
position.size();
i++) {
946 if (1_m - stepResult.
position[
i].x() < 1
e-4) {
971 DenseStepperPropagatorOptions<ActionList<StepCollector>,
972 AbortList<EndOfWorld>>
975 propOptsDense.abortList = abortList;
976 propOptsDense.maxSteps = 1000;
977 propOptsDense.maxStepSize = 1.5_m;
983 propDense(esDense, naviDet);
986 const auto& resultDense =
987 propDense.
propagate(sbtpPiecewise, *(surs[1]), propOptsDense).value();
992 for (
unsigned int i = 0;
i < stepResultDense.
position.size();
i++) {
993 if (2_m - stepResultDense.
position[
i].x() < 1
e-4) {
994 endParams = std::make_pair(stepResultDense.
position[
i],
999 for (
unsigned int i = 0;
i < stepResult.
position.size();
i++) {
1000 if (2_m - stepResult.
position[
i].x() < 1
e-4) {
1014 double rotationAngle = M_PI * 0.5;
1015 Vector3 xPos(cos(rotationAngle), 0., sin(rotationAngle));
1017 Vector3 zPos(-sin(rotationAngle), 0., cos(rotationAngle));
1027 std::make_shared<const RectangleBounds>(
RectangleBounds(0.5_m, 0.5_m));
1028 sConf1.
surMat = std::shared_ptr<const ISurfaceMaterial>(
1040 std::make_shared<const RectangleBounds>(
RectangleBounds(0.5_m, 0.5_m));
1041 sConf2.
surMat = std::shared_ptr<const ISurfaceMaterial>(
1048 muConf1.
position = {2.3_m, 0., 0.};
1049 muConf1.
length = {20._cm, 20._cm, 20._cm};
1051 std::make_shared<HomogeneousVolumeMaterial>(
makeBeryllium());
1052 muConf1.
name =
"MDT1";
1054 muConf2.
position = {2.7_m, 0., 0.};
1055 muConf2.
length = {20._cm, 20._cm, 20._cm};
1057 std::make_shared<HomogeneousVolumeMaterial>(
makeBeryllium());
1058 muConf2.
name =
"MDT2";
1062 vConf1.
length = {1._m, 1._m, 1._m};
1063 vConf1.
layerCfg = {lConf1, lConf2};
1064 vConf1.
name =
"Tracker";
1067 vConf2.
length = {1._m, 1._m, 1._m};
1069 std::make_shared<HomogeneousVolumeMaterial>(
makeBeryllium());
1070 vConf2.
name =
"Calorimeter";
1073 vConf3.
length = {1._m, 1._m, 1._m};
1075 vConf3.
name =
"Muon system";
1077 conf.
volumeCfg = {vConf1, vConf2, vConf3};
1079 conf.
length = {3._m, 1._m, 1._m};
1085 [=](
const auto& context,
const auto& inner,
const auto& vb) {
1089 std::shared_ptr<const TrackingGeometry>
detector =
1097 1_e / 1_GeV, Covariance::Identity(),
1102 AbortList<EndOfWorld>>
1108 auto bField = std::make_shared<ConstantBField>(
Vector3(0., 0., 0.));
1120 const auto& result = prop.propagate(sbtp, propOpts).value();
1125 double lastMomentum = stepResult.
momentum[0].x();
1126 for (
unsigned int i = 0;
i < stepResult.
position.size();
i++) {
1128 if ((stepResult.
position[
i].x() > 0.3_m &&
1138 BOOST_CHECK_LE(stepResult.
momentum[
i].x(), lastMomentum);
1139 lastMomentum = stepResult.
momentum[
i].x();
1143 if (stepResult.
position[
i].x() < 0.3_m ||
1150 BOOST_CHECK_EQUAL(stepResult.
momentum[
i].x(), lastMomentum);