LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ISCalculationCorrelated.cxx
Go to the documentation of this file.
1 // \file ISCalculationCorrelated.cxx
3 // \brief Interface to algorithm class for calculating ionization electrons
4 // and scintillation photon based on simple microphysics arguments
5 // to establish anticorrelation between these two quantities.
6 //
7 // To enable this in simulation, change LArG4Parameters variable
8 // in your fhicl file:
9 //
10 // services.LArG4Parameters.IonAndScintCalculator: "Correlated"
11 //
12 // TO DO:
13 // [ ] Add fluctuations from Fano factor
14 // [ ] Get W_ph = 19.5 eV from somewhere more centralized instead
15 // of hard-coding it into this algorithm
16 //
17 // \author W. Foreman, May 2020
18 // Modified: Adding corrections for low electric field (LArQL model)
19 // Mar 2021 by L. Paulucci and F. Marinho
21 
22 #include "Geant4/G4EmSaturation.hh"
23 #include "Geant4/G4LossTableManager.hh"
24 #include "Geant4/G4ParticleTypes.hh"
25 
32 
33 #include "cetlib_except/exception.h"
35 
36 namespace larg4 {
37 
38  //----------------------------------------------------------------------------
40  {
41  std::cout << "LegacyLArG4/ISCalculationCorrelated Initialize." << std::endl;
43  const detinfo::LArProperties* larp = lar::providerFrom<detinfo::LArPropertiesService>();
44 
45  double density = detProp.Density(detProp.Temperature());
46  fEfield = detProp.Efield();
47  fScintPreScale = larp->ScintPreScale();
48 
49  // ionization work function
50  fWion = 1. / lgpHandle->GeVToElectrons() * 1e3; // MeV
51 
52  // ion+excitation work function (\todo: get from LArG4Parameters or LArProperties?)
53  fWph = 19.5 * 1e-6; // MeV
54 
55  // the recombination coefficient is in g/(MeVcm^2), but
56  // we report energy depositions in MeV/cm, need to divide
57  // Recombk from the LArG4Parameters service by the density
58  // of the argon we got above.
59  fRecombA = lgpHandle->RecombA();
60  fRecombk = lgpHandle->Recombk() / density;
61  fModBoxA = lgpHandle->ModBoxA();
62  fModBoxB = lgpHandle->ModBoxB() / density;
63  fEllipsModBoxA = lgpHandle->EllipsModBoxA();
64  fEllipsModBoxB = lgpHandle->EllipsModBoxB() / detProp.Density(detProp.Temperature());
65  fEllipsModBoxR = lgpHandle->EllipsModBoxR();
66  fLarqlChi0A = lgpHandle->LarqlChi0A();
67  fLarqlChi0B = lgpHandle->LarqlChi0B();
68  fLarqlChi0C = lgpHandle->LarqlChi0C();
69  fLarqlChi0D = lgpHandle->LarqlChi0D();
70  fLarqlAlpha = lgpHandle->LarqlAlpha();
71  fLarqlBeta = lgpHandle->LarqlBeta();
72  fUseModBoxRecomb = lgpHandle->UseModBoxRecomb();
73  fUseEllipsModBoxRecomb = (bool)lgpHandle->UseEllipsModBoxRecomb();
74 
76 
77  // determine the step size using the voxel sizes
79  double maxsize =
80  std::max(lvc->VoxelSizeX(), std::max(lvc->VoxelSizeY(), lvc->VoxelSizeZ())) * CLHEP::cm;
81 
82  fStepSize = 0.1 * maxsize;
83  }
84 
85  //----------------------------------------------------------------------------
86  // fNumIonElectrons returns a value that is not corrected for life time effects
88  {
89  fEnergyDeposit = 0.;
90  fNumScintPhotons = 0.;
91  fNumIonElectrons = 0.;
92 
93  return;
94  }
95 
96  //----------------------------------------------------------------------------
97  // fNumIonElectrons returns a value that is not corrected for life time effects
99  {
100  fEnergyDeposit = step->GetTotalEnergyDeposit() / CLHEP::MeV;
101 
102  // calculate total quanta (ions + excitons)
103  double Nq = fEnergyDeposit / fWph;
104 
105  // Get the recombination factor for this voxel - Nucl.Instrum.Meth.A523:275-286,2004
106  // R = A/(1 + (dE/dx)*k)
107  // dE/dx is given by the voxel energy deposition, but have to convert it to MeV/cm
108  // from GeV/voxel width
109  // A = 0.800 +/- 0.003
110  // k = (0.097+/-0.001) g/(MeVcm^2)
111  // the dx depends on the trajectory of the step
112  // k should be divided by the density as our dE/dx is in MeV/cm,
113  // the division is handled in the constructor when we set fRecombk
114  // B.Baller: Add Modified Box recombination - ArgoNeuT result submitted to JINST
115 
116  G4ThreeVector totstep = step->GetPostStepPoint()->GetPosition();
117  totstep -= step->GetPreStepPoint()->GetPosition();
118  double dx = totstep.mag() / CLHEP::cm;
119  double dEdx = (dx == 0.0) ? 0.0 : fEnergyDeposit / dx;
120  double EFieldStep = EFieldAtStep(fEfield, step);
121 
122  // Guard against spurious values of dE/dx. Note: assumes density of LAr
123  if (dEdx < 1.) dEdx = 1.;
124 
125  // calculate the recombination survival fraction
126  double recomb = 0.;
127  if (fUseModBoxRecomb) {
128  if (dx) {
129  double Xi = fModBoxB * dEdx / EFieldStep;
130  recomb = log(fModBoxA + Xi) / Xi;
131  }
132  else
133  recomb = 0;
134  }
135  else if (fUseEllipsModBoxRecomb) {
136 
137  double phi = std::acos(abs(step->GetPreStepPoint()->GetPosition().x() -
138  step->GetPostStepPoint()->GetPosition().x()) /
139  step->GetStepLength());
140 
141  if (phi > std::atan(1) * 2) { phi = std::atan(1) * 4 - phi; }
142 
143  if (phi != phi) {
144  double Xi = fModBoxB * dEdx / EFieldStep;
145  recomb = std::log(fModBoxA + Xi) / Xi;
146  }
147  else {
148  double B_ellips = fEllipsModBoxB * dEdx /
149  (EFieldStep * std::hypot(std::sin(phi), std::cos(phi) / fEllipsModBoxR));
150 
151  recomb = std::log(fEllipsModBoxA + B_ellips) / B_ellips;
152  }
153  }
154  else {
155  recomb = fRecombA / (1. + dEdx * fRecombk / EFieldStep);
156  }
157 
158  if (fUseModLarqlRecomb) { //Use corrections from LArQL model
159  recomb += EscapingEFraction(dEdx) * FieldCorrection(EFieldStep, dEdx); //Correction for low EF
160  }
161 
162  // using this recombination, calculate number of ionization electrons
163  fNumIonElectrons = (fEnergyDeposit / fWion) * recomb;
164 
165  // calculate scintillation photons
167 
168  // apply the scintillation pre-scaling (normally this is already folded into
169  // the particle-specific scintillation yields)
171 
172  MF_LOG_DEBUG("ISCalculationCorrelated")
173  << " Electrons produced for " << fEnergyDeposit << " MeV deposited with " << recomb
174  << " recombination: " << fNumIonElectrons;
175  MF_LOG_DEBUG("ISCalculationCorrelated") << "number photons: " << fNumScintPhotons;
176 
177  return;
178  }
179 
181  { //LArQL chi0 function = fraction of escaping electrons
182  return fLarqlChi0A / (fLarqlChi0B + exp(fLarqlChi0C + fLarqlChi0D * dEdx));
183  }
184 
185  double ISCalculationCorrelated::FieldCorrection(double const EF, double const dEdx)
186  { //LArQL f_corr function = correction factor for electric field dependence
187  return exp(-EF / (fLarqlAlpha * log(dEdx) + fLarqlBeta));
188  }
189 
190 } // namespace
Store parameters for running LArG4.
double fWion
W_ion (23.6 eV) == 1/fGeVToElectrons.
double VoxelSizeX() const
Access to voxel dimensions and offsets.
double ModBoxA() const
Utilities related to art service access.
double fModBoxA
from LArG4Parameters service
double fLarqlChi0D
from LArG4Parameters service
Encapsulates calculation of LArVoxelID and LArVoxel parameters.
double EFieldAtStep(double fEfield, const G4Step *step) const
double fLarqlChi0B
from LArG4Parameters service
double LarqlChi0B() const
double Temperature() const
In kelvin.
double LarqlBeta() const
double LarqlAlpha() const
double fEllipsModBoxR
from LArG4Parameters service
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool UseModBoxRecomb() const
Geant4 interface.
double fLarqlAlpha
from LArG4Parameters service
double LarqlChi0D() const
bool fUseModLarqlRecomb
from LArG4Parameters service
double EllipsModBoxA() const
double Efield(unsigned int planegap=0) const
kV/cm
double EllipsModBoxR() const
double LarqlChi0C() const
bool fUseEllipsModBoxRecomb
from LArG4Parameters service
double fLarqlChi0C
from LArG4Parameters service
bool UseModLarqlRecomb() const
double fNumIonElectrons
number of ionization electrons for this step
Definition: ISCalculation.h:33
bool fUseModBoxRecomb
from LArG4Parameters service
double Density(double temperature=0.) const
Returns argon density at a given temperature.
virtual double ScintPreScale(bool prescale=true) const =0
double RecombA() const
double LarqlChi0A() const
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2675
ISCalculationCorrelated(detinfo::DetectorPropertiesData const &detProp)
double fEllipsModBoxB
from LArG4Parameters service
double fStepSize
maximum step to take
double fScintPreScale
scintillation pre-scale from LArProperties service
double EllipsModBoxB() const
double ModBoxB() const
double EscapingEFraction(double const dEdx)
double Recombk() const
double fEllipsModBoxA
from LArG4Parameters service
bool UseEllipsModBoxRecomb() const
#define MF_LOG_DEBUG(id)
double fNumScintPhotons
number of scintillation photons for this step
Definition: ISCalculation.h:34
double fRecombA
from LArG4Parameters service
double fLarqlChi0A
from LArG4Parameters service
double fEnergyDeposit
total energy deposited in the step
Definition: ISCalculation.h:32
void CalculateIonizationAndScintillation(const G4Step *step)
Float_t e
Definition: plot.C:35
double fRecombk
from LArG4Parameters service
double FieldCorrection(double const EF, double const dEdx)
double fEfield
value of electric field from LArProperties service
double GeVToElectrons() const
double fModBoxB
from LArG4Parameters service
double fLarqlBeta
from LArG4Parameters service