Import Geant4 6.0.0 source tree
This commit is contained in:
@@ -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....
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user