HighLAND
ProtonInteractionSystematic.cxx
1 #include "ProtonInteractionSystematic.hxx"
2 #include <cmath>
3 
4 //#define DEBUG
5 //#define DDEBUG
6 
7 
8 const Float_t proton_si::ProtonSIPropagator::_thEnergy = 20 * units::GeV;
9 
10 //##########################################################
11 //Proton cross-section parametrization, GEANT4
12 //##########################################################
13 // Cross-sections for proton nuclear scattering up to 20 GeV, getting the low
14 // energy threshold behaviour right.
15 // H.P. Wellisch (TRIUMF), D. Axen (British Columbia U.). 1996.
16 // Published in Phys.Rev.C54:1329-1332,1996
17 // Implements corrected parameterization from
18 // http://laws.lanl.gov/XCI/PEOPLE/rep/pdf/RPS96.pdf
19 
20 //********************************************************************
21 Double_t proton_si::ProtonSIPropagator::GetProtonInelasticCrossSection(const Double_t& momentum, const Double_t& Z, const Double_t& A) const{
22  //********************************************************************
23 
24  Double_t kineticEnergy = anaUtils::ComputeKineticEnergy(momentum, units::mass_proton);
25 
26  if (kineticEnergy <= 0.) { return 0.; }
27 
28  if (A < Z) { return 0.; }
29 
30 
31  // constant cross section above ~20GeV
32  if (kineticEnergy > _thEnergy) { kineticEnergy = _thEnergy; }
33 
34  Double_t A13 = std::pow(A,-0.3333333333);
35  Double_t nOfNeutrons = A - Z;
36  kineticEnergy /=units::GeV;
37  Double_t alog10E = std::log10(kineticEnergy);
38 
39  const Double_t nuleonRadius = 1.36E-15;
40  const Double_t fac = M_PI*nuleonRadius*nuleonRadius;
41 
42  Double_t b0 = 2.247-0.915*(1 - A13);
43  Double_t fac1 = b0*(1 - A13);
44  Double_t fac2 = 1.;
45  if(nOfNeutrons > 1) { fac2=std::log(((Double_t)(nOfNeutrons))); }
46  Double_t crossSection = 1.0E31*fac*fac2*(1. + 1./A13 - fac1);
47 
48  // high energy correction
49  crossSection *= (1 - 0.15*std::exp(-kineticEnergy))/(1.0 - 0.0007*A);
50 
51  // first try on low energies: rise
52  Double_t ff1= 0.70-0.002*A; // slope of the drop at medium energies.
53  Double_t ff2= 1.00+1/A; // start of the slope.
54  Double_t ff3= 0.8+18/A-0.002*A; // stephight
55 
56  Double_t ff4= 1.0 - (1.0/(1+std::exp(-8*ff1*(alog10E + 1.37*ff2))));
57 
58  crossSection *= (1 + ff3*ff4);
59 
60  // low energy return to zero
61 
62  ff1=1. - 1./A - 0.001*A; // slope of the rise
63  ff2=1.17 - 2.7/A - 0.0014*A; // start of the rise
64 
65  ff4=-8.*ff1*(alog10E + 2.0*ff2);
66 
67  crossSection *= units::millibarn/(1. + std::exp(ff4));
68  return crossSection;
69 }
70 
71 
72 //********************************************************************
73 Double_t proton_si::ProtonSIPropagator::GetCrossSection(const si_syst::InteractionType& type, const Float_t& mom, const Int_t& pdg, TGeoNode* node) const{
74 //********************************************************************
75 
76  // Only work with inelastic at the moment
77  if (type != si_syst::kInelastic) return 0.;
78 
79  (void)pdg;
80 
81  TGeoVolume *volume = node->GetVolume();
82  TGeoMaterial *material = volume->GetMaterial();
83  TGeoMixture *mixture = (TGeoMixture*)material;
84 
85  return GetProtonInelasticCrossSection(mom, mixture->GetZ(), mixture->GetA());
86 
87 }
88 
89 //********************************************************************
90 Bool_t proton_si::ProtonSIPropagator::InVOI(const TVector3& pos) const{
91  //********************************************************************
92 
93  if (_det == SubDetId::kFGD1){
94  // This is the edges of the FGD1 volume, plus all the way out to TPCGasMixture in downstream z.
95  // (Rounded to the next integer value that includes the value from the geometry in its range).
96  Bool_t xOK = -1150.0 < pos.X() && pos.X() < 1150.0;
97  Bool_t yOK = -1170.0 < pos.Y() && pos.Y() < 1230.0;
98  Bool_t zOK = 98.0 < pos.Z() && pos.Z() < 576.0;
99 
100  return xOK && yOK && zOK;
101  }
102  else if (_det == SubDetId::kFGD2){
103  // This is from the TPCGasMixture in upstream z through FGD2 all the way out to TPCGasMixture in downstream z.
104  // (Rounded to the next integer value that includes the value from the geometry in its range).
105  Bool_t xOK = -1150.0 < pos.X() && pos.X() < 1150.0;
106  Bool_t yOK = -1170.0 < pos.Y() && pos.Y() < 1230.0;
107  Bool_t zOK = 1347.0 < pos.Z() && pos.Z() < 1934.0;
108  return xOK && yOK && zOK;
109  }
110  return false;
111 
112 }
virtual Double_t GetCrossSection(const si_syst::InteractionType &, const Float_t &, const Int_t &, TGeoNode *) const
virtual Bool_t InVOI(const TVector3 &) const
Whether a track is in VOI given a position and detector.
Float_t ComputeKineticEnergy(Float_t mom, Float_t mass)
Compute kinetic energy given momentum and mass.
SubDetId::SubDetEnum _det
Keep the relevant sub-detector here for the moment.