Import Geant4 6.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 10:41:53 +02:00
parent 4aea781e80
commit 96686e0c8f
6560 changed files with 153347 additions and 238155 deletions
@@ -22,7 +22,7 @@
//
//
// $Id: G4AnnihiToMuPair.cc,v 1.2 2003/02/04 11:08:42 maire Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
// ------------ G4AnnihiToMuPair physics process ------
// by H.Burkhardt, S. Kelner and R. Kokoulin, November 2002
@@ -22,7 +22,7 @@
//
//
// $Id: G4ComptonScattering.cc,v 1.17 2003/06/16 17:02:08 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
//
//------------ G4ComptonScattering physics process -----------------------------
@@ -22,7 +22,7 @@
//
//
// $Id: G4GammaConversion.cc,v 1.18 2003/06/16 17:02:09 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
//------------------ G4GammaConversion physics process -------------------------
// by Michel Maire, 24 May 1996
@@ -22,7 +22,7 @@
//
//
// $Id: G4GammaConversionToMuons.cc,v 1.4 2002/08/07 10:53:25 maire Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
// ------------ G4GammaConversionToMuons physics process ------
// by H.Burkhardt, S. Kelner and R. Kokoulin, April 2002
@@ -47,15 +47,15 @@ G4IonisationByLogicalVolume( const G4String& particleName,
if ( fParticleName == "e+" || fParticleName == "e-" )
{
feIonisation = new G4eIonisation(particleName) ;
feIonisation = new G4eIonisation52(particleName) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
fMuIonisation = new G4MuIonisation(particleName) ;
fMuIonisation = new G4MuIonisation52(particleName) ;
}
else
{
fhIonisation = new G4hIonisation(particleName) ;
fhIonisation = new G4hIonisation52(particleName) ;
}
}
@@ -20,6 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4MollerBhabhaModel.cc,v 1.11 2003/07/21 12:52:23 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
// -------------------------------------------------------------------
//
@@ -123,14 +125,14 @@ void G4MollerBhabhaModel::Initialise(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MollerBhabhaModel::ComputeDEDX(const G4Material* material,
G4double G4MollerBhabhaModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
{
if(!particle) SetParticle(p);
// calculate the dE/dx due to the ionization by Seltzer-Berger formula
const G4Material* material = couple->GetMaterial();
G4double electronDensity = material->GetElectronDensity();
G4double Zeff = electronDensity/material->GetTotNbOfAtomsPerVolume();
G4double th = 0.25*sqrt(Zeff)*keV;
@@ -202,19 +204,20 @@ G4double G4MollerBhabhaModel::ComputeDEDX(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MollerBhabhaModel::CrossSection(const G4Material* material,
G4double G4MollerBhabhaModel::CrossSection(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxEnergy)
G4double maxEnergy)
{
if(!particle) SetParticle(p);
G4double cross = 0.0;
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
tmax = std::min(maxEnergy, tmax);
if(cutEnergy < tmax) {
G4double xmin = cutEnergy/kineticEnergy;
G4double xmax = tmax/kineticEnergy;
G4double gam = kineticEnergy/electron_mass_c2 + 1.0;
@@ -225,8 +228,8 @@ G4double G4MollerBhabhaModel::CrossSection(const G4Material* material,
if (isElectron) {
G4double g = (2.0*gam - 1.0)/gamma2;
cross = ((xmax - xmin)*(1.0 - g + 1.0/(xmin*xmax)
+ 1.0/((1.0-xmin)*(1.0 - xmax)))
cross = ((xmax - xmin)*(1.0 - g + 1.0/(xmin*xmax)
+ 1.0/((1.0-xmin)*(1.0 - xmax)))
- g*log( xmax*(1.0 - xmin)/(xmin*(1.0 - xmax)) ) ) / beta2;
//Bhabha (e+e-) scattering
@@ -238,16 +241,16 @@ G4double G4MollerBhabhaModel::CrossSection(const G4Material* material,
G4double b1 = 2.0 - y2;
G4double b2 = y12*(3.0 + y2);
G4double y122= y12*y12;
G4double b4 = y122*y12;
G4double b4 = y122*y12;
G4double b3 = b4 + y122;
cross = (xmax - xmin)*(1.0/(beta2*xmin*xmax) + b2
- 0.5*b3*(xmin + xmax)
cross = (xmax - xmin)*(1.0/(beta2*xmin*xmax) + b2
- 0.5*b3*(xmin + xmax)
+ b4*(xmin*xmin + xmin*xmax + xmax*xmax)/3.0)
- b1*log(xmax/xmin);
}
cross *= twopi_mc2_rcl2*(material->GetElectronDensity())/kineticEnergy;
cross *= twopi_mc2_rcl2*(couple->GetMaterial()->GetElectronDensity())/kineticEnergy;
}
return cross;
}
@@ -0,0 +1,892 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// File name: G4PAIModel.cc
//
// Author: Vladimir.Grichine@cern.ch on base of Vladimir Ivanchenko code
//
// Creation date: 05.10.2003
//
// Modifications:
//
#include "G4Region.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsFreeVector.hh"
#include "G4PhysicsTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4MaterialTable.hh"
#include "G4SandiaTable.hh"
#include "G4PAIxSection.hh"
#include "G4PAIModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
#include "G4Poisson.hh"
#include "G4Step.hh"
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
const G4double G4PAIModel::fLowestKineticEnergy = 10.0*keV ; // 100.0*MeV ;
const G4double G4PAIModel::fHighestKineticEnergy = 100.*TeV ; // 1000.0*MeV ;
G4int G4PAIModel::fTotBin = 200 ; // 50
G4int G4PAIModel::fMeanNumber = 20 ; // 50 for dispersion
// create physics vector and fill it
G4PhysicsLogVector*
G4PAIModel::fProtonEnergyVector = new G4PhysicsLogVector(fLowestKineticEnergy,
fHighestKineticEnergy,
fTotBin);
////////////////////////////////////////////////////////////////////////
G4PAIModel::G4PAIModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),G4VEmFluctuationModel(nam),
fParticle(0),
fHighKinEnergy(100.*TeV),
fLowKinEnergy(2.0*MeV),
fTwoln10(2.0*log(10.0)),
fBg2lim(0.0169),
fTaulim(8.4146e-3)
{
if(p) SetParticle(p);
}
////////////////////////////////////////////////////////////////////////////
G4PAIModel::~G4PAIModel()
{
// delete member used ???
if(fdEdxVector) delete fdEdxVector ;
if ( fLambdaVector) delete fLambdaVector;
if ( fdNdxCutVector) delete fdNdxCutVector;
if( fPAItransferBank )
{
fPAItransferBank->clearAndDestroy();
delete fPAItransferBank ;
}
for(G4int i=0;i<fSandiaIntervalNumber;i++)
{
delete[] fSandiaPhotoAbsCof[i];
}
delete[] fSandiaPhotoAbsCof;
}
///////////////////////////////////////////////////////////////////////////////
void G4PAIModel::SetParticle(const G4ParticleDefinition* p)
{
fParticle = p;
fMass = fParticle->GetPDGMass();
fSpin = fParticle->GetPDGSpin();
G4double q = fParticle->GetPDGCharge()/eplus;
fChargeSquare = q*q;
fLowKinEnergy *= fMass/proton_mass_c2;
fRatio = electron_mass_c2/fMass;
fQc = fMass/fRatio;
}
//////////////////////////////////////////////////////////////////////////////
G4double G4PAIModel::HighEnergyLimit(const G4ParticleDefinition* p)
{
if(!fParticle) SetParticle(p);
return fHighKinEnergy;
}
///////////////////////////////////////////////////////////////////////////
G4double G4PAIModel::LowEnergyLimit( const G4ParticleDefinition* p )
{
if(!fParticle) SetParticle(p);
return fLowKinEnergy;
}
////////////////////////////////////////////////////////////////////////////
G4double G4PAIModel::MinEnergyCut( const G4ParticleDefinition*,
const G4MaterialCutsCouple* couple )
{
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
}
////////////////////////////////////////////////////////////////////////////
G4bool G4PAIModel::IsInCharge( const G4ParticleDefinition* p )
{
if(!fParticle) SetParticle(p);
return (p->GetPDGCharge() != 0.0 );
}
////////////////////////////////////////////////////////////////////////////
void G4PAIModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
if(!fParticle) SetParticle(p);
const G4ProductionCutsTable* theCoupleTable =
G4ProductionCutsTable::GetProductionCutsTable();
for(size_t iReg = 0; iReg < fPAIRegionVector.size();++iReg) // region loop
{
const G4Region* curReg = fPAIRegionVector[iReg];
// (*fPAIRegionVector[iRegion])
std::vector<G4Material*>::const_iterator matIter = curReg->GetMaterialIterator();
size_t jMat, numOfMat = curReg->GetNumberOfMaterials();
// for(size_t jMat = 0; jMat < curReg->GetNumberOfMaterials();++jMat){}
for(jMat = 0 ; jMat < numOfMat; ++jMat) // region material loop
{
const G4MaterialCutsCouple* matCouple = theCoupleTable->
GetMaterialCutsCouple( *matIter, curReg->GetProductionCuts() );
fMaterialCutsCoupleVector.push_back(matCouple);
static const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable();
size_t numberOfMat = G4Material::GetNumberOfMaterials();
size_t iMatGlob;
for(iMatGlob = 0 ; iMatGlob < numberOfMat ; iMatGlob++ )
{
if( *matIter == (*theMaterialTable)[iMatGlob]) break ;
}
fMatIndex = iMatGlob;
ComputeSandiaPhotoAbsCof();
BuildPAIonisationTable();
fPAIxscBank.push_back(fPAItransferBank);
fPAIdEdxBank.push_back(fPAIdEdxTable);
fdEdxTable.push_back(fdEdxVector);
BuildLambdaVector(matCouple);
fdNdxCutTable.push_back(fdNdxCutVector);
fLambdaTable.push_back(fLambdaVector);
matIter++;
}
}
}
//////////////////////////////////////////////////////////////////
void G4PAIModel::ComputeSandiaPhotoAbsCof()
{
G4int i, j, numberOfElements ;
static const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4SandiaTable thisMaterialSandiaTable(fMatIndex) ;
numberOfElements = (*theMaterialTable)[fMatIndex]->
GetNumberOfElements();
G4int* thisMaterialZ = new G4int[numberOfElements] ;
for(i=0;i<numberOfElements;i++) thisMaterialZ[i] =
(G4int)(*theMaterialTable)[fMatIndex]->GetElement(i)->GetZ() ;
fSandiaIntervalNumber = thisMaterialSandiaTable.SandiaIntervals
(thisMaterialZ,numberOfElements) ;
fSandiaIntervalNumber = thisMaterialSandiaTable.SandiaMixing
( thisMaterialZ ,
(*theMaterialTable)[fMatIndex]->GetFractionVector() ,
numberOfElements,fSandiaIntervalNumber) ;
fSandiaPhotoAbsCof = new G4double*[fSandiaIntervalNumber] ;
for(i=0;i<fSandiaIntervalNumber;i++) fSandiaPhotoAbsCof[i] = new G4double[5] ;
for( i = 0 ; i < fSandiaIntervalNumber ; i++ )
{
fSandiaPhotoAbsCof[i][0] = thisMaterialSandiaTable.GetPhotoAbsorpCof(i+1,0) ;
for( j = 1; j < 5 ; j++ )
{
fSandiaPhotoAbsCof[i][j] = thisMaterialSandiaTable.
GetPhotoAbsorpCof(i+1,j)*
(*theMaterialTable)[fMatIndex]->GetDensity() ;
}
}
delete[] thisMaterialZ ;
}
////////////////////////////////////////////////////////////////////////////
//
// Build tables for the ionization energy loss
// the tables are built for MATERIALS
// *********
void
G4PAIModel::BuildPAIonisationTable()
{
G4double LowEdgeEnergy , ionloss ;
G4double massRatio, tau, Tmax, Tmin, Tkin, deltaLow, gamma, bg2 ;
/*
if( fPAItransferBank )
{
fPAItransferBank->clearAndDestroy() ;
delete fPAItransferBank ;
}
*/
fPAItransferBank = new G4PhysicsTable(fTotBin);
/*
if( fPAIdEdxTable )
{
fPAIdEdxTable->clearAndDestroy() ;
delete fPAIdEdxTable ;
}
*/
fPAIdEdxTable = new G4PhysicsTable(fTotBin);
// if(fdEdxVector) delete fdEdxVector ;
fdEdxVector = new G4PhysicsLogVector( fLowestKineticEnergy,
fHighestKineticEnergy,
fTotBin ) ;
Tmin = fSandiaPhotoAbsCof[0][0] ; // low energy Sandia interval
deltaLow = 0.5*eV ;
for (G4int i = 0 ; i < fTotBin ; i++) //The loop for the kinetic energy
{
LowEdgeEnergy = fProtonEnergyVector->GetLowEdgeEnergy(i) ;
tau = LowEdgeEnergy/proton_mass_c2 ;
// if(tau < 0.01) tau = 0.01 ;
gamma = tau +1. ;
// G4cout<<"gamma = "<<gamma<<endl ;
bg2 = tau*(tau + 2. ) ;
massRatio = electron_mass_c2/proton_mass_c2 ;
Tmax = 2.*electron_mass_c2*bg2/(1.+2.*gamma*massRatio+massRatio*massRatio) ;
// G4cout<<"proton Tkin = "<<LowEdgeEnergy/MeV<<" MeV"
// <<" Tmax = "<<Tmax/MeV<<" MeV"<<G4endl;
// Tkin = DeltaCutInKineticEnergyNow ;
// if ( DeltaCutInKineticEnergyNow > Tmax) // was <
{
Tkin = Tmax ;
}
if ( Tkin < Tmin + deltaLow ) // low energy safety
{
Tkin = Tmin + deltaLow ;
}
G4PAIxSection protonPAI( fMatIndex,
Tkin,
bg2,
fSandiaPhotoAbsCof,
fSandiaIntervalNumber ) ;
// G4cout<<"ionloss = "<<ionloss*cm/keV<<" keV/cm"<<endl ;
// G4cout<<"n1 = "<<protonPAI.GetIntegralPAIxSection(1)*cm<<" 1/cm"<<endl ;
// G4cout<<"protonPAI.GetSplineSize() = "<<
// protonPAI.GetSplineSize()<<G4endl<<G4endl ;
G4PhysicsFreeVector* transferVector = new
G4PhysicsFreeVector(protonPAI.GetSplineSize()) ;
G4PhysicsFreeVector* dEdxVector = new
G4PhysicsFreeVector(protonPAI.GetSplineSize()) ;
for( G4int k = 0 ; k < protonPAI.GetSplineSize() ; k++ )
{
transferVector->PutValue( k ,
protonPAI.GetSplineEnergy(k+1),
protonPAI.GetIntegralPAIxSection(k+1) ) ;
dEdxVector->PutValue( k ,
protonPAI.GetSplineEnergy(k+1),
protonPAI.GetIntegralPAIdEdx(k+1) ) ;
}
ionloss = protonPAI.GetMeanEnergyLoss() ; // total <dE/dx>
if ( ionloss <= 0.) ionloss = DBL_MIN ;
fdEdxVector->PutValue(i,ionloss) ;
fPAItransferBank->insertAt(i,transferVector) ;
fPAIdEdxTable->insertAt(i,dEdxVector) ;
// delete[] transferVector ;
} // end of Tkin loop
// theLossTable->insert(fdEdxVector);
// end of material loop
// G4cout<<"G4PAIonisation::BuildPAIonisationTable() have been called"<<G4endl ;
// G4cout<<"G4PAIonisation::BuildLossTable() have been called"<<G4endl ;
}
///////////////////////////////////////////////////////////////////////
//
// Build mean free path tables for the delta ray production process
// tables are built for MATERIALS
//
void
G4PAIModel::BuildLambdaVector(const G4MaterialCutsCouple* matCutsCouple)
{
G4int i ;
G4double dNdxCut, lambda;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize(), jMatCC;
for (jMatCC = 0 ; jMatCC < numOfCouples ; jMatCC++ )
{
if( matCutsCouple == theCoupleTable->GetMaterialCutsCouple(jMatCC) ) break;
}
const std::vector<G4double>* deltaCutInKineticEnergy = theCoupleTable->
GetEnergyCutsVector(idxG4ElectronCut);
if (fLambdaVector) delete fLambdaVector;
if (fdNdxCutVector) delete fdNdxCutVector;
fLambdaVector = new G4PhysicsLogVector( fLowestKineticEnergy,
fHighestKineticEnergy,
fTotBin ) ;
fdNdxCutVector = new G4PhysicsLogVector( fLowestKineticEnergy,
fHighestKineticEnergy,
fTotBin ) ;
G4double deltaCutInKineticEnergyNow = (*deltaCutInKineticEnergy)[jMatCC] ;
G4cout<<"PAIModel DeltaCutInKineticEnergyNow = "
<<deltaCutInKineticEnergyNow/keV<<" keV"<<G4endl;
for ( i = 0 ; i < fTotBin ; i++ )
{
dNdxCut = GetdNdxCut(i,deltaCutInKineticEnergyNow) ;
lambda = dNdxCut <= DBL_MIN ? DBL_MAX: 1.0/dNdxCut ;
if (lambda <= 1000*kCarTolerance) lambda = 1000*kCarTolerance ; // Mmm ???
fLambdaVector->PutValue(i, lambda) ;
fdNdxCutVector->PutValue(i, dNdxCut) ;
}
}
///////////////////////////////////////////////////////////////////////
//
// Returns integral PAI cross section for energy transfers >= transferCut
G4double
G4PAIModel::GetdNdxCut( G4int iPlace, G4double transferCut)
{
G4int iTransfer;
G4double x1, x2, y1, y2, dNdxCut;
// G4cout<<"iPlace = "<<iPlace<<"; "<<"transferCut = "<<transferCut<<G4endl;
// G4cout<<"size = "<<G4int((*fPAItransferBank)(iPlace)->GetVectorLength())
// <<G4endl;
for( iTransfer = 0 ;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) ;
iTransfer++)
{
if(transferCut <= (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer))
{
break ;
}
}
if ( iTransfer >= G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) )
{
iTransfer = (*fPAItransferBank)(iPlace)->GetVectorLength() - 1 ;
}
y1 = (*(*fPAItransferBank)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAItransferBank)(iPlace))(iTransfer) ;
// G4cout<<"y1 = "<<y1<<"; "<<"y2 = "<<y2<<G4endl;
x1 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
// G4cout<<"x1 = "<<x1<<"; "<<"x2 = "<<x2<<G4endl;
if ( y1 == y2 ) dNdxCut = y2 ;
else
{
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
}
// G4cout<<""<<dNdxCut<<G4endl;
return dNdxCut ;
}
///////////////////////////////////////////////////////////////////////
//
// Returns integral dEdx for energy transfers >= transferCut
G4double
G4PAIModel::GetdEdxCut( G4int iPlace, G4double transferCut)
{
G4int iTransfer;
G4double x1, x2, y1, y2, dEdxCut;
// G4cout<<"iPlace = "<<iPlace<<"; "<<"transferCut = "<<transferCut<<G4endl;
// G4cout<<"size = "<<G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength())
// <<G4endl;
for( iTransfer = 0 ;
iTransfer < G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) ;
iTransfer++)
{
if(transferCut <= (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
{
break ;
}
}
if ( iTransfer >= G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) )
{
iTransfer = (*fPAIdEdxTable)(iPlace)->GetVectorLength() - 1 ;
}
y1 = (*(*fPAIdEdxTable)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAIdEdxTable)(iPlace))(iTransfer) ;
// G4cout<<"y1 = "<<y1<<"; "<<"y2 = "<<y2<<G4endl;
x1 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
// G4cout<<"x1 = "<<x1<<"; "<<"x2 = "<<x2<<G4endl;
if ( y1 == y2 ) dEdxCut = y2 ;
else
{
// if ( x1 == x2 ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
else dEdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
}
// G4cout<<""<<dEdxCut<<G4endl;
return dEdxCut ;
}
//////////////////////////////////////////////////////////////////////////////
G4double G4PAIModel::ComputeDEDX(const G4MaterialCutsCouple* matCC,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
{
G4int iTkin,iPlace;
size_t jMat;
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, dEdx;
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
{
if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
}
fPAIdEdxTable = fPAIdEdxBank[jMat];
fdEdxVector = fdEdxTable[jMat];
for(iTkin = 0 ; iTkin < fTotBin ; iTkin++)
{
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
}
iPlace = iTkin - 1;
if(iPlace < 0) iPlace = 0;
dEdx = charge2*( (*fdEdxVector)(iPlace) - GetdEdxCut(iPlace,cutEnergy) ) ;
if( dEdx < 0.) dEdx = 0.;
return dEdx;
}
/////////////////////////////////////////////////////////////////////////
G4double G4PAIModel::CrossSection( const G4MaterialCutsCouple* matCC,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxEnergy )
{
G4int iTkin,iPlace;
size_t jMat;
G4double tmax = std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, cross, cross1, cross2;
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
{
if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
}
fPAItransferBank = fPAIxscBank[jMat];
for(iTkin = 0 ; iTkin < fTotBin ; iTkin++)
{
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
}
iPlace = iTkin - 1;
if(iPlace < 0) iPlace = 0;
cross1 = GetdNdxCut(iPlace,tmax) ;
cross2 = GetdNdxCut(iPlace,cutEnergy) ;
cross = (cross2-cross1)*charge2;
if( cross < 0.) cross = 0.;
return cross;
}
///////////////////////////////////////////////////////////////////////////
//
// It is analog of PostStepDoIt in terms of secondary electron.
//
G4DynamicParticle*
G4PAIModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
size_t jMat;
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
{
if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
}
fPAItransferBank = fPAIxscBank[jMat];
fdNdxCutVector = fdNdxCutTable[jMat];
G4double tmax = std::min(MaxSecondaryEnergy(dp), maxEnergy);
if( tmin >= tmax ) return 0;
G4ThreeVector momentum = dp->GetMomentumDirection();
G4double particleMass = dp->GetMass();
G4double kineticEnergy = dp->GetKineticEnergy();
G4double scaledTkin = kineticEnergy*particleMass/proton_mass_c2;
G4double totalEnergy = kineticEnergy + particleMass;
G4double pSquare = kineticEnergy*(totalEnergy+particleMass);
G4double deltaTkin = GetPostStepTransfer(scaledTkin);
if( deltaTkin <= 0. ) return 0;
G4double deltaTotalMomentum = sqrt(deltaTkin*(deltaTkin + 2. * electron_mass_c2 ));
G4double totalMomentum = sqrt(pSquare);
G4double costheta = deltaTkin*(totalEnergy + electron_mass_c2)
/(deltaTotalMomentum * totalMomentum);
if (costheta < 0.) costheta = 0.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
G4double phi = twopi*G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
G4ThreeVector deltaDirection(dirx,diry,dirz);
deltaDirection.rotateUz(momentum);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* deltaRay = new G4DynamicParticle;
deltaRay->SetDefinition(G4Electron::Electron());
deltaRay->SetKineticEnergy( deltaTkin );
deltaRay->SetMomentumDirection(deltaDirection);
return deltaRay;
}
///////////////////////////////////////////////////////////////////////
//
// Returns post step PAI energy transfer > cut electron energy according to passed
// scaled kinetic energy of particle
G4double
G4PAIModel::GetPostStepTransfer( G4double scaledTkin )
{
// G4cout<<"G4PAIModel::GetPostStepTransfer"<<G4endl ;
G4int iTkin, iTransfer, iPlace ;
G4double transfer = 0.0, position, dNdxCut1, dNdxCut2, E1, E2, W1, W2, W ;
for(iTkin=0;iTkin<fTotBin;iTkin++)
{
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
}
iPlace = iTkin - 1 ;
dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
// G4cout<<"iPlace = "<<iPlace<<endl ;
if(iTkin == fTotBin) // Fermi plato, try from left
{
position = dNdxCut1*G4UniformRand() ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
}
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
}
else
{
dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
if(iTkin == 0) // Tkin is too small, trying from right only
{
position = dNdxCut2*G4UniformRand() ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace+1)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
}
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 = ( dNdxCut1*W1 + dNdxCut2*W2 )*G4UniformRand() ;
// G4cout<<position<<"\t" ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
{
if( position >=
( (*(*fPAItransferBank)(iPlace))(iTransfer)*W1 +
(*(*fPAItransferBank)(iPlace+1))(iTransfer)*W2) ) break ;
}
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
}
}
// G4cout<<"PAImodel PostStepTransfer = "<<transfer/keV<<" keV"<<endl ;
if(transfer < 0.0 ) transfer = 0.0 ;
return transfer ;
}
///////////////////////////////////////////////////////////////////////
//
// Returns random PAI energy transfer according to passed
// indexes of particle kinetic
G4double
G4PAIModel::GetEnergyTransfer( G4int iPlace, G4double position, G4int iTransfer )
{
G4double x1, x2, y1, y2, energyTransfer ;
if(iTransfer == 0)
{
energyTransfer = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
}
else
{
if ( iTransfer >= G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) )
{
iTransfer = (*fPAItransferBank)(iPlace)->GetVectorLength() - 1 ;
}
y1 = (*(*fPAItransferBank)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAItransferBank)(iPlace))(iTransfer) ;
x1 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
if ( x1 == x2 ) energyTransfer = x2 ;
else
{
if ( y1 == y2 ) energyTransfer = x1 + (x2 - x1)*G4UniformRand() ;
else
{
energyTransfer = x1 + (position - y1)*(x2 - x1)/(y2 - y1) ;
}
}
}
return energyTransfer ;
}
////////////////////////////////////////////////////////////////////////////
std::vector<G4DynamicParticle*>*
G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
return vdp;
}
///////////////////////////////////////////////////////////////////////
G4double G4PAIModel::SampleFluctuations( const G4Material* material,
const G4DynamicParticle* aParticle,
G4double&,
G4double& step,
G4double&)
{
size_t jMat;
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
{
if( material == fMaterialCutsCoupleVector[jMat]->GetMaterial() ) break;
}
fPAItransferBank = fPAIxscBank[jMat];
fdNdxCutVector = fdNdxCutTable[jMat];
G4int iTkin, iTransfer, iPlace ;
G4long numOfCollisions;
// G4cout<<"G4PAIModel::SampleFluctuations"<<G4endl ;
G4double loss = 0.0, charge2 ;
G4double position, E1, E2, W1, W2, W, dNdxCut1, dNdxCut2, meanNumber;
G4double Tkin = aParticle->GetKineticEnergy() ;
G4double MassRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass() ;
G4double charge = aParticle->GetDefinition()->GetPDGCharge() ;
charge2 = charge*charge ;
G4double TkinScaled = Tkin*MassRatio ;
for(iTkin=0;iTkin<fTotBin;iTkin++)
{
if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
}
iPlace = iTkin - 1 ;
dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
// G4cout<<"iPlace = "<<iPlace<<endl ;
if(iTkin == fTotBin) // Fermi plato, try from left
{
meanNumber =((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*step*charge2;
if(meanNumber < 0.) meanNumber = 0. ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
position = dNdxCut1+
((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*G4UniformRand() ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
}
loss += GetEnergyTransfer(iPlace,position,iTransfer);
numOfCollisions-- ;
}
}
else
{
dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
if(iTkin == 0) // Tkin is too small, trying from right only
{
meanNumber =((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*step*charge2;
if( meanNumber < 0. ) meanNumber = 0. ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
position = dNdxCut2+
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*G4UniformRand();
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace+1)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
}
loss += GetEnergyTransfer(iPlace+1,position,iTransfer);
numOfCollisions-- ;
}
}
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 - TkinScaled)*W ;
W2 = (TkinScaled - E1)*W ;
// G4cout<<"(*(*fPAItransferBank)(iPlace))(0) = "<<
// (*(*fPAItransferBank)(iPlace))(0)<<G4endl ;
// G4cout<<"(*(*fPAItransferBank)(iPlace+1))(0) = "<<
// (*(*fPAItransferBank)(iPlace+1))(0)<<G4endl ;
meanNumber=( ((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*W1 +
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*W2 )*step*charge2;
if(meanNumber<0.0) meanNumber = 0.0;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// G4cout<<"numOfCollisions = "<<numOfCollisions<<endl ;
while(numOfCollisions)
{
position =( (dNdxCut1+
((*(*fPAItransferBank)(iPlace ))(0)-dNdxCut1))*W1 +
(dNdxCut2+
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2))*W2 )*G4UniformRand();
// G4cout<<position<<"\t" ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
{
if( position >=
( (*(*fPAItransferBank)(iPlace))(iTransfer)*W1 +
(*(*fPAItransferBank)(iPlace+1))(iTransfer)*W2) )
{
break ;
}
}
// loss += (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
loss += GetEnergyTransfer(iPlace,position,iTransfer);
numOfCollisions-- ;
}
}
}
// G4cout<<"PAIModel AlongStepLoss = "<<loss/keV<<" keV"<<endl ;
return loss ;
}
//////////////////////////////////////////////////////////////////////
//
// Returns the statistical estimation of the energy loss distribution variance
//
G4double G4PAIModel::Dispersion( const G4Material* material,
const G4DynamicParticle* aParticle,
G4double& tmax,
G4double& step )
{
G4double loss, sumLoss=0., sumLoss2=0., sigma2, meanLoss=0.;
for(G4int i = 0 ; i < fMeanNumber; i++)
{
loss = SampleFluctuations(material,aParticle,tmax,step,meanLoss);
sumLoss += loss;
sumLoss2 += loss*loss;
}
meanLoss = sumLoss/fMeanNumber;
sigma2 = meanLoss*meanLoss + (sumLoss2-2*sumLoss*meanLoss)/fMeanNumber;
return sigma2;
}
//
//
/////////////////////////////////////////////////
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PAIxSection.cc,v 1.16 2003/06/25 13:40:42 gcosmo Exp $
// GEANT4 tag $Name: geant4-05-02 $
// $Id: G4PAIxSection.cc,v 1.17 2003/10/19 15:21:22 grichine Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
//
// G4PAIxSection.cc -- class implementation file
@@ -925,23 +925,27 @@ G4double G4PAIxSection::PAIdNdxPlasmon( G4int i ,
void G4PAIxSection::IntegralPAIxSection()
{
fIntegralPAIxSection[fSplineNumber] = 0 ;
fIntegralPAIxSection[0] = 0 ;
G4int k = fIntervalNumber -1 ;
for(G4int i=fSplineNumber-1;i>=1;i--)
{
if(fSplineEnergy[i] >= fEnergyInterval[k])
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] + SumOverInterval(i) ;
}
else
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] +
SumOverBorder(i+1,fEnergyInterval[k]) ;
k-- ;
}
}
fIntegralPAIxSection[fSplineNumber] = 0 ;
fIntegralPAIdEdx[fSplineNumber] = 0 ;
fIntegralPAIxSection[0] = 0 ;
G4int k = fIntervalNumber -1 ;
for(G4int i = fSplineNumber-1 ; i >= 1 ; i--)
{
if(fSplineEnergy[i] >= fEnergyInterval[k])
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] + SumOverInterval(i) ;
fIntegralPAIdEdx[i] = fIntegralPAIdEdx[i+1] + SumOverIntervaldEdx(i) ;
}
else
{
fIntegralPAIxSection[i] = fIntegralPAIxSection[i+1] +
SumOverBorder(i+1,fEnergyInterval[k]) ;
fIntegralPAIdEdx[i] = fIntegralPAIdEdx[i+1] +
SumOverBorderdEdx(i+1,fEnergyInterval[k]) ;
k-- ;
}
}
} // end of IntegralPAIxSection
////////////////////////////////////////////////////////////////////////
@@ -1042,6 +1046,33 @@ G4double G4PAIxSection::SumOverInterval( G4int i )
} // end of SumOverInterval
/////////////////////////////////
G4double G4PAIxSection::SumOverIntervaldEdx( G4int i )
{
G4double x0,x1,y0,yy1,a,b,c,result ;
x0 = fSplineEnergy[i] ;
x1 = fSplineEnergy[i+1] ;
y0 = fDifPAIxSection[i] ;
yy1 = fDifPAIxSection[i+1];
c = x1/x0;
a = log10(yy1/y0)/log10(c) ;
// b = log10(y0) - a*log10(x0) ;
b = y0/pow(x0,a) ;
a += 2 ;
if(a == 0)
{
result = b*log(x1/x0) ;
}
else
{
result = y0*(x1*x1*pow(c,a-2) - x0*x0)/a ;
}
return result ;
} // end of SumOverInterval
//////////////////////////////////////////////////////////////////////
//
// Calculation the PAI Cerenkov integral cross-section inside
@@ -1178,6 +1209,57 @@ G4double G4PAIxSection::SumOverBorder( G4int i ,
}
///////////////////////////////////////////////////////////////////////
G4double G4PAIxSection::SumOverBorderdEdx( G4int i ,
G4double en0 )
{
G4double x0,x1,y0,yy1,a,b,c,d,e0,result ;
e0 = en0 ;
x0 = fSplineEnergy[i] ;
x1 = fSplineEnergy[i+1] ;
y0 = fDifPAIxSection[i] ;
yy1 = fDifPAIxSection[i+1] ;
c = x1/x0;
d = e0/x0;
a = log10(yy1/y0)/log10(x1/x0) ;
// b0 = log10(y0) - a*log10(x0) ;
b = y0/pow(x0,a); // pow(10.,b) ;
a += 2 ;
if(a == 0)
{
result = b*log(x0/e0) ;
}
else
{
result = y0*(x0*x0 - e0*e0*pow(d,a-2))/a ;
}
x0 = fSplineEnergy[i - 1] ;
x1 = fSplineEnergy[i - 2] ;
y0 = fDifPAIxSection[i - 1] ;
yy1 = fDifPAIxSection[i - 2] ;
c = x1/x0;
d = e0/x0;
a = log10(yy1/y0)/log10(x1/x0) ;
// b0 = log10(y0) - a*log10(x0) ;
b = y0/pow(x0,a) ;
a += 2 ;
if(a == 0)
{
result += b*log(e0/x0) ;
}
else
{
result += y0*(e0*e0*pow(d,a-2) - x0*x0)/a ;
}
return result ;
}
///////////////////////////////////////////////////////////////////////////////
//
// Integration of Cerenkov cross-section for the case of
@@ -22,7 +22,7 @@
//
//
// $Id: G4PhotoElectricEffect.cc,v 1.29 2003/06/16 17:02:11 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -22,7 +22,7 @@
//
//
// $Id: G4PolarizedComptonScattering.cc,v 1.10 2003/05/26 16:13:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
//
//---------- G4PolarizedComptonScattering physics process ----------------------
@@ -22,7 +22,7 @@
//
//
// $Id: G4SynchrotronRadiation.cc,v 1.8 2003/05/26 16:13:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
@@ -22,7 +22,7 @@
//
//
// $Id: G4VPAIenergyLoss.cc,v 1.7 2003/03/10 12:22:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
@@ -22,7 +22,7 @@
//
//
// $Id: G4VeEnergyLoss.cc,v 1.32 2003/06/16 17:02:12 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
// -----------------------------------------------------------------------------
@@ -22,7 +22,7 @@
//
//
// $Id: G4VhEnergyLoss.cc,v 1.46 2003/06/16 17:02:13 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
// -----------------------------------------------------------------------------
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -20,6 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4eBremsstrahlungModel.cc,v 1.14 2003/07/21 12:52:23 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
// -------------------------------------------------------------------
//
@@ -63,7 +65,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eBremsstrahlungModel::G4eBremsstrahlungModel(const G4ParticleDefinition* p,
G4eBremsstrahlungModel::G4eBremsstrahlungModel(const G4ParticleDefinition* p,
const G4String& nam)
: G4VEmModel(nam),
particle(0),
@@ -141,8 +143,8 @@ void G4eBremsstrahlungModel::Initialise(const G4ParticleDefinition* p,
for (size_t ii=0; ii<partialSumSigma.size(); ii++){
G4DataVector* a=partialSumSigma[ii];
if ( a ) delete a;
}
if ( a ) delete a;
}
partialSumSigma.clear();
for (size_t i=0; i<numOfCouples; i++) {
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
@@ -156,7 +158,7 @@ void G4eBremsstrahlungModel::Initialise(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlungModel::ComputeDEDX(const G4Material* material,
G4double G4eBremsstrahlungModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
@@ -165,7 +167,7 @@ G4double G4eBremsstrahlungModel::ComputeDEDX(const G4Material* material,
if(kineticEnergy < lowKinEnergy) return 0.0;
const G4double thigh = 100.*GeV;
G4double cut = std::min(cutEnergy, kineticEnergy);
G4double rate, loss;
@@ -173,6 +175,7 @@ G4double G4eBremsstrahlungModel::ComputeDEDX(const G4Material* material,
const G4double coef1 = -0.5;
const G4double coef2 = 2./9.;
const G4Material* material = couple->GetMaterial();
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
@@ -194,7 +197,7 @@ G4double G4eBremsstrahlungModel::ComputeDEDX(const G4Material* material,
// extrapolation for KineticEnergy>100 GeV
} else {
// G4double xhigh = log(thigh/electron_mass_c2);
G4double cuthigh = thigh*0.5;
@@ -330,9 +333,9 @@ G4double G4eBremsstrahlungModel::ComputeBremLoss(G4double Z, G4double T,
G4double delz = 1.e6;
for (G4int ii=0; ii<NZ; ii++)
{
G4double dz = abs(Z-ZZ[ii]);
G4double dz = abs(Z-ZZ[ii]);
if(dz < delz) {
iz = ii;
iz = ii;
delz = dz;
}
}
@@ -351,7 +354,7 @@ G4double G4eBremsstrahlungModel::ComputeBremLoss(G4double Z, G4double T,
G4double E = T+electron_mass_c2 ;
loss = Z*(Z+ksi)*E*E/(T+E)*exp(beta*log(Cut/T))*(2.-clossh*exp(log(Z)/4.));
if (T <= Tlim) loss /= exp(closslow*log(Tlim/T));
if (T <= Tlim) loss /= exp(closslow*log(Tlim/T));
if( T <= Cut) loss *= exp(alosslow*log(T/Cut));
// correction
@@ -390,7 +393,7 @@ G4double G4eBremsstrahlungModel::PositronCorrFactorLoss(G4double Z,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eBremsstrahlungModel::CrossSection(const G4Material* material,
G4double G4eBremsstrahlungModel::CrossSection(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
@@ -402,6 +405,7 @@ G4double G4eBremsstrahlungModel::CrossSection(const G4Material* material,
G4double cut = std::max(cutEnergy, minThreshold);
if(cut >= tmax) return cross;
const G4Material* material = couple->GetMaterial();
const G4ElementVector* theElementVector = material->GetElementVector() ;
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
@@ -1,121 +0,0 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4eBremsstrahlungSTD
//
// Author: Michel Maire
//
// Creation date: 26.06.1996
//
// Modifications:
//
// 26-09-96 extension of the total crosssection above 100 GeV, M.Maire
// 1-10-96 new type G4OrderedTable; ComputePartialSumSigma(), M.Maire
// 16-10-96 DoIt() call to the non static GetEnergyCuts(), L.Urban
// 13-12-96 Sign corrected in grejmax and greject
// error definition of screenvar, L.Urban
// 20-03-97 new energy loss+ionisation+brems scheme, L.Urban
// 07-04-98 remove 'tracking cut' of the diffracted particle, MMa
// 13-08-98 new methods SetBining() PrintInfo()
// 03-03-99 Bug fixed in LPM effect, L.Urban
// 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
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 09-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 21-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined (mma)
// 08-11-01 particleMass becomes a local variable
// 30-04-02 V.Ivanchenko update to new design
// 23-12-02 Change interface in order to move to cut per region (VI)
// 26-12-02 Secondary production moved to derived classes (VI)
// 23-05-03 Define default integral + BohrFluctuations (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4eBremsstrahlungSTD.hh"
#include "G4Gamma.hh"
#include "G4eBremsstrahlungModel.hh"
#include "G4UniversalFluctuation.hh"
#include "G4UnitsTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4MaterialCutsCouple.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eBremsstrahlungSTD::G4eBremsstrahlungSTD(const G4String& name)
: G4VEnergyLossSTD(name)
{
InitialiseProcess();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eBremsstrahlungSTD::~G4eBremsstrahlungSTD()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungSTD::InitialiseProcess()
{
SetSecondaryParticle(G4Gamma::Gamma());
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
// G4VEmFluctuationModel* fm = new G4UniversalFluctuation();
// AddEmFluctuationModel(fm);
G4VEmModel* em = new G4eBremsstrahlungModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlungSTD::PrintInfoDefinition()
{
G4VEnergyLossSTD::PrintInfoDefinition();
G4cout << " Total cross sections from a parametrisation"
<< " based on the EEDL data library. "
<< G4endl
<< " Good description from 1 KeV to 100 GeV, "
<< "log scale extrapolation above 100 GeV."
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -20,13 +20,21 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4eIonisation.cc,v 1.37 2003/11/12 16:23:42 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
// $Id: G4eIonisation.cc,v 1.31 2003/06/16 17:02:16 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
// -------------------------------------------------------------------
//
//--------------- G4eIonisation physics process --------------------------------
// by Laszlo Urban, 20 March 1997
//------------------------------------------------------------------------------
// GEANT4 Class file
//
//
// File name: G4eIonisation
//
// Author: Laszlo Urban
//
// Creation date: 20.03.1997
//
// Modifications:
//
// 07-04-98 remove 'tracking cut' of the ionizing particle, mma
// 04-09-98 new methods SetBining() PrintInfo()
@@ -41,585 +49,94 @@
// 29-10-01 all static functions no more inlined (mma)
// 07-11-01 particleMass and Charge become local variables
// 26-03-02 change access to cuts in BuildLossTables (V.Ivanchenko)
// 16-01-03 Migrade to cut per region (V.Ivanchenko)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// 30-04-02 V.Ivanchenko update to new design
// 23-12-02 Change interface in order to move to cut per region (VI)
// 26-12-02 Secondary production moved to derived classes (VI)
// 13-02-03 SubCutoff regime is assigned to a region (V.Ivanchenko)
// 23-05-03 Define default integral + BohrFluctuations (V.Ivanchenko)
// 03-06-03 Fix initialisation problem for STD ionisation (V.Ivanchenko)
// 08-08-03 STD substitute standard (V.Ivanchenko)
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4eIonisation.hh"
#include "G4Electron.hh"
#include "G4MollerBhabhaModel.hh"
#include "G4UniversalFluctuation.hh"
//#include "G4BohrFluctuations.hh"
#include "G4UnitsTable.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eIonisation::LowerBoundLambda = 1.*keV;
G4double G4eIonisation::UpperBoundLambda = 100.*TeV;
G4int G4eIonisation::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4eIonisation::G4eIonisation(const G4String& processName)
: G4VeEnergyLoss(processName),
theMeanFreePathTable(NULL)
G4eIonisation::G4eIonisation(const G4String& name)
: G4VEnergyLossProcess(name),
theElectron(G4Electron::Electron()),
subCutoff(false),
isElectron(true),
isInitialised(false)
{
verboseLevel = -1;
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eIonisation::~G4eIonisation()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisation::InitialiseProcess()
{
if (theMeanFreePathTable)
{theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
}
SetSecondaryParticle(theElectron);
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
if(IsIntegral()) {
// flucModel = new G4BohrFluctuations();
flucModel = new G4UniversalFluctuation();
void G4eIonisation::SetLowerBoundLambda(G4double val)
{LowerBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation::SetUpperBoundLambda(G4double val)
{UpperBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation::SetNbinLambda(G4int n)
{NbinLambda = n;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation::GetLowerBoundLambda()
{return LowerBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation::GetUpperBoundLambda()
{return UpperBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4eIonisation::GetNbinLambda()
{return NbinLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
if( !CutsWhereModified() && theLossTable) return;
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
BuildLossTable(aParticleType);
if (&aParticleType==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildLambdaTable(aParticleType);
BuildDEDXTable(aParticleType);
if (&aParticleType==G4Electron::Electron()) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theLossTable) {theLossTable->clearAndDestroy(); delete theLossTable;}
theLossTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
//
for (size_t J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
// now comes the loop for the kinetic energy values
//
for (G4int i = 0; i < TotBin; i++)
{
G4double dEdx = ComputeRestrictedMeandEdx(aParticleType,
aVector->GetLowEdgeEnergy(i),
material,
DeltaThreshold);
if(1 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << aVector->GetLowEdgeEnergy(i)/MeV
<< " dEdx(MeV/mm)= " << dEdx*mm/MeV
<< G4endl;
}
aVector->PutValue(i,dEdx);
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4eIonisation::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
} else {
flucModel = new G4UniversalFluctuation();
}
//create table
//
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4VEmModel* em = new G4MollerBhabhaModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em, flucModel);
isInitialised = true;
if (theMeanFreePathTable)
{ theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
for (size_t J=0 ; J < numOfCouples; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundLambda, UpperBoundLambda, NbinLambda);
// compute the (macroscopic) cross section first
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
for (G4int i = 0 ; i < NbinLambda ; i++)
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double SIGMA = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
SIGMA += NbOfAtomsPerVolume[iel]*
ComputeCrossSectionPerAtom(aParticleType,
LowEdgeEnergy,
(*theElementVector)[iel]->GetZ(),
DeltaThreshold);
}
// mean free path = 1./macroscopic cross section
G4double Value = SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
aVector->PutValue(i, Value);
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4eIonisation::ComputeRestrictedMeandEdx (
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
const G4Material* material,
G4double DeltaThreshold)
const G4ParticleDefinition* G4eIonisation::DefineBaseParticle(const G4ParticleDefinition* p)
{
// calculate the dE/dx due to the ionization process (Geant4 internal units)
// Seltzer-Berger formula
//
G4double particleMass = aParticleType.GetPDGMass();
G4double ElectronDensity = material->GetElectronDensity();
G4double Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
Eexc /= particleMass; G4double Eexcm2 = Eexc*Eexc;
// for the lowenergy extrapolation
G4double Zeff = material->GetTotNbOfElectPerVolume()/
material->GetTotNbOfAtomsPerVolume();
G4double Th = 0.25*sqrt(Zeff)*keV;
G4double Tsav = 0.;
if (KineticEnergy < Th) {Tsav = KineticEnergy; KineticEnergy = Th;}
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau + 1., gamma2 = gamma*gamma, bg2 = tau*(tau+2.);
G4double beta2 = bg2/gamma2;
G4double Tmax,d,dEdx;
// electron
if (&aParticleType==G4Electron::Electron())
{
Tmax = KineticEnergy/2.;
d = std::min(DeltaThreshold, Tmax)/particleMass;
dEdx = log(2.*(tau+2.)/Eexcm2)-1.-beta2
+ log((tau-d)*d)+tau/(tau-d)
+ (0.5*d*d+(2.*tau+1.)*log(1.-d/tau))/gamma2;
}
else //positron
{
Tmax = KineticEnergy;
d = std::min(DeltaThreshold, Tmax)/particleMass;
G4double d2=d*d/2., d3=d*d*d/3., d4=d*d*d*d/4.;
G4double y=1./(1.+gamma);
dEdx = log(2.*(tau+2.)/Eexcm2)+log(tau*d)
- beta2*(tau+2.*d-y*(3.*d2+y*(d-d3+y*(d2-tau*d3+d4))))/tau;
}
//density correction
G4double Cden = material->GetIonisation()->GetCdensity();
G4double Mden = material->GetIonisation()->GetMdensity();
G4double Aden = material->GetIonisation()->GetAdensity();
G4double X0den = material->GetIonisation()->GetX0density();
G4double X1den = material->GetIonisation()->GetX1density();
const G4double twoln10 = 2.*log(10.);
G4double x = log(bg2)/twoln10;
G4double delta;
if (x < X0den) delta = 0.;
else {delta = twoln10*x - Cden;
if (x < X1den) delta += Aden*pow((X1den-x),Mden);
}
//now you can compute the total ionization loss
dEdx -= delta;
dEdx *= twopi_mc2_rcl2*ElectronDensity/beta2;
if (dEdx <= 0.) dEdx = 0.;
// low energy ?
const G4double Tl = 0.2*keV;
if (Tsav > 0.)
{
if (Tsav >= Tl) dEdx *= sqrt(KineticEnergy/Tsav);
else dEdx *= sqrt(KineticEnergy*Tsav)/Tl;
}
return dEdx;
if(p == G4Positron::Positron()) isElectron = false;
if(!isInitialised) InitialiseProcess();
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation::ComputeCrossSectionPerAtom(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber ,
G4double DeltaThreshold)
{
// calculates the cross section per atom (Geant4 internal units)
//(it is called for elements , AtomicNumber = Z )
G4double particleMass = aParticleType.GetPDGMass();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double betasquare = KineticEnergy*(TotalEnergy+particleMass)
/(TotalEnergy*TotalEnergy);
G4double gamma = TotalEnergy/particleMass, gamma2 = gamma*gamma;
G4double x=DeltaThreshold/KineticEnergy, x2 = x*x;
G4double MaxKineticEnergyTransfer;
if (&aParticleType==G4Electron::Electron())
MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
G4double TotalCrossSection = 0.;
if (MaxKineticEnergyTransfer > DeltaThreshold)
{
if (&aParticleType==G4Electron::Electron()) //Moller (e-e-) scattering
{
TotalCrossSection = (gamma-1.)*(gamma-1.)*(0.5-x)/gamma2 + 1./x
- 1./(1.-x)-(2.*gamma-1.)*log((1.-x)/x)/gamma2;
TotalCrossSection /= betasquare;
}
else //Bhabha (e+e-) scattering
{
G4double y=1./(1.+gamma), y2 =y*y, y12=1.-2.*y;
G4double b1=2.-y2, b2=y12*(3.+y2), b4=y12*y12*y12, b3=b4+y12*y12;
TotalCrossSection = (1./x-1.)/betasquare+b1*log(x)+b2*(1.-x)
- b3*(1.-x2)/2.+b4*(1.-x2*x)/3.;
}
TotalCrossSection *= (twopi_mc2_rcl2*AtomicNumber/KineticEnergy);
}
return TotalCrossSection ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4eIonisation::PostStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double particleMass = aParticle->GetDefinition()->GetPDGMass();
G4double Charge = aParticle->GetDefinition()->GetPDGCharge();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+particleMass);
G4double TotalMomentum = sqrt(Psquare);
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
// get kinetic energy cut for the electron
G4double DeltaThreshold = SecondaryEnergyThreshold(couple->GetIndex());
// some kinematics
G4double MaxKineticEnergyTransfer;
if (Charge < 0.) MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
// sampling kinetic energy of the delta ray
if (MaxKineticEnergyTransfer <= DeltaThreshold)
// pathological case (should not happen, there is no change at all)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// normal case
G4double cc,y,y2,c2,b0,b1,b2,b3,b4,x,x1,grej,grejc;
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau+1., gamma2=gamma*gamma;
G4double xc = DeltaThreshold/KineticEnergy, xc1=1.-xc;
if (Charge < 0.) // Moller (e-e-) scattering
{
b1=4./(9.*gamma2-10.*gamma+5.);
b2=tau*tau*b1; b3=(2.*gamma2+2.*gamma-1.)*b1;
cc=1.-2.*xc;
do {
x = xc/(1.-cc*G4UniformRand()); x1 = 1.-x;
grej = b2*x*x-b3*x/x1+b1*gamma2/(x1*x1);
} while (G4UniformRand()>grej);
}
else // Bhabha (e+e-) scattering
{
y=1./(gamma+1.); y2=y*y; cc=1.-2.*y;
b1=2.-y2; b2=cc*(3.+y2);
c2=cc*cc; b4=c2*cc; b3=c2+b4;
b0=gamma2/(gamma2-1.);
grejc=(((b4*xc-b3)*xc+b2)*xc-b1)*xc+b0;
do {
x = xc/(1.-xc1*G4UniformRand());
grej = ((((b4*x-b3)*x+b2)*x-b1)*x+b0)/grejc;
} while (G4UniformRand()>grej);
}
G4double DeltaKineticEnergy = x * KineticEnergy;
// protection :do not produce a secondary with 0. kinetic energy !
if (DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
G4double DeltaTotalMomentum = sqrt(DeltaKineticEnergy*(DeltaKineticEnergy +
2.*electron_mass_c2 ));
G4double costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum);
if (costheta < -1.) costheta = -1.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
G4double phi = twopi * G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
// changed energy and momentum of the actual particle
G4double finalKineticEnergy = KineticEnergy - DeltaKineticEnergy;
G4double Edep = 0.;
if (finalKineticEnergy > MinKineticEnergy)
{
G4double finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
G4double finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
G4double finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
G4double finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.SetMomentumChange(finalPx, finalPy, finalPz);
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (Charge < 0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange(finalKineticEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.SetLocalEnergyDeposit(Edep);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eIonisation::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
if ( !theLossTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if ( !theMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eIonisation::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theLossTable and theMeanFreePathTable
if (theLossTable != 0) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
G4String filename;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// retreive stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
theLossTable = new G4PhysicsTable(numOfCouples);
if ( !theLossTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (particle==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildDEDXTable(*particle);
if (particle==G4Electron::Electron()) PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisation::PrintInfoDefinition()
{
G4String comments = "delta cross sections from Moller+Bhabha. "
"Good description from 1 KeV to 100 GeV.\n"
" delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowerBoundLambda,"Energy")
<< " to " << G4BestUnit(UpperBoundLambda,"Energy")
<< " in " << NbinLambda << " bins."
<< "\n Step function: finalRange(mm)= " << finalRange
<< ", dRoverRange= " << dRoverRange
<< G4endl;
G4VEnergyLossProcess::PrintInfoDefinition();
G4cout << " Delta cross sections from Moller+Bhabha, "
<< "good description from 1 KeV to 100 GeV."
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisation::SetSubCutoff(G4bool val)
{
subCutoff = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,626 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4eIonisation52.cc,v 1.1 2003/08/08 11:30:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
//--------------- G4eIonisation52 physics process --------------------------------
// by Laszlo Urban, 20 March 1997
//------------------------------------------------------------------------------
//
// 07-04-98 remove 'tracking cut' of the ionizing particle, mma
// 04-09-98 new methods SetBining() PrintInfo()
// 07-09-98 Cleanup
// 02-02-99 correction inDoIt , L.Urban
// 10-02-00 modifications , new e.m. structure, L.Urban
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 09-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 13-08-01 new function ComputeRestrictedMeandEdx() (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 21-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined (mma)
// 07-11-01 particleMass and Charge become local variables
// 26-03-02 change access to cuts in BuildLossTables (V.Ivanchenko)
// 16-01-03 Migrade to cut per region (V.Ivanchenko)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4eIonisation52.hh"
#include "G4UnitsTable.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::LowerBoundLambda = 1.*keV;
G4double G4eIonisation52::UpperBoundLambda = 100.*TeV;
G4int G4eIonisation52::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4eIonisation52::G4eIonisation52(const G4String& processName)
: G4VeEnergyLoss(processName),
theMeanFreePathTable(NULL)
{
verboseLevel = -1;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4eIonisation52::~G4eIonisation52()
{
if (theMeanFreePathTable)
{theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::SetLowerBoundLambda(G4double val)
{LowerBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::SetUpperBoundLambda(G4double val)
{UpperBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::SetNbinLambda(G4int n)
{NbinLambda = n;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::GetLowerBoundLambda()
{return LowerBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::GetUpperBoundLambda()
{return UpperBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4eIonisation52::GetNbinLambda()
{return NbinLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
if( !CutsWhereModified() && theLossTable) return;
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
BuildLossTable(aParticleType);
if (&aParticleType==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildLambdaTable(aParticleType);
BuildDEDXTable(aParticleType);
if (&aParticleType==G4Electron::Electron()) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theLossTable) {theLossTable->clearAndDestroy(); delete theLossTable;}
theLossTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
//
for (size_t J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
// now comes the loop for the kinetic energy values
//
for (G4int i = 0; i < TotBin; i++)
{
G4double dEdx = ComputeRestrictedMeandEdx(aParticleType,
aVector->GetLowEdgeEnergy(i),
material,
DeltaThreshold);
if(1 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << aVector->GetLowEdgeEnergy(i)/MeV
<< " dEdx(MeV/mm)= " << dEdx*mm/MeV
<< G4endl;
}
aVector->PutValue(i,dEdx);
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4eIonisation52::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
//create table
//
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theMeanFreePathTable)
{ theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
for (size_t J=0 ; J < numOfCouples; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundLambda, UpperBoundLambda, NbinLambda);
// compute the (macroscopic) cross section first
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
for (G4int i = 0 ; i < NbinLambda ; i++)
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double SIGMA = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
SIGMA += NbOfAtomsPerVolume[iel]*
ComputeCrossSectionPerAtom(aParticleType,
LowEdgeEnergy,
(*theElementVector)[iel]->GetZ(),
DeltaThreshold);
}
// mean free path = 1./macroscopic cross section
G4double Value = SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
aVector->PutValue(i, Value);
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::ComputeRestrictedMeandEdx (
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
const G4Material* material,
G4double DeltaThreshold)
{
// calculate the dE/dx due to the ionization process (Geant4 internal units)
// Seltzer-Berger formula
//
G4double particleMass = aParticleType.GetPDGMass();
G4double ElectronDensity = material->GetElectronDensity();
G4double Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
Eexc /= particleMass; G4double Eexcm2 = Eexc*Eexc;
// for the lowenergy extrapolation
G4double Zeff = material->GetTotNbOfElectPerVolume()/
material->GetTotNbOfAtomsPerVolume();
G4double Th = 0.25*sqrt(Zeff)*keV;
G4double Tsav = 0.;
if (KineticEnergy < Th) {Tsav = KineticEnergy; KineticEnergy = Th;}
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau + 1., gamma2 = gamma*gamma, bg2 = tau*(tau+2.);
G4double beta2 = bg2/gamma2;
G4double Tmax,d,dEdx;
// electron
if (&aParticleType==G4Electron::Electron())
{
Tmax = KineticEnergy/2.;
d = std::min(DeltaThreshold, Tmax)/particleMass;
dEdx = log(2.*(tau+2.)/Eexcm2)-1.-beta2
+ log((tau-d)*d)+tau/(tau-d)
+ (0.5*d*d+(2.*tau+1.)*log(1.-d/tau))/gamma2;
}
else //positron
{
Tmax = KineticEnergy;
d = std::min(DeltaThreshold, Tmax)/particleMass;
G4double d2=d*d/2., d3=d*d*d/3., d4=d*d*d*d/4.;
G4double y=1./(1.+gamma);
dEdx = log(2.*(tau+2.)/Eexcm2)+log(tau*d)
- beta2*(tau+2.*d-y*(3.*d2+y*(d-d3+y*(d2-tau*d3+d4))))/tau;
}
//density correction
G4double Cden = material->GetIonisation()->GetCdensity();
G4double Mden = material->GetIonisation()->GetMdensity();
G4double Aden = material->GetIonisation()->GetAdensity();
G4double X0den = material->GetIonisation()->GetX0density();
G4double X1den = material->GetIonisation()->GetX1density();
const G4double twoln10 = 2.*log(10.);
G4double x = log(bg2)/twoln10;
G4double delta;
if (x < X0den) delta = 0.;
else {delta = twoln10*x - Cden;
if (x < X1den) delta += Aden*pow((X1den-x),Mden);
}
//now you can compute the total ionization loss
dEdx -= delta;
dEdx *= twopi_mc2_rcl2*ElectronDensity/beta2;
if (dEdx <= 0.) dEdx = 0.;
// low energy ?
const G4double Tl = 0.2*keV;
if (Tsav > 0.)
{
if (Tsav >= Tl) dEdx *= sqrt(KineticEnergy/Tsav);
else dEdx *= sqrt(KineticEnergy*Tsav)/Tl;
}
return dEdx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::ComputeCrossSectionPerAtom(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber ,
G4double DeltaThreshold)
{
// calculates the cross section per atom (Geant4 internal units)
//(it is called for elements , AtomicNumber = Z )
G4double particleMass = aParticleType.GetPDGMass();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double betasquare = KineticEnergy*(TotalEnergy+particleMass)
/(TotalEnergy*TotalEnergy);
G4double gamma = TotalEnergy/particleMass, gamma2 = gamma*gamma;
G4double x=DeltaThreshold/KineticEnergy, x2 = x*x;
G4double MaxKineticEnergyTransfer;
if (&aParticleType==G4Electron::Electron())
MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
G4double TotalCrossSection = 0.;
if (MaxKineticEnergyTransfer > DeltaThreshold)
{
if (&aParticleType==G4Electron::Electron()) //Moller (e-e-) scattering
{
TotalCrossSection = (gamma-1.)*(gamma-1.)*(0.5-x)/gamma2 + 1./x
- 1./(1.-x)-(2.*gamma-1.)*log((1.-x)/x)/gamma2;
TotalCrossSection /= betasquare;
}
else //Bhabha (e+e-) scattering
{
G4double y=1./(1.+gamma), y2 =y*y, y12=1.-2.*y;
G4double b1=2.-y2, b2=y12*(3.+y2), b4=y12*y12*y12, b3=b4+y12*y12;
TotalCrossSection = (1./x-1.)/betasquare+b1*log(x)+b2*(1.-x)
- b3*(1.-x2)/2.+b4*(1.-x2*x)/3.;
}
TotalCrossSection *= (twopi_mc2_rcl2*AtomicNumber/KineticEnergy);
}
return TotalCrossSection ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4eIonisation52::PostStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double particleMass = aParticle->GetDefinition()->GetPDGMass();
G4double Charge = aParticle->GetDefinition()->GetPDGCharge();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+particleMass);
G4double TotalMomentum = sqrt(Psquare);
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
// get kinetic energy cut for the electron
G4double DeltaThreshold = SecondaryEnergyThreshold(couple->GetIndex());
// some kinematics
G4double MaxKineticEnergyTransfer;
if (Charge < 0.) MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
// sampling kinetic energy of the delta ray
if (MaxKineticEnergyTransfer <= DeltaThreshold)
// pathological case (should not happen, there is no change at all)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// normal case
G4double cc,y,y2,c2,b0,b1,b2,b3,b4,x,x1,grej,grejc;
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau+1., gamma2=gamma*gamma;
G4double xc = DeltaThreshold/KineticEnergy, xc1=1.-xc;
if (Charge < 0.) // Moller (e-e-) scattering
{
b1=4./(9.*gamma2-10.*gamma+5.);
b2=tau*tau*b1; b3=(2.*gamma2+2.*gamma-1.)*b1;
cc=1.-2.*xc;
do {
x = xc/(1.-cc*G4UniformRand()); x1 = 1.-x;
grej = b2*x*x-b3*x/x1+b1*gamma2/(x1*x1);
} while (G4UniformRand()>grej);
}
else // Bhabha (e+e-) scattering
{
y=1./(gamma+1.); y2=y*y; cc=1.-2.*y;
b1=2.-y2; b2=cc*(3.+y2);
c2=cc*cc; b4=c2*cc; b3=c2+b4;
b0=gamma2/(gamma2-1.);
grejc=(((b4*xc-b3)*xc+b2)*xc-b1)*xc+b0;
do {
x = xc/(1.-xc1*G4UniformRand());
grej = ((((b4*x-b3)*x+b2)*x-b1)*x+b0)/grejc;
} while (G4UniformRand()>grej);
}
G4double DeltaKineticEnergy = x * KineticEnergy;
// protection :do not produce a secondary with 0. kinetic energy !
if (DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
G4double DeltaTotalMomentum = sqrt(DeltaKineticEnergy*(DeltaKineticEnergy +
2.*electron_mass_c2 ));
G4double costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum);
if (costheta < -1.) costheta = -1.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
G4double phi = twopi * G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
// changed energy and momentum of the actual particle
G4double finalKineticEnergy = KineticEnergy - DeltaKineticEnergy;
G4double Edep = 0.;
if (finalKineticEnergy > MinKineticEnergy)
{
G4double finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
G4double finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
G4double finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
G4double finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.SetMomentumChange(finalPx, finalPy, finalPz);
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (Charge < 0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange(finalKineticEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.SetLocalEnergyDeposit(Edep);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eIonisation52::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
if ( !theLossTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if ( !theMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eIonisation52::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theLossTable and theMeanFreePathTable
if (theLossTable != 0) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
G4String filename;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// retreive stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
theLossTable = new G4PhysicsTable(numOfCouples);
if ( !theLossTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (particle==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildDEDXTable(*particle);
if (particle==G4Electron::Electron()) PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::PrintInfoDefinition()
{
G4String comments = "delta cross sections from Moller+Bhabha. "
"Good description from 1 KeV to 100 GeV.\n"
" delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowerBoundLambda,"Energy")
<< " to " << G4BestUnit(UpperBoundLambda,"Energy")
<< " in " << NbinLambda << " bins."
<< "\n Step function: finalRange(mm)= " << finalRange
<< ", dRoverRange= " << dRoverRange
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -1,132 +0,0 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4eIonisationSTD
//
// Author: Laszlo Urban
//
// Creation date: 20.03.1997
//
// Modifications:
//
// 07-04-98 remove 'tracking cut' of the ionizing particle, mma
// 04-09-98 new methods SetBining() PrintInfo()
// 07-09-98 Cleanup
// 02-02-99 correction inDoIt , L.Urban
// 10-02-00 modifications , new e.m. structure, L.Urban
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 09-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 13-08-01 new function ComputeRestrictedMeandEdx() (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 21-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined (mma)
// 07-11-01 particleMass and Charge become local variables
// 26-03-02 change access to cuts in BuildLossTables (V.Ivanchenko)
// 30-04-02 V.Ivanchenko update to new design
// 23-12-02 Change interface in order to move to cut per region (VI)
// 26-12-02 Secondary production moved to derived classes (VI)
// 13-02-03 SubCutoff regime is assigned to a region (V.Ivanchenko)
// 23-05-03 Define default integral + BohrFluctuations (V.Ivanchenko)
// 03-06-03 Fix initialisation problem for STD ionisation (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4eIonisationSTD.hh"
#include "G4Electron.hh"
#include "G4MollerBhabhaModel.hh"
#include "G4UniversalFluctuation.hh"
#include "G4BohrFluctuations.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eIonisationSTD::G4eIonisationSTD(const G4String& name)
: G4VEnergyLossSTD(name),
theElectron(G4Electron::Electron()),
subCutoff(false),
isElectron(true),
isInitialised(false)
{
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eIonisationSTD::~G4eIonisationSTD()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationSTD::InitialiseProcess()
{
SetSecondaryParticle(theElectron);
if(IsIntegral()) flucModel = new G4BohrFluctuations();
else flucModel = new G4UniversalFluctuation();
G4VEmModel* em = new G4MollerBhabhaModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em, flucModel);
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4ParticleDefinition* G4eIonisationSTD::DefineBaseParticle(const G4ParticleDefinition* p)
{
if(p == G4Positron::Positron()) isElectron = false;
if(!isInitialised) InitialiseProcess();
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationSTD::PrintInfoDefinition()
{
G4VEnergyLossSTD::PrintInfoDefinition();
G4cout << " Delta cross sections from Moller+Bhabha, "
<< "good description from 1 KeV to 100 GeV."
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisationSTD::SetSubCutoff(G4bool val)
{
subCutoff = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -22,7 +22,7 @@
//
//
// $Id: G4eplusAnnihilation.cc,v 1.15 2003/05/26 16:13:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-02 $
// GEANT4 tag $Name: geant4-06-00 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -20,13 +20,21 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4hIonisation.cc,v 1.50 2003/11/12 16:23:42 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
// $Id: G4hIonisation.cc,v 1.44 2003/06/16 17:02:17 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
// -------------------------------------------------------------------
//
//---------------- G4hIonisation physics process -------------------------------
// by Laszlo Urban, 30 May 1997
//------------------------------------------------------------------------------
// GEANT4 Class file
//
//
// File name: G4hIonisation
//
// Author: Laszlo Urban
//
// Creation date: 30.05.1997
//
// Modifications:
//
// corrected by L.Urban on 24/09/97
// several bugs corrected by L.Urban on 13/01/98
@@ -48,683 +56,114 @@
// 08-11-01 Charge renamed zparticle; added to the dedx
// 27-03-02 Bug fix in scaling of lambda table (V.Ivanchenko)
// 09-04-02 Update calculation of tables for GenericIons (V.Ivanchenko)
// 10-06-02 bug fixed for stopping hadrons (V.Ivanchenko)
// 15-01-03 Migrade to cut per region (V.Ivanchenko)
// 10-03-03 Use SubType for GenericIons (V.Ivanchenko)
// 07-04-03 Fix problem of several runs (V.Ivanchenko)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 17-04-03 fix problem of hadron tests (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 30-04-02 V.Ivanchenko update to new design
// 04-12-02 Add verbose level definition (VI)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 13-02-03 SubCutoff regime is assigned to a region (V.Ivanchenko)
// 23-05-03 Define default integral + BohrFluctuations (V.Ivanchenko)
// 03-06-03 Fix initialisation problem for STD ionisation (V.Ivanchenko)
// 04-08-03 Set integral=false to be default (V.Ivanchenko)
// 08-08-03 STD substitute standard (V.Ivanchenko)
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
//
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4hIonisation.hh"
#include "G4ProcessManager.hh"
#include "G4Electron.hh"
#include "G4Proton.hh"
#include "G4AntiProton.hh"
#include "G4BraggModel.hh"
#include "G4BetheBlochModel.hh"
#include "G4UniversalFluctuation.hh"
#include "G4BohrFluctuations.hh"
#include "G4UnitsTable.hh"
#include "G4EnergyLossTables.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4hIonisation::LowerBoundLambda = 1.*keV;
G4double G4hIonisation::UpperBoundLambda = 100.*TeV;
G4int G4hIonisation::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4hIonisation::G4hIonisation(const G4String& processName)
: G4VhEnergyLoss(processName),
theMeanFreePathTable(0),
Tmincut(1*keV)
G4hIonisation::G4hIonisation(const G4String& name)
: G4VEnergyLossProcess(name),
theParticle(0),
theBaseParticle(0),
subCutoff(false),
isInitialised(false)
{
verboseLevel = 0;
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
SetVerboseLevel(0);
SetIntegral(false);
mass = 0.0;
ratio = 0.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4hIonisation::~G4hIonisation()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisation::InitialiseProcess()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
if(isInitialised) return;
SetSecondaryParticle(G4Electron::Electron());
mass = theParticle->GetPDGMass();
ratio = electron_mass_c2/mass;
G4double massFactor = mass/proton_mass_c2;
G4VEmModel* em = new G4BraggModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(2.0*MeV*massFactor);
if(IsIntegral()) {
flucModel = new G4BohrFluctuations();
} else {
flucModel = new G4UniversalFluctuation();
}
AddEmModel(1, em, flucModel);
G4VEmModel* em1 = new G4BetheBlochModel();
em1->SetLowEnergyLimit(2.0*MeV*massFactor);
em1->SetHighEnergyLimit(100.0*TeV);
AddEmModel(2, em1, flucModel);
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisation::SetLowerBoundLambda(G4double val)
{LowerBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation::SetUpperBoundLambda(G4double val)
{UpperBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation::SetNbinLambda(G4int n)
{NbinLambda = n;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation::GetLowerBoundLambda()
{return LowerBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation::GetUpperBoundLambda()
{return UpperBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4hIonisation::GetNbinLambda()
{return NbinLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
const G4ParticleDefinition* G4hIonisation::DefineBaseParticle(
const G4ParticleDefinition* p)
{
if(!theParticle) theParticle = p;
if(p != BaseParticle() && p != G4Proton::Proton()) theBaseParticle = G4Proton::Proton();
if(!isInitialised) InitialiseProcess();
if(verboseLevel > 0) {
G4cout << "G4hIonisation::BuildPhysicsTable for "
<< aParticleType.GetParticleName()
<< " mass(MeV)= " << aParticleType.GetPDGMass()/MeV
<< " charge= " << aParticleType.GetPDGCharge()/eplus
<< " type= " << aParticleType.GetParticleType()
<< G4endl;
if(verboseLevel > 1) {
G4cout << " MFPtable= " << theMeanFreePathTable
<< " DEDXtable= " << theDEDXpTable
<< " iniMass= " << initialMass
<< G4endl;
}
}
if(aParticleType.GetParticleType() == "nucleus" &&
aParticleType.GetParticleName() != "GenericIon" &&
aParticleType.GetParticleSubType() == "generic")
{
G4EnergyLossTables::Register(&aParticleType,
theDEDXpTable,
theRangepTable,
theInverseRangepTable,
theLabTimepTable,
theProperTimepTable,
LowestKineticEnergy, HighestKineticEnergy,
proton_mass_c2/aParticleType.GetPDGMass(),
TotBin);
return;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
const G4ParticleDefinition* theProton = G4Proton::Proton();
G4bool makeTables = false;
if (aParticleType.GetPDGCharge() > 0.)
{
if( CutsWhereModified() || !theDEDXpTable )
{
BuildLossTable(*theProton);
RecorderOfpProcess[0] = (*this).theLossTable;
// CounterOfpProcess++;
makeTables = true;
}
}
else
{
if( CutsWhereModified() || !theDEDXpbarTable )
{
BuildLossTable(*(G4AntiProton::AntiProton())) ;
RecorderOfpProcess[0] = (*this).theLossTable;
// CounterOfpbarProcess++;
makeTables = true;
}
}
BuildLambdaTable(aParticleType);
if( makeTables ) BuildDEDXTable(aParticleType);
if(2 < verboseLevel) {
G4cout << "MeanFreePathTable is built for "
<< aParticleType.GetParticleName() << G4endl;
G4cout << (*theMeanFreePathTable) << G4endl;
}
if (&aParticleType == theProton) PrintInfoDefinition();
return theBaseParticle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4hIonisation::BuildLossTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theLossTable) {theLossTable->clearAndDestroy(); delete theLossTable;}
theLossTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
//
for (size_t J=0; J<numOfCouples; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
// now comes the loop for the kinetic energy values
//
for (G4int i = 0 ; i < TotBin ; i++)
{
G4double dEdx = ComputeRestrictedMeandEdx(aParticleType,
aVector->GetLowEdgeEnergy(i),
material,
DeltaThreshold);
aVector->PutValue(i,dEdx);
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4hIonisation::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
//create table
//
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theMeanFreePathTable)
{theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// get electron cut in kinetic energy
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
for (size_t J=0 ; J < numOfCouples; J++)
{
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundLambda,UpperBoundLambda,NbinLambda);
// compute the (macroscopic) cross section first
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " Tcut(MeV)= " << DeltaThreshold/MeV
<< " Tmin(MeV)= " << LowerBoundLambda/MeV
<< " Tmax(MeV)= " << UpperBoundLambda/MeV
<< " nbins= " << NbinLambda
<< G4endl;
}
for ( G4int i = 0 ; i < NbinLambda ; i++ )
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double sigma = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
sigma += NbOfAtomsPerVolume[iel]*
ComputeCrossSectionPerAtom(aParticleType,
LowEdgeEnergy,
(*theElementVector)[iel]->GetZ(),
DeltaThreshold);
}
// mean free path = 1./macroscopic cross section
G4double Value = sigma > DBL_MIN ? 1./sigma : DBL_MAX;
aVector->PutValue(i, Value) ;
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation::ComputeRestrictedMeandEdx (
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
const G4Material* material,
G4double DeltaThreshold)
{
// calculate the dE/dx due to the ionization process (Geant4 internal units)
// Bethe-Bloch formula
//
G4double particleMass = proton_mass_c2;
G4double ElectronDensity = material->GetElectronDensity();
G4double Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
G4double Eexc2 = Eexc*Eexc;
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau + 1., bg2 = tau*(tau+2.), beta2 = bg2/(gamma*gamma);
G4double RateMass = electron_mass_c2/particleMass;
G4double Tmax=2.*electron_mass_c2*bg2/(1.+2.*gamma*RateMass+RateMass*RateMass);
G4double taul = material->GetIonisation()->GetTaul();
G4double dEdx = 0.;
//
// high energy part , Bethe-Bloch formula
//
if (tau > taul)
{
G4double rcut = std::min(DeltaThreshold/Tmax, 1.);
dEdx = log(2.*electron_mass_c2*bg2*Tmax/Eexc2)
+log(rcut)-(1.+rcut)*beta2;
//density correction
G4double Cden = material->GetIonisation()->GetCdensity();
G4double Mden = material->GetIonisation()->GetMdensity();
G4double Aden = material->GetIonisation()->GetAdensity();
G4double X0den = material->GetIonisation()->GetX0density();
G4double X1den = material->GetIonisation()->GetX1density();
const G4double twoln10 = 2.*log(10.);
G4double x = log(bg2)/twoln10;
G4double delta;
if (x < X0den) delta = 0.;
else {delta = twoln10*x - Cden;
if (x < X1den) delta += Aden*pow((X1den-x),Mden);
}
// shell correction
G4double* ShellCorrectionVector = material->GetIonisation()->
GetShellCorrectionVector();
const G4double bg2lim = 0.0169, taulim = 8.4146e-3;
G4double sh = 0., xs = 1.;
if (bg2 > bg2lim) for (G4int k=0; k<3; k++)
{xs *= bg2; sh += ShellCorrectionVector[k]/xs;}
else { for (G4int k=0; k<3; k++)
{xs *= bg2lim; sh += ShellCorrectionVector[k]/xs;}
sh *= log(tau/taul)/log(taulim/taul);
}
// now you can compute the total ionization loss
dEdx -= (delta + sh);
dEdx *= twopi_mc2_rcl2*ElectronDensity/beta2;
if (dEdx < 0.) dEdx = 0.;
}
//
// low energy part , parametrized energy loss formulae
//
if (tau <= taul)
{
// get elements in the actual material,
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume=material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
// loop for the elements in the material
dEdx = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)[iel];
if (tau < element->GetIonisation()->GetTau0())
dEdx += NbOfAtomsPerVolume[iel]
*(element->GetIonisation()->GetAlow()*sqrt(tau)
+ element->GetIonisation()->GetBlow()*tau);
else
dEdx += NbOfAtomsPerVolume[iel]
* element->GetIonisation()->GetClow()/sqrt(tau);
}
G4double deltaloss = 0.;
if (DeltaThreshold < Tmax)
{
deltaloss = log(Tmax/DeltaThreshold)-
beta2*(1.-DeltaThreshold/Tmax) ;
if (aParticleType.GetPDGSpin() == 0.5)
deltaloss += 0.25*(Tmax-DeltaThreshold)*(Tmax-DeltaThreshold)/
(KineticEnergy*KineticEnergy+proton_mass_c2*proton_mass_c2);
deltaloss *= twopi_mc2_rcl2*ElectronDensity/beta2;
}
dEdx -= deltaloss;
if (dEdx < 0.) dEdx = 0.;
}
return dEdx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation::ComputeCrossSectionPerAtom(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double DeltaThreshold)
{
// calculates the totalcross section per atom in GEANT4 internal units
// ( it is called for elements , AtomicNumber = Z )
//
// nb: cross section formula is OK for spin=0 and 1/2 only !
initialMass = aParticleType.GetPDGMass();
G4double particleMass = initialMass;
G4double TotalEnergy = KineticEnergy + particleMass;
G4double betasquare = KineticEnergy*(TotalEnergy+particleMass)
/(TotalEnergy*TotalEnergy);
G4double tempvar = particleMass+electron_mass_c2;
G4double MaxKineticEnergyTransfer = 2.*electron_mass_c2*KineticEnergy
*(TotalEnergy+particleMass)
/(tempvar*tempvar+2.*electron_mass_c2*KineticEnergy);
G4double TotalCrossSection = 0.;
if (MaxKineticEnergyTransfer > DeltaThreshold)
{
tempvar = DeltaThreshold/MaxKineticEnergyTransfer;
TotalCrossSection = (1.-tempvar*(1.-betasquare*log(tempvar)))
/DeltaThreshold;
G4double spin = aParticleType.GetPDGSpin();
if (spin == 0.5) TotalCrossSection += 0.5
*(MaxKineticEnergyTransfer-DeltaThreshold)
/(TotalEnergy*TotalEnergy);
if (spin == 1.) TotalCrossSection +=
-log(tempvar)/(3.0*DeltaThreshold) +
(MaxKineticEnergyTransfer - DeltaThreshold) *
((5.0+ 1.0/tempvar)*0.25 / (TotalEnergy*TotalEnergy) -
betasquare /
(MaxKineticEnergyTransfer * DeltaThreshold)) / 3.0;
TotalCrossSection *= twopi_mc2_rcl2*AtomicNumber/betasquare;
}
return TotalCrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4hIonisation::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double particleMass = aParticle->GetMass();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+particleMass);
G4double Esquare = TotalEnergy*TotalEnergy;
G4double betasquare=Psquare/Esquare;
G4double summass = particleMass + electron_mass_c2;
G4double MaxKineticEnergyTransfer = 2.*electron_mass_c2*Psquare
/(summass*summass+2.*electron_mass_c2*KineticEnergy);
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
// get electron cut in kinetic energy
G4double DeltaThreshold = SecondaryEnergyThreshold(couple->GetIndex());
// sampling kinetic energy of the delta ray
//
if (MaxKineticEnergyTransfer <= DeltaThreshold)
// pathological case (it should not happen, there is no change at all)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// normal case
G4double xc = DeltaThreshold/MaxKineticEnergyTransfer;
G4double rate = MaxKineticEnergyTransfer/TotalEnergy;
G4double te2 = 0.;
if (aParticle->GetDefinition()->GetPDGSpin() == 0.5) te2=0.5*rate*rate;
// sampling follows ...
G4double x,grej;
G4double grejc=1.-betasquare*xc+te2*xc*xc;
do { x=xc/(1.-(1.-xc)*G4UniformRand());
grej=(1.-x*(betasquare-x*te2))/grejc;
} while(G4UniformRand() > grej);
G4double DeltaKineticEnergy = x * MaxKineticEnergyTransfer;
if (DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
G4double DeltaTotalMomentum = sqrt(DeltaKineticEnergy * (DeltaKineticEnergy +
2. * electron_mass_c2 ));
G4double TotalMomentum = sqrt(Psquare);
G4double costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum);
if (costheta < -1.) costheta = -1.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
//
G4double phi = twopi*G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for delta ray
//
G4DynamicParticle *theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
//
G4double finalKineticEnergy = KineticEnergy - DeltaKineticEnergy;
G4double Edep = 0;
if (finalKineticEnergy > MinKineticEnergy)
{
G4double finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
G4double finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
G4double finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
G4double finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.SetLocalEnergyDeposit (Edep);
//ResetNumberOfInteractionLengthLeft();
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4hIonisation::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String particleName = particle->GetParticleName();
G4String filename;
// store stopping power table
if ((particleName == "proton")||(particleName == "anti_proton")) {
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
if ( !theLossTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
}
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if ( !theMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particleName
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4hIonisation::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String particleName = particle->GetParticleName();
if(particle->GetParticleType() == "nucleus" &&
particleName != "GenericIon" &&
particle->GetParticleSubType() == "generic")
{
G4EnergyLossTables::Register(particle,
theDEDXpTable,
theRangepTable,
theInverseRangepTable,
theLabTimepTable,
theProperTimepTable,
LowestKineticEnergy, HighestKineticEnergy,
proton_mass_c2/particle->GetPDGMass(),
TotBin);
return true;
}
// delete theLossTable and theMeanFreePathTable
if (theLossTable != 0) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
G4String filename;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
G4double charge = particle->GetPDGCharge()/eplus;
G4ParticleDefinition* basep = G4Proton::Proton();
if(charge < 0.0) basep = G4AntiProton::AntiProton();
filename = GetPhysicsTableFileName(basep,directory,"StoppingPower",ascii);
theLossTable = new G4PhysicsTable(numOfCouples);
if ( !theLossTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable0->RetrievePhysicsTable in " << filename
<< G4endl;
BuildPhysicsTable(*particle);
return true;
}
RecorderOfpProcess[0] = (*this).theLossTable;
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
initialMass = particle->GetPDGMass();
G4cout << GetProcessName() << " for " << particleName
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
BuildDEDXTable(*particle);
if (particle == G4Proton::Proton()) PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisation::PrintInfoDefinition()
{
G4String comments = " Knock-on electron cross sections . "
"\n Good description above the mean excitation energy.\n"
" delta ray energy sampled from differential Xsection.";
G4VEnergyLossProcess::PrintInfoDefinition();
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. "
<< "\n Step function: finalRange(mm)= " << finalRange
<< ", dRoverRange= " << dRoverRange
<< G4endl;
G4cout << " Bether-Bloch model for Escaled > 2 MeV, "
<< "parametrisation of Bragg peak below, "
<< "Integral mode " << IsIntegral()
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisation::SetSubCutoff(G4bool val)
{
subCutoff = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,731 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4hIonisation52.cc,v 1.1 2003/08/08 11:30:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
//---------------- G4hIonisation52 physics process -------------------------------
// by Laszlo Urban, 30 May 1997
//------------------------------------------------------------------------------
//
// corrected by L.Urban on 24/09/97
// several bugs corrected by L.Urban on 13/01/98
// 07-04-98 remove 'tracking cut' of the ionizing particle, mma
// 22-10-98 cleanup L.Urban
// 02-02-99 bugs fixed , L.Urban
// 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
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 10-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 14-08-01 new function ComputeRestrictedMeandEdx() + 'cleanup' (mma)
// 29-08-01 PostStepDoIt: correction for spin 1/2 (instead of 1) (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 25-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined
// 08-11-01 Charge renamed zparticle; added to the dedx
// 27-03-02 Bug fix in scaling of lambda table (V.Ivanchenko)
// 09-04-02 Update calculation of tables for GenericIons (V.Ivanchenko)
// 10-06-02 bug fixed for stopping hadrons (V.Ivanchenko)
// 15-01-03 Migrade to cut per region (V.Ivanchenko)
// 10-03-03 Use SubType for GenericIons (V.Ivanchenko)
// 07-04-03 Fix problem of several runs (V.Ivanchenko)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 17-04-03 fix problem of hadron tests (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
//
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4hIonisation52.hh"
#include "G4ProcessManager.hh"
#include "G4UnitsTable.hh"
#include "G4EnergyLossTables.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::LowerBoundLambda = 1.*keV;
G4double G4hIonisation52::UpperBoundLambda = 100.*TeV;
G4int G4hIonisation52::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4hIonisation52::G4hIonisation52(const G4String& processName)
: G4VhEnergyLoss(processName),
theMeanFreePathTable(0),
Tmincut(1*keV)
{
verboseLevel = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4hIonisation52::~G4hIonisation52()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::SetLowerBoundLambda(G4double val)
{LowerBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::SetUpperBoundLambda(G4double val)
{UpperBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::SetNbinLambda(G4int n)
{NbinLambda = n;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::GetLowerBoundLambda()
{return LowerBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::GetUpperBoundLambda()
{return UpperBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4hIonisation52::GetNbinLambda()
{return NbinLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
if(verboseLevel > 0) {
G4cout << "G4hIonisation52::BuildPhysicsTable for "
<< aParticleType.GetParticleName()
<< " mass(MeV)= " << aParticleType.GetPDGMass()/MeV
<< " charge= " << aParticleType.GetPDGCharge()/eplus
<< " type= " << aParticleType.GetParticleType()
<< G4endl;
if(verboseLevel > 1) {
G4cout << " MFPtable= " << theMeanFreePathTable
<< " DEDXtable= " << theDEDXpTable
<< " iniMass= " << initialMass
<< G4endl;
}
}
if(aParticleType.GetParticleType() == "nucleus" &&
aParticleType.GetParticleName() != "GenericIon" &&
aParticleType.GetParticleSubType() == "generic")
{
G4EnergyLossTables::Register(&aParticleType,
theDEDXpTable,
theRangepTable,
theInverseRangepTable,
theLabTimepTable,
theProperTimepTable,
LowestKineticEnergy, HighestKineticEnergy,
proton_mass_c2/aParticleType.GetPDGMass(),
TotBin);
return;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
const G4ParticleDefinition* theProton = G4Proton::Proton();
G4bool makeTables = false;
if (aParticleType.GetPDGCharge() > 0.)
{
if( CutsWhereModified() || !theDEDXpTable )
{
BuildLossTable(*theProton);
RecorderOfpProcess[0] = (*this).theLossTable;
// CounterOfpProcess++;
makeTables = true;
}
}
else
{
if( CutsWhereModified() || !theDEDXpbarTable )
{
BuildLossTable(*(G4AntiProton::AntiProton())) ;
RecorderOfpProcess[0] = (*this).theLossTable;
// CounterOfpbarProcess++;
makeTables = true;
}
}
BuildLambdaTable(aParticleType);
if( makeTables ) BuildDEDXTable(aParticleType);
if(2 < verboseLevel) {
G4cout << "MeanFreePathTable is built for "
<< aParticleType.GetParticleName() << G4endl;
G4cout << (*theMeanFreePathTable) << G4endl;
}
if (&aParticleType == theProton) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4hIonisation52::BuildLossTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theLossTable) {theLossTable->clearAndDestroy(); delete theLossTable;}
theLossTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
//
for (size_t J=0; J<numOfCouples; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
// now comes the loop for the kinetic energy values
//
for (G4int i = 0 ; i < TotBin ; i++)
{
G4double dEdx = ComputeRestrictedMeandEdx(aParticleType,
aVector->GetLowEdgeEnergy(i),
material,
DeltaThreshold);
aVector->PutValue(i,dEdx);
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4hIonisation52::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
//create table
//
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theMeanFreePathTable)
{theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// get electron cut in kinetic energy
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
for (size_t J=0 ; J < numOfCouples; J++)
{
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundLambda,UpperBoundLambda,NbinLambda);
// compute the (macroscopic) cross section first
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " Tcut(MeV)= " << DeltaThreshold/MeV
<< " Tmin(MeV)= " << LowerBoundLambda/MeV
<< " Tmax(MeV)= " << UpperBoundLambda/MeV
<< " nbins= " << NbinLambda
<< G4endl;
}
for ( G4int i = 0 ; i < NbinLambda ; i++ )
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double sigma = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
sigma += NbOfAtomsPerVolume[iel]*
ComputeCrossSectionPerAtom(aParticleType,
LowEdgeEnergy,
(*theElementVector)[iel]->GetZ(),
DeltaThreshold);
}
// mean free path = 1./macroscopic cross section
G4double Value = sigma > DBL_MIN ? 1./sigma : DBL_MAX;
aVector->PutValue(i, Value) ;
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::ComputeRestrictedMeandEdx (
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
const G4Material* material,
G4double DeltaThreshold)
{
// calculate the dE/dx due to the ionization process (Geant4 internal units)
// Bethe-Bloch formula
//
G4double particleMass = proton_mass_c2;
G4double ElectronDensity = material->GetElectronDensity();
G4double Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
G4double Eexc2 = Eexc*Eexc;
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau + 1., bg2 = tau*(tau+2.), beta2 = bg2/(gamma*gamma);
G4double RateMass = electron_mass_c2/particleMass;
G4double Tmax=2.*electron_mass_c2*bg2/(1.+2.*gamma*RateMass+RateMass*RateMass);
G4double taul = material->GetIonisation()->GetTaul();
G4double dEdx = 0.;
//
// high energy part , Bethe-Bloch formula
//
if (tau > taul)
{
G4double rcut = std::min(DeltaThreshold/Tmax, 1.);
dEdx = log(2.*electron_mass_c2*bg2*Tmax/Eexc2)
+log(rcut)-(1.+rcut)*beta2;
//density correction
G4double Cden = material->GetIonisation()->GetCdensity();
G4double Mden = material->GetIonisation()->GetMdensity();
G4double Aden = material->GetIonisation()->GetAdensity();
G4double X0den = material->GetIonisation()->GetX0density();
G4double X1den = material->GetIonisation()->GetX1density();
const G4double twoln10 = 2.*log(10.);
G4double x = log(bg2)/twoln10;
G4double delta;
if (x < X0den) delta = 0.;
else {delta = twoln10*x - Cden;
if (x < X1den) delta += Aden*pow((X1den-x),Mden);
}
// shell correction
G4double* ShellCorrectionVector = material->GetIonisation()->
GetShellCorrectionVector();
const G4double bg2lim = 0.0169, taulim = 8.4146e-3;
G4double sh = 0., xs = 1.;
if (bg2 > bg2lim) for (G4int k=0; k<3; k++)
{xs *= bg2; sh += ShellCorrectionVector[k]/xs;}
else { for (G4int k=0; k<3; k++)
{xs *= bg2lim; sh += ShellCorrectionVector[k]/xs;}
sh *= log(tau/taul)/log(taulim/taul);
}
// now you can compute the total ionization loss
dEdx -= (delta + sh);
dEdx *= twopi_mc2_rcl2*ElectronDensity/beta2;
if (dEdx < 0.) dEdx = 0.;
}
//
// low energy part , parametrized energy loss formulae
//
if (tau <= taul)
{
// get elements in the actual material,
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume=material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
// loop for the elements in the material
dEdx = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)[iel];
if (tau < element->GetIonisation()->GetTau0())
dEdx += NbOfAtomsPerVolume[iel]
*(element->GetIonisation()->GetAlow()*sqrt(tau)
+ element->GetIonisation()->GetBlow()*tau);
else
dEdx += NbOfAtomsPerVolume[iel]
* element->GetIonisation()->GetClow()/sqrt(tau);
}
G4double deltaloss = 0.;
if (DeltaThreshold < Tmax)
{
deltaloss = log(Tmax/DeltaThreshold)-
beta2*(1.-DeltaThreshold/Tmax) ;
if (aParticleType.GetPDGSpin() == 0.5)
deltaloss += 0.25*(Tmax-DeltaThreshold)*(Tmax-DeltaThreshold)/
(KineticEnergy*KineticEnergy+proton_mass_c2*proton_mass_c2);
deltaloss *= twopi_mc2_rcl2*ElectronDensity/beta2;
}
dEdx -= deltaloss;
if (dEdx < 0.) dEdx = 0.;
}
return dEdx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::ComputeCrossSectionPerAtom(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double DeltaThreshold)
{
// calculates the totalcross section per atom in GEANT4 internal units
// ( it is called for elements , AtomicNumber = Z )
//
// nb: cross section formula is OK for spin=0 and 1/2 only !
initialMass = aParticleType.GetPDGMass();
G4double particleMass = initialMass;
G4double TotalEnergy = KineticEnergy + particleMass;
G4double betasquare = KineticEnergy*(TotalEnergy+particleMass)
/(TotalEnergy*TotalEnergy);
G4double tempvar = particleMass+electron_mass_c2;
G4double MaxKineticEnergyTransfer = 2.*electron_mass_c2*KineticEnergy
*(TotalEnergy+particleMass)
/(tempvar*tempvar+2.*electron_mass_c2*KineticEnergy);
G4double TotalCrossSection = 0.;
if (MaxKineticEnergyTransfer > DeltaThreshold)
{
tempvar = DeltaThreshold/MaxKineticEnergyTransfer;
TotalCrossSection = (1.-tempvar*(1.-betasquare*log(tempvar)))
/DeltaThreshold;
G4double spin = aParticleType.GetPDGSpin();
if (spin == 0.5) TotalCrossSection += 0.5
*(MaxKineticEnergyTransfer-DeltaThreshold)
/(TotalEnergy*TotalEnergy);
if (spin == 1.) TotalCrossSection +=
-log(tempvar)/(3.0*DeltaThreshold) +
(MaxKineticEnergyTransfer - DeltaThreshold) *
((5.0+ 1.0/tempvar)*0.25 / (TotalEnergy*TotalEnergy) -
betasquare /
(MaxKineticEnergyTransfer * DeltaThreshold)) / 3.0;
TotalCrossSection *= twopi_mc2_rcl2*AtomicNumber/betasquare;
}
return TotalCrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4hIonisation52::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double particleMass = aParticle->GetMass();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+particleMass);
G4double Esquare = TotalEnergy*TotalEnergy;
G4double betasquare=Psquare/Esquare;
G4double summass = particleMass + electron_mass_c2;
G4double MaxKineticEnergyTransfer = 2.*electron_mass_c2*Psquare
/(summass*summass+2.*electron_mass_c2*KineticEnergy);
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
// get electron cut in kinetic energy
G4double DeltaThreshold = SecondaryEnergyThreshold(couple->GetIndex());
// sampling kinetic energy of the delta ray
//
if (MaxKineticEnergyTransfer <= DeltaThreshold)
// pathological case (it should not happen, there is no change at all)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// normal case
G4double xc = DeltaThreshold/MaxKineticEnergyTransfer;
G4double rate = MaxKineticEnergyTransfer/TotalEnergy;
G4double te2 = 0.;
if (aParticle->GetDefinition()->GetPDGSpin() == 0.5) te2=0.5*rate*rate;
// sampling follows ...
G4double x,grej;
G4double grejc=1.-betasquare*xc+te2*xc*xc;
do { x=xc/(1.-(1.-xc)*G4UniformRand());
grej=(1.-x*(betasquare-x*te2))/grejc;
} while(G4UniformRand() > grej);
G4double DeltaKineticEnergy = x * MaxKineticEnergyTransfer;
if (DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
G4double DeltaTotalMomentum = sqrt(DeltaKineticEnergy * (DeltaKineticEnergy +
2. * electron_mass_c2 ));
G4double TotalMomentum = sqrt(Psquare);
G4double costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum);
if (costheta < -1.) costheta = -1.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
//
G4double phi = twopi*G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for delta ray
//
G4DynamicParticle *theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
//
G4double finalKineticEnergy = KineticEnergy - DeltaKineticEnergy;
G4double Edep = 0;
if (finalKineticEnergy > MinKineticEnergy)
{
G4double finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
G4double finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
G4double finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
G4double finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.SetLocalEnergyDeposit (Edep);
//ResetNumberOfInteractionLengthLeft();
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4hIonisation52::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String particleName = particle->GetParticleName();
G4String filename;
// store stopping power table
if ((particleName == "proton")||(particleName == "anti_proton")) {
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
if ( !theLossTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
}
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if ( !theMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particleName
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4hIonisation52::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String particleName = particle->GetParticleName();
if(particle->GetParticleType() == "nucleus" &&
particleName != "GenericIon" &&
particle->GetParticleSubType() == "generic")
{
G4EnergyLossTables::Register(particle,
theDEDXpTable,
theRangepTable,
theInverseRangepTable,
theLabTimepTable,
theProperTimepTable,
LowestKineticEnergy, HighestKineticEnergy,
proton_mass_c2/particle->GetPDGMass(),
TotBin);
return true;
}
// delete theLossTable and theMeanFreePathTable
if (theLossTable != 0) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
G4String filename;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
G4double charge = particle->GetPDGCharge()/eplus;
G4ParticleDefinition* basep = G4Proton::Proton();
if(charge < 0.0) basep = G4AntiProton::AntiProton();
filename = GetPhysicsTableFileName(basep,directory,"StoppingPower",ascii);
theLossTable = new G4PhysicsTable(numOfCouples);
if ( !theLossTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable0->RetrievePhysicsTable in " << filename
<< G4endl;
BuildPhysicsTable(*particle);
return true;
}
RecorderOfpProcess[0] = (*this).theLossTable;
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
initialMass = particle->GetPDGMass();
G4cout << GetProcessName() << " for " << particleName
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
BuildDEDXTable(*particle);
if (particle == G4Proton::Proton()) PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::PrintInfoDefinition()
{
G4String comments = " Knock-on electron cross sections . "
"\n Good description above the mean excitation energy.\n"
" delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. "
<< "\n Step function: finalRange(mm)= " << finalRange
<< ", dRoverRange= " << dRoverRange
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -1,156 +0,0 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4hIonisationSTD
//
// Author: Laszlo Urban
//
// Creation date: 30.05.1997
//
// Modifications:
//
// corrected by L.Urban on 24/09/97
// several bugs corrected by L.Urban on 13/01/98
// 07-04-98 remove 'tracking cut' of the ionizing particle, mma
// 22-10-98 cleanup L.Urban
// 02-02-99 bugs fixed , L.Urban
// 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
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 10-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 14-08-01 new function ComputeRestrictedMeandEdx() + 'cleanup' (mma)
// 29-08-01 PostStepDoIt: correction for spin 1/2 (instead of 1) (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 25-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined
// 08-11-01 Charge renamed zparticle; added to the dedx
// 27-03-02 Bug fix in scaling of lambda table (V.Ivanchenko)
// 09-04-02 Update calculation of tables for GenericIons (V.Ivanchenko)
// 30-04-02 V.Ivanchenko update to new design
// 04-12-02 Add verbose level definition (VI)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 13-02-03 SubCutoff regime is assigned to a region (V.Ivanchenko)
// 23-05-03 Define default integral + BohrFluctuations (V.Ivanchenko)
// 03-06-03 Fix initialisation problem for STD ionisation (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4hIonisationSTD.hh"
#include "G4Electron.hh"
#include "G4Proton.hh"
#include "G4AntiProton.hh"
#include "G4BraggModel.hh"
#include "G4BetheBlochModel.hh"
#include "G4UniversalFluctuation.hh"
#include "G4BohrFluctuations.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4hIonisationSTD::G4hIonisationSTD(const G4String& name)
: G4VEnergyLossSTD(name),
theParticle(0),
theBaseParticle(0),
subCutoff(false),
isInitialised(false)
{
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
SetVerboseLevel(0);
mass = 0.0;
ratio = 0.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4hIonisationSTD::~G4hIonisationSTD()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisationSTD::InitialiseProcess()
{
SetSecondaryParticle(G4Electron::Electron());
G4VEmModel* em = new G4BraggModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(2.0*MeV);
if(IsIntegral()) flucModel = new G4BohrFluctuations();
else flucModel = new G4UniversalFluctuation();
AddEmModel(1, em, flucModel);
G4VEmModel* em1 = new G4BetheBlochModel();
em1->SetLowEnergyLimit(2.0*MeV);
em1->SetHighEnergyLimit(100.0*TeV);
AddEmModel(2, em1, flucModel);
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4ParticleDefinition* G4hIonisationSTD::DefineBaseParticle(
const G4ParticleDefinition* p)
{
if(!theParticle) theParticle = p;
if(!theBaseParticle && p != G4Proton::Proton()) theBaseParticle = G4Proton::Proton();
if(!isInitialised) InitialiseProcess();
mass = p->GetPDGMass();
ratio = electron_mass_c2/mass;
return theBaseParticle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisationSTD::PrintInfoDefinition()
{
G4VEnergyLossSTD::PrintInfoDefinition();
G4cout << " Bether-Bloch model for Escaled > 2 MeV, "
<< "parametrisation of Bragg peak below."
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisationSTD::SetSubCutoff(G4bool val)
{
subCutoff = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -20,6 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4ionIonisation.cc,v 1.21 2003/11/12 16:23:42 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00 $
//
// -------------------------------------------------------------------
//
@@ -38,6 +40,8 @@
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 13-02-03 SubCutoff regime is assigned to a region (V.Ivanchenko)
// 18-04-03 Use IonFluctuations (V.Ivanchenko)
// 03-08-03 Add effective charge (V.Ivanchenko)
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
//
//
// -------------------------------------------------------------------
@@ -57,9 +61,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ionIonisation::G4ionIonisation(const G4String& name)
: G4VEnergyLossSTD(name),
: G4VEnergyLossProcess(name),
theParticle(0),
theBaseParticle(G4Proton::Proton()),
subCutoff(false)
{
InitialiseProcess();
@@ -74,8 +77,6 @@ G4ionIonisation::~G4ionIonisation()
void G4ionIonisation::InitialiseProcess()
{
SetVerboseLevel(0);
SetSecondaryParticle(G4Electron::Electron());
SetDEDXBinning(120);
@@ -94,6 +95,11 @@ void G4ionIonisation::InitialiseProcess()
em1->SetHighEnergyLimit(100.0*TeV);
AddEmModel(2, em1, flucModel);
SetIntegral(false);
chargeLowLimit = 0.1;
energyLowLimit = 250.*MeV;
SetLinearLossLimit(0.15);
//SetStepLimits(0.1, 0.1*mm);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -101,15 +107,16 @@ void G4ionIonisation::InitialiseProcess()
const G4ParticleDefinition* G4ionIonisation::DefineBaseParticle(
const G4ParticleDefinition* p)
{
if(!theParticle) theParticle = p;
if(p) theParticle = p;
theBaseParticle = G4Proton::Proton();
return theBaseParticle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ionIonisation::PrintInfoDefinition()
void G4ionIonisation::PrintInfoDefinition()
{
G4VEnergyLossSTD::PrintInfoDefinition();
G4VEnergyLossProcess::PrintInfoDefinition();
G4cout << " Scaling relation is used to proton dE/dx and range"
<< G4endl
@@ -127,4 +134,141 @@ void G4ionIonisation::SetSubCutoff(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ionIonisation::EffectiveCharge(const G4ParticleDefinition* p,
const G4Material* material,
G4double kineticEnergy)
{
G4double mass = p->GetPDGMass();
G4double charge = p->GetPDGCharge();
G4double Zi = charge/eplus;
chargeCorrection = 1.0;
// The aproximation of ion effective charge from:
// J.F.Ziegler, J.P. Biersack, U. Littmark
// The Stopping and Range of Ions in Matter,
// Vol.1, Pergamon Press, 1985
// Fast ions or hadrons
G4double reducedEnergy = kineticEnergy * proton_mass_c2/mass ;
if( reducedEnergy > energyLowLimit || Zi < 1.5 ) return charge ;
static G4double vFermi[92] = {
1.0309, 0.15976, 0.59782, 1.0781, 1.0486, 1.0, 1.058, 0.93942, 0.74562, 0.3424,
0.45259, 0.71074, 0.90519, 0.97411, 0.97184, 0.89852, 0.70827, 0.39816, 0.36552, 0.62712,
0.81707, 0.9943, 1.1423, 1.2381, 1.1222, 0.92705, 1.0047, 1.2, 1.0661, 0.97411,
0.84912, 0.95, 1.0903, 1.0429, 0.49715, 0.37755, 0.35211, 0.57801, 0.77773, 1.0207,
1.029, 1.2542, 1.122, 1.1241, 1.0882, 1.2709, 1.2542, 0.90094, 0.74093, 0.86054,
0.93155, 1.0047, 0.55379, 0.43289, 0.32636, 0.5131, 0.695, 0.72591, 0.71202, 0.67413,
0.71418, 0.71453, 0.5911, 0.70263, 0.68049, 0.68203, 0.68121, 0.68532, 0.68715, 0.61884,
0.71801, 0.83048, 1.1222, 1.2381, 1.045, 1.0733, 1.0953, 1.2381, 1.2879, 0.78654,
0.66401, 0.84912, 0.88433, 0.80746, 0.43357, 0.41923, 0.43638, 0.51464, 0.73087, 0.81065,
1.9578, 1.0257} ;
static G4double lFactor[92] = {
1.0, 1.0, 1.1, 1.06, 1.01, 1.03, 1.04, 0.99, 0.95, 0.9,
0.82, 0.81, 0.83, 0.88, 1.0, 0.95, 0.97, 0.99, 0.98, 0.97,
0.98, 0.97, 0.96, 0.93, 0.91, 0.9, 0.88, 0.9, 0.9, 0.9,
0.9, 0.85, 0.9, 0.9, 0.91, 0.92, 0.9, 0.9, 0.9, 0.9,
0.9, 0.88, 0.9, 0.88, 0.88, 0.9, 0.9, 0.88, 0.9, 0.9,
0.9, 0.9, 0.96, 1.2, 0.9, 0.88, 0.88, 0.85, 0.9, 0.9,
0.92, 0.95, 0.99, 1.03, 1.05, 1.07, 1.08, 1.1, 1.08, 1.08,
1.08, 1.08, 1.09, 1.09, 1.1, 1.11, 1.12, 1.13, 1.14, 1.15,
1.17, 1.2, 1.18, 1.17, 1.17, 1.16, 1.16, 1.16, 1.16, 1.16,
1.16, 1.16} ;
static G4double c[6] = {0.2865, 0.1266, -0.001429,
0.02402,-0.01135, 0.001475} ;
// get elements in the actual material,
const G4ElementVector* theElementVector = material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements = material->GetNumberOfElements() ;
// loop for the elements in the material
// to find out average values Z, vF, lF
G4double z = 0.0, vF = 0.0, lF = 0.0, norm = 0.0 ;
if( 1 == NumberOfElements ) {
z = material->GetZ() ;
G4int iz = G4int(z) - 1 ;
if(iz < 0) iz = 0 ;
else if(iz > 91) iz = 91 ;
vF = vFermi[iz] ;
lF = lFactor[iz] ;
} else {
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)[iel] ;
G4double z2 = element->GetZ() ;
const G4double weight = theAtomicNumDensityVector[iel] ;
norm += weight ;
z += z2 * weight ;
G4int iz = G4int(z2) - 1 ;
if(iz < 0) iz = 0 ;
else if(iz > 91) iz =91 ;
vF += vFermi[iz] * weight ;
lF += lFactor[iz] * weight ;
}
z /= norm ;
vF /= norm ;
lF /= norm ;
}
G4double q;
// Helium ion case
if( Zi < 2.5 ) {
// Normalise to He4 mass
G4double e = log(std::max(1.0, kineticEnergy / (keV*4.0026) ) );
G4double x = c[0] ;
G4double y = 1.0 ;
for (G4int i=1; i<6; i++) {
y *= e ;
x += y * c[i] ;
}
q = 7.6 - e ;
q = 1.0 + ( 0.007 + 0.00005 * z ) * exp( -q*q ) * sqrt(1.0 - exp(-x)) ;
if( q < chargeLowLimit ) q = chargeLowLimit ;
// Heavy ion case
} else {
// v1 is ion velocity in vF unit
G4double v1 = sqrt( reducedEnergy / (25.0 * keV) )/ vF ;
G4double y ;
G4double z13 = pow(Zi, 0.3333) ;
// Faster than Fermi velocity
if ( v1 > 1.0 ) {
y = vF * v1 * ( 1.0 + 0.2 / (v1*v1) ) / (z13*z13) ;
// Slower than Fermi velocity
} else {
y = 0.6923 * vF * (1.0 + 2.0*v1*v1/3.0 + v1*v1*v1*v1/15.0) / (z13*z13) ;
}
G4double y3 = pow(y, 0.3) ;
// G4cout << "y= " << y << " y3= " << y3 << " v1= " << v1 << " vF= " << vF << G4endl;
q = 1.0 - exp( 0.803*y3 - 1.3167*y3*y3 - 0.38157*y - 0.008983*y*y ) ;
if( q < chargeLowLimit ) q = chargeLowLimit ;
G4double s = 7.6 - log(std::max(1.0, reducedEnergy/keV)) ;
s = 1.0 + ( 0.18 + 0.0015 * z ) * exp( -s*s )/ (Zi*Zi) ;
// Screen length according to
// J.F.Ziegler and J.M.Manoyan, The stopping of ions in compaunds,
// Nucl. Inst. & Meth. in Phys. Res. B35 (1988) 215-228.
G4double lambda = 10.0 * vF * pow(1.0-q, 0.6667) / (z13 * (6.0 + q)) ;
chargeCorrection = s * (1.0 + 0.5*(1.0/q - 1.0)*log(1.0 + lambda*lambda)/(vF*vF) );
}
// G4cout << "G4ionIonisation: charge= " << charge << " q= " << q
// << " chargeCor= " << chargeCorrection << G4endl;
return charge*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....