Import Geant4 0.0.0 source tree
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
// G4LeptonHadronInteractionModel.cc
|
||||
//
|
||||
// M.Takahata (Makoto.Takahata@cern.ch)
|
||||
|
||||
#include "G4LeptonHadronInteractionModel.hh"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4LeptonHadronInteractionModel::G4LeptonHadronInteractionModel()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4LeptonHadronInteractionModel::~G4LeptonHadronInteractionModel()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// G4LeptonHadronProcess.cc
|
||||
//
|
||||
// M.Takahata (Makoto.Takahata@cern.ch)
|
||||
|
||||
#include "G4LeptonHadronProcess.hh"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4LeptonHadronProcess::G4LeptonHadronProcess( const G4String &processName )
|
||||
//-----------------------------------------------------------------------------
|
||||
: G4VDiscreteProcess( processName )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4LeptonHadronProcess::~G4LeptonHadronProcess()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4VParticleChange*
|
||||
G4LeptonHadronProcess::GeneralPostStepDoIt( const G4Track &leptonTrack,
|
||||
const G4Step &aStep )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
targetNucleus.ChooseParameters(leptonTrack.GetMaterial());
|
||||
G4VParticleChange *result
|
||||
= theInteractionModel->applyInteractionModel(leptonTrack, targetNucleus);
|
||||
|
||||
ResetNumberOfInteractionLengthLeft();
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
// 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.cc,v 1.2 1998/11/24 13:12:11 hpw 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
|
||||
// -------- G4MuNuclearInteraction physics process ---------
|
||||
// by Laszlo Urban, May 1998
|
||||
// added simple model for hadronic vertex, J.P. Wellisch, November 1998
|
||||
// --------------------------------------------------------------
|
||||
// 26/10/98: new corr.s from R.Kokoulin + cleanup , L.Urban
|
||||
//
|
||||
#include "G4MuNuclearInteraction.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
|
||||
// static members ........
|
||||
G4int G4MuNuclearInteraction::nzdat = 5 ;
|
||||
G4double G4MuNuclearInteraction::zdat[]={1.,4.,13.,29.,92.};
|
||||
G4double G4MuNuclearInteraction::adat[]={1.01,9.01,26.98,63.55,238.03};
|
||||
G4int G4MuNuclearInteraction::ntdat = 8 ;
|
||||
G4double G4MuNuclearInteraction::tdat[]={1.e3,1.e4,1.e5,1.e6,1.e7,1.e8,
|
||||
1.e9,1.e10};
|
||||
G4int G4MuNuclearInteraction::NBIN = 100 ; //500 ;
|
||||
G4double G4MuNuclearInteraction::ya[1000]={0.};
|
||||
G4double G4MuNuclearInteraction::proba[5][8][1000]={0.};
|
||||
|
||||
G4MuNuclearInteraction::G4MuNuclearInteraction(const G4String& processName)
|
||||
: G4VDiscreteProcess(processName),
|
||||
theCrossSectionTable(NULL),
|
||||
theMeanFreePathTable(NULL),
|
||||
LowestKineticEnergy (1.*GeV),
|
||||
HighestKineticEnergy (1000000.*TeV),
|
||||
TotBin(50),
|
||||
theMuonMinus ( G4MuonMinus::MuonMinus() ),
|
||||
theMuonPlus ( G4MuonPlus::MuonPlus() ),
|
||||
thePionZero (G4PionZero::PionZero() ),
|
||||
CutFixed ( 0.200*GeV)
|
||||
{ }
|
||||
|
||||
G4MuNuclearInteraction::~G4MuNuclearInteraction()
|
||||
{
|
||||
if (theMeanFreePathTable) {
|
||||
theMeanFreePathTable->clearAndDestroy();
|
||||
delete theMeanFreePathTable;
|
||||
}
|
||||
if (theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy();
|
||||
delete theCrossSectionTable;
|
||||
}
|
||||
|
||||
if (&PartialSumSigma) {
|
||||
PartialSumSigma.clearAndDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
void G4MuNuclearInteraction::SetPhysicsTableBining(G4double lowE,
|
||||
G4double highE, G4int nBins)
|
||||
{
|
||||
LowestKineticEnergy = lowE; HighestKineticEnergy = highE ; TotBin = nBins ;
|
||||
}
|
||||
|
||||
void G4MuNuclearInteraction::BuildPhysicsTable(
|
||||
const G4ParticleDefinition& aParticleType)
|
||||
{
|
||||
G4double LowEdgeEnergy , Value;
|
||||
G4PhysicsLogVector* ptrVector;
|
||||
|
||||
if (theCrossSectionTable) {
|
||||
theCrossSectionTable->clearAndDestroy() ;
|
||||
delete theCrossSectionTable ;
|
||||
}
|
||||
|
||||
// make tables for the sampling at initialization
|
||||
if (theMeanFreePathTable == NULL) MakeSamplingTables(&aParticleType);
|
||||
|
||||
theCrossSectionTable = new G4PhysicsTable (G4Element::GetNumberOfElements());
|
||||
const G4ElementTable* theElementTable = G4Element::GetElementTable() ;
|
||||
G4double AtomicNumber,AtomicWeight ;
|
||||
|
||||
for (G4int J=0; J < G4Element::GetNumberOfElements(); J++ )
|
||||
{
|
||||
ptrVector = new G4PhysicsLogVector(LowestKineticEnergy,
|
||||
HighestKineticEnergy,TotBin) ;
|
||||
AtomicNumber = (*theElementTable )(J)->GetZ() ;
|
||||
AtomicWeight = (*theElementTable )(J)->GetA() ;
|
||||
|
||||
for ( G4int i = 0 ; i < TotBin ; i++)
|
||||
{
|
||||
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i) ;
|
||||
Value = ComputeMicroscopicCrossSection(&aParticleType,
|
||||
LowEdgeEnergy,
|
||||
AtomicNumber,AtomicWeight) ;
|
||||
ptrVector->PutValue(i,Value) ;
|
||||
}
|
||||
|
||||
theCrossSectionTable->insertAt( J , ptrVector ) ;
|
||||
}
|
||||
|
||||
G4double FixedEnergy = (LowestKineticEnergy + HighestKineticEnergy)/2. ;
|
||||
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
|
||||
if (theMeanFreePathTable) {
|
||||
theMeanFreePathTable->clearAndDestroy();
|
||||
delete theMeanFreePathTable;
|
||||
}
|
||||
theMeanFreePathTable = new G4PhysicsTable(G4Material::GetNumberOfMaterials());
|
||||
|
||||
for (G4int K=0 ; K < G4Material::GetNumberOfMaterials(); K++ )
|
||||
{
|
||||
ptrVector = new G4PhysicsLogVector(LowestKineticEnergy,
|
||||
HighestKineticEnergy,
|
||||
TotBin ) ;
|
||||
|
||||
const G4Material* material= (*theMaterialTable)[K];
|
||||
|
||||
for ( G4int i = 0 ; i < TotBin ; i++ )
|
||||
{
|
||||
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
|
||||
Value = ComputeMeanFreePath( &aParticleType, LowEdgeEnergy,
|
||||
material );
|
||||
|
||||
ptrVector->PutValue( i , Value ) ;
|
||||
}
|
||||
|
||||
theMeanFreePathTable->insertAt( K , ptrVector );
|
||||
|
||||
// Compute the PartialSumSigma table at a given fixed energy
|
||||
ComputePartialSumSigma( &aParticleType, FixedEnergy, material);
|
||||
}
|
||||
|
||||
if (&aParticleType == theMuonPlus) PrintInfoDefinition();
|
||||
}
|
||||
|
||||
void G4MuNuclearInteraction::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();
|
||||
|
||||
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()) ;
|
||||
PartialSumSigma(Imate)->insertAt(Ielem, SIGMA);
|
||||
}
|
||||
}
|
||||
|
||||
G4double G4MuNuclearInteraction::ComputeMicroscopicCrossSection(
|
||||
const G4ParticleDefinition* ParticleType,
|
||||
G4double KineticEnergy,
|
||||
G4double AtomicNumber,G4double AtomicWeight)
|
||||
{
|
||||
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 Mass,epmin,epmax,epln,ep,aaa,bbb,hhh,x ;
|
||||
G4int kkk ;
|
||||
|
||||
Mass = ParticleType->GetPDGMass() ;
|
||||
|
||||
G4double CrossSection = 0.0 ;
|
||||
|
||||
if ( AtomicNumber < 1. ) return CrossSection;
|
||||
if ( KineticEnergy <= CutFixed ) return CrossSection;
|
||||
|
||||
epmin = CutFixed ;
|
||||
epmax = KineticEnergy + Mass - 0.5*proton_mass_c2 ;
|
||||
|
||||
aaa = log(epmin) ;
|
||||
bbb = log(epmax) ;
|
||||
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 += ep*wgi[ll]* ComputeDMicroscopicCrossSection(ParticleType,
|
||||
KineticEnergy,
|
||||
AtomicNumber,AtomicWeight,
|
||||
ep) ;
|
||||
}
|
||||
}
|
||||
CrossSection *= hhh ;
|
||||
|
||||
if (CrossSection < 0.) CrossSection = 0.;
|
||||
|
||||
return CrossSection;
|
||||
}
|
||||
|
||||
G4double G4MuNuclearInteraction::ComputeDMicroscopicCrossSection(
|
||||
const G4ParticleDefinition* ParticleType,
|
||||
G4double KineticEnergy,
|
||||
G4double AtomicNumber,G4double AtomicWeight,
|
||||
G4double epsilon)
|
||||
// Calculates the differential (D) microscopic cross section
|
||||
// using the cross section formula of R.P. Kokoulin (18/01/98)
|
||||
{
|
||||
const G4double alam2 = 0.400*GeV*GeV ;
|
||||
const G4double alam = 0.632456*GeV ;
|
||||
const G4double coeffn = fine_structure_const/pi ;
|
||||
|
||||
G4double ep,a,aeff,sigph,v,v1,v2,mass2,up,down ;
|
||||
G4double ParticleMass = ParticleType->GetPDGMass() ;
|
||||
G4double TotalEnergy = KineticEnergy + ParticleMass ;
|
||||
|
||||
G4double DCrossSection = 0. ;
|
||||
|
||||
if((epsilon >= TotalEnergy - 0.5*proton_mass_c2)
|
||||
||
|
||||
(epsilon <= CutFixed))
|
||||
return DCrossSection ;
|
||||
|
||||
ep = epsilon/GeV ;
|
||||
a = AtomicWeight/(g/mole) ;
|
||||
|
||||
aeff = 0.22*a+0.78*exp(0.89*log(a)) ; //shadowing
|
||||
sigph = (49.2+11.1*log(ep)+151.8/sqrt(ep))*microbarn ; //!!!!!!!!!!!
|
||||
|
||||
v=epsilon/TotalEnergy ;
|
||||
v1 = 1.-v ;
|
||||
v2 = v*v ;
|
||||
mass2 = ParticleMass*ParticleMass ;
|
||||
|
||||
up = TotalEnergy*TotalEnergy*v1/mass2*(1.+mass2*v2/(alam2*v1)) ;
|
||||
down = 1.+epsilon/alam*(1.+alam/(2.*proton_mass_c2)+epsilon/alam) ;
|
||||
|
||||
DCrossSection = coeffn*aeff*sigph/epsilon*
|
||||
(-v1+(v1+0.5*v2*(1.+2.*mass2/alam2))*log(up/down)) ;
|
||||
|
||||
if( DCrossSection < 0.)
|
||||
DCrossSection = 0. ;
|
||||
|
||||
return DCrossSection ;
|
||||
}
|
||||
|
||||
void G4MuNuclearInteraction::MakeSamplingTables(
|
||||
const G4ParticleDefinition* ParticleType)
|
||||
{
|
||||
|
||||
G4double epbin[1000],xbin[1000],prbin[1000] ;
|
||||
G4int nbin;
|
||||
G4double AtomicNumber,AtomicWeight,KineticEnergy,
|
||||
TotalEnergy,Maxep ;
|
||||
|
||||
G4double ParticleMass = ParticleType->GetPDGMass() ;
|
||||
|
||||
for (G4int iz=0; iz<nzdat; iz++)
|
||||
{
|
||||
AtomicNumber = zdat[iz];
|
||||
AtomicWeight = adat[iz]*GramPerMole ;
|
||||
|
||||
for (G4int it=0; it<ntdat; it++)
|
||||
{
|
||||
KineticEnergy = tdat[it];
|
||||
TotalEnergy = KineticEnergy + ParticleMass;
|
||||
Maxep = TotalEnergy - 0.5*proton_mass_c2 ;
|
||||
|
||||
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* G4MuNuclearInteraction::PostStepDoIt(
|
||||
const G4Track& trackData,
|
||||
const G4Step& stepData)
|
||||
{
|
||||
static const G4double Mass=theMuonPlus->GetPDGMass() ;
|
||||
static const G4double m0=0.2*GeV ;
|
||||
|
||||
aParticleChange.Initialize(trackData);
|
||||
G4Material* aMaterial=trackData.GetMaterial() ;
|
||||
|
||||
const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
|
||||
|
||||
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
|
||||
G4ParticleMomentum ParticleDirection =
|
||||
aDynamicParticle->GetMomentumDirection();
|
||||
|
||||
// limits of the energy sampling
|
||||
G4double TotalEnergy = KineticEnergy + Mass ;
|
||||
G4double epmin = CutFixed ;
|
||||
G4double epmax = TotalEnergy - 0.5*proton_mass_c2 ;
|
||||
// check against insufficient energy
|
||||
if (epmax <= epmin )
|
||||
{
|
||||
aParticleChange.SetMomentumChange( ParticleDirection );
|
||||
aParticleChange.SetEnergyChange( KineticEnergy );
|
||||
aParticleChange.SetLocalEnergyDeposit (0.);
|
||||
aParticleChange.SetNumberOfSecondaries(0);
|
||||
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
|
||||
}
|
||||
|
||||
// select randomly one element constituing the material
|
||||
G4Element* anElement = SelectRandomAtom(aMaterial);
|
||||
|
||||
// sample energy of the secondary ( pi0)
|
||||
// sampling using tables
|
||||
G4double ep,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) ;
|
||||
ep = epmin*exp(x*log(epmax/epmin)) ;
|
||||
|
||||
// sample scattering angle of mu, but first t should be sampled.
|
||||
G4double yy = ep/TotalEnergy ;
|
||||
G4double tmin=Mass*Mass*yy*yy/(1.-yy) ;
|
||||
G4double tmax=2.*proton_mass_c2*ep ;
|
||||
G4double t1,t2,t,w1,w2,w3,y1,y2,y3,rej ;
|
||||
if(m0<ep)
|
||||
{
|
||||
t1=m0*m0;
|
||||
t2=ep*ep;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1=ep*ep;
|
||||
t2=m0*m0;
|
||||
}
|
||||
|
||||
w1=tmax*t1;
|
||||
w2=tmax+t1 ;
|
||||
w3=tmax*(tmin+t1)/(tmin*w2);
|
||||
y1=1.-yy;
|
||||
y2=0.5*yy*yy;
|
||||
y3=y1+y2;
|
||||
|
||||
// now the sampling of t
|
||||
G4int ntry=0;
|
||||
do
|
||||
{
|
||||
ntry += 1 ;
|
||||
t=w1/(w2*exp(G4UniformRand()*log(w3))-tmax) ;
|
||||
rej = (1.-t/tmax)*(y1*(1.-tmin/t)+y2)/(y3*(1.-t/t2));
|
||||
} while (G4UniformRand() > rej) ;
|
||||
|
||||
// compute angle from t
|
||||
G4double sinth2,theta ; // sinth2 = sin(theta/2)*sin(theta/2) !
|
||||
sinth2 = 0.5*(t-tmin)/(2.*(TotalEnergy*(TotalEnergy-ep)-Mass*Mass)-tmin) ;
|
||||
theta = acos(1.-2.*sinth2) ;
|
||||
|
||||
G4double phi=twopi*G4UniformRand() ;
|
||||
G4double sinth=sin(theta) ;
|
||||
G4double dirx=sinth*cos(phi) , diry=sinth*sin(phi) , dirz=cos(theta);
|
||||
|
||||
G4ThreeVector finalDirection(dirx,diry,dirz) ;
|
||||
finalDirection.rotateUz(ParticleDirection) ;
|
||||
|
||||
G4double NewKinEnergy = KineticEnergy - ep ;
|
||||
G4double finalMomentum=sqrt(NewKinEnergy*
|
||||
(NewKinEnergy+2.*Mass)) ;
|
||||
|
||||
G4double Ef=NewKinEnergy+Mass ;
|
||||
G4double initMomentum=sqrt(KineticEnergy*(TotalEnergy+Mass)) ;
|
||||
|
||||
G4double Q2=2.*(TotalEnergy*Ef-initMomentum*finalMomentum*cos(theta)-Mass*Mass) ;
|
||||
|
||||
aParticleChange.SetMomentumChange( finalDirection );
|
||||
aParticleChange.SetEnergyChange( NewKinEnergy );
|
||||
|
||||
G4LorentzVector primaryMomentum(initMomentum*ParticleDirection, TotalEnergy);
|
||||
G4LorentzVector fsMomentum(finalMomentum*finalDirection, Ef);
|
||||
G4LorentzVector momentumTransfere = primaryMomentum-fsMomentum;
|
||||
|
||||
G4DynamicParticle* aGamma =
|
||||
new G4DynamicParticle(G4Gamma::Gamma(), momentumTransfere);
|
||||
G4Track gammaTrack(aGamma, trackData.GetGlobalTime(), trackData.GetPosition() );
|
||||
gammaTrack.SetStep(trackData.GetStep());
|
||||
G4Nucleus theTarget(aMaterial);
|
||||
|
||||
G4VParticleChange* aHadronicFS;
|
||||
aHadronicFS = theHadronicVertex.ApplyYourself(theTarget, gammaTrack);
|
||||
delete aGamma;
|
||||
|
||||
G4int numSecondaries = aHadronicFS->GetNumberOfSecondaries();
|
||||
aParticleChange.SetNumberOfSecondaries(numSecondaries);
|
||||
|
||||
G4ParticleMomentum secondaryMomentum = G4ThreeVector(0.,0.,0.);
|
||||
for(G4int iSec=0; iSec<numSecondaries; iSec++)
|
||||
{
|
||||
secondaryMomentum
|
||||
= secondaryMomentum + aHadronicFS->GetSecondary(iSec)->GetMomentum();
|
||||
aParticleChange.AddSecondary(aHadronicFS->GetSecondary(iSec));
|
||||
}
|
||||
aHadronicFS->Clear();
|
||||
|
||||
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
|
||||
}
|
||||
|
||||
G4Element* G4MuNuclearInteraction::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 G4MuNuclearInteraction::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";
|
||||
|
||||
G4cout << " For the moment there is no secondary, only energy loss!" << endl;
|
||||
G4cout << " =======================================================" << endl;
|
||||
G4cout << endl;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
// G4MuonNucleusInteractionModel.cc
|
||||
//
|
||||
// M.Takahata (Makoto.Takahata@cern.ch)
|
||||
|
||||
#include "G4MuonNucleusInteractionModel.hh"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4MuonNucleusInteractionModel::G4MuonNucleusInteractionModel()
|
||||
: G4LeptonHadronInteractionModel()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// build the physics vector
|
||||
Nbin = 90;
|
||||
kEmin = 1.0e-5*GeV;
|
||||
kEmax = 1.0e+4*GeV;
|
||||
cascadeModelMarginalEnergy = 25.0*GeV;
|
||||
theCoefficientVector = new G4PhysicsLogVector(kEmin, kEmax, Nbin);
|
||||
makePhysicsVector();
|
||||
|
||||
// construct variables
|
||||
LEPionMinusInelastic = new G4LEPionMinusInelastic;
|
||||
LEPionPlusInelastic = new G4LEPionPlusInelastic;
|
||||
HEPionMinusInelastic = new G4HEPionMinusInelastic;
|
||||
HEPionPlusInelastic = new G4HEPionPlusInelastic;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4MuonNucleusInteractionModel::~G4MuonNucleusInteractionModel()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
delete LEPionMinusInelastic;
|
||||
delete LEPionPlusInelastic;
|
||||
delete HEPionMinusInelastic;
|
||||
delete HEPionPlusInelastic;
|
||||
|
||||
delete theCoefficientVector;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4double G4MuonNucleusInteractionModel::tetal[35] = {
|
||||
//-----------------------------------------------------------------------------
|
||||
1.0000000, 0.9999995, 0.9999990, 0.9999981, 0.9999962,
|
||||
0.9999943, 0.9999905, 0.9999847, 0.9999752, 0.9999599,
|
||||
0.9999352, 0.9998951, 0.9998302, 0.9997253, 0.9995556,
|
||||
0.9992810, 0.9988368, 0.9981183, 0.9969561, 0.9950773,
|
||||
0.9920409, 0.9871377, 0.9792297, 0.9665010, 0.9460785,
|
||||
0.9134827, 0.8618938, 0.7813507, 0.6583430, 0.4770452,
|
||||
0.2247237, -0.0955139, -0.4461272, -0.7495149, -0.9900000
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4double G4MuonNucleusInteractionModel::xeml[23] = {
|
||||
//-----------------------------------------------------------------------------
|
||||
1.000, 0.998, 0.997, 0.996, 0.995, 0.994, 0.992, 0.990,
|
||||
0.970, 0.950, 0.920, 0.890, 0.850, 0.800, 0.750, 0.700,
|
||||
0.600, 0.500, 0.400, 0.300, 0.200, 0.100, 0.050
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4double G4MuonNucleusInteractionModel::computeMicroscopicCrossSection
|
||||
(const G4Track &muonTrack)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
const G4DynamicParticle *muonDynamics = muonTrack.GetDynamicParticle();
|
||||
G4double kineticEnergy = muonDynamics->GetKineticEnergy();
|
||||
G4double muonMass = muonDynamics->GetDefinition()->GetPDGMass();
|
||||
|
||||
G4double totalEnergy = kineticEnergy + muonMass;
|
||||
|
||||
G4double microscopicCrossSection;
|
||||
if(totalEnergy <= 30.0*GeV) {
|
||||
microscopicCrossSection
|
||||
= 0.0003*millibarn;
|
||||
} else {
|
||||
microscopicCrossSection
|
||||
= 0.0003*pow((totalEnergy/(30.0*GeV)), 0.25)*millibarn;
|
||||
}
|
||||
|
||||
return microscopicCrossSection;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void G4MuonNucleusInteractionModel::makePhysicsVector()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
G4double Ei, Ef; // initial and final energy of incident muon;
|
||||
G4double muonMass = G4MuonMinus::MuonMinus()->GetPDGMass();
|
||||
|
||||
for (G4int i=0; i<=(Nbin-1); i++)
|
||||
{
|
||||
G4double totalCrossSection = 0.0;
|
||||
Ei = theCoefficientVector->GetLowEdgeEnergy(i) + muonMass;
|
||||
for (G4int j=1; j<=34; j++)
|
||||
{
|
||||
cosTheta = 0.5 * (tetal[j] + tetal[j-1]);
|
||||
for (G4int k=1; k<=22; k++)
|
||||
{
|
||||
Ef = 0.5 * Ei * (xeml[k]+xeml[k-1]);
|
||||
G4double dsigma = computeDifferentialCrossSection(Ei,Ef,cosTheta);
|
||||
totalCrossSection = totalCrossSection
|
||||
+ Ei * (tetal[j-1]-tetal[j])*(xeml[k-1]-xeml[k]) * dsigma;
|
||||
}
|
||||
}
|
||||
theCoefficientVector->PutValue(i, totalCrossSection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4VParticleChange* G4MuonNucleusInteractionModel::applyInteractionModel
|
||||
(const G4Track &muonTrack, G4Nucleus &targetNucleus )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
G4int icos, ie1;
|
||||
G4double E1, P1;
|
||||
G4double rndm[3];
|
||||
G4bool isOutRange;
|
||||
|
||||
// Initialization
|
||||
aParticleChange.Initialize(muonTrack);
|
||||
|
||||
const G4DynamicParticle *muonDynamics = muonTrack.GetDynamicParticle();
|
||||
G4double kineticEnergy = muonDynamics->GetKineticEnergy();
|
||||
G4double totalMomentum = muonDynamics->GetTotalMomentum();
|
||||
G4double totalEnergy = muonDynamics->GetTotalEnergy();
|
||||
G4double muonMass = muonDynamics->GetDefinition()->GetPDGMass();
|
||||
|
||||
|
||||
G4double W2 = 0.0; G4int W2try = 0;
|
||||
while (W2 <= 0.0)
|
||||
{
|
||||
G4double totalCrossSection = 0.0;
|
||||
G4bool interpolated = false;
|
||||
G4double fRndm = RandFlat::shoot();
|
||||
G4double Hmax
|
||||
= theCoefficientVector->GetValue(kineticEnergy, isOutRange);
|
||||
for (G4int i=1; i<=34; i++)
|
||||
{
|
||||
cosTheta = 0.5 * (tetal[i] + tetal[i-1]);
|
||||
for (G4int j=1; j<=22; j++)
|
||||
{
|
||||
E1 = 0.5 * totalEnergy * (xeml[j]+xeml[j-1]);
|
||||
G4double dsigma
|
||||
= computeDifferentialCrossSection(totalEnergy, E1, cosTheta);
|
||||
totalCrossSection = totalCrossSection
|
||||
+ totalEnergy*(tetal[i-1]-tetal[i])*(xeml[j-1]-xeml[j])*dsigma;
|
||||
|
||||
if((fRndm*Hmax)<totalCrossSection) {
|
||||
interpolated = true;
|
||||
icos = i; ie1 = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(interpolated) {
|
||||
// calculate energy, momentum and angle of outgoing muon
|
||||
RandFlat::shootArray(3, rndm);
|
||||
G4double theta = acos(tetal[icos-1])
|
||||
+ rndm[0]*(acos(tetal[icos])-acos(tetal[icos-1]));
|
||||
cosTheta = cos(theta);
|
||||
E1 = (xeml[ie1] + rndm[1]*(xeml[ie1-1]-xeml[ie1])) * totalEnergy;
|
||||
if(E1<muonMass) E1 = muonMass + 0.0001*GeV;
|
||||
P1 = sqrt(abs(E1*E1-muonMass*muonMass));
|
||||
|
||||
// invariant mass of final hadron state must be greater than zero
|
||||
W2 = proton_mass_c2*proton_mass_c2
|
||||
+2.0*proton_mass_c2*(totalEnergy-E1)
|
||||
-2.0*(totalEnergy*E1-totalMomentum*P1*cosTheta-muonMass*muonMass);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
W2try++;
|
||||
if (W2try>100) return &aParticleChange;
|
||||
}
|
||||
|
||||
// calculate momentum of outgoing muon / pion(photon)
|
||||
G4double sinTheta = sqrt(abs(1.0 - cosTheta*cosTheta));
|
||||
G4double phi = rndm[2]*twopi;
|
||||
G4ThreeVector muonDirection(sinTheta*cos(phi),sinTheta*sin(phi),cosTheta);
|
||||
G4ThreeVector muonDirectionInit = muonTrack.GetMomentumDirection();
|
||||
muonDirection.rotateUz(muonDirectionInit);
|
||||
|
||||
G4ParticleMomentum pionMomentum
|
||||
= muonDynamics->GetMomentum() - P1*muonDirection;
|
||||
G4double muonKineticEnergy
|
||||
= sqrt(P1*P1 + muonMass*muonMass) - muonMass;
|
||||
aParticleChange.SetMomentumChange(muonDirection);
|
||||
aParticleChange.SetEnergyChange(muonKineticEnergy);
|
||||
aParticleChange.SetStatusChange(fAlive);
|
||||
|
||||
|
||||
// virtual photon is exchanged with a pion of same Q2
|
||||
// select pi+/pi- randomly and generate pion track
|
||||
G4ParticleDefinition* pdPion;
|
||||
if(RandFlat::shootBit())
|
||||
pdPion = G4PionMinus::PionMinusDefinition();
|
||||
else
|
||||
pdPion = G4PionPlus::PionPlusDefinition();
|
||||
|
||||
G4DynamicParticle* pionDynamics
|
||||
= new G4DynamicParticle(pdPion, pionMomentum);
|
||||
|
||||
G4Track* pionTrack = new G4Track(pionDynamics,
|
||||
muonTrack.GetGlobalTime(),
|
||||
muonTrack.GetPosition() );
|
||||
pionTrack->SetStep(muonTrack.GetStep());
|
||||
|
||||
// Invoke pion-nucleus inelastic process
|
||||
invokePionNucleus(*pionTrack, targetNucleus);
|
||||
|
||||
// Termination
|
||||
delete pionTrack;
|
||||
|
||||
return &aParticleChange;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void G4MuonNucleusInteractionModel::invokePionNucleus
|
||||
(const G4Track &pionTrack, G4Nucleus &targetNucleus )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// force interaction of pion with target nucleus
|
||||
G4double pionKineticEnergy = pionTrack.GetKineticEnergy();
|
||||
if(pionTrack.GetDefinition()->GetParticleName() == "pi-") {
|
||||
if(pionKineticEnergy <= cascadeModelMarginalEnergy)
|
||||
pionChange
|
||||
= LEPionMinusInelastic->ApplyYourself(pionTrack, targetNucleus);
|
||||
else
|
||||
pionChange
|
||||
= HEPionMinusInelastic->ApplyYourself(pionTrack, targetNucleus);
|
||||
} else if(pionTrack.GetDefinition()->GetParticleName() == "pi+") {
|
||||
if(pionKineticEnergy <= cascadeModelMarginalEnergy)
|
||||
pionChange
|
||||
= LEPionPlusInelastic->ApplyYourself(pionTrack, targetNucleus);
|
||||
else
|
||||
pionChange
|
||||
= HEPionPlusInelastic->ApplyYourself(pionTrack, targetNucleus);
|
||||
}
|
||||
|
||||
|
||||
// add local energy deposit
|
||||
G4double localEnergyDeposited = 0.0;
|
||||
localEnergyDeposited = pionChange->GetLocalEnergyDeposit();
|
||||
aParticleChange.SetLocalEnergyDeposit(localEnergyDeposited);
|
||||
|
||||
|
||||
// register secondary particles
|
||||
G4int numSecondaries = pionChange->GetNumberOfSecondaries();
|
||||
aParticleChange.SetNumberOfSecondaries(numSecondaries);
|
||||
|
||||
G4ParticleMomentum secondaryMomentum = G4ThreeVector(0.,0.,0.);
|
||||
for(G4int iS=0; iS<=(numSecondaries-1); iS++) {
|
||||
secondaryMomentum
|
||||
= secondaryMomentum + pionChange->GetSecondary(iS)->GetMomentum();
|
||||
aParticleChange.AddSecondary(pionChange->GetSecondary(iS));
|
||||
}
|
||||
pionChange->Clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4double G4MuonNucleusInteractionModel::computeDifferentialCrossSection
|
||||
(G4double initialEnergy, G4double finalEnergy, G4double cosTheta)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
G4double muonMass = G4MuonMinus::MuonMinus()->GetPDGMass();
|
||||
|
||||
if(finalEnergy < muonMass) return(0.0);
|
||||
if(cosTheta >= 1.0) return DBL_MAX;
|
||||
|
||||
G4double initialMomentum
|
||||
= sqrt(initialEnergy*initialEnergy - muonMass*muonMass);
|
||||
G4double finalMomentum
|
||||
= sqrt(finalEnergy*finalEnergy - muonMass*muonMass);
|
||||
|
||||
|
||||
// calculate momentum transfer (Q2)
|
||||
// and invariant mass of final state of hadrons (W2)
|
||||
G4double Q2
|
||||
= 2.0*(initialEnergy*finalEnergy
|
||||
-initialMomentum*finalMomentum*cosTheta-muonMass*muonMass);
|
||||
if(Q2 < 0.0) return(0.0);
|
||||
|
||||
G4double W2
|
||||
= proton_mass_c2*proton_mass_c2
|
||||
+2.0*proton_mass_c2*(initialEnergy-finalEnergy)-Q2;
|
||||
if(W2 < 0.0) return(0.0);
|
||||
|
||||
|
||||
// calculate factors
|
||||
// Nu : energy transfer
|
||||
// K : incident flux of photon
|
||||
// Epsilon : virtual photon polarization
|
||||
G4double fNu = initialEnergy-finalEnergy;
|
||||
G4double fK = fNu+Q2/(2.0*fNu);
|
||||
G4double fEpsilon
|
||||
= 1.0/(1.0+2.0*((1.0-cosTheta)/(1.0+cosTheta))*(Q2+fNu*fNu)/Q2);
|
||||
if(fEpsilon > 1.0) return DBL_MAX;
|
||||
|
||||
|
||||
// calculate photoabsorption cross sections
|
||||
// fGamma : flux of transverse photons
|
||||
// sigma_t : for transverse photons
|
||||
// sigma_l : for longitudinal photons
|
||||
G4double fGamma
|
||||
= fine_structure_const*fK*finalEnergy
|
||||
/ (pi*Q2*initialEnergy*(1.0 - fEpsilon));
|
||||
G4double sigma_t = 0.12*millibarn;
|
||||
G4double sigma_l = 0.3*(1.0-Q2/(1.868*GeV*fNu))*sigma_t;
|
||||
if(sigma_l < 0.) sigma_l = 0.;
|
||||
|
||||
return fGamma*(sigma_t+fEpsilon*sigma_l);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// G4MuonNucleusProcess.cc
|
||||
//
|
||||
// M.Takahata (Makoto.Takahata@cern.ch)
|
||||
|
||||
#include "G4MuonNucleusProcess.hh"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4MuonNucleusProcess::G4MuonNucleusProcess(const G4String& processName)
|
||||
//-----------------------------------------------------------------------------
|
||||
: G4LeptonHadronProcess( processName)
|
||||
{
|
||||
theInteractionModel = chooseInteractionModel();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4MuonNucleusProcess::~G4MuonNucleusProcess()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
delete theInteractionModel;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4LeptonHadronInteractionModel*
|
||||
G4MuonNucleusProcess::chooseInteractionModel()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
G4MuonNucleusInteractionModel* aModel = new G4MuonNucleusInteractionModel;
|
||||
return aModel;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
G4double
|
||||
G4MuonNucleusProcess::GetMeanFreePath( const G4Track &muonTrack,
|
||||
G4double previousStepSize,
|
||||
G4ForceCondition *condition )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
G4Material *aMaterial = muonTrack.GetMaterial();
|
||||
|
||||
const G4double* theAtomicNumDensityVector
|
||||
= aMaterial->GetAtomicNumDensityVector();
|
||||
const G4int theNumberOfElements
|
||||
= aMaterial->GetNumberOfElements();
|
||||
|
||||
G4double macroscopicCrossSection = 0.0;
|
||||
for(G4int iel=0; iel<theNumberOfElements; iel++)
|
||||
{
|
||||
macroscopicCrossSection
|
||||
+= theAtomicNumDensityVector[iel]
|
||||
*theInteractionModel->computeMicroscopicCrossSection(muonTrack);
|
||||
}
|
||||
|
||||
if( macroscopicCrossSection > 0.0 ) {
|
||||
return 1.0/macroscopicCrossSection;
|
||||
} else {
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "G4ParametrizedHadronicVertex.hh"
|
||||
|
||||
G4VParticleChange * G4ParametrizedHadronicVertex::
|
||||
ApplyYourself(const G4Nucleus & theTarget, const G4Track &thePhoton)
|
||||
{
|
||||
G4double theKineticEnergy = thePhoton.GetKineticEnergy();
|
||||
if(RandFlat::shootBit())
|
||||
{
|
||||
if(theKineticEnergy<20*GeV) return theLowEPionMinus.ApplyYourself(thePhoton, theTarget);
|
||||
return theHighEPionMinus.ApplyYourself(thePhoton, theTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(theKineticEnergy<20*GeV) return theLowEPionPlus.ApplyYourself(thePhoton, theTarget);
|
||||
return theHighEPionPlus.ApplyYourself(thePhoton, theTarget);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user