Import Geant4 7.1.0 source tree
This commit is contained in:
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4BetheBlochModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4BetheBlochModel.cc,v 1.6 2005/04/12 18:12:41 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -40,6 +40,8 @@
|
||||
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
|
||||
// 27-01-03 Make models region aware (V.Ivanchenko)
|
||||
// 13-02-03 Add name (V.Ivanchenko)
|
||||
// 24-03-05 Add G4EmCorrections (V.Ivanchenko)
|
||||
// 11-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -51,6 +53,9 @@
|
||||
#include "G4BetheBlochModel.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4EmCorrections.hh"
|
||||
#include "G4ParticleChangeForLoss.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -59,14 +64,13 @@ using namespace std;
|
||||
G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p, const G4String& nam)
|
||||
: G4VEmModel(nam),
|
||||
particle(0),
|
||||
highKinEnergy(100.*TeV),
|
||||
lowKinEnergy(2.0*MeV),
|
||||
twoln10(2.0*log(10.0)),
|
||||
bg2lim(0.0169),
|
||||
taulim(8.4146e-3),
|
||||
isIon(false)
|
||||
{
|
||||
if(p) SetParticle(p);
|
||||
theElectron = G4Electron::Electron();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -76,37 +80,6 @@ G4BetheBlochModel::~G4BetheBlochModel()
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(particle != p) {
|
||||
particle = p;
|
||||
mass = particle->GetPDGMass();
|
||||
spin = particle->GetPDGSpin();
|
||||
G4double q = particle->GetPDGCharge()/eplus;
|
||||
chargeSquare = q*q;
|
||||
ratio = electron_mass_c2/mass;
|
||||
if(particle->GetParticleName() == "GenericIon") isIon = true;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BetheBlochModel::HighEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return highKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return lowKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BetheBlochModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple* couple)
|
||||
{
|
||||
@@ -115,26 +88,28 @@ G4double G4BetheBlochModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4bool G4BetheBlochModel::IsInCharge(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4BetheBlochModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
G4String pname = particle->GetParticleName();
|
||||
if(particle->GetParticleType() == "nucleus" &&
|
||||
pname != "deuteron" && pname != "triton") isIon = true;
|
||||
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForLoss();
|
||||
|
||||
corr = G4LossTableManager::Instance()->EmCorrections();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BetheBlochModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cut)
|
||||
G4double G4BetheBlochModel::ComputeDEDXPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cut)
|
||||
{
|
||||
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
|
||||
G4double cutEnergy = min(cut,tmax);
|
||||
@@ -144,20 +119,18 @@ G4double G4BetheBlochModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
G4double bg2 = tau * (tau+2.0);
|
||||
G4double beta2 = bg2/(gam*gam);
|
||||
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
G4double eexc = material->GetIonisation()->GetMeanExcitationEnergy();
|
||||
G4double eexc2 = eexc*eexc;
|
||||
G4double taul = material->GetIonisation()->GetTaul();
|
||||
G4double cden = material->GetIonisation()->GetCdensity();
|
||||
G4double mden = material->GetIonisation()->GetMdensity();
|
||||
G4double aden = material->GetIonisation()->GetAdensity();
|
||||
G4double x0den = material->GetIonisation()->GetX0density();
|
||||
G4double x1den = material->GetIonisation()->GetX1density();
|
||||
G4double* shellCorrectionVector =
|
||||
material->GetIonisation()->GetShellCorrectionVector();
|
||||
|
||||
G4double eDensity = material->GetElectronDensity();
|
||||
|
||||
G4double dedx = log(2.0*electron_mass_c2*bg2*cutEnergy/eexc2)-(1.0 + cutEnergy/tmax)*beta2;
|
||||
G4double dedx = log(2.0*electron_mass_c2*bg2*cutEnergy/eexc2)
|
||||
- (1.0 + cutEnergy/tmax)*beta2;
|
||||
|
||||
if(0.5 == spin) {
|
||||
G4double del = 0.5*cutEnergy/(kineticEnergy + mass);
|
||||
@@ -172,23 +145,7 @@ G4double G4BetheBlochModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
}
|
||||
|
||||
// shell correction
|
||||
G4double sh = 0.0;
|
||||
x = 1.0;
|
||||
|
||||
if ( bg2 > bg2lim ) {
|
||||
for (G4int k=0; k<3; k++) {
|
||||
x *= bg2 ;
|
||||
sh += shellCorrectionVector[k]/x;
|
||||
}
|
||||
|
||||
} else {
|
||||
for (G4int k=0; k<3; k++) {
|
||||
x *= bg2lim ;
|
||||
sh += shellCorrectionVector[k]/x;
|
||||
}
|
||||
sh *= log(tau/taul)/log(taulim/taul);
|
||||
}
|
||||
dedx -= sh;
|
||||
dedx -= 2.0*corr->ShellCorrection(p,material,kineticEnergy);
|
||||
|
||||
// now compute the total ionization loss
|
||||
|
||||
@@ -196,16 +153,19 @@ G4double G4BetheBlochModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
|
||||
dedx *= twopi_mc2_rcl2*chargeSquare*eDensity/beta2;
|
||||
|
||||
//High order correction only for hadrons
|
||||
if(!isIon) dedx += corr->HighOrderCorrections(p,material,kineticEnergy);
|
||||
|
||||
return dedx;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BetheBlochModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
G4double maxKinEnergy)
|
||||
G4double G4BetheBlochModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
G4double maxKinEnergy)
|
||||
{
|
||||
G4double cross = 0.0;
|
||||
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
|
||||
@@ -221,8 +181,7 @@ G4double G4BetheBlochModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
// +term for spin=1/2 particle
|
||||
if( 0.5 == spin ) cross += 0.5*(maxEnergy - cutEnergy)/energy2;
|
||||
|
||||
cross *= twopi_mc2_rcl2*chargeSquare*
|
||||
(couple->GetMaterial()->GetElectronDensity())/beta2;
|
||||
cross *= twopi_mc2_rcl2*chargeSquare*material->GetElectronDensity()/beta2;
|
||||
}
|
||||
// G4cout << "BB: e= " << kineticEnergy << " tmin= " << cutEnergy << " tmax= " << tmax
|
||||
// << " cross= " << cross << G4endl;
|
||||
@@ -231,17 +190,18 @@ G4double G4BetheBlochModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticle* G4BetheBlochModel::SampleSecondary(
|
||||
vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double minEnergy,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
G4double tmax = MaxSecondaryEnergy(dp);
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
G4double tmax = MaxSecondaryEnergy(dp->GetDefinition(),kineticEnergy);
|
||||
|
||||
G4double maxKinEnergy = min(maxEnergy,tmax);
|
||||
G4double minKinEnergy = min(minEnergy,maxKinEnergy);
|
||||
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
G4double totEnergy = kineticEnergy + mass;
|
||||
G4double etot2 = totEnergy*totEnergy;
|
||||
G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/etot2;
|
||||
@@ -281,26 +241,21 @@ G4DynamicParticle* G4BetheBlochModel::SampleSecondary(
|
||||
deltaDirection.rotateUz(direction);
|
||||
|
||||
// create G4DynamicParticle object for delta ray
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(G4Electron::Electron(),
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,
|
||||
deltaDirection,deltaKinEnergy);
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
|
||||
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
|
||||
vdp->push_back(delta);
|
||||
|
||||
// Change kinematics of primary particle
|
||||
kineticEnergy -= deltaKinEnergy;
|
||||
G4ThreeVector finalP = direction*totMomentum - deltaDirection*deltaMomentum;
|
||||
finalP = finalP.unit();
|
||||
|
||||
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
|
||||
fParticleChange->SetProposedMomentumDirection(finalP);
|
||||
|
||||
return vdp;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4BetheHeitlerModel.cc,v 1.3 2005/05/12 11:06:43 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4BetheHeitlerModel
|
||||
//
|
||||
// Author: Vladimir Ivanchenko on base of Michel Maire code
|
||||
//
|
||||
// Creation date: 15.03.2005
|
||||
//
|
||||
// Modifications:
|
||||
// 18-04-05 Use G4ParticleChangeForGamma (V.Ivantchenko)
|
||||
//
|
||||
// Class Description:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#include "G4BetheHeitlerModel.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Positron.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4DataVector.hh"
|
||||
#include "G4PhysicsLogVector.hh"
|
||||
#include "G4ParticleChangeForGamma.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4BetheHeitlerModel::G4BetheHeitlerModel(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam),
|
||||
theCrossSectionTable(0),
|
||||
nbins(100)
|
||||
{
|
||||
theGamma = G4Gamma::Gamma();
|
||||
thePositron = G4Positron::Positron();
|
||||
theElectron = G4Electron::Electron();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4BetheHeitlerModel::~G4BetheHeitlerModel()
|
||||
{
|
||||
if(theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy();
|
||||
delete theCrossSectionTable;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4BetheHeitlerModel::Initialise(const G4ParticleDefinition*,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForGamma();
|
||||
|
||||
if(theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy();
|
||||
delete theCrossSectionTable;
|
||||
}
|
||||
|
||||
const G4ElementTable* theElementTable = G4Element::GetElementTable();
|
||||
size_t nvect = G4Element::GetNumberOfElements();
|
||||
theCrossSectionTable = new G4PhysicsTable(nvect);
|
||||
G4PhysicsLogVector* ptrVector;
|
||||
G4double emin = LowEnergyLimit();
|
||||
G4double emax = HighEnergyLimit();
|
||||
G4double e, value;
|
||||
|
||||
for(size_t j=0; j<nvect ; j++) {
|
||||
|
||||
ptrVector = new G4PhysicsLogVector(emin, emax, nbins);
|
||||
G4double Z = (*theElementTable)[j]->GetZ();
|
||||
G4int iz = G4int(Z);
|
||||
indexZ[iz] = j;
|
||||
|
||||
for(G4int i=0; i<nbins; i++) {
|
||||
e = ptrVector->GetLowEdgeEnergy( i ) ;
|
||||
value = InitializeCrossSectionPerAtom(e, Z);
|
||||
ptrVector->PutValue( i, value );
|
||||
}
|
||||
|
||||
theCrossSectionTable->insert(ptrVector);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BetheHeitlerModel::InitializeCrossSectionPerAtom(G4double GammaEnergy,
|
||||
G4double Z)
|
||||
// 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)
|
||||
{
|
||||
static const G4double GammaEnergyLimit = 1.5*MeV;
|
||||
G4double CrossSection = 0.0 ;
|
||||
if ( Z < 1. ) return CrossSection;
|
||||
if ( GammaEnergy <= 2.0*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 = (Z + 1.)*(F1*Z + F2*Z*Z + 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....
|
||||
|
||||
std::vector<G4DynamicParticle*>* G4BetheHeitlerModel::SampleSecondaries(
|
||||
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
|
||||
// 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.
|
||||
{
|
||||
const G4Material* aMaterial = couple->GetMaterial();
|
||||
|
||||
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
|
||||
G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection();
|
||||
|
||||
G4double epsil ;
|
||||
G4double epsil0 = electron_mass_c2/GammaEnergy ;
|
||||
|
||||
// do it fast if GammaEnergy < 2. MeV
|
||||
static 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
|
||||
const G4Element* anElement = SelectRandomAtom(aMaterial, theGamma, GammaEnergy);
|
||||
|
||||
// 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 (RandBit::shootBit()) {
|
||||
|
||||
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.
|
||||
|
||||
G4double ElectKineEnergy = max(0.,ElectTotEnergy - electron_mass_c2);
|
||||
|
||||
G4ThreeVector ElectDirection (dxEl, dyEl, dzEl);
|
||||
ElectDirection.rotateUz(GammaDirection);
|
||||
|
||||
// create G4DynamicParticle object for the particle1
|
||||
G4DynamicParticle* aParticle1= new G4DynamicParticle(
|
||||
theElectron,ElectDirection,ElectKineEnergy);
|
||||
|
||||
// the e+ is always created (even with Ekine=0) for further annihilation.
|
||||
|
||||
G4double PositKineEnergy = max(0.,PositTotEnergy - electron_mass_c2);
|
||||
|
||||
G4ThreeVector PositDirection (dxPo, dyPo, dzPo);
|
||||
PositDirection.rotateUz(GammaDirection);
|
||||
|
||||
// create G4DynamicParticle object for the particle2
|
||||
G4DynamicParticle* aParticle2= new G4DynamicParticle(
|
||||
thePositron,PositDirection,PositKineEnergy);
|
||||
|
||||
// Fill output vector
|
||||
std::vector<G4DynamicParticle*>* fvect = new std::vector<G4DynamicParticle*>;
|
||||
fvect->push_back(aParticle1);
|
||||
fvect->push_back(aParticle2);
|
||||
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
|
||||
return fvect;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4BohrFluctuations.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4BohrFluctuations.cc,v 1.3 2005/05/01 20:26:24 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -100,7 +100,7 @@ G4double G4BohrFluctuations::SampleFluctuations(const G4Material* material,
|
||||
navr = meanLoss*meanLoss/siga;
|
||||
if (navr < minNumberInteractionsBohr) gauss = false;
|
||||
}
|
||||
// G4cout << "### meanLoss= " << meanLoss << " navr= " << navr << " sig= " << sqrt(siga) << G4endl;
|
||||
//G4cout << "### meanLoss= " << meanLoss << " navr= " << navr << " sig= " << sqrt(siga) << G4endl;
|
||||
|
||||
if(gauss) {
|
||||
// Increase fluctuations for big fractional energy loss
|
||||
@@ -114,7 +114,7 @@ G4double G4BohrFluctuations::SampleFluctuations(const G4Material* material,
|
||||
siga *= 0.25*(1.0 + x)*(x3 + (1.0/b2 - 0.5)/(1.0/beta2 - 0.5) );
|
||||
}
|
||||
siga = sqrt(siga);
|
||||
|
||||
//G4cout << "siga= " << siga << G4endl;
|
||||
G4double twomeanLoss = meanLoss + meanLoss;
|
||||
|
||||
if(twomeanLoss < siga) {
|
||||
@@ -134,6 +134,7 @@ G4double G4BohrFluctuations::SampleFluctuations(const G4Material* material,
|
||||
G4double n = (G4double)(G4Poisson(navr));
|
||||
loss = meanLoss*n/navr;
|
||||
}
|
||||
// G4cout << "loss= " << loss << G4endl;
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4BraggIonModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4BraggIonModel.cc,v 1.6 2005/05/30 08:46:58 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -35,6 +35,7 @@
|
||||
// Creation date: 13.10.2004
|
||||
//
|
||||
// Modifications:
|
||||
// 11-05-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
|
||||
// Class Description:
|
||||
@@ -52,6 +53,8 @@
|
||||
#include "G4BraggIonModel.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Alpha.hh"
|
||||
#include "G4ParticleChangeForLoss.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -60,8 +63,6 @@ using namespace std;
|
||||
G4BraggIonModel::G4BraggIonModel(const G4ParticleDefinition* p, const G4String& nam)
|
||||
: G4VEmModel(nam),
|
||||
particle(0),
|
||||
HeMassAMU(4.0026),
|
||||
rateMass(HeMassAMU/1.007276),
|
||||
iMolecula(0),
|
||||
isIon(false)
|
||||
{
|
||||
@@ -69,7 +70,11 @@ G4BraggIonModel::G4BraggIonModel(const G4ParticleDefinition* p, const G4String&
|
||||
highKinEnergy = 2.0*MeV;
|
||||
lowKinEnergy = 0.0*MeV;
|
||||
lowestKinEnergy = 1.0*keV;
|
||||
HeMass = G4Alpha::Alpha()->GetPDGMass();
|
||||
rateMassHe2p = HeMass/proton_mass_c2;
|
||||
massFactor = 1000.*amu_c2/HeMass;
|
||||
theZieglerFactor = eV*cm2*1.0e-15;
|
||||
theElectron = G4Electron::Electron();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -79,69 +84,38 @@ G4BraggIonModel::~G4BraggIonModel()
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4BraggIonModel::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(particle != p) {
|
||||
particle = p;
|
||||
mass = particle->GetPDGMass();
|
||||
spin = particle->GetPDGSpin();
|
||||
G4double q = particle->GetPDGCharge()/eplus;
|
||||
chargeSquare = q*q;
|
||||
massRate = mass/proton_mass_c2;
|
||||
ratio = electron_mass_c2/mass;
|
||||
if(particle->GetParticleName() == "GenericIon") isIon = true;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggIonModel::HighEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return highKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggIonModel::LowEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return lowKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggIonModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple* couple)
|
||||
const G4MaterialCutsCouple* couple)
|
||||
{
|
||||
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4bool G4BraggIonModel::IsInCharge(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4BraggIonModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
if(p != particle) SetParticle(p);
|
||||
G4String pname = particle->GetParticleName();
|
||||
if(particle->GetParticleType() == "nucleus" &&
|
||||
pname != "deuteron" && pname != "triton") isIon = true;
|
||||
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForLoss();
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggIonModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
G4double G4BraggIonModel::ComputeDEDXPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
{
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
|
||||
G4double tmin = min(cutEnergy, tmax);
|
||||
G4double tkin = kineticEnergy/massRate;
|
||||
G4double dedx = 0.0;
|
||||
if(tkin > lowestKinEnergy) dedx = DEDX(material, tkin);
|
||||
@@ -153,7 +127,7 @@ G4double G4BraggIonModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
G4double gam = tau + 1.0;
|
||||
G4double bg2 = tau * (tau+2.0);
|
||||
G4double beta2 = bg2/(gam*gam);
|
||||
G4double x = cutEnergy/tmax;
|
||||
G4double x = tmin/tmax;
|
||||
|
||||
dedx += (log(x) + (1.0 - x)*beta2) * twopi_mc2_rcl2
|
||||
* (material->GetElectronDensity())/beta2;
|
||||
@@ -165,16 +139,19 @@ G4double G4BraggIonModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
|
||||
dedx *= chargeSquare;
|
||||
|
||||
//G4cout << " tkin(MeV)= " << tkin/MeV << " dedx(MeVxcm^2/g)= " << dedx*gram/(MeV*cm2*material->GetDensity())
|
||||
// << " q2= " << chargeSquare << G4endl;
|
||||
|
||||
return dedx;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggIonModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
G4double maxKinEnergy)
|
||||
G4double G4BraggIonModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
G4double maxKinEnergy)
|
||||
{
|
||||
|
||||
G4double cross = 0.0;
|
||||
@@ -187,8 +164,7 @@ G4double G4BraggIonModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/energy2;
|
||||
cross = 1.0/cutEnergy - 1.0/maxEnergy - beta2*log(maxEnergy/cutEnergy)/tmax;
|
||||
|
||||
cross *= twopi_mc2_rcl2*chargeSquare*
|
||||
(couple->GetMaterial()->GetElectronDensity())/beta2;
|
||||
cross *= twopi_mc2_rcl2*chargeSquare*material->GetElectronDensity()/beta2;
|
||||
}
|
||||
// G4cout << "BR: e= " << kineticEnergy << " tmin= " << cutEnergy << " tmax= " << tmax
|
||||
// << " cross= " << cross << G4endl;
|
||||
@@ -197,15 +173,15 @@ G4double G4BraggIonModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticle* G4BraggIonModel::SampleSecondary(
|
||||
std::vector<G4DynamicParticle*>* G4BraggIonModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double minEnergy,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
G4double tmax = MaxSecondaryEnergy(dp);
|
||||
G4double tmax = MaxSecondaryKinEnergy(dp);
|
||||
G4double xmax = min(tmax, maxEnergy);
|
||||
G4double xmin = min(xmax,tmin);
|
||||
G4double xmin = min(xmax, minEnergy);
|
||||
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
G4double energy = kineticEnergy + mass;
|
||||
@@ -214,7 +190,7 @@ G4DynamicParticle* G4BraggIonModel::SampleSecondary(
|
||||
G4double grej = 1.0;
|
||||
G4double deltaKinEnergy, f;
|
||||
|
||||
G4ThreeVector momentum = dp->GetMomentumDirection();
|
||||
G4ThreeVector direction = dp->GetMomentumDirection();
|
||||
|
||||
// sampling follows ...
|
||||
do {
|
||||
@@ -242,27 +218,23 @@ G4DynamicParticle* G4BraggIonModel::SampleSecondary(
|
||||
G4double phi = twopi * G4UniformRand() ;
|
||||
|
||||
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
|
||||
deltaDirection.rotateUz(momentum);
|
||||
deltaDirection.rotateUz(direction);
|
||||
|
||||
// create G4DynamicParticle object for delta ray
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(G4Electron::Electron(),
|
||||
deltaDirection,deltaKinEnergy);
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,deltaDirection,
|
||||
deltaKinEnergy);
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
vector<G4DynamicParticle*>* G4BraggIonModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
|
||||
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
|
||||
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
|
||||
vdp->push_back(delta);
|
||||
|
||||
// Change kinematics of primary particle
|
||||
kineticEnergy -= deltaKinEnergy;
|
||||
G4ThreeVector finalP = direction*totMomentum - deltaDirection*deltaMomentum;
|
||||
finalP = finalP.unit();
|
||||
|
||||
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
|
||||
fParticleChange->SetProposedMomentumDirection(finalP);
|
||||
|
||||
return vdp;
|
||||
}
|
||||
|
||||
@@ -275,7 +247,7 @@ G4bool G4BraggIonModel::HasMaterial(const G4Material* material)
|
||||
// ICRU Report N49, 1993. Power's model for He.
|
||||
const size_t numberOfMolecula = 30 ;
|
||||
SetMoleculaNumber(numberOfMolecula) ;
|
||||
static G4String name[numberOfMolecula] = {
|
||||
static G4String nameMol[numberOfMolecula] = {
|
||||
"H_2", "Be-Solid", "C-Solid", "Graphite", "N_2",
|
||||
"O_2", "Al-Solid", "Si-Solid", "Ar-Solid", "Cu-Solid",
|
||||
"Ge", "W-Solid", "Au-Solid", "Pb-Solid", "C_2H_2",
|
||||
@@ -291,7 +263,7 @@ G4bool G4BraggIonModel::HasMaterial(const G4Material* material)
|
||||
|
||||
// Search for the material in the table
|
||||
for (size_t i=0; i<numberOfMolecula; i++) {
|
||||
if (chFormula == name[i]) {
|
||||
if (chFormula == nameMol[i]) {
|
||||
SetMoleculaNumber(i) ;
|
||||
return true ;
|
||||
}
|
||||
@@ -312,7 +284,7 @@ G4double G4BraggIonModel::StoppingPower(const G4Material* material,
|
||||
// ICRU Report N49, 1993. Ziegler's model for protons.
|
||||
// Proton kinetic energy for parametrisation (keV/amu)
|
||||
|
||||
G4double T = kineticEnergy*rateMass/MeV ;
|
||||
G4double T = kineticEnergy*rateMassHe2p/MeV ;
|
||||
|
||||
static G4double c[30][7] = {
|
||||
{8.0080, 3.6287, 23.0700, 14.9900, 0.8507, 0.60, 2.0
|
||||
@@ -369,7 +341,7 @@ G4double G4BraggIonModel::StoppingPower(const G4Material* material,
|
||||
G4double z = (material->GetTotNbOfElectPerVolume()) /
|
||||
(material->GetTotNbOfAtomsPerVolume()) ;
|
||||
|
||||
ionloss = a1*a2 / HeEffChargeSquare(z, T*keV) ;
|
||||
ionloss = a1*a2 / HeEffChargeSquare(z, T) ;
|
||||
|
||||
if ( ionloss < 0.0) ionloss = 0.0 ;
|
||||
}
|
||||
@@ -392,19 +364,21 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
// Proton kinetic energy for parametrisation (keV/amu)
|
||||
|
||||
// He energy in internal units of parametrisation formula (MeV)
|
||||
G4double T = kineticEnergy*rateMass/MeV ;
|
||||
G4double T = kineticEnergy*rateMassHe2p/MeV ;
|
||||
|
||||
static G4double a[92][5] = {
|
||||
{0.35485, 0.6456, 6.01525, 20.8933, 4.3515
|
||||
},{ 0.58, 0.59, 6.3, 130.0, 44.07
|
||||
},{ 1.42, 0.49, 12.25, 32.0, 9.161
|
||||
},{ 2.1895, 0.47183,7.2362, 134.30, 197.96
|
||||
},{ 2.206, 0.51, 15.32, 0.25, 8.995 //Be Ziegler77
|
||||
// },{ 2.1895, 0.47183,7.2362, 134.30, 197.96 //Be from ICRU
|
||||
},{ 3.691, 0.4128, 18.48, 50.72, 9.0
|
||||
},{ 3.83523, 0.42993,12.6125, 227.41, 188.97
|
||||
},{ 1.9259, 0.5550, 27.15125, 26.0665, 6.2768
|
||||
},{ 2.81015, 0.4759, 50.0253, 10.556, 1.0382
|
||||
},{ 1.533, 0.531, 40.44, 18.41, 2.718
|
||||
},{ 2.303, 0.4861, 37.01, 37.96, 5.092
|
||||
// Z= 11-20
|
||||
},{ 9.894, 0.3081, 23.65, 0.384, 92.93
|
||||
},{ 4.3, 0.47, 34.3, 3.3, 12.74
|
||||
},{ 2.5, 0.625, 45.7, 0.1, 4.359
|
||||
@@ -415,6 +389,7 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 2.291, 0.6284, 73.88, 4.478, 2.066
|
||||
},{ 8.554, 0.3817, 83.61, 11.84, 1.875
|
||||
},{ 6.297, 0.4622, 65.39, 10.14, 5.036
|
||||
// Z= 21-30
|
||||
},{ 5.307, 0.4918, 61.74, 12.4, 6.665
|
||||
},{ 4.71, 0.5087, 65.28, 8.806, 5.948
|
||||
},{ 6.151, 0.4524, 83.0, 18.31, 2.71
|
||||
@@ -425,6 +400,7 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 4.652, 0.4571, 80.73, 22.0, 4.952
|
||||
},{ 3.114, 0.5236, 76.67, 7.62, 6.385
|
||||
},{ 3.114, 0.5236, 76.67, 7.62, 7.502
|
||||
// Z= 31-40
|
||||
},{ 3.114, 0.5236, 76.67, 7.62, 8.514
|
||||
},{ 5.746, 0.4662, 79.24, 1.185, 7.993
|
||||
},{ 2.792, 0.6346, 106.1, 0.2986, 2.331
|
||||
@@ -435,6 +411,7 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 7.126, 0.4804, 119.3, 5.784, 2.454
|
||||
},{ 11.61, 0.3955, 146.7, 7.031, 1.423
|
||||
},{ 10.99, 0.41, 163.9, 7.1, 1.052
|
||||
// Z= 41-50
|
||||
},{ 9.241, 0.4275, 163.1, 7.954, 1.102
|
||||
},{ 9.276, 0.418, 157.1, 8.038, 1.29
|
||||
},{ 3.999, 0.6152, 97.6, 1.297, 5.792
|
||||
@@ -445,6 +422,7 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 3.55, 0.6068, 124.7, 1.112, 3.119
|
||||
},{ 3.6, 0.62, 105.8, 0.1692, 6.026
|
||||
},{ 5.4, 0.53, 103.1, 3.931, 7.767
|
||||
// Z= 51-60
|
||||
},{ 3.97, 0.6459, 131.8, 0.2233, 2.723
|
||||
},{ 3.65, 0.64, 126.8, 0.6834, 3.411
|
||||
},{ 3.118, 0.6519, 164.9, 1.208, 1.51
|
||||
@@ -455,6 +433,7 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 10.54, 0.4533, 159.3, 4.832, 2.529
|
||||
},{ 10.33, 0.4502, 162.0, 5.132, 2.444
|
||||
},{ 10.15, 0.4471, 165.6, 5.378, 2.328
|
||||
// Z= 61-70
|
||||
},{ 9.976, 0.4439, 168.0, 5.721, 2.258
|
||||
},{ 9.804, 0.4408, 176.2, 5.675, 1.997
|
||||
},{ 14.22, 0.363, 228.4, 7.024, 1.016
|
||||
@@ -465,6 +444,7 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 11.94, 0.3783, 247.2, 6.655, 0.849
|
||||
},{ 8.472, 0.4405, 195.5, 4.051, 1.604
|
||||
},{ 8.301, 0.4399, 203.7, 3.667, 1.459
|
||||
// Z= 71-80
|
||||
},{ 6.567, 0.4858, 193.0, 2.65, 1.66
|
||||
},{ 5.951, 0.5016, 196.1, 2.662, 1.589
|
||||
},{ 7.495, 0.4523, 251.4, 3.433, 0.8619
|
||||
@@ -473,8 +453,10 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 4.02, 0.5681, 219.9, 2.402, 1.191
|
||||
},{ 3.836, 0.5765, 210.2, 2.742, 1.305
|
||||
},{ 4.68, 0.5247, 244.7, 2.749, 0.8962
|
||||
},{ 3.223, 0.5883, 232.7, 2.954, 1.05
|
||||
},{ 2.892, 0.6204, 208.6, 2.415, 1.416 //Au Z77
|
||||
// },{ 3.223, 0.5883, 232.7, 2.954, 1.05 //Au ICRU
|
||||
},{ 2.892, 0.6204, 208.6, 2.415, 1.416
|
||||
// Z= 81-90
|
||||
},{ 4.728, 0.5522, 217.0, 3.091, 1.386
|
||||
},{ 6.18, 0.52, 170.0, 4.0, 3.224
|
||||
},{ 9.0, 0.47, 198.0, 3.8, 2.032
|
||||
@@ -485,6 +467,7 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
},{ 7.962, 0.519, 235.7, 4.347, 1.313
|
||||
},{ 6.227, 0.5645, 231.9, 3.961, 1.379
|
||||
},{ 5.246, 0.5947, 228.6, 4.027, 1.432
|
||||
// Z= 91-92
|
||||
},{ 5.408, 0.5811, 235.7, 3.961, 1.358
|
||||
},{ 5.218, 0.5828, 245.0, 3.838, 1.25}
|
||||
};
|
||||
@@ -502,12 +485,17 @@ G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
|
||||
G4double slow = a[i][0] * pow((T*1000.0), a[i][1]) ;
|
||||
G4double shigh = log( 1.0 + a[i][3]/T + a[i][4]*T ) * a[i][2]/T ;
|
||||
ionloss = slow*shigh / (slow + shigh) ;
|
||||
|
||||
/*
|
||||
G4cout << "## " << i << ". T= " << T << " slow= " << slow
|
||||
<< " a0= " << a[i][0] << " a1= " << a[i][1]
|
||||
<< " shigh= " << shigh
|
||||
<< " dedx= " << ionloss << " q^2= " << HeEffChargeSquare(z, T*MeV) << G4endl;
|
||||
*/
|
||||
}
|
||||
if ( ionloss < 0.0) ionloss = 0.0 ;
|
||||
|
||||
// He effective charge
|
||||
ionloss /= HeEffChargeSquare(z, T*MeV);
|
||||
ionloss /= HeEffChargeSquare(z, T);
|
||||
|
||||
return ionloss;
|
||||
}
|
||||
@@ -527,7 +515,6 @@ G4double G4BraggIonModel::DEDX(const G4Material* material,
|
||||
|
||||
eloss = StoppingPower(material, kineticEnergy)
|
||||
* (material->GetTotNbOfAtomsPerVolume());
|
||||
eloss *= material->GetTotNbOfAtomsPerVolume();
|
||||
if(1 < numberOfElements) {
|
||||
G4int nAtoms = 0;
|
||||
|
||||
@@ -562,7 +549,7 @@ G4double G4BraggIonModel::DEDX(const G4Material* material,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggIonModel::HeEffChargeSquare(G4double z, G4double kinEnergyHe) const
|
||||
G4double G4BraggIonModel::HeEffChargeSquare(G4double z, G4double kinEnergyHeInMeV) const
|
||||
{
|
||||
// The aproximation of He effective charge from:
|
||||
// J.F.Ziegler, J.P. Biersack, U. Littmark
|
||||
@@ -572,7 +559,7 @@ G4double G4BraggIonModel::HeEffChargeSquare(G4double z, G4double kinEnergyHe) co
|
||||
static G4double c[6] = {0.2865, 0.1266, -0.001429,
|
||||
0.02402,-0.01135, 0.001475} ;
|
||||
|
||||
G4double e = log( max( 1.0, kinEnergyHe/(keV*HeMassAMU))) ;
|
||||
G4double e = log( max( 1.0, kinEnergyHeInMeV*massFactor));
|
||||
G4double x = c[0] ;
|
||||
G4double y = 1.0 ;
|
||||
for (G4int i=1; i<6; i++) {
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4BraggModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4BraggModel.cc,v 1.8 2005/05/12 11:06:43 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -42,6 +42,7 @@
|
||||
// 13-02-03 Add name (V.Ivanchenko)
|
||||
// 04-06-03 Fix compilation warnings (V.Ivanchenko)
|
||||
// 12-09-04 Add lowestKinEnergy and change order of if in DEDX method (V.Ivanchenko)
|
||||
// 11-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
|
||||
// Class Description:
|
||||
//
|
||||
@@ -58,6 +59,7 @@
|
||||
#include "G4BraggModel.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4ParticleChangeForLoss.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -71,10 +73,9 @@ G4BraggModel::G4BraggModel(const G4ParticleDefinition* p, const G4String& nam)
|
||||
isIon(false)
|
||||
{
|
||||
if(p) SetParticle(p);
|
||||
highKinEnergy = 2.0*MeV;
|
||||
lowKinEnergy = 0.0*MeV;
|
||||
lowestKinEnergy = 1.0*keV;
|
||||
theZieglerFactor = eV*cm2*1.0e-15;
|
||||
theElectron = G4Electron::Electron();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -84,38 +85,6 @@ G4BraggModel::~G4BraggModel()
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(particle != p) {
|
||||
particle = p;
|
||||
mass = particle->GetPDGMass();
|
||||
spin = particle->GetPDGSpin();
|
||||
G4double q = particle->GetPDGCharge()/eplus;
|
||||
chargeSquare = q*q;
|
||||
massRate = mass/proton_mass_c2;
|
||||
ratio = electron_mass_c2/mass;
|
||||
if(particle->GetParticleName() == "GenericIon") isIon = true;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggModel::HighEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return highKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return lowKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple* couple)
|
||||
{
|
||||
@@ -124,28 +93,27 @@ G4double G4BraggModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4bool G4BraggModel::IsInCharge(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4BraggModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
if(p != particle) SetParticle(p);
|
||||
G4String pname = particle->GetParticleName();
|
||||
if(particle->GetParticleType() == "nucleus" &&
|
||||
pname != "deuteron" && pname != "triton") isIon = true;
|
||||
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForLoss();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
G4double G4BraggModel::ComputeDEDXPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
{
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
|
||||
G4double tkin = kineticEnergy/massRate;
|
||||
G4double dedx = 0.0;
|
||||
@@ -175,7 +143,8 @@ G4double G4BraggModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4BraggModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
G4double G4BraggModel::CrossSectionPerVolume(
|
||||
const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
@@ -192,8 +161,7 @@ G4double G4BraggModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/energy2;
|
||||
cross = 1.0/cutEnergy - 1.0/maxEnergy - beta2*log(maxEnergy/cutEnergy)/tmax;
|
||||
|
||||
cross *= twopi_mc2_rcl2*chargeSquare*
|
||||
(couple->GetMaterial()->GetElectronDensity())/beta2;
|
||||
cross *= twopi_mc2_rcl2*chargeSquare*(material->GetElectronDensity())/beta2;
|
||||
}
|
||||
// G4cout << "BR: e= " << kineticEnergy << " tmin= " << cutEnergy << " tmax= " << tmax
|
||||
// << " cross= " << cross << G4endl;
|
||||
@@ -202,13 +170,13 @@ G4double G4BraggModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticle* G4BraggModel::SampleSecondary(
|
||||
vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
G4double tmax = MaxSecondaryEnergy(dp);
|
||||
G4double tmax = MaxSecondaryKinEnergy(dp);
|
||||
G4double xmax = min(tmax, maxEnergy);
|
||||
G4double xmin = min(xmax,tmin);
|
||||
|
||||
@@ -219,7 +187,7 @@ G4DynamicParticle* G4BraggModel::SampleSecondary(
|
||||
G4double grej = 1.0;
|
||||
G4double deltaKinEnergy, f;
|
||||
|
||||
G4ThreeVector momentum = dp->GetMomentumDirection();
|
||||
G4ThreeVector direction = dp->GetMomentumDirection();
|
||||
|
||||
// sampling follows ...
|
||||
do {
|
||||
@@ -247,27 +215,22 @@ G4DynamicParticle* G4BraggModel::SampleSecondary(
|
||||
G4double phi = twopi * G4UniformRand() ;
|
||||
|
||||
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
|
||||
deltaDirection.rotateUz(momentum);
|
||||
deltaDirection.rotateUz(direction);
|
||||
|
||||
// Change kinematics of primary particle
|
||||
kineticEnergy -= deltaKinEnergy;
|
||||
G4ThreeVector finalP = direction*totMomentum - deltaDirection*deltaMomentum;
|
||||
finalP = finalP.unit();
|
||||
|
||||
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
|
||||
fParticleChange->SetProposedMomentumDirection(finalP);
|
||||
|
||||
// create G4DynamicParticle object for delta ray
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(G4Electron::Electron(),
|
||||
deltaDirection,deltaKinEnergy);
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,deltaDirection,
|
||||
deltaKinEnergy);
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
|
||||
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
|
||||
vdp->push_back(delta);
|
||||
|
||||
return vdp;
|
||||
}
|
||||
|
||||
@@ -391,6 +354,7 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{2.652E+0, 3.000E+0, 1.920E+3, 2.000E+3, 2.230E-2},
|
||||
{2.085E+0, 2.352E+0, 2.157E+3, 2.634E+3, 1.816E-2},
|
||||
{1.951E+0, 2.199E+0, 2.393E+3, 2.699E+3, 1.568E-2},
|
||||
// Z= 11-20
|
||||
{2.542E+0, 2.869E+0, 2.628E+3, 1.854E+3, 1.472E-2},
|
||||
{3.791E+0, 4.293E+0, 2.862E+3, 1.009E+3, 1.397E-2},
|
||||
{4.154E+0, 4.739E+0, 2.766E+3, 1.645E+2, 2.023E-2},
|
||||
@@ -401,6 +365,7 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{5.731E+0, 6.500E+0, 4.253E+3, 5.300E+2, 1.123E-2},
|
||||
{5.152E+0, 5.833E+0, 4.482E+3, 5.457E+2, 1.129E-2},
|
||||
{5.521E+0, 6.252E+0, 4.710E+3, 5.533E+2, 1.112E-2},
|
||||
// Z= 21-30
|
||||
{5.201E+0, 5.884E+0, 4.938E+3, 5.609E+2, 9.995E-3},
|
||||
{4.858E+0, 5.489E+0, 5.260E+3, 6.511E+2, 8.930E-3},
|
||||
{4.479E+0, 5.055E+0, 5.391E+3, 9.523E+2, 9.117E-3},
|
||||
@@ -411,6 +376,7 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{3.553E+0, 4.004E+0, 6.205E+3, 5.551E+2, 8.763E-3},
|
||||
{3.696E+0, 4.194E+0, 4.649E+3, 8.113E+1, 2.242E-2},
|
||||
{4.210E+0, 4.750E+0, 6.953E+3, 2.952E+2, 6.809E-3},
|
||||
// Z= 31-40
|
||||
{5.041E+0, 5.697E+0, 7.173E+3, 2.026E+2, 6.725E-3},
|
||||
{5.554E+0, 6.300E+0, 6.496E+3, 1.100E+2, 9.689E-3},
|
||||
{5.323E+0, 6.012E+0, 7.611E+3, 2.925E+2, 6.447E-3},
|
||||
@@ -421,16 +387,19 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{6.339E+0, 7.159E+0, 8.693E+3, 3.303E+2, 6.003E-3},
|
||||
{6.407E+0, 7.234E+0, 8.907E+3, 3.678E+2, 5.889E-3},
|
||||
{6.734E+0, 7.603E+0, 9.120E+3, 4.052E+2, 5.765E-3},
|
||||
// Z= 41-50
|
||||
{6.901E+0, 7.791E+0, 9.333E+3, 4.427E+2, 5.587E-3},
|
||||
{6.424E+0, 7.248E+0, 9.545E+3, 4.802E+2, 5.376E-3},
|
||||
{6.799E+0, 7.671E+0, 9.756E+3, 5.176E+2, 5.315E-3},
|
||||
{6.109E+0, 6.887E+0, 9.966E+3, 5.551E+2, 5.151E-3},
|
||||
{5.924E+0, 6.677E+0, 1.018E+4, 5.925E+2, 4.919E-3},
|
||||
{5.238E+0, 5.900E+0, 1.038E+4, 6.300E+2, 4.758E-3},
|
||||
{5.345E+0, 6.038E+0, 6.790E+3, 3.978E+2, 1.676E-2},
|
||||
// {5.623, 6.354, 7160.0, 337.6, 0.013940}, // Ag Ziegler77
|
||||
{5.345E+0, 6.038E+0, 6.790E+3, 3.978E+2, 1.676E-2}, // Ag ICRU49
|
||||
{5.814E+0, 6.554E+0, 1.080E+4, 3.555E+2, 4.626E-3},
|
||||
{6.229E+0, 7.024E+0, 1.101E+4, 3.709E+2, 4.540E-3},
|
||||
{6.409E+0, 7.227E+0, 1.121E+4, 3.864E+2, 4.474E-3},
|
||||
// Z= 51-60
|
||||
{7.500E+0, 8.480E+0, 8.608E+3, 3.480E+2, 9.074E-3},
|
||||
{6.979E+0, 7.871E+0, 1.162E+4, 3.924E+2, 4.402E-3},
|
||||
{7.725E+0, 8.716E+0, 1.183E+4, 3.948E+2, 4.376E-3},
|
||||
@@ -441,6 +410,7 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{7.488E+0, 8.444E+0, 1.283E+4, 4.069E+2, 4.420E-3},
|
||||
{7.291E+0, 8.219E+0, 1.303E+4, 4.093E+2, 4.298E-3},
|
||||
{7.098E+0, 8.000E+0, 1.323E+4, 4.118E+2, 4.182E-3},
|
||||
// Z= 61-70
|
||||
{6.909E+0, 7.786E+0, 1.343E+4, 4.142E+2, 4.058E-3},
|
||||
{6.728E+0, 7.580E+0, 1.362E+4, 4.166E+2, 3.976E-3},
|
||||
{6.551E+0, 7.380E+0, 1.382E+4, 4.190E+2, 3.877E-3},
|
||||
@@ -451,6 +421,7 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{5.071E+0, 5.706E+0, 1.479E+4, 4.330E+2, 3.405E-3},
|
||||
{4.926E+0, 5.542E+0, 1.498E+4, 4.335E+2, 3.342E-3},
|
||||
{4.788E+0, 5.386E+0, 1.517E+4, 4.359E+2, 3.292E-3},
|
||||
// Z= 71-80
|
||||
{4.893E+0, 5.505E+0, 1.536E+4, 4.384E+2, 3.243E-3},
|
||||
{5.028E+0, 5.657E+0, 1.555E+4, 4.408E+2, 3.195E-3},
|
||||
{4.738E+0, 5.329E+0, 1.574E+4, 4.432E+2, 3.186E-3},
|
||||
@@ -459,8 +430,10 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{5.071E+0, 5.704E+0, 1.630E+4, 4.409E+2, 3.082E-3},
|
||||
{4.946E+0, 5.563E+0, 1.649E+4, 4.401E+2, 2.965E-3},
|
||||
{4.477E+0, 5.034E+0, 1.667E+4, 4.393E+2, 2.871E-3},
|
||||
{4.844E+0, 5.458E+0, 7.852E+3, 9.758E+2, 2.077E-2},
|
||||
// {4.856, 5.460, 18320.0, 438.5, 0.002542}, //Ziegler77
|
||||
{4.844E+0, 5.458E+0, 7.852E+3, 9.758E+2, 2.077E-2}, //ICRU49
|
||||
{4.307E+0, 4.843E+0, 1.704E+4, 4.878E+2, 2.882E-3},
|
||||
// Z= 81-90
|
||||
{4.723E+0, 5.311E+0, 1.722E+4, 5.370E+2, 2.913E-3},
|
||||
{5.319E+0, 5.982E+0, 1.740E+4, 5.863E+2, 2.871E-3},
|
||||
{5.956E+0, 6.700E+0, 1.780E+4, 6.770E+2, 2.660E-3},
|
||||
@@ -471,6 +444,7 @@ G4double G4BraggModel::ElectronicStoppingPower(G4double z,
|
||||
{7.506E+0, 8.448E+0, 1.848E+4, 5.863E+2, 2.727E-3},
|
||||
{7.648E+0, 8.609E+0, 1.866E+4, 5.863E+2, 2.697E-3},
|
||||
{7.711E+0, 8.679E+0, 1.883E+4, 5.863E+2, 2.641E-3},
|
||||
// Z= 91-92
|
||||
{7.407E+0, 8.336E+0, 1.901E+4, 5.863E+2, 2.603E-3},
|
||||
{7.290E+0, 8.204E+0, 1.918E+4, 5.863E+2, 2.673E-3}
|
||||
};
|
||||
@@ -513,7 +487,6 @@ G4double G4BraggModel::DEDX(const G4Material* material,
|
||||
|
||||
eloss = StoppingPower(material, kineticEnergy)
|
||||
* (material->GetTotNbOfAtomsPerVolume());
|
||||
eloss *= material->GetTotNbOfAtomsPerVolume();
|
||||
if(1 < numberOfElements) {
|
||||
G4int nAtoms = 0;
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4ComptonScattering.cc,v 1.23 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4ComptonScattering.cc,v 1.24 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//
|
||||
//------------ G4ComptonScattering physics process -----------------------------
|
||||
@@ -49,430 +49,67 @@
|
||||
// 17-04-02, LowestEnergyLimit = 1*keV
|
||||
// 26-05-04, cross section parametrization improved for low energy :
|
||||
// Egamma <~ 15 keV (Laszlo)
|
||||
// 08-11-04, Remove Store/Retrieve tables (V.Ivantchenko)
|
||||
// 08-11-04, Remove Store/Retrieve tables (V.Ivanchenko)
|
||||
// 09-03-05 Migrate to model interface and inherit from G4VEmProcess (V.Ivanchenko)
|
||||
// 04-05-05, Make class to be default (V.Ivanchenko)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "G4ComptonScattering.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4PhysicsTableHelper.hh"
|
||||
#include "G4KleinNishinaCompton.hh"
|
||||
#include "G4Electron.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4ComptonScattering::G4ComptonScattering(const G4String& processName,
|
||||
G4ProcessType type):G4VDiscreteProcess (processName, type),
|
||||
theCrossSectionTable(NULL),
|
||||
theMeanFreePathTable(NULL),
|
||||
LowestEnergyLimit ( 1*keV),
|
||||
HighestEnergyLimit(100*GeV),
|
||||
NumbBinTable(80),
|
||||
fminimalEnergy(1*eV)
|
||||
G4ProcessType type):G4VEmProcess (processName, type),
|
||||
isInitialised(false),
|
||||
selectedModel(0),
|
||||
mType(0)
|
||||
{
|
||||
SetLambdaBinning(90);
|
||||
SetMinKinEnergy(0.1*keV);
|
||||
SetMaxKinEnergy(100.0*GeV);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4ComptonScattering::~G4ComptonScattering()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// destructor
|
||||
|
||||
G4ComptonScattering::~G4ComptonScattering()
|
||||
{
|
||||
if (theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy();
|
||||
delete theCrossSectionTable;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
if (theMeanFreePathTable) {
|
||||
theMeanFreePathTable->clearAndDestroy();
|
||||
delete theMeanFreePathTable;
|
||||
}
|
||||
void G4ComptonScattering::InitialiseProcess(const G4ParticleDefinition*)
|
||||
{
|
||||
if(!isInitialised) {
|
||||
isInitialised = true;
|
||||
SetBuildTableFlag(true);
|
||||
SetSecondaryParticle(G4Electron::Electron());
|
||||
G4double emin = MinKinEnergy();
|
||||
G4double emax = MaxKinEnergy();
|
||||
if(0 == mType) selectedModel = new G4KleinNishinaCompton();
|
||||
selectedModel->SetLowEnergyLimit(emin);
|
||||
selectedModel->SetHighEnergyLimit(emax);
|
||||
AddEmModel(1, selectedModel);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4ComptonScattering::IsApplicable( const G4ParticleDefinition& particle)
|
||||
void G4ComptonScattering::PrintInfo()
|
||||
{
|
||||
return ( &particle == G4Gamma::Gamma() );
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ComptonScattering::SetPhysicsTableBining(
|
||||
G4double lowE, G4double highE, G4int nBins)
|
||||
{
|
||||
LowestEnergyLimit = lowE; HighestEnergyLimit = highE; NumbBinTable = nBins;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ComptonScattering::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
// Build cross section and mean free path tables
|
||||
{
|
||||
G4double LowEdgeEnergy, Value;
|
||||
G4PhysicsLogVector* ptrVector;
|
||||
|
||||
// Build cross section per atom tables for the Compton Scattering process
|
||||
|
||||
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 Compton Scattering process
|
||||
|
||||
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 G4ComptonScattering::ComputeCrossSectionPerAtom
|
||||
(G4double GammaEnergy, G4double Z)
|
||||
|
||||
// Calculates the cross section per atom 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 10 keV to 100/Z GeV.
|
||||
// lower limit 1 keV now with a correction for low energy
|
||||
|
||||
{
|
||||
G4double CrossSection = 0.0 ;
|
||||
if ( Z < 1. ) return CrossSection;
|
||||
if ( GammaEnergy < 1.*keV ) return CrossSection;
|
||||
if ( GammaEnergy > (100.*GeV/Z) ) return CrossSection;
|
||||
|
||||
static const G4double a = 20.0 , b = 230.0 , c = 440.0;
|
||||
|
||||
static const G4double
|
||||
d1= 2.7965e-1*barn, d2=-1.8300e-1*barn, d3= 6.7527 *barn, d4=-1.9798e+1*barn,
|
||||
e1= 1.9756e-5*barn, e2=-1.0205e-2*barn, e3=-7.3913e-2*barn, e4= 2.7079e-2*barn,
|
||||
f1=-3.9178e-7*barn, f2= 6.8241e-5*barn, f3= 6.0480e-5*barn, f4= 3.0274e-4*barn;
|
||||
|
||||
G4double p1Z = Z*(d1 + e1*Z + f1*Z*Z), p2Z = Z*(d2 + e2*Z + f2*Z*Z),
|
||||
p3Z = Z*(d3 + e3*Z + f3*Z*Z), p4Z = Z*(d4 + e4*Z + f4*Z*Z);
|
||||
|
||||
G4double T0 = 15*keV; if (Z == 1.) T0 = 40*keV;
|
||||
|
||||
G4double X = max(GammaEnergy, T0) / electron_mass_c2;
|
||||
CrossSection = p1Z*log(1.+2*X)/X
|
||||
+ (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
|
||||
|
||||
// modification for low energy. (special case for Hydrogen)
|
||||
if (GammaEnergy < T0) {
|
||||
G4double dT0 = 1.*keV;
|
||||
X = (T0+dT0) / electron_mass_c2 ;
|
||||
G4double sigma = p1Z*log(1.+2*X)/X
|
||||
+ (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
|
||||
G4double c1 = -T0*(sigma-CrossSection)/(CrossSection*dT0);
|
||||
G4double c2 = 0.150; if (Z > 1.) c2 = 0.375-0.0556*log(Z);
|
||||
G4double y = log(GammaEnergy/T0);
|
||||
CrossSection *= exp(-y*(c1+c2*y));
|
||||
}
|
||||
|
||||
return CrossSection;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4ComptonScattering::ComputeMeanFreePath(G4double GammaEnergy,
|
||||
G4Material* aMaterial)
|
||||
|
||||
// returns the gamma 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(GammaEnergy,
|
||||
(*theElementVector)[elm]->GetZ());
|
||||
}
|
||||
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4ComptonScattering::GetCrossSectionPerAtom(
|
||||
G4DynamicParticle* aDynamicGamma,
|
||||
G4Element* anElement)
|
||||
|
||||
// gives the microscopic total cross section in GEANT4 internal units
|
||||
|
||||
{
|
||||
G4double crossSection;
|
||||
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
|
||||
G4bool isOutRange ;
|
||||
if (GammaEnergy < LowestEnergyLimit || GammaEnergy > HighestEnergyLimit)
|
||||
crossSection = 0.;
|
||||
else
|
||||
crossSection = (*theCrossSectionTable)(anElement->GetIndex())->
|
||||
GetValue(GammaEnergy, isOutRange);
|
||||
|
||||
return crossSection;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
G4double G4ComptonScattering::GetMeanFreePath(const G4Track& aTrack,
|
||||
G4double,
|
||||
G4ForceCondition*)
|
||||
|
||||
// returns the gamma mean free path in GEANT4 internal units
|
||||
|
||||
{
|
||||
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
|
||||
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
|
||||
G4Material* aMaterial = aTrack.GetMaterial();
|
||||
|
||||
G4double MeanFreePath;
|
||||
G4bool isOutRange;
|
||||
|
||||
if (GammaEnergy > HighestEnergyLimit || GammaEnergy < LowestEnergyLimit)
|
||||
MeanFreePath = DBL_MAX;
|
||||
else
|
||||
MeanFreePath = (*theMeanFreePathTable)(aMaterial->GetIndex())->
|
||||
GetValue(GammaEnergy, isOutRange);
|
||||
return MeanFreePath;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4VParticleChange* G4ComptonScattering::PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep)
|
||||
//
|
||||
// The scattered gamma energy is sampled according to Klein - Nishina formula.
|
||||
// The random number techniques of Butcher & Messel are used
|
||||
// (Nuc Phys 20(1960),15).
|
||||
// GEANT4 internal units
|
||||
//
|
||||
// Note : Effects due to binding of atomic electrons are negliged.
|
||||
|
||||
{
|
||||
aParticleChange.Initialize(aTrack);
|
||||
|
||||
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
|
||||
G4double GammaEnergy0 = aDynamicGamma->GetKineticEnergy();
|
||||
G4double E0_m = GammaEnergy0 / electron_mass_c2 ;
|
||||
|
||||
G4ParticleMomentum GammaDirection0 = aDynamicGamma->GetMomentumDirection();
|
||||
|
||||
//
|
||||
// sample the energy rate of the scattered gamma
|
||||
//
|
||||
|
||||
G4double epsilon, epsilonsq, onecost, sint2, greject ;
|
||||
|
||||
G4double epsilon0 = 1./(1. + 2*E0_m) , epsilon0sq = epsilon0*epsilon0;
|
||||
G4double alpha1 = - log(epsilon0) , alpha2 = 0.5*(1.- epsilon0sq);
|
||||
|
||||
do {
|
||||
if ( alpha1/(alpha1+alpha2) > G4UniformRand() )
|
||||
{ epsilon = exp(-alpha1*G4UniformRand()); // epsilon0**r
|
||||
epsilonsq = epsilon*epsilon; }
|
||||
else {
|
||||
epsilonsq = epsilon0sq + (1.- epsilon0sq)*G4UniformRand();
|
||||
epsilon = sqrt(epsilonsq);
|
||||
};
|
||||
onecost = (1.- epsilon)/(epsilon*E0_m);
|
||||
sint2 = onecost*(2.-onecost);
|
||||
greject = 1. - epsilon*sint2/(1.+ epsilonsq);
|
||||
} while (greject < G4UniformRand());
|
||||
|
||||
//
|
||||
// scattered gamma angles. ( Z - axis along the parent gamma)
|
||||
//
|
||||
|
||||
G4double cosTeta = 1. - onecost , sinTeta = sqrt (sint2);
|
||||
G4double Phi = twopi * G4UniformRand();
|
||||
G4double dirx = sinTeta*cos(Phi), diry = sinTeta*sin(Phi), dirz = cosTeta;
|
||||
|
||||
//
|
||||
// update G4VParticleChange for the scattered gamma
|
||||
//
|
||||
|
||||
G4ThreeVector GammaDirection1 ( dirx,diry,dirz );
|
||||
GammaDirection1.rotateUz(GammaDirection0);
|
||||
aParticleChange.ProposeMomentumDirection( GammaDirection1 );
|
||||
G4double GammaEnergy1 = epsilon*GammaEnergy0;
|
||||
G4double localEnergyDeposit = 0.;
|
||||
|
||||
if (GammaEnergy1 > fminimalEnergy)
|
||||
{
|
||||
aParticleChange.ProposeEnergy( GammaEnergy1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
localEnergyDeposit += GammaEnergy1;
|
||||
aParticleChange.ProposeEnergy(0.) ;
|
||||
aParticleChange.ProposeTrackStatus(fStopAndKill);
|
||||
}
|
||||
|
||||
//
|
||||
// kinematic of the scattered electron
|
||||
//
|
||||
|
||||
G4double ElecKineEnergy = GammaEnergy0 - GammaEnergy1;
|
||||
|
||||
if (ElecKineEnergy > fminimalEnergy)
|
||||
{
|
||||
G4double ElecMomentum = sqrt(ElecKineEnergy*
|
||||
(ElecKineEnergy+2.*electron_mass_c2));
|
||||
G4ThreeVector ElecDirection (
|
||||
(GammaEnergy0*GammaDirection0 - GammaEnergy1*GammaDirection1)
|
||||
*(1./ElecMomentum) );
|
||||
|
||||
// create G4DynamicParticle object for the electron.
|
||||
G4DynamicParticle* aElectron= new G4DynamicParticle(
|
||||
G4Electron::Electron(),ElecDirection,ElecKineEnergy);
|
||||
|
||||
aParticleChange.SetNumberOfSecondaries(1);
|
||||
aParticleChange.AddSecondary( aElectron );
|
||||
}
|
||||
else
|
||||
{
|
||||
aParticleChange.SetNumberOfSecondaries(0);
|
||||
localEnergyDeposit += ElecKineEnergy;
|
||||
}
|
||||
aParticleChange.ProposeLocalEnergyDeposit (localEnergyDeposit);
|
||||
|
||||
// Reset NbOfInteractionLengthLeft and return aParticleChange
|
||||
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4ComptonScattering::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 G4ComptonScattering::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 G4ComptonScattering::PrintInfoDefinition()
|
||||
{
|
||||
G4String comments = "Total cross sections from a parametrisation. ";
|
||||
comments += "Good description from 10 KeV to (100/Z) GeV. \n";
|
||||
comments += " Scattered gamma energy according Klein-Nishina.";
|
||||
|
||||
G4cout << G4endl << GetProcessName() << ": " << comments
|
||||
<< "\n PhysicsTables from "
|
||||
<< G4BestUnit(LowestEnergyLimit,"Energy")
|
||||
<< " to " << G4BestUnit(HighestEnergyLimit,"Energy")
|
||||
<< " in " << NumbBinTable << " bins. \n";
|
||||
G4cout << " Total cross sections has a good parametrisation"
|
||||
<< " from 10 KeV to (100/Z) GeV"
|
||||
<< "\n Sampling according " << selectedModel->GetName() << " model"
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ComptonScattering::SetModel(const G4String& s)
|
||||
{
|
||||
if(s == "Klein-Nishina") mType = 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4ComptonScattering52.cc,v 1.1 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//
|
||||
//------------ G4ComptonScattering52 physics process -----------------------------
|
||||
// by Michel Maire, April 1996
|
||||
//
|
||||
// 28-05-96, DoIt() small change in ElecDirection, by M.Maire
|
||||
// 10-06-96, simplification in ComputeMicroscopicCrossSection(), by M.Maire
|
||||
// 21-06-96, SetCuts implementation, M.Maire
|
||||
// 13-09-96, small changes in DoIt for better efficiency. Thanks to P.Urban
|
||||
// 06-01-97, crossection table + meanfreepath table, M.Maire
|
||||
// 05-03-97, new Physics scheme, M.Maire
|
||||
// 28-03-97, protection in BuildPhysicsTable, M.Maire
|
||||
// 07-04-98, remove 'tracking cut' of the scattered gamma, MMa
|
||||
// 04-06-98, in DoIt, secondary production condition:
|
||||
// range>std::min(threshold,safety)
|
||||
// 13-08-98, new methods SetBining() PrintInfo()
|
||||
// 15-12-98, cross section=0 below 10 keV
|
||||
// 28-05-01, V.Ivanchenko minor changes to provide ANSI -wall compilation
|
||||
// 13-07-01, DoIt: suppression of production cut for the electron (mma)
|
||||
// 03-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&)
|
||||
// 17-04-02, LowestEnergyLimit = 1*keV
|
||||
// 26-05-04, cross section parametrization improved for low energy :
|
||||
// Egamma <~ 15 keV (Laszlo)
|
||||
// 08-11-04, Remove Store/Retrieve tables (V.Ivanchenko)
|
||||
// 04-05-05, Add 52 to class name (V.Ivanchenko)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "G4ComptonScattering52.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4PhysicsTableHelper.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4ComptonScattering52::G4ComptonScattering52(const G4String& processName,
|
||||
G4ProcessType type):G4VDiscreteProcess (processName, type),
|
||||
theCrossSectionTable(NULL),
|
||||
theMeanFreePathTable(NULL),
|
||||
LowestEnergyLimit ( 1*keV),
|
||||
HighestEnergyLimit(100*GeV),
|
||||
NumbBinTable(80),
|
||||
fminimalEnergy(1*eV)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// destructor
|
||||
|
||||
G4ComptonScattering52::~G4ComptonScattering52()
|
||||
{
|
||||
if (theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy();
|
||||
delete theCrossSectionTable;
|
||||
}
|
||||
|
||||
if (theMeanFreePathTable) {
|
||||
theMeanFreePathTable->clearAndDestroy();
|
||||
delete theMeanFreePathTable;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4ComptonScattering52::IsApplicable( const G4ParticleDefinition& particle)
|
||||
{
|
||||
return ( &particle == G4Gamma::Gamma() );
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ComptonScattering52::SetPhysicsTableBining(
|
||||
G4double lowE, G4double highE, G4int nBins)
|
||||
{
|
||||
LowestEnergyLimit = lowE; HighestEnergyLimit = highE; NumbBinTable = nBins;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ComptonScattering52::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
// Build cross section and mean free path tables
|
||||
{
|
||||
G4double LowEdgeEnergy, Value;
|
||||
G4PhysicsLogVector* ptrVector;
|
||||
|
||||
// Build cross section per atom tables for the Compton Scattering process
|
||||
|
||||
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 Compton Scattering process
|
||||
|
||||
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 G4ComptonScattering52::ComputeCrossSectionPerAtom
|
||||
(G4double GammaEnergy, G4double Z)
|
||||
|
||||
// Calculates the cross section per atom 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 10 keV to 100/Z GeV.
|
||||
// lower limit 1 keV now with a correction for low energy
|
||||
|
||||
{
|
||||
G4double CrossSection = 0.0 ;
|
||||
if ( Z < 1. ) return CrossSection;
|
||||
if ( GammaEnergy < 1.*keV ) return CrossSection;
|
||||
if ( GammaEnergy > (100.*GeV/Z) ) return CrossSection;
|
||||
|
||||
static const G4double a = 20.0 , b = 230.0 , c = 440.0;
|
||||
|
||||
static const G4double
|
||||
d1= 2.7965e-1*barn, d2=-1.8300e-1*barn, d3= 6.7527 *barn, d4=-1.9798e+1*barn,
|
||||
e1= 1.9756e-5*barn, e2=-1.0205e-2*barn, e3=-7.3913e-2*barn, e4= 2.7079e-2*barn,
|
||||
f1=-3.9178e-7*barn, f2= 6.8241e-5*barn, f3= 6.0480e-5*barn, f4= 3.0274e-4*barn;
|
||||
|
||||
G4double p1Z = Z*(d1 + e1*Z + f1*Z*Z), p2Z = Z*(d2 + e2*Z + f2*Z*Z),
|
||||
p3Z = Z*(d3 + e3*Z + f3*Z*Z), p4Z = Z*(d4 + e4*Z + f4*Z*Z);
|
||||
|
||||
G4double T0 = 15*keV; if (Z == 1.) T0 = 40*keV;
|
||||
|
||||
G4double X = max(GammaEnergy, T0) / electron_mass_c2;
|
||||
CrossSection = p1Z*log(1.+2*X)/X
|
||||
+ (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
|
||||
|
||||
// modification for low energy. (special case for Hydrogen)
|
||||
if (GammaEnergy < T0) {
|
||||
G4double dT0 = 1.*keV;
|
||||
X = (T0+dT0) / electron_mass_c2 ;
|
||||
G4double sigma = p1Z*log(1.+2*X)/X
|
||||
+ (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
|
||||
G4double c1 = -T0*(sigma-CrossSection)/(CrossSection*dT0);
|
||||
G4double c2 = 0.150; if (Z > 1.) c2 = 0.375-0.0556*log(Z);
|
||||
G4double y = log(GammaEnergy/T0);
|
||||
CrossSection *= exp(-y*(c1+c2*y));
|
||||
}
|
||||
|
||||
return CrossSection;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4ComptonScattering52::ComputeMeanFreePath(G4double GammaEnergy,
|
||||
G4Material* aMaterial)
|
||||
|
||||
// returns the gamma 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(GammaEnergy,
|
||||
(*theElementVector)[elm]->GetZ());
|
||||
}
|
||||
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4ComptonScattering52::GetCrossSectionPerAtom(
|
||||
G4DynamicParticle* aDynamicGamma,
|
||||
G4Element* anElement)
|
||||
|
||||
// gives the microscopic total cross section in GEANT4 internal units
|
||||
|
||||
{
|
||||
G4double crossSection;
|
||||
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
|
||||
G4bool isOutRange ;
|
||||
if (GammaEnergy < LowestEnergyLimit || GammaEnergy > HighestEnergyLimit)
|
||||
crossSection = 0.;
|
||||
else
|
||||
crossSection = (*theCrossSectionTable)(anElement->GetIndex())->
|
||||
GetValue(GammaEnergy, isOutRange);
|
||||
|
||||
return crossSection;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
G4double G4ComptonScattering52::GetMeanFreePath(const G4Track& aTrack,
|
||||
G4double,
|
||||
G4ForceCondition*)
|
||||
|
||||
// returns the gamma mean free path in GEANT4 internal units
|
||||
|
||||
{
|
||||
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
|
||||
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
|
||||
G4Material* aMaterial = aTrack.GetMaterial();
|
||||
|
||||
G4double MeanFreePath;
|
||||
G4bool isOutRange;
|
||||
|
||||
if (GammaEnergy > HighestEnergyLimit || GammaEnergy < LowestEnergyLimit)
|
||||
MeanFreePath = DBL_MAX;
|
||||
else
|
||||
MeanFreePath = (*theMeanFreePathTable)(aMaterial->GetIndex())->
|
||||
GetValue(GammaEnergy, isOutRange);
|
||||
return MeanFreePath;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4VParticleChange* G4ComptonScattering52::PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep)
|
||||
//
|
||||
// The scattered gamma energy is sampled according to Klein - Nishina formula.
|
||||
// The random number techniques of Butcher & Messel are used
|
||||
// (Nuc Phys 20(1960),15).
|
||||
// GEANT4 internal units
|
||||
//
|
||||
// Note : Effects due to binding of atomic electrons are negliged.
|
||||
|
||||
{
|
||||
aParticleChange.Initialize(aTrack);
|
||||
|
||||
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
|
||||
G4double GammaEnergy0 = aDynamicGamma->GetKineticEnergy();
|
||||
G4double E0_m = GammaEnergy0 / electron_mass_c2 ;
|
||||
|
||||
G4ParticleMomentum GammaDirection0 = aDynamicGamma->GetMomentumDirection();
|
||||
|
||||
//
|
||||
// sample the energy rate of the scattered gamma
|
||||
//
|
||||
|
||||
G4double epsilon, epsilonsq, onecost, sint2, greject ;
|
||||
|
||||
G4double epsilon0 = 1./(1. + 2*E0_m) , epsilon0sq = epsilon0*epsilon0;
|
||||
G4double alpha1 = - log(epsilon0) , alpha2 = 0.5*(1.- epsilon0sq);
|
||||
|
||||
do {
|
||||
if ( alpha1/(alpha1+alpha2) > G4UniformRand() )
|
||||
{ epsilon = exp(-alpha1*G4UniformRand()); // epsilon0**r
|
||||
epsilonsq = epsilon*epsilon; }
|
||||
else {
|
||||
epsilonsq = epsilon0sq + (1.- epsilon0sq)*G4UniformRand();
|
||||
epsilon = sqrt(epsilonsq);
|
||||
};
|
||||
onecost = (1.- epsilon)/(epsilon*E0_m);
|
||||
sint2 = onecost*(2.-onecost);
|
||||
greject = 1. - epsilon*sint2/(1.+ epsilonsq);
|
||||
} while (greject < G4UniformRand());
|
||||
|
||||
//
|
||||
// scattered gamma angles. ( Z - axis along the parent gamma)
|
||||
//
|
||||
|
||||
G4double cosTeta = 1. - onecost , sinTeta = sqrt (sint2);
|
||||
G4double Phi = twopi * G4UniformRand();
|
||||
G4double dirx = sinTeta*cos(Phi), diry = sinTeta*sin(Phi), dirz = cosTeta;
|
||||
|
||||
//
|
||||
// update G4VParticleChange for the scattered gamma
|
||||
//
|
||||
|
||||
G4ThreeVector GammaDirection1 ( dirx,diry,dirz );
|
||||
GammaDirection1.rotateUz(GammaDirection0);
|
||||
aParticleChange.ProposeMomentumDirection( GammaDirection1 );
|
||||
G4double GammaEnergy1 = epsilon*GammaEnergy0;
|
||||
G4double localEnergyDeposit = 0.;
|
||||
|
||||
if (GammaEnergy1 > fminimalEnergy)
|
||||
{
|
||||
aParticleChange.ProposeEnergy( GammaEnergy1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
localEnergyDeposit += GammaEnergy1;
|
||||
aParticleChange.ProposeEnergy(0.) ;
|
||||
aParticleChange.ProposeTrackStatus(fStopAndKill);
|
||||
}
|
||||
|
||||
//
|
||||
// kinematic of the scattered electron
|
||||
//
|
||||
|
||||
G4double ElecKineEnergy = GammaEnergy0 - GammaEnergy1;
|
||||
|
||||
if (ElecKineEnergy > fminimalEnergy)
|
||||
{
|
||||
G4double ElecMomentum = sqrt(ElecKineEnergy*
|
||||
(ElecKineEnergy+2.*electron_mass_c2));
|
||||
G4ThreeVector ElecDirection (
|
||||
(GammaEnergy0*GammaDirection0 - GammaEnergy1*GammaDirection1)
|
||||
*(1./ElecMomentum) );
|
||||
|
||||
// create G4DynamicParticle object for the electron.
|
||||
G4DynamicParticle* aElectron= new G4DynamicParticle(
|
||||
G4Electron::Electron(),ElecDirection,ElecKineEnergy);
|
||||
|
||||
aParticleChange.SetNumberOfSecondaries(1);
|
||||
aParticleChange.AddSecondary( aElectron );
|
||||
}
|
||||
else
|
||||
{
|
||||
aParticleChange.SetNumberOfSecondaries(0);
|
||||
localEnergyDeposit += ElecKineEnergy;
|
||||
}
|
||||
aParticleChange.ProposeLocalEnergyDeposit (localEnergyDeposit);
|
||||
|
||||
// Reset NbOfInteractionLengthLeft and return aParticleChange
|
||||
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4ComptonScattering52::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 G4ComptonScattering52::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 G4ComptonScattering52::PrintInfoDefinition()
|
||||
{
|
||||
G4String comments = "Total cross sections from a parametrisation. ";
|
||||
comments += "Good description from 10 KeV to (100/Z) GeV. \n";
|
||||
comments += " Scattered gamma energy according Klein-Nishina.";
|
||||
|
||||
G4cout << G4endl << GetProcessName() << ": " << comments
|
||||
<< "\n PhysicsTables from "
|
||||
<< G4BestUnit(LowestEnergyLimit,"Energy")
|
||||
<< " to " << G4BestUnit(HighestEnergyLimit,"Energy")
|
||||
<< " in " << NumbBinTable << " bins. \n";
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -20,10 +20,10 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4GammaConversion.cc,v 1.24 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// $Id: G4GammaConversion.cc,v 1.23 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
//
|
||||
//
|
||||
//------------------ G4GammaConversion physics process -------------------------
|
||||
// by Michel Maire, 24 May 1996
|
||||
//
|
||||
@@ -56,528 +56,59 @@
|
||||
// 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)
|
||||
// 19-04-05 Migrate to model interface and inherit from G4VEmProcess (V.Ivanchenko)
|
||||
// 04-05-05, Make class to be default (V.Ivanchenko)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "G4GammaConversion.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4BetheHeitlerModel.hh"
|
||||
#include "G4Electron.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
G4GammaConversion::G4GammaConversion(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)
|
||||
{}
|
||||
G4ProcessType type):G4VEmProcess (processName, type),
|
||||
isInitialised(false)
|
||||
{
|
||||
SetLambdaBinning(100);
|
||||
SetMinKinEnergy(2.0*electron_mass_c2);
|
||||
SetMaxKinEnergy(100.0*GeV);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// destructor
|
||||
|
||||
G4GammaConversion::~G4GammaConversion()
|
||||
{
|
||||
if (theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy();
|
||||
delete theCrossSectionTable;
|
||||
}
|
||||
{}
|
||||
|
||||
if (theMeanFreePathTable) {
|
||||
theMeanFreePathTable->clearAndDestroy();
|
||||
delete theMeanFreePathTable;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4GammaConversion::InitialiseProcess(const G4ParticleDefinition*)
|
||||
{
|
||||
if(!isInitialised) {
|
||||
isInitialised = true;
|
||||
// SetVerboseLevel(1);
|
||||
SetBuildTableFlag(true);
|
||||
SetSecondaryParticle(G4Electron::Electron());
|
||||
G4double emin = max(MinKinEnergy(), 2.0*electron_mass_c2);
|
||||
SetMinKinEnergy(emin);
|
||||
G4double emax = MaxKinEnergy();
|
||||
G4VEmModel* model = new G4BetheHeitlerModel();
|
||||
model->SetLowEnergyLimit(emin);
|
||||
model->SetHighEnergyLimit(emax);
|
||||
AddEmModel(1, model);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4GammaConversion::IsApplicable( const G4ParticleDefinition& particle)
|
||||
void G4GammaConversion::PrintInfo()
|
||||
{
|
||||
return ( &particle == G4Gamma::Gamma() );
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
void G4GammaConversion::SetPhysicsTableBining(
|
||||
G4double lowE, G4double highE, G4int nBins)
|
||||
{
|
||||
LowestEnergyLimit = lowE; HighestEnergyLimit = highE; NumbBinTable = nBins;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4GammaConversion::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 G4GammaConversion::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 G4GammaConversion::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 G4GammaConversion::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 G4GammaConversion::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* G4GammaConversion::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 (RandBit::shootBit())
|
||||
{
|
||||
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* G4GammaConversion::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 G4GammaConversion::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 G4GammaConversion::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 G4GammaConversion::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 << " Total cross sections has a good parametrisation"
|
||||
<< " from 1.5 MeV to 100 GeV for all Z;"
|
||||
<< "\n sampling secondary e+e- according to the Bethe-Heitler model"
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -0,0 +1,584 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4GammaConversion52.cc,v 1.1 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//------------------ 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)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#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 (RandBit::shootBit())
|
||||
{
|
||||
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";
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -21,8 +21,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4InitXscPAI.cc,v 1.7 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4InitXscPAI.cc,v 1.8 2005/05/03 08:07:41 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//
|
||||
// G4InitXscPAI.cc -- class implementation file
|
||||
@@ -208,7 +208,7 @@ void G4InitXscPAI::Normalisation()
|
||||
energy2 = (*(*fMatSandiaMatrix)[0])[0] +
|
||||
( (*(*fMatSandiaMatrix)[0])[0] - (*(*fMatSandiaMatrix)[0])[0] )*i/100.;
|
||||
shift = RutherfordIntegral(0,energy1,energy2);
|
||||
if( shift >= fabs(delta) ) break;
|
||||
if( shift >= std::abs(delta) ) break;
|
||||
}
|
||||
(*(*fMatSandiaMatrix)[0])[0] = energy2;
|
||||
cof -= shift;
|
||||
@@ -357,12 +357,12 @@ G4double G4InitXscPAI::RePartDielectricConst(G4double enb)
|
||||
a3 = (*(*fMatSandiaMatrix)[i])[3];
|
||||
a4 = (*(*fMatSandiaMatrix)[i])[4];
|
||||
|
||||
if( fabs(x0-x1) < 0.5*(x0+x1)*fDelta )
|
||||
if( std::abs(x0-x1) < 0.5*(x0+x1)*fDelta )
|
||||
{
|
||||
if(x0 >= x1) x0 = x1*(1+fDelta);
|
||||
else x0 = x1*(1-fDelta);
|
||||
}
|
||||
if( fabs(x0-x2) < 0.5*(x0+x2)*fDelta )
|
||||
if( std::abs(x0-x2) < 0.5*(x0+x2)*fDelta )
|
||||
{
|
||||
if(x0 >= x2) x0 = x2*(1+fDelta);
|
||||
else x0 = x2*(1-fDelta);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4IonFluctuations.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4KleinNishinaCompton.cc,v 1.5 2005/04/18 17:31:38 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4KleinNishinaCompton
|
||||
//
|
||||
// Author: Vladimir Ivanchenko on base of Michel Maire code
|
||||
//
|
||||
// Creation date: 15.03.2005
|
||||
//
|
||||
// Modifications:
|
||||
// 18-04-05 Use G4ParticleChangeForGamma (V.Ivantchenko)
|
||||
//
|
||||
// Class Description:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#include "G4KleinNishinaCompton.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4DataVector.hh"
|
||||
#include "G4ParticleChangeForGamma.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4KleinNishinaCompton::G4KleinNishinaCompton(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam)
|
||||
{
|
||||
theGamma = G4Gamma::Gamma();
|
||||
theElectron = G4Electron::Electron();
|
||||
lowestGammaEnergy = 1.0*eV;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4KleinNishinaCompton::~G4KleinNishinaCompton()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4KleinNishinaCompton::Initialise(const G4ParticleDefinition*,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForGamma();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4KleinNishinaCompton::ComputeCrossSectionPerAtom(
|
||||
const G4ParticleDefinition*,
|
||||
G4double GammaEnergy,
|
||||
G4double Z, G4double,
|
||||
G4double, G4double)
|
||||
{
|
||||
G4double CrossSection = 0.0 ;
|
||||
if ( Z < 0.9999 ) return CrossSection;
|
||||
if ( GammaEnergy < 0.1*keV ) return CrossSection;
|
||||
if ( GammaEnergy > (100.*GeV/Z) ) return CrossSection;
|
||||
|
||||
static const G4double a = 20.0 , b = 230.0 , c = 440.0;
|
||||
|
||||
static const G4double
|
||||
d1= 2.7965e-1*barn, d2=-1.8300e-1*barn, d3= 6.7527 *barn, d4=-1.9798e+1*barn,
|
||||
e1= 1.9756e-5*barn, e2=-1.0205e-2*barn, e3=-7.3913e-2*barn, e4= 2.7079e-2*barn,
|
||||
f1=-3.9178e-7*barn, f2= 6.8241e-5*barn, f3= 6.0480e-5*barn, f4= 3.0274e-4*barn;
|
||||
|
||||
G4double p1Z = Z*(d1 + e1*Z + f1*Z*Z), p2Z = Z*(d2 + e2*Z + f2*Z*Z),
|
||||
p3Z = Z*(d3 + e3*Z + f3*Z*Z), p4Z = Z*(d4 + e4*Z + f4*Z*Z);
|
||||
|
||||
G4double T0 = 15.0*keV;
|
||||
if (Z < 1.5) T0 = 40.0*keV;
|
||||
|
||||
G4double X = max(GammaEnergy, T0) / electron_mass_c2;
|
||||
CrossSection = p1Z*std::log(1.+2.*X)/X
|
||||
+ (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
|
||||
|
||||
// modification for low energy. (special case for Hydrogen)
|
||||
if (GammaEnergy < T0) {
|
||||
G4double dT0 = 1.*keV;
|
||||
X = (T0+dT0) / electron_mass_c2 ;
|
||||
G4double sigma = p1Z*log(1.+2*X)/X
|
||||
+ (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
|
||||
G4double c1 = -T0*(sigma-CrossSection)/(CrossSection*dT0);
|
||||
G4double c2 = 0.150;
|
||||
if (Z > 1.5) c2 = 0.375-0.0556*log(Z);
|
||||
G4double y = log(GammaEnergy/T0);
|
||||
CrossSection *= exp(-y*(c1+c2*y));
|
||||
}
|
||||
// G4cout << "e= " << GammaEnergy << " Z= " << Z << " cross= " << CrossSection << G4endl;
|
||||
return CrossSection;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
std::vector<G4DynamicParticle*>* G4KleinNishinaCompton::SampleSecondaries(
|
||||
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
|
||||
// (Nuc Phys 20(1960),15).
|
||||
// Note : Effects due to binding of atomic electrons are negliged.
|
||||
|
||||
G4double gamEnergy0 = aDynamicGamma->GetKineticEnergy();
|
||||
G4double E0_m = gamEnergy0 / electron_mass_c2 ;
|
||||
|
||||
G4ThreeVector gamDirection0 = aDynamicGamma->GetMomentumDirection();
|
||||
|
||||
//
|
||||
// sample the energy rate of the scattered gamma
|
||||
//
|
||||
|
||||
G4double epsilon, epsilonsq, onecost, sint2, greject ;
|
||||
|
||||
G4double epsilon0 = 1./(1. + 2.*E0_m);
|
||||
G4double epsilon0sq = epsilon0*epsilon0;
|
||||
G4double alpha1 = - log(epsilon0);
|
||||
G4double alpha2 = 0.5*(1.- epsilon0sq);
|
||||
|
||||
do {
|
||||
if ( alpha1/(alpha1+alpha2) > G4UniformRand() ) {
|
||||
epsilon = exp(-alpha1*G4UniformRand()); // epsilon0**r
|
||||
epsilonsq = epsilon*epsilon;
|
||||
|
||||
} else {
|
||||
epsilonsq = epsilon0sq + (1.- epsilon0sq)*G4UniformRand();
|
||||
epsilon = sqrt(epsilonsq);
|
||||
};
|
||||
|
||||
onecost = (1.- epsilon)/(epsilon*E0_m);
|
||||
sint2 = onecost*(2.-onecost);
|
||||
greject = 1. - epsilon*sint2/(1.+ epsilonsq);
|
||||
|
||||
} while (greject < G4UniformRand());
|
||||
|
||||
//
|
||||
// scattered gamma angles. ( Z - axis along the parent gamma)
|
||||
//
|
||||
|
||||
G4double cosTeta = 1. - onecost;
|
||||
G4double sinTeta = sqrt (sint2);
|
||||
G4double Phi = twopi * G4UniformRand();
|
||||
G4double dirx = sinTeta*cos(Phi), diry = sinTeta*sin(Phi), dirz = cosTeta;
|
||||
|
||||
//
|
||||
// update G4VParticleChange for the scattered gamma
|
||||
//
|
||||
|
||||
G4ThreeVector gamDirection1 ( dirx,diry,dirz );
|
||||
gamDirection1.rotateUz(gamDirection0);
|
||||
G4double gamEnergy1 = epsilon*gamEnergy0;
|
||||
fParticleChange->SetProposedKineticEnergy(gamEnergy1);
|
||||
if(gamEnergy1 > lowestGammaEnergy) {
|
||||
fParticleChange->ProposeMomentumDirection(gamDirection1);
|
||||
} else {
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
gamEnergy1 += fParticleChange->GetLocalEnergyDeposit();
|
||||
fParticleChange->ProposeLocalEnergyDeposit(gamEnergy1);
|
||||
}
|
||||
|
||||
std::vector<G4DynamicParticle*>* fvect = new std::vector<G4DynamicParticle*>;
|
||||
|
||||
//
|
||||
// kinematic of the scattered electron
|
||||
//
|
||||
|
||||
G4double eKinEnergy = gamEnergy0 - gamEnergy1;
|
||||
|
||||
if(eKinEnergy > DBL_MIN) {
|
||||
G4ThreeVector eDirection = gamEnergy0*gamDirection0 - gamEnergy1*gamDirection1;
|
||||
eDirection = eDirection.unit();
|
||||
|
||||
// create G4DynamicParticle object for the electron.
|
||||
G4DynamicParticle* dp = new G4DynamicParticle(theElectron,eDirection,eKinEnergy);
|
||||
fvect->push_back(dp);
|
||||
}
|
||||
return fvect;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4MollerBhabhaModel.cc,v 1.15 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4MollerBhabhaModel.cc,v 1.20 2005/04/12 18:12:41 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -41,6 +41,7 @@
|
||||
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
|
||||
// 27-01-03 Make models region aware (V.Ivanchenko)
|
||||
// 13-02-03 Add name (V.Ivanchenko)
|
||||
// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
//
|
||||
// Class Description:
|
||||
@@ -56,6 +57,7 @@
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Positron.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4ParticleChangeForLoss.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -65,8 +67,6 @@ G4MollerBhabhaModel::G4MollerBhabhaModel(const G4ParticleDefinition* p,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam),
|
||||
particle(0),
|
||||
highKinEnergy(100.*TeV),
|
||||
lowKinEnergy(0.1*keV),
|
||||
twoln10(2.0*log(10.0)),
|
||||
lowLimit(0.2*keV),
|
||||
isElectron(true)
|
||||
@@ -90,20 +90,6 @@ void G4MollerBhabhaModel::SetParticle(const G4ParticleDefinition* p)
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4MollerBhabhaModel::HighEnergyLimit(const G4ParticleDefinition*)
|
||||
{
|
||||
return highKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4MollerBhabhaModel::LowEnergyLimit(const G4ParticleDefinition*)
|
||||
{
|
||||
return lowKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4MollerBhabhaModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple* couple)
|
||||
{
|
||||
@@ -112,29 +98,27 @@ G4double G4MollerBhabhaModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4bool G4MollerBhabhaModel::IsInCharge(const G4ParticleDefinition* p)
|
||||
{
|
||||
return (p == theElectron || p == G4Positron::Positron());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4MollerBhabhaModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForLoss();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4MollerBhabhaModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
G4double G4MollerBhabhaModel::ComputeDEDXPerVolume(
|
||||
const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
{
|
||||
if(!particle) SetParticle(p);
|
||||
// calculate the dE/dx due to the ionization by Seltzer-Berger formula
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
|
||||
G4double electronDensity = material->GetElectronDensity();
|
||||
G4double Zeff = electronDensity/material->GetTotNbOfAtomsPerVolume();
|
||||
G4double th = 0.25*sqrt(Zeff)*keV;
|
||||
@@ -206,7 +190,8 @@ G4double G4MollerBhabhaModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4MollerBhabhaModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
G4double G4MollerBhabhaModel::CrossSectionPerVolume(
|
||||
const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
@@ -252,20 +237,21 @@ G4double G4MollerBhabhaModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
- b1*log(xmax/xmin);
|
||||
}
|
||||
|
||||
cross *= twopi_mc2_rcl2*(couple->GetMaterial()->GetElectronDensity())/kineticEnergy;
|
||||
cross *= twopi_mc2_rcl2*(material->GetElectronDensity())/kineticEnergy;
|
||||
}
|
||||
return cross;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticle* G4MollerBhabhaModel::SampleSecondary(
|
||||
std::vector<G4DynamicParticle*>* G4MollerBhabhaModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
G4double tmax = min(maxEnergy, MaxSecondaryEnergy(dp));
|
||||
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
|
||||
G4double tmax = std::min(maxEnergy, MaxSecondaryKinEnergy(dp));
|
||||
if(tmin > tmax) tmin = tmax;
|
||||
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
@@ -278,7 +264,7 @@ G4DynamicParticle* G4MollerBhabhaModel::SampleSecondary(
|
||||
G4double beta2 = 1.0 - 1.0/gamma2;
|
||||
G4double x, z, q, grej;
|
||||
|
||||
G4ThreeVector momentum = dp->GetMomentumDirection();
|
||||
G4ThreeVector direction = dp->GetMomentumDirection();
|
||||
|
||||
//Moller (e-e-) scattering
|
||||
if (isElectron) {
|
||||
@@ -357,25 +343,19 @@ G4DynamicParticle* G4MollerBhabhaModel::SampleSecondary(
|
||||
G4double phi = twopi * G4UniformRand() ;
|
||||
|
||||
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
|
||||
deltaDirection.rotateUz(momentum);
|
||||
deltaDirection.rotateUz(direction);
|
||||
|
||||
// primary change
|
||||
kineticEnergy -= deltaKinEnergy;
|
||||
G4ThreeVector dir = totalMomentum*direction - deltaMomentum*deltaDirection;
|
||||
direction = dir.unit();
|
||||
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
|
||||
fParticleChange->SetProposedMomentumDirection(direction);
|
||||
|
||||
// create G4DynamicParticle object for delta ray
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,deltaDirection,deltaKinEnergy);
|
||||
return delta;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
vector<G4DynamicParticle*>* G4MollerBhabhaModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
|
||||
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
|
||||
G4DynamicParticle* delta = new G4DynamicParticle(theElectron,
|
||||
deltaDirection,deltaKinEnergy);
|
||||
vdp->push_back(delta);
|
||||
|
||||
return vdp;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4MscModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4MscModel.cc,v 1.8 2005/05/12 11:06:43 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -68,6 +68,7 @@
|
||||
//
|
||||
// 03-11-04 precision problem for very high energy ions and small stepsize
|
||||
// solved in SampleCosineTheta (L.Urban).
|
||||
// 15-04-05 optimize internal interface - add SampleSecondaries method (V.Ivanchenko)
|
||||
//
|
||||
|
||||
// Class Description:
|
||||
@@ -87,14 +88,17 @@
|
||||
#include "G4Electron.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4PhysicsTable.hh"
|
||||
#include "G4ParticleChangeForMSC.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "G4Navigator.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4MscModel::G4MscModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
|
||||
G4double& m_FactPar, G4double& m_factail,
|
||||
G4bool& m_samplez, const G4String& nam)
|
||||
G4double& m_FactPar, G4double& m_factail,
|
||||
G4bool& m_samplez, const G4String& nam)
|
||||
: G4VEmModel(nam),
|
||||
taubig(8.0),
|
||||
tausmall(1.e-20),
|
||||
@@ -103,10 +107,9 @@ G4MscModel::G4MscModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
|
||||
NuclCorrPar (m_NuclCorrPar),
|
||||
FactPar(m_FactPar),
|
||||
factail(m_factail),
|
||||
samplez(m_samplez)
|
||||
samplez(m_samplez),
|
||||
isInitialized(false)
|
||||
{
|
||||
highKinEnergy = 100.0*TeV;
|
||||
lowKinEnergy = 0.1*keV;
|
||||
stepmin = 1.e-6*mm;
|
||||
currentRange = 0. ;
|
||||
}
|
||||
@@ -116,18 +119,12 @@ G4MscModel::G4MscModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
|
||||
G4MscModel::~G4MscModel()
|
||||
{}
|
||||
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4bool G4MscModel::IsInCharge(const G4ParticleDefinition* p)
|
||||
{
|
||||
return (p->GetPDGCharge() != 0.0);
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4MscModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(isInitialized) return;
|
||||
// set values of some data members
|
||||
sigmafactor = twopi*classic_electr_radius*classic_electr_radius;
|
||||
particle = p;
|
||||
@@ -135,17 +132,24 @@ void G4MscModel::Initialise(const G4ParticleDefinition* p,
|
||||
charge = particle->GetPDGCharge()/eplus;
|
||||
b = 1. ;
|
||||
xsi = 3.00 ;
|
||||
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForMSC*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForMSC();
|
||||
|
||||
navigator = G4TransportationManager::GetTransportationManager()
|
||||
->GetNavigatorForTracking();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4MscModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double,
|
||||
G4double)
|
||||
G4double G4MscModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
const G4ElementVector* theElementVector = material->GetElementVector();
|
||||
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
|
||||
G4int NumberOfElements = material->GetNumberOfElements();
|
||||
@@ -518,6 +522,60 @@ G4double G4MscModel::TrueStepLength(G4double geomStepLength)
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
std::vector<G4DynamicParticle*>* G4MscModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle* dynParticle,
|
||||
G4double truestep,
|
||||
G4double safety)
|
||||
{
|
||||
G4double kineticEnergy = dynParticle->GetKineticEnergy();
|
||||
if(kineticEnergy <= 0.0) return 0;
|
||||
|
||||
G4double cth = SampleCosineTheta(truestep,kineticEnergy);
|
||||
G4double sth = sqrt((1.0 - cth)*(1.0 + cth));
|
||||
G4double phi = twopi*G4UniformRand();
|
||||
G4double dirx = sth*cos(phi);
|
||||
G4double diry = sth*sin(phi);
|
||||
|
||||
G4ThreeVector oldDirection = dynParticle->GetMomentumDirection();
|
||||
G4ThreeVector newDirection(dirx,diry,cth);
|
||||
newDirection.rotateUz(oldDirection);
|
||||
fParticleChange->ProposeMomentumDirection(newDirection);
|
||||
|
||||
/*
|
||||
const G4ParticleDefinition* pd = dynParticle->GetDefinition();
|
||||
G4cout << "G4MscModel: Sample secondary; E(MeV)= " << kineticEnergy/MeV
|
||||
<< " MeV; step(mm)= " << truestep/mm
|
||||
<< ", safety(mm)= " << safety/mm << " " << pd->GetParticleName()
|
||||
<< G4endl;
|
||||
*/
|
||||
|
||||
if (latDisplasment && safety > 0.0) {
|
||||
|
||||
G4double r = SampleDisplacement();
|
||||
if (r > safety) r = safety;
|
||||
|
||||
// sample direction of lateral displacement
|
||||
G4double phi = twopi*G4UniformRand();
|
||||
G4double dirx = std::cos(phi);
|
||||
G4double diry = std::sin(phi);
|
||||
|
||||
G4ThreeVector newPosition(dirx,diry,0.0);
|
||||
newPosition.rotateUz(oldDirection);
|
||||
|
||||
// compute new endpoint of the Step
|
||||
newPosition *= r;
|
||||
newPosition += *(fParticleChange->GetProposedPosition());
|
||||
|
||||
navigator->LocateGlobalPointWithinVolume(newPosition);
|
||||
|
||||
fParticleChange->ProposePosition(newPosition);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4MscModel::SampleCosineTheta(G4double trueStepLength, G4double KineticEnergy)
|
||||
{
|
||||
G4double cth = 1. ;
|
||||
@@ -545,7 +603,7 @@ G4double G4MscModel::SampleCosineTheta(G4double trueStepLength, G4double Kinetic
|
||||
// ( Highland formula: Particle Physics Booklet, July 2002, eq. 26.10)
|
||||
// here : theta0 = 13.6*MeV*Q*(t/X0)**0.555/(beta*cp)
|
||||
const G4double c_highland = 13.6*MeV, corr_highland=0.555 ;
|
||||
G4double Q = fabs(charge) ;
|
||||
G4double Q = std::abs(charge) ;
|
||||
G4double xx0 = trueStepLength/currentRadLength;
|
||||
G4double betacp = sqrt(currentKinEnergy*(currentKinEnergy+2.*mass)*
|
||||
KineticEnergy*(KineticEnergy+2.*mass)/
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4MultipleScattering.cc,v 1.23 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4MultipleScattering.cc,v 1.27 2005/04/15 14:41:13 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// 16/05/01 value of cparm changed , L.Urban
|
||||
@@ -63,7 +63,8 @@
|
||||
// 23-04-04 value of data member dtrl changed from 0.15 to 0.05 (L.Urban)
|
||||
// 17-08-04 name of facxsi changed to factail (L.Urban)
|
||||
// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko)
|
||||
//
|
||||
// 07-02-05 correction in order to have a working Setsamplez function (L.Urban)
|
||||
// 15-04-05 optimize internal interface (V.Ivanchenko)
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -77,16 +78,19 @@
|
||||
using namespace std;
|
||||
|
||||
G4MultipleScattering::G4MultipleScattering(const G4String& processName)
|
||||
: G4VMultipleScattering(processName),
|
||||
totBins(120),
|
||||
facrange(0.199),
|
||||
dtrl(0.05),
|
||||
NuclCorrPar (0.0615),
|
||||
FactPar(0.40),
|
||||
factail(1.0),
|
||||
cf(1.001),
|
||||
stepnolastmsc(-1000000),
|
||||
nsmallstep(5)
|
||||
: G4VMultipleScattering(processName),
|
||||
totBins(120),
|
||||
facrange(0.199),
|
||||
dtrl(0.05),
|
||||
NuclCorrPar (0.0615),
|
||||
FactPar(0.40),
|
||||
factail(1.0),
|
||||
cf(1.001),
|
||||
stepnolastmsc(-1000000),
|
||||
nsmallstep(5),
|
||||
samplez(true),
|
||||
boundary(true),
|
||||
isInitialized(false)
|
||||
{
|
||||
lowKineticEnergy = 0.1*keV;
|
||||
highKineticEnergy= 100.*TeV;
|
||||
@@ -108,22 +112,23 @@ G4MultipleScattering::~G4MultipleScattering()
|
||||
|
||||
void G4MultipleScattering::InitialiseProcess(const G4ParticleDefinition* particle)
|
||||
{
|
||||
if(isInitialized) return;
|
||||
|
||||
if (particle->GetParticleType() == "nucleus") {
|
||||
SetBoundary(false);
|
||||
boundary = false;
|
||||
SetLateralDisplasmentFlag(false);
|
||||
SetBuildLambdaTable(false);
|
||||
Setsamplez(false) ;
|
||||
} else {
|
||||
SetBoundary(true);
|
||||
SetLateralDisplasmentFlag(true);
|
||||
SetBuildLambdaTable(true);
|
||||
Setsamplez(true) ;
|
||||
}
|
||||
G4MscModel* em = new G4MscModel(dtrl,NuclCorrPar,FactPar,factail,samplez);
|
||||
em->SetLateralDisplasmentFlag(LateralDisplasmentFlag());
|
||||
em->SetLowEnergyLimit(lowKineticEnergy);
|
||||
em->SetHighEnergyLimit(highKineticEnergy);
|
||||
AddEmModel(1, em);
|
||||
boundary = BoundaryAlgorithmFlag();
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -169,9 +174,8 @@ G4double G4MultipleScattering::TruePathLengthLimit(const G4Track& track,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4MultipleScattering::PrintInfoDefinition()
|
||||
void G4MultipleScattering::PrintInfo()
|
||||
{
|
||||
G4VMultipleScattering::PrintInfoDefinition();
|
||||
if(boundary) {
|
||||
G4cout << " Boundary algorithm is active with facrange= "
|
||||
<< facrange
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4MultipleScattering52.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4MultipleScattering52.cc,v 1.3 2005/05/03 08:07:41 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// 16/05/01 value of cparm changed , L.Urban
|
||||
@@ -723,7 +723,7 @@ G4VParticleChange* G4MultipleScattering52::PostStepDoIt(
|
||||
// (Particle Physics Booklet, July 2002, eq. 26.10)
|
||||
if(Mass > electron_mass_c2) // + other conditions (beta, x/X0,...?)
|
||||
{
|
||||
G4double Q = fabs(aParticle->GetDefinition()->GetPDGCharge()) ;
|
||||
G4double Q = std::abs(aParticle->GetDefinition()->GetPDGCharge()) ;
|
||||
G4double X0 = trackData.GetMaterialCutsCouple()->
|
||||
GetMaterial()->GetRadlen() ;
|
||||
G4double xx0 = truestep/X0 ;
|
||||
@@ -833,7 +833,7 @@ G4VParticleChange* G4MultipleScattering52::PostStepDoIt(
|
||||
if(pr)
|
||||
{
|
||||
const G4double prlim = 0.10 ;
|
||||
if((fabs((xmeanth-xmean2)/(xmean1-xmean2)-prob)/prob > prlim) ||
|
||||
if((std::abs((xmeanth-xmean2)/(xmean1-xmean2)-prob)/prob > prlim) ||
|
||||
((xmeanth-xmean2)/(xmean1-xmean2) > 1.) ||
|
||||
((xmeanth-xmean2)/(xmean1-xmean2) < 0.) )
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
//
|
||||
// 17.08.04 V.Grichine, bug fixed for Tkin<=0 in SampleSecondary
|
||||
// 16.08.04 V.Grichine, bug fixed in massRatio for DEDX, CrossSection, SampleSecondary
|
||||
// 08.04.05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
|
||||
#include "G4Region.hh"
|
||||
@@ -50,6 +51,7 @@
|
||||
#include "G4Material.hh"
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4ParticleChangeForLoss.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -57,8 +59,6 @@ using namespace std;
|
||||
|
||||
G4PAIModel::G4PAIModel(const G4ParticleDefinition* p, const G4String& nam)
|
||||
: G4VEmModel(nam),G4VEmFluctuationModel(nam),
|
||||
fLowestKineticEnergy(10.0*keV),
|
||||
fHighestKineticEnergy(100.*TeV),
|
||||
fTotBin(200),
|
||||
fMeanNumber(20),
|
||||
fParticle(0),
|
||||
@@ -69,6 +69,8 @@ G4PAIModel::G4PAIModel(const G4ParticleDefinition* p, const G4String& nam)
|
||||
fTaulim(8.4146e-3)
|
||||
{
|
||||
if(p) SetParticle(p);
|
||||
fLowestKineticEnergy = LowEnergyLimit();
|
||||
fHighestKineticEnergy = HighEnergyLimit();
|
||||
fProtonEnergyVector = new G4PhysicsLogVector(fLowestKineticEnergy,
|
||||
fHighestKineticEnergy,
|
||||
fTotBin);
|
||||
@@ -118,45 +120,18 @@ void G4PAIModel::SetParticle(const G4ParticleDefinition* p)
|
||||
fQc = fMass/fRatio;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIModel::HighEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return fHighKinEnergy;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIModel::LowEnergyLimit( const G4ParticleDefinition* p )
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return fLowKinEnergy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIModel::MinEnergyCut( const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple*)
|
||||
{
|
||||
return 0.*eV; // any positive cut
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4bool G4PAIModel::IsInCharge( const G4ParticleDefinition* p )
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return (p->GetPDGCharge() != 0.0 );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void G4PAIModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForLoss();
|
||||
|
||||
const G4ProductionCutsTable* theCoupleTable =
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
|
||||
@@ -434,7 +409,7 @@ G4PAIModel::GetdNdxCut( G4int iPlace, G4double transferCut)
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( std::abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dNdxCut<<G4endl;
|
||||
@@ -476,7 +451,7 @@ G4PAIModel::GetdEdxCut( G4int iPlace, G4double transferCut)
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( std::abs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dEdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dEdxCut<<G4endl;
|
||||
@@ -568,11 +543,11 @@ G4double G4PAIModel::CrossSection( const G4MaterialCutsCouple* matCC,
|
||||
// It is analog of PostStepDoIt in terms of secondary electron.
|
||||
//
|
||||
|
||||
G4DynamicParticle*
|
||||
G4PAIModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
std::vector<G4DynamicParticle*>*
|
||||
G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple* matCC,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
size_t jMat;
|
||||
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
|
||||
@@ -584,12 +559,12 @@ G4PAIModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
fPAItransferTable = fPAIxscBank[jMat];
|
||||
fdNdxCutVector = fdNdxCutTable[jMat];
|
||||
|
||||
G4double tmax = min(MaxSecondaryEnergy(dp), maxEnergy);
|
||||
G4double tmax = min(MaxSecondaryKinEnergy(dp), maxEnergy);
|
||||
if( tmin >= tmax )
|
||||
{
|
||||
G4cout<<"G4PAIModel::SampleSecondary: tmin >= tmax "<<G4endl;
|
||||
}
|
||||
G4ThreeVector momentum = dp->GetMomentumDirection();
|
||||
G4ThreeVector direction= dp->GetMomentumDirection();
|
||||
G4double particleMass = dp->GetMass();
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
|
||||
@@ -606,32 +581,46 @@ G4PAIModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
deltaTkin = 10*eV;
|
||||
G4cout<<"Set G4PAIModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
|
||||
}
|
||||
if(deltaTkin > kineticEnergy) deltaTkin = kineticEnergy;
|
||||
if(deltaTkin > kineticEnergy &&
|
||||
particleMass != electron_mass_c2) deltaTkin = kineticEnergy;
|
||||
if (deltaTkin > 0.5*kineticEnergy &&
|
||||
dp->GetDefinition()->GetParticleName() == "e-") deltaTkin = 0.5*kineticEnergy;
|
||||
|
||||
G4double deltaTotalMomentum = sqrt(deltaTkin*(deltaTkin + 2. * electron_mass_c2 ));
|
||||
G4double totalMomentum = sqrt(pSquare);
|
||||
G4double costheta = deltaTkin*(totalEnergy + electron_mass_c2)
|
||||
/(deltaTotalMomentum * totalMomentum);
|
||||
if (costheta < 0.) costheta = 0.;
|
||||
if (costheta > +1.) costheta = +1.;
|
||||
if( costheta >= 0.99999 ) costheta = 0.99999;
|
||||
G4double sintheta, sin2 = 1. - costheta*costheta;
|
||||
|
||||
// direction of the delta electron
|
||||
if( sin2 <= 0.) sintheta = 0.;
|
||||
else sintheta = sqrt(sin2);
|
||||
|
||||
// direction of the delta electron
|
||||
|
||||
G4double phi = twopi*G4UniformRand();
|
||||
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
|
||||
G4double phi = twopi*G4UniformRand();
|
||||
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
|
||||
|
||||
G4ThreeVector deltaDirection(dirx,diry,dirz);
|
||||
deltaDirection.rotateUz(momentum);
|
||||
deltaDirection.rotateUz(direction);
|
||||
deltaDirection.unit();
|
||||
|
||||
// create G4DynamicParticle object for e- delta ray
|
||||
|
||||
// primary change
|
||||
kineticEnergy -= deltaTkin;
|
||||
G4ThreeVector dir = totalMomentum*direction - deltaTotalMomentum*deltaDirection;
|
||||
direction = dir.unit();
|
||||
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
|
||||
fParticleChange->SetProposedMomentumDirection(direction);
|
||||
|
||||
// create G4DynamicParticle object for e- delta ray
|
||||
G4DynamicParticle* deltaRay = new G4DynamicParticle;
|
||||
deltaRay->SetDefinition(G4Electron::Electron());
|
||||
deltaRay->SetKineticEnergy( deltaTkin ); // !!! trick for last steps /2.0 ???
|
||||
deltaRay->SetMomentumDirection(deltaDirection);
|
||||
|
||||
return deltaRay;
|
||||
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
|
||||
vdp->push_back(deltaRay);
|
||||
return vdp;
|
||||
}
|
||||
|
||||
|
||||
@@ -751,22 +740,6 @@ G4PAIModel::GetEnergyTransfer( G4int iPlace, G4double position, G4int iTransfer
|
||||
return energyTransfer ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<G4DynamicParticle*>*
|
||||
G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle*,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
vector<G4DynamicParticle*>* vdp = 0;
|
||||
// vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
|
||||
// G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
|
||||
// vdp->push_back(delta);
|
||||
return vdp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIModel::SampleFluctuations( const G4Material* material,
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
//
|
||||
// 17.08.04 V.Grichine, bug fixed for Tkin<=0 in SampleSecondary
|
||||
// 16.08.04 V.Grichine, bug fixed in massRatio for DEDX, CrossSection, SampleSecondary
|
||||
// 11.04.05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
|
||||
#include "G4Region.hh"
|
||||
@@ -51,6 +52,7 @@
|
||||
#include "G4Material.hh"
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4ParticleChangeForLoss.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -135,39 +137,6 @@ void G4PAIPhotonModel::SetParticle(const G4ParticleDefinition* p)
|
||||
fQc = fMass/fRatio;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIPhotonModel::HighEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return fHighKinEnergy;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIPhotonModel::LowEnergyLimit( const G4ParticleDefinition* p )
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return fLowKinEnergy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIPhotonModel::MinEnergyCut( const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple*)
|
||||
{
|
||||
// return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
|
||||
return 0.0; // any positive cut
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4bool G4PAIPhotonModel::IsInCharge( const G4ParticleDefinition* p )
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return (p->GetPDGCharge() != 0.0 );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void G4PAIPhotonModel::Initialise(const G4ParticleDefinition* p,
|
||||
@@ -175,6 +144,11 @@ void G4PAIPhotonModel::Initialise(const G4ParticleDefinition* p,
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForLoss();
|
||||
|
||||
const G4ProductionCutsTable* theCoupleTable =
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
|
||||
@@ -498,7 +472,7 @@ G4PAIPhotonModel::GetdNdxCut( G4int iPlace, G4double transferCut)
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( std::abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dNdxCut<<G4endl;
|
||||
@@ -541,7 +515,7 @@ G4PAIPhotonModel::GetdNdxPhotonCut( G4int iPlace, G4double transferCut)
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( std::abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dNdxPhotonCut<<G4endl;
|
||||
@@ -585,7 +559,7 @@ G4PAIPhotonModel::GetdNdxPlasmonCut( G4int iPlace, G4double transferCut)
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( std::abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dNdxPlasmonCut<<G4endl;
|
||||
@@ -628,7 +602,7 @@ G4PAIPhotonModel::GetdEdxCut( G4int iPlace, G4double transferCut)
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( std::abs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dEdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dEdxCut<<G4endl;
|
||||
@@ -744,12 +718,13 @@ G4double G4PAIPhotonModel::CrossSection( const G4MaterialCutsCouple* matCC,
|
||||
// be returned as G4Dynamicparticle*.
|
||||
//
|
||||
|
||||
G4DynamicParticle*
|
||||
G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
std::vector<G4DynamicParticle*>*
|
||||
G4PAIPhotonModel::SampleSecondaries( 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 )
|
||||
{
|
||||
@@ -765,13 +740,13 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
fdNdxCutPhotonVector = fdNdxCutPhotonTable[jMat];
|
||||
fdNdxCutPlasmonVector = fdNdxCutPlasmonTable[jMat];
|
||||
|
||||
G4double tmax = min(MaxSecondaryEnergy(dp), maxEnergy);
|
||||
G4double tmax = min(MaxSecondaryKinEnergy(dp), maxEnergy);
|
||||
if( tmin >= tmax )
|
||||
{
|
||||
G4cout<<"G4PAIPhotonModel::SampleSecondary: tmin >= tmax "<<G4endl;
|
||||
}
|
||||
|
||||
G4ThreeVector momentum = dp->GetMomentumDirection();
|
||||
G4ThreeVector direction = dp->GetMomentumDirection();
|
||||
G4double particleMass = dp->GetMass();
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
G4double scaledTkin = kineticEnergy*proton_mass_c2/particleMass;
|
||||
@@ -823,7 +798,14 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
|
||||
|
||||
G4ThreeVector deltaDirection(dirx,diry,dirz);
|
||||
deltaDirection.rotateUz(momentum);
|
||||
deltaDirection.rotateUz(direction);
|
||||
|
||||
// primary change
|
||||
|
||||
kineticEnergy -= deltaTkin;
|
||||
G4ThreeVector dir = totalMomentum*direction - deltaTotalMomentum*deltaDirection;
|
||||
direction = dir.unit();
|
||||
fParticleChange->SetProposedMomentumDirection(direction);
|
||||
|
||||
// create G4DynamicParticle object for e- delta ray
|
||||
|
||||
@@ -831,8 +813,8 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
deltaRay->SetDefinition(G4Electron::Electron());
|
||||
deltaRay->SetKineticEnergy( deltaTkin );
|
||||
deltaRay->SetMomentumDirection(deltaDirection);
|
||||
vdp->push_back(deltaRay);
|
||||
|
||||
return deltaRay;
|
||||
}
|
||||
else // secondary 'Cherenkov' photon
|
||||
{
|
||||
@@ -866,7 +848,10 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
|
||||
|
||||
G4ThreeVector deltaDirection(dirx,diry,dirz);
|
||||
deltaDirection.rotateUz(momentum);
|
||||
deltaDirection.rotateUz(direction);
|
||||
|
||||
// primary change
|
||||
kineticEnergy -= deltaTkin;
|
||||
|
||||
// create G4DynamicParticle object for photon ray
|
||||
|
||||
@@ -875,8 +860,11 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
photonRay->SetKineticEnergy( deltaTkin );
|
||||
photonRay->SetMomentumDirection(deltaDirection);
|
||||
|
||||
return photonRay;
|
||||
vdp->push_back(photonRay);
|
||||
}
|
||||
|
||||
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
|
||||
return vdp;
|
||||
}
|
||||
|
||||
|
||||
@@ -991,21 +979,6 @@ G4PAIPhotonModel::GetEnergyTransfer( G4PhysicsTable* pTable, G4int iPlace,
|
||||
return energyTransfer ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<G4DynamicParticle*>*
|
||||
G4PAIPhotonModel::SampleSecondaries( const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
|
||||
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
|
||||
vdp->push_back(delta);
|
||||
return vdp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Works like AlongStepDoIt method of process family
|
||||
|
||||
@@ -1,848 +0,0 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// File name: G4PAIwithPhotons.cc
|
||||
//
|
||||
// Author: Vladimir.Grichine@cern.ch on base of Vladimir Ivanchenko code
|
||||
//
|
||||
// Creation date: 05.10.2003
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
|
||||
#include "G4Region.hh"
|
||||
#include "G4PhysicsLogVector.hh"
|
||||
#include "G4PhysicsFreeVector.hh"
|
||||
#include "G4PhysicsTable.hh"
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4MaterialTable.hh"
|
||||
#include "G4SandiaTable.hh"
|
||||
#include "G4PAIxSection.hh"
|
||||
|
||||
#include "G4PAIwithPhotons.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Poisson.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4Timer.hh"
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4PAIwithPhotons::G4PAIwithPhotons(const G4ParticleDefinition* p, const G4String& nam)
|
||||
: G4VEmModel(nam),G4VEmFluctuationModel(nam),
|
||||
fLowestKineticEnergy(10.0*keV),
|
||||
fHighestKineticEnergy(100.*TeV),
|
||||
fTotBin(200),
|
||||
fMeanNumber(20),
|
||||
fParticle(0),
|
||||
fHighKinEnergy(100.*TeV),
|
||||
fLowKinEnergy(2.0*MeV),
|
||||
fTwoln10(2.0*log(10.0)),
|
||||
fBg2lim(0.0169),
|
||||
fTaulim(8.4146e-3)
|
||||
{
|
||||
if(p) SetParticle(p);
|
||||
fProtonEnergyVector = new G4PhysicsLogVector(fLowestKineticEnergy,
|
||||
fHighestKineticEnergy,
|
||||
fTotBin);
|
||||
fInitXscPAI = 0;
|
||||
fPAItransferBank = 0;
|
||||
fPAIdEdxTable = 0;
|
||||
fdEdxVector = 0;
|
||||
fLambdaVector = 0;
|
||||
fdNdxCutVector = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4PAIwithPhotons::~G4PAIwithPhotons()
|
||||
{
|
||||
if(fProtonEnergyVector) delete fProtonEnergyVector;
|
||||
if(fInitXscPAI) delete fInitXscPAI;
|
||||
if(fdEdxVector) delete fdEdxVector ;
|
||||
if ( fLambdaVector) delete fLambdaVector;
|
||||
if ( fdNdxCutVector) delete fdNdxCutVector;
|
||||
if( fPAItransferBank )
|
||||
{
|
||||
fPAItransferBank->clearAndDestroy();
|
||||
delete fPAItransferBank ;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void G4PAIwithPhotons::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
fParticle = p;
|
||||
fMass = fParticle->GetPDGMass();
|
||||
fSpin = fParticle->GetPDGSpin();
|
||||
G4double q = fParticle->GetPDGCharge()/eplus;
|
||||
fChargeSquare = q*q;
|
||||
fLowKinEnergy *= fMass/proton_mass_c2;
|
||||
fRatio = electron_mass_c2/fMass;
|
||||
fQc = fMass/fRatio;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIwithPhotons::HighEnergyLimit(const G4ParticleDefinition* p)
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return fHighKinEnergy;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIwithPhotons::LowEnergyLimit( const G4ParticleDefinition* p )
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return fLowKinEnergy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIwithPhotons::MinEnergyCut( const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple* couple )
|
||||
{
|
||||
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4bool G4PAIwithPhotons::IsInCharge( const G4ParticleDefinition* p )
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
return (p->GetPDGCharge() != 0.0 );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void G4PAIwithPhotons::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(!fParticle) SetParticle(p);
|
||||
|
||||
const G4ProductionCutsTable* theCoupleTable =
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
G4Timer timer;
|
||||
for(size_t iReg = 0; iReg < fPAIRegionVector.size();++iReg) // region loop
|
||||
{
|
||||
const G4Region* curReg = fPAIRegionVector[iReg];
|
||||
|
||||
// (*fPAIRegionVector[iRegion])
|
||||
|
||||
vector<G4Material*>::const_iterator matIter = curReg->GetMaterialIterator();
|
||||
size_t jMat;
|
||||
size_t numOfMat = curReg->GetNumberOfMaterials();
|
||||
|
||||
|
||||
for(jMat = 0 ; jMat < numOfMat; ++jMat) // region material loop
|
||||
{
|
||||
const G4MaterialCutsCouple* matCouple = theCoupleTable->
|
||||
GetMaterialCutsCouple( *matIter, curReg->GetProductionCuts() );
|
||||
fMaterialCutsCoupleVector.push_back(matCouple);
|
||||
|
||||
fInitXscPAI = new G4InitXscPAI(matCouple);
|
||||
|
||||
timer.Start();
|
||||
|
||||
BuildPAIonisationTable();
|
||||
fPAIxscBank.push_back(fPAItransferBank);
|
||||
fPAIdEdxBank.push_back(fPAIdEdxTable);
|
||||
fdEdxTable.push_back(fdEdxVector);
|
||||
|
||||
BuildLambdaVector(matCouple);
|
||||
fdNdxCutTable.push_back(fdNdxCutVector);
|
||||
fLambdaTable.push_back(fLambdaVector);
|
||||
|
||||
timer.Stop();
|
||||
|
||||
G4cout<<"Initialisation for "<<matCouple->GetMaterial()->GetName()<<" = "
|
||||
<<timer.GetUserElapsed()<<" s " <<"("<<fParticle->GetParticleName()<<")"<<G4endl;
|
||||
matIter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Build tables for the ionization energy loss
|
||||
// the tables are built for MATERIALS
|
||||
// *********
|
||||
|
||||
void
|
||||
G4PAIwithPhotons::BuildPAIonisationTable()
|
||||
{
|
||||
G4double LowEdgeEnergy , ionloss ;
|
||||
G4double massRatio, tau, Tmax, Tmin, Tkin, deltaLow, gamma, bg2 ;
|
||||
/*
|
||||
if( fPAItransferBank )
|
||||
{
|
||||
fPAItransferBank->clearAndDestroy() ;
|
||||
delete fPAItransferBank ;
|
||||
}
|
||||
*/
|
||||
fPAItransferBank = new G4PhysicsTable(fTotBin);
|
||||
/*
|
||||
if( fPAIdEdxTable )
|
||||
{
|
||||
fPAIdEdxTable->clearAndDestroy() ;
|
||||
delete fPAIdEdxTable ;
|
||||
}
|
||||
*/
|
||||
fPAIdEdxTable = new G4PhysicsTable(fTotBin);
|
||||
|
||||
// if(fdEdxVector) delete fdEdxVector ;
|
||||
fdEdxVector = new G4PhysicsLogVector( fLowestKineticEnergy,
|
||||
fHighestKineticEnergy,
|
||||
fTotBin ) ;
|
||||
Tmin = fInitXscPAI->GetMatSandiaMatrix(0,0) ; // low energy Sandia interval
|
||||
deltaLow = 0.5*eV ;
|
||||
|
||||
for (G4int i = 0 ; i < fTotBin ; i++) //The loop for the kinetic energy
|
||||
{
|
||||
LowEdgeEnergy = fProtonEnergyVector->GetLowEdgeEnergy(i) ;
|
||||
tau = LowEdgeEnergy/proton_mass_c2 ;
|
||||
// if(tau < 0.01) tau = 0.01 ;
|
||||
gamma = tau +1. ;
|
||||
// G4cout<<"gamma = "<<gamma<<endl ;
|
||||
bg2 = tau*(tau + 2. ) ;
|
||||
massRatio = electron_mass_c2/proton_mass_c2 ;
|
||||
Tmax = 2.*electron_mass_c2*bg2/(1.+2.*gamma*massRatio+massRatio*massRatio) ;
|
||||
// G4cout<<"proton Tkin = "<<LowEdgeEnergy/MeV<<" MeV"
|
||||
// <<" Tmax = "<<Tmax/MeV<<" MeV"<<G4endl;
|
||||
// Tkin = DeltaCutInKineticEnergyNow ;
|
||||
|
||||
// if ( DeltaCutInKineticEnergyNow > Tmax) // was <
|
||||
{
|
||||
Tkin = Tmax ;
|
||||
}
|
||||
if ( Tkin < Tmin + deltaLow ) // low energy safety
|
||||
{
|
||||
Tkin = Tmin + deltaLow ;
|
||||
}
|
||||
fInitXscPAI->IntegralPAIxSection(bg2,Tkin);
|
||||
fInitXscPAI->IntegralPAIdEdx(bg2,Tkin);
|
||||
fInitXscPAI->IntegralCherenkov(bg2,Tkin);
|
||||
|
||||
|
||||
// G4cout<<"ionloss = "<<ionloss*cm/keV<<" keV/cm"<<endl ;
|
||||
// G4cout<<"n1 = "<<protonPAI.GetIntegralPAIxSection(1)*cm<<" 1/cm"<<endl ;
|
||||
// G4cout<<"protonPAI.GetSplineSize() = "<<
|
||||
// protonPAI.GetSplineSize()<<G4endl<<G4endl ;
|
||||
|
||||
G4PhysicsLogVector* transferVector = fInitXscPAI->GetPAIxscVector();
|
||||
G4PhysicsLogVector* dEdxVector = fInitXscPAI->GetPAIdEdxVector();
|
||||
|
||||
ionloss = (*dEdxVector)(0); // total <dE/dx>
|
||||
if ( ionloss <= 0.) ionloss = DBL_MIN;
|
||||
|
||||
fdEdxVector->PutValue(i,ionloss) ;
|
||||
|
||||
fPAItransferBank->insertAt(i,transferVector) ;
|
||||
fPAIdEdxTable->insertAt(i,dEdxVector) ;
|
||||
|
||||
// delete[] transferVector ;
|
||||
} // end of Tkin loop
|
||||
// theLossTable->insert(fdEdxVector);
|
||||
// end of material loop
|
||||
// G4cout<<"G4PAIonisation::BuildPAIonisationTable() have been called"<<G4endl ;
|
||||
// G4cout<<"G4PAIonisation::BuildLossTable() have been called"<<G4endl ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Build mean free path tables for the delta ray production process
|
||||
// tables are built for MATERIALS
|
||||
//
|
||||
|
||||
void
|
||||
G4PAIwithPhotons::BuildLambdaVector(const G4MaterialCutsCouple* matCutsCouple)
|
||||
{
|
||||
G4int i ;
|
||||
G4double dNdxCut, lambda;
|
||||
|
||||
const G4ProductionCutsTable* theCoupleTable=
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
|
||||
size_t numOfCouples = theCoupleTable->GetTableSize();
|
||||
size_t jMatCC;
|
||||
|
||||
for (jMatCC = 0 ; jMatCC < numOfCouples ; jMatCC++ )
|
||||
{
|
||||
if( matCutsCouple == theCoupleTable->GetMaterialCutsCouple(jMatCC) ) break;
|
||||
}
|
||||
if( jMatCC == numOfCouples && jMatCC > 0 ) jMatCC--;
|
||||
|
||||
const vector<G4double>* deltaCutInKineticEnergy = theCoupleTable->
|
||||
GetEnergyCutsVector(idxG4ElectronCut);
|
||||
|
||||
if (fLambdaVector) delete fLambdaVector;
|
||||
if (fdNdxCutVector) delete fdNdxCutVector;
|
||||
|
||||
fLambdaVector = new G4PhysicsLogVector( fLowestKineticEnergy,
|
||||
fHighestKineticEnergy,
|
||||
fTotBin ) ;
|
||||
fdNdxCutVector = new G4PhysicsLogVector( fLowestKineticEnergy,
|
||||
fHighestKineticEnergy,
|
||||
fTotBin ) ;
|
||||
G4double deltaCutInKineticEnergyNow = (*deltaCutInKineticEnergy)[jMatCC] ;
|
||||
|
||||
G4cout<<"PAIwithPhotons DeltaCutInKineticEnergyNow = "
|
||||
<<deltaCutInKineticEnergyNow/keV<<" keV"<<G4endl;
|
||||
|
||||
for ( i = 0 ; i < fTotBin ; i++ )
|
||||
{
|
||||
dNdxCut = GetdNdxCut(i,deltaCutInKineticEnergyNow) ;
|
||||
lambda = dNdxCut <= DBL_MIN ? DBL_MAX: 1.0/dNdxCut ;
|
||||
|
||||
if (lambda <= 1000*kCarTolerance) lambda = 1000*kCarTolerance ; // Mmm ???
|
||||
|
||||
fLambdaVector->PutValue(i, lambda) ;
|
||||
fdNdxCutVector->PutValue(i, dNdxCut) ;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Returns integral PAI cross section for energy transfers >= transferCut
|
||||
|
||||
G4double
|
||||
G4PAIwithPhotons::GetdNdxCut( G4int iPlace, G4double transferCut)
|
||||
{
|
||||
G4int iTransfer;
|
||||
G4double x1, x2, y1, y2, dNdxCut;
|
||||
// G4cout<<"iPlace = "<<iPlace<<"; "<<"transferCut = "<<transferCut<<G4endl;
|
||||
// G4cout<<"size = "<<G4int((*fPAItransferBank)(iPlace)->GetVectorLength())
|
||||
// <<G4endl;
|
||||
for( iTransfer = 0 ;
|
||||
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) ;
|
||||
iTransfer++)
|
||||
{
|
||||
if(transferCut <= (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer))
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( iTransfer >= G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) )
|
||||
{
|
||||
iTransfer = (*fPAItransferBank)(iPlace)->GetVectorLength() - 1 ;
|
||||
}
|
||||
y1 = (*(*fPAItransferBank)(iPlace))(iTransfer-1) ;
|
||||
y2 = (*(*fPAItransferBank)(iPlace))(iTransfer) ;
|
||||
// G4cout<<"y1 = "<<y1<<"; "<<"y2 = "<<y2<<G4endl;
|
||||
x1 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
|
||||
x2 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
|
||||
// G4cout<<"x1 = "<<x1<<"; "<<"x2 = "<<x2<<G4endl;
|
||||
|
||||
if ( y1 == y2 ) dNdxCut = y2 ;
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dNdxCut<<G4endl;
|
||||
return dNdxCut ;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Returns integral dEdx for energy transfers >= transferCut
|
||||
|
||||
G4double
|
||||
G4PAIwithPhotons::GetdEdxCut( G4int iPlace, G4double transferCut)
|
||||
{
|
||||
G4int iTransfer;
|
||||
G4double x1, x2, y1, y2, dEdxCut;
|
||||
// G4cout<<"iPlace = "<<iPlace<<"; "<<"transferCut = "<<transferCut<<G4endl;
|
||||
// G4cout<<"size = "<<G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength())
|
||||
// <<G4endl;
|
||||
for( iTransfer = 0 ;
|
||||
iTransfer < G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) ;
|
||||
iTransfer++)
|
||||
{
|
||||
if(transferCut <= (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( iTransfer >= G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) )
|
||||
{
|
||||
iTransfer = (*fPAIdEdxTable)(iPlace)->GetVectorLength() - 1 ;
|
||||
}
|
||||
y1 = (*(*fPAIdEdxTable)(iPlace))(iTransfer-1) ;
|
||||
y2 = (*(*fPAIdEdxTable)(iPlace))(iTransfer) ;
|
||||
// G4cout<<"y1 = "<<y1<<"; "<<"y2 = "<<y2<<G4endl;
|
||||
x1 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
|
||||
x2 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
|
||||
// G4cout<<"x1 = "<<x1<<"; "<<"x2 = "<<x2<<G4endl;
|
||||
|
||||
if ( y1 == y2 ) dEdxCut = y2 ;
|
||||
else
|
||||
{
|
||||
// if ( x1 == x2 ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
if ( fabs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
|
||||
else dEdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
|
||||
}
|
||||
// G4cout<<""<<dEdxCut<<G4endl;
|
||||
return dEdxCut ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIwithPhotons::ComputeDEDX(const G4MaterialCutsCouple* matCC,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
{
|
||||
G4int iTkin,iPlace;
|
||||
size_t jMat;
|
||||
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
|
||||
G4double charge = p->GetPDGCharge();
|
||||
G4double charge2 = charge*charge, dEdx;
|
||||
|
||||
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
|
||||
{
|
||||
if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
|
||||
}
|
||||
if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
|
||||
|
||||
fPAIdEdxTable = fPAIdEdxBank[jMat];
|
||||
fdEdxVector = fdEdxTable[jMat];
|
||||
for(iTkin = 0 ; iTkin < fTotBin ; iTkin++)
|
||||
{
|
||||
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
|
||||
}
|
||||
iPlace = iTkin - 1;
|
||||
if(iPlace < 0) iPlace = 0;
|
||||
dEdx = charge2*( (*fdEdxVector)(iPlace) - GetdEdxCut(iPlace,cutEnergy) ) ;
|
||||
|
||||
if( dEdx < 0.) dEdx = 0.;
|
||||
return dEdx;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIwithPhotons::CrossSection( const G4MaterialCutsCouple* matCC,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
G4double maxEnergy )
|
||||
{
|
||||
G4int iTkin,iPlace;
|
||||
size_t jMat;
|
||||
G4double tmax = min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
|
||||
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
|
||||
G4double charge = p->GetPDGCharge();
|
||||
G4double charge2 = charge*charge, cross, cross1, cross2;
|
||||
|
||||
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
|
||||
{
|
||||
if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
|
||||
}
|
||||
if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
|
||||
|
||||
fPAItransferBank = fPAIxscBank[jMat];
|
||||
|
||||
for(iTkin = 0 ; iTkin < fTotBin ; iTkin++)
|
||||
{
|
||||
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
|
||||
}
|
||||
iPlace = iTkin - 1;
|
||||
if(iPlace < 0) iPlace = 0;
|
||||
|
||||
cross1 = GetdNdxCut(iPlace,tmax) ;
|
||||
cross2 = GetdNdxCut(iPlace,cutEnergy) ;
|
||||
cross = (cross2-cross1)*charge2;
|
||||
if( cross < 0.) cross = 0.;
|
||||
return cross;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// It is analog of PostStepDoIt in terms of secondary electron.
|
||||
//
|
||||
|
||||
G4DynamicParticle*
|
||||
G4PAIwithPhotons::SampleSecondary( const G4MaterialCutsCouple* matCC,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
size_t jMat;
|
||||
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
|
||||
{
|
||||
if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
|
||||
}
|
||||
if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
|
||||
|
||||
fPAItransferBank = fPAIxscBank[jMat];
|
||||
fdNdxCutVector = fdNdxCutTable[jMat];
|
||||
|
||||
G4double tmax = min(MaxSecondaryEnergy(dp), maxEnergy);
|
||||
if( tmin >= tmax ) return 0;
|
||||
G4ThreeVector momentum = dp->GetMomentumDirection();
|
||||
G4double particleMass = dp->GetMass();
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
G4double scaledTkin = kineticEnergy*particleMass/proton_mass_c2;
|
||||
G4double totalEnergy = kineticEnergy + particleMass;
|
||||
G4double pSquare = kineticEnergy*(totalEnergy+particleMass);
|
||||
|
||||
G4double deltaTkin = GetPostStepTransfer(scaledTkin);
|
||||
if( deltaTkin <= 0. ) return 0;
|
||||
G4double deltaTotalMomentum = sqrt(deltaTkin*(deltaTkin + 2. * electron_mass_c2 ));
|
||||
G4double totalMomentum = sqrt(pSquare);
|
||||
G4double costheta = deltaTkin*(totalEnergy + electron_mass_c2)
|
||||
/(deltaTotalMomentum * totalMomentum);
|
||||
if (costheta < 0.) costheta = 0.;
|
||||
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(momentum);
|
||||
|
||||
// create G4DynamicParticle object for delta ray
|
||||
|
||||
G4DynamicParticle* deltaRay = new G4DynamicParticle;
|
||||
deltaRay->SetDefinition(G4Electron::Electron());
|
||||
deltaRay->SetKineticEnergy( deltaTkin );
|
||||
deltaRay->SetMomentumDirection(deltaDirection);
|
||||
|
||||
return deltaRay;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Returns post step PAI energy transfer > cut electron energy according to passed
|
||||
// scaled kinetic energy of particle
|
||||
|
||||
G4double
|
||||
G4PAIwithPhotons::GetPostStepTransfer( G4double scaledTkin )
|
||||
{
|
||||
// G4cout<<"G4PAIwithPhotons::GetPostStepTransfer"<<G4endl ;
|
||||
|
||||
G4int iTkin, iTransfer, iPlace ;
|
||||
G4double transfer = 0.0, position, dNdxCut1, dNdxCut2, E1, E2, W1, W2, W ;
|
||||
|
||||
for(iTkin=0;iTkin<fTotBin;iTkin++)
|
||||
{
|
||||
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
|
||||
}
|
||||
iPlace = iTkin - 1 ;
|
||||
if(iPlace < 0) iPlace = 0;
|
||||
dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
|
||||
|
||||
// G4cout<<"iPlace = "<<iPlace<<endl ;
|
||||
|
||||
if(iTkin == fTotBin) // Fermi plato, try from left
|
||||
{
|
||||
position = dNdxCut1*G4UniformRand() ;
|
||||
|
||||
for( iTransfer = 0;
|
||||
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
|
||||
{
|
||||
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
|
||||
}
|
||||
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
|
||||
}
|
||||
else
|
||||
{
|
||||
dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
|
||||
if(iTkin == 0) // Tkin is too small, trying from right only
|
||||
{
|
||||
position = dNdxCut2*G4UniformRand() ;
|
||||
|
||||
for( iTransfer = 0;
|
||||
iTransfer < G4int((*fPAItransferBank)(iPlace+1)->GetVectorLength()); iTransfer++ )
|
||||
{
|
||||
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
|
||||
}
|
||||
transfer = GetEnergyTransfer(iPlace+1,position,iTransfer);
|
||||
}
|
||||
else // general case: Tkin between two vectors of the material
|
||||
{
|
||||
E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1) ;
|
||||
E2 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin) ;
|
||||
W = 1.0/(E2 - E1) ;
|
||||
W1 = (E2 - scaledTkin)*W ;
|
||||
W2 = (scaledTkin - E1)*W ;
|
||||
|
||||
position = ( dNdxCut1*W1 + dNdxCut2*W2 )*G4UniformRand() ;
|
||||
|
||||
// G4cout<<position<<"\t" ;
|
||||
|
||||
for( iTransfer = 0;
|
||||
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
|
||||
{
|
||||
if( position >=
|
||||
( (*(*fPAItransferBank)(iPlace))(iTransfer)*W1 +
|
||||
(*(*fPAItransferBank)(iPlace+1))(iTransfer)*W2) ) break ;
|
||||
}
|
||||
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
|
||||
}
|
||||
}
|
||||
// G4cout<<"PAImodel PostStepTransfer = "<<transfer/keV<<" keV"<<endl ;
|
||||
if(transfer < 0.0 ) transfer = 0.0 ;
|
||||
return transfer ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Returns random PAI energy transfer according to passed
|
||||
// indexes of particle kinetic
|
||||
|
||||
G4double
|
||||
G4PAIwithPhotons::GetEnergyTransfer( G4int iPlace, G4double position, G4int iTransfer )
|
||||
{
|
||||
G4double x1, x2, y1, y2, energyTransfer ;
|
||||
|
||||
if(iTransfer == 0)
|
||||
{
|
||||
energyTransfer = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( iTransfer >= G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) )
|
||||
{
|
||||
iTransfer = (*fPAItransferBank)(iPlace)->GetVectorLength() - 1 ;
|
||||
}
|
||||
y1 = (*(*fPAItransferBank)(iPlace))(iTransfer-1) ;
|
||||
y2 = (*(*fPAItransferBank)(iPlace))(iTransfer) ;
|
||||
|
||||
x1 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
|
||||
x2 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
|
||||
|
||||
if ( x1 == x2 ) energyTransfer = x2 ;
|
||||
else
|
||||
{
|
||||
if ( y1 == y2 ) energyTransfer = x1 + (x2 - x1)*G4UniformRand() ;
|
||||
else
|
||||
{
|
||||
energyTransfer = x1 + (position - y1)*(x2 - x1)/(y2 - y1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return energyTransfer ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<G4DynamicParticle*>*
|
||||
G4PAIwithPhotons::SampleSecondaries( const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
|
||||
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
|
||||
vdp->push_back(delta);
|
||||
return vdp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double G4PAIwithPhotons::SampleFluctuations( const G4Material* material,
|
||||
const G4DynamicParticle* aParticle,
|
||||
G4double&,
|
||||
G4double& step,
|
||||
G4double&)
|
||||
{
|
||||
size_t jMat;
|
||||
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
|
||||
{
|
||||
if( material == fMaterialCutsCoupleVector[jMat]->GetMaterial() ) break;
|
||||
}
|
||||
if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
|
||||
|
||||
fPAItransferBank = fPAIxscBank[jMat];
|
||||
fdNdxCutVector = fdNdxCutTable[jMat];
|
||||
|
||||
G4int iTkin, iTransfer, iPlace ;
|
||||
G4long numOfCollisions;
|
||||
|
||||
// G4cout<<"G4PAIwithPhotons::SampleFluctuations"<<G4endl ;
|
||||
|
||||
G4double loss = 0.0, charge2 ;
|
||||
|
||||
G4double position, E1, E2, W1, W2, W, dNdxCut1, dNdxCut2, meanNumber;
|
||||
|
||||
G4double Tkin = aParticle->GetKineticEnergy() ;
|
||||
G4double MassRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass() ;
|
||||
G4double charge = aParticle->GetDefinition()->GetPDGCharge() ;
|
||||
charge2 = charge*charge ;
|
||||
G4double TkinScaled = Tkin*MassRatio ;
|
||||
|
||||
for(iTkin=0;iTkin<fTotBin;iTkin++)
|
||||
{
|
||||
if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
|
||||
}
|
||||
iPlace = iTkin - 1 ;
|
||||
dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
|
||||
|
||||
// G4cout<<"iPlace = "<<iPlace<<endl ;
|
||||
|
||||
if(iTkin == fTotBin) // Fermi plato, try from left
|
||||
{
|
||||
meanNumber =((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*step*charge2;
|
||||
if(meanNumber < 0.) meanNumber = 0. ;
|
||||
numOfCollisions = RandPoisson::shoot(meanNumber) ;
|
||||
|
||||
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
|
||||
|
||||
while(numOfCollisions)
|
||||
{
|
||||
position = dNdxCut1+
|
||||
((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*G4UniformRand() ;
|
||||
|
||||
for( iTransfer = 0;
|
||||
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
|
||||
{
|
||||
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
|
||||
}
|
||||
loss += GetEnergyTransfer(iPlace,position,iTransfer);
|
||||
numOfCollisions-- ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
|
||||
|
||||
if(iTkin == 0) // Tkin is too small, trying from right only
|
||||
{
|
||||
meanNumber =((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*step*charge2;
|
||||
if( meanNumber < 0. ) meanNumber = 0. ;
|
||||
numOfCollisions = RandPoisson::shoot(meanNumber) ;
|
||||
|
||||
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
|
||||
|
||||
while(numOfCollisions)
|
||||
{
|
||||
position = dNdxCut2+
|
||||
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*G4UniformRand();
|
||||
|
||||
for( iTransfer = 0;
|
||||
iTransfer < G4int((*fPAItransferBank)(iPlace+1)->GetVectorLength()); iTransfer++ )
|
||||
{
|
||||
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
|
||||
}
|
||||
loss += GetEnergyTransfer(iPlace+1,position,iTransfer);
|
||||
numOfCollisions-- ;
|
||||
}
|
||||
}
|
||||
else // general case: Tkin between two vectors of the material
|
||||
{
|
||||
E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1) ;
|
||||
E2 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin) ;
|
||||
W = 1.0/(E2 - E1) ;
|
||||
W1 = (E2 - TkinScaled)*W ;
|
||||
W2 = (TkinScaled - E1)*W ;
|
||||
|
||||
// G4cout<<"(*(*fPAItransferBank)(iPlace))(0) = "<<
|
||||
// (*(*fPAItransferBank)(iPlace))(0)<<G4endl ;
|
||||
// G4cout<<"(*(*fPAItransferBank)(iPlace+1))(0) = "<<
|
||||
// (*(*fPAItransferBank)(iPlace+1))(0)<<G4endl ;
|
||||
|
||||
meanNumber=( ((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*W1 +
|
||||
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*W2 )*step*charge2;
|
||||
if(meanNumber<0.0) meanNumber = 0.0;
|
||||
numOfCollisions = RandPoisson::shoot(meanNumber) ;
|
||||
|
||||
// G4cout<<"numOfCollisions = "<<numOfCollisions<<endl ;
|
||||
|
||||
while(numOfCollisions)
|
||||
{
|
||||
position =( (dNdxCut1+
|
||||
((*(*fPAItransferBank)(iPlace ))(0)-dNdxCut1))*W1 +
|
||||
(dNdxCut2+
|
||||
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2))*W2 )*G4UniformRand();
|
||||
|
||||
// G4cout<<position<<"\t" ;
|
||||
|
||||
for( iTransfer = 0;
|
||||
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
|
||||
{
|
||||
if( position >=
|
||||
( (*(*fPAItransferBank)(iPlace))(iTransfer)*W1 +
|
||||
(*(*fPAItransferBank)(iPlace+1))(iTransfer)*W2) )
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
// loss += (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
|
||||
loss += GetEnergyTransfer(iPlace,position,iTransfer);
|
||||
numOfCollisions-- ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// G4cout<<"PAIwithPhotons AlongStepLoss = "<<loss/keV<<" keV"<<endl ;
|
||||
|
||||
return loss ;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Returns the statistical estimation of the energy loss distribution variance
|
||||
//
|
||||
|
||||
|
||||
G4double G4PAIwithPhotons::Dispersion( const G4Material* material,
|
||||
const G4DynamicParticle* aParticle,
|
||||
G4double& tmax,
|
||||
G4double& step )
|
||||
{
|
||||
G4double loss, sumLoss=0., sumLoss2=0., sigma2, meanLoss=0.;
|
||||
for(G4int i = 0 ; i < fMeanNumber; i++)
|
||||
{
|
||||
loss = SampleFluctuations(material,aParticle,tmax,step,meanLoss);
|
||||
sumLoss += loss;
|
||||
sumLoss2 += loss*loss;
|
||||
}
|
||||
meanLoss = sumLoss/fMeanNumber;
|
||||
sigma2 = meanLoss*meanLoss + (sumLoss2-2*sumLoss*meanLoss)/fMeanNumber;
|
||||
return sigma2;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4PAIxSection.cc,v 1.20 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//
|
||||
// G4PAIxSection.cc -- class implementation file
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4PEEffectModel.cc,v 1.2 2005/05/02 12:44:18 maire Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4PEEffectModel
|
||||
//
|
||||
// Author: Vladimir Ivanchenko on base of Michel Maire code
|
||||
//
|
||||
// Creation date: 21.03.2005
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
// Class Description:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#include "G4PEEffectModel.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4DataVector.hh"
|
||||
#include "G4ParticleChangeForGamma.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4PEEffectModel::G4PEEffectModel(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam),isInitialized(false)
|
||||
{
|
||||
theGamma = G4Gamma::Gamma();
|
||||
theElectron = G4Electron::Electron();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4PEEffectModel::~G4PEEffectModel()
|
||||
{
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4PEEffectModel::Initialise(const G4ParticleDefinition*,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if(isInitialized) return;
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForGamma();
|
||||
|
||||
fminimalEnergy = 1.0*eV;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
std::vector<G4DynamicParticle*>* G4PEEffectModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* aDynamicPhoton,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
const G4Material* aMaterial = couple->GetMaterial();
|
||||
|
||||
G4double energy = aDynamicPhoton->GetKineticEnergy();
|
||||
G4ParticleMomentum PhotonDirection = aDynamicPhoton->GetMomentumDirection();
|
||||
|
||||
// select randomly one element constituing the material.
|
||||
const G4Element* anElement = SelectRandomAtom(aMaterial,theGamma,energy);
|
||||
|
||||
//
|
||||
// Photo electron
|
||||
//
|
||||
std::vector<G4DynamicParticle*>* fvect = new std::vector<G4DynamicParticle*>;
|
||||
|
||||
// Select atomic shell
|
||||
G4int nShells = anElement->GetNbOfAtomicShells();
|
||||
G4int i = 0;
|
||||
while ((i<nShells) && (energy<anElement->GetAtomicShell(i))) i++;
|
||||
|
||||
// no shell available
|
||||
if (i == nShells) return fvect;
|
||||
|
||||
G4double bindingEnergy = anElement->GetAtomicShell(i);
|
||||
G4double ElecKineEnergy = energy - bindingEnergy;
|
||||
|
||||
if (ElecKineEnergy > fminimalEnergy)
|
||||
{
|
||||
// direction of the photo electron
|
||||
//
|
||||
G4double cosTeta = ElecCosThetaDistribution(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* aParticle = new G4DynamicParticle (
|
||||
theElectron,ElecDirection, ElecKineEnergy);
|
||||
fvect->push_back(aParticle);
|
||||
}
|
||||
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->ProposeLocalEnergyDeposit(bindingEnergy);
|
||||
return fvect;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4PEEffectModel::ElecCosThetaDistribution(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......
|
||||
@@ -20,12 +20,13 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4PhotoElectricEffect.cc,v 1.34 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// $Id: G4PhotoElectricEffect.cc,v 1.33 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
//------------------ G4PhotoElectricEffect physics process -------------------------
|
||||
// by Michel Maire, 24 May 1996
|
||||
//
|
||||
// 12-06-96, Added SelectRandomAtom() method, by M.Maire
|
||||
// 21-06-96, SetCuts implementation, M.Maire
|
||||
// 17-09-96, PartialSumSigma(i)
|
||||
@@ -49,235 +50,58 @@
|
||||
// 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&)
|
||||
// 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)
|
||||
// distribution (mma)
|
||||
// 15-01-03, photoelectron theta ditribution : return costeta=1 if gamma>5
|
||||
// (helmut burkhardt)
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
// 21-04-05 Migrate to model interface and inherit from G4VEmProcess (V.Ivanchenko)
|
||||
// 04-05-05, Make class to be default (V.Ivanchenko)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "G4PhotoElectricEffect.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4PEEffectModel.hh"
|
||||
#include "G4Electron.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
G4PhotoElectricEffect::G4PhotoElectricEffect(const G4String& processName,
|
||||
G4ProcessType type):G4VDiscreteProcess (processName, type),
|
||||
fminimalEnergy(1*eV)
|
||||
|
||||
{ PrintInfoDefinition();}
|
||||
G4ProcessType type):G4VEmProcess (processName, type),
|
||||
isInitialised(false)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// destructor
|
||||
|
||||
|
||||
G4PhotoElectricEffect::~G4PhotoElectricEffect()
|
||||
{ }
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
inline G4bool G4PhotoElectricEffect::IsApplicable(const G4ParticleDefinition&
|
||||
particle)
|
||||
void G4PhotoElectricEffect::InitialiseProcess(const G4ParticleDefinition*)
|
||||
{
|
||||
return ( &particle == G4Gamma::Gamma() );
|
||||
if(!isInitialised) {
|
||||
isInitialised = true;
|
||||
// SetVerboseLevel(1);
|
||||
SetBuildTableFlag(false);
|
||||
SetSecondaryParticle(G4Electron::Electron());
|
||||
G4VEmModel* model = new G4PEEffectModel();
|
||||
model->SetLowEnergyLimit(MinKinEnergy());
|
||||
model->SetHighEnergyLimit(MaxKinEnergy());
|
||||
AddEmModel(1, model);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4PhotoElectricEffect::ComputeCrossSectionPerAtom(G4double GammaEnergy,
|
||||
G4double AtomicNumber)
|
||||
|
||||
// returns the photoElectric cross Section in GEANT4 internal units
|
||||
void G4PhotoElectricEffect::PrintInfo()
|
||||
{
|
||||
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;
|
||||
|
||||
G4cout << " Total cross sections from Sandia parametrisation. "
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4PhotoElectricEffect::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 G4PhotoElectricEffect::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* G4PhotoElectricEffect::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* G4PhotoElectricEffect::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 G4PhotoElectricEffect::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 G4PhotoElectricEffect::PrintInfoDefinition()
|
||||
{
|
||||
G4String comments = "Total cross sections from Sandia parametrisation. ";
|
||||
|
||||
G4cout << G4endl << GetProcessName() << ": " << comments << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4PhotoElectricEffect52.cc,v 1.1 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//....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;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -21,8 +21,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4PolarizedComptonScattering.cc,v 1.12 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4PolarizedComptonScattering.cc,v 1.14 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//
|
||||
//---------- G4PolarizedComptonScattering physics process ----------------------
|
||||
@@ -32,21 +32,22 @@
|
||||
// Corrections by Rui Curado da Silva (Nov. 2000)
|
||||
// - Sampling of Phi
|
||||
// - Depolarization probability
|
||||
//
|
||||
//
|
||||
// 13-07-01, DoIt: suppression of production cut for the electron (mma)
|
||||
// 20-09-01, DoIt: fminimalEnergy = 1*eV (mma)
|
||||
// 20-09-01, DoIt: fminimalEnergy = 1*eV (mma)
|
||||
// 04-05-05, Inheritance from ComptonScattering52 (V.Ivanchenko)
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "G4PolarizedComptonScattering.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
G4PolarizedComptonScattering::G4PolarizedComptonScattering(
|
||||
const G4String& processName)
|
||||
: G4ComptonScattering (processName)
|
||||
: G4ComptonScattering52 (processName)
|
||||
{ }
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -61,16 +62,16 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(
|
||||
// GEANT4 internal units
|
||||
//
|
||||
// Note : Effects due to binding of atomic electrons are negliged.
|
||||
|
||||
|
||||
{
|
||||
aParticleChange.Initialize(aTrack);
|
||||
|
||||
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
|
||||
|
||||
G4ThreeVector GammaPolarization0 = aDynamicGamma->GetPolarization();
|
||||
|
||||
if (fabs(GammaPolarization0.mag() - 1.e0) > 1.e-14)
|
||||
G4ComptonScattering::PostStepDoIt(aTrack,aStep);
|
||||
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
|
||||
|
||||
G4ThreeVector GammaPolarization0 = aDynamicGamma->GetPolarization();
|
||||
|
||||
if (std::abs(GammaPolarization0.mag() - 1.e0) > 1.e-14)
|
||||
G4ComptonScattering52::PostStepDoIt(aTrack,aStep);
|
||||
|
||||
G4double GammaEnergy0 = aDynamicGamma->GetKineticEnergy();
|
||||
G4double E0_m = GammaEnergy0 / electron_mass_c2;
|
||||
@@ -106,7 +107,7 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(
|
||||
G4double Rand = G4UniformRand();
|
||||
|
||||
int j = 0;
|
||||
while ((j < 100) && (fabs(SetPhi(epsilon,sint2,middle,Rand)) > resolution))
|
||||
while ((j < 100) && (std::abs(SetPhi(epsilon,sint2,middle,Rand)) > resolution))
|
||||
{
|
||||
middle = (maximum + minimum)/2;
|
||||
if (SetPhi(epsilon,sint2,middle,Rand)*
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4SCProcessorStand.cc,v 1.2 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4SynchrotronRadiation.cc,v 1.12 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// --------------------------------------------------------------
|
||||
// GEANT 4 class implementation file
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4UniversalFluctuation.cc,v 1.2 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4UniversalFluctuation.cc,v 1.4 2005/05/03 13:37:43 urban Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -43,9 +43,13 @@
|
||||
// 07-11-03 Fix problem of rounding of double in G4UniversalFluctuations
|
||||
// 06-02-04 Add control on big sigma > 2*meanLoss (V.Ivanchenko)
|
||||
// 26-04-04 Comment out the case of very small step (V.Ivanchenko)
|
||||
// 07-02-05 define problim = 5.e-3 (mma)
|
||||
// 03-05-05 conditions of Gaussian fluctuation changed (bugfix)
|
||||
// + smearing for very small loss (L.Urban)
|
||||
//
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "G4UniversalFluctuation.hh"
|
||||
#include "Randomize.hh"
|
||||
@@ -55,7 +59,7 @@
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -64,21 +68,22 @@ G4UniversalFluctuation::G4UniversalFluctuation(const G4String& nam)
|
||||
particle(0),
|
||||
minNumberInteractionsBohr(10.0),
|
||||
theBohrBeta2(50.0*keV/proton_mass_c2),
|
||||
minLoss(0.001*eV),
|
||||
sumalim(0.01),
|
||||
minLoss(10.*eV),
|
||||
problim(5.e-3),
|
||||
alim(10.),
|
||||
nmaxCont1(4.),
|
||||
nmaxCont2(16.)
|
||||
{
|
||||
sumalim = -log(problim);
|
||||
lastMaterial = 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4UniversalFluctuation::~G4UniversalFluctuation()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4UniversalFluctuation::InitialiseMe(const G4ParticleDefinition* part)
|
||||
{
|
||||
@@ -88,7 +93,7 @@ void G4UniversalFluctuation::InitialiseMe(const G4ParticleDefinition* part)
|
||||
chargeSquare = q*q;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
|
||||
const G4DynamicParticle* dp,
|
||||
@@ -96,54 +101,59 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
|
||||
G4double& length,
|
||||
G4double& meanLoss)
|
||||
{
|
||||
// calculate actual loss from the mean loss
|
||||
// The model used to get the fluctuation is essentially the same
|
||||
// as in Glandz in Geant3.
|
||||
// G4cout << "### Mean loss= " << meanLoss << G4endl;
|
||||
// Calculate actual loss from the mean loss.
|
||||
// The model used to get the fluctuations is essentially the same
|
||||
// as in Glandz in Geant3 (Cern program library W5013, phys332).
|
||||
// L. Urban et al. NIM A362, p.416 (1995) and Geant4 Physics Reference Manual
|
||||
|
||||
// shortcut for very very small loss
|
||||
if(meanLoss < minLoss) return meanLoss;
|
||||
// shortcut for very very small loss (out of validity of the model)
|
||||
//
|
||||
if (meanLoss < minLoss) return meanLoss;
|
||||
|
||||
if(!particle) InitialiseMe(dp->GetDefinition());
|
||||
|
||||
ipotFluct = material->GetIonisation()->GetMeanExcitationEnergy();
|
||||
|
||||
G4double tau = dp->GetKineticEnergy()/particleMass;
|
||||
G4double gam = tau + 1.0;
|
||||
G4double gam2 = gam*gam;
|
||||
G4double beta2 = tau*(tau + 2.0)/gam2;
|
||||
|
||||
// Validity range for delta electron cross section
|
||||
G4double loss, siga;
|
||||
// G4cout << "tmax= " << tmax << " kappa= " << minNumberInteractionsBohr << " l= " << length << G4endl;
|
||||
// Gaussian fluctuation
|
||||
// if(meanLoss >= minNumberInteractionsBohr*tmax || tmax <= ipotFluct*minNumberInteractionsBohr)
|
||||
if(meanLoss >= minNumberInteractionsBohr*tmax)
|
||||
G4double loss(0.), siga(0.);
|
||||
|
||||
// Gaussian regime
|
||||
// for heavy particles only and conditions
|
||||
// for Gauusian fluct. has been changed
|
||||
//
|
||||
if ((particleMass > electron_mass_c2) &&
|
||||
(meanLoss >= minNumberInteractionsBohr*tmax))
|
||||
{
|
||||
electronDensity = material->GetElectronDensity();
|
||||
siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
|
||||
* electronDensity * chargeSquare ;
|
||||
siga = sqrt(siga);
|
||||
G4double twomeanLoss = meanLoss + meanLoss;
|
||||
if(twomeanLoss < siga) {
|
||||
G4double x;
|
||||
do {
|
||||
loss = twomeanLoss*G4UniformRand();
|
||||
x = (loss - meanLoss)/siga;
|
||||
} while (1.0 - 0.5*x*x < G4UniformRand());
|
||||
} else {
|
||||
do {
|
||||
loss = G4RandGauss::shoot(meanLoss,siga);
|
||||
} while (loss < 0. || loss > twomeanLoss);
|
||||
G4double massrate = electron_mass_c2/particleMass ;
|
||||
G4double tmaxkine = 2.*electron_mass_c2*beta2*gam2/
|
||||
(1.+massrate*(2.*gam+massrate)) ;
|
||||
if (tmaxkine <= 2.*tmax)
|
||||
{
|
||||
electronDensity = material->GetElectronDensity();
|
||||
siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
|
||||
* electronDensity * chargeSquare;
|
||||
siga = sqrt(siga);
|
||||
G4double twomeanLoss = meanLoss + meanLoss;
|
||||
if (twomeanLoss < siga) {
|
||||
G4double x;
|
||||
do {
|
||||
loss = twomeanLoss*G4UniformRand();
|
||||
x = (loss - meanLoss)/siga;
|
||||
} while (1.0 - 0.5*x*x < G4UniformRand());
|
||||
} else {
|
||||
do {
|
||||
loss = G4RandGauss::shoot(meanLoss,siga);
|
||||
} while (loss < 0. || loss > twomeanLoss);
|
||||
}
|
||||
return loss;
|
||||
}
|
||||
//G4cout << "### meanLoss= " << meanLoss << " fluc= " << loss-meanLoss << " sig= " << siga << G4endl;
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
// Non Gaussian fluctuation
|
||||
|
||||
if(material != lastMaterial) {
|
||||
// Glandz regime : initialisation
|
||||
//
|
||||
if (material != lastMaterial) {
|
||||
f1Fluct = material->GetIonisation()->GetF1fluct();
|
||||
f2Fluct = material->GetIonisation()->GetF2fluct();
|
||||
e1Fluct = material->GetIonisation()->GetEnergy1fluct();
|
||||
@@ -151,141 +161,141 @@ G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
|
||||
e1LogFluct = material->GetIonisation()->GetLogEnergy1fluct();
|
||||
e2LogFluct = material->GetIonisation()->GetLogEnergy2fluct();
|
||||
rateFluct = material->GetIonisation()->GetRateionexcfluct();
|
||||
ipotFluct = material->GetIonisation()->GetMeanExcitationEnergy();
|
||||
ipotLogFluct = material->GetIonisation()->GetLogMeanExcEnergy();
|
||||
lastMaterial = material;
|
||||
}
|
||||
|
||||
G4double a1 = 0. , a2 = 0., a3 = 0. ;
|
||||
G4double p1,p2,p3;
|
||||
G4double rate = rateFluct ;
|
||||
|
||||
G4double w1 = tmax/ipotFluct;
|
||||
G4double w2 = log(2.*electron_mass_c2*beta2*gam2);
|
||||
G4double w2 = log(2.*electron_mass_c2*beta2*gam2)-beta2;
|
||||
|
||||
G4double C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
|
||||
if(w2 > ipotLogFluct)
|
||||
{
|
||||
G4double C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct);
|
||||
a1 = C*f1Fluct*(w2-e1LogFluct)/e1Fluct;
|
||||
a2 = C*f2Fluct*(w2-e2LogFluct)/e2Fluct;
|
||||
if(a2 < 0.)
|
||||
{
|
||||
a1 = 0. ;
|
||||
a2 = 0. ;
|
||||
rate = 1. ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rate = 1. ;
|
||||
}
|
||||
|
||||
G4double a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
|
||||
G4double a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
|
||||
G4double a3 = rateFluct*meanLoss*(tmax-ipotFluct)/(ipotFluct*tmax*log(w1));
|
||||
if(a1 < 0.) a1 = 0.;
|
||||
if(a2 < 0.) a2 = 0.;
|
||||
if(a3 < 0.) a3 = 0.;
|
||||
a3 = rate*meanLoss*(tmax-ipotFluct)/(ipotFluct*tmax*log(w1));
|
||||
|
||||
G4double suma = a1+a2+a3;
|
||||
loss = 0. ;
|
||||
|
||||
if(suma < sumalim) // very small Step
|
||||
// Glandz regime
|
||||
//
|
||||
if (suma > sumalim)
|
||||
{
|
||||
p1 = 0., p2 = 0 ;
|
||||
if((a1+a2) > 0.)
|
||||
{
|
||||
//G4cout << "A very small step" << G4endl;
|
||||
G4double e0 = material->GetIonisation()->GetEnergy0fluct();
|
||||
|
||||
if(tmax == ipotFluct)
|
||||
{
|
||||
a3 = meanLoss/e0;
|
||||
|
||||
if(a3>alim)
|
||||
{
|
||||
siga=sqrt(a3) ;
|
||||
p3 = max(0.,G4RandGauss::shoot(a3,siga)+0.5);
|
||||
} else {
|
||||
p3 = G4double(G4Poisson(a3));
|
||||
}
|
||||
loss = p3*e0 ;
|
||||
|
||||
if(p3 > 0.) loss += (1.-2.*G4UniformRand())*e0 ;
|
||||
|
||||
} else {
|
||||
tmax = tmax-ipotFluct+e0 ;
|
||||
a3 = meanLoss*(tmax-e0)/(tmax*e0*log(tmax/e0));
|
||||
|
||||
if(a3>alim)
|
||||
{
|
||||
siga=sqrt(a3) ;
|
||||
p3 = max(0.,G4RandGauss::shoot(a3,siga)+0.5);
|
||||
} else {
|
||||
p3 = G4double(G4Poisson(a3));
|
||||
}
|
||||
if(p3 > 0.) {
|
||||
G4double w = (tmax-e0)/tmax ;
|
||||
G4double corrfac = 1. ;
|
||||
if(p3 > nmaxCont2) {
|
||||
corrfac = p3/nmaxCont2 ;
|
||||
p3 = nmaxCont2 ;
|
||||
}
|
||||
G4int ip3 = (G4int)p3;
|
||||
for(G4int i=0; i<ip3; i++) {
|
||||
loss += 1./(1.-w*G4UniformRand()) ;
|
||||
}
|
||||
loss *= e0*corrfac ;
|
||||
}
|
||||
}
|
||||
// Not so small Step
|
||||
} else {
|
||||
//G4cout << "Excitation alim= " << alim << " a1= " << a1 << " a2= " << a2 << G4endl;
|
||||
// excitation type 1
|
||||
if(a1>alim) {
|
||||
if (a1>alim) {
|
||||
siga=sqrt(a1) ;
|
||||
p1 = max(0.,G4RandGauss::shoot(a1,siga)+0.5);
|
||||
} else {
|
||||
p1 = G4double(G4Poisson(a1));
|
||||
}
|
||||
|
||||
// excitation type 2
|
||||
if(a2>alim) {
|
||||
if (a2>alim) {
|
||||
siga=sqrt(a2) ;
|
||||
p2 = max(0.,G4RandGauss::shoot(a2,siga)+0.5);
|
||||
} else {
|
||||
p2 = G4double(G4Poisson(a2));
|
||||
}
|
||||
|
||||
loss = p1*e1Fluct+p2*e2Fluct;
|
||||
|
||||
// smearing to avoid unphysical peaks
|
||||
if(p2 > 0.)
|
||||
if (p2 > 0.)
|
||||
loss += (1.-2.*G4UniformRand())*e2Fluct;
|
||||
else if (loss>0.)
|
||||
loss += (1.-2.*G4UniformRand())*e1Fluct;
|
||||
if(loss < 0.) loss = 0.0;
|
||||
|
||||
// ionisation
|
||||
if(a3 > 0.) {
|
||||
if(a3>alim) {
|
||||
siga=sqrt(a3) ;
|
||||
p3 = max(0.,G4RandGauss::shoot(a3,siga)+0.5);
|
||||
} else {
|
||||
p3 = G4double(G4Poisson(a3));
|
||||
}
|
||||
G4double lossc = 0.;
|
||||
if(p3 > 0) {
|
||||
G4double na = 0.;
|
||||
G4double alfa = 1.;
|
||||
if (p3 > nmaxCont2) {
|
||||
G4double rfac = p3/(nmaxCont2+p3);
|
||||
G4double namean = p3*rfac;
|
||||
G4double sa = nmaxCont1*rfac;
|
||||
na = G4RandGauss::shoot(namean,sa);
|
||||
if (na > 0.) {
|
||||
alfa = w1*(nmaxCont2+p3)/(w1*nmaxCont2+p3);
|
||||
G4double alfa1 = alfa*log(alfa)/(alfa-1.);
|
||||
G4double ea = na*ipotFluct*alfa1;
|
||||
G4double sea = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
|
||||
lossc += G4RandGauss::shoot(ea,sea);
|
||||
}
|
||||
}
|
||||
|
||||
if (p3 > na) {
|
||||
w2 = alfa*ipotFluct;
|
||||
G4double w = (tmax-w2)/tmax;
|
||||
G4int nb = G4int(p3-na);
|
||||
for (G4int k=0; k<nb; k++) {
|
||||
lossc += w2/(1.-w*G4UniformRand());
|
||||
}
|
||||
}
|
||||
}
|
||||
loss += lossc;
|
||||
}
|
||||
if (loss < 0.) loss = 0.0;
|
||||
}
|
||||
//G4cout << "### Final loss= " << loss << G4endl;
|
||||
return loss;
|
||||
|
||||
// ionisation
|
||||
if (a3 > 0.) {
|
||||
if (a3>alim) {
|
||||
siga=sqrt(a3) ;
|
||||
p3 = max(0.,G4RandGauss::shoot(a3,siga)+0.5);
|
||||
} else {
|
||||
p3 = G4double(G4Poisson(a3));
|
||||
}
|
||||
G4double lossc = 0.;
|
||||
if (p3 > 0) {
|
||||
G4double na = 0.;
|
||||
G4double alfa = 1.;
|
||||
if (p3 > nmaxCont2) {
|
||||
G4double rfac = p3/(nmaxCont2+p3);
|
||||
G4double namean = p3*rfac;
|
||||
G4double sa = nmaxCont1*rfac;
|
||||
na = G4RandGauss::shoot(namean,sa);
|
||||
if (na > 0.) {
|
||||
alfa = w1*(nmaxCont2+p3)/(w1*nmaxCont2+p3);
|
||||
G4double alfa1 = alfa*log(alfa)/(alfa-1.);
|
||||
G4double ea = na*ipotFluct*alfa1;
|
||||
G4double sea = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
|
||||
lossc += G4RandGauss::shoot(ea,sea);
|
||||
}
|
||||
}
|
||||
|
||||
if (p3 > na) {
|
||||
w2 = alfa*ipotFluct;
|
||||
G4double w = (tmax-w2)/tmax;
|
||||
G4int nb = G4int(p3-na);
|
||||
for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
|
||||
}
|
||||
}
|
||||
loss += lossc;
|
||||
}
|
||||
return loss;
|
||||
}
|
||||
|
||||
// suma < sumalim; very small energy loss;
|
||||
//
|
||||
G4double e0 = material->GetIonisation()->GetEnergy0fluct();
|
||||
|
||||
a3 = meanLoss*(tmax-e0)/(tmax*e0*log(tmax/e0));
|
||||
if (a3 > alim)
|
||||
{
|
||||
siga=sqrt(a3);
|
||||
p3 = max(0.,G4RandGauss::shoot(a3,siga)+0.5);
|
||||
} else {
|
||||
p3 = G4double(G4Poisson(a3));
|
||||
}
|
||||
if (p3 > 0.) {
|
||||
G4double w = (tmax-e0)/tmax;
|
||||
G4double corrfac = 1.;
|
||||
if (p3 > nmaxCont2) {
|
||||
corrfac = p3/nmaxCont2;
|
||||
p3 = nmaxCont2;
|
||||
}
|
||||
G4int ip3 = (G4int)p3;
|
||||
for (G4int i=0; i<ip3; i++) loss += 1./(1.-w*G4UniformRand());
|
||||
loss *= e0*corrfac;
|
||||
// smearing for losses near to e0
|
||||
if(p3 <= 2.)
|
||||
loss += e0*(1.-2.*G4UniformRand()) ;
|
||||
}
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
G4double G4UniversalFluctuation::Dispersion(
|
||||
@@ -307,4 +317,4 @@ G4double G4UniversalFluctuation::Dispersion(
|
||||
return siga;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4VeEnergyLoss.cc,v 1.34 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4VhEnergyLoss.cc,v 1.48 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4eBremsstrahlung.cc,v 1.40 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4eBremsstrahlung.cc,v 1.42 2005/04/08 12:39:58 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -62,6 +62,7 @@
|
||||
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
|
||||
// 04-11-04 add gamma threshold (V.Ivanchenko)
|
||||
// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko)
|
||||
// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -100,11 +101,12 @@ G4eBremsstrahlung::~G4eBremsstrahlung()
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eBremsstrahlung::InitialiseEnergyLossProcess(const G4ParticleDefinition*,
|
||||
void G4eBremsstrahlung::InitialiseEnergyLossProcess(const G4ParticleDefinition* p,
|
||||
const G4ParticleDefinition*)
|
||||
{
|
||||
if(!isInitialised) {
|
||||
isInitialised = true;
|
||||
particle = p;
|
||||
SetSecondaryParticle(G4Gamma::Gamma());
|
||||
SetIonisation(false);
|
||||
|
||||
@@ -120,10 +122,8 @@ void G4eBremsstrahlung::InitialiseEnergyLossProcess(const G4ParticleDefinition*,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eBremsstrahlung::PrintInfoDefinition()
|
||||
void G4eBremsstrahlung::PrintInfo()
|
||||
{
|
||||
G4VEnergyLossProcess::PrintInfoDefinition();
|
||||
|
||||
G4cout << " Total cross sections from a parametrisation"
|
||||
<< " based on the EEDL data library. "
|
||||
<< G4endl
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4eBremsstrahlung52.cc,v 1.4 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4eBremsstrahlung52.cc,v 1.5 2005/05/03 08:07:41 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//
|
||||
// ------------ G4eBremsstrahlung52 physics process --------
|
||||
@@ -377,7 +377,7 @@ G4double G4eBremsstrahlung52::ComputeBremLoss(G4double Z,G4double,
|
||||
G4double delz = 1.e6;
|
||||
for (G4int ii=0; ii<NZ; ii++)
|
||||
{
|
||||
if(fabs(Z-ZZ[ii]) < delz) { iz = ii; delz = fabs(Z-ZZ[ii]);}
|
||||
if(std::abs(Z-ZZ[ii]) < delz) { iz = ii; delz = std::abs(Z-ZZ[ii]);}
|
||||
}
|
||||
|
||||
G4double xx = log10(T);
|
||||
@@ -618,10 +618,10 @@ G4double G4eBremsstrahlung52::ComputeCrossSectionPerAtom(
|
||||
G4double delz = 1.e6 ;
|
||||
for (G4int ii=0; ii<NZ; ii++)
|
||||
{
|
||||
if(fabs(AtomicNumber-ZZ[ii]) < delz)
|
||||
if(std::abs(AtomicNumber-ZZ[ii]) < delz)
|
||||
{
|
||||
iz = ii ;
|
||||
delz = fabs(AtomicNumber-ZZ[ii]) ;
|
||||
delz = std::abs(AtomicNumber-ZZ[ii]) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4eBremsstrahlungModel.cc,v 1.18 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4eBremsstrahlungModel.cc,v 1.25 2005/05/03 08:07:41 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -44,6 +44,7 @@
|
||||
// 13-02-03 Add name (V.Ivanchenko)
|
||||
// 09-05-03 Fix problem of supression function + optimise sampling (V.Ivanchenko)
|
||||
// 20-05-04 Correction to ensure unit independence (L.Urban)
|
||||
// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
// Class Description:
|
||||
//
|
||||
@@ -63,6 +64,7 @@
|
||||
#include "G4ElementVector.hh"
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
#include "G4DataVector.hh"
|
||||
#include "G4ParticleChangeForLoss.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -108,20 +110,6 @@ void G4eBremsstrahlungModel::SetParticle(const G4ParticleDefinition* p)
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eBremsstrahlungModel::HighEnergyLimit(const G4ParticleDefinition*)
|
||||
{
|
||||
return highKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eBremsstrahlungModel::LowEnergyLimit(const G4ParticleDefinition*)
|
||||
{
|
||||
return lowKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eBremsstrahlungModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple*)
|
||||
{
|
||||
@@ -130,17 +118,12 @@ G4double G4eBremsstrahlungModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4bool G4eBremsstrahlungModel::IsInCharge(const G4ParticleDefinition* p)
|
||||
{
|
||||
return (p == G4Electron::Electron() || p == G4Positron::Positron());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eBremsstrahlungModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector& cuts)
|
||||
{
|
||||
if(p) SetParticle(p);
|
||||
highKinEnergy = HighEnergyLimit();
|
||||
lowKinEnergy = LowEnergyLimit();
|
||||
const G4ProductionCutsTable* theCoupleTable=
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
size_t numOfCouples = theCoupleTable->GetTableSize();
|
||||
@@ -157,12 +140,17 @@ void G4eBremsstrahlungModel::Initialise(const G4ParticleDefinition* p,
|
||||
min(cuts[i], 0.25*highKinEnergy));
|
||||
partialSumSigma.push_back(dv);
|
||||
}
|
||||
if(pParticleChange)
|
||||
fParticleChange = reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
|
||||
else
|
||||
fParticleChange = new G4ParticleChangeForLoss();
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eBremsstrahlungModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
G4double G4eBremsstrahlungModel::ComputeDEDXPerVolume(
|
||||
const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
@@ -179,7 +167,6 @@ G4double G4eBremsstrahlungModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
|
||||
const G4double coef1 = -0.5;
|
||||
const G4double coef2 = 2./9.;
|
||||
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
const G4ElementVector* theElementVector = material->GetElementVector();
|
||||
const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
|
||||
|
||||
@@ -337,7 +324,7 @@ G4double G4eBremsstrahlungModel::ComputeBremLoss(G4double Z, G4double T,
|
||||
G4double delz = 1.e6;
|
||||
for (G4int ii=0; ii<NZ; ii++)
|
||||
{
|
||||
G4double dz = fabs(Z-ZZ[ii]);
|
||||
G4double dz = std::abs(Z-ZZ[ii]);
|
||||
if(dz < delz) {
|
||||
iz = ii;
|
||||
delz = dz;
|
||||
@@ -397,7 +384,8 @@ G4double G4eBremsstrahlungModel::PositronCorrFactorLoss(G4double Z,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eBremsstrahlungModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
G4double G4eBremsstrahlungModel::CrossSectionPerVolume(
|
||||
const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
@@ -409,7 +397,6 @@ G4double G4eBremsstrahlungModel::CrossSection(const G4MaterialCutsCouple* couple
|
||||
G4double cut = max(cutEnergy, minThreshold);
|
||||
if(cut >= tmax) return cross;
|
||||
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
const G4ElementVector* theElementVector = material->GetElementVector() ;
|
||||
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
|
||||
|
||||
@@ -539,10 +526,11 @@ G4double G4eBremsstrahlungModel::CrossSectionPerAtom(G4double kineticEnergy,
|
||||
G4double delz = 1.e6 ;
|
||||
for (G4int ii=0; ii<NZ; ii++)
|
||||
{
|
||||
if(fabs(Z-ZZ[ii]) < delz)
|
||||
G4double absdelz = std::abs(Z-ZZ[ii]);
|
||||
if(absdelz < delz)
|
||||
{
|
||||
iz = ii ;
|
||||
delz = fabs(Z-ZZ[ii]);
|
||||
delz = absdelz;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,7 +612,7 @@ G4DataVector* G4eBremsstrahlungModel::ComputePartialSumSigma(
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
|
||||
std::vector<G4DynamicParticle*>* G4eBremsstrahlungModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
G4double tmin,
|
||||
@@ -641,6 +629,7 @@ G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
|
||||
// A modified version of the random number techniques of Butcher & Messel is used
|
||||
// (Nuc Phys 20(1960),15).
|
||||
{
|
||||
std::vector<G4DynamicParticle*>* newp = new std::vector<G4DynamicParticle*>;
|
||||
G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
G4double tmax = min(maxEnergy, kineticEnergy);
|
||||
if(tmin > tmax) tmin = tmax;
|
||||
@@ -825,21 +814,13 @@ G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
|
||||
G4ThreeVector gammaDirection(sint*cos(phi),sint*sin(phi), cos(theta));
|
||||
gammaDirection.rotateUz(direction);
|
||||
|
||||
kineticEnergy -= gammaEnergy;
|
||||
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
|
||||
|
||||
// create G4DynamicParticle object for the Gamma
|
||||
G4DynamicParticle* g = new G4DynamicParticle(theGamma,gammaDirection,gammaEnergy);
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
vector<G4DynamicParticle*>* G4eBremsstrahlungModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle*,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
return 0;
|
||||
newp->push_back(g);
|
||||
return newp;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4eIonisation.cc,v 1.39 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4eIonisation.cc,v 1.41 2005/05/01 20:26:24 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -58,6 +58,7 @@
|
||||
// 08-08-03 STD substitute standard (V.Ivanchenko)
|
||||
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
|
||||
// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko)
|
||||
// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -68,6 +69,7 @@
|
||||
#include "G4Electron.hh"
|
||||
#include "G4MollerBhabhaModel.hh"
|
||||
#include "G4UniversalFluctuation.hh"
|
||||
#include "G4BohrFluctuations.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -77,7 +79,6 @@ using namespace std;
|
||||
G4eIonisation::G4eIonisation(const G4String& name)
|
||||
: G4VEnergyLossProcess(name),
|
||||
theElectron(G4Electron::Electron()),
|
||||
subCutoff(false),
|
||||
isElectron(true),
|
||||
isInitialised(false)
|
||||
{
|
||||
@@ -102,6 +103,7 @@ void G4eIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part
|
||||
SetSecondaryParticle(theElectron);
|
||||
|
||||
flucModel = new G4UniversalFluctuation();
|
||||
//flucModel = new G4BohrFluctuations();
|
||||
|
||||
G4VEmModel* em = new G4MollerBhabhaModel();
|
||||
em->SetLowEnergyLimit(0.1*keV);
|
||||
@@ -113,20 +115,11 @@ void G4eIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eIonisation::PrintInfoDefinition()
|
||||
void G4eIonisation::PrintInfo()
|
||||
{
|
||||
G4VEnergyLossProcess::PrintInfoDefinition();
|
||||
|
||||
G4cout << " Delta cross sections from Moller+Bhabha, "
|
||||
<< "good description from 1 KeV to 100 GeV."
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eIonisation::SetSubCutoff(G4bool val)
|
||||
{
|
||||
subCutoff = val;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4eIonisation52.cc,v 1.4 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//--------------- G4eIonisation52 physics process --------------------------------
|
||||
// by Laszlo Urban, 20 March 1997
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4eeToTwoGammaModel.cc,v 1.4 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4eeToTwoGammaModel.cc,v 1.8 2005/04/29 18:02:35 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -35,6 +35,8 @@
|
||||
// Creation date: 02.08.2004
|
||||
//
|
||||
// Modifications:
|
||||
// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
// 18-04-05 Compute CrossSectionPerVolume (V.Ivantchenko)
|
||||
//
|
||||
//
|
||||
// Class Description:
|
||||
@@ -74,8 +76,6 @@ using namespace std;
|
||||
G4eeToTwoGammaModel::G4eeToTwoGammaModel(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam),
|
||||
highKinEnergy(10.*TeV),
|
||||
lowKinEnergy(0.1*keV),
|
||||
pi_rcl2(pi*classic_electr_radius*classic_electr_radius)
|
||||
{
|
||||
}
|
||||
@@ -87,60 +87,20 @@ G4eeToTwoGammaModel::~G4eeToTwoGammaModel()
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eeToTwoGammaModel::HighEnergyLimit(const G4ParticleDefinition*)
|
||||
{
|
||||
return highKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eeToTwoGammaModel::LowEnergyLimit(const G4ParticleDefinition*)
|
||||
{
|
||||
return lowKinEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eeToTwoGammaModel::MinEnergyCut(const G4ParticleDefinition*,
|
||||
const G4MaterialCutsCouple*)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4bool G4eeToTwoGammaModel::IsInCharge(const G4ParticleDefinition* p)
|
||||
{
|
||||
return (p == G4Positron::Positron());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eeToTwoGammaModel::Initialise(const G4ParticleDefinition*,
|
||||
const G4DataVector&)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eeToTwoGammaModel::ComputeDEDX(const G4MaterialCutsCouple*,
|
||||
const G4ParticleDefinition*,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eeToTwoGammaModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
const G4ParticleDefinition*,
|
||||
G4double kineticEnergy,
|
||||
G4double,
|
||||
G4double)
|
||||
G4double G4eeToTwoGammaModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition*,
|
||||
G4double kineticEnergy,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
// Calculates the cross section per atom of annihilation into two photons
|
||||
// from the Heilter formula.
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
G4double eDensity = material->GetElectronDensity();
|
||||
|
||||
G4double tau = kineticEnergy/electron_mass_c2;
|
||||
@@ -156,17 +116,6 @@ G4double G4eeToTwoGammaModel::CrossSection(const G4MaterialCutsCouple* couple,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticle* G4eeToTwoGammaModel::SampleSecondary(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle*,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
vector<G4DynamicParticle*>* G4eeToTwoGammaModel::SampleSecondaries(
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle* dp,
|
||||
|
||||
@@ -20,475 +20,116 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4eplusAnnihilation.cc,v 1.22 2005/05/12 11:06:43 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// $Id: G4eplusAnnihilation.cc,v 1.20 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4eplusAnnihilation
|
||||
//
|
||||
// Author: Vladimir Ivanchenko on base of Michel Maire code
|
||||
//
|
||||
// Creation date: 02.08.2004
|
||||
//
|
||||
// Modifications:
|
||||
// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivanchenko)
|
||||
// 08-04-05 Major optimisation of internal interfaces (V.Ivanchenko)
|
||||
// 03-05-05 suppress Integral option (mma)
|
||||
// 04-05-05, Make class to be default (V.Ivanchenko)
|
||||
//
|
||||
//....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)
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#include "G4eplusAnnihilation.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4PhysicsVector.hh"
|
||||
#include "G4PhysicsLogVector.hh"
|
||||
#include "G4eeToTwoGammaModel.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4eplusAnnihilation::G4eplusAnnihilation(const G4String& processName,
|
||||
G4ProcessType type):G4VRestDiscreteProcess (processName, type),
|
||||
theCrossSectionTable(NULL),
|
||||
theMeanFreePathTable(NULL),
|
||||
LowestEnergyLimit (10*keV),
|
||||
HighestEnergyLimit(10*TeV),
|
||||
NumbBinTable(100),
|
||||
fminimalEnergy(1*eV)
|
||||
|
||||
G4eplusAnnihilation::G4eplusAnnihilation(const G4String& name)
|
||||
: G4VEmProcess(name), isInitialised(false)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// destructor
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4eplusAnnihilation::~G4eplusAnnihilation()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eplusAnnihilation::InitialiseProcess(const G4ParticleDefinition*)
|
||||
{
|
||||
if (theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy();
|
||||
delete theCrossSectionTable;
|
||||
}
|
||||
|
||||
if (theMeanFreePathTable) {
|
||||
theMeanFreePathTable->clearAndDestroy();
|
||||
delete theMeanFreePathTable;
|
||||
}
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4eplusAnnihilation::IsApplicable( const G4ParticleDefinition& particle)
|
||||
{
|
||||
return ( &particle == G4Positron::Positron() );
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
void G4eplusAnnihilation::SetPhysicsTableBining(
|
||||
G4double lowE, G4double highE, G4int nBins)
|
||||
{
|
||||
LowestEnergyLimit = lowE; HighestEnergyLimit = highE; NumbBinTable = nBins;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4eplusAnnihilation::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- annihilation
|
||||
|
||||
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- annihilation
|
||||
|
||||
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();
|
||||
if(!isInitialised) {
|
||||
isInitialised = true;
|
||||
// SetVerboseLevel(3);
|
||||
SetBuildTableFlag(true);
|
||||
SetStartFromNullFlag(false);
|
||||
SetSecondaryParticle(G4Gamma::Gamma());
|
||||
G4double emin = 0.1*keV;
|
||||
G4double emax = 100.*TeV;
|
||||
SetLambdaBinning(120);
|
||||
SetMinKinEnergy(emin);
|
||||
SetMaxKinEnergy(emax);
|
||||
G4VEmModel* em = new G4eeToTwoGammaModel();
|
||||
em->SetLowEnergyLimit(emin);
|
||||
em->SetHighEnergyLimit(emax);
|
||||
AddEmModel(1, em);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4eplusAnnihilation::ComputeCrossSectionPerAtom
|
||||
(G4double PositKinEnergy, G4double AtomicNumber)
|
||||
|
||||
// Calculates the cross section per atom of annihilation into two photons
|
||||
// from the Heilter formula.
|
||||
// GEANT4 internal units.
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eplusAnnihilation::PrintInfo()
|
||||
{
|
||||
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.));
|
||||
G4cout << " Heilter model of formula of annihilation into 2 photons"
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4eplusAnnihilation::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 G4eplusAnnihilation::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 G4eplusAnnihilation::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 G4eplusAnnihilation::GetMeanLifeTime(const G4Track&,
|
||||
G4ForceCondition*)
|
||||
|
||||
// returns the annihilation mean life time in GEANT4 internal units
|
||||
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
G4VParticleChange* G4eplusAnnihilation::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 annihilation 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 annihilation then
|
||||
// should be performed by the AtRestDoIt!
|
||||
if (aTrack.GetTrackStatus() == fStopButAlive) 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* G4eplusAnnihilation::AtRestDoIt(const G4Track& aTrack,
|
||||
const G4Step& )
|
||||
const G4Step& )
|
||||
//
|
||||
// Performs the e+ e- annihilation when both particles are assumed at rest.
|
||||
// It generates two back to back photons with energy = electron_mass.
|
||||
// The angular distribution is isotropic.
|
||||
// The angular distribution is isotropic.
|
||||
// GEANT4 internal units
|
||||
//
|
||||
// Note : Effects due to binding of atomic electrons are negliged.
|
||||
|
||||
{
|
||||
aParticleChange.Initialize(aTrack);
|
||||
fParticleChange.InitializeForPostStep(aTrack);
|
||||
|
||||
aParticleChange.SetNumberOfSecondaries(2);
|
||||
// Below gamma production threshold
|
||||
if (GetGammaEnergyCut() > electron_mass_c2) {
|
||||
fParticleChange.ProposeLocalEnergyDeposit(2.0*electron_mass_c2);
|
||||
|
||||
} else { // Real gamma production
|
||||
fParticleChange.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;
|
||||
G4double cosTeta = 2.*G4UniformRand()-1. , sinTeta = sqrt(1.-cosTeta*cosTeta);
|
||||
G4double phi = twopi * G4UniformRand();
|
||||
G4ThreeVector direction (sinTeta*cos(phi), sinTeta*sin(phi), cosTeta);
|
||||
fParticleChange.AddSecondary( new G4DynamicParticle (G4Gamma::Gamma(),
|
||||
direction, electron_mass_c2) );
|
||||
fParticleChange.AddSecondary( new G4DynamicParticle (G4Gamma::Gamma(),
|
||||
-direction, electron_mass_c2) );
|
||||
}
|
||||
// Kill the incident positron
|
||||
//
|
||||
fParticleChange.ProposeTrackStatus(fStopAndKill);
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4eplusAnnihilation::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 G4eplusAnnihilation::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 G4eplusAnnihilation::PrintInfoDefinition()
|
||||
{
|
||||
G4String comments = "Total cross section from Heilter formula"
|
||||
"(annihilation 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";
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -0,0 +1,495 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4eplusAnnihilation52.cc,v 1.1 2005/05/04 16:16:12 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//....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) 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";
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -1,141 +0,0 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * DISCLAIMER *
|
||||
// * *
|
||||
// * The following disclaimer summarizes all the specific disclaimers *
|
||||
// * of contributors to this software. The specific disclaimers,which *
|
||||
// * govern, are listed with their locations in: *
|
||||
// * http://cern.ch/geant4/license *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. *
|
||||
// * *
|
||||
// * This code implementation is the intellectual property of the *
|
||||
// * GEANT4 collaboration. *
|
||||
// * By copying, distributing or modifying the Program (or any work *
|
||||
// * based on the Program) you indicate your acceptance of this *
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4eplusAnnihilation70.cc,v 1.3 2004/12/01 19:37:15 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4eplusAnnihilation70
|
||||
//
|
||||
// Author: Vladimir Ivanchenko on base of Michel Maire code
|
||||
//
|
||||
// Creation date: 02.08.2004
|
||||
//
|
||||
// Modifications:
|
||||
// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko)
|
||||
//
|
||||
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#include "G4eplusAnnihilation70.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4PhysicsVector.hh"
|
||||
#include "G4PhysicsLogVector.hh"
|
||||
#include "G4eeToTwoGammaModel.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4eplusAnnihilation70::G4eplusAnnihilation70(const G4String& name)
|
||||
: G4VEmProcess(name), isInitialised(false)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4eplusAnnihilation70::~G4eplusAnnihilation70()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eplusAnnihilation70::InitialiseProcess(const G4ParticleDefinition*)
|
||||
{
|
||||
if(!isInitialised) {
|
||||
isInitialised = true;
|
||||
SetSecondaryParticle(G4Gamma::Gamma());
|
||||
G4double emin = 0.1*keV;
|
||||
G4double emax = 100.*TeV;
|
||||
SetLambdaBinning(120);
|
||||
SetMinKinEnergy(emin);
|
||||
SetMaxKinEnergy(emax);
|
||||
G4VEmModel* em = new G4eeToTwoGammaModel();
|
||||
em->SetLowEnergyLimit(emin);
|
||||
em->SetHighEnergyLimit(emax);
|
||||
AddEmModel(1, em);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eplusAnnihilation70::PrintInfoDefinition()
|
||||
{
|
||||
G4VEmProcess::PrintInfoDefinition();
|
||||
|
||||
G4cout << " Heilter model of formula of annihilation into 2 photons"
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4PhysicsVector* G4eplusAnnihilation70::LambdaPhysicsVector(const G4MaterialCutsCouple*)
|
||||
{
|
||||
G4PhysicsVector* v = new G4PhysicsLogVector(MinKinEnergy(), MaxKinEnergy(),
|
||||
LambdaBinning());
|
||||
return v;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4VParticleChange* G4eplusAnnihilation70::AtRestDoIt(const G4Track& aTrack,
|
||||
const G4Step& )
|
||||
//
|
||||
// Performs the e+ e- annihilation 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.
|
||||
{
|
||||
fParticleChange.InitializeForPostStep(aTrack);
|
||||
|
||||
// Below gamma production threshold
|
||||
if(electron_mass_c2 < GetGammaEnergyCut()) {
|
||||
fParticleChange.ProposeLocalEnergyDeposit(2.0*electron_mass_c2);
|
||||
|
||||
// Real gamma production
|
||||
} else {
|
||||
fParticleChange.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);
|
||||
fParticleChange.AddSecondary( new G4DynamicParticle (G4Gamma::Gamma(),
|
||||
direction, electron_mass_c2) );
|
||||
fParticleChange.AddSecondary( new G4DynamicParticle (G4Gamma::Gamma(),
|
||||
-direction, electron_mass_c2) );
|
||||
}
|
||||
// Kill the incident positron
|
||||
//
|
||||
fParticleChange.ProposeTrackStatus(fStopAndKill);
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4hIonisation.cc,v 1.54 2004/12/01 19:37:16 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4hIonisation.cc,v 1.56 2005/04/08 12:39:58 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -68,6 +68,7 @@
|
||||
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
|
||||
// 27-05-04 Set integral to be a default regime (V.Ivanchenko)
|
||||
// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko)
|
||||
// 24-03-05 Optimize internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -92,7 +93,6 @@ G4hIonisation::G4hIonisation(const G4String& name)
|
||||
: G4VEnergyLossProcess(name),
|
||||
theParticle(0),
|
||||
theBaseParticle(0),
|
||||
subCutoff(false),
|
||||
isInitialised(false)
|
||||
{
|
||||
SetDEDXBinning(120);
|
||||
@@ -127,16 +127,16 @@ void G4hIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part
|
||||
mass = theParticle->GetPDGMass();
|
||||
ratio = electron_mass_c2/mass;
|
||||
|
||||
G4double massFactor = mass/proton_mass_c2;
|
||||
G4VEmModel* em = new G4BraggModel();
|
||||
em->SetLowEnergyLimit(0.1*keV);
|
||||
em->SetHighEnergyLimit(2.0*MeV*massFactor);
|
||||
eth = 2.0*MeV*mass/proton_mass_c2;
|
||||
em->SetHighEnergyLimit(eth);
|
||||
|
||||
flucModel = new G4UniversalFluctuation();
|
||||
|
||||
AddEmModel(1, em, flucModel);
|
||||
G4VEmModel* em1 = new G4BetheBlochModel();
|
||||
em1->SetLowEnergyLimit(2.0*MeV*massFactor);
|
||||
em1->SetLowEnergyLimit(eth);
|
||||
em1->SetHighEnergyLimit(100.0*TeV);
|
||||
AddEmModel(2, em1, flucModel);
|
||||
|
||||
@@ -147,21 +147,13 @@ void G4hIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4hIonisation::PrintInfoDefinition()
|
||||
void G4hIonisation::PrintInfo()
|
||||
{
|
||||
G4VEnergyLossProcess::PrintInfoDefinition();
|
||||
|
||||
G4cout << " Bether-Bloch model for Escaled > 2 MeV, "
|
||||
<< "parametrisation of Bragg peak below, "
|
||||
<< "Integral mode " << IsIntegral()
|
||||
G4cout << " Scaling relation is used to proton dE/dx and range"
|
||||
<< G4endl
|
||||
<< " Bether-Bloch model for Escaled > " << eth << " MeV, ICRU49 "
|
||||
<< "parametrisation for protons below."
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4hIonisation::SetSubCutoff(G4bool val)
|
||||
{
|
||||
subCutoff = val;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4hIonisation52.cc,v 1.4 2004/12/01 19:37:16 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
//---------------- G4hIonisation52 physics process -------------------------------
|
||||
// by Laszlo Urban, 30 May 1997
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// * statement, and all its terms. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4ionIonisation.cc,v 1.31 2004/12/01 19:37:16 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-00-cand-03 $
|
||||
// $Id: G4ionIonisation.cc,v 1.33 2005/04/08 12:39:58 vnivanch Exp $
|
||||
// GEANT4 tag $Name: geant4-07-01 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -44,6 +44,7 @@
|
||||
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
|
||||
// 27-05-04 Set integral to be a default regime (V.Ivanchenko)
|
||||
// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko)
|
||||
// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
@@ -61,6 +62,7 @@
|
||||
#include "G4IonFluctuations.hh"
|
||||
#include "G4UniversalFluctuation.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -70,14 +72,14 @@ G4ionIonisation::G4ionIonisation(const G4String& name)
|
||||
: G4VEnergyLossProcess(name),
|
||||
theParticle(0),
|
||||
theBaseParticle(0),
|
||||
isInitialised(false),
|
||||
subCutoff(false)
|
||||
isInitialised(false)
|
||||
{
|
||||
SetDEDXBinning(120);
|
||||
SetLambdaBinning(120);
|
||||
SetMinKinEnergy(0.1*keV);
|
||||
SetMaxKinEnergy(100.0*TeV);
|
||||
SetVerboseLevel(0);
|
||||
corr = G4LossTableManager::Instance()->EmCorrections();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -101,14 +103,19 @@ void G4ionIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* pa
|
||||
SetBaseParticle(theBaseParticle);
|
||||
SetSecondaryParticle(G4Electron::Electron());
|
||||
|
||||
if(theBaseParticle) baseMass = theBaseParticle->GetPDGMass();
|
||||
else baseMass = theParticle->GetPDGMass();
|
||||
|
||||
flucModel = new G4IonFluctuations();
|
||||
|
||||
eth = 2.0*MeV;
|
||||
|
||||
G4VEmModel* em = new G4BraggIonModel();
|
||||
em->SetLowEnergyLimit(0.1*keV);
|
||||
em->SetHighEnergyLimit(2.0*MeV);
|
||||
em->SetHighEnergyLimit(eth);
|
||||
AddEmModel(1, em, flucModel);
|
||||
G4VEmModel* em1 = new G4BetheBlochModel();
|
||||
em1->SetLowEnergyLimit(2.0*MeV);
|
||||
em1->SetLowEnergyLimit(eth);
|
||||
em1->SetHighEnergyLimit(100.0*TeV);
|
||||
AddEmModel(2, em1, flucModel);
|
||||
|
||||
@@ -120,24 +127,15 @@ void G4ionIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* pa
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4ionIonisation::PrintInfoDefinition()
|
||||
void G4ionIonisation::PrintInfo()
|
||||
{
|
||||
G4VEnergyLossProcess::PrintInfoDefinition();
|
||||
|
||||
G4cout << " Scaling relation is used to proton dE/dx and range"
|
||||
<< G4endl
|
||||
<< " Bether-Bloch model for Escaled > 2 MeV, "
|
||||
<< "parametrisation of Bragg peak below."
|
||||
<< " Bether-Bloch model for Escaled > " << eth << " MeV, ICRU49 "
|
||||
<< "parametrisation for alpha particles below."
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4ionIonisation::SetSubCutoff(G4bool val)
|
||||
{
|
||||
subCutoff = val;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user