Public Member Functions | Private Member Functions | Private Attributes | List of all members
larg4::ISCalcNESTLAr Class Reference

#include <ISCalcNESTLAr.h>

Inheritance diagram for larg4::ISCalcNESTLAr:
larg4::ISCalc

Public Member Functions

 ISCalcNESTLAr (CLHEP::HepRandomEngine &fEngine)
 
double EFieldAtStep (double efield, sim::SimEnergyDeposit const &edep) override
 
ISCalcData CalcIonAndScint (detinfo::DetectorPropertiesData const &detProp, sim::SimEnergyDeposit const &edep) override
 
- Public Member Functions inherited from larg4::ISCalc
virtual ~ISCalc ()=default
 

Private Member Functions

int BinomFluct (int N0, double prob)
 
double CalcElectronLET (double E)
 
double GetScintYieldRatio (sim::SimEnergyDeposit const &edep)
 

Private Attributes

CLHEP::HepRandomEngine & fEngine
 
const spacecharge::SpaceChargefSCE
 
const detinfo::LArPropertiesfLArProp
 

Detailed Description

Definition at line 23 of file ISCalcNESTLAr.h.

Constructor & Destructor Documentation

larg4::ISCalcNESTLAr::ISCalcNESTLAr ( CLHEP::HepRandomEngine &  fEngine)
explicit

Definition at line 31 of file ISCalcNESTLAr.cxx.

32  : fEngine(Engine)
33  , fSCE{lar::providerFrom<spacecharge::SpaceChargeService>()}
34  , fLArProp{lar::providerFrom<detinfo::LArPropertiesService>()}
35  {
36  std::cout << "ISCalcNESTLAr Initialize." << std::endl;
37  }
CLHEP::HepRandomEngine & fEngine
Definition: ISCalcNESTLAr.h:34
const spacecharge::SpaceCharge * fSCE
Definition: ISCalcNESTLAr.h:35
const detinfo::LArProperties * fLArProp
Definition: ISCalcNESTLAr.h:36
QTextStream & endl(QTextStream &s)

Member Function Documentation

int larg4::ISCalcNESTLAr::BinomFluct ( int  N0,
double  prob 
)
private

Definition at line 176 of file ISCalcNESTLAr.cxx.

177  {
178  CLHEP::RandGauss GaussGen(fEngine);
179  CLHEP::RandFlat UniformGen(fEngine);
180 
181  double mean = N0 * prob;
182  double sigma = sqrt(N0 * prob * (1 - prob));
183  int N1 = 0;
184  if (prob == 0.00) { return N1; }
185  if (prob == 1.00) { return N0; }
186 
187  if (N0 < 10) {
188  for (int i = 0; i < N0; i++) {
189  if (UniformGen.fire() < prob) { N1++; }
190  }
191  }
192  else {
193  N1 = int(floor(GaussGen.fire(mean, sigma) + 0.5));
194  }
195  if (N1 > N0) { N1 = N0; }
196  if (N1 < 0) { N1 = 0; }
197  return N1;
198  }
CLHEP::HepRandomEngine & fEngine
Definition: ISCalcNESTLAr.h:34
Definition: group.cpp:53
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:16
double larg4::ISCalcNESTLAr::CalcElectronLET ( double  E)
private

Definition at line 202 of file ISCalcNESTLAr.cxx.

203  {
204  double LET;
205 
206  if (E >= 1) {
207  LET = 116.70 - 162.97 * log10(E) + 99.361 * pow(log10(E), 2) - 33.405 * pow(log10(E), 3) +
208  6.5069 * pow(log10(E), 4) - 0.69334 * pow(log10(E), 5) + .031563 * pow(log10(E), 6);
209  }
210  else if (E > 0 && E < 1) {
211  LET = 100;
212  }
213  else {
214  LET = 0;
215  }
216 
217  return LET;
218  }
constexpr T pow(T x)
Definition: pow.h:72
ISCalcData larg4::ISCalcNESTLAr::CalcIonAndScint ( detinfo::DetectorPropertiesData const &  detProp,
sim::SimEnergyDeposit const &  edep 
)
overridevirtual

Implements larg4::ISCalc.

Definition at line 41 of file ISCalcNESTLAr.cxx.

