File indexing completed on 2025-01-18 09:12:43
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/data/test_case.hpp>
0010 #include <boost/test/unit_test.hpp>
0011
0012 #include "Acts/Definitions/PdgParticle.hpp"
0013 #include "Acts/Definitions/Units.hpp"
0014 #include "Acts/Material/Interactions.hpp"
0015 #include "Acts/Material/Material.hpp"
0016 #include "Acts/Material/MaterialSlab.hpp"
0017 #include "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp"
0018
0019 #include <utility>
0020
0021 namespace data = boost::unit_test::data;
0022 using namespace Acts::UnitLiterals;
0023
0024
0025 static const Acts::Material material = Acts::Test::makeSilicon();
0026
0027
0028 static const double valuesThickness[] = {200_um, 1_mm};
0029 static auto thickness = data::make(valuesThickness);
0030
0031 static const Acts::PdgParticle pdg[] = {Acts::eElectron, Acts::eMuon,
0032 Acts::ePionPlus, Acts::eProton};
0033 static const double mass[] = {511_keV, 105.7_MeV, 139.6_MeV, 938.3_MeV};
0034 static const double charge[] = {-1_e, -1_e, 1_e, 1_e};
0035 static const auto particle =
0036 data::make(pdg) ^ data::make(mass) ^ data::make(charge);
0037
0038 static const auto momentum_low = data::xrange(100_MeV, 10_GeV, 100_MeV);
0039 static const auto momentum_med = data::xrange(10_GeV, 100_GeV, 10_GeV);
0040 static const auto momentum_high = data::xrange(100_GeV, 10_TeV, 100_GeV);
0041 static const auto momentum = momentum_low + momentum_med + momentum_high;
0042
0043 BOOST_AUTO_TEST_SUITE(interactions)
0044
0045
0046 BOOST_DATA_TEST_CASE(energy_loss_consistency, thickness* particle* momentum, x,
0047 i, m, q, p) {
0048 const auto slab = Acts::MaterialSlab(material, x);
0049 const auto qOverP = q / p;
0050 const auto absQ = std::abs(q);
0051 const auto absPdg = Acts::makeAbsolutePdgParticle(i);
0052
0053 auto dEBethe = computeEnergyLossBethe(slab, m, qOverP, absQ);
0054 auto dELandau = computeEnergyLossLandau(slab, m, qOverP, absQ);
0055 auto dELandauSigma = computeEnergyLossLandauSigma(slab, m, qOverP, absQ);
0056 auto dELandauSigmaQOverP =
0057 computeEnergyLossLandauSigmaQOverP(slab, m, qOverP, absQ);
0058 auto dERad = computeEnergyLossRadiative(slab, absPdg, m, qOverP, absQ);
0059 auto dEMean = computeEnergyLossMean(slab, absPdg, m, qOverP, absQ);
0060 auto dEMode = computeEnergyLossMode(slab, absPdg, m, qOverP, absQ);
0061
0062 BOOST_CHECK_LT(0, dEBethe);
0063 BOOST_CHECK_LT(0, dELandau);
0064 BOOST_CHECK_LT(0, dELandauSigma);
0065 BOOST_CHECK_LT(0, dELandauSigmaQOverP);
0066 BOOST_CHECK_LE(dELandauSigma, dEBethe);
0067
0068 BOOST_CHECK_LE(0, dERad);
0069 BOOST_CHECK_LT(0, dEMean);
0070 BOOST_CHECK_LT(0, dEMode);
0071 BOOST_CHECK_LE((dEBethe + dERad), dEMean);
0072
0073
0074 }
0075
0076
0077 BOOST_DATA_TEST_CASE(multiple_scattering_consistency,
0078 thickness* particle* momentum, x, i, m, q, p) {
0079 const auto slab = Acts::MaterialSlab(material, x);
0080 const auto slabDoubled = Acts::MaterialSlab(material, 2 * x);
0081 const auto qOverP = q / p;
0082 const auto qOver2P = q / (2 * p);
0083 const auto absQ = std::abs(q);
0084 const auto absPdg = Acts::makeAbsolutePdgParticle(i);
0085
0086 auto t0 = computeMultipleScatteringTheta0(slab, absPdg, m, qOverP, absQ);
0087 BOOST_CHECK_LT(0, t0);
0088
0089 auto tanti = computeMultipleScatteringTheta0(slab, absPdg, m, -qOverP, absQ);
0090 BOOST_CHECK_LT(0, tanti);
0091 BOOST_CHECK_EQUAL(t0, tanti);
0092
0093 auto t2x =
0094 computeMultipleScatteringTheta0(slabDoubled, absPdg, m, qOverP, absQ);
0095 BOOST_CHECK_LT(0, t2x);
0096 BOOST_CHECK_LT(t0, t2x);
0097
0098 auto t2p = computeMultipleScatteringTheta0(slab, absPdg, m, qOver2P, absQ);
0099 BOOST_CHECK_LT(0, t2p);
0100 BOOST_CHECK_LT(t2p, t0);
0101 }
0102
0103
0104 BOOST_DATA_TEST_CASE(vacuum, thickness* particle* momentum, x, i, m, q, p) {
0105 const auto vacuum = Acts::MaterialSlab(Acts::Material(), x);
0106 const auto qOverP = q / p;
0107 const auto absQ = std::abs(q);
0108 const auto absPdg = Acts::makeAbsolutePdgParticle(i);
0109
0110 BOOST_CHECK_EQUAL(computeEnergyLossBethe(vacuum, m, qOverP, absQ), 0);
0111 BOOST_CHECK_EQUAL(computeEnergyLossLandau(vacuum, m, qOverP, absQ), 0);
0112 BOOST_CHECK_EQUAL(computeEnergyLossLandauSigma(vacuum, m, qOverP, absQ), 0);
0113 BOOST_CHECK_EQUAL(computeEnergyLossLandauSigmaQOverP(vacuum, m, qOverP, absQ),
0114 0);
0115 BOOST_CHECK_EQUAL(computeEnergyLossRadiative(vacuum, absPdg, m, qOverP, absQ),
0116 0);
0117 BOOST_CHECK_EQUAL(computeEnergyLossMean(vacuum, absPdg, m, qOverP, absQ), 0);
0118 BOOST_CHECK_EQUAL(computeEnergyLossMode(vacuum, absPdg, m, qOverP, absQ), 0);
0119 BOOST_CHECK_EQUAL(
0120 computeMultipleScatteringTheta0(vacuum, absPdg, m, qOverP, absQ), 0);
0121 }
0122
0123
0124
0125 static const double momentum[] = {0.1003_GeV, 1.101_GeV, 10.11_GeV, 100.1_GeV};
0126 static const double energy_loss[] = {2.608, 1.803, 2.177, 2.451};
0127
0128 BOOST_DATA_TEST_CASE(silicon_energy_loss,
0129 data::make(momentum) ^ data::make(energy_loss), p, loss) {
0130 const Acts::Material silicon = Acts::Test::makeSilicon();
0131 const auto thickness = 1_cm;
0132 const auto slab = Acts::MaterialSlab(silicon, thickness);
0133 const auto m = 105.7_MeV;
0134 const auto q = -1_e;
0135 const auto qOverP = q / p;
0136 const auto absQ = std::abs(q);
0137
0138
0139 BOOST_CHECK_CLOSE(computeEnergyLossBethe(slab, m, qOverP, absQ) / thickness /
0140 slab.material().massDensity() / (1_MeV * 1_cm2 / 1_g),
0141 loss, 5.);
0142 }
0143
0144
0145 BOOST_AUTO_TEST_CASE(silicon_landau) {
0146 const Acts::Material silicon = Acts::Test::makeSilicon();
0147 const auto thickness = 0.17_cm;
0148 const auto slab = Acts::MaterialSlab(silicon, thickness);
0149 const float m = 105.7_MeV;
0150 const float q = -1_e;
0151 const float qOverP = q / 10_GeV;
0152 const float absQ = std::abs(q);
0153
0154
0155 const auto dE = computeEnergyLossLandau(slab, m, qOverP, absQ) / 1_MeV;
0156 BOOST_CHECK_CLOSE(dE, 0.525, 5.);
0157
0158
0159 const auto fwhm =
0160 Acts::computeEnergyLossLandauFwhm(slab, m, qOverP, absQ) / 1_MeV;
0161 BOOST_CHECK_CLOSE(fwhm, 0.13, 10.);
0162 }
0163
0164 BOOST_AUTO_TEST_SUITE_END()