Import Geant4 4.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 16:39:52 +02:00
parent 921d3b1cda
commit 330b82b769
4524 changed files with 178689 additions and 43575 deletions
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4ComptonScattering.cc,v 1.14 2001/10/01 15:00:29 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4ComptonScattering.cc,v 1.16 2002/04/18 10:12:01 maire Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//
//------------ G4ComptonScattering physics process -----------------------------
@@ -46,7 +46,8 @@
// 06-08-01, BuildThePhysicsTable() called from constructor (mma)
// 17-09-01, migration of Materials to pure STL (mma)
// 20-09-01, DoIt: fminimalEnergy = 1*eV (mma)
// 01-10-01, come back to BuildPhysicsTable(const G4ParticleDefinition&)
// 01-10-01, come back to BuildPhysicsTable(const G4ParticleDefinition&)
// 17-04-02, LowestEnergyLimit = 1*keV
// -----------------------------------------------------------------------------
#include "G4ComptonScattering.hh"
@@ -60,9 +61,9 @@ G4ComptonScattering::G4ComptonScattering(const G4String& processName)
: G4VDiscreteProcess (processName),
theCrossSectionTable(NULL),
theMeanFreePathTable(NULL),
LowestEnergyLimit ( 10*keV),
LowestEnergyLimit ( 1*keV),
HighestEnergyLimit(100*GeV),
NumbBinTable(100),
NumbBinTable(80),
fminimalEnergy(1*eV)
{}
@@ -170,7 +171,7 @@ G4double G4ComptonScattering::ComputeCrossSectionPerAtom
{
G4double CrossSection = 0.0 ;
if ( Z < 1. ) return CrossSection;
if ( GammaEnergy < 10.*keV ) return CrossSection;
if ( GammaEnergy < 1.*keV ) return CrossSection;
if ( GammaEnergy > (100.*GeV/Z) ) return CrossSection;
static const G4double a = 20.0 , b = 230.0 , c = 440.0;
@@ -21,38 +21,40 @@
// ********************************************************************
//
//
// $Id: G4GammaConversion.cc,v 1.14 2001/10/01 15:00:29 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4GammaConversion.cc,v 1.17 2002/04/09 17:34:41 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//------------------ G4GammaConversion physics process -------------------------
// by Michel Maire, 24 May 1996
//
// 11-06-96, Added SelectRandomAtom() method, M.Maire
// 21-06-96, SetCuts implementation, M.Maire
// 24-06-96, simplification in ComputeCrossSectionPerAtom, M.Maire
// 24-06-96, in DoIt : change the particleType stuff, M.Maire
// 25-06-96, modification in the generation of the teta angle, M.Maire
// 16-09-96, minors optimisations in DoIt. Thanks to P.Urban
// dynamical array PartialSumSigma
// 13-12-96, fast sampling of epsil below 2 MeV, L.Urban
// 14-01-97, crossection table + meanfreepath table.
// PartialSumSigma removed, M.Maire
// 14-01-97, in DoIt the positron is always created, even with Ekine=0,
// for further annihilation, M.Maire
// 14-03-97, new Physics scheme for geant4alpha, M.Maire
// 28-03-97, protection in BuildPhysicsTable, M.Maire
// 19-06-97, correction in ComputeCrossSectionPerAtom, L.Urban
// 04-06-98, in DoIt, secondary production condition:
// range>G4std::min(threshold,safety)
// 13-08-98, new methods SetBining() PrintInfo()
// 28-05-01, V.Ivanchenko minor changes to provide ANSI -wall compilation
// 11-07-01, PostStepDoIt - sampling epsil: power(rndm,0.333333)
// 13-07-01, DoIt: suppression of production cut for the (e-,e+) (mma)
// 06-08-01, new methods Store/Retrieve PhysicsTable (mma)
// 06-08-01, BuildThePhysicsTable() called from constructor (mma)
// 17-09-01, migration of Materials to pure STL (mma)
// 20-09-01, DoIt: fminimalEnergy = 1*eV (mma)
// 01-10-01, come back to BuildPhysicsTable(const G4ParticleDefinition&)
// 11-06-96 Added SelectRandomAtom() method, M.Maire
// 21-06-96 SetCuts implementation, M.Maire
// 24-06-96 simplification in ComputeCrossSectionPerAtom, M.Maire
// 24-06-96 in DoIt : change the particleType stuff, M.Maire
// 25-06-96 modification in the generation of the teta angle, M.Maire
// 16-09-96 minors optimisations in DoIt. Thanks to P.Urban
// dynamical array PartialSumSigma
// 13-12-96 fast sampling of epsil below 2 MeV, L.Urban
// 14-01-97 crossection table + meanfreepath table.
// PartialSumSigma removed, M.Maire
// 14-01-97 in DoIt the positron is always created, even with Ekine=0,
// for further annihilation, M.Maire
// 14-03-97 new Physics scheme for geant4alpha, M.Maire
// 28-03-97 protection in BuildPhysicsTable, M.Maire
// 19-06-97 correction in ComputeCrossSectionPerAtom, L.Urban
// 04-06-98 in DoIt, secondary production condition:
// range>G4std::min(threshold,safety)
// 13-08-98 new methods SetBining() PrintInfo()
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 11-07-01 PostStepDoIt - sampling epsil: power(rndm,0.333333)
// 13-07-01 DoIt: suppression of production cut for the (e-,e+) (mma)
// 06-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 06-08-01 BuildThePhysicsTable() called from constructor (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 20-09-01 DoIt: fminimalEnergy = 1*eV (mma)
// 01-10-01 come back to BuildPhysicsTable(const G4ParticleDefinition&)
// 11-01-02 ComputeCrossSection: correction of extrapolation below EnergyLimit
// 21-03-02 DoIt: correction of the e+e- angular distribution (bug 363) mma
// -----------------------------------------------------------------------------
#include "G4GammaConversion.hh"
@@ -208,7 +210,8 @@ G4double G4GammaConversion::ComputeCrossSectionPerAtom
if (GammaEnergySave < GammaEnergyLimit)
{
X=GammaEnergySave-2.*electron_mass_c2;
X = (GammaEnergySave - 2.*electron_mass_c2)
/(GammaEnergyLimit- 2.*electron_mass_c2);
CrossSection *= X*X;
}
@@ -325,24 +328,26 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
if (9./(9.+d) >G4UniformRand()) u= - log(G4UniformRand()*G4UniformRand())/a1;
else u= - log(G4UniformRand()*G4UniformRand())/a2;
G4double Teta = u*electron_mass_c2/GammaEnergy;
G4double TetEl = u*electron_mass_c2/ElectTotEnergy;
G4double TetPo = u*electron_mass_c2/PositTotEnergy;
G4double Phi = twopi * G4UniformRand();
G4double dirx=sin(Teta)*cos(Phi), diry=sin(Teta)*sin(Phi), dirz=cos(Teta);
G4double dxEl= sin(TetEl)*cos(Phi),dyEl= sin(TetEl)*sin(Phi),dzEl=cos(TetEl);
G4double dxPo=-sin(TetPo)*cos(Phi),dyPo=-sin(TetPo)*sin(Phi),dzPo=cos(TetPo);
//
// kinematic of the created pair
//
// the electron and positron are assumed to have a symetric
// angular distribution with respect to the Z axis along the parent photon.
aParticleChange.SetNumberOfSecondaries(2) ;
aParticleChange.SetNumberOfSecondaries(2);
G4double ElectKineEnergy = G4std::max(0.,ElectTotEnergy - electron_mass_c2);
G4double localEnergyDeposit = 0.;
if (ElectKineEnergy > fminimalEnergy)
{
G4ThreeVector ElectDirection (dirx, diry, dirz);
G4ThreeVector ElectDirection (dxEl, dyEl, dzEl);
ElectDirection.rotateUz(GammaDirection);
// create G4DynamicParticle object for the particle1
@@ -359,7 +364,7 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
if (PositKineEnergy < fminimalEnergy)
{ localEnergyDeposit += PositKineEnergy; PositKineEnergy = 0.;}
G4ThreeVector PositDirection (-dirx, -diry, dirz);
G4ThreeVector PositDirection (dxPo, dyPo, dzPo);
PositDirection.rotateUz(GammaDirection);
// create G4DynamicParticle object for the particle2
@@ -0,0 +1,322 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4GammaConversionToMuons.cc,v 1.3 2002/05/06 09:32:41 maire Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
// ------------ G4GammaConversionToMuons physics process ------
// by H.Burkhardt, S. Kelner and R. Kokoulin, April 2002
// ---------------------------------------------------------------------------
#include "G4GammaConversionToMuons.hh"
#include "G4EnergyLossTables.hh"
#include "G4UnitsTable.hh"
#include "G4MuonPlus.hh"
#include "G4MuonMinus.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
// constructor
G4GammaConversionToMuons::G4GammaConversionToMuons(const G4String& processName)
: G4VDiscreteProcess (processName),
LowestEnergyLimit (4*G4MuonPlus::MuonPlus()->GetPDGMass()), // 4*Mmuon
HighestEnergyLimit(1e21*eV), // ok to 1e21eV=1e12GeV, then LPM suppression
CrossSecFactor(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
// destructor
G4GammaConversionToMuons::~G4GammaConversionToMuons() // (empty) destructor
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4GammaConversionToMuons::BuildPhysicsTable(const G4ParticleDefinition&)
// Build cross section and mean free path tables
{ //here no tables, just calling PrintInfoDefinition
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4GammaConversionToMuons::SetCrossSecFactor(G4double fac)
// Set the factor to artificially increase the cross section
{ CrossSecFactor=fac;
G4cout << "The cross section for GammaConversionToMuons is artificially "
<< "increased by the CrossSecFactor=" << CrossSecFactor << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4double G4GammaConversionToMuons::ComputeCrossSectionPerAtom(
G4double Egam, G4double Z, G4double A)
// Calculates the microscopic cross section in GEANT4 internal units.
// Total cross section parametrisation from H.Burkhardt
// It gives a good description at any energy (from 0 to 10**21 eV)
{ static const G4double Mmuon=G4MuonPlus::MuonPlus()->GetPDGMass();
static const G4double Mele=electron_mass_c2;
static const G4double GammaEnergyLimit=4* Mmuon;
static const G4double Rc=elm_coupling/Mmuon; // classical particle radius
static const G4double sqrte=sqrt(exp(1.));
static const G4double PowSat=-0.88;
static G4double CrossSection = 0.0 ;
if ( A < 1. ) return 0;
if ( Egam < 4*Mmuon ) return 0 ; // below threshold return 0
static G4double EgamLast=0,Zlast=0,PowThres,Ecor,B,Dn,Zthird,Winfty,WMedAppr,
Wsatur,sigfac;
if(Zlast==Z && Egam==EgamLast) return CrossSection; // already calculated
EgamLast=Egam;
if(Zlast!=Z) // new element
{ Zlast=Z;
if(Z==1) // special case of Hydrogen
{ B=202.4;
Dn=1.49;
}
else
{ B=183.;
Dn=1.54*pow(A,0.27);
}
Zthird=pow(Z,-1./3.); // Z**(-1/3)
Winfty=B*Zthird*Mmuon/(Dn*Mele);
WMedAppr=1./(4.*Dn*sqrte*Mmuon);
Wsatur=Winfty/WMedAppr;
sigfac=4.*fine_structure_const*Z*Z*Rc*Rc;
PowThres=1.479+0.00799*Dn;
Ecor=-18.+4347./(B*Zthird);
}
G4double CorFuc=1.+.04*log(1.+Ecor/Egam);
G4double Eg=pow(1.-4.*Mmuon/Egam,PowThres)*pow( pow(Wsatur,PowSat)+
pow(Egam,PowSat),1./PowSat); // threshold and saturation
CrossSection=7./9.*sigfac*log(1.+WMedAppr*CorFuc*Eg);
CrossSection*=CrossSecFactor; // increase the CrossSection by (by default 1)
return CrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4VParticleChange* G4GammaConversionToMuons::PostStepDoIt(
const G4Track& aTrack,
const G4Step& aStep)
//
// generation of gamma->mu+mu-
//
{
aParticleChange.Initialize(aTrack);
G4Material* aMaterial = aTrack.GetMaterial();
static const G4double Mmuon=G4MuonPlus::MuonPlus()->GetPDGMass();
static const G4double Mele=electron_mass_c2;
static const G4double sqrte=sqrt(exp(1.));
// current Gamma energy and direction, return if energy too low
const G4DynamicParticle *aDynamicGamma = aTrack.GetDynamicParticle();
G4double Egam = aDynamicGamma->GetKineticEnergy();
if (Egam < 4*Mmuon) return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection();
// select randomly one element constituting the material
const G4Element& anElement = *SelectRandomAtom(aDynamicGamma, aMaterial);
G4double Z = anElement.GetZ();
G4double A = anElement.GetA()/(g/mole);
static G4double Zlast=0,B,Dn,Zthird,Winfty,A027,C1Num2,C2Term2;
if(Zlast!=Z) // the element has changed
{ Zlast=Z;
if(Z==1) // special case of Hydrogen
{ B=202.4;
Dn=1.49;
}
else
{ B=183.;
Dn=1.54*pow(A,0.27);
}
Zthird=pow(Z,-1./3.); // Z**(-1/3)
Winfty=B*Zthird*Mmuon/(Dn*Mele);
A027=pow(A,0.27);
G4double C1Num=0.35*A027;
C1Num2=C1Num*C1Num;
C2Term2=Mele/(183.*Zthird*Mmuon);
}
G4double GammaMuonInv=Mmuon/Egam;
G4double sqrtx=sqrt(.25-GammaMuonInv);
G4double xmax=.5+sqrtx;
G4double xmin=.5-sqrtx;
// generate xPlus according to the differential cross section by rejection
G4double Ds2=(Dn*sqrte-2.);
G4double sBZ=sqrte*B*Zthird/Mele;
G4double LogWmaxInv=1./log(Winfty*(1.+2.*Ds2*GammaMuonInv)
/(1.+2.*sBZ*Mmuon*GammaMuonInv));
G4double xPlus,xMinus,xPM,result,W;
do
{ xPlus=xmin+G4UniformRand()*(xmax-xmin);
xMinus=1.-xPlus;
xPM=xPlus*xMinus;
G4double del=Mmuon*Mmuon/(2.*Egam*xPM);
W=Winfty*(1.+Ds2*del/Mmuon)/(1.+sBZ*del);
if(W<1.) W=1.; // to avoid negative cross section at xmin
G4double xxp=1.-4./3.*xPM; // the main xPlus dependence
result=xxp*log(W)*LogWmaxInv;
if(result>1.)
{ G4cout << "error in dSigxPlusGen, result=" << result << " is >1" << '\n';
exit(10);
}
}
while (G4UniformRand() > result);
// now generate the angular variables via the auxilary variables t,psi,rho
G4double t;
G4double psi;
G4double rho;
G4double thetaPlus,thetaMinus,phiHalf; // final angular variables
do // t, psi, rho generation start (while angle < pi)
{
//generate t by the rejection method
G4double C1=C1Num2* GammaMuonInv/xPM;
G4double f1_max=(1.-xPM) / (1.+C1);
G4double f1; // the probability density
do
{ t=G4UniformRand();
f1=(1.-2.*xPM+4.*xPM*t*(1.-t)) / (1.+C1/(t*t));
if(f1<0 | f1> f1_max) // should never happend
{ G4cout << "outside allowed range f1=" << f1 << G4endl;
exit(1);
}
}
while ( G4UniformRand()*f1_max > f1);
// generate psi by the rejection method
G4double f2_max=1.-2.*xPM*(1.-4.*t*(1.-t));
// long version
G4double f2;
do
{ psi=2.*pi*G4UniformRand();
f2=1.-2.*xPM+4.*xPM*t*(1.-t)*(1.+cos(2.*psi));
if(f2<0 | f2> f2_max) // should never happend
{ G4cout << "outside allowed range f2=" << f2 << G4endl;
exit(1);
}
}
while ( G4UniformRand()*f2_max > f2);
// generate rho by direct transformation
G4double C2Term1=GammaMuonInv/(2.*xPM*t);
G4double C2=4./sqrt(xPM)*pow(C2Term1*C2Term1+C2Term2*C2Term2,2);
G4double rhomax=1.9/A027*(1./t-1.);
G4double beta=log( (C2+pow(rhomax,4))/C2 );
rho=pow(C2 *( exp(beta*G4UniformRand())-1. ) ,0.25);
//now get from t and psi the kinematical variables
G4double u=sqrt(1./t-1.);
G4double xiHalf=0.5*rho*cos(psi);
phiHalf=0.5*rho/u*sin(psi);
thetaPlus =GammaMuonInv*(u+xiHalf)/xPlus;
thetaMinus=GammaMuonInv*(u-xiHalf)/xMinus;
} while ( abs(thetaPlus)>pi | abs(thetaMinus) >pi);
// now construct the vectors
// azimuthal symmetry, take phi0 at random between 0 and 2 pi
G4double phi0=2.*pi*G4UniformRand();
G4double EPlus=xPlus*Egam;
G4double EMinus=xMinus*Egam;
// mu+ mu- directions for gamma in z-direction
G4ThreeVector MuPlusDirection ( sin(thetaPlus) *cos(phi0+phiHalf),
sin(thetaPlus) *sin(phi0+phiHalf), cos(thetaPlus) );
G4ThreeVector MuMinusDirection (-sin(thetaMinus)*cos(phi0-phiHalf),
-sin(thetaMinus) *sin(phi0-phiHalf), cos(thetaMinus) );
// rotate to actual gamma direction
MuPlusDirection.rotateUz(GammaDirection);
MuMinusDirection.rotateUz(GammaDirection);
aParticleChange.SetNumberOfSecondaries(2);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1= new G4DynamicParticle(
G4MuonPlus::MuonPlus(),MuPlusDirection,EPlus-Mmuon);
aParticleChange.AddSecondary(aParticle1);
// create G4DynamicParticle object for the particle2
G4DynamicParticle* aParticle2= new G4DynamicParticle(
G4MuonMinus::MuonMinus(),MuMinusDirection,EMinus-Mmuon);
aParticleChange.AddSecondary(aParticle2);
//
// Kill the incident photon
//
aParticleChange.SetMomentumChange( 0., 0., 0. ) ;
aParticleChange.SetEnergyChange( 0. ) ;
aParticleChange.SetStatusChange( fStopAndKill ) ;
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4Element* G4GammaConversionToMuons::SelectRandomAtom(
const G4DynamicParticle* aDynamicGamma,
G4Material* aMaterial)
{
// select randomly 1 element within the material, invoked by PostStepDoIt
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)[0];
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double PartialSumSigma = 0. ;
G4double rval = G4UniformRand()/MeanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ )
{ PartialSumSigma += NbOfAtomsPerVolume[i] *
GetCrossSectionPerAtom(aDynamicGamma, (*theElementVector)[i]);
if (rval <= PartialSumSigma) return ((*theElementVector)[i]);
}
G4cout << " WARNING !!! - The Material '"<< aMaterial->GetName()
<< "' has no elements, NULL pointer returned." << G4endl;
return NULL;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4GammaConversionToMuons::PrintInfoDefinition()
{
G4String comments ="gamma->mu+mu- Bethe Heitler process.\n";
G4cout << G4endl << GetProcessName() << ": " << comments
<< " good cross section parametrization from "
<< G4BestUnit(LowestEnergyLimit,"Energy")
<< " to " << HighestEnergyLimit/GeV << " GeV for all Z." << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PAIonisation.cc,v 1.22 2001/11/09 13:59:46 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4PAIonisation.cc,v 1.23 2002/04/09 17:34:41 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//
// **************************************************************
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PAIxSection.cc,v 1.8 2001/10/17 14:01:11 gcosmo Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4PAIxSection.cc,v 1.10 2002/04/09 17:34:42 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//
// G4PAIxSection.cc -- class implementation file
@@ -298,8 +298,12 @@ G4PAIxSection::G4PAIxSection( G4int materialIndex,
for(i = 1 ; i <= fSplineNumber ; i++)
{
fDifPAIxSection[i] = DifPAIxSection(i,betaGammaSq);
fdNdxCerenkov[i] = PAIdNdxCerenkov(i,betaGammaSq);
fdNdxPlasmon[i] = PAIdNdxPlasmon(i,betaGammaSq);
}
IntegralPAIxSection() ;
IntegralCerenkov() ;
IntegralPlasmon() ;
delete[] fEnergyInterval ;
delete[] fA1 ;
@@ -428,8 +432,12 @@ G4PAIxSection::G4PAIxSection( G4int materialIndex,
for(i = 1 ; i <= fSplineNumber ; i++)
{
fDifPAIxSection[i] = DifPAIxSection(i,betaGammaSq);
fdNdxCerenkov[i] = PAIdNdxCerenkov(i,betaGammaSq);
fdNdxPlasmon[i] = PAIdNdxPlasmon(i,betaGammaSq);
}
IntegralPAIxSection() ;
IntegralCerenkov() ;
IntegralPlasmon() ;
// delete[] fEnergyInterval ;
delete[] fA1 ;
@@ -470,7 +478,10 @@ void G4PAIxSection::InitPAI()
NormShift(betaGammaSq) ;
SplainPAI(betaGammaSq) ;
IntegralPAIxSection() ;
IntegralCerenkov() ;
IntegralPlasmon() ;
for(i = 0 ; i<=fSplineNumber ; i++)
{
@@ -484,17 +495,19 @@ void G4PAIxSection::InitPAI()
for(G4int j = 1 ; j < 112 ; j++) // for other gammas
{
if(j == fRefGammaNumber)
{
continue ;
}
if( j == fRefGammaNumber ) continue ;
betaGammaSq = fLorentzFactor[j]*fLorentzFactor[j] - 1 ;
for(i = 1 ; i <= fSplineNumber ; i++)
{
fDifPAIxSection[i] = DifPAIxSection(i,betaGammaSq);
fdNdxCerenkov[i] = PAIdNdxCerenkov(i,betaGammaSq);
fdNdxPlasmon[i] = PAIdNdxPlasmon(i,betaGammaSq);
}
IntegralPAIxSection() ;
IntegralCerenkov() ;
IntegralPlasmon() ;
for(i = 0 ; i <= fSplineNumber ; i++)
{
@@ -511,46 +524,43 @@ void G4PAIxSection::InitPAI()
void G4PAIxSection::NormShift(G4double betaGammaSq)
{
G4int i,j;
for(i=1;i<=fIntervalNumber-1;i++)
{
for(j=1;j<=2;j++)
{
fSplineNumber = (i-1)*2 + j ;
G4int i, j ;
if(j==1)
{
fSplineEnergy[fSplineNumber]=fEnergyInterval[i]*(1+fDelta);
}
else
{
fSplineEnergy[fSplineNumber]=fEnergyInterval[i+1]*(1-fDelta);
}
}
}
fIntegralTerm[1]=RutherfordIntegral(1,fEnergyInterval[1],fSplineEnergy[1]);
j=1;
for(i=2;i<=fSplineNumber;i++)
{
if(fSplineEnergy[i]<fEnergyInterval[j+1])
{
for( i = 1 ; i <= fIntervalNumber-1 ; i++ )
{
for(j=1;j<=2;j++)
{
fSplineNumber = (i-1)*2 + j ;
if( j == 1 ) fSplineEnergy[fSplineNumber] = fEnergyInterval[i]*(1+fDelta);
else fSplineEnergy[fSplineNumber] = fEnergyInterval[i+1]*(1-fDelta);
}
}
fIntegralTerm[1]=RutherfordIntegral(1,fEnergyInterval[1],fSplineEnergy[1]);
j = 1 ;
for(i=2;i<=fSplineNumber;i++)
{
if(fSplineEnergy[i]<fEnergyInterval[j+1])
{
fIntegralTerm[i] = fIntegralTerm[i-1] +
RutherfordIntegral(j,fSplineEnergy[i-1],
fSplineEnergy[i] ) ;
}
else
{
G4double x = RutherfordIntegral(j,fSplineEnergy[i-1],
}
else
{
G4double x = RutherfordIntegral(j,fSplineEnergy[i-1],
fEnergyInterval[j+1] ) ;
j++;
fIntegralTerm[i] = fIntegralTerm[i-1] + x +
RutherfordIntegral(j,fEnergyInterval[j],
fSplineEnergy[i] ) ;
}
}
// G4cout<<i<<"\t"<<fSplineEnergy[i]<<"\t"<<fIntegralTerm[i]<<"\n"<<G4endl;
}
fNormalizationCof = 2*pi*pi*hbarc*hbarc*fine_structure_const/electron_mass_c2 ;
fNormalizationCof *= fElectronDensity/fIntegralTerm[fSplineNumber] ;
}
fNormalizationCof = 2*pi*pi*hbarc*hbarc*fine_structure_const/electron_mass_c2 ;
fNormalizationCof *= fElectronDensity/fIntegralTerm[fSplineNumber] ;
// G4cout<<"fNormalizationCof = "<<fNormalizationCof<<G4endl ;
@@ -567,7 +577,10 @@ void G4PAIxSection::NormShift(G4double betaGammaSq)
fRePartDielectricConst[i] = fNormalizationCof*
RePartDielectricConst(fSplineEnergy[i]);
fIntegralTerm[i] *= fNormalizationCof;
fDifPAIxSection[i] = DifPAIxSection(i,betaGammaSq);
fdNdxCerenkov[i] = PAIdNdxCerenkov(i,betaGammaSq);
fdNdxPlasmon[i] = PAIdNdxPlasmon(i,betaGammaSq);
}
}
@@ -597,13 +610,16 @@ void
// average of 'i' and 'i+1' energy points to 'i+1' place
fSplineNumber++;
for(G4int j=fSplineNumber;j>=i+2;j--)
for(G4int j = fSplineNumber; j >= i+2 ; j-- )
{
fSplineEnergy[j] = fSplineEnergy[j-1];
fSplineEnergy[j] = fSplineEnergy[j-1];
fImPartDielectricConst[j] = fImPartDielectricConst[j-1];
fRePartDielectricConst[j] = fRePartDielectricConst[j-1];
fIntegralTerm[j] = fIntegralTerm[j-1];
fIntegralTerm[j] = fIntegralTerm[j-1];
fDifPAIxSection[j] = fDifPAIxSection[j-1];
fdNdxCerenkov[j] = fdNdxCerenkov[j-1];
fdNdxPlasmon[j] = fdNdxPlasmon[j-1];
}
G4double x1 = fSplineEnergy[i];
G4double x2 = fSplineEnergy[i+1];
@@ -630,7 +646,10 @@ void
fIntegralTerm[i+1] = fIntegralTerm[i] + fNormalizationCof*
RutherfordIntegral(k,fSplineEnergy[i],
fSplineEnergy[i+1]);
fDifPAIxSection[i+1] = DifPAIxSection(i+1,betaGammaSq);
fdNdxCerenkov[i+1] = PAIdNdxCerenkov(i+1,betaGammaSq);
fdNdxPlasmon[i+1] = PAIdNdxPlasmon(i+1,betaGammaSq);
// Condition for next division of this segment or to pass
// to higher energies
@@ -651,32 +670,6 @@ void
} // end of SplainPAI
////////////////////////////////////////////////////////////////////////
//
// Calculation of the PAI integral cross-section
// fIntegralPAIxSection[1] = specific primary ionisation, 1/cm
// and fIntegralPAIxSection[0] = mean energy loss per cm in keV/cm
void G4PAIxSection::IntegralPAIxSection()
{
fIntegralPAIxSection[fSplineNumber] = 0 ;
fIntegralPAIxSection[0] = 0 ;
G4int k = fIntervalNumber -1 ;
for(G4int i=fSplineNumber-1;i>=1;i--)
{
if(fSplineEnergy[i] >= fEnergyInterval[k])
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] + SumOverInterval(i) ;
}
else
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] +
SumOverBorder(i+1,fEnergyInterval[k]) ;
k-- ;
}
}
} // end of IntegralPAIxSection
////////////////////////////////////////////////////////////////////
//
@@ -722,7 +715,7 @@ G4double G4PAIxSection::ImPartDielectricConst( G4int k ,
//////////////////////////////////////////////////////////////////////////////
//
// Real part of dielectric constant minus unit
// Real part of dielectric constant minus unit: epsilon_1 - 1
// (G4double enb - energy point)
//
@@ -836,6 +829,187 @@ G4double G4PAIxSection::DifPAIxSection( G4int i ,
} // end of DifPAIxSection
//////////////////////////////////////////////////////////////////////////
//
// Calculation od dN/dx of collisions with creation of Cerenkov pseudo-photons
G4double G4PAIxSection::PAIdNdxCerenkov( G4int i ,
G4double betaGammaSq )
{
G4double cof, logarithm, x3, x5, argument, modul2, dNdxC ;
G4double be2, be4, betaBohr2,betaBohr4,cofBetaBohr ;
cof = 1.0 ;
cofBetaBohr = 4.0 ;
betaBohr2 = fine_structure_const*fine_structure_const ;
betaBohr4 = betaBohr2*betaBohr2*cofBetaBohr ;
be2 = betaGammaSq/(1 + betaGammaSq) ;
be4 = be2*be2 ;
if( betaGammaSq < 0.01 ) logarithm = log(1.0+betaGammaSq) ; // 0.0 ;
else
{
logarithm = -log( (1/betaGammaSq - fRePartDielectricConst[i])*
(1/betaGammaSq - fRePartDielectricConst[i]) +
fImPartDielectricConst[i]*fImPartDielectricConst[i] )*0.5 ;
logarithm += log(1+1.0/betaGammaSq) ;
}
if( fImPartDielectricConst[i] == 0.0 || betaGammaSq < 0.01 )
{
argument = 0.0 ;
}
else
{
x3 = -fRePartDielectricConst[i] + 1.0/betaGammaSq ;
x5 = -1.0 - fRePartDielectricConst[i] +
be2*((1.0 +fRePartDielectricConst[i])*(1.0 + fRePartDielectricConst[i]) +
fImPartDielectricConst[i]*fImPartDielectricConst[i]) ;
if( x3 == 0.0 ) argument = 0.5*pi;
else argument = atan2(fImPartDielectricConst[i],x3) ;
argument *= x5 ;
}
dNdxC = ( logarithm*fImPartDielectricConst[i] + argument )/hbarc ;
if(dNdxC < 1.0e-8) dNdxC = 1.0e-8 ;
dNdxC *= fine_structure_const/be2/pi ;
dNdxC *= (1-exp(-be4/betaBohr4)) ;
if(fDensity >= 0.1)
{
modul2 = (1.0 + fRePartDielectricConst[i])*(1.0 + fRePartDielectricConst[i]) +
fImPartDielectricConst[i]*fImPartDielectricConst[i] ;
dNdxC /= modul2 ;
}
return dNdxC ;
} // end of PAIdNdxCerenkov
//////////////////////////////////////////////////////////////////////////
//
// Calculation od dN/dx of collisions with creation of longitudinal EM
// excitations (plasmons, delta-electrons)
G4double G4PAIxSection::PAIdNdxPlasmon( G4int i ,
G4double betaGammaSq )
{
G4double cof, resonance, modul2, dNdxP ;
G4double be2, be4, betaBohr2, betaBohr4, cofBetaBohr ;
cof = 1 ;
cofBetaBohr = 4.0 ;
betaBohr2 = fine_structure_const*fine_structure_const ;
betaBohr4 = betaBohr2*betaBohr2*cofBetaBohr ;
be2 = betaGammaSq/(1 + betaGammaSq) ;
be4 = be2*be2 ;
resonance = log(2*electron_mass_c2*be2/fSplineEnergy[i]) ;
resonance *= fImPartDielectricConst[i]/hbarc ;
dNdxP = ( resonance + cof*fIntegralTerm[i]/fSplineEnergy[i]/fSplineEnergy[i] ) ;
if( dNdxP < 1.0e-8 ) dNdxP = 1.0e-8 ;
dNdxP *= fine_structure_const/be2/pi ;
dNdxP *= (1-exp(-be4/betaBohr4)) ;
if( fDensity >= 0.1 )
{
modul2 = (1 + fRePartDielectricConst[i])*(1 + fRePartDielectricConst[i]) +
fImPartDielectricConst[i]*fImPartDielectricConst[i] ;
dNdxP /= modul2 ;
}
return dNdxP ;
} // end of PAIdNdxPlasmon
////////////////////////////////////////////////////////////////////////
//
// Calculation of the PAI integral cross-section
// fIntegralPAIxSection[1] = specific primary ionisation, 1/cm
// and fIntegralPAIxSection[0] = mean energy loss per cm in keV/cm
void G4PAIxSection::IntegralPAIxSection()
{
fIntegralPAIxSection[fSplineNumber] = 0 ;
fIntegralPAIxSection[0] = 0 ;
G4int k = fIntervalNumber -1 ;
for(G4int i=fSplineNumber-1;i>=1;i--)
{
if(fSplineEnergy[i] >= fEnergyInterval[k])
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] + SumOverInterval(i) ;
}
else
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] +
SumOverBorder(i+1,fEnergyInterval[k]) ;
k-- ;
}
}
} // end of IntegralPAIxSection
////////////////////////////////////////////////////////////////////////
//
// Calculation of the PAI Cerenkov integral cross-section
// fIntegralCrenkov[1] = specific Crenkov ionisation, 1/cm
// and fIntegralCerenkov[0] = mean Cerenkov loss per cm in keV/cm
void G4PAIxSection::IntegralCerenkov()
{
fIntegralCerenkov[fSplineNumber] = 0 ;
fIntegralCerenkov[0] = 0 ;
G4int k = fIntervalNumber -1 ;
for(G4int i=fSplineNumber-1;i>=1;i--)
{
if(fSplineEnergy[i] >= fEnergyInterval[k])
{
fIntegralCerenkov[i] = fIntegralCerenkov[i+1] + SumOverInterCerenkov(i) ;
}
else
{
fIntegralCerenkov[i] = fIntegralCerenkov[i+1] +
SumOverBordCerenkov(i+1,fEnergyInterval[k]) ;
k-- ;
}
}
} // end of IntegralCerenkov
////////////////////////////////////////////////////////////////////////
//
// Calculation of the PAI Plasmon integral cross-section
// fIntegralPlasmon[1] = splasmon primary ionisation, 1/cm
// and fIntegralPlasmon[0] = mean plasmon loss per cm in keV/cm
void G4PAIxSection::IntegralPlasmon()
{
fIntegralPlasmon[fSplineNumber] = 0 ;
fIntegralPlasmon[0] = 0 ;
G4int k = fIntervalNumber -1 ;
for(G4int i=fSplineNumber-1;i>=1;i--)
{
if(fSplineEnergy[i] >= fEnergyInterval[k])
{
fIntegralPlasmon[i] = fIntegralPlasmon[i+1] + SumOverInterPlasmon(i) ;
}
else
{
fIntegralPlasmon[i] = fIntegralPlasmon[i+1] +
SumOverBordPlasmon(i+1,fEnergyInterval[k]) ;
k-- ;
}
}
} // end of IntegralPlasmon
//////////////////////////////////////////////////////////////////////
//
// Calculation the PAI integral cross-section inside
@@ -876,6 +1050,68 @@ G4double G4PAIxSection::SumOverInterval( G4int i )
} // end of SumOverInterval
//////////////////////////////////////////////////////////////////////
//
// Calculation the PAI Cerenkov integral cross-section inside
// of interval of continuous values of photo-ionisation Cerenkov
// cross-section. Parameter 'i' is the number of interval.
G4double G4PAIxSection::SumOverInterCerenkov( G4int i )
{
G4double x0,x1,y0,yy1,a,b,result ;
x0 = fSplineEnergy[i] ;
x1 = fSplineEnergy[i+1] ;
y0 = fdNdxCerenkov[i] ;
yy1 = fdNdxCerenkov[i+1];
a = log10(yy1/y0)/log10(x1/x0) ;
b = log10(y0) - a*log10(x0) ;
b = pow(10.0,b) ;
a += 1.0 ;
if(a == 0) result = b*log(x1/x0) ;
else result = b*(pow(x1,a) - pow(x0,a))/a ;
a += 1.0 ;
if( a == 0 ) fIntegralCerenkov[0] += b*log(x1/x0) ;
else fIntegralCerenkov[0] += b*(pow(x1,a) - pow(x0,a))/a ;
return result ;
} // end of SumOverInterCerenkov
//////////////////////////////////////////////////////////////////////
//
// Calculation the PAI Plasmon integral cross-section inside
// of interval of continuous values of photo-ionisation Plasmon
// cross-section. Parameter 'i' is the number of interval.
G4double G4PAIxSection::SumOverInterPlasmon( G4int i )
{
G4double x0,x1,y0,yy1,a,b,result ;
x0 = fSplineEnergy[i] ;
x1 = fSplineEnergy[i+1] ;
y0 = fdNdxPlasmon[i] ;
yy1 = fdNdxPlasmon[i+1];
a = log10(yy1/y0)/log10(x1/x0) ;
b = log10(y0) - a*log10(x0) ;
b = pow(10.0,b) ;
a += 1.0 ;
if(a == 0) result = b*log(x1/x0) ;
else result = b*(pow(x1,a) - pow(x0,a))/a ;
a += 1.0 ;
if( a == 0 ) fIntegralPlasmon[0] += b*log(x1/x0) ;
else fIntegralPlasmon[0] += b*(pow(x1,a) - pow(x0,a))/a ;
return result ;
} // end of SumOverInterPlasmon
///////////////////////////////////////////////////////////////////////////////
//
// Integration of PAI cross-section for the case of
@@ -944,6 +1180,104 @@ G4double G4PAIxSection::SumOverBorder( G4int i ,
}
///////////////////////////////////////////////////////////////////////////////
//
// Integration of Cerenkov cross-section for the case of
// passing across border between intervals
G4double G4PAIxSection::SumOverBordCerenkov( G4int i ,
G4double en0 )
{
G4double x0,x1,y0,yy1,a,b,e0,result ;
e0 = en0 ;
x0 = fSplineEnergy[i] ;
x1 = fSplineEnergy[i+1] ;
y0 = fdNdxCerenkov[i] ;
yy1 = fdNdxCerenkov[i+1] ;
a = log10(yy1/y0)/log10(x1/x0) ;
b = log10(y0) - a*log10(x0) ;
b = pow(10,b) ;
a += 1.0 ;
if( a == 0 ) result = b*log(x0/e0) ;
else result = b*(pow(x0,a) - pow(e0,a))/a ;
a += 1.0 ;
if( a == 0 ) fIntegralCerenkov[0] += b*log(x0/e0) ;
else fIntegralCerenkov[0] += b*(pow(x0,a) - pow(e0,a))/a ;
x0 = fSplineEnergy[i - 1] ;
x1 = fSplineEnergy[i - 2] ;
y0 = fdNdxCerenkov[i - 1] ;
yy1 = fdNdxCerenkov[i - 2] ;
a = log10(yy1/y0)/log10(x1/x0) ;
b = log10(y0) - a*log10(x0) ;
b = pow(10,b) ;
a += 1.0 ;
if( a == 0 ) result += b*log(e0/x0) ;
else result += b*(pow(e0,a) - pow(x0,a))/a ;
a += 1.0 ;
if( a == 0 ) fIntegralCerenkov[0] += b*log(e0/x0) ;
else fIntegralCerenkov[0] += b*(pow(e0,a) - pow(x0,a))/a ;
return result ;
}
///////////////////////////////////////////////////////////////////////////////
//
// Integration of Plasmon cross-section for the case of
// passing across border between intervals
G4double G4PAIxSection::SumOverBordPlasmon( G4int i ,
G4double en0 )
{
G4double x0,x1,y0,yy1,a,b,e0,result ;
e0 = en0 ;
x0 = fSplineEnergy[i] ;
x1 = fSplineEnergy[i+1] ;
y0 = fdNdxPlasmon[i] ;
yy1 = fdNdxPlasmon[i+1] ;
a = log10(yy1/y0)/log10(x1/x0) ;
b = log10(y0) - a*log10(x0) ;
b = pow(10,b) ;
a += 1.0 ;
if( a == 0 ) result = b*log(x0/e0) ;
else result = b*(pow(x0,a) - pow(e0,a))/a ;
a += 1.0 ;
if( a == 0 ) fIntegralPlasmon[0] += b*log(x0/e0) ;
else fIntegralPlasmon[0] += b*(pow(x0,a) - pow(e0,a))/a ;
x0 = fSplineEnergy[i - 1] ;
x1 = fSplineEnergy[i - 2] ;
y0 = fdNdxPlasmon[i - 1] ;
yy1 = fdNdxPlasmon[i - 2] ;
a = log10(yy1/y0)/log10(x1/x0) ;
b = log10(y0) - a*log10(x0) ;
b = pow(10,b) ;
a += 1.0 ;
if( a == 0 ) result += b*log(e0/x0) ;
else result += b*(pow(e0,a) - pow(x0,a))/a ;
a += 1.0 ;
if( a == 0 ) fIntegralPlasmon[0] += b*log(e0/x0) ;
else fIntegralPlasmon[0] += b*(pow(e0,a) - pow(x0,a))/a ;
return result ;
}
/////////////////////////////////////////////////////////////////////////
//
//
@@ -980,6 +1314,78 @@ G4double G4PAIxSection::GetStepEnergyLoss( G4double step )
return loss ;
}
/////////////////////////////////////////////////////////////////////////
//
//
G4double G4PAIxSection::GetStepCerenkovLoss( G4double step )
{
G4int iTransfer ;
G4long numOfCollisions ;
G4double loss = 0.0 ;
G4double meanNumber, position ;
// G4cout<<" G4PAIxSection::GetStepCreLosnkovs "<<G4endl ;
meanNumber = fIntegralCerenkov[1]*step ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
position = fIntegralCerenkov[1]*G4UniformRand() ;
for( iTransfer=1 ; iTransfer<=fSplineNumber ; iTransfer++ )
{
if( position >= fIntegralCerenkov[iTransfer] ) break ;
}
loss += fSplineEnergy[iTransfer] ;
numOfCollisions-- ;
}
// G4cout<<"PAI Cerenkov loss = "<<loss/keV<<" keV"<<G4endl ;
return loss ;
}
/////////////////////////////////////////////////////////////////////////
//
//
G4double G4PAIxSection::GetStepPlasmonLoss( G4double step )
{
G4int iTransfer ;
G4long numOfCollisions ;
G4double loss = 0.0 ;
G4double meanNumber, position ;
// G4cout<<" G4PAIxSection::GetStepCreLosnkovs "<<G4endl ;
meanNumber = fIntegralPlasmon[1]*step ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
position = fIntegralPlasmon[1]*G4UniformRand() ;
for( iTransfer=1 ; iTransfer<=fSplineNumber ; iTransfer++ )
{
if( position >= fIntegralPlasmon[iTransfer] ) break ;
}
loss += fSplineEnergy[iTransfer] ;
numOfCollisions-- ;
}
// G4cout<<"PAI Plasmon loss = "<<loss/keV<<" keV"<<G4endl ;
return loss ;
}
/////////////////////////////////////////////////////////////////////////////
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PhotoElectricEffect.cc,v 1.22 2001/10/01 15:00:29 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4PhotoElectricEffect.cc,v 1.27 2002/05/02 11:37:22 maire Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -48,9 +48,14 @@
// 06-08-01, new methods Store/Retrieve PhysicsTable (mma)
// 06-08-01, BuildThePhysicsTable() called from constructor (mma)
// 17-09-01, migration of Materials to pure STL (mma)
// 20-09-01, DoIt: fminimalEnergy = 1*eV (mma)
// 20-09-01, DoIt: fminimalEnergy of generated electron = 1*eV (mma)
// 01-10-01, come back to BuildPhysicsTable(const G4ParticleDefinition&)
//
// 10-01-02, moved few function from icc to cc
// 17-04-02, Keep only Sandia crossSections. Remove BuildPhysicsTables.
// Simplify public interface (mma)
// 29-04-02, Generate theta angle of the photoelectron from Sauter-Gavrila
// distribution (mma)
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -62,180 +67,56 @@
// constructor
G4PhotoElectricEffect::G4PhotoElectricEffect(const G4String& processName)
: G4VDiscreteProcess (processName), // initialization
theCrossSectionTable(NULL),
theMeanFreePathTable(NULL),
LowestEnergyLimit (50*keV),
HighestEnergyLimit(50*MeV),
NumbBinTable(100),
: G4VDiscreteProcess (processName),
fminimalEnergy(1*eV)
{}
{ PrintInfoDefinition();}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// destructor
G4PhotoElectricEffect::~G4PhotoElectricEffect()
{
if (theCrossSectionTable) {
theCrossSectionTable->clearAndDestroy();
delete theCrossSectionTable;
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
}
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4PhotoElectricEffect::SetPhysicsTableBining(
G4double lowE, G4double highE, G4int nBins)
{
LowestEnergyLimit = lowE; HighestEnergyLimit = highE; NumbBinTable = nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4PhotoElectricEffect::BuildPhysicsTable(const G4ParticleDefinition&)
// Build cross section per atom and mean free path tables
{
G4double LowEdgeEnergy, Value;
G4PhysicsLogVector* ptrVector;
// Build cross section per atom tables for the Photo Electric Effect
if (theCrossSectionTable) {
theCrossSectionTable->clearAndDestroy(); delete theCrossSectionTable;}
theCrossSectionTable = new G4PhysicsTable( G4Element::GetNumberOfElements());
const G4ElementTable* theElementTable = G4Element::GetElementTable();
G4double AtomicNumber;
size_t J;
for ( J=0 ; J < G4Element::GetNumberOfElements(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit,HighestEnergyLimit,
NumbBinTable ) ;
AtomicNumber = (*theElementTable)[J]->GetZ();
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeCrossSectionPerAtom( LowEdgeEnergy, AtomicNumber);
ptrVector->PutValue( i , Value ) ;
}
theCrossSectionTable->insertAt( J , ptrVector ) ;
}
// Build mean free path table for the Photo Electric Effect
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable= new G4PhysicsTable(G4Material::GetNumberOfMaterials());
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4Material* material;
for ( J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit,HighestEnergyLimit,
NumbBinTable );
material = (*theMaterialTable)[J];
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeMeanFreePath( LowEdgeEnergy, material);
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector ) ;
}
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4PhotoElectricEffect::ComputeCrossSectionPerAtom(
G4double PhotonEnergy,
G4double AtomicNumber)
// Calculates the cross section per atom in GEANT4 internal units.
// A parametrized formula from L. Urban is used to estimate the
// total cross section.
// It gives a good description of the elements : 5 < Atomic Number < 100 and
// from 10 keV to 50 MeV.
{
G4double CrossSection = 0.0 ;
if ( AtomicNumber < 1. ) return CrossSection;
if ( PhotonEnergy > 50.*MeV ) return CrossSection;
static const G4double
p1K =-8.8893e+2*nanobarn, p2K = 2.4394 *nanobarn, p3K = 2.8835e+2*nanobarn,
p4K = 1.2133e+1*nanobarn, p5K =-3.1104e+2*nanobarn, p6K =-1.7284e-1*nanobarn,
p7K = 1.4400e+1*nanobarn, p8K = 6.8357e+1*nanobarn, p9K = 7.3945e-4*nanobarn,
p10K=-4.8149e-2*nanobarn, p11K= 5.5823e-1*nanobarn, p12K=-1.0089e-1*nanobarn;
static const G4double
p1L1=-1.0927e+3*nanobarn, p2L1=-9.7897e-1*nanobarn, p3L1= 1.2854e+2*nanobarn;
static const G4double
p1L2=-4.5803e+3*nanobarn, p2L2= 1.6858e-3*nanobarn, p3L2= 1.2013e+2*nanobarn;
static const G4double
p1M = 1.6924e+1*nanobarn;
const G4double pwZ = 3.845 , pwE = 2.975 ;
G4double Z = AtomicNumber, Z2 = Z*Z, Z3 = Z*Z*Z;
G4double Em = PhotonEnergy/electron_mass_c2, Em2 = Em*Em, Em3 = Em*Em*Em;
CrossSection = pow(Z,pwZ)/pow(Em,pwE);
if (PhotonEnergy > ComputeKBindingEnergy(Z) ) {
CrossSection *= (p1K/Z + p2K/Em + p3K + p4K*Z + p5K*Em
+ p6K*Z2 + p7K *Z *Em + p8K *Em2
+ p9K*Z3 + p10K*Z2*Em + p11K*Z*Em2 + p12K*Em3);
if (CrossSection < 0.) CrossSection = 0. ;
}
else if (PhotonEnergy > ComputeL1BindingEnergy(Z) ) {
CrossSection *= (p1L1/Z + p2L1/Em + p3L1 );
if (CrossSection < 0.) CrossSection = 0. ;
}
else if (PhotonEnergy > ComputeL2BindingEnergy(Z) ) {
CrossSection *= (p1L2/Z + p2L2/Em + p3L2 );
if (CrossSection < 0.) CrossSection = 0. ;
}
else CrossSection *= p1M;
return CrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4PhotoElectricEffect::ComputeSandiaCrossSection(G4double PhotonEnergy,
G4double G4PhotoElectricEffect::ComputeCrossSectionPerAtom(G4double GammaEnergy,
G4double AtomicNumber)
{
G4double energy2 = PhotonEnergy*PhotonEnergy, energy3 = PhotonEnergy*energy2,
energy4 = energy2*energy2;
G4double* SandiaCof
= G4SandiaTable::GetSandiaCofPerAtom((int)AtomicNumber,PhotonEnergy);
// returns the photoElectric cross Section in GEANT4 internal units
{
G4double* SandiaCof
= G4SandiaTable::GetSandiaCofPerAtom((int)AtomicNumber,GammaEnergy);
G4double energy2 = GammaEnergy*GammaEnergy, energy3 = GammaEnergy*energy2,
energy4 = energy2*energy2;
return SandiaCof[0]/PhotonEnergy + SandiaCof[1]/energy2 +
SandiaCof[2]/energy3 + SandiaCof[3]/energy4;
return SandiaCof[0]/GammaEnergy + SandiaCof[1]/energy2 +
SandiaCof[2]/energy3 + SandiaCof[3]/energy4;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4PhotoElectricEffect::ComputeMeanFreePath(G4double GammaEnergy,
G4Material* aMaterial)
// returns the gamma mean free path in GEANT4 internal units
{
G4double* SandiaCof = aMaterial->GetSandiaTable()
->GetSandiaCofForMaterial(GammaEnergy);
G4double energy2 = GammaEnergy*GammaEnergy, energy3 = GammaEnergy*energy2,
energy4 = energy2*energy2;
G4double SIGMA = SandiaCof[0]/GammaEnergy + SandiaCof[1]/energy2 +
SandiaCof[2]/energy3 + SandiaCof[3]/energy4;
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4PhotoElectricEffect::PostStepDoIt(const G4Track& aTrack,
@@ -271,11 +152,19 @@ G4VParticleChange* G4PhotoElectricEffect::PostStepDoIt(const G4Track& aTrack,
if (ElecKineEnergy > fminimalEnergy)
{
// the electron is created in the direction of the incident photon ...
// direction of the photo electron
//
G4double cosTeta = ElecThetaDistribution(ElecKineEnergy);
G4double sinTeta = sqrt(1.-cosTeta*cosTeta);
G4double Phi = twopi * G4UniformRand();
G4double dirx = sinTeta*cos(Phi),diry = sinTeta*sin(Phi),dirz = cosTeta;
G4ThreeVector ElecDirection(dirx,diry,dirz);
ElecDirection.rotateUz(PhotonDirection);
//
G4DynamicParticle* aElectron = new G4DynamicParticle (
G4Electron::Electron(),PhotonDirection, ElecKineEnergy);
G4Electron::Electron(),ElecDirection, ElecKineEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( aElectron );
aParticleChange.AddSecondary(aElectron);
}
else
{
@@ -306,6 +195,7 @@ G4Element* G4PhotoElectricEffect::SelectRandomAtom(
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)[0];
G4double GammaEnergy = aDynamicPhoton->GetKineticEnergy();
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double PartialSumSigma = 0. ;
@@ -313,8 +203,8 @@ G4Element* G4PhotoElectricEffect::SelectRandomAtom(
for ( G4int elm=0 ; elm < NumberOfElements ; elm++ )
{PartialSumSigma += NbOfAtomsPerVolume[elm] *
GetCrossSectionPerAtom(aDynamicPhoton,
(*theElementVector)[elm]);
ComputeCrossSectionPerAtom(GammaEnergy,
(*theElementVector)[elm]->GetZ());
if (rval<=PartialSumSigma*MeanFreePath) return ((*theElementVector)[elm]);
}
return ((*theElementVector)[NumberOfElements-1]);
@@ -322,90 +212,37 @@ G4Element* G4PhotoElectricEffect::SelectRandomAtom(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4PhotoElectricEffect::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
G4double G4PhotoElectricEffect::ElecThetaDistribution(G4double kineEnergy)
{
G4String filename;
// store cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
if ( !theCrossSectionTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if ( !theMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
// Compute Theta distribution of the emitted electron, with respect to the
// incident Gamma.
// The Sauter-Gavrila distribution for the K-shell is used.
//
G4double gamma = 1. + kineEnergy/electron_mass_c2;
G4double beta = sqrt(gamma*gamma-1.)/gamma;
G4double b = 0.5*gamma*(gamma-1.)*(gamma-2);
G4double rndm,costeta,term,greject,grejsup;
if (gamma < 2.) grejsup = gamma*gamma*(1.+b-beta*b);
else grejsup = gamma*gamma*(1.+b+beta*b);
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
do { rndm = 1.-2*G4UniformRand();
costeta = (rndm+beta)/(rndm*beta+1.);
term = 1.-beta*costeta;
greject = (1.-costeta*costeta)*(1.+b*term)/(term*term);
} while(greject < G4UniformRand()*grejsup);
return costeta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4PhotoElectricEffect::RetrievePhysicsTable(
G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theCrossSectionTable and theMeanFreePathTable
if (theCrossSectionTable != 0) {
theCrossSectionTable->clearAndDestroy();
delete theCrossSectionTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
G4String filename;
// retreive cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
theCrossSectionTable = new G4PhysicsTable(G4Element::GetNumberOfElements());
if ( !theCrossSectionTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4PhotoElectricEffect::PrintInfoDefinition()
{
G4String comments = "Total cross sections from a parametrisation. ";
comments += "Good description from 10 KeV to 50 MeV for all Z";
comments += "\n Sandia crossSection below 50 KeV";
G4String comments = "Total cross sections from Sandia parametrisation. ";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowestEnergyLimit, "Energy")
<< " to " << G4BestUnit(HighestEnergyLimit,"Energy")
<< " in " << NumbBinTable << " bins. \n";
G4cout << G4endl << GetProcessName() << ": " << comments << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PolarizedComptonScattering.cc,v 1.8 2001/09/21 09:50:54 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4PolarizedComptonScattering.cc,v 1.9 2002/04/09 17:34:43 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//
//---------- G4PolarizedComptonScattering physics process ----------------------
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4SynchrotronRadiation.cc,v 1.6 2001/10/24 16:27:45 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4SynchrotronRadiation.cc,v 1.7 2002/04/09 17:34:43 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VPAIenergyLoss.cc,v 1.5 2001/10/29 16:23:41 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4VPAIenergyLoss.cc,v 1.6 2002/04/09 17:34:43 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VeEnergyLoss.cc,v 1.22 2001/11/12 11:20:51 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4VeEnergyLoss.cc,v 1.25 2002/04/09 17:34:43 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
// -----------------------------------------------------------------------------
@@ -40,6 +40,8 @@
// 17-09-01, migration of Materials to pure STL (mma)
// 29-10-01 all static functions no more inlined (mma)
// 08-11-01 Charge,lastCharge not data members, L.Urban
// 06-02-02 bug fixed in MinDeltaCutInRange computation, L.Urban
// 26-02-02 bug fixed in TouchebleHandle definition, V.Ivanchenko
// -----------------------------------------------------------------------------
@@ -380,7 +382,7 @@ void G4VeEnergyLoss::BuildDEDXTable(
// set default MinDeltaCutInRange to rcut/10.
if(!setMinDeltaCutInRange )
MinDeltaCutInRange = (G4Electron::Electron()
->GetEnergyCuts())[mat]/10.;
->GetLengthCuts())[mat]/10.;
LowerLimitForced[mat] = false ;
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
@@ -395,7 +397,7 @@ void G4VeEnergyLoss::BuildDEDXTable(
// if((subSecFlag) && (&aParticleType==G4Electron::Electron()))
// {
// G4cout << G4std::setw(20) << (*theMaterialTable)(mat)->GetName()
// G4cout << G4std::setw(20) << (*theMaterialTable)[mat]->GetName()
// << G4std::setw(15) << MinDeltaEnergy[mat]/keV ;
// if(LowerLimitForced[mat])
// G4cout << " lower limit forced." << G4endl;
@@ -646,7 +648,7 @@ G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
G4Track* deltaTrack =
new G4Track(theDelta,DeltaTime,DeltaPosition);
deltaTrack->SetTouchableHandle(stepData.GetPostStepPoint()
deltaTrack->SetTouchableHandle(stepData.GetPreStepPoint()
->GetTouchableHandle());
deltaTrack->SetParentID(trackData.GetTrackID()) ;
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VhEnergyLoss.cc,v 1.29 2001/11/12 11:20:51 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4VhEnergyLoss.cc,v 1.35 2002/06/10 15:38:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
// -----------------------------------------------------------------------------
@@ -48,6 +48,10 @@
// 29-10-01 all static functions no more inlined (mma)
// 08-11-01 BuildDEDXTable not static,Charge local variable, L.Urban
// 09-11-01 cosmetics; 80 columns everywhere (mma)
// 06-02-02 bug fixed in MinDeltaCutInRange computation, L.Urban
// 26-02-02 bug fixed in TouchebleHandle definition, V.Ivanchenko
// 29-05-02 bug fixed in N of subcutoff delta, V.Ivanchenko
// 10-06-02 bug fixed for stopping hadrons, V.Ivanchenko
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -57,6 +61,7 @@
#include "G4Poisson.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4ProcessManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -288,7 +293,6 @@ void G4VhEnergyLoss::BuildDEDXTable(
// reset counter to zero
if(Charge >0.) CounterOfpProcess=0;
else CounterOfpbarProcess=0;
ParticleMass = aParticleType.GetPDGMass();
if(Charge > 0.)
{
@@ -391,7 +395,7 @@ void G4VhEnergyLoss::BuildDEDXTable(
{
// create array for the min. delta cuts in kinetic energy
if(!setMinDeltaCutInRange)
MinDeltaCutInRange = (G4Electron::Electron()->GetEnergyCuts())[mat]/10.;
MinDeltaCutInRange = (G4Electron::Electron()->GetLengthCuts())[mat]/10.;
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),MinDeltaCutInRange,
(*theMaterialTable)[mat]);
@@ -412,9 +416,9 @@ G4double G4VhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
// it calculates dEdx and the range as well....
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double massratio=proton_mass_c2/(aParticle->GetDefinition()->GetPDGMass());
G4double massratio=proton_mass_c2/(aParticle->GetMass());
G4double Tscaled = KineticEnergy*massratio;
G4double Charge = aParticle->GetDefinition()->GetPDGCharge()/eplus;
G4double Charge = aParticle->GetCharge()/eplus;
G4double ChargeSquare = Charge*Charge;
if (Charge>0.)
@@ -461,8 +465,9 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
G4int index = aMaterial->GetIndex();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double Charge = aParticle->GetDefinition()->GetPDGCharge()/eplus;
G4double Charge = aParticle->GetCharge()/eplus;
G4double ChargeSquare = Charge*Charge;
G4double mass=aParticle->GetMass();
// get the actual (true) Step length from stepData
G4double Step = stepData.GetStepLength();
@@ -479,8 +484,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
{
if (Step>linLossLimit*fRangeNow)
{
G4double massratio = proton_mass_c2/
aParticle->GetDefinition()->GetPDGMass();
G4double massratio = proton_mass_c2/mass;
G4double rscaled = fRangeNow*massratio*ChargeSquare;
G4double sscaled = Step *massratio*ChargeSquare;
@@ -520,7 +524,6 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
G4double MinDeltaEnergyNow = MinDeltaEnergy[index] ;
G4double Tc=(G4Electron::Electron()->GetEnergyCuts())[index];
G4double mass=aParticle->GetDefinition()->GetPDGMass();
G4double w=mass+electron_mass_c2 ;
G4double ww=2.*mass-MinDeltaEnergyNow ;
G4double TmintoProduceDelta=0.5*(sqrt(ww*ww+2.*w*w*MinDeltaEnergyNow/
@@ -597,7 +600,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
G4double deldedx=cN*aMaterial->GetDensity()*
((E+mass)*(E+mass)*log(Tc/T0)/(E*(E+mass)));
G4double delToverTc=1.-T0/Tc ;
G4double N = G4int(deldedx*fragment*delToverTc/(T0*log(Tc/T0))+0.5);
G4int N = G4int(deldedx*fragment*delToverTc/(T0*log(Tc/T0))+0.5);
if(N > Ndeltamax) N = Ndeltamax;
G4ThreeVector ParticleDirection = aParticle->GetMomentumDirection();
@@ -675,7 +678,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
G4Track* deltaTrack =
new G4Track(theDelta,DeltaTime,DeltaPosition);
deltaTrack->SetTouchableHandle(stepData.GetPostStepPoint()
deltaTrack->SetTouchableHandle(stepData.GetPreStepPoint()
->GetTouchableHandle());
deltaTrack->SetParentID(trackData.GetTrackID());
@@ -711,7 +714,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
if (finalT <= 0.)
{
finalT = 0.;
if(aParticle->GetDefinition()->GetParticleName() == "proton")
if(!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eBremsstrahlung.cc,v 1.24 2001/11/09 13:59:46 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4eBremsstrahlung.cc,v 1.25 2002/04/09 17:34:44 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//
// ------------ G4eBremsstrahlung physics process --------
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eIonisation.cc,v 1.22 2001/11/09 13:59:47 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4eIonisation.cc,v 1.25 2002/04/09 17:34:44 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//--------------- G4eIonisation physics process --------------------------------
// by Laszlo Urban, 20 March 1997
@@ -40,6 +40,7 @@
// 21-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined (mma)
// 07-11-01 particleMass and Charge become local variables
// 26-03-02 change access to cuts in BuildLossTables (V.Ivanchenko)
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -59,7 +60,7 @@ G4int G4eIonisation::NbinLambda = 100;
G4eIonisation::G4eIonisation(const G4String& processName)
: G4VeEnergyLoss(processName),
theMeanFreePathTable(NULL)
{ }
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -143,9 +144,22 @@ void G4eIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
if (theLossTable) {theLossTable->clearAndDestroy(); delete theLossTable;}
theLossTable = new G4PhysicsTable(numOfMaterials);
// get electron cuts in kinetic energy
// The electron cuts needed in the case of the positron , too!
// This is the reason why SetCut has to be called for electron first !!
if((G4Electron::Electron()->GetEnergyCuts() == 0) &&
(&aParticleType == G4Positron::Positron()))
{
G4cout << " The ELECTRON energy cuts needed to compute energy loss"
" and mean free path; and for POSITRON, too. " << G4endl;
G4Exception(" Call SetCut for e- first !!");
}
// get DeltaCut in energy
G4double* DeltaCutInKineticEnergy = aParticleType.GetEnergyCuts();
G4double* DeltaCutInKineticEnergy = G4Electron::Electron()->GetEnergyCuts();
// loop for materials
//
@@ -166,6 +180,12 @@ void G4eIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
aVector->GetLowEdgeEnergy(i),
material,
DeltaThreshold);
if(1 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << aVector->GetLowEdgeEnergy(i)/MeV
<< " dEdx(MeV/mm)= " << dEdx*mm/MeV
<< G4endl;
}
aVector->PutValue(i,dEdx);
}
theLossTable->insert(aVector);
@@ -201,7 +221,7 @@ void G4eIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
G4Exception(" Call SetCut for e- first !!");
}
G4double* DeltaCutInKineticEnergy = G4Electron::Electron()->GetEnergyCuts() ;
G4double* DeltaCutInKineticEnergy = G4Electron::Electron()->GetEnergyCuts();
// loop for materials
@@ -223,7 +243,7 @@ void G4eIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
// it will be used in ComputeCrossSectionPerAtom
// (--> it will be the same for all the elements in this material )
G4double DeltaThreshold = DeltaCutInKineticEnergy[J];
for (G4int i = 0 ; i < NbinLambda ; i++)
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eplusAnnihilation.cc,v 1.13 2001/10/01 15:00:29 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4eplusAnnihilation.cc,v 1.14 2002/04/09 17:34:44 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4hIonisation.cc,v 1.23 2001/11/09 13:59:47 maire Exp $
// GEANT4 tag $Name: geant4-04-00 $
// $Id: G4hIonisation.cc,v 1.30 2002/06/10 15:50:46 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
//---------------- G4hIonisation physics process -------------------------------
// by Laszlo Urban, 30 May 1997
@@ -46,6 +46,9 @@
// 25-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined
// 08-11-01 Charge renamed zparticle; added to the dedx
// 27-03-02 Bug fix in scaling of lambda table (V.Ivanchenko)
// 09-04-02 Update calculation of tables for GenericIons (V.Ivanchenko)
// 10-06-02 bug fixed for stopping hadrons, V.Ivanchenko
//
//------------------------------------------------------------------------------
@@ -53,7 +56,9 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4hIonisation.hh"
#include "G4ProcessManager.hh"
#include "G4UnitsTable.hh"
#include "G4EnergyLossTables.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -112,10 +117,51 @@ G4int G4hIonisation::GetNbinLambda()
void G4hIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
if(verboseLevel > 0) {
G4cout << "G4hIonisation::BuildPhysicsTable for "
<< aParticleType.GetParticleName()
<< " mass(MeV)= " << aParticleType.GetPDGMass()/MeV
<< " charge= " << aParticleType.GetPDGCharge()/eplus
<< " type= " << aParticleType.GetParticleType()
<< G4endl;
if(verboseLevel > 1) {
G4ProcessVector* pv = aParticleType.GetProcessManager()->GetProcessList();
G4cout << " 0: " << (*pv)[0]->GetProcessName() << " " << (*pv)[0]
<< " 1: " << (*pv)[1]->GetProcessName() << " " << (*pv)[1]
// << " 2: " << (*pv)[2]->GetProcessName() << " " << (*pv)[2]
<< G4endl;
G4cout << " MFPtable= " << theMeanFreePathTable
<< " DEDXtable= " << theDEDXpTable
<< " iniMass= " << initialMass
<< G4endl;
}
}
if(aParticleType.GetParticleType() == "nucleus" &&
aParticleType.GetParticleName() != "GenericIon" &&
theMeanFreePathTable) {
G4EnergyLossTables::Register(&aParticleType,
theDEDXpTable,
theRangepTable,
theInverseRangepTable,
theLabTimepTable,
theProperTimepTable,
LowestKineticEnergy, HighestKineticEnergy,
proton_mass_c2/aParticleType.GetPDGMass(),
TotBin);
return;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
const G4ParticleDefinition* theProton = G4Proton::Proton();
G4double* ElectronCutInRange = G4Electron::Electron()->GetLengthCuts();
@@ -124,7 +170,7 @@ void G4hIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
if( !EqualCutVectors(ptableElectronCutInRange,ElectronCutInRange)
|| (theDEDXpTable == NULL))
{
BuildLossTable(aParticleType);
BuildLossTable(*theProton);
RecorderOfpProcess[CounterOfpProcess] = theLossTable;
CounterOfpProcess++;
}
@@ -134,7 +180,7 @@ void G4hIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
if( !EqualCutVectors(pbartableElectronCutInRange,ElectronCutInRange)
|| (theDEDXpbarTable == NULL))
{
BuildLossTable(aParticleType) ;
BuildLossTable(*(G4AntiProton::AntiProton())) ;
RecorderOfpbarProcess[CounterOfpbarProcess] = theLossTable;
CounterOfpbarProcess++;
}
@@ -144,7 +190,15 @@ void G4hIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
BuildDEDXTable(aParticleType);
if (&aParticleType == G4Proton::Proton()) PrintInfoDefinition();
if(2 < verboseLevel) {
G4cout << "MeanFreePathTable is built for "
<< aParticleType.GetParticleName() << G4endl;
G4cout << (*theMeanFreePathTable) << G4endl;
}
if (&aParticleType == theProton) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -198,6 +252,12 @@ void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
// Build mean free path tables for the delta ray production process
// tables are built for MATERIALS
if(0 < verboseLevel) {
G4cout << "G4hIonisation::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
//create table
//
@@ -211,7 +271,7 @@ void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
theMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
// get electron cut in kinetic energy
G4double* DeltaCutInKinEnergy = (G4Electron::Electron())->GetEnergyCuts() ;
G4double* DeltaCutInKinEnergy = (G4Electron::Electron())->GetEnergyCuts();
// loop for materials
@@ -232,6 +292,16 @@ void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
// it will be used in ComputeCrossSectionPerAtom
// ( --> it will be the same for all the elements in this material)
G4double DeltaThreshold =G4std::max(DeltaCutInKinEnergy[J],Tmincut);
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " Tcut(MeV)= " << DeltaThreshold/MeV
<< " Tmin(MeV)= " << LowerBoundLambda/MeV
<< " Tmax(MeV)= " << UpperBoundLambda/MeV
<< " nbins= " << NbinLambda
<< G4endl;
}
for ( G4int i = 0 ; i < NbinLambda ; i++ )
{
@@ -265,9 +335,7 @@ G4double G4hIonisation::ComputeRestrictedMeandEdx (
// calculate the dE/dx due to the ionization process (Geant4 internal units)
// Bethe-Bloch formula
//
G4double particleMass = aParticleType.GetPDGMass();
G4double particleZ = aParticleType.GetPDGCharge()/eplus;
G4double zsquare = particleZ*particleZ;
G4double particleMass = proton_mass_c2;
G4double ElectronDensity = material->GetElectronDensity();
G4double Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
@@ -319,7 +387,7 @@ G4double G4hIonisation::ComputeRestrictedMeandEdx (
// now you can compute the total ionization loss
dEdx -= (delta + sh);
dEdx *= twopi_mc2_rcl2*ElectronDensity*zsquare/beta2;
dEdx *= twopi_mc2_rcl2*ElectronDensity/beta2;
if (dEdx < 0.) dEdx = 0.;
}
//
@@ -353,7 +421,7 @@ G4double G4hIonisation::ComputeRestrictedMeandEdx (
if (aParticleType.GetPDGSpin() == 0.5)
deltaloss += 0.25*(Tmax-DeltaThreshold)*(Tmax-DeltaThreshold)/
(KineticEnergy*KineticEnergy+proton_mass_c2*proton_mass_c2);
deltaloss *= twopi_mc2_rcl2*ElectronDensity*zsquare/beta2;
deltaloss *= twopi_mc2_rcl2*ElectronDensity/beta2;
}
dEdx -= deltaloss;
if (dEdx < 0.) dEdx = 0.;
@@ -374,9 +442,8 @@ G4double G4hIonisation::ComputeCrossSectionPerAtom(
//
// nb: cross section formula is OK for spin=0 and 1/2 only !
G4double particleMass = aParticleType.GetPDGMass();
G4double particleZ = aParticleType.GetPDGCharge()/eplus;
G4double zparticle2 = particleZ*particleZ;
initialMass = aParticleType.GetPDGMass();
G4double particleMass = initialMass;
G4double TotalEnergy = KineticEnergy + particleMass;
@@ -405,7 +472,7 @@ G4double G4hIonisation::ComputeCrossSectionPerAtom(
betasquare /
(MaxKineticEnergyTransfer * DeltaThreshold)) / 3.0;
TotalCrossSection *= twopi_mc2_rcl2*AtomicNumber*zparticle2/betasquare;
TotalCrossSection *= twopi_mc2_rcl2*AtomicNumber/betasquare;
}
return TotalCrossSection;
}
@@ -420,7 +487,7 @@ G4VParticleChange* G4hIonisation::PostStepDoIt(const G4Track& trackData,
G4Material* aMaterial = trackData.GetMaterial();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double particleMass = aParticle->GetDefinition()->GetPDGMass();
G4double particleMass = aParticle->GetMass();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+particleMass);
@@ -511,7 +578,7 @@ G4VParticleChange* G4hIonisation::PostStepDoIt(const G4Track& trackData,
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (aParticle->GetDefinition()->GetParticleName() == "proton")
if (!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}