Import Geant4 2.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 15:42:07 +02:00
parent 103bda00c8
commit e7d7193284
3106 changed files with 171117 additions and 90550 deletions
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4ComptonScattering.cc,v 1.2.8.1.2.1 1999/12/08 17:34:22 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4ComptonScattering.cc,v 1.3 1999/12/15 14:51:50 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// --------------------------------------------------------------
@@ -28,7 +28,7 @@
// 05-03-97, new Physics scheme, M.Maire
// 28-03-97, protection in BuildPhysicsTable, M.Maire
// 07-04-98, remove 'tracking cut' of the scattered gamma, MMa
// 04-06-98, in DoIt, secondary production condition: range>min(threshold,safety)
// 04-06-98, in DoIt, secondary production condition: range>G4std::min(threshold,safety)
// 13-08-98, new methods SetBining() PrintInfo()
// 15-12-98, cross section=0 below 10 keV
// --------------------------------------------------------------
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4EnergyLossMessenger.cc,v 1.2.6.1.2.5 1999/12/14 09:16:48 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4EnergyLossMessenger.cc,v 1.5 2000/05/23 14:42:21 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
@@ -15,10 +15,8 @@
#include "G4EnergyLossMessenger.hh"
#include "G4eEnergyLoss.hh"
#include "G4hEnergyLoss.hh"
#include "G4eEnergyLossPlus.hh"
#include "G4hEnergyLossPlus.hh"
#include "G4VeEnergyLoss.hh"
#include "G4VhEnergyLoss.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
@@ -42,6 +40,12 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
EnlossFlucCmd->SetDefaultValue(true);
EnlossFlucCmd->AvailableForStates(Idle);
SubSecCmd = new G4UIcmdWithABool("/process/Loss/subsec",this);
SubSecCmd->SetGuidance("Switch on/off the subcutoff generation.");
SubSecCmd->SetParameterName("choice",true);
SubSecCmd->SetDefaultValue(true);
SubSecCmd->AvailableForStates(Idle);
StepFuncCmd = new G4UIcommand("/process/eLoss/StepFunction",this);
StepFuncCmd->SetGuidance("Set the energy loss step limitation parameters.");
StepFuncCmd->SetGuidance(" dRoverR : max Range variation per step");
@@ -69,6 +73,7 @@ G4EnergyLossMessenger::~G4EnergyLossMessenger()
{
delete RndmStepCmd;
delete EnlossFlucCmd;
delete SubSecCmd;
delete StepFuncCmd;
}
@@ -77,17 +82,18 @@ G4EnergyLossMessenger::~G4EnergyLossMessenger()
void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
{
if (command == RndmStepCmd)
{ G4eEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
G4hEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
G4eEnergyLossPlus::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
G4hEnergyLossPlus::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
{ G4VeEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
G4VhEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
}
if (command == EnlossFlucCmd)
{ G4eEnergyLoss::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
G4hEnergyLoss::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
G4eEnergyLossPlus::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
G4hEnergyLossPlus::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
{ G4VeEnergyLoss::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
G4VhEnergyLoss::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
}
if (command == SubSecCmd)
{ G4VeEnergyLoss::SetSubSec(SubSecCmd->GetNewBoolValue(newValue));
G4VhEnergyLoss::SetSubSec(SubSecCmd->GetNewBoolValue(newValue));
}
if (command == StepFuncCmd)
@@ -99,10 +105,8 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
is >> v1 >> v2 >> unts;
G4String unt = unts;
v2 *= G4UIcommand::ValueOf(unt);
G4eEnergyLoss::SetStepFunction(v1,v2);
G4hEnergyLoss::SetStepFunction(v1,v2);
G4eEnergyLossPlus::SetStepFunction(v1,v2);
G4hEnergyLossPlus::SetStepFunction(v1,v2);
G4VeEnergyLoss::SetStepFunction(v1,v2);
G4VhEnergyLoss::SetStepFunction(v1,v2);
}
}
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4GammaConversion.cc,v 1.2.8.1.2.2 1999/12/10 15:41:58 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4GammaConversion.cc,v 1.3 1999/12/15 14:51:50 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// --------------------------------------------------------------
@@ -35,7 +35,7 @@
// 14-03-97, new Physics scheme for geant4alpha, M.Maire
// 28-03-97, protection in BuildPhysicsTable, M.Maire
// 19-06-97, correction in ComputeMicroscopicCrossSection, L.Urban
// 04-06-98, in DoIt, secondary production condition: range>min(threshold,safety)
// 04-06-98, in DoIt, secondary production condition: range>G4std::min(threshold,safety)
// 13-08-98, new methods SetBining() PrintInfo()
// --------------------------------------------------------------
@@ -341,7 +341,7 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
G4double PositKineEnergy = G4std::max(0.,PositTotEnergy - electron_mass_c2) ;
// if (G4EnergyLossTables::GetRange(G4Positron::Positron(),PositKineEnergy,aMaterial)
// < min(G4Positron::GetCuts(), aStep.GetPostStepPoint()->GetSafety()) )
// < G4std::min(G4Positron::GetCuts(), aStep.GetPostStepPoint()->GetSafety()) )
if((G4EnergyLossTables::GetRange(G4Positron::Positron(),
PositKineEnergy,aMaterial)<aStep.GetPostStepPoint()->GetSafety())
&&
@@ -1,820 +0,0 @@
// 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: G4IMultipleScattering.cc,v 1.2.8.1.2.1 1999/12/08 17:34:22 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
//
// $Id:
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4IMultipleScattering physics process ------------
// by Laszlo Urban, October 1997
// **************************************************************
// 09/12/98: charge can be != +- 1 !!!! L.Urban
// ************************************************************
// It is the first implementation of the
// MULTIPLESCATTERING PROCESS
// using an INTEGRAL APPROACH instead of the differential
// one used in the standard implementation .
// ************************************************************
// by Laszlo Urban, 23 June 1998
// ---------------------------------------------------------------
// 27/10/98: cleanup , L. Urban
#include "G4IMultipleScattering.hh"
#include "G4UnitsTable.hh"
G4IMultipleScattering::G4IMultipleScattering(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(NULL),
theIntegralITable(NULL),
theIntegralJTable(NULL),
lastMaterial(NULL),
lastKineticEnergy(-1.*MeV),
fTransportMeanFreePath(1.e12),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
NumberOfBuildPhysicsTableCalls(0),
theElectron(G4Electron::Electron()),
thePositron(G4Positron::Positron()),
plowloss ( 0.5 ),
plowlambda ( 0.4 ),
tLast (0.0),
zLast (0.0),
CosTheta (1.0),
biglambda ( 1.e10*mm),
tuning(1.0)
{ }
G4IMultipleScattering::~G4IMultipleScattering()
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
if(theIntegralITable)
{
theIntegralITable->clearAndDestroy() ;
delete theIntegralITable ;
}
if(theIntegralJTable)
{
theIntegralJTable->clearAndDestroy() ;
delete theIntegralJTable ;
}
}
void G4IMultipleScattering::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
{
NumberOfBuildPhysicsTableCalls += 1 ;
if(NumberOfBuildPhysicsTableCalls == 1)
{ ; }
else
{
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius ;
G4double KineticEnergy,AtomicNumber,sigma,lambda ;
G4double density ;
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
G4int numOfMaterials = theMaterialTable->length() ;
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials) ;
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin) ;
const G4Material* material = (*theMaterialTable)(J) ;
const G4ElementVector* theElementVector =
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements =
material->GetNumberOfElements() ;
density = material->GetDensity() ;
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
sigma = 0. ;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
AtomicNumber = (*theElementVector)(iel)->GetZ() ;
sigma += theAtomicNumDensityVector[iel]*
ComputeTransportCrossSection(aParticleType,
KineticEnergy,AtomicNumber) ;
}
sigma *= sigmafactor ;
lambda = 1./sigma ;
aVector->PutValue(i,lambda) ;
}
theTransportMeanFreePathTable->insert(aVector) ;
}
BuildIntegralITable(aParticleType) ;
BuildIntegralJTable(aParticleType) ;
NumberOfBuildPhysicsTableCalls = 0 ;
if( (&aParticleType == G4Electron::Electron()) ||
(&aParticleType == G4MuonPlus::MuonPlus()) ||
(&aParticleType == G4Proton::Proton()) )
{
PrintInfoDefinition() ;
}
}
}
void G4IMultipleScattering::BuildIntegralITable(
const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
G4Material* aMaterial ;
G4double fmin,lmin,Value,KineticEnergy,lambda,Tlast,Vlast ;
G4double u,umax,du,t,coeff,dEdx ;
G4int n,nmax ;
G4bool isOut ;
const G4int nb = 100 ;
G4double rmin ;
if(theIntegralITable)
{
theIntegralITable->clearAndDestroy() ;
delete theIntegralITable ;
}
G4int numOfMaterials = theMaterialTable->length() ;
theIntegralITable = new G4PhysicsTable(numOfMaterials) ;
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin) ;
aMaterial = (*theMaterialTable)(J) ;
rmin = G4EnergyLossTables::GetPreciseRangeFromEnergy(
&aParticleType,
LowestKineticEnergy,
aMaterial) ;
lmin = (*theTransportMeanFreePathTable)(J)->
GetValue(LowestKineticEnergy,isOut) ;
// this value comes from z=r*l/(r+l) = exp(-I) !!!
Value = -log(rmin*lmin/(rmin+lmin)) ;
aVector->PutValue(0,Value) ;
Tlast = LowestKineticEnergy ;
Vlast = Value ;
for (G4int i=1; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
umax = log(KineticEnergy/Tlast) ;
nmax = int(nb*umax + 0.5) ;
if(nmax<1)
nmax = 1 ;
du = umax/nmax ;
Value = 0. ;
u = -du ;
for(n=0; n<=nmax; n++)
{
u += du ;
t = Tlast*exp(u) ;
lambda = (*theTransportMeanFreePathTable)(J)->
GetValue(t,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(&aParticleType,
t,aMaterial) ;
if((n == 0) || (n == nmax))
coeff = 0.5 ;
else
coeff = 1. ;
Value += coeff*t/(dEdx*lambda) ;
}
Value *= du ;
Value += Vlast ;
aVector->PutValue(i,Value) ;
Tlast = KineticEnergy ;
Vlast = Value ;
}
theIntegralITable->insert(aVector) ;
}
}
void G4IMultipleScattering::BuildIntegralJTable(
const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
G4Material* aMaterial ;
G4double rmin,lmin,Value,KineticEnergy,lambda,Tlast,Vlast ;
G4double u,umax,du,t,coeff,dEdx,w,ww ;
G4double cmin,lndu ;
G4int n,nmax ;
G4bool isOut ;
const G4int nb = 100 ;
if(theIntegralJTable)
{
theIntegralJTable->clearAndDestroy() ;
delete theIntegralJTable ;
}
G4int numOfMaterials = theMaterialTable->length() ;
theIntegralJTable = new G4PhysicsTable(numOfMaterials) ;
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin) ;
aMaterial = (*theMaterialTable)(J) ;
rmin = G4EnergyLossTables::GetPreciseRangeFromEnergy(
&aParticleType,
LowestKineticEnergy,
aMaterial) ;
lmin = (*theTransportMeanFreePathTable)(J)->
GetValue(LowestKineticEnergy,isOut) ;
Value = rmin*lmin/(rmin+lmin) ;
aVector->PutValue(0,Value) ;
Tlast = LowestKineticEnergy ;
Vlast = Value ;
for (G4int i=1; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
umax = log(KineticEnergy/Tlast) ;
nmax =int(nb*umax + 0.5) ;
if(nmax<1)
nmax = 1 ;
du = umax/nmax ;
Value = 0. ;
u = -du ;
for(n=0; n<=nmax; n++)
{
u += du ;
t = Tlast*exp(u) ;
w = (*theIntegralITable)(J)->
GetValue(t,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(&aParticleType,
t,aMaterial) ;
if((n == 0) || (n == nmax))
coeff = 0.5 ;
else
coeff = 1. ;
Value += coeff*t*exp(w)/dEdx ;
}
Value *= du ;
w = (*theIntegralITable)(J)->
GetValue(Tlast,isOut) ;
ww = (*theIntegralITable)(J)->
GetValue(KineticEnergy,isOut) ;
Value *= exp(-ww) ;
Value += exp(w-ww)*Vlast ;
aVector->PutValue(i,Value) ;
Tlast = KineticEnergy ;
Vlast = Value ;
}
theIntegralJTable->insert(aVector) ;
}
}
G4double G4IMultipleScattering::GetIntegralI(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
G4Material* aMaterial)
{
G4double intI ;
G4bool isOut ;
if(KineticEnergy < LowestKineticEnergy)
{
intI = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(LowestKineticEnergy,isOut) ;
intI *= exp((1.-plowloss-plowlambda)*
log(KineticEnergy/LowestKineticEnergy)) ;
}
else if(KineticEnergy <= HighestKineticEnergy)
{
intI = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(KineticEnergy,isOut) ;
}
else
{
intI = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut) ;
intI += (KineticEnergy-HighestKineticEnergy)/
((*theTransportMeanFreePathTable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut)
*
G4EnergyLossTables::GetPreciseDEDX(aParticle,
HighestKineticEnergy,aMaterial)) ;
}
return intI ;
}
G4double G4IMultipleScattering::GetIntegralJ(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
G4Material* aMaterial)
{
G4double intJ,lmin,lmax,fmax,Imin,Imin2,t ;
G4bool isOut ;
if(KineticEnergy < LowestKineticEnergy)
{
lmin = (*theTransportMeanFreePathTable)(aMaterial->GetIndex())->
GetValue(KineticEnergy,isOut) ;
Imin = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(LowestKineticEnergy,isOut) ;
Imin2= Imin*Imin ;
t = exp(0.1*log(KineticEnergy/LowestKineticEnergy)) ;
intJ = (((t-4./Imin)*t+12./Imin2)*t-24./(Imin*Imin2))*t+24./(Imin2*Imin2);
intJ -= 24.*exp(-Imin*t)/(Imin2*Imin2) ;
intJ *= lmin ;
}
else if(KineticEnergy <= HighestKineticEnergy)
{
intJ = (*theIntegralJTable)(aMaterial->GetIndex())->
GetValue(KineticEnergy,isOut) ;
}
else
{
lmax = (*theTransportMeanFreePathTable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut) ;
fmax = G4EnergyLossTables::GetPreciseDEDX(aParticle,
HighestKineticEnergy,aMaterial) ;
intJ = lmax - (lmax-(*theIntegralJTable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut))*
exp((HighestKineticEnergy-KineticEnergy)/(fmax*lmax)) ;
}
return intJ ;
}
G4double G4IMultipleScattering::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc) ;
const G4double epsmin = 1.e-4 , epsmax = 1.e10 ;
const G4double cpar=1.50 ;
const G4double Zdat[15] = {4.,6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. } ;
const G4double Tdat[22] =
{ 0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,0.01*MeV,
0.02*MeV,0.04*MeV,0.07*MeV,0.1*MeV,0.2*MeV,
0.4*MeV,0.7*MeV,1.*MeV,2.*MeV,4.*MeV,
7.*MeV,10.*MeV,20.*MeV} ;
// corr. factors for e-/e+ lambda
const G4double celectron[15][22] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, misprint?
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949 }};
const G4double cpositron[15][22] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282 }};
G4double Z23,ParticleMass,rat2,Charge,TotalEnergy,beta2,bg2,
eps,Z1,Z2,ratZ,T,E,b2small,b2big,ratb2,c1,c2,cc1,cc2,
corr,sigma,corrfactor,ChargeSquare ;
G4int iZ,iT ;
Z23 = 2.*log(AtomicNumber)/3. ;
Z23 = exp(Z23) ;
ParticleMass = aParticleType.GetPDGMass() ;
rat2 = ParticleMass/electron_mass_c2 ;
rat2 = rat2*rat2 ;
Charge = aParticleType.GetPDGCharge() ;
ChargeSquare = Charge*Charge/(eplus*eplus) ;
TotalEnergy = KineticEnergy + ParticleMass ;
beta2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(TotalEnergy*TotalEnergy) ;
bg2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(ParticleMass*ParticleMass) ;
eps = rat2*epsfactor*bg2/Z23 ;
if(eps<epsmin)
sigma = 2.*eps*eps*eps/3. ;
else if(eps<epsmax)
sigma = log(1.+2.*eps)-2.*eps/(1.+eps) ;
else
sigma = log(2.*eps)-2.+2.5/eps ;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/rat2 ;
sigma /= beta2*bg2 ;
// correct this value using the corrections computed for e+/e-
KineticEnergy *= electron_mass_c2/ParticleMass ;
// interpolate in AtomicNumber and beta2
// get bin number in Z
iZ = 14 ;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber))
{
iZ -= 1 ;
}
if(iZ==14)
{
iZ = 13 ;
}
if(iZ==-1)
{
iZ = 0 ;
}
Z1 = Zdat[iZ] ;
Z2 = Zdat[iZ+1] ;
ratZ = (AtomicNumber-Z1)/(Z2-Z1) ;
// get bin number in T (beta2)
iT = 21 ;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy))
iT -= 1 ;
if(iT==21)
iT = 20 ;
if(iT==-1)
iT = 0 ;
// calculate betasquare values
T = Tdat[iT] ;
E = T + electron_mass_c2 ;
b2small = T*(E+electron_mass_c2)/(E*E) ;
T = Tdat[iT+1] ;
E = T + electron_mass_c2 ;
b2big = T*(E+electron_mass_c2)/(E*E) ;
ratb2 = (beta2-b2small)/(b2big-b2small) ;
corrfactor = tuning*(1.+cpar)/(1.+cpar*beta2) ;
if(Charge < 0.)
{
c1 = celectron[iZ][iT] ;
c2 = celectron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = celectron[iZ][iT+1] ;
c2 = celectron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
if(Charge > 0.)
{
c1 = cpositron[iZ][iT] ;
c2 = cpositron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = cpositron[iZ][iT+1] ;
c2 = cpositron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
sigma *= corrfactor ;
return sigma ;
}
G4VParticleChange* G4IMultipleScattering::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
G4double lambdasave ;
const G4double taulim = 1.e-10 , randlim = 0.25*taulim*taulim ;
const G4double tausmall = 5.e-5,taubig =50.;
const G4double scatteringparameter=1.00 ,
kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
const G4DynamicParticle* aParticle ;
G4Material* aMaterial ;
G4int materialIndex ;
G4double KineticEnergy,truestep,tau,prob,cth,sth,phi,
dirx,diry,dirz,w,w1,etau,rmean,safetyminustolerance,
xnew,ynew,znew ;
G4double rand,rmax2 ;
G4bool isOut;
aParticleChange.Initialize(trackData) ;
aMaterial = stepData.GetPreStepPoint()->GetMaterial() ;
truestep = stepData.GetStepLength() ;
// there is no scattering for truestep=0. !
if(truestep == 0.)
return &aParticleChange ;
aParticle = trackData.GetDynamicParticle() ;
materialIndex = aMaterial->GetIndex() ;
KineticEnergy = aParticle->GetKineticEnergy() ;
// shortcut if the particle is not Alive (e.g. stopped in energy loss)
if(trackData.GetTrackStatus() != fAlive)
return &aParticleChange ;
if ((lastMaterial == aMaterial) && (lastKineticEnergy == KineticEnergy))
{
;
}
else
{
lastMaterial=aMaterial;
lastKineticEnergy=KineticEnergy;
if(KineticEnergy<LowestKineticEnergy)
{
fTransportMeanFreePath =
exp(plowlambda*log(KineticEnergy/LowestKineticEnergy))*
(*theTransportMeanFreePathTable)
(materialIndex)->GetValue(LowestKineticEnergy,isOut);
}
else
{
// TransportMeanFreePath taken at kin.energy after the energy loss!
if(KineticEnergy>HighestKineticEnergy)
KineticEnergy = HighestKineticEnergy ;
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
}
}
// effective lambda used in scattering .....................
lambdasave = fTransportMeanFreePath ;
if(CosTheta == 1.)
{
fTransportMeanFreePath = biglambda ;
tau = 0.;
cth = 1. ;
}
else if(CosTheta == 0.)
{
fTransportMeanFreePath = 0. ;
tau = biglambda ;
cth = -1.+2.*G4UniformRand() ;
}
else
{
fTransportMeanFreePath = -truestep/log(CosTheta) ;
tau = truestep/fTransportMeanFreePath ;
prob = exp(-tau)*(1.+scatteringparameter*tau) ;
if(G4UniformRand()<prob)
{
if(tau<taulim)
{
rand = G4UniformRand() ;
if(rand > randlim)
cth = 1.-tau*(1./sqrt(rand)-1.) ;
else
cth = -1. ;
}
else
{
w = 1.+scatteringparameter*tau ;
w1 = w-1. ;
cth = w-w1*(w+1.)/sqrt(w1*w1+4.*w*G4UniformRand()) ;
}
}
else
cth = -1.+2.*G4UniformRand() ;
}
sth = sqrt(1.-cth*cth) ;
phi = twopi*G4UniformRand() ;
dirx = sth*cos(phi) ;
diry = sth*sin(phi) ;
dirz = cth ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz) ;
newDirection.rotateUz(ParticleDirection) ;
aParticleChange.SetNumberOfSecondaries(0) ;
aParticleChange.SetEnergyChange( KineticEnergy ) ;
aParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z()) ;
// compute lateral displacement
// only for safety > tolerance !!!!!
safetyminustolerance = stepData.GetPostStepPoint()->GetSafety()
-kCarTolerance ;
if(safetyminustolerance > 0.)
{
if(truestep == GeomStepFinal)
{ ; }
else
{
rmax2 = (truestep+GeomStepFinal)*(truestep-GeomStepFinal) ;
if(tau<tausmall)
rmean = 5.*tau*tau*tau/12. ;
else
{
if(tau<taubig)
etau = exp(-tau) ;
else
etau = 0. ;
rmean = -kappa*tau ;
rmean = -exp(rmean)/(kappa*kappami1) ;
rmean += tau-kappapl1/kappa+kappa*etau/kappami1 ;
}
rmean *= 4.*fTransportMeanFreePath*fTransportMeanFreePath/3.;
if(rmean>rmax2)
rmean = rmax2 ;
if(rmean>0.)
{
rmean = sqrt(rmean) ;
if(rmean>safetyminustolerance)
rmean = safetyminustolerance ;
fMeanLateralDisplacement = rmean ;
// sample direction of lateral displacement
phi = twopi*G4UniformRand() ;
dirx = cos(phi) ;
diry = sin(phi) ;
dirz = 0. ;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection) ;
// compute new endpoint of the Step
xnew = stepData.GetPostStepPoint()->GetPosition().x()+
rmean*latDirection.x() ;
ynew = stepData.GetPostStepPoint()->GetPosition().y()+
rmean*latDirection.y() ;
znew = stepData.GetPostStepPoint()->GetPosition().z()+
rmean*latDirection.z() ;
aParticleChange.SetPositionChange(xnew,ynew,znew) ;
}
}
}
fTransportMeanFreePath = lambdasave ;
return &aParticleChange ;
}
void G4IMultipleScattering::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
comments += "\n New model of MSC , computes the lateral \n";
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IeBremsstrahlung.cc,v 1.3.8.1.2.3 1999/12/10 15:41:59 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4IeBremsstrahlung.cc,v 1.5 2000/04/25 14:33:08 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// --------------------------------------------------------------
@@ -36,7 +36,7 @@
G4IeBremsstrahlung::G4IeBremsstrahlung(const G4String& processName)
: G4IeEnergyLoss(processName),
: G4VIeEnergyLoss(processName),
theMeanFreePathTable(NULL),
theNlambdaTable(NULL),
theInverseNlambdaTable(NULL),
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IeIonisation.cc,v 1.3.8.1.2.3 1999/12/10 15:41:59 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4IeIonisation.cc,v 1.5 2000/04/25 14:33:08 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// -------------------------------------------------------------
@@ -33,7 +33,7 @@
G4IeIonisation::G4IeIonisation(const G4String& processName)
: G4IeEnergyLoss(processName),
: G4VIeEnergyLoss(processName),
theMeanFreePathTable(NULL),
theNlambdaTable(NULL),
theInverseNlambdaTable(NULL),
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IeplusAnnihilation.cc,v 1.5.8.1.2.2 1999/12/09 16:18:04 gcosmo Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4IeplusAnnihilation.cc,v 1.6 1999/12/15 14:51:50 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// --------------------------------------------------------------
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IhIonisation.cc,v 1.5.8.1.2.2 1999/12/09 16:18:04 gcosmo Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4IhIonisation.cc,v 1.7 2000/04/25 14:33:09 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// -------------------------------------------------------------
// GEANT 4 class implementation file
@@ -34,7 +34,7 @@
// constructor and destructor
G4IhIonisation::G4IhIonisation(const G4String& processName)
: G4IhEnergyLoss(processName),
: G4VIhEnergyLoss(processName),
theMeanFreePathTable(NULL),
NumberOfBuildPhysicsTableCalls(0),
theProton (G4Proton::Proton()),
@@ -0,0 +1,259 @@
// Implementation of class for selecting ionisation model depending on
// logical volume
//
//
#include "G4IonisationByLogicalVolume.hh"
///////////////////////////////////////////////////////////////////////////
//
//
G4IonisationByLogicalVolume::
G4IonisationByLogicalVolume( const G4String& particleName,
G4LogicalVolume* volumeForPAImodel,
const G4String& processName ) :
G4VContinuousDiscreteProcess(processName),
fPAIonisation(NULL),feIonisation(NULL),fMuIonisation(NULL),fhIonisation(NULL)
{
fParticleName = particleName ;
fVolumeForPAImodel = volumeForPAImodel ;
fMaterialNameForPAI = volumeForPAImodel->GetMaterial()->GetName() ;
fPAIonisation = new G4PAIonisation(fMaterialNameForPAI);
if ( fParticleName == "e+" || fParticleName == "e-" )
{
feIonisation = new G4eIonisation() ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
fMuIonisation = new G4MuIonisation() ;
}
else
{
fhIonisation = new G4hIonisation() ;
}
}
///////////////////////////////////////////////////////////////////////////
//
//
G4IonisationByLogicalVolume::~G4IonisationByLogicalVolume()
{
if(fPAIonisation) delete fPAIonisation ;
if(feIonisation) delete feIonisation ;
if(fMuIonisation) delete fMuIonisation ;
if(fhIonisation) delete fhIonisation ;
}
///////////////////////////////////////////////////////////////////////////
//
// Methods
G4bool G4IonisationByLogicalVolume::
IsApplicable( const G4ParticleDefinition& particle )
{
return( particle.GetPDGCharge() != 0.) ;
}
/////////////////////////////////////////////////////////////////////////
//
//
/* ***********************************************
G4double G4IonisationByLogicalVolume::
GetConstraints(const G4DynamicParticle* aParticle,
G4Material* aMaterial )
{
if ( aMaterial->GetName() == fMaterialNameForPAI )
{
return fPAIonisation->GetConstraints(aParticle,aMaterial) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
return feIonisation->GetConstraints(aParticle,aMaterial) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
return fMuIonisation->GetConstraints(aParticle,aMaterial) ;
}
else
{
return fhIonisation->GetConstraints(aParticle,aMaterial) ;
}
}
}
************************************** */
////////////////////////////////////////////////////////////////////////////
//
//
G4VParticleChange*
G4IonisationByLogicalVolume::PostStepDoIt( const G4Track& track,
const G4Step& step )
{
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
return fPAIonisation->PostStepDoIt(track,step) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
return feIonisation->PostStepDoIt(track,step) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
return fMuIonisation->PostStepDoIt(track,step) ;
}
else
{
return fhIonisation->PostStepDoIt(track,step) ;
}
}
}
////////////////////////////////////////////////////////////////////////
//
//
void G4IonisationByLogicalVolume::
BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
fPAIonisation->BuildPhysicsTable(aParticleType) ;
if ( fParticleName == "e+" || fParticleName == "e-" )
{
feIonisation->BuildPhysicsTable(aParticleType) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
fMuIonisation->BuildPhysicsTable(aParticleType) ;
}
else
{
fhIonisation->BuildPhysicsTable(aParticleType) ;
}
}
////////////////////////////////////////////////////////////////////////
//
//
G4double G4IonisationByLogicalVolume::
GetContinuousStepLimit( const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety )
{
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
return fPAIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
return feIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
return fMuIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
else
{
return fhIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
}
}
////////////////////////////////////////////////////////////////////////
//
//
G4double G4IonisationByLogicalVolume::
GetMeanFreePath( const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition )
{
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
return fPAIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
return feIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
return fMuIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
else
{
return fhIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
}
}
/////////////////////////////////////////////////////////////////////////
//
//
G4VParticleChange*
G4IonisationByLogicalVolume::AlongStepDoIt( const G4Track& track ,
const G4Step& step )
{
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
return fPAIonisation->AlongStepDoIt(track,step) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
return feIonisation->AlongStepDoIt(track,step) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
return fMuIonisation->AlongStepDoIt(track,step) ;
}
else
{
return fhIonisation->AlongStepDoIt(track,step) ;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
//
void G4IonisationByLogicalVolume::
SetVolumeForPAImodel( G4LogicalVolume* volumeForPAImodel )
{
fVolumeForPAImodel = volumeForPAImodel ;
}
//
//
/////////////////////////////////////////////////////////////////////////
@@ -1,579 +0,0 @@
// 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: G4MultipleScattering.cc,v 1.16.6.1.2.1 1999/12/08 17:34:24 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
//
// $Id:
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MultipleScattering physics process ------------
// by Laszlo Urban, October 1997
// **************************************************************
// 24/10/97 correction in PostStepDoIt for tau << 1. L.Urban
// 09/12/98: charge can be different from +-1 !!!! L.Urban
// 29/07/99: corr. for low energy , L.Urban
// 17/09/99: corr. for high energy and/or small step , L.Urban
// 30/09/99: nuclear size effect correction, L.Urban
// --------------------------------------------------------------
#include "G4MultipleScattering.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
G4MultipleScattering::G4MultipleScattering(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(NULL),
lastMaterial(NULL),
lastKineticEnergy(0.),
materialIndex(0),
fTransportMeanFreePath (1.e12),
range(1.e10*mm),
alpha1(5.),
stepFlag(0),
biglambda (1.e10*mm),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
theElectron(G4Electron::Electron()),
thePositron(G4Positron::Positron()),
tLast (0.0),
zLast (0.0),
Tlimit(0.*keV),
scatteringparameter(0.9),
tuning (1.00),
cpar (1.5),
NuclCorrPar (0.0615),FactPar(0.40),
fLatDisplFlag(true)
{ }
G4MultipleScattering::~G4MultipleScattering()
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
}
// .........methods..............................
void G4MultipleScattering::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
// tables are built for MATERIALS
{
// parameter for "low energy" msc (not for ions)
if((&aParticleType == G4Electron::Electron()) ||
(&aParticleType == G4Positron::Positron()) )
// Tlimit = 100.*keV ;
;
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius ;
G4double KineticEnergy,AtomicNumber,AtomicWeight,
sigma,lambda ;
G4double density ;
// destroy old tables if any
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
// create table
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length() ;
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials) ;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin) ;
// get elements in the material
const G4Material* material = (*theMaterialTable)(J) ;
const G4ElementVector* theElementVector =
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements =
material->GetNumberOfElements() ;
density = material->GetDensity() ;
// loop for kinetic energy values
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
sigma = 0. ;
// loop for element in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
AtomicNumber = (*theElementVector)(iel)->GetZ() ;
AtomicWeight = (*theElementVector)(iel)->GetA() ;
sigma += theAtomicNumDensityVector[iel]*
ComputeTransportCrossSection(aParticleType,
KineticEnergy,
AtomicNumber,AtomicWeight) ;
}
sigma *= sigmafactor ;
lambda = 1./sigma ;
aVector->PutValue(i,lambda) ;
}
theTransportMeanFreePathTable->insert(aVector) ;
}
if( (&aParticleType == G4Electron::Electron()) ||
(&aParticleType == G4MuonPlus::MuonPlus()) ||
(&aParticleType == G4Proton::Proton()) )
{
PrintInfoDefinition() ;
}
}
G4double G4MultipleScattering::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,G4double AtomicWeight)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc) ;
const G4double epsmin = 1.e-4 , epsmax = 1.e10 ;
const G4double Zdat[15] = {4.,6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. } ;
const G4double Tdat[22] =
{ 0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,0.01*MeV,
0.02*MeV,0.04*MeV,0.07*MeV,0.1*MeV,0.2*MeV,
0.4*MeV,0.7*MeV,1.*MeV,2.*MeV,4.*MeV,
7.*MeV,10.*MeV,20.*MeV} ;
// corr. factors for e-/e+ lambda
const G4double celectron[15][22] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, misprint?
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949 }};
const G4double cpositron[15][22] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282 }};
G4double Z23,ParticleMass,rat2,Charge,TotalEnergy,beta2,bg2,
eps,Z1,Z2,ratZ,T,E,b2small,b2big,ratb2,c1,c2,cc1,cc2,
corr,sigma,corrfactor,ChargeSquare ;
G4int iZ,iT ;
Z23 = 2.*log(AtomicNumber)/3. ;
Z23 = exp(Z23) ;
ParticleMass = aParticleType.GetPDGMass() ;
rat2 = ParticleMass/electron_mass_c2 ;
rat2 = rat2*rat2 ;
Charge = aParticleType.GetPDGCharge() ;
ChargeSquare = Charge*Charge/(eplus*eplus) ;
TotalEnergy = KineticEnergy + ParticleMass ;
beta2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(TotalEnergy*TotalEnergy) ;
bg2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(ParticleMass*ParticleMass) ;
eps = rat2*epsfactor*bg2/Z23 ;
if(eps<epsmin)
sigma = 2.*eps*eps*eps/3. ;
else if(eps<epsmax)
sigma = log(1.+2.*eps)-2.*eps/(1.+eps) ;
else
sigma = log(2.*eps)-2.+2.5/eps ;
sigma *=ChargeSquare*AtomicNumber*AtomicNumber/rat2 ;
sigma /= beta2*bg2 ;
// nuclear size effect correction for high energy
// ( a simple approximation at present)
G4double corrnuclsize,a,x0,w1,w2,w ;
x0 = 1. - NuclCorrPar*ParticleMass/(KineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.)) ;
if((x0 < -1.) || (KineticEnergy <= 10.*MeV))
{
x0=-1. ;
corrnuclsize = 1. ;
}
else
{
a = 1.+1./eps ;
if(eps > epsmax)
w1=log(2.*eps)+1./eps-3./(8.*eps*eps) ;
else
w1=log((a+1.)/(a-1.))-2./(a+1.) ;
w = 1./((1.-x0)*eps) ;
if(w < epsmin)
w2=-log(w)-1.+2.*w-1.5*w*w ;
else
w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0) ;
corrnuclsize = w1/w2 ;
// ####################################################
corrnuclsize = exp(-FactPar*proton_mass_c2/KineticEnergy)*
(corrnuclsize-1.)+1. ;
}
// correct this value using the corrections computed for e+/e-
KineticEnergy *= electron_mass_c2/ParticleMass ;
// interpolate in AtomicNumber and beta2
// get bin number in Z
iZ = 14 ;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber)) iZ -= 1 ;
if (iZ==14) iZ = 13 ;
if (iZ==-1) iZ = 0 ;
Z1 = Zdat[iZ] ;
Z2 = Zdat[iZ+1] ;
ratZ = (AtomicNumber-Z1)/(Z2-Z1) ;
// get bin number in T (beta2)
iT = 21 ;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy))
iT -= 1 ;
if(iT==21)
iT = 20 ;
if(iT==-1)
iT = 0 ;
// calculate betasquare values
T = Tdat[iT] ;
E = T + electron_mass_c2 ;
b2small = T*(E+electron_mass_c2)/(E*E) ;
T = Tdat[iT+1] ;
E = T + electron_mass_c2 ;
b2big = T*(E+electron_mass_c2)/(E*E) ;
ratb2 = (beta2-b2small)/(b2big-b2small) ;
corrfactor = tuning*(1.+cpar)/(1.+cpar*beta2) ;
if(Charge < 0.)
{
c1 = celectron[iZ][iT] ;
c2 = celectron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = celectron[iZ][iT+1] ;
c2 = celectron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
if(Charge > 0.)
{
c1 = cpositron[iZ][iT] ;
c2 = cpositron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = cpositron[iZ][iT+1] ;
c2 = cpositron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
sigma *= corrfactor ;
sigma /= corrnuclsize ;
return sigma ;
}
G4VParticleChange* G4MultipleScattering::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
static G4double taulim=1.e-6 , randlim = 0.25*taulim*taulim ;
static const G4double tausmall = 5.e-5,taubig =50.,
kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
const G4DynamicParticle* aParticle ;
G4Material* aMaterial ;
G4double KineticEnergy,truestep,tau,prob,cth,sth,phi,
dirx,diry,dirz,w,w1,etau,rmean,safetyminustolerance,
xnew,ynew,znew ;
G4double rand ;
G4bool isOut;
fParticleChange.Initialize(trackData) ;
truestep = stepData.GetStepLength() ;
aParticle = trackData.GetDynamicParticle() ;
KineticEnergy = aParticle->GetKineticEnergy() ;
if(stepFlag == 0)
{
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
}
// change direction first ( scattering ) ..........................
if(stepFlag == 0)
{
tau = truestep/fTransportMeanFreePath ;
if(tau > taulim)
prob = exp(-tau)*(1.+scatteringparameter*tau) ;
else
prob=1.-(1.-scatteringparameter)*tau ;
}
else
{
tau = truestep/range ;
if(tau < taulim)
prob = exp(-(alpha1-1.)*tau)*(1.+scatteringparameter*tau) ;
else
prob = exp((alpha1-1.)*log(1.-tau))*(1.+scatteringparameter*tau) ;
}
if(G4UniformRand()<prob)
{
if(tau<taulim)
{
rand = G4UniformRand() ;
if(rand > randlim)
{
cth = 1.-scatteringparameter*tau*(1./sqrt(rand)-1.) ;
if(cth < -1.) cth = -1. ;
}
else
cth = -1. ;
}
else
{
w = 1.+scatteringparameter*tau ;
w1 = w-1. ;
cth = w-w1*(w+1.)/sqrt(w1*w1+4.*w*G4UniformRand()) ;
}
}
else
cth = -1.+2.*G4UniformRand() ;
sth = sqrt(1.-cth*cth) ;
phi = twopi*G4UniformRand() ;
dirx = sth*cos(phi) ;
diry = sth*sin(phi) ;
dirz = cth ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz) ;
newDirection.rotateUz(ParticleDirection) ;
fParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z()) ;
if(fLatDisplFlag)
{
// compute mean lateral displacement ...............
// only for safety > tolerance !!!!!!!!!
safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
if(safetyminustolerance > 0.)
{
if(tau<tausmall)
rmean = 5.*tau*tau*tau/12. ;
else
{
if(tau<taubig)
etau = exp(-tau) ;
else
etau = 0. ;
rmean = -kappa*tau ;
rmean = -exp(rmean)/(kappa*kappami1) ;
rmean += tau-kappapl1/kappa+kappa*etau/kappami1 ;
}
if(rmean>0.)
rmean = 2.*fTransportMeanFreePath*sqrt(rmean/3.) ;
else
rmean = 0. ;
// for rmean > 0) only
if(rmean>0.)
{
if(rmean>safetyminustolerance)
rmean = safetyminustolerance ;
// sample direction of lateral displacement
phi = twopi*G4UniformRand() ;
dirx = cos(phi) ;
diry = sin(phi) ;
dirz = 0. ;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection) ;
// compute new endpoint of the Step
G4ThreeVector newPosition=
stepData.GetPostStepPoint()->GetPosition()+
rmean*latDirection;
G4Navigator *navigator=
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
navigator->LocateGlobalPointWithinVolume( newPosition );
fParticleChange.SetPositionChange(newPosition) ;
}
}
}
return &fParticleChange ;
}
void G4MultipleScattering::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
comments += "\n New model of MSC , computes the lateral \n";
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
@@ -1,845 +0,0 @@
// 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: G4PAIenergyLoss.cc,v 1.2.8.1 1999/12/07 20:50:59 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
//
// $Id:
// -----------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4PAIenergyLoss physics process -----------
// by V. Grichine, 30 Nov 1997
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of charged hadrons.
// **************************************************************
//
// corrected by V. Grichine on 24/11/97
// corrected by L. Urban on 27/05/98 ( other corrections come soon!)
//
#include "G4PAIenergyLoss.hh"
#include "G4PAIonisation.hh"
#include "G4EnergyLossTables.hh"
////////////////////////////////////////////////////////////////////////////
//
// Initialisation of static members
// ( this stuff should be defined later using RW ..........)
// contributing processes : ion.loss ->NUMBEROFPROCESSES is initialized
// to 1 . YOU DO NOT HAVE TO CHANGE this variable for a 'normal' run.
// You have to change NUMBEROFPROCESSES
// if you invent a new process contributing to the cont. energy loss,
// NUMBEROFPROCESSES should be 2 in this case,
// or for debugging purposes.
// The NUMBEROFPROCESSES data member can be changed using the (public static)
// functions Get/Set/Plus/MinusNUMBEROFPROCESSES (see G4hEnergyLoss.hh)
G4int G4PAIenergyLoss::NUMBEROFPROCESSES = 1 ;
G4PhysicsTable** G4PAIenergyLoss::RecorderOfpProcess =
new G4PhysicsTable*[10] ;
G4int G4PAIenergyLoss::CounterOfpProcess = 0 ;
G4PhysicsTable* G4PAIenergyLoss::theDEDXpTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theRangepTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theInverseRangepTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theLabTimepTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theProperTimepTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::thepRangeCoeffATable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::thepRangeCoeffBTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::thepRangeCoeffCTable = NULL ;
G4PhysicsTable** G4PAIenergyLoss::RecorderOfpbarProcess =
new G4PhysicsTable*[10] ;
G4int G4PAIenergyLoss::CounterOfpbarProcess = 0 ;
G4PhysicsTable* G4PAIenergyLoss::theDEDXpbarTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theRangepbarTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theInverseRangepbarTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theLabTimepbarTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theProperTimepbarTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::thepbarRangeCoeffATable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::thepbarRangeCoeffBTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::thepbarRangeCoeffCTable = NULL ;
G4PhysicsTable* G4PAIenergyLoss::theDEDXTable = NULL;
// G4PhysicsTable* G4PAIenergyLoss::fPAItransferBank = NULL ;
G4double G4PAIenergyLoss::Mass,
G4PAIenergyLoss::taulow,
G4PAIenergyLoss::tauhigh,
G4PAIenergyLoss::ltaulow,
G4PAIenergyLoss::ltauhigh;
G4double G4PAIenergyLoss::CutInRange = 0;
const G4double G4PAIenergyLoss::LowestKineticEnergy= 1.00*keV ;
const G4double G4PAIenergyLoss::HighestKineticEnergy= 100.*TeV ;
G4int G4PAIenergyLoss::TotBin ;
G4double G4PAIenergyLoss::RTable,G4PAIenergyLoss::LOGRTable;
// constructor and destructor
G4PAIenergyLoss::G4PAIenergyLoss(const G4String& processName)
: G4VContinuousDiscreteProcess (processName),
dToverTini(0.20), // max.relative range loss in one Step = 20%
// LowestKineticEnergy(1.00*keV),
// HighestKineticEnergy(100.*TeV),
MaxExcitationNumber (1.e6),
probLimFluct (0.01),
nmaxDirectFluct (100),
nmaxCont1(4),
nmaxCont2(16),
theElectron ( G4Electron::Electron() ),
theProton ( G4Proton::Proton() ),
theAntiProton ( G4AntiProton::AntiProton() )
{
theLossTable = NULL ;
lastMaterial = NULL ;
// calculate data members TotBin,LOGRTable,RTable first
G4double lrate ;
G4int nbin ;
// binning corresponds to 2.*dToverTini........................
G4double binning = 2.*dToverTini ;
lrate = log(HighestKineticEnergy/LowestKineticEnergy) ;
// nbin = G4int((lrate/log(1.+dToverTini) + lrate/log(1.+2.*dToverTini))/2.);
nbin = G4int((lrate/log(1.+binning) + lrate/log(1.+2.*binning))/2.);
nbin = (nbin+25)/50 ;
TotBin = 50*nbin ;
if(TotBin<50)
TotBin = 50 ;
if(TotBin>500)
TotBin = 500 ;
LOGRTable=lrate/TotBin;
RTable =exp(LOGRTable);
}
G4PAIenergyLoss::~G4PAIenergyLoss()
{
if(theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
}
/////////////////////////////////////////////////////////////////////////
//
//
void G4PAIenergyLoss::BuildDEDXTable(const G4ParticleDefinition& aParticleType)
{
G4bool MakeTable = false ;
G4double newCutInRange = aParticleType.GetLengthCuts();
// Create tables only if there is a new cut value !
// create/fill proton or antiproton tables depending on the charge of the particle
G4double Charge = aParticleType.GetPDGCharge();
if (Charge>0.)
{
theDEDXTable= theDEDXpTable;
}
else
{
theDEDXTable= theDEDXpbarTable;
}
if ((CutInRange != newCutInRange) || (theDEDXTable==NULL))
{
MakeTable = true ;
CutInRange = newCutInRange ;
}
if( MakeTable )
{
// Build energy loss table as a sum of the energy loss due to the
// different processes.
//
// different processes.
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
// create table for the total energy loss
G4int numOfMaterials = theMaterialTable->length();
G4PhysicsTable** RecorderOfProcess;
int CounterOfProcess;
if( Charge >0.)
{
RecorderOfProcess=RecorderOfpProcess;
CounterOfProcess=CounterOfpProcess;
if(CounterOfProcess == NUMBEROFPROCESSES)
{
// create tables
if(theDEDXpTable)
{ theDEDXpTable->clearAndDestroy();
delete theDEDXpTable; }
theDEDXpTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpTable;
}
}
else
{
RecorderOfProcess=RecorderOfpbarProcess;
CounterOfProcess=CounterOfpbarProcess;
if(CounterOfProcess == NUMBEROFPROCESSES)
{
// create tables
if(theDEDXpbarTable)
{ theDEDXpbarTable->clearAndDestroy();
delete theDEDXpbarTable; }
theDEDXpbarTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpbarTable;
}
}
if(CounterOfProcess == NUMBEROFPROCESSES)
{
// fill the tables
// loop for materials
G4double LowEdgeEnergy , Value ;
G4bool isOutRange ;
G4PhysicsTable* pointer ;
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
// loop for the kinetic energy
for (G4int i=0; i<TotBin; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
// here comes the sum of the different tables created by the
// processes (ionisation,etc...)
Value = 0. ;
for (G4int process=0; process < NUMBEROFPROCESSES; process++)
{
pointer= RecorderOfProcess[process];
Value += (*pointer)[J]->
GetValue(LowEdgeEnergy,isOutRange) ;
}
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
// reset counter to zero
if( Charge >0.) CounterOfpProcess=0 ;
else CounterOfpbarProcess=0 ;
// Build range table
BuildRangeTable( aParticleType);
// Build coeff tables for the energy loss calculation
BuildRangeCoeffATable( aParticleType);
BuildRangeCoeffBTable( aParticleType);
BuildRangeCoeffCTable( aParticleType);
}
}
// make the energy loss and the range table available
const G4double lowestKineticEnergy(1.00*keV);
const G4double highestKineticEnergy(100.*TeV);
G4EnergyLossTables::Register(&aParticleType,
(Charge>0)?
theDEDXpTable: theDEDXpbarTable,
(Charge>0)?
theRangepTable: theRangepbarTable,
(Charge>0)?
theInverseRangepTable: theInverseRangepbarTable,
(Charge>0)?
theLabTimepTable: theLabTimepbarTable,
(Charge>0)?
theProperTimepTable: theProperTimepbarTable,
lowestKineticEnergy, highestKineticEnergy,
proton_mass_c2/aParticleType.GetPDGMass(),TotBin);
}
/////////////////////////////////////////////////////////////////////////
//
// Build range table from the energy loss table
void G4PAIenergyLoss::BuildRangeTable( const G4ParticleDefinition& aParticleType)
{
G4double Charge = aParticleType.GetPDGCharge() ;
Mass = proton_mass_c2;
// create table
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4PhysicsTable* theRangeTable;
if( Charge >0.)
{
if(theRangepTable)
{ theRangepTable->clearAndDestroy();
delete theRangepTable; }
theRangepTable = new G4PhysicsTable(numOfMaterials);
theRangeTable = theRangepTable ;
}
else
{
if(theRangepbarTable)
{ theRangepbarTable->clearAndDestroy();
delete theRangepbarTable; }
theRangepbarTable = new G4PhysicsTable(numOfMaterials);
theRangeTable = theRangepbarTable ;
}
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create vector
G4PhysicsLogVector* aVector;
aVector = new G4PhysicsLogVector(LowestKineticEnergy,
HighestKineticEnergy,TotBin);
// fill the vector ( ranges for the actual material)
BuildRangeVector(J, aVector);
// insert vector to the table
theRangeTable->insert(aVector);
}
}
///////////////////////////////////////////////////////////////////
//
// create range vector for a material
//
void G4PAIenergyLoss::BuildRangeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector)
{
static G4int nbin;
const G4double BigRange = DBL_MAX ;
G4int maxbint=100;
G4bool isOut;
G4double tlim=2.*MeV,t1=0.1*MeV,t2=0.025*MeV ;
G4double loss1,loss2,ca,cb,cba ;
G4double taulim,rangelim,ltaulim,ltaumax,
LowEdgeEnergy,tau,Value,tau1,sqtau1 ;
G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
// low energy part first...
loss1 = physicsVector->GetValue(t1,isOut);
loss2 = physicsVector->GetValue(t2,isOut);
tau1 = t1/Mass ;
sqtau1 = sqrt(tau1) ;
ca = (4.*loss2-loss1)/sqtau1 ;
cb = (2.*loss1-4.*loss2)/tau1 ;
cba = cb/ca ;
taulim = tlim/Mass ;
ltaulim = log(taulim) ;
ltaumax = log(HighestKineticEnergy/Mass) ;
// loop for kinetic energy
for (G4int i=0; i<TotBin; i++)
{
LowEdgeEnergy = rangeVector->GetLowEdgeEnergy(i);
tau = LowEdgeEnergy/Mass;
if ( tau <= tau1 )
{
Value = 2.*Mass*log(1.+cba*sqrt(tau))/cb ;
}
else
{
Value = 2.*Mass*log(1.+cba*sqtau1)/cb ;
if(tau<=taulim)
{
nbin = (G4int)(maxbint*(tau-tau1)/(taulim-tau1)) ;
if(nbin<1) nbin = 1;
taulow = tau1 ;
tauhigh = tau ;
Value += RangeIntLin(physicsVector,nbin);
}
else
{
taulow = tau1 ;
tauhigh = taulim ;
Value += RangeIntLin(physicsVector,maxbint) ;
ltaulow = ltaulim ;
ltauhigh = log(tau) ;
nbin = (G4int)(maxbint*(ltauhigh-ltaulow)/(ltaumax-ltaulow)) ;
if(nbin<1) nbin= 1 ;
Value += RangeIntLog(physicsVector,nbin);
}
}
rangeVector->PutValue(i,Value);
}
}
///////////////////////////////////////////////////////////////////
//
// num. integration, linear binning
//
G4double G4PAIenergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
G4int nbin)
{
G4double dtau,Value,taui,ti,lossi,ci;
G4bool isOut;
dtau = (tauhigh-taulow)/nbin;
Value = 0.;
for (G4int i=0; i<=nbin; i++)
{
taui = taulow + dtau*i ;
ti = Mass*taui;
lossi = physicsVector->GetValue(ti,isOut);
if(i==0)
ci=0.5;
else
{
if(i<nbin)
ci=1.;
else
ci=0.5;
}
Value += ci/lossi;
}
Value *= Mass*dtau;
return Value;
}
//////////////////////////////////////////////////////////////////
//
// num. integration, logarithmic binning
//
G4double G4PAIenergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
{
G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
G4bool isOut;
ltt = ltauhigh-ltaulow;
dltau = ltt/nbin;
Value = 0.;
for (G4int i=0; i<=nbin; i++)
{
ui = ltaulow+dltau*i;
taui = exp(ui);
ti = Mass*taui;
lossi = physicsVector->GetValue(ti,isOut);
if(i==0)
ci=0.5;
else
{
if(i<nbin)
ci=1.;
else
ci=0.5;
}
Value += ci*taui/lossi;
}
Value *= Mass*dltau;
return Value;
}
//////////////////////////////////////////////////////////////////////
//
// returns the range of a particle in a given material
//
G4double G4PAIenergyLoss::OldGetRange(const G4DynamicParticle *aParticle,
G4Material *aMaterial)
{
G4int materialIndex;
G4double KineticEnergy,Range;
G4double BigRange = DBL_MAX;
G4bool isOut;
G4double Charge = aParticle->GetDefinition()->GetPDGCharge() ;
G4double Chargesquare = Charge*Charge ;
G4double MassRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass() ;
G4PhysicsTable* theRangeTable;
if(Charge>0.) theRangeTable=theRangepTable ;
else theRangeTable=theRangepbarTable ;
materialIndex = aMaterial->GetIndex();
KineticEnergy = aParticle->GetKineticEnergy()*MassRatio;
if(KineticEnergy<LowestKineticEnergy)
Range = BigRange ;
else
{
if(KineticEnergy>HighestKineticEnergy) Range = BigRange ;
else Range = (*theRangeTable)[materialIndex]->GetValue(KineticEnergy,isOut) ;
}
return Range/Chargesquare ;
}
///////////////////////////////////////////////////////////////////////
//
// Build tables of coefficients for the energy loss calculation
//
void G4PAIenergyLoss::
BuildRangeCoeffATable(const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
// create table for coefficients "A"
G4int numOfMaterials = theMaterialTable->length();
G4double Charge = aParticleType.GetPDGCharge() ;
G4PhysicsTable* theRangeTable;
G4PhysicsTable* theRangeCoeffATable;
if(Charge>0.)
{
if(thepRangeCoeffATable)
{
thepRangeCoeffATable->clearAndDestroy() ;
delete thepRangeCoeffATable ;
}
thepRangeCoeffATable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffATable = thepRangeCoeffATable ;
theRangeTable = theRangepTable ;
}
else
{
if(thepbarRangeCoeffATable)
{
thepbarRangeCoeffATable->clearAndDestroy() ;
delete thepbarRangeCoeffATable ;
}
thepbarRangeCoeffATable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffATable = thepbarRangeCoeffATable ;
theRangeTable = theRangepbarTable ;
}
G4double R2 = RTable*RTable ;
G4double R1 = RTable+1.;
G4double w = R1*(RTable-1.)*(RTable-1.);
G4double w1 = RTable/w , w2 = -RTable*R1/w , w3 = R2/w ;
G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
G4bool isOut;
for (G4int J=0; J<numOfMaterials; J++) // loop for materials
{
// create vector
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector = new G4PhysicsLinearVector(0.,binmax, TotBin);
// loop for kinetic energy
Ti = LowestKineticEnergy ;
G4PhysicsVector* rangeVector= (*theRangeTable)[J];
for ( G4int i=0; i<TotBin; i++)
{
Ri = rangeVector->GetValue(Ti,isOut) ;
if ( i==0 ) Rim = 0. ;
else
{
Tim = Ti/RTable ;
Rim = rangeVector->GetValue(Tim,isOut);
}
if ( i==(TotBin-1)) Rip = Ri ;
else
{
Tip = Ti*RTable ;
Rip = rangeVector->GetValue(Tip,isOut);
}
Value = (w1*Rip + w2*Ri + w3*Rim)/(Ti*Ti) ;
aVector->PutValue(i,Value);
Ti = RTable*Ti ;
}
theRangeCoeffATable->insert(aVector);
}
}
////////////////////////////////////////////////////////////////////////
//
// Build tables of coefficients for the energy loss calculation
//
void G4PAIenergyLoss::
BuildRangeCoeffBTable(const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
// create table for coefficients "B"
G4int numOfMaterials = theMaterialTable->length();
G4double Charge = aParticleType.GetPDGCharge() ;
G4PhysicsTable* theRangeTable;
G4PhysicsTable* theRangeCoeffBTable;
if(Charge>0.)
{
if(thepRangeCoeffBTable)
{
thepRangeCoeffBTable->clearAndDestroy();
delete thepRangeCoeffBTable ;
}
thepRangeCoeffBTable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffBTable = thepRangeCoeffBTable ;
theRangeTable = theRangepTable ;
}
else
{
if(thepbarRangeCoeffBTable)
{
thepbarRangeCoeffBTable->clearAndDestroy();
delete thepbarRangeCoeffBTable;
}
thepbarRangeCoeffBTable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffBTable = thepbarRangeCoeffBTable ;
theRangeTable = theRangepbarTable ;
}
G4double R2 = RTable*RTable ;
G4double R1 = RTable+1.;
G4double w = R1*(RTable-1.)*(RTable-1.);
G4double w1 = -R1/w , w2 = R1*(R2+1.)/w , w3 = -R2*R1/w ;
G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create vector
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector = new G4PhysicsLinearVector(0.,binmax, TotBin);
// loop for kinetic energy
Ti = LowestKineticEnergy ;
G4PhysicsVector* rangeVector= (*theRangeTable)[J];
for ( G4int i=0; i<TotBin; i++)
{
Ri = rangeVector->GetValue(Ti,isOut) ;
if ( i==0 ) Rim = 0. ;
else
{
Tim = Ti/RTable ;
Rim = rangeVector->GetValue(Tim,isOut);
}
if ( i==(TotBin-1)) Rip = Ri ;
else
{
Tip = Ti*RTable ;
Rip = rangeVector->GetValue(Tip,isOut);
}
Value = (w1*Rip + w2*Ri + w3*Rim)/Ti;
aVector->PutValue(i,Value);
Ti = RTable*Ti ;
}
theRangeCoeffBTable->insert(aVector) ;
}
}
///////////////////////////////////////////////////////////////////////////
//
// Build tables of coefficients for the energy loss calculation
//
void G4PAIenergyLoss::BuildRangeCoeffCTable(
const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
// create table for coefficients "C"
G4int numOfMaterials = theMaterialTable->length();
G4double Charge = aParticleType.GetPDGCharge() ;
G4PhysicsTable* theRangeTable;
G4PhysicsTable* theRangeCoeffCTable;
if(Charge>0.)
{
if(thepRangeCoeffCTable)
{ thepRangeCoeffCTable->clearAndDestroy();
delete thepRangeCoeffCTable; }
thepRangeCoeffCTable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffCTable = thepRangeCoeffCTable ;
theRangeTable = theRangepTable ;
}
else
{
if(thepbarRangeCoeffCTable)
{ thepbarRangeCoeffCTable->clearAndDestroy();
delete thepbarRangeCoeffCTable; }
thepbarRangeCoeffCTable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffCTable = thepbarRangeCoeffCTable ;
theRangeTable = theRangepbarTable ;
}
const G4double BigRange = DBL_MAX ;
G4double R2 = RTable*RTable ;
G4double R1 = RTable+1.;
G4double w = R1*(RTable-1.)*(RTable-1.);
G4double w1 = 1./w , w2 = -RTable*R1/w , w3 = RTable*R2/w ;
G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create vector
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector = new G4PhysicsLinearVector(0.,binmax, TotBin);
// loop for kinetic energy
Ti = LowestKineticEnergy ;
G4PhysicsVector* rangeVector= (*theRangeTable)[J];
for ( G4int i=0; i<TotBin; i++)
{
Ri = rangeVector->GetValue(Ti,isOut) ;
if ( i==0 ) Rim = 0. ;
else
{
Tim = Ti/RTable ;
Rim = rangeVector->GetValue(Tim,isOut);
}
if ( i==(TotBin-1)) Rip = Ri ;
else
{
Tip = Ti*RTable ;
Rip = rangeVector->GetValue(Tip,isOut);
}
Value = w1*Rip + w2*Ri + w3*Rim ;
aVector->PutValue(i,Value);
Ti = RTable*Ti ;
}
theRangeCoeffCTable->insert(aVector) ;
}
}
//
//
/////////////////////////////////////////////////////////////////////////
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4PAIonisation.cc,v 1.2.8.1.2.1 1999/12/08 17:34:24 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4PAIonisation.cc,v 1.8 2000/05/02 15:12:45 grichine Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// -------------------------------------------------------------
@@ -52,7 +52,7 @@ G4PAIonisation::fProtonEnergyVector = new G4PhysicsLogVector(LowestKineticEnergy
G4PAIonisation::G4PAIonisation( const G4String& materialName,
const G4String& processName)
: G4PAIenergyLoss(processName),
: G4VPAIenergyLoss(processName),
theElectron ( G4Electron::Electron() )
{
G4int numberOfMat, iMat ;
@@ -85,12 +85,17 @@ G4PAIonisation::G4PAIonisation( const G4String& materialName,
G4PAIonisation::~G4PAIonisation()
{
if (theMeanFreePathTable)
{
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if ( theMeanFreePathTable )
{
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if( fPAItransferBank )
{
fPAItransferBank->clearAndDestroy() ;
delete fPAItransferBank ;
}
}
/////////////////////////////////////////////////////////////////////////
@@ -179,7 +184,7 @@ G4PAIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
lastCutInRange = CutInRange ;
BuildLambdaTable(aParticleType) ;
}
// G4PAIenergyLoss::BuildDEDXTable(aParticleType) ;
// G4VPAIenergyLoss::BuildDEDXTable(aParticleType) ;
}
////////////////////////////////////////////////////////////////////////////
@@ -195,7 +200,7 @@ G4PAIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
G4double Charge = aParticleType.GetPDGCharge() ;
G4double LowEdgeEnergy , ionloss ;
G4double ParticleMass , RateMass ;
G4double RateMass ;
G4bool isOutRange ;
static const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const G4double SmallIonLoss = DBL_MIN ;
@@ -304,7 +309,9 @@ G4PAIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
tau = 0.01 ;
}
gamma = tau +1. ;
G4cout<<"gamma = "<<gamma<<G4endl ;
// G4cout<<"gamma = "<<gamma<<endl ;
bg2 = tau*(tau+2.) ;
beta2 = bg2/(gamma*gamma) ;
Tmax = 2.*electron_mass_c2*bg2
@@ -319,8 +326,8 @@ G4PAIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
ionloss = protonPAI.GetMeanEnergyLoss() ; // total <dE/dx>
G4cout<<"ionloss = "<<ionloss*cm/keV<<" keV/cm"<<G4endl ;
G4cout<<"n1 = "<<protonPAI.GetIntegralPAIxSection(1)*cm<<" 1/cm"<<G4endl ;
// G4cout<<"ionloss = "<<ionloss*cm/keV<<" keV/cm"<<endl ;
// G4cout<<"n1 = "<<protonPAI.GetIntegralPAIxSection(1)*cm<<" 1/cm"<<endl ;
// G4cout<<"protonPAI.GetSplineSize() = "<<
// protonPAI.GetSplineSize()<<G4endl ;
@@ -435,7 +442,7 @@ ComputeMicroscopicCrossSection( const G4ParticleDefinition& aParticleType,
G4double KineticEnergy ,
G4double AtomicNumber )
{
G4double TotalEnergy, ParticleMass, betasquare,
G4double TotalEnergy, betasquare,
MaxKineticEnergyTransfer,
TotalCrossSection, tempvar ;
const G4double SmallCrossSection = DBL_MIN;
@@ -487,7 +494,7 @@ G4PAIonisation::PostStepDoIt( const G4Track& trackData,
{
const G4DynamicParticle* aParticle ;
G4Material* aMaterial;
G4double KineticEnergy, TotalEnergy, ParticleMass, TotalMomentum,
G4double KineticEnergy, TotalEnergy, TotalMomentum,
betasquare, MaxKineticEnergyTransfer, DeltaKineticEnergy,
DeltaTotalMomentum, costheta, sintheta, phi, dirx, diry,
dirz, finalKineticEnergy, finalPx, finalPy, finalPz, x, xc,
@@ -656,10 +663,7 @@ G4VParticleChange* G4PAIonisation::AlongStepDoIt( const G4Track& trackData,
if( Step == 0. || index != fMatIndex ) return &aParticleChange ;
G4cout<<"step = "<<Step/mm<<" mm"<<G4endl ;
// G4cout<<"step = "<<Step/mm<<" mm"<<endl ;
// get particle and material pointers from trackData
@@ -730,7 +734,7 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
G4int index = aMaterial->GetIndex() ;
G4bool isOutRange ;
// G4cout<<"G4PAIenergyLoss::GetLossWithFluct"<<G4endl ;
// G4cout<<"G4VPAIenergyLoss::GetLossWithFluct"<<G4endl ;
G4double loss = 0.0 ;
G4double transfer, position, E1, E2, W1, W2, W, firstMu, secondMu ;
@@ -751,7 +755,7 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
}
G4int iPlace = iTkin - 1 ; // index*(G4PAIonisation::GetBinNumber()) +
G4cout<<"iPlace = "<<iPlace<<G4endl ;
// G4cout<<"iPlace = "<<iPlace<<endl ;
G4PhysicsVector* firstVector = (*fPAItransferBank)(iPlace) ;
G4PhysicsVector* secondVector = (*fPAItransferBank)(iPlace + 1) ;
@@ -760,7 +764,7 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
{
numOfCollisions = RandPoisson::shoot((*(*fPAItransferBank)(iPlace))(0)*Step) ;
G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
@@ -781,7 +785,7 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
numOfCollisions = RandPoisson::
shoot((*(*fPAItransferBank)(iPlace+1))(0)*Step) ;
G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
@@ -812,7 +816,8 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
( (*(*fPAItransferBank)(iPlace))(0)*W1 +
(*(*fPAItransferBank)(iPlace+1))(0)*W2 )*Step) ;
G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<endl ;
while(numOfCollisions)
{
@@ -835,7 +840,8 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
}
}
}
G4cout<<"PAI loss = "<<loss/keV<<" keV"<<G4endl ;
// G4cout<<"PAI loss = "<<loss/keV<<" keV"<<endl ;
return loss ;
}
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4PAIxSection.cc,v 1.3.6.1.2.1 1999/12/08 17:34:24 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4PAIxSection.cc,v 1.4 1999/12/15 14:51:51 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// G4PAIxSection.cc -- class implementation file
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4PhotoElectricEffect.cc,v 1.8.6.1.2.1 1999/12/08 17:34:25 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4PhotoElectricEffect.cc,v 1.9 1999/12/15 14:51:52 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// --------------------------------------------------------------
@@ -27,7 +27,7 @@
// 08-01-97, crossection table + meanfreepath table, M.Maire
// 13-03-97, adapted for the new physics scheme, M.Maire
// 28-03-97, protection in BuildPhysicsTable, M.Maire
// 04-06-98, in DoIt, secondary production condition: range>min(threshold,safety)
// 04-06-98, in DoIt, secondary production condition: range>G4std::min(threshold,safety)
// 13-08-98, new methods SetBining() PrintInfo()
// 17-11-98, use table of Atomic shells in PostStepDoIt
// 06-01-99, use Sandia crossSection below 50 keV, V.Grichine mma
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4PolarizedComptonScattering.cc,v 1.1.10.1 1999/12/07 20:51:01 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4PolarizedComptonScattering.cc,v 1.2 1999/12/15 14:51:52 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4SynchrotronRadiation.cc,v 1.1.10.1 1999/12/07 20:51:01 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4SynchrotronRadiation.cc,v 1.2 1999/12/15 14:51:52 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IeEnergyLoss.cc,v 1.7.6.1 1999/12/07 20:50:58 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4VIeEnergyLoss.cc,v 1.1 2000/04/25 14:33:09 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// -----------------------------------------------------------
@@ -16,7 +16,7 @@
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4IeEnergyLoss physics process -----------
// ---------- G4VIeEnergyLoss physics process -----------
// by Laszlo Urban, 20 March 1997
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
@@ -31,7 +31,7 @@
// 26-10-98: revision, TOF tables L.Urban
// --------------------------------------------------------------
#include "G4IeEnergyLoss.hh"
#include "G4VIeEnergyLoss.hh"
#include "G4EnergyLossTables.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4Poisson.hh"
@@ -46,47 +46,47 @@
// You have to change NbOfProcesses if you invent a new process contributing
// to the continuous energy loss.
// The NbOfProcesses data member can be changed using the (public static)
// functions Get/Set/Plus/MinusNbOfProcesses (see G4IeEnergyLoss.hh)
// functions Get/Set/Plus/MinusNbOfProcesses (see G4VIeEnergyLoss.hh)
G4int G4IeEnergyLoss::NbOfProcesses = 2;
G4int G4VIeEnergyLoss::NbOfProcesses = 2;
G4int G4IeEnergyLoss::CounterOfElectronProcess = 0;
G4int G4IeEnergyLoss::CounterOfPositronProcess = 0;
G4PhysicsTable** G4IeEnergyLoss::RecorderOfElectronProcess =
G4int G4VIeEnergyLoss::CounterOfElectronProcess = 0;
G4int G4VIeEnergyLoss::CounterOfPositronProcess = 0;
G4PhysicsTable** G4VIeEnergyLoss::RecorderOfElectronProcess =
new G4PhysicsTable*[10];
G4PhysicsTable** G4IeEnergyLoss::RecorderOfPositronProcess =
G4PhysicsTable** G4VIeEnergyLoss::RecorderOfPositronProcess =
new G4PhysicsTable*[10];
G4bool G4IeEnergyLoss::rndmStepFlag = false;
G4bool G4IeEnergyLoss::EnlossFlucFlag = true;
G4double G4IeEnergyLoss::dRoverRange = 20*perCent;
G4double G4IeEnergyLoss::finalRange = 200*micrometer;
G4bool G4VIeEnergyLoss::rndmStepFlag = false;
G4bool G4VIeEnergyLoss::EnlossFlucFlag = true;
G4double G4VIeEnergyLoss::dRoverRange = 20*perCent;
G4double G4VIeEnergyLoss::finalRange = 200*micrometer;
G4PhysicsTable* G4IeEnergyLoss::theDEDXElectronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theDEDXPositronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theRangeElectronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theRangePositronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theInverseRangeElectronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theInverseRangePositronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theLabTimeElectronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theLabTimePositronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theProperTimeElectronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theProperTimePositronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theDEDXElectronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theDEDXPositronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theRangeElectronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theRangePositronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theInverseRangeElectronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theInverseRangePositronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theLabTimeElectronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theLabTimePositronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theProperTimeElectronTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theProperTimePositronTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theeRangeCoeffATable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theeRangeCoeffBTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::theeRangeCoeffCTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::thepRangeCoeffATable = NULL;
G4PhysicsTable* G4IeEnergyLoss::thepRangeCoeffBTable = NULL;
G4PhysicsTable* G4IeEnergyLoss::thepRangeCoeffCTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theeRangeCoeffATable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theeRangeCoeffBTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::theeRangeCoeffCTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::thepRangeCoeffATable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::thepRangeCoeffBTable = NULL;
G4PhysicsTable* G4VIeEnergyLoss::thepRangeCoeffCTable = NULL;
G4EnergyLossMessenger* G4IeEnergyLoss::eLossMessenger = NULL;
G4EnergyLossMessenger* G4VIeEnergyLoss::eLossMessenger = NULL;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// constructor and destructor
G4IeEnergyLoss::G4IeEnergyLoss(const G4String& processName)
G4VIeEnergyLoss::G4VIeEnergyLoss(const G4String& processName)
: G4IVContinuousDiscreteProcess (processName),
theLossTable(NULL),
theRangeCoeffATable(NULL),
@@ -107,7 +107,7 @@ G4IeEnergyLoss::G4IeEnergyLoss(const G4String& processName)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4IeEnergyLoss::~G4IeEnergyLoss()
G4VIeEnergyLoss::~G4VIeEnergyLoss()
{
if (theLossTable)
{
@@ -118,7 +118,7 @@ G4IeEnergyLoss::~G4IeEnergyLoss()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildDEDXTable(
void G4VIeEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
{
ParticleMass = aParticleType.GetPDGMass();
@@ -252,7 +252,7 @@ void G4IeEnergyLoss::BuildDEDXTable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildRangeTable(
void G4VIeEnergyLoss::BuildRangeTable(
const G4ParticleDefinition& aParticleType)
{
// Build range table from the energy loss table
@@ -293,7 +293,7 @@ void G4IeEnergyLoss::BuildRangeTable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildTimeTables(
void G4VIeEnergyLoss::BuildTimeTables(
const G4ParticleDefinition& aParticleType)
{
// Build time tables from the energy loss table
@@ -355,7 +355,7 @@ void G4IeEnergyLoss::BuildTimeTables(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildRangeVector(G4int materialIndex,
void G4VIeEnergyLoss::BuildRangeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector)
{
// create range vector for a material
@@ -412,7 +412,7 @@ void G4IeEnergyLoss::BuildRangeVector(G4int materialIndex,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildLabTimeVector(G4int materialIndex,
void G4VIeEnergyLoss::BuildLabTimeVector(G4int materialIndex,
G4PhysicsLogVector* timeVector)
// create lab time vector for a material
{
@@ -469,7 +469,7 @@ void G4IeEnergyLoss::BuildLabTimeVector(G4int materialIndex,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildProperTimeVector(G4int materialIndex,
void G4VIeEnergyLoss::BuildProperTimeVector(G4int materialIndex,
G4PhysicsLogVector* timeVector)
{
// create lab time vector for a material
@@ -526,7 +526,7 @@ void G4IeEnergyLoss::BuildProperTimeVector(G4int materialIndex,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IeEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
G4double G4VIeEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
// num. integration, logarithmic binning
{
@@ -550,7 +550,7 @@ G4double G4IeEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IeEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
G4double G4VIeEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
// num. integration, logarithmic binning
{
@@ -575,7 +575,7 @@ G4double G4IeEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IeEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
G4double G4VIeEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
// num. integration, logarithmic binning
{
@@ -600,7 +600,7 @@ G4double G4IeEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildRangeCoeffATable(
void G4VIeEnergyLoss::BuildRangeCoeffATable(
const G4ParticleDefinition& aParticleType)
{
// Build tables of coefficients for the energy loss calculation
@@ -661,7 +661,7 @@ void G4IeEnergyLoss::BuildRangeCoeffATable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildRangeCoeffBTable(
void G4VIeEnergyLoss::BuildRangeCoeffBTable(
const G4ParticleDefinition& aParticleType)
{
// Build tables of coefficients for the energy loss calculation
@@ -722,7 +722,7 @@ void G4IeEnergyLoss::BuildRangeCoeffBTable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildRangeCoeffCTable(
void G4VIeEnergyLoss::BuildRangeCoeffCTable(
const G4ParticleDefinition& aParticleType)
{
// Build tables of coefficients for the energy loss calculation
@@ -782,7 +782,7 @@ void G4IeEnergyLoss::BuildRangeCoeffCTable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::BuildInverseRangeTable(
void G4VIeEnergyLoss::BuildInverseRangeTable(
const G4ParticleDefinition& aParticleType)
{
// Build inverse table of the range table
@@ -844,7 +844,7 @@ void G4IeEnergyLoss::BuildRangeCoeffCTable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IeEnergyLoss::InvertRangeVector(G4int materialIndex,
void G4VIeEnergyLoss::InvertRangeVector(G4int materialIndex,
G4PhysicsLogVector* aVector)
{
// invert range vector for a material
@@ -888,7 +888,7 @@ void G4IeEnergyLoss::InvertRangeVector(G4int materialIndex,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IeEnergyLoss::GetConstraints(const G4DynamicParticle* aParticle,
G4double G4VIeEnergyLoss::GetConstraints(const G4DynamicParticle* aParticle,
G4Material* aMaterial)
{
// returns the Step limit = range here!
@@ -956,7 +956,7 @@ G4double G4IeEnergyLoss::GetConstraints(const G4DynamicParticle* aParticle,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4IeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
G4VParticleChange* G4VIeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
// compute the energy loss after a Step
@@ -1039,7 +1039,7 @@ G4VParticleChange* G4IeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IeEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4double G4VIeEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
G4double MeanLoss)
// calculate actual loss from the mean loss
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IhEnergyLoss.cc,v 1.7.6.1 1999/12/07 20:50:59 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4VIhEnergyLoss.cc,v 1.1 2000/04/25 14:33:10 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// -----------------------------------------------------------
@@ -16,7 +16,7 @@
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4IhEnergyLoss physics process -----------
// ---------- G4VIhEnergyLoss physics process -----------
// by Laszlo Urban, 30 May 1997
//
// **************************************************************
@@ -28,7 +28,7 @@
// 26/10/98 : cleanup + TOF tables, L.Urban
// --------------------------------------------------------------
#include "G4IhEnergyLoss.hh"
#include "G4VIhEnergyLoss.hh"
#include "G4EnergyLossTables.hh"
#include "G4Poisson.hh"
@@ -40,77 +40,77 @@
// NumberOfProcesses should be 2 in this case,
// or for debugging purposes.
// The NumberOfProcesses data member can be changed using the (public static)
// functions Get/Set/Plus/MinusNumberOfProcesses (see G4IhEnergyLoss.hh)
// functions Get/Set/Plus/MinusNumberOfProcesses (see G4VIhEnergyLoss.hh)
G4int G4IhEnergyLoss::NumberOfProcesses = 1 ;
G4int G4VIhEnergyLoss::NumberOfProcesses = 1 ;
G4int G4IhEnergyLoss::CounterOfProcess = 0 ;
G4PhysicsTable** G4IhEnergyLoss::RecorderOfProcess =
G4int G4VIhEnergyLoss::CounterOfProcess = 0 ;
G4PhysicsTable** G4VIhEnergyLoss::RecorderOfProcess =
new G4PhysicsTable*[10] ;
G4int G4IhEnergyLoss::CounterOfpProcess = 0 ;
G4PhysicsTable** G4IhEnergyLoss::RecorderOfpProcess =
G4int G4VIhEnergyLoss::CounterOfpProcess = 0 ;
G4PhysicsTable** G4VIhEnergyLoss::RecorderOfpProcess =
new G4PhysicsTable*[10] ;
G4int G4IhEnergyLoss::CounterOfpbarProcess = 0 ;
G4PhysicsTable** G4IhEnergyLoss::RecorderOfpbarProcess =
G4int G4VIhEnergyLoss::CounterOfpbarProcess = 0 ;
G4PhysicsTable** G4VIhEnergyLoss::RecorderOfpbarProcess =
new G4PhysicsTable*[10] ;
G4PhysicsTable* G4IhEnergyLoss::theDEDXpTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theDEDXpbarTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theRangepTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theRangepbarTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theInverseRangepTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theInverseRangepbarTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theLabTimepTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theLabTimepbarTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theProperTimepTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theProperTimepbarTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theDEDXpTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theDEDXpbarTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theRangepTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theRangepbarTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theInverseRangepTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theInverseRangepbarTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theLabTimepTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theLabTimepbarTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theProperTimepTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theProperTimepbarTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::thepRangeCoeffATable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::thepRangeCoeffBTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::thepRangeCoeffCTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::thepbarRangeCoeffATable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::thepbarRangeCoeffBTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::thepbarRangeCoeffCTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::thepRangeCoeffATable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::thepRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::thepRangeCoeffCTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::thepbarRangeCoeffATable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::thepbarRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::thepbarRangeCoeffCTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theDEDXTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theRangeTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theInverseRangeTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theLabTimeTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theProperTimeTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theDEDXTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theRangeTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theInverseRangeTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theLabTimeTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theProperTimeTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theRangeCoeffATable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theRangeCoeffBTable = NULL ;
G4PhysicsTable* G4IhEnergyLoss::theRangeCoeffCTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theRangeCoeffATable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VIhEnergyLoss::theRangeCoeffCTable = NULL ;
const G4Proton* G4IhEnergyLoss::theProton =G4Proton::Proton() ;
const G4AntiProton* G4IhEnergyLoss::theAntiProton=G4AntiProton::AntiProton() ;
const G4Proton* G4VIhEnergyLoss::theProton =G4Proton::Proton() ;
const G4AntiProton* G4VIhEnergyLoss::theAntiProton=G4AntiProton::AntiProton() ;
G4double G4IhEnergyLoss::ParticleMass;
G4double G4VIhEnergyLoss::ParticleMass;
G4double G4IhEnergyLoss::Mass,
G4IhEnergyLoss::taulow,
G4IhEnergyLoss::tauhigh,
G4IhEnergyLoss::ltaulow,
G4IhEnergyLoss::ltauhigh;
G4double G4VIhEnergyLoss::Mass,
G4VIhEnergyLoss::taulow,
G4VIhEnergyLoss::tauhigh,
G4VIhEnergyLoss::ltaulow,
G4VIhEnergyLoss::ltauhigh;
G4double G4IhEnergyLoss::CutInRange = 0. ;
G4double G4VIhEnergyLoss::CutInRange = 0. ;
G4double G4IhEnergyLoss::dRoverRange = 0.20 ;
G4double G4IhEnergyLoss::finalRange = 200.*micrometer ;
G4double G4VIhEnergyLoss::dRoverRange = 0.20 ;
G4double G4VIhEnergyLoss::finalRange = 200.*micrometer ;
G4bool G4IhEnergyLoss::rndmStepFlag = false ;
G4bool G4IhEnergyLoss::EnlossFlucFlag = true ;
G4bool G4VIhEnergyLoss::rndmStepFlag = false ;
G4bool G4VIhEnergyLoss::EnlossFlucFlag = true ;
G4double G4IhEnergyLoss::LowestKineticEnergy;
G4double G4IhEnergyLoss::HighestKineticEnergy;
G4int G4IhEnergyLoss::TotBin;
G4double G4IhEnergyLoss::RTable,G4IhEnergyLoss::LOGRTable;
G4double G4VIhEnergyLoss::LowestKineticEnergy;
G4double G4VIhEnergyLoss::HighestKineticEnergy;
G4int G4VIhEnergyLoss::TotBin;
G4double G4VIhEnergyLoss::RTable,G4VIhEnergyLoss::LOGRTable;
// constructor and destructor
G4IhEnergyLoss::G4IhEnergyLoss(const G4String& processName)
G4VIhEnergyLoss::G4VIhEnergyLoss(const G4String& processName)
: G4IVContinuousDiscreteProcess (processName),
theLossTable (NULL),
lastMaterial (NULL),
@@ -121,7 +121,7 @@ G4IhEnergyLoss::G4IhEnergyLoss(const G4String& processName)
nmaxCont2(16)
{ }
G4IhEnergyLoss::~G4IhEnergyLoss()
G4VIhEnergyLoss::~G4VIhEnergyLoss()
{
if(theLossTable) {
theLossTable->clearAndDestroy();
@@ -129,7 +129,7 @@ G4IhEnergyLoss::~G4IhEnergyLoss()
}
}
void G4IhEnergyLoss::BuildDEDXTable(
void G4VIhEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
{
// calculate data members TotBin,LOGRTable,RTable first
@@ -276,7 +276,7 @@ void G4IhEnergyLoss::BuildDEDXTable(
proton_mass_c2/aParticleType.GetPDGMass(),TotBin);
}
void G4IhEnergyLoss::BuildRangeTable(
void G4VIhEnergyLoss::BuildRangeTable(
const G4ParticleDefinition& aParticleType)
// Build range table from the energy loss table
{
@@ -316,7 +316,7 @@ void G4IhEnergyLoss::BuildRangeTable(
}
}
void G4IhEnergyLoss::BuildTimeTables(
void G4VIhEnergyLoss::BuildTimeTables(
const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable=
@@ -372,7 +372,7 @@ void G4IhEnergyLoss::BuildTimeTables(
}
}
void G4IhEnergyLoss::BuildRangeVector(G4int materialIndex,
void G4VIhEnergyLoss::BuildRangeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector)
// create range vector for a material
{
@@ -449,7 +449,7 @@ void G4IhEnergyLoss::BuildRangeVector(G4int materialIndex,
}
}
void G4IhEnergyLoss::BuildLabTimeVector(G4int materialIndex,
void G4VIhEnergyLoss::BuildLabTimeVector(G4int materialIndex,
G4PhysicsLogVector* timeVector)
// create lab time vector for a material
{
@@ -509,7 +509,7 @@ void G4IhEnergyLoss::BuildLabTimeVector(G4int materialIndex,
}
}
void G4IhEnergyLoss::BuildProperTimeVector(G4int materialIndex,
void G4VIhEnergyLoss::BuildProperTimeVector(G4int materialIndex,
G4PhysicsLogVector* timeVector)
// create proper time vector for a material
{
@@ -568,7 +568,7 @@ void G4IhEnergyLoss::BuildProperTimeVector(G4int materialIndex,
}
}
G4double G4IhEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
G4double G4VIhEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
G4int nbin)
// num. integration, linear binning
{
@@ -598,7 +598,7 @@ G4double G4IhEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
}
G4double G4IhEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
G4double G4VIhEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
// num. integration, logarithmic binning
{
@@ -629,7 +629,7 @@ G4double G4IhEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
return Value;
}
G4double G4IhEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
G4double G4VIhEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
// num. integration, logarithmic binning
{
@@ -660,7 +660,7 @@ G4double G4IhEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
return Value;
}
G4double G4IhEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
G4double G4VIhEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
// num. integration, logarithmic binning
{
@@ -691,7 +691,7 @@ G4double G4IhEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
return Value;
}
void G4IhEnergyLoss::BuildRangeCoeffATable(
void G4VIhEnergyLoss::BuildRangeCoeffATable(
const G4ParticleDefinition& aParticleType)
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "A"
@@ -764,7 +764,7 @@ void G4IhEnergyLoss::BuildRangeCoeffATable(
}
void G4IhEnergyLoss::BuildRangeCoeffBTable(
void G4VIhEnergyLoss::BuildRangeCoeffBTable(
const G4ParticleDefinition& aParticleType)
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "B"
@@ -835,7 +835,7 @@ void G4IhEnergyLoss::BuildRangeCoeffBTable(
}
}
void G4IhEnergyLoss::BuildRangeCoeffCTable(
void G4VIhEnergyLoss::BuildRangeCoeffCTable(
const G4ParticleDefinition& aParticleType)
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "C"
@@ -906,7 +906,7 @@ void G4IhEnergyLoss::BuildRangeCoeffCTable(
}
}
void G4IhEnergyLoss::BuildInverseRangeTable(
void G4VIhEnergyLoss::BuildInverseRangeTable(
const G4ParticleDefinition& aParticleType)
// Build inverse table of the range table
{
@@ -960,7 +960,7 @@ void G4IhEnergyLoss::BuildInverseRangeTable(
}
}
void G4IhEnergyLoss::InvertRangeVector(G4int materialIndex,
void G4VIhEnergyLoss::InvertRangeVector(G4int materialIndex,
G4PhysicsLogVector* aVector)
// invert range vector for a material
{
@@ -1008,7 +1008,7 @@ void G4IhEnergyLoss::InvertRangeVector(G4int materialIndex,
}
}
G4double G4IhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
G4double G4VIhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
G4Material *aMaterial)
{
// returns the Step limit = range !
@@ -1051,7 +1051,7 @@ G4double G4IhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
return StepLimit ;
}
G4VParticleChange* G4IhEnergyLoss::AlongStepDoIt(
G4VParticleChange* G4VIhEnergyLoss::AlongStepDoIt(
const G4Track& trackData,const G4Step& stepData)
// compute the energy loss after a step
{
@@ -1169,7 +1169,7 @@ G4VParticleChange* G4IhEnergyLoss::AlongStepDoIt(
}
G4double G4IhEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4double G4VIhEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
G4double MeanLoss)
// calculate actual loss from the mean loss
@@ -0,0 +1,364 @@
// 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: G4VPAIenergyLoss.cc,v 1.1 2000/04/25 14:33:10 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4VPAIenergyLoss physics process -----------
// by V. Grichine, 30 Nov 1997
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of charged hadrons.
// **************************************************************
//
// corrected by V. Grichine on 24/11/97
// corrected by L. Urban on 27/05/98 ( other corrections come soon!)
// 10/02/00 modifications , new e.m. structure, L.Urban
// 02/03/00 initialisation of theDEDXTable
//
#include "G4VPAIenergyLoss.hh"
#include "G4PAIonisation.hh"
#include "G4EnergyLossTables.hh"
////////////////////////////////////////////////////////////////////////////
//
// Initialisation of static members
G4int G4VPAIenergyLoss::NbOfProcesses = 1 ;
G4PhysicsTable** G4VPAIenergyLoss::RecorderOfpProcess =
new G4PhysicsTable*[10] ;
G4int G4VPAIenergyLoss::CounterOfpProcess = 0 ;
G4PhysicsTable* G4VPAIenergyLoss::theDEDXpTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theRangepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theInverseRangepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theLabTimepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theProperTimepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepRangeCoeffATable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepRangeCoeffCTable = NULL ;
G4PhysicsTable** G4VPAIenergyLoss::RecorderOfpbarProcess =
new G4PhysicsTable*[10] ;
G4int G4VPAIenergyLoss::CounterOfpbarProcess = 0 ;
G4PhysicsTable* G4VPAIenergyLoss::theDEDXpbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theRangepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theInverseRangepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theLabTimepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theProperTimepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepbarRangeCoeffATable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepbarRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepbarRangeCoeffCTable = NULL ;
// G4PhysicsTable* G4VPAIenergyLoss::fPAItransferBank = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theDEDXTable = NULL ;
G4double G4VPAIenergyLoss::CutInRange = 0;
G4double G4VPAIenergyLoss::LowerBoundEloss= 1.00*keV ;
G4double G4VPAIenergyLoss::UpperBoundEloss= 100.*TeV ;
G4int G4VPAIenergyLoss::NbinEloss =100 ;
G4double G4VPAIenergyLoss::RTable,G4VPAIenergyLoss::LOGRTable;
// constructor and destructor
G4VPAIenergyLoss::G4VPAIenergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
dToverTini(0.20), // max.relative range loss in one Step = 20%
theElectron ( G4Electron::Electron() ),
theProton ( G4Proton::Proton() ),
theAntiProton ( G4AntiProton::AntiProton() )
{
theLossTable = NULL ;
// calculate data members LOGRTable,RTable first
G4double lrate ;
lrate = log(UpperBoundEloss/LowerBoundEloss) ;
LOGRTable=lrate/NbinEloss;
RTable =exp(LOGRTable);
}
G4VPAIenergyLoss::~G4VPAIenergyLoss()
{
if(theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
}
/////////////////////////////////////////////////////////////////////////
//
//
void G4VPAIenergyLoss::BuildDEDXTable(const G4ParticleDefinition& aParticleType)
{
G4bool MakeTable = false ;
G4double newCutInRange = aParticleType.GetLengthCuts();
// Create tables only if there is a new cut value !
// create/fill proton or antiproton tables depending on the charge of the particle
G4double Charge = aParticleType.GetPDGCharge();
if (Charge>0.)
{
theDEDXTable= theDEDXpTable;
}
else
{
theDEDXTable= theDEDXpbarTable;
}
if ((CutInRange != newCutInRange) || (theDEDXTable==NULL))
{
MakeTable = true ;
CutInRange = newCutInRange ;
}
if( MakeTable )
{
// Build energy loss table as a sum of the energy loss due to the
// different processes.
//
// different processes.
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
// create table for the total energy loss
G4int numOfMaterials = theMaterialTable->length();
G4PhysicsTable** RecorderOfProcess;
int CounterOfProcess;
if( Charge >0.)
{
RecorderOfProcess=RecorderOfpProcess;
CounterOfProcess=CounterOfpProcess;
if(CounterOfProcess == NbOfProcesses)
{
// create tables
if(theDEDXpTable)
{ theDEDXpTable->clearAndDestroy();
delete theDEDXpTable; }
theDEDXpTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpTable;
}
}
else
{
RecorderOfProcess=RecorderOfpbarProcess;
CounterOfProcess=CounterOfpbarProcess;
if(CounterOfProcess == NbOfProcesses)
{
// create tables
if(theDEDXpbarTable)
{ theDEDXpbarTable->clearAndDestroy();
delete theDEDXpbarTable; }
theDEDXpbarTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpbarTable;
}
}
if(CounterOfProcess == NbOfProcesses)
{
// fill the tables
// loop for materials
G4double LowEdgeEnergy , Value ;
G4bool isOutRange ;
G4PhysicsTable* pointer ;
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundEloss, UpperBoundEloss, NbinEloss);
// loop for the kinetic energy
for (G4int i=0; i<NbinEloss; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
// here comes the sum of the different tables created by the
// processes (ionisation,etc...)
Value = 0. ;
for (G4int process=0; process < NbOfProcesses; process++)
{
pointer= RecorderOfProcess[process];
Value += (*pointer)[J]->
GetValue(LowEdgeEnergy,isOutRange) ;
}
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
// reset counter to zero
if( Charge >0.) CounterOfpProcess=0 ;
else CounterOfpbarProcess=0 ;
ParticleMass = aParticleType.GetPDGMass() ;
if(Charge > 0.)
{
// Build range table
theRangepTable = BuildRangeTable(theDEDXpTable,
theRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimepTable = BuildLabTimeTable(theDEDXpTable,
theLabTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepTable = BuildProperTimeTable(theDEDXpTable,
theProperTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepRangeCoeffATable = BuildRangeCoeffATable(theRangepTable,
thepRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffBTable = BuildRangeCoeffBTable(theRangepTable,
thepRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffCTable = BuildRangeCoeffCTable(theRangepTable,
thepRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangepTable = BuildInverseRangeTable(theRangepTable,
thepRangeCoeffATable,
thepRangeCoeffBTable,
thepRangeCoeffCTable,
theInverseRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
else
{
// Build range table
theRangepbarTable = BuildRangeTable(theDEDXpbarTable,
theRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimepbarTable = BuildLabTimeTable(theDEDXpbarTable,
theLabTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepbarTable = BuildProperTimeTable(theDEDXpbarTable,
theProperTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepbarRangeCoeffATable = BuildRangeCoeffATable(theRangepbarTable,
thepbarRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffBTable = BuildRangeCoeffBTable(theRangepbarTable,
thepbarRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffCTable = BuildRangeCoeffCTable(theRangepbarTable,
thepbarRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangepbarTable = BuildInverseRangeTable(theRangepbarTable,
thepbarRangeCoeffATable,
thepbarRangeCoeffBTable,
thepbarRangeCoeffCTable,
theInverseRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
}
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
(Charge>0)?
theDEDXpTable: theDEDXpbarTable,
(Charge>0)?
theRangepTable: theRangepbarTable,
(Charge>0)?
theInverseRangepTable: theInverseRangepbarTable,
(Charge>0)?
theLabTimepTable: theLabTimepbarTable,
(Charge>0)?
theProperTimepTable: theProperTimepbarTable,
LowerBoundEloss, UpperBoundEloss,
proton_mass_c2/aParticleType.GetPDGMass(),NbinEloss);
}
//////////////////////////////////////////////////////////////////////
@@ -0,0 +1,621 @@
// 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: G4VeEnergyLoss.cc,v 1.5 2000/06/13 16:49:57 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4VeEnergyLoss physics process -----------
// by Laszlo Urban, 20 March 1997
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of e+/e-.
// --------------------------------------------------------------
// 18/11/98 , L. Urban
// It is a modified version of G4VeEnergyLoss:
// continuous energy loss with generation of subcutoff delta rays
// 02/02/99 important correction in AlongStepDoIt , L.Urban
// 28/04/99 bug fixed (unit independece now),L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// --------------------------------------------------------------
#include "G4VeEnergyLoss.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4Poisson.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// Initialisation of static data members
// -------------------------------------
G4int G4VeEnergyLoss::NbOfProcesses = 2;
G4int G4VeEnergyLoss::CounterOfElectronProcess = 0;
G4int G4VeEnergyLoss::CounterOfPositronProcess = 0;
G4PhysicsTable** G4VeEnergyLoss::RecorderOfElectronProcess =
new G4PhysicsTable*[10];
G4PhysicsTable** G4VeEnergyLoss::RecorderOfPositronProcess =
new G4PhysicsTable*[10];
G4double G4VeEnergyLoss::MinDeltaCutInRange = 0.100*mm ;
G4double* G4VeEnergyLoss::MinDeltaEnergy = NULL ;
G4bool G4VeEnergyLoss::setMinDeltaCutInRange = false ;
G4PhysicsTable* G4VeEnergyLoss::theDEDXElectronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theDEDXPositronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theRangeElectronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theRangePositronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theInverseRangeElectronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theInverseRangePositronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theLabTimeElectronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theLabTimePositronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theProperTimeElectronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theProperTimePositronTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theeRangeCoeffATable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theeRangeCoeffBTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::theeRangeCoeffCTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::thepRangeCoeffATable = NULL;
G4PhysicsTable* G4VeEnergyLoss::thepRangeCoeffBTable = NULL;
G4PhysicsTable* G4VeEnergyLoss::thepRangeCoeffCTable = NULL;
G4double G4VeEnergyLoss::LowerBoundEloss =0.1*keV ;
G4double G4VeEnergyLoss::UpperBoundEloss = 100.*TeV ;
G4int G4VeEnergyLoss::NbinEloss = 150 ;
G4double G4VeEnergyLoss::RTable,G4VeEnergyLoss::LOGRTable;
G4EnergyLossMessenger* G4VeEnergyLoss::eLossMessenger = NULL;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// constructor and destructor
G4VeEnergyLoss::G4VeEnergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
theLossTable(NULL),
theDEDXTable(NULL),
Charge(-1.),lastCharge(0.),
MinKineticEnergy(1.*eV),
linLossLimit(0.05),
c1N(2.86e-23*MeV*mm*mm),
c2N(c1N*MeV/10.),
Ndeltamax(100)
{
//create (only once) EnergyLoss messenger
if(!eLossMessenger) eLossMessenger = new G4EnergyLossMessenger();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VeEnergyLoss::~G4VeEnergyLoss()
{
if (theLossTable)
{
theLossTable->clearAndDestroy();
delete theLossTable; theLossTable = NULL;
/// if(MinDeltaEnergy) delete MinDeltaEnergy;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VeEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
{
ParticleMass = aParticleType.GetPDGMass();
// calculate data members LOGRTable,RTable first
G4double lrate = log(UpperBoundEloss/LowerBoundEloss);
LOGRTable=lrate/NbinEloss;
RTable =exp(LOGRTable);
// Build energy loss table as a sum of the energy loss due to the
// different processes.
//
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
// create table for the total energy loss
if (&aParticleType==G4Electron::Electron())
{
RecorderOfProcess=RecorderOfElectronProcess;
CounterOfProcess=CounterOfElectronProcess;
if (CounterOfProcess == NbOfProcesses)
{
if (theDEDXElectronTable)
{
theDEDXElectronTable->clearAndDestroy();
delete theDEDXElectronTable;
}
theDEDXElectronTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXElectronTable;
}
}
if (&aParticleType==G4Positron::Positron())
{
RecorderOfProcess=RecorderOfPositronProcess;
CounterOfProcess=CounterOfPositronProcess;
if (CounterOfProcess == NbOfProcesses)
{
if (theDEDXPositronTable)
{
theDEDXPositronTable->clearAndDestroy();
delete theDEDXPositronTable;
}
theDEDXPositronTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXPositronTable;
}
}
if (CounterOfProcess == NbOfProcesses)
{
// fill the tables
// loop for materials
G4double LowEdgeEnergy , Value;
G4bool isOutRange;
G4PhysicsTable* pointer;
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundEloss, UpperBoundEloss, NbinEloss);
// loop for the kinetic energy
for (G4int i=0; i<NbinEloss; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
//here comes the sum of the different tables created by the
//processes (ionisation,bremsstrahlung,etc...)
Value = 0.;
for (G4int process=0; process < NbOfProcesses; process++)
{
pointer= RecorderOfProcess[process];
Value += (*pointer)[J]->GetValue(LowEdgeEnergy,isOutRange);
}
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
//reset counter to zero
if (&aParticleType==G4Electron::Electron()) CounterOfElectronProcess=0;
if (&aParticleType==G4Positron::Positron()) CounterOfPositronProcess=0;
ParticleMass = aParticleType.GetPDGMass();
if (&aParticleType==G4Electron::Electron())
{
// Build range table
theRangeElectronTable = BuildRangeTable(theDEDXElectronTable,
theRangeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimeElectronTable = BuildLabTimeTable(theDEDXElectronTable,
theLabTimeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimeElectronTable = BuildProperTimeTable(theDEDXElectronTable,
theProperTimeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
theeRangeCoeffATable = BuildRangeCoeffATable(theRangeElectronTable,
theeRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theeRangeCoeffBTable = BuildRangeCoeffBTable(theRangeElectronTable,
theeRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theeRangeCoeffCTable = BuildRangeCoeffCTable(theRangeElectronTable,
theeRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangeElectronTable = BuildInverseRangeTable(theRangeElectronTable,
theeRangeCoeffATable,
theeRangeCoeffBTable,
theeRangeCoeffCTable,
theInverseRangeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
if (&aParticleType==G4Positron::Positron())
{
// Build range table
theRangePositronTable = BuildRangeTable(theDEDXPositronTable,
theRangePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimePositronTable = BuildLabTimeTable(theDEDXPositronTable,
theLabTimePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimePositronTable = BuildProperTimeTable(theDEDXPositronTable,
theProperTimePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepRangeCoeffATable = BuildRangeCoeffATable(theRangePositronTable,
thepRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffBTable = BuildRangeCoeffBTable(theRangePositronTable,
thepRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffCTable = BuildRangeCoeffCTable(theRangePositronTable,
thepRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangePositronTable = BuildInverseRangeTable(theRangePositronTable,
thepRangeCoeffATable,
thepRangeCoeffBTable,
thepRangeCoeffCTable,
theInverseRangePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
(&aParticleType==G4Electron::Electron())?
theDEDXElectronTable: theDEDXPositronTable,
(&aParticleType==G4Electron::Electron())?
theRangeElectronTable: theRangePositronTable,
(&aParticleType==G4Electron::Electron())?
theInverseRangeElectronTable: theInverseRangePositronTable,
(&aParticleType==G4Electron::Electron())?
theLabTimeElectronTable: theLabTimePositronTable,
(&aParticleType==G4Electron::Electron())?
theProperTimeElectronTable: theProperTimePositronTable,
LowerBoundEloss, UpperBoundEloss, 1.,NbinEloss);
// create array for the min. delta cuts in kinetic energy
G4double absLowerLimit = 1.*keV ;
// set default MinDeltaCutInRange to rcut/10.
if(!setMinDeltaCutInRange )
MinDeltaCutInRange = G4Electron::Electron()->GetCuts()/10. ;
if(&aParticleType==G4Electron::Electron())
{
G4cout << G4endl;
G4cout.precision(5) ;
G4cout << " eIoni Minimum Delta cut in range=" << MinDeltaCutInRange/mm
<< " mm." << G4endl;
G4cout << G4endl;
G4cout << " material min.delta energy(keV) " << G4endl;
G4cout << G4endl;
}
if(MinDeltaEnergy) delete MinDeltaEnergy ;
MinDeltaEnergy = new G4double [numOfMaterials] ;
for(G4int mat=0; mat<numOfMaterials; mat++)
{
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),MinDeltaCutInRange,
(*theMaterialTable)(mat)) ;
if(MinDeltaEnergy[mat]<absLowerLimit)
MinDeltaEnergy[mat] = absLowerLimit ;
if(MinDeltaEnergy[mat]>G4Electron::Electron()->GetCutsInEnergy()[mat])
MinDeltaEnergy[mat]=G4Electron::Electron()->GetCutsInEnergy()[mat] ;
if(&aParticleType==G4Electron::Electron())
{
G4cout << G4std::setw(20) << (*theMaterialTable)(mat)->GetName()
<< G4std::setw(15) << MinDeltaEnergy[mat]/keV << G4endl;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
// compute the energy loss after a Step
static const G4double faclow = 1.5 ;
static const G4double Tlow = 1.0*keV;
// get particle and material pointers from trackData
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double E = aParticle->GetKineticEnergy() ;
G4Material* aMaterial = trackData.GetMaterial();
G4int index = aMaterial->GetIndex();
G4double Step = stepData.GetStepLength();
aParticleChange.Initialize(trackData);
G4double MeanLoss, finalT;
if (E < MinKineticEnergy) finalT = 0.;
else if (E<faclow*LowerBoundEloss)
{
if (Step >= fRangeNow) finalT = 0.;
else finalT = E*(1.-sqrt(Step/fRangeNow)) ;
}
else if (E>=UpperBoundEloss) finalT = E - Step*fdEdx;
else if (Step >= fRangeNow) finalT = 0.;
else
{
if((Step/fRangeNow < linLossLimit)||(E < Tlow)) finalT = E-Step*fdEdx ;
else
{
if (Charge<0.) finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
(G4Electron::Electron(),fRangeNow-Step,aMaterial);
else finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
(G4Positron::Positron(),fRangeNow-Step,aMaterial);
}
}
if(finalT < MinKineticEnergy) finalT = 0. ;
MeanLoss = E - finalT ;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// start of subcutoff generation
if(subSecFlag)
{
G4double MinDeltaEnergyNow = MinDeltaEnergy[index] ;
G4double TmintoProduceDelta=0.5*(3.-Charge)*MinDeltaEnergyNow ;
if((E > TmintoProduceDelta) && (MeanLoss > MinDeltaEnergyNow)
&& (finalT > MinKineticEnergy))
{
G4double rcut,Tc,T0,presafety,postsafety,safety,
delta,fragment ;
G4double frperstep,x1,y1,z1,dx,dy,dz,dTime,time0,DeltaTime;
G4double epsil= MinKineticEnergy/2. ;
if(Charge < 0.)
{
rcut=G4Electron::Electron()->GetCuts();
Tc=G4Electron::Electron()->GetCutsInEnergy()[index];
// threshold !
if(Tc > 0.5*E) Tc=0.5*E ;
}
else
{
rcut=G4Positron::Positron()->GetCuts();
Tc=G4Positron::Positron()->GetCutsInEnergy()[index];
// threshold !
if(Tc > E) Tc=E ;
}
// generate subcutoff delta rays only if Tc>MinDeltaEnergy!
if(Tc > MinDeltaEnergyNow)
{
presafety = stepData.GetPreStepPoint()->GetSafety() ;
// postsafety = stepData.GetPostStepPoint()->GetSafety() ;
G4Navigator *navigator=
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
postsafety =
navigator->ComputeSafety(stepData.GetPostStepPoint()->GetPosition());
safety=G4std::min(presafety,postsafety);
if(safety<rcut)
{
T0=G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),safety,aMaterial) ;
// absolute lower limit for T0
if(T0<MinDeltaEnergyNow) T0=MinDeltaEnergyNow ;
// ..................................................................
x1=stepData.GetPreStepPoint()->GetPosition().x();
y1=stepData.GetPreStepPoint()->GetPosition().y();
z1=stepData.GetPreStepPoint()->GetPosition().z();
dx=stepData.GetPostStepPoint()->GetPosition().x()-x1 ;
dy=stepData.GetPostStepPoint()->GetPosition().y()-y1 ;
dz=stepData.GetPostStepPoint()->GetPosition().z()-z1 ;
time0=stepData.GetPreStepPoint()->GetGlobalTime();
dTime=stepData.GetPostStepPoint()->GetGlobalTime()-time0;
if((presafety<rcut)&&(postsafety<rcut))
{
fragment = Step ;
frperstep=1. ;
}
else if(presafety<rcut)
{
delta=presafety*Step/(postsafety-presafety) ;
fragment=rcut*(Step+delta)/postsafety-delta ;
frperstep=fragment/Step;
}
else if(postsafety<rcut)
{
delta=postsafety*Step/(presafety-postsafety) ;
fragment=rcut*(Step+delta)/presafety-delta ;
x1 += dx;
y1 += dy;
z1 += dz;
time0 += dTime ;
frperstep=-fragment/Step;
}
if(fragment>0.)
{
// compute nb of delta rays to be generated
G4int N=int(fragment*(c1N*(1.-T0/Tc)+c2N/E)*
(aMaterial->GetTotNbOfElectPerVolume())/T0+0.5) ;
if(N > Ndeltamax)
N = Ndeltamax ;
G4double Px,Py,Pz ;
G4ThreeVector ParticleDirection ;
ParticleDirection=stepData.GetPostStepPoint()->
GetMomentumDirection() ;
Px =ParticleDirection.x() ;
Py =ParticleDirection.y() ;
Pz =ParticleDirection.z() ;
G4int subdelta = 0;
if(N > 0)
{
G4double Tkin,Etot,P,T,p,costheta,sintheta,phi,dirx,diry,dirz,
Pnew,delToverTc,
sumT,delTkin,delLoss,rate,
urandom ;
G4StepPoint *point ;
sumT=0.;
Tkin = E ;
Etot = Tkin+electron_mass_c2 ;
P = sqrt(Tkin*(Etot+electron_mass_c2)) ;
aParticleChange.SetNumberOfSecondaries(N);
do {
subdelta += 1 ;
if((Charge<0.)&&(Tc>0.5*Tkin)) Tc=0.5*Tkin ;
if((Charge>0.)&&(Tc> Tkin)) Tc= Tkin ;
//check if there is enough energy ....
if((Tkin>TmintoProduceDelta)&&(Tc > T0)&&(MeanLoss>0.))
{
delToverTc=1.-T0/Tc ;
T=T0/(1.-delToverTc*G4UniformRand()) ;
if(T > MeanLoss) T=MeanLoss ;
MeanLoss -= T ;
p=sqrt(T*(T+2.*electron_mass_c2)) ;
costheta = T*(Etot+electron_mass_c2)/(P*p) ;
if(costheta<-1.) costheta=-1.;
if(costheta> 1.) costheta= 1.;
phi=twopi*G4UniformRand() ;
sintheta=sqrt(1.-costheta*costheta);
dirx=sintheta*cos(phi);
diry=sintheta*sin(phi);
dirz=costheta;
sumT += T ;
urandom = G4UniformRand() ;
// distribute x,y,z along Pre-Post !
G4double xd,yd,zd ;
xd=x1+frperstep*dx*urandom ;
yd=y1+frperstep*dy*urandom ;
zd=z1+frperstep*dz*urandom ;
G4ThreeVector DeltaPosition(xd,yd,zd) ;
DeltaTime=time0+frperstep*dTime*urandom ;
ParticleDirection=stepData.GetPostStepPoint()->
GetMomentumDirection() ;
G4ThreeVector DeltaDirection(dirx,diry,dirz) ;
DeltaDirection.rotateUz(ParticleDirection);
G4DynamicParticle* theDelta = new G4DynamicParticle ;
theDelta->SetDefinition(G4Electron::Electron());
theDelta->SetKineticEnergy(T);
theDelta->SetMomentumDirection(DeltaDirection.x(),
DeltaDirection.y(),DeltaDirection.z());
// update initial particle,fill ParticleChange
Tkin -= T ;
Px =(P*ParticleDirection.x()-p*DeltaDirection.x()) ;
Py =(P*ParticleDirection.y()-p*DeltaDirection.y()) ;
Pz =(P*ParticleDirection.z()-p*DeltaDirection.z()) ;
Pnew = sqrt(Px*Px+Py*Py+Pz*Pz) ;
Px /= Pnew ;
Py /= Pnew ;
Pz /= Pnew ;
P = Pnew ;
G4ThreeVector ParticleDirectionnew(Px,Py,Pz) ;
ParticleDirection = ParticleDirectionnew;
G4Track* deltaTrack =
new G4Track(theDelta,DeltaTime,DeltaPosition);
deltaTrack->
SetTouchable(stepData.GetPostStepPoint()->GetTouchable()) ;
deltaTrack->SetParentID(trackData.GetTrackID()) ;
aParticleChange.AddSecondary(deltaTrack) ;
}
} while (subdelta<N) ;
// update the particle direction and kinetic energy
if(subdelta > 0)
aParticleChange.SetMomentumChange(Px,Py,Pz) ;
E = Tkin ;
}
}
// ................................................................
}
}
}
}
// end of subcutoff generation
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
finalT = E - MeanLoss ;
if(finalT < MinKineticEnergy) finalT = 0. ;
//now the loss with fluctuation
if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
{
finalT = E-GetLossWithFluct(aParticle,aMaterial,MeanLoss);
if (finalT < 0.) finalT = 0. ;
}
// kill the particle if the kinetic energy <= 0
if (finalT <= 0. )
{
finalT = 0.;
if (Charge < 0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange(finalT);
aParticleChange.SetLocalEnergyDeposit(E-finalT);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,702 @@
// 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: G4VhEnergyLoss.cc,v 1.5 2000/06/13 16:49:58 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4VhEnergyLoss physics process -----------
// by Laszlo Urban, 30 May 1997
//
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of charged hadrons.
// **************************************************************
//
// 7/10/98: bug fixes + some cleanup , L.Urban
// 22/10/98 : cleanup , L.Urban
// 07/12/98 : works for ions as well+ bug corrected, L.Urban
// 02/02/99 : several bugs fixed, L.Urban
// 01/03/99 : creation of sub-cutoff delta rays, L.Urban
// 28/04/99 : bug fixed in DoIt , L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// --------------------------------------------------------------
#include "G4VhEnergyLoss.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4EnergyLossTables.hh"
#include "G4Poisson.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
// Initialisation of static members ******************************************
G4int G4VhEnergyLoss::NbOfProcesses = 1 ;
G4int G4VhEnergyLoss::CounterOfProcess = 0 ;
G4PhysicsTable** G4VhEnergyLoss::RecorderOfProcess =
new G4PhysicsTable*[10] ;
G4int G4VhEnergyLoss::CounterOfpProcess = 0 ;
G4PhysicsTable** G4VhEnergyLoss::RecorderOfpProcess =
new G4PhysicsTable*[10] ;
G4int G4VhEnergyLoss::CounterOfpbarProcess = 0 ;
G4PhysicsTable** G4VhEnergyLoss::RecorderOfpbarProcess =
new G4PhysicsTable*[10] ;
G4PhysicsTable* G4VhEnergyLoss::theDEDXpTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theDEDXpbarTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theRangepTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theRangepbarTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theInverseRangepTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theInverseRangepbarTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theLabTimepTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theLabTimepbarTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theProperTimepTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theProperTimepbarTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::thepRangeCoeffATable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::thepRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::thepRangeCoeffCTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::thepbarRangeCoeffATable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::thepbarRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::thepbarRangeCoeffCTable = NULL ;
G4PhysicsTable* G4VhEnergyLoss::theDEDXTable = NULL ;
const G4Proton* G4VhEnergyLoss::theProton=G4Proton::Proton() ;
const G4AntiProton* G4VhEnergyLoss::theAntiProton=G4AntiProton::AntiProton() ;
G4double G4VhEnergyLoss::ptableElectronCutInRange = 0.0*mm ;
G4double G4VhEnergyLoss::pbartableElectronCutInRange = 0.0*mm ;
G4double G4VhEnergyLoss::MinDeltaCutInRange = 0.1*mm ;
G4double* G4VhEnergyLoss::MinDeltaEnergy = NULL ;
G4bool G4VhEnergyLoss::setMinDeltaCutInRange = false ;
G4double G4VhEnergyLoss::Charge ;
G4double G4VhEnergyLoss::LowerBoundEloss = 1.*keV ;
G4double G4VhEnergyLoss::UpperBoundEloss = 100.*TeV;
G4int G4VhEnergyLoss::NbinEloss = 100 ;
G4double G4VhEnergyLoss::RTable,G4VhEnergyLoss::LOGRTable;
G4double G4VhEnergyLoss::c0N = 9.0e-21*MeV*MeV*mm*mm ;
G4double G4VhEnergyLoss::c1N = 25.0e-21*keV*mm*mm ;
G4double G4VhEnergyLoss::c2N = 13.25e-21*keV*mm*mm ;
G4double G4VhEnergyLoss::c3N = 0.500e-21*mm*mm ;
G4int G4VhEnergyLoss::Ndeltamax = 100 ;
G4EnergyLossMessenger* G4VhEnergyLoss::hLossMessenger = NULL;
// constructor and destructor
G4VhEnergyLoss::G4VhEnergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
theLossTable (NULL),
MinKineticEnergy(1.*eV),
linLossLimit(0.05)
{
//create (only once) EnergyLoss messenger
if(!hLossMessenger) hLossMessenger = new G4EnergyLossMessenger();
}
G4VhEnergyLoss::~G4VhEnergyLoss()
{
if(theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable; theLossTable = NULL;
}
/// if(MinDeltaEnergy) delete MinDeltaEnergy;
}
void G4VhEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
{
// calculate data members LOGRTable,RTable first
G4double lrate = log(UpperBoundEloss/LowerBoundEloss);
LOGRTable=lrate/NbinEloss;
RTable =exp(LOGRTable);
// create table if there is no table or there is a new cut value
G4bool MakeTable = false ;
G4double ElectronCutInRange = G4Electron::Electron()->GetCuts();
// create/fill proton or antiproton tables depending on the charge
Charge = aParticleType.GetPDGCharge()/eplus;
ParticleMass = aParticleType.GetPDGMass() ;
if (Charge>0.) {theDEDXTable= theDEDXpTable;}
else {theDEDXTable= theDEDXpbarTable;}
if(
((Charge>0.) && ((theDEDXTable==NULL) ||
(ElectronCutInRange != ptableElectronCutInRange)))
||
((Charge<0.) && ((theDEDXTable==NULL) ||
(ElectronCutInRange != pbartableElectronCutInRange)))
)
MakeTable = true ;
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if( MakeTable )
{
// Build energy loss table as a sum of the energy loss due to the
// different processes.
if( Charge >0.)
{
RecorderOfProcess=RecorderOfpProcess;
CounterOfProcess=CounterOfpProcess;
if(CounterOfProcess == NbOfProcesses)
{
if(theDEDXpTable)
{ theDEDXpTable->clearAndDestroy();
delete theDEDXpTable; }
theDEDXpTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpTable;
ptableElectronCutInRange = ElectronCutInRange ;
}
}
else
{
RecorderOfProcess=RecorderOfpbarProcess;
CounterOfProcess=CounterOfpbarProcess;
if(CounterOfProcess == NbOfProcesses)
{
if(theDEDXpbarTable)
{ theDEDXpbarTable->clearAndDestroy();
delete theDEDXpbarTable; }
theDEDXpbarTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpbarTable;
pbartableElectronCutInRange = ElectronCutInRange ;
}
}
if(CounterOfProcess == NbOfProcesses)
{
// loop for materials
G4double LowEdgeEnergy , Value ;
G4bool isOutRange ;
G4PhysicsTable* pointer ;
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundEloss, UpperBoundEloss, NbinEloss);
// loop for the kinetic energy
for (G4int i=0; i<NbinEloss; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
Value = 0. ;
// loop for the contributing processes
for (G4int process=0; process < NbOfProcesses; process++)
{
pointer= RecorderOfProcess[process];
Value += (*pointer)[J]->
GetValue(LowEdgeEnergy,isOutRange) ;
}
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
// reset counter to zero ..................
if( Charge >0.)
CounterOfpProcess=0 ;
else
CounterOfpbarProcess=0 ;
ParticleMass = aParticleType.GetPDGMass() ;
if(Charge > 0.)
{
// Build range table
theRangepTable = BuildRangeTable(theDEDXpTable,
theRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimepTable = BuildLabTimeTable(theDEDXpTable,
theLabTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepTable = BuildProperTimeTable(theDEDXpTable,
theProperTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepRangeCoeffATable = BuildRangeCoeffATable(theRangepTable,
thepRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffBTable = BuildRangeCoeffBTable(theRangepTable,
thepRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffCTable = BuildRangeCoeffCTable(theRangepTable,
thepRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangepTable = BuildInverseRangeTable(theRangepTable,
thepRangeCoeffATable,
thepRangeCoeffBTable,
thepRangeCoeffCTable,
theInverseRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
else
{
// Build range table
theRangepbarTable = BuildRangeTable(theDEDXpbarTable,
theRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimepbarTable = BuildLabTimeTable(theDEDXpbarTable,
theLabTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepbarTable = BuildProperTimeTable(theDEDXpbarTable,
theProperTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepbarRangeCoeffATable = BuildRangeCoeffATable(theRangepbarTable,
thepbarRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffBTable = BuildRangeCoeffBTable(theRangepbarTable,
thepbarRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffCTable = BuildRangeCoeffCTable(theRangepbarTable,
thepbarRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangepbarTable = BuildInverseRangeTable(theRangepbarTable,
thepbarRangeCoeffATable,
thepbarRangeCoeffBTable,
thepbarRangeCoeffCTable,
theInverseRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
}
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
(Charge>0)?
theDEDXpTable: theDEDXpbarTable,
(Charge>0)?
theRangepTable: theRangepbarTable,
(Charge>0)?
theInverseRangepTable: theInverseRangepbarTable,
(Charge>0)?
theLabTimepTable: theLabTimepbarTable,
(Charge>0)?
theProperTimepTable: theProperTimepbarTable,
LowerBoundEloss, UpperBoundEloss,
proton_mass_c2/aParticleType.GetPDGMass(),NbinEloss);
// create array for the min. delta cuts in kinetic energy
if(!setMinDeltaCutInRange)
MinDeltaCutInRange = G4Electron::Electron()->GetCuts()/10.;
if(aParticleType.GetParticleName()=="proton")
{
G4cout << G4endl;
G4cout.precision(5) ;
G4cout << " hIoni Minimum Delta cut in range=" << MinDeltaCutInRange/mm
<< " mm." << G4endl;
G4cout << G4endl;
G4cout << " material min.delta energy(keV) " << G4endl;
G4cout << G4endl;
}
if(MinDeltaEnergy) delete MinDeltaEnergy ;
MinDeltaEnergy = new G4double [numOfMaterials] ;
G4double Tlowerlimit = 1.*keV ;
for(G4int mat=0; mat<numOfMaterials; mat++)
{
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),MinDeltaCutInRange,
(*theMaterialTable)(mat)) ;
if(MinDeltaEnergy[mat]<Tlowerlimit) MinDeltaEnergy[mat]=Tlowerlimit ;
if(MinDeltaEnergy[mat]>G4Electron::Electron()->GetCutsInEnergy()[mat])
MinDeltaEnergy[mat]=G4Electron::Electron()->GetCutsInEnergy()[mat] ;
if(aParticleType.GetParticleName()=="proton")
G4cout << G4std::setw(20) << (*theMaterialTable)(mat)->GetName()
<< G4std::setw(15) << MinDeltaEnergy[mat]/keV << G4endl;
}
}
G4double G4VhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
G4Material *aMaterial)
{
// returns the Step limit
// dRoverRange is the max. allowed relative range loss in one step
// it calculates dEdx and the range as well....
G4double KineticEnergy,StepLimit;
G4bool isOut ;
Charge = aParticle->GetDefinition()->GetPDGCharge()/eplus ;
KineticEnergy = aParticle->GetKineticEnergy();
G4double massratio=proton_mass_c2/
aParticle->GetDefinition()->GetPDGMass() ;
G4double Tscaled= KineticEnergy*massratio ;
G4double ChargeSquare = Charge*Charge ;
if(Charge>0.)
{
fRangeNow = G4EnergyLossTables::GetRange( theProton,
Tscaled,aMaterial) ;
fdEdx = G4EnergyLossTables::GetDEDX( theProton,
Tscaled,aMaterial) ;
}
else
{
fRangeNow = G4EnergyLossTables::GetRange( theAntiProton,
Tscaled,aMaterial) ;
fdEdx = G4EnergyLossTables::GetDEDX( theAntiProton,
Tscaled,aMaterial) ;
}
fdEdx *= ChargeSquare ;
fRangeNow /= (ChargeSquare*massratio) ;
// compute the (random) Step limit ..............
if(fRangeNow > finalRange)
{
StepLimit = (c1lim*fRangeNow+c2lim+c3lim/fRangeNow) ;
// randomise this value
if(rndmStepFlag) StepLimit =
finalRange+(StepLimit-finalRange)*G4UniformRand() ;
if(StepLimit > fRangeNow) StepLimit = fRangeNow ;
}
else StepLimit = fRangeNow ;
return StepLimit ;
}
G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
const G4Track& trackData,const G4Step& stepData)
// compute the energy loss after a step
{
const G4DynamicParticle* aParticle;
G4Material* aMaterial;
G4double E,finalT,Step,ChargeSquare,MeanLoss ;
aParticleChange.Initialize(trackData) ;
aMaterial = trackData.GetMaterial() ;
// get the actual (true) Step length from stepData
Step = stepData.GetStepLength() ;
aParticle = trackData.GetDynamicParticle() ;
ChargeSquare = Charge*Charge ;
G4int index = aMaterial->GetIndex() ;
E = aParticle->GetKineticEnergy() ;
if(E < MinKineticEnergy) MeanLoss = E ;
else
{
if(Step >= fRangeNow ) MeanLoss = E ;
else if(( E > UpperBoundEloss)||( E <= LowerBoundEloss))
MeanLoss = Step*fdEdx ;
else
{
if(Step>linLossLimit*fRangeNow)
{
G4double massratio=proton_mass_c2/
aParticle->GetDefinition()->GetPDGMass() ;
G4double rscaled= fRangeNow*massratio*ChargeSquare ;
G4double sscaled= Step *massratio*ChargeSquare ;
if(Charge>0.)
{
MeanLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(
theProton,
rscaled ,aMaterial) -
G4EnergyLossTables::GetPreciseEnergyFromRange(
theProton,
rscaled-sscaled,aMaterial) ;
}
else
{
MeanLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(
theAntiProton,
rscaled ,aMaterial) -
G4EnergyLossTables::GetPreciseEnergyFromRange(
theAntiProton,
rscaled-sscaled,aMaterial) ;
}
MeanLoss /= (massratio*ChargeSquare) ;
}
else MeanLoss = Step*fdEdx ;
}
}
finalT = E - MeanLoss ;
// subcutoff delta ray production start
if(subSecFlag)
{
G4double MinDeltaEnergyNow,Tc,TmintoProduceDelta,w,ww ;
G4double rcut,T0,presafety,postsafety,safety,
delta,fragment,Tmax,mass ;
G4double frperstep,x1,y1,z1,dx,dy,dz,dTime,time0,DeltaTime;
G4double epsil = MinKineticEnergy/2. ;
MinDeltaEnergyNow = MinDeltaEnergy[index] ;
Tc=G4Electron::Electron()->GetCutsInEnergy()[index];
const G4ParticleDefinition* aParticleType=aParticle->GetDefinition() ;
mass=aParticleType->GetPDGMass() ;
w=mass+electron_mass_c2 ;
ww=2.*mass-MinDeltaEnergyNow ;
TmintoProduceDelta=0.5*(sqrt(ww*ww+2.*w*w*MinDeltaEnergyNow/
electron_mass_c2)-ww) ;
if((E > TmintoProduceDelta) && (MeanLoss > MinDeltaEnergyNow)
&& (finalT > MinKineticEnergy))
{
// max. possible delta energy
Tmax = 2.*electron_mass_c2*E*(E+2.*mass)/
(mass*mass+2.*electron_mass_c2*(E+mass)+
electron_mass_c2*electron_mass_c2) ;
rcut=G4Electron::Electron()->GetCuts();
if(Tc > Tmax) Tc=Tmax ;
// generate subcutoff delta rays only if Tc>MinDeltaEnergyNow!
if((Tc > MinDeltaEnergyNow) && (Tmax > MinDeltaEnergyNow))
{
presafety = stepData.GetPreStepPoint()->GetSafety() ;
// postsafety = stepData.GetPostStepPoint()->GetSafety() ;
G4Navigator *navigator=
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
postsafety =
navigator->ComputeSafety(stepData.GetPostStepPoint()->GetPosition());
safety = G4std::min(presafety,postsafety) ;
if(safety < rcut)
{
x1=stepData.GetPreStepPoint()->GetPosition().x();
y1=stepData.GetPreStepPoint()->GetPosition().y();
z1=stepData.GetPreStepPoint()->GetPosition().z();
dx=stepData.GetPostStepPoint()->GetPosition().x()-x1 ;
dy=stepData.GetPostStepPoint()->GetPosition().y()-y1 ;
dz=stepData.GetPostStepPoint()->GetPosition().z()-z1 ;
time0=stepData.GetPreStepPoint()->GetGlobalTime();
dTime=stepData.GetPostStepPoint()->GetGlobalTime()-time0;
if((presafety<rcut)&&(postsafety<rcut))
{
fragment = Step ;
frperstep=1. ;
}
else if(presafety<rcut)
{
delta=presafety*Step/(postsafety-presafety) ;
fragment=rcut*(Step+delta)/postsafety-delta ;
frperstep=fragment/Step;
}
else if(postsafety<rcut)
{
delta=postsafety*Step/(presafety-postsafety) ;
fragment=rcut*(Step+delta)/presafety-delta ;
x1 += dx;
y1 += dy;
z1 += dz;
time0 += dTime ;
frperstep=-fragment/Step;
}
if(fragment>0.)
{
T0=G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),
G4std::min(presafety,postsafety),
aMaterial) ;
// absolute lower limit for T0
if(T0<MinDeltaEnergyNow) T0=MinDeltaEnergyNow ;
// compute nb of delta rays to be generated
G4int N=int(fragment*(c0N/(E*T0)+c1N/T0-(c2N+c3N*T0)/Tc)*
(aMaterial->GetTotNbOfElectPerVolume())+0.5) ;
G4double Px,Py,Pz ;
G4ThreeVector ParticleDirection ;
ParticleDirection=stepData.GetPostStepPoint()->
GetMomentumDirection() ;
Px =ParticleDirection.x() ;
Py =ParticleDirection.y() ;
Pz =ParticleDirection.z() ;
G4int subdelta = 0;
if(N > 0)
{
G4double Tkin,Etot,P,T,p,costheta,sintheta,phi,dirx,diry,dirz,
Pnew,delToverTc,
delTkin,delLoss,rate,
urandom ;
G4StepPoint *point ;
Tkin = E ;
Etot = Tkin+mass ;
P = sqrt(Tkin*(Etot+mass)) ;
aParticleChange.SetNumberOfSecondaries(N);
do {
subdelta += 1 ;
Tmax = 2.*electron_mass_c2*Tkin*(Tkin+2.*mass)/
(mass*mass+2.*electron_mass_c2*(Tkin+mass)+
electron_mass_c2*electron_mass_c2) ;
if(Tc>Tmax) Tc = Tmax ;
//check if there is enough energy ....
if((Tkin>TmintoProduceDelta)&&(Tc > T0)&&(MeanLoss>0.))
{
delToverTc=1.-T0/Tc ;
T=T0/(1.-delToverTc*G4UniformRand()) ;
if(T > MeanLoss) T=MeanLoss ;
MeanLoss -= T ;
p=sqrt(T*(T+2.*electron_mass_c2)) ;
costheta = T*(Etot+electron_mass_c2)/(P*p) ;
if(costheta<-1.) costheta=-1.;
if(costheta> 1.) costheta= 1.;
phi=twopi*G4UniformRand() ;
sintheta=sqrt(1.-costheta*costheta);
dirx=sintheta*cos(phi);
diry=sintheta*sin(phi);
dirz=costheta;
urandom = G4UniformRand() ;
// distribute x,y,z along Pre-Post !
G4double xd,yd,zd ;
xd=x1+frperstep*dx*urandom ;
yd=y1+frperstep*dy*urandom ;
zd=z1+frperstep*dz*urandom ;
G4ThreeVector DeltaPosition(xd,yd,zd) ;
DeltaTime=time0+frperstep*dTime*urandom ;
G4ThreeVector DeltaDirection(dirx,diry,dirz) ;
DeltaDirection.rotateUz(ParticleDirection);
G4DynamicParticle* theDelta = new G4DynamicParticle ;
theDelta->SetDefinition(G4Electron::Electron());
theDelta->SetKineticEnergy(T);
theDelta->SetMomentumDirection(DeltaDirection.x(),
DeltaDirection.y(),DeltaDirection.z());
// update initial particle,fill ParticleChange
Tkin -= T ;
Px =(P*ParticleDirection.x()-p*DeltaDirection.x()) ;
Py =(P*ParticleDirection.y()-p*DeltaDirection.y()) ;
Pz =(P*ParticleDirection.z()-p*DeltaDirection.z()) ;
Pnew = sqrt(Px*Px+Py*Py+Pz*Pz) ;
Px /= Pnew ;
Py /= Pnew ;
Pz /= Pnew ;
P = Pnew ;
G4ThreeVector ParticleDirectionnew(Px,Py,Pz) ;
ParticleDirection = ParticleDirectionnew;
G4Track* deltaTrack =
new G4Track(theDelta,DeltaTime,DeltaPosition);
deltaTrack->
SetTouchable(stepData.GetPostStepPoint()->GetTouchable()) ;
deltaTrack->SetParentID(trackData.GetTrackID()) ;
aParticleChange.AddSecondary(deltaTrack) ;
}
} while (subdelta<N) ;
// update the particle direction and kinetic energy
if(subdelta > 0)
aParticleChange.SetMomentumChange(Px,Py,Pz) ;
E = Tkin ;
}
}
}
}
}
}
// end of subcutoff business
finalT = E - MeanLoss ;
if(finalT < MinKineticEnergy) finalT = 0. ;
// now the loss with fluctuation
if((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
{
MeanLoss /= ChargeSquare ;
finalT = E-GetLossWithFluct(aParticle,aMaterial,MeanLoss)*ChargeSquare ;
if (finalT < 0.) finalT = 0. ;
}
// kill the particle if the kinetic energy <= 0
if (finalT <= 0. )
{
finalT = 0.;
if(aParticle->GetDefinition()->GetParticleName() == "proton")
aParticleChange.SetStatusChange(fStopAndKill);
else
aParticleChange.SetStatusChange(fStopButAlive);
}
// aParticleChange.SetNumberOfSecondaries(0);
aParticleChange.SetEnergyChange( finalT ) ;
aParticleChange.SetLocalEnergyDeposit(E-finalT) ;
return &aParticleChange ;
}
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4eBremsstrahlung.cc,v 1.6.8.1.2.2 1999/12/10 15:41:59 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4eBremsstrahlung.cc,v 1.11 2000/05/23 15:44:29 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// --------------------------------------------------------------
@@ -29,6 +29,7 @@
// 07-04-98 : remove 'tracking cut' of the diffracted particle, MMa
// 13-08-98 : new methods SetBining() PrintInfo()
// 03-03-99 : Bug fixed in LPM effect, L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// --------------------------------------------------------------
#include "G4eBremsstrahlung.hh"
@@ -36,17 +37,19 @@
#include "G4ios.hh"
#include "G4UnitsTable.hh"
G4double G4eBremsstrahlung::LowerBoundLambda = 1.*keV ;
G4double G4eBremsstrahlung::UpperBoundLambda = 100.*TeV ;
G4int G4eBremsstrahlung::NbinLambda = 100 ;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// constructor
G4eBremsstrahlung::G4eBremsstrahlung(const G4String& processName)
: G4eEnergyLoss(processName), // initialization
theMeanFreePathTable(NULL),
LowestKineticEnergy (1.*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100)
{ }
: G4VeEnergyLoss(processName), // initialization
theMeanFreePathTable(NULL)
{MinThreshold = 10*keV; }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -66,16 +69,13 @@ G4eBremsstrahlung::~G4eBremsstrahlung()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::SetPhysicsTableBining(G4double lowE, G4double highE, G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE; TotBin = nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss() ;
HighestKineticEnergy = GetUpperBoundEloss() ;
TotBin = GetNbinEloss() ;
BuildLossTable(aParticleType) ;
@@ -108,7 +108,6 @@ void G4eBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aParticleType
losslim,loss,rate,natom,Cut;
const G4double MinKinEnergy = 1.*keV;
const G4double MinCut = 1.*keV;
const G4double Thigh = 100.*GeV;
const G4double Cuthigh = 50.*GeV;
const G4double Factorhigh = 36./(1450.*GeV);
@@ -151,15 +150,13 @@ void G4eBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aParticleType
TotalEnergy = KineticEnergy+ParticleMass ;
Cut = GammaCutInKineticEnergy[J] ;
if (Cut < MinCut) Cut = MinCut ;
if (Cut > KineticEnergy) Cut = KineticEnergy ;
if (Cut < MinThreshold) Cut = MinThreshold;
if (Cut > KineticEnergy) Cut = KineticEnergy;
bremloss = 0.;
if (KineticEnergy>MinKinEnergy)
{
if (Cut > KineticEnergy) Cut = KineticEnergy ;
// loop for elements in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
@@ -418,7 +415,7 @@ void G4eBremsstrahlung::BuildLambdaTable(const G4ParticleDefinition& ParticleTyp
// tables are Build for MATERIALS.
{
G4double LowEdgeEnergy , Value;
G4double FixedEnergy = (LowestKineticEnergy + HighestKineticEnergy)/2.;
G4double FixedEnergy = (LowerBoundLambda + UpperBoundLambda)/2.;
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
@@ -433,12 +430,12 @@ void G4eBremsstrahlung::BuildLambdaTable(const G4ParticleDefinition& ParticleTyp
for ( G4int J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestKineticEnergy, HighestKineticEnergy,
TotBin ) ;
ptrVector = new G4PhysicsLogVector(LowerBoundLambda, UpperBoundLambda,
NbinLambda ) ;
const G4Material* material= (*theMaterialTable)[J];
for ( G4int i = 0 ; i < TotBin ; i++ )
for ( G4int i = 0 ; i < NbinLambda ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeMeanFreePath( &ParticleType, LowEdgeEnergy,
@@ -456,31 +453,27 @@ void G4eBremsstrahlung::BuildLambdaTable(const G4ParticleDefinition& ParticleTyp
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::ComputePartialSumSigma(const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
// Build the table of cross section per element. The table is built for MATERIALS.
// This table is used by DoIt to select randomly an element in the material.
G4double G4eBremsstrahlung::ComputeMeanFreePath(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
{
G4int Imate = aMaterial->GetIndex();
G4int NbOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[Imate];
const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
if (GammaEnergyCut < MinThreshold) GammaEnergyCut = MinThreshold;
G4double SIGMA = 0 ;
PartialSumSigma(Imate) = new G4ValVector(NbOfElements);
G4double SIGMA = 0. ;
for ( G4int Ielem=0 ; Ielem < NbOfElements ; Ielem++ )
for ( G4int i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
SIGMA += theAtomNumDensityVector[Ielem] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(Ielem)->GetZ(),
GammaEnergyCut );
PartialSumSigma(Imate)->insertAt(Ielem, SIGMA);
}
SIGMA += theAtomNumDensityVector[i] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(i)->GetZ(),
GammaEnergyCut );
}
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -677,6 +670,35 @@ G4double G4eBremsstrahlung::ComputePositronCorrFactorSigma( G4double AtomicNumbe
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::ComputePartialSumSigma(const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
// Build the table of cross section per element. The table is built for MATERIALS.
// This table is used by DoIt to select randomly an element in the material.
{
G4int Imate = aMaterial->GetIndex();
G4int NbOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[Imate];
PartialSumSigma(Imate) = new G4ValVector(NbOfElements);
G4double SIGMA = 0. ;
for ( G4int Ielem=0 ; Ielem < NbOfElements ; Ielem++ )
{
SIGMA += theAtomNumDensityVector[Ielem] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(Ielem)->GetZ(),
GammaEnergyCut );
PartialSumSigma(Imate)->insertAt(Ielem, SIGMA);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4eBremsstrahlung::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData)
//
@@ -734,7 +756,8 @@ G4VParticleChange* G4eBremsstrahlung::PostStepDoIt(const G4Track& trackData,
// Gamma production cut in this material
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
if (GammaEnergyCut < MinThreshold) GammaEnergyCut = MinThreshold;
// check against insufficient energy
if (KineticEnergy < GammaEnergyCut)
{
@@ -933,14 +956,14 @@ G4Element* G4eBremsstrahlung::SelectRandomAtom(G4Material* aMaterial) const
void G4eBremsstrahlung::PrintInfoDefinition()
{
G4String comments = "Total cross sections from a parametrisation. ";
comments += "Good description from 1 KeV to 100 GeV.\n";
comments += "Good description from 10 KeV to 100 GeV.\n";
comments += " log scale extrapolation above 100 GeV \n";
comments += " Gamma energy sampled from a parametrised formula.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
<< "\n PhysicsTables from " << G4BestUnit(LowerBoundLambda,"Energy")
<< " to " << G4BestUnit(UpperBoundLambda,"Energy")
<< " in " << NbinLambda << " bins. \n";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1,947 +0,0 @@
// 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: G4eBremsstrahlungPlus.cc,v 1.6.8.1.2.2 1999/12/10 15:41:59 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4eBremsstrahlungPlus physics process --------
// by Michel Maire, 24 July 1996
// **************************************************************
// 26-09-96 : extension of the total crosssection above 100 GeV, M.Maire
// 1-10-96 : new type G4OrderedTable; ComputePartialSumSigma(), M.Maire
// 16-10-96 : DoIt() call to the non static GetEnergyCuts(), L.Urban
// 13-12-96 : Sign corrected in grejmax and greject
// error definition of screenvar, L.Urban
// 20-03-97 : new energy loss+ionisation+brems scheme, L.Urban
// 07-04-98 : remove 'tracking cut' of the diffracted particle, MMa
// 13-08-98 : new methods SetBining() PrintInfo()
// 03-03-99 : Bug fixed in LPM effect, L.Urban
// --------------------------------------------------------------
#include "G4eBremsstrahlungPlus.hh"
#include "G4EnergyLossTables.hh"
#include "G4ios.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// constructor
G4eBremsstrahlungPlus::G4eBremsstrahlungPlus(const G4String& processName)
: G4eEnergyLossPlus(processName), // initialization
theMeanFreePathTable(NULL),
LowestKineticEnergy (1.*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// destructor
G4eBremsstrahlungPlus::~G4eBremsstrahlungPlus()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if (&PartialSumSigma) {
PartialSumSigma.clearAndDestroy();
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungPlus::SetPhysicsTableBining(G4double lowE, G4double highE, G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE; TotBin = nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungPlus::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
BuildLossTable(aParticleType) ;
if (&aParticleType==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable ;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable ;
CounterOfPositronProcess++;
}
BuildLambdaTable(aParticleType) ;
BuildDEDXTable (aParticleType) ;
if(&aParticleType==G4Electron::Electron())
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungPlus::BuildLossTable(const G4ParticleDefinition& aParticleType)
// Build table for energy loss due to soft brems
// tables are built for *MATERIALS*
{
G4double KineticEnergy,TotalEnergy,bremloss,Z,x,
losslim,loss,rate,natom,Cut;
const G4double MinKinEnergy = 1.*keV;
const G4double MinCut = 1.*keV;
const G4double Thigh = 100.*GeV;
const G4double Cuthigh = 50.*GeV;
const G4double Factorhigh = 36./(1450.*GeV);
const G4double coef1 = -0.5, coef2 = 2./9.;
ParticleMass = aParticleType.GetPDGMass() ;
G4double* GammaCutInKineticEnergy = G4Gamma::Gamma()->GetEnergyCuts();
// create table
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length() ;
if (theLossTable) { theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4Material* material = (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
const G4int NumberOfElements = material->GetNumberOfElements();
// loop for the kinetic energy values
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
TotalEnergy = KineticEnergy+ParticleMass ;
Cut = GammaCutInKineticEnergy[J] ;
if (Cut < MinCut) Cut = MinCut ;
if (Cut > KineticEnergy) Cut = KineticEnergy ;
bremloss = 0.;
if (KineticEnergy>MinKinEnergy)
{
if (Cut > KineticEnergy) Cut = KineticEnergy ;
// loop for elements in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
Z=(*theElementVector)(iel)->GetZ();
natom = theAtomicNumDensityVector[iel] ;
if (KineticEnergy <= Thigh)
{
//loss for MinKinEnergy<KineticEnergy<=100 GeV
x=log(TotalEnergy/ParticleMass);
loss = ComputeBremLoss(Z,natom,KineticEnergy,Cut,x) ;
if (&aParticleType==G4Positron::Positron())
loss *= ComputePositronCorrFactorLoss(Z,KineticEnergy,Cut) ;
}
else
{
// extrapolation for KineticEnergy>100 GeV
x=log(Thigh/ParticleMass) ;
if (Cut<Thigh)
{
losslim = ComputeBremLoss(Z,natom,Thigh,Cut,x) ;
if (&aParticleType==G4Positron::Positron())
loss *= ComputePositronCorrFactorLoss(Z,Thigh,Cut) ;
rate = Cut/TotalEnergy ;
loss = losslim*(1.+coef1*rate+coef2*rate*rate) ;
rate = Cut/Thigh ;
loss /= (1.+coef1*rate+coef2*rate*rate) ;
}
else
{
losslim = ComputeBremLoss(Z,natom,Thigh,Cuthigh,x) ;
if (&aParticleType==G4Positron::Positron())
loss *= ComputePositronCorrFactorLoss(Z,Thigh,Cuthigh) ;
rate = Cut/TotalEnergy ;
loss = losslim*(1.+coef1*rate+coef2*rate*rate) ;
loss *= Factorhigh*Cut ;
}
}
bremloss += natom*loss;
}
}
// now compute the correction due to the LPM effect
const G4double MigdalConstant = classic_electr_radius*
electron_Compton_length*
electron_Compton_length/pi ;
const G4double LPMconstant = fine_structure_const*electron_mass_c2*
electron_mass_c2/(8.*pi*hbarc) ;
const G4double kmin = 1.*eV ;
const G4double klim = 1.*keV ;
G4double LPMEnergy = LPMconstant*(material->GetRadlen()) ;
G4double TotalEnergysquare = TotalEnergy*TotalEnergy ;
G4double LPMGammaEnergyLimit = TotalEnergysquare/LPMEnergy ;
if(LPMGammaEnergyLimit > klim)
{
G4double kmax = G4std::min(Cut,LPMGammaEnergyLimit) ;
G4double floss = 0. ;
G4int nmax = 1000 ;
G4int nn ;
G4double vmin=log(kmin);
G4double vmax=log(Cut) ;
nn = int(nmax*(vmax-vmin)/(log(HighestKineticEnergy)-vmin)) ;
G4double u,uu,s2lpm,sp,fac,c,v,dv,w ;
dv = (vmax-vmin)/nn ;
v = vmin-dv ;
for(G4int n=0; n<=nn; n++)
{
v += dv ;
u = exp(v) ;
uu = u*u ;
if(u<=kmax)
{
sp=uu/(uu+MigdalConstant*TotalEnergysquare*
(material->GetElectronDensity())) ;
s2lpm=LPMEnergy*u/TotalEnergysquare ;
if(s2lpm<1.)
{
w=s2lpm*(1.+sp) ;
fac=sp*(sqrt(w*w+4.*s2lpm*sp*sp)-w)/
(sqrt(1.+2.*sp+5.*sp*sp)-1.-sp) ;
}
else
{
fac=sp ;
}
}
else
{
fac=1. ;
}
fac *= uu*u ;
if((n==0)||(n==nn))
c=0.5;
else
c=1.;
fac *= c ;
floss += fac ;
}
floss *=dv*3./(Cut*Cut*Cut-kmin*kmin*kmin) ;
if(floss > 1.) floss = 1. ;
// correct the loss
bremloss *= floss ;
}
if(bremloss < 0.) bremloss = 0. ;
aVector->PutValue(i,bremloss);
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlungPlus::ComputeXYPolynomial(G4double x, G4double y,
G4int xSize, G4int ySize,
const G4double coeff[])
{
// Computes the polynomial (1 y y^2 ...) * matrix * (1 x x^2 ...) .
// xSize and ySize are the dimensions of the matrix,
// coeff containts the elements, stored row-wise.
G4double* a= new G4double[xSize];
G4int i, j;
for (i=0; i<xSize; i++) a[i]= 0.0;
G4int index= 0; G4double yy= 1.0;
for (j=0; j<ySize; j++)
{ for (i=0; i<xSize; i++) a[i]+= coeff[index++]*yy;
yy*= y;
}
G4double r= a[0]; G4double xx= x;
for (i=1; i<xSize; i++) { r+= a[i]*xx; xx*= x;}
delete[] a;
return r;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlungPlus::ComputeBremLoss(G4double Z,G4double natom,
G4double T,G4double Cut,G4double x)
// compute loss due to soft brems
// 'Migdal' version , this is the default in GEANT3
{
const G4double beta=0.99,ksi=2.51,ve=0.00004 ;
const G4double corrfac = classic_electr_radius*electron_Compton_length*electron_Compton_length/pi ;
static const G4double
CMbarn[]= {
-0.960613e-1, 0.631029e-1,-0.142819e-1, 0.150437e-2,-0.733286e-4, 0.131404e-5,
0.859343e-1,-0.529023e-1, 0.131899e-1,-0.159201e-2, 0.926958e-4,-0.208439e-5,
-0.684096e+1, 0.370364e+1,-0.786752e0, 0.822670e-1,-0.424710e-2, 0.867980e-4,
-0.200856e+1, 0.129573e+1,-0.306533e0, 0.343682e-1,-0.185931e-2, 0.392432e-4,
0.127538e+1,-0.515705e0, 0.820644e-1,-0.641997e-2, 0.245913e-3,-0.365789e-5,
0.115792e0, -0.463143e-1, 0.725442e-2,-0.556266e-3, 0.208049e-4,-0.300895e-6};
static const G4double
CPbarn[]= {
-0.960613e-1, 0.631029e-1,-0.142819e-1, 0.150437e-2,-0.733286e-4, 0.131404e-5,
0.859343e-1,-0.529023e-1, 0.131899e-1,-0.159201e-2, 0.926958e-4,-0.208439e-5,
-0.271082e-1, 0.173949e-1,-0.452531e-2, 0.569405e-3,-0.344856e-4, 0.803964e-6,
0.419855e-2,-0.277188e-2, 0.737658e-3,-0.939463e-4, 0.569748e-5,-0.131737e-6,
-0.318752e-3, 0.215144e-3,-0.579787e-4, 0.737972e-5,-0.441485e-6, 0.994726e-8,
0.938233e-5,-0.651642e-5, 0.177303e-5,-0.224680e-6, 0.132080e-7,-0.288593e-9};
static const G4double
CCMbarn[]= {
-0.245667e-3, 0.833406e-4,-0.129217e-4, 0.915099e-6,-0.247179e-7,
0.147696e-3,-0.498793e-4, 0.402375e-5, 0.989281e-7,-0.133378e-7,
-0.737702e-2, 0.333057e-2,-0.553141e-3, 0.402464e-4,-0.107977e-5,
-0.641533e-2, 0.290113e-2,-0.477641e-3, 0.342008e-4,-0.900582e-6,
0.574303e-5, 0.908521e-4,-0.256900e-4, 0.239921e-5,-0.741271e-7};
static const G4double
CCPbarn[]= {
-0.245667e-3, 0.833406e-4,-0.129217e-4, 0.915099e-6,-0.247179e-7,
0.147696e-3,-0.498793e-4, 0.402375e-5, 0.989281e-7,-0.133378e-7,
-0.341260e-4, 0.971711e-5,-0.172031e-6,-0.119455e-6, 0.704166e-8,
0.341740e-5,-0.775867e-6,-0.653231e-7, 0.225605e-7,-0.114860e-8,
-0.119391e-6, 0.194885e-7, 0.588959e-8,-0.127589e-8, 0.608247e-10};
G4double CM[36],CP[36],CCM[25],CCP[25]; //Set the unit: barn
for (G4int i=0; i<36; i++) { CM[i] = CMbarn[i]*barn;
CP[i] = CPbarn[i]*barn;
}
for (G4int ii=0; ii<25; ii++) { CCM[ii] = CCMbarn[ii]*barn;
CCP[ii] = CCPbarn[ii]*barn;
}
// -----------------------------------------------------------
G4double TotalEnergy = T + electron_mass_c2;
G4double y=log(Cut/(ve*TotalEnergy));
G4double loss;
if (y <= 0.) loss = ComputeXYPolynomial(x, y, 6, 6, CM)
+ Z * ComputeXYPolynomial(x, y, 5, 5, CCM);
else loss = ComputeXYPolynomial(x, y, 6, 6, CP)
+ Z * ComputeXYPolynomial(x, y, 5, 5, CCP);
G4double rate = TotalEnergy/Cut ;
G4double corr = 1./(1.+corrfac*natom*rate*rate) ;
G4double factor = pow(Cut*corr/T,beta);
factor *= Z*(Z+ksi)*TotalEnergy*TotalEnergy/(TotalEnergy+electron_mass_c2) ;
loss *= factor ;
return loss ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlungPlus::ComputePositronCorrFactorLoss(
G4double Z,G4double KineticEnergy,G4double GammaCut)
//calculates the correction factor for the energy loss due to bremsstrahlung for positrons
//the same correction is in the (discrete) bremsstrahlung
{
static const G4double K = 132.9416*eV ;
static const G4double a1=4.15e-1, a3=2.10e-3, a5=54.0e-5 ;
G4double x = log(KineticEnergy/(K*Z*Z)), x2 = x*x, x3 = x2*x;
G4double eta = 0.5+atan(a1*x+a3*x3+a5*x3*x2)/pi;
G4double e0 = GammaCut/KineticEnergy;
G4double factor(0.);
if (e0!=1.0) { factor=log(1.-e0)/eta; factor=exp(factor);}
factor = eta*(1.-factor)/e0;
return factor;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungPlus::BuildLambdaTable(const G4ParticleDefinition& ParticleType)
// Build mean free path tables for the gamma emission by e- or e+.
// tables are Build for MATERIALS.
{
G4double LowEdgeEnergy , Value;
G4double FixedEnergy = (LowestKineticEnergy + HighestKineticEnergy)/2.;
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
//create table
if (theMeanFreePathTable) {theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
PartialSumSigma.resize(G4Material::GetNumberOfMaterials());
G4PhysicsLogVector* ptrVector;
for ( G4int J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestKineticEnergy, HighestKineticEnergy,
TotBin ) ;
const G4Material* material= (*theMaterialTable)[J];
for ( G4int i = 0 ; i < TotBin ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeMeanFreePath( &ParticleType, LowEdgeEnergy,
material );
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector );
// Compute the PartialSumSigma table at a given fixed energy
ComputePartialSumSigma( &ParticleType, FixedEnergy, material) ;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungPlus::ComputePartialSumSigma(const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
// Build the table of cross section per element. The table is built for MATERIALS.
// This table is used by DoIt to select randomly an element in the material.
{
G4int Imate = aMaterial->GetIndex();
G4int NbOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[Imate];
PartialSumSigma(Imate) = new G4ValVector(NbOfElements);
G4double SIGMA = 0. ;
for ( G4int Ielem=0 ; Ielem < NbOfElements ; Ielem++ )
{
SIGMA += theAtomNumDensityVector[Ielem] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(Ielem)->GetZ(),
GammaEnergyCut );
PartialSumSigma(Imate)->insertAt(Ielem, SIGMA);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlungPlus::ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy, G4double AtomicNumber,
G4double GammaEnergyCut)
// Calculates the microscopic cross section in GEANT4 internal units.
// A parametrized formula from L. Urban is used to estimate the total cross section.
// This parametrization is derived from :
// tabulated cross-section values of Seltzer and Berger below 10 GeV,
// screened Bethe Heilter differential cross section above 10 GeV,
// Migdal corrections in both case.
// Seltzer & Berger: Nim B 12:95 (1985)
// Nelson, Hirayama & Rogers: Technical report 265 SLAC (1985)
// Migdal: Phys Rev 103:1811 (1956); Messel & Crawford: Pergamon Press (1970)
//
// Above 100 GeV the Cross section is scaled in log(KineticEnergy).
{
G4double CrossSection = 0.0 ;
if ( KineticEnergy < 1*keV ) return CrossSection;
if ( KineticEnergy <= GammaEnergyCut ) return CrossSection;
G4double LocalKineticEnergy = KineticEnergy, LocalGammaEnergyCut = GammaEnergyCut;
const G4double KinLimitScale = 100.*GeV, CutLimitScale = 50.*GeV;
const G4double Tlim = 1.*MeV;
if (KineticEnergy < Tlim) LocalKineticEnergy = Tlim;
if (KineticEnergy > KinLimitScale)
{ LocalKineticEnergy = KinLimitScale;
if (GammaEnergyCut > KinLimitScale) LocalGammaEnergyCut = CutLimitScale;
}
static const G4double
aay0x0= 0.430748E-02*barn, aay0x1= 0.576058E-02*barn, aay0x2=-0.122564E-02*barn,
aay0x3= 0.114843E-03*barn, aay0x4=-0.489452E-05*barn, aay0x5= 0.795991E-07*barn;
static const G4double
aay1x0= 0.326746E-02*barn, aay1x1=-0.132872E-02*barn, aay1x2= 0.217197E-03*barn,
aay1x3=-0.179769E-04*barn, aay1x4= 0.766114E-06*barn, aay1x5=-0.125603E-07*barn;
static const G4double
amy2x0= 0.326452E-02*barn, amy2x1=-0.175331E-02*barn, amy2x2= 0.415488E-03*barn,
amy2x3=-0.507652E-04*barn, amy2x4= 0.297569E-05*barn, amy2x5=-0.651741E-07*barn;
static const G4double
amy3x0= 0.847189E-03*barn, amy3x1=-0.433923E-03*barn, amy3x2= 0.116672E-03*barn,
amy3x3=-0.166799E-04*barn, amy3x4= 0.110237E-05*barn, amy3x5=-0.263383E-07*barn;
static const G4double
amy4x0= 0.846052E-04*barn, amy4x1=-0.415764E-04*barn, amy4x2= 0.129610E-04*barn,
amy4x3=-0.212844E-05*barn, amy4x4= 0.152871E-06*barn, amy4x5=-0.384393E-08*barn;
static const G4double
amy5x0= 0.300838E-05*barn, amy5x1=-0.136833E-05*barn, amy5x2= 0.507296E-06*barn,
amy5x3=-0.943623E-07*barn, amy5x4= 0.720305E-08*barn, amy5x5=-0.187210E-09*barn;
static const G4double
apy2x0= 0.448230E-01*barn, apy2x1=-0.210048E-01*barn, apy2x2= 0.379434E-02*barn,
apy2x3=-0.328431E-03*barn, apy2x4= 0.136710E-04*barn, apy2x5=-0.220593E-06*barn;
static const G4double
apy3x0=-0.539248E-02*barn, apy3x1= 0.330244E-02*barn, apy3x2=-0.733726E-03*barn,
apy3x3= 0.732312E-04*barn, apy3x4=-0.336810E-05*barn, apy3x5= 0.583913E-07*barn;
static const G4double
apy4x0=-0.106983E-02*barn, apy4x1= 0.378021E-03*barn, apy4x2=-0.384854E-04*barn,
apy4x3= 0.978156E-06*barn, apy4x4= 0.410622E-07*barn, apy4x5=-0.174250E-08*barn;
static const G4double
apy5x0=-0.117501E-04*barn, apy5x1=-0.983887E-05*barn, apy5x2= 0.239644E-05*barn,
apy5x3=-0.190104E-06*barn, apy5x4= 0.619226E-08*barn, apy5x5=-0.680932E-10*barn;
static const G4double
bby0x0= 0.168074E-03*barn, bby0x1=-0.934609E-04*barn, bby0x2= 0.141293E-04*barn,
bby0x3=-0.854216E-06*barn, bby0x4= 0.183287E-07*barn;
static const G4double
bby1x0= 0.932144E-04*barn, bby1x1=-0.234926E-04*barn, bby1x2= 0.136656E-05*barn,
bby1x3= 0.351109E-07*barn, bby1x4=-0.330189E-08*barn;
static const G4double
bmy2x0= 0.174523E-04*barn, bmy2x1= 0.253854E-05*barn, bmy2x2=-0.171643E-05*barn,
bmy2x3= 0.183074E-06*barn, bmy2x4=-0.566331E-08*barn;
static const G4double
bmy3x0= 0.111970E-05*barn, bmy3x1= 0.112776E-05*barn, bmy3x2=-0.386924E-06*barn,
bmy3x3= 0.367597E-07*barn, bmy3x4=-0.108504E-08*barn;
static const G4double
bmy4x0= 0.171604E-07*barn, bmy4x1= 0.738801E-07*barn, bmy4x2=-0.218761E-07*barn,
bmy4x3= 0.199032E-08*barn, bmy4x4=-0.576173E-10*barn;
static const G4double
bpy2x0=-0.105531E-03*barn, bpy2x1= 0.362995E-04*barn, bpy2x2=-0.433334E-05*barn,
bpy2x3= 0.207664E-06*barn, bpy2x4=-0.330250E-08*barn;
static const G4double
bpy3x0=-0.168293E-05*barn, bpy3x1=-0.773204E-06*barn, bpy3x2= 0.227974E-06*barn,
bpy3x3=-0.159385E-07*barn, bpy3x4= 0.321958E-09*barn;
static const G4double
bpy4x0= 0.167046E-05*barn, bpy4x1=-0.440761E-06*barn, bpy4x2= 0.396377E-07*barn,
bpy4x3=-0.151053E-08*barn, bpy4x4= 0.215624E-10*barn;
static const G4double ksi=1.8, alfa=0.98, vs= 1.E-4;
G4double TotalEnergy = LocalKineticEnergy + electron_mass_c2;
G4double X = log(TotalEnergy/electron_mass_c2), X2=X*X, X3=X2*X, X4=X3*X, X5=X4*X;
G4double Y = log(vs*TotalEnergy/LocalGammaEnergyCut), Y2=Y*Y, Y3=Y2*Y, Y4=Y3*Y, Y5=Y4*Y;
G4double ay0, ay1, ay2, ay3, ay4, ay5, by0, by1, by2, by3, by4;
if (Y < 0.) {
ay0 = aay0x0 + aay0x1*X + aay0x2*X2 + aay0x3*X3 + aay0x4*X4 + aay0x5*X5;
ay1 = aay1x0 + aay1x1*X + aay1x2*X2 + aay1x3*X3 + aay1x4*X4 + aay1x5*X5;
ay2 = amy2x0 + amy2x1*X + amy2x2*X2 + amy2x3*X3 + amy2x4*X4 + amy2x5*X5;
ay3 = amy3x0 + amy3x1*X + amy3x2*X2 + amy3x3*X3 + amy3x4*X4 + amy3x5*X5;
ay4 = amy4x0 + amy4x1*X + amy4x2*X2 + amy4x3*X3 + amy4x4*X4 + amy4x5*X5;
ay5 = amy5x0 + amy5x1*X + amy5x2*X2 + amy5x3*X3 + amy5x4*X4 + amy5x5*X5;
by0 = bby0x0 + bby0x1*X + bby0x2*X2 + bby0x3*X3 + bby0x4*X4;
by1 = bby1x0 + bby1x1*X + bby1x2*X2 + bby1x3*X3 + bby1x4*X4;
by2 = bmy2x0 + bmy2x1*X + bmy2x2*X2 + bmy2x3*X3 + bmy2x4*X4;
by3 = bmy3x0 + bmy3x1*X + bmy3x2*X2 + bmy3x3*X3 + bmy3x4*X4;
by4 = bmy4x0 + bmy4x1*X + bmy4x2*X2 + bmy4x3*X3 + bmy4x4*X4;
}
else {
ay0 = aay0x0 + aay0x1*X + aay0x2*X2 + aay0x3*X3 + aay0x4*X4 + aay0x5*X5;
ay1 = aay1x0 + aay1x1*X + aay1x2*X2 + aay1x3*X3 + aay1x4*X4 + aay1x5*X5;
ay2 = apy2x0 + apy2x1*X + apy2x2*X2 + apy2x3*X3 + apy2x4*X4 + apy2x5*X5;
ay3 = apy3x0 + apy3x1*X + apy3x2*X2 + apy3x3*X3 + apy3x4*X4 + apy3x5*X5;
ay4 = apy4x0 + apy4x1*X + apy4x2*X2 + apy4x3*X3 + apy4x4*X4 + apy4x5*X5;
ay5 = apy5x0 + apy5x1*X + apy5x2*X2 + apy5x3*X3 + apy5x4*X4 + apy5x5*X5;
by0 = bby0x0 + bby0x1*X + bby0x2*X2 + bby0x3*X3 + bby0x4*X4;
by1 = bby1x0 + bby1x1*X + bby1x2*X2 + bby1x3*X3 + bby1x4*X4;
by2 = bpy2x0 + bpy2x1*X + bpy2x2*X2 + bpy2x3*X3 + bpy2x4*X4;
by3 = bpy3x0 + bpy3x1*X + bpy3x2*X2 + bpy3x3*X3 + bpy3x4*X4;
by4 = bpy4x0 + bpy4x1*X + bpy4x2*X2 + bpy4x3*X3 + bpy4x4*X4;
}
G4double F0 = ay0 + ay1*Y + ay2*Y2 + ay3*Y3 + ay4*Y4 + ay5*Y5,
F1 = by0 + by1*Y + by2*Y2 + by3*Y3 + by4*Y4;
CrossSection = AtomicNumber*(AtomicNumber+ksi)*TotalEnergy*TotalEnergy
* pow(log(LocalKineticEnergy/LocalGammaEnergyCut),alfa)
* (F0 + F1*AtomicNumber)
/ (LocalKineticEnergy*(LocalKineticEnergy+2*electron_mass_c2));
if (ParticleType == G4Positron::Positron())
CrossSection *= ComputePositronCorrFactorSigma(AtomicNumber, LocalKineticEnergy,
LocalGammaEnergyCut);
if (KineticEnergy < Tlim) CrossSection *= log(KineticEnergy/GammaEnergyCut)
/log(Tlim/GammaEnergyCut);
// now comes the scaling above 100GeV
if (KineticEnergy > KinLimitScale)
{ G4double X1 = GammaEnergyCut/KineticEnergy,
X2 = LocalGammaEnergyCut/LocalKineticEnergy;
CrossSection *= (-log(X1) -2./3. + X1 - X1*X1/3.)/(-log(X2) -2./3. + X2 - X2*X2/3.);
}
if (CrossSection < 0.) CrossSection = 0.;
return CrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlungPlus::ComputePositronCorrFactorSigma( G4double AtomicNumber,
G4double KineticEnergy, G4double GammaEnergyCut)
// Calculates the correction factor for the total cross section of the positron bremsstrahl.
// Eta is the ratio of positron to electron energy loss by bremstrahlung.
// A parametrized formula from L. Urban is used to estimate eta. It is a fit to the results
// of L. Kim & al: Phys Rev. A33,3002 (1986)
{
static const G4double K = 132.9416*eV;
static const G4double a1 = 4.15e-1, a3 = 2.10e-3, a5 = 54.0e-5;
G4double x = log(KineticEnergy/(K*AtomicNumber*AtomicNumber));
G4double eta = 0.5 + atan(a1*x + a3*x*x*x + a5*x*x*x*x*x)/pi ;
G4double alfa = (1. - eta)/eta;
return eta*pow((1. - GammaEnergyCut/KineticEnergy) , alfa);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4eBremsstrahlungPlus::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData)
//
// The emitted gamma energy is sampled using a parametrized formula from L. Urban.
// This parametrization is derived from :
// cross-section values of Seltzer and Berger for electron energies 1 keV - 10 GeV,
// screened Bethe Heilter differential cross section above 10 GeV,
// Migdal corrections in both case.
// Seltzer & Berger: Nim B 12:95 (1985)
// Nelson, Hirayama & Rogers: Technical report 265 SLAC (1985)
// Migdal: Phys Rev 103:1811 (1956); Messel & Crawford: Pergamon Press (1970)
//
// A modified version of the random number techniques of Butcher & Messel is used
// (Nuc Phys 20(1960),15).
//
// GEANT4 internal units.
//
{
static const G4double
ah10 = 4.67733E+00, ah11 =-6.19012E-01, ah12 = 2.02225E-02,
ah20 =-7.34101E+00, ah21 = 1.00462E+00, ah22 =-3.20985E-02,
ah30 = 2.93119E+00, ah31 =-4.03761E-01, ah32 = 1.25153E-02;
static const G4double
bh10 = 4.23071E+00, bh11 =-6.10995E-01, bh12 = 1.95531E-02,
bh20 =-7.12527E+00, bh21 = 9.69160E-01, bh22 =-2.74255E-02,
bh30 = 2.69925E+00, bh31 =-3.63283E-01, bh32 = 9.55316E-03;
static const G4double
al00 =-2.05398E+00, al01 = 2.38815E-02, al02 = 5.25483E-04,
al10 =-7.69748E-02, al11 =-6.91499E-02, al12 = 2.22453E-03,
al20 = 4.06463E-02, al21 =-1.01281E-02, al22 = 3.40919E-04;
static const G4double
bl00 = 1.04133E+00, bl01 =-9.43291E-03, bl02 =-4.54758E-04,
bl10 = 1.19253E-01, bl11 = 4.07467E-02, bl12 =-1.30718E-03,
bl20 =-1.59391E-02, bl21 = 7.27752E-03, bl22 =-1.94405E-04;
static const G4double MigdalConstant = classic_electr_radius
*electron_Compton_length
*electron_Compton_length/pi;
const G4double LPMconstant = fine_structure_const*electron_mass_c2*
electron_mass_c2/(8.*pi*hbarc) ;
aParticleChange.Initialize(trackData);
G4Material* aMaterial=trackData.GetMaterial() ;
G4double LPMEnergy = LPMconstant*(aMaterial->GetRadlen()) ;
const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
G4double charge = aDynamicParticle->GetDefinition()->GetPDGCharge();
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
G4ParticleMomentum ParticleDirection = aDynamicParticle->GetMomentumDirection();
// Gamma production cut in this material
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
// check against insufficient energy
if (KineticEnergy < GammaEnergyCut)
{
aParticleChange.SetMomentumChange( ParticleDirection );
aParticleChange.SetEnergyChange( KineticEnergy );
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.SetNumberOfSecondaries(0);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
// select randomly one element constituing the material
G4Element* anElement = SelectRandomAtom(aMaterial);
// Extract Z factors for this Element
G4double lnZ = 3.*(anElement->GetIonisation()->GetlogZ3());
G4double FZ = lnZ* (4.- 0.55*lnZ);
G4double ZZ = anElement->GetIonisation()->GetZZ3();
// limits of the energy sampling
G4double TotalEnergy = KineticEnergy + electron_mass_c2;
G4double TotalEnergysquare = TotalEnergy*TotalEnergy ;
G4double LPMGammaEnergyLimit = TotalEnergysquare/LPMEnergy ;
G4double xmin = GammaEnergyCut/KineticEnergy, epsilmin = GammaEnergyCut/TotalEnergy;
G4double epsilmax = KineticEnergy/TotalEnergy;
// Migdal factor
G4double MigdalFactor = (aMaterial->GetElectronDensity())*MigdalConstant
/(epsilmax*epsilmax);
//
G4double x, epsil, greject, migdal, grejmax;
G4double U = log(KineticEnergy/electron_mass_c2), U2 = U*U;
//
// sample the energy rate of the emitted gamma for electron kinetic energy > 1 MeV
//
if (KineticEnergy > 1.*MeV)
{
// parameters
G4double ah1 = ah10 + ZZ* (ah11 + ZZ* ah12),
ah2 = ah20 + ZZ* (ah21 + ZZ* ah22),
ah3 = ah30 + ZZ* (ah31 + ZZ* ah32);
G4double bh1 = bh10 + ZZ* (bh11 + ZZ* bh12),
bh2 = bh20 + ZZ* (bh21 + ZZ* bh22),
bh3 = bh30 + ZZ* (bh31 + ZZ* bh32);
G4double ah = 1. + (ah1*U2 + ah2*U + ah3) / (U2*U);
G4double bh = 0.75 + (bh1*U2 + bh2*U + bh3) / (U2*U);
// limit of the screening variable
G4double screenfac =
136.*electron_mass_c2/((anElement->GetIonisation()->GetZ3())*TotalEnergy);
G4double screenmin = screenfac*epsilmin/(1.-epsilmin);
// Compute the maximum of the rejection function
G4double F1 = G4std::max(ScreenFunction1(screenmin) - FZ ,0.);
G4double F2 = G4std::max(ScreenFunction2(screenmin) - FZ ,0.);
grejmax = (F1 - epsilmin* (F1*ah - bh*epsilmin*F2))/(42.392 - FZ);
// sample the energy rate of the emitted Gamma
G4double screenvar;
do {
x = pow(xmin, G4UniformRand());
epsil = x*KineticEnergy/TotalEnergy;
screenvar = screenfac*epsil/(1-epsil);
F1 = G4std::max(ScreenFunction1(screenvar) - FZ ,0.);
F2 = G4std::max(ScreenFunction2(screenvar) - FZ ,0.);
migdal = (1. + MigdalFactor)/(1. + MigdalFactor/(x*x));
greject = migdal*(F1 - epsil* (ah*F1 - bh*epsil*F2))/(42.392 - FZ);
} while( greject < G4UniformRand()*grejmax );
}
else
{
// sample the energy rate of the emitted gamma for electron kinetic energy < 1 MeV
//
// parameters
G4double al0 = al00 + ZZ* (al01 + ZZ* al02),
al1 = al10 + ZZ* (al11 + ZZ* al12),
al2 = al20 + ZZ* (al21 + ZZ* al22);
G4double bl0 = bl00 + ZZ* (bl01 + ZZ* bl02),
bl1 = bl10 + ZZ* (bl11 + ZZ* bl12),
bl2 = bl20 + ZZ* (bl21 + ZZ* bl22);
G4double al = al0 + al1*U + al2*U2;
G4double bl = bl0 + bl1*U + bl2*U2;
// Compute the maximum of the rejection function
grejmax = G4std::max(1. + xmin* (al + bl*xmin), 1.+al+bl);
G4double xm = -al/(2.*bl);
if ((xmin < xm)&&(xm < 1.)) grejmax = G4std::max(grejmax, 1.+ xm* (al + bl*xm));
// sample the energy rate of the emitted Gamma
do { x = pow(xmin, G4UniformRand());
migdal = (1. + MigdalFactor)/(1. + MigdalFactor/(x*x));
greject = migdal*(1. + x* (al + bl*x));
} while( greject < G4UniformRand()*grejmax );
}
G4double GammaEnergy = x*KineticEnergy;
// now comes the supression due to the LPM effect
if(GammaEnergy < LPMGammaEnergyLimit)
{
G4double S2LPM = LPMEnergy*GammaEnergy/TotalEnergysquare ;
G4double Spol = GammaEnergy*GammaEnergy/(GammaEnergy*GammaEnergy +
MigdalConstant*(aMaterial->GetElectronDensity())*
TotalEnergysquare) ;
G4double w=S2LPM*(1.+Spol) ;
G4double Supr=Spol*(sqrt(w*w+4.*S2LPM*Spol*Spol)-w)/
(sqrt(1.+2.*Spol+5.*Spol*Spol)-1.-Spol) ;
if (G4UniformRand() > Supr)
GammaEnergy = 0. ;
}
//protection: DO NOT PRODUCE a gamma with energy 0. !
if (GammaEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
//
// angles of the emitted gamma. ( Z - axis along the parent particle)
//
// universal distribution suggested by L. Urban (Geant3 manual (1993) Phys211),
// derived from Tsai distribution (Rev Mod Phys 49,421(1977))
G4double u;
const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ;
if (9./(9.+d) > G4UniformRand()) u = - log(G4UniformRand()*G4UniformRand())/a1 ;
else u = - log(G4UniformRand()*G4UniformRand())/a2 ;
G4double Teta = u*electron_mass_c2/TotalEnergy ;
G4double Phi = twopi * G4UniformRand() ;
G4double dirx = sin(Teta)*cos(Phi) , diry = sin(Teta)*sin(Phi) , dirz = cos(Teta) ;
G4ThreeVector GammaDirection ( dirx, diry, dirz);
GammaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for the Gamma
G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
GammaDirection, GammaEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(aGamma);
//
// Update the incident particle
//
G4double NewKinEnergy = KineticEnergy - GammaEnergy;
if (NewKinEnergy > 0.)
{
aParticleChange.SetMomentumChange( ParticleDirection );
aParticleChange.SetEnergyChange( NewKinEnergy );
aParticleChange.SetLocalEnergyDeposit (0.);
}
else
{
aParticleChange.SetEnergyChange( 0. );
aParticleChange.SetLocalEnergyDeposit (0.);
if (charge<0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4Element* G4eBremsstrahlungPlus::SelectRandomAtom(G4Material* aMaterial) const
{
// select randomly 1 element within the material
const G4int Index = aMaterial->GetIndex();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
G4double rval = G4UniformRand()*((*PartialSumSigma(Index))(NumberOfElements-1));
for ( G4int i=0; i < NumberOfElements; i++ )
if (rval <= (*PartialSumSigma(Index))(i)) return ((*theElementVector)(i));
G4cout << " WARNING !!! - The Material '"<< aMaterial->GetName()
<< "' has no elements, NULL pointer returned." << G4endl;
return NULL;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungPlus::PrintInfoDefinition()
{
G4String comments = "Total cross sections from a parametrisation. ";
comments += "Good description from 1 KeV to 100 GeV.\n";
comments += " log scale extrapolation above 100 GeV \n";
comments += " Gamma energy sampled from a parametrised formula.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4eIonisation.cc,v 1.3.8.1.2.2 1999/12/10 15:42:00 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4eIonisation.cc,v 1.10 2000/05/23 14:42:21 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// -------------------------------------------------------------
@@ -27,22 +27,23 @@
// 04-09-98: new methods SetBining() PrintInfo()
// 07-09-98: Cleanup
// 02/02/99: correction inDoIt , L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// --------------------------------------------------------------
#include "G4eIonisation.hh"
#include "G4EnergyLossTables.hh"
#include "G4ios.hh"
#include "G4UnitsTable.hh"
G4double G4eIonisation::LowerBoundLambda = 1.*keV ;
G4double G4eIonisation::UpperBoundLambda = 100.*TeV ;
G4int G4eIonisation::NbinLambda = 100 ;
// constructor and destructor
G4eIonisation::G4eIonisation(const G4String& processName)
: G4eEnergyLoss(processName),
theMeanFreePathTable(NULL),
LowestKineticEnergy(1.*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100)
: G4VeEnergyLoss(processName),
theMeanFreePathTable(NULL)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -58,16 +59,13 @@ G4eIonisation::~G4eIonisation()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisation::SetPhysicsTableBining(G4double lowE, G4double highE, G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE; TotBin = nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss() ;
HighestKineticEnergy = GetUpperBoundEloss() ;
TotBin = GetNbinEloss() ;
BuildLossTable(aParticleType) ;
@@ -100,6 +98,8 @@ void G4eIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
const G4double twoln10 = 2.*log(10.);
const G4double Factor = twopi_mc2_rcl2;
static const G4double Tl = 0.2*keV ;
G4double LowEdgeEnergy, ionloss;
// material properties
@@ -142,11 +142,27 @@ void G4eIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
X0den = material->GetIonisation()->GetX0density();
X1den = material->GetIonisation()->GetX1density();
// for the lowenergy extrapolation
G4double Zeff = material->GetTotNbOfElectPerVolume()/
material->GetTotNbOfAtomsPerVolume() ;
G4double Th = 0.25*sqrt(Zeff)*keV ;
G4double Tsav ;
// now comes the loop for the kinetic energy values
for (G4int i = 0 ; i < TotBin ; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
// low energy ?
if(LowEdgeEnergy < Th)
{
Tsav = LowEdgeEnergy ;
LowEdgeEnergy = Th ;
}
else
Tsav = 0. ;
tau = LowEdgeEnergy/ParticleMass ;
// Seltzer-Berger formula
@@ -185,6 +201,15 @@ void G4eIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
ionloss *= Factor*ElectronDensity/beta2 ;
if (ionloss <= 0.) ionloss = 0.;
// low energy ?
if(Tsav > 0.)
{
if(Tsav >= Tl)
ionloss *= sqrt(LowEdgeEnergy/Tsav) ;
else
ionloss *= sqrt(LowEdgeEnergy*Tsav)/Tl ;
}
aVector->PutValue(i,ionloss) ;
}
theLossTable->insert(aVector);
@@ -211,9 +236,19 @@ void G4eIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
theMeanFreePathTable = 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()->GetCutsInEnergy() == 0) &&
( &aParticleType == G4Positron::Positron()))
{
G4cout << " The ELECTRON energy cuts needed to compute energy loss/mean free path "
" for POSITRON , too. " << G4endl;
G4Exception(" Call SetCut for e- first !!!!!!") ;
}
G4double* DeltaCutInKineticEnergy = G4Electron::Electron()->GetCutsInEnergy() ;
// loop for materials
for (G4int J=0 ; J < numOfMaterials; J++)
@@ -221,7 +256,7 @@ void G4eIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
LowerBoundLambda, UpperBoundLambda, NbinLambda);
// compute the (macroscopic) cross section first
@@ -238,7 +273,7 @@ void G4eIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
// (--> it will be the same for all the elements in this material )
G4double DeltaThreshold = DeltaCutInKineticEnergy[J] ;
for (G4int i = 0 ; i < TotBin ; i++)
for (G4int i = 0 ; i < NbinLambda ; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
SIGMA = 0.;
@@ -257,7 +292,6 @@ void G4eIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -450,9 +484,9 @@ void G4eIonisation::PrintInfoDefinition()
comments += " delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
<< "\n PhysicsTables from " << G4BestUnit(LowerBoundLambda,"Energy")
<< " to " << G4BestUnit(UpperBoundLambda,"Energy")
<< " in " << NbinLambda << " bins. \n";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1,458 +0,0 @@
// 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: G4eIonisationPlus.cc,v 1.3.8.1.2.2 1999/12/10 15:42:00 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
//
//
// -------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4eIonisationPlus physics process -----------
// by Laszlo Urban, 20 March 1997
// **************************************************************
// It is the first implementation of the NEW IONISATION PROCESS.
// It calculates the ionisation of e+/e-.
// **************************************************************
//
// 07-04-98: remove 'tracking cut' of the ionizing particle, MMa
// 04-09-98: new methods SetBining() PrintInfo()
// 07-09-98: Cleanup
// 02/02/99: correction in DoIt , L.urban
// --------------------------------------------------------------
#include "G4eIonisationPlus.hh"
#include "G4EnergyLossTables.hh"
#include "G4ios.hh"
#include "G4UnitsTable.hh"
// constructor and destructor
G4eIonisationPlus::G4eIonisationPlus(const G4String& processName)
: G4eEnergyLossPlus(processName),
theMeanFreePathTable(NULL),
LowestKineticEnergy(1.*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eIonisationPlus::~G4eIonisationPlus()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationPlus::SetPhysicsTableBining(G4double lowE, G4double highE, G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE; TotBin = nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationPlus::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
BuildLossTable(aParticleType) ;
if(&aParticleType==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable ;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable ;
CounterOfPositronProcess++;
}
BuildLambdaTable(aParticleType) ;
BuildDEDXTable(aParticleType) ;
if(&aParticleType==G4Electron::Electron())
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationPlus::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
// Build tables for the ionization energy loss
// the tables are built for *MATERIALS*
const G4double twoln10 = 2.*log(10.);
const G4double Factor = twopi_mc2_rcl2;
G4double LowEdgeEnergy, ionloss;
// material properties
G4double ElectronDensity,Eexc,Eexcm2,Cden,Mden,Aden,X0den,X1den ;
// some local variables
G4double tau,Tmax,gamma,gamma2,bg2,beta2,d,d2,d3,d4,delta,x,y ;
ParticleMass = aParticleType.GetPDGMass();
G4double* ParticleCutInKineticEnergy = aParticleType.GetEnergyCuts() ;
// create table
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if (theLossTable) { theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
// get material parameters needed for the energy loss calculation
const G4Material* material= (*theMaterialTable)[J];
ElectronDensity = material->GetElectronDensity();
Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
Eexc /= ParticleMass; Eexcm2 = Eexc*Eexc;
Cden = material->GetIonisation()->GetCdensity();
Mden = material->GetIonisation()->GetMdensity();
Aden = material->GetIonisation()->GetAdensity();
X0den = material->GetIonisation()->GetX0density();
X1den = material->GetIonisation()->GetX1density();
// now comes the loop for the kinetic energy values
for (G4int i = 0 ; i < TotBin ; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
tau = LowEdgeEnergy/ParticleMass ;
// Seltzer-Berger formula
gamma = tau + 1.; gamma2 = gamma*gamma;
bg2 = tau*(tau+2.);
beta2 = bg2/gamma2;
// electron
if (&aParticleType==G4Electron::Electron())
{
Tmax = LowEdgeEnergy/2.;
d = G4std::min(ParticleCutInKineticEnergy[J], Tmax)/ParticleMass;
ionloss = log(2.*(tau+2.)/Eexcm2)-1.-beta2
+ log((tau-d)*d)+tau/(tau-d)
+ (0.5*d*d+(2.*tau+1.)*log(1.-d/tau))/gamma2;
}
else //positron
{
Tmax = LowEdgeEnergy ;
d = G4std::min(ParticleCutInKineticEnergy[J], Tmax)/ParticleMass;
d2=d*d/2.; d3=d*d*d/3.; d4=d*d*d*d/4.;
y=1./(1.+gamma);
ionloss = log(2.*(tau+2.)/Eexcm2)+log(tau*d)
- beta2*(tau+2.*d-y*(3.*d2+y*(d-d3+y*(d2-tau*d3+d4))))/tau;
}
//density correction
x = log(bg2)/twoln10;
if (x < X0den) delta = 0.;
else { delta = twoln10*x - Cden;
if (x < X1den) delta += Aden*pow((X1den-x),Mden);
}
//now you can compute the total ionization loss
ionloss -= delta ;
ionloss *= Factor*ElectronDensity/beta2 ;
if (ionloss <= 0.) ionloss = 0.;
aVector->PutValue(i,ionloss) ;
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationPlus::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
// Build mean free path tables for the delta ray production process
// tables are built for MATERIALS
G4double LowEdgeEnergy, Value, SIGMA;
//create table
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if (theMeanFreePathTable) { theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
theMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
// get electron cuts in kinetic energy
G4double* DeltaCutInKineticEnergy = G4Electron::Electron()->GetCutsInEnergy() ;
// loop for materials
for (G4int J=0 ; J < numOfMaterials; J++)
{
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
// compute the (macroscopic) cross section first
const G4Material* material= (*theMaterialTable)[J];
const
G4ElementVector* theElementVector = material->GetElementVector();
const
G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
const
G4int NumberOfElements = material->GetNumberOfElements() ;
// get the electron kinetic energy cut for the actual material,
// it will be used in ComputeMicroscopicCrossSection
// (--> it will be the same for all the elements in this material )
G4double DeltaThreshold = DeltaCutInKineticEnergy[J] ;
for (G4int i = 0 ; i < TotBin ; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
SIGMA = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
SIGMA += theAtomicNumDensityVector[iel]*
ComputeMicroscopicCrossSection( aParticleType,
LowEdgeEnergy,
(*theElementVector)(iel)->GetZ(),
DeltaThreshold);
}
// mean free path = 1./macroscopic cross section
Value = SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
aVector->PutValue(i, Value) ;
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eIonisationPlus::ComputeMicroscopicCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber ,
G4double DeltaThreshold)
{
// calculates the microscopic cross section
//(it is called for elements , AtomicNumber = Z )
G4double MaxKineticEnergyTransfer, TotalCrossSection(0.);
ParticleMass = aParticleType.GetPDGMass();
G4double TotalEnergy = KineticEnergy + ParticleMass;
G4double betasquare = KineticEnergy*(TotalEnergy+ParticleMass)
/(TotalEnergy*TotalEnergy);
G4double gamma = TotalEnergy/ParticleMass, gamma2 = gamma*gamma;
G4double x=DeltaThreshold/KineticEnergy, x2 = x*x;
if (&aParticleType==G4Electron::Electron())
MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
// now you can calculate the total cross section
if (MaxKineticEnergyTransfer > DeltaThreshold)
{
if (&aParticleType==G4Electron::Electron()) //Moller (e-e-) scattering
{
TotalCrossSection = (gamma-1.)*(gamma-1.)*(0.5-x)/gamma2 + 1./x
- 1./(1.-x)-(2.*gamma-1.)*log((1.-x)/x)/gamma2;
TotalCrossSection /= betasquare;
}
else //Bhabha (e+e-) scattering
{
G4double y=1./(1.+gamma), y2 =y*y, y12=1.-2.*y;
G4double b1=2.-y2, b2=y12*(3.+y2), b4=y12*y12*y12, b3=b4+y12*y12;
TotalCrossSection = (1./x-1.)/betasquare+b1*log(x)+b2*(1.-x)
- b3*(1.-x2)/2.+b4*(1.-x2*x)/3.;
}
TotalCrossSection *= (twopi_mc2_rcl2*AtomicNumber/KineticEnergy);
}
return TotalCrossSection ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4eIonisationPlus::PostStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData) ;
G4Material* aMaterial = trackData.GetMaterial() ;
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle() ;
ParticleMass = aParticle->GetDefinition()->GetPDGMass();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + ParticleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+ParticleMass);
G4double TotalMomentum = sqrt(Psquare);
G4double Esquare=TotalEnergy*TotalEnergy;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
// get kinetic energy cut for the electron
G4double* DeltaCutInKineticEnergy = G4Electron::Electron()->GetCutsInEnergy() ;
G4double DeltaThreshold = DeltaCutInKineticEnergy[aMaterial->GetIndex()];
// some kinematics
G4double MaxKineticEnergyTransfer;
if (Charge < 0.) MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
// sampling kinetic energy of the delta ray
if (MaxKineticEnergyTransfer <= DeltaThreshold) // pathological case (should not happen,
// there is no change at all)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// normal case
G4double cc,y,y2,c2,b0,b1,b2,b3,b4,x,x1,grej,grejc;
G4double tau = KineticEnergy/ParticleMass;
G4double gamma = tau+1., gamma2=gamma*gamma;
G4double xc = DeltaThreshold/KineticEnergy, xc1=1.-xc;
if (Charge < 0.) // Moller (e-e-) scattering
{
b1=4./(9.*gamma2-10.*gamma+5.);
b2=tau*tau*b1; b3=(2.*gamma2+2.*gamma-1.)*b1;
cc=1.-2.*xc;
do {
x = xc/(1.-cc*G4UniformRand()); x1 = 1.-x;
grej = b2*x*x-b3*x/x1+b1*gamma2/(x1*x1);
} while (G4UniformRand()>grej) ;
}
else // Bhabha (e+e-) scattering
{
y=1./(gamma+1.); y2=y*y; cc=1.-2.*y;
b1=2.-y2; b2=cc*(3.+y2);
c2=cc*cc; b4=c2*cc; b3=c2+b4;
b0=gamma2/(gamma2-1.);
grejc=(((b4*xc-b3)*xc+b2)*xc-b1)*xc+b0;
do {
x = xc/(1.-xc1*G4UniformRand());
grej = ((((b4*x-b3)*x+b2)*x-b1)*x+b0)/grejc;
} while (G4UniformRand()>grej);
}
G4double DeltaKineticEnergy = x * KineticEnergy;
// protection :do not produce a secondary with 0. kinetic energy !
if (DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
G4double DeltaTotalMomentum = sqrt(DeltaKineticEnergy * (DeltaKineticEnergy +
2. * electron_mass_c2 ));
G4double costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum);
if (costheta < -1.) costheta = -1.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
G4double phi = twopi * G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta * cos(phi), diry = sintheta * sin(phi), dirz = costheta;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
// changed energy and momentum of the actual particle
G4double finalKineticEnergy = KineticEnergy - DeltaKineticEnergy;
G4double Edep = 0. ;
if (finalKineticEnergy > MinKineticEnergy)
{
G4double finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
G4double finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
G4double finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
G4double finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz) ;
finalPx /= finalMomentum ;
finalPy /= finalMomentum ;
finalPz /= finalMomentum ;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
}
else
{
finalKineticEnergy = 0.;
Edep = finalKineticEnergy ;
if (Charge < 0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( theDeltaRay );
aParticleChange.SetLocalEnergyDeposit (Edep);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationPlus::PrintInfoDefinition()
{
G4String comments = "delta cross sections from Moller+Bhabha. ";
comments += "Good description from 1 KeV to 100 GeV.\n";
comments += " delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4eplusAnnihilation.cc,v 1.1.10.1.2.1 1999/12/08 17:34:26 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4eplusAnnihilation.cc,v 1.2 1999/12/15 14:51:53 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// --------------------------------------------------------------
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4hIonisation.cc,v 1.6.8.1.2.1 1999/12/08 17:34:27 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4hIonisation.cc,v 1.11 2000/05/23 14:42:22 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// -------------------------------------------------------------
// GEANT 4 class implementation file
@@ -27,16 +27,23 @@
// 22/10/98: cleanup L.Urban
// 02/02/99: bugs fixed , L.Urban
// 29/07/99: correction in BuildLossTable for low energy, L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// --------------------------------------------------------------
#include "G4hIonisation.hh"
#include "G4UnitsTable.hh"
G4double G4hIonisation::LowerBoundLambda = 1.*keV ;
G4double G4hIonisation::UpperBoundLambda = 100.*TeV ;
G4int G4hIonisation::NbinLambda = 100 ;
G4double G4hIonisation::Tmincut = 1.*keV ;
// constructor and destructor
G4hIonisation::G4hIonisation(const G4String& processName)
: G4hEnergyLoss(processName),
: G4VhEnergyLoss(processName),
theMeanFreePathTable(NULL),
theProton (G4Proton::Proton()),
theAntiProton (G4AntiProton::AntiProton()),
@@ -51,24 +58,16 @@ G4hIonisation::~G4hIonisation()
}
}
void G4hIonisation::SetPhysicsTableBining(G4double lowE, G4double highE,
G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE;
TotBin = nBins ;
}
// methods.............................................
void G4hIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
if(&aParticleType == G4Proton::Proton())
{
LowestKineticEnergy= 1.00*keV;
HighestKineticEnergy= 100.*TeV;
TotBin=100 ;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss() ;
HighestKineticEnergy = GetUpperBoundEloss() ;
TotBin = GetNbinEloss() ;
ParticleMass = aParticleType.GetPDGMass() ;
@@ -176,7 +175,7 @@ void G4hIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
// get electron cut in kin. energy for the material
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[J] ;
DeltaCutInKineticEnergyNow = G4std::max(DeltaCutInKineticEnergy[J],Tmincut) ;
// some local variables -------------------
G4double tau,tau0,Tmax,gamma,bg2,beta2,rcut,delta,x,sh ;
@@ -317,7 +316,7 @@ void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
LowerBoundLambda,UpperBoundLambda,NbinLambda);
// compute the (macroscopic) cross section first
@@ -335,9 +334,10 @@ void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
// ( it is the SAME for ALL the ELEMENTS in THIS MATERIAL )
// ------------------------------------------------------
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[J] ;
DeltaCutInKineticEnergyNow =G4std::max(DeltaCutInKineticEnergy[J],Tmincut) ;
for ( G4int i = 0 ; i < TotBin ; i++ )
for ( G4int i = 0 ; i < NbinLambda ; i++ )
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
@@ -450,7 +450,8 @@ G4VParticleChange* G4hIonisation::PostStepDoIt(
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection() ;
// get kinetic energy cut for the electron....
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[aMaterial->GetIndex()];
DeltaCutInKineticEnergyNow =
G4std::max(DeltaCutInKineticEnergy[aMaterial->GetIndex()],Tmincut);
// some kinematics......................
@@ -1,574 +0,0 @@
// 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: G4hIonisationPlus.cc,v 1.3.8.1.2.1 1999/12/08 17:34:27 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
//
// -------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4hIonisationPlus physics process -----------
// by Laszlo Urban, 30 May 1997
// **************************************************************
// It is the first implementation of the NEW IONISATION PROCESS.
// It calculates the ionisation of charged hadrons.
// **************************************************************
// corrected by L.Urban on 24/09/97
// several bugs corrected by L.Urban on 13/01/98
// 07-04-98: remove 'tracking cut' of the ionizing particle, MMa
// 22/10/98: cleanup L.Urban
// 02/02/99: bugs fixed , L.Urban
// --------------------------------------------------------------
#include "G4hIonisationPlus.hh"
#include "G4UnitsTable.hh"
// constructor and destructor
G4hIonisationPlus::G4hIonisationPlus(const G4String& processName)
: G4hEnergyLossPlus(processName),
theMeanFreePathTable(NULL),
theProton (G4Proton::Proton()),
theAntiProton (G4AntiProton::AntiProton()),
theElectron ( G4Electron::Electron() )
{ }
G4hIonisationPlus::~G4hIonisationPlus()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
}
void G4hIonisationPlus::SetPhysicsTableBining(G4double lowE, G4double highE,
G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE;
TotBin = nBins ;
}
// methods.............................................
void G4hIonisationPlus::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
if(&aParticleType == G4Proton::Proton())
{
LowestKineticEnergy= 1.00*keV;
HighestKineticEnergy= 100.*TeV;
TotBin=100 ;
}
ParticleMass = aParticleType.GetPDGMass() ;
Charge = aParticleType.GetPDGCharge();
G4double ElectronCutInRange = G4Electron::Electron()->GetCuts();
DeltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
if(Charge>0.)
{
if( (ptableElectronCutInRange != ElectronCutInRange)
|| (theDEDXpTable == NULL))
{
BuildLossTable(aParticleType) ;
RecorderOfpProcess[CounterOfpProcess] = theLossTable ;
CounterOfpProcess++;
}
}
else
{
if( (pbartableElectronCutInRange != ElectronCutInRange)
|| (theDEDXpbarTable == NULL))
{
BuildLossTable(aParticleType) ;
RecorderOfpbarProcess[CounterOfpbarProcess] = theLossTable ;
CounterOfpbarProcess++;
}
}
BuildLambdaTable(aParticleType) ;
BuildDEDXTable(aParticleType) ;
if(&aParticleType == G4Proton::Proton())
PrintInfoDefinition();
}
void G4hIonisationPlus::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
// cuts for electron ....................
DeltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
G4double LowEdgeEnergy , ionloss ;
G4double RateMass ;
G4double deltaloss ;
G4bool isOutRange ;
static const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
const G4double twoln10 = 2.*log(10.) ;
const G4double Factor = twopi_mc2_rcl2 ;
const G4double bg2lim = 0.0169 , taulim = 8.4146e-3 ;
RateMass = electron_mass_c2/proton_mass_c2 ;
// create table
G4int numOfMaterials = theMaterialTable->length();
if ( theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
// get material parameters needed for the energy loss calculation
G4double ElectronDensity,Eexc,Eexc2,Cden,Mden,Aden,X0den,X1den,taul ;
G4double* ShellCorrectionVector;
const G4Material* material= (*theMaterialTable)[J];
ElectronDensity = material->GetElectronDensity();
Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
Eexc2 = Eexc*Eexc ;
Cden = material->GetIonisation()->GetCdensity();
Mden = material->GetIonisation()->GetMdensity();
Aden = material->GetIonisation()->GetAdensity();
X0den = material->GetIonisation()->GetX0density();
X1den = material->GetIonisation()->GetX1density();
taul = material->GetIonisation()->GetTaul() ;
ShellCorrectionVector = material->GetIonisation()->
GetShellCorrectionVector();
// get elements in the actual material,
// they are needed for the low energy part ....
const G4ElementVector* theElementVector=
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector=
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements=
material->GetNumberOfElements() ;
// get electron cut in kin. energy for the material
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[J] ;
// some local variables -------------------
G4double tau,tau0,Tmax,gamma,bg2,beta2,rcut,delta,x,sh ;
// now comes the loop for the kinetic energy values*****************
for (G4int i = 0 ; i < TotBin ; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
tau = LowEdgeEnergy/proton_mass_c2 ;
gamma = tau +1. ;
bg2 = tau*(tau+2.) ;
beta2 = bg2/(gamma*gamma) ;
Tmax = 2.*electron_mass_c2*bg2
/(1.+2.*gamma*RateMass+RateMass*RateMass) ;
if ( tau < taul )
// low energy part , parametrized energy loss formulae
{
ionloss = 0. ;
deltaloss = 0. ;
// loop for the elements in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)(iel);
if ( tau < element->GetIonisation()->GetTau0())
ionloss += theAtomicNumDensityVector[iel]
*( element->GetIonisation()->GetAlow()*sqrt(tau)
+element->GetIonisation()->GetBlow()*tau) ;
else
ionloss += theAtomicNumDensityVector[iel]
* element->GetIonisation()->GetClow()/sqrt(tau) ;
}
if ( DeltaCutInKineticEnergyNow < Tmax)
{
deltaloss = log(Tmax/DeltaCutInKineticEnergyNow)-
beta2*(1.-DeltaCutInKineticEnergyNow/Tmax) ;
if(aParticleType.GetPDGSpin() == 0.5)
deltaloss += 0.25*(Tmax-DeltaCutInKineticEnergyNow)*
(Tmax-DeltaCutInKineticEnergyNow)/
(LowEdgeEnergy*LowEdgeEnergy+proton_mass_c2*proton_mass_c2) ;
deltaloss *= Factor*ElectronDensity/beta2 ;
}
ionloss -= deltaloss ;
}
else
// high energy part , Bethe-Bloch formula
{
if ( DeltaCutInKineticEnergyNow < Tmax)
rcut = DeltaCutInKineticEnergyNow/Tmax ;
else
rcut = 1.;
ionloss = log(2.*electron_mass_c2*bg2*Tmax/Eexc2)
+log(rcut)-(1.+rcut)*beta2 ;
// density correction
x = log(bg2)/twoln10 ;
if ( x < X0den )
delta = 0. ;
else
{
delta = twoln10*x - Cden ;
if ( x < X1den )
delta += Aden*pow((X1den-x),Mden) ;
}
// shell correction
if ( bg2 > bg2lim ) {
sh = 0. ;
x = 1. ;
for (G4int k=0; k<=2; k++) {
x *= bg2 ;
sh += ShellCorrectionVector[k]/x;
}
}
else {
sh = 0. ;
x = 1. ;
for (G4int k=0; k<=2; k++) {
x *= bg2lim ;
sh += ShellCorrectionVector[k]/x;
}
sh *= log(tau/taul)/log(taulim/taul) ;
}
// now you can compute the total ionization loss
ionloss -= delta + sh ;
ionloss *= Factor*ElectronDensity/beta2 ;
}
if ( ionloss <= 0.)
ionloss = 0. ;
aVector->PutValue(i,ionloss) ;
}
theLossTable->insert(aVector);
}
}
void G4hIonisationPlus::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
// Build mean free path tables for the delta ray production process
// tables are built for MATERIALS
G4double LowEdgeEnergy , Value ,sigma ;
G4bool isOutRange ;
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
//create table
G4int numOfMaterials = theMaterialTable->length();
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
theMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
// get electron and particle cuts in kinetic energy
DeltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
// loop for materials
for (G4int J=0 ; J < numOfMaterials; J++)
{
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
// compute the (macroscopic) cross section first
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector=
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
const G4int NumberOfElements=
material->GetNumberOfElements() ;
// get the electron kinetic energy cut for the actual material,
// it will be used in ComputeMicroscopicCrossSection
// ( it is the SAME for ALL the ELEMENTS in THIS MATERIAL )
// ------------------------------------------------------
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[J] ;
for ( G4int i = 0 ; i < TotBin ; i++ )
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
sigma = 0. ;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
sigma += theAtomicNumDensityVector[iel]*
ComputeMicroscopicCrossSection(aParticleType,
LowEdgeEnergy,
(*theElementVector)(iel)->GetZ() ) ;
}
// mean free path = 1./macroscopic cross section
Value = sigma<=0 ? DBL_MAX : 1./sigma ;
aVector->PutValue(i, Value) ;
}
theMeanFreePathTable->insert(aVector);
}
}
G4double G4hIonisationPlus::ComputeMicroscopicCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber)
{
//******************************************************************
// cross section formula is OK for spin=0 and 1/2 only !
// *****************************************************************
// calculates the microscopic cross section in GEANT4 internal units
// ( it is called for elements , AtomicNumber = Z )
G4double TotalEnergy,
betasquare,
MaxKineticEnergyTransfer,TotalCrossSection,tempvar;
// get particle data ...................................
TotalEnergy=KineticEnergy + ParticleMass;
// some kinematics......................
betasquare = KineticEnergy*(TotalEnergy+ParticleMass)
/(TotalEnergy*TotalEnergy);
tempvar = ParticleMass+electron_mass_c2;
MaxKineticEnergyTransfer = 2.*electron_mass_c2*KineticEnergy
*(TotalEnergy+ParticleMass)
/(tempvar*tempvar+2.*electron_mass_c2*KineticEnergy);
// now you can calculate the total cross section ------------------
if( MaxKineticEnergyTransfer > DeltaCutInKineticEnergyNow )
{
tempvar=DeltaCutInKineticEnergyNow/MaxKineticEnergyTransfer;
TotalCrossSection = (1.-tempvar*(1.-betasquare*log(tempvar)))
/DeltaCutInKineticEnergyNow;
// +term for spin=1/2 particle
if(aParticleType.GetPDGSpin() == 0.5)
{
TotalCrossSection += 0.5
*(MaxKineticEnergyTransfer-DeltaCutInKineticEnergyNow)
/(TotalEnergy*TotalEnergy);
G4double Section = 0.5
*(MaxKineticEnergyTransfer-DeltaCutInKineticEnergyNow)
/(TotalEnergy*TotalEnergy);
}
TotalCrossSection = twopi_mc2_rcl2 * AtomicNumber
*TotalCrossSection/betasquare;
}
else
TotalCrossSection= 0. ;
return TotalCrossSection ;
}
G4VParticleChange* G4hIonisationPlus::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
// Units are expressed in GEANT4 internal units.
const G4DynamicParticle* aParticle ;
G4Material* aMaterial;
G4double KineticEnergy,TotalEnergy,TotalMomentum,
betasquare,MaxKineticEnergyTransfer,
DeltaKineticEnergy,DeltaTotalMomentum,costheta,sintheta,phi,
dirx,diry,dirz,finalKineticEnergy,finalPx,finalPy,finalPz,
x,xc,te2,grej,Psquare,Esquare,summass,rate,grejc,finalMomentum ;
aParticleChange.Initialize(trackData) ;
aMaterial = trackData.GetMaterial() ;
aParticle = trackData.GetDynamicParticle() ;
ParticleMass=aParticle->GetDefinition()->GetPDGMass();
KineticEnergy=aParticle->GetKineticEnergy();
TotalEnergy=KineticEnergy + ParticleMass ;
Psquare=KineticEnergy*(TotalEnergy+ParticleMass) ;
Esquare=TotalEnergy*TotalEnergy ;
summass = ParticleMass + electron_mass_c2 ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection() ;
// get kinetic energy cut for the electron....
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[aMaterial->GetIndex()];
// some kinematics......................
betasquare=Psquare/Esquare ;
MaxKineticEnergyTransfer = 2.*electron_mass_c2*Psquare
/(summass*summass+2.*electron_mass_c2*KineticEnergy);
// sampling kinetic energy of the delta ray
if( MaxKineticEnergyTransfer <= DeltaCutInKineticEnergyNow )
{
// pathological case (it should not happen ,
// there is no change at all).....
// return &aParticleChange;
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
else
{
// normal case ......................................
xc=DeltaCutInKineticEnergyNow/MaxKineticEnergyTransfer ;
rate=MaxKineticEnergyTransfer/TotalEnergy ;
if(aParticle->GetDefinition()->GetPDGSpin() == 1)
te2=0.5*rate*rate ;
else
te2=0. ;
// sampling follows ...
grejc=1.-betasquare*xc+te2*xc*xc ;
do {
x=xc/(1.-(1.-xc)*G4UniformRand());
grej=(1.-x*(betasquare-x*te2))/grejc ;
} while( G4UniformRand()>grej );
}
DeltaKineticEnergy = x * MaxKineticEnergyTransfer ;
if(DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
DeltaTotalMomentum = sqrt(DeltaKineticEnergy * (DeltaKineticEnergy +
2. * electron_mass_c2 )) ;
TotalMomentum = sqrt(Psquare) ;
costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum) ;
// protection against costheta > 1 or < -1 ---------------
if ( costheta < -1. )
costheta = -1. ;
if ( costheta > +1. )
costheta = +1. ;
// direction of the delta electron ........
phi = twopi * G4UniformRand() ;
sintheta = sqrt((1.+costheta)*(1.-costheta));
dirx = sintheta * cos(phi) ;
diry = sintheta * sin(phi) ;
dirz = costheta ;
G4ThreeVector DeltaDirection(dirx,diry,dirz) ;
DeltaDirection.rotateUz(ParticleDirection) ;
// create G4DynamicParticle object for delta ray
G4DynamicParticle *theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
finalKineticEnergy = KineticEnergy - DeltaKineticEnergy ;
G4double Edep = 0 ;
if (finalKineticEnergy > MinKineticEnergy)
{
finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz) ;
finalPx /= finalMomentum ;
finalPy /= finalMomentum ;
finalPz /= finalMomentum ;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
}
else
{
finalKineticEnergy = 0. ;
Edep = finalKineticEnergy ;
if (aParticle->GetDefinition()->GetParticleName() == "proton")
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( theDeltaRay );
aParticleChange.SetLocalEnergyDeposit (Edep);
//ResetNumberOfInteractionLengthLeft();
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
void G4hIonisationPlus::PrintInfoDefinition()
{
G4String comments = " Knock-on electron cross sections . ";
comments += "\n Good description above the mean excitation energy.\n";
comments += " delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4ionIonisation.cc,v 1.3.8.1.2.1 1999/12/08 17:34:27 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4ionIonisation.cc,v 1.4 1999/12/15 14:51:54 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// -------------------------------------------------------------
// GEANT 4 class implementation file