Import Geant4 9.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 15:16:48 +02:00
parent 75c7fd177d
commit a8e9364cea
6592 changed files with 84274 additions and 69292 deletions
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4ASTARStopping.cc,v 1.6 2006/06/29 19:52:36 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//---------------------------------------------------------------------------
//
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4BetheBlochModel.cc,v 1.12 2006/08/29 20:21:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4BetheBlochModel.cc,v 1.13 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -229,17 +229,17 @@ G4double G4BetheBlochModel::ComputeDEDXPerVolume(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double minKinEnergy,
G4double maxEnergy)
void G4BetheBlochModel::SampleSecondaries(vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double minKinEnergy,
G4double maxEnergy)
{
G4double kineticEnergy = dp->GetKineticEnergy();
G4double tmax = MaxSecondaryEnergy(dp->GetDefinition(),kineticEnergy);
G4double maxKinEnergy = min(maxEnergy,tmax);
if(minKinEnergy >= maxKinEnergy) return 0;
if(minKinEnergy >= maxKinEnergy) return;
G4double totEnergy = kineticEnergy + mass;
G4double etot2 = totEnergy*totEnergy;
@@ -297,7 +297,6 @@ vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,
deltaDirection,deltaKinEnergy);
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
vdp->push_back(delta);
// Change kinematics of primary particle
@@ -307,8 +306,6 @@ vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
fParticleChange->SetProposedMomentumDirection(finalP);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4BetheHeitlerModel.cc,v 1.10 2007/02/20 17:06:35 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4BetheHeitlerModel.cc,v 1.11 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -180,11 +180,11 @@ G4double G4BetheHeitlerModel::ComputeCrossSectionPerAtom(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4BetheHeitlerModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
void G4BetheHeitlerModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
// The secondaries e+e- energies are sampled using the Bethe - Heitler
// cross sections with Coulomb correction.
// A modified version of the random number techniques of Butcher & Messel
@@ -205,7 +205,7 @@ std::vector<G4DynamicParticle*>* G4BetheHeitlerModel::SampleSecondaries(
G4double epsil ;
G4double epsil0 = electron_mass_c2/GammaEnergy ;
if(epsil0 > 1.0) return 0;
if(epsil0 > 1.0) return;
// do it fast if GammaEnergy < 2. MeV
static const G4double Egsmall=2.*MeV;
@@ -272,8 +272,8 @@ std::vector<G4DynamicParticle*>* G4BetheHeitlerModel::SampleSecondaries(
} else {
PositTotEnergy = (1.-epsil)*GammaEnergy;
ElectTotEnergy = epsil*GammaEnergy;
PositTotEnergy = (1.-epsil)*GammaEnergy;
ElectTotEnergy = epsil*GammaEnergy;
}
//
@@ -322,15 +322,12 @@ std::vector<G4DynamicParticle*>* G4BetheHeitlerModel::SampleSecondaries(
thePositron,PositDirection,PositKineEnergy);
// Fill output vector
std::vector<G4DynamicParticle*>* fvect = new std::vector<G4DynamicParticle*>;
fvect->push_back(aParticle1);
fvect->push_back(aParticle2);
// kill incident photon
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
return fvect;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4BohrFluctuations.cc,v 1.4 2006/06/29 19:52:42 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4BraggIonModel.cc,v 1.15 2006/10/23 18:57:19 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4BraggIonModel.cc,v 1.16 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -212,15 +212,15 @@ G4double G4BraggIonModel::ComputeDEDXPerVolume(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
std::vector<G4DynamicParticle*>* G4BraggIonModel::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double xmin,
G4double maxEnergy)
void G4BraggIonModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double xmin,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryKinEnergy(dp);
G4double xmax = min(tmax, maxEnergy);
if(xmin >= xmax) return 0;
if(xmin >= xmax) return;
G4double kineticEnergy = dp->GetKineticEnergy();
G4double energy = kineticEnergy + mass;
@@ -263,7 +263,6 @@ std::vector<G4DynamicParticle*>* G4BraggIonModel::SampleSecondaries(
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,deltaDirection,
deltaKinEnergy);
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
vdp->push_back(delta);
// Change kinematics of primary particle
@@ -273,8 +272,6 @@ std::vector<G4DynamicParticle*>* G4BraggIonModel::SampleSecondaries(
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
fParticleChange->SetProposedMomentumDirection(finalP);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4BraggModel.cc,v 1.14 2006/06/29 19:52:46 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4BraggModel.cc,v 1.15 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -206,15 +206,15 @@ G4double G4BraggModel::ComputeDEDXPerVolume(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double xmin,
G4double maxEnergy)
void G4BraggModel::SampleSecondaries(vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double xmin,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryKinEnergy(dp);
G4double xmax = min(tmax, maxEnergy);
if(xmin >= xmax) return 0;
if(xmin >= xmax) return;
G4double kineticEnergy = dp->GetKineticEnergy();
G4double energy = kineticEnergy + mass;
@@ -265,9 +265,7 @@ vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,deltaDirection,
deltaKinEnergy);
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
vdp->push_back(delta);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4ComptonScattering.cc,v 1.27 2006/09/14 10:27:19 maire Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
//
//------------ G4ComptonScattering physics process -----------------------------
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4ComptonScattering52.cc,v 1.3 2006/10/16 15:26:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4ComptonScattering52.cc,v 1.5 2007/05/16 14:00:56 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
//
//------------ G4ComptonScattering52 physics process -----------------------------
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4CoulombScattering.cc,v 1.7 2006/10/19 09:44:27 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4CoulombScatteringModel.cc,v 1.7 2006/10/19 09:44:27 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4CoulombScatteringModel.cc,v 1.8 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -142,13 +142,12 @@ G4double G4CoulombScatteringModel::SelectIsotope(const G4Element* elm)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4CoulombScatteringModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double,
G4double)
void G4CoulombScatteringModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double,
G4double)
{
std::vector<G4DynamicParticle*>* fvect = 0;
const G4Material* aMaterial = couple->GetMaterial();
const G4ParticleDefinition* p = dp->GetDefinition();
@@ -180,7 +179,7 @@ std::vector<G4DynamicParticle*>* G4CoulombScatteringModel::SampleSecondaries(
G4double costm = std::max(cosThetaMax, 1.0 - 0.5*q2Limit/momCM2);
if(1 == iz && p == theProton) costm = std::max(0.0, costm);
if(costm > cosThetaMin) return fvect;
if(costm > cosThetaMin) return;
G4double x = G4UniformRand();
G4double y = (a + 1.0 - cosThetaMin)/(cosThetaMin - costm);
@@ -213,15 +212,12 @@ std::vector<G4DynamicParticle*>* G4CoulombScatteringModel::SampleSecondaries(
ekin = lfv2.e() - m2;
if(ekin > Z*aMaterial->GetIonisation()->GetMeanExcitationEnergy()) {
fvect = new std::vector<G4DynamicParticle*>;
G4ParticleDefinition* ion = theParticleTable->GetIon(iz, in, 0.0);
G4DynamicParticle* newdp = new G4DynamicParticle(ion, lfv2);
fvect->push_back(newdp);
} else if(ekin > 0.0) {
fParticleChange->ProposeLocalEnergyDeposit(ekin);
}
return fvect;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4GammaConversion.cc,v 1.27 2006/09/14 10:27:19 maire Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
//
//------------------ G4GammaConversion physics process -------------------------
@@ -1,590 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4GammaConversion52.cc,v 1.4 2006/10/16 15:26:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
//------------------ G4GammaConversion52 physics process -------------------------
// by Michel Maire, 24 May 1996
//
// 11-06-96 Added SelectRandomAtom() method, M.Maire
// 21-06-96 SetCuts implementation, M.Maire
// 24-06-96 simplification in ComputeCrossSectionPerAtom, M.Maire
// 24-06-96 in DoIt : change the particleType stuff, M.Maire
// 25-06-96 modification in the generation of the teta angle, M.Maire
// 16-09-96 minors optimisations in DoIt. Thanks to P.Urban
// dynamical array PartialSumSigma
// 13-12-96 fast sampling of epsil below 2 MeV, L.Urban
// 14-01-97 crossection table + meanfreepath table.
// PartialSumSigma removed, M.Maire
// 14-01-97 in DoIt the positron is always created, even with Ekine=0,
// for further annihilation, M.Maire
// 14-03-97 new Physics scheme for geant4alpha, M.Maire
// 28-03-97 protection in BuildPhysicsTable, M.Maire
// 19-06-97 correction in ComputeCrossSectionPerAtom, L.Urban
// 04-06-98 in DoIt, secondary production condition:
// range>std::min(threshold,safety)
// 13-08-98 new methods SetBining() PrintInfo()
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 11-07-01 PostStepDoIt - sampling epsil: power(rndm,0.333333)
// 13-07-01 DoIt: suppression of production cut for the (e-,e+) (mma)
// 06-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 06-08-01 BuildThePhysicsTable() called from constructor (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 20-09-01 DoIt: fminimalEnergy = 1*eV (mma)
// 01-10-01 come back to BuildPhysicsTable(const G4ParticleDefinition&)
// 11-01-02 ComputeCrossSection: correction of extrapolation below EnergyLimit
// 21-03-02 DoIt: correction of the e+e- angular distribution (bug 363) mma
// 08-11-04 Remove of Store/Retrieve tables (V.Ivantchenko)
// 04-05-05 Add 52 to class name (V.Ivanchenko)
// 16-11-05 replace shootBit() by G4UniformRand() mma
// -----------------------------------------------------------------------------
#include "G4GammaConversion52.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4GammaConversion52::G4GammaConversion52(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
theCrossSectionTable(NULL),
theMeanFreePathTable(NULL),
LowestEnergyLimit (2*electron_mass_c2),
HighestEnergyLimit(100*GeV),
NumbBinTable(100),
fminimalEnergy(1*eV)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// destructor
G4GammaConversion52::~G4GammaConversion52()
{
if (theCrossSectionTable) {
theCrossSectionTable->clearAndDestroy();
delete theCrossSectionTable;
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4GammaConversion52::IsApplicable( const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4GammaConversion52::SetPhysicsTableBining(
G4double lowE, G4double highE, G4int nBins)
{
LowestEnergyLimit = lowE; HighestEnergyLimit = highE; NumbBinTable = nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4GammaConversion52::BuildPhysicsTable(const G4ParticleDefinition&)
// Build cross section and mean free path tables
{
G4double LowEdgeEnergy, Value;
G4PhysicsLogVector* ptrVector;
// Build cross section per atom tables for the e+e- pair creation
if (theCrossSectionTable) {
theCrossSectionTable->clearAndDestroy(); delete theCrossSectionTable;}
theCrossSectionTable = new G4PhysicsTable(G4Element::GetNumberOfElements());
const G4ElementTable* theElementTable = G4Element::GetElementTable();
G4double AtomicNumber;
size_t J;
for ( J=0 ; J < G4Element::GetNumberOfElements(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit,HighestEnergyLimit,
NumbBinTable );
AtomicNumber = (*theElementTable)[J]->GetZ();
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeCrossSectionPerAtom( LowEdgeEnergy, AtomicNumber);
ptrVector->PutValue( i , Value ) ;
}
theCrossSectionTable->insertAt( J , ptrVector ) ;
}
// Build mean free path table for the e+e- pair creation
if (theMeanFreePathTable)
{ theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable= new G4PhysicsTable(G4Material::GetNumberOfMaterials());
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4Material* material;
for ( J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit,HighestEnergyLimit,
NumbBinTable);
material = (*theMaterialTable)[J];
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeMeanFreePath( LowEdgeEnergy, material);
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector ) ;
}
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4GammaConversion52::ComputeCrossSectionPerAtom
(G4double GammaEnergy, G4double AtomicNumber)
// Calculates the microscopic cross section in GEANT4 internal units.
// A parametrized formula from L. Urban is used to estimate
// the total cross section.
// It gives a good description of the data from 1.5 MeV to 100 GeV.
// below 1.5 MeV: sigma=sigma(1.5MeV)*(GammaEnergy-2electronmass)
// *(GammaEnergy-2electronmass)
{
G4double GammaEnergyLimit = 1.5*MeV;
G4double CrossSection = 0.0 ;
if ( AtomicNumber < 1. ) return CrossSection;
if ( GammaEnergy < 2*electron_mass_c2 ) return CrossSection;
static const G4double
a0= 8.7842e+2*microbarn, a1=-1.9625e+3*microbarn, a2= 1.2949e+3*microbarn,
a3=-2.0028e+2*microbarn, a4= 1.2575e+1*microbarn, a5=-2.8333e-1*microbarn;
static const G4double
b0=-1.0342e+1*microbarn, b1= 1.7692e+1*microbarn, b2=-8.2381 *microbarn,
b3= 1.3063 *microbarn, b4=-9.0815e-2*microbarn, b5= 2.3586e-3*microbarn;
static const G4double
c0=-4.5263e+2*microbarn, c1= 1.1161e+3*microbarn, c2=-8.6749e+2*microbarn,
c3= 2.1773e+2*microbarn, c4=-2.0467e+1*microbarn, c5= 6.5372e-1*microbarn;
G4double GammaEnergySave = GammaEnergy ;
if (GammaEnergy < GammaEnergyLimit) GammaEnergy = GammaEnergyLimit ;
G4double X=log(GammaEnergy/electron_mass_c2),X2=X*X, X3=X2*X, X4=X3*X, X5=X4*X;
G4double F1 = a0 + a1*X + a2*X2 + a3*X3 + a4*X4 + a5*X5,
F2 = b0 + b1*X + b2*X2 + b3*X3 + b4*X4 + b5*X5,
F3 = c0 + c1*X + c2*X2 + c3*X3 + c4*X4 + c5*X5;
CrossSection = (AtomicNumber+1.)*
(F1*AtomicNumber + F2*AtomicNumber*AtomicNumber + F3);
if (GammaEnergySave < GammaEnergyLimit)
{
X = (GammaEnergySave - 2.*electron_mass_c2)
/(GammaEnergyLimit- 2.*electron_mass_c2);
CrossSection *= X*X;
}
if (CrossSection < 0.) CrossSection = 0.;
return CrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4GammaConversion52::ComputeMeanFreePath(G4double GammaEnergy,
G4Material* aMaterial)
// computes and returns the photon mean free path in GEANT4 internal units
{
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double SIGMA = 0 ;
for ( size_t i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
SIGMA += NbOfAtomsPerVolume[i] *
ComputeCrossSectionPerAtom(GammaEnergy,
(*theElementVector)[i]->GetZ());
}
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4GammaConversion52::GetCrossSectionPerAtom(
const G4DynamicParticle* aDynamicGamma,
G4Element* anElement)
// gives the total cross section per atom in GEANT4 internal units
{
G4double crossSection;
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
G4bool isOutRange ;
if (GammaEnergy < LowestEnergyLimit)
crossSection = 0. ;
else {
if (GammaEnergy > HighestEnergyLimit) GammaEnergy=0.99*HighestEnergyLimit;
crossSection = (*theCrossSectionTable)(anElement->GetIndex())->
GetValue( GammaEnergy, isOutRange );
}
return crossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4GammaConversion52::GetMeanFreePath(const G4Track& aTrack,
G4double,
G4ForceCondition*)
// returns the photon mean free path in GEANT4 internal units
// (MeanFreePath is a private member of the class)
{
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
G4Material* aMaterial = aTrack.GetMaterial();
G4bool isOutRange;
if (GammaEnergy < LowestEnergyLimit)
MeanFreePath = DBL_MAX;
else {
if (GammaEnergy > HighestEnergyLimit) GammaEnergy=0.99*HighestEnergyLimit;
MeanFreePath = (*theMeanFreePathTable)(aMaterial->GetIndex())->
GetValue( GammaEnergy, isOutRange );
}
return MeanFreePath;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4GammaConversion52::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
//
// The secondaries e+e- energies are sampled using the Bethe - Heitler
// cross sections with Coulomb correction.
// A modified version of the random number techniques of Butcher & Messel
// is used (Nuc Phys 20(1960),15).
//
// GEANT4 internal units.
//
// Note 1 : Effects due to the breakdown of the Born approximation at
// low energy are ignored.
// Note 2 : The differential cross section implicitly takes account of
// pair creation in both nuclear and atomic electron fields.
// However triplet prodution is not generated.
{
aParticleChange.Initialize(aTrack);
G4Material* aMaterial = aTrack.GetMaterial();
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection();
G4double epsil ;
G4double epsil0 = electron_mass_c2/GammaEnergy ;
// do it fast if GammaEnergy < 2. MeV
const G4double Egsmall=2.*MeV;
if (GammaEnergy<Egsmall) { epsil = epsil0 + (0.5-epsil0)*G4UniformRand(); }
else
{ // now comes the case with GammaEnergy >= 2. MeV
// select randomly one element constituing the material
G4Element* anElement = SelectRandomAtom(aDynamicGamma, aMaterial);
// Extract Coulomb factor for this Element
G4double FZ = 8.*(anElement->GetIonisation()->GetlogZ3());
if (GammaEnergy > 50.*MeV) FZ += 8.*(anElement->GetfCoulomb());
// limits of the screening variable
G4double screenfac = 136.*epsil0/(anElement->GetIonisation()->GetZ3());
G4double screenmax = exp ((42.24 - FZ)/8.368) - 0.952 ;
G4double screenmin = min(4.*screenfac,screenmax);
// limits of the energy sampling
G4double epsil1 = 0.5 - 0.5*sqrt(1. - screenmin/screenmax) ;
G4double epsilmin = max(epsil0,epsil1) , epsilrange = 0.5 - epsilmin;
//
// sample the energy rate of the created electron (or positron)
//
//G4double epsil, screenvar, greject ;
G4double screenvar, greject ;
G4double F10 = ScreenFunction1(screenmin) - FZ;
G4double F20 = ScreenFunction2(screenmin) - FZ;
G4double NormF1 = max(F10*epsilrange*epsilrange,0.);
G4double NormF2 = max(1.5*F20,0.);
do {
if ( NormF1/(NormF1+NormF2) > G4UniformRand() )
{ epsil = 0.5 - epsilrange*pow(G4UniformRand(), 0.333333);
screenvar = screenfac/(epsil*(1-epsil));
greject = (ScreenFunction1(screenvar) - FZ)/F10;
}
else { epsil = epsilmin + epsilrange*G4UniformRand();
screenvar = screenfac/(epsil*(1-epsil));
greject = (ScreenFunction2(screenvar) - FZ)/F20;
}
} while( greject < G4UniformRand() );
} // end of epsil sampling
//
// fixe charges randomly
//
G4double ElectTotEnergy, PositTotEnergy;
if (G4UniformRand() > 0.5)
{
ElectTotEnergy = (1.-epsil)*GammaEnergy;
PositTotEnergy = epsil*GammaEnergy;
}
else
{
PositTotEnergy = (1.-epsil)*GammaEnergy;
ElectTotEnergy = epsil*GammaEnergy;
}
//
// scattered electron (positron) angles. ( Z - axis along the parent photon)
//
// universal distribution suggested by L. Urban
// (Geant3 manual (1993) Phys211),
// derived from Tsai distribution (Rev Mod Phys 49,421(1977))
G4double u;
const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ;
if (9./(9.+d) >G4UniformRand()) u= - log(G4UniformRand()*G4UniformRand())/a1;
else u= - log(G4UniformRand()*G4UniformRand())/a2;
G4double TetEl = u*electron_mass_c2/ElectTotEnergy;
G4double TetPo = u*electron_mass_c2/PositTotEnergy;
G4double Phi = twopi * G4UniformRand();
G4double dxEl= sin(TetEl)*cos(Phi),dyEl= sin(TetEl)*sin(Phi),dzEl=cos(TetEl);
G4double dxPo=-sin(TetPo)*cos(Phi),dyPo=-sin(TetPo)*sin(Phi),dzPo=cos(TetPo);
//
// kinematic of the created pair
//
// the electron and positron are assumed to have a symetric
// angular distribution with respect to the Z axis along the parent photon.
aParticleChange.SetNumberOfSecondaries(2);
G4double ElectKineEnergy = max(0.,ElectTotEnergy - electron_mass_c2);
G4double localEnergyDeposit = 0.;
if (ElectKineEnergy > fminimalEnergy)
{
G4ThreeVector ElectDirection (dxEl, dyEl, dzEl);
ElectDirection.rotateUz(GammaDirection);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1= new G4DynamicParticle(
G4Electron::Electron(),ElectDirection,ElectKineEnergy);
aParticleChange.AddSecondary(aParticle1);
}
else
{ localEnergyDeposit += ElectKineEnergy;}
// the e+ is always created (even with Ekine=0) for further annihilation.
G4double PositKineEnergy = max(0.,PositTotEnergy - electron_mass_c2);
if (PositKineEnergy < fminimalEnergy)
{ localEnergyDeposit += PositKineEnergy; PositKineEnergy = 0.;}
G4ThreeVector PositDirection (dxPo, dyPo, dzPo);
PositDirection.rotateUz(GammaDirection);
// create G4DynamicParticle object for the particle2
G4DynamicParticle* aParticle2= new G4DynamicParticle(
G4Positron::Positron(),PositDirection,PositKineEnergy);
aParticleChange.AddSecondary(aParticle2);
aParticleChange.ProposeLocalEnergyDeposit(localEnergyDeposit);
//
// Kill the incident photon
//
aParticleChange.ProposeEnergy( 0. );
aParticleChange.ProposeTrackStatus( fStopAndKill );
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4Element* G4GammaConversion52::SelectRandomAtom(
const G4DynamicParticle* aDynamicGamma,
G4Material* aMaterial)
{
// select randomly 1 element within the material
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)[0];
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double PartialSumSigma = 0. ;
G4double rval = G4UniformRand()/MeanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ )
{ PartialSumSigma += NbOfAtomsPerVolume[i] *
GetCrossSectionPerAtom(aDynamicGamma, (*theElementVector)[i]);
if (rval <= PartialSumSigma) return ((*theElementVector)[i]);
}
G4cout << " WARNING !!! - The Material '"<< aMaterial->GetName()
<< "' has no elements, NULL pointer returned." << G4endl;
return NULL;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4GammaConversion52::StorePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
if ( !theCrossSectionTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if ( !theMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
/*
G4bool G4GammaConversion52::RetrievePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theCrossSectionTable and theMeanFreePathTable
if (theCrossSectionTable != 0) {
theCrossSectionTable->clearAndDestroy();
delete theCrossSectionTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
G4String filename;
// retreive cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
theCrossSectionTable = new G4PhysicsTable(G4Element::GetNumberOfElements());
if ( !G4PhysicsTableHelper::RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if ( !G4PhysicsTableHelper::RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
return true;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4GammaConversion52::PrintInfoDefinition()
{
G4String comments = "Total cross sections from a parametrisation. ";
comments += "Good description from 1.5 MeV to 100 GeV for all Z. \n";
comments += " e+e- energies according Bethe-Heitler";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowestEnergyLimit, "Energy")
<< " to " << G4BestUnit(HighestEnergyLimit,"Energy")
<< " in " << NumbBinTable << " bins. \n";
G4cout << " WARNING: This process is obsolete and will be soon removed"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -25,7 +25,7 @@
//
//
// $Id: G4InitXscPAI.cc,v 1.9 2006/06/29 19:53:00 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
//
// G4InitXscPAI.cc -- class implementation file
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4IonFluctuations.cc,v 1.3 2006/06/29 19:53:02 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4KleinNishinaCompton.cc,v 1.8 2006/06/29 19:53:04 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4KleinNishinaCompton.cc,v 1.9 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -132,11 +132,11 @@ G4double G4KleinNishinaCompton::ComputeCrossSectionPerAtom(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4KleinNishinaCompton::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
void G4KleinNishinaCompton::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple*,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
// The scattered gamma energy is sampled according to Klein - Nishina formula.
// The random number techniques of Butcher & Messel are used
@@ -200,8 +200,6 @@ std::vector<G4DynamicParticle*>* G4KleinNishinaCompton::SampleSecondaries(
fParticleChange->ProposeLocalEnergyDeposit(gamEnergy1);
}
std::vector<G4DynamicParticle*>* fvect = new std::vector<G4DynamicParticle*>;
//
// kinematic of the scattered electron
//
@@ -216,7 +214,6 @@ std::vector<G4DynamicParticle*>* G4KleinNishinaCompton::SampleSecondaries(
G4DynamicParticle* dp = new G4DynamicParticle(theElectron,eDirection,eKinEnergy);
fvect->push_back(dp);
}
return fvect;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4MollerBhabhaModel.cc,v 1.29 2007/01/17 09:17:56 maire Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4MollerBhabhaModel.cc,v 1.30 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -282,14 +282,14 @@ G4double G4MollerBhabhaModel::ComputeDEDXPerVolume(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
std::vector<G4DynamicParticle*>* G4MollerBhabhaModel::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
void G4MollerBhabhaModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4double tmax = std::min(maxEnergy, MaxSecondaryKinEnergy(dp));
if(tmin >= tmax) return 0;
if(tmin >= tmax) return;
G4double kineticEnergy = dp->GetKineticEnergy();
G4double energy = kineticEnergy + electron_mass_c2;
@@ -394,11 +394,9 @@ std::vector<G4DynamicParticle*>* G4MollerBhabhaModel::SampleSecondaries(
}
// create G4DynamicParticle object for delta ray
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,
deltaDirection,deltaKinEnergy);
vdp->push_back(delta);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4MscModel71.cc,v 1.4 2006/06/29 19:53:08 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4MscModel71.cc,v 1.5 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -502,14 +502,14 @@ G4double G4MscModel71::TrueStepLength(G4double geomStepLength)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4MscModel71::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dynParticle,
G4double truestep,
G4double safety)
void G4MscModel71::SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dynParticle,
G4double truestep,
G4double safety)
{
G4double kineticEnergy = dynParticle->GetKineticEnergy();
if(kineticEnergy <= 0.0) return 0;
if(kineticEnergy <= 0.0) return;
G4double cth = SampleCosineTheta(truestep,kineticEnergy);
G4double sth = sqrt((1.0 - cth)*(1.0 + cth));
@@ -551,7 +551,6 @@ std::vector<G4DynamicParticle*>* G4MscModel71::SampleSecondaries(
fParticleChange->ProposePosition(newPosition);
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4MultipleScattering.cc,v 1.64 2007/04/24 12:00:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4MultipleScattering.cc,v 1.69 2007/06/11 15:01:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -----------------------------------------------------------------------------
//
@@ -119,6 +119,7 @@
// 23-10-06 skin = 1 by default (L.Urban)
// 23-11-06 skin = 1 by default for e+-, 0 for other particles (VI)
// 12-02-07 skin can be changed via UI command, default skin=1 (VI)
// 24-04-07 default skin=0 (temporal protection) (VI)
//
// -----------------------------------------------------------------------------
//
@@ -127,8 +128,7 @@
#include "G4MultipleScattering.hh"
#include "G4UrbanMscModel.hh"
#include "G4TransportationManager.hh"
#include "G4Navigator.hh"
#include "G4MscStepLimitType.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -137,25 +137,11 @@ using namespace std;
G4MultipleScattering::G4MultipleScattering(const G4String& processName)
: G4VMultipleScattering(processName)
{
lowKineticEnergy = 0.1*keV;
highKineticEnergy = 100.*TeV;
totBins = 120;
facrange = 0.02;
dtrl = 0.05;
lambdalimit = 1.*mm;
facgeom = 2.5;
steppingAlgorithm = true;
samplez = false ;
isInitialized = false;
SetBinning(totBins);
SetMinKinEnergy(lowKineticEnergy);
SetMaxKinEnergy(highKineticEnergy);
SetLateralDisplasmentFlag(true);
SetSkin(0.0);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -172,45 +158,34 @@ G4bool G4MultipleScattering::IsApplicable (const G4ParticleDefinition& p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering::MscStepLimitation(G4bool algorithm, G4double factor)
{
steppingAlgorithm = algorithm;
if (factor > 0.) SetFacrange(factor);
else { if (algorithm) SetFacrange(0.02); else SetFacrange(0.2);}
if(verboseLevel > 1)
G4cout << "Stepping algorithm is set to " << steppingAlgorithm
<< " with facrange = " << facrange << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering::InitialiseProcess(const G4ParticleDefinition* p)
{
// Modification of parameters between runs
if(isInitialized) {
mscUrban->SetMscStepLimitation(steppingAlgorithm, facrange);
if (p->GetParticleType() != "nucleus") {
mscUrban->SetStepLimitType(StepLimitType());
mscUrban->SetLateralDisplasmentFlag(LateralDisplasmentFlag());
mscUrban->SetSkin(Skin());
mscUrban->SetRangeFactor(RangeFactor());
mscUrban->SetGeomFactor(GeomFactor());
}
return;
}
// initialisation of parameters
G4String part_name = p->GetParticleName();
mscUrban = new G4UrbanMscModel(RangeFactor(),dtrl,lambdalimit,
GeomFactor(),Skin(),
samplez,StepLimitType());
mscUrban->SetLateralDisplasmentFlag(LateralDisplasmentFlag());
if (p->GetParticleType() == "nucleus") {
mscUrban->SetStepLimitType(fMinimal);
SetLateralDisplasmentFlag(false);
SetBuildLambdaTable(false);
SetSkin(0.0);
} else {
SetBuildLambdaTable(true);
SetRangeFactor(0.2);
}
mscUrban = new G4UrbanMscModel(facrange,dtrl,lambdalimit,
facgeom,Skin(),
samplez,steppingAlgorithm);
mscUrban->SetLateralDisplasmentFlag(LateralDisplasmentFlag());
mscUrban->SetLowEnergyLimit(lowKineticEnergy);
mscUrban->SetHighEnergyLimit(highKineticEnergy);
AddEmModel(1,mscUrban);
isInitialized = true;
/*
@@ -226,9 +201,9 @@ void G4MultipleScattering::InitialiseProcess(const G4ParticleDefinition* p)
void G4MultipleScattering::PrintInfo()
{
G4cout << " Boundary/stepping algorithm is active with facrange= "
<< facrange
<< " Step limitation " << steppingAlgorithm
G4cout << " Boundary/stepping algorithm is active with RangeFactor= "
<< RangeFactor()
<< " Step limit type " << StepLimitType()
<< G4endl;
}
@@ -1,955 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4MultipleScattering52.cc,v 1.5 2006/10/16 15:26:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
// 18/05/01 V.Ivanchenko Clean up against Linux ANSI compilation
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 23-08-01 new angle and z distribution,energy dependence reduced,
// Store,Retrieve methods commented out temporarily, L.Urban
// 27-08-01 in BuildPhysicsTable:aParticleType.GetParticleName()=="mu+" (mma)
// 28-08-01 GetContinuousStepLimit and AlongStepDoIt moved from .icc file (mma)
// 03-09-01 value of data member factlim changed, L.Urban
// 10-09-01 small change in GetContinuousStepLimit, L.Urban
// 11-09-01 G4MultipleScatteringx put as default G4MultipleScattering
// store/retrieve physics table reactivated (mma)
// 13-09-01 corr. in ComputeTransportCrossSection, L.Urban
// 14-09-01 protection in GetContinuousStepLimit, L.Urban
// 17-09-01 migration of Materials to pure STL (mma)
// 27-09-01 value of data member factlim changed, L.Urban
// 31-10-01 big fixed in PostStepDoIt,L.Urban
// 24-04-02 some minor changes in boundary algorithm, L.Urban
// 06-05-02 bug fixed in GetContinuousStepLimit, L.Urban
// 24-05-02 changes in angle distribution and boundary algorithm, L.Urban
// 11-06-02 bug fixed in ComputeTransportCrossSection, L.Urban
// 12-08-02 bug fixed in PostStepDoIt (lateral displacement), L.Urban
// 15-08-02 new angle distribution, L.Urban
// 26-09-02 angle distribution + boundary algorithm modified, L.Urban
// 15-10-02 temporary fix for proton scattering
// 30-10-02 modified angle distribution,mods in boundary algorithm,
// changes in data members, L.Urban
// 30-10-02 rename variable cm - Ecm, V.Ivanchenko
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured, L.Urban
// 05-02-03 changes in data members, new sampling for geom.
// path length, step dependence reduced with new
// method
// 17-03-03 cut per region, V.Ivanchenko
// 13-04-03 add initialisation in GetContinuesStepLimit
// + change table size (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (M.Asai)
// 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)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
// 08-11-04 Remove Store/Retrieve tables (V.Ivantchenko)
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4MultipleScattering52.hh"
#include "G4StepStatus.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4MultipleScattering52::G4MultipleScattering52(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),
NuclCorrPar (0.0615),
FactPar(0.40),
facxsi(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScattering52::~G4MultipleScattering52()
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering52::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 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();
// 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 G4MultipleScattering52::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();
G4double ParticleKineticEnergy = KineticEnergy ;
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
G4double Mass = ParticleMass ;
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/Mass ;
G4double c = Mass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
KineticEnergy = electron_mass_c2*tau ;
Mass = electron_mass_c2 ;
}
G4double Charge = aParticleType.GetPDGCharge();
G4double ChargeSquare = Charge*Charge/(eplus*eplus);
G4double TotalEnergy = KineticEnergy + Mass ;
G4double beta2 = KineticEnergy*(TotalEnergy+Mass)
/(TotalEnergy*TotalEnergy);
G4double bg2 = KineticEnergy*(TotalEnergy+Mass)
/(Mass*Mass);
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/(ParticleKineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( (x0 < -1.) || (ParticleKineticEnergy <= 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/ParticleKineticEnergy)*
(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 G4MultipleScattering52::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;
// 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 = G4EnergyLossTables::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)
{
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
// if : diff.treatment for small/not small Z
if(range > 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;
}
}
}
}
}
// do the true -> geom transformation
zmean = tPathLength;
tau = tPathLength/lambda0 ;
if (tau < tausmall || range < currentMinimumStep) zPathLength = tPathLength;
else
{
if(tPathLength/range < dtrl) zmean = lambda0*(1.-exp(-tau));
else
{
T1 = G4EnergyLossTables::GetPreciseEnergyFromRange(
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* G4MultipleScattering52::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. ;
//VI change order of if operators
if(geomPathLength == zLast) truePathLength = tLast;
else if(geomPathLength/lambda0 < tausmall) truePathLength = geomPathLength;
else
{
if(lambda1 < 0.) truePathLength = -lambda0*log(1.-geomPathLength/lambda0) ;
else if(lambdam < 0.)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = tLast;
}
else
{
if(geomPathLength <= zm)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = 0.5*tLast;
lambdam = -1. ;
}
else
{
if(clam*(geomPathLength-zm)/(alam*cthm) < 1.)
truePathLength = 0.5*tLast + alam*(1.-
exp(log(1.-clam*(geomPathLength-zm)/(alam*cthm)))/clam) ;
else
truePathLength = tLast ;
}
}
// protection ....
if(truePathLength > tLast)
truePathLength = tLast ;
}
//VI truePath length cannot be smaller than geomPathLength
if (truePathLength < geomPathLength) truePathLength = geomPathLength;
fParticleChange.ProposeTrueStepLength(truePathLength);
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScattering52::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();
G4double Mass = aParticle->GetDefinition()->GetPDGMass() ;
// do nothing for stopped particles !
if(KineticEnergy > 0.)
{
// change direction first ( scattering )
G4double cth = 1.0 ;
G4double tau = truestep/lambda0 ;
if (tau < tausmall) cth = 1.;
else if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
if(lambda1 > 0.)
{
if(lambdam < 0.)
tau = -alam*log(1.-truestep/alam)/lambda0 ;
else
tau = -log(cthm)-alam*log(1.-(truestep-0.5*tLast)/alam)/lambdam ;
}
if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double amax=25. ;
const G4double tau0 = 0.02 ;
const G4double 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 ;
// 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 = std::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
{
w = log(tau/tau0) ;
if(tau < tau0)
a = (alfa1-alfa2*w)/tau ;
else
a = (alfa1+alfa3*w)/tau ;
}
xmeanth = exp(-tau) ;
x0 = 1.-xsi/a ;
if(x0 < -1.) x0 = -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((std::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)
{
if(G4UniformRand() < prob)
cth = 1.+log(ea+G4UniformRand()*eaa)/a ;
else
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
cth = -1.+2.*G4UniformRand() ;
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi), diry = sth*sin(phi), dirz = cth;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz);
newDirection.rotateUz(ParticleDirection);
fParticleChange.ProposeMomentumDirection(newDirection.x(),
newDirection.y(),
newDirection.z());
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean, etau;
if (safetyminustolerance > 0.)
{
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6.;
else
{
if(tau<taubig) etau = exp(-tau);
else etau = 0.;
rmean = -kappa*tau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += tau-kappapl1/kappa+kappa*etau/kappami1;
}
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.);
else rmean = 0.;
// for rmean > 0) only
if (rmean > 0.)
{
if (rmean>safetyminustolerance) rmean = safetyminustolerance;
// sample direction of lateral displacement
phi = twopi*G4UniformRand();
dirx = cos(phi); diry = sin(phi); dirz = 0.;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection);
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
navigator->LocateGlobalPointWithinVolume(newPosition);
fParticleChange.ProposePosition(newPosition);
}
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering52::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";
G4cout << " WARNING: This process is obsolete and will be soon removed"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4MultipleScattering71.cc,v 1.4 2006/10/16 15:26:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
@@ -55,6 +55,7 @@
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleChangeForLoss.hh"
#include "G4GeometryTolerance.hh"
////////////////////////////////////////////////////////////////////////
@@ -356,6 +357,8 @@ G4PAIModel::BuildLambdaVector(const G4MaterialCutsCouple* matCutsCouple)
{
G4int i ;
G4double dNdxCut, lambda;
G4double kCarTolerance = G4GeometryTolerance::GetInstance()
->GetSurfaceTolerance();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
@@ -568,12 +571,12 @@ G4double G4PAIModel::CrossSection( const G4MaterialCutsCouple* matCC,
//
// It is analog of PostStepDoIt in terms of secondary electron.
//
std::vector<G4DynamicParticle*>*
G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple* matCC,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
void G4PAIModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple* matCC,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
size_t jMat;
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
@@ -611,7 +614,7 @@ G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple* matCC,
// deltaTkin = 10*eV;
G4cout<<"Set G4PAIModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
}
if( deltaTkin <= 0.) return 0;
if( deltaTkin <= 0.) return;
if(deltaTkin > kineticEnergy &&
particleMass != electron_mass_c2) deltaTkin = kineticEnergy;
@@ -652,9 +655,7 @@ G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple* matCC,
deltaRay->SetKineticEnergy( deltaTkin ); // !!! trick for last steps /2.0 ???
deltaRay->SetMomentumDirection(deltaDirection);
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
vdp->push_back(deltaRay);
return vdp;
}
@@ -56,6 +56,7 @@
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleChangeForLoss.hh"
#include "G4GeometryTolerance.hh"
////////////////////////////////////////////////////////////////////////
@@ -377,6 +378,8 @@ G4PAIPhotonModel::BuildLambdaVector(const G4MaterialCutsCouple* matCutsCouple)
{
G4int i ;
G4double dNdxCut,dNdxPhotonCut,dNdxPlasmonCut, lambda;
G4double kCarTolerance = G4GeometryTolerance::GetInstance()
->GetSurfaceTolerance();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
@@ -721,13 +724,12 @@ G4double G4PAIPhotonModel::CrossSection( const G4MaterialCutsCouple* matCC,
// be returned as G4Dynamicparticle*.
//
std::vector<G4DynamicParticle*>*
G4PAIPhotonModel::SampleSecondaries( const G4MaterialCutsCouple* matCC,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
void G4PAIPhotonModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple* matCC,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
size_t jMat;
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
{
@@ -867,7 +869,6 @@ G4PAIPhotonModel::SampleSecondaries( const G4MaterialCutsCouple* matCC,
}
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
return vdp;
}
@@ -25,7 +25,7 @@
//
//
// $Id: G4PAIxSection.cc,v 1.21 2006/06/29 19:53:20 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
//
// G4PAIxSection.cc -- class implementation file
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PEEffectModel.cc,v 1.5 2006/06/29 19:53:22 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4PEEffectModel.cc,v 1.6 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -90,11 +90,11 @@ void G4PEEffectModel::Initialise(const G4ParticleDefinition*,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4PEEffectModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicPhoton,
G4double,
G4double)
void G4PEEffectModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicPhoton,
G4double,
G4double)
{
const G4Material* aMaterial = couple->GetMaterial();
@@ -107,7 +107,6 @@ std::vector<G4DynamicParticle*>* G4PEEffectModel::SampleSecondaries(
//
// Photo electron
//
std::vector<G4DynamicParticle*>* fvect = new std::vector<G4DynamicParticle*>;
// Select atomic shell
G4int nShells = anElement->GetNbOfAtomicShells();
@@ -115,7 +114,7 @@ std::vector<G4DynamicParticle*>* G4PEEffectModel::SampleSecondaries(
while ((i<nShells) && (energy<anElement->GetAtomicShell(i))) i++;
// no shell available
if (i == nShells) return fvect;
if (i == nShells) return;
G4double bindingEnergy = anElement->GetAtomicShell(i);
G4double ElecKineEnergy = energy - bindingEnergy;
@@ -139,7 +138,6 @@ std::vector<G4DynamicParticle*>* G4PEEffectModel::SampleSecondaries(
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->ProposeLocalEnergyDeposit(bindingEnergy);
return fvect;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4PSTARStopping.cc,v 1.5 2006/06/29 19:53:24 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//---------------------------------------------------------------------------
//
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4PhotoElectricEffect.cc,v 1.37 2006/09/14 10:27:19 maire Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
//
//------------------ G4PhotoElectricEffect physics process ---------------------
@@ -1,289 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4PhotoElectricEffect52.cc,v 1.3 2006/10/16 15:26:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// 12-06-96, Added SelectRandomAtom() method, by M.Maire
// 21-06-96, SetCuts implementation, M.Maire
// 17-09-96, PartialSumSigma(i)
// split of ComputeBindingEnergy, M.Maire
// 08-01-97, crossection table + meanfreepath table, M.Maire
// 13-03-97, adapted for the new physics scheme, M.Maire
// 28-03-97, protection in BuildPhysicsTable, M.Maire
// 04-06-98, in DoIt, secondary production condition:
// range > std::min(threshold,safety)
// 13-08-98, new methods SetBining() PrintInfo()
// 17-11-98, use table of Atomic shells in PostStepDoIt
// 06-01-99, use Sandia crossSection below 50 keV, V.Grichine mma
// 20-05-99, protection against very low energy photons ,L.Urban
// 08-06-99, removed this above protection from the DoIt. mma
// 21-06-00, in DoIt, killing photon: aParticleChange.SetEnergyChange(0.); mma
// 22-06-00, in DoIt, absorbe very low energy photon (back to 20-05-99); mma
// 22-02-01, back to 08-06-99 after correc in SandiaTable (materials-V03-00-05)
// 28-05-01, V.Ivanchenko minor changes to provide ANSI -wall compilation
// 13-07-01, DoIt: suppression of production cut of the electron (mma)
// 06-08-01, new methods Store/Retrieve PhysicsTable (mma)
// 06-08-01, BuildThePhysicsTable() called from constructor (mma)
// 17-09-01, migration of Materials to pure STL (mma)
// 20-09-01, DoIt: fminimalEnergy of generated electron = 1*eV (mma)
// 01-10-01, come back to BuildPhysicsTable(const G4ParticleDefinition&)
// 10-01-02, moved few function from icc to cc
// 17-04-02, Keep only Sandia crossSections. Remove BuildPhysicsTables.
// Simplify public interface (mma)
// 29-04-02, Generate theta angle of the photoelectron from Sauter-Gavrila
// distribution (mma)
// 15-01-03, photoelectron theta ditribution : return costeta=1 if gamma>5
// (helmut burkhardt)
// 04-05-05, Add 52 to class name (V.Ivanchenko)
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4PhotoElectricEffect52.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4PhotoElectricEffect52::G4PhotoElectricEffect52(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
fminimalEnergy(1*eV)
{ PrintInfoDefinition();}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// destructor
G4PhotoElectricEffect52::~G4PhotoElectricEffect52()
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4bool G4PhotoElectricEffect52::IsApplicable(const G4ParticleDefinition&
particle)
{
return ( &particle == G4Gamma::Gamma() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4PhotoElectricEffect52::ComputeCrossSectionPerAtom(G4double GammaEnergy,
G4double AtomicNumber)
// returns the photoElectric cross Section in GEANT4 internal units
{
G4double* SandiaCof
= G4SandiaTable::GetSandiaCofPerAtom((int)AtomicNumber,GammaEnergy);
G4double energy2 = GammaEnergy*GammaEnergy, energy3 = GammaEnergy*energy2,
energy4 = energy2*energy2;
return SandiaCof[0]/GammaEnergy + SandiaCof[1]/energy2 +
SandiaCof[2]/energy3 + SandiaCof[3]/energy4;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4PhotoElectricEffect52::ComputeMeanFreePath(G4double GammaEnergy,
G4Material* aMaterial)
// returns the gamma mean free path in GEANT4 internal units
{
G4double* SandiaCof = aMaterial->GetSandiaTable()
->GetSandiaCofForMaterial(GammaEnergy);
G4double energy2 = GammaEnergy*GammaEnergy, energy3 = GammaEnergy*energy2,
energy4 = energy2*energy2;
G4double SIGMA = SandiaCof[0]/GammaEnergy + SandiaCof[1]/energy2 +
SandiaCof[2]/energy3 + SandiaCof[3]/energy4;
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4double G4PhotoElectricEffect52::GetMeanFreePath(const G4Track& aTrack,
G4double,
G4ForceCondition*)
// returns the gamma mean free path in GEANT4 internal units
{
G4double GammaEnergy = aTrack.GetDynamicParticle()->GetKineticEnergy();
G4double* SandiaCof = aTrack.GetMaterial()->GetSandiaTable()
->GetSandiaCofForMaterial(GammaEnergy);
G4double energy2 = GammaEnergy*GammaEnergy, energy3 = GammaEnergy*energy2,
energy4 = energy2*energy2;
G4double SIGMA = SandiaCof[0]/GammaEnergy + SandiaCof[1]/energy2 +
SandiaCof[2]/energy3 + SandiaCof[3]/energy4;
MeanFreePath = SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
return MeanFreePath;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4PhotoElectricEffect52::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
//
// Generate an electron resulting of a photo electric effect.
// The incident photon disappear.
// GEANT4 internal units
//
{ aParticleChange.Initialize(aTrack);
G4Material* aMaterial = aTrack.GetMaterial();
const G4DynamicParticle* aDynamicPhoton = aTrack.GetDynamicParticle();
G4double PhotonEnergy = aDynamicPhoton->GetKineticEnergy();
G4ParticleMomentum PhotonDirection = aDynamicPhoton->GetMomentumDirection();
// select randomly one element constituing the material.
G4Element* anElement = SelectRandomAtom(aDynamicPhoton, aMaterial);
//
// Photo electron
//
G4int NbOfShells = anElement->GetNbOfAtomicShells();
G4int i=0;
while ((i<NbOfShells)&&(PhotonEnergy<anElement->GetAtomicShell(i))) i++;
if (i==NbOfShells) return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
G4double ElecKineEnergy = PhotonEnergy - anElement->GetAtomicShell(i);
if (ElecKineEnergy > fminimalEnergy)
{
// direction of the photo electron
//
G4double cosTeta = ElecThetaDistribution(ElecKineEnergy);
G4double sinTeta = sqrt(1.-cosTeta*cosTeta);
G4double Phi = twopi * G4UniformRand();
G4double dirx = sinTeta*cos(Phi),diry = sinTeta*sin(Phi),dirz = cosTeta;
G4ThreeVector ElecDirection(dirx,diry,dirz);
ElecDirection.rotateUz(PhotonDirection);
//
G4DynamicParticle* aElectron = new G4DynamicParticle (
G4Electron::Electron(),ElecDirection, ElecKineEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(aElectron);
}
else
{
ElecKineEnergy = 0.;
aParticleChange.SetNumberOfSecondaries(0);
}
//
// Kill the incident photon
//
aParticleChange.ProposeLocalEnergyDeposit(PhotonEnergy-ElecKineEnergy);
aParticleChange.ProposeEnergy(0.);
aParticleChange.ProposeTrackStatus(fStopAndKill);
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4Element* G4PhotoElectricEffect52::SelectRandomAtom(
const G4DynamicParticle* aDynamicPhoton,
G4Material* aMaterial)
{
// select randomly 1 element within the material
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)[0];
G4double GammaEnergy = aDynamicPhoton->GetKineticEnergy();
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double PartialSumSigma = 0. ;
G4double rval = G4UniformRand();
for ( G4int elm=0 ; elm < NumberOfElements ; elm++ )
{PartialSumSigma += NbOfAtomsPerVolume[elm] *
ComputeCrossSectionPerAtom(GammaEnergy,
(*theElementVector)[elm]->GetZ());
if (rval<=PartialSumSigma*MeanFreePath) return ((*theElementVector)[elm]);
}
return ((*theElementVector)[NumberOfElements-1]);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4PhotoElectricEffect52::ElecThetaDistribution(G4double kineEnergy)
{
// Compute Theta distribution of the emitted electron, with respect to the
// incident Gamma.
// The Sauter-Gavrila distribution for the K-shell is used.
//
G4double costeta = 1.;
G4double gamma = 1. + kineEnergy/electron_mass_c2;
if (gamma > 5.) return costeta;
G4double beta = sqrt(gamma*gamma-1.)/gamma;
G4double b = 0.5*gamma*(gamma-1.)*(gamma-2);
G4double rndm,term,greject,grejsup;
if (gamma < 2.) grejsup = gamma*gamma*(1.+b-beta*b);
else grejsup = gamma*gamma*(1.+b+beta*b);
do { rndm = 1.-2*G4UniformRand();
costeta = (rndm+beta)/(rndm*beta+1.);
term = 1.-beta*costeta;
greject = (1.-costeta*costeta)*(1.+b*term)/(term*term);
} while(greject < G4UniformRand()*grejsup);
return costeta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4PhotoElectricEffect52::PrintInfoDefinition()
{
G4String comments = "Total cross sections from Sandia parametrisation. ";
G4cout << G4endl << GetProcessName() << ": " << comments << G4endl;
G4cout << " WARNING: This process is obsolete and will be soon removed"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -25,7 +25,7 @@
//
//
// $Id: G4PolarizedComptonScattering.cc,v 1.16 2006/06/29 19:53:30 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
//
//---------- G4PolarizedComptonScattering physics process ----------------------
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4UniversalFluctuation.cc,v 1.13 2007/03/21 15:23:45 urban Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4UniversalFluctuation.cc,v 1.14 2007/04/03 11:08:36 urban Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -54,7 +54,7 @@
// 17-10-05 correction for very small loss (L.Urban)
// 20-03-07 'GLANDZ' part rewritten completely, no 'very small loss'
// regime any more (L.Urban)
// 21-03-07 optimization in ionization part (L.Urban)
// 03-04-07 correction to get better width of eloss distr.(L.Urban)
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -82,6 +82,9 @@ G4UniversalFluctuation::G4UniversalFluctuation(const G4String& nam)
nmaxCont2(16.)
{
lastMaterial = 0;
facwidth = 1.000/keV;
oldloss = 0.;
samestep = 0.;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -114,7 +117,11 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
// shortcut for very very small loss (out of validity of the model)
//
if (meanLoss < minLoss) return meanLoss;
if (meanLoss < minLoss)
{
oldloss = meanLoss;
return meanLoss;
}
if(!particle) InitialiseMe(dp->GetDefinition());
@@ -174,6 +181,17 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
G4double a1 = 0. , a2 = 0., a3 = 0. ;
// correction to get better width even using stepmax
if(abs(meanLoss- oldloss) < 1.*eV)
samestep += 1;
else
samestep = 1.;
oldloss = meanLoss;
G4double width = 1.+samestep*facwidth*meanLoss;
if(width > 4.50) width = 4.50;
e1 = width*e1Fluct;
e2 = width*e2Fluct;
// cut and material dependent rate
G4double rate = 1.0;
if(tmax > ipotFluct) {
@@ -183,8 +201,8 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
rate = 0.03+0.23*log(log(tmax/ipotFluct));
G4double C = meanLoss*(1.-rate)/(w2-ipotLogFluct);
a1 = C*f1Fluct*(w2-e1LogFluct)/e1Fluct;
a2 = C*f2Fluct*(w2-e2LogFluct)/e2Fluct;
a1 = C*f1Fluct*(w2-e1LogFluct)/e1;
a2 = C*f2Fluct*(w2-e2LogFluct)/e2;
}
}
@@ -200,29 +218,29 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
// excitation of type 1
if(a1 > nmaxCont2)
{
emean += a1*e1Fluct;
sig2e += a1*e1Fluct*e1Fluct;
emean += a1*e1;
sig2e += a1*e1*e1;
}
else if(a1 > 0.)
{
p1 = G4double(G4Poisson(a1));
loss += p1*e1Fluct;
loss += p1*e1;
if(p1 > 0.)
loss += (1.-2.*G4UniformRand())*e1Fluct;
loss += (1.-2.*G4UniformRand())*e1;
}
// excitation of type 2
if(a2 > nmaxCont2)
{
emean += a2*e2Fluct;
sig2e += a2*e2Fluct*e2Fluct;
emean += a2*e2;
sig2e += a2*e2*e2;
}
else if(a2 > 0.)
{
p2 = G4double(G4Poisson(a2));
loss += p2*e2Fluct;
loss += p2*e2;
if(p2 > 0.)
loss += (1.-2.*G4UniformRand())*e2Fluct;
loss += (1.-2.*G4UniformRand())*e2;
}
// ionisation
@@ -236,24 +254,16 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
alfa = w1*(nmaxCont2+a3)/(w1*nmaxCont2+a3);
G4double alfa1 = alfa*log(alfa)/(alfa-1.);
G4double namean = a3*w1*(alfa-1.)/((w1-1.)*alfa);
emean += namean*e0*alfa1;
emean += namean*e0*alfa1;
sig2e += e0*e0*namean*(alfa-alfa1*alfa1);
p3 = a3-namean;
}
G4double w2 = alfa*e0;
G4double w = (tmax-w2)/tmax;
G4double scale = 1.;
G4int nb = 0;
if(p3 < nmaxCont2)
nb = G4Poisson(p3);
else
{
nb = G4Poisson(nmaxCont2);
scale = p3/nmaxCont2;
}
G4int nb = G4Poisson(p3);
if(nb > 0)
for (G4int k=0; k<nb; k++) lossc += scale*w2/(1.-w*G4UniformRand());
for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
}
if(emean > 0.)
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4UrbanMscModel.cc,v 1.47 2007/03/07 15:44:42 urban Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4UrbanMscModel.cc,v 1.60 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -134,6 +134,9 @@
// 24-02-07 step reduction before boundary for 'small' geomlimit only
// 03-03-07 single scattering around boundaries only (L.Urban)
// 07-03-07 bugfix in ComputeTruePathLengthLimit (for skin > 0.) (L.Urban)
// 10-04-07 optimize logic of ComputeTruePathLengthLimit, remove
// unused members, use unique G4SafetyHelper (V.Ivanchenko)
// 01-05-07 optimization for skin > 0 (L.Urban)
//
// Class Description:
@@ -155,6 +158,7 @@
#include "G4ParticleChangeForMSC.hh"
#include "G4TransportationManager.hh"
#include "G4Navigator.hh"
#include "G4SafetyHelper.hh"
#include "G4Poisson.hh"
@@ -165,7 +169,7 @@ using namespace std;
G4UrbanMscModel::G4UrbanMscModel(G4double m_facrange, G4double m_dtrl,
G4double m_lambdalimit,
G4double m_facgeom,G4double m_skin,
G4bool m_samplez, G4bool m_stepAlg,
G4bool m_samplez, G4MscStepLimitType m_stepAlg,
const G4String& nam)
: G4VEmModel(nam),
dtrl(m_dtrl),
@@ -173,8 +177,8 @@ G4UrbanMscModel::G4UrbanMscModel(G4double m_facrange, G4double m_dtrl,
facrange(m_facrange),
facgeom(m_facgeom),
skin(m_skin),
samplez(m_samplez),
steppingAlgorithm(m_stepAlg),
samplez(m_samplez),
isInitialized(false)
{
taubig = 8.0;
@@ -190,7 +194,6 @@ G4UrbanMscModel::G4UrbanMscModel(G4double m_facrange, G4double m_dtrl,
frscaling1 = 1.-frscaling2;
tlimit = 1.e10*mm;
tlimitmin = 10.*tlimitminfix;
tnow = 10.*tlimitminfix;
nstepmax = 25.;
geombig = 1.e50*mm;
geommin = 1.e-3*mm;
@@ -208,9 +211,7 @@ G4UrbanMscModel::G4UrbanMscModel(G4double m_facrange, G4double m_dtrl,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4UrbanMscModel::~G4UrbanMscModel()
{
delete safetyHelper;
}
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -226,25 +227,9 @@ void G4UrbanMscModel::Initialise(const G4ParticleDefinition* p,
else
fParticleChange = new G4ParticleChangeForMSC();
navigator = G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
safetyHelper= new G4SafetyHelper();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4UrbanMscModel::SetMscStepLimitation(G4bool alg, G4double factor)
{
steppingAlgorithm = alg;
facrange = factor;
// reinitialisation
stepmin = tlimitminfix;
skindepth = skin*stepmin;
tlimitmin = 10.*tlimitminfix;
tnow = 10.*tlimitminfix;
inside = false;
safetyHelper = G4TransportationManager::GetTransportationManager()
->GetSafetyHelper();
safetyHelper->InitialiseHelper();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -499,10 +484,18 @@ G4double G4UrbanMscModel::ComputeTruePathLengthLimit(
G4PhysicsTable* theTable,
G4double currentMinimalStep)
{
theLambdaTable = theTable;
tPathLength = currentMinimalStep;
G4int stepNumber = track.GetCurrentStepNumber();
const G4DynamicParticle* dp = track.GetDynamicParticle();
SetParticle( dp->GetDefinition() );
if(stepNumber == 1) {
inside = false;
insideskin = false;
tlimit = geombig;
SetParticle( dp->GetDefinition() );
}
theLambdaTable = theTable;
couple = track.GetMaterialCutsCouple();
currentMaterialIndex = couple->GetIndex();
currentKinEnergy = dp->GetKineticEnergy();
@@ -510,213 +503,181 @@ G4double G4UrbanMscModel::ComputeTruePathLengthLimit(
theManager->GetRangeFromRestricteDEDX(particle,currentKinEnergy,couple);
lambda0 = GetLambda(currentKinEnergy);
tPathLength = currentMinimalStep;
if(tPathLength > currentRange)
tPathLength = currentRange;
// stop here if small range particle
if(inside) return tPathLength;
if(tPathLength > currentRange) tPathLength = currentRange;
G4StepPoint* sp = track.GetStep()->GetPreStepPoint();
presafety = sp->GetSafety();
// G4cout << "G4UrbanMscModel::ComputeTruePathLengthLimit tPathLength= "
// <<tPathLength<<" safety= " << presafety
// << " range= " <<currentRange<<G4endl;
// far from geometry boundary
if(currentRange < presafety)
{
inside = true;
return tPathLength;
}
G4StepStatus stepStatus = sp->GetStepStatus();
G4int stepNumber = track.GetCurrentStepNumber();
if(stepNumber == 1) insideskin = false;
// standard version
//
if (steppingAlgorithm)
{
//for precise simulation for the case without magnatic field
// small step(s) + single/plural scattering around boundaries
if(skin > 0.)
if (steppingAlgorithm == fUseDistanceToBoundary)
{
if((stepNumber > 1) && inside)
return tPathLength;
//compute geomlimit and presafety
GeomLimit(track);
// is far from boundary
if(currentRange <= presafety)
{
inside = true;
return tPathLength;
}
insideskin = false;
smallstep += 1.;
insideskin = false;
if((stepStatus == fGeomBoundary) || (stepNumber == 1))
{
if(stepNumber == 1) smallstep = 1.e10;
else smallstep = 1.;
{
if((stepNumber == 1) && (currentRange < presafety))
{
stepmin = tlimitminfix;
inside = true;
return tPathLength;
}
else
inside = false;
if(stepNumber == 1) smallstep = 1.e10;
else smallstep = 1.;
// facrange scaling in lambda
// not so strong step restriction above lambdalimit
G4double facr = facrange;
if(lambda0 > lambdalimit)
facr *= frscaling1+frscaling2*lambda0/lambdalimit;
// facrange scaling in lambda
// not so strong step restriction above lambdalimit
G4double facr = facrange;
if(lambda0 > lambdalimit)
facr *= frscaling1+frscaling2*lambda0/lambdalimit;
// constraint from the physics
if (currentRange > lambda0) tlimit = facr*currentRange;
else tlimit = facr*lambda0;
// constraint from the physics
if (currentRange > lambda0) tlimit = facr*currentRange;
else tlimit = facr*lambda0;
// constraint from the geometry (if tlimit above is too big)
G4double tgeom = geombig;
if(geomlimit > geommin)
{
if(stepStatus == fGeomBoundary)
tgeom = geomlimit/facgeom;
else
tgeom = 2.*geomlimit/facgeom;
}
// constraint from the geometry (if tlimit above is too big)
G4double tgeom = geombig;
if(geomlimit > geommin)
{
if(stepStatus == fGeomBoundary)
tgeom = geomlimit/facgeom;
else
tgeom = 2.*geomlimit/facgeom;
}
//define stepmin here (it depends on lambda!)
//rough estimation of lambda_elastic/lambda_transport
G4double rat = currentKinEnergy/MeV ;
rat = 1.e-3/(rat*(10.+rat)) ;
//stepmin ~ lambda_elastic
stepmin = rat*lambda0;
skindepth = skin*stepmin;
//define stepmin here (it depends on lambda!)
//rough estimation of lambda_elastic/lambda_transport
G4double rat = currentKinEnergy/MeV ;
rat = 1.e-3/(rat*(10.+rat)) ;
//stepmin ~ lambda_elastic
stepmin = rat*lambda0;
skindepth = skin*stepmin;
//define tlimitmin
tlimitmin = lambda0/nstepmax;
if(tlimitmin < stepmin) tlimitmin = 1.01*stepmin;
if(tlimitmin < tlimitminfix) tlimitmin = tlimitminfix;
//define tlimitmin
tlimitmin = lambda0/nstepmax;
if(tlimitmin < stepmin) tlimitmin = 1.01*stepmin;
if(tlimitmin < tlimitminfix) tlimitmin = tlimitminfix;
//lower limit for tlimit
if(tlimit < tlimitmin) tlimit = tlimitmin;
//lower limit for tlimit
if(tlimit < tlimitmin) tlimit = tlimitmin;
//check against geometry limit
if(tlimit > tgeom) tlimit = tgeom;
//check against geometry limit
if(tlimit > tgeom) tlimit = tgeom;
}
//if track starts far from boundaries increase tlimit!
if(tlimit < facsafety*presafety)
tlimit = facsafety*presafety ;
}
//if track starts far from boundaries increase tlimit!
if(tlimit < facsafety*presafety) tlimit = facsafety*presafety ;
if(currentRange < presafety)
{
inside = true;
return tPathLength;
}
// G4cout << "tgeom= " << tgeom << " geomlimit= " << geomlimit
// << " tlimit= " << tlimit << " presafety= " << presafety << G4endl;
// shortcut
if((tPathLength < tlimit) &&
(tPathLength < presafety))
return tPathLength;
//if track far from boundaries increase tPathLength
tnow = tlimit;
if(tlimit < facsafety*presafety)
tnow = facsafety*presafety ;
if((tPathLength < tlimit) && (tPathLength < presafety))
return tPathLength;
G4double tnow = tlimit;
// optimization ...
if(geomlimit < geombig) tnow = max(tlimit,facsafety*geomlimit);
// step reduction near to boundary
if(smallstep < skin)
{
tnow = stepmin;
insideskin = true;
}
{
tnow = stepmin;
insideskin = true;
}
else if(geomlimit < geombig)
{
if(geomlimit > skindepth)
{
if(tnow > geomlimit-0.999*skindepth)
tnow = geomlimit-0.999*skindepth;
}
else
{
insideskin = true;
if(tnow > stepmin)
tnow = stepmin;
}
}
{
if(geomlimit > skindepth)
{
if(tnow > geomlimit-0.999*skindepth)
tnow = geomlimit-0.999*skindepth;
}
else
{
insideskin = true;
if(tnow > stepmin) tnow = stepmin;
}
}
if(tnow < stepmin)
tnow = stepmin;
if(tnow < stepmin) tnow = stepmin;
if(tPathLength > tnow)
tPathLength = tnow ;
if(tPathLength > tnow) tPathLength = tnow ;
}
// for 'normal' simulation with or without magnetic field
// for 'normal' simulation with or without magnetic field
// there no small step/single scattering at boundaries
else
else if(steppingAlgorithm == fUseSafety)
{
if((stepNumber > 1) && inside)
return tPathLength;
// compute presafety again if presafety <= 0 and no boundary
// i.e. when it is needed for optimization purposes
if((stepStatus != fGeomBoundary) && (presafety <= 0.))
{
presafety = safetyHelper->ComputeSafety(sp->GetPosition());
if(currentRange < presafety)
// is far from boundary
if(currentRange < presafety)
{
stepmin = tlimitminfix;
inside = true;
return tPathLength;
}
else
inside = false;
}
if((stepStatus == fGeomBoundary) || (stepNumber == 1))
{
if(stepNumber == 1)
insideskin = false;
// facrange scaling in lambda
// not so strong step restriction above lambdalimit
G4double facr = facrange;
if(lambda0 > lambdalimit)
facr *= frscaling1+frscaling2*lambda0/lambdalimit;
{
// facrange scaling in lambda
// not so strong step restriction above lambdalimit
G4double facr = facrange;
if(lambda0 > lambdalimit)
facr *= frscaling1+frscaling2*lambda0/lambdalimit;
// constraint from the physics
if (currentRange > lambda0) tlimit = facr*currentRange;
else tlimit = facr*lambda0;
// constraint from the physics
if (currentRange > lambda0) tlimit = facr*currentRange;
else tlimit = facr*lambda0;
//lower limit for tlimit
tlimitmin = lambda0/nstepmax;
if(tlimitmin < tlimitminfix) tlimitmin = tlimitminfix;
if(tlimit < tlimitmin) tlimit = tlimitmin;
//lower limit for tlimit
tlimitmin = std::max(tlimitminfix,lambda0/nstepmax);
if(tlimit < tlimitmin) tlimit = tlimitmin;
}
//if track starts far from boundaries increase tlimit!
if(tlimit < facsafety*presafety)
tlimit = facsafety*presafety ;
}
if(currentRange < presafety)
{
inside = true;
return tPathLength;
}
// shortcut
if((tPathLength < tlimit) &&
(tPathLength < presafety))
return tPathLength;
//if track starts far from boundaries increase tlimit!
if(tlimit < facsafety*presafety) tlimit = facsafety*presafety ;
if(tPathLength > tlimit) tPathLength = tlimit;
}
}
// version similar to 7.1 (needed for some experiments)
else
{
if(stepNumber == 1)
tlimit = geombig;
if (stepStatus == fGeomBoundary)
{
if (currentRange > lambda0) tlimit = facrange*currentRange;
else tlimit = facrange*lambda0;
if (stepStatus == fGeomBoundary)
{
if (currentRange > lambda0) tlimit = facrange*currentRange;
else tlimit = facrange*lambda0;
if(tlimit < tlimitmin) tlimit = tlimitmin;
if(tPathLength > tlimit) tPathLength = tlimit;
if(tlimit < tlimitmin) tlimit = tlimitmin;
if(tPathLength > tlimit) tPathLength = tlimit;
}
}
}
// G4cout << "tPathLength= " << tPathLength << " geomlimit= " << geomlimit
// << " currentMinimalStep= " << currentMinimalStep << G4endl;
return tPathLength ;
}
@@ -729,17 +690,17 @@ void G4UrbanMscModel::GeomLimit(const G4Track& track)
// no geomlimit for the World volume
if((track.GetVolume() != 0) &&
(track.GetVolume() != navigator->GetWorldVolume()))
(track.GetVolume() != safetyHelper->GetWorldVolume()))
{
const G4double cstep = tPathLength;
geomlimit = navigator->ComputeStep(
G4double cstep = tPathLength;
geomlimit = safetyHelper->CheckNextStep(
track.GetStep()->GetPreStepPoint()->GetPosition(),
track.GetMomentumDirection(),
cstep,
presafety);
// G4cout << "!!!G4UrbanMscModel::GeomLimit presafety= " << presafety
// G4cout << "!!!G4UrbanMscModel::GeomLimit presafety= " << presafety
// << " limit= " << geomlimit << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -771,8 +732,8 @@ G4double G4UrbanMscModel::ComputeGeomPathLength(G4double)
G4double zmean = tPathLength;
if (tPathLength < currentRange*dtrl) {
zmean = lambda0*(1.-exp(-tau));
if(tau < taulim) zmean = tPathLength*(1.-0.5*tau) ;
else zmean = lambda0*(1.-exp(-tau));
} else if(currentKinEnergy < mass) {
par1 = 1./currentRange ;
par2 = 1./(par1*lambda0) ;
@@ -886,14 +847,14 @@ G4double G4UrbanMscModel::ComputeTheta0(G4double trueStepLength,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
std::vector<G4DynamicParticle*>* G4UrbanMscModel::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dynParticle,
G4double truestep,
G4double safety)
void G4UrbanMscModel::SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dynParticle,
G4double truestep,
G4double safety)
{
G4double kineticEnergy = dynParticle->GetKineticEnergy();
if((kineticEnergy <= 0.0) || (truestep <= tlimitminfix)) return 0;
if((kineticEnergy <= 0.0) || (truestep <= tlimitminfix)) return;
G4double cth = SampleCosineTheta(truestep,kineticEnergy);
G4double sth = sqrt((1.0 - cth)*(1.0 + cth));
@@ -906,7 +867,7 @@ std::vector<G4DynamicParticle*>* G4UrbanMscModel::SampleSecondaries(
newDirection.rotateUz(oldDirection);
fParticleChange->ProposeMomentumDirection(newDirection);
if (latDisplasment) {
if (latDisplasment && safety > 0.0) {
G4double r = SampleDisplacement();
/*
@@ -916,7 +877,7 @@ std::vector<G4DynamicParticle*>* G4UrbanMscModel::SampleSecondaries(
<< " geomStep(mm)= " << zPathLength
<< G4endl;
*/
if(r > 0.)
if(r > 0.)
{
G4double latcorr = LatCorrelation();
if(latcorr > r) latcorr = r;
@@ -937,21 +898,12 @@ std::vector<G4DynamicParticle*>* G4UrbanMscModel::SampleSecondaries(
latDirection.rotateUz(oldDirection);
G4ThreeVector Position = *(fParticleChange->GetProposedPosition());
G4double fac = 0.;
if(r < safety)
{
//normal case, no need to check safety
fac = 1.;
}
else
{
// ******* we do not have track info at this level ***********
G4double fac = 1.;
if(r > safety) {
// ******* so safety is computed at boundary too ************
G4double newsafety = safetyHelper->ComputeSafety(Position);
safety= newsafety;
if(r < newsafety)
fac = 1.;
else
G4double newsafety = safetyHelper->ComputeSafety(Position);
//G4double newsafety = safety;
if(r > newsafety)
fac = newsafety/r ;
}
@@ -960,13 +912,29 @@ std::vector<G4DynamicParticle*>* G4UrbanMscModel::SampleSecondaries(
// compute new endpoint of the Step
G4ThreeVector newPosition = Position+fac*r*latDirection;
safetyHelper->ReLocateWithinVolume(newPosition);
// definetly not on boundary
if(1. == fac) {
//if(0. < fac) {
safetyHelper->ReLocateWithinVolume(newPosition);
} else {
// check safety after displacement
G4double postsafety = safetyHelper->ComputeSafety(newPosition);
// displacement to boundary
if(postsafety <= 0.) {
safetyHelper->Locate(newPosition, newDirection);
// not on the boundary
} else {
safetyHelper->ReLocateWithinVolume(newPosition);
}
}
fParticleChange->ProposePosition(newPosition);
}
}
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -984,7 +952,7 @@ G4double G4UrbanMscModel::SampleCosineTheta(G4double trueStepLength,
{
//no scattering, single or plural scattering
G4double mean = trueStepLength/stepmin ;
cth = 1.;
G4int n = G4Poisson(mean);
if(n > 0)
{
@@ -1,723 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4VeEnergyLoss.cc,v 1.35 2006/06/29 19:53:36 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
// -----------------------------------------------------------------------------
// 18/11/98 , L. Urban
// It is a modified version of G4VeEnergyLoss:
// continuous energy loss with generation of subcutoff delta rays
// 02/02/99 important correction in AlongStepDoIt , L.Urban
// 28/04/99 bug fixed (unit independece now),L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// 23/01/01 bug fixed in AlongStepDoIt , L.Urban
// 27/03/01 : commented out the printing of subcutoff energies
// 28/05/01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 11/09/01 minor correction in 'subcutoff' delta generation, L.Urban
// 12/09/01 min.delta cut is set as rcut/100 + some optimisation, L.Urban
// 17-09-01, migration of Materials to pure STL (mma)
// 29-10-01 all static functions no more inlined (mma)
// 08-11-01 Charge,lastCharge not data members, L.Urban
// 06-02-02 bug fixed in MinDeltaCutInRange computation, L.Urban
// 26-02-02 bug fixed in TouchebleHandle definition, V.Ivanchenko
// 15-01-03 Migrade to cut per region (V.Ivanchenko)
// 10-03-03 remove tails of old cuts (V.Ivanchenko)
// 25-03-03 add finalRangeRequested (mma)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 09-05-03 number of dEdx bins 120 (V.Ivanchenko)
// -----------------------------------------------------------------------------
#include "G4VeEnergyLoss.hh"
#include "G4Poisson.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Initialisation of static data members
// -------------------------------------
G4int G4VeEnergyLoss::NbOfProcesses = 2;
G4int G4VeEnergyLoss::CounterOfElectronProcess = 0;
G4int G4VeEnergyLoss::CounterOfPositronProcess = 0;
G4PhysicsTable** G4VeEnergyLoss::RecorderOfElectronProcess =
new G4PhysicsTable*[10];
G4PhysicsTable** G4VeEnergyLoss::RecorderOfPositronProcess =
new G4PhysicsTable*[10];
G4PhysicsTable* G4VeEnergyLoss::theDEDXElectronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theDEDXPositronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theRangeElectronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theRangePositronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theInverseRangeElectronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theInverseRangePositronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theLabTimeElectronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theLabTimePositronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theProperTimeElectronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theProperTimePositronTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theeRangeCoeffATable = 0;
G4PhysicsTable* G4VeEnergyLoss::theeRangeCoeffBTable = 0;
G4PhysicsTable* G4VeEnergyLoss::theeRangeCoeffCTable = 0;
G4PhysicsTable* G4VeEnergyLoss::thepRangeCoeffATable = 0;
G4PhysicsTable* G4VeEnergyLoss::thepRangeCoeffBTable = 0;
G4PhysicsTable* G4VeEnergyLoss::thepRangeCoeffCTable = 0;
G4double G4VeEnergyLoss::LowerBoundEloss =0.1*keV ;
G4double G4VeEnergyLoss::UpperBoundEloss = 100.*TeV ;
G4int G4VeEnergyLoss::NbinEloss = 120 ;
G4double G4VeEnergyLoss::RTable,G4VeEnergyLoss::LOGRTable;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4VeEnergyLoss::G4VeEnergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
theLossTable(0),
MinKineticEnergy(1.*eV),
theDEDXTable(0),
linLossLimit(0.05),
cN(0.077*MeV*cm2/g),
Ndeltamax(100)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VeEnergyLoss::~G4VeEnergyLoss()
{
if (theLossTable)
{
theLossTable->clearAndDestroy();
delete theLossTable; theLossTable = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VeEnergyLoss::SetNbOfProcesses(G4int nb)
{NbOfProcesses=nb;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VeEnergyLoss::PlusNbOfProcesses()
{NbOfProcesses++ ;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VeEnergyLoss::MinusNbOfProcesses()
{NbOfProcesses-- ;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4VeEnergyLoss::GetNbOfProcesses()
{return NbOfProcesses;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VeEnergyLoss::SetLowerBoundEloss(G4double val)
{LowerBoundEloss=val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VeEnergyLoss::SetUpperBoundEloss(G4double val)
{UpperBoundEloss=val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VeEnergyLoss::SetNbinEloss(G4int nb)
{NbinEloss=nb;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VeEnergyLoss::GetLowerBoundEloss()
{return LowerBoundEloss;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VeEnergyLoss::GetUpperBoundEloss()
{return UpperBoundEloss;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4VeEnergyLoss::GetNbinEloss()
{return NbinEloss;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VeEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
{
ParticleMass = aParticleType.GetPDGMass();
// calculate data members LOGRTable,RTable first
G4double lrate = log(UpperBoundEloss/LowerBoundEloss);
LOGRTable=lrate/NbinEloss;
RTable =exp(LOGRTable);
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
//set physically consistent value for finalRange
//and parameters for en.loss step limit
if (finalRangeRequested > 0.) { finalRange = finalRangeRequested;}
/*
else
{
for (size_t idxMate=0; idxMate<numOfCouples; idxMate++)
{
G4double rcut = theCoupleTable->GetMaterialCutsCouple(idxMate)
->GetProductionCuts()->GetProductionCut(idxG4ElectronCut);
if (finalRange > rcut) finalRange = rcut;
}
}
c1lim = dRoverRange;
c2lim = 2.*(1.-dRoverRange)*finalRange;
c3lim = -(1.-dRoverRange)*finalRange*finalRange;
*/
// Build energy loss table as a sum of the energy loss due to the
// different processes.
// create table if there is no table or there is a new cut value
if (&aParticleType==G4Electron::Electron())
{theDEDXTable= theDEDXElectronTable;}
else if (&aParticleType==G4Positron::Positron())
{theDEDXTable= theDEDXPositronTable;}
if ( !theDEDXTable || CutsWhereModified() )
{
// create table for the total energy loss
if (&aParticleType==G4Electron::Electron())
{
RecorderOfProcess=RecorderOfElectronProcess;
CounterOfProcess=CounterOfElectronProcess;
if (CounterOfProcess == NbOfProcesses)
{
if (theDEDXElectronTable)
{
theDEDXElectronTable->clearAndDestroy();
delete theDEDXElectronTable;
}
theDEDXElectronTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXElectronTable;
}
}
if (&aParticleType==G4Positron::Positron())
{
RecorderOfProcess=RecorderOfPositronProcess;
CounterOfProcess=CounterOfPositronProcess;
if (CounterOfProcess == NbOfProcesses)
{
if (theDEDXPositronTable)
{
theDEDXPositronTable->clearAndDestroy();
delete theDEDXPositronTable;
}
theDEDXPositronTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXPositronTable;
}
}
if (CounterOfProcess == NbOfProcesses)
{
// fill the tables
// loop for materials
G4double LowEdgeEnergy , Value;
G4bool isOutRange;
G4PhysicsTable* pointer;
for (size_t J=0; J<numOfCouples; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundEloss, UpperBoundEloss, NbinEloss);
// loop for the kinetic energy
for (G4int i=0; i<NbinEloss; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
//here comes the sum of the different tables created by the
//processes (ionisation,bremsstrahlung,etc...)
Value = 0.;
for (G4int process=0; process < NbOfProcesses; process++)
{
pointer= RecorderOfProcess[process];
Value += (*pointer)[J]->GetValue(LowEdgeEnergy,isOutRange);
}
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
//reset counter to zero
if (&aParticleType==G4Electron::Electron()) CounterOfElectronProcess=0;
if (&aParticleType==G4Positron::Positron()) CounterOfPositronProcess=0;
ParticleMass = aParticleType.GetPDGMass();
if (&aParticleType==G4Electron::Electron())
{
// Build range table
theRangeElectronTable = BuildRangeTable(theDEDXElectronTable,
theRangeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimeElectronTable = BuildLabTimeTable(theDEDXElectronTable,
theLabTimeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimeElectronTable = BuildProperTimeTable(theDEDXElectronTable,
theProperTimeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
theeRangeCoeffATable = BuildRangeCoeffATable(theRangeElectronTable,
theeRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theeRangeCoeffBTable = BuildRangeCoeffBTable(theRangeElectronTable,
theeRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theeRangeCoeffCTable = BuildRangeCoeffCTable(theRangeElectronTable,
theeRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangeElectronTable = BuildInverseRangeTable(
theRangeElectronTable,
theeRangeCoeffATable,
theeRangeCoeffBTable,
theeRangeCoeffCTable,
theInverseRangeElectronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
/*
G4cout << "DEDXTable address= " << theDEDXElectronTable << G4endl;
if(theDEDXElectronTable) G4cout << (*theDEDXElectronTable) << G4endl;
G4cout << "RangeTable address= " << theRangeElectronTable << G4endl;
if(theRangeElectronTable) G4cout << (*theRangeElectronTable) << G4endl;
G4cout << "InverseRangeTable address= " << theInverseRangeElectronTable << G4endl;
if(theInverseRangeElectronTable) G4cout << (*theInverseRangeElectronTable) << G4endl;
*/
}
if (&aParticleType==G4Positron::Positron())
{
// Build range table
theRangePositronTable = BuildRangeTable(theDEDXPositronTable,
theRangePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimePositronTable = BuildLabTimeTable(theDEDXPositronTable,
theLabTimePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimePositronTable = BuildProperTimeTable(theDEDXPositronTable,
theProperTimePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepRangeCoeffATable = BuildRangeCoeffATable(theRangePositronTable,
thepRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffBTable = BuildRangeCoeffBTable(theRangePositronTable,
thepRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffCTable = BuildRangeCoeffCTable(theRangePositronTable,
thepRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangePositronTable = BuildInverseRangeTable(
theRangePositronTable,
thepRangeCoeffATable,
thepRangeCoeffBTable,
thepRangeCoeffCTable,
theInverseRangePositronTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
(&aParticleType==G4Electron::Electron())?
theDEDXElectronTable: theDEDXPositronTable,
(&aParticleType==G4Electron::Electron())?
theRangeElectronTable: theRangePositronTable,
(&aParticleType==G4Electron::Electron())?
theInverseRangeElectronTable: theInverseRangePositronTable,
(&aParticleType==G4Electron::Electron())?
theLabTimeElectronTable: theLabTimePositronTable,
(&aParticleType==G4Electron::Electron())?
theProperTimeElectronTable: theProperTimePositronTable,
LowerBoundEloss, UpperBoundEloss, 1.,NbinEloss);
// create array for the min. delta cuts in kinetic energy
G4double absLowerLimit = 1.*keV ;
// if((subSecFlag) && (&aParticleType==G4Electron::Electron()))
// {
// G4cout << G4endl;
// G4cout.precision(5) ;
// G4cout << " eIoni Minimum Delta cut in range="
// << MinDeltaCutInRange/mm
// << " mm." << G4endl;
// G4cout << G4endl;
// G4cout << " material min.delta energy(keV) " << G4endl;
// G4cout << G4endl;
// }
if(MinDeltaEnergy) {delete [] MinDeltaEnergy; MinDeltaEnergy=0;}
MinDeltaEnergy = new G4double [numOfCouples];
if(LowerLimitForced) {delete [] LowerLimitForced; LowerLimitForced=0;}
LowerLimitForced = new G4bool [numOfCouples];
for(size_t mat=0; mat<numOfCouples; mat++)
{
// create array for the min. delta cuts in kinetic energy
G4double ecut = (*(theCoupleTable->GetEnergyCutsVector(idxG4ElectronCut)))[mat];
if(!setMinDeltaCutInRange) MinDeltaCutInRange = ecut/10.0;
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),
MinDeltaCutInRange,
theCoupleTable->GetMaterialCutsCouple(mat));
if(MinDeltaEnergy[mat]<absLowerLimit) MinDeltaEnergy[mat] = absLowerLimit;
if(MinDeltaEnergy[mat]>ecut) MinDeltaEnergy[mat]=ecut;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
// compute the energy loss after a Step
static const G4double faclow = 1.5 ;
static const G4double Tlow = 1.0*keV;
// get particle and material pointers from trackData
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double Charge = aParticle->GetDefinition()->GetPDGCharge()/eplus;
G4double E = aParticle->GetKineticEnergy() ;
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4Material* aMaterial = couple->GetMaterial();
G4int index = couple->GetIndex();
G4double Step = stepData.GetStepLength();
aParticleChange.Initialize(trackData);
G4double MeanLoss, finalT;
if (E < MinKineticEnergy) finalT = 0.;
else if (E<faclow*LowerBoundEloss)
{
if (Step >= fRangeNow) finalT = 0.;
else finalT = E*(1.-sqrt(Step/fRangeNow)) ;
}
else if (E>=UpperBoundEloss) finalT = E - Step*fdEdx;
else if (Step >= fRangeNow) finalT = 0.;
else
{
if((Step/fRangeNow < linLossLimit)||(E < Tlow)) finalT = E-Step*fdEdx ;
else
{
if (Charge<0.) finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
(G4Electron::Electron(),fRangeNow-Step,couple);
else finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
(G4Positron::Positron(),fRangeNow-Step,couple);
}
}
if(finalT < MinKineticEnergy) finalT = 0. ;
MeanLoss = E - finalT ;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// start of subcutoff generation
// do not generate subdeltas for the initial step !! (time..)
if((subSecFlag) && (trackData.GetCurrentStepNumber() > 1))
{
G4double MinDeltaEnergyNow = MinDeltaEnergy[index] ;
G4double TmintoProduceDelta=0.5*(3.-Charge)*MinDeltaEnergyNow ;
if((E > TmintoProduceDelta) && (MeanLoss > MinDeltaEnergyNow)
&& (finalT > MinKineticEnergy))
{
G4double T0,presafety,postsafety,safety,delta;
G4double fragment = Step;
G4double frperstep= 1.0;
G4double x1,y1,z1,dx,dy,dz,dTime,time0,DeltaTime;
//G4double epsil= MinKineticEnergy/2. ;
G4double Tc = SecondaryEnergyThreshold(index);
G4double rcut=couple->GetProductionCuts()->GetProductionCut(idxG4ElectronCut);
if(Charge < 0.)
{
if(Tc > 0.5*E) Tc=0.5*E ;
}
else
{
if(Tc > E) Tc=E ;
}
// generate subcutoff delta rays only if Tc>MinDeltaEnergy!
if(Tc > MinDeltaEnergyNow)
{
presafety = stepData.GetPreStepPoint()->GetSafety() ;
G4Navigator *navigator=
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
postsafety =
navigator->ComputeSafety(stepData.GetPostStepPoint()->GetPosition());
safety=min(presafety,postsafety);
if(safety<rcut)
{
T0=G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),safety,couple) ;
// absolute lower limit for T0
// if(T0<MinDeltaEnergyNow) T0=MinDeltaEnergyNow ;
if((T0<MinDeltaEnergyNow)||(LowerLimitForced[index]))
T0=MinDeltaEnergyNow ;
// ..................................................................
x1=stepData.GetPreStepPoint()->GetPosition().x();
y1=stepData.GetPreStepPoint()->GetPosition().y();
z1=stepData.GetPreStepPoint()->GetPosition().z();
dx=stepData.GetPostStepPoint()->GetPosition().x()-x1 ;
dy=stepData.GetPostStepPoint()->GetPosition().y()-y1 ;
dz=stepData.GetPostStepPoint()->GetPosition().z()-z1 ;
time0=stepData.GetPreStepPoint()->GetGlobalTime();
dTime=stepData.GetPostStepPoint()->GetGlobalTime()-time0;
if((presafety<rcut)&&(postsafety<rcut))
{
fragment = Step ;
frperstep=1. ;
}
else if(presafety<rcut)
{
delta=presafety*Step/(postsafety-presafety) ;
fragment=rcut*(Step+delta)/postsafety-delta ;
frperstep=fragment/Step;
}
else if(postsafety<rcut)
{
delta=postsafety*Step/(presafety-postsafety) ;
fragment=rcut*(Step+delta)/presafety-delta ;
x1 += dx;
y1 += dy;
z1 += dz;
time0 += dTime ;
frperstep=-fragment/Step;
}
if(fragment>0.)
{
// compute nb of delta rays to be generated
// from the de/dx formula (approximately)
// and assuming an 1/T**2 delta energy spectrum
G4double delToverTc=1.-T0/Tc ;
G4double deldedx=cN*aMaterial->GetDensity()*
((E+electron_mass_c2)*(E+electron_mass_c2)*
log(Tc/T0)/(E*(E+electron_mass_c2))) ;
G4int N=G4int(deldedx*fragment*delToverTc/(T0*log(Tc/T0))+0.5) ;
if(N > Ndeltamax)
N = Ndeltamax ;
G4double Px,Py,Pz ;
G4ThreeVector ParticleDirection ;
ParticleDirection=stepData.GetPreStepPoint()->
GetMomentumDirection() ;
Px =ParticleDirection.x() ;
Py =ParticleDirection.y() ;
Pz =ParticleDirection.z() ;
G4int subdelta = 0;
if(N > 0)
{
G4double Tkin,Etot,P,T,p,costheta,sintheta,phi,dirx,diry,dirz,
Pnew,sumT,urandom ;
//delTkin,delLoss,rate,
//G4StepPoint *point ;
sumT=0.;
Tkin = E ;
Etot = Tkin+electron_mass_c2 ;
P = sqrt(Tkin*(Etot+electron_mass_c2)) ;
aParticleChange.SetNumberOfSecondaries(N);
do {
subdelta += 1 ;
if((Charge<0.)&&(Tc>0.5*Tkin)) Tc=0.5*Tkin ;
if((Charge>0.)&&(Tc> Tkin)) Tc= Tkin ;
//check if there is enough energy ....
if((Tkin>TmintoProduceDelta)&&(Tc > T0)&&(MeanLoss>0.))
{
delToverTc=1.-T0/Tc ;
T=T0/(1.-delToverTc*G4UniformRand()) ;
if(T > MeanLoss) T=MeanLoss ;
MeanLoss -= T ;
p=sqrt(T*(T+2.*electron_mass_c2)) ;
costheta = T*(Etot+electron_mass_c2)/(P*p) ;
if(costheta<-1.) costheta=-1.;
if(costheta> 1.) costheta= 1.;
phi=twopi*G4UniformRand() ;
sintheta=sqrt(1.-costheta*costheta);
dirx=sintheta*cos(phi);
diry=sintheta*sin(phi);
dirz=costheta;
sumT += T ;
urandom = G4UniformRand() ;
// distribute x,y,z along Pre-Post !
G4double xd,yd,zd ;
xd=x1+frperstep*dx*urandom ;
yd=y1+frperstep*dy*urandom ;
zd=z1+frperstep*dz*urandom ;
G4ThreeVector DeltaPosition(xd,yd,zd) ;
DeltaTime=time0+frperstep*dTime*urandom ;
G4ThreeVector DeltaDirection(dirx,diry,dirz) ;
DeltaDirection.rotateUz(ParticleDirection);
G4DynamicParticle* theDelta = new G4DynamicParticle ;
theDelta->SetDefinition(G4Electron::Electron());
theDelta->SetKineticEnergy(T);
theDelta->SetMomentumDirection(DeltaDirection.x(),
DeltaDirection.y(),DeltaDirection.z());
// update initial particle,fill ParticleChange
Tkin -= T ;
Px =(P*ParticleDirection.x()-p*DeltaDirection.x()) ;
Py =(P*ParticleDirection.y()-p*DeltaDirection.y()) ;
Pz =(P*ParticleDirection.z()-p*DeltaDirection.z()) ;
Pnew = sqrt(Px*Px+Py*Py+Pz*Pz) ;
Px /= Pnew ;
Py /= Pnew ;
Pz /= Pnew ;
P = Pnew ;
G4ThreeVector ParticleDirectionnew(Px,Py,Pz) ;
ParticleDirection = ParticleDirectionnew;
G4Track* deltaTrack =
new G4Track(theDelta,DeltaTime,DeltaPosition);
deltaTrack->SetTouchableHandle(stepData.GetPreStepPoint()
->GetTouchableHandle());
deltaTrack->SetParentID(trackData.GetTrackID()) ;
aParticleChange.AddSecondary(deltaTrack) ;
}
} while (subdelta<N) ;
// update the particle direction and kinetic energy
if(subdelta > 0)
aParticleChange.ProposeMomentumDirection(Px,Py,Pz) ;
E = Tkin ;
}
}
// ................................................................
}
}
}
}
// end of subcutoff generation
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
finalT = E - MeanLoss ;
if(finalT < MinKineticEnergy) finalT = 0. ;
//now the loss with fluctuation
if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
{
finalT = E-GetLossWithFluct(aParticle,couple,1.,MeanLoss,Step);
if (finalT < 0.) finalT = 0. ;
}
// kill the particle if the kinetic energy <= 0
if (finalT <= 0. )
{
finalT = 0.;
if (Charge < 0.) aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.ProposeEnergy(finalT);
aParticleChange.ProposeLocalEnergyDeposit(E-finalT);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -1,723 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4VhEnergyLoss.cc,v 1.49 2006/06/29 19:53:38 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
// -----------------------------------------------------------------------------
// 07/10/98 bug fixes + some cleanup , L.Urban
// 22/10/98 cleanup , L.Urban
// 07/12/98 works for ions as well+ bug corrected, L.Urban
// 02/02/99 several bugs fixed, L.Urban
// 01/03/99 creation of sub-cutoff delta rays, L.Urban
// 28/04/99 bug fixed in DoIt , L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// 18/07/00 bug fix in AlongStepDoIt V.Ivanchenko
// 10/08/00 V.Ivanchenko change AlongStepDoIt and
// add EnergyLossFluctuation in order to simulate
// energy losses of ions
// 17/08/00 V.Ivanchenko change EnergyLossFluctuation
// 18/08/00 V.Ivanchenko bug fixed in GetConstrained
// 23/01/01 bug fixed in AlongStepDoIt , L.Urban
// 27/03/01 commented out the printing of subcutoff energies
// 28/05/01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 10/09/01 bugfix in subcutoff delta generation, L.Urban
// 12/09/01 min.delta cut is set as rcut/100 + some optimisation, L.Urban
// 17-09-01 migration of Materials to pure STL (mma)
// 29-10-01 all static functions no more inlined (mma)
// 08-11-01 BuildDEDXTable not static,Charge local variable, L.Urban
// 09-11-01 cosmetics; 80 columns everywhere (mma)
// 06-02-02 bug fixed in MinDeltaCutInRange computation, L.Urban
// 26-02-02 bug fixed in TouchebleHandle definition, V.Ivanchenko
// 29-05-02 bug fixed in N of subcutoff delta, V.Ivanchenko
// 10-06-02 bug fixed for stopping hadrons, V.Ivanchenko
// 15-01-03 Migrade to cut per region (V.Ivanchenko)
// 25-03-03 add finalRangeRequested (mma)
// 07-04-03 add verbosity (V.Ivanchenko)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 17-04-03 fix problem of hadron tests (V.Ivanchenko)
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4VhEnergyLoss.hh"
#include "G4EnergyLossTables.hh"
#include "G4Poisson.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4ProcessManager.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4VhEnergyLoss::NbOfProcesses = 1;
G4int G4VhEnergyLoss::CounterOfProcess = 0;
G4PhysicsTable** G4VhEnergyLoss::RecorderOfProcess =
new G4PhysicsTable*[10];
G4int G4VhEnergyLoss::CounterOfpProcess = 0;
G4PhysicsTable** G4VhEnergyLoss::RecorderOfpProcess =
new G4PhysicsTable*[10];
G4int G4VhEnergyLoss::CounterOfpbarProcess = 0;
G4PhysicsTable** G4VhEnergyLoss::RecorderOfpbarProcess =
new G4PhysicsTable*[10];
G4PhysicsTable* G4VhEnergyLoss::theDEDXpTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theDEDXpbarTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theRangepTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theRangepbarTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theInverseRangepTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theInverseRangepbarTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theLabTimepTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theLabTimepbarTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theProperTimepTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theProperTimepbarTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::thepRangeCoeffATable = NULL;
G4PhysicsTable* G4VhEnergyLoss::thepRangeCoeffBTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::thepRangeCoeffCTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::thepbarRangeCoeffATable = NULL;
G4PhysicsTable* G4VhEnergyLoss::thepbarRangeCoeffBTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::thepbarRangeCoeffCTable = NULL;
G4PhysicsTable* G4VhEnergyLoss::theDEDXTable = NULL;
G4double G4VhEnergyLoss::LowerBoundEloss = 1.*keV;
G4double G4VhEnergyLoss::UpperBoundEloss = 100.*TeV;
G4int G4VhEnergyLoss::NbinEloss = 100;
G4double G4VhEnergyLoss::RTable,G4VhEnergyLoss::LOGRTable;
G4double G4VhEnergyLoss::cN = 0.077*MeV*cm2/g;
G4int G4VhEnergyLoss::Ndeltamax = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4VhEnergyLoss::G4VhEnergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
theLossTable (NULL),
MinKineticEnergy(1.*eV),
linLossLimit(0.05)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VhEnergyLoss::~G4VhEnergyLoss()
{
if(theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable; theLossTable = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VhEnergyLoss::SetNbOfProcesses(G4int nb)
{NbOfProcesses=nb;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VhEnergyLoss::PlusNbOfProcesses()
{NbOfProcesses++ ;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VhEnergyLoss::MinusNbOfProcesses()
{NbOfProcesses-- ;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4VhEnergyLoss::GetNbOfProcesses()
{return NbOfProcesses;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VhEnergyLoss::SetLowerBoundEloss(G4double val)
{LowerBoundEloss=val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VhEnergyLoss::SetUpperBoundEloss(G4double val)
{UpperBoundEloss=val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VhEnergyLoss::SetNbinEloss(G4int nb)
{NbinEloss=nb;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VhEnergyLoss::GetLowerBoundEloss()
{return LowerBoundEloss;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VhEnergyLoss::GetUpperBoundEloss()
{return UpperBoundEloss;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4VhEnergyLoss::GetNbinEloss()
{return NbinEloss;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VhEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4VhEnergyLoss::BuildDEDXTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
// calculate data members LOGRTable,RTable first
G4double lrate = log(UpperBoundEloss/LowerBoundEloss);
LOGRTable=lrate/NbinEloss;
RTable =exp(LOGRTable);
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
//set physically consistent value for finalRange
//and parameters for en.loss step limit
if (finalRangeRequested > 0.) { finalRange = finalRangeRequested;}
// create table if there is no table or there is a new cut value
// create/fill proton or antiproton tables depending on the charge
G4double Charge = aParticleType.GetPDGCharge()/eplus;
ParticleMass = aParticleType.GetPDGMass() ;
if (Charge>0.) {theDEDXTable= theDEDXpTable;}
else {theDEDXTable= theDEDXpbarTable;}
G4String pname = aParticleType.GetParticleName();
if( !theDEDXTable || (CutsWhereModified() &&
(pname == "proton" || pname == "anti_proton")) )
{
// Build energy loss table as a sum of the energy loss due to the
// different processes.
if (Charge >0.)
{
if(theDEDXpTable) {theDEDXpTable->clearAndDestroy();
delete theDEDXpTable;}
theDEDXpTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXpTable;
}
else
{
if(theDEDXpbarTable) {theDEDXpbarTable->clearAndDestroy();
delete theDEDXpbarTable;}
theDEDXpbarTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXpbarTable;
}
// loop for materials
//
G4bool isOutRange;
G4PhysicsTable* pointer;
for (size_t J=0; J<numOfCouples; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundEloss, UpperBoundEloss, NbinEloss);
// loop for the kinetic energy
for (G4int i=0; i<NbinEloss; i++)
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double Value = 0. ;
// loop for the contributing processes
for (G4int process=0; process < NbOfProcesses; process++)
{
pointer= RecorderOfpProcess[process];
Value += (*pointer)[J]->GetValue(LowEdgeEnergy,isOutRange);
}
aVector->PutValue(i,Value);
}
theDEDXTable->insert(aVector);
}
if(Charge > 0.)
{
// Build range table
//
theRangepTable = BuildRangeTable(theDEDXpTable, theRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
//
theLabTimepTable = BuildLabTimeTable(theDEDXpTable, theLabTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepTable = BuildProperTimeTable(theDEDXpTable,
theProperTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
//
thepRangeCoeffATable = BuildRangeCoeffATable(theRangepTable,
thepRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffBTable = BuildRangeCoeffBTable(theRangepTable,
thepRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffCTable = BuildRangeCoeffCTable(theRangepTable,
thepRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
//
theInverseRangepTable = BuildInverseRangeTable(theRangepTable,
thepRangeCoeffATable,
thepRangeCoeffBTable,
thepRangeCoeffCTable,
theInverseRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
else
{
// Build range table
//
theRangepbarTable = BuildRangeTable(theDEDXpbarTable, theRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
//
theLabTimepbarTable = BuildLabTimeTable(theDEDXpbarTable,
theLabTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepbarTable = BuildProperTimeTable(theDEDXpbarTable,
theProperTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
//
thepbarRangeCoeffATable = BuildRangeCoeffATable(theRangepbarTable,
thepbarRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffBTable = BuildRangeCoeffBTable(theRangepbarTable,
thepbarRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffCTable = BuildRangeCoeffCTable(theRangepbarTable,
thepbarRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
//
theInverseRangepbarTable = BuildInverseRangeTable(theRangepbarTable,
thepbarRangeCoeffATable,
thepbarRangeCoeffBTable,
thepbarRangeCoeffCTable,
theInverseRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
(Charge>0)? theDEDXpTable: theDEDXpbarTable,
(Charge>0)? theRangepTable: theRangepbarTable,
(Charge>0)? theInverseRangepTable: theInverseRangepbarTable,
(Charge>0)? theLabTimepTable: theLabTimepbarTable,
(Charge>0)? theProperTimepTable: theProperTimepbarTable,
LowerBoundEloss, UpperBoundEloss,
proton_mass_c2/aParticleType.GetPDGMass(),NbinEloss);
if(MinDeltaEnergy) {delete [] MinDeltaEnergy; MinDeltaEnergy=0;}
MinDeltaEnergy = new G4double [numOfCouples];
if(LowerLimitForced) {delete [] LowerLimitForced; LowerLimitForced=0;}
LowerLimitForced = new G4bool [numOfCouples];
G4double Tlowerlimit = 1.*keV;
for (size_t mat=0; mat<numOfCouples; mat++)
{
// create array for the min. delta cuts in kinetic energy
G4double ecut = (*(theCoupleTable->GetEnergyCutsVector(1)))[mat];
if(!setMinDeltaCutInRange) MinDeltaCutInRange = ecut/10.0;
MinDeltaEnergy[mat] = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),
MinDeltaCutInRange,
theCoupleTable->GetMaterialCutsCouple(mat));
if(MinDeltaEnergy[mat]<Tlowerlimit) MinDeltaEnergy[mat]=Tlowerlimit;
if(MinDeltaEnergy[mat]>ecut) MinDeltaEnergy[mat]=ecut;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
const G4MaterialCutsCouple * couple)
{
// returns the Step limit
// dRoverRange is the max. allowed relative range loss in one step
// it calculates dEdx and the range as well....
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double massratio=proton_mass_c2/(aParticle->GetMass());
G4double Tscaled = KineticEnergy*massratio;
G4double Charge = aParticle->GetCharge()/eplus;
G4double ChargeSquare = Charge*Charge;
if (Charge>0.)
{
fRangeNow=G4EnergyLossTables::GetRange(G4Proton::Proton(),Tscaled,couple);
fdEdx =G4EnergyLossTables::GetDEDX (G4Proton::Proton(),Tscaled,couple);
}
else
{
fRangeNow=G4EnergyLossTables::GetRange(G4AntiProton::AntiProton(),
Tscaled,couple);
fdEdx =G4EnergyLossTables::GetDEDX (G4AntiProton::AntiProton(),
Tscaled,couple);
}
fdEdx *= ChargeSquare;
fRangeNow /= (ChargeSquare*massratio);
// compute the (random) Step limit
//
G4double r = min(finalRange, couple->GetProductionCuts()
->GetProductionCut(idxG4ElectronCut));
G4double StepLimit;
if (fRangeNow > r)
{
StepLimit = dRoverRange*fRangeNow + r*(1.0 - dRoverRange)*(2.0 - r/fRangeNow);
// StepLimit = (c1lim*fRangeNow+c2lim+c3lim/fRangeNow);
// randomise this value
if (rndmStepFlag) StepLimit=r+(StepLimit-r)*G4UniformRand();
if (StepLimit > fRangeNow) StepLimit = fRangeNow;
}
else StepLimit = fRangeNow;
return StepLimit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
const G4Track& trackData,const G4Step& stepData)
{
// compute the energy loss after a step
//
aParticleChange.Initialize(trackData);
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4Material* aMaterial = couple->GetMaterial();
G4int index = couple->GetIndex();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double Charge = aParticle->GetCharge()/eplus;
G4double ChargeSquare = Charge*Charge;
G4double mass=aParticle->GetMass();
// get the actual (true) Step length from stepData
G4double Step = stepData.GetStepLength();
G4double E = aParticle->GetKineticEnergy();
G4double MeanLoss = 0.;
if (E < MinKineticEnergy) MeanLoss = E;
else
{
if(Step >= fRangeNow) MeanLoss = E;
else if((E > UpperBoundEloss)||(E <= LowerBoundEloss)) MeanLoss = Step*fdEdx;
else
{
if (Step>linLossLimit*fRangeNow)
{
G4double massratio = proton_mass_c2/mass;
G4double rscaled = fRangeNow*massratio*ChargeSquare;
G4double sscaled = Step *massratio*ChargeSquare;
if (Charge>0.)
{
MeanLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Proton::Proton(),
rscaled ,couple) -
G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Proton::Proton(),
rscaled-sscaled,couple);
}
else
{
MeanLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(
G4AntiProton::AntiProton(),
rscaled ,couple) -
G4EnergyLossTables::GetPreciseEnergyFromRange(
G4AntiProton::AntiProton(),
rscaled-sscaled,couple);
}
MeanLoss /= massratio;
}
else MeanLoss = Step*fdEdx;
}
}
G4double finalT = E - MeanLoss;
// subcutoff delta ray production start
//
if((subSecFlag) && (trackData.GetCurrentStepNumber() > 1))
{
G4double delta;
G4double fragment = Step;
G4double frperstep = 1.0;
G4double x1,y1,z1,dx,dy,dz,dTime,time0,DeltaTime;
G4double MinDeltaEnergyNow = MinDeltaEnergy[index] ;
G4double Tc = SecondaryEnergyThreshold(index);
G4double w=mass+electron_mass_c2 ;
G4double ww=2.*mass-MinDeltaEnergyNow ;
G4double TmintoProduceDelta=0.5*(sqrt(ww*ww+2.*w*w*MinDeltaEnergyNow/
electron_mass_c2)-ww);
if((E > TmintoProduceDelta) && (MeanLoss > MinDeltaEnergyNow)
&& (finalT > MinKineticEnergy))
{
// max. possible delta energy
G4double Tmax = 2.*electron_mass_c2*E*(E+2.*mass)/
(mass*mass+2.*electron_mass_c2*(E+mass)+
electron_mass_c2*electron_mass_c2);
G4double rcut=couple->GetProductionCuts()->GetProductionCut(1);
if (Tc > Tmax) Tc=Tmax;
// generate subcutoff delta rays only if Tc>MinDeltaEnergyNow
if ((Tc > MinDeltaEnergyNow) && (Tmax > MinDeltaEnergyNow))
{
G4double presafety = stepData.GetPreStepPoint()->GetSafety();
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
G4double postsafety =
navigator->ComputeSafety(stepData.GetPostStepPoint()->GetPosition());
G4double safety = min(presafety,postsafety);
if (safety < rcut)
{
x1=stepData.GetPreStepPoint()->GetPosition().x();
y1=stepData.GetPreStepPoint()->GetPosition().y();
z1=stepData.GetPreStepPoint()->GetPosition().z();
dx=stepData.GetPostStepPoint()->GetPosition().x()-x1;
dy=stepData.GetPostStepPoint()->GetPosition().y()-y1;
dz=stepData.GetPostStepPoint()->GetPosition().z()-z1;
time0=stepData.GetPreStepPoint()->GetGlobalTime();
dTime=stepData.GetPostStepPoint()->GetGlobalTime()-time0;
if ((presafety<rcut)&&(postsafety<rcut))
{
fragment = Step;
frperstep=1.;
}
else if (presafety<rcut)
{
delta=presafety*Step/(postsafety-presafety) ;
fragment=rcut*(Step+delta)/postsafety-delta ;
frperstep=fragment/Step;
}
else if(postsafety<rcut)
{
delta=postsafety*Step/(presafety-postsafety);
fragment=rcut*(Step+delta)/presafety-delta ;
x1 += dx;
y1 += dy;
z1 += dz;
time0 += dTime ;
frperstep=-fragment/Step;
}
if (fragment>0.)
{
G4double T0=G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),
min(presafety,postsafety),
couple);
// absolute lower limit for T0
if((T0<MinDeltaEnergyNow)||(LowerLimitForced[index]))
T0=MinDeltaEnergyNow;
//compute nb of delta rays to be generated
//approximate value based on Bethe-Bloch and
//assuming an 1/E**2 delta spectrum
G4double deldedx=cN*aMaterial->GetDensity()*
((E+mass)*(E+mass)*log(Tc/T0)/(E*(E+mass)));
G4double delToverTc=1.-T0/Tc ;
G4int N = G4int(deldedx*fragment*delToverTc/(T0*log(Tc/T0))+0.5);
if(N > Ndeltamax) N = Ndeltamax;
G4ThreeVector ParticleDirection = aParticle->GetMomentumDirection();
G4double Px =ParticleDirection.x();
G4double Py =ParticleDirection.y();
G4double Pz =ParticleDirection.z();
G4int subdelta = 0;
if (N > 0)
{
G4double T,p,costheta,sintheta,phi,dirx,diry,dirz,
Pnew,urandom;
G4double Tkin = E;
G4double Etot = Tkin+mass;
G4double P = sqrt(Tkin*(Etot+mass));
aParticleChange.SetNumberOfSecondaries(N);
do {
subdelta += 1;
Tmax = 2.*electron_mass_c2*Tkin*(Tkin+2.*mass)/
(mass*mass+2.*electron_mass_c2*(Tkin+mass)+
electron_mass_c2*electron_mass_c2);
if(Tc>Tmax) Tc = Tmax;
//check if there is enough energy ....
if((Tkin>TmintoProduceDelta)&&(Tc > T0)&&(MeanLoss>0.))
{
delToverTc=1.-T0/Tc;
T=T0/(1.-delToverTc*G4UniformRand());
if(T > MeanLoss) T=MeanLoss;
MeanLoss -= T;
p=sqrt(T*(T+2.*electron_mass_c2));
costheta = T*(Etot+electron_mass_c2)/(P*p);
if(costheta<-1.) costheta=-1.;
if(costheta> 1.) costheta= 1.;
phi=twopi*G4UniformRand();
sintheta=sqrt(1.-costheta*costheta);
dirx=sintheta*cos(phi);
diry=sintheta*sin(phi);
dirz=costheta;
urandom = G4UniformRand() ;
// distribute x,y,z along Pre-Post !
G4double xd=x1+frperstep*dx*urandom;
G4double yd=y1+frperstep*dy*urandom;
G4double zd=z1+frperstep*dz*urandom;
G4ThreeVector DeltaPosition(xd,yd,zd);
DeltaTime=time0+frperstep*dTime*urandom;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
G4DynamicParticle* theDelta = new G4DynamicParticle;
theDelta->SetDefinition(G4Electron::Electron());
theDelta->SetKineticEnergy(T);
theDelta->SetMomentumDirection(DeltaDirection.x(),
DeltaDirection.y(),DeltaDirection.z());
// update initial particle,fill ParticleChange
Tkin -= T;
Px =(P*ParticleDirection.x()-p*DeltaDirection.x());
Py =(P*ParticleDirection.y()-p*DeltaDirection.y());
Pz =(P*ParticleDirection.z()-p*DeltaDirection.z());
Pnew = sqrt(Px*Px+Py*Py+Pz*Pz);
Px /= Pnew;
Py /= Pnew;
Pz /= Pnew;
P = Pnew;
G4ThreeVector ParticleDirectionnew(Px,Py,Pz);
ParticleDirection = ParticleDirectionnew;
G4Track* deltaTrack =
new G4Track(theDelta,DeltaTime,DeltaPosition);
deltaTrack->SetTouchableHandle(stepData.GetPreStepPoint()
->GetTouchableHandle());
deltaTrack->SetParentID(trackData.GetTrackID());
aParticleChange.AddSecondary(deltaTrack);
}
} while (subdelta<N);
// update the particle direction and kinetic energy
if(subdelta > 0) aParticleChange.ProposeMomentumDirection(Px,Py,Pz);
E = Tkin;
}
}
}
}
}
}
// end of subcutoff business
finalT = E - MeanLoss;
if(finalT < MinKineticEnergy) finalT = 0.;
// now the loss with fluctuation
if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
{
finalT = E -
EnergyLossFluctuation(aParticle,couple,ChargeSquare,MeanLoss,Step);
if (finalT < 0.) finalT = 0.;
}
// kill the particle if the kinetic energy <= 0
if (finalT <= 0.)
{
finalT = 0.;
if(!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.ProposeEnergy(finalT);
aParticleChange.ProposeLocalEnergyDeposit(E-finalT);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VhEnergyLoss::EnergyLossFluctuation(
const G4DynamicParticle* aParticle,
const G4MaterialCutsCouple* couple,
G4double ChargeSquare,
G4double MeanLoss,
G4double Step)
{
return GetLossWithFluct(aParticle,couple,ChargeSquare,MeanLoss,Step);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4WaterStopping.cc,v 1.2 2006/06/29 19:53:40 gunter Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//---------------------------------------------------------------------------
//
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4eBremsstrahlung.cc,v 1.46 2007/01/18 12:17:04 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4eBremsstrahlung.cc,v 1.48 2007/05/23 08:47:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -88,17 +88,10 @@
using namespace std;
G4eBremsstrahlung::G4eBremsstrahlung(const G4String& name, G4double thresh):
G4eBremsstrahlung::G4eBremsstrahlung(const G4String& name):
G4VEnergyLossProcess(name),
gammaThreshold(thresh),
isInitialised(false)
{
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
}
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -111,7 +104,6 @@ void G4eBremsstrahlung::InitialiseEnergyLossProcess(
const G4ParticleDefinition* p,
const G4ParticleDefinition*)
{
gammaThreshold = G4LossTableManager::Instance()->BremsstrahlungTh();
if(!isInitialised) {
particle = p;
SetSecondaryParticle(G4Gamma::Gamma());
@@ -124,19 +116,31 @@ void G4eBremsstrahlung::InitialiseEnergyLossProcess(
AddEmModel(1, EmModel(), FluctModel());
isInitialised = true;
}
G4LossTableManager* man = G4LossTableManager::Instance();
dynamic_cast<G4eBremsstrahlungModel*>(EmModel())
->SetEnergyThreshold(man->BremsstrahlungTh());
dynamic_cast<G4eBremsstrahlungModel*>(EmModel())
->SetLPMflag(man->LPMFlag());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::PrintInfo()
{
if(EmModel())
if(EmModel()) {
G4cout << " Total cross sections and sampling from "
<< EmModel()->GetName() << " model"
<< " (based on the EEDL data library) "
<< "\n Good description from 1 KeV to 100 GeV, "
<< "log scale extrapolation above 100 GeV."
<< " LPM flag "
<< dynamic_cast<G4eBremsstrahlungModel*>(EmModel())->LPMflag()
<< G4endl;
G4double eth = dynamic_cast<G4eBremsstrahlungModel*>(EmModel())->EnergyThreshold();
if(eth < DBL_MIN)
G4cout << " HighEnergyThreshold(GeV)= " << eth/GeV
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
File diff suppressed because it is too large Load Diff
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4eBremsstrahlungModel.cc,v 1.37 2007/02/15 10:37:37 maire Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4eBremsstrahlungModel.cc,v 1.39 2007/05/23 08:47:35 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -81,18 +81,20 @@ using namespace std;
G4eBremsstrahlungModel::G4eBremsstrahlungModel(const G4ParticleDefinition* p,
const G4String& nam)
: G4VEmModel(nam),
particle(0),
minThreshold(1.0*keV),
isElectron(true),
highKinEnergy(100.*TeV),
lowKinEnergy(1.0*keV),
probsup(1.0),
MigdalConstant(classic_electr_radius*electron_Compton_length*electron_Compton_length/pi),
LPMconstant(fine_structure_const*electron_mass_c2*electron_mass_c2/(4.*pi*hbarc)),
theLPMflag(true)
particle(0),
isElectron(true),
probsup(1.0),
MigdalConstant(classic_electr_radius*electron_Compton_length*electron_Compton_length/pi),
LPMconstant(fine_structure_const*electron_mass_c2*electron_mass_c2/(4.*pi*hbarc)),
theLPMflag(true),
isInitialised(false)
{
if(p) SetParticle(p);
theGamma = G4Gamma::Gamma();
minThreshold = 1.0*keV;
highKinEnergy= 100.*TeV;
lowKinEnergy = 1.0*keV;
highEnergyTh = DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -159,11 +161,14 @@ void G4eBremsstrahlungModel::Initialise(const G4ParticleDefinition* p,
}
}
}
if(isInitialised) return;
if(pParticleChange)
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
else
fParticleChange = new G4ParticleChangeForLoss();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -645,11 +650,11 @@ G4DataVector* G4eBremsstrahlungModel::ComputePartialSumSigma(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4eBremsstrahlungModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
void G4eBremsstrahlungModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
// The emitted gamma energy is sampled using a parametrized formula
// from L. Urban.
// This parametrization is derived from :
@@ -666,7 +671,7 @@ std::vector<G4DynamicParticle*>* G4eBremsstrahlungModel::SampleSecondaries(
{
G4double kineticEnergy = dp->GetKineticEnergy();
G4double tmax = min(maxEnergy, kineticEnergy);
if(tmin >= tmax) return 0;
if(tmin >= tmax) return;
//
// GEANT4 internal units.
@@ -861,19 +866,31 @@ std::vector<G4DynamicParticle*>* G4eBremsstrahlungModel::SampleSecondaries(
gammaDirection.rotateUz(direction);
// create G4DynamicParticle object for the Gamma
std::vector<G4DynamicParticle*>* newp = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* g = new G4DynamicParticle(theGamma,gammaDirection,
gammaEnergy);
newp->push_back(g);
vdp->push_back(g);
G4double totMomentum = sqrt(kineticEnergy*(totalEnergy + electron_mass_c2));
G4ThreeVector dir = totMomentum*direction - gammaEnergy*gammaDirection;
direction = dir.unit();
fParticleChange->SetProposedMomentumDirection(direction);
fParticleChange->SetProposedKineticEnergy(kineticEnergy - gammaEnergy);
// energy of primary
G4double finalE = kineticEnergy - gammaEnergy;
return newp;
// stop tracking and create new secondary instead of primary
if(gammaEnergy > highEnergyTh) {
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->SetProposedKineticEnergy(0.0);
G4DynamicParticle* el =
new G4DynamicParticle(const_cast<G4ParticleDefinition*>(particle),
direction, finalE);
vdp->push_back(el);
// continue tracking
} else {
fParticleChange->SetProposedMomentumDirection(direction);
fParticleChange->SetProposedKineticEnergy(finalE);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4eCoulombScatteringModel.cc,v 1.10 2006/10/26 17:36:17 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4eCoulombScatteringModel.cc,v 1.11 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -176,11 +176,11 @@ G4double G4eCoulombScatteringModel::CalculateCrossSectionPerAtom(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4eCoulombScatteringModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double,
G4double)
void G4eCoulombScatteringModel::SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double,
G4double)
{
const G4Material* aMaterial = couple->GetMaterial();
const G4ParticleDefinition* p = dp->GetDefinition();
@@ -198,7 +198,7 @@ std::vector<G4DynamicParticle*>* G4eCoulombScatteringModel::SampleSecondaries(
G4double a = 2.*ScreeningParameter(Z, q2, mom2, invbeta2);
G4double costm = std::max(cosThetaMax, 1.0 - 0.5*q2Limit/mom2);
if(costm >= cosThetaMin) return 0;
if(costm >= cosThetaMin) return;
G4double x = G4UniformRand();
G4double y = (a + 1.0 - cosThetaMin)/(cosThetaMin - costm);
@@ -221,7 +221,7 @@ std::vector<G4DynamicParticle*>* G4eCoulombScatteringModel::SampleSecondaries(
fParticleChange->ProposeMomentumDirection(newDirection);
return 0;
return;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4eIonisation.cc,v 1.52 2007/01/18 12:17:04 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4eIonisation.cc,v 1.53 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -89,10 +89,6 @@ G4eIonisation::G4eIonisation(const G4String& name)
isElectron(true),
isInitialised(false)
{
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
SetStepFunction(0.2, 1*mm);
SetIntegral(true);
SetVerboseLevel(1);
@@ -1,538 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4eIonisation52.cc,v 1.6 2006/10/16 15:26:50 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
//--------------- G4eIonisation52 physics process --------------------------------
// by Laszlo Urban, 20 March 1997
//------------------------------------------------------------------------------
//
// 07-04-98 remove 'tracking cut' of the ionizing particle, mma
// 04-09-98 new methods SetBining() PrintInfo()
// 07-09-98 Cleanup
// 02-02-99 correction inDoIt , L.Urban
// 10-02-00 modifications , new e.m. structure, L.Urban
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 09-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 13-08-01 new function ComputeRestrictedMeandEdx() (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 21-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined (mma)
// 07-11-01 particleMass and Charge become local variables
// 26-03-02 change access to cuts in BuildLossTables (V.Ivanchenko)
// 16-01-03 Migrade to cut per region (V.Ivanchenko)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
// 08-11-04 Remove of Store/Retrieve tables (V.Ivantchenko)
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4eIonisation52.hh"
#include "G4UnitsTable.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::LowerBoundLambda = 1.*keV;
G4double G4eIonisation52::UpperBoundLambda = 100.*TeV;
G4int G4eIonisation52::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4eIonisation52::G4eIonisation52(const G4String& processName)
: G4VeEnergyLoss(processName),
theMeanFreePathTable(NULL)
{
verboseLevel = -1;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4eIonisation52::~G4eIonisation52()
{
if (theMeanFreePathTable)
{theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::SetLowerBoundLambda(G4double val)
{LowerBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::SetUpperBoundLambda(G4double val)
{UpperBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::SetNbinLambda(G4int n)
{NbinLambda = n;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::GetLowerBoundLambda()
{return LowerBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::GetUpperBoundLambda()
{return UpperBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4eIonisation52::GetNbinLambda()
{return NbinLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
if( !CutsWhereModified() && theLossTable) return;
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
BuildLossTable(aParticleType);
if (&aParticleType==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildLambdaTable(aParticleType);
BuildDEDXTable(aParticleType);
if (&aParticleType==G4Electron::Electron()) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theLossTable) {theLossTable->clearAndDestroy(); delete theLossTable;}
theLossTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
//
for (size_t J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
// now comes the loop for the kinetic energy values
//
for (G4int i = 0; i < TotBin; i++)
{
G4double dEdx = ComputeRestrictedMeandEdx(aParticleType,
aVector->GetLowEdgeEnergy(i),
material,
DeltaThreshold);
if(1 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << aVector->GetLowEdgeEnergy(i)/MeV
<< " dEdx(MeV/mm)= " << dEdx*mm/MeV
<< G4endl;
}
aVector->PutValue(i,dEdx);
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4eIonisation52::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
//create table
//
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theMeanFreePathTable)
{ theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
for (size_t J=0 ; J < numOfCouples; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundLambda, UpperBoundLambda, NbinLambda);
// compute the (macroscopic) cross section first
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
for (G4int i = 0 ; i < NbinLambda ; i++)
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double SIGMA = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
SIGMA += NbOfAtomsPerVolume[iel]*
ComputeCrossSectionPerAtom(aParticleType,
LowEdgeEnergy,
(*theElementVector)[iel]->GetZ(),
DeltaThreshold);
}
// mean free path = 1./macroscopic cross section
G4double Value = SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
aVector->PutValue(i, Value);
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::ComputeRestrictedMeandEdx (
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
const G4Material* material,
G4double DeltaThreshold)
{
// calculate the dE/dx due to the ionization process (Geant4 internal units)
// Seltzer-Berger formula
//
G4double particleMass = aParticleType.GetPDGMass();
G4double ElectronDensity = material->GetElectronDensity();
G4double Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
Eexc /= particleMass; G4double Eexcm2 = Eexc*Eexc;
// for the lowenergy extrapolation
G4double Zeff = material->GetTotNbOfElectPerVolume()/
material->GetTotNbOfAtomsPerVolume();
G4double Th = 0.25*sqrt(Zeff)*keV;
G4double Tsav = 0.;
if (KineticEnergy < Th) {Tsav = KineticEnergy; KineticEnergy = Th;}
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau + 1., gamma2 = gamma*gamma, bg2 = tau*(tau+2.);
G4double beta2 = bg2/gamma2;
G4double Tmax,d,dEdx;
// electron
if (&aParticleType==G4Electron::Electron())
{
Tmax = KineticEnergy/2.;
d = min(DeltaThreshold, Tmax)/particleMass;
dEdx = log(2.*(tau+2.)/Eexcm2)-1.-beta2
+ log((tau-d)*d)+tau/(tau-d)
+ (0.5*d*d+(2.*tau+1.)*log(1.-d/tau))/gamma2;
}
else //positron
{
Tmax = KineticEnergy;
d = min(DeltaThreshold, Tmax)/particleMass;
G4double d2=d*d/2., d3=d*d*d/3., d4=d*d*d*d/4.;
G4double y=1./(1.+gamma);
dEdx = log(2.*(tau+2.)/Eexcm2)+log(tau*d)
- beta2*(tau+2.*d-y*(3.*d2+y*(d-d3+y*(d2-tau*d3+d4))))/tau;
}
//density correction
G4double Cden = material->GetIonisation()->GetCdensity();
G4double Mden = material->GetIonisation()->GetMdensity();
G4double Aden = material->GetIonisation()->GetAdensity();
G4double X0den = material->GetIonisation()->GetX0density();
G4double X1den = material->GetIonisation()->GetX1density();
const G4double twoln10 = 2.*log(10.);
G4double x = log(bg2)/twoln10;
G4double delta;
if (x < X0den) delta = 0.;
else {delta = twoln10*x - Cden;
if (x < X1den) delta += Aden*pow((X1den-x),Mden);
}
//now you can compute the total ionization loss
dEdx -= delta;
dEdx *= twopi_mc2_rcl2*ElectronDensity/beta2;
if (dEdx <= 0.) dEdx = 0.;
// low energy ?
const G4double Tl = 0.2*keV;
if (Tsav > 0.)
{
if (Tsav >= Tl) dEdx *= sqrt(KineticEnergy/Tsav);
else dEdx *= sqrt(KineticEnergy*Tsav)/Tl;
}
return dEdx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eIonisation52::ComputeCrossSectionPerAtom(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber ,
G4double DeltaThreshold)
{
// calculates the cross section per atom (Geant4 internal units)
//(it is called for elements , AtomicNumber = Z )
G4double particleMass = aParticleType.GetPDGMass();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double betasquare = KineticEnergy*(TotalEnergy+particleMass)
/(TotalEnergy*TotalEnergy);
G4double gamma = TotalEnergy/particleMass, gamma2 = gamma*gamma;
G4double x=DeltaThreshold/KineticEnergy, x2 = x*x;
G4double MaxKineticEnergyTransfer;
if (&aParticleType==G4Electron::Electron())
MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
G4double TotalCrossSection = 0.;
if (MaxKineticEnergyTransfer > DeltaThreshold)
{
if (&aParticleType==G4Electron::Electron()) //Moller (e-e-) scattering
{
TotalCrossSection = (gamma-1.)*(gamma-1.)*(0.5-x)/gamma2 + 1./x
- 1./(1.-x)-(2.*gamma-1.)*log((1.-x)/x)/gamma2;
TotalCrossSection /= betasquare;
}
else //Bhabha (e+e-) scattering
{
G4double y=1./(1.+gamma), y2 =y*y, y12=1.-2.*y;
G4double b1=2.-y2, b2=y12*(3.+y2), b4=y12*y12*y12, b3=b4+y12*y12;
TotalCrossSection = (1./x-1.)/betasquare+b1*log(x)+b2*(1.-x)
- b3*(1.-x2)/2.+b4*(1.-x2*x)/3.;
}
TotalCrossSection *= (twopi_mc2_rcl2*AtomicNumber/KineticEnergy);
}
return TotalCrossSection ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4eIonisation52::PostStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double particleMass = aParticle->GetDefinition()->GetPDGMass();
G4double Charge = aParticle->GetDefinition()->GetPDGCharge();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+particleMass);
G4double TotalMomentum = sqrt(Psquare);
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
// get kinetic energy cut for the electron
G4double DeltaThreshold = SecondaryEnergyThreshold(couple->GetIndex());
// some kinematics
G4double MaxKineticEnergyTransfer;
if (Charge < 0.) MaxKineticEnergyTransfer = 0.5*KineticEnergy;
else MaxKineticEnergyTransfer = KineticEnergy;
// sampling kinetic energy of the delta ray
if (MaxKineticEnergyTransfer <= DeltaThreshold)
// pathological case (should not happen, there is no change at all)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// normal case
G4double cc,y,y2,c2,b0,b1,b2,b3,b4,x,x1,grej,grejc;
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau+1., gamma2=gamma*gamma;
G4double xc = DeltaThreshold/KineticEnergy, xc1=1.-xc;
if (Charge < 0.) // Moller (e-e-) scattering
{
b1=4./(9.*gamma2-10.*gamma+5.);
b2=tau*tau*b1; b3=(2.*gamma2+2.*gamma-1.)*b1;
cc=1.-2.*xc;
do {
x = xc/(1.-cc*G4UniformRand()); x1 = 1.-x;
grej = b2*x*x-b3*x/x1+b1*gamma2/(x1*x1);
} while (G4UniformRand()>grej);
}
else // Bhabha (e+e-) scattering
{
y=1./(gamma+1.); y2=y*y; cc=1.-2.*y;
b1=2.-y2; b2=cc*(3.+y2);
c2=cc*cc; b4=c2*cc; b3=c2+b4;
b0=gamma2/(gamma2-1.);
grejc=(((b4*xc-b3)*xc+b2)*xc-b1)*xc+b0;
do {
x = xc/(1.-xc1*G4UniformRand());
grej = ((((b4*x-b3)*x+b2)*x-b1)*x+b0)/grejc;
} while (G4UniformRand()>grej);
}
G4double DeltaKineticEnergy = x * KineticEnergy;
// protection :do not produce a secondary with 0. kinetic energy !
if (DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
G4double DeltaTotalMomentum = sqrt(DeltaKineticEnergy*(DeltaKineticEnergy +
2.*electron_mass_c2 ));
G4double costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum);
if (costheta < -1.) costheta = -1.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
G4double phi = twopi * G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
// changed energy and momentum of the actual particle
G4double finalKineticEnergy = KineticEnergy - DeltaKineticEnergy;
G4double Edep = 0.;
if (finalKineticEnergy > MinKineticEnergy)
{
G4double finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
G4double finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
G4double finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
G4double finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.ProposeMomentumDirection(finalPx, finalPy, finalPz);
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (Charge < 0.) aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.ProposeEnergy(finalKineticEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.ProposeLocalEnergyDeposit(Edep);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::PrintInfoDefinition()
{
G4String comments = "delta cross sections from Moller+Bhabha. "
"Good description from 1 KeV to 100 GeV.\n"
" delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowerBoundLambda,"Energy")
<< " to " << G4BestUnit(UpperBoundLambda,"Energy")
<< " in " << NbinLambda << " bins."
<< "\n Step function: finalRange(mm)= " << finalRange
<< ", dRoverRange= " << dRoverRange
<< G4endl;
G4cout << " WARNING: This process is obsolete and will be soon removed"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4eeToTwoGammaModel.cc,v 1.12 2006/10/20 08:59:50 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
// $Id: G4eeToTwoGammaModel.cc,v 1.14 2007/05/23 08:47:35 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -70,10 +70,12 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4eeToTwoGammaModel.hh"
#include "G4TrackStatus.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4Gamma.hh"
#include "Randomize.hh"
#include "G4ParticleChangeForGamma.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -82,7 +84,8 @@ using namespace std;
G4eeToTwoGammaModel::G4eeToTwoGammaModel(const G4ParticleDefinition*,
const G4String& nam)
: G4VEmModel(nam),
pi_rcl2(pi*classic_electr_radius*classic_electr_radius)
pi_rcl2(pi*classic_electr_radius*classic_electr_radius),
isInitialised(false)
{
theGamma = G4Gamma::Gamma();
}
@@ -96,7 +99,18 @@ G4eeToTwoGammaModel::~G4eeToTwoGammaModel()
void G4eeToTwoGammaModel::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{}
{
if(isInitialised) return;
if(pParticleChange)
fParticleChange =
reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
else
fParticleChange = new G4ParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eeToTwoGammaModel::ComputeCrossSectionPerElectron(
@@ -148,13 +162,12 @@ G4double G4eeToTwoGammaModel::CrossSectionPerVolume(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
vector<G4DynamicParticle*>* G4eeToTwoGammaModel::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double,
G4double)
void G4eeToTwoGammaModel::SampleSecondaries(vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double,
G4double)
{
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
G4double PositKinEnergy = dp->GetKineticEnergy();
// Case at rest
@@ -244,7 +257,8 @@ vector<G4DynamicParticle*>* G4eeToTwoGammaModel::SampleSecondaries(
<< Phot2Direction << G4endl;
*/
}
return vdp;
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4eplusAnnihilation.cc,v 1.26 2006/09/14 10:27:19 maire Exp $
// GEANT4 tag $Name: geant4-08-02 $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -1,501 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4eplusAnnihilation52.cc,v 1.3 2006/10/16 15:26:50 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// 10-01-97, crossection table + mean free path table, M.Maire
// 17-03-97, merge 'in fly' and 'at rest', M.Maire
// 23-03-97, protection in BuildPhysicsTable, M.Maire
// 31-08-98, new methods SetBining() and PrintInfo()
// 22-02-01, postStepDoIt: fStopButAlive instead of kineEnergy == 0.
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 13-07-01, DoIt: suppression of production cut for the gamma (mma)
// 06-08-01, new methods Store/Retrieve PhysicsTable (mma)
// 06-08-01, BuildThePhysicsTable() called from constructor (mma)
// 17-09-01, migration of Materials to pure STL (mma)
// 20-09-01, DoIt: fminimalEnergy = 1*eV (mma)
// 01-10-01, come back to BuildPhysicsTable(const G4ParticleDefinition&)
// 08-11-04, Remove of Store/Retrieve tables (V.Ivantchenko)
// 04-05-05, Add 52 to class name (V.Ivanchenko)
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4eplusAnnihilation52.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4eplusAnnihilation52::G4eplusAnnihilation52(const G4String& processName,
G4ProcessType type):G4VRestDiscreteProcess (processName, type),
theCrossSectionTable(NULL),
theMeanFreePathTable(NULL),
LowestEnergyLimit (10*keV),
HighestEnergyLimit(10*TeV),
NumbBinTable(100),
fminimalEnergy(1*eV)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// destructor
G4eplusAnnihilation52::~G4eplusAnnihilation52()
{
if (theCrossSectionTable) {
theCrossSectionTable->clearAndDestroy();
delete theCrossSectionTable;
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eplusAnnihilation52::IsApplicable( const G4ParticleDefinition& particle)
{
return ( &particle == G4Positron::Positron() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eplusAnnihilation52::SetPhysicsTableBining(
G4double lowE, G4double highE, G4int nBins)
{
LowestEnergyLimit = lowE; HighestEnergyLimit = highE; NumbBinTable = nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eplusAnnihilation52::BuildPhysicsTable(const G4ParticleDefinition& )
{
// Build total cross section and mean free path tables
G4double LowEdgeEnergy, Value;
G4PhysicsLogVector* ptrVector;
// Build cross section per atom tables for the e+e- Annihilation52
if (theCrossSectionTable) {
theCrossSectionTable->clearAndDestroy(); delete theCrossSectionTable;}
theCrossSectionTable = new G4PhysicsTable( G4Element::GetNumberOfElements());
const G4ElementTable* theElementTable = G4Element::GetElementTable() ;
G4double AtomicNumber;
size_t J;
for ( J=0 ; J < G4Element::GetNumberOfElements(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit, HighestEnergyLimit,
NumbBinTable );
AtomicNumber = (*theElementTable)[J]->GetZ();
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
Value = ComputeCrossSectionPerAtom( LowEdgeEnergy, AtomicNumber);
ptrVector->PutValue( i , Value ) ;
}
theCrossSectionTable->insertAt( J , ptrVector );
}
// Build mean free path table for the e+e- Annihilation52
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4Material* material;
for ( J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit, HighestEnergyLimit,
NumbBinTable );
material = (*theMaterialTable)[J];
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
Value = ComputeMeanFreePath( LowEdgeEnergy, material);
ptrVector->PutValue( i , Value );
}
theMeanFreePathTable->insertAt( J , ptrVector );
}
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eplusAnnihilation52::ComputeCrossSectionPerAtom
(G4double PositKinEnergy, G4double AtomicNumber)
// Calculates the cross section per atom of Annihilation52 into two photons
// from the Heilter formula.
// GEANT4 internal units.
{
static const G4double pi_rcl2 = pi*classic_electr_radius*classic_electr_radius;
G4double gama = 1. + PositKinEnergy/electron_mass_c2;
G4double gama2 = gama*gama, sqgama2 = sqrt(gama2-1.);
return pi_rcl2*AtomicNumber
*((gama2+4*gama+1.)*log(gama+sqgama2) - (gama+3.)*sqgama2)
/((gama2-1.)*(gama+1.));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eplusAnnihilation52::ComputeMeanFreePath( G4double PositKinEnergy,
G4Material* aMaterial)
// returns the positron mean free path in GEANT4 internal units
{
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double SIGMA = 0 ;
for (size_t elm=0 ; elm < aMaterial->GetNumberOfElements() ; elm++ )
{
SIGMA += NbOfAtomsPerVolume[elm] *
ComputeCrossSectionPerAtom(PositKinEnergy,
(*theElementVector)[elm]->GetZ());
}
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eplusAnnihilation52::GetCrossSectionPerAtom(
G4DynamicParticle* aDynamicPositron,
G4Element* anElement)
// return the total cross section per atom in GEANT4 internal units
{
G4double crossSection;
G4double PositronEnergy = aDynamicPositron->GetKineticEnergy();
G4bool isOutRange ;
if (PositronEnergy > HighestEnergyLimit)
crossSection = 0. ;
else {
if (PositronEnergy < LowestEnergyLimit) PositronEnergy = 1.01*LowestEnergyLimit;
crossSection = (*theCrossSectionTable)(anElement->GetIndex())->
GetValue( PositronEnergy, isOutRange );
}
return crossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eplusAnnihilation52::GetMeanFreePath(const G4Track& aTrack,
G4double,
G4ForceCondition*)
// returns the positron mean free path in GEANT4 internal units
{
const G4DynamicParticle* aDynamicPositron = aTrack.GetDynamicParticle();
G4double PositronEnergy = aDynamicPositron->GetKineticEnergy();
G4Material* aMaterial = aTrack.GetMaterial();
G4double MeanFreePath;
G4bool isOutRange ;
if (PositronEnergy > HighestEnergyLimit) MeanFreePath = DBL_MAX;
else
{
if (PositronEnergy < LowestEnergyLimit)
PositronEnergy = 1.01*LowestEnergyLimit;
MeanFreePath = (*theMeanFreePathTable)(aMaterial->GetIndex())->
GetValue( PositronEnergy, isOutRange );
}
return MeanFreePath;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4eplusAnnihilation52::GetMeanLifeTime(const G4Track&,
G4ForceCondition*)
// returns the Annihilation52 mean life time in GEANT4 internal units
{
return 0.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4eplusAnnihilation52::PostStepDoIt(const G4Track& aTrack,
const G4Step& )
//
// The secondaries Gamma energies are sampled using the Heitler cross section.
//
// A modified version of the random number techniques of Butcher & Messel
// is used (Nuc Phys 20(1960),15).
//
// GEANT4 internal units.
//
// Note 1: The initial electron is assumed free and at rest.
//
// Note 2: The Annihilation52 processes producing one or more than two photons are
// ignored, as negligible compared to the two photons process.
{
aParticleChange.Initialize(aTrack);
const G4DynamicParticle* aDynamicPositron = aTrack.GetDynamicParticle();
G4double PositKinEnergy = aDynamicPositron->GetKineticEnergy();
G4ParticleMomentum PositDirection = aDynamicPositron->GetMomentumDirection();
aParticleChange.Initialize(aTrack);
// Do not make anything if particle is stopped, the Annihilation52 then
// should be performed by the AtRestDoIt!
if (aTrack.GetTrackStatus() == fStopButAlive || PositKinEnergy == 0.0)
return &aParticleChange;
G4double gamam1 = PositKinEnergy/electron_mass_c2;
G4double gama = gamam1+1. , gamap1 = gamam1+2.;
G4double sqgrate = sqrt(gamam1/gamap1)/2. , sqg2m1 = sqrt(gamam1*gamap1);
// limits of the energy sampling
G4double epsilmin = 0.5 - sqgrate , epsilmax = 0.5 + sqgrate;
G4double epsilqot = epsilmax/epsilmin;
//
// sample the energy rate of the created gammas
//
G4double epsil, greject;
do {
epsil = epsilmin*pow(epsilqot,G4UniformRand());
greject = 1. - epsil + (2*gama*epsil-1.)/(epsil*gamap1*gamap1);
} while( greject < G4UniformRand() );
//
// scattered Gamma angles. ( Z - axis along the parent positron)
//
G4double cost = (epsil*gamap1-1.)/(epsil*sqg2m1);
G4double sint = sqrt((1.+cost)*(1.-cost));
G4double phi = twopi * G4UniformRand();
G4double dirx = sint*cos(phi) , diry = sint*sin(phi) , dirz = cost;
//
// kinematic of the created pair
//
aParticleChange.SetNumberOfSecondaries(2);
G4double localEnergyDeposit = 0.;
G4double TotalAvailableEnergy = PositKinEnergy + 2*electron_mass_c2;
G4double Phot1Energy = epsil*TotalAvailableEnergy;
if (Phot1Energy > fminimalEnergy) {
G4ThreeVector Phot1Direction (dirx, diry, dirz);
Phot1Direction.rotateUz(PositDirection);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1= new G4DynamicParticle (G4Gamma::Gamma(),
Phot1Direction, Phot1Energy);
aParticleChange.AddSecondary(aParticle1);
}
else localEnergyDeposit += Phot1Energy;
G4double Phot2Energy =(1.-epsil)*TotalAvailableEnergy;
if (Phot2Energy > fminimalEnergy) {
G4double Eratio= Phot1Energy/Phot2Energy;
G4double PositP= sqrt(PositKinEnergy*(PositKinEnergy+2.*electron_mass_c2));
G4ThreeVector Phot2Direction (-dirx*Eratio, -diry*Eratio,
(PositP-dirz*Phot1Energy)/Phot2Energy);
Phot2Direction.rotateUz(PositDirection);
// create G4DynamicParticle object for the particle2
G4DynamicParticle* aParticle2= new G4DynamicParticle (G4Gamma::Gamma(),
Phot2Direction, Phot2Energy);
aParticleChange.AddSecondary(aParticle2);
}
else localEnergyDeposit += Phot2Energy;
aParticleChange.ProposeLocalEnergyDeposit(localEnergyDeposit);
//
// Kill the incident positron
//
aParticleChange.ProposeEnergy(0.);
aParticleChange.ProposeTrackStatus(fStopAndKill);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4eplusAnnihilation52::AtRestDoIt(const G4Track& aTrack,
const G4Step& )
//
// Performs the e+ e- Annihilation52 when both particles are assumed at rest.
// It generates two back to back photons with energy = electron_mass.
// The angular distribution is isotropic.
// GEANT4 internal units
//
// Note : Effects due to binding of atomic electrons are negliged.
{
aParticleChange.Initialize(aTrack);
aParticleChange.SetNumberOfSecondaries(2);
G4double cosTeta = 2*G4UniformRand()-1. , sinTeta = sqrt(1.-cosTeta*cosTeta);
G4double Phi = twopi * G4UniformRand();
G4ThreeVector Direction (sinTeta*cos(Phi), sinTeta*sin(Phi), cosTeta);
aParticleChange.AddSecondary( new G4DynamicParticle (G4Gamma::Gamma(),
Direction, electron_mass_c2) );
aParticleChange.AddSecondary( new G4DynamicParticle (G4Gamma::Gamma(),
-Direction, electron_mass_c2) );
aParticleChange.ProposeLocalEnergyDeposit(0.);
// Kill the incident positron
//
aParticleChange.ProposeTrackStatus(fStopAndKill);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eplusAnnihilation52::StorePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
if ( !theCrossSectionTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
// store mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
if ( !theMeanFreePathTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->StorePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
/*
G4bool G4eplusAnnihilation52::RetrievePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theCrossSectionTable and theMeanFreePathTable
if (theCrossSectionTable != 0) {
theCrossSectionTable->clearAndDestroy();
delete theCrossSectionTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
G4String filename;
// retreive cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
theCrossSectionTable = new G4PhysicsTable(G4Element::GetNumberOfElements());
if ( !theCrossSectionTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
return true;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eplusAnnihilation52::PrintInfoDefinition()
{
G4String comments = "Total cross section from Heilter formula"
"(Annihilation52 into 2 photons).\n";
comments += " gamma energies sampled according Heitler";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowestEnergyLimit ,"Energy")
<< " to " << G4BestUnit(HighestEnergyLimit,"Energy")
<< " in " << NumbBinTable << " bins. \n";
G4cout << " WARNING: This process is obsolete and will be soon removed"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4hIonisation.cc,v 1.68 2007/02/23 14:54:00 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4hIonisation.cc,v 1.69 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -106,10 +106,6 @@ G4hIonisation::G4hIonisation(const G4String& name)
theBaseParticle(0),
isInitialised(false)
{
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
SetStepFunction(0.2, 1*mm);
SetIntegral(true);
SetVerboseLevel(1);
@@ -1,623 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4hIonisation52.cc,v 1.6 2006/10/16 15:26:50 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-02 $
//
//---------------- G4hIonisation52 physics process -------------------------------
// by Laszlo Urban, 30 May 1997
//------------------------------------------------------------------------------
//
// corrected by L.Urban on 24/09/97
// several bugs corrected by L.Urban on 13/01/98
// 07-04-98 remove 'tracking cut' of the ionizing particle, mma
// 22-10-98 cleanup L.Urban
// 02-02-99 bugs fixed , L.Urban
// 29-07-99 correction in BuildLossTable for low energy, L.Urban
// 10-02-00 modifications , new e.m. structure, L.Urban
// 10-08-00 V.Ivanchenko change BuildLambdaTable, in order to
// simulate energy losses of ions; correction to
// cross section for particles with spin 1 is inserted as well
// 28-05-01 V.Ivanchenko minor changes to provide ANSI -wall compilation
// 10-08-01 new methods Store/Retrieve PhysicsTable (mma)
// 14-08-01 new function ComputeRestrictedMeandEdx() + 'cleanup' (mma)
// 29-08-01 PostStepDoIt: correction for spin 1/2 (instead of 1) (mma)
// 17-09-01 migration of Materials to pure STL (mma)
// 25-09-01 completion of RetrievePhysicsTable() (mma)
// 29-10-01 all static functions no more inlined
// 08-11-01 Charge renamed zparticle; added to the dedx
// 27-03-02 Bug fix in scaling of lambda table (V.Ivanchenko)
// 09-04-02 Update calculation of tables for GenericIons (V.Ivanchenko)
// 10-06-02 bug fixed for stopping hadrons (V.Ivanchenko)
// 15-01-03 Migrade to cut per region (V.Ivanchenko)
// 10-03-03 Use SubType for GenericIons (V.Ivanchenko)
// 07-04-03 Fix problem of several runs (V.Ivanchenko)
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 17-04-03 fix problem of hadron tests (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
// 08-11-04 Remove of Store/Retrieve tables (V.Ivantchenko)
//
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4hIonisation52.hh"
#include "G4ProcessManager.hh"
#include "G4UnitsTable.hh"
#include "G4EnergyLossTables.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::LowerBoundLambda = 1.*keV;
G4double G4hIonisation52::UpperBoundLambda = 100.*TeV;
G4int G4hIonisation52::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4hIonisation52::G4hIonisation52(const G4String& processName)
: G4VhEnergyLoss(processName),
theMeanFreePathTable(0),
Tmincut(1*keV)
{
verboseLevel = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4hIonisation52::~G4hIonisation52()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::SetLowerBoundLambda(G4double val)
{LowerBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::SetUpperBoundLambda(G4double val)
{UpperBoundLambda = val;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::SetNbinLambda(G4int n)
{NbinLambda = n;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::GetLowerBoundLambda()
{return LowerBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::GetUpperBoundLambda()
{return UpperBoundLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4hIonisation52::GetNbinLambda()
{return NbinLambda;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
if(verboseLevel > 0) {
G4cout << "G4hIonisation52::BuildPhysicsTable for "
<< aParticleType.GetParticleName()
<< " mass(MeV)= " << aParticleType.GetPDGMass()/MeV
<< " charge= " << aParticleType.GetPDGCharge()/eplus
<< " type= " << aParticleType.GetParticleType()
<< G4endl;
if(verboseLevel > 1) {
G4cout << " MFPtable= " << theMeanFreePathTable
<< " DEDXtable= " << theDEDXpTable
<< " iniMass= " << initialMass
<< G4endl;
}
}
if(aParticleType.GetParticleType() == "nucleus" &&
aParticleType.GetParticleName() != "GenericIon" &&
aParticleType.GetParticleSubType() == "generic")
{
G4EnergyLossTables::Register(&aParticleType,
theDEDXpTable,
theRangepTable,
theInverseRangepTable,
theLabTimepTable,
theProperTimepTable,
LowestKineticEnergy, HighestKineticEnergy,
proton_mass_c2/aParticleType.GetPDGMass(),
TotBin);
return;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
const G4ParticleDefinition* theProton = G4Proton::Proton();
G4bool makeTables = false;
if (aParticleType.GetPDGCharge() > 0.)
{
if( CutsWhereModified() || !theDEDXpTable )
{
BuildLossTable(*theProton);
RecorderOfpProcess[0] = (*this).theLossTable;
// CounterOfpProcess++;
makeTables = true;
}
}
else
{
if( CutsWhereModified() || !theDEDXpbarTable )
{
BuildLossTable(*(G4AntiProton::AntiProton())) ;
RecorderOfpProcess[0] = (*this).theLossTable;
// CounterOfpbarProcess++;
makeTables = true;
}
}
BuildLambdaTable(aParticleType);
if( makeTables ) BuildDEDXTable(aParticleType);
if(2 < verboseLevel) {
G4cout << "MeanFreePathTable is built for "
<< aParticleType.GetParticleName() << G4endl;
G4cout << (*theMeanFreePathTable) << G4endl;
}
if (&aParticleType == theProton) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4hIonisation52::BuildLossTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theLossTable) {theLossTable->clearAndDestroy(); delete theLossTable;}
theLossTable = new G4PhysicsTable(numOfCouples);
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
//
for (size_t J=0; J<numOfCouples; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
// now comes the loop for the kinetic energy values
//
for (G4int i = 0 ; i < TotBin ; i++)
{
G4double dEdx = ComputeRestrictedMeandEdx(aParticleType,
aVector->GetLowEdgeEnergy(i),
material,
DeltaThreshold);
aVector->PutValue(i,dEdx);
}
theLossTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
if(0 < verboseLevel) {
G4cout << "G4hIonisation52::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< aParticleType.GetParticleName() << G4endl;
}
//create table
//
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if (theMeanFreePathTable)
{theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable;}
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// get electron cut in kinetic energy
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// loop for materials
for (size_t J=0 ; J < numOfCouples; J++)
{
//create physics vector then fill it ....
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundLambda,UpperBoundLambda,NbinLambda);
// compute the (macroscopic) cross section first
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(J);
const G4Material* material= couple->GetMaterial();
// get electron cut in kinetic energy for the material
G4double DeltaThreshold = SecondaryEnergyThreshold(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " Tcut(MeV)= " << DeltaThreshold/MeV
<< " Tmin(MeV)= " << LowerBoundLambda/MeV
<< " Tmax(MeV)= " << UpperBoundLambda/MeV
<< " nbins= " << NbinLambda
<< G4endl;
}
for ( G4int i = 0 ; i < NbinLambda ; i++ )
{
G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double sigma = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
sigma += NbOfAtomsPerVolume[iel]*
ComputeCrossSectionPerAtom(aParticleType,
LowEdgeEnergy,
(*theElementVector)[iel]->GetZ(),
DeltaThreshold);
}
// mean free path = 1./macroscopic cross section
G4double Value = sigma > DBL_MIN ? 1./sigma : DBL_MAX;
aVector->PutValue(i, Value) ;
}
theMeanFreePathTable->insert(aVector);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::ComputeRestrictedMeandEdx (
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
const G4Material* material,
G4double DeltaThreshold)
{
// calculate the dE/dx due to the ionization process (Geant4 internal units)
// Bethe-Bloch formula
//
G4double particleMass = proton_mass_c2;
G4double ElectronDensity = material->GetElectronDensity();
G4double Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
G4double Eexc2 = Eexc*Eexc;
G4double tau = KineticEnergy/particleMass;
G4double gamma = tau + 1., bg2 = tau*(tau+2.), beta2 = bg2/(gamma*gamma);
G4double RateMass = electron_mass_c2/particleMass;
G4double Tmax=2.*electron_mass_c2*bg2/(1.+2.*gamma*RateMass+RateMass*RateMass);
G4double taul = material->GetIonisation()->GetTaul();
G4double dEdx = 0.;
//
// high energy part , Bethe-Bloch formula
//
if (tau > taul)
{
G4double rcut = min(DeltaThreshold/Tmax, 1.);
dEdx = log(2.*electron_mass_c2*bg2*Tmax/Eexc2)
+log(rcut)-(1.+rcut)*beta2;
//density correction
G4double Cden = material->GetIonisation()->GetCdensity();
G4double Mden = material->GetIonisation()->GetMdensity();
G4double Aden = material->GetIonisation()->GetAdensity();
G4double X0den = material->GetIonisation()->GetX0density();
G4double X1den = material->GetIonisation()->GetX1density();
const G4double twoln10 = 2.*log(10.);
G4double x = log(bg2)/twoln10;
G4double delta;
if (x < X0den) delta = 0.;
else {delta = twoln10*x - Cden;
if (x < X1den) delta += Aden*pow((X1den-x),Mden);
}
// shell correction
G4double* ShellCorrectionVector = material->GetIonisation()->
GetShellCorrectionVector();
const G4double bg2lim = 0.0169, taulim = 8.4146e-3;
G4double sh = 0., xs = 1.;
if (bg2 > bg2lim) for (G4int k=0; k<3; k++)
{xs *= bg2; sh += ShellCorrectionVector[k]/xs;}
else { for (G4int k=0; k<3; k++)
{xs *= bg2lim; sh += ShellCorrectionVector[k]/xs;}
sh *= log(tau/taul)/log(taulim/taul);
}
// now you can compute the total ionization loss
dEdx -= (delta + sh);
dEdx *= twopi_mc2_rcl2*ElectronDensity/beta2;
if (dEdx < 0.) dEdx = 0.;
}
//
// low energy part , parametrized energy loss formulae
//
if (tau <= taul)
{
// get elements in the actual material,
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume=material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
// loop for the elements in the material
dEdx = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)[iel];
if (tau < element->GetIonisation()->GetTau0())
dEdx += NbOfAtomsPerVolume[iel]
*(element->GetIonisation()->GetAlow()*sqrt(tau)
+ element->GetIonisation()->GetBlow()*tau);
else
dEdx += NbOfAtomsPerVolume[iel]
* element->GetIonisation()->GetClow()/sqrt(tau);
}
G4double deltaloss = 0.;
if (DeltaThreshold < Tmax)
{
deltaloss = log(Tmax/DeltaThreshold)-
beta2*(1.-DeltaThreshold/Tmax) ;
if (aParticleType.GetPDGSpin() == 0.5)
deltaloss += 0.25*(Tmax-DeltaThreshold)*(Tmax-DeltaThreshold)/
(KineticEnergy*KineticEnergy+proton_mass_c2*proton_mass_c2);
deltaloss *= twopi_mc2_rcl2*ElectronDensity/beta2;
}
dEdx -= deltaloss;
if (dEdx < 0.) dEdx = 0.;
}
return dEdx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4hIonisation52::ComputeCrossSectionPerAtom(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double DeltaThreshold)
{
// calculates the totalcross section per atom in GEANT4 internal units
// ( it is called for elements , AtomicNumber = Z )
//
// nb: cross section formula is OK for spin=0 and 1/2 only !
initialMass = aParticleType.GetPDGMass();
G4double particleMass = initialMass;
G4double TotalEnergy = KineticEnergy + particleMass;
G4double betasquare = KineticEnergy*(TotalEnergy+particleMass)
/(TotalEnergy*TotalEnergy);
G4double tempvar = particleMass+electron_mass_c2;
G4double MaxKineticEnergyTransfer = 2.*electron_mass_c2*KineticEnergy
*(TotalEnergy+particleMass)
/(tempvar*tempvar+2.*electron_mass_c2*KineticEnergy);
G4double TotalCrossSection = 0.;
if (MaxKineticEnergyTransfer > DeltaThreshold)
{
tempvar = DeltaThreshold/MaxKineticEnergyTransfer;
TotalCrossSection = (1.-tempvar*(1.-betasquare*log(tempvar)))
/DeltaThreshold;
G4double spin = aParticleType.GetPDGSpin();
if (spin == 0.5) TotalCrossSection += 0.5
*(MaxKineticEnergyTransfer-DeltaThreshold)
/(TotalEnergy*TotalEnergy);
if (spin == 1.) TotalCrossSection +=
-log(tempvar)/(3.0*DeltaThreshold) +
(MaxKineticEnergyTransfer - DeltaThreshold) *
((5.0+ 1.0/tempvar)*0.25 / (TotalEnergy*TotalEnergy) -
betasquare /
(MaxKineticEnergyTransfer * DeltaThreshold)) / 3.0;
TotalCrossSection *= twopi_mc2_rcl2*AtomicNumber/betasquare;
}
return TotalCrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4hIonisation52::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double particleMass = aParticle->GetMass();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double TotalEnergy = KineticEnergy + particleMass;
G4double Psquare = KineticEnergy*(TotalEnergy+particleMass);
G4double Esquare = TotalEnergy*TotalEnergy;
G4double betasquare=Psquare/Esquare;
G4double summass = particleMass + electron_mass_c2;
G4double MaxKineticEnergyTransfer = 2.*electron_mass_c2*Psquare
/(summass*summass+2.*electron_mass_c2*KineticEnergy);
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
// get electron cut in kinetic energy
G4double DeltaThreshold = SecondaryEnergyThreshold(couple->GetIndex());
// sampling kinetic energy of the delta ray
//
if (MaxKineticEnergyTransfer <= DeltaThreshold)
// pathological case (it should not happen, there is no change at all)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// normal case
G4double xc = DeltaThreshold/MaxKineticEnergyTransfer;
G4double rate = MaxKineticEnergyTransfer/TotalEnergy;
G4double te2 = 0.;
if (aParticle->GetDefinition()->GetPDGSpin() == 0.5) te2=0.5*rate*rate;
// sampling follows ...
G4double x,grej;
G4double grejc=1.-betasquare*xc+te2*xc*xc;
do { x=xc/(1.-(1.-xc)*G4UniformRand());
grej=(1.-x*(betasquare-x*te2))/grejc;
} while(G4UniformRand() > grej);
G4double DeltaKineticEnergy = x * MaxKineticEnergyTransfer;
if (DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
G4double DeltaTotalMomentum = sqrt(DeltaKineticEnergy * (DeltaKineticEnergy +
2. * electron_mass_c2 ));
G4double TotalMomentum = sqrt(Psquare);
G4double costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum);
if (costheta < -1.) costheta = -1.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
//
G4double phi = twopi*G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
G4ThreeVector DeltaDirection(dirx,diry,dirz);
DeltaDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for delta ray
//
G4DynamicParticle *theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
// fill aParticleChange
//
G4double finalKineticEnergy = KineticEnergy - DeltaKineticEnergy;
G4double Edep = 0;
if (finalKineticEnergy > MinKineticEnergy)
{
G4double finalPx = TotalMomentum*ParticleDirection.x()
- DeltaTotalMomentum*DeltaDirection.x();
G4double finalPy = TotalMomentum*ParticleDirection.y()
- DeltaTotalMomentum*DeltaDirection.y();
G4double finalPz = TotalMomentum*ParticleDirection.z()
- DeltaTotalMomentum*DeltaDirection.z();
G4double finalMomentum =
sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.ProposeMomentumDirection( finalPx,finalPy,finalPz );
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.ProposeEnergy( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.ProposeLocalEnergyDeposit (Edep);
//ResetNumberOfInteractionLengthLeft();
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::PrintInfoDefinition()
{
G4String comments = " Knock-on electron cross sections . "
"\n Good description above the mean excitation energy.\n"
" delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. "
<< "\n Step function: finalRange(mm)= " << finalRange
<< ", dRoverRange= " << dRoverRange
<< G4endl;
G4cout << " WARNING: This process is obsolete and will be soon removed"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4hMultipleScattering.cc,v 1.3 2007/03/20 15:40:59 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4hMultipleScattering.cc,v 1.6 2007/06/11 15:01:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -----------------------------------------------------------------------------
//
@@ -47,8 +47,7 @@
#include "G4hMultipleScattering.hh"
#include "G4UrbanMscModel.hh"
#include "G4TransportationManager.hh"
#include "G4Navigator.hh"
#include "G4MscStepLimitType.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -57,25 +56,17 @@ using namespace std;
G4hMultipleScattering::G4hMultipleScattering(const G4String& processName)
: G4VMultipleScattering(processName)
{
lowKineticEnergy = 0.1*keV;
highKineticEnergy = 100.*TeV;
totBins = 120;
facrange = 0.2;
dtrl = 0.05;
lambdalimit = 1.*mm;
facgeom = 0.1;
steppingAlgorithm = false;
samplez = false ;
isInitialized = false;
SetBinning(totBins);
SetMinKinEnergy(lowKineticEnergy);
SetMaxKinEnergy(highKineticEnergy);
SetLateralDisplasmentFlag(true);
SetSkin(0.0);
SetRangeFactor(0.2);
SetGeomFactor(0.1);
SetStepLimitType(fMinimal);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -92,43 +83,34 @@ G4bool G4hMultipleScattering::IsApplicable (const G4ParticleDefinition& p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hMultipleScattering::MscStepLimitation(G4bool algorithm, G4double factor)
{
steppingAlgorithm = algorithm;
if (factor > 0.) SetFacrange(factor);
else { if (algorithm) SetFacrange(0.02); else SetFacrange(0.2);}
if(verboseLevel > 1)
G4cout << "Stepping algorithm is set to " << steppingAlgorithm
<< " with facrange = " << facrange << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hMultipleScattering::InitialiseProcess(const G4ParticleDefinition* p)
{
// Modification of parameters between runs
if(isInitialized) {
mscUrban->SetMscStepLimitation(steppingAlgorithm, facrange);
if (p->GetParticleType() != "nucleus") {
mscUrban->SetStepLimitType(StepLimitType());
mscUrban->SetLateralDisplasmentFlag(LateralDisplasmentFlag());
mscUrban->SetSkin(Skin());
mscUrban->SetRangeFactor(RangeFactor());
mscUrban->SetGeomFactor(GeomFactor());
}
return;
}
// initialisation of parameters
G4String part_name = p->GetParticleName();
mscUrban = new G4UrbanMscModel(RangeFactor(),dtrl,lambdalimit,
GeomFactor(),Skin(),
samplez,StepLimitType());
mscUrban->SetLateralDisplasmentFlag(LateralDisplasmentFlag());
if (p->GetParticleType() == "nucleus") {
mscUrban->SetStepLimitType(fMinimal);
SetLateralDisplasmentFlag(false);
SetBuildLambdaTable(false);
SetSkin(0.0);
} else {
SetBuildLambdaTable(true);
SetRangeFactor(0.2);
}
mscUrban = new G4UrbanMscModel(facrange,dtrl,lambdalimit,
facgeom,Skin(),
samplez,steppingAlgorithm);
mscUrban->SetLateralDisplasmentFlag(LateralDisplasmentFlag());
mscUrban->SetLowEnergyLimit(lowKineticEnergy);
mscUrban->SetHighEnergyLimit(highKineticEnergy);
AddEmModel(1,mscUrban);
isInitialized = true;
}
@@ -137,9 +119,9 @@ void G4hMultipleScattering::InitialiseProcess(const G4ParticleDefinition* p)
void G4hMultipleScattering::PrintInfo()
{
G4cout << " Boundary/stepping algorithm is active with facrange= "
<< facrange
<< " Step limitation " << steppingAlgorithm
G4cout << " Boundary/stepping algorithm is active with RangeFactor= "
<< RangeFactor()
<< " Step limit type " << StepLimitType()
<< G4endl;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4ionIonisation.cc,v 1.39 2007/01/18 12:17:04 vnivanch Exp $
// GEANT4 tag $Name: geant4-08-03 $
// $Id: G4ionIonisation.cc,v 1.43 2007/05/22 17:34:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
// -------------------------------------------------------------------
//
@@ -52,6 +52,7 @@
// 10-05-06 Add a possibility to download user data (V.Ivantchenko)
// 13-05-06 Add data for light ion stopping in water (V.Ivantchenko)
// 14-01-07 use SetEmModel() and SetFluctModel() from G4VEnergyLossProcess (mma)
// 16-05-07 Add data for light ion stopping only for GenericIon (V.Ivantchenko)
//
//
// -------------------------------------------------------------------
@@ -80,12 +81,9 @@ G4ionIonisation::G4ionIonisation(const G4String& name)
theParticle(0),
theBaseParticle(0),
isInitialised(false),
stopDataActive(true)
stopDataActive(true),
nuclearStopping(true)
{
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
SetLinearLossLimit(0.15);
SetStepFunction(0.1, 0.1*mm);
SetIntegral(true);
@@ -130,8 +128,13 @@ void G4ionIonisation::InitialiseEnergyLossProcess(
EmModel(2)->SetHighEnergyLimit(100*TeV);
AddEmModel(2, EmModel(2), FluctModel());
effCharge = corr->GetIonEffectiveCharge(EmModel(1));
G4WaterStopping ws(corr);
// Add ion stoping tables for Generic Ion
if(part == G4GenericIon::GenericIon()) {
G4WaterStopping ws(corr);
effCharge = corr->GetIonEffectiveCharge(EmModel(1));
} else {
effCharge = corr->GetIonEffectiveCharge(0);
}
isInitialised = true;
}
@@ -147,6 +150,7 @@ void G4ionIonisation::PrintInfo()
<< eth/MeV << " MeV"
<< "\n Parametrisation from "
<< EmModel(1)->GetName() << " for protons below."
<< " NuclearStopping " << nuclearStopping
<< G4endl;
if (stopDataActive)
G4cout << "\n Stopping Power data for "
@@ -157,19 +161,6 @@ void G4ionIonisation::PrintInfo()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ionIonisation::GetMeanFreePath(const G4Track& track,
G4double,
G4ForceCondition* cond)
{
DefineMassCharge(track.GetDefinition(),
track.GetMaterial(),
track.GetDynamicParticle()->GetMass(),
track.GetKineticEnergy());
return G4VEnergyLossProcess::GetMeanFreePath(track, 0.0, cond);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ionIonisation::AddStoppingData(G4int Z, G4int A,
const G4String& mname,
G4PhysicsVector& dVector)