Project
Loading...
Searching...
No Matches
MaterialPhysics.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include <cmath>
15
16// Reuse the public energy-loss constants and Bethe-Bloch helper. These
17// headers are implementation details of this translation unit.
20
22{
23
24namespace
25{
26constexpr float kHighlandConst2 = 0.0136f * 0.0136f;
27constexpr float kStragglingConst = 0.0007f;
28constexpr float kMinMomentumGeV = 0.01f;
29
30// Compute the capped substep count without an out-of-range float-to-int
31// conversion.
32uint8_t classifySubsteps(float fullStepEnergyLossGeV, float kineticEnergyGeV) noexcept
33{
34 const float ratio = std::fabs(fullStepEnergyLossGeV) / kineticEnergyGeV * o2::track::ELoss2EKinThreshInv;
35 if (ratio >= static_cast<float>(o2::track::MaxELossIter)) {
36 return static_cast<uint8_t>(o2::track::MaxELossIter);
37 }
38 // Keep the conversion in range even when ratio is unordered. Subsequent
39 // arithmetic remains responsible for propagating invalid inputs.
40 const float boundedRatio = ratio < static_cast<float>(o2::track::MaxELossIter) ? ratio : 0.f;
41 const int requested = 1 + static_cast<int>(boundedRatio);
42 return static_cast<uint8_t>(requested);
43}
44
45} // namespace
46
48 float momentumGeV,
50 uint8_t absCharge,
53 float& momentumAfterGeV,
54 float& outHighlandTheta2Rad2,
55 float& outRelativeInverseMomentumVariance) noexcept
56{
58 return false;
59 }
60 if (material.xOverX0 < 0.f || material.arealDensityGPerCm2 < 0.f) {
61 return false;
62 }
63 if (momentumGeV <= 0.f) {
64 return false;
65 }
66 if (pid.getID() >= o2::track::PID::NIDsTot) {
67 return false;
68 }
69 const float mass = pid.getMass();
70 if (mass == 0.f) {
71 return false;
72 }
73
74 const float q2 = static_cast<float>(absCharge) * static_cast<float>(absCharge);
75 const float p0 = momentumGeV;
76 const float p0Squared = p0 * p0;
77 const float e0 = std::sqrt(p0Squared + mass * mass);
78 const float beta2 = p0Squared / (e0 * e0);
79 if (beta2 <= 0.f) {
80 return false;
81 }
82
83 float e = e0;
84 float p = p0;
85
86 if (material.arealDensityGPerCm2 > 0.f) {
87 const float ekin = e0 - mass;
88 const float bg0 = p0 / mass;
89 const float dedx0 = o2::track::BetheBlochSolidOpt<float>(bg0) * q2;
90 const float fullStepEnergyLoss = dedx0 * material.arealDensityGPerCm2;
91
92 const uint8_t substeps = classifySubsteps(fullStepEnergyLoss, ekin);
93
94 const float arealDensityStep = material.arealDensityGPerCm2 / static_cast<float>(substeps);
95 for (uint8_t i = 0; i < substeps; ++i) {
96 const float bg = p / mass;
97 const float dedx = o2::track::BetheBlochSolidOpt<float>(bg) * q2;
98 const float dE = dedx * arealDensityStep;
99 e = (direction == MaterialTraversalDirection::AlongMomentum) ? (e - dE) : (e + dE);
100 if (e <= mass) {
101 return false;
102 }
103 p = std::sqrt(e * e - mass * mass);
104 }
105 }
106
107 if (p < kMinMomentumGeV) {
108 return false;
109 }
110 const float signedEnergyChangeGeV = e - e0;
111
112 float highlandTheta2Rad2 = 0.f;
113 if (material.xOverX0 > 0.f) {
114 highlandTheta2Rad2 = kHighlandConst2 / (beta2 * p0 * p0) * material.xOverX0 * q2;
115 if (highlandTheta2Rad2 > o2::constants::math::PI * o2::constants::math::PI) {
116 return false;
117 }
118 }
119
120 float relativeInverseMomentumVariance = 0.f;
121 if (signedEnergyChangeGeV != 0.f) {
122 relativeInverseMomentumVariance = kStragglingConst * kStragglingConst * std::fabs(signedEnergyChangeGeV) * e0 * e0 / (p0 * p0 * p0 * p0);
123 }
124
125 momentumAfterGeV = p;
126 outHighlandTheta2Rad2 = highlandTheta2Rad2;
127 outRelativeInverseMomentumVariance = relativeInverseMomentumVariance;
128 return true;
129}
130
131} // namespace o2::itsmft::tracking::material
int32_t i
uint16_t pid
Definition RawData.h:2
uint8_t itsSharedClusterMap uint8_t
bool calculateMaterialPhysics(float momentumGeV, o2::track::PID pid, uint8_t absCharge, MaterialTraversalDirection direction, IntegratedMaterialBudget material, float &momentumAfterGeV, float &highlandTheta2Rad2, float &relativeInverseMomentumVariance) noexcept