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};
35 , fSCE{lar::providerFrom<spacecharge::SpaceChargeService>()}
37 std::cout <<
"ISCalcNESTLAr Initialize." << std::endl;
45 CLHEP::RandGauss GaussGen(
fEngine);
46 CLHEP::RandFlat UniformGen(
fEngine);
48 double yieldFactor = 1.0;
49 double excitationRatio =
52 double const energyDeposit = edep.
Energy();
53 if (energyDeposit < 1 * CLHEP::eV)
55 return {0., 0., 0., 0.};
71 DokeBirks[0] = 0.07 * pow((eField / 1.0e3), -0.85);
75 DokeBirks[0] = 0.0003;
79 double Density = detProp.
Density() /
84 double epsilon = 11.5 * (energyDeposit / CLHEP::keV) * pow(LAr_Z, (-7. / 3.));
86 if (pdgcode == 2112 || pdgcode == -2112)
88 yieldFactor = 0.23 * (1 +
exp(-5 * epsilon));
89 excitationRatio = 0.69337 + 0.3065 *
exp(-0.008806 * pow(eField, 0.76313));
95 double MeanNumQuanta = scint_yield * energyDeposit;
96 double sigma = sqrt(resolution_scale * MeanNumQuanta);
97 int NumQuanta = int(floor(GaussGen.fire(MeanNumQuanta, sigma) + 0.5));
98 double LeffVar = GaussGen.fire(yieldFactor, 0.25 * yieldFactor);
99 LeffVar = std::clamp(LeffVar, 0., 1.);
108 if (energyDeposit < 1 / scint_yield || NumQuanta < 0) { NumQuanta = 0; }
111 int NumExcitons =
BinomFluct(NumQuanta, excitationRatio / (1 + excitationRatio));
112 int NumIons = NumQuanta - NumExcitons;
122 if (pdgcode != 11 && pdgcode != -11 && pdgcode != 13 &&
132 dx = dE / (Density * LET);
135 if (
abs(pdgcode) == 2112)
142 dx = std::hypot(startx - endx, starty - endy, startz - endz) / CLHEP::cm;
144 LET = (dE / dx) * (1 / Density);
146 if (LET > 0 && dE > 0 && dx > 0) {
148 if (ratio < 0.7 && pdgcode == 11) {
155 DokeBirks[1] = DokeBirks[0] / (1 - DokeBirks[2]);
156 recombProb = (DokeBirks[0] * LET) / (1 + DokeBirks[1] * LET) +
161 recombProb = std::clamp(recombProb, 0., 1.);
166 int const NumPhotons = NumExcitons +
BinomFluct(NumIons, recombProb);
167 int const NumElectrons = NumQuanta - NumPhotons;
169 return {energyDeposit,
170 static_cast<double>(NumElectrons),
171 static_cast<double>(NumPhotons),
179 CLHEP::RandGauss GaussGen(
fEngine);
180 CLHEP::RandFlat UniformGen(
fEngine);
182 double mean = N0 * prob;
183 double sigma = sqrt(N0 * prob * (1 - prob));
185 if (prob == 0.00) {
return N1; }
186 if (prob == 1.00) {
return N0; }
189 for (
int i = 0; i < N0; i++) {
190 if (UniformGen.fire() < prob) { N1++; }
194 N1 = int(floor(GaussGen.fire(mean, sigma) + 0.5));
196 if (N1 > N0) { N1 = N0; }
197 if (N1 < 0) { N1 = 0; }
208 LET = 116.70 - 162.97 * log10(E) + 99.361 * pow(log10(E), 2) - 33.405 * pow(log10(E), 3) +
209 6.5069 * pow(log10(E), 4) - 0.69334 * pow(log10(E), 5) + .031563 * pow(log10(E), 6);
211 else if (E > 0 && E < 1) {
226 double EField = efield;
231 std::sqrt((efield + efield * eFieldOffsets.X()) * (efield + efield * eFieldOffsets.X()) +
232 (efield * eFieldOffsets.Y() * efield * eFieldOffsets.Y()) +
233 (efield * eFieldOffsets.Z() * efield * eFieldOffsets.Z()));
geo::Length_t StartX() const
CLHEP::HepRandomEngine & fEngine
geo::Length_t EndZ() const
ISCalcNESTLAr(CLHEP::HepRandomEngine &fEngine)
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
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.
const spacecharge::SpaceCharge * fSCE
geo::Length_t StartY() const
util::quantities::megaelectronvolt MeV
double Efield(unsigned int planegap=0) const
kV/cm
geo::Length_t EndX() const
fEngine(art::ServiceHandle< rndm::NuRandomService >() ->createEngine(*this,"HepJamesRandom","ISCalcAlg", pset,"SeedISCalcAlg"))
virtual geo::Vector_t GetEfieldOffsets(geo::Point_t const &point) const =0
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
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.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
double GetScintYieldRatio(sim::SimEnergyDeposit const &edep)
double EFieldAtStep(double efield, sim::SimEnergyDeposit const &edep) override
virtual bool EnableSimEfieldSCE() const =0
BEGIN_PROLOG could also be cout