1 #define AVO 6.022e23 //Avogadro's number (#/mol)     2 #define EMASS 9.109e-31*CLHEP::kg     3 #define MillerDriftSpeed true     5 #define GASGAP 0.25*CLHEP::cm //S2 generation region     6 #define BORDER 0*CLHEP::cm //liquid-gas border z-coordinate     8 #define QE_EFF 1 //a base or maximum quantum efficiency     9 #define phe_per_e 1 //S2 gain for quick studies    12 #define WIN 0&&CLHEP::mm //top Cu block (also, quartz window)    13 #define TOP 0 //top grid wires    14 #define ANE 0 //anode mesh    15 #define SRF 0 //liquid-gas interface    16 #define GAT 0 //gate grid    17 #define CTH 0 //cathode grid    18 #define BOT 0 //bottom PMT grid    19 #define PMT 0 //bottom Cu block and PMTs    20 #define MIN_ENE -1*CLHEP::eV //lets you turn NEST off BELOW a certain energy    21 #define MAX_ENE 1.*CLHEP::TeV //lets you turn NEST off ABOVE a certain energy    22 #define HIENLIM 5*CLHEP::MeV //energy at which Doke model used exclusively    23 #define R_TOL 0.2*CLHEP::mm //tolerance (for edge events)    24 #define R_MAX 1*CLHEP::km //for corraling diffusing electrons    25 #define Density_LXe 2.9 //reference density for density-dep. effects    26 #define Density_LAr 1.393    27 #define Density_LNe 1.207    28 #define Density_LKr 2.413    30 #include "Geant4/Randomize.hh"    31 #include "Geant4/G4Ions.hh"    32 #include "Geant4/G4OpticalPhoton.hh"    33 #include "Geant4/G4VProcess.hh"    38 #include "CLHEP/Random/RandGauss.h"    39 #include "CLHEP/Random/RandFlat.h"    87     CLHEP::RandGauss GaussGen(
fEngine);
    88     CLHEP::RandFlat  UniformGen(
fEngine);
   102     bool   fTrackSecondariesFirst = 
false;
   103     bool   fExcitedNucleus        = 
false;
   104     bool   fVeryHighEnergy        = 
false;
   106     bool   fMultipleScattering    = 
