Import Geant4 5.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 16:57:27 +02:00
parent 330b82b769
commit 37fff30d2e
5733 changed files with 263867 additions and 74574 deletions
@@ -0,0 +1,300 @@
//
// ********************************************************************
// * 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 header file
//
//
// File name: G4BetheBlochModel
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
// Creation date: 03.01.2002
//
// Modifications: 04.12.2002 VI Fix problem of G4DynamicParticle constructor
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BetheBlochModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p)
: G4VEmModel(),
particle(0),
highKinEnergy(100.*TeV),
lowKinEnergy(2.0*MeV),
twoln10(2.0*log(10.0)),
bg2lim(0.0169),
taulim(8.4146e-3)
{
if(p) SetParticle(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BetheBlochModel::~G4BetheBlochModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
{
particle = p;
mass = particle->GetPDGMass();
spin = particle->GetPDGSpin();
G4double q = particle->GetPDGCharge()/eplus;
chargeSquare = q*q;
lowKinEnergy *= mass/proton_mass_c2;
ratio = electron_mass_c2/mass;
qc = mass/ratio;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
{
if(!particle) SetParticle(p);
return highKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
{
if(!particle) SetParticle(p);
return lowKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::MinEnergyCut(const G4ParticleDefinition* p,
const G4Material* material)
{
return material->GetIonisation()->GetMeanExcitationEnergy();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BetheBlochModel::IsInCharge(const G4ParticleDefinition* p,
const G4Material*)
{
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::ComputeDEDX(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
{
if(!particle) SetParticle(p);
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double tau = kineticEnergy/mass;
G4double x = 1.0;
if(cutEnergy < tmax) x = cutEnergy/tmax;
G4double gam = tau + 1.0;
G4double beta2 = 1. - 1./(gam*gam);
G4double bg2 = tau * (tau+2.0);
G4double eexc = material->GetIonisation()->GetMeanExcitationEnergy();
G4double eexc2 = eexc*eexc;
G4double taul = material->GetIonisation()->GetTaul();
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();
G4double* shellCorrectionVector =
material->GetIonisation()->GetShellCorrectionVector();
G4double eDensity = material->GetElectronDensity();
G4double dedx = log(2.0*electron_mass_c2*bg2*tmax*x/eexc2)-(1.0 + x)*beta2;
if(0.5 == spin) {
G4double del = 0.5*x*tmax/(kineticEnergy + mass);
dedx += del*del;
}
// density correction
x = log(bg2)/twoln10;
if ( x >= x0den ) {
dedx -= twoln10*x - cden ;
if ( x < x1den ) dedx -= aden*pow((x1den-x),mden) ;
}
// shell correction
G4double sh = 0.0;
x = 1.0;
if ( bg2 > bg2lim ) {
for (G4int k=0; k<3; k++) {
x *= bg2 ;
sh += shellCorrectionVector[k]/x;
}
} else {
for (G4int k=0; k<3; k++) {
x *= bg2lim ;
sh += shellCorrectionVector[k]/x;
}
sh *= log(tau/taul)/log(taulim/taul);
}
dedx -= sh;
// now compute the total ionization loss
if (dedx < 0.0) dedx = 0.0 ;
dedx *= twopi_mc2_rcl2*chargeSquare*eDensity/beta2;
return dedx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::CrossSection(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxEnergy)
{
if(!particle) SetParticle(p);
G4double cross = 0.0;
G4double tmax = G4std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
if(cutEnergy < tmax) {
G4double x = cutEnergy/tmax;
G4double energy = kineticEnergy + mass;
G4double gam = energy/mass;
G4double beta2 = 1. - 1./(gam*gam);
cross = (1.0 - x*(1.0 - beta2*log(x)))/cutEnergy;
// +term for spin=1/2 particle
if( 0.5 == spin ) {
cross += 0.5 * (tmax - cutEnergy) / (energy*energy);
// +term for spin=1 particle
} else if( 0.9 < spin ) {
cross += -log(x)/(3.0*qc) +
(tmax - cutEnergy) * ((1.0+ 0.25*tmax*(1.0 + x)/qc)/(energy*energy)
- beta2 / (tmax * qc) )/3.0;
}
cross *= twopi_mc2_rcl2*chargeSquare*material->GetElectronDensity()/beta2;
}
// G4cout << "tmin= " << cutEnergy << " tmax= " << tmax
// << " cross= " << cross << G4endl;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondary(
const G4Material* material,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
G4double xmax = G4std::min(tmax, maxEnergy)/tmax;
if(xmin >= xmax) return 0;
G4ThreeVector momentum = dp->GetMomentumDirection();
G4double kineticEnergy = dp->GetKineticEnergy();
G4double energy = kineticEnergy + mass;
G4double beta2 = 1. - mass*mass/(energy*energy);
G4double totMomentum = sqrt(energy*energy - mass*mass);
G4double x = 0.0;
G4double y = 0.0;
G4double grej = 1.0 - beta2*xmin;
if(spin > 0.0) {
x = 0.5*tmax*tmax/(energy*energy);
if(spin < 0.9) {
grej += xmax*xmax*x;
} else {
y = tmax/(3.0*qc);
grej += (1.0 - beta2*xmin)*xmin*y + x*xmin*xmin*(2.0/3.0 + xmin*y);
}
}
G4double z, f;
// sampling follows ...
do {
G4double q = G4UniformRand();
z = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
f = 1.0 - z * (beta2 - z*x);
if (spin > 0.9) {
f += (1.0 - beta2*z)*z*y + x*z*z*(2.0/3.0 + z*y);
}
if(f > grej) {
G4cout << "G4BetheBlochModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for x= " << z
<< G4endl;
}
} while( grej*G4UniformRand() > f );
G4double deltaKinEnergy = z * tmax;
G4double deltaMomentum =
sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
G4double cost = deltaKinEnergy * (energy + electron_mass_c2) /
(deltaMomentum * totMomentum);
G4double sint = sqrt(1.0 - cost*cost);
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
deltaDirection.rotateUz(momentum);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* delta = new G4DynamicParticle();
delta->SetDefinition(G4Electron::Electron());
delta->SetKineticEnergy(deltaKinEnergy);
delta->SetMomentumDirection(deltaDirection);
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
vdp->push_back(delta);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,663 @@
//
// ********************************************************************
// * 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: G4BraggModel
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications: 04.12.2002 VI Fix problem of G4DynamicParticle constructor
//
// Class Description:
//
// Implementation of energy loss and delta-electron production by
// slow charged heavy particles
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BraggModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BraggModel::G4BraggModel(const G4ParticleDefinition* p)
: G4VEmModel(),
particle(0),
highKinEnergy(2.0*MeV),
lowKinEnergy(0.0*MeV),
iMolecula(0),
protonMassAMU(1.007276),
theZieglerFactor(eV*cm2*1.0e-15)
{
if(p) SetParticle(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BraggModel::~G4BraggModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
{
particle = p;
mass = particle->GetPDGMass();
spin = particle->GetPDGSpin();
G4double q = particle->GetPDGCharge()/eplus;
chargeSquare = q*q;
massRate = mass/proton_mass_c2;
highKinEnergy *= massRate;
ratio = electron_mass_c2/mass;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
{
if(!particle) SetParticle(p);
return highKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
{
if(!particle) SetParticle(p);
return lowKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::MinEnergyCut(const G4ParticleDefinition* p,
const G4Material* material)
{
return material->GetIonisation()->GetMeanExcitationEnergy();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::IsInCharge(const G4ParticleDefinition* p,
const G4Material*)
{
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ComputeDEDX(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
{
if(!particle) SetParticle(p);
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double dedx = DEDX(material, kineticEnergy/massRate);
if (cutEnergy < tmax) {
G4double x = cutEnergy/tmax;
G4double tau = kineticEnergy/mass;
G4double gam = tau + 1.0;
G4double beta2 = 1. - 1./(gam*gam);
// G4double bg2 = tau * (tau+2.0);
dedx += (log(x) + (1.0 - x)*beta2) * twopi_mc2_rcl2
* (material->GetElectronDensity())/beta2;
}
// now compute the total ionization loss
if (dedx < 0.0) dedx = 0.0 ;
dedx *= chargeSquare;
return dedx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::CrossSection(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxEnergy)
{
if(!particle) SetParticle(p);
G4double cross = 0.0;
G4double tmax = G4std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
if(cutEnergy < tmax) {
G4double x = cutEnergy/tmax;
G4double energy = kineticEnergy + mass;
G4double gam = energy/mass;
G4double beta2 = 1. - 1./(gam*gam);
cross = (1.0 - x*(1.0 - beta2*log(x)))/cutEnergy;
cross *= twopi_mc2_rcl2*chargeSquare*material->GetElectronDensity()/beta2;
}
// G4cout << "tmin= " << cutEnergy << " tmax= " << tmax
// << " cross= " << cross << G4endl;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
const G4Material* material,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
G4double xmax = G4std::min(tmax, maxEnergy)/tmax;
if(xmin >= xmax) return 0;
G4double kineticEnergy = dp->GetKineticEnergy();
G4double energy = kineticEnergy + mass;
G4double beta2 = 1. - mass*mass/(energy*energy);
G4double grej = 1.0 - beta2*xmin;
G4double z, f;
G4ThreeVector momentum = dp->GetMomentumDirection();
// sampling follows ...
do {
G4double q = G4UniformRand();
z = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
f = 1.0 - beta2 * z;
if(f > grej) {
G4cout << "G4BraggModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for x= " << z
<< G4endl;
}
} while( grej*G4UniformRand() >= f );
G4double deltaKinEnergy = z * tmax;
G4double deltaMomentum =
sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
G4double totMomentum = sqrt(energy*energy - mass*mass);
G4double cost = deltaKinEnergy * (energy + electron_mass_c2) /
(deltaMomentum * totMomentum);
G4double sint = sqrt(1.0 - cost*cost);
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
deltaDirection.rotateUz(momentum);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* delta = new G4DynamicParticle();
delta->SetDefinition(G4Electron::Electron());
delta->SetKineticEnergy(deltaKinEnergy);
delta->SetMomentumDirection(deltaDirection);
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
vdp->push_back(delta);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::HasMaterial(const G4Material* material)
{
G4String chFormula = material->GetChemicalFormula() ;
G4String myFormula = G4String(" ") ;
if (myFormula == chFormula ) {
if(1 == (material->GetNumberOfElements())) return true;
return false ;
}
// ICRU Report N49, 1993. Power's model for He.
const size_t numberOfMolecula = 11 ;
static G4String name[numberOfMolecula] = {
"Al_2O_3", "CO_2", "CH_4",
"(C_2H_4)_N-Polyethylene", "(C_2H_4)_N-Polypropylene", "(C_8H_8)_N",
"C_3H_8", "SiO_2", "H_2O",
"H_2O-Gas", "Graphite" } ;
// Special treatment for water in gas state
const G4State theState = material->GetState() ;
myFormula = G4String("H_2O");
if( theState == kStateGas && myFormula == chFormula) {
chFormula = G4String("H_2O-Gas");
}
// Search for the material in the table
for (size_t i=0; i<numberOfMolecula; i++) {
if (chFormula == name[i]) {
SetMoleculaNumber(i) ;
return true ;
}
}
return false ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::StoppingPower(const G4Material* material,
G4double kineticEnergy)
{
G4double ionloss = 0.0 ;
// pure material (normally not the case for this function)
if(1 == (material->GetNumberOfElements())) {
G4double z = material->GetZ() ;
ionloss = ElectronicStoppingPower( z, kineticEnergy ) ;
} else if (iMolecula < 11) {
// The data and the fit from:
// ICRU Report N49, 1993. Ziegler's model for protons.
// Proton kinetic energy for parametrisation (keV/amu)
G4double T = kineticEnergy/(keV*protonMassAMU) ;
static G4double a[11][5] = {
{1.187E+1, 1.343E+1, 1.069E+4, 7.723E+2, 2.153E-2},
{7.802E+0, 8.814E+0, 8.303E+3, 7.446E+2, 7.966E-3},
{7.294E+0, 8.284E+0, 5.010E+3, 4.544E+2, 8.153E-3},
{8.646E+0, 9.800E+0, 7.066E+3, 4.581E+2, 9.383E-3},
{1.286E+1, 1.462E+1, 5.625E+3, 2.621E+3, 3.512E-2},
{3.229E+1, 3.696E+1, 8.918E+3, 3.244E+3, 1.273E-1},
{1.604E+1, 1.825E+1, 6.967E+3, 2.307E+3, 3.775E-2},
{8.049E+0, 9.099E+0, 9.257E+3, 3.846E+2, 1.007E-2},
{4.015E+0, 4.542E+0, 3.955E+3, 4.847E+2, 7.904E-3},
{4.571E+0, 5.173E+0, 4.346E+3, 4.779E+2, 8.572E-3},
{2.631E+0, 2.601E+0, 1.701E+3, 1.279E+3, 1.638E-2} };
if ( T < 10.0 ) {
ionloss = a[iMolecula][0] * sqrt(T) ;
} else if ( T < 10000.0 ) {
G4double slow = a[iMolecula][1] * pow(T, 0.45) ;
G4double shigh = log( 1.0 + a[iMolecula][3]/T
+ a[iMolecula][4]*T ) * a[iMolecula][2]/T ;
ionloss = slow*shigh / (slow + shigh) ;
}
if ( ionloss < 0.0) ionloss = 0.0 ;
if ( 10 == iMolecula ) {
if (T < 100.0) {
ionloss *= (1.0+0.023+0.0066*log10(T));
}
else if (T < 700.0) {
ionloss *=(1.0+0.089-0.0248*log10(T-99.));
}
else if (T < 10000.0) {
ionloss *=(1.0+0.089-0.0248*log10(700.-99.));
}
}
}
return ionloss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ElectronicStoppingPower(G4double z,
G4double kineticEnergy) const
{
G4double ionloss ;
G4int i = G4int(z)-1 ; // index of atom
if(i < 0) i = 0 ;
if(i > 91) i = 91 ;
// The data and the fit from:
// ICRU Report 49, 1993. Ziegler's type of parametrisations.
// Proton kinetic energy for parametrisation (keV/amu)
G4double T = kineticEnergy/(keV*protonMassAMU) ;
static G4double a[92][5] = {
{1.254E+0, 1.440E+0, 2.426E+2, 1.200E+4, 1.159E-1},
{1.229E+0, 1.397E+0, 4.845E+2, 5.873E+3, 5.225E-2},
{1.411E+0, 1.600E+0, 7.256E+2, 3.013E+3, 4.578E-2},
{2.248E+0, 2.590E+0, 9.660E+2, 1.538E+2, 3.475E-2},
{2.474E+0, 2.815E+0, 1.206E+3, 1.060E+3, 2.855E-2},
{2.631E+0, 2.601E+0, 1.701E+3, 1.279E+3, 1.638E-2},
{2.954E+0, 3.350E+0, 1.683E+3, 1.900E+3, 2.513E-2},
{2.652E+0, 3.000E+0, 1.920E+3, 2.000E+3, 2.230E-2},
{2.085E+0, 2.352E+0, 2.157E+3, 2.634E+3, 1.816E-2},
{1.951E+0, 2.199E+0, 2.393E+3, 2.699E+3, 1.568E-2},
{2.542E+0, 2.869E+0, 2.628E+3, 1.854E+3, 1.472E-2},
{3.791E+0, 4.293E+0, 2.862E+3, 1.009E+3, 1.397E-2},
{4.154E+0, 4.739E+0, 2.766E+3, 1.645E+2, 2.023E-2},
{4.914E+0, 5.598E+0, 3.193E+3, 2.327E+2, 1.419E-2},
{3.232E+0, 3.647E+0, 3.561E+3, 1.560E+3, 1.267E-2},
{3.447E+0, 3.891E+0, 3.792E+3, 1.219E+3, 1.211E-2},
{5.301E+0, 6.008E+0, 3.969E+3, 6.451E+2, 1.183E-2},
{5.731E+0, 6.500E+0, 4.253E+3, 5.300E+2, 1.123E-2},
{5.152E+0, 5.833E+0, 4.482E+3, 5.457E+2, 1.129E-2},
{5.521E+0, 6.252E+0, 4.710E+3, 5.533E+2, 1.112E-2},
{5.201E+0, 5.884E+0, 4.938E+3, 5.609E+2, 9.995E-3},
{4.858E+0, 5.489E+0, 5.260E+3, 6.511E+2, 8.930E-3},
{4.479E+0, 5.055E+0, 5.391E+3, 9.523E+2, 9.117E-3},
{3.983E+0, 4.489E+0, 5.616E+3, 1.336E+3, 8.413E-3},
{3.469E+0, 3.907E+0, 5.725E+3, 1.461E+3, 8.829E-3},
{3.519E+0, 3.963E+0, 6.065E+3, 1.243E+3, 7.782E-3},
{3.140E+0, 3.535E+0, 6.288E+3, 1.372E+3, 7.361E-3},
{3.553E+0, 4.004E+0, 6.205E+3, 5.551E+2, 8.763E-3},
{3.696E+0, 4.194E+0, 4.649E+3, 8.113E+1, 2.242E-2},
{4.210E+0, 4.750E+0, 6.953E+3, 2.952E+2, 6.809E-3},
{5.041E+0, 5.697E+0, 7.173E+3, 2.026E+2, 6.725E-3},
{5.554E+0, 6.300E+0, 6.496E+3, 1.100E+2, 9.689E-3},
{5.323E+0, 6.012E+0, 7.611E+3, 2.925E+2, 6.447E-3},
{5.874E+0, 6.656E+0, 7.395E+3, 1.175E+2, 7.684E-3},
{6.658E+0, 7.536E+0, 7.694E+3, 2.223E+2, 6.509E-3},
{6.413E+0, 7.240E+0, 1.185E+4, 1.537E+2, 2.880E-3},
{5.694E+0, 6.429E+0, 8.478E+3, 2.929E+2, 6.087E-3},
{6.339E+0, 7.159E+0, 8.693E+3, 3.303E+2, 6.003E-3},
{6.407E+0, 7.234E+0, 8.907E+3, 3.678E+2, 5.889E-3},
{6.734E+0, 7.603E+0, 9.120E+3, 4.052E+2, 5.765E-3},
{6.901E+0, 7.791E+0, 9.333E+3, 4.427E+2, 5.587E-3},
{6.424E+0, 7.248E+0, 9.545E+3, 4.802E+2, 5.376E-3},
{6.799E+0, 7.671E+0, 9.756E+3, 5.176E+2, 5.315E-3},
{6.109E+0, 6.887E+0, 9.966E+3, 5.551E+2, 5.151E-3},
{5.924E+0, 6.677E+0, 1.018E+4, 5.925E+2, 4.919E-3},
{5.238E+0, 5.900E+0, 1.038E+4, 6.300E+2, 4.758E-3},
{5.345E+0, 6.038E+0, 6.790E+3, 3.978E+2, 1.676E-2},
{5.814E+0, 6.554E+0, 1.080E+4, 3.555E+2, 4.626E-3},
{6.229E+0, 7.024E+0, 1.101E+4, 3.709E+2, 4.540E-3},
{6.409E+0, 7.227E+0, 1.121E+4, 3.864E+2, 4.474E-3},
{7.500E+0, 8.480E+0, 8.608E+3, 3.480E+2, 9.074E-3},
{6.979E+0, 7.871E+0, 1.162E+4, 3.924E+2, 4.402E-3},
{7.725E+0, 8.716E+0, 1.183E+4, 3.948E+2, 4.376E-3},
{8.337E+0, 9.425E+0, 1.051E+4, 2.696E+2, 6.206E-3},
{7.287E+0, 8.218E+0, 1.223E+4, 3.997E+2, 4.447E-3},
{7.899E+0, 8.911E+0, 1.243E+4, 4.021E+2, 4.511E-3},
{8.041E+0, 9.071E+0, 1.263E+4, 4.045E+2, 4.540E-3},
{7.488E+0, 8.444E+0, 1.283E+4, 4.069E+2, 4.420E-3},
{7.291E+0, 8.219E+0, 1.303E+4, 4.093E+2, 4.298E-3},
{7.098E+0, 8.000E+0, 1.323E+4, 4.118E+2, 4.182E-3},
{6.909E+0, 7.786E+0, 1.343E+4, 4.142E+2, 4.058E-3},
{6.728E+0, 7.580E+0, 1.362E+4, 4.166E+2, 3.976E-3},
{6.551E+0, 7.380E+0, 1.382E+4, 4.190E+2, 3.877E-3},
{6.739E+0, 7.592E+0, 1.402E+4, 4.214E+2, 3.863E-3},
{6.212E+0, 6.996E+0, 1.421E+4, 4.239E+2, 3.725E-3},
{5.517E+0, 6.210E+0, 1.440E+4, 4.263E+2, 3.632E-3},
{5.220E+0, 5.874E+0, 1.460E+4, 4.287E+2, 3.498E-3},
{5.071E+0, 5.706E+0, 1.479E+4, 4.330E+2, 3.405E-3},
{4.926E+0, 5.542E+0, 1.498E+4, 4.335E+2, 3.342E-3},
{4.788E+0, 5.386E+0, 1.517E+4, 4.359E+2, 3.292E-3},
{4.893E+0, 5.505E+0, 1.536E+4, 4.384E+2, 3.243E-3},
{5.028E+0, 5.657E+0, 1.555E+4, 4.408E+2, 3.195E-3},
{4.738E+0, 5.329E+0, 1.574E+4, 4.432E+2, 3.186E-3},
{4.587E+0, 5.160E+0, 1.541E+4, 4.153E+2, 3.406E-3},
{5.201E+0, 5.851E+0, 1.612E+4, 4.416E+2, 3.122E-3},
{5.071E+0, 5.704E+0, 1.630E+4, 4.409E+2, 3.082E-3},
{4.946E+0, 5.563E+0, 1.649E+4, 4.401E+2, 2.965E-3},
{4.477E+0, 5.034E+0, 1.667E+4, 4.393E+2, 2.871E-3},
{4.844E+0, 5.458E+0, 7.852E+3, 9.758E+2, 2.077E-2},
{4.307E+0, 4.843E+0, 1.704E+4, 4.878E+2, 2.882E-3},
{4.723E+0, 5.311E+0, 1.722E+4, 5.370E+2, 2.913E-3},
{5.319E+0, 5.982E+0, 1.740E+4, 5.863E+2, 2.871E-3},
{5.956E+0, 6.700E+0, 1.780E+4, 6.770E+2, 2.660E-3},
{6.158E+0, 6.928E+0, 1.777E+4, 5.863E+2, 2.812E-3},
{6.203E+0, 6.979E+0, 1.795E+4, 5.863E+2, 2.776E-3},
{6.181E+0, 6.954E+0, 1.812E+4, 5.863E+2, 2.748E-3},
{6.949E+0, 7.820E+0, 1.830E+4, 5.863E+2, 2.737E-3},
{7.506E+0, 8.448E+0, 1.848E+4, 5.863E+2, 2.727E-3},
{7.648E+0, 8.609E+0, 1.866E+4, 5.863E+2, 2.697E-3},
{7.711E+0, 8.679E+0, 1.883E+4, 5.863E+2, 2.641E-3},
{7.407E+0, 8.336E+0, 1.901E+4, 5.863E+2, 2.603E-3},
{7.290E+0, 8.204E+0, 1.918E+4, 5.863E+2, 2.673E-3}
};
G4double fac = 1.0 ;
// Carbon specific case for E < 40 keV
if ( T < 40.0 && 5 == i) {
fac = sqrt(T/40.0) ;
T = 40.0 ;
// Free electron gas model
} else if ( T < 10.0 ) {
fac = sqrt(T*0.1) ;
T =10.0 ;
}
// Main parametrisation
G4double slow = a[i][1] * pow(T, 0.45) ;
G4double shigh = log( 1.0 + a[i][3]/T + a[i][4]*T ) * a[i][2]/T ;
ionloss = slow*shigh*fac / (slow + shigh) ;
if ( ionloss < 0.0) ionloss = 0.0 ;
return ionloss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::DEDX(const G4Material* material,
G4double kineticEnergy)
{
G4double eloss = 0.0;
const G4int numberOfElements = material->GetNumberOfElements();
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
// pure material
if(1 == numberOfElements) {
G4double z = material->GetZ();
eloss = ElectronicStoppingPower(z, kineticEnergy)
* (material->GetTotNbOfAtomsPerVolume());
// compaund material with parametrisation
} else if( HasMaterial(material) ) {
eloss = StoppingPower(material, kineticEnergy)
* (material->GetTotNbOfAtomsPerVolume());
G4int nAtoms = 0;
const G4int* theAtomsVector = material->GetAtomsVector();
for (G4int iel=0; iel<numberOfElements; iel++) {
nAtoms += theAtomsVector[iel];
}
eloss /= nAtoms;
// Experimental data exist only for kinetic energy 125 keV
} else if( MolecIsInZiegler1988(material) ) {
// Cycle over elements - calculation based on Bragg's rule
G4double eloss125 = 0.0 ;
const G4ElementVector* theElementVector =
material->GetElementVector();
// loop for the elements in the material
for (G4int i=0; i<numberOfElements; i++) {
const G4Element* element = (*theElementVector)[i] ;
G4double z = element->GetZ() ;
eloss += ElectronicStoppingPower(z,kineticEnergy)
* theAtomicNumDensityVector[i] ;
eloss125 += ElectronicStoppingPower(z,125.0*keV)
* theAtomicNumDensityVector[i] ;
}
// Chemical factor is taken into account
eloss *= ChemicalFactor(kineticEnergy, eloss125) ;
// Brugg's rule calculation
} else {
const G4ElementVector* theElementVector =
material->GetElementVector() ;
// loop for the elements in the material
for (G4int i=0; i<numberOfElements; i++)
{
const G4Element* element = (*theElementVector)[i] ;
eloss += ElectronicStoppingPower(element->GetZ(), kineticEnergy)
* theAtomicNumDensityVector[i];
}
}
return eloss*theZieglerFactor;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::MolecIsInZiegler1988(const G4Material* material)
{
// The list of molecules from
// J.F.Ziegler and J.M.Manoyan, The stopping of ions in compaunds,
// Nucl. Inst. & Meth. in Phys. Res. B35 (1988) 215-228.
G4String myFormula = G4String(" ") ;
const G4String chFormula = material->GetChemicalFormula() ;
if (myFormula == chFormula ) return false ;
// There are no evidence for difference of stopping power depended on
// phase of the compound except for water. The stopping power of the
// water in gas phase can be predicted using Bragg's rule.
//
// No chemical factor for water-gas
myFormula = G4String("H_2O") ;
const G4State theState = material->GetState() ;
if( theState == kStateGas && myFormula == chFormula) return false ;
const size_t numberOfMolecula = 53 ;
// The coffecient from Table.4 of Ziegler & Manoyan
const G4double HeEff = 2.8735 ;
static G4String name[numberOfMolecula] = {
"H_2O", "C_2H_4O", "C_3H_6O", "C_2H_2", "C_H_3OH",
"C_2H_5OH", "C_3H_7OH", "C_3H_4", "NH_3", "C_14H_10",
"C_6H_6", "C_4H_10", "C_4H_6", "C_4H_8O", "CCl_4",
"CF_4", "C_6H_8", "C_6H_12", "C_6H_10O", "C_6H_10",
"C_8H_16", "C_5H_10", "C_5H_8", "C_3H_6-Cyclopropane","C_2H_4F_2",
"C_2H_2F_2", "C_4H_8O_2", "C_2H_6", "C_2F_6", "C_2H_6O",
"C_3H_6O", "C_4H_10O", "C_2H_4", "C_2H_4O", "C_2H_4S",
"SH_2", "CH_4", "CCLF_3", "CCl_2F_2", "CHCl_2F",
"(CH_3)_2S", "N_2O", "C_5H_10O", "C_8H_6", "(CH_2)_N",
"(C_3H_6)_N","(C_8H_8)_N", "C_3H_8", "C_3H_6-Propylene", "C_3H_6O",
"C_3H_6S", "C_4H_4S", "C_7H_8"
} ;
static G4double expStopping[numberOfMolecula] = {
66.1, 190.4, 258.7, 42.2, 141.5,
210.9, 279.6, 198.8, 31.0, 267.5,
122.8, 311.4, 260.3, 328.9, 391.3,
206.6, 374.0, 422.0, 432.0, 398.0,
554.0, 353.0, 326.0, 74.6, 220.5,
197.4, 362.0, 170.0, 330.5, 211.3,
262.3, 349.6, 51.3, 187.0, 236.9,
121.9, 35.8, 247.0, 292.6, 268.0,
262.3, 49.0, 398.9, 444.0, 22.91,
68.0, 155.0, 84.0, 74.2, 254.7,
306.8, 324.4, 420.0
} ;
static G4double expCharge[numberOfMolecula] = {
HeEff, HeEff, HeEff, 1.0, HeEff,
HeEff, HeEff, HeEff, 1.0, 1.0,
1.0, HeEff, HeEff, HeEff, HeEff,
HeEff, HeEff, HeEff, HeEff, HeEff,
HeEff, HeEff, HeEff, 1.0, HeEff,
HeEff, HeEff, HeEff, HeEff, HeEff,
HeEff, HeEff, 1.0, HeEff, HeEff,
HeEff, 1.0, HeEff, HeEff, HeEff,
HeEff, 1.0, HeEff, HeEff, 1.0,
1.0, 1.0, 1.0, 1.0, HeEff,
HeEff, HeEff, HeEff
} ;
static G4double numberOfAtomsPerMolecula[numberOfMolecula] = {
3.0, 7.0, 10.0, 4.0, 6.0,
9.0, 12.0, 7.0, 4.0, 24.0,
12.0, 14.0, 10.0, 13.0, 5.0,
5.0, 14.0, 18.0, 17.0, 17.0,
24.0, 15.0, 13.0, 9.0, 8.0,
6.0, 14.0, 8.0, 8.0, 9.0,
10.0, 15.0, 6.0, 7.0, 7.0,
3.0, 5.0, 5.0, 5.0, 5.0,
9.0, 3.0, 16.0, 14.0, 3.0,
9.0, 16.0, 11.0, 9.0, 10.0,
10.0, 9.0, 15.0
} ;
// Search for the compaund in the table
for (size_t i=0; i<numberOfMolecula; i++)
{
if(chFormula == name[i]) {
G4double exp125 = expStopping[i] *
(material->GetTotNbOfAtomsPerVolume()) /
(expCharge[i] * numberOfAtomsPerMolecula[i]) ;
SetExpStopPower125(exp125);
return true;
}
}
return false;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ChemicalFactor(G4double kineticEnergy,
G4double eloss125) const
{
// Approximation of Chemical Factor 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 gamma = 1.0 + kineticEnergy/proton_mass_c2 ;
G4double gamma25 = 1.0 + 25.0*keV /proton_mass_c2 ;
G4double gamma125 = 1.0 + 125.0*keV/proton_mass_c2 ;
G4double beta = sqrt(1.0 - 1.0/(gamma*gamma)) ;
G4double beta25 = sqrt(1.0 - 1.0/(gamma25*gamma25)) ;
G4double beta125 = sqrt(1.0 - 1.0/(gamma125*gamma125)) ;
G4double factor = 1.0 + (expStopPower125/eloss125 - 1.0) *
(1.0 + exp( 1.48 * ( beta125/beta25 - 7.0 ) ) ) /
(1.0 + exp( 1.48 * ( beta/beta25 - 7.0 ) ) ) ;
return factor ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,585 @@
//
// ********************************************************************
// * 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: G4EmModelManager
//
// Author: Vladimir Ivanchenko
//
// Creation date: 07.05.2002
//
// Modifications:
//
// Class Description:
//
// It is the unified energy loss process it calculates the continuous
// energy loss for charged particles using a set of Energy Loss
// models valid for different energy regions. There are a possibility
// to create and access to dE/dx and range tables, or to calculate
// that information on fly.
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4EmModelManager.hh"
#include "G4LossTableManager.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4DataVector.hh"
#include "G4PhysicsVector.hh"
#include "G4VParticleChange.hh"
#include "G4Positron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::G4EmModelManager():
nEmModels(0),
nmax(4),
orderIsChanged(false),
minSubRange(0.1),
particle(0)
{
verboseLevel = 0;
for(G4int i = 0; i<nmax; i++) {
emModels[i] = 0;
order[i] = 0;
upperEkin[i] = 0.0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::~G4EmModelManager()
{
Clear();
for(G4int i = 0; i<nmax; i++) {
if(emModels[i]) delete emModels[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::Clear()
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::Clear()" << G4endl;
}
theCuts.clear();
theSubCuts.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
G4double theMinSubRange,
G4int val)
{
// Are models defined?
if(!nEmModels) {
G4Exception("G4EmModelManager::Initialise without any model defined");
}
particle = p;
secondaryParticle = sp;
minSubRange = theMinSubRange;
verboseLevel = val;
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< p->GetParticleName()
<< G4endl;
}
// Ordering
if(orderIsChanged) {
G4int oldOrder[5];
G4VEmModel* oldEmModels[5];
for(G4int k = 0; k<nmax; k++) {
oldEmModels[k] = emModels[k];
oldOrder[k] = order[k];
}
for(G4int ik=0; ik<nEmModels; ik++) {
G4int low = INT_MAX;
G4int index = 0;
for(G4int kk=0; kk<nEmModels; kk++) {
if(oldEmModels[kk]) {
if(oldOrder[kk] < low) {
low = oldOrder[kk];
index = kk;
}
}
}
emModels[ik] = oldEmModels[index];
order[ik] = ik;
oldEmModels[index] = 0;
}
orderIsChanged = false;
}
G4DataVector eLow;
eLow.clear();
G4int n = 0;
for(G4int j=0; j<nEmModels; j++) {
G4double ep = 0.0;
if(0 < n) ep = upperEkin[n-1];
G4VEmModel* model = emModels[j];
G4bool accepted = false;
if(model->IsInCharge(particle, 0)) {
G4double tmin = model->LowEnergyLimit(particle, 0);
G4double tmax = model->HighEnergyLimit(particle, 0);
if(1 < verboseLevel) {
G4cout << "New model for tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< "; tlast(MeV)= " << ep/MeV
<< G4endl;
}
if(tmax > tmin) {
if(n == 0 || tmax > upperEkin[n-1]) {
// First model or next model for more high energy range;
upperEkin[n] = (tmax);
if(0 < n) tmin = G4std::max(tmin, upperEkin[n-1]);
eLow.push_back(tmin);
n++;
accepted = true;
} else {
G4cout << "The model number #" << j
<< " has no active range "
<< "; tmax(MeV)= " << tmax/MeV
<< "; tlast(MeV)= " << ep/MeV
<< G4endl;
}
} else {
G4cout << "The model number #" << j
<< " has no active range "
<< "; tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< G4endl;
}
}
if(!accepted) {
upperEkin[n] = ep;
eLow.push_back(ep);
n++;
}
}
// Access to materials and build cuts
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
for(size_t i=0; i<nMaterials; i++) {
const G4Material* material = (*theMaterialTable)[i];
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< material->GetName() << G4endl;
}
G4double cut = 0.0;
G4double subcut = 0.0;
if(secondaryParticle) {
cut = secondaryParticle->GetEnergyThreshold(material);
subcut = minSubRange*cut;
}
for(G4int j=0; j<nEmModels; j++) {
G4VEmModel* model = emModels[j];
if(upperEkin[j] > eLow[j]) {
G4double tcutmin = model->MinEnergyCut(particle, material);
if(1 < verboseLevel) {
G4cout << "The model # " << j
<< "; tcutmin(MeV)= " << tcutmin/MeV
<< G4endl;
}
cut = G4std::max(cut, tcutmin);
subcut = G4std::max(subcut, tcutmin);
}
}
theCuts.push_back(cut);
theSubCuts.push_back(subcut);
}
if(1 < verboseLevel) {
G4cout << "G4EmModelManager is initialised "
<< G4endl;
}
return &theCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::AddEmModel(G4VEmModel* p, G4int num)
{
if(nEmModels) {
for(G4int i=0; i<nEmModels; i++) {
if(num < order[i]) orderIsChanged = true;
}
}
if(nEmModels == nmax) {
G4cout << "G4EmModelManager::AddEmModel WARNING: cannot accept model #"
<< nEmModels << " - the list is closed"
<< G4endl;
} else {
emModels[nEmModels] = p;
order[nEmModels] = num;
currentModel = p;
nEmModels++;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
const G4Material* material)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< material->GetName()
<< G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
G4DataVector dedxHigh;
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
factor.resize(nEmModels);
dedxLow.resize(nEmModels);
dedxHigh.resize(nEmModels);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
<< material->GetName() << G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLoss = aVector->GetVectorLength();
dedxLow[0] = 0.0;
e = upperEkin[0];
dedxHigh[0] = emModels[0]->ComputeDEDX(material,particle,e,cut);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
e = upperEkin[j-1];
dedxLow[j] = emModels[j]->ComputeDEDX(material,particle,e,cut);
e = upperEkin[j];
dedxHigh[j] = emModels[j]->ComputeDEDX(material,particle,e,cut);
}
for(j=1; j<nEmModels; j++) {
if(dedxLow[j] > 0.0) factor[j] = (dedxHigh[j-1]/dedxLow[j] - 1.0);
else factor[j] = 0.0;
}
if(0 < verboseLevel) {
G4cout << "Loop over " << totBinsLoss << " bins start " << G4endl;
}
}
// Calculate energy losses vector
for(j=0; j<totBinsLoss; j++) {
G4double e = aVector->GetLowEdgeEnergy(j);
G4double fac = 1.0;
// Choose a model of energy losses
G4int k = 0;
if(nEmModels > 1) {
if (e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
}
G4double dedx = emModels[k]->ComputeDEDX(material,particle,e,cut)*fac;
if(dedx < 0.0) dedx = 0.0;
if(0 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< G4endl;
}
aVector->PutValue(j, dedx);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillLambdaVector() for particle "
<< particle->GetParticleName() << G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector sigmaLow;
G4DataVector sigmaHigh;
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
<< material->GetName() << G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLambda = aVector->GetVectorLength();
sigmaLow[0] = 0.0;
e = upperEkin[0];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " " << nEmModels
<< " models"
<< " Ecut(MeV)= " << cut/MeV
<< " Emax(MeV)= " << e/MeV
<< " nbins= " << totBinsLambda
<< G4endl;
}
sigmaHigh[0] = emModels[0]->CrossSection(material,particle,e,cut,e);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
e = upperEkin[j-1];
sigmaLow[j] = emModels[j]->CrossSection(material,particle,e,cut,e);
e = upperEkin[j];
sigmaHigh[j] = emModels[j]->CrossSection(material,particle,e,cut,e);
}
for(j=1; j<nEmModels; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
// Calculate lambda vector
for(j=0; j<totBinsLambda; j++) {
e = aVector->GetLowEdgeEnergy(j);
// Choose a model of energy losses
G4int k = 0;
G4double fac = 1.0;
if(nEmModels > 1) {
if(e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
}
// Cross section interpolation should start from zero
G4double cross = 0.0;
if(j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,cut,e)*fac;
}
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
<< " fac= " << fac
<< G4endl;
}
if(cross <= 0.0) cross = 0.0;
// if(cross <= 0.0) cross = DBL_MAX;
// else cross = 1.0/cross;
aVector->PutValue(j, cross);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::BuildLambdaSubTable() for particle "
<< particle->GetParticleName() << G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector sigmaLow;
G4DataVector sigmaHigh;
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
G4double subcut = theSubCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
<< material->GetName() << G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLambda = aVector->GetVectorLength();
sigmaLow[0] = 0.0;
e = upperEkin[0];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " are available " << nEmModels
<< " models"
<< " Ecut(MeV)= " << cut/MeV
<< " nbins= " << totBinsLambda
<< G4endl;
}
sigmaHigh[0] = emModels[0]->CrossSection(material,particle,e,subcut,cut);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
e = upperEkin[j-1];
sigmaLow[j] = emModels[j]->CrossSection(material,particle,e,subcut,cut);
e = upperEkin[j];
sigmaHigh[j] = emModels[j]->CrossSection(material,particle,e,subcut,cut);
}
for(j=1; j<nEmModels; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
// Calculate energy losses vector
for(j=0; j<totBinsLambda; j++) {
e = aVector->GetLowEdgeEnergy(j);
// Choose a model of energy losses
G4int k = 0;
G4double fac = 1.0;
if(nEmModels > 1) {
if(e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
}
G4double cross = 0.0;
// Cross section interpolation should start from zero
if (j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,subcut,cut)*fac;
}
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
<< " fac= " << fac
<< G4endl;
}
if(cross <= 0.0) cross = 0.0;
aVector->PutValue(j, cross);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossMessenger.cc,v 1.4 2001/07/11 10:03:41 gunter Exp $
// GEANT4 tag $Name: geant4-04-01 $
// $Id: G4EnergyLossMessenger.cc,v 1.5 2002/12/04 21:07:43 asaim Exp $
// GEANT4 tag $Name: geant4-05-00 $
//
//
@@ -52,24 +52,24 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
RndmStepCmd->SetGuidance("Randomize the proposed step by eLoss.");
RndmStepCmd->SetParameterName("choice",true);
RndmStepCmd->SetDefaultValue(false);
RndmStepCmd->AvailableForStates(Idle);
RndmStepCmd->AvailableForStates(G4State_Idle);
EnlossFlucCmd = new G4UIcmdWithABool("/process/eLoss/fluct",this);
EnlossFlucCmd->SetGuidance("Switch true/false the energy loss fluctuations.");
EnlossFlucCmd->SetParameterName("choice",true);
EnlossFlucCmd->SetDefaultValue(true);
EnlossFlucCmd->AvailableForStates(Idle);
EnlossFlucCmd->AvailableForStates(G4State_Idle);
SubSecCmd = new G4UIcmdWithABool("/process/eLoss/subsec",this);
SubSecCmd->SetGuidance("Switch true/false the subcutoff generation.");
SubSecCmd->SetParameterName("choice",true);
SubSecCmd->SetDefaultValue(true);
SubSecCmd->AvailableForStates(Idle);
SubSecCmd->AvailableForStates(G4State_Idle);
MinSubSecCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/minsubsec",this);
MinSubSecCmd->SetGuidance("Set the min. cut for subcutoff delta in range.");
MinSubSecCmd->SetParameterName("rcmin",true);
MinSubSecCmd->AvailableForStates(Idle);
MinSubSecCmd->AvailableForStates(G4State_Idle);
StepFuncCmd = new G4UIcommand("/process/eLoss/StepFunction",this);
StepFuncCmd->SetGuidance("Set the energy loss step limitation parameters.");
@@ -93,7 +93,7 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
unitPrm->SetParameterCandidates(unitCandidates);
StepFuncCmd->SetParameter(unitPrm);
StepFuncCmd->AvailableForStates(Idle);
StepFuncCmd->AvailableForStates(G4State_Idle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,190 @@
//
// ********************************************************************
// * 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: G4EnergyLossMessengerSTD
//
// Author:
//
// Creation date:
//
// Modifications:
//
// 03.01.2002 V.Ivanchenko update to new design
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4EnergyLossMessengerSTD.hh"
#include "G4LossTableManager.hh"
#include "G4UIdirectory.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
#include "G4UIcmdWithABool.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "g4std/strstream"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EnergyLossMessengerSTD::G4EnergyLossMessengerSTD()
{
eLossDirectory = new G4UIdirectory("/process/eLoss/");
eLossDirectory->SetGuidance("Commands for G4VEnergyLoss.");
RndmStepCmd = new G4UIcmdWithABool("/process/eLoss/rndmStep",this);
RndmStepCmd->SetGuidance("Randomize the proposed step by eLoss.");
RndmStepCmd->SetParameterName("rndmStep",true);
RndmStepCmd->SetDefaultValue(false);
RndmStepCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
EnlossFlucCmd = new G4UIcmdWithABool("/process/eLoss/fluct",this);
EnlossFlucCmd->SetGuidance("Switch true/false the energy loss fluctuations.");
EnlossFlucCmd->SetParameterName("fluct",true);
EnlossFlucCmd->SetDefaultValue(true);
EnlossFlucCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
SubSecCmd = new G4UIcmdWithABool("/process/eLoss/subsec",this);
SubSecCmd->SetGuidance("Switch true/false the subcutoff generation.");
SubSecCmd->SetParameterName("subsec",true);
SubSecCmd->SetDefaultValue(true);
SubSecCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
IntegCmd = new G4UIcmdWithABool("/process/eLoss/integral",this);
IntegCmd->SetGuidance("Switch true/false the integration of cross section over step.");
IntegCmd->SetParameterName("integ",true);
IntegCmd->SetDefaultValue(true);
IntegCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MinSubSecCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/minsubsec",this);
MinSubSecCmd->SetGuidance("Set the min. cut for subcutoff delta in range.");
MinSubSecCmd->SetParameterName("minsubsec",true);
MinSubSecCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MinEnCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/minKinEnergy",this);
MinEnCmd->SetGuidance("Set the min kinetic energy");
MinEnCmd->SetParameterName("emin",true);
MinEnCmd->SetUnitCategory("Energy");
MinEnCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MaxEnCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/maxKinEnergy",this);
MaxEnCmd->SetGuidance("Set the max kinetic energy");
MaxEnCmd->SetParameterName("emax",true);
MaxEnCmd->SetUnitCategory("Energy");
MaxEnCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd = new G4UIcommand("/process/eLoss/StepFunction",this);
StepFuncCmd->SetGuidance("Set the energy loss step limitation parameters.");
StepFuncCmd->SetGuidance(" dRoverR : max Range variation per step");
StepFuncCmd->SetGuidance(" finalRange: range for final step");
G4UIparameter* dRoverRPrm = new G4UIparameter("dRoverR",'d',false);
dRoverRPrm->SetGuidance("max Range variation per step (fractional number)");
dRoverRPrm->SetParameterRange("dRoverR>0. && dRoverR<=1.");
StepFuncCmd->SetParameter(dRoverRPrm);
G4UIparameter* finalRangePrm = new G4UIparameter("finalRange",'d',false);
finalRangePrm->SetGuidance("range for final step");
finalRangePrm->SetParameterRange("finalRange>0.");
StepFuncCmd->SetParameter(finalRangePrm);
G4UIparameter* unitPrm = new G4UIparameter("unit",'s',true);
unitPrm->SetGuidance("unit of finalRange");
unitPrm->SetDefaultValue("mm");
G4String unitCandidates = G4UIcommand::UnitsList(G4UIcommand::CategoryOf("mm"));
unitPrm->SetParameterCandidates(unitCandidates);
StepFuncCmd->SetParameter(unitPrm);
StepFuncCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EnergyLossMessengerSTD::~G4EnergyLossMessengerSTD()
{
delete RndmStepCmd;
delete EnlossFlucCmd;
delete SubSecCmd;
delete MinSubSecCmd;
delete MinEnCmd;
delete MaxEnCmd;
delete StepFuncCmd;
delete IntegCmd;
delete eLossDirectory;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EnergyLossMessengerSTD::SetNewValue(G4UIcommand* command,G4String newValue)
{
G4LossTableManager* lossTables = G4LossTableManager::Instance();
if (command == RndmStepCmd) {
lossTables->SetRandomStep(RndmStepCmd->GetNewBoolValue(newValue));
}
if (command == IntegCmd) {
lossTables->SetIntegral(IntegCmd->GetNewBoolValue(newValue));
}
if (command == EnlossFlucCmd) {
lossTables->SetLossFluctuations(EnlossFlucCmd->GetNewBoolValue(newValue));
}
if (command == SubSecCmd) {
lossTables->SetSubCutoff(SubSecCmd->GetNewBoolValue(newValue));
}
if (command == MinEnCmd) {
lossTables->SetMinEnergy(MinEnCmd->GetNewDoubleValue(newValue));
}
if (command == MaxEnCmd) {
lossTables->SetMaxEnergy(MaxEnCmd->GetNewDoubleValue(newValue));
}
if (command == StepFuncCmd) {
G4double v1,v2;
char unts[30];
const char* t = newValue;
G4std::istrstream is((char*)t);
is >> v1 >> v2 >> unts;
G4String unt = unts;
v2 *= G4UIcommand::ValueOf(unt);
lossTables->SetStepLimits(v1,v2);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -22,7 +22,7 @@
//
//
// $Id: G4EnergyLossTables.cc,v 1.17 2001/10/29 09:40:52 maire Exp $
// GEANT4 tag $Name: geant4-04-01 $
// GEANT4 tag $Name: geant4-05-00 $
//
// -------------------------------------------------------------------
// first version created by P.Urban , 06/04/1998
@@ -0,0 +1,200 @@
//
// ********************************************************************
// * 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: G4LossTableBuilder
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LossTableBuilder.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsLogVector.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildDEDXTable(
const G4std::vector<G4PhysicsTable*>& list)
{
size_t n_processes = list.size();
if (0 == n_processes) return 0;
else if (1 == n_processes) return list[0];
size_t n_vectors = list[0]->length();
if(!n_vectors) return 0;
G4PhysicsVector* pv = (*(list[0]))[0];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4PhysicsTable* theTable = new G4PhysicsTable();
G4bool b;
for (size_t i=0; i<n_vectors; i++) {
G4PhysicsLogVector* v = new G4PhysicsLogVector(elow, ehigh, nbins);
for (size_t j=0; j<nbins; j++) {
G4double dedx = 0.0;
G4double energy = pv->GetLowEdgeEnergy(j);
for (size_t k=0; k<n_processes; k++) {
dedx += ((*(list[k]))[i])->GetValue(energy, b);
}
v->PutValue(j, dedx);
}
theTable->insert(v);
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
const G4PhysicsTable* dedxTable)
// Build range table from the energy loss table
{
size_t n_vectors = dedxTable->length();
if(!n_vectors) return 0;
G4bool b;
size_t n = 100;
G4double del = 1.0/(G4double)n;
G4PhysicsVector* pv = (*dedxTable)[0];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4PhysicsTable* theTable = new G4PhysicsTable();
for (size_t i=0; i<n_vectors; i++) {
G4PhysicsLogVector* v = new G4PhysicsLogVector(elow, ehigh, nbins);
pv = (*dedxTable)[i];
G4double dedx1 = pv->GetValue(elow, b);
G4double range = 0.5*elow/dedx1;
v->PutValue(0,range);
G4double energy1 = elow;
for (size_t j=1; j<nbins; j++) {
G4double energy2 = pv->GetLowEdgeEnergy(j);
G4double dedx2 = pv->GetValue(energy2, b);
G4double de = (energy2 - energy1) * del;
G4double energy = energy1 - de*0.5;
G4double fac = log(dedx2/dedx1)/log(energy2/energy1);
for (size_t k=0; k<n; k++) {
energy += de;
G4double f = dedx1*exp(fac*log(energy/energy1));
range += de/f;
}
v->PutValue(j,range);
energy1 = energy2;
dedx1 = dedx2;
}
theTable->insert(v);
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
const G4PhysicsTable* dedxTable,
const G4PhysicsTable* rangeTable)
// Build inverse range table from the energy loss table
{
size_t n_vectors = rangeTable->length();
if(!n_vectors) return 0;
G4bool b;
G4PhysicsTable* theTable = new G4PhysicsTable();
for (size_t i=0; i<n_vectors; i++) {
G4PhysicsVector* pv = (*rangeTable)[i];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins-1);
G4double rlow = pv->GetValue(elow, b);
G4double rhigh = pv->GetValue(ehigh, b);
rhigh *= exp(log(rhigh/rlow)/((G4double)(nbins-1)));
G4PhysicsLogVector* v = new G4PhysicsLogVector(rlow, rhigh, nbins);
v->PutValue(0,elow);
G4double energy1 = elow;
G4double range1 = rlow;
G4double energy2 = elow;
G4double range2 = rlow;
size_t ilow = 0;
size_t ihigh;
for (size_t j=1; j<nbins; j++) {
G4double range = v->GetLowEdgeEnergy(j);
for (ihigh=ilow+1; ihigh<nbins; ihigh++) {
energy2 = pv->GetLowEdgeEnergy(ihigh);
range2 = pv->GetValue(energy2, b);
if(range2 >= range || ihigh == nbins-1) {
ilow = ihigh - 1;
energy1 = pv->GetLowEdgeEnergy(ilow);
range1 = pv->GetValue(energy1, b);
break;
}
}
G4double e = log(energy1) + log(energy2/energy1)*log(range/range1)/log(range2/range1);
v->PutValue(j,exp(e));
}
theTable->insert(v);
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,557 @@
//
// ********************************************************************
// * 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: G4LossTableManager
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LossTableManager.hh"
#include "G4EnergyLossMessengerSTD.hh"
#include "G4PhysicsTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4ProcessManager.hh"
#include "G4Electron.hh"
G4LossTableManager* G4LossTableManager::theInstance = 0;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4LossTableManager* G4LossTableManager::Instance()
{
if(0 == theInstance) {
theInstance = new G4LossTableManager();
}
return theInstance;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4LossTableManager::~G4LossTableManager()
{
delete theMessenger;
delete tableBuilder;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4LossTableManager::G4LossTableManager()
{
n_loss = 0;
all_tables_are_built = false;
all_particles_are_mapped = false;
electron_table_are_built = false;
currentLoss = 0;
currentParticle = 0;
lossFluctuationFlag = true;
subCutoffFlag = false;
rndmStepFlag = false;
minSubRange = 0.0;
maxRangeVariation = 1.0;
maxFinalStep = 0.0;
eIonisation = 0;
minKinEnergy = 0.1*eV;
maxKinEnergy = 100.0*GeV;
theMessenger = new G4EnergyLossMessengerSTD();
theElectron = G4Electron::Electron();
tableBuilder = new G4LossTableBuilder();
integral = true;
verbose = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::Clear()
{
all_tables_are_built = false;
all_particles_are_mapped = false;
electron_table_are_built = false;
eIonisation = 0;
currentLoss = 0;
currentParticle = 0;
if(n_loss)
{
for(G4int i=0; i<n_loss; i++)
{
if(dedx_vector[i]) dedx_vector[i]->clearAndDestroy();
if(range_vector[i]) range_vector[i]->clearAndDestroy();
if(inv_range_vector[i]) inv_range_vector[i]->clearAndDestroy();
}
dedx_vector.clear();
range_vector.clear();
inv_range_vector.clear();
loss_map.clear();
loss_vector.clear();
part_vector.clear();
base_part_vector.clear();
tables_are_built.clear();
n_loss = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::Register(G4VEnergyLossSTD* p)
{
n_loss++;
loss_vector.push_back(p);
part_vector.push_back(0);
base_part_vector.push_back(0);
dedx_vector.push_back(0);
range_vector.push_back(0);
inv_range_vector.push_back(0);
tables_are_built.push_back(false);
all_particles_are_mapped = false;
all_tables_are_built = false;
/*
p->SetLossFluctuations(lossFluctuationFlag);
p->SetSubCutoff(subCutoffFlag);
p->SetRandomStep(rndmStepFlag);
p->SetMinSubRange(minSubRange);
p->SetMinKinEnergy(minKinEnergy);
p->SetMaxKinEnergy(maxKinEnergy);
p->SetStepLimits(maxRangeVariation, maxFinalStep);
p->SetIntegral(integral);
*/
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::Initialise()
{
all_tables_are_built = true;
for(G4int j=0; j<n_loss; j++) {
if(1 < verbose) {
G4String nm = "unknown";
const G4ParticleDefinition* pd = loss_vector[j]->Particle();
if(pd) nm = pd->GetParticleName();
G4cout << "For " << loss_vector[j]->GetProcessName()
<< " for " << nm
<< " tables_are_built= " << tables_are_built[j]
<< G4endl;
}
if(!loss_vector[j]->TablesAreBuilt()) {
all_tables_are_built = false;
break;
}
}
// All tables have to be rebuilt
if(all_particles_are_mapped && all_tables_are_built) {
for(G4int i=0; i<n_loss; i++) {
tables_are_built[i] = false;
}
all_tables_are_built = false;
electron_table_are_built = false;
loss_map.clear();
}
// map all particles
if(!all_particles_are_mapped) {
const G4ParticleDefinition* pd;
for(G4int i=0; i<n_loss; i++) {
if(!part_vector[i]) {
pd = loss_vector[i]->Particle();
if(!pd) {
pd = loss_vector[i]->GetProcessManager()->GetParticleType();
loss_vector[i]->SetParticle(pd);
}
if(pd == theElectron) eIonisation = loss_vector[i];
part_vector[i] = pd;
pd = loss_vector[i]->BaseParticle();
base_part_vector[i] = pd;
}
}
all_particles_are_mapped = true;
}
if(1 < verbose) {
G4cout << "electron_table_are_built= " << electron_table_are_built
<< " all_tables_are_built= " << all_tables_are_built
<< " all_particles_are_mapped= " << all_particles_are_mapped
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::BuildDEDXTable(const G4ParticleDefinition* aParticle)
{
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable() for "
<< aParticle->GetParticleName()
<< G4endl;
}
Initialise();
// identify all particles and built electron table
if(!electron_table_are_built) {
eIonisation = BuildTables(theElectron);
electron_table_are_built = true;
}
// If particle is not an electron
if(aParticle != theElectron) {
for(G4int i=0; i<n_loss; i++) {
if(1 < verbose) {
G4String nm = "0";
G4String nm1= "0";
G4String nm2= "0";
const G4ParticleDefinition* pd = loss_vector[i]->Particle();
const G4ParticleDefinition* bpd = loss_vector[i]->BaseParticle();
if(pd) nm = pd->GetParticleName();
if(bpd) nm2 = bpd->GetParticleName();
if(part_vector[i]) nm1 = part_vector[i]->GetParticleName();
G4cout << "For " << loss_vector[i]->GetProcessName()
<< " for " << nm
<< " (" << nm1 << ") "
<< " base_part= " << nm2
<< " tables_are_built= " << tables_are_built[i]
<< G4endl;
}
if(aParticle == part_vector[i]) {
if(tables_are_built[i]) break;
base_part_vector[i] = loss_vector[i]->BaseParticle();
if(!base_part_vector[i]) {
G4VEnergyLossSTD* hIonisation = BuildTables(aParticle);
for(G4int j=0; j<i; j++) {
if(aParticle == base_part_vector[j]) {
tables_are_built[j] = true;
G4VEnergyLossSTD* em = loss_vector[j];
em->Initialise();
em->SetDEDXTable(hIonisation->DEDXTable());
em->SetRangeTable(hIonisation->RangeTable());
em->SetInverseRangeTable(hIonisation->InverseRangeTable());
loss_map[part_vector[j]] = hIonisation;
if(em->SecondaryParticle() == theElectron) {
em->SetSecondaryRangeTable(eIonisation->RangeTable());
}
}
}
} else {
G4VEnergyLossSTD* em = loss_vector[i];
for(G4int j=0; j<n_loss; j++) {
if(part_vector[j] == base_part_vector[i]) {
G4VEnergyLossSTD* hIonisation = loss_vector[j];
if(tables_are_built[j] && hIonisation->DEDXTable()) {
tables_are_built[i] = true;
em->Initialise();
em->SetDEDXTable(hIonisation->DEDXTable());
em->SetRangeTable(hIonisation->RangeTable());
em->SetInverseRangeTable(hIonisation->InverseRangeTable());
loss_map[part_vector[i]] = hIonisation;
if(em->SecondaryParticle() == theElectron) {
em->SetSecondaryRangeTable(eIonisation->RangeTable());
}
break;
}
}
}
}
break;
}
}
}
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable: end; "
<< "all_tables_are_built= " << all_tables_are_built
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::RetrieveDEDXTable(const G4ParticleDefinition* aParticle,
G4VEnergyLossSTD* theModel)
{
for(G4int i=0; i<n_loss; i++) {
if(theModel == loss_vector[i]) {
tables_are_built[i] = true;
if(theModel->DEDXTable()) {
for(G4int j=0; j<n_loss; j++) {
if(j != i && tables_are_built[j]) {
if(aParticle == base_part_vector[j]) {
G4VEnergyLossSTD* em = loss_vector[j];
em->SetDEDXTable(theModel->DEDXTable());
em->SetRangeTable(theModel->RangeTable());
em->SetInverseRangeTable(theModel->InverseRangeTable());
loss_map[part_vector[j]] = theModel;
}
}
}
} else {
const G4ParticleDefinition* bp = theModel->BaseParticle();
for(G4int j=0; j<n_loss; j++) {
if(j != i && tables_are_built[j]) {
if(bp == part_vector[j] && loss_vector[j]->DEDXTable()) {
G4VEnergyLossSTD* hIonisation = loss_vector[j];
theModel->SetDEDXTable(hIonisation->DEDXTable());
theModel->SetRangeTable(hIonisation->RangeTable());
theModel->SetInverseRangeTable(hIonisation->InverseRangeTable());
loss_map[part_vector[j]] = hIonisation;
break;
}
}
}
}
break;
}
}
// identify all particles and built electron table
if(aParticle == theElectron) {
electron_table_are_built = true;
for(G4int i=0; i<n_loss; i++) {
if(loss_vector[i]->SecondaryParticle() == theElectron) {
loss_vector[i]->SetSecondaryRangeTable(theModel->RangeTable());
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aParticle)
{
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildTables() for "
<< aParticle->GetParticleName() << G4endl;
}
// Check is it new particle or all tables have to be rebuilt
G4std::vector<G4PhysicsTable*> list;
list.clear();
G4std::vector<G4VEnergyLossSTD*> loss_list;
loss_list.clear();
G4VEnergyLossSTD* em = 0;
G4int iem = 0;
G4bool no_el = true;
for(G4int i=0; i<n_loss; i++) {
if(aParticle == part_vector[i]) {
base_part_vector[i] = loss_vector[i]->BaseParticle();
loss_vector[i]->Initialise();
if(no_el && loss_vector[i]->SecondaryParticle() == theElectron) {
em = loss_vector[i];
iem= i;
no_el = false;
}
if(!em) {
em = loss_vector[i];
iem= i;
}
tables_are_built[i] = true;
list.push_back(loss_vector[i]->BuildDEDXTable());
loss_list.push_back(loss_vector[i]);
}
}
G4int n_dedx = list.size();
if(!n_dedx) return 0;
if(aParticle == theElectron) eIonisation = em;
if(0 < verbose) {
G4cout << "G4LossTableManager::BuildTables() start to build range tables"
<< " and the sum of " << n_dedx << " processes"
<< G4endl;
}
G4PhysicsTable* dedx = list[0];
if(1 < n_dedx) {
dedx = tableBuilder->BuildDEDXTable(list);
for(G4int i=0; i<n_dedx; i++) {
list[i]->clearAndDestroy();
}
}
em->SetDEDXTable(dedx);
dedx_vector[iem] = dedx;
G4PhysicsTable* range = tableBuilder->BuildRangeTable(dedx);
em->SetRangeTable(range);
range_vector[iem] = range;
G4PhysicsTable* invrange = tableBuilder->BuildInverseRangeTable(dedx, range);
em->SetInverseRangeTable(invrange);
inv_range_vector[iem] = invrange;
loss_map[aParticle] = em;
for(G4int j=0; j<n_dedx; j++) {
if(loss_list[j]->SecondaryParticle() == theElectron) {
loss_list[j]->SetSecondaryRangeTable(eIonisation->RangeTable());
}
}
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildTables: Tables are built"
<< " for " << em->GetProcessName()
<< G4endl;
}
return em;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetLossFluctuations(G4bool val)
{
lossFluctuationFlag = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetLossFluctuations(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetSubCutoff(G4bool val)
{
subCutoffFlag = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetSubCutoff(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetIntegral(G4bool val)
{
integral = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetIntegral(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMinSubRange(G4double val)
{
minSubRange = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetMinSubRange(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetRandomStep(G4bool val)
{
rndmStepFlag = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetRandomStep(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMinEnergy(G4double val)
{
minKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetMinKinEnergy(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMaxEnergy(G4double val)
{
maxKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetMaxKinEnergy(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetStepLimits(G4double v1, G4double v2)
{
maxRangeVariation = v1;
maxFinalStep = v2;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetStepLimits(v1, v2);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4LossTableManager::StorePhysicsTable(G4VEnergyLossSTD* el,
const G4String& dedx_file,
const G4String& range_file,
const G4String& inv_range_file,
G4bool ascii)
{
G4int i=0;
for(i=0; i<n_loss; i++) {
if(el == loss_vector[i]) break;
}
// store stopping power table
if (dedx_vector[i]) {
if ( !dedx_vector[i]->StorePhysicsTable(dedx_file, ascii) ){
G4cout << "Fatal error theDEDXTable->StorePhysicsTable in <"
<< dedx_file << ">"
<< G4endl;
return false;
}
}
if (range_vector[i]) {
if ( !range_vector[i]->StorePhysicsTable(range_file, ascii) ){
G4cout << "Fatal error theRangeTable->StorePhysicsTable in <"
<< range_file << ">"
<< G4endl;
return false;
}
}
if (inv_range_vector[i]) {
if ( !inv_range_vector[i]->StorePhysicsTable(inv_range_file, ascii) ){
G4cout << "Fatal error theInverseRangeTable->StorePhysicsTable in <"
<< inv_range_file << ">"
<< G4endl;
return false;
}
}
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -20,13 +20,14 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4MultipleScattering.cc,v 1.22 2002/06/11 08:06:47 urban Exp $
// GEANT4 tag $Name: geant4-04-01 $
//
// $Id: G4MultipleScattering.cc,v 1.30 2002/12/11 12:05:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
// 18/05/01 V.Ivanchenko Clean up against Linux ANSI compilation
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 23-08-01 new angle and z distribution,energy dependence reduced,
// Store,Retrieve methods commented out temporarily, L.Urban
// 27-08-01 in BuildPhysicsTable:aParticleType.GetParticleName()=="mu+" (mma)
@@ -40,14 +41,19 @@
// 17-09-01 migration of Materials to pure STL (mma)
// 27-09-01 value of data member factlim changed, L.Urban
// 31-10-01 big fixed in PostStepDoIt,L.Urban
// 17-04-02 NEW angle distribution + boundary algorithm modified, L.Urban
// 22-04-02 boundary algorithm modified -> important improvement in timing !!!!
// (L.Urban)
// 24-04-02 some minor changes in boundary algorithm, L.Urban
// 06-05-02 bug fixed in GetContinuousStepLimit, L.Urban
// 24-05-02 changes in angle distribution and boundary algorithm, L.Urban
// 11-06-06 bug fixed in ComputeTransportCrossSection, L.Urban
//
// 11-06-02 bug fixed in ComputeTransportCrossSection, L.Urban
// 12-08-02 bug fixed in PostStepDoIt (lateral displacement), L.Urban
// 15-08-02 new angle distribution, L.Urban
// 26-09-02 angle distribution + boundary algorithm modified, L.Urban
// 15-10-02 temporary fix for proton scattering
// 30-10-02 modified angle distribution,mods in boundary algorithm,
// changes in data members, L.Urban
// 30-10-02 rename variable cm - Ecm, V.Ivanchenko
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured, L.Urban
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -65,7 +71,7 @@ G4MultipleScattering::G4MultipleScattering(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(0),
fTransportMeanFreePath (1.e12),kappa(2.5),
taubig(10.),tausmall(1.e-12),taulim(1.e-6),
taubig(8.0),tausmall(1.e-14),taulim(1.e-5),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
@@ -73,17 +79,17 @@ G4MultipleScattering::G4MultipleScattering(const G4String& processName)
tLast (0.0),
zLast (0.0),
boundary(true),
facrange(0.199),tlimit(1.e10),
facrange(0.199),tlimit(1.e10*mm),tlimitmin(1.e-7*mm),
cf(1.001),
stepno(0),stepnolastmsc(-1000000),nsmallstep(5),
laststep(0.),
valueGPILSelectionMSC(NotCandidateForSelection),
pcz(0.17),zmean(0.),
range(1.0),T1(1.0),lambda1(-1.),cth1(1.),z1(1.e10),dtrl(0.15),
tuning (1.00),
cparm (0.0),
Tlim(1.e6*MeV),
fLatDisplFlag(true),
NuclCorrPar (0.0615),
FactPar(0.40)
FactPar(0.40),
facxsi(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -102,6 +108,27 @@ G4MultipleScattering::~G4MultipleScattering()
void G4MultipleScattering::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 1.80 ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.42 ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius;
@@ -167,7 +194,6 @@ void G4MultipleScattering::BuildPhysicsTable(
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
@@ -188,7 +214,6 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
10000.0*MeV};
// corr. factors for e-/e+ lambda
G4double celectron[15][23] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
@@ -284,29 +309,44 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
1.456,1.412,1.364,1.328,1.307,1.282,1.2026 }};
G4double sigma;
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
G4double ParticleMass = aParticleType.GetPDGMass();
G4double rat2 = ParticleMass/electron_mass_c2; rat2 = rat2*rat2;
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
G4double Mass = ParticleMass ;
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
// TAU = Tkin/ParticleMass , tau = Tkin_scaled/electronmass
// p*beta = Mass*TAU*(TAU+2.)/(TAU+1.) =
// electron_mass_c2*tau*(tau+2.)/(tau+1.)
G4double TAU = KineticEnergy/Mass ;
G4double c = Mass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
KineticEnergy = electron_mass_c2*tau ;
Mass = electron_mass_c2 ;
}
G4double Charge = aParticleType.GetPDGCharge();
G4double ChargeSquare = Charge*Charge/(eplus*eplus);
G4double TotalEnergy = KineticEnergy + ParticleMass ;
G4double beta2 = KineticEnergy*(TotalEnergy+ParticleMass)
G4double TotalEnergy = KineticEnergy + Mass ;
G4double beta2 = KineticEnergy*(TotalEnergy+Mass)
/(TotalEnergy*TotalEnergy);
G4double bg2 = KineticEnergy*(TotalEnergy+ParticleMass)
/(ParticleMass*ParticleMass);
G4double bg2 = KineticEnergy*(TotalEnergy+Mass)
/(Mass*Mass);
G4double eps = rat2*epsfactor*bg2/Z23;
G4double eps = epsfactor*bg2/Z23;
if (eps<epsmin) sigma = 2.*eps*eps;
else if(eps<epsmax) sigma = log(1.+2.*eps)-2.*eps/(1.+2.*eps);
else sigma = log(2.*eps)-1.+1./eps;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/(rat2*beta2*bg2);
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/(beta2*bg2);
// nuclear size effect correction for high energy
// ( a simple approximation at present)
@@ -324,16 +364,10 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*proton_mass_c2/KineticEnergy)*
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
// correct this value using the corrections computed for e+/e-
// scaling: mass*beta*gamma does not depend on the kind of particle !
G4double tau=KineticEnergy/electron_mass_c2 ;
KineticEnergy = sqrt(ParticleMass*ParticleMass+tau*(tau+2.)*
electron_mass_c2*electron_mass_c2)-ParticleMass ;
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
@@ -357,18 +391,11 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
T = Tdat[iT+1]; E = T + electron_mass_c2;
G4double b2big = T*(E+electron_mass_c2)/(E*E);
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double beta2lim = Tlim*(Tlim+2.*electron_mass_c2)/
((Tlim+electron_mass_c2)*(Tlim+electron_mass_c2));
G4double corrfactor ;
if(T < Tlim)
corrfactor = tuning*(1.+cparm*beta2lim)/(1.+cparm*beta2);
else
corrfactor = tuning ;
G4double c1,c2,cc1,cc2,corr;
if (Charge < 0.)
{
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
@@ -395,8 +422,6 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
sigma /= corr;
}
sigma *= corrfactor;
// nucl. size correction for particles other than e+/e- only at present !!!!
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
@@ -404,7 +429,7 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
return sigma;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -453,20 +478,27 @@ G4double G4MultipleScattering::GetContinuousStepLimit(
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
tlimit = facrange*range ;
// if : diff.treatment for small/not small Z
if(range > fTransportMeanFreePath)
tlimit = facrange*range ;
else
tlimit = facrange*fTransportMeanFreePath ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
laststep = tlimit ;
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
else if(stepno >= stepnolastmsc)
else if(stepno > stepnolastmsc)
{
if((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
@@ -479,7 +511,7 @@ G4double G4MultipleScattering::GetContinuousStepLimit(
z1 = 1.e10 ;
tau = tPathLength/fTransportMeanFreePath ;
if(tau < tausmall) zPathLength = tPathLength;
else
@@ -580,11 +612,11 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
(materialIndex)->GetValue(KineticEnergy,isOut);
// change direction first ( scattering )
G4double cth,tau;
tau = truestep/fTransportMeanFreePath;
G4double cth =1 ;
G4double tau = truestep/fTransportMeanFreePath;
if(KineticEnergy <= 0.)
cth = -1.+2.*G4UniformRand() ;
;
else
{
if (tau < tausmall) cth = 1.;
@@ -596,71 +628,80 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double alfa = 0.385 ;
const G4double beta = 0.0626 ;
const G4double c = 2.500 ;
const G4double x2mean3 = 1./3. ;
const G4double amax=25. ;
const G4double tau0 = 0.02 ;
const G4double b = 1. ;
G4double a,b,c1,bp1,bm1,bbp1,bbm1,
xmean1,x2mean1,xmean2,x2mean2,
x2mean,xmeanth,x2meanth,pp,qq ;
G4double a,x0,c,xmean1,xmean2,
xmeanth,prob,qprob ;
G4double ea,eaa,b1,bx,eb1,ebx,cnorm1,cnorm2,f1x0,f2x0,w ;
a = 2.*exp(-alfa*tau)/(1.-exp(-alfa*tau)) ;
w = log(tau/tau0) ;
if(tau < tau0)
a = (alfa1-alfa2*w)/tau ;
else
a = (alfa1+alfa3*w)/tau ;
xmean1 = a/(a+2.) ;
x2mean1= (a*a+a+2.)/((a+2.)*(a+3.)) ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
b = exp((1.+beta)*tau) ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
c1 = 1.-c ;
bp1=b+1. ;
bm1=b-1. ;
bbp1=exp(log(bp1)*c1) ;
bbm1=exp(log(bm1)*c1) ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
xmean2 = -(bbp1+bbm1)/(bbp1-bbm1)+(bp1*bbp1-bm1*bbm1)/
((2.-c)*(bbp1-bbm1)) ;
x2mean2= 1.-2.*(bp1*bbp1+bm1*bbm1)/((2.-c)*(bbp1-bbm1))+
2.*(bp1*bp1*bbp1-bm1*bm1*bbm1)/((2.-c)*(3.-c)*(bbp1-bbm1)) ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
xmeanth = exp(-tau) ;
x2meanth = (1.+2.*exp(-kappa*tau))/3. ;
b1 = b+1. ;
bx=b-x0 ;
eb1=exp((c-1.)*log(b1)) ;
ebx=exp((c-1.)*log(bx)) ;
xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
pp = (xmeanth-xmean2)/(xmean1-xmean2) ;
x2mean = pp*x2mean1+(1.-pp)*x2mean2 ;
if(x2mean >= x2meanth)
{
qq = 1. ;
}
else
{
pp = (x2meanth*xmean1-x2mean1*xmeanth+x2mean3*xmeanth
+x2mean1*xmean2-x2mean3*xmean2-x2mean2*xmean1)/
(xmean2*x2mean1-xmean2*x2mean3-xmean1*x2mean2+xmean1*x2mean3) ;
xmeanth = exp(-tau) ;
qq = (xmeanth-(1.-pp)*xmean2)/(pp*xmean1) ;
}
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
if(G4UniformRand() < pp)
{
if(G4UniformRand() < qq)
{
cth = -1.+2.*exp(log(G4UniformRand())/(1.+a)) ;
}
else
{
cth = -1.+2.*G4UniformRand() ;
}
}
else
{
cth = b- exp(log(bbp1-G4UniformRand()*(bbp1-bbm1))/c1) ;
}
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
// protection against qprob > 1
// *******************************************
if(qprob > 1.)
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
// *******************************************
// sampling of costheta
if(G4UniformRand() < qprob)
{
if(G4UniformRand() < prob)
cth = 1.+log(ea+G4UniformRand()*eaa)/a ;
else
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
cth = -1.+2.*G4UniformRand() ;
}
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi), diry = sth*sin(phi), dirz = cth;
@@ -682,7 +723,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
if (safetyminustolerance > 0.)
{
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = 5.*tau*tau*tau/12.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6. ;
else
{
if(tau<taubig) etau = exp(-tau);
@@ -0,0 +1,839 @@
//
// ********************************************************************
// * 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: G4MultipleScatteringSTD.cc,v 1.6 2002/12/11 12:05:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
// 18/05/01 V.Ivanchenko Clean up against Linux ANSI compilation
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 23-08-01 new angle and z distribution,energy dependence reduced,
// Store,Retrieve methods commented out temporarily, L.Urban
// 27-08-01 in BuildPhysicsTable:aParticleType.GetParticleName()=="mu+" (mma)
// 28-08-01 GetContinuousStepLimit and AlongStepDoIt moved from .icc file (mma)
// 03-09-01 value of data member factlim changed, L.Urban
// 10-09-01 small change in GetContinuousStepLimit, L.Urban
// 11-09-01 G4MultipleScatteringx put as default G4MultipleScattering
// store/retrieve physics table reactivated (mma)
// 13-09-01 corr. in ComputeTransportCrossSection, L.Urban
// 14-09-01 protection in GetContinuousStepLimit, L.Urban
// 17-09-01 migration of Materials to pure STL (mma)
// 27-09-01 value of data member factlim changed, L.Urban
// 31-10-01 big fixed in PostStepDoIt,L.Urban
// 17-04-02 NEW angle distribution + boundary algorithm modified, L.Urban
// 22-04-02 boundary algorithm modified -> important improvement in timing (L.Urban)
// 24-04-02 some minor changes in boundary algorithm, L.Urban
// 06-05-02 bug fixed in GetContinuousStepLimit, L.Urban
// 24-05-02 changes in angle distribution and boundary algorithm, L.Urban
// 11-06-02 bug fixed in ComputeTransportCrossSection, L.Urban
// 12-08-02 bug fixed in PostStepDoIt (lateral displacement), L.Urban
// 15-08-02 new angle distribution, L.Urban
// 26-09-02 angle distribution + boundary algorithm modified, L.Urban
// 15-10-02 temporary fix for proton scattering
// 30-10-02 modified angle distribution,mods in boundary algorithm,
// changes in data members, L.Urban
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured from L.Urban
//
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4MultipleScatteringSTD.hh"
#include "G4LossTableManager.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScatteringSTD::G4MultipleScatteringSTD(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(0),
fTransportMeanFreePath (1.e12),kappa(2.5),
taubig(8.0),tausmall(1.e-14),taulim(1.e-5),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
materialIndex(0),
tLast (0.0),
zLast (0.0),
boundary(true),
facrange(0.199),tlimit(1.e10*mm),tlimitmin(1.e-7*mm),
cf(1.001),
stepno(0),stepnolastmsc(-1000000),nsmallstep(5),
laststep(0.),
valueGPILSelectionMSC(NotCandidateForSelection),
pcz(0.17),zmean(0.),
range(1.0),T1(1.0),lambda1(-1.),cth1(1.),z1(1.e10),dtrl(0.15),
fLatDisplFlag(true),
NuclCorrPar (0.0615),
FactPar(0.40),
facxsi(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScatteringSTD::~G4MultipleScatteringSTD()
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScatteringSTD::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 1.80 ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.42 ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius;
G4double KineticEnergy,AtomicNumber,AtomicWeight,sigma,lambda;
G4double density;
// destroy old tables if any
if (theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
// create table
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4Material* material = (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume =
material->GetVecNbOfAtomsPerVolume();
const G4int NumberOfElements = material->GetNumberOfElements();
density = material->GetDensity();
// loop for kinetic energy values
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i);
sigma = 0.;
// loop for element in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
AtomicNumber = (*theElementVector)[iel]->GetZ();
AtomicWeight = (*theElementVector)[iel]->GetA();
sigma += NbOfAtomsPerVolume[iel]*
ComputeTransportCrossSection(aParticleType,KineticEnergy,
AtomicNumber,AtomicWeight);
}
sigma *= sigmafactor;
lambda = 1./sigma;
aVector->PutValue(i,lambda);
}
theTransportMeanFreePathTable->insert(aVector);
}
if((aParticleType.GetParticleName() == "e-" ) ||
(aParticleType.GetParticleName() == "mu+" ) ||
(aParticleType.GetParticleName() == "proton") ) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,G4double AtomicWeight)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc);
const G4double epsmin = 1.e-4 , epsmax = 1.e10;
const G4double Zdat[15] = { 4., 6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. };
const G4double Tdat[23] = {0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,
0.01*MeV,0.02*MeV,0.04*MeV,0.07*MeV,
0.1*MeV,0.2*MeV,0.4*MeV,0.7*MeV,
1.*MeV,2.*MeV,4.*MeV,7.*MeV,10.*MeV,20.*MeV,
10000.0*MeV};
// corr. factors for e-/e+ lambda
G4double celectron[15][23] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087,0.7235 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082,0.7925 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098,0.9147 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098,0.9700 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056,1.0022 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052,1.0158 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050,1.0284 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036,1.0515 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024,1.0834 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020,1.0937 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011,1.1140 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987,1.1410 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963,1.1750 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954,1.1922 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, // paper.....
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949,1.2026 }};
G4double cpositron[15][23] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100,0.7235 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102,0.7925 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145,0.9147 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174,0.9700 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151,1.0022 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159,1.0158 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170,1.0284 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179,1.0515 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205,1.0834 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214,1.0937 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233,1.1140 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239,1.1410 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258,1.1750 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272,1.1922 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282,1.2026 }};
G4double sigma;
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
G4double ParticleMass = aParticleType.GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/ParticleMass ;
G4double c = ParticleMass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
KineticEnergy = electron_mass_c2*tau ;
}
G4double Charge = aParticleType.GetPDGCharge();
G4double ChargeSquare = Charge*Charge/(eplus*eplus);
G4double TotalEnergy = KineticEnergy + electron_mass_c2 ;
G4double beta2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
/(TotalEnergy*TotalEnergy);
G4double bg2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
/(electron_mass_c2*electron_mass_c2);
G4double eps = epsfactor*bg2/Z23;
if (eps<epsmin) sigma = 2.*eps*eps;
else if(eps<epsmax) sigma = log(1.+2.*eps)-2.*eps/(1.+2.*eps);
else sigma = log(2.*eps)-1.+1./eps;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/(beta2*bg2);
// nuclear size effect correction for high energy
// ( a simple approximation at present)
G4double corrnuclsize,a,x0,w1,w2,w;
x0 = 1. - NuclCorrPar*ParticleMass/(KineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( (x0 < -1.) || (KineticEnergy <= 10.*MeV))
{ x0 = -1.; corrnuclsize = 1.;}
else
{ a = 1.+1./eps;
if (eps > epsmax) w1=log(2.*eps)+1./eps-3./(8.*eps*eps);
else w1=log((a+1.)/(a-1.))-2./(a+1.);
w = 1./((1.-x0)*eps);
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber)) iZ -= 1;
if (iZ==14) iZ = 13;
if (iZ==-1) iZ = 0 ;
G4double Z1 = Zdat[iZ];
G4double Z2 = Zdat[iZ+1];
G4double ratZ = (AtomicNumber-Z1)/(Z2-Z1);
// get bin number in T (beta2)
G4int iT = 22;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy)) iT -= 1;
if(iT==22) iT = 21;
if(iT==-1) iT = 0 ;
// calculate betasquare values
G4double T = Tdat[iT], E = T + electron_mass_c2;
G4double b2small = T*(E+electron_mass_c2)/(E*E);
T = Tdat[iT+1]; E = T + electron_mass_c2;
G4double b2big = T*(E+electron_mass_c2)/(E*E);
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double c1,c2,cc1,cc2,corr;
if (Charge < 0.)
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = celectron[iZ][iT+1];
c2 = celectron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
if (Charge > 0.)
{
c1 = cpositron[iZ][iT];
c2 = cpositron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = cpositron[iZ][iT+1];
c2 = cpositron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
// nucl. size correction for particles other than e+/e- only at present !!!!
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
sigma /= corrnuclsize;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength;
const G4DynamicParticle* aParticle;
G4Material* aMaterial;
G4double KineticEnergy,tau,z0,kz;
G4bool isOut;
G4LossTableManager* theManager = G4LossTableManager::Instance();
// this process is not a candidate for selection by default
valueGPILSelectionMSC = NotCandidateForSelection;
tPathLength = currentMinimumStep;
aMaterial = track.GetMaterial();
materialIndex = aMaterial->GetIndex();
aParticle = track.GetDynamicParticle();
KineticEnergy = aParticle->GetKineticEnergy();
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
range = theManager->GetRange(aParticle->GetDefinition(),
KineticEnergy,aMaterial);
// special treatment near boundaries ?
if (boundary)
{
// step limitation at boundary ?
stepno = track.GetCurrentStepNumber() ;
if(stepno == 1)
{
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
// if : diff.treatment for small/not small Z
if(range > fTransportMeanFreePath)
tlimit = facrange*range ;
else
tlimit = facrange*fTransportMeanFreePath ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
laststep = tlimit ;
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
else if(stepno > stepnolastmsc)
{
if((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
}
}
// do the true -> geom transformation
lambda1 = -1.;
z1 = 1.e10 ;
tau = tPathLength/fTransportMeanFreePath ;
if(tau < tausmall) zPathLength = tPathLength;
else
{
if(tPathLength/range < dtrl) zmean = fTransportMeanFreePath*(1.-exp(-tau));
else
{
T1 = theManager->GetEnergy(
aParticle->GetDefinition(),range-0.5*tPathLength,aMaterial);
lambda1 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T1,isOut);
z1 = fTransportMeanFreePath*(1.-exp(-0.5*tau));
cth1 = exp(-0.5*tau);
zmean = z1 + lambda1*(1.-exp(-0.5*tPathLength/lambda1))*cth1;
}
// sample z
if ((pcz > 0.) && (2.*zmean > tPathLength))
{
z0 = zmean+pcz*(tPathLength-zmean);
kz = (2.*zmean-tPathLength)/(z0-zmean)+1.;
if (G4UniformRand() < z0/tPathLength)
zPathLength = z0*exp(log(G4UniformRand())/kz);
else zPathLength = tPathLength-(tPathLength-z0)
*exp(log(1.-G4UniformRand())/kz);
}
else
{
zPathLength = zmean;
}
}
tLast = tPathLength;
zLast = zPathLength;
return zPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScatteringSTD::AlongStepDoIt(
const G4Track& track,const G4Step& Step)
{
// only a geom path->true path transformation is performed
fParticleChange.Initialize(track);
G4double geomPathLength = track.GetStepLength();
G4double truePathLength;
if (geomPathLength/fTransportMeanFreePath < tausmall)
truePathLength = geomPathLength;
else if(geomPathLength == zLast) truePathLength = tLast;
else
{
if (geomPathLength <= z1)
{
if (geomPathLength < fTransportMeanFreePath)
truePathLength = -fTransportMeanFreePath
*log(1.-geomPathLength/fTransportMeanFreePath);
else truePathLength = range;
lambda1 = -1.;
}
else
{
if ((geomPathLength-z1)/(cth1*lambda1) < 1.)
truePathLength = 0.5*tLast-lambda1
*log(1.-(geomPathLength-z1)/(cth1*lambda1));
else truePathLength = range;
}
}
fParticleChange.SetTrueStepLength(truePathLength);
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
// angle distribution parameters
const G4double kappapl1 = kappa+1., kappami1 = kappa-1. ;
G4bool isOut;
fParticleChange.Initialize(trackData);
G4double truestep = stepData.GetStepLength();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double KineticEnergy = aParticle->GetKineticEnergy();
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
// change direction first ( scattering )
G4double cth =1 ;
G4double tau = truestep/fTransportMeanFreePath;
if(KineticEnergy <= 0.)
;
else
{
if (tau < tausmall) cth = 1.;
else if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
if(lambda1 > 0.) tau = 0.5*tLast/lambda1
+(truestep-0.5*tLast)/fTransportMeanFreePath;
if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double amax=25. ;
const G4double tau0 = 0.02 ;
const G4double b = 1. ;
G4double a,x0,c,xmean1,xmean2,
xmeanth,prob,qprob ;
G4double ea,eaa,b1,bx,eb1,ebx,cnorm1,cnorm2,f1x0,f2x0,w ;
w = log(tau/tau0) ;
if(tau < tau0)
a = (alfa1-alfa2*w)/tau ;
else
a = (alfa1+alfa3*w)/tau ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
b1 = b+1. ;
bx=b-x0 ;
eb1=exp((c-1.)*log(b1)) ;
ebx=exp((c-1.)*log(bx)) ;
xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
xmeanth = exp(-tau) ;
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
// protection against qprob > 1
// *******************************************
if(qprob > 1.)
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
// *******************************************
// sampling of costheta
if(G4UniformRand() < qprob)
{
if(G4UniformRand() < prob)
cth = 1.+log(ea+G4UniformRand()*eaa)/a ;
else
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
cth = -1.+2.*G4UniformRand() ;
}
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi), diry = sth*sin(phi), dirz = cth;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz);
newDirection.rotateUz(ParticleDirection);
fParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z());
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean, etau;
if (safetyminustolerance > 0.)
{
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6. ;
else
{
if(tau<taubig) etau = exp(-tau);
else etau = 0.;
rmean = -kappa*tau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += tau-kappapl1/kappa+kappa*etau/kappami1;
}
if (rmean>0.) rmean = 2.*fTransportMeanFreePath*sqrt(rmean/3.);
else rmean = 0.;
// for rmean > 0) only
if (rmean > 0.)
{
if (rmean>safetyminustolerance) rmean = safetyminustolerance;
// sample direction of lateral displacement
phi = twopi*G4UniformRand();
dirx = cos(phi); diry = sin(phi); dirz = 0.;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection);
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
navigator->LocateGlobalPointWithinVolume(newPosition);
fParticleChange.SetPositionChange(newPosition);
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4MultipleScatteringSTD::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if (!theTransportMeanFreePathTable->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 G4MultipleScatteringSTD::RetrievePhysicsTable(
G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theTransportMeanFreePathTable
if (theTransportMeanFreePathTable != 0) {
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
G4String filename;
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theTransportMeanFreePathTable =
new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if (!theTransportMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScatteringSTD::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
comments += "\n New model of MSC , computes the lateral \n";
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowestKineticEnergy ,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,190 @@
//
// ********************************************************************
// * 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: G4SCProcessorStand
//
// Author: Vladimir Ivanchenko
//
// Creation date: 10.05.2002
//
// Modifications: 09.12.2002 VI remove warning
//
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4SCProcessorStand.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4EmModelManager.hh"
#include "G4MaterialTable.hh"
#include "G4VEmModel.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4SCProcessorStand::G4SCProcessorStand()
: G4VSubCutoffProcessor(),
theLambdaSubTable(0),
thePositron(G4Positron::Positron()),
modelManager(0)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4SCProcessorStand::~G4SCProcessorStand()
{
if(theLambdaSubTable) theLambdaSubTable->clearAndDestroy();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4SCProcessorStand::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
G4EmModelManager* m)
{
particle = p;
secondaryParticle = sp;
modelManager = m;
navigator = (G4TransportationManager::GetTransportationManager())
->GetNavigatorForTracking();
theCuts = modelManager->Cuts();
theSubCuts = modelManager->Cuts();
initialMass= particle->GetPDGMass();
// Access to materials
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
rangeCuts.clear();
for(size_t i=0; i<nMaterials; i++) {
const G4Material* aMaterial = (*theMaterialTable)[i];
rangeCuts.push_back(secondaryParticle->GetRangeThreshold(aMaterial));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step,
const G4DynamicParticle* dp,
G4double meanLoss)
{
G4bool b;
const G4Material* mat = (step.GetTrack())->GetMaterial();
if(mat != material) {
material = mat;
materialIndex = material->GetIndex();
cut = (*theCuts)[materialIndex];
subcut = (*theSubCuts)[materialIndex];
rcut = rangeCuts[materialIndex];
}
if(subcut >= cut) return 0;
G4double ekin = dp->GetKineticEnergy();
G4double effChargeFactor = 1.0;
G4double massRatio = 1.0;
G4double mass = initialMass;
if(dp->GetDefinition() != particle) {
mass = dp->GetMass();
massRatio = initialMass/mass;
G4double q = particle->GetPDGCharge()/dp->GetCharge();
effChargeFactor = q*q;
}
G4double cross = (*theLambdaSubTable)[materialIndex]->GetValue(ekin*massRatio, b);
if(0.0 >= cross) return 0;
G4StepPoint* pre = step.GetPreStepPoint();
G4double presafety = pre->GetSafety();
G4ThreeVector postpoint = step.GetPostStepPoint()->GetPosition();
G4double postsafety = navigator->ComputeSafety(postpoint);
G4double safety = G4std::min(presafety,postsafety);
if(safety >= rcut) return 0;
G4ThreeVector prepoint = pre->GetPosition();
G4ThreeVector dr = postpoint - prepoint;
G4double pretime = step.GetPreStepPoint()->GetGlobalTime();
G4double fragment = 0.0;
G4double dt = 0.0;
G4double length = step.GetStepLength();
G4double inv_v = (ekin + mass)/(c_light*dp->GetTotalMomentum());
G4VEmModel* currentModel = modelManager->SelectModel(ekin);
G4std::vector<G4Track*>* vtr = new G4std::vector<G4Track*>;
do {
G4double del = G4UniformRand()*effChargeFactor / cross;
fragment += del/length;
if (fragment > 1.0) break;
dt += del * inv_v;
G4std::vector<G4DynamicParticle*>* newp =
currentModel->SampleSecondary(material, dp, subcut, cut);
if (newp) {
G4DynamicParticle* p;
G4int nNew = newp->size();
for (G4int i=0; i<nNew; i++) {
p = (*newp)[i];
G4double e = p->GetKineticEnergy();
if (p->GetDefinition() == thePositron) e += electron_mass_c2;
if (e <= meanLoss) {
meanLoss -= e;
G4Track* t = new G4Track(p, pretime + dt, prepoint + fragment*dr);
vtr->push_back(t);
} else {
delete p;
}
}
}
} while (fragment < 1.0);
return vtr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,321 @@
//
// ********************************************************************
// * 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: G4UniversalFluctuation
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4UniversalFluctuation.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4Step.hh"
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4UniversalFluctuation::G4UniversalFluctuation()
:G4VEmFluctuationModel(),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minLoss(0.000001*eV),
problim(0.01),
alim(10.),
nmaxCont1(4),
nmaxCont2(16)
{
lastMaterial = 0;
sumalim = -log(problim);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4UniversalFluctuation::~G4UniversalFluctuation()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4UniversalFluctuation::Initialise(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double meanLoss)
{
// calculate actual loss from the mean loss
// The model used to get the fluctuation is essentially the same
// as in Glandz in Geant3.
// shortcut for very very small loss
if(meanLoss < minLoss) return;
G4double preStepKinEnergy = dp->GetKineticEnergy();
if(dp->GetDefinition() != particle) {
particleMass = dp->GetMass();
G4double q = dp->GetCharge();
chargeSquare = q*q;
}
// data members for a given material
if(material != lastMaterial) {
ipotFluct = material->GetIonisation()->GetMeanExcitationEnergy();
electronDensity = material->GetElectronDensity();
// zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
}
// get particle data
G4double tau = preStepKinEnergy/particleMass;
G4double tau1 = tau + 1.0;
G4double tau2 = tau * (tau+2.0);
G4double beta2 = tau2/(tau1*tau1);
// Validity range for delta electron cross section
G4double loss, siga;
// Gaussian fluctuation
if(meanLoss >= minNumberInteractionsBohr*tmax || tmax <= ipotFluct*minNumberInteractionsBohr)
{
siga = tmax * (1.0-0.5*beta2) * length * twopi_mc2_rcl2
* electronDensity / beta2;
siga = sqrt(siga * chargeSquare);
/*
// High velocity or negatively charged particle
if( beta2 > 3.0*theBohrBeta2*zeff || charge < 0.0) {
siga = sqrt( siga * chargeSquare ) ;
// Low velocity - additional ion charge fluctuations according to
// Q.Yang et al., NIM B61(1991)149-155.
} else {
G4double chu = theIonChuFluctuationModel->TheValue(particle, material);
G4double yang = theIonYangFluctuationModel->TheValue(particle, material);
siga = sqrt( siga * (chargeSquare * chu + yang)) ;
}
*/
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0.);
meanLoss = loss;
if(lastMaterial != material) lastMaterial = material;
return;
}
// Non Gaussian fluctuation
if(material != lastMaterial) {
zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
f1Fluct = material->GetIonisation()->GetF1fluct();
f2Fluct = material->GetIonisation()->GetF2fluct();
e1Fluct = material->GetIonisation()->GetEnergy1fluct();
e2Fluct = material->GetIonisation()->GetEnergy2fluct();
e1LogFluct = material->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = material->GetIonisation()->GetLogEnergy2fluct();
rateFluct = material->GetIonisation()->GetRateionexcfluct();
ipotLogFluct= material->GetIonisation()->GetLogMeanExcEnergy();
lastMaterial = material;
}
G4double suma,w1,w2,C,e0,lossc,w;
G4double a1,a2,a3;
G4int p1,p2,p3;
G4int nb;
G4double corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
G4double dp3;
w1 = tmax/ipotFluct;
w2 = log(2.*electron_mass_c2*tau2);
C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
a3 = rateFluct*meanLoss*(tmax-ipotFluct)/(ipotFluct*tmax*log(w1));
if(a1 < 0.) a1 = 0.;
if(a2 < 0.) a2 = 0.;
if(a3 < 0.) a3 = 0.;
suma = a1+a2+a3;
loss = 0. ;
if(suma < sumalim) // very small Step
{
e0 = material->GetIonisation()->GetEnergy0fluct();
if(tmax == ipotFluct)
{
a3 = meanLoss/e0;
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
loss = p3*e0 ;
if(p3 > 0)
loss += (1.-2.*G4UniformRand())*e0 ;
}
else
{
tmax = tmax-ipotFluct+e0 ;
a3 = meanLoss*(tmax-e0)/(tmax*e0*log(tmax/e0));
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
if(p3 > 0)
{
w = (tmax-e0)/tmax ;
if(p3 > nmaxCont2)
{
dp3 = G4float(p3) ;
corrfac = dp3/G4float(nmaxCont2) ;
p3 = nmaxCont2 ;
}
else
corrfac = 1. ;
for(G4int i=0; i<p3; i++) loss += 1./(1.-w*G4UniformRand()) ;
loss *= e0*corrfac ;
}
}
}
else // not so small Step
{
// excitation type 1
if(a1>alim)
{
siga=sqrt(a1) ;
p1 = G4std::max(0,int(G4RandGauss::shoot(a1,siga)+0.5));
}
else
p1 = G4Poisson(a1);
// excitation type 2
if(a2>alim)
{
siga=sqrt(a2) ;
p2 = G4std::max(0,int(G4RandGauss::shoot(a2,siga)+0.5));
}
else
p2 = G4Poisson(a2);
loss = p1*e1Fluct+p2*e2Fluct;
// smearing to avoid unphysical peaks
if(p2 > 0)
loss += (1.-2.*G4UniformRand())*e2Fluct;
else if (loss>0.)
loss += (1.-2.*G4UniformRand())*e1Fluct;
// ionisation .......................................
if(a3 > 0.)
{
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
lossc = 0.;
if(p3 > 0)
{
na = 0.;
alfa = 1.;
if (p3 > nmaxCont2)
{
dp3 = G4float(p3);
rfac = dp3/(G4float(nmaxCont2)+dp3);
namean = G4float(p3)*rfac;
sa = G4float(nmaxCont1)*rfac;
na = G4RandGauss::shoot(namean,sa);
if (na > 0.)
{
alfa = w1*G4float(nmaxCont2+p3)/
(w1*G4float(nmaxCont2)+G4float(p3));
alfa1 = alfa*log(alfa)/(alfa-1.);
ea = na*ipotFluct*alfa1;
sea = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
lossc += G4RandGauss::shoot(ea,sea);
}
}
nb = G4int(G4float(p3)-na);
if (nb > 0)
{
w2 = alfa*ipotFluct;
w = (tmax-w2)/tmax;
for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
}
}
loss += lossc;
}
}
meanLoss = loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VEnergyLoss.cc,v 1.32 2002/02/26 12:21:51 maire Exp $
// GEANT4 tag $Name: geant4-04-01 $
// $Id: G4VEnergyLoss.cc,v 1.33 2002/07/22 10:55:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
//
// --------------------------------------------------------------
@@ -39,6 +39,8 @@
// 11.02.02 subSecFlag = false --> No sucutoff generation (mma)
// 14.02.02 initial value of data member finalRange has been changed L.Urban
// 26.02.02 initial value of data member finalRange = 1 mm (mma)
// 21.07.02 V.Ivanchenko Fix at low energies - if tmax below ionisation
// potential then only Gaussian fluctuations are sampled.
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -948,22 +950,22 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
if(Tm > threshold) Tm = threshold;
beta2 = tau2/(tau1*tau1);
// Gaussian fluctuation ?
if(MeanLoss >= kappa*Tm)
if(MeanLoss >= kappa*Tm || Tm < kappa*ipotFluct)
{
electronDensity = aMaterial->GetElectronDensity() ;
siga = sqrt(Tm*(1.0-0.5*beta2)*step*
factor*electronDensity*ChargeSquare/beta2) ;
loss = G4RandGauss::shoot(MeanLoss,siga) ;
if(loss < 0.) loss = 0. ;
return loss ;
do {
loss = G4RandGauss::shoot(MeanLoss,siga) ;
} while (loss < 0. || loss > 2.*MeanLoss);
return loss;
}
if (Tm <= ipotFluct) Tm = ipotFluct ;
if(Tm > threshold) Tm = threshold;
w1 = Tm/ipotFluct;
w2 = log(2.*electron_mass_c2*tau2);
@@ -971,14 +973,10 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
if(Tm > ipotFluct)
a3 = rateFluct*MeanLoss*(Tm-ipotFluct)/(ipotFluct*Tm*log(w1));
else
{
a1 /= 1.-rateFluct ;
a2 /= 1.-rateFluct ;
a3 = 0. ;
}
a3 = rateFluct*MeanLoss*(Tm-ipotFluct)/(ipotFluct*Tm*log(w1));
if(a1 < 0.) a1 = 0.;
if(a2 < 0.) a2 = 0.;
if(a3 < 0.) a3 = 0.;
suma = a1+a2+a3;
@@ -0,0 +1,915 @@
//
// ********************************************************************
// * 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: G4VEnergyLossSTD
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications: 13.11.2002 Minor fix - use normalised direction (VI)
// 04.12.2002 Minor change in PostStepDoIt (VI)
//
// Class Description:
//
// It is the unified energy loss process it calculates the continuous
// energy loss for charged particles using a set of Energy Loss
// models valid for different energy regions. There are a possibility
// to create and access to dE/dx and range tables, or to calculate
// that information on fly.
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VEnergyLossSTD.hh"
#include "G4LossTableManager.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4VEmFluctuationModel.hh"
#include "G4DataVector.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsVector.hh"
#include "G4PhysicsLogVector.hh"
#include "G4VParticleChange.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4VSubCutoffProcessor.hh"
#include "G4ProcessManager.hh"
#include "G4UnitsTable.hh"
#include "G4Proton.hh"
#include "G4GenericIon.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEnergyLossSTD::G4VEnergyLossSTD(const G4String& name, G4ProcessType type):
G4VContinuousDiscreteProcess(name, type),
subCutoffProcessor(0),
emFluctModel(0),
theDEDXTable(0),
theRangeTable(0),
theSecondaryRangeTable(0),
theInverseRangeTable(0),
theLambdaTable(0),
minKinEnergy(1.0*eV),
maxKinEnergy(100.0*GeV),
particle(0),
baseParticle(0),
secondaryParticle(0),
theGamma(G4Gamma::Gamma()),
theElectron(G4Electron::Electron()),
lossFluctuationFlag(false),
subCutoffFlag(false),
subCutoffIsDesired(false),
rndmStepFlag(false),
hasRestProcess(true),
tablesAreBuilt(false),
integral(true),
linLossLimit(0.05),
minSubRange(0.1)
{
modelManager = new G4EmModelManager();
(G4LossTableManager::Instance())->Register(this);
// default dRoverRange and finalRange
SetStepLimits(0.2, 200.0*micrometer);
verboseLevel = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEnergyLossSTD::~G4VEnergyLossSTD()
{
Clear();
if(theLambdaTable) theLambdaTable->clearAndDestroy();
if(subCutoffProcessor) delete subCutoffProcessor;
delete modelManager;
if(emFluctModel) delete emFluctModel;
(G4LossTableManager::Instance())->Clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::Clear()
{
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::Clear() for " << GetProcessName() << G4endl;
}
theDEDXTable = 0;
theRangeTable = 0;
theInverseRangeTable = 0;
theSecondaryRangeTable = 0;
modelManager->Clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::Initialise()
{
Clear();
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::Initialise() for "
<< GetProcessName() << G4endl;
}
G4double initialCharge = particle->GetPDGCharge();
G4double initialMass = particle->GetPDGMass();
chargeSquare = initialCharge*initialCharge/(eplus*eplus);
chargeSqRatio = 1.0;
massRatio = 1.0;
reduceFactor = 1.0;
if(particle->GetProcessManager()->GetAtRestProcessVector()->size())
hasRestProcess = true;
else hasRestProcess = false;
if (baseParticle) {
massRatio = (baseParticle->GetPDGMass())/initialMass;
G4double q = initialCharge/baseParticle->GetPDGCharge();
chargeSqRatio = q*q;
reduceFactor = 1.0/(chargeSqRatio*massRatio);
}
theCuts = modelManager->Initialise(particle, secondaryParticle, minSubRange, verboseLevel);
if(1 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::Initialise(): emFluctModel= " << emFluctModel
<< " subCutoffFlag= " << subCutoffFlag
<< G4endl;
}
if(emFluctModel) emFluctModel->Initialise(particle);
if (subCutoffFlag) {
subCutoffProcessor->Initialise(particle, secondaryParticle, modelManager);
}
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::Initialise() is done "
<< " chargeSqRatio= " << chargeSqRatio
<< " massRatio= " << massRatio
<< " reduceFactor= " << reduceFactor
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::BuildPhysicsTable(const G4ParticleDefinition& part)
{
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::BuildPhysicsTable() for "
<< GetProcessName() << G4endl;
}
tablesAreBuilt = false;
// Are particle defined?
if(!particle || particle->GetParticleType() == "nucleus") {
particle = &part;
}
if(particle != &part) {
G4cout << "G4VEnergyLossSTD::BuildPhysicsTable: "
<< particle->GetParticleName()
<< " != " << part.GetParticleName()
<< G4endl;
G4Exception("G4VEnergyLossSTD::BuildPhysicsTable with wrong G4ParticleDefinition");
}
if(!baseParticle) baseParticle = DefineBaseParticle(particle);
if(particle->GetParticleType() == "nucleus" &&
particle->GetParticleName() != "GenericIon" &&
theLambdaTable) return;
// It is responsability of the G4LossTables to build DEDX and range tables
(G4LossTableManager::Instance())->BuildDEDXTable(particle);
// Access to materials
//const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
//!!!! To be checked because finalRange is changed here !!!!
for (size_t i=0; i<nMaterials; i++) {
G4double lengthCut = (G4Electron::Electron()->GetLengthCuts())[i];
if (finalRange > lengthCut) finalRange = lengthCut;
}
if(theLambdaTable) theLambdaTable->clearAndDestroy();
theLambdaTable = BuildLambdaTable();
if (subCutoffFlag) {
subCutoffProcessor->SetLambdaSubTable(BuildLambdaSubTable());
}
tablesAreBuilt = true;
// if(particle == G4Electron::Electron() || particle == G4Proton::Proton()
// || particle == G4GenericIon::GenericIon())
if(!baseParticle) PrintInfoDefinition();
if(0 < verboseLevel) {
G4cout << "Tables are built for " << particle->GetParticleName()
<< " Integral= " << integral
<< G4endl;
if(2 < verboseLevel) {
G4cout << "DEDXTable address= " << theDEDXTable << G4endl;
if(theDEDXTable) G4cout << (*theDEDXTable) << G4endl;
G4cout << "RangeTable address= " << theRangeTable << G4endl;
if(theRangeTable) G4cout << (*theRangeTable) << G4endl;
G4cout << "InverseRangeTable address= " << theInverseRangeTable << G4endl;
if(theInverseRangeTable) G4cout << (*theInverseRangeTable) << G4endl;
}
}
if(2 < verboseLevel) {
G4cout << "LambdaTable address= " << theLambdaTable << G4endl;
if(theLambdaTable) G4cout << (*theLambdaTable) << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4VEnergyLossSTD::StorePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
G4String filename;
if (!baseParticle) {
G4String f1 = GetPhysicsTableFileName(part,directory,"DEDX",ascii);
G4String f2 = GetPhysicsTableFileName(part,directory,"Range",ascii);
G4String f3 = GetPhysicsTableFileName(part,directory,"InverseRange",ascii);
if(!((G4LossTableManager::Instance())->StorePhysicsTable(this,f1,f2,f3,ascii)))
{
return false;
}
}
if (theLambdaTable) {
filename = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
if ( !theLambdaTable->StorePhysicsTable(filename, ascii) ){
G4cout << "Fatal error theLambdaTable->StorePhysicsTable in <"
<< filename << ">"
<< G4endl;
return false;
}
}
G4PhysicsTable* theLambdaSubTable = 0;
if(subCutoffProcessor) theLambdaSubTable = subCutoffProcessor->LambdaSubTable();
if (theLambdaSubTable) {
filename = GetPhysicsTableFileName(part,directory,"LambdaSub",ascii);
if ( !theLambdaSubTable->StorePhysicsTable(filename, ascii) ){
G4cout << "Fatal error theLambdaSubTable->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 G4VEnergyLossSTD::RetrievePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
// Are particle defined?
if(!particle) {
particle = part;
}
if(particle != part) {
G4cout << "G4VEnergyLossSTD::RetrievePhysicsTable: "
<< particle->GetParticleName()
<< " != " << part->GetParticleName()
<< G4endl;
G4Exception("G4VEnergyLossSTD::RetrievePhysicsTable with wrong G4ParticleDefinition");
}
Initialise();
G4PhysicsTable* theTable;
G4String filename;
G4String particleName = particle->GetParticleName();
G4int nMaterials = G4Material::GetNumberOfMaterials();
filename = GetPhysicsTableFileName(part,directory,"DEDX",ascii);
theTable = new G4PhysicsTable(nMaterials);
if (theTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << "DEDX table for " << particleName << " is retrieved from <"
<< filename << ">"
<< G4endl;
} else {
G4cout << "DEDX table for " << particleName << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
theDEDXTable = theTable;
filename = GetPhysicsTableFileName(part,directory,"Range",ascii);
theTable = new G4PhysicsTable(nMaterials);
if (theTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << "Range table for " << particleName << " is retrieved from <"
<< filename << ">"
<< G4endl;
} else {
G4cout << "Range table for " << particleName << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
theRangeTable = theTable;
filename = GetPhysicsTableFileName(part,directory,"InverseRange",ascii);
theTable = new G4PhysicsTable(nMaterials);
if (theTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << "Inverse table for " << particleName << " is retrieved from <"
<< filename << ">"
<< G4endl;
return false;
}
theInverseRangeTable = theTable;
filename = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
theLambdaTable = new G4PhysicsTable(nMaterials);
if (theLambdaTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << "Lambda table for " << particleName << " is retrieved from <"
<< filename << ">"
<< G4endl;
} else {
G4cout << "Lambda table for " << particleName << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
G4PhysicsTable* theLambdaSubTable = 0;
filename = GetPhysicsTableFileName(part,directory,"LambdaSub",ascii);
theLambdaSubTable = new G4PhysicsTable(nMaterials);
if (theLambdaSubTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << "LambdaSub table for " << particleName << " is retrieved from <"
<< filename << ">"
<< G4endl;
if(subCutoffProcessor) subCutoffProcessor->SetLambdaSubTable(theLambdaSubTable);
} else {
G4cout << "LambdaSub table for " << particleName << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
// G4LossTableManager manages DEDX and range tables
(G4LossTableManager::Instance())->RetrieveDEDXTable(particle, this);
G4cout << GetProcessName() << " for " << particleName
<< ": end of retrieving PhysicsTables from directory <"
<< directory << ">" << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::SetParticles(const G4ParticleDefinition* p1,
const G4ParticleDefinition* p2,
const G4ParticleDefinition* p3)
{
particle = p1;
baseParticle = p2;
secondaryParticle = p3;
G4bool yes = false;
if(particle) yes = particle->GetPDGCharge();
if(baseParticle) {
if(!baseParticle->GetPDGCharge()) yes = false;
else {
if((particle->GetPDGMass() < MeV &&
baseParticle->GetPDGMass() > MeV) ||
(particle->GetPDGMass() > MeV &&
baseParticle->GetPDGMass() < MeV)) yes = false;
}
}
if(!yes) {
G4cout << "Warning in G4VEnergyLossSTD::SetParticle: "
<< particle->GetParticleName()
<< " losses cannot be obtained from "
<< baseParticle->GetParticleName()
<< " losses" << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::AddEmModel(G4VEmModel* p, G4int order)
{
modelManager->AddEmModel(p, order);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::AddEmFluctuationModel(G4VEmFluctuationModel* p)
{
if(emFluctModel) delete emFluctModel;
emFluctModel = p;
if(p) lossFluctuationFlag = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4VEnergyLossSTD::BuildDEDXTable()
{
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::BuildDEDXTable() for "
<< GetProcessName()
<< " and particle " << particle->GetParticleName()
<< G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
G4DataVector dedxHigh;
// Access to materials
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
G4PhysicsTable* theTable = new G4PhysicsTable(nMaterials);
if(0 < verboseLevel) {
G4cout << nMaterials << " materials"
<< " minKinEnergy= " << minKinEnergy
<< " maxKinEnergy= " << maxKinEnergy
<< G4endl;
}
for(size_t i=0; i<nMaterials; i++) {
// create physics vector and fill it
const G4Material* material = (*theMaterialTable)[i];
G4PhysicsVector* aVector = DEDXPhysicsVector(material);
modelManager->FillDEDXVector(aVector, material);
// Insert vector for this material into the table
theTable->insert(aVector) ;
}
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::BuildDEDXTable(): table is built" << G4endl;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4VEnergyLossSTD::BuildLambdaTable()
{
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< particle->GetParticleName()
<< G4endl;
}
// Access to materials
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int nMaterials = G4Material::GetNumberOfMaterials();
G4PhysicsTable* theTable = new G4PhysicsTable(nMaterials);
for(G4int i=0; i<nMaterials; i++) {
// create physics vector and fill it
const G4Material* material = (*theMaterialTable)[i];
G4PhysicsVector* aVector = LambdaPhysicsVector(material);
modelManager->FillLambdaVector(aVector, material);
// Insert vector for this material into the table
theTable->insert(aVector) ;
}
if(1 < verboseLevel) {
G4cout << "Lambda table is built" << G4endl;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4VEnergyLossSTD::BuildLambdaSubTable()
{
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::BuildLambdaSubTable() for process "
<< GetProcessName() << " and particle "
<< particle->GetParticleName() << G4endl;
}
// Access to materials
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
G4PhysicsTable* theTable = new G4PhysicsTable(nMaterials);
for(size_t i=0; i<nMaterials; i++) {
// create physics vector and fill it
const G4Material* material = (*theMaterialTable)[i];
G4PhysicsVector* aVector = SubLambdaPhysicsVector(material);
modelManager->FillSubLambdaVector(aVector, material);
// Insert vector for this material into the table
theTable->insert(aVector) ;
}
if(1 < verboseLevel) {
G4cout << "Table is built" << G4endl;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VEnergyLossSTD::AlongStepDoIt(const G4Track& track,
const G4Step& step)
{
aParticleChange.Initialize(track);
// The process has range table - calculate energy loss
if(!theRangeTable) return &aParticleChange;
// Get the actual (true) Step length
G4double length = step.GetStepLength();
G4double eloss = 0.0;
G4bool b;
G4double finalT = preStepKinEnergy;
/*
if(-1 < verboseLevel) {
G4cout << "AlongStepDoIt for "
<< GetProcessName() << " and particle "
<< particle->GetParticleName()
<< " eScaled(MeV)= " << finalT/MeV
<< " slim(mm)= " << fRange/mm
<< " s(mm)= " << length/mm
<< G4endl;
}
*/
static const G4double faclow = 1.5;
// low energy deposit case
if (finalT < minKinEnergy || length >= fRange) {
eloss = finalT;
} else if(finalT < faclow*minKinEnergy) {
eloss = finalT*sqrt(length/fRange);
// Short step
} else if( length <= linLossLimit * fRange ) {
eloss = (((*theDEDXTable)[currentMaterialIndex])->
GetValue(preStepScaledEnergy, b))*length*chargeSqRatio;
// Long step
} else {
G4double x = (fRange-length)/reduceFactor;
G4PhysicsVector* v = (*theInverseRangeTable)[currentMaterialIndex];
G4double postStepScaledEnergy = v->GetValue(x, b);
eloss = (preStepScaledEnergy - postStepScaledEnergy)/massRatio;
/*
if(-1 < verboseLevel) {
G4cout << "fRange(mm)= " << fRange/mm
<< " xPost(mm)= " << x/mm
<< " ePre(MeV)= " << preStepScaledEnergy/MeV
<< " ePost(MeV)= " << postStepScaledEnergy/MeV
<< " eloss(MeV)= " << eloss/MeV
<< " eloss0(MeV)= " << (((*theDEDXTable)[currentMaterialIndex])->
GetValue(preStepScaledEnergy, b))*length*chargeSqRatio
<< G4endl;
}
*/
if(eloss < 0.0) eloss = 0.0;
}
//
if(eloss > finalT) eloss = finalT;
const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
// Sub cutoff generation
if(subCutoffFlag) {
G4std::vector<G4Track*>* newp = subCutoffProcessor->
SampleSecondary(step, dynParticle, eloss);
if(newp) {
G4ThreeVector finalP = dynParticle->GetMomentum();
G4int n = newp->size();
if(n > 0) {
aParticleChange.SetNumberOfSecondaries(n);
G4Track* t;
G4double e;
for (G4int i=0; i<n; i++) {
t = (*newp)[i];
e = t->GetKineticEnergy();
const G4ParticleDefinition* pd = t->GetDefinition();
if (pd != theGamma && pd != theElectron ) e += pd->GetPDGMass();
finalT -= e;
finalP -= t->GetMomentum();
aParticleChange.AddSecondary(t);
}
finalP = finalP.unit();
aParticleChange.SetMomentumChange(finalP);
}
delete newp;
}
}
// Sample fluctuations
if (lossFluctuationFlag && eloss + minKinEnergy > finalT) {
G4double tmax = MaxSecondaryEnergy(dynParticle);
tmax = G4std::min(tmax,(*theCuts)[currentMaterialIndex]);
emFluctModel->SampleFluctuations(currentMaterial, dynParticle,
tmax, length, eloss);
}
/*
if(1 < verboseLevel) {
G4cout << "eloss(MeV)= " << eloss/MeV
<< " currentChargeSquare= " << chargeSquare
<< G4endl;
}
*/
finalT -= eloss;
// G4cout << "finalT= " << finalT << G4endl;
if (finalT < minKinEnergy) {
eloss += finalT;
finalT = 0.0;
// !!!! to be checked - problem of Forced processes
if (hasRestProcess) aParticleChange.SetStatusChange(fStopButAlive);
else aParticleChange.SetStatusChange(fStopAndKill);
}
aParticleChange.SetEnergyChange(finalT);
aParticleChange.SetLocalEnergyDeposit(eloss);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VEnergyLossSTD::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
aParticleChange.Initialize(track);
G4double finalT = track.GetKineticEnergy();
// Integral approach
if(integral) {
G4bool b;
G4double postStepLambda =
(((*theLambdaTable)[currentMaterialIndex])->GetValue(finalT,b))*chargeSqRatio;
if(preStepLambda*G4UniformRand() > postStepLambda)
return G4VContinuousDiscreteProcess::PostStepDoIt(track,step);
}
G4VEmModel* currentModel = modelManager->SelectModel(finalT);
G4double tcut = (*theCuts)[currentMaterialIndex];
const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
if(0 < verboseLevel) {
const G4ParticleDefinition* pd = dynParticle->GetDefinition();
G4cout << "G4VEnergyLossSTD::PostStepDoIt: Sample secondary; E= " << finalT/MeV
<< " MeV; model= (" << currentModel->LowEnergyLimit(pd, currentMaterial)
<< ", " << currentModel->HighEnergyLimit(pd, currentMaterial) << ")"
<< G4endl;
}
G4std::vector<G4DynamicParticle*>* newp =
currentModel->SampleSecondary(currentMaterial, dynParticle, tcut, finalT);
if (newp) {
G4int n = newp->size();
G4ThreeVector finalP = dynParticle->GetMomentum();
G4DynamicParticle* dp;
G4double e;
aParticleChange.SetNumberOfSecondaries(n);
for (G4int i=0; i<n; i++) {
dp = (*newp)[i];
e = dp->GetKineticEnergy();
if (dp->GetDefinition() != theElectron ) e += dp->GetMass();
finalT -= e;
finalP -= dp->GetMomentum();
aParticleChange.AddSecondary(dp);
}
if (finalT < minKinEnergy) {
aParticleChange.SetLocalEnergyDeposit(finalT);
finalT = 0.0;
// !!!! to be checked - problem of Forced processes
if (hasRestProcess) aParticleChange.SetStatusChange(fStopButAlive);
else aParticleChange.SetStatusChange(fStopAndKill);
}
aParticleChange.SetEnergyChange(finalT);
finalP = finalP.unit();
aParticleChange.SetMomentumChange(finalP);
delete newp;
}
return G4VContinuousDiscreteProcess::PostStepDoIt(track,step);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::PrintInfoDefinition() const
{
G4cout << G4endl << GetProcessName() << ": " << G4endl
<< " dE/dx and range tables from "
<< G4BestUnit(MinKinEnergy(),"Energy")
<< " to " << G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << DEDXBinning() << " bins." << G4endl
<< " Lambda tables from threshold to "
<< G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << LambdaBinning() << " bins."
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::SetDEDXTable(G4PhysicsTable* p)
{
if(theDEDXTable) delete theDEDXTable;
theDEDXTable = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::SetRangeTable(G4PhysicsTable* p)
{
if(theRangeTable) delete theRangeTable;
theRangeTable = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::SetSecondaryRangeTable(G4PhysicsTable* p)
{
if(theSecondaryRangeTable) delete theSecondaryRangeTable;
theSecondaryRangeTable = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::SetInverseRangeTable(G4PhysicsTable* p)
{
if(theInverseRangeTable) delete theInverseRangeTable;
theInverseRangeTable = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VEnergyLossSTD::DEDXPhysicsVector(const G4Material*)
{
return new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nDEDXBins);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VEnergyLossSTD::LambdaPhysicsVector(const G4Material* material)
{
G4PhysicsVector* v = 0;
G4double cut = (*theCuts)[material->GetIndex()];
if(cut > maxKinEnergy) {
v = new G4PhysicsLogVector(maxKinEnergy*0.5, maxKinEnergy, 2);
} else {
G4double tmin = G4std::max(MinPrimaryEnergy(particle, material, cut), minKinEnergy);
if(tmin >= maxKinEnergy) tmin = 0.5*maxKinEnergy;
v = new G4PhysicsLogVector(tmin, maxKinEnergy, nLambdaBins);
}
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VEnergyLossSTD::SubLambdaPhysicsVector(const G4Material* material)
{
G4PhysicsVector* v = 0;
G4double cut = (*theCuts)[material->GetIndex()];
if(cut > maxKinEnergy) {
v = new G4PhysicsLogVector(maxKinEnergy*0.5, maxKinEnergy, 2);
} else {
G4double tmin = G4std::max(MinPrimaryEnergy(particle, material, cut), minKinEnergy);
if(tmin >= maxKinEnergy) tmin = 0.5*maxKinEnergy;
v = new G4PhysicsLogVector(tmin, maxKinEnergy, nLambdaBins);
}
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::SetSubCutoffProcessor(G4VSubCutoffProcessor* p)
{
if(subCutoffProcessor) delete subCutoffProcessor;
subCutoffProcessor = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEnergyLossSTD::MicroscopicCrossSection(G4double kineticEnergy,
const G4Material* material)
{
// Cross section per atom is calculated
DefineMaterial(material);
G4double cross = 0.0;
G4bool b;
if(theLambdaTable) {
cross = (((*theLambdaTable)[currentMaterialIndex])->
GetValue(kineticEnergy, b));
cross /= material->GetTotNbOfAtomsPerVolume();
}
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEnergyLossSTD::MeanFreePath(const G4Track& track,
G4double s,
G4ForceCondition* cond)
{
return GetMeanFreePath(track, s, cond);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEnergyLossSTD::ContinuousStepLimit(const G4Track& track,
G4double x, G4double y, G4double& z)
{
return GetContinuousStepLimit(track, x, y, z);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....