Import Geant4 0.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-01 15:25:35 +02:00
parent 54d6b71f95
commit b97f8d0df7
3237 changed files with 807095 additions and 0 deletions
@@ -0,0 +1,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;
}