1212#ifndef ALICEO2_ITSMFT_TRACKING_MATERIALPHYSICS_H_
1313#define ALICEO2_ITSMFT_TRACKING_MATERIALPHYSICS_H_
1414
15- #include < cstddef>
1615#include < cstdint>
17- #include < type_traits>
1816
1917#include " ReconstructionDataFormats/PID.h"
2018
@@ -38,71 +36,6 @@ struct IntegratedMaterialBudget {
3836 float arealDensityGPerCm2; // /< crossed length*density, g/cm^2
3937};
4038
41- // Reasons a scalar material-physics operation can fail. SourceSurfaceKindMismatch,
42- // NonFiniteState, InvalidStateKinematics, and InvalidCovariance are reserved
43- // for future full-state operations and are never emitted by
44- // calculateMaterialPhysics().
45- enum class MaterialFailureReason : uint8_t {
46- None = 0 ,
47- SourceSurfaceKindMismatch = 1 ,
48- NonFiniteState = 2 ,
49- InvalidStateKinematics = 3 ,
50- InvalidPID = 4 ,
51- ChargedMasslessPID = 5 ,
52- InvalidDirection = 6 ,
53- InvalidMaterial = 7 ,
54- StoppedInMaterial = 8 ,
55- MomentumBelowMinimum = 9 ,
56- ExcessiveScattering = 10 ,
57- InvalidCovariance = 11 ,
58- NonFiniteResult = 12
59- };
60-
61- enum class MaterialOperationFlags : uint8_t {
62- None = 0 ,
63- SubstepCountClamped = 1
64- };
65-
66- // Result of one scalar material-physics evaluation. On failure,
67- // momentumBeforeGeV echoes the input, failure gives the reason, and all other
68- // fields are deterministic zero/None values with no physical meaning.
69- // reserved is always zero.
70- struct MaterialOperationResult {
71- float momentumBeforeGeV;
72- float momentumAfterGeV;
73- float signedEnergyChangeGeV;
74- float highlandTheta2Rad2;
75- float relativeInverseMomentumVariance;
76- uint8_t energyLossSubsteps;
77- MaterialOperationFlags flags;
78- MaterialFailureReason failure;
79- uint8_t reserved;
80-
81- bool ok () const noexcept { return failure == MaterialFailureReason::None; }
82- };
83-
84- // Lock the current in-memory layout; this is not a serialized or device ABI.
85- #define O2_ITSMFT_MATERIAL_ASSERT_LAYOUT (Type, Size, Alignment ) \
86- static_assert (std::is_standard_layout_v<Type>); \
87- static_assert (std::is_trivially_copyable_v<Type>); \
88- static_assert (sizeof (Type) == Size); \
89- static_assert (alignof (Type) == Alignment)
90-
91- O2_ITSMFT_MATERIAL_ASSERT_LAYOUT (IntegratedMaterialBudget, 8 , 4 );
92- O2_ITSMFT_MATERIAL_ASSERT_LAYOUT (MaterialOperationResult, 24 , 4 );
93-
94- #undef O2_ITSMFT_MATERIAL_ASSERT_LAYOUT
95-
96- static_assert (offsetof(MaterialOperationResult, momentumBeforeGeV) == 0 );
97- static_assert (offsetof(MaterialOperationResult, momentumAfterGeV) == 4 );
98- static_assert (offsetof(MaterialOperationResult, signedEnergyChangeGeV) == 8 );
99- static_assert (offsetof(MaterialOperationResult, highlandTheta2Rad2) == 12 );
100- static_assert (offsetof(MaterialOperationResult, relativeInverseMomentumVariance) == 16 );
101- static_assert (offsetof(MaterialOperationResult, energyLossSubsteps) == 20 );
102- static_assert (offsetof(MaterialOperationResult, flags) == 21 );
103- static_assert (offsetof(MaterialOperationResult, failure) == 22 );
104- static_assert (offsetof(MaterialOperationResult, reserved) == 23 );
105-
10639// Detector-neutral, PID/absCharge-aware scalar material-physics kernel.
10740// pid supplies the mass; absCharge supplies |q| for energy-loss and
10841// scattering scale factors. It need not equal PID::getCharge(). For
@@ -114,7 +47,7 @@ static_assert(offsetof(MaterialOperationResult, reserved) == 23);
11447// The PID range is checked before accessing its mass.
11548//
11649// For charged massive states, non-positive beta^2 is rejected before either
117- // material-effect calculation. Failure gives NonFiniteResult.
50+ // material-effect calculation.
11851//
11952// For charged massive states, momentumGeV is the caller-selected physical
12053// momentum; no covariance projection is performed. Energy loss uses the same
@@ -123,29 +56,30 @@ static_assert(offsetof(MaterialOperationResult, reserved) == 23);
12356// requested substep count is
12457// 1 + floor(|dE_full| / eKin * o2::track::ELoss2EKinThreshInv)
12558// with a range-bounded float-to-int conversion, capped at
126- // o2::track::MaxELossIter (50). flags marks SubstepCountClamped when the
127- // request exceeds 50. All arealDensityGPerCm2 is processed; only the
59+ // o2::track::MaxELossIter (50). All arealDensityGPerCm2 is processed; only the
12860// granularity changes. Bethe-Bloch is recomputed from the current momentum
12961// at each substep.
13062// MaterialTraversalDirection::AlongMomentum subtracts energy per substep;
131- // OppositeMomentum adds it; signedEnergyChangeGeV is always
132- // Eafter - Ebefore. A particle whose energy would fall to or below its rest
133- // mass fails with StoppedInMaterial; a particle that completes with
134- // momentum below 0.01 GeV/c fails with MomentumBelowMinimum.
63+ // OppositeMomentum adds it. Reject particles stopped in material or ending
64+ // with momentum below 0.01 GeV/c.
13565//
13666// highlandTheta2Rad2 and relativeInverseMomentumVariance use the simplified
13767// O2 Highland variance (no logarithmic correction) and pre-material momentum,
13868// energy, and beta. Both scale with absCharge^2. highlandTheta2Rad2 > pi^2
139- // fails with ExcessiveScattering .
69+ // is rejected .
14070//
14171// This kernel does not construct track states, detector geometry, or
14272// ITS/MFT/topology/propagation objects.
143- MaterialOperationResult calculateMaterialPhysics (
73+ // Output values are committed only on success.
74+ bool calculateMaterialPhysics (
14475 float momentumGeV,
14576 o2::track::PID pid,
14677 uint8_t absCharge,
14778 MaterialTraversalDirection direction,
148- IntegratedMaterialBudget material) noexcept ;
79+ IntegratedMaterialBudget material,
80+ float & momentumAfterGeV,
81+ float & highlandTheta2Rad2,
82+ float & relativeInverseMomentumVariance) noexcept ;
14983
15084} // namespace o2::itsmft::tracking::material
15185
0 commit comments