Import Geant4 3.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 15:55:53 +02:00
parent e7d7193284
commit cfcb558cfe
3050 changed files with 91703 additions and 48310 deletions
@@ -5,21 +5,14 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4ComptonScattering.cc,v 1.3 1999/12/15 14:51:50 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4ComptonScattering.cc,v 1.4 2000/11/17 15:03:17 maire Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
//
// --------------------------------------------------------------
// 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
// ------------ G4ComptonScattering physics process --------
//------------ G4ComptonScattering physics process --------
// by Michel Maire, April 1996
// **************************************************************
//
// --------------------------------------------------------------
// 28-05-96, DoIt() small change in ElecDirection, by M.Maire
// 10-06-96, simplification in ComputeMicroscopicCrossSection(), by M.Maire
// 21-06-96, SetCuts implementation, M.Maire
@@ -1,113 +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: G4EnergyLossMessenger.cc,v 1.5 2000/05/23 14:42:21 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4EnergyLossMessenger.hh"
#include "G4VeEnergyLoss.hh"
#include "G4VhEnergyLoss.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
#include "G4UIcmdWithABool.hh"
#include "g4std/strstream"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EnergyLossMessenger::G4EnergyLossMessenger()
{
RndmStepCmd = new G4UIcmdWithABool("/process/eLoss/rndmStep",this);
RndmStepCmd->SetGuidance("Randomize the proposed step for eLoss.");
RndmStepCmd->SetParameterName("choice",true);
RndmStepCmd->SetDefaultValue(false);
RndmStepCmd->AvailableForStates(Idle);
EnlossFlucCmd = new G4UIcmdWithABool("/process/eLoss/fluct",this);
EnlossFlucCmd->SetGuidance("Switch on/off the energy loss fluctuation.");
EnlossFlucCmd->SetParameterName("choice",true);
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");
StepFuncCmd->SetGuidance(" finalRange: range for final step");
G4UIparameter* dRoverRPrm = new G4UIparameter("dRoverR",'d',false);
dRoverRPrm->SetGuidance("max Range variation per step (fractional number)");
dRoverRPrm->SetParameterRange("dRoverR>0. && dRoverR<=1.");
StepFuncCmd->SetParameter(dRoverRPrm);
G4UIparameter* finalRangePrm = new G4UIparameter("finalRange",'d',false);
finalRangePrm->SetGuidance("range for final step");
finalRangePrm->SetParameterRange("finalRange>0.");
StepFuncCmd->SetParameter(finalRangePrm);
G4UIparameter* unitPrm = new G4UIparameter("unit",'s',true);
unitPrm->SetGuidance("unit of finalRange");
unitPrm->SetDefaultValue("mm");
G4String unitCandidates = G4UIcommand::UnitsList(G4UIcommand::CategoryOf("mm"));
unitPrm->SetParameterCandidates(unitCandidates);
StepFuncCmd->SetParameter(unitPrm);
StepFuncCmd->AvailableForStates(Idle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EnergyLossMessenger::~G4EnergyLossMessenger()
{
delete RndmStepCmd;
delete EnlossFlucCmd;
delete SubSecCmd;
delete StepFuncCmd;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
{
if (command == RndmStepCmd)
{ G4VeEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
G4VhEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
}
if (command == EnlossFlucCmd)
{ 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)
{
G4double v1,v2;
char unts[30];
const char* t = newValue;
G4std::istrstream is((char*)t);
is >> v1 >> v2 >> unts;
G4String unt = unts;
v2 *= G4UIcommand::ValueOf(unt);
G4VeEnergyLoss::SetStepFunction(v1,v2);
G4VhEnergyLoss::SetStepFunction(v1,v2);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4GammaConversion.cc,v 1.3 1999/12/15 14:51:50 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4GammaConversion.cc,v 1.4 2000/08/03 08:36:52 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
//
// --------------------------------------------------------------
@@ -14,7 +14,7 @@
// CERN Geneva Switzerland
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// GEANT4 Collaboration
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4GammaConversion physics process --------
@@ -280,7 +280,7 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
//
G4double ElectTotEnergy, PositTotEnergy;
if (RandFlat::shootBit())
if (RandBit::shootBit())
{
ElectTotEnergy = (1.-epsil)*GammaEnergy;
PositTotEnergy = epsil*GammaEnergy;
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4IeBremsstrahlung.cc,v 1.5 2000/04/25 14:33:08 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
// GEANT4 tag $Name: geant4-03-00 $
//
// $Id:
// --------------------------------------------------------------
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4IeIonisation.cc,v 1.5 2000/04/25 14:33:08 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
// GEANT4 tag $Name: geant4-03-00 $
//
// $Id:
// -------------------------------------------------------------
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4IeplusAnnihilation.cc,v 1.6 1999/12/15 14:51:50 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// GEANT4 tag $Name: geant4-03-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.7 2000/04/25 14:33:09 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4IhIonisation.cc,v 1.9 2000/08/01 08:12:13 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
// -------------------------------------------------------------
// GEANT 4 class implementation file
@@ -35,7 +35,12 @@
G4IhIonisation::G4IhIonisation(const G4String& processName)
: G4VIhEnergyLoss(processName),
theMeanFreePathTable(NULL),
theMeanFreePathTable(0),
theNlambdaTable(0),
theInverseNlambdaTable(0),
theCoeffATable(0),
theCoeffBTable(0),
theCoeffCTable(0),
NumberOfBuildPhysicsTableCalls(0),
theProton (G4Proton::Proton()),
theAntiProton (G4AntiProton::AntiProton()),
@@ -5,28 +5,20 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4PAIonisation.cc,v 1.8 2000/05/02 15:12:45 grichine Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4PAIonisation.cc,v 1.13 2000/09/22 14:46:38 grichine Exp $
// GEANT4 tag $Name: geant4-03-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
// ---------- G4PAIonisation physics process -----------
// modified by V.Grichine 27.11.97
// **************************************************************
// It is the first implementation of the NEW IONISATION PROCESS.
// It calculates the ionisation of charged hadrons.
// **************************************************************
//
// 12.07.00, V.Grichine - modifications in BuildPAIonisationTable
// 11.07.00, V.Grichine - GetRandomEnergyTransfer, and PostStepDoIt
// modifications
// 03.07.00, V.Grichine - modifications in AlongStepDoIt
// 08-04-98: remove 'traking cut' of the ionizing particle, MMa
// 30-11-97: V. Grichine
//
//
// **************************************************************
#include "G4PAIonisation.hh"
#include "G4PAIxSection.hh"
@@ -73,10 +65,10 @@ G4PAIonisation::G4PAIonisation( const G4String& materialName,
G4Exception("Invalid material name in G4PAIonisation constructor") ;
}
ComputeSandiaPhotoAbsCof() ;
BuildPAIonisationTable() ;
// G4cout<<"G4PAIonisation constructor is called"<<G4endl ;
// BuildPAIonisationTable() ;
}
///////////////////////////////////////////////////////////////////////////
@@ -95,7 +87,13 @@ G4PAIonisation::~G4PAIonisation()
fPAItransferBank->clearAndDestroy() ;
delete fPAItransferBank ;
}
for(G4int i=0;i<fSandiaIntervalNumber;i++)
{
delete[] fSandiaPhotoAbsCof[i] ;
}
delete[] fSandiaPhotoAbsCof ;
// if(fProtonEnergyVector) delete fProtonEnergyVector ;
}
/////////////////////////////////////////////////////////////////////////
@@ -167,7 +165,7 @@ G4PAIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
G4double Chargesquare = Charge*Charge ;
CutInRange = aParticleType.GetLengthCuts();
BuildLossTable(aParticleType) ;
// BuildLossTable(aParticleType) ;
if(Charge>0.)
{
@@ -193,47 +191,18 @@ G4PAIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// the tables are built for MATERIALS
// *********
void
G4PAIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
//G4PAIonisation::BuildPAIonisationTable()
void
G4PAIonisation::BuildPAIonisationTable()
{
G4double Charge = aParticleType.GetPDGCharge() ;
G4double LowEdgeEnergy , ionloss ;
G4double RateMass ;
G4bool isOutRange ;
static const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const G4double SmallIonLoss = DBL_MIN ;
const G4double twoln10 = 2.*log(10.) ;
const G4double Factor = twopi_mc2_rcl2 ;
const G4double bg2lim = 0.0169 , taulim = 8.4146e-3 ;
// cuts for p/pbar and electron
// /* *********************************************
if(Charge>0.)
{
ParticleCutInKineticEnergy = theProton->GetCutsInEnergy() ;
}
else
{
ParticleCutInKineticEnergy = theAntiProton->GetCutsInEnergy() ;
}
DeltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
// ************************************************** */
ParticleMass = proton_mass_c2;
RateMass = electron_mass_c2/ParticleMass ;
G4int numOfMaterials = theMaterialTable->length(); // create table
G4double massRatio, tau, Tmax, gamma, bg2 ;
if ( theLossTable)
{
theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = new G4PhysicsTable(numOfMaterials);
// theLossTable = new G4PhysicsTable(1);
theLossTable = new G4PhysicsTable();
if( fPAItransferBank )
{
@@ -241,118 +210,72 @@ G4PAIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
delete fPAItransferBank ;
}
fPAItransferBank = new G4PhysicsTable(TotBin) ;
for (G4int J=0; J<numOfMaterials; J++) // loop for materials
{
if( J != fMatIndex ) continue ; // skip another material
//create physics vector then fill it ....
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector( LowestKineticEnergy,
G4PhysicsLogVector* aVector = new G4PhysicsLogVector( LowestKineticEnergy,
HighestKineticEnergy,
TotBin ) ;
// get material parameters needed for the energy loss calculation
// From gas detector experience
G4double ElectronDensity, Eexc, Eexc2, Cden, Mden, Aden, X0den, X1den, taul ;
G4double* ShellCorrectionVector ;
const G4Material* material= (*theMaterialTable)[J];
DeltaCutInKineticEnergyNow = 100*keV ;
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();
for (G4int i = 0 ; i < TotBin ; i++) //The loop for the kinetic energy
{
LowEdgeEnergy = fProtonEnergyVector->GetLowEdgeEnergy(i) ;
tau = LowEdgeEnergy/proton_mass_c2 ;
// 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] ;
// From gas detector experience
DeltaCutInKineticEnergyNow = 100*keV ;
// some local variables
G4double tau,tau0,Tmax,gamma,bg2,beta2,rcut,delta,x,sh ;
// G4cout<<"Material no. = "<<J<<"\t"<<"TotBin = "<<TotBin<<G4endl ;
for (G4int i = 0 ; i < TotBin ; i++) //The loop for the kinetic energy
if(tau < 0.01) // was 0.11, 0.05
{
G4PhysicsFreeVector* transferVector ;
LowEdgeEnergy = fProtonEnergyVector->GetLowEdgeEnergy(i) ;
tau = LowEdgeEnergy/ParticleMass ;
// high energy part , <dE/dx> according PAI cross section
{
if(tau < 0.01) // was 0.11, 0.05
{
tau = 0.01 ;
}
gamma = tau +1. ;
}
gamma = tau +1. ;
// G4cout<<"gamma = "<<gamma<<endl ;
// G4cout<<"gamma = "<<gamma<<endl ;
bg2 = tau*(tau+2.) ;
beta2 = bg2/(gamma*gamma) ;
Tmax = 2.*electron_mass_c2*bg2
/(1.+2.*gamma*RateMass+RateMass*RateMass) ;
bg2 = tau*(tau + 2. ) ;
massRatio = electron_mass_c2/proton_mass_c2 ;
if ( DeltaCutInKineticEnergyNow > Tmax) // was <
{
DeltaCutInKineticEnergyNow = Tmax ;
}
G4PAIxSection protonPAI(J,DeltaCutInKineticEnergyNow,bg2,
fSandiaPhotoAbsCof,fSandiaIntervalNumber) ;
Tmax = 2.*electron_mass_c2*bg2/(1.+2.*gamma*massRatio+massRatio*massRatio) ;
if ( DeltaCutInKineticEnergyNow > Tmax) // was <
{
DeltaCutInKineticEnergyNow = Tmax ;
}
G4PAIxSection protonPAI( fMatIndex,
DeltaCutInKineticEnergyNow,
bg2,
fSandiaPhotoAbsCof,
fSandiaIntervalNumber ) ;
ionloss = protonPAI.GetMeanEnergyLoss() ; // total <dE/dx>
ionloss = protonPAI.GetMeanEnergyLoss() ; // total <dE/dx>
// G4cout<<"ionloss = "<<ionloss*cm/keV<<" keV/cm"<<endl ;
// G4cout<<"n1 = "<<protonPAI.GetIntegralPAIxSection(1)*cm<<" 1/cm"<<endl ;
// G4cout<<"protonPAI.GetSplineSize() = "<<
// protonPAI.GetSplineSize()<<G4endl ;
transferVector = new
G4PhysicsFreeVector* transferVector = new
G4PhysicsFreeVector(protonPAI.GetSplineSize()) ;
for(G4int k=0;k<protonPAI.GetSplineSize();k++)
{
transferVector->PutValue( k ,
for(G4int k=0;k<protonPAI.GetSplineSize();k++)
{
transferVector->PutValue( k ,
protonPAI.GetSplineEnergy(k+1),
protonPAI.GetIntegralPAIxSection(k+1) ) ;
}
}
if ( ionloss <= 0.)
{
ionloss = SmallIonLoss ;
}
aVector->PutValue(i,ionloss) ;
}
if ( ionloss <= 0.) ionloss = DBL_MIN ;
fPAItransferBank->insertAt(i,transferVector) ;
aVector->PutValue(i,ionloss) ;
fPAItransferBank->insertAt(i,transferVector) ;
// delete[] transferVector ;
} // end of Tkin loop
theLossTable->insert(aVector);
} // end of material loop
} // end of Tkin loop
theLossTable->insert(aVector);
// end of material loop
// G4cout<<"G4PAIonisation::BuildPAIonisationTable() have been called"<<G4endl ;
// G4cout<<"G4PAIonisation::BuildLossTable() have been called"<<G4endl ;
}
@@ -492,144 +415,38 @@ G4VParticleChange*
G4PAIonisation::PostStepDoIt( const G4Track& trackData,
const G4Step& stepData )
{
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 ;
G4double Charge;
G4double kinE, massRatio, scaledTkin, energyTransfer, finalTkin ;
aParticleChange.Initialize(trackData) ;
aMaterial = trackData.GetMaterial() ;
aParticle = trackData.GetDynamicParticle() ;
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle() ;
Charge=aParticle->GetDefinition()->GetPDGCharge();
KineticEnergy=aParticle->GetKineticEnergy();
ParticleMass=aParticle->GetDefinition()->GetPDGMass();
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()];
betasquare=Psquare/Esquare ; // kinematics
MaxKineticEnergyTransfer = 2.*electron_mass_c2*Psquare
/(summass*summass+2.*electron_mass_c2*KineticEnergy);
// sampling kinetic energy of the delta ray
if( MaxKineticEnergyTransfer <= DeltaCutInKineticEnergyNow ) // no change at all
if( trackData.GetMaterial()->GetIndex() != fMatIndex )
{
//return &aParticleChange;
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
else // normal case
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
kinE = aParticle->GetKineticEnergy() ;
massRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass() ;
scaledTkin = kinE*massRatio ;
energyTransfer = GetRandomEnergyTransfer(scaledTkin) ;
finalTkin = kinE - energyTransfer ;
// kill the particle if the kinetic energy <= 0
if (finalTkin <= 0. )
{
xc=DeltaCutInKineticEnergyNow/MaxKineticEnergyTransfer ;
rate=MaxKineticEnergyTransfer/TotalEnergy ;
if(aParticle->GetDefinition()->GetPDGSpin() == 1)
{
te2 = 0.5*rate*rate ;
}
else
{
te2 = 0.0 ;
}
grejc=1.-betasquare*xc+te2*xc*xc ; // sampling follows ...
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) ;
if ( costheta < -1. ) // protection against costheta > 1 or < -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 ;
if (finalKineticEnergy > 0.)
{
// changed energy and momentum of the actual particle
finalMomentum=sqrt(finalKineticEnergy*
(finalKineticEnergy+2.*ParticleMass)) ;
finalPx = (TotalMomentum*ParticleDirection.x()
-DeltaTotalMomentum*DeltaDirection.x())/finalMomentum ;
finalPy = (TotalMomentum*ParticleDirection.y()
-DeltaTotalMomentum*DeltaDirection.y())/finalMomentum ;
finalPz = (TotalMomentum*ParticleDirection.z()
-DeltaTotalMomentum*DeltaDirection.z())/finalMomentum ;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
}
else
{
finalKineticEnergy = 0. ;
if (aParticle->GetDefinition()->GetParticleName() == "proton")
{
aParticleChange.SetStatusChange(fStopAndKill);
}
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( theDeltaRay );
aParticleChange.SetLocalEnergyDeposit (0.);
finalTkin = 0.;
if (aParticle->GetDefinition()->GetParticleName() == "proton")
{
aParticleChange.SetStatusChange( fStopAndKill ) ;
}
else aParticleChange.SetStatusChange( fStopButAlive ) ;
}
aParticleChange.SetNumberOfSecondaries(0) ;
aParticleChange.SetEnergyChange( finalTkin ) ;
aParticleChange.SetLocalEnergyDeposit (energyTransfer) ;
// ResetNumberOfInteractionLengthLeft;
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// return &aParticleChange ;
}
@@ -695,7 +512,7 @@ G4VParticleChange* G4PAIonisation::AlongStepDoIt( const G4Track& trackData,
// now the loss with fluctuation
finalT = E-GetLossWithFluct(Step,aParticle,aMaterial)*Chargesquare ;
finalT = E-GetLossWithFluct(Step,aParticle,aMaterial) ;
if (finalT<0.) finalT = 0. ;
@@ -722,7 +539,7 @@ G4VParticleChange* G4PAIonisation::AlongStepDoIt( const G4Track& trackData,
///////////////////////////////////////////////////////////////////////
//
//
// Returns random energy loss from step
G4double
G4PAIonisation::GetLossWithFluct( G4double Step,
@@ -736,19 +553,17 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
// G4cout<<"G4VPAIenergyLoss::GetLossWithFluct"<<G4endl ;
G4double loss = 0.0 ;
G4double loss = 0.0, charge2 ;
G4double transfer, position, E1, E2, W1, W2, W, firstMu, secondMu ;
G4double Tkin = aParticle->GetKineticEnergy() ;
G4double MassRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass() ;
G4double charge = aParticle->GetDefinition()->GetPDGCharge() ;
charge2 = charge*charge ;
G4double TkinScaled = Tkin*MassRatio ;
G4PhysicsLogVector*
aLogVector = new G4PhysicsLogVector( G4PAIonisation::GetMinKineticEnergy(),
G4PAIonisation::GetMaxKineticEnergy(),
G4PAIonisation::GetBinNumber() ) ;
for(iTkin=0;iTkin<G4PAIonisation::GetBinNumber();iTkin++)
{
if(TkinScaled < aLogVector->GetLowEdgeEnergy(iTkin)) // <= ?
if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) // <= ?
{
break ;
}
@@ -757,13 +572,11 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
// G4cout<<"iPlace = "<<iPlace<<endl ;
G4PhysicsVector* firstVector = (*fPAItransferBank)(iPlace) ;
G4PhysicsVector* secondVector = (*fPAItransferBank)(iPlace + 1) ;
if(iTkin == G4PAIonisation::GetBinNumber()) // Fermi plato, try from left
{
numOfCollisions = RandPoisson::shoot((*(*fPAItransferBank)(iPlace))(0)*Step) ;
numOfCollisions = RandPoisson::
shoot((*(*fPAItransferBank)(iPlace))(0)*Step*charge2) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
@@ -774,7 +587,8 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
{
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
}
loss += (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
// loss += (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
loss += GetEnergyTransfer(iPlace,position,iTransfer);
numOfCollisions-- ;
}
}
@@ -783,7 +597,7 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
if(iTkin == 0) // Tkin is too small, trying from right only
{
numOfCollisions = RandPoisson::
shoot((*(*fPAItransferBank)(iPlace+1))(0)*Step) ;
shoot((*(*fPAItransferBank)(iPlace+1))(0)*Step*charge2) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
@@ -795,14 +609,15 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
{
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
}
loss += (*fPAItransferBank)(iPlace+1)->GetLowEdgeEnergy(iTransfer) ;
// loss += (*fPAItransferBank)(iPlace+1)->GetLowEdgeEnergy(iTransfer) ;
loss += GetEnergyTransfer(iPlace+1,position,iTransfer);
numOfCollisions-- ;
}
}
else // general case: Tkin between two vectors of the material
{
E1 = aLogVector->GetLowEdgeEnergy(iTkin - 1) ;
E2 = aLogVector->GetLowEdgeEnergy(iTkin) ;
E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1) ;
E2 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin) ;
W = 1.0/(E2 - E1) ;
W1 = (E2 - TkinScaled)*W ;
W2 = (TkinScaled - E1)*W ;
@@ -814,8 +629,7 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
numOfCollisions = RandPoisson::shoot(
( (*(*fPAItransferBank)(iPlace))(0)*W1 +
(*(*fPAItransferBank)(iPlace+1))(0)*W2 )*Step) ;
(*(*fPAItransferBank)(iPlace+1))(0)*W2 )*Step*charge2) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<endl ;
@@ -835,7 +649,8 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
break ;
}
}
loss += (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
// loss += (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
loss += GetEnergyTransfer(iPlace,position,iTransfer);
numOfCollisions-- ;
}
}
@@ -845,7 +660,125 @@ G4PAIonisation::GetLossWithFluct( G4double Step,
return loss ;
}
///////////////////////////////////////////////////////////////////////
//
// Returns random PAI energy transfer according to passed scaled kinetic
// energy of particle
G4double
G4PAIonisation::GetRandomEnergyTransfer( G4double scaledTkin )
{
// G4cout<<"G4VPAIenergyLoss::GetRandomEnergyTransfer"<<G4endl ;
G4int iTkin, iTransfer, iPlace ;
G4double transfer = 0.0, position, E1, E2, W1, W2, W ;
for(iTkin=0;iTkin<G4PAIonisation::GetBinNumber();iTkin++)
{
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
}
iPlace = iTkin - 1 ;
// G4cout<<"iPlace = "<<iPlace<<endl ;
if(iTkin == G4PAIonisation::GetBinNumber()) // Fermi plato, try from left
{
position = (*(*fPAItransferBank)(iPlace))(0)*G4UniformRand() ;
for(iTransfer=0;;iTransfer++)
{
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
}
// transfer = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
}
else
{
if(iTkin == 0) // Tkin is too small, trying from right only
{
position = (*(*fPAItransferBank)(iPlace+1))(0)*G4UniformRand() ;
for(iTransfer=0;;iTransfer++)
{
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
}
// transfer = (*fPAItransferBank)(iPlace+1)->GetLowEdgeEnergy(iTransfer) ;
transfer = GetEnergyTransfer(iPlace+1,position,iTransfer);
}
else // general case: Tkin between two vectors of the material
{
E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1) ;
E2 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin) ;
W = 1.0/(E2 - E1) ;
W1 = (E2 - scaledTkin)*W ;
W2 = (scaledTkin - E1)*W ;
position =( (*(*fPAItransferBank)(iPlace))(0)*W1 +
(*(*fPAItransferBank)(iPlace+1))(0)*W2 )*G4UniformRand() ;
// G4cout<<position<<"\t" ;
for(iTransfer=0;;iTransfer++)
{
if( position >=
( (*(*fPAItransferBank)(iPlace))(iTransfer)*W1 +
(*(*fPAItransferBank)(iPlace+1))(iTransfer)*W2) ) break ;
}
// transfer = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
}
}
// G4cout<<"PAI transfer = "<<transfer/keV<<" keV"<<endl ;
if(transfer < 0.0 ) transfer = 0.0 ;
return transfer ;
}
///////////////////////////////////////////////////////////////////////
//
// Returns random PAI energy transfer according to passed scaled kinetic
// energy of particle
G4double
G4PAIonisation::GetEnergyTransfer( G4int iPlace, G4double position, G4int iTransfer )
{
G4double x1, x2, y1, y2, result ;
if(iTransfer == 0)
{
result = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
}
else
{
y1 = (*(*fPAItransferBank)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAItransferBank)(iPlace))(iTransfer) ;
x1 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
if ( x1 == x2 ) result = x2 ;
else
{
if ( y1 == y2 ) result = x1 + (x2 - x1)*G4UniformRand() ;
else
{
result = x1 + (position - y1)*(x2 - x1)/(y2 - y1) ;
}
}
}
return result ;
}
//
//
/////////////////////////////////////////////////////////////////////////
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4PAIxSection.cc,v 1.4 1999/12/15 14:51:51 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// GEANT4 tag $Name: geant4-03-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.9 1999/12/15 14:51:52 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4PhotoElectricEffect.cc,v 1.11 2000/06/22 08:57:11 maire Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
//
// --------------------------------------------------------------
@@ -33,6 +33,8 @@
// 06-01-99, use Sandia crossSection below 50 keV, V.Grichine mma
// 20-05-99, protection against very low energy photons ,L.Urban
// 08-06-99, removed this above protection from the DoIt. mma
// 21-06-00, in DoIt, killing photon: aParticleChange.SetEnergyChange(0.); mma
// 22-06-00, in DoIt, absorbe very low energy photon (back to 20-05-99); mma
// --------------------------------------------------------------
#include "G4PhotoElectricEffect.hh"
@@ -242,9 +244,10 @@ G4VParticleChange* G4PhotoElectricEffect::PostStepDoIt(const G4Track& aTrack,
G4int NbOfShells = anElement->GetNbOfAtomicShells();
G4int i=0;
while ((i<NbOfShells)&&(PhotonEnergy<anElement->GetAtomicShell(i))) i++;
if (i==NbOfShells) return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
G4double ElecKineEnergy = PhotonEnergy - anElement->GetAtomicShell(i);
G4double BindingEnergy = 0.;
if (i<NbOfShells) BindingEnergy = anElement->GetAtomicShell(i);
G4double ElecKineEnergy = PhotonEnergy - BindingEnergy;
if ((G4EnergyLossTables::GetRange(G4Electron::Electron(),
ElecKineEnergy,aMaterial)>aStep.GetPostStepPoint()->GetSafety())
||
@@ -266,7 +269,8 @@ G4VParticleChange* G4PhotoElectricEffect::PostStepDoIt(const G4Track& aTrack,
//
// Kill the incident photon
//
aParticleChange.SetLocalEnergyDeposit(PhotonEnergy-ElecKineEnergy);
aParticleChange.SetLocalEnergyDeposit(PhotonEnergy-ElecKineEnergy);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetStatusChange(fStopAndKill);
// Reset NbOfInteractionLengthLeft and return aParticleChange
@@ -5,19 +5,17 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4PolarizedComptonScattering.cc,v 1.2 1999/12/15 14:51:52 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4PolarizedComptonScattering.cc,v 1.4 2000/11/17 15:03:18 maire Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
//
//---------- G4PolarizedComptonScattering physics process -------
// by Vicente Lara, March 1998
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
//
// For information related to this code contact:
// CERN, IT Division, ASD group
//
// ---------- G4PolarizedComptonScattering physics process --------
// by Vicente Lara, March 1998
// **************************************************************
// Corrections by Rui Curado da Silva (Nov. 2000)
// - Sampling of Phi
// - Depolarization probability
//
// --------------------------------------------------------------
@@ -50,6 +48,7 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(const G4Track& aTr
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4ThreeVector GammaPolarization0 = aDynamicGamma->GetPolarization();
if (abs(GammaPolarization0.mag() - 1.e0) > 1.e-14)
G4ComptonScattering::PostStepDoIt(aTrack,aStep);
@@ -81,14 +80,49 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(const G4Track& aTr
greject = 1. - epsilon*sint2/(1.+ epsilonsq);
} while (greject < G4UniformRand());
// ****************************************************
// Phi determination
// ****************************************************
G4double middle;
G4double maximum, minimum;
G4double resolution;
G4double Rand = G4UniformRand();
minimum = 0.;
middle = 0.;
maximum = twopi;
resolution = 0.001;
int j = 0;
while ((j < 100) && (abs(SetPhi(epsilon,sint2,middle,Rand)) > resolution))
{
middle = (maximum + minimum)/2;
if (SetPhi(epsilon,sint2,middle,Rand)*SetPhi(epsilon,sint2,minimum,Rand)<0) {
maximum = middle;
} else {
minimum = middle;
}
j++;
}
//
// scattered gamma angles. ( Z - axis along the parent gamma)
//
G4double cosTeta = 1. - onecost , sinTeta = sqrt (sint2);
G4double Phi = twopi * G4UniformRand() ;
G4double Phi = middle;
G4double dirx = sinTeta*cos(Phi) , diry = sinTeta*sin(Phi) , dirz = cosTeta ;
//
// update G4VParticleChange for the scattered gamma
//
@@ -103,6 +137,8 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(const G4Track& aTr
// Set new direction
G4ThreeVector GammaDirection1 ( dirx,diry,dirz );
// Change reference frame.
SystemOfRefChange(GammaDirection0,GammaDirection1,
GammaPolarization0,GammaPolarization1);
@@ -151,6 +187,20 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(const G4Track& aTr
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4PolarizedComptonScattering::SetPhi(G4double EnergyRate,
G4double sinsqrth,
G4double phi,
G4double rand)
{
G4double cosphi = cos(phi), sinphi = sin(phi);
G4double PhiDetermination = ((twopi*rand - phi)*(EnergyRate + 1./EnergyRate - sinsqrth)) + (sinsqrth*sinphi*cosphi);
return PhiDetermination;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ThreeVector G4PolarizedComptonScattering::SetNewPolarization(G4double EnergyRate,
@@ -160,19 +210,21 @@ G4ThreeVector G4PolarizedComptonScattering::SetNewPolarization(G4double EnergyRa
G4ThreeVector& GammaPolarization0)
{
G4double cosphi = cos(phi), sinphi = sin(phi);
G4double ParallelIntensityPolar = EnergyRate + 1./EnergyRate + 2. - 4.*sinsqrth*cosphi*cosphi;
// G4double ParallelIntensityPolar = EnergyRate + 1./EnergyRate + 2. - 4.*sinsqrth*cosphi*cosphi;
G4double ParallelIntensityPolar = EnergyRate + 1./EnergyRate - 2.*sinsqrth*cosphi*cosphi;
G4double PerpendiIntensityPolar = EnergyRate + 1./EnergyRate - 2.;
G4double PolarizationDegree = sqrt(sinsqrth*sinphi*sinphi + costheta*costheta);
G4double sintheta = sqrt(sinsqrth);
G4ThreeVector GammaPolarization1;
// depolarization probability (1-P)
if ( G4UniformRand() > 0.5*(PerpendiIntensityPolar/ParallelIntensityPolar) )
if ( G4UniformRand() > (PerpendiIntensityPolar/ParallelIntensityPolar) )
{
// Parallel to initial polarization
GammaPolarization1.setX(PolarizationDegree);
GammaPolarization1.setY(-sinsqrth*sinphi*cosphi/PolarizationDegree);
GammaPolarization1.setZ(-sintheta*costheta*cosphi/PolarizationDegree);
}
else
{
@@ -180,6 +232,7 @@ G4ThreeVector G4PolarizedComptonScattering::SetNewPolarization(G4double EnergyRa
GammaPolarization1.setX(0.);
GammaPolarization1.setY(costheta/PolarizationDegree);
GammaPolarization1.setZ(-sintheta*sinphi/PolarizationDegree);
};
return GammaPolarization1;
@@ -196,6 +249,8 @@ void G4PolarizedComptonScattering::SystemOfRefChange(G4ThreeVector& Direction0,
G4double cosTeta0 = Direction0.cosTheta(), sinTeta0 = sin(Direction0.theta());
G4double cosPhi0 = cos(Direction0.phi()), sinPhi0 = sin(Direction0.phi());
G4double cosPsi, sinPsi;
if (sinTeta0 != 0. ) {
@@ -218,7 +273,6 @@ void G4PolarizedComptonScattering::SystemOfRefChange(G4ThreeVector& Direction0,
Direction1.rotateUz(Direction0);
aParticleChange.SetMomentumChange( Direction1 ) ;
// 3 Euler angles rotation for scattered photon polarization
Polarization1.rotateZ(Psi);
Polarization1.rotateUz(Direction0);
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4SynchrotronRadiation.cc,v 1.2 1999/12/15 14:51:52 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4SynchrotronRadiation.cc,v 1.3 2000/11/01 15:30:46 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
@@ -87,7 +87,7 @@ G4SynchrotronRadiation::PostStepDoIt(const G4Track& trackData,
G4bool FieldExists = globalFieldMgr->DoesFieldExist() ;
G4ThreeVector FieldValue;
G4Field* pField = 0 ;
const G4Field* pField = 0 ;
if (FieldExists)
{
pField = globalFieldMgr->GetDetectorField() ;
@@ -218,7 +218,7 @@ G4SynchrotronRadiation::GetPhotonEnergy( const G4Track& trackData,
G4bool FieldExists = globalFieldMgr->DoesFieldExist() ;
G4ThreeVector FieldValue;
G4Field* pField = 0 ;
const G4Field* pField = 0 ;
if (FieldExists)
{
pField = globalFieldMgr->GetDetectorField() ;
@@ -5,15 +5,15 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4VIeEnergyLoss.cc,v 1.1 2000/04/25 14:33:09 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4VIeEnergyLoss.cc,v 1.3 2000/08/15 09:42:45 urban Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
// $Id:
// -----------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// GEANT4 Collaboration
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4VIeEnergyLoss physics process -----------
@@ -1017,7 +1017,7 @@ G4VParticleChange* G4VIeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowestKineticEnergy))
{
finalT = E-GetLossWithFluct(aParticle,aMaterial,MeanLoss);
finalT = E-GetLossWithFluct(aParticle,aMaterial,1.,MeanLoss,Step);
if (finalT < 0.) finalT = E-MeanLoss;
}
}
@@ -1041,141 +1041,224 @@ G4VParticleChange* G4VIeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
G4double G4VIeEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
G4double MeanLoss)
// calculate actual loss from the mean loss
// The model used to get the fluctuation is the same as in Glandz in Geant3.
G4double ChargeSquare,
G4double MeanLoss,
G4double step )
{
static const G4double Tlow=10.*keV ;
// calculate actual loss from the mean loss
// The model used to get the fluctuation is essentially the same as in Glandz in Geant3.
static const G4double minLoss = 1.*eV ;
static const G4double probLim = 0.01 ;
static const G4double sumaLim = -log(probLim) ;
static const G4double alim=10.;
static const G4double kappa = 10. ;
static const G4double factor = twopi_mc2_rcl2 ;
// check if the material has changed ( cache mechanism)
if (aMaterial != lastMaterial)
{
lastMaterial = aMaterial;
imat = aMaterial->GetIndex();
f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
e2Fluct = aMaterial->GetIonisation()->GetEnergy2fluct();
e1LogFluct = aMaterial->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = aMaterial->GetIonisation()->GetLogEnergy2fluct();
rateFluct = aMaterial->GetIonisation()->GetRateionexcfluct();
ipotFluct = aMaterial->GetIonisation()->GetMeanExcitationEnergy();
ipotLogFluct = aMaterial->GetIonisation()->GetLogMeanExcEnergy();
imat = aMaterial->GetIndex();
f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
e2Fluct = aMaterial->GetIonisation()->GetEnergy2fluct();
e1LogFluct = aMaterial->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = aMaterial->GetIonisation()->GetLogEnergy2fluct();
rateFluct = aMaterial->GetIonisation()->GetRateionexcfluct();
ipotFluct = aMaterial->GetIonisation()->GetMeanExcitationEnergy();
ipotLogFluct = aMaterial->GetIonisation()->GetLogMeanExcEnergy();
}
G4double threshold,w1,w2,w3,lnw3,C,prob,
beta2,suma,e0,Em,loss,lossc ,w;
G4double threshold,w1,w2,C,
beta2,suma,e0,loss,lossc ,w,electronDensity;
G4double a1,a2,a3;
G4long p1,p2,p3;
G4int p1,p2,p3;
G4int nb;
G4double Corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
G4double dp1,dnmaxDirectFluct,dp3,dnmaxCont2;
G4double dp1,dp3;
G4double siga ;
// shortcut for very very small loss
if(MeanLoss < minLoss) return MeanLoss ;
// get particle data
G4double Tkin = aParticle->GetKineticEnergy();
G4double charge = aParticle->GetDefinition()->GetPDGCharge();
if (charge<0.) threshold =((*G4Electron::Electron()).GetCutsInEnergy())[imat];
else threshold =((*G4Positron::Positron()).GetCutsInEnergy())[imat];
G4double Tkin = aParticle->GetKineticEnergy();
ParticleMass = aParticle->GetMass() ;
threshold =((*G4Electron::Electron()).GetCutsInEnergy())[imat];
G4double rmass = electron_mass_c2/ParticleMass;
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass)
-ipotFluct;
if (Tm < 0.) Tm = 0.;
else if (Tm > threshold) Tm = threshold;
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
w1 = Tm+ipotFluct;
w2 = w1/ipotFluct;
w3 = 2.*electron_mass_c2*tau2;
lnw3 = log(w3);
if (Tm <= ipotFluct) Tm = ipotFluct ;
if(Tm > threshold) Tm = threshold;
beta2 = tau2/(tau1*tau1);
C = (1.-rateFluct)*MeanLoss/(lnw3-ipotLogFluct-beta2);
// Gaussian fluctuation ?
if(MeanLoss >= kappa*Tm)
{
electronDensity = aMaterial->GetElectronDensity() ;
siga = sqrt(MeanLoss*Tm*(0.5-0.25*beta2)*step*
factor*electronDensity*ChargeSquare/beta2) ;
loss = G4RandGauss::shoot(MeanLoss,siga) ;
if(loss < 0.) loss = 0. ;
return loss ;
}
w1 = Tm/ipotFluct;
w2 = log(2.*electron_mass_c2*tau2);
C = MeanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
if(Tm > ipotFluct)
a3 = rateFluct*MeanLoss*(Tm-ipotFluct)/(ipotFluct*Tm*log(w1));
else
{
a1 /= 1.-rateFluct ;
a2 /= 1.-rateFluct ;
a3 = 0. ;
}
a1 = C*f1Fluct*(lnw3-e1LogFluct-beta2)/e1Fluct;
a2 = C*f2Fluct*(lnw3-e2LogFluct-beta2)/e2Fluct;
if (Tm > 0.) a3 = rateFluct*MeanLoss*Tm/(ipotFluct*w1*log(w2));
else { a1 /= rateFluct; a2 /= rateFluct; a3 = 0.;}
suma = a1+a2+a3;
//no fluctuation if the loss is too big
if (suma > MaxExcitationNumber) return MeanLoss;
suma<50.? prob = exp(-suma) : prob = 0.;
loss = 0. ;
if (prob > probLimFluct) // very small Step
if(suma < sumaLim) // very small Step
{
e0 = aMaterial->GetIonisation()->GetEnergy0fluct();
if (Tm <= 0.)
{
a1 = MeanLoss/e0;
p1 = G4Poisson(a1);
loss = p1*e0 ;
}
else
{
Em = Tm+e0;
a1 = MeanLoss*(Em-e0)/(Em*e0*log(Em/e0));
p1 = G4Poisson(a1);
w = (Em-e0)/Em;
// just to save time
if (p1 > nmaxDirectFluct)
{
dp1 = p1;
dnmaxDirectFluct=nmaxDirectFluct;
Corrfac = dp1/dnmaxDirectFluct;
p1 = nmaxDirectFluct;
}
else Corrfac = 1.;
e0 = aMaterial->GetIonisation()->GetEnergy0fluct();
loss = 0.;
for (long i=0; i<p1; i++) loss += 1./(1.-w*G4UniformRand());
loss *= (e0*Corrfac);
if(Tm == ipotFluct)
{
a3 = MeanLoss/e0;
}
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
p3 = G4Poisson(a3);
loss = p3*e0 ;
if(p3 > 0)
loss += (1.-2.*G4UniformRand())*e0 ;
}
else
{
Tm = Tm-ipotFluct+e0 ;
a3 = MeanLoss*(Tm-e0)/(Tm*e0*log(Tm/e0));
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
if(p3 > 0)
{
w = (Tm-e0)/Tm ;
if(p3 > nmaxCont2)
{
dp3 = G4float(p3) ;
Corrfac = dp3/G4float(nmaxCont2) ;
p3 = nmaxCont2 ;
}
else
Corrfac = 1. ;
for(G4int i=0; i<p3; i++) loss += 1./(1.-w*G4UniformRand()) ;
loss *= e0*Corrfac ;
}
}
}
else // not so small Step
else // not so small Step
{
p1 = G4Poisson(a1);
p2 = G4Poisson(a2);
loss = p1*e1Fluct+p2*e2Fluct;
if (loss>0.) loss += (1.-2.*G4UniformRand())*e1Fluct;
p3 = G4Poisson(a3);
// excitation type 1
if(a1>alim)
{
siga=sqrt(a1) ;
p1 = G4std::max(0,int(G4RandGauss::shoot(a1,siga)+0.5));
}
else
p1 = G4Poisson(a1);
lossc = 0.; na = 0.; alfa = 1.;
if (p3 > nmaxCont2)
{
dp3 = p3;
dnmaxCont2 = nmaxCont2;
rfac = dp3/(dnmaxCont2+dp3);
namean = p3*rfac;
sa = nmaxCont1*rfac;
na = RandGauss::shoot(namean,sa);
// excitation type 2
if(a2>alim)
{
siga=sqrt(a2) ;
p2 = G4std::max(0,int(G4RandGauss::shoot(a2,siga)+0.5));
}
else
p2 = G4Poisson(a2);
loss = p1*e1Fluct+p2*e2Fluct;
// smearing to avoid unphysical peaks
if(p2 > 0)
loss += (1.-2.*G4UniformRand())*e2Fluct;
else if (loss>0.)
loss += (1.-2.*G4UniformRand())*e1Fluct;
// ionisation .......................................
if(a3 > 0.)
{
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
lossc = 0.;
if(p3 > 0)
{
na = 0.;
alfa = 1.;
if (p3 > nmaxCont2)
{
dp3 = G4float(p3);
rfac = dp3/(G4float(nmaxCont2)+dp3);
namean = G4float(p3)*rfac;
sa = G4float(nmaxCont1)*rfac;
na = G4RandGauss::shoot(namean,sa);
if (na > 0.)
{
alfa = w2*(nmaxCont2+p3)/(w2*nmaxCont2+p3);
alfa1 = alfa*log(alfa)/(alfa-1.);
ea = na*ipotFluct*alfa1;
sea = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
lossc += RandGauss::shoot(ea,sea);
}
{
alfa = w1*G4float(nmaxCont2+p3)/(w1*G4float(nmaxCont2)+G4float(p3));
alfa1 = alfa*log(alfa)/(alfa-1.);
ea = na*ipotFluct*alfa1;
sea = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
lossc += G4RandGauss::shoot(ea,sea);
}
}
nb = G4int(p3-na);
if (nb > 0)
{
nb = G4int(G4float(p3)-na);
if (nb > 0)
{
w2 = alfa*ipotFluct;
w = (w1-w2)/w1;
for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
}
loss += lossc;
}
w = (Tm-w2)/Tm;
for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
}
}
loss += lossc;
}
}
return loss ;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -5,15 +5,15 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4VIhEnergyLoss.cc,v 1.1 2000/04/25 14:33:10 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4VIhEnergyLoss.cc,v 1.3 2000/08/15 09:42:45 urban Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
// $Id:
// -----------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD group
// GEANT4 Collaboration
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4VIhEnergyLoss physics process -----------
@@ -1147,7 +1147,7 @@ G4VParticleChange* G4VIhEnergyLoss::AlongStepDoIt(
if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowestKineticEnergy))
{
MeanLoss /= ChargeSquare ;
finalT = E-GetLossWithFluct(aParticle,aMaterial,MeanLoss)*ChargeSquare ;
finalT = E-GetLossWithFluct(aParticle,aMaterial,ChargeSquare,MeanLoss,Step)*ChargeSquare ;
if (finalT < 0.) finalT = 0. ;
}
@@ -1168,141 +1168,236 @@ G4VParticleChange* G4VIhEnergyLoss::AlongStepDoIt(
return &aParticleChange ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VIhEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
G4double MeanLoss)
// calculate actual loss from the mean loss
// The model used to get the fluctuation is the same as in Glandz in Geant3.
G4Material* aMaterial,
G4double ChargeSquare,
G4double MeanLoss,
G4double step )
{
static const G4double Tlow=10.*keV ;
// calculate actual loss from the mean loss
// The model used to get the fluctuation is essentially the same as in Glandz in Geant3.
static const G4double minLoss = 1.*eV ;
static const G4double probLim = 0.01 ;
static const G4double sumaLim = -log(probLim) ;
static const G4double alim=10.;
static const G4double kappa = 10. ;
static const G4double factor = twopi_mc2_rcl2 ;
// check if the material has changed ( cache mechanism)
if (aMaterial != lastMaterial)
{
lastMaterial = aMaterial;
imat = aMaterial->GetIndex();
f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
e2Fluct = aMaterial->GetIonisation()->GetEnergy2fluct();
e1LogFluct = aMaterial->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = aMaterial->GetIonisation()->GetLogEnergy2fluct();
rateFluct = aMaterial->GetIonisation()->GetRateionexcfluct();
ipotFluct = aMaterial->GetIonisation()->GetMeanExcitationEnergy();
ipotLogFluct = aMaterial->GetIonisation()->GetLogMeanExcEnergy();
imat = aMaterial->GetIndex();
f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
e2Fluct = aMaterial->GetIonisation()->GetEnergy2fluct();
e1LogFluct = aMaterial->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = aMaterial->GetIonisation()->GetLogEnergy2fluct();
rateFluct = aMaterial->GetIonisation()->GetRateionexcfluct();
ipotFluct = aMaterial->GetIonisation()->GetMeanExcitationEnergy();
ipotLogFluct = aMaterial->GetIonisation()->GetLogMeanExcEnergy();
}
G4double threshold,w1,w2,w3,lnw3,C,prob,
beta2,suma,e0,Em,loss,lossc ,w;
G4double threshold,w1,w2,C,
beta2,suma,e0,loss,lossc ,w,electronDensity;
G4double a1,a2,a3;
G4long p1,p2,p3;
G4int p1,p2,p3;
G4int nb;
G4double Corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
G4double dp1,dnmaxDirectFluct,dp3,dnmaxCont2;
G4double dp1,dp3;
G4double siga ;
// shortcut for very very small loss
if(MeanLoss < minLoss) return MeanLoss ;
// get particle data
G4double Tkin = aParticle->GetKineticEnergy();
G4double charge = aParticle->GetDefinition()->GetPDGCharge();
G4double Tkin = aParticle->GetKineticEnergy();
ParticleMass = aParticle->GetMass() ;
threshold =((*G4Electron::Electron()).GetCutsInEnergy())[imat];
G4double rmass = electron_mass_c2/ParticleMass;
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass)
-ipotFluct;
if (Tm < 0.) Tm = 0.;
else if (Tm > threshold) Tm = threshold;
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
w1 = Tm+ipotFluct;
w2 = w1/ipotFluct;
w3 = 2.*electron_mass_c2*tau2;
lnw3 = log(w3);
if (Tm <= ipotFluct) Tm = ipotFluct ;
if(Tm > threshold) Tm = threshold;
beta2 = tau2/(tau1*tau1);
C = (1.-rateFluct)*MeanLoss/(lnw3-ipotLogFluct-beta2);
// Gaussian fluctuation ?
if(MeanLoss >= kappa*Tm)
{
electronDensity = aMaterial->GetElectronDensity() ;
siga = sqrt(MeanLoss*Tm*(0.5-0.25*beta2)*step*
factor*electronDensity*ChargeSquare/beta2) ;
loss = G4RandGauss::shoot(MeanLoss,siga) ;
if(loss < 0.) loss = 0. ;
return loss ;
}
w1 = Tm/ipotFluct;
w2 = log(2.*electron_mass_c2*tau2);
C = MeanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
if(Tm > ipotFluct)
a3 = rateFluct*MeanLoss*(Tm-ipotFluct)/(ipotFluct*Tm*log(w1));
else
{
a1 /= 1.-rateFluct ;
a2 /= 1.-rateFluct ;
a3 = 0. ;
}
a1 = C*f1Fluct*(lnw3-e1LogFluct-beta2)/e1Fluct;
a2 = C*f2Fluct*(lnw3-e2LogFluct-beta2)/e2Fluct;
if (Tm > 0.) a3 = rateFluct*MeanLoss*Tm/(ipotFluct*w1*log(w2));
else { a1 /= rateFluct; a2 /= rateFluct; a3 = 0.;}
suma = a1+a2+a3;
//no fluctuation if the loss is too big
if (suma > MaxExcitationNumber) return MeanLoss;
suma<50.? prob = exp(-suma) : prob = 0.;
loss = 0. ;
if (prob > probLimFluct) // very small Step
if(suma < sumaLim) // very small Step
{
e0 = aMaterial->GetIonisation()->GetEnergy0fluct();
if (Tm <= 0.)
{
a1 = MeanLoss/e0;
p1 = G4Poisson(a1);
loss = p1*e0 ;
}
else
{
Em = Tm+e0;
a1 = MeanLoss*(Em-e0)/(Em*e0*log(Em/e0));
p1 = G4Poisson(a1);
w = (Em-e0)/Em;
// just to save time
if (p1 > nmaxDirectFluct)
{
dp1 = p1;
dnmaxDirectFluct=nmaxDirectFluct;
Corrfac = dp1/dnmaxDirectFluct;
p1 = nmaxDirectFluct;
}
else Corrfac = 1.;
e0 = aMaterial->GetIonisation()->GetEnergy0fluct();
loss = 0.;
for (long i=0; i<p1; i++) loss += 1./(1.-w*G4UniformRand());
loss *= (e0*Corrfac);
if(Tm == ipotFluct)
{
a3 = MeanLoss/e0;
}
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
p3 = G4Poisson(a3);
loss = p3*e0 ;
if(p3 > 0)
loss += (1.-2.*G4UniformRand())*e0 ;
}
else
{
Tm = Tm-ipotFluct+e0 ;
a3 = MeanLoss*(Tm-e0)/(Tm*e0*log(Tm/e0));
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
if(p3 > 0)
{
w = (Tm-e0)/Tm ;
if(p3 > nmaxCont2)
{
dp3 = G4float(p3) ;
Corrfac = dp3/G4float(nmaxCont2) ;
p3 = nmaxCont2 ;
}
else
Corrfac = 1. ;
for(G4int i=0; i<p3; i++) loss += 1./(1.-w*G4UniformRand()) ;
loss *= e0*Corrfac ;
}
}
}
else // not so small Step
else // not so small Step
{
p1 = G4Poisson(a1);
p2 = G4Poisson(a2);
loss = p1*e1Fluct+p2*e2Fluct;
if (loss>0.) loss += (1.-2.*G4UniformRand())*e1Fluct;
p3 = G4Poisson(a3);
// excitation type 1
if(a1>alim)
{
siga=sqrt(a1) ;
p1 = G4std::max(0,int(G4RandGauss::shoot(a1,siga)+0.5));
}
else
p1 = G4Poisson(a1);
lossc = 0.; na = 0.; alfa = 1.;
if (p3 > nmaxCont2)
{
dp3 = p3;
dnmaxCont2 = nmaxCont2;
rfac = dp3/(dnmaxCont2+dp3);
namean = p3*rfac;
sa = nmaxCont1*rfac;
na = RandGauss::shoot(namean,sa);
// excitation type 2
if(a2>alim)
{
siga=sqrt(a2) ;
p2 = G4std::max(0,int(G4RandGauss::shoot(a2,siga)+0.5));
}
else
p2 = G4Poisson(a2);
loss = p1*e1Fluct+p2*e2Fluct;
// smearing to avoid unphysical peaks
if(p2 > 0)
loss += (1.-2.*G4UniformRand())*e2Fluct;
else if (loss>0.)
loss += (1.-2.*G4UniformRand())*e1Fluct;
// ionisation .......................................
if(a3 > 0.)
{
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
lossc = 0.;
if(p3 > 0)
{
na = 0.;
alfa = 1.;
if (p3 > nmaxCont2)
{
dp3 = G4float(p3);
rfac = dp3/(G4float(nmaxCont2)+dp3);
namean = G4float(p3)*rfac;
sa = G4float(nmaxCont1)*rfac;
na = G4RandGauss::shoot(namean,sa);
if (na > 0.)
{
alfa = w2*(nmaxCont2+p3)/(w2*nmaxCont2+p3);
alfa1 = alfa*log(alfa)/(alfa-1.);
ea = na*ipotFluct*alfa1;
sea = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
lossc += RandGauss::shoot(ea,sea);
}
{
alfa = w1*G4float(nmaxCont2+p3)/(w1*G4float(nmaxCont2)+G4float(p3));
alfa1 = alfa*log(alfa)/(alfa-1.);
ea = na*ipotFluct*alfa1;
sea = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
lossc += G4RandGauss::shoot(ea,sea);
}
}
nb = G4int(p3-na);
if (nb > 0)
{
nb = G4int(G4float(p3)-na);
if (nb > 0)
{
w2 = alfa*ipotFluct;
w = (w1-w2)/w1;
for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
}
w = (Tm-w2)/Tm;
for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
loss += lossc;
}
}
loss += lossc;
}
}
return loss ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4VPAIenergyLoss.cc,v 1.1 2000/04/25 14:33:10 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
// GEANT4 tag $Name: geant4-03-00 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
@@ -5,21 +5,10 @@
// 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 $
// $Id: G4VeEnergyLoss.cc,v 1.8 2000/10/30 07:01:09 urban Exp $
// GEANT4 tag $Name: geant4-03-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:
@@ -28,14 +17,13 @@
// 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
@@ -49,10 +37,6 @@ G4PhysicsTable** G4VeEnergyLoss::RecorderOfElectronProcess =
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;
@@ -76,8 +60,6 @@ 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
@@ -92,11 +74,7 @@ G4VeEnergyLoss::G4VeEnergyLoss(const G4String& processName)
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....
@@ -106,7 +84,6 @@ G4VeEnergyLoss::~G4VeEnergyLoss()
{
theLossTable->clearAndDestroy();
delete theLossTable; theLossTable = NULL;
/// if(MinDeltaEnergy) delete MinDeltaEnergy;
}
}
@@ -301,7 +278,7 @@ void G4VeEnergyLoss::BuildDEDXTable(
if(!setMinDeltaCutInRange )
MinDeltaCutInRange = G4Electron::Electron()->GetCuts()/10. ;
if(&aParticleType==G4Electron::Electron())
if((subSecFlag) && (&aParticleType==G4Electron::Electron()))
{
G4cout << G4endl;
G4cout.precision(5) ;
@@ -314,8 +291,12 @@ void G4VeEnergyLoss::BuildDEDXTable(
if(MinDeltaEnergy) delete MinDeltaEnergy ;
MinDeltaEnergy = new G4double [numOfMaterials] ;
if(LowerLimitForced) delete LowerLimitForced ;
LowerLimitForced = new G4bool [numOfMaterials] ;
for(G4int mat=0; mat<numOfMaterials; mat++)
{
LowerLimitForced[mat] = false ;
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),MinDeltaCutInRange,
(*theMaterialTable)(mat)) ;
@@ -326,10 +307,14 @@ void G4VeEnergyLoss::BuildDEDXTable(
if(MinDeltaEnergy[mat]>G4Electron::Electron()->GetCutsInEnergy()[mat])
MinDeltaEnergy[mat]=G4Electron::Electron()->GetCutsInEnergy()[mat] ;
if(&aParticleType==G4Electron::Electron())
if((subSecFlag) && (&aParticleType==G4Electron::Electron()))
{
G4cout << G4std::setw(20) << (*theMaterialTable)(mat)->GetName()
<< G4std::setw(15) << MinDeltaEnergy[mat]/keV << G4endl;
<< G4std::setw(15) << MinDeltaEnergy[mat]/keV ;
if(LowerLimitForced[mat])
G4cout << " lower limit forced." << G4endl;
else
G4cout << G4endl ;
}
}
@@ -436,7 +421,9 @@ G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
G4Electron::Electron(),safety,aMaterial) ;
// absolute lower limit for T0
if(T0<MinDeltaEnergyNow) T0=MinDeltaEnergyNow ;
// if(T0<MinDeltaEnergyNow) T0=MinDeltaEnergyNow ;
if((T0<MinDeltaEnergyNow)||(LowerLimitForced[aMaterial->GetIndex()]))
T0=MinDeltaEnergyNow ;
// ..................................................................
x1=stepData.GetPreStepPoint()->GetPosition().x();
@@ -597,7 +584,7 @@ G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
//now the loss with fluctuation
if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
{
finalT = E-GetLossWithFluct(aParticle,aMaterial,MeanLoss);
finalT = E-GetLossWithFluct(aParticle,aMaterial,1.,MeanLoss,Step);
if (finalT < 0.) finalT = 0. ;
}
@@ -5,24 +5,11 @@
// 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 $
// $Id: G4VhEnergyLoss.cc,v 1.13 2000/10/30 07:01:09 urban Exp $
// GEANT4 tag $Name: geant4-03-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
@@ -30,16 +17,24 @@
// 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
// 18/07/00 : bug fix in AlongStepDoIt V.Ivanchenko
// 10/08/00 : V.Ivanchenko change AlongStepDoIt and
// add EnergyLossFluctuation in order to simulate
// energy losses of ions
// 17/08/00 : V.Ivanchenko change EnergyLossFluctuation
// 18/08/00 : V.Ivanchenko bug fixed in GetConstrained
// --------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VhEnergyLoss.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4EnergyLossTables.hh"
#include "G4Poisson.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
// Initialisation of static members ******************************************
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4VhEnergyLoss::NbOfProcesses = 1 ;
G4int G4VhEnergyLoss::CounterOfProcess = 0 ;
@@ -80,10 +75,6 @@ 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 ;
@@ -97,28 +88,26 @@ 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
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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();
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
}
G4VhEnergyLoss::~G4VhEnergyLoss()
{
if(theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable; theLossTable = NULL;
}
/// if(MinDeltaEnergy) delete MinDeltaEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VhEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
@@ -305,6 +294,7 @@ void G4VhEnergyLoss::BuildDEDXTable(
}
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
@@ -325,7 +315,7 @@ void G4VhEnergyLoss::BuildDEDXTable(
if(!setMinDeltaCutInRange)
MinDeltaCutInRange = G4Electron::Electron()->GetCuts()/10.;
if(aParticleType.GetParticleName()=="proton")
if((subSecFlag) && (aParticleType.GetParticleName()=="proton"))
{
G4cout << G4endl;
G4cout.precision(5) ;
@@ -338,9 +328,13 @@ void G4VhEnergyLoss::BuildDEDXTable(
if(MinDeltaEnergy) delete MinDeltaEnergy ;
MinDeltaEnergy = new G4double [numOfMaterials] ;
if(LowerLimitForced) delete LowerLimitForced ;
LowerLimitForced = new G4bool [numOfMaterials] ;
G4double Tlowerlimit = 1.*keV ;
for(G4int mat=0; mat<numOfMaterials; mat++)
{
LowerLimitForced[mat] = false ;
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),MinDeltaCutInRange,
(*theMaterialTable)(mat)) ;
@@ -349,12 +343,19 @@ void G4VhEnergyLoss::BuildDEDXTable(
if(MinDeltaEnergy[mat]>G4Electron::Electron()->GetCutsInEnergy()[mat])
MinDeltaEnergy[mat]=G4Electron::Electron()->GetCutsInEnergy()[mat] ;
if(aParticleType.GetParticleName()=="proton")
if((subSecFlag) && (aParticleType.GetParticleName()=="proton"))
{
G4cout << G4std::setw(20) << (*theMaterialTable)(mat)->GetName()
<< G4std::setw(15) << MinDeltaEnergy[mat]/keV << G4endl;
<< G4std::setw(15) << MinDeltaEnergy[mat]/keV ;
if(LowerLimitForced[mat])
G4cout << " lower limit forced." << G4endl;
else
G4cout << G4endl ;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
G4Material *aMaterial)
@@ -408,6 +409,8 @@ G4double G4VhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
return StepLimit ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
const G4Track& trackData,const G4Step& stepData)
// compute the energy loss after a step
@@ -464,7 +467,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
theAntiProton,
rscaled-sscaled,aMaterial) ;
}
MeanLoss /= (massratio*ChargeSquare) ;
MeanLoss /= massratio ;
}
else MeanLoss = Step*fdEdx ;
}
@@ -557,7 +560,9 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
aMaterial) ;
// absolute lower limit for T0
if(T0<MinDeltaEnergyNow) T0=MinDeltaEnergyNow ;
// if(T0<MinDeltaEnergyNow) T0=MinDeltaEnergyNow ;
if((T0<MinDeltaEnergyNow)||(LowerLimitForced[aMaterial->GetIndex()]))
T0=MinDeltaEnergyNow ;
// compute nb of delta rays to be generated
G4int N=int(fragment*(c0N/(E*T0)+c1N/T0-(c2N+c3N*T0)/Tc)*
@@ -677,8 +682,8 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
// now the loss with fluctuation
if((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
{
MeanLoss /= ChargeSquare ;
finalT = E-GetLossWithFluct(aParticle,aMaterial,MeanLoss)*ChargeSquare ;
finalT = E -
EnergyLossFluctuation(aParticle,aMaterial,ChargeSquare,MeanLoss,Step) ;
if (finalT < 0.) finalT = 0. ;
}
@@ -699,4 +704,18 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
return &aParticleChange ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VhEnergyLoss::EnergyLossFluctuation(
const G4DynamicParticle *aParticle,
G4Material *aMaterial,
G4double ChargeSquare,
G4double MeanLoss,
G4double Step)
{
G4double loss = GetLossWithFluct(aParticle,aMaterial,
ChargeSquare,MeanLoss,Step) ;
return loss ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4eBremsstrahlung.cc,v 1.11 2000/05/23 15:44:29 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4eBremsstrahlung.cc,v 1.13 2000/09/21 09:34:29 urban Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
//
// --------------------------------------------------------------
@@ -30,6 +30,8 @@
// 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
// 07/08/00 new cross section/en.loss parametrisation, LPM flag , L.Urban
// 21/09/00 : corrections in the LPM implementation, L.Urban
// --------------------------------------------------------------
#include "G4eBremsstrahlung.hh"
@@ -40,6 +42,8 @@
G4double G4eBremsstrahlung::LowerBoundLambda = 1.*keV ;
G4double G4eBremsstrahlung::UpperBoundLambda = 100.*TeV ;
G4int G4eBremsstrahlung::NbinLambda = 100 ;
G4double G4eBremsstrahlung::probsup = 1.00 ;
G4bool G4eBremsstrahlung::LPMflag = true;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -49,7 +53,8 @@ G4int G4eBremsstrahlung::NbinLambda = 100 ;
G4eBremsstrahlung::G4eBremsstrahlung(const G4String& processName)
: G4VeEnergyLoss(processName), // initialization
theMeanFreePathTable(NULL)
{MinThreshold = 10*keV; }
{ // MinThreshold = 10*keV;
MinThreshold = 1*keV; }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -148,7 +153,6 @@ void G4eBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aParticleType
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
TotalEnergy = KineticEnergy+ParticleMass ;
Cut = GammaCutInKineticEnergy[J] ;
if (Cut < MinThreshold) Cut = MinThreshold;
if (Cut > KineticEnergy) Cut = KineticEnergy;
@@ -200,60 +204,40 @@ void G4eBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aParticleType
}
// now compute the correction due to the LPM effect
const G4double MigdalConstant = classic_electr_radius*
electron_Compton_length*
electron_Compton_length/pi ;
static const G4double MigdalConstant = classic_electr_radius
*electron_Compton_length
*electron_Compton_length/pi;
G4double TotalEnergy = KineticEnergy+electron_mass_c2 ;
G4double kp2 = MigdalConstant*TotalEnergy*TotalEnergy*
(material->GetElectronDensity()) ;
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 ;
// now compute the correction due to the supression(s)
G4double kmin = 1.*eV ;
G4double kmax = Cut ;
G4double LPMEnergy = LPMconstant*(material->GetRadlen()) ;
G4double TotalEnergysquare = TotalEnergy*TotalEnergy ;
G4double LPMGammaEnergyLimit = TotalEnergysquare/LPMEnergy ;
if(LPMGammaEnergyLimit > klim)
if(kmax > kmin)
{
G4double kmax = G4std::min(Cut,LPMGammaEnergyLimit) ;
G4double floss = 0. ;
G4int nmax = 1000 ;
G4int nmax = 100 ;
G4int nn ;
G4double vmin=log(kmin);
G4double vmax=log(Cut) ;
G4double vmax=log(kmax) ;
nn = int(nmax*(vmax-vmin)/(log(HighestKineticEnergy)-vmin)) ;
G4double u,uu,s2lpm,sp,fac,c,v,dv,w ;
G4double u,fac,c,v,dv ;
dv = (vmax-vmin)/nn ;
v = vmin-dv ;
if(nn > 0)
{
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 = u*SupressionFunction(material,KineticEnergy,u) ;
fac *= uu*u ;
probsup = 1. ;
fac *= probsup*(u*u/(u*u+kp2))+1.-probsup ;
if((n==0)||(n==nn))
c=0.5;
@@ -264,13 +248,18 @@ void G4eBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aParticleType
floss += fac ;
}
floss *=dv*3./(Cut*Cut*Cut-kmin*kmin*kmin) ;
floss *=dv/(kmax-kmin) ;
}
else
floss = 1. ;
if(floss > 1.) floss = 1. ;
// correct the loss
bremloss *= floss ;
}
if(bremloss < 0.) bremloss = 0. ;
aVector->PutValue(i,bremloss);
}
@@ -314,72 +303,96 @@ G4double G4eBremsstrahlung::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 beta=1.00,ksi=2.00 ;
static const G4double clossh = 0.254 , closslow = 1./3. , alosslow = 1. ;
static const G4double Tlim= 10.*MeV ;
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 xlim = 1.2 ;
static const G4int NZ = 8 ;
static const G4int Nloss = 11 ;
static const G4double ZZ[NZ] =
{2.,4.,6.,14.,26.,50.,82.,92.};
static const G4double coefloss[NZ][Nloss] = {
// Z=2
0.98916, 0.47564, -0.2505, -0.45186, 0.14462,
0.21307, -0.013738, -0.045689, -0.0042914, 0.0034429,
0.00064189,
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};
// Z=4
1.0626, 0.37662, -0.23646, -0.45188, 0.14295,
0.22906, -0.011041, -0.051398, -0.0055123, 0.0039919,
0.00078003,
// Z=6
1.0954, 0.315, -0.24011, -0.43849, 0.15017,
0.23001, -0.012846, -0.052555, -0.0055114, 0.0041283,
0.00080318,
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};
// Z=14
1.1649, 0.18976, -0.24972, -0.30124, 0.1555,
0.13565, -0.024765, -0.027047, -0.00059821, 0.0019373,
0.00027647,
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};
// Z=26
1.2261, 0.14272, -0.25672, -0.28407, 0.13874,
0.13586, -0.020562, -0.026722, -0.00089557, 0.0018665,
0.00026981,
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;
}
// -----------------------------------------------------------
// Z=50
1.3147, 0.020049, -0.35543, -0.13927, 0.17666,
0.073746, -0.036076, -0.013407, 0.0025727, 0.00084005,
-1.4082e-05,
G4double TotalEnergy = T + electron_mass_c2;
G4double y=log(Cut/(ve*TotalEnergy));
// Z=82
1.3986, -0.10586, -0.49187, -0.0048846, 0.23621,
0.031652, -0.052938, -0.0076639, 0.0048181, 0.00056486,
-0.00011995,
// Z=92
1.4217, -0.116, -0.55497, -0.044075, 0.27506,
0.081364, -0.058143, -0.023402, 0.0031322, 0.0020201,
0.00017519
} ;
G4int iz = 0 ;
G4double delz = 1.e6 ;
for (G4int ii=0; ii<NZ; ii++)
{
if(abs(Z-ZZ[ii]) < delz)
{
iz = ii ;
delz = abs(Z-ZZ[ii]) ;
}
}
G4double xx = log10(T) ;
G4double fl = 1. ;
if(xx <= xlim)
{
fl = coefloss[iz][Nloss-1] ;
for (G4int j=Nloss-2; j>=0; j--)
{
fl = fl*xx+coefloss[iz][j] ;
}
if(fl < 0.) fl = 0. ;
}
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 E = T+electron_mass_c2 ;
G4double rate = TotalEnergy/Cut ;
G4double corr = 1./(1.+corrfac*natom*rate*rate) ;
loss = Z*(Z+ksi)*E*E/(T+E)*exp(beta*log(Cut/T))*(2.-clossh*exp(log(Z)/4.)) ;
G4double factor = pow(Cut*corr/T,beta);
factor *= Z*(Z+ksi)*TotalEnergy*TotalEnergy/(TotalEnergy+electron_mass_c2) ;
if(T <= Tlim)
loss /= exp(closslow*log(Tlim/T)) ;
loss *= factor ;
if(T <= Cut)
loss *= exp(alosslow*log(T/Cut)) ;
loss *= fl ;
loss /= Avogadro ;
return loss ;
}
@@ -472,6 +485,66 @@ G4double G4eBremsstrahlung::ComputeMeanFreePath(
(*theElementVector)(i)->GetZ(),
GammaEnergyCut );
}
// now compute the correction due to the supression(s)
G4double kmax = KineticEnergy ;
G4double kmin = GammaEnergyCut ;
static const G4double MigdalConstant = classic_electr_radius
*electron_Compton_length
*electron_Compton_length/pi;
G4double TotalEnergy = KineticEnergy+electron_mass_c2 ;
G4double kp2 = MigdalConstant*TotalEnergy*TotalEnergy*
(aMaterial->GetElectronDensity()) ;
if(kmax > kmin)
{
G4double fsig = 0. ;
G4int nmax = 100 ;
G4int nn ;
G4double vmin=log(kmin);
G4double vmax=log(kmax) ;
nn = int(nmax*(vmax-vmin)/(log(HighestKineticEnergy)-vmin)) ;
G4double u,fac,c,v,dv,y ;
dv = (vmax-vmin)/nn ;
v = vmin-dv ;
if(nn > 0)
{
for(G4int n=0; n<=nn; n++)
{
v += dv ;
u = exp(v) ;
fac = SupressionFunction(aMaterial,KineticEnergy,u) ;
y = u/kmax ;
fac *= (4.-4.*y+3.*y*y)/3. ;
fac *= probsup*(u*u/(u*u+kp2))+1.-probsup ;
if((n==0)||(n==nn))
c=0.5;
else
c=1.;
fac *= c ;
fsig += fac ;
}
y = kmin/kmax ;
fsig *=dv/(-4.*log(y)/3.-4.*(1.-y)/3.+0.5*(1.-y*y)) ;
}
else
fsig = 1. ;
if(fsig > 1.) fsig = 1. ;
// correct the cross section
SIGMA *= fsig ;
}
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
}
@@ -484,165 +557,103 @@ G4double G4eBremsstrahlung::ComputeMicroscopicCrossSection(
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;
static const G4double ksi=2.0, alfa=1.00;
static const G4double csigh = 0.127, csiglow = 0.25, asiglow = 0.020*MeV ;
static const G4double Tlim = 10.*MeV ;
const G4double KinLimitScale = 100.*GeV, CutLimitScale = 50.*GeV;
static const G4double xlim = 1.2 ;
static const G4int NZ = 8 ;
static const G4int Nsig = 11 ;
static const G4double ZZ[NZ] =
{2.,4.,6.,14.,26.,50.,82.,92.} ;
static const G4double coefsig[NZ][Nsig] = {
// Z=2
0.4638, 0.37748, 0.32249, -0.060362, -0.065004,
-0.033457, -0.004583, 0.011954, 0.0030404, -0.0010077,
-0.00028131,
// Z=4
0.50008, 0.33483, 0.34364, -0.086262, -0.055361,
-0.028168, -0.0056172, 0.011129, 0.0027528, -0.00092265,
-0.00024348,
const G4double Tlim = 1.*MeV;
if (KineticEnergy < Tlim) LocalKineticEnergy = Tlim;
// Z=6
0.51587, 0.31095, 0.34996, -0.11623, -0.056167,
-0.0087154, 0.00053943, 0.0054092, 0.00077685, -0.00039635,
-6.7818e-05,
if (KineticEnergy > KinLimitScale)
{ LocalKineticEnergy = KinLimitScale;
if (GammaEnergyCut > KinLimitScale) LocalGammaEnergyCut = CutLimitScale;
}
// Z=14
0.55058, 0.25629, 0.35854, -0.080656, -0.054308,
-0.049933, -0.00064246, 0.016597, 0.0021789, -0.001327,
-0.00025983,
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;
// Z=26
0.5791, 0.26152, 0.38953, -0.17104, -0.099172,
0.024596, 0.023718, -0.0039205, -0.0036658, 0.00041749,
0.00023408,
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;
// Z=50
0.62085, 0.27045, 0.39073, -0.37916, -0.18878,
0.23905, 0.095028, -0.068744, -0.023809, 0.0062408,
0.0020407,
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;
// Z=82
0.66053, 0.24513, 0.35404, -0.47275, -0.22837,
0.35647, 0.13203, -0.1049, -0.034851, 0.0095046,
0.0030535,
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;
// Z=92
0.67143, 0.23079, 0.32256, -0.46248, -0.20013,
0.3506, 0.11779, -0.1024, -0.032013, 0.0092279,
0.0028592
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;
G4int iz = 0 ;
G4double delz = 1.e6 ;
for (G4int ii=0; ii<NZ; ii++)
{
if(abs(AtomicNumber-ZZ[ii]) < delz)
{
iz = ii ;
delz = abs(AtomicNumber-ZZ[ii]) ;
}
}
G4double F0 = ay0 + ay1*Y + ay2*Y2 + ay3*Y3 + ay4*Y4 + ay5*Y5,
F1 = by0 + by1*Y + by2*Y2 + by3*Y3 + by4*Y4;
G4double xx = log10(KineticEnergy) ;
G4double fs = 1. ;
if(xx <= xlim)
{
fs = coefsig[iz][Nsig-1] ;
for (G4int j=Nsig-2; j>=0; j--)
{
fs = fs*xx+coefsig[iz][j] ;
}
if(fs < 0.) fs = 0. ;
}
CrossSection = AtomicNumber*(AtomicNumber+ksi)*TotalEnergy*TotalEnergy
* pow(log(LocalKineticEnergy/LocalGammaEnergyCut),alfa)
* (F0 + F1*AtomicNumber)
/ (LocalKineticEnergy*(LocalKineticEnergy+2*electron_mass_c2));
CrossSection = AtomicNumber*(AtomicNumber+ksi)*
(1.-csigh*exp(log(AtomicNumber)/4.))*
pow(log(KineticEnergy/GammaEnergyCut),alfa) ;
if(KineticEnergy <= Tlim)
CrossSection *= exp(csiglow*log(Tlim/KineticEnergy))*
(1.+asiglow/(sqrt(AtomicNumber)*KineticEnergy)) ;
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.);
}
CrossSection *= ComputePositronCorrFactorSigma(AtomicNumber, KineticEnergy,
GammaEnergyCut);
CrossSection *= fs ;
CrossSection /= Avogadro ;
if (CrossSection < 0.) CrossSection = 0.;
return CrossSection;
@@ -742,6 +753,8 @@ G4VParticleChange* G4eBremsstrahlung::PostStepDoIt(const G4Track& trackData,
*electron_Compton_length/pi;
const G4double LPMconstant = fine_structure_const*electron_mass_c2*
electron_mass_c2/(8.*pi*hbarc) ;
G4double GammaEnergy ;
G4bool LPMOK = false ;
aParticleChange.Initialize(trackData);
G4Material* aMaterial=trackData.GetMaterial() ;
@@ -780,12 +793,12 @@ G4VParticleChange* G4eBremsstrahlung::PostStepDoIt(const G4Track& trackData,
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
G4double
MigdalFactor = (aMaterial->GetElectronDensity())*MigdalConstant
/(epsilmax*epsilmax);
//
@@ -796,6 +809,7 @@ G4VParticleChange* G4eBremsstrahlung::PostStepDoIt(const G4Track& trackData,
// sample the energy rate of the emitted gamma for electron kinetic energy > 1 MeV
//
do {
if (KineticEnergy > 1.*MeV)
{
// parameters
@@ -823,6 +837,7 @@ G4VParticleChange* G4eBremsstrahlung::PostStepDoIt(const G4Track& trackData,
// sample the energy rate of the emitted Gamma
G4double screenvar;
do {
x = pow(xmin, G4UniformRand());
@@ -865,21 +880,19 @@ G4VParticleChange* G4eBremsstrahlung::PostStepDoIt(const G4Track& trackData,
} while( greject < G4UniformRand()*grejmax );
}
G4double GammaEnergy = x*KineticEnergy;
GammaEnergy = x*KineticEnergy;
// now comes the supression due to the LPM effect
if(GammaEnergy < LPMGammaEnergyLimit)
if(LPMflag)
{
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. ;
// take into account the supression due to the LPM effect
if (G4UniformRand() <= SupressionFunction(aMaterial,KineticEnergy,GammaEnergy))
LPMOK = true ;
}
else
LPMOK = true ;
} while (!LPMOK) ;
//protection: DO NOT PRODUCE a gamma with energy 0. !
if (GammaEnergy <= 0.)
@@ -953,10 +966,68 @@ G4Element* G4eBremsstrahlung::SelectRandomAtom(G4Material* aMaterial) const
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlung::SupressionFunction(const G4Material* aMaterial,
G4double KineticEnergy,G4double GammaEnergy)
{
// supression due to the LPM effect+polarisation of the medium/
// supression due to the polarisation alone
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) ;
G4double TotalEnergy,TotalEnergySquare,LPMEnergy,LPMGammaEnergyLimit,
LPMGammaEnergyLimit2,GammaEnergySquare,sp,s2lpm,supr,w,splim,Cnorm ;
TotalEnergy = KineticEnergy+electron_mass_c2 ;
TotalEnergySquare = TotalEnergy*TotalEnergy ;
LPMEnergy = LPMconstant*(aMaterial->GetRadlen()) ;
LPMGammaEnergyLimit = TotalEnergySquare/LPMEnergy ;
GammaEnergySquare = GammaEnergy*GammaEnergy ;
LPMGammaEnergyLimit2 = LPMGammaEnergyLimit*LPMGammaEnergyLimit ;
splim = LPMGammaEnergyLimit2/(LPMGammaEnergyLimit2+MigdalConstant*TotalEnergySquare*
(aMaterial->GetElectronDensity())) ;
w = 1.+1./splim ;
Cnorm = 2./(sqrt(w*w+4.)-w) ;
sp = GammaEnergySquare/(GammaEnergySquare+MigdalConstant*TotalEnergySquare*
(aMaterial->GetElectronDensity())) ;
if(LPMflag)
{
s2lpm = LPMEnergy*GammaEnergy/TotalEnergySquare ;
if(s2lpm < 1.)
{
if((1.-sp) < 1.e-6)
w = s2lpm*(3.-sp) ;
else
w = s2lpm*(1.+1./sp) ;
supr = Cnorm*(sqrt(w*w+4.*s2lpm)-w)/2. ;
}
else
{
supr = sp ;
}
}
else
supr = sp ;
supr /= sp ;
return supr ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::PrintInfoDefinition()
{
G4String comments = "Total cross sections from a parametrisation. ";
comments += "Good description from 10 KeV to 100 GeV.\n";
G4String comments = "Total cross sections from a NEW parametrisation based on the EEDL data library. ";
// comments += "Good description from 10 KeV to 100 GeV.\n";
comments += "\n 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.";
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4eIonisation.cc,v 1.10 2000/05/23 14:42:21 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
// GEANT4 tag $Name: geant4-03-00 $
//
//
// -------------------------------------------------------------
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4eplusAnnihilation.cc,v 1.2 1999/12/15 14:51:53 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
// GEANT4 tag $Name: geant4-03-00 $
//
//
// --------------------------------------------------------------
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4hIonisation.cc,v 1.11 2000/05/23 14:42:22 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
// $Id: G4hIonisation.cc,v 1.12 2000/08/10 22:13:01 vnivanch Exp $
// GEANT4 tag $Name: geant4-03-00 $
//
// -------------------------------------------------------------
// GEANT 4 class implementation file
@@ -28,6 +28,10 @@
// 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
// 10/08/00 : V.Ivanchenko change BuildLambdaTable, in order to
// simulate energy losses of ions; correction to
// cross section for particles with spin 1 is inserted
// as well
// --------------------------------------------------------------
@@ -71,7 +75,7 @@ void G4hIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
ParticleMass = aParticleType.GetPDGMass() ;
Charge = aParticleType.GetPDGCharge();
Charge = (aParticleType.GetPDGCharge())/eplus;
G4double ElectronCutInRange = G4Electron::Electron()->GetCuts();
@@ -289,6 +293,7 @@ void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
// Build mean free path tables for the delta ray production process
// tables are built for MATERIALS
G4double chargeSquare = Charge*Charge ;
G4double LowEdgeEnergy , Value ,sigma ;
G4bool isOutRange ;
const G4MaterialTable* theMaterialTable=
@@ -345,10 +350,10 @@ void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
sigma += theAtomicNumDensityVector[iel]*
ComputeMicroscopicCrossSection(aParticleType,
LowEdgeEnergy,
(*theElementVector)(iel)->GetZ() ) ;
sigma += theAtomicNumDensityVector[iel]*
chargeSquare*
ComputeMicroscopicCrossSection(aParticleType,
LowEdgeEnergy,(*theElementVector)(iel)->GetZ() ) ;
}
// mean free path = 1./macroscopic cross section
@@ -401,16 +406,26 @@ G4double G4hIonisation::ComputeMicroscopicCrossSection(
TotalCrossSection = (1.-tempvar*(1.-betasquare*log(tempvar)))
/DeltaCutInKineticEnergyNow;
G4double spin = aParticleType.GetPDGSpin() ;
// +term for spin=1/2 particle
if(aParticleType.GetPDGSpin() == 0.5)
{
TotalCrossSection += 0.5
if(0.5 == spin)
{
TotalCrossSection += 0.5
*(MaxKineticEnergyTransfer-DeltaCutInKineticEnergyNow)
/(TotalEnergy*TotalEnergy);
G4double Section = 0.5
*(MaxKineticEnergyTransfer-DeltaCutInKineticEnergyNow)
/(TotalEnergy*TotalEnergy);
}
// +term for spin=1 particle
} else if( 0.9 < spin )
{
TotalCrossSection +=
-log(tempvar)/(3.0*DeltaCutInKineticEnergyNow) +
(MaxKineticEnergyTransfer - DeltaCutInKineticEnergyNow) *
( (5.0+ 1.0/tempvar)*0.25 / (TotalEnergy*TotalEnergy) -
betasquare /
(MaxKineticEnergyTransfer * DeltaCutInKineticEnergyNow)
) / 3.0 ;
}
TotalCrossSection = twopi_mc2_rcl2 * AtomicNumber
*TotalCrossSection/betasquare;
}
@@ -1,459 +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: G4ionIonisation.cc,v 1.4 1999/12/15 14:51:54 gunter 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
// ---------- G4ionIonisation physics process -----------
// by Laszlo Urban, 08 Dec 1998
// **************************************************************
// It is the first implementation of the ionisation for IONS
// --------------------------------------------------------------
#include "G4ionIonisation.hh"
#include "G4UnitsTable.hh"
// constructor and destructor
G4ionIonisation::G4ionIonisation(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
ParticleMass(proton_mass_c2),Charge(eplus),
dEdx(1.*MeV/mm),MinKineticEnergy(1.*keV)
{ PrintInfoDefinition() ; }
G4ionIonisation::~G4ionIonisation()
{ }
G4double G4ionIonisation::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....
const G4double minstep=0.01*mm ;
G4double KineticEnergy,StepLimit;
Charge = aParticle->GetDefinition()->GetPDGCharge()/eplus ;
KineticEnergy = aParticle->GetKineticEnergy();
G4double massratio=proton_mass_c2/
aParticle->GetDefinition()->GetPDGMass() ;
G4double Tscaled= KineticEnergy*massratio ;
G4double ChargeSquare = Charge*Charge ;
dEdx=ComputedEdx(aParticle,aMaterial) ;
StepLimit = 0.2*KineticEnergy/dEdx ;
if(StepLimit < minstep)
StepLimit = minstep ;
return StepLimit ;
}
G4VParticleChange* G4ionIonisation::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() ;
G4double massratio=proton_mass_c2/
aParticle->GetDefinition()->GetPDGMass() ;
ChargeSquare = Charge*Charge ;
G4int index = aMaterial->GetIndex() ;
E = aParticle->GetKineticEnergy() ;
if(E < MinKineticEnergy) MeanLoss = E ;
else
{
MeanLoss = Step*dEdx ;
MeanLoss /= (massratio*ChargeSquare) ;
}
finalT = E - MeanLoss ;
if(finalT < MinKineticEnergy) finalT = 0. ;
// kill the particle if the kinetic energy <= 0
if (finalT <= 0. )
{
finalT = 0.;
aParticleChange.SetStatusChange(fStopAndKill);
}
aParticleChange.SetEnergyChange( finalT ) ;
aParticleChange.SetLocalEnergyDeposit(E-finalT) ;
return &aParticleChange ;
}
G4double G4ionIonisation::GetMeanFreePath(
const G4Track& trackData,
G4double previousStepSize,
G4ForceCondition* condition)
{
const G4DynamicParticle* aParticle ;
G4Material* aMaterial ;
G4double MeanFreePath;
*condition = NotForced ;
aParticle = trackData.GetDynamicParticle() ;
aMaterial = trackData.GetMaterial() ;
G4double KineticEnergy = aParticle->GetKineticEnergy() ;
Charge=(aParticle->GetDefinition()->GetPDGCharge())/eplus;
G4double ChargeSquare=Charge*Charge ;
// compute the (macroscopic) cross section first
const G4ElementVector* theElementVector=
aMaterial->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
aMaterial->GetAtomicNumDensityVector();
const G4int NumberOfElements=
aMaterial->GetNumberOfElements() ;
G4int index = aMaterial->GetIndex() ;
DeltaCutInKineticEnergy = G4Electron::Electron()->GetCutsInEnergy();
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[index] ;
G4double sigma = 0. ;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
sigma += theAtomicNumDensityVector[iel]*
ComputeMicroscopicCrossSection(aParticle,
KineticEnergy,
(*theElementVector)(iel)->GetZ() ) ;
}
sigma *= twopi_mc2_rcl2 * ChargeSquare ;
// mean free path = 1./macroscopic cross section
MeanFreePath = sigma<=0 ? DBL_MAX : 1./sigma ;
return MeanFreePath ;
}
G4double G4ionIonisation::ComputeMicroscopicCrossSection(
const G4DynamicParticle* aParticle,
G4double KineticEnergy,
G4double AtomicNumber)
{
G4double TotalEnergy,
betasquare,
MaxKineticEnergyTransfer,TotalCrossSection,tempvar;
// get particle data ...................................
ParticleMass = aParticle->GetDefinition()->GetPDGMass() ;
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;
TotalCrossSection *= AtomicNumber/betasquare;
}
else
TotalCrossSection= 0. ;
return TotalCrossSection ;
}
G4double G4ionIonisation::ComputedEdx(const G4DynamicParticle* aParticle,
G4Material* material)
{
// cuts for electron ....................
DeltaCutInKineticEnergy = G4Electron::Electron()->GetCutsInEnergy() ;
G4double KineticEnergy , ionloss ;
G4double RateMass ;
G4bool isOutRange ;
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 ;
// get material parameters needed for the energy loss calculation
G4double ElectronDensity,Eexc,Eexc2,Cden,Mden,Aden,X0den,X1den,taul ;
G4double* ShellCorrectionVector;
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[material->GetIndex()] ;
// some local variables -------------------
G4double tau,tau0,Tmax,gamma,bg2,beta2,rcut,delta,x,sh ;
KineticEnergy=aParticle->GetKineticEnergy();
tau = KineticEnergy/proton_mass_c2 ;
if ( tau < taul )
// low energy part , parametrized energy loss formulae
{
ionloss = 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) ;
}
}
else
// high energy part , Bethe-Bloch formula
{
gamma = tau +1. ;
bg2 = tau*(tau+2.) ;
beta2 = bg2/(gamma*gamma) ;
Tmax = 2.*electron_mass_c2*bg2
/(1.+2.*gamma*RateMass+RateMass*RateMass) ;
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. ;
dEdx = ionloss ;
return dEdx ;
}
G4VParticleChange* G4ionIonisation::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
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,grej,Psquare,Esquare,summass,rate,grejc,finalMomentum ;
aParticleChange.Initialize(trackData) ;
aMaterial = trackData.GetMaterial() ;
aParticle = trackData.GetDynamicParticle() ;
KineticEnergy=aParticle->GetKineticEnergy();
TotalEnergy=KineticEnergy + ParticleMass ;
Psquare=KineticEnergy*(TotalEnergy+ParticleMass) ;
Esquare=TotalEnergy*TotalEnergy ;
summass = ParticleMass + electron_mass_c2 ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection() ;
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 )
{
// there is no change at all).....
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
else
{
// normal case ......................................
xc=DeltaCutInKineticEnergyNow/MaxKineticEnergyTransfer ;
rate=MaxKineticEnergyTransfer/TotalEnergy ;
// sampling follows ...
grejc=1.-betasquare*xc ;
do {
x=xc/(1.-(1.-xc)*G4UniformRand());
grej=(1.-x*betasquare)/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 ;
if (finalKineticEnergy > 0.)
{
// changed energy and momentum of the actual particle
finalMomentum=sqrt(finalKineticEnergy*
(finalKineticEnergy+2.*ParticleMass)) ;
finalPx = (TotalMomentum*ParticleDirection.x()
-DeltaTotalMomentum*DeltaDirection.x())/finalMomentum ;
finalPy = (TotalMomentum*ParticleDirection.y()
-DeltaTotalMomentum*DeltaDirection.y())/finalMomentum ;
finalPz = (TotalMomentum*ParticleDirection.z()
-DeltaTotalMomentum*DeltaDirection.z())/finalMomentum ;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
}
else
{
finalKineticEnergy = 0. ;
aParticleChange.SetStatusChange(fStopAndKill);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( theDeltaRay );
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
void G4ionIonisation::PrintInfoDefinition()
{
G4String comments = " Knock-on electron cross sections . ";
comments += "\n MeanFreePath is computed at tracking time.\n";
comments += " delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments << G4endl;
}