Import Geant4 2.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 15:42:07 +02:00
parent 103bda00c8
commit e7d7193284
3106 changed files with 171117 additions and 90550 deletions
@@ -0,0 +1,51 @@
$Id: History,v 1.1 2000/05/24 15:36:10 maire Exp $
-------------------------------------------------------------------
=========================================================
Geant4 - an Object-Oriented Toolkit for Simulation in HEP
=========================================================
Category History file
---------------------
This file should be used by G4 developers and category coordinators
to briefly summarize all major modifications introduced in the code
and keep track of all category-tags.
It DOES NOT substitute the CVS log-message one should put at every
committal in the CVS repository !
----------------------------------------------------------
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
24 may 00: mma (utils-V01-01-02)
- merge "plus" processes into standard
27 apr 00 mma (em-V01-01-01)
- G4endl (dec/iso)
26 apr 00 mma (em-V01-01-00)
- all EnergyLoss classes renamed G4V...
Most classes in standard and muons affected.
- G4Muls moved in utils
- bugs fixe in MuPairProduction
- cowork with geant4-01-01-ref-02
02 mar 00 mma (em-V01-00-00)
- new G4VEnergyLoss class and related structure
- cowork with geant4-01-00-ref-06
10 nov 99 mma (em-V00-01-03)
- migration to STL: remove RWT hash dictionnary
14th June 1999 John Allison (em-01-00-05b)
- Muon corrections in G4MultipleScattering.cc, G4MuBremsstrahlung.cc
and G4MuPairProduction.cc by Laszlo Urban, Pedro Arce.
(Also in rocesses/photoleplon_hadron/src/G4MuNuclearInteraction.cc.)
5th June 1999 John Allison
- standard/GNUmakefile: Force non-optimised compliation of some
files on HP with aCC: HP ANSI C++ B3910B A.01.15.
May 29, 1999: John Allison
- Added electromagnetic/lowenergy to GNUmakefile and
electromagnetic/GNUmakefile..
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4EnergyLossTables.hh,v 1.8.2.1.2.1 1999/12/09 10:28:49 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4EnergyLossTables.hh,v 1.9 1999/12/15 14:52:01 gunter Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
//
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4EnergyLossTables.icc,v 1.7.2.1 1999/12/07 20:51:21 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4EnergyLossTables.icc,v 1.11 2000/05/23 14:24:47 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// Inline members of the G4EnergyLossTables class
@@ -138,7 +138,8 @@ inline G4double G4EnergyLossTables::GetDEDX(
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
dEdx =(*dEdxTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
t.theLowestKineticEnergy,isOut)
*sqrt(scaledKineticEnergy/t.theLowestKineticEnergy);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
@@ -417,7 +418,7 @@ inline G4double G4EnergyLossTables::GetRange(
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
Range = scaledKineticEnergy/t.theLowestKineticEnergy*
Range = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)*
(*rangeTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
@@ -454,6 +455,7 @@ inline G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
@@ -480,7 +482,7 @@ inline G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
if(scaledrange < rmin)
{
scaledKineticEnergy = t.theLowestKineticEnergy*
scaledrange/rmin ;
scaledrange*scaledrange/(rmin*rmin) ;
}
else
{
@@ -0,0 +1,156 @@
// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IMultipleScattering.hh,v 1.1 2000/03/20 14:44:03 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// --------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// --------- G4IMultipleScattering physics process --------
// by Laszlo Urban, October 1997
// **************************************************************
// UNIVERSAL: for arbitrary single charged particle
// 09/12/98: charge can be != +- 1 !!!! L.Urban
// --------------------------------------------------------------
// *****************************************************************
// It is the first implementation of the multiple scattering process
// using an INTEGRAL APPROACH instead of the differential
// one used in the standard implementation .
// *****************************************************************
// by Laszlo Urban, 23 June 1998
// -----------------------------------------------------------------
// 27/10/98: cleanup , L.Urban
#ifndef G4IMultipleScattering_h
#define G4IMultipleScattering_h 1
#include "G4ios.hh"
#include "g4std/fstream"
#include "g4std/iomanip"
#include "globals.hh"
#include "Randomize.hh"
#include "G4EnergyLossTables.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4MuonPlus.hh"
#include "G4Proton.hh"
#include "G4PhysicsLogVector.hh"
#include "G4GPILSelection.hh"
#include "G4VContinuousDiscreteProcess.hh"
#include "G4Step.hh"
#include "G4Track.hh"
#include "G4MaterialTable.hh"
#include "G4ElementTable.hh"
#include "G4ElementVector.hh"
#include "G4VParticleChange.hh"
class G4IMultipleScattering : public G4VContinuousDiscreteProcess
{
public:
G4IMultipleScattering(const G4String& processName="Imsc") ;
~G4IMultipleScattering() ;
G4bool IsApplicable ( const G4ParticleDefinition& ) ;
void SetPhysicsTableBining(G4double lowE,G4double highE,G4int nBins);
void BuildPhysicsTable(const G4ParticleDefinition& aParticleType) ;
void BuildIntegralITable(const G4ParticleDefinition& aParticleType) ;
void BuildIntegralJTable(const G4ParticleDefinition& aParticleType) ;
G4double GetIntegralI(const G4ParticleDefinition *aParticle,
G4double KineticEnergy,G4Material* aMaterial) ;
G4double GetIntegralJ(const G4ParticleDefinition *aParticle,
G4double KineticEnergy,G4Material* aMaterial) ;
void PrintInfoDefinition();
G4double GetContinuousStepLimit(const G4Track& aTrack,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) ;
G4double GetMeanFreePath(const G4Track& aTrack,
G4double previousStepSize,
G4ForceCondition* condition) ;
G4VParticleChange* AlongStepDoIt(const G4Track& aTrack,const G4Step& aStep) ;
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,const G4Step& aStep) ;
protected:
G4double ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber) ;
G4double TrueToGeomTransformation(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
G4double truePathLength) ;
private:
// hide assignment operator as private
G4IMultipleScattering & operator = (const G4IMultipleScattering &right) ;
G4IMultipleScattering ( const G4IMultipleScattering &) ;
private:
// data members ...................................................
G4PhysicsTable* theTransportMeanFreePathTable;
G4PhysicsTable* theIntegralITable ;
G4PhysicsTable* theIntegralJTable ;
G4double fTransportMeanFreePath ;
G4double fMeanLateralDisplacement ;
G4double LowestKineticEnergy ;
G4double HighestKineticEnergy ;
G4int TotBin ;
const G4Electron* theElectron ;
const G4Positron* thePositron ;
G4Material* lastMaterial;
G4double lastKineticEnergy;
// GeomStepFinal is the geom.steplength at the end of the AlongStep loop
// the others are some 'cache' variables
G4double GeomStepFinal ;
G4double tLast,zLast,CosTheta ;
G4double biglambda ;
//parameters for low energy extrapolation of dE/dx and lambda
const G4double plowloss,plowlambda ;
G4int NumberOfBuildPhysicsTableCalls ;
G4double tuning ;
};
#include "G4IMultipleScattering.icc"
#endif
@@ -0,0 +1,268 @@
// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IMultipleScattering.icc,v 1.1 2000/03/20 14:44:03 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// -------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ------- G4IMultipleScattering physics process ------
// by Laszlo Urban, October 1997
// **************************************************************
// 25/11/97: mods for KinEnergy > HighestLimit
//---------------------------------------------------------------
// *****************************************************************
// It is the first implementation of the multiple scattering process
// using an INTEGRAL APPROACH instead of the differential
// one used in the standard implementation .
// *****************************************************************
// by Laszlo Urban, 23 June 1998
// -----------------------------------------------------------------
// 27/10/98: cleanup , L.Urban
inline G4double G4IMultipleScattering::TrueToGeomTransformation(
const G4DynamicParticle *aParticle,
G4Material *aMaterial,
G4double truePathLength)
// it sets the data member fTransportMeanFreePath and
// performs the true path length -> geometrical path length
// transformation
{
const G4double factt=1.-1.e-6,tausmall=5.e-5,taubig=50.,
minim=1.e-6,smalldroverr=1.e-2,smalldToverT=2.e-2 ;
G4double KineticEnergy,Tfinal,tau,etau,geomPathLength,range,w1,w2,ww1,ww2 ;
G4int materialIndex ;
G4bool isOut ;
KineticEnergy = aParticle->GetKineticEnergy() ;
if((lastMaterial == aMaterial) && (lastKineticEnergy == KineticEnergy))
{ ; }
else
{
lastMaterial=aMaterial;
lastKineticEnergy=KineticEnergy;
materialIndex = aMaterial->GetIndex() ;
if(KineticEnergy<LowestKineticEnergy)
{
fTransportMeanFreePath =
exp(plowlambda*log((KineticEnergy/LowestKineticEnergy)))*
(*theTransportMeanFreePathTable)
(materialIndex)->GetValue(LowestKineticEnergy,isOut);
}
else
{
if(KineticEnergy>HighestKineticEnergy)
KineticEnergy=HighestKineticEnergy;
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
}
}
// do the true -> geom transformation
if( fTransportMeanFreePath > biglambda )
{
geomPathLength = truePathLength ;
CosTheta = 1. ;
}
else
{
const G4ParticleDefinition *theParticle = aParticle->GetDefinition() ;
G4double range = G4EnergyLossTables::GetPreciseRangeFromEnergy(
theParticle,KineticEnergy,aMaterial) ;
if(truePathLength > factt*range)
{
geomPathLength = GetIntegralJ(theParticle,
KineticEnergy,aMaterial) ;
CosTheta = 0. ;
}
else
{
if(truePathLength/range < smalldroverr)
{
Tfinal = KineticEnergy - truePathLength*
G4EnergyLossTables::GetPreciseDEDX(
theParticle,KineticEnergy,aMaterial) ;
}
else
{
Tfinal = G4EnergyLossTables::GetPreciseEnergyFromRange(
theParticle,range-truePathLength,
aMaterial) ;
}
if((KineticEnergy-Tfinal)> smalldToverT)
{
w1 = GetIntegralI(theParticle,KineticEnergy,aMaterial) ;
w2 = GetIntegralI(theParticle,Tfinal ,aMaterial) ;
CosTheta = exp(w2-w1) ;
if( CosTheta < minim)
CosTheta = 0. ;
ww1 = GetIntegralJ(theParticle,KineticEnergy,aMaterial) ;
ww2 = GetIntegralJ(theParticle,Tfinal ,aMaterial) ;
geomPathLength = ww1 - ww2*CosTheta ;
}
else
{
tau = truePathLength/fTransportMeanFreePath ;
if(tau<tausmall)
etau = tau ;
else
{
if(tau>taubig)
etau = 1. ;
else
etau = 1.-exp(-tau) ;
}
geomPathLength = fTransportMeanFreePath*etau ;
CosTheta = exp(-truePathLength/fTransportMeanFreePath) ;
}
}
}
if(geomPathLength>truePathLength)
geomPathLength = truePathLength ;
tLast = truePathLength ;
zLast = geomPathLength ;
return geomPathLength ;
}
inline G4double G4IMultipleScattering::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength ;
const G4DynamicParticle* aParticle ;
// this process is not a candidate for selection!!!!!!!!!
SetGPILSelection(NotCandidateForSelection) ;
tPathLength = currentMinimumStep ;
aParticle = track.GetDynamicParticle() ;
zPathLength = TrueToGeomTransformation(aParticle,
track.GetMaterial(),tPathLength);
return zPathLength ;
}
inline G4double G4IMultipleScattering::GetMeanFreePath(const G4Track&,
G4double,
G4ForceCondition* condition)
// it does not limit the Step size , but it sets condition to
// Forced , because the PostStepDoIt always has to be called
{
*condition = Forced ;
return DBL_MAX ;
}
inline G4VParticleChange* G4IMultipleScattering::AlongStepDoIt(
const G4Track& track,const G4Step& Step)
// only a geom path->true path transformation is performed
{
const G4double Tlowlimit=100.*keV ;
const G4double fact = 1.-1.e-10 ;
//!! const G4double tausmall=5.e-5,taubig=0.9999,trueBig=5. ;
const G4double tausmall=5.e-5,taubig=0.9999,trueBig=9.21034 ;
G4double tau ,geomPathLength, truePathLength ;
aParticleChange.Initialize(track);
geomPathLength = track.GetStepLength() ;
//Store this value for later use in PostStepDoIt
GeomStepFinal = geomPathLength ;
if(geomPathLength == zLast)
{
truePathLength = tLast ;
}
else
{
if( fTransportMeanFreePath > biglambda )
{
truePathLength = track.GetStepLength() ;
CosTheta = 1. ;
}
else
{
G4double T = track.GetDynamicParticle()->GetKineticEnergy() ;
if(T < Tlowlimit)
{ // spec. low energy msc code
G4double range = G4EnergyLossTables::GetPreciseRangeFromEnergy(
track.GetDynamicParticle()->GetDefinition(),
T,track.GetMaterial()) ;
G4double alfa = 1.+range/fTransportMeanFreePath ;
G4double z = geomPathLength ;
//protection: z can not be greater than zmax !!!!!!!
G4double zmax = fact*range/alfa ;
if(z > zmax)
z = zmax ;
if(z == zmax)
{
truePathLength = range ;
CosTheta = 0. ;
}
else
{
truePathLength = range*
(1.-exp(log(1.-alfa*z/range)/alfa)) ;
CosTheta = (1.-alfa*z/range)/(1.-truePathLength/range) ;
}
}
else
{
tau = geomPathLength/fTransportMeanFreePath ;
if(tau<tausmall)
truePathLength = fTransportMeanFreePath*tau*(1.+0.5*tau) ;
else
{
if(tau<taubig)
truePathLength = -fTransportMeanFreePath*log(1.-tau) ;
else
truePathLength = fTransportMeanFreePath*trueBig ;
}
CosTheta = exp(-truePathLength/fTransportMeanFreePath) ;
}
}
}
if(truePathLength<geomPathLength)
truePathLength = geomPathLength ;
aParticleChange.SetTrueStepLength(truePathLength) ;
return &aParticleChange ;
}
inline G4bool G4IMultipleScattering::IsApplicable(
const G4ParticleDefinition& particle)
{
return(particle.GetPDGCharge() != 0.);
}
@@ -0,0 +1,159 @@
// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4MultipleScattering.hh,v 1.1 2000/03/20 14:44:04 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// --------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// --------- G4MultipleScattering physics process --------
// by Laszlo Urban, October 1997
// **************************************************************
// UNIVERSAL: for arbitrary single charged particle
// 09/12/98: charge can be != +- 1 !!!! L.Urban
// 30/09/99: nuclear size effect correction L.Urban
// --------------------------------------------------------------
// 22/10/98: cleanup , L.Urban
#ifndef G4MultipleScattering_h
#define G4MultipleScattering_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4EnergyLossTables.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4MuonPlus.hh"
#include "G4PionPlus.hh"
#include "G4Proton.hh"
#include "G4PhysicsLogVector.hh"
#include "G4GPILSelection.hh"
#include "G4VContinuousDiscreteProcess.hh"
#include "G4Step.hh"
#include "G4Track.hh"
#include "G4Material.hh"
#include "G4ParticleChangeForMSC.hh"
#include "G4UnitsTable.hh"
class G4MultipleScattering : public G4VContinuousDiscreteProcess
{
public:
G4MultipleScattering(const G4String& processName="msc") ;
~G4MultipleScattering() ;
G4bool IsApplicable ( const G4ParticleDefinition& ) ;
void SetPhysicsTableBining(G4double lowE,G4double highE,G4int nBins);
void BuildPhysicsTable(const G4ParticleDefinition& aParticleType) ;
void PrintInfoDefinition();
G4double GetContinuousStepLimit(const G4Track& aTrack,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) ;
G4double GetMeanFreePath(const G4Track& aTrack,
G4double previousStepSize,
G4ForceCondition* condition) ;
G4VParticleChange* AlongStepDoIt(const G4Track& aTrack,const G4Step& aStep);
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,const G4Step& aStep) ;
G4double GetLambda(G4double KineticEnergy,G4Material* material);
void SetScatteringParameter(G4double value)
{ scatteringparameter = value ; } ;
void SetTuning(G4double value) { tuning = value ; };
void SetCpar (G4double value) { cpar = value ; };
void SetTlimitmsc (G4double value) { Tlimit = value ; };
void SetLateralDisplacementFlag(G4bool flag) {fLatDisplFlag = flag;};
void SetNuclCorrPar(G4double val) { NuclCorrPar = val; } ;
void SetFactPar(G4double val) { FactPar = val ; } ;
protected:
G4double ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicWeight) ;
G4double TrueToGeomTransformation(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
G4double truePathLength) ;
private:
// hide assignment operator as private
G4MultipleScattering & operator = (const G4MultipleScattering &right) ;
G4MultipleScattering ( const G4MultipleScattering &) ;
// data members ...................................................
private:
G4PhysicsTable* theTransportMeanFreePathTable ;
G4double fTransportMeanFreePath ;
G4double range,alpha1 ;
G4int stepFlag ;
G4double biglambda ;
G4double LowestKineticEnergy ;
G4double HighestKineticEnergy ;
G4int TotBin ;
const G4Electron* theElectron ;
const G4Positron* thePositron ;
G4Material* lastMaterial;
G4double lastKineticEnergy;
G4int materialIndex ;
G4double tLast ;
G4double zLast ;
G4double Tlimit ;
// model parameters
G4double scatteringparameter;
G4double tuning;
G4double cpar;
// with/without lateral displacement
G4bool fLatDisplFlag ;
// nuclear size effect correction
G4double NuclCorrPar ;
G4double FactPar ;
//New ParticleChange
G4ParticleChangeForMSC fParticleChange ;
};
#include "G4MultipleScattering.icc"
#endif
@@ -0,0 +1,181 @@
// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4MultipleScattering.icc,v 1.2 2000/03/24 08:08:08 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// -------------------------------------------------------------
// GEANT 4 class inlined methods file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ------- G4MultipleScattering physics process ------
// by Laszlo Urban, October 1997
// **************************************************************
// 25/11/97: mods for KinEnergy > HighestLimit
// 22/10/98: cleanup , L.Urban
// 15/10/99: bugfix, some accuracy problems fixed , L.Urban
//---------------------------------------------------------------
inline G4double G4MultipleScattering::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength ;
const G4DynamicParticle* aParticle ;
G4Material* aMaterial ;
G4double KineticEnergy,tau ;
G4bool isOut ;
// this process is not a candidate for selection!!!!!!!!!
SetGPILSelection(NotCandidateForSelection) ;
if(track.GetCurrentStepNumber() == 1)
stepFlag = 0 ;
tPathLength = currentMinimumStep ;
aMaterial = track.GetMaterial() ;
materialIndex = aMaterial->GetIndex() ;
aParticle = track.GetDynamicParticle() ;
KineticEnergy = aParticle->GetKineticEnergy() ;
if((lastMaterial != aMaterial) || (lastKineticEnergy != KineticEnergy))
{
lastKineticEnergy = KineticEnergy ;
materialIndex = aMaterial->GetIndex() ;
if((lastMaterial != aMaterial)||(KineticEnergy >= Tlimit)||(stepFlag != 1))
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
lastMaterial = aMaterial;
if(KineticEnergy < Tlimit)
{
stepFlag = 1 ;
range = G4EnergyLossTables::GetRange(aParticle->GetDefinition(),
KineticEnergy,aMaterial) ;
alpha1 = range/fTransportMeanFreePath+1 ;
}
}
// do the true -> geom transformation
if( fTransportMeanFreePath > biglambda )
{
zPathLength = tPathLength ;
}
else if(stepFlag == 0)
{
tau = tPathLength/fTransportMeanFreePath ;
if(tau < perMillion)
zPathLength = tPathLength ;
else
zPathLength = fTransportMeanFreePath*(1.-exp(-tau)) ;
}
else
{
tau = tPathLength/range ;
if(tau<perMillion)
zPathLength = range*(1.-exp(-alpha1*tau))/alpha1 ;
else if(tau<0.99)
zPathLength = range*(1.-exp(alpha1*log(1.-tau)))/alpha1 ;
else
zPathLength = range/alpha1 ;
}
tLast = tPathLength ;
zLast = zPathLength ;
return zPathLength ;
}
inline G4double G4MultipleScattering::GetMeanFreePath(
const G4Track& track,
G4double,
G4ForceCondition* condition)
// it does not limit the Step size , but it sets condition to
// Forced , because the PostStepDoIt always has to be called
{
*condition = Forced ;
return DBL_MAX ;
}
inline G4VParticleChange* G4MultipleScattering::AlongStepDoIt(
const G4Track& track,const G4Step& Step)
// only a geom path->true path transformation is performed
{
static const G4double tfacmx = 10. ;
G4double tau,geomPathLength, truePathLength ;
fParticleChange.Initialize(track);
geomPathLength = track.GetStepLength() ;
if(geomPathLength == zLast)
{
truePathLength = tLast ;
}
else if( fTransportMeanFreePath > biglambda )
{
truePathLength = geomPathLength ;
}
else if(stepFlag == 0)
{
tau = geomPathLength/fTransportMeanFreePath ;
if(tau<perMillion)
truePathLength = fTransportMeanFreePath*tau ;
else if(tau < 1.)
truePathLength = -fTransportMeanFreePath*log(1.-tau) ;
else
truePathLength = tfacmx*fTransportMeanFreePath ;
}
else
{
if(geomPathLength/range < perMillion)
truePathLength = range*(1.-exp(-geomPathLength/range)) ;
else
truePathLength = range*(1.-exp(log(1.-alpha1*geomPathLength/range)/
alpha1)) ;
}
fParticleChange.SetTrueStepLength(truePathLength) ;
return &fParticleChange ;
}
inline G4bool G4MultipleScattering::IsApplicable(
const G4ParticleDefinition& particle)
{
return(particle.GetPDGCharge() != 0.);
}
inline G4double G4MultipleScattering::GetLambda(
G4double KineticEnergy,
G4Material* material)
{
G4bool isOut;
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
G4double lambda = (*theTransportMeanFreePathTable)
(material->GetIndex())->
GetValue(KineticEnergy,isOut);
return lambda;
}
@@ -0,0 +1,224 @@
// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4VEnergyLoss.hh,v 1.5 2000/05/23 14:24:48 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// ------------------------------------------------------------
// GEANT 4 class header file
//
// For information related to this code contact:
// CERN, CN Division, ASD group
//
// Class Description
//
// General service class for the energy loss classes
//
// It contains code needed to compute the range tables,
// time tables, the inverse range tables and some auxiliary
// tables.
// The energy loss fluctuation code is here,too.
//
// All the EnergyLoss classes are inherited from G4VEnergyLoss
// class.
//
// -----------------------------------------------------------
// created on 28 January 2000 by L. Urban
// -----------------------------------------------------------
#ifndef G4VEnergyLoss_h
#define G4VEnergyLoss_h 1
#include "globals.hh"
#include "G4ios.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4Electron.hh"
#include "G4VContinuousDiscreteProcess.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsLinearVector.hh"
class G4VEnergyLoss : public G4VContinuousDiscreteProcess
{
public:
G4VEnergyLoss(const G4String& ,
G4ProcessType aType = fNotDefined );
G4VEnergyLoss(G4VEnergyLoss &);
virtual ~G4VEnergyLoss();
virtual G4double GetContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) = 0 ;
virtual G4VParticleChange* AlongStepDoIt(const G4Track& track,
const G4Step& Step) = 0 ;
virtual G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition) = 0;
virtual G4VParticleChange* PostStepDoIt(const G4Track& track,
const G4Step& Step) = 0;
protected:// with description
// code for the energy loss fluctuation
G4double GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
G4double threshold);
private:
// hide default constructor and assignment operator as private
G4VEnergyLoss();
G4VEnergyLoss & operator=(const G4VEnergyLoss &right);
protected:
// data members to speed up the fluctuation calculation
G4Material* lastMaterial;
G4int imat;
G4double f1Fluct,f2Fluct,e1Fluct,e2Fluct,rateFluct,ipotFluct;
G4double e1LogFluct,e2LogFluct,ipotLogFluct;
const G4int nmaxCont1,nmaxCont2 ;
// static part of the class
public: // With description
static void SetRndmStep (G4bool value) {rndmStepFlag = value;}
// use / do not use randomisation in energy loss steplimit
// ( default = no randomisation)
static void SetEnlossFluc (G4bool value) {EnlossFlucFlag = value;}
// compute energy loss with/without fluctuation
// ( default : with fluctuation)
static void SetSubSec (G4bool value) {subSecFlag = value ; }
// switch on/off the generation of the subcutoff secondaries
// ( default = subcutoff secondary generation )
static void SetStepFunction (G4double c1, G4double c2)
{dRoverRange = c1; finalRange = c2;
c1lim=dRoverRange ;
c2lim=2.*(1-dRoverRange)*finalRange;
c3lim=-(1.-dRoverRange)*finalRange*finalRange;
}
// sets values for data members used to compute the step limit:
// dRoverRange : max. relative range change in one step,
// finalRange : if range <= finalRange --> last step for the particle.
protected: // With description
// Build range table starting from the DEDXtable
static G4PhysicsTable*
BuildRangeTable(G4PhysicsTable* theDEDXTable,
G4PhysicsTable* theRangeTable,
G4double Tmin,G4double Tmax,G4int nbin);
// Build time tables starting from the DEDXtable
static G4PhysicsTable*
BuildLabTimeTable(G4PhysicsTable* theDEDXTable,
G4PhysicsTable* theLabTimeTable,
G4double Tmin,G4double Tmax,G4int nbin);
static G4PhysicsTable*
BuildProperTimeTable(G4PhysicsTable* theDEDXTable,
G4PhysicsTable* ProperTimeTable,
G4double Tmin,G4double Tmax,G4int nbin);
// Build tables of coefficients needed for inverting the range table
static G4PhysicsTable*
BuildRangeCoeffATable(G4PhysicsTable* theRangeTable,
G4PhysicsTable* theCoeffATable,
G4double Tmin,G4double Tmax,G4int nbin);
static G4PhysicsTable*
BuildRangeCoeffBTable(G4PhysicsTable* theRangeTable,
G4PhysicsTable* theCoeffBTable,
G4double Tmin,G4double Tmax,G4int nbin);
static G4PhysicsTable*
BuildRangeCoeffCTable(G4PhysicsTable* theRangeTable,
G4PhysicsTable* theCoeffCTable,
G4double Tmin,G4double Tmax,G4int nbin);
// Invert range table
static G4PhysicsTable*
BuildInverseRangeTable(G4PhysicsTable* theRangeTable,
G4PhysicsTable* theRangeCoeffATable,
G4PhysicsTable* theRangeCoeffBTable,
G4PhysicsTable* theRangeCoeffCTable,
G4PhysicsTable* theInverseRangeTable,
G4double Tmin,G4double Tmax,G4int nbin);
private:
static void BuildRangeVector(G4PhysicsTable* theDEDXTable,
G4double Tmin,G4double Tmax,G4int nbin,
G4int materialIndex,G4PhysicsLogVector* rangeVector);
static G4double RangeIntLin(G4PhysicsVector* physicsVector
,G4int nbin);
static G4double RangeIntLog(G4PhysicsVector* physicsVector
,G4int nbin);
static void BuildLabTimeVector(G4PhysicsTable* theDEDXTable,
G4double Tmin,G4double Tmax,G4int nbin,
G4int materialIndex,G4PhysicsLogVector* rangeVector);
static void BuildProperTimeVector(G4PhysicsTable* theDEDXTable,
G4double Tmin,G4double Tmax,G4int nbin,
G4int materialIndex,G4PhysicsLogVector* rangeVector);
static G4double LabTimeIntLog(G4PhysicsVector* physicsVector
,G4int nbin);
static G4double ProperTimeIntLog(G4PhysicsVector* physicsVector,
G4int nbin);
static void InvertRangeVector(G4PhysicsTable* theRangeTable,
G4PhysicsTable* theRangeCoeffATable,
G4PhysicsTable* theRangeCoeffBTable,
G4PhysicsTable* theRangeCoeffCTable,
G4double Tmin,G4double Tmax,G4int nbin,
G4int materialIndex,G4PhysicsLogVector* rangeVector);
// data members
protected:
// variables for the integration routines
static G4double ParticleMass,taulow,tauhigh,ltaulow,ltauhigh;
static G4double dRoverRange; // dRoverRange is the maximum allowed
// deltarange/range in one Step
static G4double finalRange; // final step before stopping
static G4double c1lim,c2lim,c3lim ; // coeffs for computing steplimit
static G4bool rndmStepFlag; // control the randomization of the step
static G4bool EnlossFlucFlag; // control the energy loss fluctuation
static G4bool subSecFlag; // control the generation of subcutoff secondaries
};
#endif
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4EnergyLossTables.cc,v 1.9.2.1 1999/12/07 20:51:22 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
// $Id: G4EnergyLossTables.cc,v 1.12 2000/05/23 14:25:26 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// -------------------------------------------------------------------
// first version created by P.Urban , 06/04/1998
@@ -80,7 +80,8 @@ void G4EnergyLossTables::Register(
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
dEdx = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)
*(*dEdxTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
@@ -128,7 +129,7 @@ void G4EnergyLossTables::Register(
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
Range = scaledKineticEnergy/t.theLowestKineticEnergy*
Range = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)*
(*rangeTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
@@ -0,0 +1,820 @@
// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4IMultipleScattering.cc,v 1.1 2000/03/20 14:44:04 maire Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4IMultipleScattering physics process ------------
// by Laszlo Urban, October 1997
// **************************************************************
// 09/12/98: charge can be != +- 1 !!!! L.Urban
// ************************************************************
// It is the first implementation of the
// MULTIPLESCATTERING PROCESS
// using an INTEGRAL APPROACH instead of the differential
// one used in the standard implementation .
// ************************************************************
// by Laszlo Urban, 23 June 1998
// ---------------------------------------------------------------
// 27/10/98: cleanup , L. Urban
#include "G4IMultipleScattering.hh"
#include "G4UnitsTable.hh"
G4IMultipleScattering::G4IMultipleScattering(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(NULL),
theIntegralITable(NULL),
theIntegralJTable(NULL),
lastMaterial(NULL),
lastKineticEnergy(-1.*MeV),
fTransportMeanFreePath(1.e12),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
NumberOfBuildPhysicsTableCalls(0),
theElectron(G4Electron::Electron()),
thePositron(G4Positron::Positron()),
plowloss ( 0.5 ),
plowlambda ( 0.4 ),
tLast (0.0),
zLast (0.0),
CosTheta (1.0),
biglambda ( 1.e10*mm),
tuning(1.0)
{ }
G4IMultipleScattering::~G4IMultipleScattering()
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
if(theIntegralITable)
{
theIntegralITable->clearAndDestroy() ;
delete theIntegralITable ;
}
if(theIntegralJTable)
{
theIntegralJTable->clearAndDestroy() ;
delete theIntegralJTable ;
}
}
void G4IMultipleScattering::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
{
NumberOfBuildPhysicsTableCalls += 1 ;
if(NumberOfBuildPhysicsTableCalls == 1)
{ ; }
else
{
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius ;
G4double KineticEnergy,AtomicNumber,sigma,lambda ;
G4double density ;
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
G4int numOfMaterials = theMaterialTable->length() ;
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials) ;
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() ;
density = material->GetDensity() ;
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
sigma = 0. ;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
AtomicNumber = (*theElementVector)(iel)->GetZ() ;
sigma += theAtomicNumDensityVector[iel]*
ComputeTransportCrossSection(aParticleType,
KineticEnergy,AtomicNumber) ;
}
sigma *= sigmafactor ;
lambda = 1./sigma ;
aVector->PutValue(i,lambda) ;
}
theTransportMeanFreePathTable->insert(aVector) ;
}
BuildIntegralITable(aParticleType) ;
BuildIntegralJTable(aParticleType) ;
NumberOfBuildPhysicsTableCalls = 0 ;
if( (&aParticleType == G4Electron::Electron()) ||
(&aParticleType == G4MuonPlus::MuonPlus()) ||
(&aParticleType == G4Proton::Proton()) )
{
PrintInfoDefinition() ;
}
}
}
void G4IMultipleScattering::BuildIntegralITable(
const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
G4Material* aMaterial ;
G4double fmin,lmin,Value,KineticEnergy,lambda,Tlast,Vlast ;
G4double u,umax,du,t,coeff,dEdx ;
G4int n,nmax ;
G4bool isOut ;
const G4int nb = 100 ;
G4double rmin ;
if(theIntegralITable)
{
theIntegralITable->clearAndDestroy() ;
delete theIntegralITable ;
}
G4int numOfMaterials = theMaterialTable->length() ;
theIntegralITable = new G4PhysicsTable(numOfMaterials) ;
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin) ;
aMaterial = (*theMaterialTable)(J) ;
rmin = G4EnergyLossTables::GetPreciseRangeFromEnergy(
&aParticleType,
LowestKineticEnergy,
aMaterial) ;
lmin = (*theTransportMeanFreePathTable)(J)->
GetValue(LowestKineticEnergy,isOut) ;
// this value comes from z=r*l/(r+l) = exp(-I) !!!
Value = -log(rmin*lmin/(rmin+lmin)) ;
aVector->PutValue(0,Value) ;
Tlast = LowestKineticEnergy ;
Vlast = Value ;
for (G4int i=1; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
umax = log(KineticEnergy/Tlast) ;
nmax = int(nb*umax + 0.5) ;
if(nmax<1)
nmax = 1 ;
du = umax/nmax ;
Value = 0. ;
u = -du ;
for(n=0; n<=nmax; n++)
{
u += du ;
t = Tlast*exp(u) ;
lambda = (*theTransportMeanFreePathTable)(J)->
GetValue(t,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(&aParticleType,
t,aMaterial) ;
if((n == 0) || (n == nmax))
coeff = 0.5 ;
else
coeff = 1. ;
Value += coeff*t/(dEdx*lambda) ;
}
Value *= du ;
Value += Vlast ;
aVector->PutValue(i,Value) ;
Tlast = KineticEnergy ;
Vlast = Value ;
}
theIntegralITable->insert(aVector) ;
}
}
void G4IMultipleScattering::BuildIntegralJTable(
const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable() ;
G4Material* aMaterial ;
G4double rmin,lmin,Value,KineticEnergy,lambda,Tlast,Vlast ;
G4double u,umax,du,t,coeff,dEdx,w,ww ;
G4double cmin,lndu ;
G4int n,nmax ;
G4bool isOut ;
const G4int nb = 100 ;
if(theIntegralJTable)
{
theIntegralJTable->clearAndDestroy() ;
delete theIntegralJTable ;
}
G4int numOfMaterials = theMaterialTable->length() ;
theIntegralJTable = new G4PhysicsTable(numOfMaterials) ;
for (G4int J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin) ;
aMaterial = (*theMaterialTable)(J) ;
rmin = G4EnergyLossTables::GetPreciseRangeFromEnergy(
&aParticleType,
LowestKineticEnergy,
aMaterial) ;
lmin = (*theTransportMeanFreePathTable)(J)->
GetValue(LowestKineticEnergy,isOut) ;
Value = rmin*lmin/(rmin+lmin) ;
aVector->PutValue(0,Value) ;
Tlast = LowestKineticEnergy ;
Vlast = Value ;
for (G4int i=1; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
umax = log(KineticEnergy/Tlast) ;
nmax =int(nb*umax + 0.5) ;
if(nmax<1)
nmax = 1 ;
du = umax/nmax ;
Value = 0. ;
u = -du ;
for(n=0; n<=nmax; n++)
{
u += du ;
t = Tlast*exp(u) ;
w = (*theIntegralITable)(J)->
GetValue(t,isOut) ;
dEdx = G4EnergyLossTables::GetPreciseDEDX(&aParticleType,
t,aMaterial) ;
if((n == 0) || (n == nmax))
coeff = 0.5 ;
else
coeff = 1. ;
Value += coeff*t*exp(w)/dEdx ;
}
Value *= du ;
w = (*theIntegralITable)(J)->
GetValue(Tlast,isOut) ;
ww = (*theIntegralITable)(J)->
GetValue(KineticEnergy,isOut) ;
Value *= exp(-ww) ;
Value += exp(w-ww)*Vlast ;
aVector->PutValue(i,Value) ;
Tlast = KineticEnergy ;
Vlast = Value ;
}
theIntegralJTable->insert(aVector) ;
}
}
G4double G4IMultipleScattering::GetIntegralI(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
G4Material* aMaterial)
{
G4double intI ;
G4bool isOut ;
if(KineticEnergy < LowestKineticEnergy)
{
intI = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(LowestKineticEnergy,isOut) ;
intI *= exp((1.-plowloss-plowlambda)*
log(KineticEnergy/LowestKineticEnergy)) ;
}
else if(KineticEnergy <= HighestKineticEnergy)
{
intI = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(KineticEnergy,isOut) ;
}
else
{
intI = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut) ;
intI += (KineticEnergy-HighestKineticEnergy)/
((*theTransportMeanFreePathTable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut)
*
G4EnergyLossTables::GetPreciseDEDX(aParticle,
HighestKineticEnergy,aMaterial)) ;
}
return intI ;
}
G4double G4IMultipleScattering::GetIntegralJ(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
G4Material* aMaterial)
{
G4double intJ,lmin,lmax,fmax,Imin,Imin2,t ;
G4bool isOut ;
if(KineticEnergy < LowestKineticEnergy)
{
lmin = (*theTransportMeanFreePathTable)(aMaterial->GetIndex())->
GetValue(KineticEnergy,isOut) ;
Imin = (*theIntegralITable)(aMaterial->GetIndex())->
GetValue(LowestKineticEnergy,isOut) ;
Imin2= Imin*Imin ;
t = exp(0.1*log(KineticEnergy/LowestKineticEnergy)) ;
intJ = (((t-4./Imin)*t+12./Imin2)*t-24./(Imin*Imin2))*t+24./(Imin2*Imin2);
intJ -= 24.*exp(-Imin*t)/(Imin2*Imin2) ;
intJ *= lmin ;
}
else if(KineticEnergy <= HighestKineticEnergy)
{
intJ = (*theIntegralJTable)(aMaterial->GetIndex())->
GetValue(KineticEnergy,isOut) ;
}
else
{
lmax = (*theTransportMeanFreePathTable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut) ;
fmax = G4EnergyLossTables::GetPreciseDEDX(aParticle,
HighestKineticEnergy,aMaterial) ;
intJ = lmax - (lmax-(*theIntegralJTable)(aMaterial->GetIndex())->
GetValue(HighestKineticEnergy,isOut))*
exp((HighestKineticEnergy-KineticEnergy)/(fmax*lmax)) ;
}
return intJ ;
}
G4double G4IMultipleScattering::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc) ;
const G4double epsmin = 1.e-4 , epsmax = 1.e10 ;
const G4double cpar=1.50 ;
const G4double Zdat[15] = {4.,6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. } ;
const G4double Tdat[22] =
{ 0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,0.01*MeV,
0.02*MeV,0.04*MeV,0.07*MeV,0.1*MeV,0.2*MeV,
0.4*MeV,0.7*MeV,1.*MeV,2.*MeV,4.*MeV,
7.*MeV,10.*MeV,20.*MeV} ;
// corr. factors for e-/e+ lambda
const G4double celectron[15][22] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, misprint?
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949 }};
const G4double cpositron[15][22] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282 }};
G4double Z23,ParticleMass,rat2,Charge,TotalEnergy,beta2,bg2,
eps,Z1,Z2,ratZ,T,E,b2small,b2big,ratb2,c1,c2,cc1,cc2,
corr,sigma,corrfactor,ChargeSquare ;
G4int iZ,iT ;
Z23 = 2.*log(AtomicNumber)/3. ;
Z23 = exp(Z23) ;
ParticleMass = aParticleType.GetPDGMass() ;
rat2 = ParticleMass/electron_mass_c2 ;
rat2 = rat2*rat2 ;
Charge = aParticleType.GetPDGCharge() ;
ChargeSquare = Charge*Charge/(eplus*eplus) ;
TotalEnergy = KineticEnergy + ParticleMass ;
beta2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(TotalEnergy*TotalEnergy) ;
bg2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(ParticleMass*ParticleMass) ;
eps = rat2*epsfactor*bg2/Z23 ;
if(eps<epsmin)
sigma = 2.*eps*eps*eps/3. ;
else if(eps<epsmax)
sigma = log(1.+2.*eps)-2.*eps/(1.+eps) ;
else
sigma = log(2.*eps)-2.+2.5/eps ;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/rat2 ;
sigma /= beta2*bg2 ;
// correct this value using the corrections computed for e+/e-
KineticEnergy *= electron_mass_c2/ParticleMass ;
// interpolate in AtomicNumber and beta2
// get bin number in Z
iZ = 14 ;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber))
{
iZ -= 1 ;
}
if(iZ==14)
{
iZ = 13 ;
}
if(iZ==-1)
{
iZ = 0 ;
}
Z1 = Zdat[iZ] ;
Z2 = Zdat[iZ+1] ;
ratZ = (AtomicNumber-Z1)/(Z2-Z1) ;
// get bin number in T (beta2)
iT = 21 ;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy))
iT -= 1 ;
if(iT==21)
iT = 20 ;
if(iT==-1)
iT = 0 ;
// calculate betasquare values
T = Tdat[iT] ;
E = T + electron_mass_c2 ;
b2small = T*(E+electron_mass_c2)/(E*E) ;
T = Tdat[iT+1] ;
E = T + electron_mass_c2 ;
b2big = T*(E+electron_mass_c2)/(E*E) ;
ratb2 = (beta2-b2small)/(b2big-b2small) ;
corrfactor = tuning*(1.+cpar)/(1.+cpar*beta2) ;
if(Charge < 0.)
{
c1 = celectron[iZ][iT] ;
c2 = celectron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = celectron[iZ][iT+1] ;
c2 = celectron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
if(Charge > 0.)
{
c1 = cpositron[iZ][iT] ;
c2 = cpositron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = cpositron[iZ][iT+1] ;
c2 = cpositron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
sigma *= corrfactor ;
return sigma ;
}
G4VParticleChange* G4IMultipleScattering::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
G4double lambdasave ;
const G4double taulim = 1.e-10 , randlim = 0.25*taulim*taulim ;
const G4double tausmall = 5.e-5,taubig =50.;
const G4double scatteringparameter=1.00 ,
kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
const G4DynamicParticle* aParticle ;
G4Material* aMaterial ;
G4int materialIndex ;
G4double KineticEnergy,truestep,tau,prob,cth,sth,phi,
dirx,diry,dirz,w,w1,etau,rmean,safetyminustolerance,
xnew,ynew,znew ;
G4double rand,rmax2 ;
G4bool isOut;
aParticleChange.Initialize(trackData) ;
aMaterial = stepData.GetPreStepPoint()->GetMaterial() ;
truestep = stepData.GetStepLength() ;
// there is no scattering for truestep=0. !
if(truestep == 0.)
return &aParticleChange ;
aParticle = trackData.GetDynamicParticle() ;
materialIndex = aMaterial->GetIndex() ;
KineticEnergy = aParticle->GetKineticEnergy() ;
// shortcut if the particle is not Alive (e.g. stopped in energy loss)
if(trackData.GetTrackStatus() != fAlive)
return &aParticleChange ;
if ((lastMaterial == aMaterial) && (lastKineticEnergy == KineticEnergy))
{
;
}
else
{
lastMaterial=aMaterial;
lastKineticEnergy=KineticEnergy;
if(KineticEnergy<LowestKineticEnergy)
{
fTransportMeanFreePath =
exp(plowlambda*log(KineticEnergy/LowestKineticEnergy))*
(*theTransportMeanFreePathTable)
(materialIndex)->GetValue(LowestKineticEnergy,isOut);
}
else
{
// TransportMeanFreePath taken at kin.energy after the energy loss!
if(KineticEnergy>HighestKineticEnergy)
KineticEnergy = HighestKineticEnergy ;
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
}
}
// effective lambda used in scattering .....................
lambdasave = fTransportMeanFreePath ;
if(CosTheta == 1.)
{
fTransportMeanFreePath = biglambda ;
tau = 0.;
cth = 1. ;
}
else if(CosTheta == 0.)
{
fTransportMeanFreePath = 0. ;
tau = biglambda ;
cth = -1.+2.*G4UniformRand() ;
}
else
{
fTransportMeanFreePath = -truestep/log(CosTheta) ;
tau = truestep/fTransportMeanFreePath ;
prob = exp(-tau)*(1.+scatteringparameter*tau) ;
if(G4UniformRand()<prob)
{
if(tau<taulim)
{
rand = G4UniformRand() ;
if(rand > randlim)
cth = 1.-tau*(1./sqrt(rand)-1.) ;
else
cth = -1. ;
}
else
{
w = 1.+scatteringparameter*tau ;
w1 = w-1. ;
cth = w-w1*(w+1.)/sqrt(w1*w1+4.*w*G4UniformRand()) ;
}
}
else
cth = -1.+2.*G4UniformRand() ;
}
sth = sqrt(1.-cth*cth) ;
phi = twopi*G4UniformRand() ;
dirx = sth*cos(phi) ;
diry = sth*sin(phi) ;
dirz = cth ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz) ;
newDirection.rotateUz(ParticleDirection) ;
aParticleChange.SetNumberOfSecondaries(0) ;
aParticleChange.SetEnergyChange( KineticEnergy ) ;
aParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z()) ;
// compute lateral displacement
// only for safety > tolerance !!!!!
safetyminustolerance = stepData.GetPostStepPoint()->GetSafety()
-kCarTolerance ;
if(safetyminustolerance > 0.)
{
if(truestep == GeomStepFinal)
{ ; }
else
{
rmax2 = (truestep+GeomStepFinal)*(truestep-GeomStepFinal) ;
if(tau<tausmall)
rmean = 5.*tau*tau*tau/12. ;
else
{
if(tau<taubig)
etau = exp(-tau) ;
else
etau = 0. ;
rmean = -kappa*tau ;
rmean = -exp(rmean)/(kappa*kappami1) ;
rmean += tau-kappapl1/kappa+kappa*etau/kappami1 ;
}
rmean *= 4.*fTransportMeanFreePath*fTransportMeanFreePath/3.;
if(rmean>rmax2)
rmean = rmax2 ;
if(rmean>0.)
{
rmean = sqrt(rmean) ;
if(rmean>safetyminustolerance)
rmean = safetyminustolerance ;
fMeanLateralDisplacement = rmean ;
// sample direction of lateral displacement
phi = twopi*G4UniformRand() ;
dirx = cos(phi) ;
diry = sin(phi) ;
dirz = 0. ;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection) ;
// compute new endpoint of the Step
xnew = stepData.GetPostStepPoint()->GetPosition().x()+
rmean*latDirection.x() ;
ynew = stepData.GetPostStepPoint()->GetPosition().y()+
rmean*latDirection.y() ;
znew = stepData.GetPostStepPoint()->GetPosition().z()+
rmean*latDirection.z() ;
aParticleChange.SetPositionChange(xnew,ynew,znew) ;
}
}
}
fTransportMeanFreePath = lambdasave ;
return &aParticleChange ;
}
void G4IMultipleScattering::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
comments += "\n New model of MSC , computes the lateral \n";
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
@@ -0,0 +1,582 @@
// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4MultipleScattering.cc,v 1.3 2000/03/24 08:12:26 urban Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
// $Id:
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// For information related to this code contact:
// CERN, IT Division, ASD Group
// History: based on object model of
// 2nd December 1995, G.Cosmo
// -------- G4MultipleScattering physics process ------------
// by Laszlo Urban, October 1997
// **************************************************************
// 24/10/97 correction in PostStepDoIt for tau << 1. L.Urban
// 09/12/98: charge can be different from +-1 !!!! L.Urban
// 29/07/99: corr. for low energy , L.Urban
// 17/09/99: corr. for high energy and/or small step , L.Urban
// 30/09/99: nuclear size effect correction, L.Urban
// 22/03/00: value of member cpar has changed! , L.Urban
// --------------------------------------------------------------
#include "G4MultipleScattering.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
G4MultipleScattering::G4MultipleScattering(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(NULL),
lastMaterial(NULL),
lastKineticEnergy(0.),
materialIndex(0),
fTransportMeanFreePath (1.e12),
range(1.e10*mm),
alpha1(5.),
stepFlag(0),
biglambda (1.e10*mm),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
TotBin(100),
theElectron(G4Electron::Electron()),
thePositron(G4Positron::Positron()),
tLast (0.0),
zLast (0.0),
Tlimit(0.*keV),
scatteringparameter(0.9),
tuning (1.00),
cpar (-0.35),
NuclCorrPar (0.0615),FactPar(0.40),
fLatDisplFlag(true)
{ }
G4MultipleScattering::~G4MultipleScattering()
{
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
}
// .........methods..............................
void G4MultipleScattering::BuildPhysicsTable(
const G4ParticleDefinition& aParticleType)
// tables are built for MATERIALS
{
// parameter for "low energy" msc (not for ions)
if((&aParticleType == G4Electron::Electron()) ||
(&aParticleType == G4Positron::Positron()) )
// Tlimit = 100.*keV ;
;
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius ;
G4double KineticEnergy,AtomicNumber,AtomicWeight,
sigma,lambda ;
G4double density ;
// destroy old tables if any
if(theTransportMeanFreePathTable)
{
theTransportMeanFreePathTable->clearAndDestroy() ;
delete theTransportMeanFreePathTable ;
}
// create table
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length() ;
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials) ;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy,HighestKineticEnergy,TotBin) ;
// get elements in the material
const G4Material* material = (*theMaterialTable)(J) ;
const G4ElementVector* theElementVector =
material->GetElementVector() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector() ;
const G4int NumberOfElements =
material->GetNumberOfElements() ;
density = material->GetDensity() ;
// loop for kinetic energy values
for (G4int i=0; i<TotBin; i++)
{
KineticEnergy = aVector->GetLowEdgeEnergy(i) ;
sigma = 0. ;
// loop for element in the material
for (G4int iel=0; iel<NumberOfElements; iel++)
{
AtomicNumber = (*theElementVector)(iel)->GetZ() ;
AtomicWeight = (*theElementVector)(iel)->GetA() ;
sigma += theAtomicNumDensityVector[iel]*
ComputeTransportCrossSection(aParticleType,
KineticEnergy,
AtomicNumber,AtomicWeight) ;
}
sigma *= sigmafactor ;
lambda = 1./sigma ;
aVector->PutValue(i,lambda) ;
}
theTransportMeanFreePathTable->insert(aVector) ;
}
if( (&aParticleType == G4Electron::Electron()) ||
(&aParticleType == G4MuonPlus::MuonPlus()) ||
(&aParticleType == G4Proton::Proton()) )
{
PrintInfoDefinition() ;
}
}
G4double G4MultipleScattering::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
G4double AtomicNumber,G4double AtomicWeight)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc) ;
const G4double epsmin = 1.e-4 , epsmax = 1.e10 ;
const G4double Zdat[15] = {4.,6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. } ;
const G4double Tdat[22] =
{ 0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,0.01*MeV,
0.02*MeV,0.04*MeV,0.07*MeV,0.1*MeV,0.2*MeV,
0.4*MeV,0.7*MeV,1.*MeV,2.*MeV,4.*MeV,
7.*MeV,10.*MeV,20.*MeV} ;
// corr. factors for e-/e+ lambda
const G4double celectron[15][22] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, misprint?
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949 }};
const G4double cpositron[15][22] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282 }};
G4double Z23,ParticleMass,rat2,Charge,TotalEnergy,beta2,bg2,
eps,Z1,Z2,ratZ,T,E,b2small,b2big,ratb2,c1,c2,cc1,cc2,
corr,sigma,corrfactor,ChargeSquare ;
G4int iZ,iT ;
Z23 = 2.*log(AtomicNumber)/3. ;
Z23 = exp(Z23) ;
ParticleMass = aParticleType.GetPDGMass() ;
rat2 = ParticleMass/electron_mass_c2 ;
rat2 = rat2*rat2 ;
Charge = aParticleType.GetPDGCharge() ;
ChargeSquare = Charge*Charge/(eplus*eplus) ;
TotalEnergy = KineticEnergy + ParticleMass ;
beta2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(TotalEnergy*TotalEnergy) ;
bg2 = KineticEnergy*(TotalEnergy+ParticleMass)/
(ParticleMass*ParticleMass) ;
eps = rat2*epsfactor*bg2/Z23 ;
if(eps<epsmin)
sigma = 2.*eps*eps*eps/3. ;
else if(eps<epsmax)
sigma = log(1.+2.*eps)-2.*eps/(1.+eps) ;
else
sigma = log(2.*eps)-2.+2.5/eps ;
sigma *=ChargeSquare*AtomicNumber*AtomicNumber/rat2 ;
sigma /= beta2*bg2 ;
// nuclear size effect correction for high energy
// ( a simple approximation at present)
G4double corrnuclsize,a,x0,w1,w2,w ;
x0 = 1. - NuclCorrPar*ParticleMass/(KineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.)) ;
if((x0 < -1.) || (KineticEnergy <= 10.*MeV))
{
x0=-1. ;
corrnuclsize = 1. ;
}
else
{
a = 1.+1./eps ;
if(eps > epsmax)
w1=log(2.*eps)+1./eps-3./(8.*eps*eps) ;
else
w1=log((a+1.)/(a-1.))-2./(a+1.) ;
w = 1./((1.-x0)*eps) ;
if(w < epsmin)
w2=-log(w)-1.+2.*w-1.5*w*w ;
else
w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0) ;
corrnuclsize = w1/w2 ;
// ####################################################
corrnuclsize = exp(-FactPar*proton_mass_c2/KineticEnergy)*
(corrnuclsize-1.)+1. ;
}
// correct this value using the corrections computed for e+/e-
KineticEnergy *= electron_mass_c2/ParticleMass ;
// interpolate in AtomicNumber and beta2
// get bin number in Z
iZ = 14 ;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber)) iZ -= 1 ;
if (iZ==14) iZ = 13 ;
if (iZ==-1) iZ = 0 ;
Z1 = Zdat[iZ] ;
Z2 = Zdat[iZ+1] ;
ratZ = (AtomicNumber-Z1)/(Z2-Z1) ;
// get bin number in T (beta2)
iT = 21 ;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy))
iT -= 1 ;
if(iT==21)
iT = 20 ;
if(iT==-1)
iT = 0 ;
// calculate betasquare values
T = Tdat[iT] ;
E = T + electron_mass_c2 ;
b2small = T*(E+electron_mass_c2)/(E*E) ;
T = Tdat[iT+1] ;
E = T + electron_mass_c2 ;
b2big = T*(E+electron_mass_c2)/(E*E) ;
ratb2 = (beta2-b2small)/(b2big-b2small) ;
corrfactor = tuning*(1.+cpar)/(1.+cpar*beta2) ;
if(Charge < 0.)
{
c1 = celectron[iZ][iT] ;
c2 = celectron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = celectron[iZ][iT+1] ;
c2 = celectron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
if(Charge > 0.)
{
c1 = cpositron[iZ][iT] ;
c2 = cpositron[iZ+1][iT] ;
cc1 = c1+ratZ*(c2-c1) ;
c1 = cpositron[iZ][iT+1] ;
c2 = cpositron[iZ+1][iT+1] ;
cc2 = c1+ratZ*(c2-c1) ;
corr = cc1+ratb2*(cc2-cc1) ;
sigma /= corr ;
}
sigma *= corrfactor ;
sigma /= corrnuclsize ;
return sigma ;
}
G4VParticleChange* G4MultipleScattering::PostStepDoIt(
const G4Track& trackData,
const G4Step& stepData)
{
static G4double taulim=1.e-6 , randlim = 0.25*taulim*taulim ;
static const G4double tausmall = 5.e-5,taubig =50.,
kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
const G4DynamicParticle* aParticle ;
G4Material* aMaterial ;
G4double KineticEnergy,truestep,tau,prob,cth,sth,phi,
dirx,diry,dirz,w,w1,etau,rmean,safetyminustolerance,
xnew,ynew,znew ;
G4double rand ;
G4bool isOut;
fParticleChange.Initialize(trackData) ;
truestep = stepData.GetStepLength() ;
aParticle = trackData.GetDynamicParticle() ;
KineticEnergy = aParticle->GetKineticEnergy() ;
if(stepFlag == 0)
{
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
}
// change direction first ( scattering ) ..........................
if(stepFlag == 0)
{
tau = truestep/fTransportMeanFreePath ;
if(tau > taulim)
prob = exp(-tau)*(1.+scatteringparameter*tau) ;
else
prob=1.-(1.-scatteringparameter)*tau ;
}
else
{
tau = truestep/range ;
if(tau < taulim)
prob = exp(-(alpha1-1.)*tau)*(1.+scatteringparameter*tau) ;
else if(tau < 1.)
prob = exp((alpha1-1.)*log(1.-tau))*(1.+scatteringparameter*tau) ;
else
prob = 0. ;
}
if(G4UniformRand()<prob)
{
if(tau<taulim)
{
rand = G4UniformRand() ;
if(rand > randlim)
{
cth = 1.-scatteringparameter*tau*(1./sqrt(rand)-1.) ;
if(cth < -1.) cth = -1. ;
}
else
cth = -1. ;
}
else
{
w = 1.+scatteringparameter*tau ;
w1 = w-1. ;
cth = w-w1*(w+1.)/sqrt(w1*w1+4.*w*G4UniformRand()) ;
}
}
else
cth = -1.+2.*G4UniformRand() ;
sth = sqrt(1.-cth*cth) ;
phi = twopi*G4UniformRand() ;
dirx = sth*cos(phi) ;
diry = sth*sin(phi) ;
dirz = cth ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz) ;
newDirection.rotateUz(ParticleDirection) ;
fParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z()) ;
if(fLatDisplFlag)
{
// compute mean lateral displacement ...............
// only for safety > tolerance !!!!!!!!!
safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
if(safetyminustolerance > 0.)
{
if(tau<tausmall)
rmean = 5.*tau*tau*tau/12. ;
else
{
if(tau<taubig)
etau = exp(-tau) ;
else
etau = 0. ;
rmean = -kappa*tau ;
rmean = -exp(rmean)/(kappa*kappami1) ;
rmean += tau-kappapl1/kappa+kappa*etau/kappami1 ;
}
if(rmean>0.)
rmean = 2.*fTransportMeanFreePath*sqrt(rmean/3.) ;
else
rmean = 0. ;
// for rmean > 0) only
if(rmean>0.)
{
if(rmean>safetyminustolerance)
rmean = safetyminustolerance ;
// sample direction of lateral displacement
phi = twopi*G4UniformRand() ;
dirx = cos(phi) ;
diry = sin(phi) ;
dirz = 0. ;
G4ThreeVector latDirection(dirx,diry,dirz);
latDirection.rotateUz(ParticleDirection) ;
// compute new endpoint of the Step
G4ThreeVector newPosition=
stepData.GetPostStepPoint()->GetPosition()+
rmean*latDirection;
G4Navigator *navigator=
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
navigator->LocateGlobalPointWithinVolume( newPosition );
fParticleChange.SetPositionChange(newPosition) ;
}
}
}
return &fParticleChange ;
}
void G4MultipleScattering::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
comments += "\n New model of MSC , computes the lateral \n";
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from " << G4BestUnit(LowestKineticEnergy,
"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
}
File diff suppressed because it is too large Load Diff