Import Geant4 5.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 10:15:15 +02:00
parent 37fff30d2e
commit fbd4999cf7
4396 changed files with 56662 additions and 52446 deletions
@@ -29,10 +29,15 @@
// 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
// Modifications:
//
// 04-12-02 Fix problem of G4DynamicParticle constructor (V.Ivanchenko)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
@@ -47,13 +52,13 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p)
: G4VEmModel(),
G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),
particle(0),
highKinEnergy(100.*TeV),
lowKinEnergy(2.0*MeV),
twoln10(2.0*log(10.0)),
bg2lim(0.0169),
bg2lim(0.0169),
taulim(8.4146e-3)
{
if(p) SetParticle(p);
@@ -61,12 +66,12 @@ G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BetheBlochModel::~G4BetheBlochModel()
G4BetheBlochModel::~G4BetheBlochModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
{
particle = p;
mass = particle->GetPDGMass();
@@ -80,17 +85,15 @@ void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BetheBlochModel::HighEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return highKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return lowKinEnergy;
@@ -99,32 +102,39 @@ G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::MinEnergyCut(const G4ParticleDefinition* p,
const G4Material* material)
const G4MaterialCutsCouple* couple)
{
return material->GetIonisation()->GetMeanExcitationEnergy();
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BetheBlochModel::IsInCharge(const G4ParticleDefinition* p,
const G4Material*)
G4bool G4BetheBlochModel::IsInCharge(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BetheBlochModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
if(!particle) SetParticle(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::ComputeDEDX(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
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 gam = tau + 1.0;
G4double beta2 = 1. - 1./(gam*gam);
G4double bg2 = tau * (tau+2.0);
@@ -190,24 +200,23 @@ G4double G4BetheBlochModel::CrossSection(const G4Material* material,
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;
@@ -222,11 +231,11 @@ G4double G4BetheBlochModel::CrossSection(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondary(
const G4Material* material,
G4DynamicParticle* G4BetheBlochModel::SampleSecondary(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
@@ -253,7 +262,7 @@ G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondary(
}
G4double z, f;
// sampling follows ...
// sampling follows ...
do {
G4double q = G4UniformRand();
z = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
@@ -267,34 +276,48 @@ G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondary(
G4cout << "G4BetheBlochModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for x= " << z
<< G4endl;
<< G4endl;
}
} while( grej*G4UniformRand() > f );
G4double deltaKinEnergy = z * tmax;
G4double deltaMomentum =
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() ;
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);
return delta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,112 @@
//
// ********************************************************************
// * 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: G4BohrFluctuations
//
// Author: Vladimir Ivanchenko
//
// Creation date: 02.04.2003
//
// Modifications:
//
//
// Class Description: Sampling of Gaussion fluctuations
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BohrFluctuations.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BohrFluctuations::G4BohrFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
minNumberInteractionsBohr(10.0),
minFraction(0.2)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BohrFluctuations::~G4BohrFluctuations()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BohrFluctuations::Initialise(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BohrFluctuations::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
// Gaussian fluctuation
if (meanLoss >= minNumberInteractionsBohr*tmax) {
// Increase fluctuations for big fractional energy loss
if ( meanLoss > minFraction*kineticEnergy ) {
G4double gam = (kineticEnergy - meanLoss)/particleMass + 1.0;
G4double b2 = 1.0 - 1.0/(gam*gam);
G4double x = b2/beta2;
G4double x3 = 1.0/(x*x*x);
siga *= 0.25*(1.0 + x)*(x3 + (1.0/b2 - 0.5)/(1.0/beta2 - 0.5) );
}
siga = sqrt(siga);
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0. || loss > 2.*meanLoss);
// Poisson fluctuations
} else {
G4double navr = meanLoss*meanLoss/siga;
G4double n = (G4double)G4Poisson(navr);
loss = meanLoss*n/navr;
}
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -32,12 +32,17 @@
//
// Creation date: 03.01.2002
//
// Modifications: 04.12.2002 VI Fix problem of G4DynamicParticle constructor
// Modifications:
//
// Class Description:
// 04-12-02 Fix problem of G4DynamicParticle constructor (V.Ivanchenko)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
// Class Description:
//
// Implementation of energy loss and delta-electron production by
// slow charged heavy particles
// Implementation of energy loss and delta-electron production by
// slow charged heavy particles
// -------------------------------------------------------------------
//
@@ -52,8 +57,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BraggModel::G4BraggModel(const G4ParticleDefinition* p)
: G4VEmModel(),
G4BraggModel::G4BraggModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),
particle(0),
highKinEnergy(2.0*MeV),
lowKinEnergy(0.0*MeV),
@@ -66,12 +71,12 @@ G4BraggModel::G4BraggModel(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BraggModel::~G4BraggModel()
G4BraggModel::~G4BraggModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
{
particle = p;
mass = particle->GetPDGMass();
@@ -85,17 +90,15 @@ void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BraggModel::HighEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return highKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return lowKinEnergy;
@@ -104,27 +107,34 @@ G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::MinEnergyCut(const G4ParticleDefinition* p,
const G4Material* material)
const G4MaterialCutsCouple* couple)
{
return material->GetIonisation()->GetMeanExcitationEnergy();
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::IsInCharge(const G4ParticleDefinition* p,
const G4Material*)
G4bool G4BraggModel::IsInCharge(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BraggModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
if(!particle) SetParticle(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ComputeDEDX(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
G4double cutEnergy)
{
if(!particle) SetParticle(p);
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double dedx = DEDX(material, kineticEnergy/massRate);
@@ -133,20 +143,20 @@ G4double G4BraggModel::ComputeDEDX(const G4Material* material,
G4double x = cutEnergy/tmax;
G4double tau = kineticEnergy/mass;
G4double gam = tau + 1.0;
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
// 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;
return dedx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -155,9 +165,9 @@ G4double G4BraggModel::CrossSection(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxEnergy)
G4double maxEnergy)
{
if(!particle) SetParticle(p);
G4double cross = 0.0;
G4double tmax = G4std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
if(cutEnergy < tmax) {
@@ -177,11 +187,11 @@ G4double G4BraggModel::CrossSection(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
const G4Material* material,
G4DynamicParticle* G4BraggModel::SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
@@ -193,10 +203,10 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
G4double beta2 = 1. - mass*mass/(energy*energy);
G4double grej = 1.0 - beta2*xmin;
G4double z, f;
G4ThreeVector momentum = dp->GetMomentumDirection();
// sampling follows ...
// sampling follows ...
do {
G4double q = G4UniformRand();
z = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
@@ -207,21 +217,21 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
G4cout << "G4BraggModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for x= " << z
<< G4endl;
<< G4endl;
}
} while( grej*G4UniformRand() >= f );
G4double deltaKinEnergy = z * tmax;
G4double deltaMomentum =
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() ;
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
deltaDirection.rotateUz(momentum);
@@ -232,7 +242,19 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
delta->SetKineticEnergy(deltaKinEnergy);
delta->SetMomentumDirection(deltaDirection);
return delta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
return vdp;
@@ -240,7 +262,7 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::HasMaterial(const G4Material* material)
G4bool G4BraggModel::HasMaterial(const G4Material* material)
{
G4String chFormula = material->GetChemicalFormula() ;
G4String myFormula = G4String(" ") ;
@@ -251,10 +273,10 @@ G4bool G4BraggModel::HasMaterial(const G4Material* material)
}
// ICRU Report N49, 1993. Power's model for He.
const size_t numberOfMolecula = 11 ;
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",
"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" } ;
@@ -335,7 +357,7 @@ G4double G4BraggModel::StoppingPower(const G4Material* material,
}
return ionloss;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -655,7 +677,7 @@ G4double G4BraggModel::ChemicalFactor(G4double kineticEnergy,
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 ;
}
@@ -28,15 +28,23 @@
//
// File name: G4EmModelManager
//
// Author: Vladimir Ivanchenko
//
// Author: Vladimir Ivanchenko
//
// Creation date: 07.05.2002
//
// Modifications:
// Modifications:
//
// Class Description:
// 23-12-02 V.Ivanchenko change interface in order to move
// to cut per region
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 24-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 The set of models is defined for region (V.Ivanchenko)
// 06-03-03 Fix in energy intervals for models (V.Ivanchenko)
// 13-04-03 Add startFromNull (V.Ivanchenko)
//
// It is the unified energy loss process it calculates the continuous
// 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
@@ -45,41 +53,88 @@
//
//....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 "G4Gamma.hh"
#include "G4Positron.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4RegionStore.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::G4RegionModels(G4int nMod, G4std::vector<G4int>& list, G4DataVector& lowE)
{
nModelsForRegion = nMod;
theListOfModelIndexes = new G4int [nModelsForRegion];
lowKineticEnergy = new G4double [nModelsForRegion];
for (G4int i=0; i<nModelsForRegion; i++) {
theListOfModelIndexes[i] = list[i];
lowKineticEnergy[i] = lowE[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::~G4RegionModels()
{
delete [] theListOfModelIndexes;
delete [] lowKineticEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::G4EmModelManager():
nEmModels(0),
nmax(4),
orderIsChanged(false),
nRegions(0),
nCouples(0),
minSubRange(0.1),
particle(0)
particle(0),
verboseLevel(0)
{
verboseLevel = 0;
for(G4int i = 0; i<nmax; i++) {
emModels[i] = 0;
order[i] = 0;
upperEkin[i] = 0.0;
}
models.clear();
flucModels.clear();
regions.clear();
orderOfModels.clear();
upperEkin.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::~G4EmModelManager()
{
G4int i,j;
Clear();
for(G4int i = 0; i<nmax; i++) {
if(emModels[i]) delete emModels[i];
for(i = 0; i<nEmModels; i++) {
orderOfModels[i] = 1;
}
for(i = 0; i<nEmModels; i++) {
if (orderOfModels[i]) {
orderOfModels[i] = 0;
for(j = i+1; j<nEmModels; j++) {
if(models[i] == models[j]) orderOfModels[j] = 0;
}
delete models[i];
}
}
for(i = 0; i<nEmModels; i++) {
orderOfModels[i] = 1;
}
for(i = 0; i<nEmModels; i++) {
if (orderOfModels[i]) {
orderOfModels[i] = 0;
for(j = i+1; j<nEmModels; j++) {
if(flucModels[i] == flucModels[j]) orderOfModels[j] = 0;
}
delete flucModels[i];
}
}
}
@@ -93,18 +148,52 @@ void G4EmModelManager::Clear()
theCuts.clear();
theSubCuts.clear();
upperEkin.clear();
idxOfRegionModels.clear();
setOfRegionModels.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
void G4EmModelManager::AddEmModel(G4int num, G4VEmModel* p,
G4VEmFluctuationModel* fm, const G4Region* r)
{
if(!p) {
G4cout << "G4EmModelManager::AddEmModel WARNING: no model defined." << G4endl;
return;
}
models.push_back(p);
flucModels.push_back(fm);
regions.push_back(r);
orderOfModels.push_back(num);
if (nEmModels) {
G4int idx = nEmModels;
do {idx--;} while (idx && num < orderOfModels[idx]);
if (num >= orderOfModels[idx] && num <= orderOfModels[idx+1]) idx++;
if (idx < nEmModels) {
models[nEmModels] = models[idx];
flucModels[nEmModels] = flucModels[idx];
regions[nEmModels] = regions[idx];
orderOfModels[nEmModels] = orderOfModels[idx];
models[idx] = p;
flucModels[idx] = fm;
regions[idx] = r;
orderOfModels[idx] = num;
}
}
nEmModels++;
}
//....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");
G4Exception("G4EmModelManager::Initialise without any model defined");
}
particle = p;
secondaryParticle = sp;
@@ -112,188 +201,161 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
verboseLevel = val;
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< p->GetParticleName()
G4cout << "### G4EmModelManager::Initialise() for "
<< p->GetParticleName()
<< G4endl;
}
Clear();
// Ordering
if(orderIsChanged) {
G4int oldOrder[5];
G4VEmModel* oldEmModels[5];
for(G4int k = 0; k<nmax; k++) {
oldEmModels[k] = emModels[k];
oldOrder[k] = order[k];
}
G4RegionStore* regionStore = G4RegionStore::GetInstance();
const G4Region* world = regionStore->GetRegion("DefaultRegionForTheWorld", false);
// Identify the list of regions with different set of models
nRegions = 1;
G4std::vector<const G4Region*> set;
set.push_back(world);
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;
}
}
for (G4int ii=0; ii<nEmModels; ii++) {
const G4Region* r = regions[ii];
if ( r && r != world) {
G4bool newRegion = true;
if (nRegions>1) {
for (G4int j=1; j<nRegions; j++) {
if ( r == set[j] ) newRegion = false;
}
}
if (newRegion) {
set.push_back(r);
nRegions++;
}
emModels[ik] = oldEmModels[index];
order[ik] = ik;
oldEmModels[index] = 0;
}
orderIsChanged = false;
}
G4DataVector eLow;
eLow.clear();
setOfRegionModels.clear();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
idxOfRegionModels.resize(numOfCouples);
upperEkin.resize(nEmModels);
G4int n = 0;
// Order models for regions
for (G4int reg=0; reg<nRegions; reg++) {
for(G4int j=0; j<nEmModels; j++) {
const G4Region* region = set[reg];
G4double ep = 0.0;
if(0 < n) ep = upperEkin[n-1];
G4VEmModel* model = emModels[j];
G4bool accepted = false;
G4int n = 0;
if(model->IsInCharge(particle, 0)) {
G4std::vector<G4int> modelAtRegion;
G4DataVector eLow;
G4DataVector eHigh;
modelAtRegion.clear();
eLow.clear();
eHigh.clear();
G4double tmin = model->LowEnergyLimit(particle, 0);
G4double tmax = model->HighEnergyLimit(particle, 0);
for (G4int ii=0; ii<nEmModels; ii++) {
if(1 < verboseLevel) {
G4cout << "New model for tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< "; tlast(MeV)= " << ep/MeV
G4VEmModel* model = models[ii];
if ( (model->IsInCharge(particle)) &&
(0 == regions[ii] || region == regions[ii]) )
{
G4double tmin = model->LowEnergyLimit(particle);
G4double tmax = model->HighEnergyLimit(particle);
if (n) tmin = G4std::max(tmin, eHigh[n-1]);
if(1 < verboseLevel) {
G4cout << "Model # " << ii << " for region <"
<< region->GetName() << "> "
<< " tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/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;
if (tmin < tmax) {
modelAtRegion.push_back(ii);
eLow.push_back(tmin);
eHigh.push_back(tmax);
upperEkin[ii] = tmax;
n++;
}
} 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++;
eLow[0] = 0.0;
if(1 < verboseLevel) {
G4cout << "New G4RegionModels set with " << n << " models for region <"
<< region->GetName() << "> " << G4endl;
}
G4RegionModels* rm = new G4RegionModels(n, modelAtRegion, eLow);
setOfRegionModels.push_back(rm);
}
// Access to materials and build cuts
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
for(size_t i=0; i<numOfCouples; i++) {
for(size_t i=0; i<nMaterials; i++) {
const G4Material* material = (*theMaterialTable)[i];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ProductionCuts* pcuts = couple->GetProductionCuts();
G4int reg = nRegions;
do {reg--;} while (reg>0 && pcuts != (set[reg]->GetProductionCuts()));
idxOfRegionModels[i] = reg;
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
G4cout << "G4EmModelManager::Initialise() for "
<< material->GetName() << G4endl;
}
G4double cut = 0.0;
G4double subcut = 0.0;
if(secondaryParticle) {
cut = secondaryParticle->GetEnergyThreshold(material);
size_t idx = 1;
if( secondaryParticle == G4Gamma::Gamma() ) idx = 0;
cut = (*theCoupleTable->GetEnergyCutsVector(idx))[i];
subcut = minSubRange*cut;
}
for(G4int j=0; j<nEmModels; j++) {
G4int nm = setOfRegionModels[reg]->NumberOfModels();
for(G4int j=0; j<nm; j++) {
G4VEmModel* model = emModels[j];
if(upperEkin[j] > eLow[j]) {
G4VEmModel* model = models[setOfRegionModels[reg]->ModelIndex(j)];
G4double tcutmin = model->MinEnergyCut(particle, material);
G4double tcutmin = model->MinEnergyCut(particle, couple);
if(1 < verboseLevel) {
G4cout << "The model # " << j
<< "; tcutmin(MeV)= " << tcutmin/MeV
<< G4endl;
}
cut = G4std::max(cut, tcutmin);
subcut = G4std::max(subcut, tcutmin);
cut = G4std::max(cut, tcutmin);
G4double x = G4std::max(cut*minSubRange, tcutmin);
subcut = G4std::max(subcut, x);
if(1 < verboseLevel) {
G4cout << "The model # " << j
<< "; tcutmin(MeV)= " << tcutmin/MeV
<< "; tcut(MeV)= " << cut/MeV
<< G4endl;
}
}
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;
}
for(G4int jj=0; jj<nEmModels; jj++) {
models[jj]->Initialise(particle, theCuts);
if(flucModels[jj]) flucModels[jj]->Initialise(particle);
}
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()
G4cout << "G4EmModelManager is initialised "
<< G4endl;
}
return &theCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple)
{
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
@@ -301,42 +363,59 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
G4double e;
G4int i = material->GetIndex();
const G4Material* material = couple->GetMaterial();
size_t i = couple->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;
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< material->GetName()
<< " Ecut(MeV)= " << cut/MeV
<< G4endl;
}
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
dedxLow.resize(nmod);
dedxHigh.resize(nmod);
if(0 < verboseLevel) {
G4cout << "There are " << nmod << " models for "
<< material->GetName()
<< " at the region #" << reg
<< 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);
e = upperEkin[regModels->ModelIndex(0)];
dedxHigh[0] = models[regModels->ModelIndex(0)]->ComputeDEDX(material,particle,e,cut);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
if(nmod > 1) {
for(j=1; j<nmod; 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);
e = upperEkin[regModels->ModelIndex(j-1)];
dedxLow[j] = models[regModels->ModelIndex(j)]->ComputeDEDX(material,particle,e,cut);
e = upperEkin[regModels->ModelIndex(j)];
dedxHigh[j] = models[regModels->ModelIndex(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);
for(j=1; j<nmod; j++) {
if(dedxLow[j] > 0.0) factor[j] = (dedxHigh[j-1]/dedxLow[j] - 1.0);
else factor[j] = 0.0;
}
if(0 < verboseLevel) {
if(1 < verboseLevel) {
G4cout << "Loop over " << totBinsLoss << " bins start " << G4endl;
}
}
@@ -349,22 +428,21 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
// 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;
}
}
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e < upperEkin[regModels->ModelIndex(k)] );
}
G4double dedx = emModels[k]->ComputeDEDX(material,particle,e,cut)*fac;
G4double dedx = models[regModels->ModelIndex(k)]->ComputeDEDX(material,particle,e,cut)*fac;
if(dedx < 0.0) dedx = 0.0;
if(0 < verboseLevel) {
if(1 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< " fac= " << fac
<< G4endl;
}
aVector->PutValue(j, dedx);
@@ -374,16 +452,11 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple,
G4bool startFromNull)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillLambdaVector() for particle "
<< particle->GetParticleName() << G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector sigmaLow;
@@ -391,14 +464,28 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
const G4Material* material = couple->GetMaterial();
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
G4cout << "G4EmModelManager::FillLambdaVector() for particle "
<< particle->GetParticleName()
<< " in " << material->GetName()
<< G4endl;
}
size_t i = couple->GetIndex();
G4double cut = theCuts[i];
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
sigmaLow.resize(nmod);
sigmaHigh.resize(nmod);
if(1 < verboseLevel) {
G4cout << "There are " << nmod << " models for "
<< material->GetName() << G4endl;
}
@@ -409,31 +496,31 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
sigmaLow[0] = 0.0;
e = upperEkin[0];
e = upperEkin[regModels->ModelIndex(0)];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " " << nEmModels
<< " " << nmod
<< " 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) {
sigmaHigh[0] = models[regModels->ModelIndex(0)]->CrossSection(material,particle,e,cut,e);
for(j=1; j<nEmModels; j++) {
if(nmod > 1) {
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<nmod; j++) {
e = upperEkin[regModels->ModelIndex(j-1)];
sigmaLow[j] = models[regModels->ModelIndex(j)]->CrossSection(material,particle,e,cut,e);
e = upperEkin[regModels->ModelIndex(j)];
sigmaHigh[j] = models[regModels->ModelIndex(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);
for(j=1; j<nmod; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
@@ -446,30 +533,23 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
// 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;
}
}
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e < upperEkin[regModels->ModelIndex(k)] );
}
// Cross section interpolation should start from zero
G4double cross = 0.0;
if(j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,cut,e)*fac;
}
G4double cross = models[regModels->ModelIndex(k)]->CrossSection(material,particle,e,cut,e)*fac;
if(j==0 && startFromNull) cross = 0.0;
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
G4cout << "FillLambdaVector: " << j << ". 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;
if(cross < 0.0) cross = 0.0;
aVector->PutValue(j, cross);
}
@@ -477,11 +557,12 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple,
G4bool startFromNull)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::BuildLambdaSubTable() for particle "
G4cout << "G4EmModelManager::BuildLambdaSubTable() for particle "
<< particle->GetParticleName() << G4endl;
}
@@ -493,15 +574,20 @@ void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
G4double e;
G4int i = material->GetIndex();
const G4Material* material = couple->GetMaterial();
size_t i = couple->GetIndex();
G4double cut = theCuts[i];
G4double subcut = theSubCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
sigmaLow.resize(nmod);
sigmaHigh.resize(nmod);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
G4cout << "There are " << nmod << " models for "
<< material->GetName() << G4endl;
}
@@ -512,31 +598,31 @@ void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
sigmaLow[0] = 0.0;
e = upperEkin[0];
e = upperEkin[regModels->ModelIndex(0)];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " are available " << nEmModels
<< " are available " << nmod
<< " models"
<< " Ecut(MeV)= " << cut/MeV
<< " nbins= " << totBinsLambda
<< G4endl;
}
sigmaHigh[0] = emModels[0]->CrossSection(material,particle,e,subcut,cut);
if(nEmModels > 1) {
sigmaHigh[0] = models[regModels->ModelIndex(0)]->CrossSection(material,particle,e,subcut,cut);
for(j=1; j<nEmModels; j++) {
if(nmod > 1) {
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<nmod; j++) {
e = upperEkin[regModels->ModelIndex(j-1)];
sigmaLow[j] = models[regModels->ModelIndex(j)]->CrossSection(material,particle,e,subcut,cut);
e = upperEkin[regModels->ModelIndex(j)];
sigmaHigh[j] = models[regModels->ModelIndex(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);
for(j=1; j<nmod; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
@@ -549,37 +635,26 @@ void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
// 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;
}
}
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e < upperEkin[regModels->ModelIndex(k)] );
}
G4double cross = 0.0;
// Cross section interpolation should start from zero
if (j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,subcut,cut)*fac;
}
G4double cross=models[regModels->ModelIndex(k)]->CrossSection(material,particle,e,subcut,cut)*fac;
if(j==0 && startFromNull) cross = 0.0;
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
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 = 0.0;
aVector->PutValue(j, cross);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,10 +21,10 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossMessenger.cc,v 1.5 2002/12/04 21:07:43 asaim Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4EnergyLossMessenger.cc,v 1.7 2003/04/04 14:33:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -32,6 +32,7 @@
#include "G4EnergyLossMessenger.hh"
#include "G4VEnergyLoss.hh"
#include "G4LossTableManager.hh"
#include "G4UIdirectory.hh"
#include "G4UIcommand.hh"
@@ -52,24 +53,24 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
RndmStepCmd->SetGuidance("Randomize the proposed step by eLoss.");
RndmStepCmd->SetParameterName("choice",true);
RndmStepCmd->SetDefaultValue(false);
RndmStepCmd->AvailableForStates(G4State_Idle);
RndmStepCmd->AvailableForStates(G4State_PreInit,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(G4State_Idle);
EnlossFlucCmd->AvailableForStates(G4State_PreInit,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(G4State_Idle);
SubSecCmd->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("rcmin",true);
MinSubSecCmd->AvailableForStates(G4State_Idle);
MinSubSecCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd = new G4UIcommand("/process/eLoss/StepFunction",this);
StepFuncCmd->SetGuidance("Set the energy loss step limitation parameters.");
@@ -93,7 +94,25 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
unitPrm->SetParameterCandidates(unitCandidates);
StepFuncCmd->SetParameter(unitPrm);
StepFuncCmd->AvailableForStates(G4State_Idle);
StepFuncCmd->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);
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);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -106,22 +125,29 @@ G4EnergyLossMessenger::~G4EnergyLossMessenger()
delete MinSubSecCmd;
delete StepFuncCmd;
delete eLossDirectory;
delete MinEnCmd;
delete MaxEnCmd;
delete IntegCmd;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
{
G4LossTableManager* lossTables = G4LossTableManager::Instance();
if (command == RndmStepCmd)
{ G4VEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
lossTables->SetRandomStep(RndmStepCmd->GetNewBoolValue(newValue));
}
if (command == EnlossFlucCmd)
{ G4VEnergyLoss::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
lossTables->SetLossFluctuations(EnlossFlucCmd->GetNewBoolValue(newValue));
}
if (command == SubSecCmd)
{ G4VEnergyLoss::SetSubSec(SubSecCmd->GetNewBoolValue(newValue));
lossTables->SetSubCutoff(SubSecCmd->GetNewBoolValue(newValue));
}
if (command == MinSubSecCmd)
@@ -138,7 +164,20 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
G4String unt = unts;
v2 *= G4UIcommand::ValueOf(unt);
G4VEnergyLoss::SetStepFunction(v1,v2);
lossTables->SetStepLimits(v1,v2);
}
if (command == MinEnCmd) {
lossTables->SetMinEnergy(MinEnCmd->GetNewDoubleValue(newValue));
}
if (command == MaxEnCmd) {
lossTables->SetMaxEnergy(MaxEnCmd->GetNewDoubleValue(newValue));
}
if (command == IntegCmd) {
lossTables->SetIntegral(IntegCmd->GetNewBoolValue(newValue));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1,190 +0,0 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: 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....
@@ -21,10 +21,10 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossTables.cc,v 1.17 2001/10/29 09:40:52 maire Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4EnergyLossTables.cc,v 1.27 2003/04/18 17:49:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// first version created by P.Urban , 06/04/1998
// modifications + "precise" functions added by L.Urban , 27/05/98
// modifications , TOF functions , 26/10/98, L.Urban
@@ -33,20 +33,32 @@
// 10.11.99: moved from RWT hash dictionary to STL map, G.Barrand, M.Maire
// 27.09.01 L.Urban , bug fixed (negative energy deposit)
// 26.10.01 all static functions moved from .icc files (mma)
// 15.01.03 Add interfaces required for "cut per region" (V.Ivanchenko)
// 12.03.03 Add warnings to obsolete interfaces (V.Ivanchenko)
// 10.04.03 Add call to G4LossTableManager is particle is not registered (V.Ivanchenko)
//
// -------------------------------------------------------------------
#include "G4EnergyLossTables.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4RegionStore.hh"
#include "G4LossTableManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EnergyLossTablesHelper G4EnergyLossTables::t ;
const G4ParticleDefinition* G4EnergyLossTables::lastParticle = 0;
G4EnergyLossTablesHelper G4EnergyLossTables::null_loss ;
const G4ParticleDefinition* G4EnergyLossTables::lastParticle = 0;
G4double G4EnergyLossTables::QQPositron = eplus*eplus ;
G4double G4EnergyLossTables::Chargesquare ;
G4int G4EnergyLossTables::oldIndex = -1 ;
G4double G4EnergyLossTables::rmin = 0. ;
G4double G4EnergyLossTables::rmax = 0. ;
G4double G4EnergyLossTables::Thigh = 0. ;
G4int G4EnergyLossTables::let_counter = 0;
G4int G4EnergyLossTables::let_max_num_warnings = 2;
G4bool G4EnergyLossTables::first_loss = true;
G4EnergyLossTables::helper_map G4EnergyLossTables::dict;
@@ -95,11 +107,15 @@ void G4EnergyLossTables::Register(
dict[p]= G4EnergyLossTablesHelper(tDEDX, tRange,tInverseRange,
tLabTime,tProperTime,lowestKineticEnergy,
highestKineticEnergy, massRatio,NumberOfBins);
t = GetTables(p) ; // important for cache !!!!!
lastParticle = p ;
Chargesquare = (p->GetPDGCharge())*(p->GetPDGCharge())/
QQPositron ;
if (first_loss ) {
null_loss = G4EnergyLossTablesHelper(0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0);
first_loss = false;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -109,7 +125,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetDEDXTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theDEDXTable;
return (*it).second.theDEDXTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -119,7 +135,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetRangeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theRangeTable;
return (*it).second.theRangeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -129,7 +145,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetInverseRangeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theInverseRangeTable;
return (*it).second.theInverseRangeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -139,7 +155,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetLabTimeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theLabTimeTable;
return (*it).second.theLabTimeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -149,7 +165,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetProperTimeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theProperTimeTable;
return (*it).second.theProperTimeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -158,9 +174,11 @@ G4EnergyLossTablesHelper G4EnergyLossTables::GetTables(
const G4ParticleDefinition* p)
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) {
G4Exception("G4EnergyLossTables::GetTables: table not found!");
exit(1);
if ((it=dict.find(p))==dict.end()) {
// G4cout << "Table is not found out for " << p->GetParticleName() << G4endl;
// G4Exception("G4EnergyLossTables::GetTables: table not found!");
// exit(1);
return null_loss;
}
return (*it).second;
}
@@ -172,6 +190,7 @@ G4double G4EnergyLossTables::GetDEDX(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -182,6 +201,7 @@ G4double G4EnergyLossTables::GetDEDX(
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
@@ -200,7 +220,7 @@ G4double G4EnergyLossTables::GetDEDX(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
@@ -216,6 +236,7 @@ G4double G4EnergyLossTables::GetLabTime(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -223,8 +244,9 @@ G4double G4EnergyLossTables::GetLabTime(
oldIndex = -1 ;
}
const G4PhysicsTable* labtimeTable= t.theLabTimeTable;
if (!labtimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double time;
@@ -243,7 +265,7 @@ G4double G4EnergyLossTables::GetLabTime(
t.theHighestKineticEnergy,isOut);
} else {
time = (*labtimeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
@@ -260,6 +282,7 @@ G4double G4EnergyLossTables::GetDeltaLabTime(
G4double KineticEnergyEnd,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -267,9 +290,10 @@ G4double G4EnergyLossTables::GetDeltaLabTime(
oldIndex = -1 ;
}
const G4PhysicsTable* labtimeTable= t.theLabTimeTable;
if (!labtimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
G4double timestart,timeend,deltatime,dTT;
G4bool isOut;
@@ -296,12 +320,12 @@ G4double G4EnergyLossTables::GetDeltaLabTime(
}
dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
if( dTT < dToverT )
scaledKineticEnergy = facT*KineticEnergyStart*t.theMassRatio;
else
scaledKineticEnergy = KineticEnergyEnd*t.theMassRatio;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
timeend = exp(ppar*log(scaledKineticEnergy/t.theLowestKineticEnergy))*
@@ -336,6 +360,7 @@ G4double G4EnergyLossTables::GetProperTime(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -343,6 +368,7 @@ G4double G4EnergyLossTables::GetProperTime(
oldIndex = -1 ;
}
const G4PhysicsTable* propertimeTable= t.theProperTimeTable;
if (!propertimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
G4int materialIndex = aMaterial->GetIndex();
@@ -380,6 +406,7 @@ G4double G4EnergyLossTables::GetDeltaProperTime(
G4double KineticEnergyEnd,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -387,9 +414,10 @@ G4double G4EnergyLossTables::GetDeltaProperTime(
oldIndex = -1 ;
}
const G4PhysicsTable* propertimeTable= t.theProperTimeTable;
if (!propertimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
G4double timestart,timeend,deltatime,dTT;
G4bool isOut;
@@ -416,12 +444,12 @@ G4double G4EnergyLossTables::GetDeltaProperTime(
}
dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
if( dTT < dToverT )
scaledKineticEnergy = facT*KineticEnergyStart*t.theMassRatio;
else
scaledKineticEnergy = KineticEnergyEnd*t.theMassRatio;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
timeend = exp(ppar*log(scaledKineticEnergy/t.theLowestKineticEnergy))*
@@ -456,6 +484,7 @@ G4double G4EnergyLossTables::GetRange(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -467,6 +496,7 @@ G4double G4EnergyLossTables::GetRange(
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable || !rangeTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
@@ -488,7 +518,7 @@ G4double G4EnergyLossTables::GetRange(
t.theHighestKineticEnergy,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
@@ -505,6 +535,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
const G4Material *aMaterial)
// it returns the value of the kinetic energy for a given range
{
CPRWarning();
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -516,6 +547,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
const G4PhysicsTable* inverseRangeTable= t.theInverseRangeTable;
if (!dEdxTable || !inverseRangeTable) ParticleHaveNoLoss(aParticle);
G4double scaledrange,scaledKineticEnergy ;
G4bool isOut ;
@@ -566,7 +598,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -577,6 +609,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
@@ -595,7 +628,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
@@ -611,6 +644,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -622,6 +656,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable || !rangeTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
@@ -648,7 +683,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
Thighr,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
@@ -659,6 +694,299 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetDEDX(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle ;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !dEdxTable )
return G4LossTableManager::Instance()->GetDEDX(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double dEdx;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
dEdx =(*dEdxTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut)
*sqrt(scaledKineticEnergy/t.theLowestKineticEnergy);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
}
return dEdx*Chargesquare;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetRange(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle ;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !rangeTable || !dEdxTable)
return G4LossTableManager::Instance()->GetRange(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double Range;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
Range = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)*
(*rangeTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
Range = (*rangeTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut)+
(scaledKineticEnergy-t.theHighestKineticEnergy)/
(*dEdxTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
}
return Range/(Chargesquare*t.theMassRatio);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
const G4ParticleDefinition *aParticle,
G4double range,
const G4MaterialCutsCouple *couple)
// it returns the value of the kinetic energy for a given range
{
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
const G4PhysicsTable* inverseRangeTable= t.theInverseRangeTable;
if ( !dEdxTable || !inverseRangeTable)
return G4LossTableManager::Instance()->GetEnergy(aParticle,range,couple);
G4double scaledrange,scaledKineticEnergy ;
G4bool isOut ;
G4int materialIndex = couple->GetIndex() ;
if(materialIndex != oldIndex)
{
oldIndex = materialIndex ;
rmin = (*inverseRangeTable)(materialIndex)->
GetLowEdgeEnergy(0) ;
rmax = (*inverseRangeTable)(materialIndex)->
GetLowEdgeEnergy(t.theNumberOfBins-2) ;
Thigh = (*inverseRangeTable)(materialIndex)->
GetValue(rmax,isOut) ;
}
scaledrange = range*Chargesquare*t.theMassRatio ;
if(scaledrange < rmin)
{
scaledKineticEnergy = t.theLowestKineticEnergy*
scaledrange*scaledrange/(rmin*rmin) ;
}
else
{
if(scaledrange < rmax)
{
scaledKineticEnergy = (*inverseRangeTable)(materialIndex)->
GetValue( scaledrange,isOut) ;
}
else
{
scaledKineticEnergy = Thigh +
(scaledrange-rmax)*
(*dEdxTable)(materialIndex)->
GetValue(Thigh,isOut) ;
}
}
return scaledKineticEnergy/t.theMassRatio ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetPreciseDEDX(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !dEdxTable )
return G4LossTableManager::Instance()->GetDEDX(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double dEdx;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
dEdx = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)
*(*dEdxTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
}
return dEdx*Chargesquare;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetPreciseRangeFromEnergy(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !dEdxTable || !rangeTable)
return G4LossTableManager::Instance()->GetDEDX(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double Thighr = t.theHighestKineticEnergy*t.theLowestKineticEnergy/
(*rangeTable)(materialIndex)->
GetLowEdgeEnergy(1) ;
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double Range;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
Range = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)*
(*rangeTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
} else if (scaledKineticEnergy>Thighr) {
Range = (*rangeTable)(materialIndex)->GetValue(
Thighr,isOut)+
(scaledKineticEnergy-Thighr)/
(*dEdxTable)(materialIndex)->GetValue(
Thighr,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
}
return Range/(Chargesquare*t.theMassRatio);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EnergyLossTables::CPRWarning()
{
// if (let_counter < let_max_num_warnings) {
// G4cout << G4endl;
// G4cout << "##### G4EnergyLossTable WARNING: The obsolete interface is used" << G4endl;
// G4cout << "##### Please, substitute G4Material by G4MaterialCutsCouple" << G4endl;
// G4cout << "##### Obsolete interface will be removed soon" << G4endl;
// G4cout << G4endl;
// let_counter++;
if ((G4RegionStore::GetInstance())->size() > 1) {
G4Exception("G4EnergyLossTables:: More than 1 region - table can't be accessed with obsolete interface");
exit(1);
}
// } else if (let_counter == let_max_num_warnings) {
// G4cout << "##### G4EnergyLossTable WARNING closed" << G4endl;
// let_counter++;
// }
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EnergyLossTables::ParticleHaveNoLoss(const G4ParticleDefinition* aParticle)
{
G4String s = "G4EnergyLossTables:: dE/dx table not found for "
+ aParticle->GetParticleName() + "!";
G4Exception(s);
exit(1);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,337 @@
//
// ********************************************************************
// * 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: G4IonFluctuation
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4IonFluctuations.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4IonFluctuations::G4IonFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minFraction(0.2)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4IonFluctuations::~G4IonFluctuations()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IonFluctuations::Initialise(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
if(dp->GetDefinition() != particle) {
particle = dp->GetDefinition();
particleMass = dp->GetMass();
charge = dp->GetCharge();
chargeSquare = charge*charge;
}
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
// Gaussian fluctuation
if (meanLoss >= minNumberInteractionsBohr*tmax) {
// Increase fluctuations for big fractional energy loss
if ( meanLoss > minFraction*kineticEnergy ) {
G4double gam = (kineticEnergy - meanLoss)/particleMass + 1.0;
G4double b2 = 1.0 - 1.0/(gam*gam);
G4double x = b2/beta2;
G4double x3 = 1.0/(x*x*x);
siga *= 0.25*(1.0 + x)*(x3 + (1.0/b2 - 0.5)/(1.0/beta2 - 0.5) );
}
siga = sqrt(siga);
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0. || loss > 2.*meanLoss);
// Poisson fluctuations
} else {
G4double navr = meanLoss*meanLoss/siga;
G4double n = (G4double)G4Poisson(navr);
loss = meanLoss*n/navr;
}
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::Dispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length)
{
G4double electronDensity = material->GetElectronDensity();
kineticEnergy = dp->GetKineticEnergy();
G4double gam = kineticEnergy/particleMass + 1.0;
beta2 = 1.0 - 1.0/(gam*gam);
G4double siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare;
// Low velocity - additional ion charge fluctuations according to
// Q.Yang et al., NIM B61(1991)149-155.
G4double zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
if ( beta2 < 3.0*theBohrBeta2*zeff ) {
G4double a = CoeffitientA (zeff);
G4double b = CoeffitientB (material, zeff);
siga *= (chargeSquare * a + b);
}
return siga;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::CoeffitientA(G4double& zeff)
{
// The aproximation of energy loss fluctuations
// Q.Yang et al., NIM B61(1991)149-155.
// Reduced energy in MeV/AMU
G4double energy = kineticEnergy * amu_c2/(particleMass*MeV) ;
static G4double a[96][4] = {
{-0.3291, -0.8312, 0.2460, -1.0220},
{-0.5615, -0.5898, 0.5205, -0.7258},
{-0.5280, -0.4981, 0.5519, -0.5865},
{-0.5125, -0.4625, 0.5660, -0.5190},
{-0.5127, -0.8595, 0.5626, -0.8721},
{-0.5174, -1.1930, 0.5565, -1.1980},
{-0.5179, -1.1850, 0.5560, -1.2070},
{-0.5209, -0.9355, 0.5590, -1.0250},
{-0.5255, -0.7766, 0.5720, -0.9412},
{-0.5776, -0.6665, 0.6598, -0.8484},
{-0.6013, -0.6045, 0.7321, -0.7671},
{-0.5781, -0.5518, 0.7605, -0.6919},
{-0.5587, -0.4981, 0.7835, -0.6195},
{-0.5466, -0.4656, 0.7978, -0.5771},
{-0.5406, -0.4690, 0.8031, -0.5718},
{-0.5391, -0.5061, 0.8024, -0.5974},
{-0.5380, -0.6483, 0.7962, -0.6970},
{-0.5355, -0.7722, 0.7962, -0.7839},
{-0.5329, -0.7720, 0.7988, -0.7846},
{-0.5335, -0.7671, 0.7984, -0.7933},
{-0.5324, -0.7612, 0.7998, -0.8031},
{-0.5305, -0.7300, 0.8031, -0.7990},
{-0.5307, -0.7178, 0.8049, -0.8216},
{-0.5248, -0.6621, 0.8165, -0.7919},
{-0.5180, -0.6502, 0.8266, -0.7986},
{-0.5084, -0.6408, 0.8396, -0.8048},
{-0.4967, -0.6331, 0.8549, -0.8093},
{-0.4861, -0.6508, 0.8712, -0.8432},
{-0.4700, -0.6186, 0.8961, -0.8132},
{-0.4545, -0.5720, 0.9227, -0.7710},
{-0.4404, -0.5226, 0.9481, -0.7254},
{-0.4288, -0.4778, 0.9701, -0.6850},
{-0.4199, -0.4425, 0.9874, -0.6539},
{-0.4131, -0.4188, 0.9998, -0.6332},
{-0.4089, -0.4057, 1.0070, -0.6218},
{-0.4039, -0.3913, 1.0150, -0.6107},
{-0.3987, -0.3698, 1.0240, -0.5938},
{-0.3977, -0.3608, 1.0260, -0.5852},
{-0.3972, -0.3600, 1.0260, -0.5842},
{-0.3985, -0.3803, 1.0200, -0.6013},
{-0.3985, -0.3979, 1.0150, -0.6168},
{-0.3968, -0.3990, 1.0160, -0.6195},
{-0.3971, -0.4432, 1.0050, -0.6591},
{-0.3944, -0.4665, 1.0010, -0.6825},
{-0.3924, -0.5109, 0.9921, -0.7235},
{-0.3882, -0.5158, 0.9947, -0.7343},
{-0.3838, -0.5125, 0.9999, -0.7370},
{-0.3786, -0.4976, 1.0090, -0.7310},
{-0.3741, -0.4738, 1.0200, -0.7155},
{-0.3969, -0.4496, 1.0320, -0.6982},
{-0.3663, -0.4297, 1.0430, -0.6828},
{-0.3630, -0.4120, 1.0530, -0.6689},
{-0.3597, -0.3964, 1.0620, -0.6564},
{-0.3555, -0.3809, 1.0720, -0.6454},
{-0.3525, -0.3607, 1.0820, -0.6289},
{-0.3505, -0.3465, 1.0900, -0.6171},
{-0.3397, -0.3570, 1.1020, -0.6384},
{-0.3314, -0.3552, 1.1130, -0.6441},
{-0.3235, -0.3531, 1.1230, -0.6498},
{-0.3150, -0.3483, 1.1360, -0.6539},
{-0.3060, -0.3441, 1.1490, -0.6593},
{-0.2968, -0.3396, 1.1630, -0.6649},
{-0.2935, -0.3225, 1.1760, -0.6527},
{-0.2797, -0.3262, 1.1940, -0.6722},
{-0.2704, -0.3202, 1.2100, -0.6770},
{-0.2815, -0.3227, 1.2480, -0.6775},
{-0.2880, -0.3245, 1.2810, -0.6801},
{-0.3034, -0.3263, 1.3270, -0.6778},
{-0.2936, -0.3215, 1.3430, -0.6835},
{-0.3282, -0.3200, 1.3980, -0.6650},
{-0.3260, -0.3070, 1.4090, -0.6552},
{-0.3511, -0.3074, 1.4470, -0.6442},
{-0.3501, -0.3064, 1.4500, -0.6442},
{-0.3490, -0.3027, 1.4550, -0.6418},
{-0.3487, -0.3048, 1.4570, -0.6447},
{-0.3478, -0.3074, 1.4600, -0.6483},
{-0.3501, -0.3283, 1.4540, -0.6669},
{-0.3494, -0.3373, 1.4550, -0.6765},
{-0.3485, -0.3373, 1.4570, -0.6774},
{-0.3462, -0.3300, 1.4630, -0.6728},
{-0.3462, -0.3225, 1.4690, -0.6662},
{-0.3453, -0.3094, 1.4790, -0.6553},
{-0.3844, -0.3134, 1.5240, -0.6412},
{-0.3848, -0.3018, 1.5310, -0.6303},
{-0.3862, -0.2955, 1.5360, -0.6237},
{-0.4262, -0.2991, 1.5860, -0.6115},
{-0.4278, -0.2910, 1.5900, -0.6029},
{-0.4303, -0.2817, 1.5940, -0.5927},
{-0.4315, -0.2719, 1.6010, -0.5829},
{-0.4359, -0.2914, 1.6050, -0.6010},
{-0.4365, -0.2982, 1.6080, -0.6080},
{-0.4253, -0.3037, 1.6120, -0.6150},
{-0.4335, -0.3245, 1.6160, -0.6377},
{-0.4307, -0.3292, 1.6210, -0.6447},
{-0.4284, -0.3204, 1.6290, -0.6380},
{-0.4227, -0.3217, 1.6360, -0.6438}
} ;
G4int iz = (G4int)zeff - 2 ;
if( 0 > iz ) iz = 0 ;
if(95 < iz ) iz = 95 ;
G4double q = 1.0 / (1.0 + a[iz][0]*pow(energy,a[iz][1])+
+ a[iz][2]*pow(energy,a[iz][3])) ;
return q ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::CoeffitientB(const G4Material* material, G4double& zeff)
{
// The aproximation of energy loss fluctuations
// Q.Yang et al., NIM B61(1991)149-155.
// Reduced energy in MeV/AMU
G4double energy = kineticEnergy *amu_c2/(particleMass*MeV) ;
G4int i = 0 ;
G4double factor = 1.0 ;
// The index of set of parameters i = 0 for protons(hadrons) in gases
// 1 for protons(hadrons) in solids
// 2 for ions in atomic gases
// 3 for ions in molecular gases
// 4 for ions in solids
static G4double b[5][4] = {
{0.1014, 0.3700, 0.9642, 3.987},
{0.1955, 0.6941, 2.522, 1.040},
{0.05058, 0.08975, 0.1419, 10.80},
{0.05009, 0.08660, 0.2751, 3.787},
{0.01273, 0.03458, 0.3951, 3.812}
} ;
// protons (hadrons)
if(1.5 > charge) {
if( kStateGas != material->GetState() ) i = 1 ;
// ions
} else {
factor = charge * pow(charge/zeff, 0.3333) ;
if( kStateGas == material->GetState() ) {
energy /= (charge * sqrt(charge)) ;
if(1 == (material->GetNumberOfElements())) {
i = 2 ;
} else {
i = 3 ;
}
} else {
energy /= (charge * sqrt(charge*zeff)) ;
i = 4 ;
}
}
G4double x = b[i][2] * (1.0 - exp( - energy * b[i][3] )) ;
G4double q = factor * x * b[i][0] /
((energy - b[i][1])*(energy - b[i][1]) + x*x) ;
return q ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,643 @@
//
// ********************************************************************
// * 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: G4LewisModel
//
// Author: Laszlo Urban
//
// Creation date: 03.03.2001
//
// Modifications:
//
// 27-03-03 Move model part from G4MultipleScattering (V.Ivanchenko)
//
// Class Description:
//
// Implementation of Lewis model of multiple scattering
// H.W.Lewis Phys Rev 78 (1950) 526
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LewisModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
#include "G4LossTableManager.hh"
#include "G4PhysicsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LewisModel::G4LewisModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
G4double& m_FactPar, G4double& m_facxsi,
G4bool& m_samplez, const G4String& nam)
: G4VEmModel(nam),
highKinEnergy(10.0*TeV),
lowKinEnergy(0.1*keV),
taubig(8.0),
tausmall(1.e-14),
taulim(1.e-5),
dtrl(m_dtrl),
NuclCorrPar (m_NuclCorrPar),
FactPar(m_FactPar),
facxsi(m_facxsi),
samplez(m_samplez),
stepmin(1.e-6*mm)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LewisModel::~G4LewisModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4LewisModel::IsInCharge(const G4ParticleDefinition* p)
{
return (p->GetPDGCharge() != 0.0);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LewisModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
// set values of some data members
if((p->GetParticleName() == "e-") || (p->GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
sigmafactor = twopi*classic_electr_radius*classic_electr_radius;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::CrossSection(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double,
G4double)
{
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
// loop for element in the material
G4double sigma = 0.0;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
G4double atomicNumber = (*theElementVector)[iel]->GetZ();
G4double atomicWeight = (*theElementVector)[iel]->GetA();
sigma += NbOfAtomsPerVolume[iel]*ComputeTransportCrossSection(p,
kineticEnergy,atomicNumber,atomicWeight);
}
sigma *= sigmafactor;
// Calculate lambda
if ( sigma > 0.0) sigma = 1.0/sigma;
else sigma = DBL_MAX;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::ComputeTransportCrossSection(
const G4ParticleDefinition* particle,
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 = particle->GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
if((particle->GetParticleName() != "e-") &&
(particle->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 = particle->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,w1,w2,w;
G4double 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((particle->GetParticleName() != "e-") &&
(particle->GetParticleName() != "e+") )
sigma /= corrnuclsize;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::GeomPathLength(
G4PhysicsTable* theLambdaTable,
const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* particle,
G4double& T0,
G4double lambda,
G4double range,
G4double truePathLength)
{
// do the true -> geom transformation
const G4double ztmin = 1./3., ztmax = 0.98 ;
lambda0 = lambda;
lambda1 = -1.;
lambdam = -1.;
alam = range;
zm = 1.;
cthm = 1.;
tPathLength = truePathLength;
G4double tau = tPathLength/lambda0 ;
if (tau <= tausmall) return tPathLength;
G4double zmean = tPathLength;
if (tPathLength < range*dtrl) {
zmean = lambda0*(1.-exp(-tau));
} else {
G4LossTableManager* theManager = G4LossTableManager::Instance();
G4double T1 = theManager->GetEnergy(particle,range-tPathLength,couple);
if (theLambdaTable) {
G4bool b;
lambda1 = ((*theLambdaTable)[couple->GetIndex()])->GetValue(T1,b);
} else {
lambda1 = CrossSection(couple->GetMaterial(),particle,T1,0.0,1.0);
}
if (T0 > particle->GetPDGMass()) alam = lambda0*tPathLength/(lambda0-lambda1) ;
G4double blam = 1.+alam/lambda0 ;
if (tPathLength < 2.*dtrl*range) {
zmean = alam*(1.-exp(blam*log(1.-tPathLength/alam)))/blam ;
} else {
G4double w = 1.-0.5*tPathLength/alam ;
lambdam = lambda0*w ;
G4double clam = 1.+alam/lambdam ;
cthm = exp(alam*log(w)/lambda0) ;
zm = alam*(1.-exp(blam*log(w)))/blam ;
zmean = zm + alam*(1.-exp(clam*log(w)))*cthm/clam ;
}
}
// sample z
G4double zPathLength = zmean ;
G4double zt = zmean/tPathLength ;
if (tPathLength >= stepmin && samplez && zt > ztmin && zt < ztmax) {
G4double cz = 0.5*(3.*zt-1.)/(1.-zt) ;
G4double cz1 = 1.+cz ;
G4double u0 = cz/cz1 ;
G4double u,grej ;
G4double grej0 = exp(cz*log(u0))*(1.-u0) ;
do {
u = exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(u))*(1.-u) ;
if (grej > grej0)
G4cout << "G4LewisModel: Warning! majorant "
<< grej0 << " < " << grej << G4endl;
} while (grej < grej0*G4UniformRand()) ;
zPathLength = tPathLength*u ;
}
return zPathLength ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::TrueStepLength(G4double geomStepLength)
{
G4double trueLength = geomStepLength;
if (geomStepLength > lambda0*tausmall) {
G4double blam = 1.+alam/lambda0;
// G4cout << "alam= " << alam << " blam= " << blam << " lambda1= " << lambda1 << G4endl;
if (lambda1 < 0.) {
trueLength = -lambda0*log(1.-geomStepLength/lambda0) ;
} else if (lambdam < 0.) {
if (blam*geomStepLength < alam)
trueLength = alam*(1.-exp(log(1.-blam*geomStepLength/alam)/blam));
else
trueLength = tPathLength;
} else {
if (geomStepLength <= zm) {
// ??? here is a problems - redefine variable
lambdam = -1.;
if(blam*geomStepLength < alam )
trueLength = alam*(1.-exp(log(1.-blam*geomStepLength/alam)/blam));
else
trueLength = 0.5*tPathLength;
} else {
G4double clam = 1.+alam/lambdam;
// G4cout << "clam= " << clam << " zm= " << zm << " cthm= " << cthm << G4endl;
if(clam*(geomStepLength-zm)/(alam*cthm) < 1.)
trueLength = 0.5*tPathLength + alam*(1.-
exp(log(1.-clam*(geomStepLength-zm)/(alam*cthm)))/clam) ;
else
trueLength = tPathLength;
}
}
// G4cout << "tLenth= " << trueLength << " tpl= " << tPathLength << G4endl;
if(trueLength > tPathLength) trueLength = tPathLength;
if(trueLength < geomStepLength) trueLength = geomStepLength;
}
return trueLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::SampleCosineTheta(G4double trueStepLength)
{
G4double cth = 1.;
currentTau = trueStepLength/lambda0;
if(trueStepLength < stepmin)
cth = exp(-currentTau) ;
else
{
// G4cout << "tau= " << currentTau << " lambda1= " << lambda1 << " lambdam= " << lambdam << G4endl;
if (currentTau > taubig) cth = -1.+2.*G4UniformRand();
else if (currentTau >= tausmall)
{
if(lambda1 > 0.)
{
if (lambdam < 0.)
currentTau = -alam*log(1.-trueStepLength/alam)/lambda0 ;
else
currentTau = -log(cthm)-alam*
log(1.-(trueStepLength-0.5*tPathLength)/alam)/lambdam ;
}
if(currentTau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double amax = 25. ;
const G4double tau0 = 0.02 ;
G4double a;
G4double w = log(currentTau/tau0) ;
if (currentTau < tau0) a = (alfa1-alfa2*w)/currentTau ;
else a = (alfa1+alfa3*w)/currentTau ;
G4double x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
G4double c = a*(b-x0) ;
if(a*currentTau < c0) c = c0*(b-x0)/currentTau ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
G4double ea = 0.0;
if (a*(1.-x0) < amax) ea = exp(-a*(1.-x0)) ;
G4double eaa = 1.-ea ;
G4double xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
G4double b1 = b+1. ;
G4double bx = b-x0 ;
G4double eb1= exp((c-1.)*log(b1)) ;
G4double ebx= exp((c-1.)*log(bx)) ;
G4double xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
G4double xmeanth = exp(-currentTau) ;
G4double cnorm1 = a/eaa ;
G4double cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
G4double f1x0 = cnorm1*exp(-a*(1.-x0)) ;
G4double f2x0 = cnorm2/exp(c*log(b-x0)) ;
// from continuity at x=x0
G4double prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
G4double qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
// protection against qprob > 1
if(qprob > 1.)
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
/*
G4cout << "tau= " << currentTau << " prob= " << prob << " qprob= " << qprob << G4endl;
G4cout << "ea= " << ea << " eaa= " << eaa << " a= " << a
<< " b= " << b << " b1= " << b1 << " bx= " << bx
<< " ebx= " << ebx << " eb1= " << eb1 << " c= " << c
<< G4endl;
*/
// 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();
}
}
}
}
// G4cout << "cth= " << cth << G4endl;
return cth;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::SampleDisplacement()
{
const G4double kappa = 2.5;
const G4double kappapl1 = kappa+1.;
const G4double kappami1 = kappa-1.;
G4double rmean = 0.0;
if (currentTau >= tausmall) {
if (currentTau < taulim) {
rmean = kappa*currentTau*currentTau*currentTau*(1.-kappapl1*currentTau*0.25)/6. ;
} else {
G4double etau = 0.0;
if (currentTau<taubig) etau = exp(-currentTau);
rmean = -kappa*currentTau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += currentTau-kappapl1/kappa+kappa*etau/kappami1;
// G4cout << "tau= " << currentTau << " lambda0= " << lambda0 << " etau= " << etau << " kappa= " << kappa << G4endl;
}
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.0);
else rmean = 0.;
// G4cout << "rmean= " << rmean << G4endl;
}
return rmean;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -29,10 +29,12 @@
// File name: G4LossTableBuilder
//
// Author: Vladimir Ivanchenko
//
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// 23.01.2003 V.Ivanchenko Cut per region
//
// Class Description:
//
@@ -59,16 +61,16 @@ G4PhysicsTable* G4LossTableBuilder::BuildDEDXTable(
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++) {
G4PhysicsVector* pv = (*(list[0]))[i];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4PhysicsLogVector* v = new G4PhysicsLogVector(elow, ehigh, nbins);
for (size_t j=0; j<nbins; j++) {
@@ -80,15 +82,15 @@ G4PhysicsTable* G4LossTableBuilder::BuildDEDXTable(
dedx += ((*(list[k]))[i])->GetValue(energy, b);
}
v->PutValue(j, dedx);
v->PutValue(j, dedx);
}
theTable->insert(v);
theTable->insert(v);
}
return theTable;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
const G4PhysicsTable* dedxTable)
// Build range table from the energy loss table
@@ -99,17 +101,16 @@ G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
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++) {
G4PhysicsVector* pv = (*dedxTable)[i];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
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);
@@ -135,11 +136,11 @@ G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
theTable->insert(v);
}
return theTable;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
const G4PhysicsTable* dedxTable,
const G4PhysicsTable* rangeTable)
@@ -178,11 +179,11 @@ G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
for (ihigh=ilow+1; ihigh<nbins; ihigh++) {
energy2 = pv->GetLowEdgeEnergy(ihigh);
range2 = pv->GetValue(energy2, b);
range2 = pv->GetValue(energy2, b);
if(range2 >= range || ihigh == nbins-1) {
ilow = ihigh - 1;
energy1 = pv->GetLowEdgeEnergy(ilow);
range1 = pv->GetValue(energy1, b);
range1 = pv->GetValue(energy1, b);
break;
}
}
@@ -194,7 +195,7 @@ G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
theTable->insert(v);
}
return theTable;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -28,13 +28,21 @@
//
// File name: G4LossTableManager
//
// Author: Vladimir Ivanchenko
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// Class Description:
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 15-02-03 Lambda table can be scaled (V.Ivanchenko)
// 17-02-03 Fix problem of store/restore tables (V.Ivanchenko)
// 10-03-03 Add Ion registration (V.Ivanchenko)
// 25-03-03 Add deregistration (V.Ivanchenko)
// 02-04-03 Change messenger (V.Ivanchenko)
// 26-04-03 Fix retrieve tables (V.Ivanchenko)
//
// Class Description:
//
// -------------------------------------------------------------------
//
@@ -42,12 +50,13 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LossTableManager.hh"
#include "G4EnergyLossMessengerSTD.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4PhysicsTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProcessManager.hh"
#include "G4Electron.hh"
#include "G4VMultipleScattering.hh"
G4LossTableManager* G4LossTableManager::theInstance = 0;
@@ -65,6 +74,13 @@ G4LossTableManager* G4LossTableManager::Instance()
G4LossTableManager::~G4LossTableManager()
{
for (G4int i=0; i<n_loss; i++) {
if( loss_vector[i] ) delete loss_vector[i];
}
size_t msc = msc_vector.size();
for (size_t j=0; j<msc; j++) {
if(msc_vector[j] ) delete msc_vector[j];
} Clear();
delete theMessenger;
delete tableBuilder;
}
@@ -72,10 +88,11 @@ G4LossTableManager::~G4LossTableManager()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4LossTableManager::G4LossTableManager()
{
{
n_loss = 0;
first_entry = true;
all_tables_are_built = false;
all_particles_are_mapped = false;
all_tables_are_stored = false;
electron_table_are_built = false;
currentLoss = 0;
currentParticle = 0;
@@ -88,7 +105,7 @@ G4LossTableManager::G4LossTableManager()
eIonisation = 0;
minKinEnergy = 0.1*eV;
maxKinEnergy = 100.0*GeV;
theMessenger = new G4EnergyLossMessengerSTD();
theMessenger = new G4EnergyLossMessenger();
theElectron = G4Electron::Electron();
tableBuilder = new G4LossTableBuilder();
integral = true;
@@ -98,22 +115,14 @@ G4LossTableManager::G4LossTableManager()
//....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)
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();
@@ -138,44 +147,95 @@ void G4LossTableManager::Register(G4VEnergyLossSTD* p)
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::DeRegister(G4VEnergyLossSTD* p)
{
for (G4int i=0; i<n_loss; i++) {
if(loss_vector[i] == p) loss_vector[i] = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::Register(G4VMultipleScattering* p)
{
msc_vector.push_back(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::DeRegister(G4VMultipleScattering* p)
{
size_t msc = msc_vector.size();
for (size_t i=0; i<msc; i++) {
if(msc_vector[i] == p) msc_vector[i] = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::RegisterIon(const G4ParticleDefinition* ion, G4VEnergyLossSTD* p)
{
loss_map[ion] = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4EnergyLossMessenger* G4LossTableManager::GetMessenger()
{
return theMessenger;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::ParticleHaveNoLoss(const G4ParticleDefinition* aParticle)
{
G4String s = "G4LossTableManager:: dE/dx table not found for "
+ aParticle->GetParticleName() + "!";
G4Exception(s);
exit(1);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::Initialise()
void G4LossTableManager::Initialise(const G4ParticleDefinition* aParticle)
{
all_tables_are_built = true;
if (first_entry) {
first_entry = false;
firstParticle = aParticle;
}
for(G4int j=0; j<n_loss; j++) {
const G4ParticleDefinition* pd = loss_vector[j]->Particle();
if (!pd) {
pd = loss_vector[j]->GetProcessManager()->GetParticleType();
loss_vector[j]->SetParticle(pd);
}
if(!tables_are_built[j]) all_tables_are_built = false;
if(pd != part_vector[j]) {
part_vector[j] = pd;
base_part_vector[j] = loss_vector[j]->BaseParticle();
}
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]
<< " procFlag= " << loss_vector[j]->TablesAreBuilt()
<< " all_tables_are_built= " << all_tables_are_built
<< 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++) {
if (all_tables_are_built && firstParticle == aParticle) {
for (G4int i=0; i<n_loss; i++) {
tables_are_built[i] = false;
}
all_tables_are_built = false;
@@ -183,29 +243,9 @@ void G4LossTableManager::Initialise()
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
<< " all_tables_are_built= " << all_tables_are_built
<< G4endl;
}
@@ -213,79 +253,77 @@ void G4LossTableManager::Initialise()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::BuildDEDXTable(const G4ParticleDefinition* aParticle)
void G4LossTableManager::BuildPhysicsTable(const G4ParticleDefinition* aParticle)
{
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable() for "
<< aParticle->GetParticleName()
if(0 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable() for "
<< aParticle->GetParticleName()
<< G4endl;
}
Initialise();
Initialise(aParticle);
// identify all particles and built electron table
if(!electron_table_are_built) {
eIonisation = BuildTables(theElectron);
currentLoss = eIonisation;
currentParticle = theElectron;
electron_table_are_built = true;
}
// If particle is not an electron
// 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]) {
if (aParticle == base_part_vector[j]) {
tables_are_built[j] = true;
G4VEnergyLossSTD* em = loss_vector[j];
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->SetLambdaTable(hIonisation->LambdaTable());
em->SetSubLambdaTable(hIonisation->SubLambdaTable());
loss_map[part_vector[j]] = em;
if (em->SecondaryParticle() == theElectron) {
em->SetSecondaryRangeTable(eIonisation->RangeTable());
}
if (0 < verbose) {
G4cout << "For " << loss_vector[j]->GetProcessName()
<< " for " << part_vector[j]->GetParticleName()
<< " base_part= " << base_part_vector[j]->GetParticleName()
<< " tables_are_built= " << G4endl;
}
}
}
} 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) {
if (tables_are_built[j] && part_vector[j] == base_part_vector[i]) {
G4VEnergyLossSTD* hIonisation = loss_vector[j];
tables_are_built[i] = true;
em->Initialise();
em->SetDEDXTable(hIonisation->DEDXTable());
em->SetRangeTable(hIonisation->RangeTable());
em->SetInverseRangeTable(hIonisation->InverseRangeTable());
em->SetLambdaTable(hIonisation->LambdaTable());
em->SetSubLambdaTable(hIonisation->SubLambdaTable());
loss_map[part_vector[i]] = em;
if (em->SecondaryParticle() == theElectron)
em->SetSecondaryRangeTable(eIonisation->RangeTable());
}
break;
if (0 < verbose) {
G4cout << "For " << em->GetProcessName()
<< " for " << part_vector[i]->GetParticleName()
<< " base_part= " << base_part_vector[i]->GetParticleName()
<< " tables_are_built= " << G4endl;
}
break;
}
}
}
@@ -293,60 +331,105 @@ void G4LossTableManager::BuildDEDXTable(const G4ParticleDefinition* aParticle)
}
}
}
all_tables_are_built = true;
for (G4int ii=0; ii<n_loss; ii++) {
if ( !tables_are_built[ii] ) {
all_tables_are_built = false;
break;
}
}
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable: end; "
<< "all_tables_are_built= " << all_tables_are_built
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)
void G4LossTableManager::RetrievePhysicsTables(const G4ParticleDefinition* aParticle,
G4VEnergyLossSTD* theLoss)
{
for(G4int i=0; i<n_loss; i++) {
if(theModel == loss_vector[i]) {
if(0 < verbose) {
G4cout << "G4LossTableManager::RetrievePhysicsTable() for "
<< aParticle->GetParticleName()
<< G4endl;
}
if (first_entry) Initialise(aParticle);
if (all_tables_are_built) return;
G4bool hasRange = false;
for (G4int i=0; i<n_loss; i++) {
if ( theLoss == 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;
}
}
}
if (theLoss->RangeTable()) {
if (part_vector[i] == theElectron) {
eIonisation = theLoss;
currentLoss = theLoss;
currentParticle = theElectron;
electron_table_are_built = true;
}
loss_map[part_vector[i]] = theLoss;
hasRange = true;
if (0 < verbose) {
G4cout << "dEdx and Range tables are defined for "
<< aParticle->GetParticleName()
<< G4endl;
}
}
}
if (electron_table_are_built && theLoss->SecondaryParticle() == theElectron)
theLoss->SetSecondaryRangeTable(eIonisation->RangeTable());
}
if ( hasRange ) {
for (G4int j=0; j<n_loss; j++) {
if ( base_part_vector[j] == aParticle && !tables_are_built[j] ) {
G4VEnergyLossSTD* em = loss_vector[j];
tables_are_built[j] = true;
em->Initialise();
em->SetDEDXTable(theLoss->DEDXTable());
em->SetRangeTable(theLoss->RangeTable());
em->SetInverseRangeTable(theLoss->InverseRangeTable());
em->SetLambdaTable(theLoss->LambdaTable());
em->SetSubLambdaTable(theLoss->SubLambdaTable());
if (electron_table_are_built && em->SecondaryParticle() == theElectron)
em->SetSecondaryRangeTable(eIonisation->RangeTable());
loss_map[part_vector[j]] = em;
if (1 < verbose) {
G4String nm = "0";
G4String nm1= "0";
G4String nm2= "0";
const G4ParticleDefinition* pd = part_vector[j];
const G4ParticleDefinition* bpd = base_part_vector[j];
if (pd) nm = pd->GetParticleName();
if (bpd) nm2 = bpd->GetParticleName();
if (part_vector[j]) nm1 = part_vector[j]->GetParticleName();
G4cout << "For " << loss_vector[j]->GetProcessName()
<< " for " << nm
<< " (" << nm1 << ") "
<< " base_part= " << nm2
<< " tables_are_built= " << tables_are_built[j]
<< G4endl;
}
}
}
}
all_tables_are_built = true;
for (G4int ii=0; ii<n_loss; ii++) {
if ( !tables_are_built[ii] ) {
all_tables_are_built = false;
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());
}
}
if(0 < verbose) {
G4cout << "G4LossTableManager::RetrievePhysicsTable: end; "
<< "all_tables_are_built= " << all_tables_are_built
<< G4endl;
}
}
@@ -354,8 +437,8 @@ void G4LossTableManager::RetrieveDEDXTable(const G4ParticleDefinition* aParticle
G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aParticle)
{
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildTables() for "
if(0 < verbose) {
G4cout << "G4LossTableManager::BuildTables() for "
<< aParticle->GetParticleName() << G4endl;
}
@@ -364,42 +447,41 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
list.clear();
G4std::vector<G4VEnergyLossSTD*> loss_list;
loss_list.clear();
G4VEnergyLossSTD* em = 0;
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();
for (G4int i=0; i<n_loss; i++) {
if (aParticle == part_vector[i]) {
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;
G4int n_dedx = list.size();
if (!n_dedx) return 0;
if(aParticle == theElectron) eIonisation = em;
if (aParticle == theElectron) eIonisation = em;
if(0 < verbose) {
if (1 < verbose) {
G4cout << "G4LossTableManager::BuildTables() start to build range tables"
<< " and the sum of " << n_dedx << " processes"
<< " and the sum of " << n_dedx << " processes"
<< G4endl;
}
G4PhysicsTable* dedx = list[0];
if(1 < n_dedx) {
if (1 < n_dedx) {
dedx = tableBuilder->BuildDEDXTable(list);
for(G4int i=0; i<n_dedx; i++) {
list[i]->clearAndDestroy();
@@ -415,14 +497,21 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
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());
for (G4int j=0; j<n_dedx; j++) {
if(loss_list[j]->SecondaryParticle() == theElectron)
loss_list[j]->SetSecondaryRangeTable(eIonisation->RangeTable());
G4PhysicsTable* lambdaTable = loss_list[j]->BuildLambdaTable();
loss_list[j]->SetLambdaTable(lambdaTable);
if (0 < loss_list[j]->NumberOfSubCutoffRegions()) {
lambdaTable = loss_list[j]->BuildLambdaSubTable();
loss_list[j]->SetSubLambdaTable(lambdaTable);
}
}
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildTables: Tables are built"
<< " for " << em->GetProcessName()
if (0 < verbose) {
G4cout << "G4LossTableManager::BuildTables: Tables are built for "
<< aParticle->GetParticleName()
<< "; ionisation process: " << em->GetProcessName()
<< G4endl;
}
return em;
@@ -430,7 +519,7 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetLossFluctuations(G4bool val)
void G4LossTableManager::SetLossFluctuations(G4bool val)
{
lossFluctuationFlag = val;
for(G4int i=0; i<n_loss; i++) {
@@ -440,7 +529,7 @@ void G4LossTableManager::SetLossFluctuations(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetSubCutoff(G4bool val)
void G4LossTableManager::SetSubCutoff(G4bool val)
{
subCutoffFlag = val;
for(G4int i=0; i<n_loss; i++) {
@@ -460,7 +549,7 @@ void G4LossTableManager::SetIntegral(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMinSubRange(G4double val)
void G4LossTableManager::SetMinSubRange(G4double val)
{
minSubRange = val;
for(G4int i=0; i<n_loss; i++) {
@@ -480,7 +569,7 @@ void G4LossTableManager::SetRandomStep(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMinEnergy(G4double val)
void G4LossTableManager::SetMinEnergy(G4double val)
{
minKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
@@ -490,7 +579,7 @@ void G4LossTableManager::SetMinEnergy(G4double val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMaxEnergy(G4double val)
void G4LossTableManager::SetMaxEnergy(G4double val)
{
maxKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
@@ -500,9 +589,9 @@ void G4LossTableManager::SetMaxEnergy(G4double val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetStepLimits(G4double v1, G4double v2)
void G4LossTableManager::SetStepLimits(G4double v1, G4double v2)
{
maxRangeVariation = v1;
maxRangeVariation = v1;
maxFinalStep = v2;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetStepLimits(v1, v2);
@@ -511,47 +600,4 @@ void G4LossTableManager::SetStepLimits(G4double v1, G4double 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......
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4MultipleScattering.cc,v 1.30 2002/12/11 12:05:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4MultipleScattering.cc,v 1.39 2003/04/28 15:31:40 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
@@ -52,8 +52,14 @@
// 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
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured, L.Urban
// 05-02-03 changes in data members, new sampling for geom.
// path length, step dependence reduced with new
// method
// 17-03-03 cut per region, V.Ivanchenko
// 13-04-03 add initialisation in GetContinuesStepLimit + change table size (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (M.Asai)
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -64,13 +70,13 @@
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScattering::G4MultipleScattering(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),
@@ -84,8 +90,10 @@ G4MultipleScattering::G4MultipleScattering(const G4String& processName)
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),
zmean(0.),samplez(true),
range(1.),T0(1.),T1(1.),lambda0(1.),lambda1(-1.),
Tlow(0.),alam(1.),blam(1.),dtrl(0.15),
lambdam(-1.),clam(1.),zm(1.),cthm(1.),
fLatDisplFlag(true),
NuclCorrPar (0.0615),
FactPar(0.40),
@@ -110,12 +118,13 @@ void G4MultipleScattering::BuildPhysicsTable(
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 1.80 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
@@ -124,11 +133,15 @@ void G4MultipleScattering::BuildPhysicsTable(
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.42 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
}
// ..............................
Tlow = aParticleType.GetPDGMass();
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius;
@@ -143,13 +156,14 @@ void G4MultipleScattering::BuildPhysicsTable(
}
// create table
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
theTransportMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t i=0; i<numOfCouples; i++)
{
// create physics vector and fill it
@@ -157,13 +171,14 @@ void G4MultipleScattering::BuildPhysicsTable(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4Material* material = (*theMaterialTable)[J];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
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++)
{
@@ -194,6 +209,7 @@ void G4MultipleScattering::BuildPhysicsTable(
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
@@ -314,11 +330,11 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
G4double ParticleMass = aParticleType.GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// compute equivalent kinetic energy
// lambda depends on p*beta ....
G4double Mass = ParticleMass ;
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
(aParticleType.GetParticleName() != "e+") )
{
// TAU = Tkin/ParticleMass , tau = Tkin_scaled/electronmass
// p*beta = Mass*TAU*(TAU+2.)/(TAU+1.) =
@@ -434,15 +450,17 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering::GetContinuousStepLimit(
const G4Track& track,
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength;
const G4DynamicParticle* aParticle;
G4Material* aMaterial;
G4double KineticEnergy,tau,z0,kz;
G4double tau,zt,cz,cz1,grej,grej0;
const G4double expmax = 100., ztmax = (2.*expmax+1.)/(2.*expmax+3.) ;
const G4double tmax = 1.e20*mm ;
G4bool isOut;
// this process is not a candidate for selection by default
@@ -450,20 +468,28 @@ G4double G4MultipleScattering::GetContinuousStepLimit(
tPathLength = currentMinimumStep;
aMaterial = track.GetMaterial();
materialIndex = aMaterial->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
materialIndex = couple->GetIndex();
aParticle = track.GetDynamicParticle();
KineticEnergy = aParticle->GetKineticEnergy();
T0 = aParticle->GetKineticEnergy();
lambda0 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T0,isOut);
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
range = G4EnergyLossTables::GetRange(aParticle->GetDefinition(),
KineticEnergy,aMaterial);
T0,couple);
//VI Initialisation at the beginning of the step
cthm = 1.;
lambda1 = -1.;
lambdam = -1.;
alam = range;
blam = 1.+alam/lambda0 ;
zm = 1.;
// special treatment near boundaries ?
if (boundary)
if (boundary && range >= currentMinimumStep)
{
// step limitation at boundary ?
stepno = track.GetCurrentStepNumber() ;
@@ -471,125 +497,165 @@ G4double G4MultipleScattering::GetContinuousStepLimit(
{
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
}
if(stepno > 1)
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
// if : diff.treatment for small/not small Z
if(range > fTransportMeanFreePath)
if(range > lambda0)
tlimit = facrange*range ;
else
tlimit = facrange*fTransportMeanFreePath ;
tlimit = facrange*lambda0 ;
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((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
}
}
}
// do the true -> geom transformation
lambda1 = -1.;
z1 = 1.e10 ;
zmean = tPathLength;
tau = tPathLength/fTransportMeanFreePath ;
if(tau < tausmall) zPathLength = tPathLength;
tau = tPathLength/lambda0 ;
if (tau < tausmall || range < currentMinimumStep) zPathLength = tPathLength;
else
{
if(tPathLength/range < dtrl) zmean = fTransportMeanFreePath*(1.-exp(-tau));
if(tPathLength/range < dtrl) zmean = lambda0*(1.-exp(-tau));
else
{
{
T1 = G4EnergyLossTables::GetPreciseEnergyFromRange(
aParticle->GetDefinition(),range-0.5*tPathLength,aMaterial);
aParticle->GetDefinition(),range-tPathLength,couple);
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;
if(T0 < Tlow)
alam = range ;
else
alam = lambda0*tPathLength/(lambda0-lambda1) ;
blam = 1.+alam/lambda0 ;
if(tPathLength/range < 2.*dtrl)
{
zmean = alam*(1.-exp(blam*log(1.-tPathLength/alam)))/blam ;
lambdam = -1. ;
}
else
{
G4double w = 1.-0.5*tPathLength/alam ;
lambdam = lambda0*w ;
clam = 1.+alam/lambdam ;
cthm = exp(alam*log(w)/lambda0) ;
zm = alam*(1.-exp(blam*log(w)))/blam ;
zmean = zm + alam*(1.-exp(clam*log(w)))*cthm/clam ;
}
}
// sample z
if ((pcz > 0.) && (2.*zmean > tPathLength))
zt = zmean/tPathLength ;
if (samplez && (zt < ztmax) && (zt > 0.5))
{
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;
cz = 0.5*(3.*zt-1.)/(1.-zt) ;
if(tPathLength < exp(log(tmax)/(2.*cz)))
{
cz1 = 1.+cz ;
grej0 = exp(cz1*log(cz*tPathLength/cz1))/cz ;
do
{
zPathLength = tPathLength*exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(zPathLength))*(tPathLength-zPathLength)/grej0 ;
} while (grej < G4UniformRand()) ;
}
else zPathLength = zmean;
}
else zPathLength = zmean;
}
// protection against z > lambda
if(zPathLength > lambda0)
zPathLength = lambda0 ;
tLast = tPathLength;
zLast = zPathLength;
zLast = zPathLength;
return zPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScattering::AlongStepDoIt(
const G4Track& track,const G4Step& Step)
{
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;
G4double geomPathLength = step.GetStepLength();
lambda1 = -1.;
}
else
{
if ((geomPathLength-z1)/(cth1*lambda1) < 1.)
truePathLength = 0.5*tLast-lambda1
*log(1.-(geomPathLength-z1)/(cth1*lambda1));
else truePathLength = range;
}
}
G4double truePathLength = 0. ;
//VI change order of if operators
if(geomPathLength == zLast) truePathLength = tLast;
else if(geomPathLength/lambda0 < tausmall) truePathLength = geomPathLength;
else
{
if(lambda1 < 0.) truePathLength = -lambda0*log(1.-geomPathLength/lambda0) ;
else if(lambdam < 0.)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = tLast;
}
else
{
if(geomPathLength <= zm)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = 0.5*tLast;
lambdam = -1. ;
}
else
{
if(clam*(geomPathLength-zm)/(alam*cthm) < 1.)
truePathLength = 0.5*tLast + alam*(1.-
exp(log(1.-clam*(geomPathLength-zm)/(alam*cthm)))/clam) ;
else
truePathLength = tLast ;
}
}
// protection ....
if(truePathLength > tLast)
truePathLength = tLast ;
}
//VI truePath length cannot be smaller than geomPathLength
if (truePathLength < geomPathLength) truePathLength = geomPathLength;
fParticleChange.SetTrueStepLength(truePathLength);
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -599,8 +665,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
const G4Step& stepData)
{
// angle distribution parameters
const G4double kappapl1 = kappa+1., kappami1 = kappa-1. ;
G4bool isOut;
const G4double kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
fParticleChange.Initialize(trackData);
G4double truestep = stepData.GetStepLength();
@@ -608,30 +673,31 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
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
// do nothing for stopped particles !
if(KineticEnergy > 0.)
{
// change direction first ( scattering )
G4double cth = 1.0 ;
G4double tau = truestep/lambda0 ;
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(lambda1 > 0.)
{
if(lambdam < 0.)
tau = -alam*log(1.-truestep/alam)/lambda0 ;
else
tau = -log(cthm)-alam*log(1.-(truestep-0.5*tLast)/alam)/lambdam ;
}
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 ;
@@ -642,11 +708,11 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
else
a = (alfa1+alfa3*w)/tau ;
x0 = 1.-xsi/a ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
@@ -659,7 +725,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
b1 = b+1. ;
bx=b-x0 ;
@@ -669,7 +735,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
xmeanth = exp(-tau) ;
cnorm1 = a/eaa ;
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
@@ -697,10 +763,9 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
cth = -1.+2.*G4UniformRand() ;
cth = -1.+2.*G4UniformRand() ;
}
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
@@ -716,13 +781,13 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean, etau;
if (safetyminustolerance > 0.)
{
if (tau < tausmall) rmean = 0.;
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6. ;
else
{
@@ -733,7 +798,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
rmean += tau-kappapl1/kappa+kappa*etau/kappami1;
}
if (rmean>0.) rmean = 2.*fTransportMeanFreePath*sqrt(rmean/3.);
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.);
else rmean = 0.;
// for rmean > 0) only
@@ -751,7 +816,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
@@ -761,6 +826,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
}
}
}
}
return &fParticleChange;
}
@@ -779,7 +845,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
@@ -793,6 +859,32 @@ G4bool G4MultipleScattering::RetrievePhysicsTable(
const G4String& directory,
G4bool ascii)
{
// set values of some data members
G4String name = particle->GetParticleName();
if(name == "e-" || name == "e+")
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
// ..............................
Tlow = particle->GetPDGMass();
// delete theTransportMeanFreePathTable
if (theTransportMeanFreePathTable != 0) {
theTransportMeanFreePathTable->clearAndDestroy();
@@ -803,22 +895,25 @@ G4bool G4MultipleScattering::RetrievePhysicsTable(
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theTransportMeanFreePathTable =
theTransportMeanFreePathTable =
new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if (!theTransportMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (name == "e-" || name == "mu+" || name == "proton") PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
@@ -20,13 +20,13 @@
// * 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 $
// $Id: G4MultipleScatteringSTD.cc,v 1.18 2003/04/28 15:31:40 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -----------------------------------------------------------------------------
// 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)
@@ -52,8 +52,14 @@
// 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
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured from L.Urban
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 05-02-03 changes in data members, new sampling for geom.
// path length, step dependence reduced with new
// method (L.Urban)
// 13-04-03 add initialisation in GetContinuesStepLimit + change table size (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
//
// -----------------------------------------------------------------------------
//
@@ -65,13 +71,13 @@
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
#include "G4ProductionCutsTable.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),
@@ -83,16 +89,18 @@ G4MultipleScatteringSTD::G4MultipleScatteringSTD(const G4String& processName)
facrange(0.199),tlimit(1.e10*mm),tlimitmin(1.e-7*mm),
cf(1.001),
stepno(0),stepnolastmsc(-1000000),nsmallstep(5),
laststep(0.),
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),
zmean(0.),samplez(true),
range(1.),T0(1.),T1(1.),lambda0(1.),lambda1(-1.),
Tlow(0.),alam(1.),blam(1.),dtrl(0.15),
lambdam(-1.),clam(1.),zm(1.),cthm(1.),
fLatDisplFlag(true),
NuclCorrPar (0.0615),
FactPar(0.40),
facxsi(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScatteringSTD::~G4MultipleScatteringSTD()
@@ -111,12 +119,13 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 1.80 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
@@ -125,10 +134,13 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.42 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
}
Tlow = aParticleType.GetPDGMass();
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
@@ -144,13 +156,14 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
}
// create table
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
theTransportMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t i=0; i<numOfCouples; i++)
{
// create physics vector and fill it
@@ -158,13 +171,14 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4Material* material = (*theMaterialTable)[J];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
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++)
{
@@ -317,12 +331,12 @@ G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
G4double ParticleMass = aParticleType.GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/ParticleMass ;
G4double c = ParticleMass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
@@ -367,7 +381,7 @@ G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
@@ -391,10 +405,10 @@ G4double G4MultipleScatteringSTD::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 c1,c2,cc1,cc2,corr;
if (Charge < 0.)
{
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
@@ -429,20 +443,21 @@ G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
return sigma;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
const G4Track& track,
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength;
const G4DynamicParticle* aParticle;
G4Material* aMaterial;
G4double KineticEnergy,tau,z0,kz;
G4double tau,zt,cz,cz1,grej,grej0;
const G4double expmax = 100., ztmax = (2.*expmax+1.)/(2.*expmax+3.) ;
const G4double tmax = 1.e20*mm ;
G4bool isOut;
G4LossTableManager* theManager = G4LossTableManager::Instance();
@@ -452,20 +467,27 @@ G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
tPathLength = currentMinimumStep;
aMaterial = track.GetMaterial();
materialIndex = aMaterial->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
materialIndex = couple->GetIndex();
aParticle = track.GetDynamicParticle();
KineticEnergy = aParticle->GetKineticEnergy();
T0 = aParticle->GetKineticEnergy();
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
lambda0 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T0,isOut);
range = theManager->GetRange(aParticle->GetDefinition(),
KineticEnergy,aMaterial);
T0,couple);
//VI Initialisation at the beginning of the step
cthm = 1.;
lambda1 = -1.;
lambdam = -1.;
alam = range;
blam = 1.+alam/lambda0 ;
zm = 1.;
// special treatment near boundaries ?
if (boundary)
if (boundary && range >= currentMinimumStep)
{
// step limitation at boundary ?
stepno = track.GetCurrentStepNumber() ;
@@ -473,126 +495,169 @@ G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
{
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
}
if(stepno > 1)
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
// if : diff.treatment for small/not small Z
if(range > fTransportMeanFreePath)
if(range > lambda0)
tlimit = facrange*range ;
else
tlimit = facrange*fTransportMeanFreePath ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
tlimit = facrange*lambda0 ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
laststep = tlimit ;
if(tPathLength > tlimit)
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
else if(stepno > stepnolastmsc)
{
if((stepno - stepnolastmsc) < nsmallstep)
if((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
}
}
}
// do the true -> geom transformation
lambda1 = -1.;
z1 = 1.e10 ;
zmean = tPathLength;
tau = tPathLength/fTransportMeanFreePath ;
if(tau < tausmall) zPathLength = tPathLength;
tau = tPathLength/lambda0 ;
//G4cout << "StepLimit: tpl= " << tPathLength << " lambda0= " << lambda0
// << " range= " << range << " currentMinStep= " << currentMinimumStep << G4endl;
if(tau < tausmall || range < currentMinimumStep ) zPathLength = tPathLength;
else
{
if(tPathLength/range < dtrl) zmean = fTransportMeanFreePath*(1.-exp(-tau));
if(tPathLength/range < dtrl) zmean = lambda0*(1.-exp(-tau));
else
{
{
T1 = theManager->GetEnergy(
aParticle->GetDefinition(),range-0.5*tPathLength,aMaterial);
aParticle->GetDefinition(),range-tPathLength,couple);
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;
if(T0 < Tlow)
alam = range ;
else
alam = lambda0*tPathLength/(lambda0-lambda1) ;
blam = 1.+alam/lambda0 ;
if(tPathLength/range < 2.*dtrl)
{
zmean = alam*(1.-exp(blam*log(1.-tPathLength/alam)))/blam ;
lambdam = -1. ;
}
else
{
G4double w = 1.-0.5*tPathLength/alam ;
lambdam = lambda0*w ;
clam = 1.+alam/lambdam ;
cthm = exp(alam*log(w)/lambda0) ;
zm = alam*(1.-exp(blam*log(w)))/blam ;
zmean = zm + alam*(1.-exp(clam*log(w)))*cthm/clam ;
}
}
// sample z
if ((pcz > 0.) && (2.*zmean > tPathLength))
zt = zmean/tPathLength ;
if (samplez && (zt < ztmax) && (zt > 0.5))
{
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;
cz = 0.5*(3.*zt-1.)/(1.-zt) ;
if(tPathLength < exp(log(tmax)/(2.*cz)))
{
cz1 = 1.+cz ;
grej0 = exp(cz1*log(cz*tPathLength/cz1))/cz ;
do
{
zPathLength = tPathLength*exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(zPathLength))*(tPathLength-zPathLength)/grej0 ;
} while (grej < G4UniformRand()) ;
}
else zPathLength = zmean;
}
else zPathLength = zmean;
}
// protection against z > lambda
if(zPathLength > lambda0)
zPathLength = lambda0 ;
tLast = tPathLength;
zLast = zPathLength;
zLast = zPathLength;
return zPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScatteringSTD::AlongStepDoIt(
const G4Track& track,const G4Step& Step)
{
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;
G4double geomPathLength = step.GetStepLength();
lambda1 = -1.;
}
else
{
if ((geomPathLength-z1)/(cth1*lambda1) < 1.)
truePathLength = 0.5*tLast-lambda1
*log(1.-(geomPathLength-z1)/(cth1*lambda1));
else truePathLength = range;
}
}
G4double truePathLength = 0. ;
if(geomPathLength == zLast) truePathLength = tLast;
else if(geomPathLength/lambda0 < tausmall) truePathLength = geomPathLength;
else
{
// G4cout << "alam= " << alam << " blam= " << blam << " lambda1= " << lambda1 << G4endl;
if(lambda1 < 0.) truePathLength = -lambda0*log(1.-geomPathLength/lambda0) ;
else if(lambdam < 0.)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = tLast;
}
else
{
if(geomPathLength <= zm)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = 0.5*tLast;
lambdam = -1. ;
}
else
{
//G4cout << "clam= " << clam << " zm= " << zm << " cthm= " << cthm << G4endl;
if(clam*(geomPathLength-zm)/(alam*cthm) < 1.)
truePathLength = 0.5*tLast + alam*(1.-
exp(log(1.-clam*(geomPathLength-zm)/(alam*cthm)))/clam) ;
else
truePathLength = tLast ;
}
}
// G4cout << "tLenth= " << truePathLength << " tpl= " << tLast << G4endl;
// protection ....
if(truePathLength > tLast)
truePathLength = tLast ;
}
//VI truePath length cannot be smaller than geomPathLength
if (truePathLength < geomPathLength) truePathLength = geomPathLength;
//G4cout << "AlongStep: trueLength= " << truePathLength << " geomLength= "
// << geomPathLength << " zlast= " << zLast << G4endl;
fParticleChange.SetTrueStepLength(truePathLength);
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -602,8 +667,7 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
const G4Step& stepData)
{
// angle distribution parameters
const G4double kappapl1 = kappa+1., kappami1 = kappa-1. ;
G4bool isOut;
const G4double kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
fParticleChange.Initialize(trackData);
G4double truestep = stepData.GetStepLength();
@@ -611,29 +675,31 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
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
// do nothing for stopped particles !
if(KineticEnergy > 0.)
{
// change direction first ( scattering )
G4double cth = 1. ;
G4double tau = truestep/lambda0 ;
//G4cout << "tau= " << tau << " lambda1= " << lambda1 << " lambdam= " << lambdam << G4endl;
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(lambda1 > 0.)
{
if(lambdam < 0.)
tau = -alam*log(1.-truestep/alam)/lambda0 ;
else
tau = -log(cthm)-alam*log(1.-(truestep-0.5*tLast)/alam)/lambdam ;
}
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 ;
@@ -645,11 +711,11 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
else
a = (alfa1+alfa3*w)/tau ;
x0 = 1.-xsi/a ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
@@ -661,9 +727,8 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
b1 = b+1. ;
bx=b-x0 ;
@@ -673,7 +738,7 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
xmeanth = exp(-tau) ;
cnorm1 = a/eaa ;
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
@@ -688,11 +753,18 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
if(qprob > 1.)
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
// *******************************************
// sampling of costheta
/*
G4cout << "tau= " << tau << " prob= " << prob << " qprob= " << qprob << G4endl;
G4cout << "ea= " << ea << " eaa= " << eaa << " a= " << a
<< " b= " << b << " b1= " << b1 << " bx= " << bx
<< " ebx= " << ebx << " eb1= " << eb1 << " c= " << c
<< G4endl;
*/
if(G4UniformRand() < qprob)
{
if(G4UniformRand() < prob)
@@ -704,12 +776,13 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
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;
//G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << tLast << G4endl;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz);
@@ -717,34 +790,35 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
fParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z());
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean, etau;
if (safetyminustolerance > 0.)
G4double rmean = 0.0;
if (safetyminustolerance > 0. && tau>=tausmall)
{
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6. ;
if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau*0.25)/6. ;
else
{
G4double etau = 0.0;
if(tau<taubig) etau = exp(-tau);
else etau = 0.;
rmean = -kappa*tau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += tau-kappapl1/kappa+kappa*etau/kappami1;
//G4cout << "tau= " << tau << " lambda0= " << lambda0 << " etau= " << etau << " kappa= " << kappa << G4endl;
}
if (rmean>0.) rmean = 2.*fTransportMeanFreePath*sqrt(rmean/3.);
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.0);
else rmean = 0.;
// for rmean > 0) only
if (rmean > 0.)
{
if (rmean>safetyminustolerance) rmean = safetyminustolerance;
//G4cout << "r= " << rmean << " safety= " << safetyminustolerance << G4endl;
// sample direction of lateral displacement
phi = twopi*G4UniformRand();
dirx = cos(phi); diry = sin(phi); dirz = 0.;
@@ -755,7 +829,7 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
@@ -765,14 +839,14 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
}
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4MultipleScatteringSTD::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
const G4String& directory,
G4bool ascii)
{
G4String filename;
@@ -783,9 +857,9 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
@@ -794,9 +868,34 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
G4bool G4MultipleScatteringSTD::RetrievePhysicsTable(
G4ParticleDefinition* particle,
const G4String& directory,
const G4String& directory,
G4bool ascii)
{
// set values of some data members
G4String name = particle->GetParticleName();
if(name == "e-" || name == "e+")
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
Tlow = particle->GetPDGMass();
// delete theTransportMeanFreePathTable
if (theTransportMeanFreePathTable != 0) {
theTransportMeanFreePathTable->clearAndDestroy();
@@ -807,22 +906,25 @@ G4bool G4MultipleScatteringSTD::RetrievePhysicsTable(
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theTransportMeanFreePathTable =
theTransportMeanFreePathTable =
new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if (!theTransportMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (name == "e-" || name == "mu+" || name == "proton") PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScatteringSTD::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
@@ -830,10 +932,14 @@ void G4MultipleScatteringSTD::PrintInfoDefinition()
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< "\n PhysicsTables from "
<< G4BestUnit(LowestKineticEnergy ,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
if(1 < verboseLevel) {
G4cout << "LambdaTable address= " << theTransportMeanFreePathTable << G4endl;
if(theTransportMeanFreePathTable) G4cout << (*theTransportMeanFreePathTable) << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -29,10 +29,16 @@
// File name: G4SCProcessorStand
//
// Author: Vladimir Ivanchenko
//
//
// Creation date: 10.05.2002
//
// Modifications: 09.12.2002 VI remove warning
// Modifications:
//
// 09-12-02 remove warning (V.Ivanchenko)
// 23-12-02 change interface in order to move to cut per region (V.Ivanchenko)
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
//
// -------------------------------------------------------------------
@@ -46,73 +52,63 @@
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4EmModelManager.hh"
#include "G4MaterialTable.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4VEmModel.hh"
#include "Randomize.hh"
#include "G4Step.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4SCProcessorStand::G4SCProcessorStand()
: G4VSubCutoffProcessor(),
G4SCProcessorStand::G4SCProcessorStand(const G4String& nam)
: G4VSubCutoffProcessor(nam),
theLambdaSubTable(0),
thePositron(G4Positron::Positron()),
modelManager(0)
thePositron(G4Positron::Positron())
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4SCProcessorStand::~G4SCProcessorStand()
{
if(theLambdaSubTable) theLambdaSubTable->clearAndDestroy();
}
G4SCProcessorStand::~G4SCProcessorStand()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4SCProcessorStand::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
G4EmModelManager* m)
const G4ParticleDefinition* sp,
const G4DataVector* vCuts,
const G4DataVector* vSubCuts)
{
particle = p;
secondaryParticle = sp;
modelManager = m;
navigator = (G4TransportationManager::GetTransportationManager())
->GetNavigatorForTracking();
theCuts = modelManager->Cuts();
theSubCuts = modelManager->Cuts();
theCuts = vCuts;
theSubCuts = vSubCuts;
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)
G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
const G4Step& step,
G4double& tmax,
G4double& meanLoss,
G4VEmModel* currentModel)
{
G4bool b;
const G4Material* mat = (step.GetTrack())->GetMaterial();
const G4Track* track = step.GetTrack();
const G4MaterialCutsCouple* couple = track->GetMaterialCutsCouple();
if(mat != material) {
material = mat;
materialIndex = material->GetIndex();
cut = (*theCuts)[materialIndex];
subcut = (*theSubCuts)[materialIndex];
rcut = rangeCuts[materialIndex];
}
size_t index = couple->GetIndex();
G4double subcut = (*theSubCuts)[index];
if(subcut >= cut) return 0;
if(subcut >= tmax) return 0;
G4double cut = (*theCuts)[index];
G4double rcut = couple->GetProductionCuts()->GetProductionCut(1);
const G4DynamicParticle* dp = track->GetDynamicParticle();
G4double ekin = dp->GetKineticEnergy();
G4double effChargeFactor = 1.0;
G4double massRatio = 1.0;
@@ -123,9 +119,9 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
massRatio = initialMass/mass;
G4double q = particle->GetPDGCharge()/dp->GetCharge();
effChargeFactor = q*q;
}
}
G4double cross = (*theLambdaSubTable)[materialIndex]->GetValue(ekin*massRatio, b);
G4double cross = (*theLambdaSubTable)[index]->GetValue(ekin*massRatio, b);
if(0.0 >= cross) return 0;
@@ -135,7 +131,7 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
G4double postsafety = navigator->ComputeSafety(postpoint);
G4double safety = G4std::min(presafety,postsafety);
if(safety >= rcut) return 0;
G4ThreeVector prepoint = pre->GetPosition();
G4ThreeVector dr = postpoint - prepoint;
@@ -145,7 +141,6 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
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 {
@@ -153,10 +148,10 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
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);
dt += del * inv_v;
G4std::vector<G4DynamicParticle*>* newp =
currentModel->SampleSecondaries(couple, dp, subcut, cut);
if (newp) {
G4DynamicParticle* p;
@@ -183,7 +178,7 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
return vtr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -33,6 +33,10 @@
//
// Modifications:
//
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
//
// -------------------------------------------------------------------
@@ -51,8 +55,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4UniversalFluctuation::G4UniversalFluctuation()
:G4VEmFluctuationModel(),
G4UniversalFluctuation::G4UniversalFluctuation(const G4String& nam)
:G4VEmFluctuationModel(nam),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minLoss(0.000001*eV),
@@ -74,94 +78,67 @@ G4UniversalFluctuation::~G4UniversalFluctuation()
void G4UniversalFluctuation::Initialise(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
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)
G4double 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
// 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(meanLoss < minLoss) return meanLoss;
if(dp->GetDefinition() != particle) {
particleMass = dp->GetMass();
G4double q = dp->GetCharge();
chargeSquare = q*q;
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);
ipotFluct = material->GetIonisation()->GetMeanExcitationEnergy();
G4double gam = (dp->GetKineticEnergy())/particleMass + 1.0;
G4double gam2 = gam*gam;
G4double beta2 = 1.0 - 1.0/gam2;
// 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)) ;
}
*/
electronDensity = material->GetElectronDensity();
siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare ;
siga = sqrt(siga);
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0.);
} while (loss < 0. || loss > 2.*meanLoss);
meanLoss = loss;
if(lastMaterial != material) lastMaterial = material;
return;
return loss;
}
// 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();
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;
}
@@ -173,7 +150,7 @@ void G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
G4double dp3;
w1 = tmax/ipotFluct;
w2 = log(2.*electron_mass_c2*tau2);
w2 = log(2.*electron_mass_c2*(gam2 - 1.0));
C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
@@ -315,7 +292,43 @@ void G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
}
}
meanLoss = loss;
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4UniversalFluctuation::Dispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length)
{
electronDensity = material->GetElectronDensity();
G4double gam = (dp->GetKineticEnergy())/particleMass + 1.0;
G4double beta2 = 1.0 - 1.0/(gam*gam);
G4double siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare;
return siga;
}
/*
// High velocity or negatively charged particle
zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
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)) ;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VEnergyLoss.cc,v 1.33 2002/07/22 10:55:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4VEnergyLoss.cc,v 1.40 2003/04/04 14:33:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// --------------------------------------------------------------
@@ -32,21 +32,26 @@
// bug fixed in fluct., L.Urban 22/11/00
// bugfix in fluct.
// (some variables are doubles instead of ints now),L.Urban 23/03/01
// 18/05/01 V.Ivanchenko Clean up againist Linux ANSI compilation
// 18/05/01 V.Ivanchenko Clean up againist Linux ANSI compilation
// 17-09-01 migration of Materials to pure STL (mma)
// 26-10-01 static inline functions moved from .hh file (mma)
// 26-10-01 static inline functions moved from .hh file (mma)
// 08.11.01 some static methods,data members are not static L.Urban
// 11.02.02 subSecFlag = false --> No sucutoff generation (mma)
// 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
// 21.07.02 V.Ivanchenko Fix at low energies - if tmax below ionisation
// potential then only Gaussian fluctuations are sampled.
//
// 15.01.03 Migrade to cut per region (V.Ivanchenko)
// 05.02.03 Minor fix for several region case (V.Ivanchenko)
// 25.03.03 add finalRangeRequested (mma)
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VEnergyLoss.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4ProductionCutsTable.hh"
#include "G4LossTableManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -61,6 +66,7 @@ G4bool G4VEnergyLoss::setMinDeltaCutInRange = false;
G4double G4VEnergyLoss::dRoverRange = 20*perCent;
G4double G4VEnergyLoss::finalRange = 1*mm;
G4double G4VEnergyLoss::finalRangeRequested = -1*mm;
G4double G4VEnergyLoss::c1lim = dRoverRange;
G4double G4VEnergyLoss::c2lim = 2.*(1.-dRoverRange)*finalRange;
G4double G4VEnergyLoss::c3lim = -(1.-dRoverRange)*finalRange*finalRange;
@@ -86,8 +92,9 @@ G4VEnergyLoss::G4VEnergyLoss(const G4String& aName , G4ProcessType aType)
nmaxCont1(4),
nmaxCont2(16)
{
//create (only once) EnergyLoss messenger
if(!ELossMessenger) ELossMessenger = new G4EnergyLossMessenger();
//create (only once) EnergyLoss messenger
// if(!ELossMessenger) ELossMessenger = new G4EnergyLossMessenger();
if(!ELossMessenger) ELossMessenger = G4LossTableManager::Instance()->GetMessenger();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -125,20 +132,20 @@ void G4VEnergyLoss::SetMinDeltaCutInRange(G4double value)
void G4VEnergyLoss::SetStepFunction(G4double c1, G4double c2)
{
dRoverRange = c1; finalRange = c2;
dRoverRange = c1; finalRangeRequested = c2;
c1lim=dRoverRange;
c2lim=2.*(1-dRoverRange)*finalRange;
c3lim=-(1.-dRoverRange)*finalRange*finalRange;
c2lim=2.*(1-dRoverRange)*finalRangeRequested;
c3lim=-(1.-dRoverRange)*finalRangeRequested*finalRangeRequested;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
G4double LowestKineticEnergy,G4double HighestKineticEnergy,G4int TotBin)
// Build range table from the energy loss table
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theDEDXTable->length();
if(theRangeTable)
{ theRangeTable->clearAndDestroy();
@@ -147,7 +154,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector;
aVector = new G4PhysicsLogVector(LowestKineticEnergy,
@@ -158,7 +165,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
theRangeTable->insert(aVector);
}
return theRangeTable ;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -373,15 +380,15 @@ G4PhysicsTable* G4VEnergyLoss::BuildLabTimeTable(G4PhysicsTable* theDEDXTable,
G4double HighestKineticEnergy,G4int TotBin)
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theDEDXTable->length();
if(theLabTimeTable)
{ theLabTimeTable->clearAndDestroy();
delete theLabTimeTable; }
theLabTimeTable = new G4PhysicsTable(numOfMaterials);
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector;
@@ -403,17 +410,17 @@ G4PhysicsTable* G4VEnergyLoss::BuildProperTimeTable(G4PhysicsTable* theDEDXTable
G4PhysicsTable* theProperTimeTable,
G4double LowestKineticEnergy,
G4double HighestKineticEnergy,G4int TotBin)
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theDEDXTable->length();
if(theProperTimeTable)
{ theProperTimeTable->clearAndDestroy();
delete theProperTimeTable; }
theProperTimeTable = new G4PhysicsTable(numOfMaterials);
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector;
@@ -629,7 +636,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRangeTa
{
G4double SmallestRange,BiggestRange ;
G4bool isOut ;
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theRangeTable->length();
if(theInverseRangeTable)
{ theInverseRangeTable->clearAndDestroy();
@@ -637,7 +644,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRangeTa
theInverseRangeTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
SmallestRange = (*theRangeTable)(J)->
GetValue(LowestKineticEnergy,isOut) ;
@@ -723,7 +730,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffATable(G4PhysicsTable* theRangeTab
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "A"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfMaterials = theRangeTable->length();
if(theRangeCoeffATable)
{ theRangeCoeffATable->clearAndDestroy();
@@ -784,7 +791,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffBTable(G4PhysicsTable* theRangeTab
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "B"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfMaterials = theRangeTable->length();
if(theRangeCoeffBTable)
{ theRangeCoeffBTable->clearAndDestroy();
@@ -844,7 +851,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRangeTab
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "C"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfMaterials = theRangeTable->length();
if(theRangeCoeffCTable)
{ theRangeCoeffCTable->clearAndDestroy();
@@ -898,27 +905,27 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRangeTab
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
const G4MaterialCutsCouple* couple,
G4double ChargeSquare,
G4double MeanLoss,
G4double step )
// calculate actual loss from the mean loss
// The model used to get the fluctuation is essentially the same as in Glandz in Geant3.
{
const G4double minLoss = 1.*eV ;
const G4double probLim = 0.01 ;
const G4double sumaLim = -log(probLim) ;
const G4double alim=10.;
const G4double kappa = 10. ;
const G4double factor = twopi_mc2_rcl2 ;
const G4double minLoss = 1.*eV ;
const G4double probLim = 0.01 ;
const G4double sumaLim = -log(probLim) ;
const G4double alim=10.;
const G4double kappa = 10. ;
const G4double factor = twopi_mc2_rcl2 ;
const G4Material* aMaterial = couple->GetMaterial();
// check if the material has changed ( cache mechanism)
if (aMaterial != lastMaterial)
{
lastMaterial = aMaterial;
imat = aMaterial->GetIndex();
imat = couple->GetIndex();
f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
@@ -938,14 +945,15 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4double dp3;
G4double siga ;
// shortcut for very very small loss
// shortcut for very very small loss
if(MeanLoss < minLoss) return MeanLoss ;
// get particle data
G4double Tkin = aParticle->GetKineticEnergy();
ParticleMass = aParticle->GetMass() ;
threshold =((G4Electron::Electron())->GetEnergyCuts())[imat];
threshold = (*((G4ProductionCutsTable::GetProductionCutsTable())
->GetEnergyCutsVector(1)))[imat];
G4double rmass = electron_mass_c2/ParticleMass;
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
@@ -1058,7 +1066,7 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
loss = p1*e1Fluct+p2*e2Fluct;
// smearing to avoid unphysical peaks
if(p2 > 0)
loss += (1.-2.*G4UniformRand())*e2Fluct;
loss += (1.-2.*G4UniformRand())*e2Fluct;
else if (loss>0.)
loss += (1.-2.*G4UniformRand())*e1Fluct;
@@ -1124,7 +1132,7 @@ G4bool G4VEnergyLoss::EqualCutVectors( G4double* vec1, G4double* vec2 )
for (size_t j=0; flag && j<G4Material::GetNumberOfMaterials(); j++){
flag = (vec1[j] == vec2[j]);
}
return flag;
}
@@ -1141,3 +1149,21 @@ G4double* G4VEnergyLoss::CopyCutVectors( G4double* dest, G4double* source )
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4VEnergyLoss::CutsWhereModified()
{
G4bool wasModified = false;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for (size_t j=0; j<numOfCouples; j++){
if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
wasModified = true;
break;
}
}
return wasModified;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,339 @@
//
// ********************************************************************
// * 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: G4VMultipleScattering
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
// Creation date: 25.03.2003
//
// Modifications: 13.04.03 Change printout (V.Ivanchenko)
//
//
// Class Description:
//
// It is the generic process of multiple scattering it includes common
// part of calculations for all charged particles
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VMultipleScattering.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 "G4UnitsTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4RegionStore.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VMultipleScattering::G4VMultipleScattering(const G4String& name, G4ProcessType type):
G4VContinuousDiscreteProcess(name, type),
navigator(0),
theLambdaTable(0),
currentCouple(0),
nBins(110),
minKinEnergy(1.0*eV),
maxKinEnergy(100.0*GeV),
boundary(false),
latDisplasment(true),
buildLambdaTable(true)
{
modelManager = new G4EmModelManager();
(G4LossTableManager::Instance())->Register(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VMultipleScattering::~G4VMultipleScattering()
{
(G4LossTableManager::Instance())->DeRegister(this);
delete modelManager;
if (theLambdaTable) {
theLambdaTable->clearAndDestroy();
delete theLambdaTable;
}
(G4LossTableManager::Instance())->DeRegister(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part)
{
currentCouple = 0;
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::BuildPhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< G4endl;
}
G4bool cutsWasModified = false;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for (size_t j=0; j<numOfCouples; j++){
if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
cutsWasModified = true;
break;
}
}
if( !cutsWasModified ) return;
InitialiseProcess(part);
if(latDisplasment) navigator = G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
modelManager->Clear();
const G4DataVector* theCuts = modelManager->Initialise(&part, 0, 10.0, verboseLevel);
if (buildLambdaTable) {
theLambdaTable = new G4PhysicsTable(numOfCouples);
for (size_t i=0; i<numOfCouples; i++) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
G4PhysicsVector* aVector = PhysicsVector(couple);
modelManager->FillLambdaVector(aVector, couple, false);
// Insert vector for this material into the table
theLambdaTable->insert(aVector) ;
}
if(0 < verboseLevel) {
G4cout << "Lambda table is built for "
<< part.GetParticleName()
<< G4endl;
}
if(2 < verboseLevel) G4cout << *theLambdaTable << G4endl;
if(5 < verboseLevel) G4cout << theCuts << G4endl;
}
G4String num = part.GetParticleName();
if (verboseLevel>0 || num == "e-" || num == "mu+" || num == "proton")
PrintInfoDefinition();
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::BuildPhysicsTable() done for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::AddEmModel(G4int order, G4VEmModel* p,
const G4Region* region)
{
G4VEmFluctuationModel* fm = 0;
modelManager->AddEmModel(order, p, fm, region);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VMultipleScattering::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
fParticleChange.Initialize(track);
G4double kineticEnergy = track.GetKineticEnergy();
G4double truestep = step.GetStepLength();
if (kineticEnergy > 0.0) {
G4double cth = currentModel->SampleCosineTheta(truestep);
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi);
G4double diry = sth*sin(phi);
G4ThreeVector oldDirection = track.GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,cth);
newDirection.rotateUz(oldDirection);
fParticleChange.SetMomentumChange(newDirection);
/*
if(0 < verboseLevel) {
const G4ParticleDefinition* pd = dynParticle->GetDefinition();
G4cout << "G4VMultipleScattering::PostStepDoIt: Sample secondary; E= " << finalT/MeV
<< " MeV; model= (" << currentModel->LowEnergyLimit(pd)
<< ", " << currentModel->HighEnergyLimit(pd) << ")"
<< G4endl;
}
*/
// G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << truePathLength << G4endl;
if (latDisplasment) {
G4double safety = step.GetPostStepPoint()->GetSafety();
if ( safety > 0.0) {
G4double r = currentModel->SampleDisplacement();
if (r > safety) r = safety;
// G4cout << "r= " << r << " safety= " << safety << G4endl;
// sample direction of lateral displacement
G4double phi = twopi*G4UniformRand();
G4double dirx = cos(phi);
G4double diry = sin(phi);
G4ThreeVector latDirection(dirx,diry,0.0);
latDirection.rotateUz(oldDirection);
// compute new endpoint of the Step
G4ThreeVector newPosition = (step.GetPostStepPoint())->GetPosition()
+ r*latDirection;
navigator->LocateGlobalPointWithinVolume(newPosition);
fParticleChange.SetPositionChange(newPosition);
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::PrintInfoDefinition() const
{
G4cout << G4endl << GetProcessName() << ": Model variant of multiple scattering " << G4endl;
if (theLambdaTable) {
G4cout << " Lambda tables from "
<< G4BestUnit(MinKinEnergy(),"Energy")
<< " to "
<< G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << nBins << " bins."
<< G4endl;
}
if (1 < verboseLevel) {
G4cout << "LambdaTable address= " << theLambdaTable << G4endl;
if(theLambdaTable) G4cout << (*theLambdaTable) << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VMultipleScattering::PhysicsVector(const G4MaterialCutsCouple* couple)
{
G4int nbins = 3;
//G4int nbins = nDEDXBins;
if( couple->IsUsed() ) nbins = nBins;
// G4double xmax = maxKinEnergy*exp( log(maxKinEnergy/minKinEnergy) / ((G4double)(nbins-1)) );
G4PhysicsVector* v = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nbins);
return v;
}
G4bool G4VMultipleScattering::StorePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
G4bool res = true;
if ( theLambdaTable ) {
const G4String name = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
G4bool yes = theLambdaTable->StorePhysicsTable(name,ascii);
if( !yes ) res = false;
}
if ( res ) {
G4cout << "Physics table are stored for " << part->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
} else {
G4cout << "Fail to store Physics Table for " << part->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
}
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4VMultipleScattering::RetrievePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::RetrievePhysicsTable() for "
<< part->GetParticleName() << " and process "
<< GetProcessName() << G4endl;
}
G4bool res = true;
if(!buildLambdaTable) return res;
G4String num = part->GetParticleName();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4String filename = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
theLambdaTable = new G4PhysicsTable(numOfCouples);
res = theLambdaTable->RetrievePhysicsTable(filename,ascii);
if ( res ) {
if (0 < verboseLevel) {
G4cout << "Lambda table for " << num << " is retrieved from <"
<< filename << ">"
<< G4endl;
}
} else {
theLambdaTable->clearAndDestroy();
theLambdaTable = 0;
if (0 < verboseLevel) {
G4cout << "Lambda table for " << num << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
}
if (verboseLevel>0 || num == "e-" || num == "mu+" || num == "proton")
PrintInfoDefinition();
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....