Public Member Functions | Private Member Functions | Private Attributes | List of all members
EDepSim::DokeBirks Class Reference

#include <EDepSimDokeBirks.hh>

Inheritance diagram for EDepSim::DokeBirks:

Public Member Functions

 DokeBirks (const G4String &processName="Doke-Birks", G4ProcessType type=fElectromagnetic)
 
 ~DokeBirks ()
 
G4bool IsApplicable (const G4ParticleDefinition &aParticleType)
 Determine which particles this process should be applied too. More...
 
G4double GetMeanFreePath (const G4Track &aTrack, G4double, G4ForceCondition *)
 
G4double GetMeanLifeTime (const G4Track &aTrack, G4ForceCondition *)
 
G4VParticleChange * PostStepDoIt (const G4Track &aTrack, const G4Step &aStep)
 Apply the scintilation process for an in-flight particle. More...
 
G4VParticleChange * AtRestDoIt (const G4Track &aTrack, const G4Step &aStep)
 

Private Member Functions

G4double CalculateElectronLET (G4double E)
 

Private Attributes

G4EmSaturation * fEmSaturation
 

Detailed Description

Definition at line 31 of file EDepSimDokeBirks.hh.

Constructor & Destructor Documentation

EDepSim::DokeBirks::DokeBirks ( const G4String &  processName = "Doke-Birks",
G4ProcessType  type = fElectromagnetic 
)

Definition at line 18 of file EDepSimDokeBirks.cc.

20  : G4VRestDiscreteProcess(processName, type),
21  fEmSaturation(nullptr)
22 {
23  SetProcessSubType(fScintillation);
24 
25  if (verboseLevel>0) {
26  G4cout << GetProcessName() << " is created " << G4endl;
27  }
28 
29 }
G4EmSaturation * fEmSaturation
EDepSim::DokeBirks::~DokeBirks ( )

Definition at line 31 of file EDepSimDokeBirks.cc.

31 {} //destructor needed to avoid linker error

Member Function Documentation

G4VParticleChange * EDepSim::DokeBirks::AtRestDoIt ( const G4Track &  aTrack,
const G4Step &  aStep 
)

