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