Import Geant4 7.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 11:11:55 +02:00
parent e083ffb441
commit 516dbf1a58
5914 changed files with 202605 additions and 71141 deletions
@@ -1,250 +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: G4AnnihiToMuPair.cc,v 1.3 2004/03/10 16:48:45 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-01 $
//
// ------------ G4AnnihiToMuPair physics process ------
// by H.Burkhardt, S. Kelner and R. Kokoulin, November 2002
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......//
//
// 04.02.03 : cosmetic simplifications (mma)
// 27.01.03 : first implementation (hbu)
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4AnnihiToMuPair.hh"
#include "G4ios.hh"
#include "Randomize.hh"
#include "G4Positron.hh"
#include "G4MuonPlus.hh"
#include "G4MuonMinus.hh"
#include "G4Material.hh"
#include "G4Step.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// constructor
G4AnnihiToMuPair::G4AnnihiToMuPair(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type)
{
//e+ Energy threshold
const G4double Mu_massc2 = G4MuonPlus::MuonPlus()->GetPDGMass();
LowestEnergyLimit = 2*Mu_massc2*Mu_massc2/electron_mass_c2 - electron_mass_c2;
//modele ok up to 1000 TeV due to neglected Z-interference
HighestEnergyLimit = 1000*TeV;
CrossSecFactor = 1.;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4AnnihiToMuPair::~G4AnnihiToMuPair() // (empty) destructor
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4AnnihiToMuPair::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Positron::Positron() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4AnnihiToMuPair::BuildPhysicsTable(const G4ParticleDefinition&)
// Build cross section and mean free path tables
//here no tables, just calling PrintInfoDefinition
{
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4AnnihiToMuPair::SetCrossSecFactor(G4double fac)
// Set the factor to artificially increase the cross section
{
CrossSecFactor = fac;
G4cout << "The cross section for AnnihiToMuPair is artificially "
<< "increased by the CrossSecFactor=" << CrossSecFactor << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4AnnihiToMuPair::ComputeCrossSectionPerAtom(G4double Epos, G4double Z)
// Calculates the microscopic cross section in GEANT4 internal units.
// It gives a good description from threshold to 1000 GeV
{
static const G4double Mmuon = G4MuonPlus::MuonPlus()->GetPDGMass();
static const G4double Rmuon = elm_coupling/Mmuon; //classical particle radius
static const G4double Sig0 = pi*Rmuon*Rmuon/3.; //constant in crossSection
G4double CrossSection = 0.;
if (Epos < LowestEnergyLimit) return CrossSection;
G4double xi = LowestEnergyLimit/Epos;
G4double SigmaEl = Sig0*xi*(1.+xi/2.)*sqrt(1.-xi); // per electron
CrossSection = SigmaEl*Z; // number of electrons per atom
CrossSection *= CrossSecFactor; //increase the CrossSection by (default 1)
return CrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4AnnihiToMuPair::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()
+electron_mass_c2;
G4Material* aMaterial = aTrack.GetMaterial();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double SIGMA = 0 ;
for ( size_t i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
G4double AtomicZ = (*theElementVector)[i]->GetZ();
SIGMA += NbOfAtomsPerVolume[i] *
ComputeCrossSectionPerAtom(PositronEnergy,AtomicZ);
}
return SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4AnnihiToMuPair::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
//
// generation of e+e- -> mu+mu-
//
{
aParticleChange.Initialize(aTrack);
static const G4double Mele=electron_mass_c2;
static const G4double Mmuon=G4MuonPlus::MuonPlus()->GetPDGMass();
// current Positron energy and direction, return if energy too low
const G4DynamicParticle *aDynamicPositron = aTrack.GetDynamicParticle();
G4double Epos = aDynamicPositron->GetKineticEnergy()+Mele;
if (Epos < LowestEnergyLimit)
{ G4cout
<< "error in G4AnnihiToMuPair::PostStepDoIt called with energy below"
" threshold Epos= "
<< Epos << G4endl; // shoud never happen
G4Exception(10);
}
if (Epos < LowestEnergyLimit)
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
G4ParticleMomentum PositronDirection =
aDynamicPositron->GetMomentumDirection();
G4double xi = LowestEnergyLimit/Epos; // xi is always less than 1,
// goes to 0 at high Epos
// generate cost
//
G4double cost;
do cost = 2.*G4UniformRand()-1.;
while (2.*G4UniformRand() > 1.+xi+cost*cost*(1.-xi) );
//1+cost**2 at high Epos
G4double sint = sqrt(1.-cost*cost);
// generate phi
//
G4double phi=2.*pi*G4UniformRand();
G4double Ecm = sqrt(0.5*Mele*(Epos+Mele));
G4double Pcm = sqrt(Ecm*Ecm-Mmuon*Mmuon);
G4double beta = sqrt((Epos-Mele)/(Epos+Mele));
G4double gamma = Ecm/Mele; // =sqrt((Epos+Mele)/(2.*Mele));
G4double Pt = Pcm*sint;
// energy and momentum of the muons in the Lab
//
G4double EmuPlus = gamma*( Ecm+cost*beta*Pcm);
G4double EmuMinus = gamma*( Ecm-cost*beta*Pcm);
G4double PmuPlusZ = gamma*(beta*Ecm+cost* Pcm);
G4double PmuMinusZ = gamma*(beta*Ecm-cost* Pcm);
G4double PmuPlusX = Pt*cos(phi);
G4double PmuPlusY = Pt*sin(phi);
G4double PmuMinusX =-Pt*cos(phi);
G4double PmuMinusY =-Pt*sin(phi);
// absolute momenta
G4double PmuPlus = sqrt(Pt*Pt+PmuPlusZ *PmuPlusZ );
G4double PmuMinus = sqrt(Pt*Pt+PmuMinusZ*PmuMinusZ);
// mu+ mu- directions for Positron in z-direction
//
G4ThreeVector
MuPlusDirection ( PmuPlusX/PmuPlus, PmuPlusY/PmuPlus, PmuPlusZ/PmuPlus );
G4ThreeVector
MuMinusDirection(PmuMinusX/PmuMinus,PmuMinusY/PmuMinus,PmuMinusZ/PmuMinus);
// rotate to actual Positron direction
//
MuPlusDirection.rotateUz(PositronDirection);
MuMinusDirection.rotateUz(PositronDirection);
aParticleChange.SetNumberOfSecondaries(2);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1= new G4DynamicParticle(
G4MuonPlus::MuonPlus(),MuPlusDirection,EmuPlus-Mmuon);
aParticleChange.AddSecondary(aParticle1);
// create G4DynamicParticle object for the particle2
G4DynamicParticle* aParticle2= new G4DynamicParticle(
G4MuonMinus::MuonMinus(),MuMinusDirection,EmuMinus-Mmuon);
aParticleChange.AddSecondary(aParticle2);
// Kill the incident positron
//
aParticleChange.SetMomentumChange( 0., 0., 0. );
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetStatusChange(fStopAndKill);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4AnnihiToMuPair::PrintInfoDefinition()
{
G4String comments ="e+e->mu+mu- annihilation, atomic e- at rest.\n";
G4cout << G4endl << GetProcessName() << ": " << comments
<< " threshold at " << LowestEnergyLimit/GeV << " GeV"
<< " good description up to "
<< HighestEnergyLimit/TeV << " TeV for all Z." << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,306 @@
//
// ********************************************************************
// * 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: G4BetheBlochModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class header file
//
//
// File name: G4BetheBlochModel
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
// Creation date: 03.01.2002
//
// Modifications:
//
// 04-12-02 Fix problem of G4DynamicParticle constructor (V.Ivanchenko)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BetheBlochModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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)
{
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
}
//....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);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cut)
{
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double cutEnergy = min(cut,tmax);
G4double tau = kineticEnergy/mass;
G4double gam = tau + 1.0;
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;
if(0.5 == spin) {
G4double del = 0.5*cutEnergy/(kineticEnergy + mass);
dedx += del*del;
}
// density correction
G4double x = log(bg2)/twoln10;
if ( x >= x0den ) {
dedx -= twoln10*x - cden ;
if ( x < x1den ) dedx -= aden*pow((x1den-x),mden) ;
}
// shell correction
G4double sh = 0.0;
x = 1.0;
if ( bg2 > bg2lim ) {
for (G4int k=0; k<3; k++) {
x *= bg2 ;
sh += shellCorrectionVector[k]/x;
}
} else {
for (G4int k=0; k<3; k++) {
x *= bg2lim ;
sh += shellCorrectionVector[k]/x;
}
sh *= log(tau/taul)/log(taulim/taul);
}
dedx -= sh;
// now compute the total ionization loss
if (dedx < 0.0) dedx = 0.0 ;
dedx *= twopi_mc2_rcl2*chargeSquare*eDensity/beta2;
return dedx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::CrossSection(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxKinEnergy)
{
G4double cross = 0.0;
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double maxEnergy = min(tmax,maxKinEnergy);
if(cutEnergy < maxEnergy) {
G4double totEnergy = kineticEnergy + mass;
G4double energy2 = totEnergy*totEnergy;
G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/energy2;
cross = 1.0/cutEnergy - 1.0/maxEnergy - beta2*log(maxEnergy/cutEnergy)/tmax;
// +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;
}
// G4cout << "BB: e= " << kineticEnergy << " tmin= " << cutEnergy << " tmax= " << tmax
// << " cross= " << cross << G4endl;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DynamicParticle* G4BetheBlochModel::SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double minEnergy,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
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;
G4double deltaKinEnergy, f;
// sampling follows ...
do {
G4double q = G4UniformRand();
deltaKinEnergy = minKinEnergy*maxKinEnergy/(minKinEnergy*(1.0 - q) + maxKinEnergy*q);
f = 1.0 - beta2*deltaKinEnergy/tmax;
if( 0.5 == spin ) f += 0.5*deltaKinEnergy*deltaKinEnergy/etot2;
if(f > 1.0) {
G4cout << "G4BetheBlochModel::SampleSecondary Warning! "
<< "Majorant 1.0 < "
<< f << " for Edelta= " << deltaKinEnergy
<< G4endl;
}
} while( G4UniformRand() > f );
G4double totMomentum = totEnergy*sqrt(beta2);
G4double deltaMomentum =
sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
G4double cost = deltaKinEnergy * (totEnergy + electron_mass_c2) /
(deltaMomentum * totMomentum);
G4double sint = sqrt(1.0 - cost*cost);
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
G4ThreeVector direction = dp->GetMomentumDirection();
deltaDirection.rotateUz(direction);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* delta = new G4DynamicParticle(G4Electron::Electron(),
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);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,143 @@
//
// ********************************************************************
// * 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: G4BohrFluctuations.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4BohrFluctuations
//
// Author: Vladimir Ivanchenko
//
// Creation date: 02.04.2003
//
// Modifications:
//
// 23-05-03 Add control on parthalogical cases (V.Ivanchenko)
// 16-10-03 Changed interface to Initialisation (V.Ivanchenko)
//
// Class Description: Sampling of Gaussion fluctuations
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BohrFluctuations.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4BohrFluctuations::G4BohrFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
particle(0),
minNumberInteractionsBohr(10.0),
minFraction(0.2),
xmin(0.2),
minLoss(0.001*eV)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BohrFluctuations::~G4BohrFluctuations()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BohrFluctuations::InitialiseMe(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BohrFluctuations::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
if(meanLoss <= minLoss) return meanLoss;
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
G4double navr = minNumberInteractionsBohr;
// Gaussian fluctuation
G4bool gauss = true;
if (meanLoss < minNumberInteractionsBohr*tmax) {
navr = meanLoss*meanLoss/siga;
if (navr < minNumberInteractionsBohr) gauss = false;
}
// G4cout << "### meanLoss= " << meanLoss << " navr= " << navr << " sig= " << sqrt(siga) << G4endl;
if(gauss) {
// Increase fluctuations for big fractional energy loss
if ( meanLoss > minFraction*kineticEnergy ) {
G4double gam = (kineticEnergy - meanLoss)/particleMass + 1.0;
G4double b2 = 1.0 - 1.0/(gam*gam);
if(b2 < xmin*beta2) b2 = xmin*beta2;
G4double x = b2/beta2;
G4double x3 = 1.0/(x*x*x);
siga *= 0.25*(1.0 + x)*(x3 + (1.0/b2 - 0.5)/(1.0/beta2 - 0.5) );
}
siga = sqrt(siga);
G4double 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 (0.0 > loss || loss > twomeanLoss);
}
// Poisson fluctuations
} else {
G4double n = (G4double)(G4Poisson(navr));
loss = meanLoss*n/navr;
}
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,591 @@
//
// ********************************************************************
// * 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: G4BraggIonModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4BraggIonModel
//
// Author: Vladimir Ivanchenko
//
// Creation date: 13.10.2004
//
// Modifications:
//
// Class Description:
//
// Implementation of energy loss and delta-electron production by
// slow charged heavy particles
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BraggIonModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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)
{
if(p) SetParticle(p);
highKinEnergy = 2.0*MeV;
lowKinEnergy = 0.0*MeV;
lowestKinEnergy = 1.0*keV;
theZieglerFactor = eV*cm2*1.0e-15;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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)
{
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&)
{
if(!particle) SetParticle(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggIonModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
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;
if(tkin > lowestKinEnergy) dedx = DEDX(material, tkin);
else dedx = DEDX(material, lowestKinEnergy)*sqrt(tkin/lowestKinEnergy);
if (cutEnergy < tmax) {
G4double tau = kineticEnergy/mass;
G4double gam = tau + 1.0;
G4double bg2 = tau * (tau+2.0);
G4double beta2 = bg2/(gam*gam);
G4double x = cutEnergy/tmax;
dedx += (log(x) + (1.0 - x)*beta2) * twopi_mc2_rcl2
* (material->GetElectronDensity())/beta2;
}
// now compute the total ionization loss
if (dedx < 0.0) dedx = 0.0 ;
dedx *= chargeSquare;
return dedx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggIonModel::CrossSection(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxKinEnergy)
{
G4double cross = 0.0;
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double maxEnergy = min(tmax,maxKinEnergy);
if(cutEnergy < tmax) {
G4double energy = kineticEnergy + mass;
G4double energy2 = energy*energy;
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;
}
// G4cout << "BR: e= " << kineticEnergy << " tmin= " << cutEnergy << " tmax= " << tmax
// << " cross= " << cross << G4endl;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DynamicParticle* G4BraggIonModel::SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmax = min(tmax, maxEnergy);
G4double xmin = min(xmax,tmin);
G4double kineticEnergy = dp->GetKineticEnergy();
G4double energy = kineticEnergy + mass;
G4double energy2 = energy*energy;
G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/energy2;
G4double grej = 1.0;
G4double deltaKinEnergy, f;
G4ThreeVector momentum = dp->GetMomentumDirection();
// sampling follows ...
do {
G4double q = G4UniformRand();
deltaKinEnergy = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
f = 1.0 - beta2*deltaKinEnergy/tmax;
if(f > grej) {
G4cout << "G4BraggIonModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for e= " << deltaKinEnergy
<< G4endl;
}
} while( grej*G4UniformRand() >= f );
G4double deltaMomentum =
sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
G4double totMomentum = sqrt(energy2 - mass*mass);
G4double cost = deltaKinEnergy * (energy + electron_mass_c2) /
(deltaMomentum * totMomentum);
G4double sint = sqrt(1.0 - cost*cost);
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
deltaDirection.rotateUz(momentum);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* delta = new G4DynamicParticle(G4Electron::Electron(),
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);
vdp->push_back(delta);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggIonModel::HasMaterial(const G4Material* material)
{
G4String chFormula = material->GetChemicalFormula() ;
// ICRU Report N49, 1993. Power's model for He.
const size_t numberOfMolecula = 30 ;
SetMoleculaNumber(numberOfMolecula) ;
static G4String name[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",
"CO_2", "Cellulose-Nitrat", "C_2H_4", "LiF",
"CH_4", "Nylon", "Polycarbonate", "(CH_2)_N-Polyetilene", "PMMA",
"(C_8H_8)_N", "SiO_2", "CsI", "H_2O", "H_2O-Gas"} ;
// Special treatment for water in gas state
const G4State theState = material->GetState() ;
if( theState == kStateGas && "H_2O" == chFormula)
chFormula = G4String("H_2O-Gas");
// Search for the material in the table
for (size_t i=0; i<numberOfMolecula; i++) {
if (chFormula == name[i]) {
SetMoleculaNumber(i) ;
return true ;
}
}
return false ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggIonModel::StoppingPower(const G4Material* material,
G4double kineticEnergy)
{
G4double ionloss = 0.0 ;
if (iMolecula < 30) {
// The data and the fit from:
// ICRU Report N49, 1993. Ziegler's model for protons.
// Proton kinetic energy for parametrisation (keV/amu)
G4double T = kineticEnergy*rateMass/MeV ;
static G4double c[30][7] = {
{8.0080, 3.6287, 23.0700, 14.9900, 0.8507, 0.60, 2.0
},{ 13.3100, 3.7432, 39.4130, 12.1990, 1.0950, 0.38, 1.4
},{ 22.7240, 3.6040, 47.1810, 17.5490, 0.9040, 0.40, 1.4
},{ 24.4040, 2.4032, 48.9440, 27.9730, 1.2933, 0.40, 1.6
},{ 58.4719, 1.5115, 77.6421, 102.490, 1.5811, 0.50, 2.0
},{ 60.5408, 1.6297, 91.7601, 94.1260, 1.3662, 0.50, 2.0
},{ 48.4480, 6.4323, 59.2890, 18.3810, 0.4937, 0.48, 1.6
},{ 59.0346, 5.1305, 47.0866, 30.0857, 0.3500, 0.60, 2.0
},{ 71.8691, 2.8250, 51.1658, 57.1235, 0.4477, 0.60, 2.0
},{ 78.3520, 4.0961, 136.731, 28.4470, 1.0621, 0.52, 1.2
},{ 120.553, 1.5374, 49.8740, 82.2980, 0.8733, 0.45, 1.6
},{ 249.896, 0.6996, -37.274, 248.592, 1.1052, 0.50, 1.5
},{ 246.698, 0.6219, -58.391, 292.921, 0.8186, 0.56, 1.8
},{ 248.563, 0.6235, -36.8968, 306.960, 1.3214, 0.50, 2.0
},{ 25.5860, 1.7125, 154.723, 118.620, 2.2580, 0.50, 2.0
},{ 138.294, 25.6413, 231.873, 17.3780, 0.3218, 0.58, 1.3
},{ 83.2091, 1.1294, 135.7457, 190.865, 2.3461, 0.50, 2.0
},{ 263.542, 1.4754, 1541.446, 781.898, 1.9209, 0.40, 2.0
},{ 59.5545, 1.5354, 132.1523, 153.3537, 2.0262, 0.50, 2.0
},{ 31.7380, 19.820, 125.2100, 6.8910, 0.7242, 0.50, 1.1
},{ 31.7549, 1.5682, 97.4777, 106.0774, 2.3204, 0.50, 2.0
},{ 230.465, 4.8967, 1845.320, 358.641, 1.0774, 0.46, 1.2
},{ 423.444, 5.3761, 1189.114, 319.030, 0.7652, 0.48, 1.5
},{ 86.3410, 3.3322, 91.0433, 73.1091, 0.4650, 0.50, 2.0
},{ 146.105, 9.4344, 515.1500, 82.8860, 0.6239, 0.55, 1.5
},{ 238.050, 5.6901, 372.3575, 146.1835, 0.3992, 0.50, 2.0
},{ 124.2338, 2.6730, 133.8175, 99.4109, 0.7776, 0.50, 2.0
},{ 221.723, 1.5415, 87.7315, 192.5266, 1.0742, 0.50, 2.0
},{ 26.7537, 1.3717, 90.8007, 77.1587, 2.3264, 0.50, 2.0
},{ 37.6121, 1.8052, 73.0250, 66.2070, 1.4038, 0.50, 2.0} };
G4double a1,a2 ;
// Free electron gas model
if ( T < 0.001 ) {
G4double T0 = 0.001 ;
a1 = 1.0 - exp(-c[iMolecula][1]*pow(T0,-2.0+c[iMolecula][5])) ;
a2 = (c[iMolecula][0]*log(T0)/T0 + c[iMolecula][2]/T0) *
exp(-c[iMolecula][4]*pow(T0,-c[iMolecula][6])) +
c[iMolecula][3]/(T0*T0) ;
ionloss *= sqrt(T/T0) ;
// Main parametrisation
} else {
a1 = 1.0 - exp(-c[iMolecula][1]*pow(T,-2.0+c[iMolecula][5])) ;
a2 = (c[iMolecula][0]*log(T)/T + c[iMolecula][2]/T) *
exp(-c[iMolecula][4]*pow(T,-c[iMolecula][6])) +
c[iMolecula][3]/(T*T) ;
}
// He effective charge
G4double z = (material->GetTotNbOfElectPerVolume()) /
(material->GetTotNbOfAtomsPerVolume()) ;
ionloss = a1*a2 / HeEffChargeSquare(z, T*keV) ;
if ( ionloss < 0.0) ionloss = 0.0 ;
}
return ionloss ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggIonModel::ElectronicStoppingPower(G4double z,
G4double kineticEnergy) const
{
G4double ionloss ;
G4int i = G4int(z)-1 ; // index of atom
if(i < 0) i = 0 ;
if(i > 91) i = 91 ;
// The data and the fit from:
// ICRU Report 49, 1993. Ziegler's type of parametrisations.
// Proton kinetic energy for parametrisation (keV/amu)
// He energy in internal units of parametrisation formula (MeV)
G4double T = kineticEnergy*rateMass/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
},{ 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
},{ 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
},{ 2.1, 0.65, 49.34, 1.788, 4.133
},{ 1.729, 0.6562, 53.41, 2.405, 3.845
},{ 1.402, 0.6791, 58.98, 3.528, 3.211
},{ 1.117, 0.7044, 69.69, 3.705, 2.156
},{ 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
},{ 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
},{ 6.57, 0.4322, 84.76, 15.53, 2.779
},{ 5.738, 0.4492, 84.6, 14.18, 3.101
},{ 5.013, 0.4707, 85.8, 16.55, 3.211
},{ 4.32, 0.4947, 76.14, 10.85, 5.441
},{ 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
},{ 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
},{ 4.667, 0.5095, 124.3, 2.102, 1.667
},{ 2.44, 0.6346, 105.0, 0.83, 2.851
},{ 1.413, 0.7377, 147.9, 1.466, 1.016
},{ 11.72, 0.3826, 102.8, 9.231, 4.371
},{ 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
},{ 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
},{ 4.306, 0.5658, 97.99, 5.514, 5.754
},{ 3.615, 0.6197, 86.26, 0.333, 8.689
},{ 5.8, 0.49, 147.2, 6.903, 1.289
},{ 5.6, 0.49, 130.0, 10.0, 2.844
},{ 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
},{ 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
},{ 3.949, 0.6209, 200.5, 1.878, 0.9126
},{ 14.4, 0.3923, 152.5, 8.354, 2.597
},{ 10.99, 0.4599, 138.4, 4.811, 3.726
},{ 16.6, 0.3773, 224.1, 6.28, 0.9121
},{ 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
},{ 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
},{ 9.952, 0.4318, 233.5, 5.065, 0.9244
},{ 9.272, 0.4345, 210.0, 4.911, 1.258
},{ 10.13, 0.4146, 225.7, 5.525, 1.055
},{ 8.949, 0.4304, 213.3, 5.071, 1.221
},{ 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
},{ 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
},{ 6.335, 0.4825, 255.1, 2.834, 0.8228
},{ 4.314, 0.5558, 214.8, 2.354, 1.263
},{ 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
},{ 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
},{ 2.324, 0.6997, 216.0, 1.599, 1.399
},{ 1.961, 0.7286, 223.0, 1.621, 1.296
},{ 1.75, 0.7427, 350.1, 0.9789, 0.5507
},{ 10.31, 0.4613, 261.2, 4.738, 0.9899
},{ 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
},{ 5.408, 0.5811, 235.7, 3.961, 1.358
},{ 5.218, 0.5828, 245.0, 3.838, 1.25}
};
// Free electron gas model
if ( T < 0.001 ) {
G4double slow = a[i][0] ;
G4double shigh = log( 1.0 + a[i][3]*1000.0 + a[i][4]*0.001 )
* a[i][2]*1000.0 ;
ionloss = slow*shigh / (slow + shigh) ;
ionloss *= sqrt(T*1000.0) ;
// Main parametrisation
} else {
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) ;
}
if ( ionloss < 0.0) ionloss = 0.0 ;
// He effective charge
ionloss /= HeEffChargeSquare(z, T*MeV);
return ionloss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggIonModel::DEDX(const G4Material* material,
G4double kineticEnergy)
{
G4double eloss = 0.0;
const G4int numberOfElements = material->GetNumberOfElements();
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
// compaund material with parametrisation
if( HasMaterial(material) ) {
eloss = StoppingPower(material, kineticEnergy)
* (material->GetTotNbOfAtomsPerVolume());
eloss *= material->GetTotNbOfAtomsPerVolume();
if(1 < numberOfElements) {
G4int nAtoms = 0;
const G4int* theAtomsVector = material->GetAtomsVector();
for (G4int iel=0; iel<numberOfElements; iel++) {
nAtoms += theAtomsVector[iel];
}
eloss /= nAtoms;
}
// pure material
} else if(1 == numberOfElements) {
G4double z = material->GetZ();
eloss = ElectronicStoppingPower(z, kineticEnergy)
* (material->GetTotNbOfAtomsPerVolume());
// Brugg's rule calculation
} else {
const G4ElementVector* theElementVector =
material->GetElementVector() ;
// loop for the elements in the material
for (G4int i=0; i<numberOfElements; i++)
{
const G4Element* element = (*theElementVector)[i] ;
eloss += ElectronicStoppingPower(element->GetZ(), kineticEnergy)
* theAtomicNumDensityVector[i];
}
}
return eloss*theZieglerFactor;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggIonModel::HeEffChargeSquare(G4double z, G4double kinEnergyHe) const
{
// The aproximation of He effective charge from:
// J.F.Ziegler, J.P. Biersack, U. Littmark
// The Stopping and Range of Ions in Matter,
// Vol.1, Pergamon Press, 1985
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 x = c[0] ;
G4double y = 1.0 ;
for (G4int i=1; i<6; i++) {
y *= e ;
x += y * c[i] ;
}
G4double w = 7.6 - e ;
w = 1.0 + (0.007 + 0.00005*z) * exp( -w*w ) ;
w = 4.0 * (1.0 - exp(-x)) * w * w ;
return w;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,693 @@
//
// ********************************************************************
// * 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: G4BraggModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4BraggModel
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// 04-12-02 Fix problem of G4DynamicParticle constructor (V.Ivanchenko)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
// 04-06-03 Fix compilation warnings (V.Ivanchenko)
// 12-09-04 Add lowestKinEnergy and change order of if in DEDX method (V.Ivanchenko)
// Class Description:
//
// Implementation of energy loss and delta-electron production by
// slow charged heavy particles
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BraggModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4BraggModel::G4BraggModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),
particle(0),
protonMassAMU(1.007276),
iMolecula(0),
isIon(false)
{
if(p) SetParticle(p);
highKinEnergy = 2.0*MeV;
lowKinEnergy = 0.0*MeV;
lowestKinEnergy = 1.0*keV;
theZieglerFactor = eV*cm2*1.0e-15;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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)
{
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
}
//....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);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
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;
if(tkin > lowestKinEnergy) dedx = DEDX(material, tkin);
else dedx = DEDX(material, lowestKinEnergy)*sqrt(tkin/lowestKinEnergy);
if (cutEnergy < tmax) {
G4double tau = kineticEnergy/mass;
G4double gam = tau + 1.0;
G4double bg2 = tau * (tau+2.0);
G4double beta2 = bg2/(gam*gam);
G4double x = cutEnergy/tmax;
dedx += (log(x) + (1.0 - x)*beta2) * twopi_mc2_rcl2
* (material->GetElectronDensity())/beta2;
}
// now compute the total ionization loss
if (dedx < 0.0) dedx = 0.0 ;
dedx *= chargeSquare;
return dedx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::CrossSection(const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxKinEnergy)
{
G4double cross = 0.0;
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double maxEnergy = min(tmax,maxKinEnergy);
if(cutEnergy < tmax) {
G4double energy = kineticEnergy + mass;
G4double energy2 = energy*energy;
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;
}
// G4cout << "BR: e= " << kineticEnergy << " tmin= " << cutEnergy << " tmax= " << tmax
// << " cross= " << cross << G4endl;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DynamicParticle* G4BraggModel::SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmax = min(tmax, maxEnergy);
G4double xmin = min(xmax,tmin);
G4double kineticEnergy = dp->GetKineticEnergy();
G4double energy = kineticEnergy + mass;
G4double energy2 = energy*energy;
G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/energy2;
G4double grej = 1.0;
G4double deltaKinEnergy, f;
G4ThreeVector momentum = dp->GetMomentumDirection();
// sampling follows ...
do {
G4double q = G4UniformRand();
deltaKinEnergy = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
f = 1.0 - beta2*deltaKinEnergy/tmax;
if(f > grej) {
G4cout << "G4BraggModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for e= " << deltaKinEnergy
<< G4endl;
}
} while( grej*G4UniformRand() >= f );
G4double deltaMomentum =
sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
G4double totMomentum = sqrt(energy2 - mass*mass);
G4double cost = deltaKinEnergy * (energy + electron_mass_c2) /
(deltaMomentum * totMomentum);
G4double sint = sqrt(1.0 - cost*cost);
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
deltaDirection.rotateUz(momentum);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* delta = new G4DynamicParticle(G4Electron::Electron(),
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;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::HasMaterial(const G4Material* material)
{
const size_t numberOfMolecula = 11 ;
SetMoleculaNumber(numberOfMolecula) ;
G4String chFormula = material->GetChemicalFormula() ;
// ICRU Report N49, 1993. Power's model for He.
static G4String molName[numberOfMolecula] = {
"Al_2O_3", "CO_2", "CH_4",
"(C_2H_4)_N-Polyethylene", "(C_2H_4)_N-Polypropylene", "(C_8H_8)_N",
"C_3H_8", "SiO_2", "H_2O",
"H_2O-Gas", "Graphite" } ;
// Special treatment for water in gas state
const G4State theState = material->GetState() ;
if( theState == kStateGas && "H_2O" == chFormula) {
chFormula = G4String("H_2O-Gas");
}
// Search for the material in the table
for (size_t i=0; i<numberOfMolecula; i++) {
if (chFormula == molName[i]) {
SetMoleculaNumber(i) ;
return true ;
}
}
return false ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::StoppingPower(const G4Material* material,
G4double kineticEnergy)
{
G4double ionloss = 0.0 ;
if (iMolecula < 11) {
// The data and the fit from:
// ICRU Report N49, 1993. Ziegler's model for protons.
// Proton kinetic energy for parametrisation (keV/amu)
G4double T = kineticEnergy/(keV*protonMassAMU) ;
static G4double a[11][5] = {
{1.187E+1, 1.343E+1, 1.069E+4, 7.723E+2, 2.153E-2},
{7.802E+0, 8.814E+0, 8.303E+3, 7.446E+2, 7.966E-3},
{7.294E+0, 8.284E+0, 5.010E+3, 4.544E+2, 8.153E-3},
{8.646E+0, 9.800E+0, 7.066E+3, 4.581E+2, 9.383E-3},
{1.286E+1, 1.462E+1, 5.625E+3, 2.621E+3, 3.512E-2},
{3.229E+1, 3.696E+1, 8.918E+3, 3.244E+3, 1.273E-1},
{1.604E+1, 1.825E+1, 6.967E+3, 2.307E+3, 3.775E-2},
{8.049E+0, 9.099E+0, 9.257E+3, 3.846E+2, 1.007E-2},
{4.015E+0, 4.542E+0, 3.955E+3, 4.847E+2, 7.904E-3},
{4.571E+0, 5.173E+0, 4.346E+3, 4.779E+2, 8.572E-3},
{2.631E+0, 2.601E+0, 1.701E+3, 1.279E+3, 1.638E-2} };
if ( T < 10.0 ) {
ionloss = a[iMolecula][0] * sqrt(T) ;
} else if ( T < 10000.0 ) {
G4double slow = a[iMolecula][1] * pow(T, 0.45) ;
G4double shigh = log( 1.0 + a[iMolecula][3]/T
+ a[iMolecula][4]*T ) * a[iMolecula][2]/T ;
ionloss = slow*shigh / (slow + shigh) ;
}
if ( ionloss < 0.0) ionloss = 0.0 ;
if ( 10 == iMolecula ) {
if (T < 100.0) {
ionloss *= (1.0+0.023+0.0066*log10(T));
}
else if (T < 700.0) {
ionloss *=(1.0+0.089-0.0248*log10(T-99.));
}
else if (T < 10000.0) {
ionloss *=(1.0+0.089-0.0248*log10(700.-99.));
}
}
// pure material (normally not the case for this function)
} else if(1 == (material->GetNumberOfElements())) {
G4double z = material->GetZ() ;
ionloss = ElectronicStoppingPower( z, kineticEnergy ) ;
}
return ionloss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ElectronicStoppingPower(G4double z,
G4double kineticEnergy) const
{
G4double ionloss ;
G4int i = G4int(z)-1 ; // index of atom
if(i < 0) i = 0 ;
if(i > 91) i = 91 ;
// The data and the fit from:
// ICRU Report 49, 1993. Ziegler's type of parametrisations.
// Proton kinetic energy for parametrisation (keV/amu)
G4double T = kineticEnergy/(keV*protonMassAMU) ;
static G4double a[92][5] = {
{1.254E+0, 1.440E+0, 2.426E+2, 1.200E+4, 1.159E-1},
{1.229E+0, 1.397E+0, 4.845E+2, 5.873E+3, 5.225E-2},
{1.411E+0, 1.600E+0, 7.256E+2, 3.013E+3, 4.578E-2},
{2.248E+0, 2.590E+0, 9.660E+2, 1.538E+2, 3.475E-2},
{2.474E+0, 2.815E+0, 1.206E+3, 1.060E+3, 2.855E-2},
{2.631E+0, 2.601E+0, 1.701E+3, 1.279E+3, 1.638E-2},
{2.954E+0, 3.350E+0, 1.683E+3, 1.900E+3, 2.513E-2},
{2.652E+0, 3.000E+0, 1.920E+3, 2.000E+3, 2.230E-2},
{2.085E+0, 2.352E+0, 2.157E+3, 2.634E+3, 1.816E-2},
{1.951E+0, 2.199E+0, 2.393E+3, 2.699E+3, 1.568E-2},
{2.542E+0, 2.869E+0, 2.628E+3, 1.854E+3, 1.472E-2},
{3.791E+0, 4.293E+0, 2.862E+3, 1.009E+3, 1.397E-2},
{4.154E+0, 4.739E+0, 2.766E+3, 1.645E+2, 2.023E-2},
{4.914E+0, 5.598E+0, 3.193E+3, 2.327E+2, 1.419E-2},
{3.232E+0, 3.647E+0, 3.561E+3, 1.560E+3, 1.267E-2},
{3.447E+0, 3.891E+0, 3.792E+3, 1.219E+3, 1.211E-2},
{5.301E+0, 6.008E+0, 3.969E+3, 6.451E+2, 1.183E-2},
{5.731E+0, 6.500E+0, 4.253E+3, 5.300E+2, 1.123E-2},
{5.152E+0, 5.833E+0, 4.482E+3, 5.457E+2, 1.129E-2},
{5.521E+0, 6.252E+0, 4.710E+3, 5.533E+2, 1.112E-2},
{5.201E+0, 5.884E+0, 4.938E+3, 5.609E+2, 9.995E-3},
{4.858E+0, 5.489E+0, 5.260E+3, 6.511E+2, 8.930E-3},
{4.479E+0, 5.055E+0, 5.391E+3, 9.523E+2, 9.117E-3},
{3.983E+0, 4.489E+0, 5.616E+3, 1.336E+3, 8.413E-3},
{3.469E+0, 3.907E+0, 5.725E+3, 1.461E+3, 8.829E-3},
{3.519E+0, 3.963E+0, 6.065E+3, 1.243E+3, 7.782E-3},
{3.140E+0, 3.535E+0, 6.288E+3, 1.372E+3, 7.361E-3},
{3.553E+0, 4.004E+0, 6.205E+3, 5.551E+2, 8.763E-3},
{3.696E+0, 4.194E+0, 4.649E+3, 8.113E+1, 2.242E-2},
{4.210E+0, 4.750E+0, 6.953E+3, 2.952E+2, 6.809E-3},
{5.041E+0, 5.697E+0, 7.173E+3, 2.026E+2, 6.725E-3},
{5.554E+0, 6.300E+0, 6.496E+3, 1.100E+2, 9.689E-3},
{5.323E+0, 6.012E+0, 7.611E+3, 2.925E+2, 6.447E-3},
{5.874E+0, 6.656E+0, 7.395E+3, 1.175E+2, 7.684E-3},
{6.658E+0, 7.536E+0, 7.694E+3, 2.223E+2, 6.509E-3},
{6.413E+0, 7.240E+0, 1.185E+4, 1.537E+2, 2.880E-3},
{5.694E+0, 6.429E+0, 8.478E+3, 2.929E+2, 6.087E-3},
{6.339E+0, 7.159E+0, 8.693E+3, 3.303E+2, 6.003E-3},
{6.407E+0, 7.234E+0, 8.907E+3, 3.678E+2, 5.889E-3},
{6.734E+0, 7.603E+0, 9.120E+3, 4.052E+2, 5.765E-3},
{6.901E+0, 7.791E+0, 9.333E+3, 4.427E+2, 5.587E-3},
{6.424E+0, 7.248E+0, 9.545E+3, 4.802E+2, 5.376E-3},
{6.799E+0, 7.671E+0, 9.756E+3, 5.176E+2, 5.315E-3},
{6.109E+0, 6.887E+0, 9.966E+3, 5.551E+2, 5.151E-3},
{5.924E+0, 6.677E+0, 1.018E+4, 5.925E+2, 4.919E-3},
{5.238E+0, 5.900E+0, 1.038E+4, 6.300E+2, 4.758E-3},
{5.345E+0, 6.038E+0, 6.790E+3, 3.978E+2, 1.676E-2},
{5.814E+0, 6.554E+0, 1.080E+4, 3.555E+2, 4.626E-3},
{6.229E+0, 7.024E+0, 1.101E+4, 3.709E+2, 4.540E-3},
{6.409E+0, 7.227E+0, 1.121E+4, 3.864E+2, 4.474E-3},
{7.500E+0, 8.480E+0, 8.608E+3, 3.480E+2, 9.074E-3},
{6.979E+0, 7.871E+0, 1.162E+4, 3.924E+2, 4.402E-3},
{7.725E+0, 8.716E+0, 1.183E+4, 3.948E+2, 4.376E-3},
{8.337E+0, 9.425E+0, 1.051E+4, 2.696E+2, 6.206E-3},
{7.287E+0, 8.218E+0, 1.223E+4, 3.997E+2, 4.447E-3},
{7.899E+0, 8.911E+0, 1.243E+4, 4.021E+2, 4.511E-3},
{8.041E+0, 9.071E+0, 1.263E+4, 4.045E+2, 4.540E-3},
{7.488E+0, 8.444E+0, 1.283E+4, 4.069E+2, 4.420E-3},
{7.291E+0, 8.219E+0, 1.303E+4, 4.093E+2, 4.298E-3},
{7.098E+0, 8.000E+0, 1.323E+4, 4.118E+2, 4.182E-3},
{6.909E+0, 7.786E+0, 1.343E+4, 4.142E+2, 4.058E-3},
{6.728E+0, 7.580E+0, 1.362E+4, 4.166E+2, 3.976E-3},
{6.551E+0, 7.380E+0, 1.382E+4, 4.190E+2, 3.877E-3},
{6.739E+0, 7.592E+0, 1.402E+4, 4.214E+2, 3.863E-3},
{6.212E+0, 6.996E+0, 1.421E+4, 4.239E+2, 3.725E-3},
{5.517E+0, 6.210E+0, 1.440E+4, 4.263E+2, 3.632E-3},
{5.220E+0, 5.874E+0, 1.460E+4, 4.287E+2, 3.498E-3},
{5.071E+0, 5.706E+0, 1.479E+4, 4.330E+2, 3.405E-3},
{4.926E+0, 5.542E+0, 1.498E+4, 4.335E+2, 3.342E-3},
{4.788E+0, 5.386E+0, 1.517E+4, 4.359E+2, 3.292E-3},
{4.893E+0, 5.505E+0, 1.536E+4, 4.384E+2, 3.243E-3},
{5.028E+0, 5.657E+0, 1.555E+4, 4.408E+2, 3.195E-3},
{4.738E+0, 5.329E+0, 1.574E+4, 4.432E+2, 3.186E-3},
{4.587E+0, 5.160E+0, 1.541E+4, 4.153E+2, 3.406E-3},
{5.201E+0, 5.851E+0, 1.612E+4, 4.416E+2, 3.122E-3},
{5.071E+0, 5.704E+0, 1.630E+4, 4.409E+2, 3.082E-3},
{4.946E+0, 5.563E+0, 1.649E+4, 4.401E+2, 2.965E-3},
{4.477E+0, 5.034E+0, 1.667E+4, 4.393E+2, 2.871E-3},
{4.844E+0, 5.458E+0, 7.852E+3, 9.758E+2, 2.077E-2},
{4.307E+0, 4.843E+0, 1.704E+4, 4.878E+2, 2.882E-3},
{4.723E+0, 5.311E+0, 1.722E+4, 5.370E+2, 2.913E-3},
{5.319E+0, 5.982E+0, 1.740E+4, 5.863E+2, 2.871E-3},
{5.956E+0, 6.700E+0, 1.780E+4, 6.770E+2, 2.660E-3},
{6.158E+0, 6.928E+0, 1.777E+4, 5.863E+2, 2.812E-3},
{6.203E+0, 6.979E+0, 1.795E+4, 5.863E+2, 2.776E-3},
{6.181E+0, 6.954E+0, 1.812E+4, 5.863E+2, 2.748E-3},
{6.949E+0, 7.820E+0, 1.830E+4, 5.863E+2, 2.737E-3},
{7.506E+0, 8.448E+0, 1.848E+4, 5.863E+2, 2.727E-3},
{7.648E+0, 8.609E+0, 1.866E+4, 5.863E+2, 2.697E-3},
{7.711E+0, 8.679E+0, 1.883E+4, 5.863E+2, 2.641E-3},
{7.407E+0, 8.336E+0, 1.901E+4, 5.863E+2, 2.603E-3},
{7.290E+0, 8.204E+0, 1.918E+4, 5.863E+2, 2.673E-3}
};
G4double fac = 1.0 ;
// Carbon specific case for E < 40 keV
if ( T < 40.0 && 5 == i) {
fac = sqrt(T/40.0) ;
T = 40.0 ;
// Free electron gas model
} else if ( T < 10.0 ) {
fac = sqrt(T*0.1) ;
T =10.0 ;
}
// Main parametrisation
G4double slow = a[i][1] * pow(T, 0.45) ;
G4double shigh = log( 1.0 + a[i][3]/T + a[i][4]*T ) * a[i][2]/T ;
ionloss = slow*shigh*fac / (slow + shigh) ;
if ( ionloss < 0.0) ionloss = 0.0 ;
return ionloss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::DEDX(const G4Material* material,
G4double kineticEnergy)
{
G4double eloss = 0.0;
const G4int numberOfElements = material->GetNumberOfElements();
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
// compaund material with parametrisation
if( HasMaterial(material) ) {
eloss = StoppingPower(material, kineticEnergy)
* (material->GetTotNbOfAtomsPerVolume());
eloss *= material->GetTotNbOfAtomsPerVolume();
if(1 < numberOfElements) {
G4int nAtoms = 0;
const G4int* theAtomsVector = material->GetAtomsVector();
for (G4int iel=0; iel<numberOfElements; iel++) {
nAtoms += theAtomsVector[iel];
}
eloss /= nAtoms;
}
// pure material
} else if(1 == numberOfElements) {
G4double z = material->GetZ();
eloss = ElectronicStoppingPower(z, kineticEnergy)
* (material->GetTotNbOfAtomsPerVolume());
// Experimental data exist only for kinetic energy 125 keV
} else if( MolecIsInZiegler1988(material) ) {
// Cycle over elements - calculation based on Bragg's rule
G4double eloss125 = 0.0 ;
const G4ElementVector* theElementVector =
material->GetElementVector();
// loop for the elements in the material
for (G4int i=0; i<numberOfElements; i++) {
const G4Element* element = (*theElementVector)[i] ;
G4double z = element->GetZ() ;
eloss += ElectronicStoppingPower(z,kineticEnergy)
* theAtomicNumDensityVector[i] ;
eloss125 += ElectronicStoppingPower(z,125.0*keV)
* theAtomicNumDensityVector[i] ;
}
// Chemical factor is taken into account
eloss *= ChemicalFactor(kineticEnergy, eloss125) ;
// Brugg's rule calculation
} else {
const G4ElementVector* theElementVector =
material->GetElementVector() ;
// loop for the elements in the material
for (G4int i=0; i<numberOfElements; i++)
{
const G4Element* element = (*theElementVector)[i] ;
eloss += ElectronicStoppingPower(element->GetZ(), kineticEnergy)
* theAtomicNumDensityVector[i];
}
}
return eloss*theZieglerFactor;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::MolecIsInZiegler1988(const G4Material* material)
{
// The list of molecules from
// J.F.Ziegler and J.M.Manoyan, The stopping of ions in compaunds,
// Nucl. Inst. & Meth. in Phys. Res. B35 (1988) 215-228.
G4String myFormula = G4String(" ") ;
const G4String chFormula = material->GetChemicalFormula() ;
if (myFormula == chFormula ) return false ;
// There are no evidence for difference of stopping power depended on
// phase of the compound except for water. The stopping power of the
// water in gas phase can be predicted using Bragg's rule.
//
// No chemical factor for water-gas
myFormula = G4String("H_2O") ;
const G4State theState = material->GetState() ;
if( theState == kStateGas && myFormula == chFormula) return false ;
const size_t numberOfMolecula = 53 ;
// The coffecient from Table.4 of Ziegler & Manoyan
const G4double HeEff = 2.8735 ;
static G4String nameOfMol[numberOfMolecula] = {
"H_2O", "C_2H_4O", "C_3H_6O", "C_2H_2", "C_H_3OH",
"C_2H_5OH", "C_3H_7OH", "C_3H_4", "NH_3", "C_14H_10",
"C_6H_6", "C_4H_10", "C_4H_6", "C_4H_8O", "CCl_4",
"CF_4", "C_6H_8", "C_6H_12", "C_6H_10O", "C_6H_10",
"C_8H_16", "C_5H_10", "C_5H_8", "C_3H_6-Cyclopropane","C_2H_4F_2",
"C_2H_2F_2", "C_4H_8O_2", "C_2H_6", "C_2F_6", "C_2H_6O",
"C_3H_6O", "C_4H_10O", "C_2H_4", "C_2H_4O", "C_2H_4S",
"SH_2", "CH_4", "CCLF_3", "CCl_2F_2", "CHCl_2F",
"(CH_3)_2S", "N_2O", "C_5H_10O", "C_8H_6", "(CH_2)_N",
"(C_3H_6)_N","(C_8H_8)_N", "C_3H_8", "C_3H_6-Propylene", "C_3H_6O",
"C_3H_6S", "C_4H_4S", "C_7H_8"
} ;
static G4double expStopping[numberOfMolecula] = {
66.1, 190.4, 258.7, 42.2, 141.5,
210.9, 279.6, 198.8, 31.0, 267.5,
122.8, 311.4, 260.3, 328.9, 391.3,
206.6, 374.0, 422.0, 432.0, 398.0,
554.0, 353.0, 326.0, 74.6, 220.5,
197.4, 362.0, 170.0, 330.5, 211.3,
262.3, 349.6, 51.3, 187.0, 236.9,
121.9, 35.8, 247.0, 292.6, 268.0,
262.3, 49.0, 398.9, 444.0, 22.91,
68.0, 155.0, 84.0, 74.2, 254.7,
306.8, 324.4, 420.0
} ;
static G4double expCharge[numberOfMolecula] = {
HeEff, HeEff, HeEff, 1.0, HeEff,
HeEff, HeEff, HeEff, 1.0, 1.0,
1.0, HeEff, HeEff, HeEff, HeEff,
HeEff, HeEff, HeEff, HeEff, HeEff,
HeEff, HeEff, HeEff, 1.0, HeEff,
HeEff, HeEff, HeEff, HeEff, HeEff,
HeEff, HeEff, 1.0, HeEff, HeEff,
HeEff, 1.0, HeEff, HeEff, HeEff,
HeEff, 1.0, HeEff, HeEff, 1.0,
1.0, 1.0, 1.0, 1.0, HeEff,
HeEff, HeEff, HeEff
} ;
static G4double numberOfAtomsPerMolecula[numberOfMolecula] = {
3.0, 7.0, 10.0, 4.0, 6.0,
9.0, 12.0, 7.0, 4.0, 24.0,
12.0, 14.0, 10.0, 13.0, 5.0,
5.0, 14.0, 18.0, 17.0, 17.0,
24.0, 15.0, 13.0, 9.0, 8.0,
6.0, 14.0, 8.0, 8.0, 9.0,
10.0, 15.0, 6.0, 7.0, 7.0,
3.0, 5.0, 5.0, 5.0, 5.0,
9.0, 3.0, 16.0, 14.0, 3.0,
9.0, 16.0, 11.0, 9.0, 10.0,
10.0, 9.0, 15.0
} ;
// Search for the compaund in the table
for (size_t i=0; i<numberOfMolecula; i++)
{
if(chFormula == nameOfMol[i]) {
G4double exp125 = expStopping[i] *
(material->GetTotNbOfAtomsPerVolume()) /
(expCharge[i] * numberOfAtomsPerMolecula[i]) ;
SetExpStopPower125(exp125);
return true;
}
}
return false;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ChemicalFactor(G4double kineticEnergy,
G4double eloss125) const
{
// Approximation of Chemical Factor according to
// J.F.Ziegler and J.M.Manoyan, The stopping of ions in compaunds,
// Nucl. Inst. & Meth. in Phys. Res. B35 (1988) 215-228.
G4double gamma = 1.0 + kineticEnergy/proton_mass_c2 ;
G4double gamma25 = 1.0 + 25.0*keV /proton_mass_c2 ;
G4double gamma125 = 1.0 + 125.0*keV/proton_mass_c2 ;
G4double beta = sqrt(1.0 - 1.0/(gamma*gamma)) ;
G4double beta25 = sqrt(1.0 - 1.0/(gamma25*gamma25)) ;
G4double beta125 = sqrt(1.0 - 1.0/(gamma125*gamma125)) ;
G4double factor = 1.0 + (expStopPower125/eloss125 - 1.0) *
(1.0 + exp( 1.48 * ( beta125/beta25 - 7.0 ) ) ) /
(1.0 + exp( 1.48 * ( beta/beta25 - 7.0 ) ) ) ;
return factor ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -20,9 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4ComptonScattering.cc,v 1.18 2004/03/10 16:48:45 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-01 $
// $Id: G4ComptonScattering.cc,v 1.23 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
//
//------------ G4ComptonScattering physics process -----------------------------
@@ -48,20 +47,24 @@
// 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.Ivantchenko)
// -----------------------------------------------------------------------------
#include "G4ComptonScattering.hh"
#include "G4UnitsTable.hh"
#include "G4PhysicsTableHelper.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// constructor
G4ComptonScattering::G4ComptonScattering(const G4String& processName,
using namespace std;
G4ComptonScattering::G4ComptonScattering(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
theCrossSectionTable(NULL),
theMeanFreePathTable(NULL),
LowestEnergyLimit ( 1*keV),
theMeanFreePathTable(NULL),
LowestEnergyLimit ( 1*keV),
HighestEnergyLimit(100*GeV),
NumbBinTable(80),
fminimalEnergy(1*eV)
@@ -86,6 +89,13 @@ G4ComptonScattering::~G4ComptonScattering()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4ComptonScattering::IsApplicable( const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4ComptonScattering::SetPhysicsTableBining(
G4double lowE, G4double highE, G4int nBins)
{
@@ -110,17 +120,17 @@ void G4ComptonScattering::BuildPhysicsTable(const G4ParticleDefinition&)
G4double AtomicNumber;
size_t J;
for ( J=0 ; J < G4Element::GetNumberOfElements(); 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++ )
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
Value = ComputeCrossSectionPerAtom(LowEdgeEnergy, AtomicNumber);
Value = ComputeCrossSectionPerAtom(LowEdgeEnergy, AtomicNumber);
ptrVector->PutValue(i,Value);
}
@@ -143,7 +153,7 @@ void G4ComptonScattering::BuildPhysicsTable(const G4ParticleDefinition&)
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit,HighestEnergyLimit,
NumbBinTable ) ;
material = (*theMaterialTable)[J];
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
@@ -155,7 +165,7 @@ void G4ComptonScattering::BuildPhysicsTable(const G4ParticleDefinition&)
}
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -167,6 +177,7 @@ G4double G4ComptonScattering::ComputeCrossSectionPerAtom
// 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 ;
@@ -184,16 +195,99 @@ G4double G4ComptonScattering::ComputeCrossSectionPerAtom
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 X = GammaEnergy / electron_mass_c2 ;
G4double T0 = 15*keV; if (Z == 1.) T0 = 40*keV;
return CrossSection = p1Z*log(1.+2*X)/X
+ (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
}
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)
const G4Step& aStep)
//
// The scattered gamma energy is sampled according to Klein - Nishina formula.
// The random number techniques of Butcher & Messel are used
@@ -214,7 +308,7 @@ G4VParticleChange* G4ComptonScattering::PostStepDoIt(const G4Track& aTrack,
//
// sample the energy rate of the scattered gamma
//
G4double epsilon, epsilonsq, onecost, sint2, greject ;
G4double epsilon0 = 1./(1. + 2*E0_m) , epsilon0sq = epsilon0*epsilon0;
@@ -242,24 +336,24 @@ G4VParticleChange* G4ComptonScattering::PostStepDoIt(const G4Track& aTrack,
G4double dirx = sinTeta*cos(Phi), diry = sinTeta*sin(Phi), dirz = cosTeta;
//
// update G4VParticleChange for the scattered gamma
// update G4VParticleChange for the scattered gamma
//
G4ThreeVector GammaDirection1 ( dirx,diry,dirz );
GammaDirection1.rotateUz(GammaDirection0);
aParticleChange.SetMomentumChange( GammaDirection1 );
aParticleChange.ProposeMomentumDirection( GammaDirection1 );
G4double GammaEnergy1 = epsilon*GammaEnergy0;
G4double localEnergyDeposit = 0.;
if (GammaEnergy1 > fminimalEnergy)
{
aParticleChange.SetEnergyChange( GammaEnergy1 );
aParticleChange.ProposeEnergy( GammaEnergy1 );
}
else
{
localEnergyDeposit += GammaEnergy1;
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.ProposeEnergy(0.) ;
aParticleChange.ProposeTrackStatus(fStopAndKill);
}
//
@@ -275,8 +369,8 @@ G4VParticleChange* G4ComptonScattering::PostStepDoIt(const G4Track& aTrack,
G4ThreeVector ElecDirection (
(GammaEnergy0*GammaDirection0 - GammaEnergy1*GammaDirection1)
*(1./ElecMomentum) );
// create G4DynamicParticle object for the electron.
// create G4DynamicParticle object for the electron.
G4DynamicParticle* aElectron= new G4DynamicParticle(
G4Electron::Electron(),ElecDirection,ElecKineEnergy);
@@ -287,18 +381,18 @@ G4VParticleChange* G4ComptonScattering::PostStepDoIt(const G4Track& aTrack,
{
aParticleChange.SetNumberOfSecondaries(0);
localEnergyDeposit += ElecKineEnergy;
}
aParticleChange.SetLocalEnergyDeposit (localEnergyDeposit);
}
aParticleChange.ProposeLocalEnergyDeposit (localEnergyDeposit);
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4ComptonScattering::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
G4bool G4ComptonScattering::StorePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
@@ -317,17 +411,17 @@ G4bool G4ComptonScattering::StorePhysicsTable(G4ParticleDefinition* particle,
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4ComptonScattering::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
/*
G4bool G4ComptonScattering::RetrievePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theCrossSectionTable and theMeanFreePathTable
@@ -345,27 +439,27 @@ G4bool G4ComptonScattering::RetrievePhysicsTable(G4ParticleDefinition* particle,
// retreive cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
theCrossSectionTable = new G4PhysicsTable(G4Element::GetNumberOfElements());
if ( !theCrossSectionTable->RetrievePhysicsTable(filename, ascii) ){
if ( !G4PhysicsTableHelper::RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
if ( !G4PhysicsTableHelper::RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
return true;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4ComptonScattering::PrintInfoDefinition()
@@ -21,12 +21,12 @@
// ********************************************************************
//
//
// $Id: G4GammaConversion.cc,v 1.19 2004/03/10 16:48:45 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-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
//
//
// 11-06-96 Added SelectRandomAtom() method, M.Maire
// 21-06-96 SetCuts implementation, M.Maire
// 24-06-96 simplification in ComputeCrossSectionPerAtom, M.Maire
@@ -54,7 +54,8 @@
// 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
// 21-03-02 DoIt: correction of the e+e- angular distribution (bug 363) mma
// 08-11-04 Remove of Store/Retrieve tables (V.Ivantchenko)
// -----------------------------------------------------------------------------
#include "G4GammaConversion.hh"
@@ -62,7 +63,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// constructor
using namespace std;
G4GammaConversion::G4GammaConversion(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
@@ -90,6 +91,13 @@ G4GammaConversion::~G4GammaConversion()
delete theMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4GammaConversion::IsApplicable( const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -146,16 +154,16 @@ void G4GammaConversion::BuildPhysicsTable(const G4ParticleDefinition&)
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++ )
for ( G4int i = 0 ; i < NumbBinTable ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeMeanFreePath( LowEdgeEnergy, material);
Value = ComputeMeanFreePath( LowEdgeEnergy, material);
ptrVector->PutValue( i , Value ) ;
}
@@ -170,7 +178,7 @@ void G4GammaConversion::BuildPhysicsTable(const G4ParticleDefinition&)
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.
@@ -183,7 +191,7 @@ G4double G4GammaConversion::ComputeCrossSectionPerAtom
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;
@@ -219,6 +227,79 @@ G4double G4GammaConversion::ComputeCrossSectionPerAtom
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......
@@ -237,7 +318,7 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
// 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();
@@ -251,7 +332,7 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
G4double epsil0 = electron_mass_c2/GammaEnergy ;
// do it fast if GammaEnergy < 2. MeV
const G4double Egsmall=2.*MeV;
const G4double Egsmall=2.*MeV;
if (GammaEnergy<Egsmall) { epsil = epsil0 + (0.5-epsil0)*G4UniformRand(); }
else
@@ -267,11 +348,11 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
// limits of the screening variable
G4double screenfac = 136.*epsil0/(anElement->GetIonisation()->GetZ3());
G4double screenmax = exp ((42.24 - FZ)/8.368) - 0.952 ;
G4double screenmin = std::min(4.*screenfac,screenmax);
G4double screenmin = min(4.*screenfac,screenmax);
// limits of the energy sampling
G4double epsil1 = 0.5 - 0.5*sqrt(1. - screenmin/screenmax) ;
G4double epsilmin = std::max(epsil0,epsil1) , epsilrange = 0.5 - epsilmin;
G4double epsilmin = max(epsil0,epsil1) , epsilrange = 0.5 - epsilmin;
//
// sample the energy rate of the created electron (or positron)
@@ -281,8 +362,8 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
G4double F10 = ScreenFunction1(screenmin) - FZ;
G4double F20 = ScreenFunction2(screenmin) - FZ;
G4double NormF1 = std::max(F10*epsilrange*epsilrange,0.);
G4double NormF2 = std::max(1.5*F20,0.);
G4double NormF1 = max(F10*epsilrange*epsilrange,0.);
G4double NormF2 = max(1.5*F20,0.);
do {
if ( NormF1/(NormF1+NormF2) > G4UniformRand() )
@@ -342,14 +423,14 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
aParticleChange.SetNumberOfSecondaries(2);
G4double ElectKineEnergy = std::max(0.,ElectTotEnergy - electron_mass_c2);
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);
@@ -360,27 +441,26 @@ G4VParticleChange* G4GammaConversion::PostStepDoIt(const G4Track& aTrack,
// the e+ is always created (even with Ekine=0) for further annihilation.
G4double PositKineEnergy = std::max(0.,PositTotEnergy - electron_mass_c2);
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.SetLocalEnergyDeposit(localEnergyDeposit);
aParticleChange.ProposeLocalEnergyDeposit(localEnergyDeposit);
//
// Kill the incident photon
//
aParticleChange.SetMomentumChange( 0., 0., 0. );
aParticleChange.SetEnergyChange( 0. );
aParticleChange.SetStatusChange( fStopAndKill );
aParticleChange.ProposeEnergy( 0. );
aParticleChange.ProposeTrackStatus( fStopAndKill );
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
@@ -392,7 +472,7 @@ G4Element* G4GammaConversion::SelectRandomAtom(
const G4DynamicParticle* aDynamicGamma,
G4Material* aMaterial)
{
// select randomly 1 element within the material
// select randomly 1 element within the material
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
@@ -402,7 +482,7 @@ G4Element* G4GammaConversion::SelectRandomAtom(
G4double PartialSumSigma = 0. ;
G4double rval = G4UniformRand()/MeanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ )
{ PartialSumSigma += NbOfAtomsPerVolume[i] *
GetCrossSectionPerAtom(aDynamicGamma, (*theElementVector)[i]);
@@ -415,9 +495,9 @@ G4Element* G4GammaConversion::SelectRandomAtom(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4GammaConversion::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
G4bool G4GammaConversion::StorePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
@@ -436,18 +516,18 @@ G4bool G4GammaConversion::StorePhysicsTable(G4ParticleDefinition* particle,
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4GammaConversion::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
/*
G4bool G4GammaConversion::RetrievePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theCrossSectionTable and theMeanFreePathTable
if (theCrossSectionTable != 0) {
@@ -464,27 +544,27 @@ G4bool G4GammaConversion::RetrievePhysicsTable(G4ParticleDefinition* particle,
// retreive cross section table
filename = GetPhysicsTableFileName(particle,directory,"CrossSection",ascii);
theCrossSectionTable = new G4PhysicsTable(G4Element::GetNumberOfElements());
if ( !theCrossSectionTable->RetrievePhysicsTable(filename, ascii) ){
if ( !G4PhysicsTableHelper::RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
if ( !G4PhysicsTableHelper::RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
return true;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4GammaConversion::PrintInfoDefinition()
@@ -492,11 +572,11 @@ 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 "
<< "\n PhysicsTables from "
<< G4BestUnit(LowestEnergyLimit, "Energy")
<< " to " << G4BestUnit(HighestEnergyLimit,"Energy")
<< " to " << G4BestUnit(HighestEnergyLimit,"Energy")
<< " in " << NumbBinTable << " bins. \n";
}
@@ -1,324 +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: G4GammaConversionToMuons.cc,v 1.5 2004/03/10 16:48:45 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-01 $
//
// ------------ G4GammaConversionToMuons physics process ------
// by H.Burkhardt, S. Kelner and R. Kokoulin, April 2002
//
//
// 07-08-02: missprint in OR condition in DoIt : f1<0 || f1>f1_max ..etc ...
// ---------------------------------------------------------------------------
#include "G4GammaConversionToMuons.hh"
#include "G4EnergyLossTables.hh"
#include "G4UnitsTable.hh"
#include "G4MuonPlus.hh"
#include "G4MuonMinus.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
// constructor
G4GammaConversionToMuons::G4GammaConversionToMuons(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
LowestEnergyLimit (4*G4MuonPlus::MuonPlus()->GetPDGMass()), // 4*Mmuon
HighestEnergyLimit(1e21*eV), // ok to 1e21eV=1e12GeV, then LPM suppression
CrossSecFactor(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
// destructor
G4GammaConversionToMuons::~G4GammaConversionToMuons() // (empty) destructor
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4GammaConversionToMuons::BuildPhysicsTable(const G4ParticleDefinition&)
// Build cross section and mean free path tables
{ //here no tables, just calling PrintInfoDefinition
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4GammaConversionToMuons::SetCrossSecFactor(G4double fac)
// Set the factor to artificially increase the cross section
{ CrossSecFactor=fac;
G4cout << "The cross section for GammaConversionToMuons is artificially "
<< "increased by the CrossSecFactor=" << CrossSecFactor << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4double G4GammaConversionToMuons::ComputeCrossSectionPerAtom(
G4double Egam, G4double Z, G4double A)
// Calculates the microscopic cross section in GEANT4 internal units.
// Total cross section parametrisation from H.Burkhardt
// It gives a good description at any energy (from 0 to 10**21 eV)
{ static const G4double Mmuon=G4MuonPlus::MuonPlus()->GetPDGMass();
static const G4double Mele=electron_mass_c2;
static const G4double Rc=elm_coupling/Mmuon; // classical particle radius
static const G4double sqrte=sqrt(exp(1.));
static const G4double PowSat=-0.88;
static G4double CrossSection = 0.0 ;
if ( A < 1. ) return 0;
if ( Egam < 4*Mmuon ) return 0 ; // below threshold return 0
static G4double EgamLast=0,Zlast=0,PowThres,Ecor,B,Dn,Zthird,Winfty,WMedAppr,
Wsatur,sigfac;
if(Zlast==Z && Egam==EgamLast) return CrossSection; // already calculated
EgamLast=Egam;
if(Zlast!=Z) // new element
{ Zlast=Z;
if(Z==1) // special case of Hydrogen
{ B=202.4;
Dn=1.49;
}
else
{ B=183.;
Dn=1.54*pow(A,0.27);
}
Zthird=pow(Z,-1./3.); // Z**(-1/3)
Winfty=B*Zthird*Mmuon/(Dn*Mele);
WMedAppr=1./(4.*Dn*sqrte*Mmuon);
Wsatur=Winfty/WMedAppr;
sigfac=4.*fine_structure_const*Z*Z*Rc*Rc;
PowThres=1.479+0.00799*Dn;
Ecor=-18.+4347./(B*Zthird);
}
G4double CorFuc=1.+.04*log(1.+Ecor/Egam);
G4double Eg=pow(1.-4.*Mmuon/Egam,PowThres)*pow( pow(Wsatur,PowSat)+
pow(Egam,PowSat),1./PowSat); // threshold and saturation
CrossSection=7./9.*sigfac*log(1.+WMedAppr*CorFuc*Eg);
CrossSection*=CrossSecFactor; // increase the CrossSection by (by default 1)
return CrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4VParticleChange* G4GammaConversionToMuons::PostStepDoIt(
const G4Track& aTrack,
const G4Step& aStep)
//
// generation of gamma->mu+mu-
//
{
aParticleChange.Initialize(aTrack);
G4Material* aMaterial = aTrack.GetMaterial();
static const G4double Mmuon=G4MuonPlus::MuonPlus()->GetPDGMass();
static const G4double Mele=electron_mass_c2;
static const G4double sqrte=sqrt(exp(1.));
// current Gamma energy and direction, return if energy too low
const G4DynamicParticle *aDynamicGamma = aTrack.GetDynamicParticle();
G4double Egam = aDynamicGamma->GetKineticEnergy();
if (Egam < 4*Mmuon) return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection();
// select randomly one element constituting the material
const G4Element& anElement = *SelectRandomAtom(aDynamicGamma, aMaterial);
G4double Z = anElement.GetZ();
G4double A = anElement.GetA()/(g/mole);
static G4double Zlast=0,B,Dn,Zthird,Winfty,A027,C1Num2,C2Term2;
if(Zlast!=Z) // the element has changed
{ Zlast=Z;
if(Z==1) // special case of Hydrogen
{ B=202.4;
Dn=1.49;
}
else
{ B=183.;
Dn=1.54*pow(A,0.27);
}
Zthird=pow(Z,-1./3.); // Z**(-1/3)
Winfty=B*Zthird*Mmuon/(Dn*Mele);
A027=pow(A,0.27);
G4double C1Num=0.35*A027;
C1Num2=C1Num*C1Num;
C2Term2=Mele/(183.*Zthird*Mmuon);
}
G4double GammaMuonInv=Mmuon/Egam;
G4double sqrtx=sqrt(.25-GammaMuonInv);
G4double xmax=.5+sqrtx;
G4double xmin=.5-sqrtx;
// generate xPlus according to the differential cross section by rejection
G4double Ds2=(Dn*sqrte-2.);
G4double sBZ=sqrte*B*Zthird/Mele;
G4double LogWmaxInv=1./log(Winfty*(1.+2.*Ds2*GammaMuonInv)
/(1.+2.*sBZ*Mmuon*GammaMuonInv));
G4double xPlus,xMinus,xPM,result,W;
do
{ xPlus=xmin+G4UniformRand()*(xmax-xmin);
xMinus=1.-xPlus;
xPM=xPlus*xMinus;
G4double del=Mmuon*Mmuon/(2.*Egam*xPM);
W=Winfty*(1.+Ds2*del/Mmuon)/(1.+sBZ*del);
if(W<1.) W=1.; // to avoid negative cross section at xmin
G4double xxp=1.-4./3.*xPM; // the main xPlus dependence
result=xxp*log(W)*LogWmaxInv;
if(result>1.)
{ G4cout << "error in dSigxPlusGen, result=" << result << " is >1" << '\n';
exit(10);
}
}
while (G4UniformRand() > result);
// now generate the angular variables via the auxilary variables t,psi,rho
G4double t;
G4double psi;
G4double rho;
G4double thetaPlus,thetaMinus,phiHalf; // final angular variables
do // t, psi, rho generation start (while angle < pi)
{
//generate t by the rejection method
G4double C1=C1Num2* GammaMuonInv/xPM;
G4double f1_max=(1.-xPM) / (1.+C1);
G4double f1; // the probability density
do
{ t=G4UniformRand();
f1=(1.-2.*xPM+4.*xPM*t*(1.-t)) / (1.+C1/(t*t));
if(f1<0 || f1> f1_max) // should never happend
{ G4cout << "outside allowed range f1=" << f1 << G4endl;
exit(1);
}
}
while ( G4UniformRand()*f1_max > f1);
// generate psi by the rejection method
G4double f2_max=1.-2.*xPM*(1.-4.*t*(1.-t));
// long version
G4double f2;
do
{ psi=2.*pi*G4UniformRand();
f2=1.-2.*xPM+4.*xPM*t*(1.-t)*(1.+cos(2.*psi));
if(f2<0 || f2> f2_max) // should never happend
{ G4cout << "outside allowed range f2=" << f2 << G4endl;
exit(1);
}
}
while ( G4UniformRand()*f2_max > f2);
// generate rho by direct transformation
G4double C2Term1=GammaMuonInv/(2.*xPM*t);
G4double C2=4./sqrt(xPM)*pow(C2Term1*C2Term1+C2Term2*C2Term2,2);
G4double rhomax=1.9/A027*(1./t-1.);
G4double beta=log( (C2+pow(rhomax,4))/C2 );
rho=pow(C2 *( exp(beta*G4UniformRand())-1. ) ,0.25);
//now get from t and psi the kinematical variables
G4double u=sqrt(1./t-1.);
G4double xiHalf=0.5*rho*cos(psi);
phiHalf=0.5*rho/u*sin(psi);
thetaPlus =GammaMuonInv*(u+xiHalf)/xPlus;
thetaMinus=GammaMuonInv*(u-xiHalf)/xMinus;
} while ( abs(thetaPlus)>pi || abs(thetaMinus) >pi);
// now construct the vectors
// azimuthal symmetry, take phi0 at random between 0 and 2 pi
G4double phi0=2.*pi*G4UniformRand();
G4double EPlus=xPlus*Egam;
G4double EMinus=xMinus*Egam;
// mu+ mu- directions for gamma in z-direction
G4ThreeVector MuPlusDirection ( sin(thetaPlus) *cos(phi0+phiHalf),
sin(thetaPlus) *sin(phi0+phiHalf), cos(thetaPlus) );
G4ThreeVector MuMinusDirection (-sin(thetaMinus)*cos(phi0-phiHalf),
-sin(thetaMinus) *sin(phi0-phiHalf), cos(thetaMinus) );
// rotate to actual gamma direction
MuPlusDirection.rotateUz(GammaDirection);
MuMinusDirection.rotateUz(GammaDirection);
aParticleChange.SetNumberOfSecondaries(2);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1= new G4DynamicParticle(
G4MuonPlus::MuonPlus(),MuPlusDirection,EPlus-Mmuon);
aParticleChange.AddSecondary(aParticle1);
// create G4DynamicParticle object for the particle2
G4DynamicParticle* aParticle2= new G4DynamicParticle(
G4MuonMinus::MuonMinus(),MuMinusDirection,EMinus-Mmuon);
aParticleChange.AddSecondary(aParticle2);
//
// Kill the incident photon
//
aParticleChange.SetMomentumChange( 0., 0., 0. ) ;
aParticleChange.SetEnergyChange( 0. ) ;
aParticleChange.SetStatusChange( fStopAndKill ) ;
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4Element* G4GammaConversionToMuons::SelectRandomAtom(
const G4DynamicParticle* aDynamicGamma,
G4Material* aMaterial)
{
// select randomly 1 element within the material, invoked by PostStepDoIt
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.....
void G4GammaConversionToMuons::PrintInfoDefinition()
{
G4String comments ="gamma->mu+mu- Bethe Heitler process.\n";
G4cout << G4endl << GetProcessName() << ": " << comments
<< " good cross section parametrization from "
<< G4BestUnit(LowestEnergyLimit,"Energy")
<< " to " << HighestEnergyLimit/GeV << " GeV for all Z." << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,388 @@
//
// ********************************************************************
// * 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: G4IonFluctuations.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4IonFluctuation
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
// 23-05-03 Add control on parthalogical cases (V.Ivanchenko)
// 16-10-03 Changed interface to Initialisation (V.Ivanchenko)
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4IonFluctuations.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4IonFluctuations::G4IonFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
particle(0),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minFraction(0.2),
xmin(0.2),
minLoss(0.001*eV)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4IonFluctuations::~G4IonFluctuations()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IonFluctuations::InitialiseMe(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
charge = part->GetPDGCharge()/eplus;
chargeSquare = charge*charge;
chargeSqRatio = 1.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
if(meanLoss <= minLoss) return meanLoss;
if(dp->GetDefinition() != particle) {
particle = dp->GetDefinition();
charge = particle->GetPDGCharge()/eplus;
}
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
G4double navr = minNumberInteractionsBohr;
// Gaussian fluctuation
G4bool gauss = true;
if (meanLoss >= minNumberInteractionsBohr*tmax) {
navr = meanLoss*meanLoss/siga;
if (navr < minNumberInteractionsBohr) gauss = false;
}
if(gauss) {
// Increase fluctuations for big fractional energy loss
//G4cout << "siga= " << siga << G4endl;
if ( meanLoss > minFraction*kineticEnergy ) {
G4double gam = (kineticEnergy - meanLoss)/particleMass + 1.0;
G4double b2 = 1.0 - 1.0/(gam*gam);
if(b2 < xmin*beta2) b2 = xmin*beta2;
G4double x = b2/beta2;
G4double x3 = 1.0/(x*x*x);
siga *= 0.25*(1.0 + x)*(x3 + (1.0/b2 - 0.5)/(1.0/beta2 - 0.5) );
}
// G4cout << "siga= " << siga << G4endl;
siga = sqrt(siga);
G4double lossmax = meanLoss+meanLoss;
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (0.0 > loss || loss > lossmax);
// Poisson fluctuations
} else {
G4double n = (G4double)(G4Poisson(navr));
loss = meanLoss*n/navr;
}
// G4cout << "meanLoss= " << meanLoss << " loss= " << loss << G4endl;
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::Dispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length)
{
particleMass = dp->GetMass();
G4double q = dp->GetCharge()/eplus;
chargeSquare = q*q;
chargeSqRatio = chargeSquare/(charge*charge);
G4double electronDensity = material->GetElectronDensity();
kineticEnergy = dp->GetKineticEnergy();
// G4cout << "e= " << kineticEnergy << " m= " << particleMass
// << " tmax= " << tmax << " l= " << length << " q^2= " << chargeSquare << G4endl;
G4double gam = kineticEnergy/particleMass + 1.0;
beta2 = 1.0 - 1.0/(gam*gam);
G4double siga = (1.0/beta2 - 0.5)*tmax*length*electronDensity*twopi_mc2_rcl2*chargeSquare;
// G4cout << "siga= " << siga << G4endl;
// Low velocity - additional ion charge fluctuations according to
// Q.Yang et al., NIM B61(1991)149-155.
G4double zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
//G4cout << "siga= " << siga << " zeff= " << zeff << G4endl;
if ( beta2 < 3.0*theBohrBeta2*zeff ) {
G4double a = CoeffitientA (zeff);
G4double b = CoeffitientB (material, zeff);
// G4cout << "a= " << a << " b= " << b << G4endl;
siga *= (a*chargeSqRatio + b);
} else {
// H.Geissel et al. NIM B, 195 (2002) 3.
siga *= RelativisticFactor(material, zeff);
}
return siga;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::CoeffitientA(G4double& zeff)
{
// The aproximation of energy loss fluctuations
// Q.Yang et al., NIM B61(1991)149-155.
// Reduced energy in MeV/AMU
G4double energy = kineticEnergy * amu_c2/(particleMass*MeV) ;
static G4double a[96][4] = {
{-0.3291, -0.8312, 0.2460, -1.0220},
{-0.5615, -0.5898, 0.5205, -0.7258},
{-0.5280, -0.4981, 0.5519, -0.5865},
{-0.5125, -0.4625, 0.5660, -0.5190},
{-0.5127, -0.8595, 0.5626, -0.8721},
{-0.5174, -1.1930, 0.5565, -1.1980},
{-0.5179, -1.1850, 0.5560, -1.2070},
{-0.5209, -0.9355, 0.5590, -1.0250},
{-0.5255, -0.7766, 0.5720, -0.9412},
{-0.5776, -0.6665, 0.6598, -0.8484},
{-0.6013, -0.6045, 0.7321, -0.7671},
{-0.5781, -0.5518, 0.7605, -0.6919},
{-0.5587, -0.4981, 0.7835, -0.6195},
{-0.5466, -0.4656, 0.7978, -0.5771},
{-0.5406, -0.4690, 0.8031, -0.5718},
{-0.5391, -0.5061, 0.8024, -0.5974},
{-0.5380, -0.6483, 0.7962, -0.6970},
{-0.5355, -0.7722, 0.7962, -0.7839},
{-0.5329, -0.7720, 0.7988, -0.7846},
{-0.5335, -0.7671, 0.7984, -0.7933},
{-0.5324, -0.7612, 0.7998, -0.8031},
{-0.5305, -0.7300, 0.8031, -0.7990},
{-0.5307, -0.7178, 0.8049, -0.8216},
{-0.5248, -0.6621, 0.8165, -0.7919},
{-0.5180, -0.6502, 0.8266, -0.7986},
{-0.5084, -0.6408, 0.8396, -0.8048},
{-0.4967, -0.6331, 0.8549, -0.8093},
{-0.4861, -0.6508, 0.8712, -0.8432},
{-0.4700, -0.6186, 0.8961, -0.8132},
{-0.4545, -0.5720, 0.9227, -0.7710},
{-0.4404, -0.5226, 0.9481, -0.7254},
{-0.4288, -0.4778, 0.9701, -0.6850},
{-0.4199, -0.4425, 0.9874, -0.6539},
{-0.4131, -0.4188, 0.9998, -0.6332},
{-0.4089, -0.4057, 1.0070, -0.6218},
{-0.4039, -0.3913, 1.0150, -0.6107},
{-0.3987, -0.3698, 1.0240, -0.5938},
{-0.3977, -0.3608, 1.0260, -0.5852},
{-0.3972, -0.3600, 1.0260, -0.5842},
{-0.3985, -0.3803, 1.0200, -0.6013},
{-0.3985, -0.3979, 1.0150, -0.6168},
{-0.3968, -0.3990, 1.0160, -0.6195},
{-0.3971, -0.4432, 1.0050, -0.6591},
{-0.3944, -0.4665, 1.0010, -0.6825},
{-0.3924, -0.5109, 0.9921, -0.7235},
{-0.3882, -0.5158, 0.9947, -0.7343},
{-0.3838, -0.5125, 0.9999, -0.7370},
{-0.3786, -0.4976, 1.0090, -0.7310},
{-0.3741, -0.4738, 1.0200, -0.7155},
{-0.3969, -0.4496, 1.0320, -0.6982},
{-0.3663, -0.4297, 1.0430, -0.6828},
{-0.3630, -0.4120, 1.0530, -0.6689},
{-0.3597, -0.3964, 1.0620, -0.6564},
{-0.3555, -0.3809, 1.0720, -0.6454},
{-0.3525, -0.3607, 1.0820, -0.6289},
{-0.3505, -0.3465, 1.0900, -0.6171},
{-0.3397, -0.3570, 1.1020, -0.6384},
{-0.3314, -0.3552, 1.1130, -0.6441},
{-0.3235, -0.3531, 1.1230, -0.6498},
{-0.3150, -0.3483, 1.1360, -0.6539},
{-0.3060, -0.3441, 1.1490, -0.6593},
{-0.2968, -0.3396, 1.1630, -0.6649},
{-0.2935, -0.3225, 1.1760, -0.6527},
{-0.2797, -0.3262, 1.1940, -0.6722},
{-0.2704, -0.3202, 1.2100, -0.6770},
{-0.2815, -0.3227, 1.2480, -0.6775},
{-0.2880, -0.3245, 1.2810, -0.6801},
{-0.3034, -0.3263, 1.3270, -0.6778},
{-0.2936, -0.3215, 1.3430, -0.6835},
{-0.3282, -0.3200, 1.3980, -0.6650},
{-0.3260, -0.3070, 1.4090, -0.6552},
{-0.3511, -0.3074, 1.4470, -0.6442},
{-0.3501, -0.3064, 1.4500, -0.6442},
{-0.3490, -0.3027, 1.4550, -0.6418},
{-0.3487, -0.3048, 1.4570, -0.6447},
{-0.3478, -0.3074, 1.4600, -0.6483},
{-0.3501, -0.3283, 1.4540, -0.6669},
{-0.3494, -0.3373, 1.4550, -0.6765},
{-0.3485, -0.3373, 1.4570, -0.6774},
{-0.3462, -0.3300, 1.4630, -0.6728},
{-0.3462, -0.3225, 1.4690, -0.6662},
{-0.3453, -0.3094, 1.4790, -0.6553},
{-0.3844, -0.3134, 1.5240, -0.6412},
{-0.3848, -0.3018, 1.5310, -0.6303},
{-0.3862, -0.2955, 1.5360, -0.6237},
{-0.4262, -0.2991, 1.5860, -0.6115},
{-0.4278, -0.2910, 1.5900, -0.6029},
{-0.4303, -0.2817, 1.5940, -0.5927},
{-0.4315, -0.2719, 1.6010, -0.5829},
{-0.4359, -0.2914, 1.6050, -0.6010},
{-0.4365, -0.2982, 1.6080, -0.6080},
{-0.4253, -0.3037, 1.6120, -0.6150},
{-0.4335, -0.3245, 1.6160, -0.6377},
{-0.4307, -0.3292, 1.6210, -0.6447},
{-0.4284, -0.3204, 1.6290, -0.6380},
{-0.4227, -0.3217, 1.6360, -0.6438}
} ;
G4int iz = (G4int)zeff - 2 ;
if( 0 > iz ) iz = 0 ;
if(95 < iz ) iz = 95 ;
G4double q = 1.0 / (1.0 + a[iz][0]*pow(energy,a[iz][1])+
+ a[iz][2]*pow(energy,a[iz][3])) ;
return q ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::CoeffitientB(const G4Material* material, G4double& zeff)
{
// The aproximation of energy loss fluctuations
// Q.Yang et al., NIM B61(1991)149-155.
// Reduced energy in MeV/AMU
G4double energy = kineticEnergy *amu_c2/(particleMass*MeV) ;
G4int i = 0 ;
G4double factor = 1.0 ;
// The index of set of parameters i = 0 for protons(hadrons) in gases
// 1 for protons(hadrons) in solids
// 2 for ions in atomic gases
// 3 for ions in molecular gases
// 4 for ions in solids
static G4double b[5][4] = {
{0.1014, 0.3700, 0.9642, 3.987},
{0.1955, 0.6941, 2.522, 1.040},
{0.05058, 0.08975, 0.1419, 10.80},
{0.05009, 0.08660, 0.2751, 3.787},
{0.01273, 0.03458, 0.3951, 3.812}
} ;
// protons (hadrons)
if(1.5 > charge) {
if( kStateGas != material->GetState() ) i = 1 ;
// ions
} else {
factor = charge * pow(charge/zeff, 0.3333) ;
if( kStateGas == material->GetState() ) {
energy /= (charge * sqrt(charge)) ;
if(1 == (material->GetNumberOfElements())) {
i = 2 ;
} else {
i = 3 ;
}
} else {
energy /= (charge * sqrt(charge*zeff)) ;
i = 4 ;
}
}
G4double x = b[i][2] * (1.0 - exp( - energy * b[i][3] )) ;
G4double q = factor * x * b[i][0] /
((energy - b[i][1])*(energy - b[i][1]) + x*x) ;
return q ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::RelativisticFactor(const G4Material*, G4double& zeff)
{
// H.Geissel et al. NIM B, 195 (2002) 3.
G4double factor = 1.0 + 0.667*theBohrBeta2*(1.0 - beta2)
* log(2.0*electron_mass_c2/(5.0*charge*eV))
/ ((1.0 - 0.5*beta2)*beta2*zeff) ;
factor *= (1.0 + 1.415e-4*chargeSquare/beta2);
// G4cout << "factor= " << factor << G4endl;
return factor;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1,288 +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. *
// ********************************************************************
//
// Implementation of class for selecting ionisation model depending on
// logical volume
//
//
#include "G4IonisationByLogicalVolume.hh"
///////////////////////////////////////////////////////////////////////////
//
//
G4IonisationByLogicalVolume::
G4IonisationByLogicalVolume( const G4String& particleName,
G4LogicalVolume* volumeForPAImodel,
const G4String& processName ) :
G4VContinuousDiscreteProcess(processName),
fPAIonisation(NULL),feIonisation(NULL),fMuIonisation(NULL),fhIonisation(NULL)
{
fParticleName = particleName ;
fVolumeForPAImodel = volumeForPAImodel ;
fMaterialNameForPAI = volumeForPAImodel->GetMaterial()->GetName() ;
// fPAIonisation = new G4PAIonisation(fMaterialNameForPAI);
fPAIonisation = new G4PAIonisation(volumeForPAImodel);
if ( fParticleName == "e+" || fParticleName == "e-" )
{
feIonisation = new G4eIonisation52(particleName) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
fMuIonisation = new G4MuIonisation52(particleName) ;
}
else
{
fhIonisation = new G4hIonisation52(particleName) ;
}
}
///////////////////////////////////////////////////////////////////////////
//
//
G4IonisationByLogicalVolume::~G4IonisationByLogicalVolume()
{
if(fPAIonisation) delete fPAIonisation ;
if(feIonisation) delete feIonisation ;
if(fMuIonisation) delete fMuIonisation ;
if(fhIonisation) delete fhIonisation ;
}
///////////////////////////////////////////////////////////////////////////
//
// Methods
G4bool G4IonisationByLogicalVolume::
IsApplicable( const G4ParticleDefinition& particle )
{
return( particle.GetPDGCharge() != 0.) ;
}
/////////////////////////////////////////////////////////////////////////
//
//
/* ***********************************************
G4double G4IonisationByLogicalVolume::
GetConstraints(const G4DynamicParticle* aParticle,
G4Material* aMaterial )
{
if ( aMaterial->GetName() == fMaterialNameForPAI )
{
return fPAIonisation->GetConstraints(aParticle,aMaterial) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
return feIonisation->GetConstraints(aParticle,aMaterial) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
return fMuIonisation->GetConstraints(aParticle,aMaterial) ;
}
else
{
return fhIonisation->GetConstraints(aParticle,aMaterial) ;
}
}
}
************************************** */
////////////////////////////////////////////////////////////////////////////
//
//
G4VParticleChange*
G4IonisationByLogicalVolume::PostStepDoIt( const G4Track& track,
const G4Step& step )
{
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
pParticleChange = fPAIonisation->PostStepDoIt(track,step) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
pParticleChange = feIonisation->PostStepDoIt(track,step) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
pParticleChange = fMuIonisation->PostStepDoIt(track,step) ;
}
else
{
pParticleChange = fhIonisation->PostStepDoIt(track,step) ;
}
}
return G4VContinuousDiscreteProcess::PostStepDoIt(track,step);
}
////////////////////////////////////////////////////////////////////////
//
//
void G4IonisationByLogicalVolume::
BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
fPAIonisation->BuildPhysicsTable(aParticleType) ;
if ( fParticleName == "e+" || fParticleName == "e-" )
{
feIonisation->BuildPhysicsTable(aParticleType) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
fMuIonisation->BuildPhysicsTable(aParticleType) ;
}
else
{
fhIonisation->BuildPhysicsTable(aParticleType) ;
}
}
////////////////////////////////////////////////////////////////////////
//
//
G4double G4IonisationByLogicalVolume::
GetContinuousStepLimit( const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety )
{
G4double x = 0.0;
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
x = fPAIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
x = feIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
x = fMuIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
else
{
x = fhIonisation->GetContinuousStepLimit(track,previousStepSize,
currentMinimumStep,currentSafety) ;
}
}
return x;
}
////////////////////////////////////////////////////////////////////////
//
//
G4double G4IonisationByLogicalVolume::
GetMeanFreePath( const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition )
{
G4double x = 0.0;
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
x = fPAIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
x = feIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
x = fMuIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
else
{
x = fhIonisation->GetMeanFreePath(track,previousStepSize,condition) ;
}
}
return x;
}
/////////////////////////////////////////////////////////////////////////
//
//
G4VParticleChange*
G4IonisationByLogicalVolume::AlongStepDoIt( const G4Track& track ,
const G4Step& step )
{
if ( track.GetVolume()->GetLogicalVolume() == fVolumeForPAImodel )
{
return fPAIonisation->AlongStepDoIt(track,step) ;
}
else
{
if ( fParticleName == "e+" || fParticleName == "e-" )
{
return feIonisation->AlongStepDoIt(track,step) ;
}
else if ( fParticleName == "mu+" || fParticleName == "mu-" )
{
return fMuIonisation->AlongStepDoIt(track,step) ;
}
else
{
return fhIonisation->AlongStepDoIt(track,step) ;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
//
void G4IonisationByLogicalVolume::
SetVolumeForPAImodel( G4LogicalVolume* volumeForPAImodel )
{
fVolumeForPAImodel = volumeForPAImodel ;
}
//
//
/////////////////////////////////////////////////////////////////////////
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4MollerBhabhaModel.cc,v 1.14 2003/11/19 19:38:46 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-01 $
// $Id: G4MollerBhabhaModel.cc,v 1.15 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
@@ -59,6 +59,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4MollerBhabhaModel::G4MollerBhabhaModel(const G4ParticleDefinition* p,
const G4String& nam)
: G4VEmModel(nam),
@@ -152,7 +154,7 @@ G4double G4MollerBhabhaModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
eexc /= electron_mass_c2;
G4double eexc2 = eexc*eexc;
G4double d = std::min(cutEnergy, MaxSecondaryEnergy(p, tkin))/electron_mass_c2;
G4double d = min(cutEnergy, MaxSecondaryEnergy(p, tkin))/electron_mass_c2;
G4double dedx;
// electron
@@ -214,7 +216,7 @@ G4double G4MollerBhabhaModel::CrossSection(const G4MaterialCutsCouple* couple,
G4double cross = 0.0;
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
tmax = std::min(maxEnergy, tmax);
tmax = min(maxEnergy, tmax);
if(cutEnergy < tmax) {
@@ -263,7 +265,7 @@ G4DynamicParticle* G4MollerBhabhaModel::SampleSecondary(
G4double tmin,
G4double maxEnergy)
{
G4double tmax = std::min(maxEnergy, MaxSecondaryEnergy(dp));
G4double tmax = min(maxEnergy, MaxSecondaryEnergy(dp));
if(tmin > tmax) tmin = tmax;
G4double kineticEnergy = dp->GetKineticEnergy();
@@ -364,13 +366,13 @@ G4DynamicParticle* G4MollerBhabhaModel::SampleSecondary(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4MollerBhabhaModel::SampleSecondaries(
vector<G4DynamicParticle*>* G4MollerBhabhaModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
@@ -0,0 +1,689 @@
//
// ********************************************************************
// * 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: G4MscModel.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4MscModel
//
// Author: Laszlo Urban
//
// Creation date: 03.03.2001
//
// Modifications:
//
// 27-03-03 Move model part from G4MultipleScattering (V.Ivanchenko)
// 23-05-03 important change in angle distribution for muons/hadrons
// the central part now is similar to the Highland parametrization +
// minor correction in angle sampling algorithm (for all particles)
// (L.Urban)
// 30-05-03 misprint in SampleCosineTheta corrected(L.Urban)
// 27-03-03 Rename (V.Ivanchenko)
// 05-08-03 angle distribution has been modified (L.Urban)
// 06-11-03 precision problems solved for high energy (PeV) particles
// change in the tail of the angular distribution
// highKinEnergy is set to 100 PeV (L.Urban)
//
// 10-11-03 highKinEnergy is set back to 100 TeV, some tail tuning +
// cleaning (L.Urban)
// 26-11-03 correction in TrueStepLength :
// trueLength <= currentRange (L.Urban)
// 01-03-04 signature changed in SampleCosineTheta,
// energy dependence calculations has been simplified,
// 11-03-04 corrections in GeomPathLength,TrueStepLength,
// SampleCosineTheta
// 23-04-04 true -> geom and geom -> true transformation has been
// rewritten, changes in the angular distribution (L.Urban)
// 19-07-04 correction in SampleCosineTheta in order to avoid
// num. precision problems at high energy/small step(L.Urban)
// 17-08-04 changes in the angle distribution (slightly modified
// Highland formula for the width of the central part,
// changes in the numerical values of some other parameters)
// ---> approximately step independent distribution (L.Urban)
// 21-09-04 change in the tail of the angular distribution (L.Urban)
//
// 03-11-04 precision problem for very high energy ions and small stepsize
// solved in SampleCosineTheta (L.Urban).
//
// Class Description:
//
// Implementation of the model of multiple scattering based on
// H.W.Lewis Phys Rev 78 (1950) 526 and others
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4MscModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
#include "G4LossTableManager.hh"
#include "G4PhysicsTable.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)
: G4VEmModel(nam),
taubig(8.0),
tausmall(1.e-20),
taulim(1.e-6),
dtrl(m_dtrl),
NuclCorrPar (m_NuclCorrPar),
FactPar(m_FactPar),
factail(m_factail),
samplez(m_samplez)
{
highKinEnergy = 100.0*TeV;
lowKinEnergy = 0.1*keV;
stepmin = 1.e-6*mm;
currentRange = 0. ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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&)
{
// set values of some data members
sigmafactor = twopi*classic_electr_radius*classic_electr_radius;
particle = p;
mass = particle->GetPDGMass();
charge = particle->GetPDGCharge()/eplus;
b = 1. ;
xsi = 3.00 ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MscModel::CrossSection(const G4MaterialCutsCouple* couple,
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();
// loop for element in the material
G4double sigma = 0.0;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
G4double atomicNumber = (*theElementVector)[iel]->GetZ();
G4double atomicWeight = (*theElementVector)[iel]->GetA();
sigma += NbOfAtomsPerVolume[iel]*ComputeTransportCrossSection(p,
kineticEnergy,atomicNumber,atomicWeight);
}
sigma *= sigmafactor;
// Calculate lambda
if ( sigma > 0.0) sigma = 1.0/sigma;
else sigma = DBL_MAX;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MscModel::ComputeTransportCrossSection(
const G4ParticleDefinition* part,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicWeight)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc);
const G4double epsmin = 1.e-4 , epsmax = 1.e10;
const G4double Zdat[15] = { 4., 6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. };
const G4double Tdat[23] = {0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,
0.01*MeV,0.02*MeV,0.04*MeV,0.07*MeV,
0.1*MeV,0.2*MeV,0.4*MeV,0.7*MeV,
1.*MeV,2.*MeV,4.*MeV,7.*MeV,10.*MeV,20.*MeV,
10000.0*MeV};
// corr. factors for e-/e+ lambda
G4double celectron[15][23] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087,0.7235 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082,0.7925 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098,0.9147 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098,0.9700 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056,1.0022 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052,1.0158 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050,1.0284 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036,1.0515 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024,1.0834 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020,1.0937 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011,1.1140 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987,1.1410 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963,1.1750 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954,1.1922 },
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949,1.2026 }};
G4double cpositron[15][23] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100,0.7235 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102,0.7925 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145,0.9147 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174,0.9700 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151,1.0022 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159,1.0158 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170,1.0284 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179,1.0515 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205,1.0834 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214,1.0937 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233,1.1140 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239,1.1410 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258,1.1750 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272,1.1922 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282,1.2026 }};
G4double sigma;
if (part != particle ) {
particle = part;
mass = particle->GetPDGMass();
charge = particle->GetPDGCharge()/eplus;
}
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
G4double eKineticEnergy = KineticEnergy;
if((particle->GetParticleName() != "e-") &&
(particle->GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/mass ;
G4double c = mass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
eKineticEnergy = electron_mass_c2*tau ;
}
G4double ChargeSquare = charge*charge;
G4double eTotalEnergy = eKineticEnergy + electron_mass_c2 ;
G4double beta2 = eKineticEnergy*(eTotalEnergy+electron_mass_c2)
/(eTotalEnergy*eTotalEnergy);
G4double bg2 = eKineticEnergy*(eTotalEnergy+electron_mass_c2)
/(electron_mass_c2*electron_mass_c2);
G4double eps = epsfactor*bg2/Z23;
if (eps<epsmin) sigma = 2.*eps*eps;
else if(eps<epsmax) sigma = log(1.+2.*eps)-2.*eps/(1.+2.*eps);
else sigma = log(2.*eps)-1.+1./eps;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/(beta2*bg2);
// nuclear size effect correction for high energy
// ( a simple approximation at present)
G4double corrnuclsize,a,w1,w2,w;
G4double x0 = 1. - NuclCorrPar*mass/(KineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( x0 < -1. || eKineticEnergy <= 10.*MeV)
{
x0 = -1.;
corrnuclsize = 1.;
}
else
{
a = 1.+1./eps;
if (eps > epsmax) w1=log(2.*eps)+1./eps-3./(8.*eps*eps);
else w1=log((a+1.)/(a-1.))-2./(a+1.);
w = 1./((1.-x0)*eps);
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*mass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber)) iZ -= 1;
if (iZ==14) iZ = 13;
if (iZ==-1) iZ = 0 ;
G4double Z1 = Zdat[iZ];
G4double Z2 = Zdat[iZ+1];
G4double ratZ = (AtomicNumber-Z1)/(Z2-Z1);
// get bin number in T (beta2)
G4int iT = 22;
while ((iT>=0)&&(Tdat[iT]>=eKineticEnergy)) iT -= 1;
if(iT==22) iT = 21;
if(iT==-1) iT = 0 ;
// calculate betasquare values
G4double T = Tdat[iT], E = T + electron_mass_c2;
G4double b2small = T*(E+electron_mass_c2)/(E*E);
T = Tdat[iT+1]; E = T + electron_mass_c2;
G4double b2big = T*(E+electron_mass_c2)/(E*E);
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double c1,c2,cc1,cc2,corr;
if (charge < 0.)
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = celectron[iZ][iT+1];
c2 = celectron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
if (charge > 0.)
{
c1 = cpositron[iZ][iT];
c2 = cpositron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = cpositron[iZ][iT+1];
c2 = cpositron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
// nucl. size correction for particles other than e+/e- only at present !!!!
if((particle->GetParticleName() != "e-") &&
(particle->GetParticleName() != "e+") )
sigma /= corrnuclsize;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MscModel::GeomPathLength(
G4PhysicsTable* theLambdaTable,
const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* theParticle,
G4double& T0,
G4double lambda,
G4double range,
G4double truePathLength)
{
// do the true -> geom transformation
const G4double ztmax = 101./103. ;
if (theParticle != particle ) {
particle = theParticle;
mass = particle->GetPDGMass();
charge = particle->GetPDGCharge()/eplus;
}
currentKinEnergy = T0;
currentRange = range ;
currentRadLength = couple->GetMaterial()->GetRadlen();
lambda0 = lambda;
par1 = -1. ;
par2 = par3 = 0. ;
tPathLength = truePathLength;
// this correction needed to run MSC with eIoni and eBrem inactivated
// and makes no harm for a normal run
if(tPathLength > range)
tPathLength = range ;
G4double tau = tPathLength/lambda0 ;
if (tau <= tausmall) return tPathLength;
G4double zmean = tPathLength;
if (tPathLength < range*dtrl) {
zmean = lambda0*(1.-exp(-tau));
if(tau < taulim) zmean = tPathLength*(1.-0.5*tPathLength/lambda0) ;
} else if(T0 < mass) {
par1 = 1./range ;
par2 = 1./(par1*lambda0) ;
par3 = 1.+par2 ;
zmean = (1.-exp(par3*log(1.-tPathLength/range)))/(par1*par3) ;
} else {
G4LossTableManager* theManager = G4LossTableManager::Instance();
G4double T1 = theManager->GetEnergy(particle,range-tPathLength,couple);
G4double lambda1 ;
if (theLambdaTable) {
G4bool bb;
lambda1 = ((*theLambdaTable)[couple->GetIndex()])->GetValue(T1,bb);
} else {
lambda1 = CrossSection(couple,particle,T1,0.0,1.0);
}
par1 = (lambda0-lambda1)/(lambda0*tPathLength) ;
par2 = 1./(par1*lambda0) ;
par3 = 1.+par2 ;
zmean = (1.-exp(par3*log(lambda1/lambda0)))/(par1*par3) ;
}
// sample z
G4double zPathLength = zmean ;
G4double zt = zmean/tPathLength ;
if (tPathLength >= stepmin && samplez && zt > 0.5 && zt < ztmax)
{
G4double cz = 0.5*(3.*zt-1.)/(1.-zt) ;
G4double cz1 = 1.+cz ;
G4double u0 = cz/cz1 ;
G4double u,grej ;
do {
u = exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(u/u0))*(1.-u)/(1.-u0) ;
} while (grej < G4UniformRand()) ;
zPathLength = tPathLength*u ;
}
return zPathLength ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MscModel::TrueStepLength(G4double geomStepLength)
{
G4double trueLength = geomStepLength;
trueLength = geomStepLength;
if(geomStepLength > lambda0*tausmall)
{
if(par1 < 0.)
trueLength = -lambda0*log(1.-geomStepLength/lambda0) ;
else
{
if(par1*par3*geomStepLength < 1.)
trueLength = (1.-exp(log(1.-par1*par3*geomStepLength)/par3))/par1 ;
else
trueLength = currentRange ;
}
}
if(trueLength > tPathLength) trueLength = tPathLength;
if(trueLength > currentRange) trueLength = currentRange ;
if(trueLength < geomStepLength) trueLength = geomStepLength;
return trueLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MscModel::SampleCosineTheta(G4double trueStepLength, G4double KineticEnergy)
{
G4double cth = 1. ;
G4double tau = trueStepLength/lambda0 ;
if(trueStepLength >= currentRange*dtrl)
if(par1*trueStepLength < 1.)
tau = -par2*log(1.-par1*trueStepLength) ;
else
tau = taubig ;
currentTau = tau ;
if(trueStepLength < stepmin)
cth = exp(-tau) ;
else
{
if (tau >= taubig) cth = -1.+2.*G4UniformRand();
else if (tau >= tausmall)
{
G4double a ;
// for all particles take the width of the central part
// from a parametrization similar to the Highland formula
// ( 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 xx0 = trueStepLength/currentRadLength;
G4double betacp = sqrt(currentKinEnergy*(currentKinEnergy+2.*mass)*
KineticEnergy*(KineticEnergy+2.*mass)/
((currentKinEnergy+mass)*(KineticEnergy+mass))) ;
G4double theta0 = c_highland*Q*exp(corr_highland*log(xx0))/betacp ;
if(theta0 > taulim) a = 0.5/(1.-cos(theta0)) ;
else a = 1.0/(theta0*theta0) ;
G4double xmeanth = exp(-tau);
G4double xmeanth1 = 1.-xmeanth ;
if(currentTau < taulim) xmeanth1 = tau ;
const G4double x1fac1 = exp(-xsi) ;
const G4double x1fac2 = (1.-(1.+xsi)*x1fac1)/(1.-x1fac1) ;
const G4double x1fac3 = 1.3 ;
G4double ea,eaa,xmean1 ;
G4double c = 2.,b1 = 2., bx = 2.,
eb1 = b1, ebx = b1, xmean2 = 0. ;
G4double prob = 1., qprob ;
G4double x0 = 1.-xsi/a;
G4double oneminusx0=xsi/a ;
G4double oneplusx0=2.+xsi/a ;
G4double f1x0=1., f2x0=1. ;
const G4double tau0 = 0.10 ;
if(tau > tau0)
{
// 1 model function
a = 1./xmeanth1 ;
ea = exp(-2.*a) ;
eaa= 1.-ea ;
xmean1 = 1.-1./a+2.*ea/eaa ;
prob = 1. ;
qprob = 1. ;
}
else if (x0 <= -1.)
{
// 2 model fuctions only
// in order to have xmean1 > xmeanth -> qprob < 1
x0 = -1.;
if( a < 1./xmeanth1)
a = 1./xmeanth1 ;
oneminusx0 = 1.-x0 ;
oneplusx0 = 1.+x0 ;
ea = exp(-a*oneminusx0);
eaa = 1.-ea ;
xmean1 = 1.-1./a+oneminusx0*ea/eaa ;
qprob = xmeanth/xmean1 ;
}
else
{
// 3 model fuctions
// in order to have xmean1 > xmeanth
if((1.-x1fac2/a) < xmeanth)
{
a = x1fac3*x1fac2/xmeanth1 ;
x0 = 1.-xsi/a ;
oneminusx0=xsi/a ;
oneplusx0=2.-xsi/a ;
}
ea = x1fac1 ;
eaa = 1.-ea ;
xmean1 = 1.-x1fac2/a ;
const G4double fctail = factail*1.0 ;
c = 2.+fctail*tau ;
G4double c1 = c-1. ;
G4double c2 = c-2. ;
if(c2 == 0.) c2 = fctail*tausmall ;
b = 1.+(c-xsi)/a ;
b1 = b+1. ;
bx = c/a ;
eb1=exp((c1)*log(b1)) ;
ebx=exp((c1)*log(bx)) ;
xmean2 = (x0*eb1+ebx-(eb1*bx-b1*ebx)/c2)/(eb1-ebx) ;
f1x0 = a*ea/eaa ;
f2x0 = c1*eb1*ebx/(eb1-ebx)/
exp(c*log(bx)) ;
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
}
// sampling of costheta
if (G4UniformRand() < qprob)
{
if (G4UniformRand() < prob)
cth = 1.+log(ea+G4UniformRand()*eaa)/a ;
else
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
{
cth = -1.+2.*G4UniformRand();
}
}
}
return cth ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4MscModel::SampleDisplacement()
{
const G4double kappa = 2.5;
const G4double kappapl1 = kappa+1.;
const G4double kappami1 = kappa-1.;
G4double rmean = 0.0;
if (currentTau >= tausmall) {
if (currentTau < taulim) {
rmean = kappa*currentTau*currentTau*currentTau*(1.-kappapl1*currentTau*0.25)/6. ;
} else {
G4double etau = 0.0;
if (currentTau<taubig) etau = exp(-currentTau);
rmean = -kappa*currentTau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += currentTau-kappapl1/kappa+kappa*etau/kappami1;
}
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.0);
else rmean = 0.;
}
return rmean;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,183 @@
//
// ********************************************************************
// * 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: G4MultipleScattering.cc,v 1.23 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
// 18/05/01 V.Ivanchenko Clean up against Linux ANSI compilation
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 23-08-01 new angle and z distribution,energy dependence reduced,
// Store,Retrieve methods commented out temporarily, L.Urban
// 27-08-01 in BuildPhysicsTable:aParticleType.GetParticleName()=="mu+" (mma)
// 28-08-01 GetContinuousStepLimit and AlongStepDoIt moved from .icc file (mma)
// 03-09-01 value of data member factlim changed, L.Urban
// 10-09-01 small change in GetContinuousStepLimit, L.Urban
// 11-09-01 G4MultipleScatteringx put as default G4MultipleScattering
// store/retrieve physics table reactivated (mma)
// 13-09-01 corr. in ComputeTransportCrossSection, L.Urban
// 14-09-01 protection in GetContinuousStepLimit, L.Urban
// 17-09-01 migration of Materials to pure STL (mma)
// 27-09-01 value of data member factlim changed, L.Urban
// 31-10-01 big fixed in PostStepDoIt,L.Urban
// 17-04-02 NEW angle distribution + boundary algorithm modified, L.Urban
// 22-04-02 boundary algorithm modified -> important improvement in timing (L.Urban)
// 24-04-02 some minor changes in boundary algorithm, L.Urban
// 06-05-02 bug fixed in GetContinuousStepLimit, L.Urban
// 24-05-02 changes in angle distribution and boundary algorithm, L.Urban
// 11-06-02 bug fixed in ComputeTransportCrossSection, L.Urban
// 12-08-02 bug fixed in PostStepDoIt (lateral displacement), L.Urban
// 15-08-02 new angle distribution, L.Urban
// 26-09-02 angle distribution + boundary algorithm modified, L.Urban
// 15-10-02 temporary fix for proton scattering
// 30-10-02 modified angle distribution,mods in boundary algorithm,
// changes in data members, L.Urban
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured from L.Urban
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 05-02-03 changes in data members, new sampling for geom.
// path length, step dependence reduced with new
// method
// 28-03-03 Move to model design (V.Ivanchenko)
// 08-08-03 STD substitute standard (V.Ivanchenko)
// 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)
//
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4MultipleScattering.hh"
#include "G4MscModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
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)
{
lowKineticEnergy = 0.1*keV;
highKineticEnergy= 100.*TeV;
tlimit = 1.e10*mm;
tlimitmin = 1.e-7*mm;
SetBinning(totBins);
SetMinKinEnergy(lowKineticEnergy);
SetMaxKinEnergy(highKineticEnergy);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScattering::~G4MultipleScattering()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering::InitialiseProcess(const G4ParticleDefinition* particle)
{
if (particle->GetParticleType() == "nucleus") {
SetBoundary(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->SetLowEnergyLimit(lowKineticEnergy);
em->SetHighEnergyLimit(highKineticEnergy);
AddEmModel(1, em);
boundary = BoundaryAlgorithmFlag();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering::TruePathLengthLimit(const G4Track& track,
G4double& lambda,
G4double currentMinimalStep)
{
G4double tPathLength = currentMinimalStep;
// special treatment near boundaries ?
if (boundary) {
G4int stepno = track.GetCurrentStepNumber() ;
// first step
if (stepno == 1) {
stepnolastmsc = -1000000 ;
tlimit = 1.e10;
} else if (stepno > 1) {
if (track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary) {
stepnolastmsc = stepno;
// if : diff.treatment for small/not small Z
G4double range = CurrentRange();
if (range > lambda) tlimit = facrange*range;
else tlimit = facrange*lambda;
if(tlimit < tlimitmin) tlimit = tlimitmin;
if(tPathLength > tlimit) tPathLength = tlimit;
} else if (stepno > stepnolastmsc && stepno - stepnolastmsc < nsmallstep
&& tPathLength > tlimit) {
tlimit *= cf;
tPathLength = tlimit;
}
}
}
return tPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering::PrintInfoDefinition()
{
G4VMultipleScattering::PrintInfoDefinition();
if(boundary) {
G4cout << " Boundary algorithm is active with facrange= "
<< facrange
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,950 @@
//
// ********************************************************************
// * 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: G4MultipleScattering52.cc,v 1.2 2004/12/01 19:37:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
// 18/05/01 V.Ivanchenko Clean up against Linux ANSI compilation
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 23-08-01 new angle and z distribution,energy dependence reduced,
// Store,Retrieve methods commented out temporarily, L.Urban
// 27-08-01 in BuildPhysicsTable:aParticleType.GetParticleName()=="mu+" (mma)
// 28-08-01 GetContinuousStepLimit and AlongStepDoIt moved from .icc file (mma)
// 03-09-01 value of data member factlim changed, L.Urban
// 10-09-01 small change in GetContinuousStepLimit, L.Urban
// 11-09-01 G4MultipleScatteringx put as default G4MultipleScattering
// store/retrieve physics table reactivated (mma)
// 13-09-01 corr. in ComputeTransportCrossSection, L.Urban
// 14-09-01 protection in GetContinuousStepLimit, L.Urban
// 17-09-01 migration of Materials to pure STL (mma)
// 27-09-01 value of data member factlim changed, L.Urban
// 31-10-01 big fixed in PostStepDoIt,L.Urban
// 24-04-02 some minor changes in boundary algorithm, L.Urban
// 06-05-02 bug fixed in GetContinuousStepLimit, L.Urban
// 24-05-02 changes in angle distribution and boundary algorithm, L.Urban
// 11-06-02 bug fixed in ComputeTransportCrossSection, L.Urban
// 12-08-02 bug fixed in PostStepDoIt (lateral displacement), L.Urban
// 15-08-02 new angle distribution, L.Urban
// 26-09-02 angle distribution + boundary algorithm modified, L.Urban
// 15-10-02 temporary fix for proton scattering
// 30-10-02 modified angle distribution,mods in boundary algorithm,
// changes in data members, L.Urban
// 30-10-02 rename variable cm - Ecm, V.Ivanchenko
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured, L.Urban
// 05-02-03 changes in data members, new sampling for geom.
// path length, step dependence reduced with new
// method
// 17-03-03 cut per region, V.Ivanchenko
// 13-04-03 add initialisation in GetContinuesStepLimit
// + change table size (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (M.Asai)
// 23-05-03 important change in angle distribution for muons/hadrons
// the central part now is similar to the Highland parametrization +
// minor correction in angle sampling algorithm (for all particles)
// (L.Urban)
// 24-05-03 bug in nuclear size corr.computation fixed thanks to Vladimir(L.Urban)
// 30-05-03 misprint in PostStepDoIt corrected(L.Urban)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
// 08-11-04 Remove Store/Retrieve tables (V.Ivantchenko)
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4MultipleScattering52.hh"
#include "G4StepStatus.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4MultipleScattering52::G4MultipleScattering52(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(0),
taubig(8.0),tausmall(1.e-14),taulim(1.e-5),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
materialIndex(0),
tLast (0.0),
zLast (0.0),
boundary(true),
facrange(0.199),tlimit(1.e10*mm),tlimitmin(1.e-7*mm),
cf(1.001),
stepno(0),stepnolastmsc(-1000000),nsmallstep(5),
laststep(0.),
valueGPILSelectionMSC(NotCandidateForSelection),
zmean(0.),samplez(true),
range(1.),T0(1.),T1(1.),lambda0(1.),lambda1(-1.),
Tlow(0.),alam(1.),blam(1.),dtrl(0.15),
lambdam(-1.),clam(1.),zm(1.),cthm(1.),
fLatDisplFlag(true),
NuclCorrPar (0.0615),
FactPar(0.40),
facxsi(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScattering52::~G4MultipleScattering52()
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering52::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
// ..............................
Tlow = aParticleType.GetPDGMass();
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius;
G4double KineticEnergy,AtomicNumber,AtomicWeight,sigma,lambda;
G4double density;
// destroy old tables if any
if (theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy();
delete theTransportMeanFreePathTable;
}
// create table
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theTransportMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (size_t i=0; i<numOfCouples; i++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4MaterialCutsCouple* couple = theCoupleTable->
GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume =
material->GetVecNbOfAtomsPerVolume();
const G4int NumberOfElements = material->GetNumberOfElements();
density = material->GetDensity();
// loop for kinetic energy values
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i);
sigma = 0.;
// loop for element in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
AtomicNumber = (*theElementVector)[iel]->GetZ();
AtomicWeight = (*theElementVector)[iel]->GetA();
sigma += NbOfAtomsPerVolume[iel]*
ComputeTransportCrossSection(aParticleType,KineticEnergy,
AtomicNumber,AtomicWeight);
}
sigma *= sigmafactor;
lambda = 1./sigma;
aVector->PutValue(i,lambda);
}
theTransportMeanFreePathTable->insert(aVector);
}
if((aParticleType.GetParticleName() == "e-" ) ||
(aParticleType.GetParticleName() == "mu+" ) ||
(aParticleType.GetParticleName() == "proton") ) PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering52::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,G4double AtomicWeight)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc);
const G4double epsmin = 1.e-4 , epsmax = 1.e10;
const G4double Zdat[15] = { 4., 6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. };
const G4double Tdat[23] = {0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,
0.01*MeV,0.02*MeV,0.04*MeV,0.07*MeV,
0.1*MeV,0.2*MeV,0.4*MeV,0.7*MeV,
1.*MeV,2.*MeV,4.*MeV,7.*MeV,10.*MeV,20.*MeV,
10000.0*MeV};
// corr. factors for e-/e+ lambda
G4double celectron[15][23] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087,0.7235 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082,0.7925 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098,0.9147 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098,0.9700 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056,1.0022 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052,1.0158 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050,1.0284 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036,1.0515 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024,1.0834 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020,1.0937 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011,1.1140 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987,1.1410 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963,1.1750 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954,1.1922 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, // paper.....
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949,1.2026 }};
G4double cpositron[15][23] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100,0.7235 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102,0.7925 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145,0.9147 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174,0.9700 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151,1.0022 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159,1.0158 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170,1.0284 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179,1.0515 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205,1.0834 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214,1.0937 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233,1.1140 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239,1.1410 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258,1.1750 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272,1.1922 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282,1.2026 }};
G4double sigma;
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
G4double ParticleMass = aParticleType.GetPDGMass();
G4double ParticleKineticEnergy = KineticEnergy ;
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
G4double Mass = ParticleMass ;
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/Mass ;
G4double c = Mass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
KineticEnergy = electron_mass_c2*tau ;
Mass = electron_mass_c2 ;
}
G4double Charge = aParticleType.GetPDGCharge();
G4double ChargeSquare = Charge*Charge/(eplus*eplus);
G4double TotalEnergy = KineticEnergy + Mass ;
G4double beta2 = KineticEnergy*(TotalEnergy+Mass)
/(TotalEnergy*TotalEnergy);
G4double bg2 = KineticEnergy*(TotalEnergy+Mass)
/(Mass*Mass);
G4double eps = epsfactor*bg2/Z23;
if (eps<epsmin) sigma = 2.*eps*eps;
else if(eps<epsmax) sigma = log(1.+2.*eps)-2.*eps/(1.+2.*eps);
else sigma = log(2.*eps)-1.+1./eps;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/(beta2*bg2);
// nuclear size effect correction for high energy
// ( a simple approximation at present)
G4double corrnuclsize,a,x0,w1,w2,w;
x0 = 1. - NuclCorrPar*ParticleMass/(ParticleKineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( (x0 < -1.) || (ParticleKineticEnergy <= 10.*MeV))
{ x0 = -1.; corrnuclsize = 1.;}
else
{ a = 1.+1./eps;
if (eps > epsmax) w1=log(2.*eps)+1./eps-3./(8.*eps*eps);
else w1=log((a+1.)/(a-1.))-2./(a+1.);
w = 1./((1.-x0)*eps);
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*ParticleMass/ParticleKineticEnergy)*
(corrnuclsize-1.)+1.;
}
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber)) iZ -= 1;
if (iZ==14) iZ = 13;
if (iZ==-1) iZ = 0 ;
G4double Z1 = Zdat[iZ];
G4double Z2 = Zdat[iZ+1];
G4double ratZ = (AtomicNumber-Z1)/(Z2-Z1);
// get bin number in T (beta2)
G4int iT = 22;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy)) iT -= 1;
if(iT==22) iT = 21;
if(iT==-1) iT = 0 ;
// calculate betasquare values
G4double T = Tdat[iT], E = T + electron_mass_c2;
G4double b2small = T*(E+electron_mass_c2)/(E*E);
T = Tdat[iT+1]; E = T + electron_mass_c2;
G4double b2big = T*(E+electron_mass_c2)/(E*E);
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double c1,c2,cc1,cc2,corr;
if (Charge < 0.)
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = celectron[iZ][iT+1];
c2 = celectron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
if (Charge > 0.)
{
c1 = cpositron[iZ][iT];
c2 = cpositron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = cpositron[iZ][iT+1];
c2 = cpositron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
// nucl. size correction for particles other than e+/e- only at present !!!!
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
sigma /= corrnuclsize;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering52::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength;
const G4DynamicParticle* aParticle;
G4double tau,zt,cz,cz1,grej,grej0;
const G4double expmax = 100., ztmax = (2.*expmax+1.)/(2.*expmax+3.) ;
const G4double tmax = 1.e20*mm ;
G4bool isOut;
// this process is not a candidate for selection by default
valueGPILSelectionMSC = NotCandidateForSelection;
tPathLength = currentMinimumStep;
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
materialIndex = couple->GetIndex();
aParticle = track.GetDynamicParticle();
T0 = aParticle->GetKineticEnergy();
lambda0 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T0,isOut);
range = G4EnergyLossTables::GetRange(aParticle->GetDefinition(),
T0,couple);
//VI Initialisation at the beginning of the step
cthm = 1.;
lambda1 = -1.;
lambdam = -1.;
alam = range;
blam = 1.+alam/lambda0 ;
zm = 1.;
// special treatment near boundaries ?
if (boundary && range >= currentMinimumStep)
{
// step limitation at boundary ?
stepno = track.GetCurrentStepNumber() ;
if(stepno == 1)
{
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
// if : diff.treatment for small/not small Z
if(range > lambda0)
tlimit = facrange*range ;
else
tlimit = facrange*lambda0 ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
laststep = tlimit ;
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
else if(stepno > stepnolastmsc)
{
if((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
}
}
// do the true -> geom transformation
zmean = tPathLength;
tau = tPathLength/lambda0 ;
if (tau < tausmall || range < currentMinimumStep) zPathLength = tPathLength;
else
{
if(tPathLength/range < dtrl) zmean = lambda0*(1.-exp(-tau));
else
{
T1 = G4EnergyLossTables::GetPreciseEnergyFromRange(
aParticle->GetDefinition(),range-tPathLength,couple);
lambda1 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T1,isOut);
if(T0 < Tlow)
alam = range ;
else
alam = lambda0*tPathLength/(lambda0-lambda1) ;
blam = 1.+alam/lambda0 ;
if(tPathLength/range < 2.*dtrl)
{
zmean = alam*(1.-exp(blam*log(1.-tPathLength/alam)))/blam ;
lambdam = -1. ;
}
else
{
G4double w = 1.-0.5*tPathLength/alam ;
lambdam = lambda0*w ;
clam = 1.+alam/lambdam ;
cthm = exp(alam*log(w)/lambda0) ;
zm = alam*(1.-exp(blam*log(w)))/blam ;
zmean = zm + alam*(1.-exp(clam*log(w)))*cthm/clam ;
}
}
// sample z
zt = zmean/tPathLength ;
if (samplez && (zt < ztmax) && (zt > 0.5))
{
cz = 0.5*(3.*zt-1.)/(1.-zt) ;
if(tPathLength < exp(log(tmax)/(2.*cz)))
{
cz1 = 1.+cz ;
grej0 = exp(cz1*log(cz*tPathLength/cz1))/cz ;
do
{
zPathLength = tPathLength*exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(zPathLength))*(tPathLength-zPathLength)/grej0 ;
} while (grej < G4UniformRand()) ;
}
else zPathLength = zmean;
}
else zPathLength = zmean;
}
// protection against z > lambda
if(zPathLength > lambda0)
zPathLength = lambda0 ;
tLast = tPathLength;
zLast = zPathLength;
return zPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScattering52::AlongStepDoIt(
const G4Track& track,const G4Step& step)
{
// only a geom path->true path transformation is performed
fParticleChange.Initialize(track);
G4double geomPathLength = step.GetStepLength();
G4double truePathLength = 0. ;
//VI change order of if operators
if(geomPathLength == zLast) truePathLength = tLast;
else if(geomPathLength/lambda0 < tausmall) truePathLength = geomPathLength;
else
{
if(lambda1 < 0.) truePathLength = -lambda0*log(1.-geomPathLength/lambda0) ;
else if(lambdam < 0.)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = tLast;
}
else
{
if(geomPathLength <= zm)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = 0.5*tLast;
lambdam = -1. ;
}
else
{
if(clam*(geomPathLength-zm)/(alam*cthm) < 1.)
truePathLength = 0.5*tLast + alam*(1.-
exp(log(1.-clam*(geomPathLength-zm)/(alam*cthm)))/clam) ;
else
truePathLength = tLast ;
}
}
// protection ....
if(truePathLength > tLast)
truePathLength = tLast ;
}
//VI truePath length cannot be smaller than geomPathLength
if (truePathLength < geomPathLength) truePathLength = geomPathLength;
fParticleChange.ProposeTrueStepLength(truePathLength);
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScattering52::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
// angle distribution parameters
const G4double kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
fParticleChange.Initialize(trackData);
G4double truestep = stepData.GetStepLength();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double KineticEnergy = aParticle->GetKineticEnergy();
G4double Mass = aParticle->GetDefinition()->GetPDGMass() ;
// do nothing for stopped particles !
if(KineticEnergy > 0.)
{
// change direction first ( scattering )
G4double cth = 1.0 ;
G4double tau = truestep/lambda0 ;
if (tau < tausmall) cth = 1.;
else if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
if(lambda1 > 0.)
{
if(lambdam < 0.)
tau = -alam*log(1.-truestep/alam)/lambda0 ;
else
tau = -log(cthm)-alam*log(1.-(truestep-0.5*tLast)/alam)/lambdam ;
}
if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double amax=25. ;
const G4double tau0 = 0.02 ;
const G4double c_highland = 13.6*MeV, corr_highland=0.038 ;
const G4double x1fac1 = exp(-xsi) ;
const G4double x1fac2 = (1.-(1.+xsi)*x1fac1)/(1.-x1fac1) ;
const G4double x1fac3 = 1.3 ; // x1fac3 >= 1. !!!!!!!!!
G4double a,x0,c,xmean1,xmean2,
xmeanth,prob,qprob ;
G4double ea,eaa,b1,bx,eb1,ebx,cnorm1,cnorm2,f1x0,f2x0,w ;
// for heavy particles take the width of the cetral part
// from the Highland formula
// (Particle Physics Booklet, July 2002, eq. 26.10)
if(Mass > electron_mass_c2) // + other conditions (beta, x/X0,...?)
{
G4double Q = fabs(aParticle->GetDefinition()->GetPDGCharge()) ;
G4double X0 = trackData.GetMaterialCutsCouple()->
GetMaterial()->GetRadlen() ;
G4double xx0 = truestep/X0 ;
G4double betacp = KineticEnergy*(KineticEnergy+2.*Mass)/
(KineticEnergy+Mass) ;
G4double theta0=c_highland*Q*sqrt(xx0)*
(1.+corr_highland*log(xx0))/betacp ;
if(theta0 > tausmall)
a = 0.5/(1.-cos(theta0)) ;
else
a = 1./(theta0*theta0) ;
}
else
{
w = log(tau/tau0) ;
if(tau < tau0)
a = (alfa1-alfa2*w)/tau ;
else
a = (alfa1+alfa3*w)/tau ;
}
xmeanth = exp(-tau) ;
x0 = 1.-xsi/a ;
if(x0 < -1.) x0 = -1. ;
if(x0 == -1.)
{
// 1 model fuction only
// in order to have xmean1 > xmeanth -> qprob < 1
if((1.-1./a) < xmeanth)
a = 1./(1.-xmeanth) ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
c = 2. ;
b1 = b+1. ;
bx = b1 ;
eb1 = b1 ;
ebx = b1 ;
xmean2 = 0. ;
prob = 1. ;
qprob = xmeanth/xmean1 ;
}
else
{
// 2 model fuctions
// in order to have xmean1 > xmeanth
if((1.-x1fac2/a) < xmeanth)
{
a = x1fac3*x1fac2/(1.-xmeanth) ;
if(a*(1.-x0) < amax)
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
}
else
{
ea = x1fac1 ;
eaa = 1.-x1fac1 ;
xmean1 = 1.-x1fac2/a ;
}
// from continuity of the 1st derivatives
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
b1 = b+1. ;
bx=b-x0 ;
eb1=exp((c-1.)*log(b1)) ;
ebx=exp((c-1.)*log(bx)) ;
xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
cnorm1 = a/eaa ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
// from continuity at x=x0
prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
}
// protection against prob or qprob > 1 and
// prob or qprob < 0
// ***************************************************************
if((qprob > 1.) || (qprob < 0.) || (prob > 1.) || (prob < 0.))
{
// this print possibility has been left intentionally
// for debugging purposes ..........................
G4bool pr = false ;
// pr = true ;
if(pr)
{
const G4double prlim = 0.10 ;
if((fabs((xmeanth-xmean2)/(xmean1-xmean2)-prob)/prob > prlim) ||
((xmeanth-xmean2)/(xmean1-xmean2) > 1.) ||
((xmeanth-xmean2)/(xmean1-xmean2) < 0.) )
{
G4cout.precision(5) ;
G4cout << "\nparticle=" << aParticle->GetDefinition()->
GetParticleName() << " in material "
<< trackData.GetMaterialCutsCouple()->
GetMaterial()->GetName() << " with kinetic energy "
<< KineticEnergy << " MeV," << G4endl ;
G4cout << " step length="
<< truestep << " mm" << G4endl ;
G4cout << "p=" << prob << " q=" << qprob << " -----> "
<< "p=" << (xmeanth-xmean2)/(xmean1-xmean2)
<< " q=" << 1. << G4endl ;
}
}
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
// **************************************************************
// sampling of costheta
if(G4UniformRand() < qprob)
{
if(G4UniformRand() < prob)
cth = 1.+log(ea+G4UniformRand()*eaa)/a ;
else
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
cth = -1.+2.*G4UniformRand() ;
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi), diry = sth*sin(phi), dirz = cth;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz);
newDirection.rotateUz(ParticleDirection);
fParticleChange.ProposeMomentumDirection(newDirection.x(),
newDirection.y(),
newDirection.z());
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean, etau;
if (safetyminustolerance > 0.)
{
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6.;
else
{
if(tau<taubig) etau = exp(-tau);
else etau = 0.;
rmean = -kappa*tau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += tau-kappapl1/kappa+kappa*etau/kappami1;
}
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.);
else rmean = 0.;
// for rmean > 0) only
if (rmean > 0.)
{
if (rmean>safetyminustolerance) rmean = safetyminustolerance;
// sample direction of lateral displacement
phi = twopi*G4UniformRand();
dirx = cos(phi); diry = sin(phi); dirz = 0.;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection);
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
navigator->LocateGlobalPointWithinVolume(newPosition);
fParticleChange.ProposePosition(newPosition);
}
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering52::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
comments += "\n New model of MSC , computes the lateral \n";
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowestKineticEnergy ,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -28,6 +28,9 @@
//
// Modifications:
//
// 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
//
#include "G4Region.hh"
#include "G4PhysicsLogVector.hh"
@@ -48,9 +51,10 @@
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
////////////////////////////////////////////////////////////////////////
using namespace std;
G4PAIModel::G4PAIModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),G4VEmFluctuationModel(nam),
fLowestKineticEnergy(10.0*keV),
@@ -68,7 +72,7 @@ G4PAIModel::G4PAIModel(const G4ParticleDefinition* p, const G4String& nam)
fProtonEnergyVector = new G4PhysicsLogVector(fLowestKineticEnergy,
fHighestKineticEnergy,
fTotBin);
fPAItransferBank = 0;
fPAItransferTable = 0;
fPAIdEdxTable = 0;
fSandiaPhotoAbsCof = 0;
fdEdxVector = 0;
@@ -84,10 +88,11 @@ G4PAIModel::~G4PAIModel()
if(fdEdxVector) delete fdEdxVector ;
if ( fLambdaVector) delete fLambdaVector;
if ( fdNdxCutVector) delete fdNdxCutVector;
if( fPAItransferBank )
if( fPAItransferTable )
{
fPAItransferBank->clearAndDestroy();
delete fPAItransferBank ;
fPAItransferTable->clearAndDestroy();
delete fPAItransferTable ;
}
if(fSandiaPhotoAbsCof)
{
@@ -132,9 +137,9 @@ G4double G4PAIModel::LowEnergyLimit( const G4ParticleDefinition* p )
////////////////////////////////////////////////////////////////////////////
G4double G4PAIModel::MinEnergyCut( const G4ParticleDefinition*,
const G4MaterialCutsCouple* couple )
const G4MaterialCutsCouple*)
{
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
return 0.*eV; // any positive cut
}
////////////////////////////////////////////////////////////////////////////
@@ -161,7 +166,7 @@ void G4PAIModel::Initialise(const G4ParticleDefinition* p,
// (*fPAIRegionVector[iRegion])
std::vector<G4Material*>::const_iterator matIter = curReg->GetMaterialIterator();
vector<G4Material*>::const_iterator matIter = curReg->GetMaterialIterator();
size_t jMat;
size_t numOfMat = curReg->GetNumberOfMaterials();
@@ -184,7 +189,8 @@ void G4PAIModel::Initialise(const G4ParticleDefinition* p,
ComputeSandiaPhotoAbsCof();
BuildPAIonisationTable();
fPAIxscBank.push_back(fPAItransferBank);
fPAIxscBank.push_back(fPAItransferTable);
fPAIdEdxBank.push_back(fPAIdEdxTable);
fdEdxTable.push_back(fdEdxVector);
@@ -253,13 +259,13 @@ G4PAIModel::BuildPAIonisationTable()
G4double LowEdgeEnergy , ionloss ;
G4double massRatio, tau, Tmax, Tmin, Tkin, deltaLow, gamma, bg2 ;
/*
if( fPAItransferBank )
if( fPAItransferTable )
{
fPAItransferBank->clearAndDestroy() ;
delete fPAItransferBank ;
fPAItransferTable->clearAndDestroy() ;
delete fPAItransferTable ;
}
*/
fPAItransferBank = new G4PhysicsTable(fTotBin);
fPAItransferTable = new G4PhysicsTable(fTotBin);
/*
if( fPAIdEdxTable )
{
@@ -328,7 +334,7 @@ G4PAIModel::BuildPAIonisationTable()
if ( ionloss <= 0.) ionloss = DBL_MIN ;
fdEdxVector->PutValue(i,ionloss) ;
fPAItransferBank->insertAt(i,transferVector) ;
fPAItransferTable->insertAt(i,transferVector) ;
fPAIdEdxTable->insertAt(i,dEdxVector) ;
// delete[] transferVector ;
@@ -363,7 +369,7 @@ G4PAIModel::BuildLambdaVector(const G4MaterialCutsCouple* matCutsCouple)
}
if( jMatCC == numOfCouples && jMatCC > 0 ) jMatCC--;
const std::vector<G4double>* deltaCutInKineticEnergy = theCoupleTable->
const vector<G4double>* deltaCutInKineticEnergy = theCoupleTable->
GetEnergyCutsVector(idxG4ElectronCut);
if (fLambdaVector) delete fLambdaVector;
@@ -402,33 +408,33 @@ G4PAIModel::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())
// G4cout<<"size = "<<G4int((*fPAItransferTable)(iPlace)->GetVectorLength())
// <<G4endl;
for( iTransfer = 0 ;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) ;
iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) ;
iTransfer++)
{
if(transferCut <= (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer))
if(transferCut <= (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
{
break ;
}
}
if ( iTransfer >= G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) )
if ( iTransfer >= G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) )
{
iTransfer = (*fPAItransferBank)(iPlace)->GetVectorLength() - 1 ;
iTransfer = (*fPAItransferTable)(iPlace)->GetVectorLength() - 1 ;
}
y1 = (*(*fPAItransferBank)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAItransferBank)(iPlace))(iTransfer) ;
y1 = (*(*fPAItransferTable)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAItransferTable)(iPlace))(iTransfer) ;
// G4cout<<"y1 = "<<y1<<"; "<<"y2 = "<<y2<<G4endl;
x1 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
x1 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
// G4cout<<"x1 = "<<x1<<"; "<<"x2 = "<<x2<<G4endl;
if ( y1 == y2 ) dNdxCut = y2 ;
else
{
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) 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;
@@ -470,7 +476,7 @@ G4PAIModel::GetdEdxCut( G4int iPlace, G4double transferCut)
else
{
// if ( x1 == x2 ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) 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;
@@ -486,7 +492,8 @@ G4double G4PAIModel::ComputeDEDX(const G4MaterialCutsCouple* matCC,
{
G4int iTkin,iPlace;
size_t jMat;
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
G4double massRatio = proton_mass_c2/p->GetPDGMass();
G4double scaledTkin = kineticEnergy*massRatio;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, dEdx;
@@ -520,8 +527,9 @@ G4double G4PAIModel::CrossSection( const G4MaterialCutsCouple* matCC,
{
G4int iTkin,iPlace;
size_t jMat;
G4double tmax = std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
G4double tmax = min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
G4double massRatio = proton_mass_c2/p->GetPDGMass();
G4double scaledTkin = kineticEnergy*massRatio;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, cross, cross1, cross2;
@@ -531,7 +539,7 @@ G4double G4PAIModel::CrossSection( const G4MaterialCutsCouple* matCC,
}
if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
fPAItransferBank = fPAIxscBank[jMat];
fPAItransferTable = fPAIxscBank[jMat];
for(iTkin = 0 ; iTkin < fTotBin ; iTkin++)
{
@@ -540,10 +548,18 @@ G4double G4PAIModel::CrossSection( const G4MaterialCutsCouple* matCC,
iPlace = iTkin - 1;
if(iPlace < 0) iPlace = 0;
cross1 = GetdNdxCut(iPlace,tmax) ;
// G4cout<<"iPlace = "<<iPlace<<"; tmax = "
// <<tmax<<"; cutEnergy = "<<cutEnergy<<G4endl;
cross1 = GetdNdxCut(iPlace,tmax) ;
// G4cout<<"cross1 = "<<cross1<<G4endl;
cross2 = GetdNdxCut(iPlace,cutEnergy) ;
// G4cout<<"cross2 = "<<cross2<<G4endl;
cross = (cross2-cross1)*charge2;
if( cross < 0.) cross = 0.;
// G4cout<<"cross = "<<cross<<G4endl;
if( cross < DBL_MIN) cross = DBL_MIN;
// if( cross2 < DBL_MIN) cross2 = DBL_MIN;
// return cross2;
return cross;
}
@@ -565,20 +581,33 @@ G4PAIModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
}
if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
fPAItransferBank = fPAIxscBank[jMat];
fdNdxCutVector = fdNdxCutTable[jMat];
fPAItransferTable = fPAIxscBank[jMat];
fdNdxCutVector = fdNdxCutTable[jMat];
G4double tmax = std::min(MaxSecondaryEnergy(dp), maxEnergy);
if( tmin >= tmax ) return 0;
G4double tmax = min(MaxSecondaryEnergy(dp), maxEnergy);
if( tmin >= tmax )
{
G4cout<<"G4PAIModel::SampleSecondary: tmin >= tmax "<<G4endl;
}
G4ThreeVector momentum = dp->GetMomentumDirection();
G4double particleMass = dp->GetMass();
G4double kineticEnergy = dp->GetKineticEnergy();
G4double scaledTkin = kineticEnergy*particleMass/proton_mass_c2;
G4double massRatio = proton_mass_c2/particleMass;
G4double scaledTkin = kineticEnergy*massRatio;
G4double totalEnergy = kineticEnergy + particleMass;
G4double pSquare = kineticEnergy*(totalEnergy+particleMass);
G4double deltaTkin = GetPostStepTransfer(scaledTkin);
if( deltaTkin <= 0. ) return 0;
if( deltaTkin <= 0. )
{
G4cout<<"Tkin of secondary e- <= 0."<<G4endl;
G4cout<<"G4PAIModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
deltaTkin = 10*eV;
G4cout<<"Set G4PAIModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
}
if(deltaTkin > kineticEnergy) deltaTkin = kineticEnergy;
G4double deltaTotalMomentum = sqrt(deltaTkin*(deltaTkin + 2. * electron_mass_c2 ));
G4double totalMomentum = sqrt(pSquare);
G4double costheta = deltaTkin*(totalEnergy + electron_mass_c2)
@@ -586,7 +615,7 @@ G4PAIModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
if (costheta < 0.) costheta = 0.;
if (costheta > +1.) costheta = +1.;
// direction of the delta electron
// direction of the delta electron
G4double phi = twopi*G4UniformRand();
G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
@@ -595,11 +624,11 @@ G4PAIModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
G4ThreeVector deltaDirection(dirx,diry,dirz);
deltaDirection.rotateUz(momentum);
// create G4DynamicParticle object for delta ray
// create G4DynamicParticle object for e- delta ray
G4DynamicParticle* deltaRay = new G4DynamicParticle;
deltaRay->SetDefinition(G4Electron::Electron());
deltaRay->SetKineticEnergy( deltaTkin );
deltaRay->SetKineticEnergy( deltaTkin ); // !!! trick for last steps /2.0 ???
deltaRay->SetMomentumDirection(deltaDirection);
return deltaRay;
@@ -624,33 +653,35 @@ G4PAIModel::GetPostStepTransfer( G4double scaledTkin )
if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
}
iPlace = iTkin - 1 ;
// G4cout<<"from search, iPlace = "<<iPlace<<G4endl ;
if(iPlace < 0) iPlace = 0;
dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
// G4cout<<"dNdxCut1 = "<<dNdxCut1<<G4endl ;
// G4cout<<"iPlace = "<<iPlace<<endl ;
if(iTkin == fTotBin) // Fermi plato, try from left
{
position = dNdxCut1*G4UniformRand() ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
if(position >= (*(*fPAItransferTable)(iPlace))(iTransfer)) break ;
}
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
}
else
{
dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
// G4cout<<"dNdxCut2 = "<<dNdxCut2<<G4endl ;
if(iTkin == 0) // Tkin is too small, trying from right only
{
position = dNdxCut2*G4UniformRand() ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace+1)->GetVectorLength()); iTransfer++ )
iTransfer < G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
if(position >= (*(*fPAItransferTable)(iPlace+1))(iTransfer)) break ;
}
transfer = GetEnergyTransfer(iPlace+1,position,iTransfer);
}
@@ -667,16 +698,16 @@ G4PAIModel::GetPostStepTransfer( G4double scaledTkin )
// G4cout<<position<<"\t" ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
{
if( position >=
( (*(*fPAItransferBank)(iPlace))(iTransfer)*W1 +
(*(*fPAItransferBank)(iPlace+1))(iTransfer)*W2) ) break ;
( (*(*fPAItransferTable)(iPlace))(iTransfer)*W1 +
(*(*fPAItransferTable)(iPlace+1))(iTransfer)*W2) ) break ;
}
transfer = GetEnergyTransfer(iPlace,position,iTransfer);
}
}
// G4cout<<"PAImodel PostStepTransfer = "<<transfer/keV<<" keV"<<endl ;
// G4cout<<"PAImodel PostStepTransfer = "<<transfer/keV<<" keV"<<G4endl ;
if(transfer < 0.0 ) transfer = 0.0 ;
return transfer ;
}
@@ -693,19 +724,19 @@ G4PAIModel::GetEnergyTransfer( G4int iPlace, G4double position, G4int iTransfer
if(iTransfer == 0)
{
energyTransfer = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
energyTransfer = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
}
else
{
if ( iTransfer >= G4int((*fPAItransferBank)(iPlace)->GetVectorLength()) )
if ( iTransfer >= G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) )
{
iTransfer = (*fPAItransferBank)(iPlace)->GetVectorLength() - 1 ;
iTransfer = (*fPAItransferTable)(iPlace)->GetVectorLength() - 1 ;
}
y1 = (*(*fPAItransferBank)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAItransferBank)(iPlace))(iTransfer) ;
y1 = (*(*fPAItransferTable)(iPlace))(iTransfer-1) ;
y2 = (*(*fPAItransferTable)(iPlace))(iTransfer) ;
x1 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
x1 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
x2 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
if ( x1 == x2 ) energyTransfer = x2 ;
else
@@ -723,15 +754,16 @@ G4PAIModel::GetEnergyTransfer( G4int iPlace, G4double position, G4int iTransfer
////////////////////////////////////////////////////////////////////////////
std::vector<G4DynamicParticle*>*
G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
vector<G4DynamicParticle*>*
G4PAIModel::SampleSecondaries( const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double,
G4double)
{
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
vector<G4DynamicParticle*>* vdp = 0;
// vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
// G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
// vdp->push_back(delta);
return vdp;
}
@@ -750,18 +782,19 @@ G4double G4PAIModel::SampleFluctuations( const G4Material* material,
}
if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
fPAItransferBank = fPAIxscBank[jMat];
fPAItransferTable = fPAIxscBank[jMat];
fdNdxCutVector = fdNdxCutTable[jMat];
G4int iTkin, iTransfer, iPlace ;
G4long numOfCollisions;
G4long numOfCollisions=0;
// G4cout<<"G4PAIModel::SampleFluctuations"<<G4endl ;
// G4cout<<"in: "<<fMaterialCutsCoupleVector[jMat]->GetMaterial()->GetName()<<G4endl ;
G4double loss = 0.0, charge2 ;
G4double stepSum = 0., stepDelta, lambda, omega;
G4double position, E1, E2, W1, W2, W, dNdxCut1, dNdxCut2, meanNumber;
G4bool numb = true;
G4double Tkin = aParticle->GetKineticEnergy() ;
G4double MassRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass() ;
G4double charge = aParticle->GetDefinition()->GetPDGCharge() ;
@@ -773,55 +806,80 @@ G4double G4PAIModel::SampleFluctuations( const G4Material* material,
if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
}
iPlace = iTkin - 1 ;
// G4cout<<"from search, iPlace = "<<iPlace<<G4endl ;
dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
// G4cout<<"dNdxCut1 = "<<dNdxCut1<<G4endl ;
// G4cout<<"iPlace = "<<iPlace<<endl ;
if(iTkin == fTotBin) // Fermi plato, try from left
{
meanNumber =((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*step*charge2;
meanNumber =((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*step*charge2;
if(meanNumber < 0.) meanNumber = 0. ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = G4Poisson(meanNumber) ;
if( meanNumber > 0.) lambda = step/meanNumber;
else lambda = DBL_MAX;
while(numb)
{
stepDelta = RandExponential::shoot(lambda);
stepSum += stepDelta;
if(stepSum >= step) break;
numOfCollisions++;
}
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
position = dNdxCut1+
((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*G4UniformRand() ;
((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*G4UniformRand() ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace))(iTransfer)) break ;
if(position >= (*(*fPAItransferTable)(iPlace))(iTransfer)) break ;
}
loss += GetEnergyTransfer(iPlace,position,iTransfer);
omega = GetEnergyTransfer(iPlace,position,iTransfer);
// G4cout<<omega/keV<<"\t";
loss += omega;
numOfCollisions-- ;
}
}
else
{
dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
// G4cout<<"dNdxCut2 = "<<dNdxCut2<<G4endl ;
if(iTkin == 0) // Tkin is too small, trying from right only
{
meanNumber =((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*step*charge2;
meanNumber =((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*step*charge2;
if( meanNumber < 0. ) meanNumber = 0. ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = G4Poisson(meanNumber) ;
if( meanNumber > 0.) lambda = step/meanNumber;
else lambda = DBL_MAX;
while(numb)
{
stepDelta = RandExponential::shoot(lambda);
stepSum += stepDelta;
if(stepSum >= step) break;
numOfCollisions++;
}
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
while(numOfCollisions)
{
position = dNdxCut2+
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*G4UniformRand();
((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*G4UniformRand();
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace+1)->GetVectorLength()); iTransfer++ )
iTransfer < G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
{
if(position >= (*(*fPAItransferBank)(iPlace+1))(iTransfer)) break ;
if(position >= (*(*fPAItransferTable)(iPlace+1))(iTransfer)) break ;
}
loss += GetEnergyTransfer(iPlace+1,position,iTransfer);
omega = GetEnergyTransfer(iPlace,position,iTransfer);
// G4cout<<omega/keV<<"\t";
loss += omega;
numOfCollisions-- ;
}
}
@@ -833,45 +891,56 @@ G4double G4PAIModel::SampleFluctuations( const G4Material* material,
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 ;
// G4cout<<"(*(*fPAItransferTable)(iPlace))(0) = "<<
// (*(*fPAItransferTable)(iPlace))(0)<<G4endl ;
// G4cout<<"(*(*fPAItransferTable)(iPlace+1))(0) = "<<
// (*(*fPAItransferTable)(iPlace+1))(0)<<G4endl ;
meanNumber=( ((*(*fPAItransferBank)(iPlace))(0)-dNdxCut1)*W1 +
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2)*W2 )*step*charge2;
meanNumber=( ((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*W1 +
((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*W2 )*step*charge2;
if(meanNumber<0.0) meanNumber = 0.0;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = G4Poisson(meanNumber) ;
if( meanNumber > 0.) lambda = step/meanNumber;
else lambda = DBL_MAX;
while(numb)
{
stepDelta = RandExponential::shoot(lambda);
stepSum += stepDelta;
if(stepSum >= step) break;
numOfCollisions++;
}
// G4cout<<"numOfCollisions = "<<numOfCollisions<<endl ;
while(numOfCollisions)
{
position =( (dNdxCut1+
((*(*fPAItransferBank)(iPlace ))(0)-dNdxCut1))*W1 +
(dNdxCut2+
((*(*fPAItransferBank)(iPlace+1))(0)-dNdxCut2))*W2 )*G4UniformRand();
position = dNdxCut1*W1 + dNdxCut2*W2 +
( ( (*(*fPAItransferTable)(iPlace))(0)-dNdxCut1 )*W1 +
dNdxCut2+
( (*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2 )*W2 )*G4UniformRand();
// G4cout<<position<<"\t" ;
for( iTransfer = 0;
iTransfer < G4int((*fPAItransferBank)(iPlace)->GetVectorLength()); iTransfer++ )
iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
{
if( position >=
( (*(*fPAItransferBank)(iPlace))(iTransfer)*W1 +
(*(*fPAItransferBank)(iPlace+1))(iTransfer)*W2) )
( (*(*fPAItransferTable)(iPlace))(iTransfer)*W1 +
(*(*fPAItransferTable)(iPlace+1))(iTransfer)*W2) )
{
break ;
}
}
// loss += (*fPAItransferBank)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
loss += GetEnergyTransfer(iPlace,position,iTransfer);
omega = GetEnergyTransfer(iPlace,position,iTransfer);
// G4cout<<omega/keV<<"\t";
loss += omega;
numOfCollisions-- ;
}
}
}
// G4cout<<"PAIModel AlongStepLoss = "<<loss/keV<<" keV"<<endl ;
// G4cout<<"PAIModel AlongStepLoss = "<<loss/keV<<" keV"<<G4endl ;
if(loss > Tkin) loss=Tkin;
return loss ;
}
@@ -22,12 +22,15 @@
//
// File name: G4PAIPhotonModel.cc
//
// Author: Vladimir.Grichine@cern.ch on base of Vladimir Ivanchenko code
// Author: Vladimir.Grichine@cern.ch based on G4PAIModel class
//
// Creation date: 05.10.2003
// Creation date: 20.05.2004
//
// Modifications:
//
// 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
//
#include "G4Region.hh"
#include "G4PhysicsLogVector.hh"
@@ -49,9 +52,10 @@
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
////////////////////////////////////////////////////////////////////////
using namespace std;
G4PAIPhotonModel::G4PAIPhotonModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),G4VEmFluctuationModel(nam),
fLowestKineticEnergy(10.0*keV),
@@ -180,7 +184,7 @@ void G4PAIPhotonModel::Initialise(const G4ParticleDefinition* p,
// (*fPAIRegionVector[iRegion])
std::vector<G4Material*>::const_iterator matIter = curReg->GetMaterialIterator();
vector<G4Material*>::const_iterator matIter = curReg->GetMaterialIterator();
size_t jMat;
size_t numOfMat = curReg->GetNumberOfMaterials();
@@ -409,9 +413,9 @@ G4PAIPhotonModel::BuildLambdaVector(const G4MaterialCutsCouple* matCutsCouple)
}
if( jMatCC == numOfCouples && jMatCC > 0 ) jMatCC--;
const std::vector<G4double>* deltaCutInKineticEnergy = theCoupleTable->
const vector<G4double>* deltaCutInKineticEnergy = theCoupleTable->
GetEnergyCutsVector(idxG4ElectronCut);
const std::vector<G4double>* photonCutInKineticEnergy = theCoupleTable->
const vector<G4double>* photonCutInKineticEnergy = theCoupleTable->
GetEnergyCutsVector(idxG4GammaCut);
if (fLambdaVector) delete fLambdaVector;
@@ -494,7 +498,7 @@ G4PAIPhotonModel::GetdNdxCut( G4int iPlace, G4double transferCut)
else
{
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) 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;
@@ -537,7 +541,7 @@ G4PAIPhotonModel::GetdNdxPhotonCut( G4int iPlace, G4double transferCut)
else
{
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) 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<<""<<dNdxPhotonCut<<G4endl;
@@ -581,7 +585,7 @@ G4PAIPhotonModel::GetdNdxPlasmonCut( G4int iPlace, G4double transferCut)
else
{
// if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) 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<<""<<dNdxPlasmonCut<<G4endl;
@@ -624,7 +628,7 @@ G4PAIPhotonModel::GetdEdxCut( G4int iPlace, G4double transferCut)
else
{
// if ( x1 == x2 ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
if ( abs(x1-x2) <= eV ) 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;
@@ -640,9 +644,10 @@ G4double G4PAIPhotonModel::ComputeDEDX(const G4MaterialCutsCouple* matCC,
{
G4int iTkin,iPlace;
size_t jMat;
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, dEdx;
G4double particleMass = p->GetPDGMass();
G4double scaledTkin = kineticEnergy*proton_mass_c2/particleMass;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, dEdx;
for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
{
@@ -674,10 +679,11 @@ G4double G4PAIPhotonModel::CrossSection( const G4MaterialCutsCouple* matCC,
{
G4int iTkin,iPlace;
size_t jMat, jMatCC;
G4double tmax = std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
G4double scaledTkin = kineticEnergy*p->GetPDGMass()/proton_mass_c2;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, cross, cross1, cross2;
G4double tmax = min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
G4double particleMass = p->GetPDGMass();
G4double scaledTkin = kineticEnergy*proton_mass_c2/particleMass;
G4double charge = p->GetPDGCharge();
G4double charge2 = charge*charge, cross, cross1, cross2;
G4double photon1, photon2, plasmon1, plasmon2;
const G4ProductionCutsTable* theCoupleTable=
@@ -691,7 +697,7 @@ G4double G4PAIPhotonModel::CrossSection( const G4MaterialCutsCouple* matCC,
}
if( jMatCC == numOfCouples && jMatCC > 0 ) jMatCC--;
const std::vector<G4double>* photonCutInKineticEnergy = theCoupleTable->
const vector<G4double>* photonCutInKineticEnergy = theCoupleTable->
GetEnergyCutsVector(idxG4GammaCut);
G4double photonCut = (*photonCutInKineticEnergy)[jMatCC] ;
@@ -713,6 +719,8 @@ G4double G4PAIPhotonModel::CrossSection( const G4MaterialCutsCouple* matCC,
iPlace = iTkin - 1;
if(iPlace < 0) iPlace = 0;
// G4cout<<"iPlace = "<<iPlace<<"; tmax = "
// <<tmax<<"; cutEnergy = "<<cutEnergy<<G4endl;
photon1 = GetdNdxPhotonCut(iPlace,tmax);
photon2 = GetdNdxPhotonCut(iPlace,photonCut);
@@ -720,8 +728,11 @@ G4double G4PAIPhotonModel::CrossSection( const G4MaterialCutsCouple* matCC,
plasmon2 = GetdNdxPlasmonCut(iPlace,cutEnergy);
cross1 = photon1 + plasmon1;
// G4cout<<"cross1 = "<<cross1<<G4endl;
cross2 = photon2 + plasmon2;
// G4cout<<"cross2 = "<<cross2<<G4endl;
cross = (cross2 - cross1)*charge2;
// G4cout<<"cross = "<<cross<<G4endl;
if( cross < 0. ) cross = 0.;
return cross;
@@ -754,13 +765,16 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
fdNdxCutPhotonVector = fdNdxCutPhotonTable[jMat];
fdNdxCutPlasmonVector = fdNdxCutPlasmonTable[jMat];
G4double tmax = std::min(MaxSecondaryEnergy(dp), maxEnergy);
if( tmin >= tmax ) return 0;
G4double tmax = min(MaxSecondaryEnergy(dp), maxEnergy);
if( tmin >= tmax )
{
G4cout<<"G4PAIPhotonModel::SampleSecondary: tmin >= tmax "<<G4endl;
}
G4ThreeVector momentum = dp->GetMomentumDirection();
G4double particleMass = dp->GetMass();
G4double kineticEnergy = dp->GetKineticEnergy();
G4double scaledTkin = kineticEnergy*particleMass/proton_mass_c2;
G4double scaledTkin = kineticEnergy*proton_mass_c2/particleMass;
G4double totalEnergy = kineticEnergy + particleMass;
G4double pSquare = kineticEnergy*(totalEnergy+particleMass);
@@ -785,9 +799,15 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
G4double deltaTkin = GetPostStepTransfer(fPAIplasmonTable, fdNdxCutPlasmonVector,
iPlace, scaledTkin);
//G4cout<<"PAIPhotonModel PlasmonPostStepTransfer = "<<deltaTkin/keV<<" keV"<<G4endl ;
if( deltaTkin <= 0. ) return 0;
// G4cout<<"PAIPhotonModel PlasmonPostStepTransfer = "<<deltaTkin/keV<<" keV"<<G4endl ;
if( deltaTkin <= 0. )
{
G4cout<<"Tkin of secondary e- <= 0."<<G4endl;
G4cout<<"G4PAIPhotonModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
deltaTkin = 10*eV;
G4cout<<"Set G4PAIPhotonModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
}
G4double deltaTotalMomentum = sqrt(deltaTkin*(deltaTkin + 2. * electron_mass_c2 ));
G4double totalMomentum = sqrt(pSquare);
@@ -819,17 +839,24 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
G4double deltaTkin = GetPostStepTransfer(fPAIphotonTable, fdNdxCutPhotonVector,
iPlace,scaledTkin);
//G4cout<<"PAIPhotonModel PhotonPostStepTransfer = "<<deltaTkin/keV<<" keV"<<G4endl ;
// G4cout<<"PAIPhotonModel PhotonPostStepTransfer = "<<deltaTkin/keV<<" keV"<<G4endl ;
if( deltaTkin <= 0. ) return 0;
if( deltaTkin <= 0. )
{
G4cout<<"Tkin of secondary photon <= 0."<<G4endl;
G4cout<<"G4PAIPhotonModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
deltaTkin = 10*eV;
G4cout<<"Set G4PAIPhotonModel::SampleSecondary::deltaTkin = "<<deltaTkin<<G4endl;
}
// G4double deltaTotalMomentum = sqrt(deltaTkin*(deltaTkin + 2. * electron_mass_c2 ));
// G4double totalMomentum = sqrt(pSquare);
// deltaTkin*(totalEnergy + electron_mass_c2)
// /(deltaTotalMomentum * totalMomentum);
G4double costheta = G4UniformRand();
if (costheta < 0.) costheta = 0.;
G4double costheta = 0.; // G4UniformRand(); // VG: ??? for start only
if (costheta < 0.) costheta = 0.;
if (costheta > 1.) costheta = 1.;
// direction of the 'Cherenkov' photon
@@ -844,7 +871,7 @@ G4PAIPhotonModel::SampleSecondary( const G4MaterialCutsCouple* matCC,
// create G4DynamicParticle object for photon ray
G4DynamicParticle* photonRay = new G4DynamicParticle;
photonRay->SetDefinition(G4Gamma::Gamma());
photonRay->SetDefinition( G4Gamma::Gamma() );
photonRay->SetKineticEnergy( deltaTkin );
photonRay->SetMomentumDirection(deltaDirection);
@@ -967,13 +994,13 @@ G4PAIPhotonModel::GetEnergyTransfer( G4PhysicsTable* pTable, G4int iPlace,
////////////////////////////////////////////////////////////////////////////
std::vector<G4DynamicParticle*>*
vector<G4DynamicParticle*>*
G4PAIPhotonModel::SampleSecondaries( const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
std::vector<G4DynamicParticle*>* vdp = new std::vector<G4DynamicParticle*>;
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
return vdp;
@@ -1028,11 +1055,13 @@ G4double G4PAIPhotonModel::SampleFluctuations( const G4Material* material,
iPlace = iTkin - 1 ;
if( iPlace < 0 ) iPlace = 0;
photonLoss = GetAlongStepTransfer(fPAIphotonTable,fdNdxCutPhotonVector,iPlace,scaledTkin,cof);
photonLoss = GetAlongStepTransfer(fPAIphotonTable,fdNdxCutPhotonVector,
iPlace,scaledTkin,step,cof);
// G4cout<<"PAIPhotonModel AlongStepPhotonLoss = "<<photonLoss/keV<<" keV"<<G4endl ;
plasmonLoss = GetAlongStepTransfer(fPAIplasmonTable,fdNdxCutPlasmonVector,iPlace,scaledTkin,cof);
plasmonLoss = GetAlongStepTransfer(fPAIplasmonTable,fdNdxCutPlasmonVector,
iPlace,scaledTkin,step,cof);
// G4cout<<"PAIPhotonModel AlongStepPlasmonLoss = "<<plasmonLoss/keV<<" keV"<<G4endl ;
@@ -1051,12 +1080,14 @@ G4double G4PAIPhotonModel::SampleFluctuations( const G4Material* material,
G4double
G4PAIPhotonModel::GetAlongStepTransfer( G4PhysicsTable* pTable,
G4PhysicsLogVector* pVector,
G4int iPlace, G4double scaledTkin,
G4int iPlace, G4double scaledTkin,G4double step,
G4double cof )
{
G4int iTkin = iPlace + 1, iTransfer;
G4double loss = 0., position, E1, E2, W1, W2, W, dNdxCut1, dNdxCut2, meanNumber;
G4long numOfCollisions;
G4double lambda, stepDelta, stepSum=0. ;
G4long numOfCollisions=0;
G4bool numb = true;
dNdxCut1 = (*pVector)(iPlace) ;
@@ -1066,7 +1097,16 @@ G4PAIPhotonModel::GetAlongStepTransfer( G4PhysicsTable* pTable,
{
meanNumber = ((*(*pTable)(iPlace))(0) - dNdxCut1)*cof;
if(meanNumber < 0.) meanNumber = 0. ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = RandPoisson::shoot(meanNumber) ;
if( meanNumber > 0.) lambda = step/meanNumber;
else lambda = DBL_MAX;
while(numb)
{
stepDelta = RandExponential::shoot(lambda);
stepSum += stepDelta;
if(stepSum >= step) break;
numOfCollisions++;
}
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
@@ -1092,7 +1132,16 @@ G4PAIPhotonModel::GetAlongStepTransfer( G4PhysicsTable* pTable,
{
meanNumber = ((*(*pTable)(iPlace+1))(0) - dNdxCut2)*cof;
if( meanNumber < 0. ) meanNumber = 0. ;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = RandPoisson::shoot(meanNumber) ;
if( meanNumber > 0.) lambda = step/meanNumber;
else lambda = DBL_MAX;
while(numb)
{
stepDelta = RandExponential::shoot(lambda);
stepSum += stepDelta;
if(stepSum >= step) break;
numOfCollisions++;
}
// G4cout<<"numOfCollisions = "<<numOfCollisions<<G4endl ;
@@ -1126,16 +1175,25 @@ G4PAIPhotonModel::GetAlongStepTransfer( G4PhysicsTable* pTable,
meanNumber=( ((*(*pTable)(iPlace))(0)-dNdxCut1)*W1 +
((*(*pTable)(iPlace+1))(0)-dNdxCut2)*W2 )*cof;
if(meanNumber<0.0) meanNumber = 0.0;
numOfCollisions = RandPoisson::shoot(meanNumber) ;
// numOfCollisions = RandPoisson::shoot(meanNumber) ;
if( meanNumber > 0.) lambda = step/meanNumber;
else lambda = DBL_MAX;
while(numb)
{
stepDelta = RandExponential::shoot(lambda);
stepSum += stepDelta;
if(stepSum >= step) break;
numOfCollisions++;
}
// G4cout<<"numOfCollisions = "<<numOfCollisions<<endl ;
while(numOfCollisions)
{
position =( (dNdxCut1+
((*(*pTable)(iPlace ))(0)-dNdxCut1))*W1 +
(dNdxCut2+
((*(*pTable)(iPlace+1))(0)-dNdxCut2))*W2 )*G4UniformRand();
position = dNdxCut1*W1 + dNdxCut2*W2 +
( ( (*(*pTable)(iPlace ))(0) - dNdxCut1)*W1 +
( (*(*pTable)(iPlace+1))(0) - dNdxCut2)*W2 )*G4UniformRand();
// G4cout<<position<<"\t" ;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,848 @@
//
// ********************************************************************
// * 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;
}
//
//
/////////////////////////////////////////////////
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PAIxSection.cc,v 1.19 2004/06/07 07:33:21 gcosmo Exp $
// GEANT4 tag $Name: geant4-06-02 $
// $Id: G4PAIxSection.cc,v 1.20 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
//
// G4PAIxSection.cc -- class implementation file
@@ -54,6 +54,7 @@
#include "G4MaterialCutsCouple.hh"
#include "G4SandiaTable.hh"
using namespace std;
/* ******************************************************************
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PhotoElectricEffect.cc,v 1.30 2004/03/10 16:48:46 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-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......
@@ -66,7 +66,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// constructor
using namespace std;
G4PhotoElectricEffect::G4PhotoElectricEffect(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
@@ -83,6 +83,14 @@ G4PhotoElectricEffect::~G4PhotoElectricEffect()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4bool G4PhotoElectricEffect::IsApplicable(const G4ParticleDefinition&
particle)
{
return ( &particle == G4Gamma::Gamma() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4PhotoElectricEffect::ComputeCrossSectionPerAtom(G4double GammaEnergy,
G4double AtomicNumber)
@@ -119,6 +127,29 @@ G4double G4PhotoElectricEffect::ComputeMeanFreePath(G4double GammaEnergy,
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,
@@ -177,9 +208,9 @@ G4VParticleChange* G4PhotoElectricEffect::PostStepDoIt(const G4Track& aTrack,
//
// Kill the incident photon
//
aParticleChange.SetLocalEnergyDeposit(PhotonEnergy-ElecKineEnergy);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.ProposeLocalEnergyDeposit(PhotonEnergy-ElecKineEnergy);
aParticleChange.ProposeEnergy(0.);
aParticleChange.ProposeTrackStatus(fStopAndKill);
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4PolarizedComptonScattering.cc,v 1.10 2003/05/26 16:13:14 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-02-patch-01 $
// $Id: G4PolarizedComptonScattering.cc,v 1.12 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
//
//---------- G4PolarizedComptonScattering physics process ----------------------
@@ -42,7 +42,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// constructor
using namespace std;
G4PolarizedComptonScattering::G4PolarizedComptonScattering(
const G4String& processName)
@@ -69,7 +69,7 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(
G4ThreeVector GammaPolarization0 = aDynamicGamma->GetPolarization();
if (abs(GammaPolarization0.mag() - 1.e0) > 1.e-14)
if (fabs(GammaPolarization0.mag() - 1.e0) > 1.e-14)
G4ComptonScattering::PostStepDoIt(aTrack,aStep);
G4double GammaEnergy0 = aDynamicGamma->GetKineticEnergy();
@@ -106,7 +106,7 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(
G4double Rand = G4UniformRand();
int j = 0;
while ((j < 100) && (abs(SetPhi(epsilon,sint2,middle,Rand)) > resolution))
while ((j < 100) && (fabs(SetPhi(epsilon,sint2,middle,Rand)) > resolution))
{
middle = (maximum + minimum)/2;
if (SetPhi(epsilon,sint2,middle,Rand)*
@@ -143,13 +143,13 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(
if (GammaEnergy1 > fminimalEnergy)
{
aParticleChange.SetEnergyChange(GammaEnergy1);
aParticleChange.ProposeEnergy(GammaEnergy1);
}
else
{
localEnergyDeposit += GammaEnergy1;
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.ProposeEnergy(0.) ;
aParticleChange.ProposeTrackStatus(fStopAndKill);
}
//
@@ -177,7 +177,7 @@ G4VParticleChange* G4PolarizedComptonScattering::PostStepDoIt(
localEnergyDeposit += ElecKineEnergy;
}
aParticleChange.SetLocalEnergyDeposit (localEnergyDeposit);
aParticleChange.ProposeLocalEnergyDeposit(localEnergyDeposit);
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
@@ -271,12 +271,12 @@ void G4PolarizedComptonScattering::SystemOfRefChange(G4ThreeVector& Direction0,
Direction1.rotateZ(Psi);
//
Direction1.rotateUz(Direction0);
aParticleChange.SetMomentumChange(Direction1);
aParticleChange.ProposeMomentumDirection(Direction1);
// 3 Euler angles rotation for scattered photon polarization
Polarization1.rotateZ(Psi);
Polarization1.rotateUz(Direction0);
aParticleChange.SetPolarizationChange(Polarization1);
aParticleChange.ProposePolarization(Polarization1);
}
@@ -0,0 +1,189 @@
//
// ********************************************************************
// * 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: G4SCProcessorStand.cc,v 1.2 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4SCProcessorStand
//
// Author: Vladimir Ivanchenko
//
// Creation date: 10.05.2002
//
// Modifications:
//
// 09-12-02 remove warning (V.Ivanchenko)
// 23-12-02 change interface in order to move to cut per region (V.Ivanchenko)
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4SCProcessorStand.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4EmModelManager.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4VEmModel.hh"
#include "Randomize.hh"
#include "G4Step.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4SCProcessorStand::G4SCProcessorStand(const G4String& nam)
: G4VSubCutoffProcessor(nam),
theLambdaSubTable(0),
thePositron(G4Positron::Positron())
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4SCProcessorStand::~G4SCProcessorStand()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4SCProcessorStand::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
const G4DataVector* vCuts,
const G4DataVector* vSubCuts)
{
particle = p;
secondaryParticle = sp;
navigator = (G4TransportationManager::GetTransportationManager())
->GetNavigatorForTracking();
theCuts = vCuts;
theSubCuts = vSubCuts;
initialMass= particle->GetPDGMass();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
const G4Step& step,
G4double& tmax,
G4double& meanLoss,
G4VEmModel* currentModel)
{
G4bool b;
const G4Track* track = step.GetTrack();
const G4MaterialCutsCouple* couple = track->GetMaterialCutsCouple();
size_t index = couple->GetIndex();
G4double subcut = (*theSubCuts)[index];
if(subcut >= tmax) return 0;
G4double cut = (*theCuts)[index];
G4double rcut = couple->GetProductionCuts()->GetProductionCut(1);
const G4DynamicParticle* dp = track->GetDynamicParticle();
G4double ekin = dp->GetKineticEnergy();
G4double effChargeFactor = 1.0;
G4double massRatio = 1.0;
G4double mass = initialMass;
if(dp->GetDefinition() != particle) {
mass = dp->GetMass();
massRatio = initialMass/mass;
G4double q = particle->GetPDGCharge()/dp->GetCharge();
effChargeFactor = q*q;
}
G4double cross = (*theLambdaSubTable)[index]->GetValue(ekin*massRatio, b);
if(0.0 >= cross) return 0;
G4StepPoint* pre = step.GetPreStepPoint();
G4double presafety = pre->GetSafety();
G4ThreeVector postpoint = step.GetPostStepPoint()->GetPosition();
G4double postsafety = navigator->ComputeSafety(postpoint);
G4double safety = min(presafety,postsafety);
if(safety >= rcut) return 0;
G4ThreeVector prepoint = pre->GetPosition();
G4ThreeVector dr = postpoint - prepoint;
G4double pretime = step.GetPreStepPoint()->GetGlobalTime();
G4double fragment = 0.0;
G4double dt = 0.0;
G4double length = step.GetStepLength();
G4double inv_v = (ekin + mass)/(c_light*dp->GetTotalMomentum());
vector<G4Track*>* vtr = new vector<G4Track*>;
do {
G4double del = G4UniformRand()*effChargeFactor / cross;
fragment += del/length;
if (fragment > 1.0) break;
dt += del * inv_v;
vector<G4DynamicParticle*>* newp =
currentModel->SampleSecondaries(couple, dp, subcut, cut);
if (newp) {
G4DynamicParticle* p;
G4int nNew = newp->size();
for (G4int i=0; i<nNew; i++) {
p = (*newp)[i];
G4double e = p->GetKineticEnergy();
if (p->GetDefinition() == thePositron) e += electron_mass_c2;
if (e <= meanLoss) {
meanLoss -= e;
G4Track* t = new G4Track(p, pretime + dt, prepoint + fragment*dr);
vtr->push_back(t);
} else {
delete p;
}
}
}
} while (fragment < 1.0);
return vtr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4SynchrotronRadiation.cc,v 1.10 2004/06/07 13:49:52 gcosmo Exp $
// GEANT4 tag $Name: geant4-06-02 $
// $Id: G4SynchrotronRadiation.cc,v 1.12 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
@@ -44,6 +44,8 @@
//
// Constructor
//
using namespace std;
G4SynchrotronRadiation::G4SynchrotronRadiation(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
@@ -256,22 +258,22 @@ G4SynchrotronRadiation::PostStepDoIt(const G4Track& trackData,
if (newKinEnergy > 0.)
{
aParticleChange.SetMomentumChange( particleDirection );
aParticleChange.SetEnergyChange( newKinEnergy );
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.ProposeMomentumDirection( particleDirection );
aParticleChange.ProposeEnergy( newKinEnergy );
aParticleChange.ProposeLocalEnergyDeposit (0.);
}
else
{
aParticleChange.SetEnergyChange( 0. );
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.ProposeEnergy( 0. );
aParticleChange.ProposeLocalEnergyDeposit (0.);
G4double charge = aDynamicParticle->GetDefinition()->GetPDGCharge();
if (charge<0.)
{
aParticleChange.SetStatusChange(fStopAndKill) ;
aParticleChange.ProposeTrackStatus(fStopAndKill) ;
}
else
{
aParticleChange.SetStatusChange(fStopButAlive) ;
aParticleChange.ProposeTrackStatus(fStopButAlive) ;
}
}
}
@@ -0,0 +1,310 @@
//
// ********************************************************************
// * 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: G4UniversalFluctuation.cc,v 1.2 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4UniversalFluctuation
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
// 16-10-03 Changed interface to Initialisation (V.Ivanchenko)
// 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)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4UniversalFluctuation.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4Step.hh"
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4UniversalFluctuation::G4UniversalFluctuation(const G4String& nam)
:G4VEmFluctuationModel(nam),
particle(0),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minLoss(0.001*eV),
sumalim(0.01),
alim(10.),
nmaxCont1(4.),
nmaxCont2(16.)
{
lastMaterial = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4UniversalFluctuation::~G4UniversalFluctuation()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4UniversalFluctuation::InitialiseMe(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
// calculate actual loss from the mean loss
// The model used to get the fluctuation is essentially the same
// as in Glandz in Geant3.
// G4cout << "### Mean loss= " << meanLoss << G4endl;
// shortcut for very very small loss
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)
{
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);
}
//G4cout << "### meanLoss= " << meanLoss << " fluc= " << loss-meanLoss << " sig= " << siga << G4endl;
return loss;
}
// Non Gaussian fluctuation
if(material != lastMaterial) {
f1Fluct = material->GetIonisation()->GetF1fluct();
f2Fluct = material->GetIonisation()->GetF2fluct();
e1Fluct = material->GetIonisation()->GetEnergy1fluct();
e2Fluct = material->GetIonisation()->GetEnergy2fluct();
e1LogFluct = material->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = material->GetIonisation()->GetLogEnergy2fluct();
rateFluct = material->GetIonisation()->GetRateionexcfluct();
ipotLogFluct = material->GetIonisation()->GetLogMeanExcEnergy();
lastMaterial = material;
}
G4double p1,p2,p3;
G4double w1 = tmax/ipotFluct;
G4double w2 = log(2.*electron_mass_c2*beta2*gam2);
G4double C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
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.;
G4double suma = a1+a2+a3;
loss = 0. ;
if(suma < sumalim) // very small Step
{
//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) {
siga=sqrt(a1) ;
p1 = max(0.,G4RandGauss::shoot(a1,siga)+0.5);
} else {
p1 = G4double(G4Poisson(a1));
}
// excitation type 2
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.)
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;
}
}
//G4cout << "### Final loss= " << loss << G4endl;
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4UniversalFluctuation::Dispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length)
{
if(!particle) InitialiseMe(dp->GetDefinition());
electronDensity = material->GetElectronDensity();
G4double gam = (dp->GetKineticEnergy())/particleMass + 1.0;
G4double beta2 = 1.0 - 1.0/(gam*gam);
G4double siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare;
return siga;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1,391 +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: G4VPAIenergyLoss.cc,v 1.7 2003/03/10 12:22:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-02-patch-01 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
//
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4VPAIenergyLoss physics process -----------
// by V. Grichine, 30 Nov 1997
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of charged hadrons.
// **************************************************************
//
// corrected by V. Grichine on 24/11/97
// corrected by L. Urban on 27/05/98 ( other corrections come soon!)
// 10/02/00 modifications , new e.m. structure, L.Urban
// 02/03/00 initialisation of theDEDXTable
// 17-09-01, migration of Materials to pure STL (mma)
// 10-03-03 remove tails of old cuts (V.Ivanchenko)
//
#include "G4VPAIenergyLoss.hh"
#include "G4PAIonisation.hh"
#include "G4EnergyLossTables.hh"
////////////////////////////////////////////////////////////////////////////
//
// Initialisation of static members
G4int G4VPAIenergyLoss::NbOfProcesses = 1 ;
G4PhysicsTable** G4VPAIenergyLoss::RecorderOfpProcess =
new G4PhysicsTable*[10] ;
G4int G4VPAIenergyLoss::CounterOfpProcess = 0 ;
G4PhysicsTable* G4VPAIenergyLoss::theDEDXpTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theRangepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theInverseRangepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theLabTimepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theProperTimepTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepRangeCoeffATable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepRangeCoeffCTable = NULL ;
G4PhysicsTable** G4VPAIenergyLoss::RecorderOfpbarProcess =
new G4PhysicsTable*[10] ;
G4int G4VPAIenergyLoss::CounterOfpbarProcess = 0 ;
G4PhysicsTable* G4VPAIenergyLoss::theDEDXpbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theRangepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theInverseRangepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theLabTimepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theProperTimepbarTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepbarRangeCoeffATable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepbarRangeCoeffBTable = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::thepbarRangeCoeffCTable = NULL ;
// G4PhysicsTable* G4VPAIenergyLoss::fPAItransferBank = NULL ;
G4PhysicsTable* G4VPAIenergyLoss::theDEDXTable = NULL ;
G4double G4VPAIenergyLoss::LowerBoundEloss= 1.00*keV ;
G4double G4VPAIenergyLoss::UpperBoundEloss= 100.*TeV ;
G4int G4VPAIenergyLoss::NbinEloss =100 ;
G4double G4VPAIenergyLoss::RTable,G4VPAIenergyLoss::LOGRTable;
// constructor and destructor
G4VPAIenergyLoss::G4VPAIenergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
dToverTini(0.20), // max.relative range loss in one Step = 20%
theElectron ( G4Electron::Electron() ),
theProton ( G4Proton::Proton() ),
theAntiProton ( G4AntiProton::AntiProton() )
{
theLossTable = NULL ;
// calculate data members LOGRTable,RTable first
G4double lrate ;
lrate = log(UpperBoundEloss/LowerBoundEloss) ;
LOGRTable=lrate/NbinEloss;
RTable =exp(LOGRTable);
}
G4VPAIenergyLoss::~G4VPAIenergyLoss()
{
if(theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
}
/////////////////////////////////////////////////////////////////////////
//
G4double G4VPAIenergyLoss::GetMaxKineticEnergy() {return UpperBoundEloss;}
G4double G4VPAIenergyLoss::GetMinKineticEnergy() {return LowerBoundEloss;}
G4int G4VPAIenergyLoss::GetBinNumber() {return NbinEloss;}
void G4VPAIenergyLoss::SetNbOfProcesses(G4int nb) {NbOfProcesses=nb;}
void G4VPAIenergyLoss::PlusNbOfProcesses() {NbOfProcesses++ ;}
void G4VPAIenergyLoss::MinusNbOfProcesses() {NbOfProcesses-- ;}
G4int G4VPAIenergyLoss::GetNbOfProcesses() {return NbOfProcesses;}
void G4VPAIenergyLoss::SetLowerBoundEloss(G4double val) {LowerBoundEloss=val;}
void G4VPAIenergyLoss::SetUpperBoundEloss(G4double val) {UpperBoundEloss=val;}
void G4VPAIenergyLoss::SetNbinEloss(G4int nb) {NbinEloss=nb;}
G4double G4VPAIenergyLoss::GetLowerBoundEloss() {return LowerBoundEloss;}
G4double G4VPAIenergyLoss::GetUpperBoundEloss() {return UpperBoundEloss;}
G4int G4VPAIenergyLoss::GetNbinEloss() {return NbinEloss;}
/////////////////////////////////////////////////////////////////////////
//
//
void G4VPAIenergyLoss::BuildDEDXTable(const G4ParticleDefinition& aParticleType)
{
G4bool MakeTable = false ;
// Create tables only if there is a new cut value !
// create/fill proton or antiproton tables depending on the charge of the particle
G4double Charge = aParticleType.GetPDGCharge();
if (Charge>0.)
{
theDEDXTable= theDEDXpTable;
}
else
{
theDEDXTable= theDEDXpbarTable;
}
if ( CutsWhereModified() || (theDEDXTable==NULL))
{
MakeTable = true ;
}
if( MakeTable )
{
// Build energy loss table as a sum of the energy loss due to the
// different processes.
//
// different processes.
// create table for the total energy loss
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4PhysicsTable** RecorderOfProcess;
int CounterOfProcess;
if( Charge >0.)
{
RecorderOfProcess=RecorderOfpProcess;
CounterOfProcess=CounterOfpProcess;
if(CounterOfProcess == NbOfProcesses)
{
// create tables
if(theDEDXpTable)
{ theDEDXpTable->clearAndDestroy();
delete theDEDXpTable; }
theDEDXpTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpTable;
}
}
else
{
RecorderOfProcess=RecorderOfpbarProcess;
CounterOfProcess=CounterOfpbarProcess;
if(CounterOfProcess == NbOfProcesses)
{
// create tables
if(theDEDXpbarTable)
{ theDEDXpbarTable->clearAndDestroy();
delete theDEDXpbarTable; }
theDEDXpbarTable = new G4PhysicsTable(numOfMaterials);
theDEDXTable = theDEDXpbarTable;
}
}
if(CounterOfProcess == NbOfProcesses)
{
// fill the tables
// loop for materials
G4double LowEdgeEnergy , Value ;
G4bool isOutRange ;
G4PhysicsTable* pointer ;
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundEloss, UpperBoundEloss, NbinEloss);
// loop for the kinetic energy
for (G4int i=0; i<NbinEloss; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
// here comes the sum of the different tables created by the
// processes (ionisation,etc...)
Value = 0. ;
for (G4int process=0; process < NbOfProcesses; process++)
{
pointer= RecorderOfProcess[process];
Value += (*pointer)[J]->
GetValue(LowEdgeEnergy,isOutRange) ;
}
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
// reset counter to zero
if( Charge >0.) CounterOfpProcess=0 ;
else CounterOfpbarProcess=0 ;
ParticleMass = aParticleType.GetPDGMass() ;
if(Charge > 0.)
{
// Build range table
theRangepTable = BuildRangeTable(theDEDXpTable,
theRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimepTable = BuildLabTimeTable(theDEDXpTable,
theLabTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepTable = BuildProperTimeTable(theDEDXpTable,
theProperTimepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepRangeCoeffATable = BuildRangeCoeffATable(theRangepTable,
thepRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffBTable = BuildRangeCoeffBTable(theRangepTable,
thepRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepRangeCoeffCTable = BuildRangeCoeffCTable(theRangepTable,
thepRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangepTable = BuildInverseRangeTable(theRangepTable,
thepRangeCoeffATable,
thepRangeCoeffBTable,
thepRangeCoeffCTable,
theInverseRangepTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
else
{
// Build range table
theRangepbarTable = BuildRangeTable(theDEDXpbarTable,
theRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build lab/proper time tables
theLabTimepbarTable = BuildLabTimeTable(theDEDXpbarTable,
theLabTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
theProperTimepbarTable = BuildProperTimeTable(theDEDXpbarTable,
theProperTimepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// Build coeff tables for the energy loss calculation
thepbarRangeCoeffATable = BuildRangeCoeffATable(theRangepbarTable,
thepbarRangeCoeffATable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffBTable = BuildRangeCoeffBTable(theRangepbarTable,
thepbarRangeCoeffBTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
thepbarRangeCoeffCTable = BuildRangeCoeffCTable(theRangepbarTable,
thepbarRangeCoeffCTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
// invert the range table
theInverseRangepbarTable = BuildInverseRangeTable(theRangepbarTable,
thepbarRangeCoeffATable,
thepbarRangeCoeffBTable,
thepbarRangeCoeffCTable,
theInverseRangepbarTable,
LowerBoundEloss,UpperBoundEloss,NbinEloss);
}
}
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
(Charge>0)?
theDEDXpTable: theDEDXpbarTable,
(Charge>0)?
theRangepTable: theRangepbarTable,
(Charge>0)?
theInverseRangepTable: theInverseRangepbarTable,
(Charge>0)?
theLabTimepTable: theLabTimepbarTable,
(Charge>0)?
theProperTimepTable: theProperTimepbarTable,
LowerBoundEloss, UpperBoundEloss,
proton_mass_c2/aParticleType.GetPDGMass(),NbinEloss);
}
//////////////////////////////////////////////////////////////////////
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VeEnergyLoss.cc,v 1.32 2003/06/16 17:02:12 gunter Exp $
// GEANT4 tag $Name: geant4-05-02-patch-01 $
// $Id: G4VeEnergyLoss.cc,v 1.34 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -----------------------------------------------------------------------------
@@ -95,7 +95,7 @@ G4double G4VeEnergyLoss::RTable,G4VeEnergyLoss::LOGRTable;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// constructor and destructor
using namespace std;
G4VeEnergyLoss::G4VeEnergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
@@ -520,7 +520,7 @@ G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
postsafety =
navigator->ComputeSafety(stepData.GetPostStepPoint()->GetPosition());
safety=std::min(presafety,postsafety);
safety=min(presafety,postsafety);
if(safety<rcut)
{
@@ -676,7 +676,7 @@ G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
// update the particle direction and kinetic energy
if(subdelta > 0)
aParticleChange.SetMomentumChange(Px,Py,Pz) ;
aParticleChange.ProposeMomentumDirection(Px,Py,Pz) ;
E = Tkin ;
}
@@ -704,12 +704,12 @@ G4VParticleChange* G4VeEnergyLoss::AlongStepDoIt( const G4Track& trackData,
if (finalT <= 0. )
{
finalT = 0.;
if (Charge < 0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
if (Charge < 0.) aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.SetEnergyChange(finalT);
aParticleChange.SetLocalEnergyDeposit(E-finalT);
aParticleChange.ProposeEnergy(finalT);
aParticleChange.ProposeLocalEnergyDeposit(E-finalT);
return &aParticleChange;
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VhEnergyLoss.cc,v 1.46 2003/06/16 17:02:13 gunter Exp $
// GEANT4 tag $Name: geant4-05-02-patch-01 $
// $Id: G4VhEnergyLoss.cc,v 1.48 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -----------------------------------------------------------------------------
@@ -115,6 +115,8 @@ G4int G4VhEnergyLoss::Ndeltamax = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4VhEnergyLoss::G4VhEnergyLoss(const G4String& processName)
: G4VEnergyLoss (processName),
theLossTable (NULL),
@@ -411,7 +413,7 @@ G4double G4VhEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
// compute the (random) Step limit
//
G4double r = std::min(finalRange, couple->GetProductionCuts()
G4double r = min(finalRange, couple->GetProductionCuts()
->GetProductionCut(idxG4ElectronCut));
G4double StepLimit;
if (fRangeNow > r)
@@ -526,7 +528,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
->GetNavigatorForTracking();
G4double postsafety =
navigator->ComputeSafety(stepData.GetPostStepPoint()->GetPosition());
G4double safety = std::min(presafety,postsafety);
G4double safety = min(presafety,postsafety);
if (safety < rcut)
{
@@ -565,7 +567,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
{
G4double T0=G4EnergyLossTables::GetPreciseEnergyFromRange(
G4Electron::Electron(),
std::min(presafety,postsafety),
min(presafety,postsafety),
couple);
// absolute lower limit for T0
if((T0<MinDeltaEnergyNow)||(LowerLimitForced[index]))
@@ -667,7 +669,7 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
} while (subdelta<N);
// update the particle direction and kinetic energy
if(subdelta > 0) aParticleChange.SetMomentumChange(Px,Py,Pz);
if(subdelta > 0) aParticleChange.ProposeMomentumDirection(Px,Py,Pz);
E = Tkin;
}
}
@@ -693,12 +695,12 @@ G4VParticleChange* G4VhEnergyLoss::AlongStepDoIt(
{
finalT = 0.;
if(!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.SetEnergyChange(finalT);
aParticleChange.SetLocalEnergyDeposit(E-finalT);
aParticleChange.ProposeEnergy(finalT);
aParticleChange.ProposeLocalEnergyDeposit(E-finalT);
return &aParticleChange;
}
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4eBremsstrahlung.cc,v 1.37 2003/11/12 16:23:42 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00-patch-01 $
// $Id: G4eBremsstrahlung.cc,v 1.40 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
@@ -60,6 +60,8 @@
// 23-05-03 Define default integral + BohrFluctuations (V.Ivanchenko)
// 08-08-03 STD substitute standard (V.Ivanchenko)
// 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)
//
// -------------------------------------------------------------------
//
@@ -77,10 +79,18 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4eBremsstrahlung::G4eBremsstrahlung(const G4String& name)
: G4VEnergyLossProcess(name)
using namespace std;
G4eBremsstrahlung::G4eBremsstrahlung(const G4String& name, G4double thresh):
G4VEnergyLossProcess(name),
gammaThreshold(thresh),
isInitialised(false)
{
InitialiseProcess();
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -90,27 +100,27 @@ G4eBremsstrahlung::~G4eBremsstrahlung()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::InitialiseProcess()
void G4eBremsstrahlung::InitialiseEnergyLossProcess(const G4ParticleDefinition*,
const G4ParticleDefinition*)
{
SetSecondaryParticle(G4Gamma::Gamma());
if(!isInitialised) {
isInitialised = true;
SetSecondaryParticle(G4Gamma::Gamma());
SetIonisation(false);
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
//G4VEmFluctuationModel* fm = 0;
G4VEmFluctuationModel* fm = new G4UniversalFluctuation();
//G4VEmFluctuationModel* fm = 0;
G4VEmFluctuationModel* fm = new G4UniversalFluctuation();
G4VEmModel* em = new G4eBremsstrahlungModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em, fm);
G4VEmModel* em = new G4eBremsstrahlungModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em, fm);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eBremsstrahlung::PrintInfoDefinition()
void G4eBremsstrahlung::PrintInfoDefinition()
{
G4VEnergyLossProcess::PrintInfoDefinition();
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eBremsstrahlung52.cc,v 1.1 2003/08/08 11:30:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00-patch-01 $
// $Id: G4eBremsstrahlung52.cc,v 1.4 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
//
// ------------ G4eBremsstrahlung52 physics process --------
@@ -50,6 +50,7 @@
// 16-01-03 Migrade to cut per region (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
// 08-11-04 Remove of Store/Retrieve tables (V.Ivantchenko)
//
// --------------------------------------------------------------
@@ -69,8 +70,8 @@ G4double G4eBremsstrahlung52::probsup = 1.00;
G4bool G4eBremsstrahlung52::LPMflag = true;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// constructor
using namespace std;
G4eBremsstrahlung52::G4eBremsstrahlung52(const G4String& processName)
: G4VeEnergyLoss(processName), // initialization
@@ -376,7 +377,7 @@ G4double G4eBremsstrahlung52::ComputeBremLoss(G4double Z,G4double,
G4double delz = 1.e6;
for (G4int ii=0; ii<NZ; ii++)
{
if(abs(Z-ZZ[ii]) < delz) { iz = ii; delz = abs(Z-ZZ[ii]);}
if(fabs(Z-ZZ[ii]) < delz) { iz = ii; delz = fabs(Z-ZZ[ii]);}
}
G4double xx = log10(T);
@@ -617,10 +618,10 @@ G4double G4eBremsstrahlung52::ComputeCrossSectionPerAtom(
G4double delz = 1.e6 ;
for (G4int ii=0; ii<NZ; ii++)
{
if(abs(AtomicNumber-ZZ[ii]) < delz)
if(fabs(AtomicNumber-ZZ[ii]) < delz)
{
iz = ii ;
delz = abs(AtomicNumber-ZZ[ii]) ;
delz = fabs(AtomicNumber-ZZ[ii]) ;
}
}
@@ -774,9 +775,9 @@ G4VParticleChange* G4eBremsstrahlung52::PostStepDoIt(const G4Track& trackData,
// check against insufficient energy
if (KineticEnergy < GammaEnergyCut)
{
aParticleChange.SetMomentumChange( ParticleDirection );
aParticleChange.SetEnergyChange( KineticEnergy );
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.ProposeMomentumDirection( ParticleDirection );
aParticleChange.ProposeEnergy( KineticEnergy );
aParticleChange.ProposeLocalEnergyDeposit (0.);
aParticleChange.SetNumberOfSecondaries(0);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
@@ -829,8 +830,8 @@ G4VParticleChange* G4eBremsstrahlung52::PostStepDoIt(const G4Track& trackData,
G4double screenmin = screenfac*epsilmin/(1.-epsilmin);
// Compute the maximum of the rejection function
G4double F1 = std::max(ScreenFunction1(screenmin) - FZ ,0.);
G4double F2 = std::max(ScreenFunction2(screenmin) - FZ ,0.);
G4double F1 = max(ScreenFunction1(screenmin) - FZ ,0.);
G4double F2 = max(ScreenFunction2(screenmin) - FZ ,0.);
grejmax = (F1 - epsilmin* (F1*ah - bh*epsilmin*F2))/(42.392 - FZ);
// sample the energy rate of the emitted Gamma
@@ -842,8 +843,8 @@ G4VParticleChange* G4eBremsstrahlung52::PostStepDoIt(const G4Track& trackData,
x = pow(xmin, G4UniformRand());
epsil = x*KineticEnergy/TotalEnergy;
screenvar = screenfac*epsil/(1-epsil);
F1 = std::max(ScreenFunction1(screenvar) - FZ ,0.);
F2 = std::max(ScreenFunction2(screenvar) - FZ ,0.);
F1 = max(ScreenFunction1(screenvar) - FZ ,0.);
F2 = max(ScreenFunction2(screenvar) - FZ ,0.);
migdal = (1. + MigdalFactor)/(1. + MigdalFactor/(x*x));
greject = migdal*(F1 - epsil* (ah*F1 - bh*epsil*F2))/(42.392 - FZ);
} while( greject < G4UniformRand()*grejmax );
@@ -867,9 +868,9 @@ G4VParticleChange* G4eBremsstrahlung52::PostStepDoIt(const G4Track& trackData,
G4double bl = bl0 + bl1*U + bl2*U2;
// Compute the maximum of the rejection function
grejmax = std::max(1. + xmin* (al + bl*xmin), 1.+al+bl);
grejmax = max(1. + xmin* (al + bl*xmin), 1.+al+bl);
G4double xm = -al/(2.*bl);
if ((xmin < xm)&&(xm < 1.)) grejmax = std::max(grejmax, 1.+ xm* (al + bl*xm));
if ((xmin < xm)&&(xm < 1.)) grejmax = max(grejmax, 1.+ xm* (al + bl*xm));
// sample the energy rate of the emitted Gamma
@@ -930,16 +931,16 @@ G4VParticleChange* G4eBremsstrahlung52::PostStepDoIt(const G4Track& trackData,
G4double NewKinEnergy = KineticEnergy - GammaEnergy;
if (NewKinEnergy > 0.)
{
aParticleChange.SetMomentumChange( ParticleDirection );
aParticleChange.SetEnergyChange( NewKinEnergy );
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.ProposeMomentumDirection( ParticleDirection );
aParticleChange.ProposeEnergy( NewKinEnergy );
aParticleChange.ProposeLocalEnergyDeposit (0.);
}
else
{
aParticleChange.SetEnergyChange( 0. );
aParticleChange.SetLocalEnergyDeposit (0.);
if (charge<0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
aParticleChange.ProposeEnergy( 0. );
aParticleChange.ProposeLocalEnergyDeposit (0.);
if (charge<0.) aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
@@ -1018,122 +1019,6 @@ G4double G4eBremsstrahlung52::SupressionFunction(const G4Material* aMaterial,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eBremsstrahlung52::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
if ( !theLossTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->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;
}
// store PartialSumSigma table (G4OrderedTable)
filename = GetPhysicsTableFileName(particle,directory,"PartSumSigma",ascii);
if ( !PartialSumSigma.Store(filename, ascii) ){
G4cout << " FAIL PartialSumSigma.store 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 G4eBremsstrahlung52::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theLossTable and theMeanFreePathTable
if (theLossTable != 0) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
G4String filename;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(0);
// retreive stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
theLossTable = new G4PhysicsTable(numOfCouples);
if ( !theLossTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable0->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retrieve PartialSumSigma table (G4OrderedTable)
PartialSumSigma.clearAndDestroy();
PartialSumSigma.reserve(numOfCouples);
filename = GetPhysicsTableFileName(particle,directory,"PartSumSigma",ascii);
if ( !PartialSumSigma.Retrieve(filename, ascii) ){
G4cout << " FAIL PartialSumSigma.retrieve in " << filename
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (particle==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildDEDXTable (*particle);
if (particle==G4Electron::Electron()) PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eBremsstrahlung52::PrintInfoDefinition()
{
G4String comments = "Total cross sections from a NEW parametrisation"
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4eBremsstrahlungModel.cc,v 1.16 2004/05/20 19:46:14 urban Exp $
// GEANT4 tag $Name: geant4-06-02 $
// $Id: G4eBremsstrahlungModel.cc,v 1.18 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
@@ -66,6 +66,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4eBremsstrahlungModel::G4eBremsstrahlungModel(const G4ParticleDefinition* p,
const G4String& nam)
: G4VEmModel(nam),
@@ -80,6 +82,7 @@ G4eBremsstrahlungModel::G4eBremsstrahlungModel(const G4ParticleDefinition* p,
theLPMflag(true)
{
if(p) SetParticle(p);
theGamma = G4Gamma::Gamma();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -151,7 +154,7 @@ void G4eBremsstrahlungModel::Initialise(const G4ParticleDefinition* p,
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
G4DataVector* dv = ComputePartialSumSigma(material, 0.5*highKinEnergy,
std::min(cuts[i], 0.25*highKinEnergy));
min(cuts[i], 0.25*highKinEnergy));
partialSumSigma.push_back(dv);
}
@@ -169,7 +172,7 @@ G4double G4eBremsstrahlungModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
const G4double thigh = 100.*GeV;
G4double cut = std::min(cutEnergy, kineticEnergy);
G4double cut = min(cutEnergy, kineticEnergy);
G4double rate, loss;
const G4double factorHigh = 36./(1450.*GeV);
@@ -334,7 +337,7 @@ G4double G4eBremsstrahlungModel::ComputeBremLoss(G4double Z, G4double T,
G4double delz = 1.e6;
for (G4int ii=0; ii<NZ; ii++)
{
G4double dz = abs(Z-ZZ[ii]);
G4double dz = fabs(Z-ZZ[ii]);
if(dz < delz) {
iz = ii;
delz = dz;
@@ -402,8 +405,8 @@ G4double G4eBremsstrahlungModel::CrossSection(const G4MaterialCutsCouple* couple
{
if(!particle) SetParticle(p);
G4double cross = 0.0;
G4double tmax = std::min(maxEnergy, kineticEnergy);
G4double cut = std::max(cutEnergy, minThreshold);
G4double tmax = min(maxEnergy, kineticEnergy);
G4double cut = max(cutEnergy, minThreshold);
if(cut >= tmax) return cross;
const G4Material* material = couple->GetMaterial();
@@ -536,10 +539,10 @@ G4double G4eBremsstrahlungModel::CrossSectionPerAtom(G4double kineticEnergy,
G4double delz = 1.e6 ;
for (G4int ii=0; ii<NZ; ii++)
{
if(abs(Z-ZZ[ii]) < delz)
if(fabs(Z-ZZ[ii]) < delz)
{
iz = ii ;
delz = abs(Z-ZZ[ii]);
delz = fabs(Z-ZZ[ii]);
}
}
@@ -639,7 +642,7 @@ G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
// (Nuc Phys 20(1960),15).
{
G4double kineticEnergy = dp->GetKineticEnergy();
G4double tmax = std::min(maxEnergy, kineticEnergy);
G4double tmax = min(maxEnergy, kineticEnergy);
if(tmin > tmax) tmin = tmax;
//
@@ -721,8 +724,8 @@ G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
G4double screenmin = screenfac*epsilmin/(1.-epsilmin);
// Compute the maximum of the rejection function
G4double F1 = std::max(ScreenFunction1(screenmin) - FZ ,0.);
G4double F2 = std::max(ScreenFunction2(screenmin) - FZ ,0.);
G4double F1 = max(ScreenFunction1(screenmin) - FZ ,0.);
G4double F2 = max(ScreenFunction2(screenmin) - FZ ,0.);
grejmax = (F1 - epsilmin* (F1*ah - bh*epsilmin*F2))/(42.392 - FZ);
} else {
@@ -739,9 +742,9 @@ G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
bh = bl0 + bl1*U + bl2*U2;
// Compute the maximum of the rejection function
grejmax = std::max(1. + xmin* (ah + bh*xmin), 1.+ah+bh);
grejmax = max(1. + xmin* (ah + bh*xmin), 1.+ah+bh);
G4double xm = -ah/(2.*bh);
if ( xmin < xm && xm < xmax) grejmax = std::max(grejmax, 1.+ xm* (ah + bh*xm));
if ( xmin < xm && xm < xmax) grejmax = max(grejmax, 1.+ xm* (ah + bh*xm));
}
//
@@ -755,8 +758,8 @@ G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
x = pow(xmin, q + kappa*(1.0 - q));
epsil = x*kineticEnergy/totalEnergy;
G4double screenvar = screenfac*epsil/(1.0-epsil);
G4double F1 = std::max(ScreenFunction1(screenvar) - FZ ,0.);
G4double F2 = std::max(ScreenFunction2(screenvar) - FZ ,0.);
G4double F1 = max(ScreenFunction1(screenvar) - FZ ,0.);
G4double F2 = max(ScreenFunction2(screenvar) - FZ ,0.);
migdal = (1. + MigdalFactor)/(1. + MigdalFactor/(x*x));
greject = migdal*(F1 - epsil* (ah*F1 - bh*epsil*F2))/(42.392 - FZ);
/*
@@ -823,14 +826,14 @@ G4DynamicParticle* G4eBremsstrahlungModel::SampleSecondary(
gammaDirection.rotateUz(direction);
// create G4DynamicParticle object for the Gamma
G4DynamicParticle* g = new G4DynamicParticle(G4Gamma::Gamma(),gammaDirection,gammaEnergy);
G4DynamicParticle* g = new G4DynamicParticle(theGamma,gammaDirection,gammaEnergy);
return g;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4eBremsstrahlungModel::SampleSecondaries(
vector<G4DynamicParticle*>* G4eBremsstrahlungModel::SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double,
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4eIonisation.cc,v 1.37 2003/11/12 16:23:42 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00-patch-01 $
// $Id: G4eIonisation.cc,v 1.39 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
@@ -57,6 +57,7 @@
// 03-06-03 Fix initialisation problem for STD ionisation (V.Ivanchenko)
// 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)
//
// -------------------------------------------------------------------
//
@@ -67,11 +68,12 @@
#include "G4Electron.hh"
#include "G4MollerBhabhaModel.hh"
#include "G4UniversalFluctuation.hh"
//#include "G4BohrFluctuations.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4eIonisation::G4eIonisation(const G4String& name)
: G4VEnergyLossProcess(name),
theElectron(G4Electron::Electron()),
@@ -92,33 +94,21 @@ G4eIonisation::~G4eIonisation()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4eIonisation::InitialiseProcess()
void G4eIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part,
const G4ParticleDefinition*)
{
SetSecondaryParticle(theElectron);
if(!isInitialised) {
if(part == G4Positron::Positron()) isElectron = false;
SetSecondaryParticle(theElectron);
if(IsIntegral()) {
// flucModel = new G4BohrFluctuations();
flucModel = new G4UniversalFluctuation();
} else {
flucModel = new G4UniversalFluctuation();
G4VEmModel* em = new G4MollerBhabhaModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em, flucModel);
isInitialised = true;
}
G4VEmModel* em = new G4MollerBhabhaModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(100.0*TeV);
AddEmModel(1, em, flucModel);
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4ParticleDefinition* G4eIonisation::DefineBaseParticle(const G4ParticleDefinition* p)
{
if(p == G4Positron::Positron()) isElectron = false;
if(!isInitialised) InitialiseProcess();
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eIonisation52.cc,v 1.1 2003/08/08 11:30:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00-patch-01 $
// $Id: G4eIonisation52.cc,v 1.4 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
//--------------- G4eIonisation52 physics process --------------------------------
// by Laszlo Urban, 20 March 1997
@@ -45,6 +45,7 @@
// 08-04-03 finalRange is region aware (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
// 08-11-04 Remove of Store/Retrieve tables (V.Ivantchenko)
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -62,6 +63,8 @@ G4int G4eIonisation52::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4eIonisation52::G4eIonisation52(const G4String& processName)
: G4VeEnergyLoss(processName),
theMeanFreePathTable(NULL)
@@ -284,7 +287,7 @@ G4double G4eIonisation52::ComputeRestrictedMeandEdx (
if (&aParticleType==G4Electron::Electron())
{
Tmax = KineticEnergy/2.;
d = std::min(DeltaThreshold, Tmax)/particleMass;
d = min(DeltaThreshold, Tmax)/particleMass;
dEdx = log(2.*(tau+2.)/Eexcm2)-1.-beta2
+ log((tau-d)*d)+tau/(tau-d)
+ (0.5*d*d+(2.*tau+1.)*log(1.-d/tau))/gamma2;
@@ -293,7 +296,7 @@ G4double G4eIonisation52::ComputeRestrictedMeandEdx (
else //positron
{
Tmax = KineticEnergy;
d = std::min(DeltaThreshold, Tmax)/particleMass;
d = min(DeltaThreshold, Tmax)/particleMass;
G4double d2=d*d/2., d3=d*d*d/3., d4=d*d*d*d/4.;
G4double y=1./(1.+gamma);
dEdx = log(2.*(tau+2.)/Eexcm2)+log(tau*d)
@@ -491,128 +494,32 @@ G4VParticleChange* G4eIonisation52::PostStepDoIt( const G4Track& trackData,
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.SetMomentumChange(finalPx, finalPy, finalPz);
aParticleChange.ProposeMomentumDirection(finalPx, finalPy, finalPz);
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (Charge < 0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
if (Charge < 0.) aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.SetEnergyChange(finalKineticEnergy);
aParticleChange.ProposeEnergy(finalKineticEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.SetLocalEnergyDeposit(Edep);
aParticleChange.ProposeLocalEnergyDeposit(Edep);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eIonisation52::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
// store stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
if ( !theLossTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->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 G4eIonisation52::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theLossTable and theMeanFreePathTable
if (theLossTable != 0) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
G4String filename;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
// retreive stopping power table
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
theLossTable = new G4PhysicsTable(numOfCouples);
if ( !theLossTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
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;
if (particle==G4Electron::Electron())
{
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
}
else
{
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildDEDXTable(*particle);
if (particle==G4Electron::Electron()) PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eIonisation52::PrintInfoDefinition()
{
G4String comments = "delta cross sections from Moller+Bhabha. "
"Good description from 1 KeV to 100 GeV.\n"
" delta ray energy sampled from differential Xsection.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< G4BestUnit(LowerBoundLambda,"Energy")
@@ -0,0 +1,239 @@
//
// ********************************************************************
// * 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: G4eeToTwoGammaModel.cc,v 1.4 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4eeToTwoGammaModel
//
// Author: Vladimir Ivanchenko on base of Michel Maire code
//
// Creation date: 02.08.2004
//
// Modifications:
//
//
// Class Description:
//
// Implementation of e+ annihilation into 2 gamma
//
// 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.
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4eeToTwoGammaModel.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4Gamma.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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)
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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)
{
// 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;
G4double gam = tau + 1.0;
G4double gamma2= gam*gam;
G4double bg2 = tau * (tau+2.0);
G4double bg = sqrt(bg2);
G4double cross = pi_rcl2*eDensity*((gamma2+4*gam+1.)*log(gam+bg) - (gam+3.)*bg)
/ (bg2*(gam+1.));
return cross;
}
//....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,
G4double,
G4double)
{
G4double PositKinEnergy = dp->GetKineticEnergy();
G4ThreeVector PositDirection = dp->GetMomentumDirection();
G4double tau = PositKinEnergy/electron_mass_c2;
G4double gam = tau + 1.0;
G4double tau2 = tau + 2.0;
G4double sqgrate = sqrt(tau/tau2)*0.5;
G4double sqg2m1 = sqrt(tau*tau2);
// limits of the energy sampling
G4double epsilmin = 0.5 - sqgrate;
G4double 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.*gam*epsil-1.)/(epsil*tau2*tau2);
} while( greject < G4UniformRand() );
//
// scattered Gamma angles. ( Z - axis along the parent positron)
//
G4double cost = (epsil*tau2-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
//
G4double TotalAvailableEnergy = PositKinEnergy + 2.0*electron_mass_c2;
G4double Phot1Energy = epsil*TotalAvailableEnergy;
vector<G4DynamicParticle*>* vdp = new vector<G4DynamicParticle*>;
G4ThreeVector Phot1Direction (dirx, diry, dirz);
Phot1Direction.rotateUz(PositDirection);
G4DynamicParticle* aParticle1 = new G4DynamicParticle (G4Gamma::Gamma(),
Phot1Direction, Phot1Energy);
vdp->push_back(aParticle1);
G4double Phot2Energy =(1.-epsil)*TotalAvailableEnergy;
G4double Eratio= Phot1Energy/Phot2Energy;
G4double PositP= sqrt(PositKinEnergy*(PositKinEnergy+2.*electron_mass_c2));
G4ThreeVector Phot2Direction (-dirx*Eratio, -diry*Eratio,
(PositP-dirz*Phot1Energy)/Phot2Energy);
Phot2Direction.unit();
Phot2Direction.rotateUz(PositDirection);
// create G4DynamicParticle object for the particle2
G4DynamicParticle* aParticle2= new G4DynamicParticle (G4Gamma::Gamma(),
Phot2Direction, Phot2Energy);
vdp->push_back(aParticle2);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eplusAnnihilation.cc,v 1.16 2004/03/10 16:48:46 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-01 $
// $Id: G4eplusAnnihilation.cc,v 1.20 2004/12/01 19:37:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -38,7 +38,8 @@
// 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......
@@ -47,7 +48,7 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// constructor
using namespace std;
G4eplusAnnihilation::G4eplusAnnihilation(const G4String& processName,
G4ProcessType type):G4VRestDiscreteProcess (processName, type),
@@ -75,6 +76,12 @@ G4eplusAnnihilation::~G4eplusAnnihilation()
delete theMeanFreePathTable;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eplusAnnihilation::IsApplicable( const G4ParticleDefinition& particle)
{
return ( &particle == G4Positron::Positron() );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -104,7 +111,7 @@ void G4eplusAnnihilation::BuildPhysicsTable(const G4ParticleDefinition& )
G4double AtomicNumber;
size_t J;
for ( J=0 ; J < G4Element::GetNumberOfElements(); J++ )
for ( J=0 ; J < G4Element::GetNumberOfElements(); J++ )
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit, HighestEnergyLimit,
@@ -132,7 +139,7 @@ void G4eplusAnnihilation::BuildPhysicsTable(const G4ParticleDefinition& )
G4Material* material;
for ( J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
{
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(LowestEnergyLimit, HighestEnergyLimit,
NumbBinTable );
@@ -149,7 +156,7 @@ void G4eplusAnnihilation::BuildPhysicsTable(const G4ParticleDefinition& )
}
PrintInfoDefinition();
PrintInfoDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -173,6 +180,92 @@ G4double G4eplusAnnihilation::ComputeCrossSectionPerAtom
}
//....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,
@@ -186,7 +279,7 @@ G4VParticleChange* G4eplusAnnihilation::PostStepDoIt(const G4Track& aTrack,
// 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.
@@ -242,7 +335,7 @@ G4VParticleChange* G4eplusAnnihilation::PostStepDoIt(const G4Track& aTrack,
G4double Phot1Energy = epsil*TotalAvailableEnergy;
if (Phot1Energy > fminimalEnergy) {
G4ThreeVector Phot1Direction (dirx, diry, dirz);
Phot1Direction.rotateUz(PositDirection);
Phot1Direction.rotateUz(PositDirection);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1= new G4DynamicParticle (G4Gamma::Gamma(),
Phot1Direction, Phot1Energy);
@@ -264,15 +357,14 @@ G4VParticleChange* G4eplusAnnihilation::PostStepDoIt(const G4Track& aTrack,
}
else localEnergyDeposit += Phot2Energy;
aParticleChange.SetLocalEnergyDeposit(localEnergyDeposit);
aParticleChange.ProposeLocalEnergyDeposit(localEnergyDeposit);
//
// Kill the incident positron
//
aParticleChange.SetMomentumChange( 0., 0., 0. );
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.ProposeEnergy(0.);
aParticleChange.ProposeTrackStatus(fStopAndKill);
return &aParticleChange;
}
@@ -288,7 +380,7 @@ G4VParticleChange* G4eplusAnnihilation::AtRestDoIt(const G4Track& aTrack,
// GEANT4 internal units
//
// Note : Effects due to binding of atomic electrons are negliged.
{
aParticleChange.Initialize(aTrack);
@@ -303,19 +395,19 @@ G4VParticleChange* G4eplusAnnihilation::AtRestDoIt(const G4Track& aTrack,
aParticleChange.AddSecondary( new G4DynamicParticle (G4Gamma::Gamma(),
-Direction, electron_mass_c2) );
aParticleChange.SetLocalEnergyDeposit(0.);
aParticleChange.ProposeLocalEnergyDeposit(0.);
// Kill the incident positron
//
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.ProposeTrackStatus(fStopAndKill);
return &aParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eplusAnnihilation::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool G4eplusAnnihilation::StorePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String filename;
@@ -335,17 +427,17 @@ G4bool G4eplusAnnihilation::StorePhysicsTable(G4ParticleDefinition* particle,
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4eplusAnnihilation::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
/*
G4bool G4eplusAnnihilation::RetrievePhysicsTable(const G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
// delete theCrossSectionTable and theMeanFreePathTable
@@ -365,7 +457,7 @@ G4bool G4eplusAnnihilation::RetrievePhysicsTable(G4ParticleDefinition* particle,
theCrossSectionTable = new G4PhysicsTable(G4Element::GetNumberOfElements());
if ( !theCrossSectionTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theCrossSectionTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
@@ -374,16 +466,16 @@ G4bool G4eplusAnnihilation::RetrievePhysicsTable(G4ParticleDefinition* particle,
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
return true;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4eplusAnnihilation::PrintInfoDefinition()
@@ -0,0 +1,141 @@
//
// ********************************************************************
// * 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.51 2004/05/27 17:23:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-02 $
// $Id: G4hIonisation.cc,v 1.54 2004/12/01 19:37:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
@@ -67,6 +67,7 @@
// 08-08-03 STD substitute standard (V.Ivanchenko)
// 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)
//
// -------------------------------------------------------------------
//
@@ -85,6 +86,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4hIonisation::G4hIonisation(const G4String& name)
: G4VEnergyLossProcess(name),
theParticle(0),
@@ -108,9 +111,18 @@ G4hIonisation::~G4hIonisation()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisation::InitialiseProcess()
void G4hIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part,
const G4ParticleDefinition* bpart)
{
if(isInitialised) return;
theParticle = part;
if(part == bpart || part == G4Proton::Proton()) theBaseParticle = 0;
else if(bpart == 0) theBaseParticle = G4Proton::Proton();
else theBaseParticle = bpart;
SetBaseParticle(theBaseParticle);
SetSecondaryParticle(G4Electron::Electron());
mass = theParticle->GetPDGMass();
ratio = electron_mass_c2/mass;
@@ -135,18 +147,6 @@ void G4hIonisation::InitialiseProcess()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4ParticleDefinition* G4hIonisation::DefineBaseParticle(
const G4ParticleDefinition* p)
{
if(!theParticle) theParticle = p;
if(p != BaseParticle() && p != G4Proton::Proton()) theBaseParticle = G4Proton::Proton();
if(!isInitialised) InitialiseProcess();
return theBaseParticle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hIonisation::PrintInfoDefinition()
{
G4VEnergyLossProcess::PrintInfoDefinition();
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4hIonisation52.cc,v 1.1 2003/08/08 11:30:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-00-patch-01 $
// $Id: G4hIonisation52.cc,v 1.4 2004/12/01 19:37:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
//---------------- G4hIonisation52 physics process -------------------------------
// by Laszlo Urban, 30 May 1997
@@ -56,6 +56,7 @@
// 17-04-03 fix problem of hadron tests (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
// 08-08-03 This class is frozen at the release 5.2 (V.Ivanchenko)
// 08-11-04 Remove of Store/Retrieve tables (V.Ivantchenko)
//
//------------------------------------------------------------------------------
@@ -76,6 +77,8 @@ G4int G4hIonisation52::NbinLambda = 100;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4hIonisation52::G4hIonisation52(const G4String& processName)
: G4VhEnergyLoss(processName),
theMeanFreePathTable(0),
@@ -357,7 +360,7 @@ G4double G4hIonisation52::ComputeRestrictedMeandEdx (
//
if (tau > taul)
{
G4double rcut = std::min(DeltaThreshold/Tmax, 1.);
G4double rcut = min(DeltaThreshold/Tmax, 1.);
dEdx = log(2.*electron_mass_c2*bg2*Tmax/Eexc2)
+log(rcut)-(1.+rcut)*beta2;
@@ -574,21 +577,21 @@ G4VParticleChange* G4hIonisation52::PostStepDoIt(const G4Track& trackData,
finalPy /= finalMomentum;
finalPz /= finalMomentum;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
aParticleChange.ProposeMomentumDirection( finalPx,finalPy,finalPz );
}
else
{
Edep = finalKineticEnergy;
finalKineticEnergy = 0.;
if (!aParticle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
aParticleChange.ProposeTrackStatus(fStopAndKill);
else aParticleChange.ProposeTrackStatus(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.ProposeEnergy( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(theDeltaRay);
aParticleChange.SetLocalEnergyDeposit (Edep);
aParticleChange.ProposeLocalEnergyDeposit (Edep);
//ResetNumberOfInteractionLengthLeft();
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
@@ -596,122 +599,6 @@ G4VParticleChange* G4hIonisation52::PostStepDoIt(const G4Track& trackData,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4hIonisation52::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String particleName = particle->GetParticleName();
G4String filename;
// store stopping power table
if ((particleName == "proton")||(particleName == "anti_proton")) {
filename = GetPhysicsTableFileName(particle,directory,"StoppingPower",ascii);
if ( !theLossTable->StorePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable->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 " << particleName
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4hIonisation52::RetrievePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
G4bool ascii)
{
G4String particleName = particle->GetParticleName();
if(particle->GetParticleType() == "nucleus" &&
particleName != "GenericIon" &&
particle->GetParticleSubType() == "generic")
{
G4EnergyLossTables::Register(particle,
theDEDXpTable,
theRangepTable,
theInverseRangepTable,
theLabTimepTable,
theProperTimepTable,
LowestKineticEnergy, HighestKineticEnergy,
proton_mass_c2/particle->GetPDGMass(),
TotBin);
return true;
}
// delete theLossTable and theMeanFreePathTable
if (theLossTable != 0) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
if (theMeanFreePathTable != 0) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
// get bining from EnergyLoss
LowestKineticEnergy = GetLowerBoundEloss();
HighestKineticEnergy = GetUpperBoundEloss();
TotBin = GetNbinEloss();
G4String filename;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
secondaryEnergyCuts = theCoupleTable->GetEnergyCutsVector(1);
G4double charge = particle->GetPDGCharge()/eplus;
G4ParticleDefinition* basep = G4Proton::Proton();
if(charge < 0.0) basep = G4AntiProton::AntiProton();
filename = GetPhysicsTableFileName(basep,directory,"StoppingPower",ascii);
theLossTable = new G4PhysicsTable(numOfCouples);
if ( !theLossTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theLossTable0->RetrievePhysicsTable in " << filename
<< G4endl;
BuildPhysicsTable(*particle);
return true;
}
RecorderOfpProcess[0] = (*this).theLossTable;
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
if ( !theMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
return false;
}
initialMass = particle->GetPDGMass();
G4cout << GetProcessName() << " for " << particleName
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
BuildDEDXTable(*particle);
if (particle == G4Proton::Proton()) PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4hIonisation52::PrintInfoDefinition()
{
G4String comments = " Knock-on electron cross sections . "
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4ionIonisation.cc,v 1.23 2004/05/27 17:22:56 vnivanch Exp $
// GEANT4 tag $Name: geant4-06-02 $
// $Id: G4ionIonisation.cc,v 1.31 2004/12/01 19:37:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-07-00-cand-03 $
//
// -------------------------------------------------------------------
//
@@ -42,7 +42,8 @@
// 18-04-03 Use IonFluctuations (V.Ivanchenko)
// 03-08-03 Add effective charge (V.Ivanchenko)
// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
// 27-05-04 Set integral to be a default regime (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)
//
//
// -------------------------------------------------------------------
@@ -53,20 +54,30 @@
#include "G4ionIonisation.hh"
#include "G4Electron.hh"
#include "G4Proton.hh"
#include "G4AntiProton.hh"
#include "G4GenericIon.hh"
#include "G4BraggModel.hh"
#include "G4BraggIonModel.hh"
#include "G4BetheBlochModel.hh"
#include "G4IonFluctuations.hh"
#include "G4UniversalFluctuation.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4ionIonisation::G4ionIonisation(const G4String& name)
: G4VEnergyLossProcess(name),
theParticle(0),
theBaseParticle(0),
isInitialised(false),
subCutoff(false)
{
InitialiseProcess();
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
SetVerboseLevel(0);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -76,18 +87,23 @@ G4ionIonisation::~G4ionIonisation()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ionIonisation::InitialiseProcess()
void G4ionIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part,
const G4ParticleDefinition* bpart)
{
SetSecondaryParticle(G4Electron::Electron());
if(isInitialised) return;
SetDEDXBinning(120);
SetLambdaBinning(120);
SetMinKinEnergy(0.1*keV);
SetMaxKinEnergy(100.0*TeV);
theParticle = part;
if(part == bpart || part == G4GenericIon::GenericIon()) theBaseParticle = 0;
else if(bpart == 0) theBaseParticle = G4GenericIon::GenericIon();
else theBaseParticle = bpart;
SetBaseParticle(theBaseParticle);
SetSecondaryParticle(G4Electron::Electron());
flucModel = new G4IonFluctuations();
G4VEmModel* em = new G4BraggModel();
G4VEmModel* em = new G4BraggIonModel();
em->SetLowEnergyLimit(0.1*keV);
em->SetHighEnergyLimit(2.0*MeV);
AddEmModel(1, em, flucModel);
@@ -96,20 +112,10 @@ void G4ionIonisation::InitialiseProcess()
em1->SetHighEnergyLimit(100.0*TeV);
AddEmModel(2, em1, flucModel);
chargeLowLimit = 0.1;
energyLowLimit = 25.*MeV;
SetLinearLossLimit(0.15);
SetStepLimits(0.1, 0.1*mm);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4ParticleDefinition* G4ionIonisation::DefineBaseParticle(
const G4ParticleDefinition* p)
{
if(p) theParticle = p;
theBaseParticle = G4Proton::Proton();
return theBaseParticle;
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -134,141 +140,4 @@ void G4ionIonisation::SetSubCutoff(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ionIonisation::EffectiveCharge(const G4ParticleDefinition* p,
const G4Material* material,
G4double kineticEnergy)
{
G4double mass = p->GetPDGMass();
G4double charge = p->GetPDGCharge();
G4double Zi = charge/eplus;
chargeCorrection = 1.0;
// The aproximation of ion effective charge from:
// J.F.Ziegler, J.P. Biersack, U. Littmark
// The Stopping and Range of Ions in Matter,
// Vol.1, Pergamon Press, 1985
// Fast ions or hadrons
G4double reducedEnergy = kineticEnergy * proton_mass_c2/mass ;
if( reducedEnergy > energyLowLimit || Zi < 1.5 ) return charge ;
static G4double vFermi[92] = {
1.0309, 0.15976, 0.59782, 1.0781, 1.0486, 1.0, 1.058, 0.93942, 0.74562, 0.3424,
0.45259, 0.71074, 0.90519, 0.97411, 0.97184, 0.89852, 0.70827, 0.39816, 0.36552, 0.62712,
0.81707, 0.9943, 1.1423, 1.2381, 1.1222, 0.92705, 1.0047, 1.2, 1.0661, 0.97411,
0.84912, 0.95, 1.0903, 1.0429, 0.49715, 0.37755, 0.35211, 0.57801, 0.77773, 1.0207,
1.029, 1.2542, 1.122, 1.1241, 1.0882, 1.2709, 1.2542, 0.90094, 0.74093, 0.86054,
0.93155, 1.0047, 0.55379, 0.43289, 0.32636, 0.5131, 0.695, 0.72591, 0.71202, 0.67413,
0.71418, 0.71453, 0.5911, 0.70263, 0.68049, 0.68203, 0.68121, 0.68532, 0.68715, 0.61884,
0.71801, 0.83048, 1.1222, 1.2381, 1.045, 1.0733, 1.0953, 1.2381, 1.2879, 0.78654,
0.66401, 0.84912, 0.88433, 0.80746, 0.43357, 0.41923, 0.43638, 0.51464, 0.73087, 0.81065,
1.9578, 1.0257} ;
static G4double lFactor[92] = {
1.0, 1.0, 1.1, 1.06, 1.01, 1.03, 1.04, 0.99, 0.95, 0.9,
0.82, 0.81, 0.83, 0.88, 1.0, 0.95, 0.97, 0.99, 0.98, 0.97,
0.98, 0.97, 0.96, 0.93, 0.91, 0.9, 0.88, 0.9, 0.9, 0.9,
0.9, 0.85, 0.9, 0.9, 0.91, 0.92, 0.9, 0.9, 0.9, 0.9,
0.9, 0.88, 0.9, 0.88, 0.88, 0.9, 0.9, 0.88, 0.9, 0.9,
0.9, 0.9, 0.96, 1.2, 0.9, 0.88, 0.88, 0.85, 0.9, 0.9,
0.92, 0.95, 0.99, 1.03, 1.05, 1.07, 1.08, 1.1, 1.08, 1.08,
1.08, 1.08, 1.09, 1.09, 1.1, 1.11, 1.12, 1.13, 1.14, 1.15,
1.17, 1.2, 1.18, 1.17, 1.17, 1.16, 1.16, 1.16, 1.16, 1.16,
1.16, 1.16} ;
static G4double c[6] = {0.2865, 0.1266, -0.001429,
0.02402,-0.01135, 0.001475} ;
// get elements in the actual material,
const G4ElementVector* theElementVector = material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements = material->GetNumberOfElements() ;
// loop for the elements in the material
// to find out average values Z, vF, lF
G4double z = 0.0, vF = 0.0, lF = 0.0, norm = 0.0 ;
if( 1 == NumberOfElements ) {
z = material->GetZ() ;
G4int iz = G4int(z) - 1 ;
if(iz < 0) iz = 0 ;
else if(iz > 91) iz = 91 ;
vF = vFermi[iz] ;
lF = lFactor[iz] ;
} else {
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)[iel] ;
G4double z2 = element->GetZ() ;
const G4double weight = theAtomicNumDensityVector[iel] ;
norm += weight ;
z += z2 * weight ;
G4int iz = G4int(z2) - 1 ;
if(iz < 0) iz = 0 ;
else if(iz > 91) iz =91 ;
vF += vFermi[iz] * weight ;
lF += lFactor[iz] * weight ;
}
z /= norm ;
vF /= norm ;
lF /= norm ;
}
G4double q;
// Helium ion case
if( Zi < 2.5 ) {
// Normalise to He4 mass
G4double e = log(std::max(1.0, kineticEnergy / (keV*4.0026) ) );
G4double x = c[0] ;
G4double y = 1.0 ;
for (G4int i=1; i<6; i++) {
y *= e ;
x += y * c[i] ;
}
q = 7.6 - e ;
q = 1.0 + ( 0.007 + 0.00005 * z ) * exp( -q*q ) * sqrt(1.0 - exp(-x)) ;
if( q < chargeLowLimit ) q = chargeLowLimit ;
// Heavy ion case
} else {
// v1 is ion velocity in vF unit
G4double v1 = sqrt( reducedEnergy / (25.0 * keV) )/ vF ;
G4double y ;
G4double z13 = pow(Zi, 0.3333) ;
// Faster than Fermi velocity
if ( v1 > 1.0 ) {
y = vF * v1 * ( 1.0 + 0.2 / (v1*v1) ) / (z13*z13) ;
// Slower than Fermi velocity
} else {
y = 0.6923 * vF * (1.0 + 2.0*v1*v1/3.0 + v1*v1*v1*v1/15.0) / (z13*z13) ;
}
G4double y3 = pow(y, 0.3) ;
// G4cout << "y= " << y << " y3= " << y3 << " v1= " << v1 << " vF= " << vF << G4endl;
q = 1.0 - exp( 0.803*y3 - 1.3167*y3*y3 - 0.38157*y - 0.008983*y*y ) ;
if( q < chargeLowLimit ) q = chargeLowLimit ;
G4double s = 7.6 - log(std::max(1.0, reducedEnergy/keV)) ;
s = 1.0 + ( 0.18 + 0.0015 * z ) * exp( -s*s )/ (Zi*Zi) ;
// Screen length according to
// J.F.Ziegler and J.M.Manoyan, The stopping of ions in compaunds,
// Nucl. Inst. & Meth. in Phys. Res. B35 (1988) 215-228.
G4double lambda = 10.0 * vF * pow(1.0-q, 0.6667) / (z13 * (6.0 + q)) ;
chargeCorrection = s * (1.0 + 0.5*(1.0/q - 1.0)*log(1.0 + lambda*lambda)/(vF*vF) );
}
// G4cout << "G4ionIonisation: charge= " << charge << " q= " << q
// << " chargeCor= " << chargeCorrection << G4endl;
return charge*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....