43  {
44  CLHEP::RandGauss GaussGen(fEngine);
45  CLHEP::RandFlat UniformGen(fEngine);
46 
47  double yieldFactor = 1.0; // default quenching factor, for electronic recoils
48  double excitationRatio =
49  0.21; // ratio for light particle in LAr, such as e-, mu-, Aprile et. al book
50 
51  double const energyDeposit = edep.Energy();
52  if (energyDeposit < 1 * CLHEP::eV) // too small energy deposition
53  {
54  return {0., 0., 0., 0.};
55  }
56 
57  int pdgcode = edep.PdgCode();
58 
59  geo::Length_t startx = edep.StartX();
60  geo::Length_t starty = edep.StartY();
61  geo::Length_t startz = edep.StartZ();
62  geo::Length_t endx = edep.EndX();
63  geo::Length_t endy = edep.EndY();
64  geo::Length_t endz = edep.EndZ();
65 
66  double DokeBirks[3];
67 
68  double eField = EFieldAtStep(detProp.Efield(), edep);
69  if (eField) {
70  DokeBirks[0] = 0.07 * pow((eField / 1.0e3), -0.85);
71  DokeBirks[2] = 0.00;
72  }
73  else {
74  DokeBirks[0] = 0.0003;
75  DokeBirks[2] = 0.75;
76  }
77 
78  double Density = detProp.Density() /
79  (CLHEP::g / CLHEP::cm3); // argon density at the temperature from Temperature()
80 
81  // nuclear recoil quenching "L" factor: total yield is
82  // reduced for nuclear recoil as per Lindhard theory
83  double epsilon = 11.5 * (energyDeposit / CLHEP::keV) * pow(LAr_Z, (-7. / 3.));
84 
85  if (pdgcode == 2112 || pdgcode == -2112) //nuclear recoil
86  {
87  yieldFactor = 0.23 * (1 + exp(-5 * epsilon)); //liquid argon L_eff
88  excitationRatio = 0.69337 + 0.3065 * exp(-0.008806 * pow(eField, 0.76313));
89  }
90 
91  // determine ultimate number of quanta from current E-deposition (ph+e-) total mean number of exc/ions
92  //the total number of either quanta produced is equal to product of the
93  //work function, the energy deposited, and yield reduction, for NR
94  double MeanNumQuanta = scint_yield * energyDeposit;
95  double sigma = sqrt(resolution_scale * MeanNumQuanta); //Fano
96  int NumQuanta = int(floor(GaussGen.fire(MeanNumQuanta, sigma) + 0.5));
97  double LeffVar = GaussGen.fire(yieldFactor, 0.25 * yieldFactor);
98  LeffVar = std::clamp(LeffVar, 0., 1.);
99 
100  if (yieldFactor < 1) //nuclear reocils
101  {
102  NumQuanta = BinomFluct(NumQuanta, LeffVar);
103  }
104 
105  //if Edep below work function, can't make any quanta, and if NumQuanta
106  //less than zero because Gaussian fluctuated low, update to zero
107  if (energyDeposit < 1 / scint_yield || NumQuanta < 0) { NumQuanta = 0; }
108 
109  // next section binomially assigns quanta to excitons and ions
110  int NumExcitons = BinomFluct(NumQuanta, excitationRatio / (1 + excitationRatio));
111  int NumIons = NumQuanta - NumExcitons;
112 
113  // this section calculates recombination following the modified Birks'Law of Doke, deposition by deposition,
114  // may be overridden later in code if a low enough energy necessitates switching to the
115  // Thomas-Imel box model for recombination instead (determined by site)
116  double dE = energyDeposit / CLHEP::MeV;
117  double dx = 0.0;
118  double LET = 0.0;
119  double recombProb;
120 
121  if (pdgcode != 11 && pdgcode != -11 && pdgcode != 13 &&
122  pdgcode != -13) //e-: 11, e+: -11, mu-: 13, mu+: -13
123  {
124  //in other words, if it's a gamma,ion,proton,alpha,pion,et al. do not
125  //use the step length provided by Geant4 because it's not relevant,
126  //instead calculate an estimated LET and range of the electrons that
127  //would have been produced if Geant4 could track them
128  LET = CalcElectronLET(1000 * dE);
129 
130  if (LET) {
131  dx = dE / (Density * LET); //find the range based on the LET
132  }
133 
134  if (abs(pdgcode) == 2112) //nuclear recoils
135  {
136  dx = 0;
137  }
138  }
139  else //normal case of an e-/+ energy deposition recorded by Geant
140  {
141  dx = std::hypot(startx - endx, starty - endy, startz - endz) / CLHEP::cm;
142  if (dx) {
143  LET = (dE / dx) * (1 / Density); //lin. energy xfer (prop. to dE/dx)
144  }
145  if (LET > 0 && dE > 0 && dx > 0) {
146  double ratio = CalcElectronLET(dE * 1e3) / LET;
147  if (ratio < 0.7 && pdgcode == 11) {
148  dx /= ratio;
149  LET *= ratio;
150  }
151  }
152  }
153 
154  DokeBirks[1] = DokeBirks[0] / (1 - DokeBirks[2]); //B=A/(1-C) (see paper) r
155  recombProb = (DokeBirks[0] * LET) / (1 + DokeBirks[1] * LET) +
156  DokeBirks[2]; //Doke/Birks' Law as spelled out in the NEST pape
157  recombProb *= (Density / Density_LAr);
158 
159  //check against unphysicality resulting from rounding errors
160  recombProb = std::clamp(recombProb, 0., 1.);
161 
162  //use binomial distribution to assign photons, electrons, where photons
163  //are excitons plus recombined ionization electrons, while final
164  //collected electrons are the "escape" (non-recombined) electrons
165  int const NumPhotons = NumExcitons + BinomFluct(NumIons, recombProb);
166  int const NumElectrons = NumQuanta - NumPhotons;
167 
168  return {energyDeposit,
169  static_cast<double>(NumElectrons),
170  static_cast<double>(NumPhotons),
171  GetScintYieldRatio(edep)};
172  }
static constexpr double cm
Definition: Units.h:68
CLHEP::HepRandomEngine & fEngine
Definition: ISCalcNESTLAr.h:34
static constexpr double keV
Definition: Units.h:128
static constexpr double g
Definition: Units.h:144
static constexpr double cm3
Definition: Units.h:70
constexpr T pow(T x)
Definition: pow.h:72
static constexpr double MeV
Definition: Units.h:129
#define Density_LAr
Definition: G4S1Light.cc:78
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
T abs(T value)
static constexpr double eV
Definition: Units.h:127
int BinomFluct(int N0, double prob)
double GetScintYieldRatio(sim::SimEnergyDeposit const &edep)
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
Definition: geo_vectors.h:137
double CalcElectronLET(double E)
double EFieldAtStep(double efield, sim::SimEnergyDeposit const &edep) override
double Density(double r)
Definition: PREM.cxx:18
double larg4::ISCalcNESTLAr::EFieldAtStep ( double  efield,
sim::SimEnergyDeposit const &  edep 
)
overridevirtual

