16 #include "CLHEP/Random/RandFlat.h" 17 #include "CLHEP/Random/RandGauss.h" 18 #include "CLHEP/Units/SystemOfUnits.h" 23 constexpr
double LAr_Z{18};
26 constexpr
double scint_yield{1.0 / (19.5 * CLHEP::eV)};
27 constexpr
double resolution_scale{0.107};
34 : fEngine(Engine), fSCE{lar::providerFrom<spacecharge::SpaceChargeService>()}
36 std::cout <<
"ISCalcNESTLAr Initialize." << std::endl;
43 CLHEP::RandGauss GaussGen(
fEngine);
44 CLHEP::RandFlat UniformGen(
fEngine);
46 double yieldFactor = 1.0;
47 double excitationRatio =
50 double const energyDeposit = edep.
Energy();
51 if (energyDeposit < 1 * CLHEP::eV)
53 return {0., 0., 0., 0.};
69 DokeBirks[0] = 0.07 * pow((eField / 1.0e3), -0.85);
73 DokeBirks[0] = 0.0003;
77 double Density = detProp.
Density() /
78 (CLHEP::g / CLHEP::cm3);
82 double epsilon = 11.5 * (energyDeposit / CLHEP::keV) * pow(LAr_Z, (-7. / 3.));
84 if (pdgcode == 2112 || pdgcode == -2112)
86 yieldFactor = 0.23 * (1 + exp(-5 * epsilon));
87 excitationRatio = 0.69337 + 0.3065 * exp(-0.008806 * pow(eField, 0.76313));
93 double MeanNumQuanta = scint_yield * energyDeposit;
94 double sigma = sqrt(resolution_scale * MeanNumQuanta);
95 int NumQuanta = int(floor(GaussGen.fire(MeanNumQuanta, sigma) + 0.5));
96 double LeffVar = GaussGen.fire(yieldFactor, 0.25 * yieldFactor);
97 LeffVar = std::clamp(LeffVar, 0., 1.);
106 if (energyDeposit < 1 / scint_yield || NumQuanta < 0) { NumQuanta = 0; }
109 int NumExcitons =
BinomFluct(NumQuanta, excitationRatio / (1 + excitationRatio));
110 int NumIons = NumQuanta - NumExcitons;
115 double dE = energyDeposit / CLHEP::MeV;
120 if (pdgcode != 11 && pdgcode != -11 && pdgcode != 13 &&
130 dx = dE / (Density * LET);
133 if (
abs(pdgcode) == 2112)
140 dx = std::hypot(startx - endx, starty - endy, startz - endz) / CLHEP::cm;
142 LET = (dE / dx) * (1 / Density);
144 if (LET > 0 && dE > 0 && dx > 0) {
146 if (ratio < 0.7 && pdgcode == 11) {
153 DokeBirks[1] = DokeBirks[0] / (1 - DokeBirks[2]);
154 recombProb = (DokeBirks[0] * LET) / (1 + DokeBirks[1] * LET) +
159 recombProb = std::clamp(recombProb, 0., 1.);
164 int const NumPhotons = NumExcitons +
BinomFluct(NumIons, recombProb);
165 int const NumElectrons = NumQuanta - NumPhotons;
167 return {energyDeposit,
168 static_cast<double>(NumElectrons),
169 static_cast<double>(NumPhotons),
176 CLHEP::RandGauss GaussGen(
fEngine);
177 CLHEP::RandFlat UniformGen(
fEngine);
179 double mean = N0 * prob;
180 double sigma = sqrt(N0 * prob * (1 - prob));
182 if (prob == 0.00) {
return N1; }
183 if (prob == 1.00) {
return N0; }
186 for (
int i = 0; i < N0; i++) {
187 if (UniformGen.fire() < prob) { N1++; }
191 N1 = int(floor(GaussGen.fire(mean, sigma) + 0.5));
193 if (N1 > N0) { N1 = N0; }
194 if (N1 < 0) { N1 = 0; }
204 LET = 116.70 - 162.97 * log10(E) + 99.361 * pow(log10(E), 2) - 33.405 * pow(log10(E), 3) +
205 6.5069 * pow(log10(E), 4) - 0.69334 * pow(log10(E), 5) + .031563 * pow(log10(E), 6);
207 else if (E > 0 && E < 1) {
221 double EField = efield;
226 std::sqrt((efield + efield * eFieldOffsets.X()) * (efield + efield * eFieldOffsets.X()) +
227 (efield * eFieldOffsets.Y() * efield * eFieldOffsets.Y()) +
228 (efield * eFieldOffsets.Z() * efield * eFieldOffsets.Z()));
geo::Length_t StartX() const
CLHEP::HepRandomEngine & fEngine
virtual bool EnableSimEfieldSCE() const =0
geo::Length_t EndZ() const
ISCalcNESTLAr(CLHEP::HepRandomEngine &fEngine)
geo::Length_t EndY() const
Utilities related to art service access.
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
const spacecharge::SpaceCharge * fSCE
constexpr auto abs(T v)
Returns the absolute value of the argument.
geo::Length_t StartY() const
double Efield(unsigned int planegap=0) const
kV/cm
geo::Length_t EndX() const
geo::Point_t MidPoint() const
double Density(double temperature=0.) const
Returns argon density at a given temperature.
int BinomFluct(int N0, double prob)
geo::Length_t StartZ() const
ISCalcData CalcIonAndScint(detinfo::DetectorPropertiesData const &detProp, sim::SimEnergyDeposit const &edep) override
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
virtual geo::Vector_t GetEfieldOffsets(geo::Point_t const &point) const =0
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
double CalcElectronLET(double E)
contains information for a single step in the detector simulation
Energy deposition in the active material.
double GetScintYieldRatio(sim::SimEnergyDeposit const &edep)
double EFieldAtStep(double efield, sim::SimEnergyDeposit const &edep) override