false;
   109     if( aTrack.GetParentID() == 0 && aTrack.GetCurrentStepNumber() == 1 ) {
   110       fExcitedNucleus = 
false; 
   111       fVeryHighEnergy = 
false; 
   113       fMultipleScattering = 
false;
   116     const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
   117     G4ParticleDefinition *pDef = aParticle->GetDefinition();
   118     G4String particleName = pDef->GetParticleName();
   119     const G4Material* aMaterial = aStep.GetPreStepPoint()->GetMaterial();
   120     const G4Material* bMaterial = aStep.GetPostStepPoint()->GetMaterial();
   122     if((particleName == 
"neutron" || particleName == 
"antineutron") &&
   123        aStep.GetTotalEnergyDeposit() <= 0)
   131     G4Element *ElementA = NULL, *ElementB = NULL;
   133       const G4ElementVector* theElementVector1 =
   134       aMaterial->GetElementVector();
   135       ElementA = (*theElementVector1)[0];
   138       const G4ElementVector* theElementVector2 =
   139       bMaterial->GetElementVector();
   140       ElementB = (*theElementVector2)[0];
   142     G4int z1,z2,j=1; G4bool NobleNow=
false,NobleLater=
false;
   143     if (ElementA) z1 = (G4int)(ElementA->GetZ()); 
else z1 = -1;
   144     if (ElementB) z2 = (G4int)(ElementB->GetZ()); 
else z2 = -1;
   145     if ( z1==2 || z1==10 || z1==18 || z1==36 || z1==54 ) {
   155     if ( z2==2 || z2==10 || z2==18 || z2==36 || z2==54 ) {
   166     if ( !NobleNow && !NobleLater )
   171     G4StepPoint* pPreStepPoint  = aStep.GetPreStepPoint();
   172     G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
   173     G4ThreeVector 
x1 = pPostStepPoint->GetPosition();
   174     G4ThreeVector x0 = pPreStepPoint->GetPosition();
   175     G4double evtStrt = pPreStepPoint->GetGlobalTime();
   176     G4double      
t0 = pPreStepPoint->GetLocalTime();
   177     G4double      
t1 = pPostStepPoint->GetLocalTime();
   183     G4bool outside = 
false, inside = 
false, InsAndOuts = 
false;
   184     G4MaterialPropertiesTable* aMaterialPropertiesTable =
   185     aMaterial->GetMaterialPropertiesTable();
   186     if ( NobleNow && !NobleLater ) outside = 
true;
   187     if ( !NobleNow && NobleLater ) {
   188       aMaterial = bMaterial; inside = 
true; z1 = z2;
   189       aMaterialPropertiesTable = bMaterial->GetMaterialPropertiesTable();
   191     if ( NobleNow && NobleLater &&
   192         aMaterial->GetDensity() != bMaterial->GetDensity() )
   197     G4double nDensity = Density*
AVO; 
   198     G4int Phase = aMaterial->GetState(); 
   199     G4double ElectricField(0.), FieldSign(0.); 
   200     G4bool GlobalFields = 
false;
   203       ElectricField = aMaterialPropertiesTable->GetConstProperty(
"ELECTRICFIELD");
   207       if ( x1[2] < 
WIN && x1[2] > 
TOP && Phase == kStateGas )
   208         ElectricField = aMaterialPropertiesTable->GetConstProperty(
"ELECTRICFIELDWINDOW");
   209       else if ( x1[2] < 
TOP && x1[2] > 
ANE && Phase == kStateGas )
   210         ElectricField = aMaterialPropertiesTable->GetConstProperty(
"ELECTRICFIELDTOP");
   211       else if ( x1[2] < 
ANE && x1[2] > 
SRF && Phase == kStateGas )
   212         ElectricField = aMaterialPropertiesTable->
   213         GetConstProperty(
"ELECTRICFIELDANODE");
   214       else if ( x1[2] < 
SRF && x1[2] > 
GAT && Phase == kStateLiquid )
   215         ElectricField = aMaterialPropertiesTable->
   216         GetConstProperty(
"ELECTRICFIELDSURFACE");
   217       else if ( x1[2] < 
GAT && x1[2] > 
CTH && Phase == kStateLiquid )
   218         ElectricField = aMaterialPropertiesTable->
   219         GetConstProperty(
"ELECTRICFIELDGATE");
   220       else if ( x1[2] < 
CTH && x1[2] > 
BOT && Phase == kStateLiquid )
   221         ElectricField = aMaterialPropertiesTable->
   222         GetConstProperty(
"ELECTRICFIELDCATHODE");
   223       else if ( x1[2] < 
BOT && x1[2] > 
PMT && Phase == kStateLiquid )
   224         ElectricField = aMaterialPropertiesTable->
   225         GetConstProperty(
"ELECTRICFIELDBOTTOM");
   227         ElectricField = aMaterialPropertiesTable->
   228         GetConstProperty(
"ELECTRICFIELD");
   230     if ( ElectricField >= 0 ) FieldSign = 1; 
else FieldSign = -1;
   232     G4double Temperature = aMaterial->GetTemperature();
   233     G4double ScintillationYield, ResolutionScale, R0 = 1.0*
CLHEP::um,
   234     DokeBirks[3], ThomasImel = 0.00, delta = 1*
CLHEP::mm;
   235     DokeBirks[0] = 0.00; DokeBirks[2] = 1.00;
   240         ScintillationYield = 1 / (41.3*
CLHEP::eV); 
   242         ResolutionScale = 0.2; 
   249         ScintillationYield = 1 / (29.2*
CLHEP::eV);
   251         ResolutionScale = 0.13; 
   254         tau3 = GaussGen.fire(15.4e3*
CLHEP::ns,200*CLHEP::ns); 
   257         ScintillationYield = 1 / (19.5*
CLHEP::eV);
   259         ResolutionScale = 0.107; 
   262           ThomasImel = 0.156977*
pow(ElectricField,-0.1);
   263           DokeBirks[0] = 0.07*
pow((ElectricField/1.0e3),-0.85);
   268           DokeBirks[0] = 0.0003;
   270         } nDensity /= 39.948; 
   272         tau1 = GaussGen.fire(6.5*CLHEP::ns,0.8*CLHEP::ns); 
   273         tau3 = GaussGen.fire(1300*CLHEP::ns,50*CLHEP::ns); 
   274         tauR = GaussGen.fire(0.8*CLHEP::ns,0.2*CLHEP::ns); 
   277         if ( Phase == kStateGas ) ScintillationYield = 1 / (30.0*
CLHEP::eV);
   278         else ScintillationYield = 1 / (15.0*
CLHEP::eV);
   280         ResolutionScale = 0.05; 
   282         tau1 = GaussGen.fire(2.8*CLHEP::ns,.04*CLHEP::ns);
   283         tau3 = GaussGen.fire(93.*CLHEP::ns,1.1*CLHEP::ns);
   284         tauR = GaussGen.fire(12.*CLHEP::ns,.76*CLHEP::ns);
   287       default: nDensity /= 131.293;
   288         ScintillationYield = 48.814+0.80877*Density+2.6721*
pow(Density,2.);
   293         ResolutionScale = 1.00 * 
   294         (0.12724-0.032152*Density-0.0013492*
pow(Density,2.));
   296         if ( Phase == kStateLiquid ) {
   297           ResolutionScale *= 1.5; 
   303             DokeBirks[0]= 19.171*
pow(ElectricField+25.552,-0.83057)+0.026772;
   319           tau1 = GaussGen.fire(3.1*CLHEP::ns,.7*CLHEP::ns); 
   320           tau3 = GaussGen.fire(24.*CLHEP::ns,1.*CLHEP::ns); 
   322         else if ( Phase == kStateGas ) {
   325             ScintillationYield = 1 / (12.98*
CLHEP::eV); } 
   327           G4double Townsend = (ElectricField/nDensity)*1e17;
   328           DokeBirks[0] = 0.0000; 
   329           DokeBirks[2] = 0.1933*
pow(Density,2.6199)+0.29754 -
   330           (0.045439*
pow(Density,2.4689)+0.066034)*log10(ElectricField);
   331           if ( ElectricField>6990 ) DokeBirks[2]=0.0;
   332           if ( ElectricField<1000 ) DokeBirks[2]=0.2;
   333           if ( ElectricField<100. ) { DokeBirks[0]=0.18; DokeBirks[2]=0.58; }
   334           if( Density < 0.061 ) ThomasImel = 0.041973*
pow(Density,1.8105);
   335           else if( Density >= 0.061 && Density <= 0.167 )
   336             ThomasImel=5.9583e-5+0.0048523*Density-0.023109*
pow(Density,2.);
   337           else ThomasImel = 6.2552e-6*
pow(Density,-1.9963);
   338           if(ElectricField)ThomasImel=1.2733e-5*
pow(Townsend/Density,-0.68426);
   341           tau1 = GaussGen.fire(5.18*CLHEP::ns,1.55*CLHEP::ns);
   342           tau3 = GaussGen.fire(100.1*CLHEP::ns,7.9*CLHEP::ns);
   350     G4double anExcitationEnergy = ((
const G4Ions*)(pDef))->
   351     GetExcitationEnergy(); 
   352     G4double TotalEnergyDeposit = 
   353     aMaterialPropertiesTable->GetConstProperty( 
"ENERGY_DEPOSIT_TOT" );
   354     G4bool 
convert = 
false, annihil = 
false;
   356     if(pPreStepPoint->GetKineticEnergy()>=(2*CLHEP::electron_mass_c2) &&
   357        !pPostStepPoint->GetKineticEnergy() &&
   358        !aStep.GetTotalEnergyDeposit() && aParticle->GetPDGcode()==22) {
   359       convert = 
true; TotalEnergyDeposit = CLHEP::electron_mass_c2;
   361     if(pPreStepPoint->GetKineticEnergy() &&
   362        !pPostStepPoint->GetKineticEnergy() &&
   363        aParticle->GetPDGcode()==-11) {
   364       annihil = 
true; TotalEnergyDeposit += aStep.GetTotalEnergyDeposit();
   366     G4bool either = 
false;
   367     if(inside || outside || convert || annihil || InsAndOuts) either=
true;
   370        !either && !fExcitedNucleus )
   373     if ( !annihil ) TotalEnergyDeposit += aStep.GetTotalEnergyDeposit();
   374     if ( !convert ) aMaterialPropertiesTable->
   375                     AddConstProperty( 
"ENERGY_DEPOSIT_TOT", TotalEnergyDeposit );
   377     TotalEnergyDeposit = aStep.GetTotalEnergyDeposit();
   382     G4double InitialKinetEnergy = aMaterialPropertiesTable->
   383     GetConstProperty( 
"ENERGY_DEPOSIT_GOL" );
   385     if ( InitialKinetEnergy == 0 ) {
   386       G4double tE = pPreStepPoint->GetKineticEnergy()+anExcitationEnergy;
   388           Phase == kStateLiquid && z1 == 54 ) tE = 9.4*
CLHEP::keV;
   389       if ( fKr83m && ElectricField != 0 )
   391       aMaterialPropertiesTable->
   392       AddConstProperty ( 
"ENERGY_DEPOSIT_GOL", tE );
   396       if ( anExcitationEnergy ) fExcitedNucleus = 
true;
   400     if(outside){ aMaterialPropertiesTable->
   401       AddConstProperty(
"ENERGY_DEPOSIT_GOL",
   402                        InitialKinetEnergy-pPostStepPoint->GetKineticEnergy());
   403       if(aMaterialPropertiesTable->
   404          GetConstProperty(
"ENERGY_DEPOSIT_GOL")<0)
   405         aMaterialPropertiesTable->AddConstProperty(
"ENERGY_DEPOSIT_GOL",0);
   409     if(inside) { aMaterialPropertiesTable->
   410       AddConstProperty(
"ENERGY_DEPOSIT_GOL",
   411                        InitialKinetEnergy+pPreStepPoint->GetKineticEnergy());
   412       if ( TotalEnergyDeposit > 0 && InitialKinetEnergy == 0 ) {
   413         aMaterialPropertiesTable->AddConstProperty(
"ENERGY_DEPOSIT_GOL",0);
   414         TotalEnergyDeposit = .000000;
   420       aMaterialPropertiesTable->
   421       AddConstProperty(
"ENERGY_DEPOSIT_GOL",(-0.1*
CLHEP::keV)+
   422                        InitialKinetEnergy-pPostStepPoint->GetKineticEnergy());
   423       InitialKinetEnergy = bMaterial->GetMaterialPropertiesTable()->
   424       GetConstProperty(
"ENERGY_DEPOSIT_GOL");
   425       bMaterial->GetMaterialPropertiesTable()->
   426       AddConstProperty(
"ENERGY_DEPOSIT_GOL",(-0.1*
CLHEP::keV)+
   427                        InitialKinetEnergy+pPreStepPoint->GetKineticEnergy());
   428       if(aMaterialPropertiesTable->
   429          GetConstProperty(
"ENERGY_DEPOSIT_GOL")<0)
   430         aMaterialPropertiesTable->AddConstProperty(
"ENERGY_DEPOSIT_GOL",0);
   431       if ( bMaterial->GetMaterialPropertiesTable()->
   432           GetConstProperty(
"ENERGY_DEPOSIT_GOL") < 0 )
   433         bMaterial->GetMaterialPropertiesTable()->
   434         AddConstProperty ( 
"ENERGY_DEPOSIT_GOL", 0 );
   436     InitialKinetEnergy = aMaterialPropertiesTable->
   437     GetConstProperty(
"ENERGY_DEPOSIT_GOL"); 
   439       InitialKinetEnergy += 2*CLHEP::electron_mass_c2;
   443       InitialKinetEnergy -= 2*CLHEP::electron_mass_c2;
   445     aMaterialPropertiesTable->
   446     AddConstProperty(
"ENERGY_DEPOSIT_GOL",InitialKinetEnergy);
   447     if (anExcitationEnergy < 1
e-100 && aStep.GetTotalEnergyDeposit()==0 &&
   448         aMaterialPropertiesTable->GetConstProperty(
"ENERGY_DEPOSIT_GOL")==0 &&
   449         aMaterialPropertiesTable->GetConstProperty(
"ENERGY_DEPOSIT_TOT")==0)
   453     if ( aTrack.GetCreatorProcess() )
   454       procName = aTrack.GetCreatorProcess()->GetProcessName();
   458       fMultipleScattering = 
true;
   465         fMultipleScattering = 
true;
   469     char xCoord[80]; 
char yCoord[80]; 
char zCoord[80];
   473       sprintf(xCoord,
"POS_X_%d",i); sprintf(yCoord,
"POS_Y_%d",i);
   474       sprintf(zCoord,
"POS_Z_%d",i);
   475       pos[0] = aMaterialPropertiesTable->GetConstProperty(xCoord);
   476       pos[1] = aMaterialPropertiesTable->GetConstProperty(yCoord);
   477       pos[2] = aMaterialPropertiesTable->GetConstProperty(zCoord);
   478       if ( sqrt(
pow(x1[0]-pos[0],2.)+
pow(x1[1]-pos[1],2.)+
   479                 pow(x1[2]-pos[2],2.)) < delta ) {
   480         exists = 
true; 
break; 
   483     if(!exists && TotalEnergyDeposit) { 
   485       sprintf(xCoord,
"POS_X_%i",j); sprintf(yCoord,
"POS_Y_%i",j);
   486       sprintf(zCoord,
"POS_Z_%i",j);
   488       aMaterialPropertiesTable->AddConstProperty( xCoord, x1[0] );
   489       aMaterialPropertiesTable->AddConstProperty( yCoord, x1[1] );
   490       aMaterialPropertiesTable->AddConstProperty( zCoord, x1[2] );
   492       aMaterialPropertiesTable-> 
   493       AddConstProperty( 
"TOTALNUM_INT_SITES", j );
   501     G4double 
a1 = ElementA->GetA();
   502     z2 = pDef->GetAtomicNumber();
   503     G4double 
a2 = (G4double)(pDef->GetAtomicMass());
   504     if ( particleName == 
"alpha" || (z2 == 2 && a2 == 4) )
   506     if ( fAlpha || 
abs(aParticle->GetPDGcode()) == 2112 )
   508     G4double epsilon = 11.5*(TotalEnergyDeposit/
CLHEP::keV)*
pow(z1,(-7./3.));
   509     G4double 
gamma = 3.*
pow(epsilon,0.15)+0.7*
pow(epsilon,0.6)+epsilon;
   510     G4double kappa = 0.133*
pow(z1,(2./3.))*
pow(a2,(-1./2.))*(2./3.);
   512     if ( (z1 == z2 && pDef->GetParticleType() == 
"nucleus") ||
   513         particleName == 
"neutron" || particleName == 
"antineutron" ) {
   515       if ( z1 == 18 && Phase == kStateLiquid )
   520       if ( ElectricField == 0 && Phase == kStateLiquid ) {
   521         if ( z1 == 54 ) ThomasImel = 0.19;
   522         if ( z1 == 18 ) ThomasImel = 0.25;
   525       0.3065*exp(-0.008806*
pow(ElectricField,0.76313));
   530     G4double MeanNumberOfQuanta = 
   531     ScintillationYield*TotalEnergyDeposit;
   534     G4double sigma = sqrt(ResolutionScale*MeanNumberOfQuanta); 
   536     G4int(floor(GaussGen.fire(MeanNumberOfQuanta,sigma)+0.5));
   538     if      (LeffVar > 1) LeffVar = 1.00000;
   539     else if (LeffVar < 0) LeffVar = 0;
   543     if(TotalEnergyDeposit < 1/ScintillationYield || NumQuanta < 0)
   549     G4int NumIons = NumQuanta - NumExcitons;
   555     G4double dE, dx=0, LET=0, recombProb;
   557     if ( particleName != 
"e-" && particleName != 
"e+" && z1 != z2 &&
   558         particleName != 
"mu-" && particleName != 
"mu+" ) {
   564       if(LET) dx = dE/(Density*LET); 
   565       if(
abs(aParticle->GetPDGcode())==2112) dx=0;
   569       if(dx) LET = (dE/dx)*(1/Density); 
   570       if ( LET > 0 && dE > 0 && dx > 0 ) {
   573             particleName == 
"e-" ) {
   576     DokeBirks[1] = DokeBirks[0]/(1-DokeBirks[2]); 
   578     recombProb = (DokeBirks[0]*LET)/(1+DokeBirks[1]*LET)+DokeBirks[2];
   579     if ( Phase == kStateLiquid ) {
   580       if ( z1 == 54 ) recombProb *= (Density/
Density_LXe);
   581       if ( z1 == 18 ) recombProb *= (Density/
Density_LAr);
   584     if(recombProb<0) recombProb=0;
   585     if(recombProb>1) recombProb=1;
   589     G4int NumPhotons = NumExcitons + 
BinomFluct(NumIons,recombProb);
   590     G4int NumElectrons = NumQuanta - NumPhotons;
   601     char numExc[80]; 
char numIon[80]; 
char numPho[80]; 
char numEle[80];
   602     sprintf(numExc,
"N_EXC_%i",counter); sprintf(numIon,
"N_ION_%i",counter);
   603     aMaterialPropertiesTable->AddConstProperty( numExc, NumExcitons );
   604     aMaterialPropertiesTable->AddConstProperty( numIon, NumIons     );
   605     sprintf(numPho,
"N_PHO_%i",counter); sprintf(numEle,
"N_ELE_%i",counter);
   606     aMaterialPropertiesTable->AddConstProperty( numPho, NumPhotons   );
   607     aMaterialPropertiesTable->AddConstProperty( numEle, NumElectrons );
   611     char trackL[80]; 
char time00[80]; 
char time01[80]; 
char energy[80];
   612     sprintf(trackL,
"TRACK_%i",counter); sprintf(energy,
"ENRGY_%i",counter);
   613     sprintf(time00,
"TIME0_%i",counter); sprintf(time01,
"TIME1_%i",counter);
   614     delta = aMaterialPropertiesTable->GetConstProperty( trackL );
   615     G4double energ = aMaterialPropertiesTable->GetConstProperty( energy );
   617     aMaterialPropertiesTable->AddConstProperty( trackL, delta );
   618     aMaterialPropertiesTable->AddConstProperty( energy, energ );
   619     if ( TotalEnergyDeposit > 0 ) {
   620       G4double deltaTime = aMaterialPropertiesTable->
   621       GetConstProperty( time00 );
   624       if (aParticle->GetCharge() != 0) {
   626           aMaterialPropertiesTable->AddConstProperty( time00, t0 );
   630           aMaterialPropertiesTable->AddConstProperty( time00, t1 );
   632       deltaTime = aMaterialPropertiesTable->GetConstProperty( time01 );
   635         aMaterialPropertiesTable->AddConstProperty( time01, t1 );
   639     TotalEnergyDeposit=aMaterialPropertiesTable->
   640     GetConstProperty(
"ENERGY_DEPOSIT_TOT"); 
   641     InitialKinetEnergy=aMaterialPropertiesTable->
   642     GetConstProperty(
"ENERGY_DEPOSIT_GOL"); 
   643     if(InitialKinetEnergy > 
HIENLIM &&
   644        abs(aParticle->GetPDGcode()) != 2112) fVeryHighEnergy=
true;
   646     if (fVeryHighEnergy && !fExcitedNucleus) safety = 0.2*
CLHEP::keV;
   650     if( !anExcitationEnergy && pDef->GetParticleType() == 
"nucleus" &&
   651        aTrack.GetTrackStatus() != fAlive && !fAlpha )
   652       InitialKinetEnergy = TotalEnergyDeposit;
   653     if ( particleName == 
"neutron" || particleName == 
"antineutron" )
   654       InitialKinetEnergy = TotalEnergyDeposit;
   659     if( 
std::abs(TotalEnergyDeposit-InitialKinetEnergy)<safety ||
   660        TotalEnergyDeposit>=InitialKinetEnergy ){
   664       NumPhotons = 0; NumElectrons = 0;
   666         sprintf(numPho,
"N_PHO_%d",i); sprintf(numEle,
"N_ELE_%d",i);
   667         sprintf(trackL,
"TRACK_%d",i); sprintf(energy,
"ENRGY_%d",i);
   669         dx += aMaterialPropertiesTable->GetConstProperty(trackL);
   670         dE += aMaterialPropertiesTable->GetConstProperty(energy);
   673       G4int buffer = 100; 
if ( fVeryHighEnergy ) buffer = 1;
   674       fParticleChange.SetNumberOfSecondaries(buffer*(NumPhotons+NumElectrons));
   676       if (fTrackSecondariesFirst) {
   677         if (aTrack.GetTrackStatus() == fAlive )
   686         sprintf(xCoord,
"POS_X_%d",i); sprintf(yCoord,
"POS_Y_%d",i);
   687         sprintf(zCoord,
"POS_Z_%d",i);
   688         sprintf(numExc,
"N_EXC_%d",i); sprintf(numIon,
"N_ION_%d",i);
   689         sprintf(numPho,
"N_PHO_%d",i); sprintf(numEle,
"N_ELE_%d",i);
   690         NumExcitons = (G4int)aMaterialPropertiesTable->
   691         GetConstProperty( numExc );
   692         NumIons     = (G4int)aMaterialPropertiesTable->
   693         GetConstProperty( numIon );
   694         sprintf(trackL,
"TRACK_%d",i); sprintf(energy,
"ENRGY_%d",i);
   695         sprintf(time00,
"TIME0_%d",i); sprintf(time01,
"TIME1_%d",i);
   696         delta = aMaterialPropertiesTable->GetConstProperty( trackL );
   697         energ = aMaterialPropertiesTable->GetConstProperty( energy );
   698         t0 = aMaterialPropertiesTable->GetConstProperty( time00 );
   699         t1 = aMaterialPropertiesTable->GetConstProperty( time01 );
   705         if ( (delta < R0 && !fVeryHighEnergy) || z2 == z1 || fAlpha ) {
   706           if( z1 == 54 && ElectricField && 
   707              Phase == kStateLiquid ) {
   708             if ( 
abs ( z1 - z2 ) && 
   709                 abs ( aParticle->GetPDGcode() ) != 2112 ) {
   710               ThomasImel = 0.056776*
pow(ElectricField,-0.11844);
   712                 ThomasImel=0.057675*
pow(ElectricField,-0.49362);
   718               -0.15169*
pow((ElectricField+215.25),0.01811)+0.20952;
   721             if (ThomasImel > 0.19) ThomasImel = 0.19;
   722             if (ThomasImel < 0.00) ThomasImel = 0.00;
   724           if ( Phase == kStateLiquid ) {
   725             if ( z1 == 54 ) ThomasImel *= 
pow((Density/2.84),0.3);
   733             xi = (G4double(NumIons)/4.)*ThomasImel;
   736               (0.17163+162.32/(ElectricField+191.39));
   737               if ( NumIonsEff > 1e6 ) NumIonsEff = 1e6;
   738               xi = (G4double(NumIonsEff)/4.)*ThomasImel;
   740             if ( fKr83m && ElectricField==0 )
   741               xi = (G4double(1.3*NumIons)/4.)*ThomasImel;
   742             recombProb = 1-log(1+xi)/xi;
   743             if(recombProb<0) recombProb=0;
   744             if(recombProb>1) recombProb=1;
   747           NumPhotons = NumExcitons + 
BinomFluct(NumIons,recombProb);
   748           NumElectrons = (NumExcitons + NumIons) - NumPhotons;
   750           aMaterialPropertiesTable->
   751           AddConstProperty( numPho, NumPhotons   );
   752           aMaterialPropertiesTable->
   753           AddConstProperty( numEle, NumElectrons );
   758         NumPhotons  = (G4int)aMaterialPropertiesTable->
   759         GetConstProperty( numPho );
   760         NumElectrons =(G4int)aMaterialPropertiesTable->
   761         GetConstProperty( numEle );
   763         G4double FanoFactor =0; 
   766           2575.9*
pow((ElectricField+15.154),-0.64064)-1.4707;
   767           if ( fKr83m ) TotalEnergyDeposit = 4*
CLHEP::keV;
   768           if ( (dE/
CLHEP::keV) <= 100 && ElectricField >= 0 ) {
   769             G4double keVee = (TotalEnergyDeposit/(100.*
CLHEP::keV));
   771               FanoFactor *= -0.00075+0.4625*keVee+34.375*
pow(keVee,2.);
   773               FanoFactor *= 0.069554+1.7322*keVee-.80215*
pow(keVee,2.);
   776         if ( Phase == kStateGas && Density>0.5 ) FanoFactor =
   777           0.42857-4.7857*Density+7.8571*
pow(Density,2.);
   778         if( FanoFactor <= 0 || fVeryHighEnergy ) FanoFactor = 0;
   779         NumQuanta = NumPhotons + NumElectrons;
   780         if(z1==54 && FanoFactor) NumElectrons = G4int(
   781                                                       floor(GaussGen.fire(NumElectrons,
   782                                                                           sqrt(FanoFactor*NumElectrons))+0.5));
   783         NumPhotons = NumQuanta - NumElectrons;
   784         if ( NumElectrons <= 0 ) NumElectrons = 0;
   785         if (   NumPhotons <= 0 )   NumPhotons = 0;
   790         } NumElectrons = G4int(floor(NumElectrons*
phe_per_e+0.5));
   797         if(fKr83m > 41) fKr83m = 0;
   803         aMaterialPropertiesTable->AddConstProperty( numExc, 0 );
   804         aMaterialPropertiesTable->AddConstProperty( numIon, 0 );
   805         aMaterialPropertiesTable->AddConstProperty( numPho, 0 );
   806         aMaterialPropertiesTable->AddConstProperty( numEle, 0 );
   809         if( InitialKinetEnergy < MAX_ENE && InitialKinetEnergy > 
MIN_ENE &&
   810            !fMultipleScattering )
   811           NumQuanta = NumPhotons + NumElectrons;
   813         for(k = 0; k < NumQuanta; k++) {
   814           G4double sampledEnergy;
   815           G4DynamicParticle* aQuantum;
   818           G4double cost = 1. - 2.*UniformGen.fire();
   819           G4double sint = std::sqrt((1.-cost)*(1.+cost));
   821           G4double sinp = std::sin(phi); G4double cosp = std::cos(phi);
   822           G4double 
px = sint*cosp; G4double 
py = sint*sinp;
   826           G4ParticleMomentum photonMomentum(px, py, pz);
   829           if (k < NumPhotons) {
   831             G4double sx = cost*cosp;
   832             G4double sy = cost*sinp;
   834             G4ThreeVector photonPolarization(sx, sy, sz);
   835             G4ThreeVector perp = photonMomentum.cross(photonPolarization);
   837             sinp = std::sin(phi);
   838             cosp = std::cos(phi);
   839             photonPolarization = cosp * photonPolarization + sinp * perp;
   840             photonPolarization = photonPolarization.unit();
   843             sampledEnergy = GaussGen.fire(PhotMean,PhotWidth);
   844             aQuantum = 
new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(),
   846             aQuantum->SetPolarization(photonPolarization.x(),
   847                                       photonPolarization.y(),
   848                                       photonPolarization.z());
   854               G4ParticleMomentum electronMomentum(0, 0, -FieldSign);
   858               if ( Phase == kStateGas ) {
   875           aQuantum->SetKineticEnergy(sampledEnergy);
   884           G4double aSecondaryTime = t0+UniformGen.fire()*(t1-
t0)+evtStrt;
   888           if ( aQuantum->GetDefinition()->
   889               GetParticleName()==
"opticalphoton" ) {
   890             if ( 
abs(z2-z1) && !fAlpha && 
   891                 abs(aParticle->GetPDGcode()) != 2112 ) {
   898               if ( Phase == kStateLiquid && z1 == 54 )
   899                 tauR = 3.5*((1+0.41*LET)/(0.18*LET))*
CLHEP::ns   900                 *exp(-0.00900*ElectricField);
   907               SingTripRatioX = GaussGen.fire(0.17,0.05);
   908               SingTripRatioR = GaussGen.fire(0.8,0.2);
   910                 SingTripRatioR = 0.2701+0.003379*LET-4.7338e-5*
pow(LET,2.)
   911                 +8.1449e-6*
pow(LET,3.); SingTripRatioX = SingTripRatioR;
   913                   SingTripRatioX = GaussGen.fire(0.36,0.06);
   914                   SingTripRatioR = GaussGen.fire(0.5,0.2); }
   918               SingTripRatioR = GaussGen.fire(2.3,0.51);
   921               if (z1==18) SingTripRatioR = (-0.065492+1.9996
   922                                             *exp(-dE/CLHEP::MeV))/(1+0.082154/
pow(dE/CLHEP::MeV,2.)) + 2.1811;
   923               SingTripRatioX = SingTripRatioR;
   928               SingTripRatioR = GaussGen.fire(7.8,1.5);
   929               if (z1==18) SingTripRatioR = 0.22218*
pow(energ/
CLHEP::keV,0.48211);
   930               SingTripRatioX = SingTripRatioR;
   935             if ( k > NumExcitons ) {
   938               aSecondaryTime += tauR*(1./UniformGen.fire()-1);
   939               if(UniformGen.fire()<SingTripRatioR/(1+SingTripRatioR))
   940                 aSecondaryTime -= tau1*log(UniformGen.fire());
   941               else aSecondaryTime -= tau3*log(UniformGen.fire());
   944               if(UniformGen.fire()<SingTripRatioX/(1+SingTripRatioX))
   945                 aSecondaryTime -= tau1*log(UniformGen.fire());
   946               else aSecondaryTime -= tau3*log(UniformGen.fire());
   950             G4double gainField = 12;
   951             G4double tauTrap = 884.83-62.069*gainField;
   952             if ( Phase == kStateLiquid )
   953               aSecondaryTime -= tauTrap*
CLHEP::ns*log(UniformGen.fire());
   965           x0[0] = aMaterialPropertiesTable->GetConstProperty( xCoord );
   966           x0[1] = aMaterialPropertiesTable->GetConstProperty( yCoord );
   967           x0[2] = aMaterialPropertiesTable->GetConstProperty( zCoord );
   968           G4double radius = sqrt(
pow(x0[0],2.)+
pow(x0[1],2.));
   971           if ( radius >= 
R_TOL ) {
   974             radius -= 
R_TOL; phi = atan ( x0[1] / x0[0] );
   975             x0[0] = fabs(radius*cos(phi))*((fabs(x0[0]))/(x0[0]));
   976             x0[1] = fabs(radius*sin(phi))*((fabs(x0[1]))/(x0[1]));
   979           G4ThreeVector aSecondaryPosition = x0;
   980           if ( k >= NumPhotons && diffusion && ElectricField > 0 ) {
   981             G4double D_T = 64*
pow(1
e-3*ElectricField,-.17);
   983             G4double D_L = 13.859*
pow(1
e-3*ElectricField,-0.58559);
   985             if ( Phase == kStateLiquid && z1 == 18 ) {
   986               D_T = 93.342*
pow(ElectricField/nDensity,0.041322);
   988             if ( Phase == kStateGas && z1 == 54 ) {
   989               D_L=4.265+19097/ElectricField-1.7397e6/
pow(ElectricField,2.)+
   990               1.2477e8/
pow(ElectricField,3.); D_T *= 0.01;
   993             G4double vDrift = sqrt((2*sampledEnergy)/(
EMASS));
   994             if ( 
BORDER == 0 ) x0[2] = 0;
   995             G4double sigmaDT = sqrt(2*D_T*fabs(
BORDER-x0[2])/vDrift);
   996             G4double sigmaDL = sqrt(2*D_L*fabs(
BORDER-x0[2])/vDrift);
   997             G4double dr = 
std::abs(GaussGen.fire(0.,sigmaDT));
   999             aSecondaryPosition[0] += cos(phi) * dr;
  1000             aSecondaryPosition[1] += sin(phi) * dr;
  1001             aSecondaryPosition[2] += GaussGen.fire(0.,sigmaDL);
  1002             radius = std::sqrt(
std::pow(aSecondaryPosition[0],2.)+
  1003                                std::pow(aSecondaryPosition[1],2.));
  1004             if(aSecondaryPosition[2] >= 
BORDER && Phase == kStateLiquid) {
  1006             if(aSecondaryPosition[2] <= 
PMT && !GlobalFields)
  1007               aSecondaryPosition[2] = 
PMT + 
R_TOL;
  1011           if ( aSecondaryTime < 0 ) aSecondaryTime = 0; 
  1022         aMaterialPropertiesTable->AddConstProperty( xCoord, 999*
CLHEP::km );
  1023         aMaterialPropertiesTable->AddConstProperty( yCoord, 999*
CLHEP::km );
  1024         aMaterialPropertiesTable->AddConstProperty( zCoord, 999*
CLHEP::km );
  1025         aMaterialPropertiesTable->AddConstProperty( trackL, 0*
CLHEP::um );
  1026         aMaterialPropertiesTable->AddConstProperty( energy, 0*
CLHEP::eV );
  1027         aMaterialPropertiesTable->AddConstProperty( time00, DBL_MAX );
  1028         aMaterialPropertiesTable->AddConstProperty( time01, -1*
CLHEP::ns );
  1033       aMaterialPropertiesTable->
  1034       AddConstProperty( 
"TOTALNUM_INT_SITES", 0 );
  1035       aMaterialPropertiesTable->
  1036       AddConstProperty( 
"ENERGY_DEPOSIT_TOT", 0*
CLHEP::keV );
  1037       aMaterialPropertiesTable->
  1038       AddConstProperty( 
"ENERGY_DEPOSIT_GOL", 0*CLHEP::MeV );
  1039       fExcitedNucleus = 
false;
  1056     std::cout << 
"WARNING: NestAlg::GetGasElectronDriftSpeed(G4double, G4double) "  1057     << 
"is not defined, returning bogus value of -999." << 
std::endl;
  1065                                                 G4double efieldinput,
  1068     if(efieldinput<0) efieldinput *= (-1);
  1070     G4double onea=144623.235704015,
  1071     oneb=850.812714257629,
  1072     onec=1192.87056676815,
  1073     oned=-395969.575204061,
  1074     onef=-355.484170008875,
  1075     oneg=-227.266219627672,
  1076     oneh=223831.601257495,
  1077     onei=6.1778950907965,
  1078     onej=18.7831533426398,
  1079     onek=-76132.6018884368;
  1081     G4double twoa=17486639.7118995,
  1082     twob=-113.174284723134,
  1083     twoc=28.005913193763,
  1084     twod=167994210.094027,
  1085     twof=-6766.42962575088,
  1086     twog=901.474643115395,
  1087     twoh=-185240292.471665,
  1088     twoi=-633.297790813084,
  1089     twoj=87.1756135457949;
  1091     G4double thra=10626463726.9833,
  1092     thrb=224025158.134792,
  1093     thrc=123254826.300172,
  1094     thrd=-4563.5678061122,
  1095     thrf=-1715.269592063,
  1096     thrg=-694181.921834368,
  1097     thrh=-50.9753281079838,
  1098     thri=58.3785811395493,
  1099     thrj=201512.080026704;
  1100     G4double y1=0,y2=0,
f1=0,
f2=0,
f3=0,edrift=0,
  1101     t1=0,t2=0,slope=0,intercept=0;
  1104     f1=onea/(1+exp(-(efieldinput-oneb)/onec))+oned/
  1105     (1+exp(-(efieldinput-onef)/oneg))+
  1106     oneh/(1+exp(-(efieldinput-onei)/onej))+onek;
  1107     f2=twoa/(1+exp(-(efieldinput-twob)/twoc))+twod/
  1108     (1+exp(-(efieldinput-twof)/twog))+
  1109     twoh/(1+exp(-(efieldinput-twoi)/twoj));
  1110     f3=thra*exp(-thrb*efieldinput)+thrc*exp(-(
pow(efieldinput-thrd,2))/
  1112     thrg*exp(-(
pow(efieldinput-thrh,2)/(thri*thri)))+thrj;
  1114     if(efieldinput<20 && efieldinput>=0) {
  1115       f1=2951*efieldinput;
  1116       f2=5312*efieldinput;
  1117       f3=7101*efieldinput;
  1120     if(tempinput<200.0 && tempinput>165.0) {
  1126     if(tempinput<230.0 && tempinput>200.0) {
  1132     if((tempinput>230.0 || tempinput<165.0) && !Miller) {
  1133       G4cout << 
"\nWARNING: TEMPERATURE OUT OF RANGE (165-230 K)\n";
  1136     if (tempinput == 165.0) edrift = 
f1;
  1137     else if (tempinput == 200.0) edrift = 
f2;
  1138     else if (tempinput == 230.0) edrift = 
f3;
  1141       slope = (y1-y2)/(
t1-t2);
  1142       intercept=y1-slope*
t1;
  1143       edrift=slope*tempinput+intercept;
  1147       if ( efieldinput <= 40. )
  1148         edrift = -0.13274+0.041082*efieldinput-0.0006886*
pow(efieldinput,2.)+
  1149         5.5503e-6*
pow(efieldinput,3.);
  1151         edrift = 0.060774*efieldinput/
pow(1+0.11336*
pow(efieldinput,0.5218),2.);
  1152       if ( efieldinput >= 1e5 ) edrift = 2.7;
  1153       if ( efieldinput >= 100 )
  1154         edrift -= 0.017 * ( tempinput - 163 );
  1156         edrift += 0.017 * ( tempinput - 163 );
  1159     if ( Z == 18 ) edrift = 1e5 * (.097384*
pow(log10(efieldinput),3.0622)-.018614*sqrt(efieldinput) );
  1160     if ( edrift < 0 ) edrift = 0.;
  1171         if ( E >= 1 ) LET = 58.482-61.183*log10(E)+19.749*
pow(log10(E),2)+
  1172           2.3101*
pow(log10(E),3)-3.3469*
pow(log10(E),4)+
  1173           0.96788*
pow(log10(E),5)-0.12619*
pow(log10(E),6)+0.0065108*
pow(log10(E),7);
  1177         else if ( E>0 && E<1 ) LET = 6.9463+815.98*E-4828*
pow(E,2)+17079*
pow(E,3)-
  1178           36394*
pow(E,4)+44553*
pow(E,5)-28659*
pow(E,6)+7483.8*
pow(E,7);
  1183         if ( E >= 1 ) LET = 116.70-162.97*log10(E)+99.361*
pow(log10(E),2)-
  1184           33.405*
pow(log10(E),3)+6.5069*
pow(log10(E),4)-
  1185           0.69334*
pow(log10(E),5)+.031563*
pow(log10(E),6);
  1186         else if ( E>0 && E<1 ) LET = 100;
  1195     CLHEP::RandGauss GaussGen(
fEngine);
  1196     CLHEP::RandFlat  UniformGen(
fEngine);
  1198     G4double 
mean = N0*prob;
  1199     G4double sigma = sqrt(N0*prob*(1-prob));
  1201     if ( prob == 0.00 ) 
return N1;
  1202     if ( prob == 1.00 ) 
return N0;
  1205       for(G4int i = 0; i < N0; i++) {
  1206         if(UniformGen.fire() < prob) N1++;
  1210       N1 = G4int(floor(GaussGen.fire(mean,sigma)+0.5));
  1212     if ( N1 > N0 ) N1 = N0;
  1213     if ( N1 < 0 ) N1 = 0;
  1220     char xCoord[80]; 
char yCoord[80]; 
char zCoord[80];
  1221     char numExc[80]; 
char numIon[80]; 
char numPho[80]; 
char numEle[80];
  1222     char trackL[80]; 
char time00[80]; 
char time01[80]; 
char energy[80];
  1225     for( G4int i=0; i<10000; i++ ) {
  1226       sprintf(xCoord,
"POS_X_%d",i); sprintf(yCoord,
"POS_Y_%d",i);
  1227       sprintf(zCoord,
"POS_Z_%d",i);
  1228       nobleElementMat->AddConstProperty( xCoord, 999*
CLHEP::km );
  1229       nobleElementMat->AddConstProperty( yCoord, 999*
CLHEP::km );
  1230       nobleElementMat->AddConstProperty( zCoord, 999*
CLHEP::km );
  1231       sprintf(numExc,
"N_EXC_%d",i); sprintf(numIon,
"N_ION_%d",i);
  1232       sprintf(numPho,
"N_PHO_%d",i); sprintf(numEle,
"N_ELE_%d",i);
  1233       nobleElementMat->AddConstProperty( numExc, 0 );
  1234       nobleElementMat->AddConstProperty( numIon, 0 );
  1235       nobleElementMat->AddConstProperty( numPho, 0 );
  1236       nobleElementMat->AddConstProperty( numEle, 0 );
  1237       sprintf(trackL,
"TRACK_%d",i); sprintf(energy,
"ENRGY_%d",i);
  1238       sprintf(time00,
"TIME0_%d",i); sprintf(time01,
"TIME1_%d",i);
  1239       nobleElementMat->AddConstProperty( trackL, 0*
CLHEP::um );
  1240       nobleElementMat->AddConstProperty( energy, 0*
CLHEP::eV );
  1241       nobleElementMat->AddConstProperty( time00, DBL_MAX );
  1242       nobleElementMat->AddConstProperty( time01,-1*
CLHEP::ns );
  1248     nobleElementMat->AddConstProperty( 
"TOTALNUM_INT_SITES", 0 );
  1249     nobleElementMat->AddConstProperty( 
"ENERGY_DEPOSIT_TOT", 0*
CLHEP::keV );
  1250     nobleElementMat->AddConstProperty( 
"ENERGY_DEPOSIT_GOL", 0*
CLHEP::MeV );
  1259     G4double a_0 = 5.29e-11*
CLHEP::m; G4double 
a = 0.626*a_0*
pow(Z,(-1./3.));
  1262     G4double zeta_0 = 
pow(Z,(1./6.)); G4double m_N = A*1.66e-27*
CLHEP::kg;
  1267     G4double s_n = log(1+1.1383*epsilon)/(2.*(epsilon +
  1268                                               0.01321*
pow(epsilon,0.21226) +
  1269                                               0.19593*sqrt(epsilon)));
  1270     G4double s_e = (a_0*zeta_0/
a)*hbar*sqrt(8*epsilon*2.*
CLHEP::twopi*epsilon_0/
  1272     return 1.38e5*0.5*(1+tanh(50*epsilon-0.25))*epsilon*(s_e/s_n);
 static constexpr double cm
 
code to link reconstructed objects back to the MC truth information 
 
static constexpr double keV
 
G4VParticleChange fParticleChange
pointer to G4VParticleChange 
 
static constexpr double g
 
double fYieldFactor
turns scint. on/off 
 
static constexpr double cm3
 
static constexpr double kg
 
int fNumIonElectrons
number of ionization electrons produced by step 
 
static constexpr double MeV
 
static constexpr double km
 
CLHEP::HepRandomEngine & fEngine
random engine 
 
kilovolt_as<> kilovolt
Type of potential stored in kilovolt, in double precision. 
 
bool exists(std::string path)
 
static G4ThermalElectron * ThermalElectron()
 
static constexpr double eV
 
static constexpr double cm2
 
def convert(inputfile, outputfile="wire-cell-garfield-fine-response.json.bz2", average=False, shaped=False)
 
G4double GetLiquidElectronDriftSpeed(double T, double F, G4bool M, G4int Z)
 
double gamma(double KE, const simb::MCParticle *part)
 
std::map< int, bool > fElementPropInit
 
int fNumScintPhotons
number of photons produced by the step 
 
General GArSoft Utilities. 
 
double fEnergyDep
energy deposited by the step 
 
const G4VParticleChange & CalculateIonizationAndScintillation(G4Track const &aTrack, G4Step const &aStep)
 
static constexpr double mm
 
NestAlg(CLHEP::HepRandomEngine &engine)
 
G4double GetGasElectronDriftSpeed(G4double efieldinput, G4double density)
 
G4int BinomFluct(G4int N0, G4double prob)
 
G4double CalculateElectronLET(G4double E, G4int Z)
 
void InitMatPropValues(G4MaterialPropertiesTable *nobleElementMat, int z)
 
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
 
QTextStream & endl(QTextStream &s)
 
G4double UnivScreenFunc(G4double E, G4double Z, G4double A)
 
double fExcitationRatio
excitons to ions