Apply the scintilation process to a stopped particle (this just calles PostStepDoIt().

Definition at line 52 of file EDepSimDokeBirks.cc.

53 {
54  return EDepSim::DokeBirks::PostStepDoIt(aTrack, aStep);
55 }
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
Apply the scintilation process for an in-flight particle.
G4double EDepSim::DokeBirks::CalculateElectronLET ( G4double  E)
private

Get the expected electron electron dEdX as a function of energy. This is normalized to denstity. The energy must be in MeV.

Definition at line 233 of file EDepSimDokeBirks.cc.

233  {
234  G4double LET;
235  if ( E >= 1 ) LET = 116.70-162.97*log10(E)+99.361*pow(log10(E),2)-
236  33.405*pow(log10(E),3)+6.5069*pow(log10(E),4)-
237  0.69334*pow(log10(E),5)+.031563*pow(log10(E),6);
238  else if ( E>0 && E<1 ) LET = 100;
239  else LET = 0;
240  return LET;
241 }
constexpr T pow(T x)
Definition: pow.h:72
G4double EDepSim::DokeBirks::GetMeanFreePath ( const G4Track &  aTrack,
G4double  ,
G4ForceCondition *  condition 
)

Don't limit the step since this process doesn't actually change the energy deposit (it returns infinity). The process does set the 'StronglyForced' condition so the DoIt is invoked at every step.

Definition at line 206 of file EDepSimDokeBirks.cc.

209 {
210  *condition = StronglyForced;
211  // Force the EDepSim::DokeBirks physics process to always happen, even if it's
212  // not the dominant process. In effect it is a meta-process on top of any
213  // and all other energy depositions which may occur, just like the
214  // original G4Scintillation (disregard DBL_MAX, this function makes the
215  // mean free path zero really, not infinite)
216 
217  return DBL_MAX;
218 }
G4double EDepSim::DokeBirks::GetMeanLifeTime ( const G4Track &  aTrack,
G4ForceCondition *  condition 
)

Don't limit the step since this process doesn't actually change the energy deposit (it returns infinity). The process does set the 'StronglyForced' condition so the DoIt is invoked at every step.

Definition at line 222 of file EDepSimDokeBirks.cc.

224 {
225  *condition = Forced;
226  // This function and this condition has the same effect as the above
227  return DBL_MAX;
228 }
G4bool EDepSim::DokeBirks::IsApplicable ( const G4ParticleDefinition &  aParticleType)

Determine which particles this process should be applied too.

Definition at line 35 of file EDepSimDokeBirks.cc.

36 {
37  // This process is applicable to some neutral particles (e.g. gammas)
38  // since G4 will fake creating the low energy electrons.
39  if (aParticleType.IsShortLived()) return false;
40  if (aParticleType.GetParticleName() == "opticalphoton") return false;
41  if (aParticleType.GetParticleName() == "thermalelectron") return false;
42  // Not applicable to the neutrinos.
43  if (std::abs(aParticleType.GetPDGEncoding())==12) return false;
44  if (std::abs(aParticleType.GetPDGEncoding())==14) return false;
45  if (std::abs(aParticleType.GetPDGEncoding())==16) return false;
46  return true;
47 }
T abs(T value)
G4VParticleChange * EDepSim::DokeBirks::PostStepDoIt ( const G4Track &  aTrack,
const G4Step &  aStep 
)

Apply the scintilation process for an in-flight particle.

Definition at line 60 of file EDepSimDokeBirks.cc.

61 {
62  aParticleChange.Initialize(aTrack);
63 
64  const G4Material* aMaterial = aTrack.GetMaterial();
65 
66  bool inLiquidArgon = true;
67  // Check that we are in liquid argon.
68  if (aMaterial->GetState() != kStateLiquid) {
69  // Do Nothing
70  if (aMaterial->GetState() == kStateUndefined) {
71  EDepSimError("Undefined material state for "
72  << aMaterial->GetName());
73  }
74  inLiquidArgon = false;
75  }
76  if (aMaterial->GetNumberOfElements() > 1) {
77  // Do Nothing
78  inLiquidArgon = false;
79  }
80  if (std::abs(aMaterial->GetElement(0)->GetZ()-18.0) > 0.5) {
81  // Do Nothing
82  inLiquidArgon = false;
83  }
84 
85  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
86  const G4ParticleDefinition *pDef = aParticle->GetDefinition();
87  G4String particleName = pDef->GetParticleName();
88  // G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
89  G4double totalEnergyDeposit = aStep.GetTotalEnergyDeposit();
90 
91  if (totalEnergyDeposit <= 0.0) {
92  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
93  }
94 
95  if (aStep.GetStepLength() <= 0.0) {
96  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
97  }
98 
99  if (!inLiquidArgon) {
100  if (!fEmSaturation) fEmSaturation = new G4EmSaturation(0);
101  G4double nonIonizingEnergy
102  = fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep);
103  aParticleChange.ProposeNonIonizingEnergyDeposit(nonIonizingEnergy);
104  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
105  }
106 
107  // Figure out the electric field for the volume.
108  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
109  const G4VPhysicalVolume* aVolume = pPostStepPoint->GetPhysicalVolume();
110  const G4LogicalVolume* aLogVolume = aVolume->GetLogicalVolume();
111  const G4FieldManager* aFieldManager = aLogVolume->GetFieldManager();
112  if (!aFieldManager) {
113  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
114  }
115  if (!aFieldManager->DoesFieldExist()) {
116  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
117  }
118  const G4Field* aField = aFieldManager->GetDetectorField();
119  if (!aField) {
120  EDepSimError("LAr Volume "
121  << aLogVolume->GetName()
122  << " should have field!");
123  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
124  }
125 
126  G4ThreeVector thePosition = pPostStepPoint->GetPosition();
127  double theTime = pPostStepPoint->GetGlobalTime();
128  double point[4] = {
129  thePosition.x(), thePosition.y(), thePosition.z(), theTime};
130  double bField[6];
131  aField->GetFieldValue(point,bField);
132 
133  double electricField = bField[3]*bField[3];
134  electricField += bField[4]*bField[4];
135  electricField += bField[5]*bField[5];
136  if (electricField > 0) {
137  electricField = std::sqrt(electricField);
138  }
139  // The code below is pulled from G4S1Light and is simplified to be
140  // Doke-Birks only, in LAr only, and for an electric field only. This is
141  // for ARGON only. The Doke-Birks constants are in kilovolt/cm
142  G4double dokeBirks[3];
143 
144  dokeBirks[0] = 0.07*pow((electricField),-0.85);
145  dokeBirks[2] = 0.00;
146  dokeBirks[1] = dokeBirks[0]/(1-dokeBirks[2]); //B=A/(1-C) (see paper)
147 
148  G4double dE = totalEnergyDeposit/MeV;
149  G4double dx = aStep.GetStepLength()/cm;
150  G4double density = aMaterial->GetDensity()/(g/cm3);
151  G4double LET = 0.0; //lin. energy transfer (prop. to dE/dx)
152  if (dx != 0.0) LET = (dE/dx)*(1/density);
153 
154  // There was some dEdX for a photon. This means that the very low energy
155  // electrons were not simulated.
156  if (particleName == "gamma") {
157  LET = CalculateElectronLET( 1000*dE );
158  dx = dE/density/LET;
159  }
160  else if (std::abs(pDef->GetPDGCharge()) < 0.1) {
161  // Handle the case where a neutral particle made an "electron". This
162  // is when there is a tiny electron scatter that is below the G4
163  // threshold. The assumption is the same as NEST. The product
164  // particle is an electron.
165  double tempLET = CalculateElectronLET( 1000*dE );
166  double electronStep = dE/density/tempLET;
167  if (dx > electronStep) {
168  LET = tempLET;
169  dx = electronStep;
170  }
171  }
172 
173  // Special case for electrons that G4 may stop when they get to short and
174  // truncate the energy deposition.
175  do {
176  if (particleName != "e+" || particleName != "e-") break;
177  if (aTrack.GetCurrentStepNumber() != 1) break;
178  double ratio = CalculateElectronLET( 1000.0*dE ) / LET;
179  if (ratio > 0.7) break;
180  LET *= ratio;
181  dx /= ratio;
182  } while (false);
183 
184  G4double recombProb = (dokeBirks[0]*LET)/(1+dokeBirks[1]*LET)+dokeBirks[2];
185 
186  G4double ScintillationYield = 1 / (19.5*eV);
187  G4double NumQuanta = ScintillationYield*totalEnergyDeposit;
188  G4double ExcitationRatio = 0.21; //Aprile et. al book
189  G4double NumExcitons = NumQuanta*ExcitationRatio/(1+ExcitationRatio);
190  G4double NumIons = NumQuanta - NumExcitons;
191  G4double NumPhotons = NumExcitons + NumIons*recombProb;
192 
193  // The number of photons and electrons for this step has been calculated
194  // using the Doke/Birks law version of recombination. For DETSIM we are
195  // only looking at argon, and according the Matt both Doke-Birks and
196  // Thomas-Imel fit the data. It's also because we are not interested in
197  // extremely low energies, so Thomas-Imel makes a negligible correction.
198  G4double nonIonizingEnergy = totalEnergyDeposit;
199  nonIonizingEnergy *= NumPhotons/NumQuanta;
200  aParticleChange.ProposeNonIonizingEnergyDeposit(nonIonizingEnergy);
201  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
202 }
static constexpr double cm
Definition: Units.h:68
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
T abs(T value)
static constexpr double eV
Definition: Units.h:127
#define EDepSimError(outStream)
Definition: EDepSimLog.hh:503
G4double CalculateElectronLET(G4double E)
G4EmSaturation * fEmSaturation

Member Data Documentation

G4EmSaturation* EDepSim::DokeBirks::fEmSaturation
private

Definition at line 71 of file EDepSimDokeBirks.hh.


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