Import Geant4 5.2.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 10:28:22 +02:00
parent fbd4999cf7
commit 4aea781e80
5454 changed files with 223141 additions and 67347 deletions
@@ -101,7 +101,7 @@ G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::MinEnergyCut(const G4ParticleDefinition* p,
G4double G4BetheBlochModel::MinEnergyCut(const G4ParticleDefinition*,
const G4MaterialCutsCouple* couple)
{
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
@@ -201,7 +201,7 @@ G4double G4BetheBlochModel::CrossSection(const G4Material* material,
G4double maxEnergy)
{
G4double cross = 0.0;
G4double tmax = G4std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
G4double tmax = std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
if(cutEnergy < tmax) {
G4double x = cutEnergy/tmax;
@@ -232,14 +232,14 @@ G4double G4BetheBlochModel::CrossSection(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DynamicParticle* G4BetheBlochModel::SampleSecondary(
const G4MaterialCutsCouple* couple,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
G4double xmax = G4std::min(tmax, maxEnergy)/tmax;
G4double xmax = std::min(tmax, maxEnergy)/tmax;
if(xmin >= xmax) return 0;
G4ThreeVector momentum = dp->GetMomentumDirection();
@@ -306,13 +306,13 @@ G4DynamicParticle* G4BetheBlochModel::SampleSecondary(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
@@ -33,6 +33,7 @@
//
// Modifications:
//
// 23-05-03 Add control on parthalogical cases (V.Ivanchenko)
//
// Class Description: Sampling of Gaussion fluctuations
//
@@ -51,8 +52,11 @@
G4BohrFluctuations::G4BohrFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
particle(0),
minNumberInteractionsBohr(10.0),
minFraction(0.2)
minFraction(0.2),
xmin(0.2),
minLoss(0.000001*eV)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -78,32 +82,42 @@ G4double G4BohrFluctuations::SampleFluctuations(const G4Material* material,
G4double& length,
G4double& meanLoss)
{
if(meanLoss <= minLoss) return meanLoss;
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
G4double navr = minNumberInteractionsBohr;
// Gaussian fluctuation
if (meanLoss >= minNumberInteractionsBohr*tmax) {
G4bool gauss = true;
if (meanLoss < minNumberInteractionsBohr*tmax) {
navr = meanLoss*meanLoss/siga;
if (navr < minNumberInteractionsBohr) gauss = false;
}
if(gauss) {
// 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);
if(b2 < xmin*beta2) b2 = xmin*beta2;
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);
G4double lossmax = meanLoss+meanLoss;
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0. || loss > 2.*meanLoss);
loss = G4RandGauss::shoot(meanLoss,siga);
} while (0.0 > loss || loss > lossmax);
// Poisson fluctuations
} else {
G4double navr = meanLoss*meanLoss/siga;
G4double n = (G4double)G4Poisson(navr);
G4double n = (G4double)(G4Poisson(navr));
loss = meanLoss*n/navr;
}
return loss;
}
@@ -38,6 +38,7 @@
// 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)
// 04-06-03 Fix compilation warnings (V.Ivanchenko)
// Class Description:
//
@@ -106,7 +107,7 @@ G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::MinEnergyCut(const G4ParticleDefinition* p,
G4double G4BraggModel::MinEnergyCut(const G4ParticleDefinition*,
const G4MaterialCutsCouple* couple)
{
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
@@ -169,7 +170,7 @@ G4double G4BraggModel::CrossSection(const G4Material* material,
{
G4double cross = 0.0;
G4double tmax = G4std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
G4double tmax = std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
if(cutEnergy < tmax) {
G4double x = cutEnergy/tmax;
@@ -195,7 +196,7 @@ G4DynamicParticle* G4BraggModel::SampleSecondary(
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
G4double xmax = G4std::min(tmax, maxEnergy)/tmax;
G4double xmax = std::min(tmax, maxEnergy)/tmax;
if(xmin >= xmax) return 0;
G4double kineticEnergy = dp->GetKineticEnergy();
@@ -247,13 +248,13 @@ G4DynamicParticle* G4BraggModel::SampleSecondary(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
@@ -274,12 +275,12 @@ G4bool G4BraggModel::HasMaterial(const G4Material* material)
// ICRU Report N49, 1993. Power's model for He.
const size_t numberOfMolecula = 11 ;
static G4String name[numberOfMolecula] = {
static G4String molName[numberOfMolecula] = {
"Al_2O_3", "CO_2", "CH_4",
"(C_2H_4)_N-Polyethylene", "(C_2H_4)_N-Polypropylene", "(C_8H_8)_N",
"C_3H_8", "SiO_2", "H_2O",
"H_2O-Gas", "Graphite" } ;
"H_2O-Gas", "Graphite" } ;
// Special treatment for water in gas state
const G4State theState = material->GetState() ;
@@ -287,11 +288,11 @@ G4bool G4BraggModel::HasMaterial(const G4Material* material)
if( theState == kStateGas && myFormula == chFormula) {
chFormula = G4String("H_2O-Gas");
}
// Search for the material in the table
for (size_t i=0; i<numberOfMolecula; i++) {
if (chFormula == name[i]) {
SetMoleculaNumber(i) ;
if (chFormula == molName[i]) {
SetMoleculaNumber(i) ;
return true ;
}
}
@@ -319,7 +320,7 @@ G4double G4BraggModel::StoppingPower(const G4Material* material,
G4double T = kineticEnergy/(keV*protonMassAMU) ;
static G4double a[11][5] = {
{1.187E+1, 1.343E+1, 1.069E+4, 7.723E+2, 2.153E-2},
{1.187E+1, 1.343E+1, 1.069E+4, 7.723E+2, 2.153E-2},
{7.802E+0, 8.814E+0, 8.303E+3, 7.446E+2, 7.966E-3},
{7.294E+0, 8.284E+0, 5.010E+3, 4.544E+2, 8.153E-3},
{8.646E+0, 9.800E+0, 7.066E+3, 4.581E+2, 9.383E-3},
@@ -328,7 +329,7 @@ G4double G4BraggModel::StoppingPower(const G4Material* material,
{1.604E+1, 1.825E+1, 6.967E+3, 2.307E+3, 3.775E-2},
{8.049E+0, 9.099E+0, 9.257E+3, 3.846E+2, 1.007E-2},
{4.015E+0, 4.542E+0, 3.955E+3, 4.847E+2, 7.904E-3},
{4.571E+0, 5.173E+0, 4.346E+3, 4.779E+2, 8.572E-3},
{4.571E+0, 5.173E+0, 4.346E+3, 4.779E+2, 8.572E-3},
{2.631E+0, 2.601E+0, 1.701E+3, 1.279E+3, 1.638E-2} };
@@ -480,7 +481,7 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
// Free electron gas model
} else if ( T < 10.0 ) {
fac = sqrt(T*0.1) ;
T =10.0 ;
T =10.0 ;
}
// Main parametrisation
@@ -585,9 +586,9 @@ G4bool G4BraggModel::MolecIsInZiegler1988(const G4Material* material)
const size_t numberOfMolecula = 53 ;
// The coffecient from Table.4 of Ziegler & Manoyan
const G4double HeEff = 2.8735 ;
const G4double HeEff = 2.8735 ;
static G4String name[numberOfMolecula] = {
static G4String nameOfMol[numberOfMolecula] = {
"H_2O", "C_2H_4O", "C_3H_6O", "C_2H_2", "C_H_3OH",
"C_2H_5OH", "C_3H_7OH", "C_3H_4", "NH_3", "C_14H_10",
"C_6H_6", "C_4H_10", "C_4H_6", "C_4H_8O", "CCl_4",
@@ -600,9 +601,9 @@ G4bool G4BraggModel::MolecIsInZiegler1988(const G4Material* material)
"(C_3H_6)_N","(C_8H_8)_N", "C_3H_8", "C_3H_6-Propylene", "C_3H_6O",
"C_3H_6S", "C_4H_4S", "C_7H_8"
} ;
static G4double expStopping[numberOfMolecula] = {
66.1, 190.4, 258.7, 42.2, 141.5,
66.1, 190.4, 258.7, 42.2, 141.5,
210.9, 279.6, 198.8, 31.0, 267.5,
122.8, 311.4, 260.3, 328.9, 391.3,
206.6, 374.0, 422.0, 432.0, 398.0,
@@ -616,7 +617,7 @@ G4bool G4BraggModel::MolecIsInZiegler1988(const G4Material* material)
} ;
static G4double expCharge[numberOfMolecula] = {
HeEff, HeEff, HeEff, 1.0, HeEff,
HeEff, HeEff, HeEff, 1.0, HeEff,
HeEff, HeEff, HeEff, 1.0, 1.0,
1.0, HeEff, HeEff, HeEff, HeEff,
HeEff, HeEff, HeEff, HeEff, HeEff,
@@ -630,7 +631,7 @@ G4bool G4BraggModel::MolecIsInZiegler1988(const G4Material* material)
} ;
static G4double numberOfAtomsPerMolecula[numberOfMolecula] = {
3.0, 7.0, 10.0, 4.0, 6.0,
3.0, 7.0, 10.0, 4.0, 6.0,
9.0, 12.0, 7.0, 4.0, 24.0,
12.0, 14.0, 10.0, 13.0, 5.0,
5.0, 14.0, 18.0, 17.0, 17.0,
@@ -645,9 +646,9 @@ G4bool G4BraggModel::MolecIsInZiegler1988(const G4Material* material)
// Search for the compaund in the table
for (size_t i=0; i<numberOfMolecula; i++)
{
if(chFormula == name[i]) {
G4double exp125 = expStopping[i] *
{
if(chFormula == nameOfMol[i]) {
G4double exp125 = expStopping[i] *
(material->GetTotNbOfAtomsPerVolume()) /
(expCharge[i] * numberOfAtomsPerMolecula[i]) ;
SetExpStopPower125(exp125);
@@ -41,6 +41,7 @@
// 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)
// 13-05-03 Add calculation of precise range (V.Ivanchenko)
//
// Class Description:
//
@@ -70,7 +71,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::G4RegionModels(G4int nMod, G4std::vector<G4int>& list, G4DataVector& lowE)
G4RegionModels::G4RegionModels(G4int nMod, std::vector<G4int>& list, G4DataVector& lowE)
{
nModelsForRegion = nMod;
theListOfModelIndexes = new G4int [nModelsForRegion];
@@ -212,7 +213,7 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
// Identify the list of regions with different set of models
nRegions = 1;
G4std::vector<const G4Region*> set;
std::vector<const G4Region*> set;
set.push_back(world);
for (G4int ii=0; ii<nEmModels; ii++) {
@@ -245,7 +246,7 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
G4int n = 0;
G4std::vector<G4int> modelAtRegion;
std::vector<G4int> modelAtRegion;
G4DataVector eLow;
G4DataVector eHigh;
modelAtRegion.clear();
@@ -261,7 +262,7 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
G4double tmin = model->LowEnergyLimit(particle);
G4double tmax = model->HighEnergyLimit(particle);
if (n) tmin = G4std::max(tmin, eHigh[n-1]);
if (n) tmin = std::max(tmin, eHigh[n-1]);
if(1 < verboseLevel) {
G4cout << "Model # " << ii << " for region <"
@@ -322,9 +323,9 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
G4double tcutmin = model->MinEnergyCut(particle, couple);
cut = G4std::max(cut, tcutmin);
G4double x = G4std::max(cut*minSubRange, tcutmin);
subcut = G4std::max(subcut, x);
cut = std::max(cut, tcutmin);
G4double x = std::max(cut*minSubRange, tcutmin);
subcut = std::max(subcut, x);
if(1 < verboseLevel) {
G4cout << "The model # " << j
<< "; tcutmin(MeV)= " << tcutmin/MeV
@@ -450,6 +451,104 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillDEDXVectorForPreciseRange(
G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple)
{
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
G4DataVector dedxHigh;
G4double e;
const G4Material* material = couple->GetMaterial();
size_t i = couple->GetIndex();
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< material->GetName()
<< 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[regModels->ModelIndex(0)];
dedxHigh[0] = models[regModels->ModelIndex(0)]->ComputeDEDX(material,particle,e,e);
if(nmod > 1) {
for(j=1; j<nmod; j++) {
e = upperEkin[regModels->ModelIndex(j-1)];
dedxLow[j] = models[regModels->ModelIndex(j)]->ComputeDEDX(material,particle,e,e);
e = upperEkin[regModels->ModelIndex(j)];
dedxHigh[j] = models[regModels->ModelIndex(j)]->ComputeDEDX(material,particle,e,e);
}
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(1 < verboseLevel) {
G4cout << "Loop over " << totBinsLoss << " bins start " << G4endl;
}
}
// Calculate energy losses vector
for(j=0; j<totBinsLoss; j++) {
G4double e = aVector->GetLowEdgeEnergy(j);
G4double fac = 1.0;
// Choose a model of energy losses
G4int k = 0;
if (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 = models[regModels->ModelIndex(k)]->ComputeDEDX(material,particle,e,e)*fac;
if(dedx < 0.0) dedx = 0.0;
if(1 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< " fac= " << fac
<< G4endl;
}
aVector->PutValue(j, dedx);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossMessenger.cc,v 1.7 2003/04/04 14:33:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
// $Id: G4EnergyLossMessenger.cc,v 1.9 2003/06/16 17:02:45 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
//
//
@@ -40,7 +40,7 @@
#include "G4UIcmdWithABool.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "g4std/strstream"
#include <strstream>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -113,6 +113,12 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
IntegCmd->SetParameterName("integ",true);
IntegCmd->SetDefaultValue(true);
IntegCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
rangeCmd = new G4UIcmdWithABool("/process/eLoss/preciseRange",this);
rangeCmd->SetGuidance("Switch true/false the precise range calculation.");
rangeCmd->SetParameterName("range",true);
rangeCmd->SetDefaultValue(true);
rangeCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -128,6 +134,7 @@ G4EnergyLossMessenger::~G4EnergyLossMessenger()
delete MinEnCmd;
delete MaxEnCmd;
delete IntegCmd;
delete rangeCmd;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -159,7 +166,7 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
G4double v1,v2;
char unts[30];
const char* t = newValue;
G4std::istrstream is((char*)t);
std::istrstream is((char*)t);
is >> v1 >> v2 >> unts;
G4String unt = unts;
v2 *= G4UIcommand::ValueOf(unt);
@@ -177,6 +184,9 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
if (command == IntegCmd) {
lossTables->SetIntegral(IntegCmd->GetNewBoolValue(newValue));
}
if (command == rangeCmd) {
lossTables->SetBuildPreciseRange(IntegCmd->GetNewBoolValue(newValue));
}
}
@@ -22,7 +22,7 @@
//
//
// $Id: G4EnergyLossTables.cc,v 1.27 2003/04/18 17:49:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
// GEANT4 tag $Name: geant4-05-02 $
//
// -------------------------------------------------------------------
// first version created by P.Urban , 06/04/1998
@@ -36,6 +36,7 @@
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
// 23-05-03 Add control on parthalogical cases (V.Ivanchenko)
//
// Class Description:
//
@@ -56,9 +57,12 @@
G4IonFluctuations::G4IonFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
particle(0),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minFraction(0.2)
minFraction(0.2),
xmin(0.2),
minLoss(0.000001*eV)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -84,6 +88,7 @@ G4double G4IonFluctuations::SampleFluctuations(const G4Material* material,
G4double& length,
G4double& meanLoss)
{
if(meanLoss <= minLoss) return meanLoss;
if(dp->GetDefinition() != particle) {
particle = dp->GetDefinition();
@@ -94,27 +99,37 @@ G4double G4IonFluctuations::SampleFluctuations(const G4Material* material,
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
G4double navr = minNumberInteractionsBohr;
// Gaussian fluctuation
G4bool gauss = true;
if (meanLoss >= minNumberInteractionsBohr*tmax) {
navr = meanLoss*meanLoss/siga;
if (navr < minNumberInteractionsBohr) gauss = false;
}
if(gauss) {
// 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);
if(b2 < xmin*beta2) b2 = xmin*beta2;
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);
G4double lossmax = meanLoss+meanLoss;
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0. || loss > 2.*meanLoss);
loss = G4RandGauss::shoot(meanLoss,siga);
} while (0.0 > loss || loss > lossmax);
// Poisson fluctuations
} else {
G4double navr = meanLoss*meanLoss/siga;
G4double n = (G4double)G4Poisson(navr);
G4double n = (G4double)(G4Poisson(navr));
loss = meanLoss*n/navr;
}
@@ -50,7 +50,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildDEDXTable(
const G4std::vector<G4PhysicsTable*>& list)
const std::vector<G4PhysicsTable*>& list)
{
size_t n_processes = list.size();
@@ -112,7 +112,8 @@ G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
G4PhysicsLogVector* v = new G4PhysicsLogVector(elow, ehigh, nbins);
G4double dedx1 = pv->GetValue(elow, b);
G4double range = 0.5*elow/dedx1;
G4double range = 0.5*elow/dedx1;
// G4double range = elow/dedx1;
v->PutValue(0,range);
G4double energy1 = elow;
@@ -142,7 +143,7 @@ G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
const G4PhysicsTable* dedxTable,
const G4PhysicsTable*,
const G4PhysicsTable* rangeTable)
// Build inverse range table from the energy loss table
{
@@ -41,6 +41,7 @@
// 25-03-03 Add deregistration (V.Ivanchenko)
// 02-04-03 Change messenger (V.Ivanchenko)
// 26-04-03 Fix retrieve tables (V.Ivanchenko)
// 13-05-03 Add calculation of precise range (V.Ivanchenko)
//
// Class Description:
//
@@ -109,6 +110,10 @@ G4LossTableManager::G4LossTableManager()
theElectron = G4Electron::Electron();
tableBuilder = new G4LossTableBuilder();
integral = true;
integralActive = false;
buildPreciseRange = false;
minEnergyActive = false;
maxEnergyActive = false;
verbose = 0;
}
@@ -148,6 +153,9 @@ void G4LossTableManager::Register(G4VEnergyLossSTD* p)
inv_range_vector.push_back(0);
tables_are_built.push_back(false);
all_tables_are_built = false;
if(integralActive) p->SetIntegral(integral);
if(minEnergyActive) p->SetMinKinEnergy(minKinEnergy);
if(maxEnergyActive) p->SetMaxKinEnergy(maxKinEnergy);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -443,9 +451,9 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
}
// Check is it new particle or all tables have to be rebuilt
G4std::vector<G4PhysicsTable*> list;
std::vector<G4PhysicsTable*> list;
list.clear();
G4std::vector<G4VEnergyLossSTD*> loss_list;
std::vector<G4VEnergyLossSTD*> loss_list;
loss_list.clear();
G4VEnergyLossSTD* em = 0;
G4int iem = 0;
@@ -490,11 +498,24 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
em->SetDEDXTable(dedx);
dedx_vector[iem] = dedx;
G4PhysicsTable* range = tableBuilder->BuildRangeTable(dedx);
em->SetRangeTable(range);
range_vector[iem] = range;
G4PhysicsTable* invrange = tableBuilder->BuildInverseRangeTable(dedx, range);
em->SetInverseRangeTable(invrange);
inv_range_vector[iem] = invrange;
if(buildPreciseRange) {
range->clearAndDestroy();
std::vector<G4PhysicsTable*> newlist;
for (G4int i=0; i<n_dedx; i++) {
newlist.push_back(loss_list[i]->BuildDEDXTableForPreciseRange());
}
G4PhysicsTable* dedxForRange = newlist[0];
if (1 < n_dedx) dedxForRange = tableBuilder->BuildDEDXTable(newlist);
range = tableBuilder->BuildRangeTable(dedx);
for(G4int j=0; j<n_dedx; j++) {
newlist[j]->clearAndDestroy();
}
}
em->SetRangeTable(range);
range_vector[iem] = range;
loss_map[aParticle] = em;
for (G4int j=0; j<n_dedx; j++) {
@@ -539,9 +560,10 @@ void G4LossTableManager::SetSubCutoff(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetIntegral(G4bool val)
void G4LossTableManager::SetIntegral(G4bool val)
{
integral = val;
integralActive = true;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetIntegral(val);
}
@@ -559,7 +581,7 @@ void G4LossTableManager::SetMinSubRange(G4double val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetRandomStep(G4bool val)
void G4LossTableManager::SetRandomStep(G4bool val)
{
rndmStepFlag = val;
for(G4int i=0; i<n_loss; i++) {
@@ -571,6 +593,7 @@ void G4LossTableManager::SetRandomStep(G4bool val)
void G4LossTableManager::SetMinEnergy(G4double val)
{
minEnergyActive = true;
minKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetMinKinEnergy(val);
@@ -581,6 +604,7 @@ void G4LossTableManager::SetMinEnergy(G4double val)
void G4LossTableManager::SetMaxEnergy(G4double val)
{
maxEnergyActive = true;
maxKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetMaxKinEnergy(val);
@@ -598,6 +622,13 @@ void G4LossTableManager::SetStepLimits(G4double v1, G4double v2)
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetBuildPreciseRange(G4bool val)
{
buildPreciseRange = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -26,7 +26,7 @@
// GEANT4 Class file
//
//
// File name: G4LewisModel
// File name: G4MscModel
//
// Author: Laszlo Urban
//
@@ -35,12 +35,20 @@
// Modifications:
//
// 27-03-03 Move model part from G4MultipleScattering (V.Ivanchenko)
// 23-05-03 important change in angle distribution for muons/hadrons
// the central part now is similar to the Highland parametrization +
// minor correction in angle sampling algorithm (for all particles)
// (L.Urban)
// 30-05-03 misprint in SampleCosineTheta corrected(L.Urban)
// 27-03-03 Rename (V.Ivanchenko)
// 04-06-03 Fix compilation warnings (V.Ivanchenko)
//
//
// Class Description:
//
// Implementation of Lewis model of multiple scattering
// H.W.Lewis Phys Rev 78 (1950) 526
// Implementation of the model of multiple scattering based on
// H.W.Lewis Phys Rev 78 (1950) 526 and others
// -------------------------------------------------------------------
//
@@ -49,7 +57,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LewisModel.hh"
#include "G4MscModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
#include "G4LossTableManager.hh"
@@ -57,7 +65,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LewisModel::G4LewisModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
G4MscModel::G4MscModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
G4double& m_FactPar, G4double& m_facxsi,
G4bool& m_samplez, const G4String& nam)
: G4VEmModel(nam),
@@ -76,20 +84,20 @@ G4LewisModel::G4LewisModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LewisModel::~G4LewisModel()
G4MscModel::~G4MscModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4LewisModel::IsInCharge(const G4ParticleDefinition* p)
G4bool G4MscModel::IsInCharge(const G4ParticleDefinition* p)
{
return (p->GetPDGCharge() != 0.0);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LewisModel::Initialise(const G4ParticleDefinition* p,
void G4MscModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
// set values of some data members
@@ -114,12 +122,14 @@ void G4LewisModel::Initialise(const G4ParticleDefinition* p,
c0 = 1.40 ;
}
sigmafactor = twopi*classic_electr_radius*classic_electr_radius;
particle = p;
mass = particle->GetPDGMass();
charge = particle->GetPDGCharge()/eplus;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::CrossSection(const G4Material* material,
G4double G4MscModel::CrossSection(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double,
@@ -150,8 +160,8 @@ G4double G4LewisModel::CrossSection(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::ComputeTransportCrossSection(
const G4ParticleDefinition* particle,
G4double G4MscModel::ComputeTransportCrossSection(
const G4ParticleDefinition* part,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicWeight)
@@ -266,50 +276,54 @@ G4double G4LewisModel::ComputeTransportCrossSection(
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 sigma;
if (part != particle ) {
particle = part;
mass = particle->GetPDGMass();
charge = particle->GetPDGCharge()/eplus;
}
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
G4double ParticleMass = particle->GetPDGMass();
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
// 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 eKineticEnergy = KineticEnergy;
if((particle->GetParticleName() != "e-") &&
(particle->GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/mass ;
G4double c = mass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
KineticEnergy = electron_mass_c2*tau ;
}
eKineticEnergy = electron_mass_c2*tau ;
}
G4double Charge = particle->GetPDGCharge();
G4double ChargeSquare = Charge*Charge/(eplus*eplus);
G4double ChargeSquare = charge*charge;
G4double TotalEnergy = KineticEnergy + electron_mass_c2 ;
G4double beta2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
/(TotalEnergy*TotalEnergy);
G4double bg2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
G4double eTotalEnergy = eKineticEnergy + electron_mass_c2 ;
G4double beta2 = eKineticEnergy*(eTotalEnergy+electron_mass_c2)
/(eTotalEnergy*eTotalEnergy);
G4double bg2 = eKineticEnergy*(eTotalEnergy+electron_mass_c2)
/(electron_mass_c2*electron_mass_c2);
G4double eps = epsfactor*bg2/Z23;
G4double eps = epsfactor*bg2/Z23;
if (eps<epsmin) sigma = 2.*eps*eps;
else if(eps<epsmax) sigma = log(1.+2.*eps)-2.*eps/(1.+2.*eps);
else sigma = log(2.*eps)-1.+1./eps;
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);
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*
G4double x0 = 1. - NuclCorrPar*mass/(KineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( x0 < -1. || KineticEnergy <= 10.*MeV)
if ( x0 < -1. || eKineticEnergy <= 10.*MeV)
{
x0 = -1.;
corrnuclsize = 1.;
@@ -323,7 +337,7 @@ G4double G4LewisModel::ComputeTransportCrossSection(
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
corrnuclsize = exp(-FactPar*mass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
@@ -340,9 +354,9 @@ G4double G4LewisModel::ComputeTransportCrossSection(
// 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 ;
while ((iT>=0)&&(Tdat[iT]>=eKineticEnergy)) iT -= 1;
if(iT==22) iT = 21;
if(iT==-1) iT = 0 ;
// calculate betasquare values
G4double T = Tdat[iT], E = T + electron_mass_c2;
@@ -352,7 +366,7 @@ G4double G4LewisModel::ComputeTransportCrossSection(
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double c1,c2,cc1,cc2,corr;
if (Charge < 0.)
if (charge < 0.)
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
@@ -366,7 +380,7 @@ G4double G4LewisModel::ComputeTransportCrossSection(
sigma /= corr;
}
if (Charge > 0.)
if (charge > 0.)
{
c1 = cpositron[iZ][iT];
c2 = cpositron[iZ+1][iT];
@@ -391,10 +405,10 @@ G4double G4LewisModel::ComputeTransportCrossSection(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::GeomPathLength(
G4double G4MscModel::GeomPathLength(
G4PhysicsTable* theLambdaTable,
const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* particle,
const G4ParticleDefinition* theParticle,
G4double& T0,
G4double lambda,
G4double range,
@@ -402,6 +416,14 @@ G4double G4LewisModel::GeomPathLength(
{
// do the true -> geom transformation
const G4double ztmin = 1./3., ztmax = 0.98 ;
if (theParticle != particle ) {
particle = theParticle;
mass = particle->GetPDGMass();
charge = particle->GetPDGCharge()/eplus;
}
currentKinEnergy = T0;
const G4Material* material = couple->GetMaterial();
currentRadLength = material->GetRadlen();
lambda0 = lambda;
lambda1 = -1.;
@@ -424,10 +446,10 @@ G4double G4LewisModel::GeomPathLength(
G4double T1 = theManager->GetEnergy(particle,range-tPathLength,couple);
if (theLambdaTable) {
G4bool b;
lambda1 = ((*theLambdaTable)[couple->GetIndex()])->GetValue(T1,b);
G4bool bb;
lambda1 = ((*theLambdaTable)[couple->GetIndex()])->GetValue(T1,bb);
} else {
lambda1 = CrossSection(couple->GetMaterial(),particle,T1,0.0,1.0);
lambda1 = CrossSection(material,particle,T1,0.0,1.0);
}
if (T0 > particle->GetPDGMass()) alam = lambda0*tPathLength/(lambda0-lambda1) ;
G4double blam = 1.+alam/lambda0 ;
@@ -456,7 +478,7 @@ G4double G4LewisModel::GeomPathLength(
u = exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(u))*(1.-u) ;
if (grej > grej0)
G4cout << "G4LewisModel: Warning! majorant "
G4cout << "G4MscModel: Warning! majorant "
<< grej0 << " < " << grej << G4endl;
} while (grej < grej0*G4UniformRand()) ;
zPathLength = tPathLength*u ;
@@ -467,12 +489,11 @@ G4double G4LewisModel::GeomPathLength(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::TrueStepLength(G4double geomStepLength)
G4double G4MscModel::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) ;
@@ -495,7 +516,6 @@ G4double G4LewisModel::TrueStepLength(G4double geomStepLength)
} 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) ;
@@ -503,7 +523,6 @@ G4double G4LewisModel::TrueStepLength(G4double geomStepLength)
trueLength = tPathLength;
}
}
// G4cout << "tLenth= " << trueLength << " tpl= " << tPathLength << G4endl;
if(trueLength > tPathLength) trueLength = tPathLength;
if(trueLength < geomStepLength) trueLength = geomStepLength;
}
@@ -513,15 +532,15 @@ G4double G4LewisModel::TrueStepLength(G4double geomStepLength)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::SampleCosineTheta(G4double trueStepLength)
G4double G4MscModel::SampleCosineTheta(G4double trueStepLength)
{
G4double cth = 1.;
currentTau = trueStepLength/lambda0;
// G4cout << "tau= " << currentTau << G4endl;
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)
{
@@ -538,61 +557,120 @@ G4double G4LewisModel::SampleCosineTheta(G4double trueStepLength)
{
const G4double amax = 25. ;
const G4double tau0 = 0.02 ;
const G4double c_highland = 13.6*MeV, corr_highland=0.038 ;
const G4double x1fac1 = exp(-xsi) ;
const G4double x1fac2 = (1.-(1.+xsi)*x1fac1)/(1.-x1fac1) ;
const G4double x1fac3 = 1.3 ; // x1fac3 >= 1. !!!!!!!!!
G4double a;
G4double w = log(currentTau/tau0) ;
if (currentTau < tau0) a = (alfa1-alfa2*w)/currentTau ;
else a = (alfa1+alfa3*w)/currentTau ;
// for heavy particles take the width of the cetral part
// from the Highland formula
// (Particle Physics Booklet, July 2002, eq. 26.10)
if(mass > electron_mass_c2) // + other conditions (beta, x/X0,...?)
{
G4double Q = abs(charge) ;
G4double xx0 = trueStepLength/currentRadLength;
G4double betacp = currentKinEnergy*(currentKinEnergy+2.*mass)/
(currentKinEnergy+mass) ;
G4double theta0 = c_highland*Q*sqrt(xx0)*
(1.+corr_highland*log(xx0))/betacp ;
G4double x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
if (theta0 > tausmall) a = 0.5/(1.-cos(theta0)) ;
else a = 1.0/(theta0*theta0) ;
// from continuity of the 1st derivatives
G4double c = a*(b-x0) ;
if(a*currentTau < c0) c = c0*(b-x0)/currentTau ;
}
else
{
G4double w = log(currentTau/tau0) ;
if (currentTau < tau0) a = (alfa1-alfa2*w)/currentTau ;
else a = (alfa1+alfa3*w)/currentTau ;
}
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
G4double xmeanth = exp(-currentTau);
G4double ea = 0.0;
if (a*(1.-x0) < amax) ea = exp(-a*(1.-x0)) ;
G4double xmean1,xmean2,eaa,b1,bx,ebx,eb1,c,qprob,prob;
G4double eaa = 1.-ea ;
G4double xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
G4double x0 = 1.-xsi/a;
G4double ea = 0.;
G4double b1 = b+1. ;
G4double bx = b-x0 ;
G4double eb1= exp((c-1.)*log(b1)) ;
G4double ebx= exp((c-1.)*log(bx)) ;
if (x0 <= -1.)
{
// 1 model fuction only
// in order to have xmean1 > xmeanth -> qprob < 1
x0 = -1.;
G4double xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
G4double xmeanth = exp(-currentTau) ;
if( a < 1./(1.-xmeanth)) a = 1./(1.-xmeanth) ;
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)) ;
if(a*(1.-x0) < amax) ea = exp(-a*(1.-x0));
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
// from continuity at x=x0
G4double prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
G4double qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
c = 2. ;
b1 = b+1. ;
bx = b1 ;
eb1 = b1 ;
ebx = b1 ;
xmean2 = 0. ;
// protection against qprob > 1
if(qprob > 1.)
prob = 1. ;
qprob = xmeanth/xmean1 ;
}
else
{
// 2 model fuctions
// in order to have xmean1 > xmeanth
if((1.-x1fac2/a) < xmeanth)
{
a = x1fac3*x1fac2/(1.-xmeanth) ;
if(a*(1.-x0) < amax) ea = exp(-a*(1.-x0));
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
}
else
{
ea = x1fac1 ;
eaa = 1.-ea ;
xmean1 = 1.-x1fac2/a ;
}
// from continuity of the 1st derivatives
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 ;
b1 = b+1. ;
bx=b-x0 ;
eb1=exp((c-1.)*log(b1)) ;
ebx=exp((c-1.)*log(bx)) ;
xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
G4double cnorm1 = a/eaa ;
G4double f1x0 = cnorm1*exp(-a*(1.-x0)) ;
G4double cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
G4double f2x0 = cnorm2/exp(c*log(b-x0)) ;
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
}
// protection against prob or qprob > 1 and
// prob or qprob < 0
if((qprob > 1.) || (qprob < 0.) || (prob > 1.) || (prob < 0.))
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
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)
{
@@ -608,13 +686,13 @@ G4double G4LewisModel::SampleCosineTheta(G4double trueStepLength)
}
}
}
// G4cout << "cth= " << cth << G4endl;
//G4cout << "cth= " << cth << G4endl;
return cth;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::SampleDisplacement()
G4double G4MscModel::SampleDisplacement()
{
const G4double kappa = 2.5;
const G4double kappapl1 = kappa+1.;
@@ -634,7 +712,7 @@ G4double G4LewisModel::SampleDisplacement()
}
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.0);
else rmean = 0.;
// G4cout << "rmean= " << rmean << G4endl;
// G4cout << "rmean= " << rmean << G4endl;
}
return rmean;
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4MultipleScattering.cc,v 1.39 2003/04/28 15:31:40 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
// $Id: G4MultipleScattering.cc,v 1.42 2003/05/30 06:40:25 urban Exp $
// GEANT4 tag $Name: geant4-05-02 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
@@ -58,8 +58,15 @@
// 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)
// 13-04-03 add initialisation in GetContinuesStepLimit
// + change table size (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (M.Asai)
// 23-05-03 important change in angle distribution for muons/hadrons
// the central part now is similar to the Highland parametrization +
// minor correction in angle sampling algorithm (for all particles)
// (L.Urban)
// 24-05-03 bug in nuclear size corr.computation fixed thanks to Vladimir(L.Urban)
// 30-05-03 misprint in PostStepDoIt corrected(L.Urban)
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -171,7 +178,8 @@ void G4MultipleScattering::BuildPhysicsTable(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4MaterialCutsCouple* couple = theCoupleTable->
GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume =
@@ -328,6 +336,7 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
G4double ParticleMass = aParticleType.GetPDGMass();
G4double ParticleKineticEnergy = KineticEnergy ;
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
@@ -336,9 +345,6 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
// TAU = Tkin/ParticleMass , tau = Tkin_scaled/electronmass
// p*beta = Mass*TAU*(TAU+2.)/(TAU+1.) =
// electron_mass_c2*tau*(tau+2.)/(tau+1.)
G4double TAU = KineticEnergy/Mass ;
G4double c = Mass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
@@ -368,9 +374,9 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
// ( a simple approximation at present)
G4double corrnuclsize,a,x0,w1,w2,w;
x0 = 1. - NuclCorrPar*ParticleMass/(KineticEnergy*
x0 = 1. - NuclCorrPar*ParticleMass/(ParticleKineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( (x0 < -1.) || (KineticEnergy <= 10.*MeV))
if ( (x0 < -1.) || (ParticleKineticEnergy <= 10.*MeV))
{ x0 = -1.; corrnuclsize = 1.;}
else
{ a = 1.+1./eps;
@@ -380,7 +386,7 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
corrnuclsize = exp(-FactPar*ParticleMass/ParticleKineticEnergy)*
(corrnuclsize-1.)+1.;
}
@@ -672,6 +678,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double Mass = aParticle->GetDefinition()->GetPDGMass() ;
// do nothing for stopped particles !
if(KineticEnergy > 0.)
@@ -697,62 +704,152 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
{
const G4double amax=25. ;
const G4double tau0 = 0.02 ;
const G4double c_highland = 13.6*MeV, corr_highland=0.038 ;
const G4double x1fac1 = exp(-xsi) ;
const G4double x1fac2 = (1.-(1.+xsi)*x1fac1)/(1.-x1fac1) ;
const G4double x1fac3 = 1.3 ; // x1fac3 >= 1. !!!!!!!!!
G4double a,x0,c,xmean1,xmean2,
xmeanth,prob,qprob ;
G4double ea,eaa,b1,bx,eb1,ebx,cnorm1,cnorm2,f1x0,f2x0,w ;
w = log(tau/tau0) ;
if(tau < tau0)
a = (alfa1-alfa2*w)/tau ;
// for heavy particles take the width of the cetral part
// from the Highland formula
// (Particle Physics Booklet, July 2002, eq. 26.10)
if(Mass > electron_mass_c2) // + other conditions (beta, x/X0,...?)
{
G4double Q = abs(aParticle->GetDefinition()->GetPDGCharge()) ;
G4double X0 = trackData.GetMaterialCutsCouple()->
GetMaterial()->GetRadlen() ;
G4double xx0 = truestep/X0 ;
G4double betacp = KineticEnergy*(KineticEnergy+2.*Mass)/
(KineticEnergy+Mass) ;
G4double theta0=c_highland*Q*sqrt(xx0)*
(1.+corr_highland*log(xx0))/betacp ;
if(theta0 > tausmall)
a = 0.5/(1.-cos(theta0)) ;
else
a = 1./(theta0*theta0) ;
}
else
a = (alfa1+alfa3*w)/tau ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
b1 = b+1. ;
bx=b-x0 ;
eb1=exp((c-1.)*log(b1)) ;
ebx=exp((c-1.)*log(bx)) ;
xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
{
w = log(tau/tau0) ;
if(tau < tau0)
a = (alfa1-alfa2*w)/tau ;
else
a = (alfa1+alfa3*w)/tau ;
}
xmeanth = exp(-tau) ;
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
x0 = 1.-xsi/a ;
if(x0 < -1.) x0 = -1. ;
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
// protection against qprob > 1
// *******************************************
if(qprob > 1.)
if(x0 == -1.)
{
// 1 model fuction only
// in order to have xmean1 > xmeanth -> qprob < 1
if((1.-1./a) < xmeanth)
a = 1./(1.-xmeanth) ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
c = 2. ;
b1 = b+1. ;
bx = b1 ;
eb1 = b1 ;
ebx = b1 ;
xmean2 = 0. ;
prob = 1. ;
qprob = xmeanth/xmean1 ;
}
else
{
// 2 model fuctions
// in order to have xmean1 > xmeanth
if((1.-x1fac2/a) < xmeanth)
{
a = x1fac3*x1fac2/(1.-xmeanth) ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
}
else
{
ea = x1fac1 ;
eaa = 1.-x1fac1 ;
xmean1 = 1.-x1fac2/a ;
}
// from continuity of the 1st derivatives
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
b1 = b+1. ;
bx=b-x0 ;
eb1=exp((c-1.)*log(b1)) ;
ebx=exp((c-1.)*log(bx)) ;
xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
cnorm1 = a/eaa ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
}
// protection against prob or qprob > 1 and
// prob or qprob < 0
// ***************************************************************
if((qprob > 1.) || (qprob < 0.) || (prob > 1.) || (prob < 0.))
{
// this print possibility has been left intentionally
// for debugging purposes ..........................
G4bool pr = false ;
// pr = true ;
if(pr)
{
const G4double prlim = 0.10 ;
if((abs((xmeanth-xmean2)/(xmean1-xmean2)-prob)/prob > prlim) ||
((xmeanth-xmean2)/(xmean1-xmean2) > 1.) ||
((xmeanth-xmean2)/(xmean1-xmean2) < 0.) )
{
G4cout.precision(5) ;
G4cout << "\nparticle=" << aParticle->GetDefinition()->
GetParticleName() << " in material "
<< trackData.GetMaterialCutsCouple()->
GetMaterial()->GetName() << " with kinetic energy "
<< KineticEnergy << " MeV," << G4endl ;
G4cout << " step length="
<< truestep << " mm" << G4endl ;
G4cout << "p=" << prob << " q=" << qprob << " -----> "
<< "p=" << (xmeanth-xmean2)/(xmean1-xmean2)
<< " q=" << 1. << G4endl ;
}
}
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
// *******************************************
// **************************************************************
// sampling of costheta
if(G4UniformRand() < qprob)
@@ -788,7 +885,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
if (safetyminustolerance > 0.)
{
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6. ;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6.;
else
{
if(tau<taubig) etau = exp(-tau);
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4MultipleScatteringSTD.cc,v 1.18 2003/04/28 15:31:40 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
// $Id: G4MultipleScatteringSTD.cc,v 1.22 2003/06/02 08:47:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-02 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
@@ -57,9 +57,8 @@
// 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)
// method
// 28-03-03 Move to model design (V.Ivanchenko)
//
// -----------------------------------------------------------------------------
//
@@ -67,879 +66,108 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4MultipleScatteringSTD.hh"
#include "G4LossTableManager.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
#include "G4ProductionCutsTable.hh"
#include "G4MscModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScatteringSTD::G4MultipleScatteringSTD(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(0),
taubig(8.0),tausmall(1.e-14),taulim(1.e-5),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
materialIndex(0),
tLast (0.0),
zLast (0.0),
boundary(true),
facrange(0.199),tlimit(1.e10*mm),tlimitmin(1.e-7*mm),
cf(1.001),
stepno(0),stepnolastmsc(-1000000),nsmallstep(5),
laststep(0.),
valueGPILSelectionMSC(NotCandidateForSelection),
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),
: G4VMultipleScattering(processName),
lowKineticEnergy(0.1*keV),
highKineticEnergy(100.*TeV),
totBins(100),
facrange(0.199),
tlimit(1.e10*mm),
tlimitmin(1.e-7*mm),
dtrl(0.15),
NuclCorrPar (0.0615),
FactPar(0.40),
facxsi(1.)
{ }
facxsi(1.0),
cf(1.001),
stepnolastmsc(-1000000),
nsmallstep(5),
samplez(true)
{
SetBinning(totBins);
SetMinKinEnergy(lowKineticEnergy);
SetMaxKinEnergy(highKineticEnergy);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScatteringSTD::~G4MultipleScatteringSTD()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScatteringSTD::InitialiseProcess(const G4ParticleDefinition& particle)
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
if (particle.GetParticleType() == "nucleus") {
SetBoundary(false);
SetLateralDisplasmentFlag(false);
SetBuildLambdaTable(false);
} else {
SetBoundary(true);
SetLateralDisplasmentFlag(true);
SetBuildLambdaTable(true);
}
G4VEmModel* em = new G4MscModel(dtrl,NuclCorrPar,FactPar,facxsi,samplez);
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em);
boundary = BoundaryAlgorithmFlag();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScatteringSTD::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
G4double G4MultipleScatteringSTD::TruePathLengthLimit(const G4Track& track,
G4double& lambda,
G4double currentMinimalStep)
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.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 ;
}
Tlow = aParticleType.GetPDGMass();
G4double tPathLength = currentMinimalStep;
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius;
G4double KineticEnergy,AtomicNumber,AtomicWeight,sigma,lambda;
G4double density;
// destroy old tables if any
if (theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
// create table
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theTransportMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (size_t i=0; i<numOfCouples; i++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
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++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i);
sigma = 0.;
// loop for element in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
AtomicNumber = (*theElementVector)[iel]->GetZ();
AtomicWeight = (*theElementVector)[iel]->GetA();
sigma += NbOfAtomsPerVolume[iel]*
ComputeTransportCrossSection(aParticleType,KineticEnergy,
AtomicNumber,AtomicWeight);
}
sigma *= sigmafactor;
lambda = 1./sigma;
aVector->PutValue(i,lambda);
}
theTransportMeanFreePathTable->insert(aVector);
}
if((aParticleType.GetParticleName() == "e-" ) ||
(aParticleType.GetParticleName() == "mu+" ) ||
(aParticleType.GetParticleName() == "proton") ) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,G4double AtomicWeight)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc);
const G4double epsmin = 1.e-4 , epsmax = 1.e10;
const G4double Zdat[15] = { 4., 6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. };
const G4double Tdat[23] = {0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,
0.01*MeV,0.02*MeV,0.04*MeV,0.07*MeV,
0.1*MeV,0.2*MeV,0.4*MeV,0.7*MeV,
1.*MeV,2.*MeV,4.*MeV,7.*MeV,10.*MeV,20.*MeV,
10000.0*MeV};
// corr. factors for e-/e+ lambda
G4double celectron[15][23] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087,0.7235 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082,0.7925 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098,0.9147 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098,0.9700 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056,1.0022 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052,1.0158 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050,1.0284 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036,1.0515 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024,1.0834 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020,1.0937 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011,1.1140 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987,1.1410 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963,1.1750 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954,1.1922 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, // paper.....
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949,1.2026 }};
G4double cpositron[15][23] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100,0.7235 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102,0.7925 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145,0.9147 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174,0.9700 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151,1.0022 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159,1.0158 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170,1.0284 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179,1.0515 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205,1.0834 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214,1.0937 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233,1.1140 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239,1.1410 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258,1.1750 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272,1.1922 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282,1.2026 }};
G4double sigma;
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
G4double ParticleMass = aParticleType.GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/ParticleMass ;
G4double c = ParticleMass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
KineticEnergy = electron_mass_c2*tau ;
}
G4double Charge = aParticleType.GetPDGCharge();
G4double ChargeSquare = Charge*Charge/(eplus*eplus);
G4double TotalEnergy = KineticEnergy + electron_mass_c2 ;
G4double beta2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
/(TotalEnergy*TotalEnergy);
G4double bg2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
/(electron_mass_c2*electron_mass_c2);
G4double eps = epsfactor*bg2/Z23;
if (eps<epsmin) sigma = 2.*eps*eps;
else if(eps<epsmax) sigma = log(1.+2.*eps)-2.*eps/(1.+2.*eps);
else sigma = log(2.*eps)-1.+1./eps;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/(beta2*bg2);
// nuclear size effect correction for high energy
// ( a simple approximation at present)
G4double corrnuclsize,a,x0,w1,w2,w;
x0 = 1. - NuclCorrPar*ParticleMass/(KineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( (x0 < -1.) || (KineticEnergy <= 10.*MeV))
{ x0 = -1.; corrnuclsize = 1.;}
else
{ a = 1.+1./eps;
if (eps > epsmax) w1=log(2.*eps)+1./eps-3./(8.*eps*eps);
else w1=log((a+1.)/(a-1.))-2./(a+1.);
w = 1./((1.-x0)*eps);
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber)) iZ -= 1;
if (iZ==14) iZ = 13;
if (iZ==-1) iZ = 0 ;
G4double Z1 = Zdat[iZ];
G4double Z2 = Zdat[iZ+1];
G4double ratZ = (AtomicNumber-Z1)/(Z2-Z1);
// get bin number in T (beta2)
G4int iT = 22;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy)) iT -= 1;
if(iT==22) iT = 21;
if(iT==-1) iT = 0 ;
// calculate betasquare values
G4double T = Tdat[iT], E = T + electron_mass_c2;
G4double b2small = T*(E+electron_mass_c2)/(E*E);
T = Tdat[iT+1]; E = T + electron_mass_c2;
G4double b2big = T*(E+electron_mass_c2)/(E*E);
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double c1,c2,cc1,cc2,corr;
if (Charge < 0.)
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = celectron[iZ][iT+1];
c2 = celectron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
if (Charge > 0.)
{
c1 = cpositron[iZ][iT];
c2 = cpositron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = cpositron[iZ][iT+1];
c2 = cpositron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
// nucl. size correction for particles other than e+/e- only at present !!!!
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
sigma /= corrnuclsize;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength;
const G4DynamicParticle* aParticle;
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();
// this process is not a candidate for selection by default
valueGPILSelectionMSC = NotCandidateForSelection;
tPathLength = currentMinimumStep;
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
materialIndex = couple->GetIndex();
aParticle = track.GetDynamicParticle();
T0 = aParticle->GetKineticEnergy();
lambda0 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T0,isOut);
range = theManager->GetRange(aParticle->GetDefinition(),
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 && range >= currentMinimumStep)
{
// step limitation at boundary ?
stepno = track.GetCurrentStepNumber() ;
if(stepno == 1)
{
if (boundary) {
G4int stepno = track.GetCurrentStepNumber() ;
// first step
if (stepno == 1) {
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
tlimit = 1.e10;
} else if (stepno > 1) {
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
if (track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary) {
stepnolastmsc = stepno;
// if : diff.treatment for small/not small Z
if(range > lambda0)
tlimit = facrange*range ;
else
tlimit = facrange*lambda0 ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
laststep = tlimit ;
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
else if(stepno > stepnolastmsc)
{
if((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
G4double range = CurrentRange();
if (range > lambda) tlimit = facrange*range;
else tlimit = facrange*lambda;
if(tlimit < tlimitmin) tlimit = tlimitmin;
if(tPathLength > tlimit) tPathLength = tlimit;
} else if (stepno > stepnolastmsc && stepno - stepnolastmsc < nsmallstep
&& tPathLength > tlimit) {
tlimit *= cf;
tPathLength = tlimit;
}
}
}
// do the true -> geom transformation
zmean = 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 = lambda0*(1.-exp(-tau));
else
{
T1 = theManager->GetEnergy(
aParticle->GetDefinition(),range-tPathLength,couple);
lambda1 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T1,isOut);
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
zt = zmean/tPathLength ;
if (samplez && (zt < ztmax) && (zt > 0.5))
{
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;
return zPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScatteringSTD::AlongStepDoIt(
const G4Track& track,const G4Step& step)
{
// only a geom path->true path transformation is performed
fParticleChange.Initialize(track);
G4double geomPathLength = step.GetStepLength();
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......
G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
// angle distribution parameters
const G4double kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
fParticleChange.Initialize(trackData);
G4double truestep = stepData.GetStepLength();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double KineticEnergy = aParticle->GetKineticEnergy();
// 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.)
{
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 ;
G4double a,x0,c,xmean1,xmean2,
xmeanth,prob,qprob ;
G4double ea,eaa,b1,bx,eb1,ebx,cnorm1,cnorm2,f1x0,f2x0,w ;
w = log(tau/tau0) ;
if(tau < tau0)
a = (alfa1-alfa2*w)/tau ;
else
a = (alfa1+alfa3*w)/tau ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
b1 = b+1. ;
bx=b-x0 ;
eb1=exp((c-1.)*log(b1)) ;
ebx=exp((c-1.)*log(bx)) ;
xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
xmeanth = exp(-tau) ;
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
// protection against qprob > 1
// *******************************************
if(qprob > 1.)
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
// *******************************************
// sampling of costheta
/*
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)
cth = 1.+log(ea+G4UniformRand()*eaa)/a ;
else
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
cth = -1.+2.*G4UniformRand() ;
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi), diry = sth*sin(phi), dirz = cth;
//G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << tLast << G4endl;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz);
newDirection.rotateUz(ParticleDirection);
fParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z());
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean = 0.0;
if (safetyminustolerance > 0. && tau>=tausmall)
{
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);
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.*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.;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection);
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
navigator->LocateGlobalPointWithinVolume(newPosition);
fParticleChange.SetPositionChange(newPosition);
}
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4MultipleScatteringSTD::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if (!theTransportMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4MultipleScatteringSTD::RetrievePhysicsTable(
G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// 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();
delete theTransportMeanFreePathTable;
}
G4String filename;
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theTransportMeanFreePathTable =
new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if (!theTransportMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (name == "e-" || name == "mu+" || name == "proton") PrintInfoDefinition();
return true;
return tPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScatteringSTD::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
comments += "\n New model of MSC , computes the lateral \n";
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowestKineticEnergy ,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
if(1 < verboseLevel) {
G4cout << "LambdaTable address= " << theTransportMeanFreePathTable << G4endl;
if(theTransportMeanFreePathTable) G4cout << (*theTransportMeanFreePathTable) << G4endl;
G4VMultipleScattering::PrintInfoDefinition();
if(boundary) {
G4cout << " Boundary algorithm is active with facrange= "
<< facrange
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -89,7 +89,7 @@ void G4SCProcessorStand::Initialise(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
std::vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
const G4Step& step,
G4double& tmax,
G4double& meanLoss,
@@ -129,7 +129,7 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
G4double presafety = pre->GetSafety();
G4ThreeVector postpoint = step.GetPostStepPoint()->GetPosition();
G4double postsafety = navigator->ComputeSafety(postpoint);
G4double safety = G4std::min(presafety,postsafety);
G4double safety = std::min(presafety,postsafety);
if(safety >= rcut) return 0;
@@ -141,7 +141,7 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
G4double length = step.GetStepLength();
G4double inv_v = (ekin + mass)/(c_light*dp->GetTotalMomentum());
G4std::vector<G4Track*>* vtr = new G4std::vector<G4Track*>;
std::vector<G4Track*>* vtr = new std::vector<G4Track*>;
do {
@@ -150,7 +150,7 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
if (fragment > 1.0) break;
dt += del * inv_v;
G4std::vector<G4DynamicParticle*>* newp =
std::vector<G4DynamicParticle*>* newp =
currentModel->SampleSecondaries(couple, dp, subcut, cut);
if (newp) {
@@ -57,6 +57,7 @@
G4UniversalFluctuation::G4UniversalFluctuation(const G4String& nam)
:G4VEmFluctuationModel(nam),
particle(0),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minLoss(0.000001*eV),
@@ -176,7 +177,7 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
p3 = std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
@@ -195,7 +196,7 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
p3 = std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
@@ -224,7 +225,7 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
if(a1>alim)
{
siga=sqrt(a1) ;
p1 = G4std::max(0,int(G4RandGauss::shoot(a1,siga)+0.5));
p1 = std::max(0,int(G4RandGauss::shoot(a1,siga)+0.5));
}
else
p1 = G4Poisson(a1);
@@ -233,7 +234,7 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
if(a2>alim)
{
siga=sqrt(a2) ;
p2 = G4std::max(0,int(G4RandGauss::shoot(a2,siga)+0.5));
p2 = std::max(0,int(G4RandGauss::shoot(a2,siga)+0.5));
}
else
p2 = G4Poisson(a2);
@@ -252,7 +253,7 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
p3 = std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
}
else
p3 = G4Poisson(a3);
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VEnergyLoss.cc,v 1.40 2003/04/04 14:33:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
// $Id: G4VEnergyLoss.cc,v 1.42 2003/06/16 17:02:50 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
//
// --------------------------------------------------------------
@@ -170,7 +170,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLoss::BuildRangeVector(G4PhysicsTable* theDEDXTable,
G4double LowestKineticEnergy,G4double HighestKineticEnergy,G4int TotBin,
G4double,G4double HighestKineticEnergy,G4int TotBin,
G4int materialIndex,G4PhysicsLogVector* rangeVector)
// create range vector for a material
{
@@ -439,7 +439,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildProperTimeTable(G4PhysicsTable* theDEDXTable
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLoss::BuildLabTimeVector(G4PhysicsTable* theDEDXTable,
G4double LowestKineticEnergy,
G4double,
G4double HighestKineticEnergy,G4int TotBin,
G4int materialIndex, G4PhysicsLogVector* timeVector)
// create lab time vector for a material
@@ -500,7 +500,7 @@ void G4VEnergyLoss::BuildLabTimeVector(G4PhysicsTable* theDEDXTable,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLoss::BuildProperTimeVector(G4PhysicsTable* theDEDXTable,
G4double LowestKineticEnergy,
G4double,
G4double HighestKineticEnergy,G4int TotBin,
G4int materialIndex, G4PhysicsLogVector* timeVector)
// create proper time vector for a material
@@ -1001,7 +1001,7 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
p3 = std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
}
else
p3 = G4float(G4Poisson(a3));
@@ -1020,7 +1020,7 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
p3 = std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
}
else
p3 = G4float(G4Poisson(a3));
@@ -1049,7 +1049,7 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
if(a1>alim)
{
siga=sqrt(a1) ;
p1 = G4std::max(0.,G4RandGauss::shoot(a1,siga)+0.5);
p1 = std::max(0.,G4RandGauss::shoot(a1,siga)+0.5);
}
else
p1 = G4float(G4Poisson(a1));
@@ -1058,7 +1058,7 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
if(a2>alim)
{
siga=sqrt(a2) ;
p2 = G4std::max(0.,G4RandGauss::shoot(a2,siga)+0.5);
p2 = std::max(0.,G4RandGauss::shoot(a2,siga)+0.5);
}
else
p2 = G4float(G4Poisson(a2));
@@ -1076,7 +1076,7 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
p3 = std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
}
else
p3 = G4float(G4Poisson(a3));
@@ -55,6 +55,11 @@
// 26-03-03 Remove finalRange modification (V.Ivanchenko)
// 09-04-03 Fix problem of negative range limit for non integral (V.Ivanchenko)
// 26-04-03 Fix retrieve tables (V.Ivanchenko)
// 06-05-03 Set defalt finalRange = 1 mm (V.Ivanchenko)
// 12-05-03 Update range calculations + lowKinEnergy (V.Ivanchenko)
// 13-05-03 Add calculation of precise range (V.Ivanchenko)
// 23-05-03 Remove tracking cuts (V.Ivanchenko)
// 03-06-03 Fix initialisation problem for STD ionisation (V.Ivanchenko)
//
// Class Description:
//
@@ -102,16 +107,25 @@ G4VEnergyLossSTD::G4VEnergyLossSTD(const G4String& name, G4ProcessType type):
theInverseRangeTable(0),
theLambdaTable(0),
theSubLambdaTable(0),
theDEDXAtMaxEnergy(0),
theRangeAtMaxEnergy(0),
particle(0),
baseParticle(0),
secondaryParticle(0),
theGamma(G4Gamma::Gamma()),
theElectron(G4Electron::Electron()),
currentCouple(0),
minKinEnergy(1.0*eV),
nDEDXBins(90),
nDEDXBinsForRange(70),
nLambdaBins(90),
faclow(1.5),
minKinEnergy(0.1*keV),
maxKinEnergy(100.0*GeV),
maxKinEnergyForRange(1.0*GeV),
lowKinEnergy(minKinEnergy*faclow),
linLossLimit(0.05),
minSubRange(0.1),
rangeCoeff(1.0),
lossFluctuationFlag(true),
rndmStepFlag(false),
hasRestProcess(true),
@@ -119,15 +133,14 @@ G4VEnergyLossSTD::G4VEnergyLossSTD(const G4String& name, G4ProcessType type):
integral(true),
meanFreePath(true)
{
// default dRoverRange and finalRange
SetStepLimits(0.2, 1.0*mm);
//SetVerboseLevel(0);
modelManager = new G4EmModelManager();
(G4LossTableManager::Instance())->Register(this);
scoffProcessors.clear();
scoffRegions.clear();
// default dRoverRange and finalRange
SetStepLimits(0.2, 200.0*micrometer);
// SetVerboseLevel(0);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -165,6 +178,8 @@ void G4VEnergyLossSTD::Clear()
if(theInverseRangeTable) theInverseRangeTable->clearAndDestroy();
if(theLambdaTable) theLambdaTable->clearAndDestroy();
if(theSubLambdaTable) theSubLambdaTable->clearAndDestroy();
if(theDEDXAtMaxEnergy) delete theDEDXAtMaxEnergy;
if(theRangeAtMaxEnergy) delete theRangeAtMaxEnergy;
}
theDEDXTable = 0;
@@ -173,6 +188,8 @@ void G4VEnergyLossSTD::Clear()
theSecondaryRangeTable = 0;
theLambdaTable = 0;
theSubLambdaTable = 0;
theDEDXAtMaxEnergy = 0;
theRangeAtMaxEnergy = 0;
modelManager->Clear();
tablesAreBuilt = false;
}
@@ -266,16 +283,18 @@ void G4VEnergyLossSTD::BuildPhysicsTable(const G4ParticleDefinition& part)
part.GetParticleSubType() == "generic")
{
(G4LossTableManager::Instance())->RegisterIon(&part, this);
/*
G4cout << part.GetProcessManager() << " "
<< (G4GenericIon::GenericIon())->GetProcessManager()
<< G4endl;
*/
return;
}
// Are particle defined?
if( !particle ) particle = &part;
if( !baseParticle ) baseParticle = DefineBaseParticle(particle);
//if( !baseParticle )
baseParticle = DefineBaseParticle(particle);
G4bool cutsWasModified = false;
const G4ProductionCutsTable* theCoupleTable=
@@ -423,6 +442,60 @@ G4PhysicsTable* G4VEnergyLossSTD::BuildDEDXTable()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4VEnergyLossSTD::BuildDEDXTableForPreciseRange()
{
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::BuildDEDXTableForPreciseRange() for "
<< GetProcessName()
<< " and particle " << particle->GetParticleName()
<< G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
G4DataVector dedxHigh;
// Access to materials
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4PhysicsTable* theTable = new G4PhysicsTable(numOfCouples);
if(0 < verboseLevel) {
G4cout << numOfCouples << " materials"
<< " minKinEnergy= " << minKinEnergy
<< " maxKinEnergy= " << maxKinEnergy
<< G4endl;
}
for(size_t i=0; i<numOfCouples; i++) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
G4PhysicsVector* aVector = DEDXPhysicsVectorForPreciseRange(couple);
modelManager->FillDEDXVectorForPreciseRange(aVector, couple);
// Insert vector for this material into the table
theTable->insert(aVector) ;
}
if(0 < verboseLevel) {
G4cout << "G4VEnergyLossSTD::BuildDEDXTableForPreciseRange(): table is built for "
<< particle->GetParticleName()
<< G4endl;
if(2 < verboseLevel) {
G4cout << *theTable << G4endl;
}
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4VEnergyLossSTD::BuildLambdaTable()
{
@@ -528,17 +601,15 @@ G4VParticleChange* G4VEnergyLossSTD::AlongStepDoIt(const G4Track& track,
<< G4endl;
}
*/
static const G4double faclow = 1.5;
// low energy deposit case
if (length >= fRange) {
eloss = preStepKinEnergy;
} else if(preStepScaledEnergy <= lowKinEnergy) {
} else if(preStepScaledEnergy < faclow*minKinEnergy) {
eloss = preStepKinEnergy*sqrt(length/fRange);
G4double x = 1.0 - length/fRange;
eloss = preStepKinEnergy*(1.0 - x*x);
// Short step
} else if( length <= linLossLimit * fRange ) {
eloss = (((*theDEDXTable)[currentMaterialIndex])->
@@ -547,10 +618,15 @@ G4VParticleChange* G4VEnergyLossSTD::AlongStepDoIt(const G4Track& track,
// Long step
} else {
G4double x = (fRange-length)/reduceFactor;
G4PhysicsVector* v = (*theInverseRangeTable)[currentMaterialIndex];
G4double postStepScaledEnergy = v->GetValue(x, b);
G4double postStepScaledEnergy = ((*theInverseRangeTable)[currentMaterialIndex])->
GetValue(x, b);
eloss = (preStepScaledEnergy - postStepScaledEnergy)/massRatio;
if (eloss <= 0.0) {
eloss = (((*theDEDXTable)[currentMaterialIndex])->
GetValue(preStepScaledEnergy, b))*length*chargeSqRatio;
}
/*
if(-1 < verboseLevel) {
G4cout << "fRange(mm)= " << fRange/mm
@@ -564,13 +640,11 @@ G4VParticleChange* G4VEnergyLossSTD::AlongStepDoIt(const G4Track& track,
}
*/
if(eloss <= 0.0) eloss = preStepKinEnergy*sqrt(length/fRange);
}
const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
G4double tmax = MaxSecondaryEnergy(dynParticle);
tmax = G4std::min(tmax,(*theCuts)[currentMaterialIndex]);
tmax = std::min(tmax,(*theCuts)[currentMaterialIndex]);
/*
//G4double eloss0 = eloss;
@@ -592,7 +666,7 @@ G4VParticleChange* G4VEnergyLossSTD::AlongStepDoIt(const G4Track& track,
*/
// Sample fluctuations
if (lossFluctuationFlag && eloss + minKinEnergy < preStepKinEnergy) {
if (lossFluctuationFlag && eloss < preStepKinEnergy && eloss > 0.0) {
eloss = modelManager->SampleFluctuations(currentMaterial, dynParticle,
tmax, length, eloss, preStepScaledEnergy,
@@ -610,7 +684,7 @@ G4VParticleChange* G4VEnergyLossSTD::AlongStepDoIt(const G4Track& track,
*/
// Subcutoff and/or deexcitation
G4std::vector<G4Track*>* newp =
std::vector<G4Track*>* newp =
SecondariesAlongStep(step, tmax, eloss, preStepScaledEnergy);
if(newp) {
@@ -645,7 +719,7 @@ G4VParticleChange* G4VEnergyLossSTD::AlongStepDoIt(const G4Track& track,
preStepKinEnergy -= eloss;
if (preStepKinEnergy < minKinEnergy) {
if (preStepKinEnergy <= 0.0) {
eloss += preStepKinEnergy;
preStepKinEnergy = 0.0;
@@ -697,8 +771,8 @@ G4VParticleChange* G4VEnergyLossSTD::PostStepDoIt(const G4Track& track,
if (tcut < tmax)
SecondariesPostStep(currentModel,currentCouple,dynParticle,tcut,finalT);
if (finalT < minKinEnergy) {
aParticleChange.SetLocalEnergyDeposit(finalT);
if (finalT <= 0.0) {
// aParticleChange.SetLocalEnergyDeposit(finalT);
aParticleChange.SetEnergyChange(0.0);
if (hasRestProcess) aParticleChange.SetStatusChange(fStopButAlive);
@@ -714,21 +788,30 @@ G4VParticleChange* G4VEnergyLossSTD::PostStepDoIt(const G4Track& track,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::PrintInfoDefinition() const
void G4VEnergyLossSTD::PrintInfoDefinition()
{
G4cout << G4endl << GetProcessName() << ": " << G4endl
<< " dE/dx and range tables from "
<< G4BestUnit(MinKinEnergy(),"Energy")
<< " to " << G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << DEDXBinning() << " bins." << G4endl
<< G4BestUnit(minKinEnergy,"Energy")
<< " to " << G4BestUnit(maxKinEnergy,"Energy")
<< " in " << nDEDXBins << " bins." << G4endl
<< " Lambda tables from threshold to "
<< G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << LambdaBinning() << " bins."
<< G4BestUnit(maxKinEnergy,"Energy")
<< " in " << nLambdaBins << " bins."
<< G4endl;
/*
G4cout << "DEDXTable address= " << theDEDXTable << G4endl;
if(theDEDXTable) G4cout << (*theDEDXTable) << G4endl;
G4cout << "RangeTable address= " << theRangeTable << G4endl;
if(theRangeTable) G4cout << (*theRangeTable) << G4endl;
G4cout << "InverseRangeTable address= " << theInverseRangeTable << G4endl;
if(theInverseRangeTable) G4cout << (*theInverseRangeTable) << G4endl;
*/
if(0 < verboseLevel) {
G4cout << "Tables are built for " << particle->GetParticleName()
<< " IntegralFlag= " << integral
<< G4endl;
if(2 < verboseLevel) {
G4cout << "DEDXTable address= " << theDEDXTable << G4endl;
if(theDEDXTable) G4cout << (*theDEDXTable) << G4endl;
@@ -756,6 +839,24 @@ void G4VEnergyLossSTD::SetDEDXTable(G4PhysicsTable* p)
void G4VEnergyLossSTD::SetRangeTable(G4PhysicsTable* p)
{
theRangeTable = p;
size_t n = p->length();
G4PhysicsVector* pv = (*p)[0];
G4bool b;
size_t nbins = pv->GetVectorLength();
highKinEnergyForRange = pv->GetLowEdgeEnergy(nbins);
theDEDXAtMaxEnergy = new G4double [n];
theRangeAtMaxEnergy = new G4double [n];
for (size_t i=0; i<n; i++) {
pv = (*p)[i];
G4double e1 = pv->GetLowEdgeEnergy(nbins-1);
G4double r1 = pv->GetValue(e1, b);
G4double e2 = pv->GetLowEdgeEnergy(nbins);
G4double r2 = pv->GetValue(e2, b);
G4double dedx = (e2-e1)/(r2-r1);
theDEDXAtMaxEnergy[i] = dedx;
theRangeAtMaxEnergy[i] = r2;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -796,22 +897,32 @@ void G4VEnergyLossSTD::SetSubLambdaTable(G4PhysicsTable* p)
G4PhysicsVector* G4VEnergyLossSTD::DEDXPhysicsVector(const G4MaterialCutsCouple* couple)
{
G4int nbins = 3;
//G4int nbins = nDEDXBins;
if( couple->IsUsed() ) nbins = nDEDXBins;
// G4double xmax = maxKinEnergy*exp( log(maxKinEnergy/minKinEnergy) / ((G4double)(nbins-1)) );
//G4double emax = maxKinEnergy*exp( log(maxKinEnergy/minKinEnergy) / ((G4double)(nbins-1)) );
G4PhysicsVector* v = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nbins);
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VEnergyLossSTD::DEDXPhysicsVectorForPreciseRange(
const G4MaterialCutsCouple* couple)
{
G4int nbins = 3;
if( couple->IsUsed() ) nbins = nDEDXBinsForRange;
//G4double emax = maxKinEnergy*exp( log(maxKinEnergy/minKinEnergy) / ((G4double)(nbins-1)) );
G4PhysicsVector* v = new G4PhysicsLogVector(minKinEnergy, maxKinEnergyForRange, nbins);
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VEnergyLossSTD::LambdaPhysicsVector(const G4MaterialCutsCouple* couple)
{
G4double cut = (*theCuts)[couple->GetIndex()];
G4int nbins = 3;
//G4int nbins = nLambdaBins;
if( couple->IsUsed() ) nbins = nLambdaBins;
G4double tmin = G4std::max(MinPrimaryEnergy(particle, couple->GetMaterial(), cut),
G4double tmin = std::max(MinPrimaryEnergy(particle, couple->GetMaterial(), cut),
minKinEnergy);
if(tmin >= maxKinEnergy) tmin = 0.5*maxKinEnergy;
// G4double xmax = maxKinEnergy*exp(log(maxKinEnergy/tmin)/((G4double)(nbins-1)) );
@@ -1087,4 +1198,43 @@ G4bool G4VEnergyLossSTD::RetrievePhysicsTable(G4ParticleDefinition* part,
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
/*
G4double G4VEnergyLossSTD::GetContinuousStepLimit(const G4Track&,
G4double, G4double currentMinimumStep, G4double& currentSafety)
{
G4double x = DBL_MAX;
if (theRangeTable) {
G4bool b;
fRange = ((*theRangeTable)[currentMaterialIndex])->
GetValue(preStepScaledEnergy, b)*reduceFactor;
x = fRange;
G4double r = std::min(finalRange, currentCouple->GetProductionCuts()
->GetProductionCut(idxG4ElectronCut));
if( integral ) {
if(x < currentMinimumStep && x > r) x *= 0.8;
} else {
if (fRange > r) {
x = dRoverRange*fRange + r*(1.0 - dRoverRange)*(2.0 - r/fRange);
if(rndmStepFlag) x = r + (x-r)*G4UniformRand();
if(x > fRange) x = fRange;
}
}
}
return x;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEnergyLossSTD::SetRangeCoeff(G4double val)
{
if (val > 0.0) {
if (val < 1.0) rangeCoeff = val;
else rangeCoeff = 1.0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -32,7 +32,10 @@
//
// Creation date: 25.03.2003
//
// Modifications: 13.04.03 Change printout (V.Ivanchenko)
// Modifications:
//
// 13.04.03 Change printout (V.Ivanchenko)
// 04-06-03 Fix compilation warnings (V.Ivanchenko)
//
//
// Class Description:
@@ -203,7 +206,7 @@ G4VParticleChange* G4VMultipleScattering::PostStepDoIt(const G4Track& track,
}
*/
// G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << truePathLength << G4endl;
// G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << truePathLength << G4endl;
if (latDisplasment) {
@@ -212,7 +215,7 @@ G4VParticleChange* G4VMultipleScattering::PostStepDoIt(const G4Track& track,
G4double r = currentModel->SampleDisplacement();
if (r > safety) r = safety;
// G4cout << "r= " << r << " safety= " << safety << G4endl;
// G4cout << "r= " << r << " safety= " << safety << G4endl;
// sample direction of lateral displacement
G4double phi = twopi*G4UniformRand();
@@ -238,7 +241,7 @@ G4VParticleChange* G4VMultipleScattering::PostStepDoIt(const G4Track& track,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::PrintInfoDefinition() const
void G4VMultipleScattering::PrintInfoDefinition()
{
G4cout << G4endl << GetProcessName() << ": Model variant of multiple scattering " << G4endl;
if (theLambdaTable) {