Implements larg4::ISCalc.

Definition at line 222 of file ISCalcNESTLAr.cxx.

223  {
224  geo::Point_t pos = edep.MidPoint();
225  double EField = efield;
226 
227  geo::Vector_t eFieldOffsets;
228 
229  if (fSCE->EnableSimEfieldSCE()) {
230  eFieldOffsets = fSCE->GetEfieldOffsets(pos);
231  EField =
232  std::sqrt((efield + efield * eFieldOffsets.X()) * (efield + efield * eFieldOffsets.X()) +
233  (efield * eFieldOffsets.Y() * efield * eFieldOffsets.Y()) +
234  (efield * eFieldOffsets.Z() * efield * eFieldOffsets.Z()));
235  }
236 
237  return EField;
238  }
virtual bool EnableSimEfieldSCE() const =0
const spacecharge::SpaceCharge * fSCE
Definition: ISCalcNESTLAr.h:35
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:164
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
virtual geo::Vector_t GetEfieldOffsets(geo::Point_t const &point) const =0
double larg4::ISCalcNESTLAr::GetScintYieldRatio ( sim::SimEnergyDeposit const &  edep)
private

Definition at line 242 of file ISCalcNESTLAr.cxx.

243  {
244  if (!fLArProp->ScintByParticleType()) { return fLArProp->ScintYieldRatio(); }
245  switch (edep.PdgCode()) {
246  case 2212: return fLArProp->ProtonScintYieldRatio();
247  case 13:
248  case -13: return fLArProp->MuonScintYieldRatio();
249  case 211:
250  case -211: return fLArProp->PionScintYieldRatio();
251  case 321:
252  case -321: return fLArProp->KaonScintYieldRatio();
253  case 1000020040: return fLArProp->AlphaScintYieldRatio();
254  case 11:
255  case -11:
256  case 22: return fLArProp->ElectronScintYieldRatio();
257  default: return fLArProp->ElectronScintYieldRatio();
258  }
259  }
virtual double ElectronScintYieldRatio() const =0
virtual double ScintYieldRatio() const =0
virtual double AlphaScintYieldRatio() const =0
virtual double ProtonScintYieldRatio() const =0
virtual double PionScintYieldRatio() const =0
const detinfo::LArProperties * fLArProp
Definition: ISCalcNESTLAr.h:36
virtual double MuonScintYieldRatio() const =0
virtual double KaonScintYieldRatio() const =0
virtual bool ScintByParticleType() const =0

Member Data Documentation

CLHEP::HepRandomEngine& larg4::ISCalcNESTLAr::fEngine
private

Definition at line 34 of file ISCalcNESTLAr.h.

const detinfo::LArProperties* larg4::ISCalcNESTLAr::fLArProp
private

Definition at line 36 of file ISCalcNESTLAr.h.

const spacecharge::SpaceCharge* larg4::ISCalcNESTLAr::fSCE
private

Definition at line 35 of file ISCalcNESTLAr.h.


The documentation for this class was generated from the following files: