Import Geant4 0.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-01 15:25:35 +02:00
parent 54d6b71f95
commit b97f8d0df7
3237 changed files with 807095 additions and 0 deletions
@@ -0,0 +1,31 @@
# $Id: GNUmakefile,v 2.0 1998/07/02 16:18:43 gunter Exp $
# --------------------------------------------------------------------
# GNUmakefile for electromagnetic sub-library. John Allison, 25/6/98.
# --------------------------------------------------------------------
name := G4muons
ifndef G4INSTALL
G4INSTALL = ../../../..
endif
include $(G4INSTALL)/config/architecture.gmk
CPPFLAGS += -I$(G4BASE)/global/management/include \
-I$(G4BASE)/global/HEPRandom/include \
-I$(G4BASE)/global/HEPGeometry/include \
-I$(G4BASE)/geometry/management/include \
-I$(G4BASE)/geometry/magneticfield/include \
-I$(G4BASE)/geometry/volumes/include \
-I$(G4BASE)/track/include \
-I$(G4BASE)/processes/management/include \
-I$(G4BASE)/processes/electromagnetic/utils/include \
-I$(G4BASE)/particles/management/include \
-I$(G4BASE)/particles/bosons/include \
-I$(G4BASE)/particles/leptons/include \
-I$(G4BASE)/particles/hadrons/barions/include \
-I$(G4BASE)/particles/hadrons/mesons/include \
-I$(G4BASE)/particles/hadrons/ions/include \
-I$(G4BASE)/materials/include
include $(G4INSTALL)/config/common.gmk
@@ -0,0 +1,159 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuBremsstrahlung.hh,v 2.1 1998/08/23 11:50:49 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4IMuBremsstrahlung physics process ---------
// by Laszlo Urban, September 1997
// ************************************************************
#ifndef G4IMuBremsstrahlung_h
#define G4IMuBremsstrahlung_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4IMuEnergyLoss.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Gamma.hh"
#include "G4MuonMinus.hh"
#include "G4MuonPlus.hh"
#include "G4OrderedTable.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsLogVector.hh"
class G4IMuBremsstrahlung : public G4IMuEnergyLoss
{
public:
G4IMuBremsstrahlung(const G4String& processName = "IMuBremsstrahlung");
~G4IMuBremsstrahlung();
G4bool IsApplicable(const G4ParticleDefinition&);
private:
G4IMuBremsstrahlung & operator=(const G4IMuBremsstrahlung &right);
G4IMuBremsstrahlung(const G4IMuBremsstrahlung&);
public:
// post Step functions .......................................
G4double PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
) ;
G4VParticleChange *PostStepDoIt(
const G4Track& track,
const G4Step& Step ) ;
void BuildLossTable(const G4ParticleDefinition& ParticleType);
void BuildLambdaTable(const G4ParticleDefinition& ParticleType);
void BuildPhysicsTable(const G4ParticleDefinition& ParticleType);
protected:
inline G4double ComputeMeanFreePath( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
void ComputePartialSumSigma( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
virtual G4double ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double GammaEnergyCut);
private:
void BuildNlambdaTable(const G4ParticleDefinition& aParticleType) ;
void BuildNlambdaVector(const G4ParticleDefinition& aParticleType,
G4int materialIndex,
G4PhysicsLogVector* nlambdaVector) ;
void BuildInverseNlambdaTable(
const G4ParticleDefinition& aParticleType) ;
void InvertNlambdaVector(const G4ParticleDefinition& aParticleType,
G4int materialIndex,
G4PhysicsLogVector* nlambdaVector) ;
void BuildCoeffATable(const G4ParticleDefinition& aParticleType) ;
void BuildCoeffBTable(const G4ParticleDefinition& aParticleType) ;
void BuildCoeffCTable(const G4ParticleDefinition& aParticleType) ;
void TestOfInversion(const G4ParticleDefinition& aParticleType,
G4int printflag) ;
G4double ComputeBremLoss(G4double Z,G4double T,
G4double Cut);
G4Element* SelectRandomAtom(G4Material* aMaterial) const;
private:
G4PhysicsTable* theMeanFreePathTable ;
G4OrderedTable PartialSumSigma; // partial sum of total crosssection
G4PhysicsTable* theNlambdaTable;
G4PhysicsTable* theInverseNlambdaTable;
G4PhysicsTable* theCoeffATable;
G4PhysicsTable* theCoeffBTable;
G4PhysicsTable* theCoeffCTable;
const G4double LowestKineticEnergy; // low energy limit of the crossection formula
const G4double HighestKineticEnergy; // high energy limit of the crossection formula
G4int TotBin; // number of bins in the tables
G4double MinKineticEnergy; //process is ignored if T<MinKineticEnergy
G4double MinCutValue; //protection against divergencies
// 1 = 2/(3.*Z**(1/3)) , 2= exp(-0.128*(1.18*A**(1/3)-0.48)
G4int NuclearFormFactor ;
G4double CutInRange;
const G4Gamma* theGamma;
const G4MuonMinus* theMuonMinus;
const G4MuonPlus* theMuonPlus;
const G4double* GammaCutInKineticEnergy;
const G4double* MuonMinusCutInKineticEnergy;
const G4double* MuonPlusCutInKineticEnergy;
const G4double* ParticleCutInKineticEnergy;
G4double GammaCutInKineticEnergyNow;
G4double MuonMinusCutInKineticEnergyNow;
G4double MuonPlusCutInKineticEnergyNow;
G4double ParticleCutInKineticEnergyNow;
G4int NumberOfBuildPhysicsTableCalls ;
};
#include "G4IMuBremsstrahlung.icc"
#endif
@@ -0,0 +1,171 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuBremsstrahlung.icc,v 2.1 1998/08/23 11:50:50 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4IMuBremsstrahlung physics process ---------
// by Laszlo Urban, September 1997
// ***************************************************************
inline G4double G4IMuBremsstrahlung::PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
)
{// get particle,particle type,kin.energy,material,mat.index
const G4double eps=1.e-2 ;
const G4double Tfac=0.95,Tfac1=1.-Tfac ;
G4double nl,nll,nlold,range,rangeold,rangenext,
dEdx,KineticEnergyOld,KineticEnergyNext,value;
G4bool isOut;
const G4DynamicParticle* particle = track.GetDynamicParticle();
const G4ParticleDefinition* particletype = particle->GetDefinition() ;
G4double KineticEnergy = particle->GetKineticEnergy();
G4Material* material = track.GetMaterial();
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable();
G4int materialindex = material->GetIndex();
nl = (*theNlambdaTable)[materialindex]->
GetValue(KineticEnergy,isOut);
range = G4EnergyLossTables::GetPreciseRangeFromEnergy(particletype,
KineticEnergy,material) ;
if ( (previousStepSize <=0.0) || (theNumberOfInteractionLengthLeft<=0.0)) {
// beggining of tracking (or just after DoIt of this process)
ResetNumberOfInteractionLengthLeft();
} else {
// subtract NumberOfInteractionLengthLeft
if(previousStepSize/range < eps)
{
nll = (*theNlambdaTable)[materialindex]->
GetValue(Tfac*KineticEnergy,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(particletype,
KineticEnergy,
material) ;
nlold = nl + dEdx*previousStepSize*(nl-nll)/
(Tfac1*KineticEnergy) ;
}
else
{
rangeold = range + previousStepSize ;
KineticEnergyOld = G4EnergyLossTables::GetPreciseEnergyFromRange(
particletype,
rangeold,material);
nlold = (*theNlambdaTable)[materialindex]->
GetValue(KineticEnergyOld,isOut);
if(nlold < nl)
{
if(verboseLevel>2)
{
G4cout << "G4IMuBremsstrahlung PostStepGPIL : Nlambda has been" <<
" increased at update.Nlambda old/new :" << nlold <<
" " << nl << endl;
G4cout << "(theNumberOfInteractionLengthLeft has been increased!)" << endl
;
G4cout << " correction : Nlambda old=new ........." << endl;
}
//corr. of num errror
nlold = nl ;
}
}
theNumberOfInteractionLengthLeft -= nlold-nl ;
if(theNumberOfInteractionLengthLeft<perMillion)
theNumberOfInteractionLengthLeft=0.;
}
// condition is set to "Not Forced"
*condition = NotForced;
if(nl <= theNumberOfInteractionLengthLeft)
{
value = BIGSTEP ;
}
else
{
if(theNumberOfInteractionLengthLeft/nl < eps)
{
nll = (*theNlambdaTable)[materialindex]->
GetValue(Tfac*KineticEnergy,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(particletype,
KineticEnergy,
material) ;
value = theNumberOfInteractionLengthLeft*Tfac1*KineticEnergy/(dEdx*(nl-nll))
;
}
else
{
KineticEnergyNext = (*theInverseNlambdaTable)[materialindex]->
GetValue(nl-theNumberOfInteractionLengthLeft,isOut);
rangenext = G4EnergyLossTables::GetPreciseRangeFromEnergy(particletype,
KineticEnergyNext,material);
value = range - rangenext ;
if(range<rangenext)
{
if(verboseLevel>2)
{
G4cout << "G4IhIonisation PostStepGPIL: Step < 0.!, Step=" << value << endl
;
G4cout << "range,rangenext:" << range << " " << rangenext << endl ;
G4cout << "correction : rangenext=range ....." << endl;
}
//corr. of num error
rangenext = range ;
value = range - rangenext ;
}
}
}
return value;
}
inline G4double G4IMuBremsstrahlung::ComputeMeanFreePath(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
{
const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
const G4double BigPath= DBL_MAX;
G4double SIGMA = 0 ;
for ( G4int i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
SIGMA += theAtomNumDensityVector[i] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(i)->GetZ(),
GammaEnergyCut );
}
return SIGMA<=0.0 ? BigPath : 1./SIGMA ;
}
inline G4bool G4IMuBremsstrahlung::IsApplicable(
const G4ParticleDefinition& particle)
{
return( (&particle == (const G4ParticleDefinition *)theMuonMinus)
||(&particle == (const G4ParticleDefinition *)theMuonPlus)
) ;
}
@@ -0,0 +1,275 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuEnergyLoss.hh,v 2.1 1998/08/23 11:50:51 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// -------------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4IMuEnergyLoss physics process -----------
// by Laszlo Urban, September 1997
// ********************************************************************
// It is the implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the continuous energy loss for muons.
// Processes giving contribution to the continuous loss :
// ionisation (= cont.ion.loss + delta ray production)
// bremsstrahlung
// e+e- pair production
// can be added more easily ..........
// This class creates static muplus/muminus dE/dx and range tables ,
// which tables can be used by other processes.
// ************************************************************
// some corrections by L.Urban on 27/05/98 , (but other corrections come soon!)
// ------------------------------------------------------------
#ifndef G4IMuEnergyLoss_h
#define G4IMuEnergyLoss_h 1
#include "G4ios.hh"
#include <fstream.h>
#include <iomanip.h>
#include "globals.hh"
#include "Randomize.hh"
#include "G4IVContinuousDiscreteProcess.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4VParticleChange.hh"
#include "globals.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4MuonMinus.hh"
#include "G4MuonPlus.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsLinearVector.hh"
class G4IMuEnergyLoss : public G4IVContinuousDiscreteProcess
{
public:
G4IMuEnergyLoss(const G4String& );
G4IMuEnergyLoss(G4IMuEnergyLoss &);
~G4IMuEnergyLoss();
G4bool IsApplicable(const G4ParticleDefinition&);
private:
// hide assignment operator
G4IMuEnergyLoss & operator=(const G4IMuEnergyLoss &right);
public:
G4double GetContinuousStepLimit(
const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) ;
G4VParticleChange* AlongStepDoIt(const G4Track& track ,const G4Step& Step) ;
virtual G4VParticleChange* PostStepDoIt(const G4Track& track,const G4Step& Step) = 0 ;
// Build energy loss table (total continuous energy loss)
void BuildDEDXTable(const G4ParticleDefinition& aParticleType);
//----------------------------------------------
// public functions .........................
// get the number of processes contributing to the cont.energy loss
static G4int GetNUMBEROFPROCESSES() { return NUMBEROFPROCESSES; };
// set the number of processes contributing to the cont.energy loss
static void SetNUMBEROFPROCESSES(G4int number)
{ NUMBEROFPROCESSES=number ; };
// Increment the number of processes contributing to the cont.energy loss
static void PlusNUMBEROFPROCESSES()
{ NUMBEROFPROCESSES++ ; };
// decrement the number of processes contributing to the cont.energy loss
static void MinusNUMBEROFPROCESSES()
{ NUMBEROFPROCESSES-- ; };
//*****************************************************************************
//
G4double GetConstraints(const G4DynamicParticle *aParticle,
G4Material *aMaterial);
G4double GetLossWithFluct(const G4DynamicParticle *aParticle,
G4Material *aMaterial) ;
protected:
G4PhysicsTable* theLossTable ;
static G4PhysicsTable* theDEDXmuplusTable ;
static G4PhysicsTable* theDEDXmuminusTable ;
static G4PhysicsTable* theRangemuplusTable ;
static G4PhysicsTable* theRangemuminusTable ;
static G4PhysicsTable* theInverseRangemuplusTable ;
static G4PhysicsTable* theInverseRangemuminusTable ;
static G4PhysicsTable* theLabTimemuplusTable ;
static G4PhysicsTable* theLabTimemuminusTable ;
static G4PhysicsTable* theProperTimemuplusTable ;
static G4PhysicsTable* theProperTimemuminusTable ;
static G4PhysicsTable* themuplusRangeCoeffATable;
static G4PhysicsTable* themuplusRangeCoeffBTable;
static G4PhysicsTable* themuplusRangeCoeffCTable;
static G4PhysicsTable* themuminusRangeCoeffATable;
static G4PhysicsTable* themuminusRangeCoeffBTable;
static G4PhysicsTable* themuminusRangeCoeffCTable;
static G4double CutInmupluslossTable;
static G4double CutInmuminuslossTable;
// processes inherited from G4IMuEnergyLoss
// register themselves in the static array Recorder
// nb of contributing processes = NUMBEROFPROCESSES
static G4int NUMBEROFPROCESSES ;
static G4PhysicsTable** RecorderOfmuplusProcess;
static G4PhysicsTable** RecorderOfmuminusProcess;
static G4int CounterOfmuplusProcess ;
static G4int CounterOfmuminusProcess ;
G4double RTable,LOGRTable; // LOGRTable=log(HighestKineticEnergy
// /LowestKineticEnergy)/TotBin
// RTable = exp(LOGRTable)
// cut in range
G4double CutInRange ;
// last cut in range
G4double lastCutInRange ;
// particle mass
G4double ParticleMass;
G4double BIGSTEP ;
private:
// private functions ..................................
void BuildRangeTable(const G4ParticleDefinition& aParticleType);
void BuildInverseRangeTable(
const G4ParticleDefinition& aParticleType);
void BuildTimeTables(const G4ParticleDefinition& aParticleType);
void BuildLabTimeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
void BuildProperTimeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
void InvertRangeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
void BuildRangeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
G4double LabTimeIntLog(G4PhysicsVector* physicsVector,G4int nbin);
G4double ProperTimeIntLog(G4PhysicsVector* physicsVector,G4int nbin);
G4double RangeIntLin(G4PhysicsVector* physicsVector,G4int nbin);
G4double RangeIntLog(G4PhysicsVector* physicsVector,G4int nbin);
void BuildRangeCoeffATable(const G4ParticleDefinition& aParticleType);
void BuildRangeCoeffBTable(const G4ParticleDefinition& aParticleType);
void BuildRangeCoeffCTable(const G4ParticleDefinition& aParticleType);
private:
G4PhysicsTable* theDEDXTable;
G4PhysicsTable* theRangeTable;
G4PhysicsTable* theInverseRangeTable;
G4PhysicsTable* theLabTimeTable;
G4PhysicsTable* theProperTimeTable;
G4PhysicsTable** RecorderOfProcess;
G4int CounterOfProcess;
// private data members ...............................
// fdEdx=(-dE/dx)
// computed in GetConstraints at every call;
G4double fdEdx;
// fRangeNow is the actual range of the particle
// computed in GetConstraints
G4double fRangeNow ;
// fMeanLoss is the energyloss without fluctuation
// computed in AlongStepDoIt ;
G4double fMeanLoss ;
// EnergyBinNumber,RangeCoeffA,... are needed to compute range
G4int EnergyBinNumber ;
G4double RangeCoeffA,RangeCoeffB,RangeCoeffC ;
//................................................................
G4PhysicsTable* theRangeCoeffATable;
G4PhysicsTable* theRangeCoeffBTable;
G4PhysicsTable* theRangeCoeffCTable;
// dToverTini is the maximum allowed deltarange/range in one Step
// ( set in this class for the moment)
const G4double dToverTini;
// LowestKineticEnergy = lower limit of particle kinetic energy
// HighestKineticEnergy = upper limit of particle kinetic energy
// TotBin = number of bins
// ---------in the energy loss/range tables-------------------
const G4double LowestKineticEnergy;
const G4double HighestKineticEnergy;
G4int TotBin;// number of bins in table, calculated in BuildPhysicsTable
// from LowestKineticEnergy,HighestKineticEnergy and
// dToverTini
// variables for the integration routines
G4double taulow,tauhigh,ltaulow,ltauhigh;
// cuts in kinetic energy ........
G4double* ParticleCutInKineticEnergy ;
G4double ParticleCutInKineticEnergyNow ;
// ...............
const G4Electron* theElectron;
const G4Positron* thePositron;
const G4MuonPlus* theMuonPlus;
const G4MuonMinus* theMuonMinus;
// data members to speed up the fluctuation calculation
G4Material *lastMaterial ;
G4double f1Fluct,f2Fluct,e1Fluct,e2Fluct,rateFluct,ipotFluct;
G4double e1LogFluct,e2LogFluct,ipotLogFluct;
const G4double MaxExcitationNumber ;
const G4double probLimFluct ;
const long nmaxDirectFluct,nmaxCont1,nmaxCont2 ;
};
#include "G4IMuEnergyLoss.icc"
#endif
@@ -0,0 +1,146 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuEnergyLoss.icc,v 2.1 1998/08/23 11:50:51 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4IMuEnergyLoss physics process ------------
// by Laszlo Urban, September 1997
// ***************************************************************
// It is the implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of muons.
// ***************************************************************
// correction for KineticEnergy< LowestKineticEnergy by L.Urban on 27/11/97
// corrections by L. Urban on 27/05/98 ( other corrs come soon!)
// ---------------------------------------------------------------
inline G4double G4IMuEnergyLoss::GetConstraints(const G4DynamicParticle *aParticle,
G4Material *aMaterial)
{
// returns the Step limit
// dToverTini is the max. allowed relative range loss in one Step
// it calculates dEdx and the range as well....
G4double KineticEnergy,StepLimit;
const G4double BigStep = DBL_MAX ;
G4bool isOutRange ;
G4int index,bin ;
if(aParticle->GetDefinition()->GetPDGCharge()>0.)
{
theDEDXTable = theDEDXmuplusTable ;
theRangeTable = theRangemuplusTable ;
theRangeCoeffATable=themuplusRangeCoeffATable ;
theRangeCoeffBTable=themuplusRangeCoeffBTable ;
theRangeCoeffCTable=themuplusRangeCoeffCTable ;
}
else
{
theDEDXTable = theDEDXmuminusTable ;
theRangeTable = theRangemuminusTable ;
theRangeCoeffATable=themuminusRangeCoeffATable ;
theRangeCoeffBTable=themuminusRangeCoeffBTable ;
theRangeCoeffCTable=themuminusRangeCoeffCTable ;
}
// min.stepsize = p*CutInRange at energy , where range=p*CutInRange
// random steplimit.........................
const G4double p=1. , cc=p*CutInRange ;
const G4double c1=dToverTini , c2=(1.-2.*dToverTini)*cc ,
c3=dToverTini*cc*cc ;
const G4double rangelim=1.5*cc ;
const G4double Thigh = 0.9*HighestKineticEnergy ;
const G4double alfa = 0.05 , alfa1 = 1.-alfa , alfa2 = 2.*alfa ;
KineticEnergy = aParticle->GetKineticEnergy();
bin = G4int(log(KineticEnergy/LowestKineticEnergy)/LOGRTable) ;
EnergyBinNumber = bin ;
index = aMaterial->GetIndex() ;
if( KineticEnergy < LowestKineticEnergy )
{
fdEdx = sqrt(KineticEnergy/LowestKineticEnergy)*
(*theDEDXTable)(index)->GetValue(LowestKineticEnergy,isOutRange) ;
fRangeNow = sqrt(KineticEnergy/LowestKineticEnergy)*
(*theRangeTable)(index)->GetValue(LowestKineticEnergy,isOutRange) ;
StepLimit = fRangeNow ;
}
else
{
if ( KineticEnergy > HighestKineticEnergy )
StepLimit = BigStep ;
else
{
fdEdx = (*theDEDXTable)(index)->
GetValue(KineticEnergy,isOutRange) ;
RangeCoeffA = (*(*theRangeCoeffATable)(index))(EnergyBinNumber) ;
RangeCoeffB = (*(*theRangeCoeffBTable)(index))(EnergyBinNumber) ;
RangeCoeffC = (*(*theRangeCoeffCTable)(index))(EnergyBinNumber) ;
fRangeNow = (RangeCoeffA*KineticEnergy+RangeCoeffB)
*KineticEnergy+RangeCoeffC ;
// vacuum ?
if(fRangeNow>=BigStep)
StepLimit = BigStep ;
else
{
// new method to compute the (random) Step limit ..............
if(fRangeNow>cc)
{
StepLimit = c1*fRangeNow+c2+c3/fRangeNow ;
// randomise this value
StepLimit = cc + (StepLimit-cc)*G4UniformRand() ;
if(StepLimit > fRangeNow) StepLimit = fRangeNow ;
}
else
StepLimit = fRangeNow ;
}
}
}
return StepLimit ;
}
inline G4double G4IMuEnergyLoss::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double Step =
GetConstraints(track.GetDynamicParticle(),track.GetMaterial()) ;
if((Step>0.0)&&(Step<currentMinimumStep))
currentMinimumStep = Step ;
return Step ;
}
inline G4bool G4IMuEnergyLoss::IsApplicable(const G4ParticleDefinition&
particle)
{
return ( (&particle == (const G4ParticleDefinition *)theMuonPlus)
||(&particle == (const G4ParticleDefinition *)theMuonMinus)
);
}
@@ -0,0 +1,148 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuIonisation.hh,v 2.1 1998/08/23 11:50:52 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4IMuIonisation physics process ------------
// by Laszlo Urban, September 1997
// ------------------------------------------------------------
// It is the implementation of the NEW IONISATION
// PROCESS. ( delta rays + continuous energy loss)
// It calculates the ionisation for muons.
// ************************************************************
//
// ------------------------------------------------------------
#ifndef G4IMuIonisation_h
#define G4IMuIonisation_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4IMuEnergyLoss.hh"
#include "globals.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Electron.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsLinearVector.hh"
class G4IMuIonisation : public G4IMuEnergyLoss
{
public:
G4IMuIonisation(const G4String& processName = "IMuIonisation");
~G4IMuIonisation();
G4bool IsApplicable(const G4ParticleDefinition&);
private:
// hide assignment operator
G4IMuIonisation & operator=(const G4IMuIonisation &right);
G4IMuIonisation(const G4IMuIonisation&);
public:
// post Step functions .......................................
G4double PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
) ;
G4VParticleChange *PostStepDoIt(
const G4Track& track,
const G4Step& Step ) ;
void BuildLossTable(const G4ParticleDefinition& aParticleType);
void BuildLambdaTable(const G4ParticleDefinition& aParticleType);
void BuildPhysicsTable(const G4ParticleDefinition& aParticleType);
virtual G4double ComputeMicroscopicCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber);
private:
void BuildNlambdaTable(const G4ParticleDefinition& aParticleType) ;
void BuildNlambdaVector(const G4ParticleDefinition& aParticleType,
G4int materialIndex,
G4PhysicsLogVector* nlambdaVector) ;
void BuildInverseNlambdaTable(
const G4ParticleDefinition& aParticleType) ;
void InvertNlambdaVector(const G4ParticleDefinition& aParticleType,
G4int materialIndex,
G4PhysicsLogVector* nlambdaVector) ;
void BuildCoeffATable(const G4ParticleDefinition& aParticleType) ;
void BuildCoeffBTable(const G4ParticleDefinition& aParticleType) ;
void BuildCoeffCTable(const G4ParticleDefinition& aParticleType) ;
void TestOfInversion(const G4ParticleDefinition& aParticleType,
G4int printflag) ;
// private data members ...............................
G4PhysicsTable* theMeanFreePathTable;
G4PhysicsTable* theNlambdaTable;
G4PhysicsTable* theInverseNlambdaTable;
G4PhysicsTable* theCoeffATable;
G4PhysicsTable* theCoeffBTable;
G4PhysicsTable* theCoeffCTable;
// LowestKineticEnergy = lower limit of particle kinetic energy
// HighestKineticEnergy = upper limit of particle kinetic energy
// TotBin = number of bins
// ---------in the energy ionisation loss table-------------------
const G4double LowestKineticEnergy;
const G4double HighestKineticEnergy;
G4int TotBin;
// cut in range
G4double CutInRange ;
G4double lastCutInRange ;
// particles , cuts in kinetic energy ........
const G4Electron* theElectron;
const G4MuonPlus* theMuonPlus;
const G4MuonMinus* theMuonMinus;
const G4double* ParticleCutInKineticEnergy;
const G4double* DeltaCutInKineticEnergy ;
G4double ParticleCutInKineticEnergyNow ;
G4double DeltaCutInKineticEnergyNow ;
G4int NumberOfBuildPhysicsTableCalls ;
};
#include "G4IMuIonisation.icc"
#endif
@@ -0,0 +1,151 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuIonisation.icc,v 2.1 1998/08/23 11:50:52 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4IMuIonisation physics process -------------
// by Laszlo Urban, September 1997
// ---------------------------------------------------------------
// It is the implementation of the NEW IONISATION PROCESS.
// It calculates the ionisation of muons.
// ***************************************************************
// 24/11/97: correction on MeanFreePath for KinEnergy > HighestLimit
// ---------------------------------------------------------------
inline G4double G4IMuIonisation::PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
)
{// get particle,particle type,kin.energy,material,mat.index
const G4double eps=1.e-2 ;
const G4double Tfac=0.95,Tfac1=1.-Tfac ;
G4double nl,nll,nlold,range,rangeold,rangenext,
dEdx,KineticEnergyOld,KineticEnergyNext,value;
G4bool isOut;
const G4DynamicParticle* particle = track.GetDynamicParticle();
const G4ParticleDefinition* particletype = particle->GetDefinition() ;
G4double KineticEnergy = particle->GetKineticEnergy();
G4Material* material = track.GetMaterial();
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable();
G4int materialindex = material->GetIndex();
nl = (*theNlambdaTable)[materialindex]->
GetValue(KineticEnergy,isOut);
range = G4EnergyLossTables::GetPreciseRangeFromEnergy(particletype,
KineticEnergy,material) ;
if ( (previousStepSize <=0.0) || (theNumberOfInteractionLengthLeft<=0.0)) {
// beggining of tracking (or just after DoIt of this process)
ResetNumberOfInteractionLengthLeft();
} else {
// subtract NumberOfInteractionLengthLeft
if(previousStepSize/range < eps)
{
nll = (*theNlambdaTable)[materialindex]->
GetValue(Tfac*KineticEnergy,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(particletype,
KineticEnergy,
material) ;
nlold = nl + dEdx*previousStepSize*(nl-nll)/
(Tfac1*KineticEnergy) ;
}
else
{
rangeold = range + previousStepSize ;
KineticEnergyOld = G4EnergyLossTables::GetPreciseEnergyFromRange(
particletype,
rangeold,material);
nlold = (*theNlambdaTable)[materialindex]->
GetValue(KineticEnergyOld,isOut);
if(nlold < nl)
{
if(verboseLevel>2)
{
G4cout << "G4IMuIonisation PostStepGPIL : Nlambda has been" <<
" increased at update.Nlambda old/new :" << nlold <<
" " << nl << endl;
G4cout << "(theNumberOfInteractionLengthLeft has been increased!)" << endl
;
G4cout << " correction : Nlambda old=new ........." << endl;
}
//corr. of num errror
nlold = nl ;
}
}
theNumberOfInteractionLengthLeft -= nlold-nl ;
if(theNumberOfInteractionLengthLeft<perMillion)
theNumberOfInteractionLengthLeft=0.;
}
// condition is set to "Not Forced"
*condition = NotForced;
if(nl <= theNumberOfInteractionLengthLeft)
{
value = BIGSTEP ;
}
else
{
if(theNumberOfInteractionLengthLeft/nl < eps)
{
nll = (*theNlambdaTable)[materialindex]->
GetValue(Tfac*KineticEnergy,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(particletype,
KineticEnergy,
material) ;
value = theNumberOfInteractionLengthLeft*Tfac1*KineticEnergy/(dEdx*(nl-nll))
;
}
else
{
KineticEnergyNext = (*theInverseNlambdaTable)[materialindex]->
GetValue(nl-theNumberOfInteractionLengthLeft,isOut);
rangenext = G4EnergyLossTables::GetPreciseRangeFromEnergy(particletype,
KineticEnergyNext,material);
value = range - rangenext ;
if(range<rangenext)
{
if(verboseLevel>2)
{
G4cout << "G4IMuIonisation PostStepGPIL: Step < 0.!, Step=" << value << endl
;
G4cout << "range,rangenext:" << range << " " << rangenext << endl ;
G4cout << "correction : rangenext=range ....." << endl;
}
//corr. of num error
rangenext = range ;
value = range - rangenext ;
}
}
}
return value;
}
inline G4bool G4IMuIonisation::IsApplicable(
const G4ParticleDefinition& particle)
{
return ( (&particle == (const G4ParticleDefinition *)theMuonPlus)
||(&particle == (const G4ParticleDefinition *)theMuonMinus)
);
}
@@ -0,0 +1,188 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuPairProduction.hh,v 2.1 1998/08/23 11:50:52 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4IMuPairProduction physics process ---------
// by Laszlo Urban, May 1998
// ************************************************************
#ifndef G4IMuPairproduction_h
#define G4IMuPairproduction_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4IMuEnergyLoss.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4MuonMinus.hh"
#include "G4MuonPlus.hh"
#include "G4OrderedTable.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsLogVector.hh"
class G4IMuPairProduction : public G4IMuEnergyLoss
{
public:
G4IMuPairProduction(const G4String& processName = "IMuPairProduction");
~G4IMuPairProduction();
G4bool IsApplicable(const G4ParticleDefinition&);
private:
G4IMuPairProduction & operator=(const G4IMuPairProduction &right);
G4IMuPairProduction(const G4IMuPairProduction&);
public:
// post Step functions .......................................
G4double PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
) ;
G4VParticleChange *PostStepDoIt(
const G4Track& track,
const G4Step& Step ) ;
void BuildLossTable(const G4ParticleDefinition& ParticleType);
void BuildLambdaTable(const G4ParticleDefinition& ParticleType);
void BuildPhysicsTable(const G4ParticleDefinition& ParticleType);
protected:
inline G4double ComputeMeanFreePath( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
void ComputePartialSumSigma( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
virtual G4double ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double ElectronEnergyCut,
G4double PositronEnergyCut);
G4double ComputeDDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double PairEnergy,
G4double asymmetry);
G4double ComputeDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double PairEnergy);
void MakeSamplingTables( const G4ParticleDefinition* ParticleType );
private:
void BuildNlambdaTable(const G4ParticleDefinition& aParticleType) ;
void BuildNlambdaVector(const G4ParticleDefinition& aParticleType,
G4int materialIndex,
G4PhysicsLogVector* nlambdaVector) ;
void BuildInverseNlambdaTable(
const G4ParticleDefinition& aParticleType) ;
void InvertNlambdaVector(const G4ParticleDefinition& aParticleType,
G4int materialIndex,
G4PhysicsLogVector* nlambdaVector) ;
void BuildCoeffATable(const G4ParticleDefinition& aParticleType) ;
void BuildCoeffBTable(const G4ParticleDefinition& aParticleType) ;
void BuildCoeffCTable(const G4ParticleDefinition& aParticleType) ;
void TestOfInversion(const G4ParticleDefinition& aParticleType,
G4int printflag) ;
G4double ComputePairLoss( const G4ParticleDefinition* ParticleType,
G4double Z,G4double T,G4double ElectronCut,
G4double PositronCut);
G4Element* SelectRandomAtom(G4Material* aMaterial) const;
private:
G4PhysicsTable* theMeanFreePathTable ;
static G4PhysicsTable* themuplusLambdaTable ;
static G4PhysicsTable* themuminusLambdaTable ;
G4OrderedTable PartialSumSigma; // partial sum of total crosssection
G4PhysicsTable* theNlambdaTable;
G4PhysicsTable* theInverseNlambdaTable;
G4PhysicsTable* theCoeffATable;
G4PhysicsTable* theCoeffBTable;
G4PhysicsTable* theCoeffCTable;
const G4double LowestKineticEnergy; // low energy limit of the crossection formula
const G4double HighestKineticEnergy; // high energy limit of the crossection formula
G4int TotBin; // number of bins in the tables
G4double MinKineticEnergy; //process is ignored if T<MinKineticEnergy
G4double MinCutValue; //protection against divergencies
G4double CutInRange;
const G4Electron* theElectron;
const G4Positron* thePositron;
const G4MuonMinus* theMuonMinus;
const G4MuonPlus* theMuonPlus;
const G4double* ElectronCutInKineticEnergy;
const G4double* PositronCutInKineticEnergy;
const G4double* MuonMinusCutInKineticEnergy;
const G4double* MuonPlusCutInKineticEnergy;
const G4double* ParticleCutInKineticEnergy;
G4double ElectronCutInKineticEnergyNow;
G4double PositronCutInKineticEnergyNow;
G4double MuonMinusCutInKineticEnergyNow;
G4double MuonPlusCutInKineticEnergyNow;
G4double ParticleCutInKineticEnergyNow;
// tables for sampling ..............
static G4int nzdat,ntdat,NBIN ;
static G4double zdat[5],tdat[8] ;
static G4double ya[1000],proba[5][8][1000] ;
G4int NumberOfBuildPhysicsTableCalls ;
};
#include "G4IMuPairProduction.icc"
#endif
@@ -0,0 +1,180 @@
// This code implementation is the intellectual property of
// the RD44 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: G4IMuPairProduction.icc,v 2.1 1998/08/23 11:50:53 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4IMuPairProduction physics process ---------
// by Laszlo Urban, May 1998
// ***************************************************************
inline G4double G4IMuPairProduction::PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
)
{// get particle,particle type,kin.energy,material,mat.index
const G4double eps=1.e-2 ;
const G4double Tfac=0.95,Tfac1=1.-Tfac ;
G4double nl,nll,nlold,range,rangeold,rangenext,
dEdx,KineticEnergyOld,KineticEnergyNext,value;
G4bool isOut;
const G4DynamicParticle* particle = track.GetDynamicParticle();
const G4ParticleDefinition* particletype = particle->GetDefinition() ;
G4double KineticEnergy = particle->GetKineticEnergy();
G4Material* material = track.GetMaterial();
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable();
G4int materialindex = material->GetIndex();
nl = (*theNlambdaTable)[materialindex]->
GetValue(KineticEnergy,isOut);
// if ( nl == 0.)
// {
// value = BIGSTEP ;
// return value ;
// }
range = G4EnergyLossTables::GetPreciseRangeFromEnergy(particletype,
KineticEnergy,material) ;
if ( (previousStepSize <=0.0) || (theNumberOfInteractionLengthLeft<=0.0)) {
// beggining of tracking (or just after DoIt of this process)
ResetNumberOfInteractionLengthLeft();
} else {
// subtract NumberOfInteractionLengthLeft
if(previousStepSize/range < eps)
{
nll = (*theNlambdaTable)[materialindex]->
GetValue(Tfac*KineticEnergy,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(particletype,
KineticEnergy,
material) ;
nlold = nl + dEdx*previousStepSize*(nl-nll)/
(Tfac1*KineticEnergy) ;
}
else
{
rangeold = range + previousStepSize ;
KineticEnergyOld = G4EnergyLossTables::GetPreciseEnergyFromRange(
particletype,
rangeold,material);
nlold = (*theNlambdaTable)[materialindex]->
GetValue(KineticEnergyOld,isOut);
if(nlold < nl)
{
if(verboseLevel>2)
{
G4cout << "G4IMuPairProduction PostStepGPIL : Nlambda has been" <<
" increased at update.Nlambda old/new :" << nlold <<
" " << nl << endl;
G4cout << "(theNumberOfInteractionLengthLeft has been increased!)" << endl
;
G4cout << " correction : Nlambda old=new ........." << endl;
}
//corr. of num errror
nlold = nl ;
}
}
theNumberOfInteractionLengthLeft -= nlold-nl ;
if(theNumberOfInteractionLengthLeft<perMillion)
theNumberOfInteractionLengthLeft=0.;
}
// condition is set to "Not Forced"
*condition = NotForced;
if(nl <= theNumberOfInteractionLengthLeft)
{
value = BIGSTEP ;
}
else
{
if(theNumberOfInteractionLengthLeft/nl < eps)
{
nll = (*theNlambdaTable)[materialindex]->
GetValue(Tfac*KineticEnergy,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(particletype,
KineticEnergy,
material) ;
value = theNumberOfInteractionLengthLeft*Tfac1*KineticEnergy/(dEdx*(nl-nll))
;
}
else
{
KineticEnergyNext = (*theInverseNlambdaTable)[materialindex]->
GetValue(nl-theNumberOfInteractionLengthLeft,isOut);
rangenext = G4EnergyLossTables::GetPreciseRangeFromEnergy(particletype,
KineticEnergyNext,material);
value = range - rangenext ;
if(range<rangenext)
{
if(verboseLevel>2)
{
G4cout << "G4IMuPairProduction PostStepGPIL: Step < 0.!, Step=" << value << endl
;
G4cout << "range,rangenext:" << range << " " << rangenext << endl ;
G4cout << "correction : rangenext=range ....." << endl;
}
//corr. of num error
rangenext = range ;
value = range - rangenext ;
}
}
}
return value;
}
inline G4double G4IMuPairProduction::ComputeMeanFreePath(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
{
const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double ElectronEnergyCut = (G4Electron::GetCutsInEnergy())[aMaterial->GetIndex()];
G4double PositronEnergyCut = (G4Positron::GetCutsInEnergy())[aMaterial->GetIndex()];
const G4double BigPath= DBL_MAX;
G4double SIGMA = 0 ;
for ( G4int i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
SIGMA += theAtomNumDensityVector[i] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(i)->GetZ(),
ElectronEnergyCut,PositronEnergyCut );
}
return SIGMA<=0.0 ? BigPath : 1./SIGMA ;
}
inline G4bool G4IMuPairProduction::IsApplicable(
const G4ParticleDefinition& particle)
{
return( (&particle == (const G4ParticleDefinition *)theMuonMinus)
||(&particle == (const G4ParticleDefinition *)theMuonPlus)
) ;
}
@@ -0,0 +1,140 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuBremsstrahlung.hh,v 2.4 1998/10/27 12:24:39 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuBremsstrahlung physics process ---------
// by Laszlo Urban, September 1997
// ************************************************************
#ifndef G4MuBremsstrahlung_h
#define G4MuBremsstrahlung_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4MuEnergyLoss.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Gamma.hh"
#include "G4MuonMinus.hh"
#include "G4MuonPlus.hh"
#include "G4OrderedTable.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsLogVector.hh"
class G4MuBremsstrahlung : public G4MuEnergyLoss
{
public:
G4MuBremsstrahlung(const G4String& processName = "MuBrems");
~G4MuBremsstrahlung();
G4bool IsApplicable(const G4ParticleDefinition&);
void SetPhysicsTableBining(G4double lowE, G4double highE, G4int nBins);
void BuildPhysicsTable(const G4ParticleDefinition& ParticleType);
void BuildLossTable(const G4ParticleDefinition& ParticleType);
void BuildLambdaTable(const G4ParticleDefinition& ParticleType);
void PrintInfoDefinition() ;
G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition ) ;
G4VParticleChange *PostStepDoIt(const G4Track& track,
const G4Step& Step ) ;
protected:
G4double ComputeMeanFreePath( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
void ComputePartialSumSigma( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
virtual G4double ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicMass,
G4double GammaEnergyCut);
virtual G4double ComputeDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicMass,
G4double GammaEnergy);
private:
G4MuBremsstrahlung & operator=(const G4MuBremsstrahlung &right);
G4MuBremsstrahlung(const G4MuBremsstrahlung&);
G4double ComputeBremLoss(const G4ParticleDefinition* ParticleType,
G4double Z,G4double A,
G4double T, G4double Cut);
G4Element* SelectRandomAtom(G4Material* aMaterial) const;
void MakeSamplingTables( const G4ParticleDefinition* ParticleType );
private:
G4PhysicsTable* theMeanFreePathTable ;
G4OrderedTable PartialSumSigma;
G4double LowestKineticEnergy;
G4double HighestKineticEnergy;
G4int TotBin;
G4double CutInRange;
const G4Gamma* theGamma;
const G4MuonMinus* theMuonMinus;
const G4MuonPlus* theMuonPlus;
const G4double* GammaCutInKineticEnergy;
const G4double* MuonMinusCutInKineticEnergy;
const G4double* MuonPlusCutInKineticEnergy;
const G4double* ParticleCutInKineticEnergy;
G4double GammaCutInKineticEnergyNow;
G4double MuonMinusCutInKineticEnergyNow;
G4double MuonPlusCutInKineticEnergyNow;
G4double ParticleCutInKineticEnergyNow;
// tables for sampling ..............
static G4int nzdat,ntdat,NBIN ;
static G4double zdat[5],adat[5],tdat[8] ;
static G4double ya[1000],proba[5][8][1000] ;
};
#include "G4MuBremsstrahlung.icc"
#endif
@@ -0,0 +1,80 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuBremsstrahlung.icc,v 2.2 1998/10/27 12:24:40 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuBremsstrahlung physics process ---------
// by Laszlo Urban, September 1997
// ***************************************************************
inline G4double G4MuBremsstrahlung::GetMeanFreePath(const G4Track& trackData,
G4double previousStepSize,
G4ForceCondition* condition)
{
const G4DynamicParticle* aDynamicParticle;
G4Material* aMaterial;
G4double MeanFreePath;
G4bool isOutRange ;
*condition = NotForced ;
aDynamicParticle = trackData.GetDynamicParticle();
aMaterial = trackData.GetMaterial();
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
if (KineticEnergy < LowestKineticEnergy)
MeanFreePath = DBL_MAX ;
else {
if (KineticEnergy > HighestKineticEnergy)
KineticEnergy = 0.99*HighestKineticEnergy ;
MeanFreePath = (*theMeanFreePathTable)(aMaterial->GetIndex())->
GetValue( KineticEnergy, isOutRange );
}
return MeanFreePath;
}
inline G4double G4MuBremsstrahlung::ComputeMeanFreePath(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
{
const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
const G4double* theAtomNumDensityVector =
aMaterial->GetAtomicNumDensityVector();
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
G4double SIGMA = 0 ;
for ( G4int i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
SIGMA += theAtomNumDensityVector[i] *
ComputeMicroscopicCrossSection(
ParticleType, KineticEnergy,
(*theElementVector)(i)->GetZ(),
(*theElementVector)(i)->GetA(),
GammaEnergyCut );
}
return SIGMA<=0.0 ? DBL_MAX : 1./SIGMA ;
}
inline G4bool G4MuBremsstrahlung::IsApplicable(
const G4ParticleDefinition& particle)
{
return( (&particle == (const G4ParticleDefinition *)theMuonMinus)
||(&particle == (const G4ParticleDefinition *)theMuonPlus)
) ;
}
@@ -0,0 +1,278 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuEnergyLoss.hh,v 2.7 1998/10/27 12:24:38 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// -------------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4MuEnergyLoss physics process -----------
// by Laszlo Urban, September 1997
// ********************************************************************
// It is the implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the continuous energy loss for muons.
// Processes giving contribution to the continuous loss :
// ionisation (= cont.ion.loss + delta ray production)
// bremsstrahlung
// e+e- pair production
// can be added more easily ..........
// This class creates static muplus/muminus dE/dx and range tables ,
// which tables can be used by other processes.
// ************************************************************
// some corrections by L.Urban on 27/05/98 , (but other corrections come soon!)
// cleanup L.Urban on 23/10/98
// ------------------------------------------------------------
#ifndef G4MuEnergyLoss_h
#define G4MuEnergyLoss_h 1
#include "G4ios.hh"
#include <fstream.h>
#include <iomanip.h>
#include "globals.hh"
#include "Randomize.hh"
#include "G4VContinuousDiscreteProcess.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4VParticleChange.hh"
#include "globals.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4MuonMinus.hh"
#include "G4MuonPlus.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsLinearVector.hh"
class G4EnergyLossMessenger ;
class G4MuEnergyLoss : public G4VContinuousDiscreteProcess
{
public:
G4MuEnergyLoss(const G4String& );
~G4MuEnergyLoss();
G4bool IsApplicable(const G4ParticleDefinition&);
void BuildDEDXTable(const G4ParticleDefinition& aParticleType);
G4double GetContinuousStepLimit(
const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) ;
G4VParticleChange* AlongStepDoIt(const G4Track& track ,const G4Step& Step) ;
virtual G4double GetMeanFreePath( const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
) = 0 ;
virtual G4VParticleChange* PostStepDoIt(
const G4Track& track,const G4Step& Step) = 0 ;
protected:
private:
// hide assignment operator
G4MuEnergyLoss(G4MuEnergyLoss &);
G4MuEnergyLoss & operator=(const G4MuEnergyLoss &right);
void BuildRangeTable(const G4ParticleDefinition& aParticleType);
void BuildInverseRangeTable(
const G4ParticleDefinition& aParticleType);
void BuildTimeTables(const G4ParticleDefinition& aParticleType);
void BuildLabTimeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
void BuildProperTimeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
void InvertRangeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
void BuildRangeVector(G4int materialIndex,
G4PhysicsLogVector* rangeVector);
G4double LabTimeIntLog(G4PhysicsVector* physicsVector,G4int nbin);
G4double ProperTimeIntLog(G4PhysicsVector* physicsVector,G4int nbin);
G4double RangeIntLin(G4PhysicsVector* physicsVector,G4int nbin);
G4double RangeIntLog(G4PhysicsVector* physicsVector,G4int nbin);
void BuildRangeCoeffATable(const G4ParticleDefinition& aParticleType);
void BuildRangeCoeffBTable(const G4ParticleDefinition& aParticleType);
void BuildRangeCoeffCTable(const G4ParticleDefinition& aParticleType);
G4double GetConstraints(const G4DynamicParticle *aParticle,
G4Material *aMaterial);
G4double GetLossWithFluct(const G4DynamicParticle *aParticle,
G4Material *aMaterial,G4double MeanLoss) ;
// =====================================================================
public:
protected:
G4PhysicsTable* theLossTable ;
// cut in range
G4double CutInRange ;
// last cut in range
G4double lastCutInRange ;
// particle mass
G4double ParticleMass;
private:
G4PhysicsTable* theDEDXTable;
G4PhysicsTable* theRangeTable;
G4PhysicsTable* theInverseRangeTable;
G4PhysicsTable* theLabTimeTable;
G4PhysicsTable* theProperTimeTable;
G4PhysicsTable** RecorderOfProcess;
G4int CounterOfProcess;
G4PhysicsTable* theRangeCoeffATable;
G4PhysicsTable* theRangeCoeffBTable;
G4PhysicsTable* theRangeCoeffCTable;
// fdEdx=(-dE/dx)
// computed in GetConstraints at every call;
G4double fdEdx;
// fRangeNow is the actual range of the particle
// computed in GetConstraints
G4double fRangeNow ;
// EnergyBinNumber,RangeCoeffA,... are needed to compute range
G4int EnergyBinNumber ;
G4double RangeCoeffA,RangeCoeffB,RangeCoeffC ;
// LowestKineticEnergy = lower limit of particle kinetic energy
// HighestKineticEnergy = upper limit of particle kinetic energy
// TotBin = number of bins
// ---------in the energy loss/range tables-------------------
G4double LowestKineticEnergy;
G4double HighestKineticEnergy;
G4int TotBin;// number of bins in table, calculated in BuildPhysicsTable
// from LowestKineticEnergy,HighestKineticEnergy and
// dToverTini
G4double RTable,LOGRTable; // LOGRTable=log(HighestKineticEnergy
// /LowestKineticEnergy)/TotBin
// RTable = exp(LOGRTable)
// variables for the integration routines
G4double taulow,tauhigh,ltaulow,ltauhigh;
// cuts in kinetic energy ........
G4double* ParticleCutInKineticEnergy ;
G4double ParticleCutInKineticEnergyNow ;
const G4Electron* theElectron;
const G4Positron* thePositron;
const G4MuonPlus* theMuonPlus;
const G4MuonMinus* theMuonMinus;
// data members to speed up the fluctuation calculation
G4int imat ;
G4Material *lastMaterial ;
G4double f1Fluct,f2Fluct,e1Fluct,e2Fluct,rateFluct,ipotFluct;
G4double e1LogFluct,e2LogFluct,ipotLogFluct;
const G4double MaxExcitationNumber ;
const G4double probLimFluct ;
const long nmaxDirectFluct,nmaxCont1,nmaxCont2 ;
// static part of the class
public:
static G4int GetNbOfProcesses() { return NbOfProcesses; };
static void SetNbOfProcesses(G4int number){ NbOfProcesses=number ; };
static void PlusNbOfProcesses() { NbOfProcesses++ ; };
static void MinusNbOfProcesses() { NbOfProcesses-- ; };
static void SetRndmStep (G4bool value) {rndmStepFlag = value;}
static void SetEnlossFluc (G4bool value) {EnlossFlucFlag = value;}
static void SetStepFunction (G4double c1, G4double c2)
{dRoverRange = c1; finalRange = c2;}
protected:
static G4PhysicsTable* theDEDXmuplusTable ;
static G4PhysicsTable* theDEDXmuminusTable ;
static G4PhysicsTable* theRangemuplusTable ;
static G4PhysicsTable* theRangemuminusTable ;
static G4PhysicsTable* theInverseRangemuplusTable ;
static G4PhysicsTable* theInverseRangemuminusTable ;
static G4PhysicsTable* theLabTimemuplusTable ;
static G4PhysicsTable* theLabTimemuminusTable ;
static G4PhysicsTable* theProperTimemuplusTable ;
static G4PhysicsTable* theProperTimemuminusTable ;
static G4double CutInmupluslossTable;
static G4double CutInmuminuslossTable;
// processes inherited from G4muEnergyLoss
// register themselves in the static array Recorder
// nb of contributing processes = NbOfProcesses
static G4int NbOfProcesses ;
static G4PhysicsTable** RecorderOfmuplusProcess;
static G4PhysicsTable** RecorderOfmuminusProcess;
static G4int CounterOfmuplusProcess ;
static G4int CounterOfmuminusProcess ;
private:
static G4PhysicsTable* themuplusRangeCoeffATable;
static G4PhysicsTable* themuplusRangeCoeffBTable;
static G4PhysicsTable* themuplusRangeCoeffCTable;
static G4PhysicsTable* themuminusRangeCoeffATable;
static G4PhysicsTable* themuminusRangeCoeffBTable;
static G4PhysicsTable* themuminusRangeCoeffCTable;
static G4double dRoverRange; // dRoverRange is the maximum allowed
// deltarange/range in one Step
static G4double finalRange; // final step before stopping
static G4bool rndmStepFlag; // control the randomization of the step
static G4bool EnlossFlucFlag; // control the energy loss fluctuation
static G4EnergyLossMessenger* eLossMessenger;
};
#include "G4MuEnergyLoss.icc"
#endif
@@ -0,0 +1,52 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuEnergyLoss.icc,v 2.2 1998/10/27 12:24:39 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4MuEnergyLoss physics process ------------
// by Laszlo Urban, September 1997
// ***************************************************************
// It is the implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of muons.
// ***************************************************************
// correction for KineticEnergy< LowestKineticEnergy by L.Urban on 27/11/97
// corrections by L. Urban on 27/05/98 ( other corrs come soon!)
// cleanup L.Urban on 23/10/98
// ---------------------------------------------------------------
inline G4double G4MuEnergyLoss::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double Step =
GetConstraints(track.GetDynamicParticle(),track.GetMaterial()) ;
if((Step>0.0)&&(Step<currentMinimumStep))
currentMinimumStep = Step ;
return Step ;
}
inline G4bool G4MuEnergyLoss::IsApplicable(const G4ParticleDefinition&
particle)
{
return ( (&particle == (const G4ParticleDefinition *)theMuonPlus)
||(&particle == (const G4ParticleDefinition *)theMuonMinus)
);
}
@@ -0,0 +1,119 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuIonisation.hh,v 2.4 1998/10/27 12:24:39 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4MuIonisation physics process ------------
// by Laszlo Urban, September 1997
// ------------------------------------------------------------
// It is the implementation of the NEW IONISATION
// PROCESS. ( delta rays + continuous energy loss)
// It calculates the ionisation for muons.
// ************************************************************
//
// ------------------------------------------------------------
#ifndef G4MuIonisation_h
#define G4MuIonisation_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4MuEnergyLoss.hh"
#include "globals.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Electron.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsLinearVector.hh"
class G4MuIonisation : public G4MuEnergyLoss
{
public:
G4MuIonisation(const G4String& processName = "MuIoni");
~G4MuIonisation();
void SetPhysicsTableBining(G4double lowE, G4double highE, G4int nBins);
G4bool IsApplicable(const G4ParticleDefinition&);
void BuildPhysicsTable(const G4ParticleDefinition& aParticleType);
void BuildLossTable(const G4ParticleDefinition& aParticleType);
void BuildLambdaTable(const G4ParticleDefinition& aParticleType);
void PrintInfoDefinition();
G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition ) ;
G4VParticleChange *PostStepDoIt(const G4Track& track,
const G4Step& Step ) ;
protected:
virtual G4double ComputeMicroscopicCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber);
G4double ComputeDMicroscopicCrossSection(
const G4ParticleDefinition& ParticleType,
G4double KineticEnergy, G4double AtomicNumber,
G4double KnockonEnergy);
private:
// hide assignment operator
G4MuIonisation & operator=(const G4MuIonisation &right);
G4MuIonisation(const G4MuIonisation&);
private:
// private data members ...............................
G4PhysicsTable* theMeanFreePathTable;
G4double LowestKineticEnergy;
G4double HighestKineticEnergy;
G4int TotBin;
// cut in range
G4double CutInRange ;
G4double lastCutInRange ;
// particles , cuts in kinetic energy ........
const G4Electron* theElectron;
const G4MuonPlus* theMuonPlus;
const G4MuonMinus* theMuonMinus;
const G4double* ParticleCutInKineticEnergy;
const G4double* DeltaCutInKineticEnergy ;
G4double ParticleCutInKineticEnergyNow ;
G4double DeltaCutInKineticEnergyNow ;
};
#include "G4MuIonisation.icc"
#endif
@@ -0,0 +1,62 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuIonisation.icc,v 2.2 1998/10/27 12:24:39 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4MuIonisation physics process -------------
// by Laszlo Urban, September 1997
// ---------------------------------------------------------------
// It is the implementation of the NEW IONISATION PROCESS.
// It calculates the ionisation of muons.
// ***************************************************************
// 24/11/97: correction on MeanFreePath for KinEnergy > HighestLimit
// ---------------------------------------------------------------
inline G4double G4MuIonisation::GetMeanFreePath(const G4Track& trackData,
G4double previousStepSize,
G4ForceCondition* condition)
{
const G4DynamicParticle* aParticle ;
G4Material* aMaterial ;
G4double KineticEnergy,MeanFreePath;
G4bool isOutRange ;
*condition = NotForced ;
aParticle = trackData.GetDynamicParticle() ;
aMaterial = trackData.GetMaterial() ;
KineticEnergy = aParticle->GetKineticEnergy() ;
if( KineticEnergy < LowestKineticEnergy )
MeanFreePath = DBL_MAX ;
else {
if(KineticEnergy > HighestKineticEnergy)
KineticEnergy = HighestKineticEnergy;
MeanFreePath = ((*theMeanFreePathTable)(aMaterial->GetIndex()))->
GetValue(KineticEnergy,isOutRange) ;
}
return MeanFreePath ;
}
inline G4bool G4MuIonisation::IsApplicable(
const G4ParticleDefinition& particle)
{
return ( (&particle == (const G4ParticleDefinition *)theMuonPlus)
||(&particle == (const G4ParticleDefinition *)theMuonMinus)
);
}
@@ -0,0 +1,125 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuNuclearInteraction.hh,v 2.4 1998/10/27 12:24:40 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuNuclearInteraction physics process ---------
// by Laszlo Urban, May 1998
// ************************************************************
#ifndef G4MuNuclearInteraction_h
#define G4MuNuclearInteraction_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4VDiscreteProcess.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4MuonMinus.hh"
#include "G4MuonPlus.hh"
#include "G4PionZero.hh"
#include "G4OrderedTable.hh"
#include "G4PhysicsTable.hh"
#include "G4ElementTable.hh"
#include "G4PhysicsLogVector.hh"
class G4MuNuclearInteraction : public G4VDiscreteProcess
{
public:
G4MuNuclearInteraction(const G4String& processName = "MuNucl");
~G4MuNuclearInteraction();
G4bool IsApplicable(const G4ParticleDefinition&);
void SetPhysicsTableBining(G4double lowE, G4double highE, G4int nBins);
void BuildPhysicsTable(const G4ParticleDefinition& ParticleType);
void PrintInfoDefinition() ;
G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition ) ;
G4VParticleChange *PostStepDoIt(const G4Track& track,
const G4Step& Step ) ;
protected:
G4double ComputeMeanFreePath( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
void ComputePartialSumSigma( const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
virtual G4double ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicMass);
virtual G4double ComputeDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicMass,
G4double epsilon);
private:
G4MuNuclearInteraction & operator=(const G4MuNuclearInteraction &right);
G4MuNuclearInteraction(const G4MuNuclearInteraction&);
G4Element* SelectRandomAtom(G4Material* aMaterial) const;
void MakeSamplingTables( const G4ParticleDefinition* ParticleType );
private:
G4PhysicsTable* theMeanFreePathTable;
G4PhysicsTable* theCrossSectionTable ;
G4OrderedTable PartialSumSigma;
G4double LowestKineticEnergy;
G4double HighestKineticEnergy;
G4int TotBin;
//cut from R.P. Kokoulin
const G4double CutFixed ;
// for the atomic weight conversion
G4double GramPerMole ;
const G4MuonMinus* theMuonMinus;
const G4MuonPlus* theMuonPlus;
const G4PionZero* thePionZero;
// tables for sampling ..............
static G4int nzdat,ntdat,NBIN ;
static G4double zdat[5],adat[5],tdat[8] ;
static G4double ya[1000],proba[5][8][1000] ;
};
#include "G4MuNuclearInteraction.icc"
#endif
@@ -0,0 +1,80 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuNuclearInteraction.icc,v 2.2 1998/10/27 12:24:41 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuNuclearInteraction physics process ---------
// by Laszlo Urban, May 1998
// ***************************************************************
inline G4double G4MuNuclearInteraction::GetMeanFreePath(
const G4Track& trackData,
G4double previousStepSize,
G4ForceCondition* condition)
{
const G4DynamicParticle* aDynamicParticle;
G4Material* aMaterial;
G4double MeanFreePath;
G4bool isOutRange ;
*condition = NotForced ;
aDynamicParticle = trackData.GetDynamicParticle();
aMaterial = trackData.GetMaterial();
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
if (KineticEnergy < LowestKineticEnergy)
MeanFreePath = DBL_MAX ;
else {
if (KineticEnergy > HighestKineticEnergy)
KineticEnergy = 0.99*HighestKineticEnergy ;
MeanFreePath = (*theMeanFreePathTable)(aMaterial->GetIndex())->
GetValue( KineticEnergy, isOutRange );
}
return MeanFreePath;
}
inline G4double G4MuNuclearInteraction::ComputeMeanFreePath(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
{
const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
const G4double* theAtomNumDensityVector =
aMaterial->GetAtomicNumDensityVector();
G4double SIGMA = 0 ;
for ( G4int i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
SIGMA += theAtomNumDensityVector[i] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(i)->GetZ(),
(*theElementVector)(i)->GetA()) ;
}
return SIGMA<=0.0 ? DBL_MAX : 1./SIGMA ;
}
inline G4bool G4MuNuclearInteraction::IsApplicable(
const G4ParticleDefinition& particle)
{
return( (&particle == (const G4ParticleDefinition *)theMuonMinus)
||(&particle == (const G4ParticleDefinition *)theMuonPlus)
) ;
}
@@ -0,0 +1,150 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuPairProduction.hh,v 2.6 1998/10/27 12:24:40 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuPairProduction physics process ---------
// by Laszlo Urban, May 1998
// ************************************************************
#ifndef G4MuPairproduction_h
#define G4MuPairproduction_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4MuEnergyLoss.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4MuonMinus.hh"
#include "G4MuonPlus.hh"
#include "G4OrderedTable.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsLogVector.hh"
class G4MuPairProduction : public G4MuEnergyLoss
{
public:
G4MuPairProduction(const G4String& processName = "MuPairProd");
~G4MuPairProduction();
G4bool IsApplicable(const G4ParticleDefinition&);
void SetPhysicsTableBining(G4double lowE,G4double highE,G4int nBins);
void BuildPhysicsTable(const G4ParticleDefinition& ParticleType);
void BuildLossTable(const G4ParticleDefinition& ParticleType);
void BuildLambdaTable(const G4ParticleDefinition& ParticleType);
void PrintInfoDefinition();
G4double GetMeanFreePath( const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition ) ;
G4VParticleChange *PostStepDoIt(const G4Track& track,
const G4Step& Step ) ;
protected:
G4double ComputeMeanFreePath(const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
void ComputePartialSumSigma(const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial);
virtual G4double ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double ElectronEnergyCut,
G4double PositronEnergyCut);
G4double ComputeDDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double PairEnergy,
G4double asymmetry);
G4double ComputeDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double PairEnergy);
private:
G4MuPairProduction & operator=(const G4MuPairProduction &right);
G4MuPairProduction(const G4MuPairProduction&);
G4double ComputePairLoss( const G4ParticleDefinition* ParticleType,
G4double Z,G4double T,G4double ElectronCut,
G4double PositronCut);
G4Element* SelectRandomAtom(G4Material* aMaterial) const;
void MakeSamplingTables( const G4ParticleDefinition* ParticleType );
private:
G4PhysicsTable* theMeanFreePathTable ;
G4OrderedTable PartialSumSigma;
G4double LowestKineticEnergy;
G4double HighestKineticEnergy;
G4int TotBin;
G4double CutInRange;
const G4Electron* theElectron;
const G4Positron* thePositron;
const G4MuonMinus* theMuonMinus;
const G4MuonPlus* theMuonPlus;
const G4double* ElectronCutInKineticEnergy;
const G4double* PositronCutInKineticEnergy;
const G4double* MuonMinusCutInKineticEnergy;
const G4double* MuonPlusCutInKineticEnergy;
const G4double* ParticleCutInKineticEnergy;
G4double ElectronCutInKineticEnergyNow;
G4double PositronCutInKineticEnergyNow;
G4double MuonMinusCutInKineticEnergyNow;
G4double MuonPlusCutInKineticEnergyNow;
G4double ParticleCutInKineticEnergyNow;
// tables for sampling ..............
static G4int nzdat,ntdat,NBIN ;
static G4double zdat[5],tdat[8] ;
static G4double ya[1000],proba[5][8][1000] ;
};
#include "G4MuPairProduction.icc"
#endif
@@ -0,0 +1,80 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuPairProduction.icc,v 2.2 1998/10/27 12:24:40 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// ---------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuPairProduction physics process ---------
// by Laszlo Urban, May 1998
// ***************************************************************
inline G4double G4MuPairProduction::GetMeanFreePath(const G4Track& trackData,
G4double previousStepSize,
G4ForceCondition* condition)
{
const G4DynamicParticle* aDynamicParticle;
G4Material* aMaterial;
G4double MeanFreePath;
G4bool isOutRange ;
*condition = NotForced ;
aDynamicParticle = trackData.GetDynamicParticle();
aMaterial = trackData.GetMaterial();
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
if (KineticEnergy < LowestKineticEnergy)
MeanFreePath = DBL_MAX ;
else {
if (KineticEnergy > HighestKineticEnergy)
KineticEnergy = 0.99*HighestKineticEnergy ;
MeanFreePath = (*theMeanFreePathTable)(aMaterial->GetIndex())->
GetValue( KineticEnergy, isOutRange );
}
return MeanFreePath;
}
inline G4double G4MuPairProduction::ComputeMeanFreePath(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
{
const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
const G4double* theAtomNumDensityVector =
aMaterial->GetAtomicNumDensityVector();
G4double ElectronEnergyCut =
(G4Electron::GetCutsInEnergy())[aMaterial->GetIndex()];
G4double PositronEnergyCut =
(G4Positron::GetCutsInEnergy())[aMaterial->GetIndex()];
G4double SIGMA = 0 ;
for ( G4int i=0 ; i < aMaterial->GetNumberOfElements() ; i++ )
{
SIGMA += theAtomNumDensityVector[i] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(i)->GetZ(),
ElectronEnergyCut,PositronEnergyCut );
}
return SIGMA<=0.0 ? DBL_MAX : 1./SIGMA ;
}
inline G4bool G4MuPairProduction::IsApplicable(
const G4ParticleDefinition& particle)
{
return( (&particle == (const G4ParticleDefinition *)theMuonMinus)
||(&particle == (const G4ParticleDefinition *)theMuonPlus)
) ;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,592 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuBremsstrahlung.cc,v 2.6 1998/11/13 13:38:35 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuBremsstrahlung physics process ---------
// by Laszlo Urban, September 1997
//
// 08-04-98: remove 'tracking cut' of muon in DoIt, MMa
// 26/10/98: new cross section of R.Kokoulin,cleanup , L.Urban
// --------------------------------------------------------------
#include "G4MuBremsstrahlung.hh"
#include "G4UnitsTable.hh"
// static members ........
G4int G4MuBremsstrahlung::nzdat = 5 ;
G4double G4MuBremsstrahlung::zdat[]={1.,4.,13.,29.,92.};
G4double G4MuBremsstrahlung::adat[]={1.01,9.01,26.98,63.55,238.03};
G4int G4MuBremsstrahlung::ntdat = 8 ;
G4double G4MuBremsstrahlung::tdat[]={1.e3,1.e4,1.e5,1.e6,1.e7,1.e8,1.e9,1.e10};
G4int G4MuBremsstrahlung::NBIN = 100 ; //500 ;
G4double G4MuBremsstrahlung::ya[1000]={0.};
G4double G4MuBremsstrahlung::proba[5][8][1000]={0.};
// constructor
G4MuBremsstrahlung::G4MuBremsstrahlung(const G4String& processName)
: G4MuEnergyLoss(processName),
theMeanFreePathTable(NULL),
LowestKineticEnergy (1.*GeV),
HighestKineticEnergy (1000000.*TeV),
TotBin(100),
theGamma (G4Gamma::Gamma() ),
theMuonMinus ( G4MuonMinus::MuonMinus() ),
theMuonPlus ( G4MuonPlus::MuonPlus() )
{ }
G4MuBremsstrahlung::~G4MuBremsstrahlung()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if (&PartialSumSigma) {
PartialSumSigma.clearAndDestroy();
}
}
void G4MuBremsstrahlung::SetPhysicsTableBining(G4double lowE, G4double highE,
G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE ; TotBin = nBins ;
}
void G4MuBremsstrahlung::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
{
BuildLossTable(aParticleType) ;
if(&aParticleType==theMuonMinus)
{
RecorderOfmuminusProcess[CounterOfmuminusProcess] = (*this).theLossTable ;
CounterOfmuminusProcess++;
}
else
{
RecorderOfmuplusProcess[CounterOfmuplusProcess] = (*this).theLossTable ;
CounterOfmuplusProcess++;
}
if(theMeanFreePathTable == NULL)
MakeSamplingTables(&aParticleType) ;
BuildLambdaTable(aParticleType) ;
G4MuEnergyLoss::BuildDEDXTable(aParticleType) ;
if(&aParticleType == theMuonPlus)
PrintInfoDefinition() ;
}
void G4MuBremsstrahlung::BuildLossTable(
const G4ParticleDefinition& aParticleType)
{
G4double KineticEnergy,TotalEnergy,bremloss,Z,
loss,natom,Cut ;
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable();
ParticleMass = aParticleType.GetPDGMass();
GammaCutInKineticEnergy = (*theGamma).GetEnergyCuts() ;
G4int numOfMaterials = theMaterialTable->length() ;
if (theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = new G4PhysicsTable(numOfMaterials) ;
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
GammaCutInKineticEnergyNow = GammaCutInKineticEnergy[J] ;
const G4Material* material = (*theMaterialTable)[J] ;
const G4ElementVector* theElementVector =
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements =
material->GetNumberOfElements() ;
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
TotalEnergy = KineticEnergy+ParticleMass ;
Cut = GammaCutInKineticEnergyNow ;
if(Cut>KineticEnergy) Cut = KineticEnergy ;
bremloss = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
Z=(*theElementVector)(iel)->GetZ();
natom = theAtomicNumDensityVector[iel] ;
loss = ComputeBremLoss((&aParticleType),Z,
(*theElementVector)(iel)->GetA(),
KineticEnergy,Cut) ;
bremloss += natom*loss ;
}
if(bremloss<0.) bremloss = 0. ;
aVector->PutValue(i,bremloss);
}
theLossTable->insert(aVector);
}
}
G4double G4MuBremsstrahlung::ComputeBremLoss(
const G4ParticleDefinition* aParticleType,
G4double AtomicNumber,G4double AtomicMass,
G4double KineticEnergy,G4double GammaEnergyCut)
{
G4double TotalEnergy,vcut,vmax,aaa,bbb,hhh,aa,x,ep ;
G4int kkk ;
G4double ak1=0.05 ;
G4int k2=5 ;
G4double xgi[]={0.03377,0.16940,0.38069,0.61931,0.83060,0.96623};
G4double wgi[]={0.08566,0.18038,0.23396,0.23396,0.18038,0.08566};
G4double loss = 0. ;
TotalEnergy=KineticEnergy+ParticleMass ;
vcut = GammaEnergyCut/TotalEnergy ;
vmax = KineticEnergy/TotalEnergy ;
aaa=0.;
bbb=vcut ;
if(vcut>vmax) bbb=vmax ;
kkk=int((bbb-aaa)/ak1)+k2 ;
hhh=(bbb-aaa)/float(kkk) ;
for(G4int l=0; l<kkk; l++)
{
aa=aaa+hhh*float(l) ;
for(G4int i=0; i<6; i++)
{
x=aa+xgi[i]*hhh ;
ep=x*TotalEnergy ;
loss += ep*wgi[i]*ComputeDMicroscopicCrossSection(
aParticleType,KineticEnergy,
AtomicNumber,AtomicMass,ep) ;
}
}
return loss ;
}
void G4MuBremsstrahlung::BuildLambdaTable(
const G4ParticleDefinition& ParticleType)
{
G4double LowEdgeEnergy , Value;
G4double FixedEnergy = (LowestKineticEnergy + HighestKineticEnergy)/2. ;
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
G4PhysicsLogVector* ptrVector;
for ( G4int J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
ptrVector=new G4PhysicsLogVector(LowestKineticEnergy, HighestKineticEnergy,
TotBin ) ;
const G4Material* material= (*theMaterialTable)[J];
for ( G4int i = 0 ; i < TotBin ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeMeanFreePath( &ParticleType, LowEdgeEnergy,
material );
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector );
// Compute the PartialSumSigma table at a given fixed energy
ComputePartialSumSigma( &ParticleType, FixedEnergy, material) ;
}
}
void G4MuBremsstrahlung::ComputePartialSumSigma(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
// Build the table of cross section per element.The table is built for MATERIALS.
// This table is used by DoIt to select randomly an element in the material.
{
G4int Imate = aMaterial->GetIndex();
G4int NbOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* theAtomNumDensityVector =
aMaterial->GetAtomicNumDensityVector();
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[Imate];
PartialSumSigma(Imate) = new G4ValVector(NbOfElements);
G4double SIGMA = 0. ;
for ( G4int Ielem=0 ; Ielem < NbOfElements ; Ielem++ )
{
SIGMA += theAtomNumDensityVector[Ielem] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(Ielem)->GetZ(),
(*theElementVector)(Ielem)->GetA(),
GammaEnergyCut );
PartialSumSigma(Imate)->insertAt(Ielem, SIGMA);
}
}
G4double G4MuBremsstrahlung::ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicMass,
G4double GammaEnergyCut)
// Cross section is calculated according to a formula of R.Kokoulin.
{
G4double TotalEnergy,vcut,vmax,aaa,bbb,hhh,aa,x,ep ;
G4int kkk ;
G4double ak1=2.3 ;
G4int k2=4 ;
G4double xgi[]={0.03377,0.16940,0.38069,0.61931,0.83060,0.96623};
G4double wgi[]={0.08566,0.18038,0.23396,0.23396,0.18038,0.08566};
G4double CrossSection = 0. ;
TotalEnergy=KineticEnergy+ParticleMass ;
vcut = GammaEnergyCut/TotalEnergy ;
vmax = KineticEnergy/TotalEnergy ;
if(vmax <= vcut) return CrossSection;
// numerical integration
aaa=log(vcut) ;
bbb=log(vmax);
kkk=int((bbb-aaa)/ak1)+k2 ;
hhh=(bbb-aaa)/float(kkk) ;
for(G4int l=0; l<kkk; l++)
{
aa=aaa+hhh*float(l) ;
for(G4int i=0; i<6; i++)
{
x=aa+xgi[i]*hhh ;
ep=exp(x)*TotalEnergy ;
CrossSection += ep*wgi[i]*ComputeDMicroscopicCrossSection(
ParticleType,KineticEnergy,
AtomicNumber,AtomicMass,ep) ;
}
}
return CrossSection;
}
G4double G4MuBremsstrahlung::ComputeDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicMass,
G4double GammaEnergy)
// differential cross section
{
static const G4double sqrte=sqrt(exp(1.)) ;
static const G4double bh=202.4,bh1=446.,btf=183.,btf1=1429. ;
static const G4double rmass=ParticleMass/electron_mass_c2 ;
static const G4double cc=classic_electr_radius/rmass ;
static const G4double coeff= 16.*fine_structure_const*cc*cc/3. ;
G4double dxsection = 0.;
if( GammaEnergy > KineticEnergy) return dxsection ;
G4double A = AtomicMass/(g/mole) ; // !!!!!!!!!!!!!!!!!!!
G4double E=KineticEnergy+ParticleMass ;
G4double v=GammaEnergy/E ;
G4double delta=0.5*ParticleMass*ParticleMass*v/(E-GammaEnergy) ;
G4double rab0=delta*sqrte ;
G4double z13=exp(-log(AtomicNumber)/3.) ;
G4double dn=1.54*exp(0.27*log(A)) ;
G4double b,b1,dnstar ;
if(AtomicNumber<1.5)
{
b=bh;
b1=bh1;
dnstar=dn ;
}
else
{
b=btf;
b1=btf1;
dnstar = exp((1.-1./AtomicNumber)*log(dn)) ;
}
// nucleus contribution logarithm
G4double rab1=b*z13;
G4double fn=log(rab1/(dnstar*(electron_mass_c2+rab0*rab1))*
(ParticleMass+delta*(dnstar*sqrte-2.))) ;
if(fn <0.) fn = 0. ;
// electron contribution logarithm
G4double epmax1=E/(1.+0.5*ParticleMass*rmass/E) ;
G4double fe=0.;
if(GammaEnergy<epmax1)
{
G4double rab2=b1*z13*z13 ;
fe=log(rab2*ParticleMass/((1.+delta*rmass/(electron_mass_c2*sqrte))*
(electron_mass_c2+rab0*rab2))) ;
if(fe<0.) fe=0. ;
}
dxsection = coeff*(1.-v*(1.-0.75*v))*AtomicNumber*(fn*AtomicNumber+fe)/
GammaEnergy ;
return dxsection ;
}
void G4MuBremsstrahlung::MakeSamplingTables(
const G4ParticleDefinition* ParticleType)
{
G4double CutFixed = 1.*keV ;
G4double epbin[1000],xbin[1000],prbin[1000] ;
G4int nbin;
G4double AtomicNumber,AtomicWeight,KineticEnergy,
TotalEnergy,Maxep ;
ParticleMass = ParticleType->GetPDGMass() ;
for (G4int iz=0; iz<nzdat; iz++)
{
AtomicNumber = zdat[iz];
AtomicWeight = adat[iz]*g/mole ;
for (G4int it=0; it<ntdat; it++)
{
KineticEnergy = tdat[it];
TotalEnergy = KineticEnergy + ParticleMass;
Maxep = KineticEnergy ;
G4double CrossSection = 0.0 ;
G4double c,y,ymin,ymax,dy,yy,dx,x,ep ;
G4int NbofIntervals ;
// calculate the differential cross section
// numerical integration in
// log ...............
c = log(Maxep/CutFixed) ;
ymin = -5. ;
ymax = 0. ;
dy = (ymax-ymin)/NBIN ;
nbin=-1;
y = ymin - 0.5*dy ;
yy = ymin - dy ;
for (G4int i=0 ; i<NBIN; i++)
{
y += dy ;
x = exp(y) ;
yy += dy ;
dx = exp(yy+dy)-exp(yy) ;
ep = CutFixed*exp(c*x) ;
CrossSection += ep*dx*ComputeDMicroscopicCrossSection(ParticleType,
KineticEnergy,AtomicNumber,
AtomicWeight,ep) ;
if(nbin<NBIN)
{
nbin += 1 ;
epbin[nbin]=ep;
xbin[nbin]=x;
prbin[nbin]=CrossSection ;
ya[nbin]=y ;
proba[iz][it][nbin] = CrossSection ;
}
}
if(CrossSection > 0.)
{
for(G4int ib=0; ib<=nbin; ib++)
{
prbin[ib] /= CrossSection ;
proba[iz][it][ib] /= CrossSection ;
}
}
}
}
}
G4VParticleChange* G4MuBremsstrahlung::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
G4Material* aMaterial=trackData.GetMaterial() ;
const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
G4ParticleMomentum ParticleDirection =
aDynamicParticle->GetMomentumDirection();
// Gamma cut in this material
G4double GammaEnergyCut =
(G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
// check against insufficient energy
if (KineticEnergy < GammaEnergyCut)
{
aParticleChange.SetMomentumChange( ParticleDirection );
aParticleChange.SetEnergyChange( KineticEnergy );
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.SetNumberOfSecondaries(0);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
// select randomly one element constituing the material
G4Element* anElement = SelectRandomAtom(aMaterial);
G4double TotalEnergy=KineticEnergy+aDynamicParticle->
GetDefinition()->GetPDGMass() ;
// sampling using tables
G4double v,xc,x,yc,y ;
G4int iZ,iT,iy ;
// select sampling table ;
G4double lnZ = log(anElement->GetZ()) ;
G4double delmin = 1.e10 ;
G4double del ;
G4int izz,itt,NBINminus1 ;
NBINminus1 = NBIN-1 ;
for (G4int iz=0; iz<nzdat; iz++)
{
del = abs(lnZ-log(zdat[iz])) ;
if(del<delmin)
{
delmin=del ;
izz=iz ;
}
}
delmin = 1.e10 ;
for (G4int it=0; it<ntdat; it++)
{
del = abs(log(KineticEnergy)-log(tdat[it])) ;
if(del<delmin)
{
del=delmin;
itt=it ;
}
}
//sample energy transfer according to the sampling table
G4double r = G4UniformRand() ;
iy = -1 ;
do {
iy += 1 ;
} while (((proba[izz][itt][iy]) < r)&&(iy < NBINminus1)) ;
//sampling is Done uniformly in y in the bin
if( iy < NBINminus1 )
y = ya[iy] + G4UniformRand() * ( ya[iy+1] - ya[iy] ) ;
else
y = ya[iy] ;
x = exp(y) ;
v = GammaEnergyCut*exp(x*log(KineticEnergy/GammaEnergyCut)) ;
if( v <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// create G4DynamicParticle object for the Gamma
G4double GammaEnergy = v;
// angles of the emitted gamma. ( Z - axis along the parent particle)
// Teta = electron_mass_c2/TotalEnergy for the moment .....
G4double Teta = electron_mass_c2/TotalEnergy ;
G4double Phi = twopi * G4UniformRand() ;
G4double dirx = sin(Teta)*cos(Phi) , diry = sin(Teta)*sin(Phi) ,
dirz = cos(Teta) ;
G4ThreeVector GammaDirection ( dirx, diry, dirz);
GammaDirection.rotateUz(ParticleDirection);
G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
GammaDirection, GammaEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(aGamma);
// Update the incident particle
G4double NewKinEnergy = KineticEnergy - GammaEnergy;
if (NewKinEnergy > 0.)
{
aParticleChange.SetMomentumChange(ParticleDirection);
aParticleChange.SetEnergyChange(NewKinEnergy);
aParticleChange.SetLocalEnergyDeposit (0.);
}
else
{
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.SetStatusChange(fStopButAlive);
}
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
G4Element* G4MuBremsstrahlung::SelectRandomAtom(G4Material* aMaterial) const
{
// select randomly 1 element within the material
const G4int Index = aMaterial->GetIndex();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
G4double rval = G4UniformRand()*((*PartialSumSigma(Index))(NumberOfElements-1));
for ( G4int i=0; i < NumberOfElements; i++ )
if (rval <= (*PartialSumSigma(Index))(i)) return ((*theElementVector)(i));
G4cout << " WARNING !!! - The Material '"<< aMaterial->GetName()
<< "' has no elements, NULL pointer returned." << endl;
return NULL;
}
void G4MuBremsstrahlung::PrintInfoDefinition()
{
G4String comments = "cross sections from R. Kokoulin \n ";
comments += " Good description up to 1000 TeV.";
G4cout << endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,507 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuIonisation.cc,v 2.6 1998/11/13 13:38:35 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// ------------ G4MuIonisation physics process -------------
// by Laszlo Urban, September 1997
// ------------------------------------------------------------------
// It is the implementation of the NEW IONISATION PROCESS.
// It calculates the ionisation of muons.
// **************************************************************
// 08-04-98: remove 'tracking cut' of the ionizing particle, MMa
// 26/10/98: new stuff from R.Kokoulin + cleanup , L.Urban
// --------------------------------------------------------------
#include "G4MuIonisation.hh"
#include "G4UnitsTable.hh"
// constructor and destructor
G4MuIonisation::G4MuIonisation(const G4String& processName)
: G4MuEnergyLoss(processName),
LowestKineticEnergy(1.00*keV),
HighestKineticEnergy(1000000.*TeV),
theMeanFreePathTable(NULL),
lastCutInRange(0.),
TotBin(100),
theElectron ( G4Electron::Electron() ),
theMuonPlus ( G4MuonPlus::MuonPlus() ),
theMuonMinus ( G4MuonMinus::MuonMinus() )
{ }
G4MuIonisation::~G4MuIonisation()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
}
void G4MuIonisation::SetPhysicsTableBining(G4double lowE, G4double highE,
G4int nBins)
{
LowestKineticEnergy = lowE; HighestKineticEnergy = highE;
TotBin = nBins;
}
void G4MuIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
G4double Charge = aParticleType.GetPDGCharge();
CutInRange = aParticleType.GetLengthCuts();
BuildLossTable(aParticleType) ;
if(Charge>0.)
{
RecorderOfmuplusProcess[CounterOfmuplusProcess] = (*this).theLossTable ;
CounterOfmuplusProcess++;
}
else
{
RecorderOfmuminusProcess[CounterOfmuminusProcess] = (*this).theLossTable ;
CounterOfmuminusProcess++;
}
if(CutInRange != lastCutInRange)
{
lastCutInRange = CutInRange ;
BuildLambdaTable(aParticleType) ;
}
G4MuEnergyLoss::BuildDEDXTable(aParticleType) ;
if(&aParticleType == theMuonPlus)
PrintInfoDefinition() ;
}
void G4MuIonisation::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
G4double Charge = aParticleType.GetPDGCharge() ;
if(Charge>0.)
ParticleCutInKineticEnergy = theMuonPlus->GetCutsInEnergy() ;
else
ParticleCutInKineticEnergy = theMuonMinus->GetCutsInEnergy() ;
DeltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
G4double LowEdgeEnergy , ionloss ;
G4double RateMass ;
G4bool isOutRange ;
static const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
const G4double twoln10 = 2.*log(10.) ;
const G4double Factor = twopi_mc2_rcl2 ;
const G4double bg2lim = 0.0169 , taulim = 8.4146e-3 ;
ParticleMass = aParticleType.GetPDGMass() ;
RateMass = electron_mass_c2/ParticleMass ;
G4int numOfMaterials = theMaterialTable->length();
if ( theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = new G4PhysicsTable(numOfMaterials);
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
G4double ElectronDensity,Eexc,Eexc2,Cden,Mden,Aden,X0den,X1den,taul ;
G4double* ShellCorrectionVector;
const G4Material* material= (*theMaterialTable)[J];
ElectronDensity = material->GetElectronDensity();
Eexc = material->GetIonisation()->GetMeanExcitationEnergy();
Eexc2 = Eexc*Eexc ;
Cden = material->GetIonisation()->GetCdensity();
Mden = material->GetIonisation()->GetMdensity();
Aden = material->GetIonisation()->GetAdensity();
X0den = material->GetIonisation()->GetX0density();
X1den = material->GetIonisation()->GetX1density();
taul = material->GetIonisation()->GetTaul() ;
ShellCorrectionVector = material->GetIonisation()
->GetShellCorrectionVector();
const G4ElementVector* theElementVector=
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector=
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements=
material->GetNumberOfElements() ;
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[J] ;
G4double tau,tau0,Tmax,gamma,bg2,beta2,rcut,delta,x,sh ;
for (G4int i = 0 ; i < TotBin ; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
tau = LowEdgeEnergy/ParticleMass ;
if ( tau < taul )
// low energy part , parametrized energy loss formulae
{
ionloss = 0. ;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)(iel);
if ( tau < element->GetIonisation()->GetTau0())
ionloss += theAtomicNumDensityVector[iel]
*( element->GetIonisation()->GetAlow()*sqrt(tau)
+element->GetIonisation()->GetBlow()*tau) ;
else
ionloss += theAtomicNumDensityVector[iel]
* element->GetIonisation()->GetClow()/sqrt(tau) ;
}
}
else
// high energy part , Bethe-Bloch formula
{
gamma = tau +1. ;
bg2 = tau*(tau+2.) ;
beta2 = bg2/(gamma*gamma) ;
Tmax = 2.*electron_mass_c2*bg2
/(1.+2.*gamma*RateMass+RateMass*RateMass) ;
if ( DeltaCutInKineticEnergyNow < Tmax)
rcut = DeltaCutInKineticEnergyNow/Tmax ;
else
rcut = 1.;
ionloss = log(2.*electron_mass_c2*bg2*Tmax/Eexc2)
+log(rcut)-(1.+rcut)*beta2 ;
// density correction
x = log(bg2)/twoln10 ;
if ( x < X0den )
delta = 0. ;
else
{
delta = twoln10*x - Cden ;
if ( x < X1den )
delta += Aden*pow((X1den-x),Mden) ;
}
// shell correction
if ( bg2 > bg2lim ) {
sh = 0. ;
x = 1. ;
for (G4int k=0; k<=2; k++) {
x *= bg2 ;
sh += ShellCorrectionVector[k]/x;
}
}
else {
sh = 0. ;
x = 1. ;
for (G4int k=0; k<=2; k++) {
x *= bg2lim ;
sh += ShellCorrectionVector[k]/x;
}
sh *= log(tau/taul)/log(taulim/taul) ;
}
ionloss -= delta + sh ;
ionloss /= beta2 ;
// correction of R. Kokoulin
G4double E = LowEdgeEnergy+ParticleMass ;
G4double epmax = RateMass*E*E/(RateMass*E+ParticleMass) ;
G4double apar = log(2.*epmax/electron_mass_c2) ;
ionloss += fine_structure_const*(log(2.*E/ParticleMass)-apar/3.)*
apar*apar/twopi ;
ionloss *= Factor*ElectronDensity ;
}
if ( ionloss <= 0.)
ionloss = 0. ;
aVector->PutValue(i,ionloss) ;
}
theLossTable->insert(aVector);
}
}
void G4MuIonisation::BuildLambdaTable(const G4ParticleDefinition& aParticleType)
{
// Build mean free path tables for the delta ray production process
G4double LowEdgeEnergy , Value ,sigma ;
G4bool isOutRange ;
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
theMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
// get electron and particle cuts in kinetic energy
DeltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
ParticleCutInKineticEnergy = aParticleType.GetEnergyCuts() ;
for (G4int J=0 ; J < numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector=
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
const G4int NumberOfElements=
material->GetNumberOfElements() ;
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[J] ;
for ( G4int i = 0 ; i < TotBin ; i++ )
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
sigma = 0. ;
for (G4int iel=0; iel<NumberOfElements; iel++ )
{
sigma += theAtomicNumDensityVector[iel]*
ComputeMicroscopicCrossSection(aParticleType,
LowEdgeEnergy,
(*theElementVector)(iel)->GetZ() ) ;
}
Value = sigma<=0 ? DBL_MAX : 1./sigma ;
aVector->PutValue(i, Value) ;
}
theMeanFreePathTable->insert(aVector);
}
}
G4double G4MuIonisation::ComputeMicroscopicCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber)
{
const G4double xgi[] = {0.06943,0.33001,0.66999,0.93057} ;
const G4double wgi[] = {0.17393,0.32607,0.32607,0.17393} ;
const G4double ak1 = 4.6 ;
const G4int k2 = 2 ;
const G4double masspar = 0.5*ParticleMass*ParticleMass/electron_mass_c2 ;
G4double TotalEnergy=KineticEnergy + ParticleMass;
G4double KnockonMaxEnergy = TotalEnergy/(1.+masspar/TotalEnergy) ;
G4double TotalCrossSection= 0. ;
if( KnockonMaxEnergy > DeltaCutInKineticEnergyNow )
{
G4double aaa = log(DeltaCutInKineticEnergyNow);
G4double bbb = log(KnockonMaxEnergy) ;
G4int kkk = int((bbb-aaa)/ak1)+k2 ;
G4double hhh = (bbb-aaa)/kkk ;
G4double step = exp(hhh) ;
G4double ymax = 1./KnockonMaxEnergy ;
for (G4int k=0; k<kkk; k++)
{
G4double ymin = ymax ;
ymax = ymin*step ;
G4double hhy = ymax-ymin ;
for (G4int i=0; i<4; i++)
{
G4double y = ymin+hhy*xgi[i];
G4double ep = 1./y ;
TotalCrossSection += ep*ep*wgi[i]*hhy*
ComputeDMicroscopicCrossSection(
aParticleType,KineticEnergy,
AtomicNumber,ep) ;
}
}
}
return TotalCrossSection ;
}
G4double G4MuIonisation::ComputeDMicroscopicCrossSection(
const G4ParticleDefinition& ParticleType,
G4double KineticEnergy, G4double AtomicNumber,
G4double KnockonEnergy)
// Calculates the differential (D) microscopic cross section
// using the cross section formula of R.P. Kokoulin (10/98)
{
const G4double masspar=0.5*ParticleMass*ParticleMass/electron_mass_c2 ;
const G4double alphaprime = fine_structure_const/twopi ;
G4double TotalEnergy = KineticEnergy + ParticleMass ;
G4double KnockonMaxEnergy = TotalEnergy/(1.+masspar/TotalEnergy) ;
G4double DCrossSection = 0. ;
if(KnockonEnergy >= KnockonMaxEnergy) return DCrossSection ;
G4double v = KnockonEnergy/TotalEnergy ;
DCrossSection = twopi_mc2_rcl2*AtomicNumber*
(1.-KnockonEnergy/KnockonMaxEnergy+0.5*v*v)/
(KnockonEnergy*KnockonEnergy) ;
G4double a1 = log(1.+2.*KnockonEnergy/electron_mass_c2) ;
G4double a3 = log(4.*TotalEnergy*(TotalEnergy-KnockonEnergy)/
(ParticleMass*ParticleMass)) ;
DCrossSection *= (1.+alphaprime*a1*(a3-a1)) ;
return DCrossSection ;
}
G4VParticleChange* G4MuIonisation::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
const G4DynamicParticle* aParticle ;
const G4double alphaprime = fine_structure_const/twopi ;
G4Material* aMaterial;
G4double KineticEnergy,TotalEnergy,TotalMomentum,
betasquare,MaxKineticEnergyTransfer,
DeltaKineticEnergy,DeltaTotalMomentum,costheta,sintheta,phi,
dirx,diry,dirz,finalKineticEnergy,finalPx,finalPy,finalPz,
x,xc,te2,grej,Psquare,Esquare,summass,rate,grejc,finalMomentum ;
G4double Charge ;
aParticleChange.Initialize(trackData) ;
aMaterial = trackData.GetMaterial() ;
aParticle = trackData.GetDynamicParticle() ;
Charge=aParticle->GetDefinition()->GetPDGCharge();
KineticEnergy=aParticle->GetKineticEnergy();
TotalEnergy=KineticEnergy + ParticleMass ;
Psquare=KineticEnergy*(TotalEnergy+ParticleMass) ;
Esquare=TotalEnergy*TotalEnergy ;
summass = ParticleMass + electron_mass_c2 ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection() ;
DeltaCutInKineticEnergyNow = DeltaCutInKineticEnergy[aMaterial->GetIndex()];
// some kinematics......................
betasquare=Psquare/Esquare ;
MaxKineticEnergyTransfer = 2.*electron_mass_c2*Psquare
/(summass*summass+2.*electron_mass_c2*KineticEnergy);
// sampling kinetic energy of the delta ray
if( MaxKineticEnergyTransfer <= DeltaCutInKineticEnergyNow )
{
// pathological case (it should not happen ,
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
else
{
// normal case ......................................
xc=DeltaCutInKineticEnergyNow/MaxKineticEnergyTransfer ;
rate=MaxKineticEnergyTransfer/TotalEnergy ;
te2=0.5*rate*rate ;
// sampling follows ...
G4double a0=log(2.*TotalEnergy/ParticleMass) ;
grejc=(1.-betasquare*xc+te2*xc*xc)*
(1.+ alphaprime*a0*a0) ;
do {
x=xc/(1.-(1.-xc)*G4UniformRand());
G4double twoep = 2.*x*MaxKineticEnergyTransfer ;
grej=(1.-x*(betasquare-x*te2))*
(1.+alphaprime*log(1.+twoep/electron_mass_c2)*
(a0+log((2.*TotalEnergy-twoep)/ParticleMass)-
log(1.+twoep/electron_mass_c2)))
/grejc ;
} while( G4UniformRand()>grej );
}
DeltaKineticEnergy = x * MaxKineticEnergyTransfer ;
if(DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
DeltaTotalMomentum = sqrt(DeltaKineticEnergy * (DeltaKineticEnergy +
2. * electron_mass_c2 )) ;
TotalMomentum = sqrt(Psquare) ;
costheta = DeltaKineticEnergy * (TotalEnergy + electron_mass_c2)
/(DeltaTotalMomentum * TotalMomentum) ;
// protection against costheta > 1 or < -1 ---------------
if ( costheta < -1. )
costheta = -1. ;
if ( costheta > +1. )
costheta = +1. ;
// direction of the delta electron ........
phi = twopi * G4UniformRand() ;
sintheta = sqrt((1.+costheta)*(1.-costheta));
dirx = sintheta * cos(phi) ;
diry = sintheta * sin(phi) ;
dirz = costheta ;
G4ThreeVector DeltaDirection(dirx,diry,dirz) ;
DeltaDirection.rotateUz(ParticleDirection) ;
// create G4DynamicParticle object for delta ray
G4DynamicParticle *theDeltaRay = new G4DynamicParticle;
theDeltaRay->SetKineticEnergy( DeltaKineticEnergy );
theDeltaRay->SetMomentumDirection(
DeltaDirection.x(),DeltaDirection.y(),DeltaDirection.z());
theDeltaRay->SetDefinition(G4Electron::Electron());
finalKineticEnergy = KineticEnergy - DeltaKineticEnergy ;
if (finalKineticEnergy > 0. )
{
// changed energy and momentum of the actual particle
finalMomentum=sqrt(finalKineticEnergy*
(finalKineticEnergy+2.*ParticleMass)) ;
finalPx = (TotalMomentum*ParticleDirection.x()
-DeltaTotalMomentum*DeltaDirection.x())/finalMomentum ;
finalPy = (TotalMomentum*ParticleDirection.y()
-DeltaTotalMomentum*DeltaDirection.y())/finalMomentum ;
finalPz = (TotalMomentum*ParticleDirection.z()
-DeltaTotalMomentum*DeltaDirection.z())/finalMomentum ;
aParticleChange.SetMomentumChange( finalPx,finalPy,finalPz );
}
else
{
finalKineticEnergy = 0. ;
aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( theDeltaRay );
aParticleChange.SetLocalEnergyDeposit (0.);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
void G4MuIonisation::PrintInfoDefinition()
{
G4String comments = "knock-on electron cross sections .\n ";
comments += " Good description above the mean excitation energy.\n";
comments += " delta ray energy sampled from differential Xsection." ;
G4cout << endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
@@ -0,0 +1,814 @@
// This code implementation is the intellectual property of
// the RD44 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: G4MuPairProduction.cc,v 2.10 1998/12/02 16:33:18 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
// $Id:
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MuPairProduction physics process ---------
// by Laszlo Urban, May 1998
// **************************************************************
// 04-06-98, in DoIt,secondary production condition:range>min(threshold,safety)
// 26/10/98, new stuff from R. Kokoulin + cleanup , L.Urban
// --------------------------------------------------------------
#include "G4MuPairProduction.hh"
#include "G4EnergyLossTables.hh"
#include "G4UnitsTable.hh"
// static members ........
G4int G4MuPairProduction::nzdat = 5 ;
G4double G4MuPairProduction::zdat[]={1.,4.,13.,26.,92.};
G4int G4MuPairProduction::ntdat = 8 ;
G4double G4MuPairProduction::tdat[]={1.e3,1.e4,1.e5,1.e6,1.e7,1.e8,1.e9,1.e10};
G4int G4MuPairProduction::NBIN = 100 ; //500 ;
G4double G4MuPairProduction::ya[1000]={0.};
G4double G4MuPairProduction::proba[5][8][1000]={0.};
G4MuPairProduction::G4MuPairProduction(const G4String& processName)
: G4MuEnergyLoss(processName),
theMeanFreePathTable(NULL),
LowestKineticEnergy (1.*GeV),
HighestKineticEnergy (1000000.*TeV),
TotBin(50),
theElectron (G4Electron::Electron() ),
thePositron (G4Positron::Positron() ),
theMuonMinus ( G4MuonMinus::MuonMinus() ),
theMuonPlus ( G4MuonPlus::MuonPlus() )
{ }
G4MuPairProduction::~G4MuPairProduction()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if (&PartialSumSigma) {
PartialSumSigma.clearAndDestroy();
}
}
void G4MuPairProduction::SetPhysicsTableBining(G4double lowE,G4double highE,
G4int nBins)
{
LowestKineticEnergy=lowE; HighestKineticEnergy=highE; TotBin=nBins;
}
void G4MuPairProduction::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
// just call BuildLossTable+BuildLambdaTable
{
BuildLossTable(aParticleType) ;
if(&aParticleType==theMuonMinus)
{
RecorderOfmuminusProcess[CounterOfmuminusProcess] = (*this).theLossTable ;
CounterOfmuminusProcess++;
}
else
{
RecorderOfmuplusProcess[CounterOfmuplusProcess] = (*this).theLossTable ;
CounterOfmuplusProcess++;
}
// sampling table should be made only once !
if(theMeanFreePathTable == NULL)
MakeSamplingTables(&aParticleType) ;
BuildLambdaTable(aParticleType) ;
G4MuEnergyLoss::BuildDEDXTable(aParticleType) ;
if(&aParticleType==theMuonPlus)
PrintInfoDefinition() ;
}
void G4MuPairProduction::BuildLossTable(
const G4ParticleDefinition& aParticleType)
{
G4double KineticEnergy,TotalEnergy,pairloss,Z,
loss,natom,eCut,pCut ;
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable();
ParticleMass = aParticleType.GetPDGMass() ;
ElectronCutInKineticEnergy = (*theElectron).GetEnergyCuts() ;
PositronCutInKineticEnergy = (*thePositron).GetEnergyCuts() ;
G4int numOfMaterials = theMaterialTable->length() ;
if (theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = new G4PhysicsTable(numOfMaterials) ;
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
ElectronCutInKineticEnergyNow = ElectronCutInKineticEnergy[J] ;
PositronCutInKineticEnergyNow = PositronCutInKineticEnergy[J] ;
const G4Material* material = (*theMaterialTable)[J] ;
const G4ElementVector* theElementVector =
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements =
material->GetNumberOfElements() ;
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
TotalEnergy = KineticEnergy+ParticleMass ;
eCut = ElectronCutInKineticEnergyNow ;
pCut = PositronCutInKineticEnergyNow ;
if(eCut>KineticEnergy)
eCut = KineticEnergy ;
if(pCut>KineticEnergy)
pCut = KineticEnergy ;
pairloss = 0.;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
Z=(*theElementVector)(iel)->GetZ();
natom = theAtomicNumDensityVector[iel] ;
loss = ComputePairLoss(&aParticleType,
Z,KineticEnergy,eCut,pCut) ;
pairloss += natom*loss ;
}
if(pairloss<0.)
pairloss = 0. ;
aVector->PutValue(i,pairloss);
}
theLossTable->insert(aVector);
}
}
G4double G4MuPairProduction::ComputePairLoss(
const G4ParticleDefinition* ParticleType,
G4double AtomicNumber,
G4double KineticEnergy,
G4double ElectronEnergyCut,
G4double PositronEnergyCut)
{
static const G4double
xgi[] ={ 0.0199,0.1017,0.2372,0.4083,0.5917,0.7628,0.8983,0.9801 };
static const G4double
wgi[] ={ 0.0506,0.1112,0.1569,0.1813,0.1813,0.1569,0.1112,0.0506 };
static const G4double ak1=6.9 ;
static const G4double ak2=1.0 ;
G4double sqrte = sqrt(exp(1.)) ;
G4double z13 = exp(log(AtomicNumber)/3.) ;
G4double loss = 0.0 ;
if ( AtomicNumber < 1. ) return loss;
G4double CutInPairEnergy = ElectronEnergyCut+PositronEnergyCut
+2.*electron_mass_c2 ;
G4double MinPairEnergy = 4.*electron_mass_c2 ;
if( CutInPairEnergy <= MinPairEnergy ) return loss ;
G4double MaxPairEnergy = KineticEnergy+ParticleMass*(1.-0.75*sqrte*z13) ;
if( CutInPairEnergy >= MaxPairEnergy )
CutInPairEnergy = MaxPairEnergy ;
G4double aaa,bbb,hhh,x,epln,ep ;
G4int kkk ;
// calculate the rectricted loss
// numerical integration in log(PairEnergy)
aaa = log(MinPairEnergy) ;
bbb = log(CutInPairEnergy) ;
kkk = int((bbb-aaa)/ak1+ak2) ;
hhh = (bbb-aaa)/kkk ;
for (G4int l=0 ; l<kkk; l++)
{
x = aaa+hhh*l ;
for (G4int ll=0; ll<8; ll++)
{
epln=x+xgi[ll]*hhh ;
ep = exp(epln) ;
loss += wgi[ll]*ep*ep*ComputeDMicroscopicCrossSection(ParticleType,
KineticEnergy,AtomicNumber,
ep) ;
}
}
loss *= hhh ;
if (loss < 0.) loss = 0.;
return loss ;
}
void G4MuPairProduction::BuildLambdaTable(
const G4ParticleDefinition& ParticleType)
{
G4double LowEdgeEnergy , Value;
G4double FixedEnergy = (LowestKineticEnergy + HighestKineticEnergy)/2. ;
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
theMeanFreePathTable = new
G4PhysicsTable( G4Material::GetNumberOfMaterials() ) ;
G4PhysicsLogVector* ptrVector;
for ( G4int J=0 ; J < G4Material::GetNumberOfMaterials(); J++ )
{
ptrVector = new
G4PhysicsLogVector(LowestKineticEnergy, HighestKineticEnergy,
TotBin ) ;
const G4Material* material= (*theMaterialTable)[J];
for ( G4int i = 0 ; i < TotBin ; i++ )
{
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
Value = ComputeMeanFreePath( &ParticleType, LowEdgeEnergy,
material );
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector );
// Compute the PartialSumSigma table at a given fixed energy
ComputePartialSumSigma( &ParticleType, FixedEnergy, material) ;
}
}
void G4MuPairProduction::ComputePartialSumSigma(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
const G4Material* aMaterial)
{
G4int Imate = aMaterial->GetIndex();
G4int NbOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* theAtomNumDensityVector = aMaterial->
GetAtomicNumDensityVector();
G4double ElectronEnergyCut = (G4Electron::GetCutsInEnergy())[Imate];
G4double PositronEnergyCut = (G4Positron::GetCutsInEnergy())[Imate];
PartialSumSigma(Imate) = new G4ValVector(NbOfElements);
G4double SIGMA = 0. ;
for ( G4int Ielem=0 ; Ielem < NbOfElements ; Ielem++ )
{
SIGMA += theAtomNumDensityVector[Ielem] *
ComputeMicroscopicCrossSection( ParticleType, KineticEnergy,
(*theElementVector)(Ielem)->GetZ(),
ElectronEnergyCut,PositronEnergyCut );
PartialSumSigma(Imate)->insertAt(Ielem, SIGMA);
}
}
G4double G4MuPairProduction::ComputeMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double ElectronEnergyCut,
G4double PositronEnergyCut)
{
static const G4double
xgi[] ={ 0.0199,0.1017,0.2372,0.4083,0.5917,0.7628,0.8983,0.9801 };
static const G4double
wgi[] ={ 0.0506,0.1112,0.1569,0.1813,0.1813,0.1569,0.1112,0.0506 };
static const G4double ak1=6.9 ;
static const G4double ak2=1.0 ;
G4double sqrte = sqrt(exp(1.)) ;
G4double z13 = exp(log(AtomicNumber)/3.) ;
G4double CrossSection = 0.0 ;
if ( AtomicNumber < 1. ) return CrossSection;
G4double CutInPairEnergy = ElectronEnergyCut+PositronEnergyCut
+2.*electron_mass_c2 ;
if( CutInPairEnergy < 4.*electron_mass_c2 )
CutInPairEnergy = 4.*electron_mass_c2 ;
G4double MaxPairEnergy = KineticEnergy+ParticleMass*(1.-0.75*sqrte*z13) ;
if( CutInPairEnergy >= MaxPairEnergy ) return CrossSection ;
G4double aaa,bbb,hhh,x,epln,ep ;
G4int kkk ;
// calculate the total cross section
// numerical integration in log(PairEnergy)
aaa = log(CutInPairEnergy) ;
bbb = log(MaxPairEnergy) ;
kkk = int((bbb-aaa)/ak1+ak2) ;
hhh = (bbb-aaa)/kkk ;
for (G4int l=0 ; l<kkk; l++)
{
x = aaa+hhh*l ;
for (G4int ll=0; ll<8; ll++)
{
epln = x+xgi[ll]*hhh;
ep = exp(epln) ;
CrossSection += wgi[ll]*ep*ComputeDMicroscopicCrossSection(ParticleType,
KineticEnergy,AtomicNumber,
ep) ;
}
}
CrossSection *= hhh ;
if (CrossSection < 0.) CrossSection = 0.;
return CrossSection;
}
void G4MuPairProduction::MakeSamplingTables(
const G4ParticleDefinition* ParticleType)
{
G4double epbin[1000],xbin[1000],prbin[1000] ;
G4int nbin;
G4double AtomicNumber,KineticEnergy,MinPairEnergy ;
G4double c,y,ymin,ymax,dy,yy,dx,x,ep ;
MinPairEnergy = 4.*electron_mass_c2 ;
G4double sqrte = sqrt(exp(1.)) ;
for (G4int iz=0; iz<nzdat; iz++)
{
AtomicNumber = zdat[iz];
G4double z13 = exp(log(AtomicNumber)/3.) ;
for (G4int it=0; it<ntdat; it++)
{
KineticEnergy = tdat[it];
G4double MaxPairEnergy = KineticEnergy+ParticleMass*(1.-0.75*sqrte*z13) ;
G4double CrossSection = 0.0 ;
G4int NbofIntervals ;
c = log(MaxPairEnergy/MinPairEnergy) ;
ymin = -5. ;
ymax = 0. ;
dy = (ymax-ymin)/NBIN ;
nbin=-1;
y = ymin - 0.5*dy ;
yy = ymin - dy ;
for (G4int i=0 ; i<NBIN; i++)
{
y += dy ;
x = exp(y) ;
yy += dy ;
dx = exp(yy+dy)-exp(yy) ;
ep = MinPairEnergy*exp(c*x) ;
CrossSection += ep*dx*ComputeDMicroscopicCrossSection(ParticleType,
KineticEnergy,AtomicNumber,ep);
if(nbin<NBIN)
{
nbin += 1 ;
epbin[nbin]=ep;
xbin[nbin]=x;
prbin[nbin]=CrossSection ;
ya[nbin]=y ;
proba[iz][it][nbin] = CrossSection ;
}
}
if(CrossSection > 0.)
{
for(G4int ib=0; ib<=nbin; ib++)
{
prbin[ib] /= CrossSection ;
proba[iz][it][ib] /= CrossSection ;
}
}
}
}
}
G4double G4MuPairProduction::ComputeDDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy, G4double AtomicNumber,
G4double PairEnergy,G4double asymmetry)
// Calculates the double differential (DD) microscopic cross section
// using the cross section formula of R.P. Kokoulin (18/01/98)
{
G4double sqrte = sqrt(exp(1.)) ;
G4double bbbtf= 183. ;
G4double bbbh = 202.4 ;
G4double g1tf = 1.95e-5 ;
G4double g2tf = 5.3e-5 ;
G4double g1h = 4.4e-5 ;
G4double g2h = 4.8e-5 ;
G4double massratio = ParticleMass/electron_mass_c2 ;
G4double massratio2 = massratio*massratio ;
G4double TotalEnergy = KineticEnergy + ParticleMass ;
G4double z13 = exp(log(AtomicNumber)/3.) ;
G4double z23 = z13*z13 ;
G4double EnergyLoss = TotalEnergy - PairEnergy ;
G4double c3 = 3.*sqrte*ParticleMass/4. ;
G4double DDCrossSection = 0. ;
if(EnergyLoss <= c3*z13)
return DDCrossSection ;
G4double c7 = 4.*electron_mass_c2 ;
G4double c8 = 6.*ParticleMass*ParticleMass ;
G4double alf = c7/PairEnergy ;
G4double a3 = 1. - alf ;
if(a3 <= 0.)
return DDCrossSection ;
// zeta calculation
G4double bbb,g1,g2,zeta1,zeta2,zeta,z2 ;
if( AtomicNumber < 1.5 )
{
bbb = bbbh ;
g1 = g1h ;
g2 = g2h ;
}
else
{
bbb = bbbtf ;
g1 = g1tf ;
g2 = g2tf ;
}
zeta1 = 0.073 * log(TotalEnergy/(ParticleMass+g1*z23*TotalEnergy))-0.26 ;
if( zeta1 > 0.)
{
zeta2 = 0.058*log(TotalEnergy/(ParticleMass+g2*z13*TotalEnergy))-0.14 ;
zeta = zeta1/zeta2 ;
}
else
{
zeta = 0. ;
}
z2 = AtomicNumber*(AtomicNumber+zeta) ;
G4double screen0 = 2.*electron_mass_c2*sqrte*bbb/(z13*PairEnergy) ;
G4double a0 = TotalEnergy*EnergyLoss ;
G4double a1 = PairEnergy*PairEnergy/a0 ;
G4double bet = 0.5*a1 ;
G4double xi0 = 0.25*massratio2*a1 ;
G4double del = c8/a0 ;
G4double romin = 0. ;
G4double romax = (1.-del)*sqrt(1.-c7/PairEnergy) ;
if((asymmetry < romin) || (asymmetry > romax))
return DDCrossSection ;
G4double a4 = 1.-asymmetry ;
G4double a5 = a4*(2.-a4) ;
G4double a6 = 1.-a5 ;
G4double a7 = 1.+a6 ;
G4double a9 = 3.+a6 ;
G4double xi = xi0*a5 ;
G4double xii = 1./xi ;
G4double xi1 = 1.+xi ;
G4double screen = screen0*xi1/a5 ;
G4double yeu = 5.-a6+4.*bet*a7 ;
G4double yed = 2.*(1.+3.*bet)*log(3.+xii)-a6-a1*(2.-a6) ;
G4double yel = 1.+yeu/yed ;
G4double ale=log(bbb/z13*sqrt(xi1*yel)/(1.+screen*yel)) ;
G4double cre = 0.5*log(1.+2.25/(massratio2*z23)*xi1*yel) ;
G4double be ;
if(xi <= 1.e3)
be = ((2.+a6)*(1.+bet)+xi*a9)*log(1.+xii)+(a5-bet)/xi1-a9;
else
be = (3.-a6+a1*a7)/(2.+xi) ;
G4double fe = (ale-cre)*be ;
if( fe < 0.)
fe = 0. ;
G4double ymu = 4.+a6 +3.*bet*a7 ;
G4double ymd = a7*(1.5+a1)*log(3.+xi)+1.-1.5*a6 ;
G4double ym1 = 1.+ymu/ymd ;
G4double alm_crm = log(bbb*massratio/(1.5*z23*(1.+screen*ym1))) ;
G4double a10,bm ;
if( xi >= 1.e-3)
{
a10 = (1.+a1)*a5 ;
bm = (a7*(1.+1.5*bet)-a10*xii)*log(xi1)+xi*(a5-bet)/xi1+a10 ;
}
else
bm = (5.-a6+bet*a9)*(xi/2.) ;
G4double fm = alm_crm*bm ;
if( fm < 0.)
fm = 0. ;
DDCrossSection = (fe+fm/massratio2) ;
DDCrossSection *= 4.*fine_structure_const*fine_structure_const
*classic_electr_radius*classic_electr_radius/(3.*pi) ;
DDCrossSection *= z2*EnergyLoss/(TotalEnergy*PairEnergy) ;
return DDCrossSection ;
}
G4double G4MuPairProduction::ComputeDMicroscopicCrossSection(
const G4ParticleDefinition* ParticleType,
G4double KineticEnergy, G4double AtomicNumber,
G4double PairEnergy)
// Calculates the differential (D) microscopic cross section
// using the cross section formula of R.P. Kokoulin (18/01/98)
{
static const G4double
xgi[] ={ 0.0199,0.1017,0.2372,0.4083,0.5917,0.7628,0.8983,0.9801 };
static const G4double
wgi[] ={ 0.0506,0.1112,0.1569,0.1813,0.1813,0.1569,0.1112,0.0506 };
G4double TotalEnergy = KineticEnergy + ParticleMass ;
G4double EnergyLoss = TotalEnergy - PairEnergy ;
G4double a = 6.*ParticleMass*ParticleMass/(TotalEnergy*EnergyLoss) ;
G4double b = 4.*electron_mass_c2/PairEnergy ;
G4double tmn=log((b+2.*a*(1.-b))/(1.+(1.-a)*sqrt(1.-b))) ;
G4double DCrossSection = 0. ;
G4double ro ;
// Gaussian integration in ln(1-ro) ( with 8 points)
for (G4int i=0; i<7; i++)
{
ro = 1.-exp(tmn*xgi[i]) ;
DCrossSection += (1.-ro)*ComputeDDMicroscopicCrossSection(
ParticleType,KineticEnergy,
AtomicNumber,PairEnergy,ro)
*wgi[i] ;
}
DCrossSection *= -tmn ;
return DCrossSection ;
}
G4VParticleChange* G4MuPairProduction::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData)
{
static const G4double esq = sqrt(exp(1.));
aParticleChange.Initialize(trackData);
G4Material* aMaterial=trackData.GetMaterial() ;
const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
G4ParticleMomentum ParticleDirection =
aDynamicParticle->GetMomentumDirection();
// e-e+ cut in this material
G4double ElectronEnergyCut =
(G4Electron::GetCutsInEnergy())[aMaterial->GetIndex()];
G4double PositronEnergyCut =
(G4Electron::GetCutsInEnergy())[aMaterial->GetIndex()];
G4double CutInPairEnergy = ElectronEnergyCut + PositronEnergyCut ;
G4double MinPairEnergy = 4.*electron_mass_c2 ;
if (CutInPairEnergy < MinPairEnergy) CutInPairEnergy = MinPairEnergy ;
// check against insufficient energy
if (KineticEnergy < CutInPairEnergy )
{
aParticleChange.SetMomentumChange( ParticleDirection );
aParticleChange.SetEnergyChange( KineticEnergy );
aParticleChange.SetLocalEnergyDeposit (0.);
aParticleChange.SetNumberOfSecondaries(0);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
// select randomly one element constituing the material
G4Element* anElement = SelectRandomAtom(aMaterial);
// limits of the energy sampling
G4double TotalEnergy = KineticEnergy + ParticleMass ;
G4double TotalMomentum = sqrt(KineticEnergy*(TotalEnergy+ParticleMass)) ;
G4double Z3 = anElement->GetIonisation()->GetZ3() ;
G4double MaxPairEnergy = TotalEnergy-0.75*esq*ParticleMass*Z3 ;
if(MinPairEnergy >= MaxPairEnergy)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// sample e-e+ energy, pair energy first
G4double PairEnergy,xc,x,yc,y ;
G4int iZ,iT,iy ;
// select sampling table ;
G4double lnZ = log(anElement->GetZ()) ;
G4double delmin = 1.e10 ;
G4double del ;
G4int izz,itt,NBINminus1 ;
NBINminus1 = NBIN-1 ;
for (G4int iz=0; iz<nzdat; iz++)
{
del = abs(lnZ-log(zdat[iz])) ;
if(del<delmin)
{
delmin=del ;
izz=iz ;
}
}
delmin = 1.e10 ;
for (G4int it=0; it<ntdat; it++)
{
del = abs(log(KineticEnergy)-log(tdat[it])) ;
if(del<delmin)
{
del=delmin;
itt=it ;
}
}
xc = log(CutInPairEnergy/MinPairEnergy)/log(MaxPairEnergy/MinPairEnergy) ;
yc = log(xc) ;
iy = -1 ;
do {
iy += 1 ;
} while ((ya[iy] < yc )&&(iy < NBINminus1)) ;
G4double norm = 1./(1.-proba[izz][itt][iy]) ;
G4double r = G4UniformRand() ;
iy = -1 ;
do {
iy += 1 ;
} while (((norm*proba[izz][itt][iy]) < r)&&(iy < NBINminus1)) ;
//sampling is uniformly in y in the bin
if( iy < NBINminus1 )
y = ya[iy] + G4UniformRand() * ( ya[iy+1] - ya[iy]) ;
else
y = ya[iy] ;
x = exp(y) ;
PairEnergy = MinPairEnergy*exp(x*log(MaxPairEnergy/MinPairEnergy)) ;
// sample r=(E+-E-)/PairEnergy ( uniformly .....)
G4double rmax = (1.-6.*ParticleMass*ParticleMass/(TotalEnergy*
(TotalEnergy-PairEnergy)))
*sqrt(1.-MinPairEnergy/PairEnergy) ;
r = rmax * (-1.+2.*G4UniformRand()) ;
// compute energies from PairEnergy,r
G4double ElectronEnergy=(1.-r)*PairEnergy/2. ;
G4double PositronEnergy=(1.+r)*PairEnergy/2. ;
// angles of the emitted particles ( Z - axis along the parent particle)
// (mean theta for the moment)
G4double Teta = electron_mass_c2/TotalEnergy ;
G4double Phi = twopi * G4UniformRand() ;
G4double dirx = sin(Teta)*cos(Phi) , diry = sin(Teta)*sin(Phi) ,
dirz = cos(Teta) ;
G4double LocalEnerDeposit = 0. ;
G4int numberofsecondaries = 1 ;
G4int flagelectron = 0 ;
G4int flagpositron = 1 ;
G4DynamicParticle *aParticle1,*aParticle2 ;
G4double ElectronMomentum , PositronMomentum ;
G4double finalPx,finalPy,finalPz ;
G4double ElectKineEnergy = ElectronEnergy - electron_mass_c2 ;
if((ElectKineEnergy > ElectronEnergyCut) ||
(G4EnergyLossTables::GetRange(
G4Electron::Electron(),ElectKineEnergy,aMaterial) >=
stepData.GetPostStepPoint()->GetSafety()))
{
numberofsecondaries += 1 ;
flagelectron = 1 ;
ElectronMomentum = sqrt(ElectKineEnergy*
(ElectronEnergy+electron_mass_c2));
G4ThreeVector ElectDirection ( dirx, diry, dirz );
ElectDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for the particle1
aParticle1= new G4DynamicParticle (G4Electron::Electron(),
ElectDirection, ElectKineEnergy);
}
else
{ LocalEnerDeposit += ElectKineEnergy ; }
// the e+ is always created (even with Ekine=0) for further annihilation.
G4double PositKineEnergy = PositronEnergy - electron_mass_c2 ;
PositronMomentum = sqrt(PositKineEnergy*(PositronEnergy+electron_mass_c2));
if((PositKineEnergy < PositronEnergyCut) &&
(G4EnergyLossTables::GetRange(
G4Positron::Positron(),PositKineEnergy,aMaterial) <=
stepData.GetPostStepPoint()->GetSafety()))
{
LocalEnerDeposit += PositKineEnergy ;
PositKineEnergy = 0. ;
}
G4ThreeVector PositDirection ( -dirx, -diry, dirz );
PositDirection.rotateUz(ParticleDirection);
// create G4DynamicParticle object for the particle2
aParticle2= new G4DynamicParticle (G4Positron::Positron(),
PositDirection, PositKineEnergy);
// fill particle change and update initial particle
aParticleChange.SetNumberOfSecondaries(numberofsecondaries) ;
if(flagelectron==1)
aParticleChange.AddSecondary( aParticle1 ) ;
if(flagpositron==1)
aParticleChange.AddSecondary( aParticle2 ) ;
G4double NewKinEnergy = KineticEnergy - ElectronEnergy - PositronEnergy ;
G4double finalMomentum=sqrt(NewKinEnergy*
(NewKinEnergy+2.*ParticleMass)) ;
aParticleChange.SetMomentumChange( ParticleDirection );
G4double KinEnergyCut = (aDynamicParticle->GetDefinition()->
GetEnergyCuts())[aMaterial->GetIndex()];
if (NewKinEnergy > KinEnergyCut)
{
aParticleChange.SetEnergyChange( NewKinEnergy );
}
else
{
aParticleChange.SetEnergyChange(0.);
LocalEnerDeposit += NewKinEnergy ;
aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetLocalEnergyDeposit( LocalEnerDeposit ) ;
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
G4Element* G4MuPairProduction::SelectRandomAtom(G4Material* aMaterial) const
{
// select randomly 1 element within the material
const G4int Index = aMaterial->GetIndex();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
G4double rval = G4UniformRand()*((*PartialSumSigma(Index))
(NumberOfElements-1));
for ( G4int i=0; i < NumberOfElements; i++ )
{
if (rval <= (*PartialSumSigma(Index))(i)) return ((*theElementVector)(i));
}
cout << " WARNING !!! - The Material '"<< aMaterial->GetName()
<< "' has no elements, NULL pointer returned." << endl;
return NULL;
}
void G4MuPairProduction::PrintInfoDefinition()
{
G4String comments = "cross sections from R. Kokoulin \n ";
comments += " Good description up to 1000 TeV.";
G4cout << endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}