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,154 @@
// 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: G4LCapture.cc,v 2.3 1998/07/13 17:24:07 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
// G4 Model: Low-energy Neutron Capture
// F.W. Jones, TRIUMF, 03-DEC-96
//
// This is a prototype of a low-energy neutron capture process.
// Currently it is based on the GHEISHA routine CAPTUR,
// and conforms fairly closely to the original Fortran.
//
// HPW Capture using models now. the code comes from the
// original G4LCapture class.
//
// 25-JUN-98 FWJ: replaced missing Initialize for ParticleChange.
//
#include "G4LCapture.hh"
#include "Randomize.hh"
G4LCapture::G4LCapture() :
G4HadronicInteraction()
{
theParticleChange.SetNumberOfSecondaries(2);
SetMinEnergy( 0.0*GeV );
SetMaxEnergy( DBL_MAX );
}
G4LCapture::~G4LCapture()
{
theParticleChange.Clear();
}
G4VParticleChange*
G4LCapture::ApplyYourself(const G4Track& aTrack, G4Nucleus& targetNucleus)
{
theParticleChange.Initialize(aTrack);
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
const G4Material* aMaterial = aTrack.GetMaterial();
theParticleChange.SetStatusChange(fStopAndKill);
G4double N = targetNucleus.GetN();
G4double Z = targetNucleus.GetZ();
G4double P = aParticle->GetTotalMomentum()/GeV;
G4double Px = P*(aParticle->GetMomentumDirection().x());
G4double Py = P*(aParticle->GetMomentumDirection().y());
G4double Pz = P*(aParticle->GetMomentumDirection().z());
G4double E = aParticle->GetTotalEnergy()/GeV;
G4double E0 = aParticle->GetDefinition()->GetPDGMass()/GeV;
G4double Q = aParticle->GetDefinition()->GetPDGCharge();
G4double pv6 = aParticle->GetDefinition()->GetPDGCharge();
if (verboseLevel > 1) {
G4cout << "G4LCapture:ApplyYourself: incident particle:" << endl;
G4cout << "P " << P << " GeV/c" << endl;
G4cout << "Px " << Px << " GeV/c" << endl;
G4cout << "Py " << Py << " GeV/c" << endl;
G4cout << "Pz " << Pz << " GeV/c" << endl;
G4cout << "E " << E << " GeV" << endl;
G4cout << "mass " << E0 << " GeV" << endl;
G4cout << "charge " << Q << endl;
}
// GHEISHA ADD operation to get total energy, mass, charge:
if (verboseLevel > 1) {
G4cout << "G4LCapture:ApplyYourself: material:" << endl;
G4cout << "A " << N << endl;
G4cout << "Z " << Z << endl;
G4cout << "atomic mass " <<
Atomas(N, Z) << "GeV" << endl;
}
E = E + Atomas(N, Z);
G4double E02 = E*E - P*P;
E0 = sqrt(abs(E02));
if (E02 < 0) E0 = -E0;
Q = Q + Z;
if (verboseLevel > 1) {
G4cout << "G4LCapture:ApplyYourself: total:" << endl;
G4cout << "E " << E << " GeV" << endl;
G4cout << "mass " << E0 << " GeV" << endl;
G4cout << "charge " << Q << endl;
}
Px = -Px;
Py = -Py;
Pz = -Pz;
// Make a gamma...
G4double ran = RandGauss::shoot();
G4double p = 0.0065 + ran*0.0010;
G4double ran1 = G4UniformRand();
G4double ran2 = G4UniformRand();
G4double cost = -1. + 2.*ran1;
G4double sint = sqrt(abs(1. - cost*cost));
G4double phi = ran2*twopi;
G4double px = p*sint*sin(phi);
G4double py = p*sint*cos(phi);
G4double pz = p*cost;
G4double e = p;
G4double e0 = 0.;
G4double a = px*Px + py*Py + pz*Pz;
a = (a/(E + E0) - e)/E0;
px = px + a*Px;
py = py + a*Py;
pz = pz + a*Pz;
G4DynamicParticle* aGamma;
aGamma = new G4DynamicParticle(G4Gamma::GammaDefinition(),
G4ThreeVector(px*GeV, py*GeV, pz*GeV));
theParticleChange.AddSecondary(aGamma);
// Make another gamma if there is sufficient energy left over...
G4double xp = 0.008 - p;
if (xp <= 0.) return &theParticleChange;
ran1 = G4UniformRand();
ran2 = G4UniformRand();
cost = -1. + 2.*ran1;
sint = sqrt(abs(1. - cost*cost));
phi = ran2*twopi;
px = xp*sint*sin(phi);
py = xp*sint*cos(phi);
pz = xp*cost;
e = xp;
e0 = 0.;
a = px*Px + py*Py + pz*Pz;
a = (a/(E + E0) - e)/E0;
px = px + a*Px;
py = py + a*Py;
pz = pz + a*Pz;
aGamma = new G4DynamicParticle(G4Gamma::GammaDefinition(),
G4ThreeVector(px*GeV, py*GeV, pz*GeV));
theParticleChange.AddSecondary(aGamma);
return &theParticleChange;
}
@@ -0,0 +1,78 @@
// 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: G4LEAlphaInelastic.cc,v 2.9 1998/12/14 15:33:13 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Alpha Inelastic Process
// J.L. Chuma, TRIUMF, 25-Feb-1997
// Last modified: 27-Mar-1997
#include "G4LEAlphaInelastic.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
G4VParticleChange *
G4LEAlphaInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
G4double A = targetNucleus.GetN();
G4double Z = targetNucleus.GetZ();
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAlphaInelastic::ApplyYourself called" << endl;
G4cout << "kinetc energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << endl;
}
// Work-around for lack of model above 100 MeV
if (originalIncident->GetKineticEnergy()/MeV > 100. ||
originalIncident->GetKineticEnergy() <= 0.1*MeV) return &theParticleChange;
G4double theAtomicMass = targetNucleus.AtomicMass( A, Z )-Z*G4Electron::Electron()->GetPDGMass();
G4double massVec[9];
massVec[0] = targetNucleus.AtomicMass( A+4.0, Z+2.0 )-(Z+2.0)*G4Electron::Electron()->GetPDGMass();
massVec[1] = targetNucleus.AtomicMass( A+3.0, Z+2.0 )-(Z+2.0)*G4Electron::Electron()->GetPDGMass();
massVec[2] = targetNucleus.AtomicMass( A+3.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[3] = targetNucleus.AtomicMass( A+2.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[4] = targetNucleus.AtomicMass( A+1.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[5] = theAtomicMass;
massVec[6] = targetNucleus.AtomicMass( A+2.0, Z+2.0 )-(Z+2.0)*G4Electron::Electron()->GetPDGMass();
massVec[7] = massVec[3];
massVec[8] = targetNucleus.AtomicMass( A+2.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
G4FastVector<G4ReactionProduct,3> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
theReactionDynamics.NuclearReaction( vec, vecLen, originalIncident,
targetNucleus, theAtomicMass, massVec );
G4double p = originalIncident->GetTotalMomentum();
theParticleChange.SetMomentumChange( originalIncident->GetMomentum() * (1.0/p) );
theParticleChange.SetEnergyChange( originalIncident->GetKineticEnergy() );
theParticleChange.SetNumberOfSecondaries( vecLen );
G4DynamicParticle *pd;
for( G4int i=0; i<vecLen; ++i )
{
pd = new G4DynamicParticle();
pd->SetDefinition( vec[i]->GetDefinition() );
pd->SetMomentum( vec[i]->GetMomentum() );
theParticleChange.AddSecondary( pd );
}
return &theParticleChange;
}
/* end of file */
@@ -0,0 +1,631 @@
// 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: G4LEAntiLambdaInelastic.cc,v 2.3 1998/07/13 17:24:10 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiLambda Inelastic Process
// J.L. Chuma, TRIUMF, 19-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEAntiLambdaInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiLambdaInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAntiLambdaInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
const G4double anni = min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
if( (originalIncident->GetKineticEnergy()/MeV > cutOff) || (G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiLambdaInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int &vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASAL0 by H. Fesefeldt (13-Sep-1987)
//
// AntiLambda undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
const G4double pOriginal = originalIncident->GetTotalMomentum()/GeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
static G4bool first = true;
const G4int numMul = 1200;
const G4int numMulA = 400;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double protmulA[numMulA], protnormA[numSec]; // proton constants
static G4double neutmulA[numMulA], neutnormA[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
G4int counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-2); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
//
// do the same for annihilation channels
//
for( i=0; i<numMulA; ++i )protmulA[i] = 0.0;
for( i=0; i<numSec; ++i )protnormA[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); ++np )
{
nm = np-1;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
protmulA[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnormA[nt-1] += protmulA[counter];
}
}
}
}
for( i=0; i<numMulA; ++i )neutmulA[i] = 0.0;
for( i=0; i<numSec; ++i )neutnormA[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
nm = np;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
neutmulA[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnormA[nt-1] += neutmulA[counter];
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnormA[i] > 0.0 )protnormA[i] = 1.0/protnormA[i];
if( neutnormA[i] > 0.0 )neutnormA[i] = 1.0/neutnormA[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *anAntiSigmaZero = G4AntiSigmaZero::AntiSigmaZero();
G4ParticleDefinition *anAntiSigmaPlus = G4AntiSigmaPlus::AntiSigmaPlus();
G4ParticleDefinition *anAntiSigmaMinus = G4AntiSigmaMinus::AntiSigmaMinus();
const G4double anhl[] = {1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,0.97,0.88,
0.85,0.81,0.75,0.64,0.64,0.55,0.55,0.45,0.47,0.40,
0.39,0.36,0.33,0.10,0.01};
G4int iplab = G4int( pOriginal*10.0 );
if( iplab > 9 )iplab = G4int( (pOriginal- 1.0)*5.0 ) + 10;
if( iplab > 14 )iplab = G4int( pOriginal- 2.0 ) + 15;
if( iplab > 22 )iplab = G4int( (pOriginal-10.0)/10.0 ) + 23;
if( iplab > 24 )iplab = 24;
if( G4UniformRand() > anhl[iplab] )
{
if( availableEnergy <= aPiPlus->GetPDGMass()/MeV )
{ // not energetically possible to produce pion(s)
quasiElastic = true;
return;
}
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
G4int counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-2); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = min( 4, max( 1, np-nm+2 ) );
switch( ncht )
{
case 1:
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
incidentHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
break;
case 3:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
incidentHasChanged = true;
}
}
else
{
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
incidentHasChanged = true;
}
}
break;
case 4:
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
}
}
else // target must be a neutron
{
G4int counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = min( 4, max( 1, np-nm+3 ) );
switch( ncht )
{
case 1:
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
incidentHasChanged = true;
}
}
else
{
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
incidentHasChanged = true;
}
}
break;
case 3:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
else
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
break;
default:
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
incidentHasChanged = true;
break;
}
}
}
else // random number <= anhl[iplab]
{
if( centerofmassEnergy <= aPiPlus->GetPDGMass()/MeV+aKaonPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
//
// annihilation channels
//
G4double n, anpn;
GetNormalizationConstant( -centerofmassEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
G4int counter = -1;
for( np=1; np<numSec/3 && ran>=excs; ++np )
{
nm = np-1;
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmulA[counter]*protnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
else // target must be a neutron
{
G4int counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
nm = np;
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmulA[counter]*neutnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nz--;
currentParticle.SetMass( 0.0 );
targetParticle.SetMass( 0.0 );
}
SetUpPions( np, nm, nz, vec, vecLen );
if( currentParticle.GetMass() == 0.0 )
{
if( nz == 0 )
{
if( nm > 0 )
{
for( G4int i=0; i<vecLen; ++i )
{
if( vec[i]->GetDefinition() == aPiMinus )
{
vec[i]->SetDefinitionAndUpdateE( aKaonMinus );
break;
}
}
}
}
else // nz > 0
{
if( nm == 0 )
{
for( G4int i=0; i<vecLen; ++i )
{
if( vec[i]->GetDefinition() == aPiZero )
{
vec[i]->SetDefinitionAndUpdateE( aKaonZL );
break;
}
}
}
else // nm > 0
{
if( G4UniformRand() < 0.5 )
{
if( nm > 0 )
{
for( G4int i=0; i<vecLen; ++i )
{
if( vec[i]->GetDefinition() == aPiMinus )
{
vec[i]->SetDefinitionAndUpdateE( aKaonMinus );
break;
}
}
}
}
else // random number >= 0.5
{
for( G4int i=0; i<vecLen; ++i )
{
if( vec[i]->GetDefinition() == aPiZero )
{
vec[i]->SetDefinitionAndUpdateE( aKaonZL );
break;
}
}
}
}
}
}
return;
}
/* end of file */
@@ -0,0 +1,523 @@
// 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: G4LEAntiNeutronInelastic.cc,v 2.3 1998/07/13 17:24:12 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiNeutron Inelastic Process
// J.L. Chuma, TRIUMF, 18-Feb-1997
// Last modified: 27-Mar-1997
// J.P.Wellisch: 23-Apr-97: Added theNucleus.SetParameters call
// J.P. Wellisch: 23-Apr-97: nm = np+1; in line 392
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEAntiNeutronInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiNeutronInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAntiNeutronInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1*MeV;
const G4double anni = min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
if( (currentParticle.GetKineticEnergy()/MeV > cutOff) ||
(G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
else
quasiElastic = true;
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiNeutronInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASNB by H. Fesefeldt (13-Sep-1987)
//
// AntiNeutron undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double pOriginal = originalIncident->GetTotalMomentum()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
static G4bool first = true;
const G4int numMul = 1200;
const G4int numMulA = 400;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double protmulA[numMulA], protnormA[numSec]; // proton constants
static G4double neutmulA[numMulA], neutnormA[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.70 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-2); nm<=np; ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
//
// do the same for annihilation channels
//
for( i=0; i<numMulA; ++i )protmulA[i] = 0.0;
for( i=0; i<numSec; ++i )protnormA[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); ++np )
{
nm = np-1;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
protmulA[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnormA[nt-1] += protmulA[counter];
}
}
}
}
for( i=0; i<numMulA; ++i )neutmulA[i] = 0.0;
for( i=0; i<numSec; ++i )neutnormA[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
nm = np;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
neutmulA[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnormA[nt-1] += neutmulA[counter];
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnormA[i] > 0.0 )protnormA[i] = 1.0/protnormA[i];
if( neutnormA[i] > 0.0 )neutnormA[i] = 1.0/neutnormA[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *anAntiProton = G4AntiProton::AntiProton();
G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
// energetically possible to produce pion(s) --> inelastic scattering
// otherwise quasi-elastic scattering
const G4double anhl[] = {1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,0.97,0.88,
0.85,0.81,0.75,0.64,0.64,0.55,0.55,0.45,0.47,0.40,
0.39,0.36,0.33,0.10,0.01};
G4int iplab = G4int( pOriginal/GeV*10.0 );
if( iplab > 9 )iplab = G4int( (pOriginal/GeV- 1.0)*5.0 ) + 10;
if( iplab > 14 )iplab = G4int( pOriginal/GeV- 2.0 ) + 15;
if( iplab > 22 )iplab = G4int( (pOriginal/GeV-10.0)/10.0 ) + 23;
if( iplab > 24 )iplab = 24;
if( G4UniformRand() > anhl[iplab] )
{
if( availableEnergy <= aPiPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
G4int ieab = availableEnergy*5.0/GeV;
const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
G4double w0, wp, wt, wm;
if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one pion will be produced
//
np = nm = nz = 0;
if( targetParticle.GetDefinition() == aProton )
{
test = exp( min( expxu, max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test;
wp = test;
if( G4UniformRand() < w0/(w0+wp) )
nz = 1;
else
np = 1;
}
else // target is a neutron
{
test = exp( min( expxu, max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test;
wp = test;
test = exp( min( expxu, max( expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
wm = test;
wt = w0+wp+wm;
wp += w0;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
}
else // (availableEnergy >= 2.0*GeV) || (random number < supp[ieab])
{
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-2); nm<=np && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
}
if( targetParticle.GetDefinition() == aProton )
{
switch( np-nm )
{
case 1:
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiProton );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
break;
case 2:
currentParticle.SetDefinitionAndUpdateE( anAntiProton );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
break;
default:
break;
}
}
else // target must be a neutron
{
switch( np-nm )
{
case 0:
if( G4UniformRand() < 0.33 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiProton );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
currentParticle.SetDefinitionAndUpdateE( anAntiProton );
incidentHasChanged = true;
break;
default:
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
}
}
}
else // random number <= anhl[iplab]
{
if( centerofmassEnergy <= 2*aPiPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
//
// annihilation channels
//
G4double n, anpn;
GetNormalizationConstant( -centerofmassEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=1; (np<numSec/3) && (ran>=excs); ++np )
{
nm = np-1;
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmulA[counter]*protnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
nm = np;
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmulA[counter]*neutnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nz--;
currentParticle.SetMass( 0.0 );
targetParticle.SetMass( 0.0 );
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,352 @@
// 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: G4LEAntiOmegaMinusInelastic.cc,v 2.4 1998/12/14 15:33:14 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiOmegaMinus Inelastic Process
// J.L. Chuma, TRIUMF, 20-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
//
// NOTE: The FORTRAN version of the cascade, CASAOM, simply called the
// routine for the OmegaMinus particle. Hence, the Cascade function
// below is just a copy of the Cascade from the OmegaMinus particle.
#include "G4LEAntiOmegaMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiOmegaMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
const G4double anni = min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
if( (currentParticle.GetKineticEnergy()/MeV > cutOff) || (G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiOmegaMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASOM by H. Fesefeldt (31-Jan-1989)
//
// AntiOmegaMinus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double pOriginal = originalIncident->GetTotalMomentum()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{ // not energetically possible to produce pion(s)
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aXiZero = G4XiZero::XiZero();
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
G4int nvefix = 0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
//
// number of secondary mesons determined by kno distribution
// check for total charge of final state mesons to determine
// the kind of baryons to be produced, taking into account
// charge and strangeness conservation
//
if( np < nm )
{
if( np+1 == nm )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
nvefix = 1;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
nvefix = 2;
}
}
else if( np > nm )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
if( np+1 < nm )
{
if( np+2 == nm )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
nvefix = 1;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
nvefix = 2;
}
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else if( np+1 == nm )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
for( G4int i=0; i<vecLen && nvefix>0; ++i )
{
if( vec[i]->GetDefinition() == G4PionMinus::PionMinus() )
{
//
// correct the strangeness by replacing a pi- by a kaon-
//
if( nvefix >= 1 )vec[i]->SetDefinitionAndUpdateE( aKaonMinus );
--nvefix;
}
}
return;
}
/* end of file */
@@ -0,0 +1,525 @@
// 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: G4LEAntiProtonInelastic.cc,v 2.5 1998/12/14 15:33:14 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiProton Inelastic Process
// J.L. Chuma, TRIUMF, 13-Feb-1997
// Last modified: 27-Mar-1997
// J.P. Wellisch: 23-Apr-97: Bug hunting
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEAntiProtonInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiProtonInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAntiProtonInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
const G4double anni = min( 1.3*originalIncident->GetTotalMomentum()/GeV, 0.4 );
if( (currentParticle.GetKineticEnergy()/MeV > cutOff) ||
(G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
else
quasiElastic = true;
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiProtonInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASPB by H. Fesefeldt (13-Sep-1987)
//
// AntiProton undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double pOriginal = originalIncident->GetTotalMomentum()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
static G4bool first = true;
const G4int numMul = 1200;
const G4int numMulA = 400;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double protmulA[numMulA], protnormA[numSec]; // proton constants
static G4double neutmulA[numMulA], neutnormA[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
//
// do the same for annihilation channels
//
for( i=0; i<numMulA; ++i )protmulA[i] = 0.0;
for( i=0; i<numSec; ++i )protnormA[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
nm = np;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
protmulA[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnormA[nt-1] += protmulA[counter];
}
}
}
}
for( i=0; i<numMulA; ++i )neutmulA[i] = 0.0;
for( i=0; i<numSec; ++i )neutnormA[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
nm = np+1;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulA[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnormA[nt-1] += neutmulA[counter];
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnormA[i] > 0.0 )protnormA[i] = 1.0/protnormA[i];
if( neutnormA[i] > 0.0 )neutnormA[i] = 1.0/neutnormA[i];
}
} // end of initialization
//
// initialization is OK
//
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *anAntiNeutron = G4AntiNeutron::AntiNeutron();
G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
const G4double anhl[] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.90,
0.6,0.52,0.47,0.44,0.41,0.39,0.37,0.35,0.34,0.24,
0.19,0.15,0.12,0.10,0.09,0.07,0.06,0.05,0.0};
G4int iplab = G4int( pOriginal/GeV*10.0 );
if( iplab > 9 )iplab = G4int( pOriginal/GeV ) + 9;
if( iplab > 18 )iplab = G4int( pOriginal/GeV/10.0 ) + 18;
if( iplab > 27 )iplab = 28;
if( G4UniformRand() > anhl[iplab] )
{
if( availableEnergy <= aPiPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
G4int ieab = availableEnergy*5.0/GeV;
const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
G4double w0, wp, wt, wm;
if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
{
//
// suppress high multiplicity events at low momentum
// only one pion will be produced
//
np = nm = nz = 0;
if( targetParticle.GetDefinition() == aProton )
{
test = exp( min( expxu, max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test;
wp = test;
test = exp( min( expxu, max( expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
wm = test;
wt = w0+wp+wm;
wp += w0;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
else // target is a neutron
{
test = exp( min( expxu, max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test;
test = exp( min( expxu, max( expxl, -(-1.0+b[0])*(-1.0+b[0])/(2.0*c*c) ) ) );
wm = test;
G4double ran = G4UniformRand();
if( ran < w0/(w0+wm) )
nz = 1;
else
nm = 1;
}
}
else // (availableEnergy >= 2.0*GeV) || (random number < supp[ieab])
{
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
}
np--; nm--; nz--;
}
if( targetParticle.GetDefinition() == aProton )
{
switch( np-nm )
{
case 0:
if( G4UniformRand() < 0.33 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiNeutron );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
default:
currentParticle.SetDefinitionAndUpdateE( anAntiNeutron );
incidentHasChanged = true;
break;
}
}
else // target must be a neutron
{
switch( np-nm )
{
case -1:
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( anAntiNeutron );
incidentHasChanged = true;
}
break;
case 0:
break;
default:
currentParticle.SetDefinitionAndUpdateE( anAntiNeutron );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
break;
}
}
}
else // random number <= anhl[iplab]
{
if( centerofmassEnergy <= 2*aPiPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
//
// annihilation channels
//
G4double n, anpn;
GetNormalizationConstant( -centerofmassEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
nm = np;
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmulA[counter]*protnormA[nt-1]/(2.0*n*n);
if( abs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
nm = np+1;
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmulA[counter]*neutnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nz--;
currentParticle.SetMass( 0.0 );
targetParticle.SetMass( 0.0 );
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,544 @@
// 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: G4LEAntiSigmaMinusInelastic.cc,v 2.4 1998/12/14 15:33:14 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiSigmaMinus Inelastic Process
// J.L. Chuma, TRIUMF, 19-Feb-1997
// Last modified: 27-Mar-1997
// J.P. Wellisch: 25.Apr-97: counter errors removed lines 426, 447
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEAntiSigmaMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiSigmaMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAntiSigmaMinusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
const G4double anni = min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
if( (currentParticle.GetKineticEnergy()/MeV > cutOff) || (G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiSigmaMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASASM by H. Fesefeldt (13-Sep-1987)
//
// AntiSigmaMinus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double pOriginal = originalIncident->GetTotalMomentum()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
static G4bool first = true;
const G4int numMul = 1200;
const G4int numMulA = 400;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double protmulA[numMulA], protnormA[numSec]; // proton constants
static G4double neutmulA[numMulA], neutnormA[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[2] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-2); nm<=np; ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
//
// do the same for annihilation channels
//
for( i=0; i<numMulA; ++i )protmulA[i] = 0.0;
for( i=0; i<numSec; ++i )protnormA[i] = 0.0;
counter = -1;
for( np=2; np<(numSec/3); ++np )
{
nm = np-2;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
protmulA[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnormA[nt-1] += protmulA[counter];
}
}
}
}
for( i=0; i<numMulA; ++i )neutmulA[i] = 0.0;
for( i=0; i<numSec; ++i )neutnormA[i] = 0.0;
counter = -1;
for( np=1; np<numSec/3; ++np )
{
nm = np-1;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
neutmulA[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnormA[nt-1] += neutmulA[counter];
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnormA[i] > 0.0 )protnormA[i] = 1.0/protnormA[i];
if( neutnormA[i] > 0.0 )neutnormA[i] = 1.0/neutnormA[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
G4ParticleDefinition *anAntiLambda = G4AntiLambda::AntiLambda();
G4ParticleDefinition *anAntiSigmaZero = G4AntiSigmaZero::AntiSigmaZero();
const G4double anhl[] = {1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,0.97,0.88,
0.85,0.81,0.75,0.64,0.64,0.55,0.55,0.45,0.47,0.40,
0.39,0.36,0.33,0.10,0.01};
G4int iplab = G4int( pOriginal/GeV*10.0 );
if( iplab > 9 )iplab = G4int( (pOriginal/GeV- 1.0)*5.0 ) + 10;
if( iplab > 14 )iplab = G4int( pOriginal/GeV- 2.0 ) + 15;
if( iplab > 23 )iplab = G4int( (pOriginal/GeV-10.0)/10.0 ) + 23;
if( iplab > 24 )iplab = 24;
if( G4UniformRand() > anhl[iplab] )
{
if( availableEnergy <= aPiPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-2); nm<=np && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = min( 3, max( 1, np-nm+1 ) );
switch( ncht )
{
case 1:
break;
case 2:
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
else
{
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
else
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
}
break;
case 3:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
else
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = min( 3, max( 1, np-nm+2 ) );
switch( ncht )
{
case 1:
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
break;
case 2:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
else
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
break;
case 3:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
else
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
break;
}
}
}
else // random number <= anhl[iplab]
{
if( centerofmassEnergy <= aPiPlus->GetPDGMass()/MeV+aKaonPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
G4double n, anpn;
GetNormalizationConstant( -centerofmassEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=2; np<numSec/3 && ran>=excs; ++np )
{
nm=np-2;
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmulA[counter]*protnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nz--;
}
else // target must be a neutron
{
counter = -1;
for( np=1; np<numSec/3 && ran>=excs; ++np )
{
nm = np-1;
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmulA[counter]*neutnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nz--;
}
if( nz > 0 )
{
if( nm > 0 )
{
if( G4UniformRand() < 0.5 )
{
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
else // random number >= 0.5
{
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonZL );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nz;
}
}
else // nm == 0
{
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonZL );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nz;
}
}
else // nz == 0
{
if( nm > 0 )
{
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
currentParticle.SetMass( 0.0 );
targetParticle.SetMass( 0.0 );
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,545 @@
// 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: G4LEAntiSigmaPlusInelastic.cc,v 2.4 1998/12/14 15:33:14 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiSigmaPlus Inelastic Process
// J.L. Chuma, TRIUMF, 19-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEAntiSigmaPlusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiSigmaPlusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAntiSigmaPlusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
const G4double anni = min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
if( (currentParticle.GetKineticEnergy()/MeV > cutOff) || (G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiSigmaPlusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASASP by H. Fesefeldt (13-Sep-1987)
//
// AntiSigmaPlus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double pOriginal = originalIncident->GetTotalMomentum()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
static G4bool first = true;
const G4int numMul = 1200;
const G4int numMulA = 400;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double protmulA[numMulA], protnormA[numSec]; // proton constants
static G4double neutmulA[numMulA], neutnormA[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
//
// do the same for annihilation channels
//
for( i=0; i<numMulA; ++i )protmulA[i] = 0.0;
for( i=0; i<numSec; ++i )protnormA[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); ++np )
{
nm = np;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
protmulA[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnormA[nt-1] += protmulA[counter];
}
}
}
}
for( i=0; i<numMulA; ++i )neutmulA[i] = 0.0;
for( i=0; i<numSec; ++i )neutnormA[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
nm = np+1;
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
neutmulA[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnormA[nt-1] += neutmulA[counter];
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnormA[i] > 0.0 )protnormA[i] = 1.0/protnormA[i];
if( neutnormA[i] > 0.0 )neutnormA[i] = 1.0/neutnormA[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
G4ParticleDefinition *anAntiLambda = G4AntiLambda::AntiLambda();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *anAntiSigmaZero = G4AntiSigmaZero::AntiSigmaZero();
const G4double anhl[] = {1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,0.97,0.88,
0.85,0.81,0.75,0.64,0.64,0.55,0.55,0.45,0.47,0.40,
0.39,0.36,0.33,0.10,0.01};
G4int iplab = G4int( pOriginal/GeV*10.0 );
if( iplab > 9 )iplab = G4int( (pOriginal/GeV- 1.0)*5.0 ) + 10;
if( iplab > 14 )iplab = G4int( pOriginal/GeV- 2.0 ) + 15;
if( iplab > 22 )iplab = G4int( (pOriginal/GeV-10.0)/10.0 ) + 23;
if( iplab > 24 )iplab = 24;
if( G4UniformRand() > anhl[iplab] )
{
if( availableEnergy <= aPiPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = min( 3, max( 1, np-nm+2 ) );
switch( ncht )
{
case 1:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
else
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
break;
case 2:
if( G4UniformRand() >= 0.5 )
{
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
else
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
}
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
case 3:
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = min( 3, max( 1, np-nm+3 ) );
switch( ncht )
{
case 1:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
else
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
else
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
break;
case 3:
break;
}
}
}
else // random number <= anhl[iplab]
{
if( centerofmassEnergy <= aPiPlus->GetPDGMass()/MeV+aKaonPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
G4double n, anpn;
GetNormalizationConstant( -centerofmassEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=1; np<numSec/3 && ran>=excs; ++np )
{
nm = np;
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmulA[counter]*protnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nz--;
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
nm = np+1;
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMulA )
{
nt = np+nm+nz;
if( nt>1 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmulA[counter]*neutnormA[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nz--;
}
if( nz > 0 )
{
if( nm > 0 )
{
if( G4UniformRand() < 0.5 )
{
vec.Initialize( 1 );
G4ReactionProduct *p= new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
else
{
vec.Initialize( 1 );
G4ReactionProduct *p= new G4ReactionProduct ;
p->SetDefinition( aKaonZL );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nz;
}
}
else // nm == 0
{
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonZL );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nz;
}
}
else // nz == 0
{
if( nm > 0 )
{
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
currentParticle.SetMass( 0.0 );
targetParticle.SetMass( 0.0 );
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,377 @@
// 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: G4LEAntiXiMinusInelastic.cc,v 2.4 1998/12/14 15:33:14 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiXiMinus Inelastic Process
// J.L. Chuma, TRIUMF, 20-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
//
// NOTE: The FORTRAN version of the cascade, CASAXM, simply called the
// routine for the XiMinus particle. Hence, the ApplyYourself function
// below is just a copy of the ApplyYourself from the XiMinus particle.
#include "G4LEAntiXiMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiXiMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAntiXiMinusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
const G4double anni = min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
if( (currentParticle.GetKineticEnergy()/MeV > cutOff) || (G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiXiMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASAXM by H. Fesefeldt (17-Jan-1989)
// which is just a copy of casxm (cascade for Xi-).
//
// AntiXiMinus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aXiZero = G4XiZero::XiZero();
//
// energetically possible to produce pion(s) --> inelastic scattering
//
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
//
// number of secondary mesons determined by kno distribution
// check for total charge of final state mesons to determine
// the kind of baryons to be produced, taking into account
// charge and strangeness conservation
//
if( np < nm )
{
if( np+1 == nm )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np == nm )
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
if( np+1 < nm )
{
if( np+2 == nm )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np+1 == nm )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,376 @@
// 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: G4LEAntiXiZeroInelastic.cc,v 2.3 1998/07/13 17:24:20 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: AntiXiZero Inelastic Process
// J.L. Chuma, TRIUMF, 20-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
//
// NOTE: The FORTRAN version of the cascade, CASAXO, simply called the
// routine for the XiZero particle. Hence, the ApplyYourself function
// below is just a copy of the ApplyYourself from the XiZero particle.
#include "G4LEAntiXiZeroInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEAntiXiZeroInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEAntiXiZeroInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
const G4double anni = min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
if( (currentParticle.GetKineticEnergy()/MeV > cutOff) || (G4UniformRand() > anni) )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEAntiXiZeroInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASAX0 by H. Fesefeldt (20-Jan-1989)
// which is just a copy of CASX0 (cascade for Xi0)
//
// AntiXiZero undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-2); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aXiMinus = G4XiMinus::XiMinus();
//
// energetically possible to produce pion(s) --> inelastic scattering
//
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-2); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
//
// number of secondary mesons determined by kno distribution
// check for total charge of final state mesons to determine
// the kind of baryons to be produced, taking into account
// charge and strangeness conservation
//
if( np < nm+1 )
{
if( np != nm ) // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np == nm+1 )
{
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
}
}
else
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
if( np < nm )
{
if( np+1 == nm )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np == nm )
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
else
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,77 @@
// 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: G4LEDeuteronInelastic.cc,v 2.8 1998/12/14 15:33:14 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Deuteron Inelastic Process
// J.L. Chuma, TRIUMF, 25-Feb-1997
// Last modified: 27-Mar-1997
#include "G4LEDeuteronInelastic.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
G4VParticleChange *
G4LEDeuteronInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEDeuteronInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
}
// Work-around for lack of model above 100 MeV
if (originalIncident->GetKineticEnergy()/MeV > 100. ||
originalIncident->GetKineticEnergy() <= 0.1*MeV) return &theParticleChange;
G4double N = targetNucleus.GetN();
G4double Z = targetNucleus.GetZ();
G4double theAtomicMass = targetNucleus.AtomicMass( N, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
G4double massVec[9];
massVec[0] = targetNucleus.AtomicMass( N+2.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[1] = targetNucleus.AtomicMass( N+1.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[2] = targetNucleus.AtomicMass( N+1.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
massVec[3] = theAtomicMass;
massVec[4] = targetNucleus.AtomicMass( N-1.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
massVec[5] = targetNucleus.AtomicMass( N-2.0, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
massVec[6] = targetNucleus.AtomicMass( N, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[7] = massVec[3];
massVec[8] = targetNucleus.AtomicMass( N, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
G4FastVector<G4ReactionProduct,3> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
theReactionDynamics.NuclearReaction( vec, vecLen, originalIncident,
targetNucleus, theAtomicMass, massVec );
G4double p = originalIncident->GetTotalMomentum();
theParticleChange.SetMomentumChange( originalIncident->GetMomentum() * (1.0/p) );
theParticleChange.SetEnergyChange( originalIncident->GetKineticEnergy() );
theParticleChange.SetNumberOfSecondaries( vecLen );
G4DynamicParticle *pd;
for( G4int i=0; i<vecLen; ++i )
{
pd = new G4DynamicParticle();
pd->SetDefinition( vec[i]->GetDefinition() );
pd->SetMomentum( vec[i]->GetMomentum() );
theParticleChange.AddSecondary( pd );
}
return &theParticleChange;
}
/* end of file */
@@ -0,0 +1,515 @@
// 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: G4LEKaonMinusInelastic.cc,v 2.4 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Low Energy KaonMinus Inelastic Process
// J.L. Chuma, TRIUMF, 12-Feb-1997
// Last modified: 27-Mar-1997
// J.P.Wellisch 23-Apr-97: bug-hunting (missing initialization of np,nm,nz fixed)
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEKaonMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEKaonMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
// create the target particle
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
G4double targetMass = originalTarget->GetDefinition()->GetPDGMass();
G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEKaonMinusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
G4ReactionProduct currentParticle( originalIncident->GetDefinition() );
currentParticle.SetMomentum( originalIncident->GetMomentum() );
currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
G4double ek = originalIncident->GetKineticEnergy();
G4double amas = originalIncident->GetDefinition()->GetPDGMass();
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
currentParticle.SetKineticEnergy( ek );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
// calculate black track energies
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
currentParticle.SetKineticEnergy( ek );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct modifiedOriginal = currentParticle;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1*MeV;
if( currentParticle.GetKineticEnergy() > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEKaonMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASKM by H. Fesefeldt (13-Sep-1987)
//
// K- undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
const G4double etOriginal = originalIncident->GetTotalEnergy();
const G4double pOriginal = originalIncident->GetTotalMomentum();
const G4double targetMass = targetParticle.GetMass();
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int nt, np, nm, nz;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.70 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
G4int counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aKaonZS = G4KaonZeroShort::KaonZeroShort();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
G4ParticleDefinition *aLambda = G4Lambda::Lambda();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aSigmaMinus = G4SigmaMinus::SigmaMinus();
G4ParticleDefinition *aSigmaZero = G4SigmaZero::SigmaZero();
const G4double cech[] = {1.,1.,1.,0.70,0.60,0.55,0.35,0.25,0.18,0.15};
G4int iplab = min( 9.0, pOriginal/GeV*5.0 );
if( (pOriginal <= 2.0*GeV) && (G4UniformRand() < cech[iplab]) )
{
np = nm = nz = nt = 0;
iplab = min( 19.0, pOriginal/GeV*10.0 );
const G4double cnk0[] = {0.17,0.18,0.17,0.24,0.26,0.20,0.22,0.21,0.34,0.45,
0.58,0.55,0.36,0.29,0.29,0.32,0.32,0.33,0.33,0.33};
if( G4UniformRand() <= cnk0[iplab] )
{
quasiElastic = true;
if( targetParticle.GetDefinition() == aProton )
{
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else // random number > cnk0[iplab]
{
G4double ran = G4UniformRand();
if( ran < 0.25 ) // k- p --> pi- s+
{
if( targetParticle.GetDefinition() == aProton )
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetHasChanged = true;
}
}
else if( ran < 0.50 ) // k- p --> pi0 s0 or k- n --> pi- s0
{
if( targetParticle.GetDefinition() == aNeutron )
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
else
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetHasChanged = true;
}
else if( ran < 0.75 ) // k- p --> pi+ s- or k- n --> pi0 s-
{
if( targetParticle.GetDefinition() == aNeutron )
currentParticle.SetDefinitionAndUpdateE( aPiZero );
else
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
targetHasChanged = true;
}
else // k- p --> pi0 L or k- n --> pi- L
{
if( targetParticle.GetDefinition() == aNeutron )
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
else
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aLambda );
incidentHasChanged = true;
targetHasChanged = true;
}
}
}
else // (pOriginal > 2.0*GeV) || (random number >= cech[iplab])
{
if( availableEnergy < aPiPlus->GetPDGMass() )
{ // not energetically possible to produce pion(s)
quasiElastic = true;
return;
}
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, test, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
G4int counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
if( np == nm )
{
if( G4UniformRand() >= 0.75 )
{
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
}
}
else if( np == nm+1 )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
incidentHasChanged = true;
}
}
else // target must be a neutron
{
G4int counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
if( np == nm-1 )
{
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
incidentHasChanged = true;
}
}
else if( np != nm )
{
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
incidentHasChanged = true;
}
}
if( G4UniformRand() >= 0.5 )
{
if( (currentParticle.GetDefinition() == aKaonMinus &&
targetParticle.GetDefinition() == aNeutron ) ||
(currentParticle.GetDefinition() == aKaonZL &&
targetParticle.GetDefinition() == aProton ) )
{
ran = G4UniformRand();
if( ran < 0.68 )
{
if( targetParticle.GetDefinition() == aProton )
{
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aLambda );
incidentHasChanged = true;
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aLambda );
incidentHasChanged = true;
targetHasChanged = true;
}
}
else if( ran < 0.84 )
{
if( targetParticle.GetDefinition() == aProton )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetHasChanged = true;
}
}
else
{
if( targetParticle.GetDefinition() == aProton )
{
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
targetHasChanged = true;
}
}
}
else // ( current != aKaonMinus || target != aNeutron ) &&
// ( current != aKaonZL || target != aProton )
{
ran = G4UniformRand();
if( ran < 0.67 )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aLambda );
incidentHasChanged = true;
targetHasChanged = true;
}
else if( ran < 0.78 )
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetHasChanged = true;
}
else if( ran < 0.89 )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
targetHasChanged = true;
}
}
}
}
if( currentParticle.GetDefinition() == aKaonZL )
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aKaonZS );
incidentHasChanged = true;
}
}
if( targetParticle.GetDefinition() == aKaonZL )
{
if( G4UniformRand() >= 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aKaonZS );
targetHasChanged = true;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,382 @@
// 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: G4LEKaonPlusInelastic.cc,v 2.4 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Low Energy KaonPlus Inelastic Process
// J.L. Chuma, TRIUMF, 05-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEKaonPlusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEKaonPlusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
// create the target particle
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
G4double targetMass = originalTarget->GetDefinition()->GetPDGMass();
G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEKaonPlusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
G4ReactionProduct currentParticle( originalIncident->GetDefinition() );
currentParticle.SetMomentum( originalIncident->GetMomentum() );
currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
G4double ek = originalIncident->GetKineticEnergy();
G4double amas = originalIncident->GetDefinition()->GetPDGMass();
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
currentParticle.SetKineticEnergy( ek );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
// calculate black track energies
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
currentParticle.SetKineticEnergy( ek );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct modifiedOriginal = currentParticle;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1*MeV;
if( currentParticle.GetKineticEnergy() > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEKaonPlusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int &vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASKP by H. Fesefeldt (13-Sep-1987)
//
// K+ undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
const G4double etOriginal = originalIncident->GetTotalEnergy();
const G4double targetMass = targetParticle.GetMass();
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy < G4PionPlus::PionPlus()->GetPDGMass() )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int nt=0, np=0, nm=0, nz=0;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.70 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
G4int counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-2); nm<=np; ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aKaonZS = G4KaonZeroShort::KaonZeroShort();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4int ieab = availableEnergy*5.0/GeV;
const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
G4double test, w0, wp, wt, wm;
if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one pion will be produced
nm = np = nz = 0;
if( targetParticle.GetDefinition() == aProton )
{
test = exp( min( expxu, max( expxl, -sqr(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test;
wp = test*2.0;
if( G4UniformRand() < w0/(w0+wp) )
nz = 1;
else
np = 1;
}
else // target is a neutron
{
test = exp( min( expxu, max( expxl, -sqr(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test;
wp = test;
test = exp( min( expxu, max( expxl, -sqr(-1.0+b[1])/(2.0*c*c) ) ) );
wm = test;
wt = w0+wp+wm;
wp += w0;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
}
else
{
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
G4int counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
for( nm=max(0,np-2); (nm<=np) && (ran>=excs); ++nm )
{
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs )return; // 3 previous loops continued to the end
np--; nm--; nz--;
}
else // target must be a neutron
{
G4int counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
for( nm=max(0,np-1); (nm<=(np+1)) && (ran>=excs); ++nm )
{
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs )return; // 3 previous loops continued to the end
np--; nm--; nz--;
}
}
if( targetParticle.GetDefinition() == aProton )
{
switch( np-nm )
{
case 1:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aKaonZS );
else
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
break;
case 2:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aKaonZS );
else
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
break;
default:
break;
}
}
else // target is a neutron
{
switch( np-nm )
{
case 0:
if( G4UniformRand() < 0.25 )
{
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aKaonZS );
else
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aKaonZS );
else
currentParticle.SetDefinitionAndUpdateE( aKaonZL );
incidentHasChanged = true;
break;
default: // assumes nm = np+1 so charge is conserved
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,486 @@
// 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: G4LEKaonZeroLInelastic.cc,v 2.3 1998/07/13 17:24:25 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Low Energy KaonZeroLong Inelastic Process
// J.L. Chuma, TRIUMF, 11-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEKaonZeroLInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEKaonZeroLInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEKaonZeroLInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
if( currentParticle.GetKineticEnergy()/MeV > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEKaonZeroLInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASK0B by H. Fesefeldt (13-Sep-1987)
//
// K0Long undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double pOriginal = originalIncident->GetTotalMomentum()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-2); nm<=np; ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aKaonZS = G4KaonZeroShort::KaonZeroShort();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
G4ParticleDefinition *aLambda = G4Lambda::Lambda();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aSigmaMinus = G4SigmaMinus::SigmaMinus();
G4ParticleDefinition *aSigmaZero = G4SigmaZero::SigmaZero();
const G4double cech[] = {1.,1.,1.,0.70,0.60,0.55,0.35,0.25,0.18,0.15};
G4int iplab = min( 9.0, 5.0*pOriginal*MeV/GeV );
if( (pOriginal*MeV/GeV <= 2.0) && (G4UniformRand() < cech[iplab]) )
{
np = nm = nz = nt = 0;
iplab = min( 19.0, pOriginal*MeV/GeV*10.0 );
const G4double cnk0[] = {0.17,0.18,0.17,0.24,0.26,0.20,0.22,0.21,0.34,0.45,
0.58,0.55,0.36,0.29,0.29,0.32,0.32,0.33,0.33,0.33};
if( G4UniformRand() > cnk0[iplab] )
{
G4double ran = G4UniformRand();
if( ran < 0.25 ) // k0Long n --> pi- s+
{
if( targetParticle.GetDefinition() == aNeutron )
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetHasChanged = true;
}
}
else if( ran < 0.50 ) // k0Long p --> pi+ s0 or k0Long n --> pi0 s0
{
if( targetParticle.GetDefinition() == aNeutron )
currentParticle.SetDefinitionAndUpdateE( aPiZero );
else
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetHasChanged = true;
}
else if( ran < 0.75 ) // k0Long n --> pi+ s-
{
if( targetParticle.GetDefinition() == aNeutron )
{
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
targetHasChanged = true;
}
}
else // k0Long p --> pi+ L or k0Long n --> pi0 L
{
if( targetParticle.GetDefinition() == aNeutron )
currentParticle.SetDefinitionAndUpdateE( aPiZero );
else
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aLambda );
incidentHasChanged = true;
targetHasChanged = true;
}
}
else // ran <= cnk0
{
quasiElastic = true;
if( targetParticle.GetDefinition() == aNeutron )
{
currentParticle.SetDefinitionAndUpdateE( aKaonMinus );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
}
}
}
else // (pOriginal > 2.0*GeV) || (random number >= cech[iplab])
{
if( availableEnergy < aPiPlus->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, test, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
for( nm=max(0,np-2); nm<=np && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
switch( np-nm )
{
case 1:
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aKaonMinus );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
case 0:
break;
default:
currentParticle.SetDefinitionAndUpdateE( aKaonMinus );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
break;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
switch( np-nm )
{
case 0:
currentParticle.SetDefinitionAndUpdateE( aKaonMinus );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
break;
case 1:
currentParticle.SetDefinitionAndUpdateE( aKaonMinus );
incidentHasChanged = true;
break;
default:
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
}
}
if( G4UniformRand() >= 0.5 )
{
if( currentParticle.GetDefinition() == aKaonMinus &&
targetParticle.GetDefinition() == aNeutron )
{
ran = G4UniformRand();
if( ran < 0.68 )
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aLambda );
}
else if( ran < 0.84 )
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
}
else
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aSigmaMinus );
}
}
else if( (currentParticle.GetDefinition() == aKaonZS ||
currentParticle.GetDefinition() == aKaonZL ) &&
targetParticle.GetDefinition() == aProton )
{
ran = G4UniformRand();
if( ran < 0.68 )
{
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aLambda );
}
else if( ran < 0.84 )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aSigmaPlus );
}
else
{
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
}
}
else
{
ran = G4UniformRand();
if( ran < 0.67 )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aLambda );
}
else if( ran < 0.78 )
{
currentParticle.SetDefinitionAndUpdateE( aPiMinus );
targetParticle.SetDefinitionAndUpdateE( aSigmaPlus );
}
else if( ran < 0.89 )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aSigmaZero );
}
else
{
currentParticle.SetDefinitionAndUpdateE( aPiPlus );
targetParticle.SetDefinitionAndUpdateE( aSigmaMinus );
}
}
incidentHasChanged = true;
targetHasChanged = true;
}
}
if( currentParticle.GetDefinition() == aKaonZL )
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aKaonZS );
incidentHasChanged = true;
}
}
if( targetParticle.GetDefinition() == aKaonZL )
{
if( G4UniformRand() >= 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aKaonZS );
targetHasChanged = true;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,391 @@
// 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: G4LEKaonZeroSInelastic.cc,v 2.3 1998/07/13 17:24:27 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Low Energy KaonZeroShort Inelastic Process
// J.L. Chuma, TRIUMF, 11-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEKaonZeroSInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEKaonZeroSInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEKaonZeroSInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
if( currentParticle.GetKineticEnergy()/MeV > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEKaonZeroSInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASK0 by H. Fesefeldt (13-Sep-1987)
//
// K0Short undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-2); nm<=np; ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *aKaonZS = G4KaonZeroShort::KaonZeroShort();
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4int ieab = 5.0*availableEnergy*MeV/GeV;
const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
G4double test, w0, wp, wt, wm;
if( (availableEnergy*MeV/GeV < 2.0) && (G4UniformRand() >= supp[ieab]) )
{
//
// suppress high multiplicity events at low momentum
// only one pion will be produced
//
nm = np = nz = 0;
if( targetParticle.GetDefinition() == aNeutron )
{
test = exp( min( expxu, max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test/2.0;
test = exp( min( expxu, max( expxl, -(-1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
wm = test*1.5;
if( G4UniformRand() < w0/(w0+wm) )
nz = 1;
else
nm = 1;
}
else // target is a proton
{
test = exp( min( expxu, max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test;
wp = test;
test = exp( min( expxu, max( expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
wm = test;
wt = w0+wp+wm;
wp += w0;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
}
else // (availableEnergy*MeV/GeV >= 2.0) || (G4UniformRand() < supp[ieab])
{
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-2); nm<=np && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
}
if( targetParticle.GetDefinition() == aProton )
{
switch( np-nm )
{
case 0:
if( G4UniformRand() < 0.25 )
{
currentParticle.SetDefinitionAndUpdateE( aKaonPlus );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
default:
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
}
}
else // targetParticle is a neutron
{
switch( np-nm ) // seems wrong, charge not conserved
{
case 1:
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aKaonPlus );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
break;
case 2:
currentParticle.SetDefinitionAndUpdateE( aKaonPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
default:
break;
}
}
if( currentParticle.GetDefinition() == aKaonZS )
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aKaonZL);
incidentHasChanged = true;
}
}
if( targetParticle.GetDefinition() == aKaonZS )
{
if( G4UniformRand() >= 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aKaonZL );
targetHasChanged = true;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,343 @@
// 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: G4LELambdaInelastic.cc,v 2.3 1998/07/13 17:24:28 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Lambda Inelastic Process
// J.L. Chuma, TRIUMF, 18-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LELambdaInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LELambdaInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LELambdaInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
if( currentParticle.GetKineticEnergy()/MeV > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LELambdaInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASL0 by H. Fesefeldt (13-Sep-1987)
//
// Lambda undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.35 };
if( first ) { // compute normalization constants, this will only be Done once
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np ) {
for( nm=max(0,np-2); nm<=(np+1); ++nm ) {
for( nz=0; nz<numSec/3; ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( nt>0 && nt<=numSec ) {
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np ) {
for( nm=max(0,np-1); nm<=(np+2); ++nm ) {
for( nz=0; nz<numSec/3; ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( nt>0 && nt<=numSec ) {
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i ) {
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aSigmaMinus = G4SigmaMinus::SigmaMinus();
G4ParticleDefinition *aSigmaZero = G4SigmaZero::SigmaZero();
// energetically possible to produce pion(s) --> inelastic scattering
// otherwise quasi-elastic scattering
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton ) {
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np ) {
for( nm=max(0,np-2); nm<=(np+1) && ran>=excs; ++nm ) {
for( nz=0; nz<numSec/3 && ran>=excs; ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( nt>0 && nt<=numSec ) {
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 ) {
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = max( 1, np-nm );
switch( ncht ) {
case 1:
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 ) {
if( G4UniformRand() < 0.5 ) {
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
}
} else {
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
break;
case 3:
if( G4UniformRand() < 0.5 ) {
if( G4UniformRand() < 0.5 ) {
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
}
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
} else {
currentParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
}
break;
default:
currentParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np ) {
for( nm=max(0,np-1); nm<=(np+2) && ran>=excs; ++nm ) {
for( nz=0; nz<numSec/3 && ran>=excs; ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( nt>0 && nt<=numSec ) {
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 ) {
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = max( 1, np-nm+3 );
switch( ncht ) {
case 1:
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 ) {
if( G4UniformRand() < 0.5 ) {
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
}
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
} else {
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
}
break;
case 3:
if( G4UniformRand() < 0.5 ) {
if( G4UniformRand() < 0.5 ) {
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
}
} else {
currentParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
break;
default:
currentParticle.SetDefinitionAndUpdateE( aSigmaMinus );
incidentHasChanged = true;
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,500 @@
// 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: G4LENeutronInelastic.cc,v 2.11 1998/12/07 12:34:07 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Low Energy Neutron Inelastic Process
// J.L. Chuma, TRIUMF, 04-Feb-1997
#include "G4LENeutronInelastic.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
G4VParticleChange *
G4LENeutronInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LENeutronInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
if( originalIncident->GetKineticEnergy()/MeV < 0.000001 )
G4Exception("G4LENeutronInelastic: should be capture process!");
if( originalIncident->GetMomentum().mag()/MeV < 0.000001 )
G4Exception("G4LENeutronInelastic: should be capture process!");
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
if( originalIncident->GetKineticEnergy()/GeV < 0.01 + 2.*G4UniformRand()/9. )
{
SlowNeutron( originalIncident, modifiedOriginal, targetParticle, targetNucleus );
delete originalTarget;
return &theParticleChange;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
const G4double cutOff = 0.1;
if( modifiedOriginal.GetKineticEnergy()/MeV <= cutOff )
{
SlowNeutron( originalIncident, modifiedOriginal, targetParticle, targetNucleus );
delete originalTarget;
return &theParticleChange;
}
G4ReactionProduct currentParticle = modifiedOriginal;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LENeutronInelastic::SlowNeutron(
const G4DynamicParticle *originalIncident,
G4ReactionProduct &modifiedOriginal,
G4ReactionProduct &targetParticle,
G4Nucleus &targetNucleus )
{
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aDeuteron = G4Deuteron::Deuteron();
G4ParticleDefinition *aTriton = G4Triton::Triton();
G4ParticleDefinition *anAlpha = G4Alpha::Alpha();
const G4double aProtonMass = aProton->GetPDGMass()/MeV;
const G4double aNeutronMass = aNeutron->GetPDGMass()/MeV;
const G4double aDeuteronMass = aDeuteron->GetPDGMass()/MeV;
const G4double aTritonMass = aTriton->GetPDGMass()/MeV;
const G4double anAlphaMass = anAlpha->GetPDGMass()/MeV;
const G4double A = targetNucleus.GetN(); // atomic weight
const G4double Z = targetNucleus.GetZ(); // atomic number
G4double currentKinetic = modifiedOriginal.GetKineticEnergy()/MeV;
G4double currentMass = modifiedOriginal.GetMass()/MeV;
if( A < 1.5 ) // Hydrogen
{
//
// very simple simulation of scattering angle and energy
// nonrelativistic approximation with isotropic angular
// distribution in the cms system
//
G4double cost1, eka = 0.0;
while (eka <= 0.0)
{
cost1 = -1.0 + 2.0*G4UniformRand();
eka = 1.0 + 2.0*cost1*A + A*A;
}
G4double cost = min( 1.0, max( -1.0, (A*cost1+1.0)/sqrt(eka) ) );
eka /= (1.0+A)*(1.0+A);
G4double ek = currentKinetic*MeV/GeV;
G4double amas = currentMass*MeV/GeV;
ek *= eka;
G4double en = ek + amas;
G4double p = sqrt(abs(en*en-amas*amas));
G4double sint = sqrt(abs(1.0-cost*cost));
G4double phi = G4UniformRand()*twopi;
G4double px = sint*sin(phi);
G4double py = sint*cos(phi);
G4double pz = cost;
targetParticle.SetMomentum( px*GeV, py*GeV, pz*GeV );
G4double pxO = originalIncident->GetMomentum().x()/GeV;
G4double pyO = originalIncident->GetMomentum().y()/GeV;
G4double pzO = originalIncident->GetMomentum().z()/GeV;
G4double ptO = pxO*pxO + pyO+pyO;
if( ptO > 0.0 )
{
G4double pO = sqrt(pxO*pxO+pyO*pyO+pzO*pzO);
cost = pzO/pO;
sint = 0.5*(sqrt(abs((1.0-cost)*(1.0+cost)))+sqrt(ptO)/pO);
G4double ph = pi/2.0;
if( pyO < 0.0 )ph = ph*1.5;
if( abs(pxO) > 0.000001 )ph = atan2(pyO,pxO);
G4double cosp = cos(ph);
G4double sinp = sin(ph);
px = cost*cosp*px - sinp*py+sint*cosp*pz;
py = cost*sinp*px + cosp*py+sint*sinp*pz;
pz = -sint*px + cost*pz;
}
else
{
if( pz < 0.0 )pz *= -1.0;
}
G4double pu = sqrt(px*px+py*py+pz*pz);
modifiedOriginal.SetMomentum( targetParticle.GetMomentum() * (p/pu) );
modifiedOriginal.SetKineticEnergy( ek*GeV );
targetParticle.SetMomentum(
originalIncident->GetMomentum() - modifiedOriginal.GetMomentum() );
G4double pp = targetParticle.GetMomentum().mag();
G4double tarmas = targetParticle.GetMass();
targetParticle.SetTotalEnergy( sqrt( pp*pp + tarmas*tarmas ) );
theParticleChange.SetEnergyChange( modifiedOriginal.GetKineticEnergy() );
theParticleChange.SetNumberOfSecondaries( 1 );
G4DynamicParticle *pd = new G4DynamicParticle;
pd->SetDefinition( targetParticle.GetDefinition() );
pd->SetMomentum( targetParticle.GetMomentum() );
theParticleChange.AddSecondary( pd );
return;
}
G4FastVector<G4ReactionProduct,3> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
G4double theAtomicMass = targetNucleus.AtomicMass( A, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
G4double massVec[9];
massVec[0] = targetNucleus.AtomicMass( A+1.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
massVec[1] = theAtomicMass;
massVec[2] = targetNucleus.AtomicMass( A , Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
massVec[3] = targetNucleus.AtomicMass( A-1.0, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
massVec[4] = targetNucleus.AtomicMass( A-2.0, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
massVec[5] = targetNucleus.AtomicMass( A-3.0, Z-2.0 )-(Z-2.0)*G4Electron::Electron()->GetPDGMass();
massVec[6] = targetNucleus.AtomicMass( A-1.0, Z );
massVec[7] = massVec[3];
massVec[8] = targetNucleus.AtomicMass( A-1.0, Z-2.0 )-(Z-2.0)*G4Electron::Electron()->GetPDGMass();
theReactionDynamics.NuclearReaction( vec, vecLen, originalIncident,
targetNucleus, theAtomicMass, massVec );
theParticleChange.SetStatusChange( fStopAndKill );
theParticleChange.SetEnergyChange( 0.0 );
theParticleChange.SetNumberOfSecondaries( vecLen );
G4DynamicParticle * pd;
for( G4int i=0; i<vecLen; ++i )
{
pd = new G4DynamicParticle();
pd->SetDefinition( vec[i]->GetDefinition() );
pd->SetMomentum( vec[i]->GetMomentum() );
theParticleChange.AddSecondary( pd );
}
}
void
G4LENeutronInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASN by H. Fesefeldt (13-Sep-1987)
//
// Neutron undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
const G4double c = 1.25;
const G4double b[] = { 0.35, 0.0 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c) /
( theReactionDynamics.Factorial(1-np+nm)*
theReactionDynamics.Factorial(1+np-nm) );
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c) /
( theReactionDynamics.Factorial(nm-np)*
theReactionDynamics.Factorial(2-nm+np) );
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4int ieab = availableEnergy*5.0/GeV;
const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
G4double test, w0, wp, wt, wm;
if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one pion will be produced
nm = np = nz = 0;
if( targetParticle.GetDefinition() == aNeutron )
{
test = exp( min( expxu, max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test/2.0;
wm = test;
if( G4UniformRand() < w0/(w0+wm) )
nz = 1;
else
nm = 1;
} else { // target is a proton
test = exp( min( expxu, max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test;
wp = test/2.0;
test = exp( min( expxu, max( expxl, -(-1.0+b[0])*(-1.0+b[0])/(2.0*c*c) ) ) );
wm = test/2.0;
wt = w0+wp+wm;
wp += w0;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
} else { // (availableEnergy >= 2.0*GeV) || (random number < supp[ieab])
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 ) {
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
} else { // target must be a neutron
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 ) {
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
}
if( targetParticle.GetDefinition() == aProton )
{
switch( np-nm )
{
case 0:
if( G4UniformRand() < 0.33 )
{
currentParticle.SetDefinitionAndUpdateE( aProton );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
default:
currentParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
break;
}
} else { // target must be a neutron
switch( np-nm )
{
case -1: // changed from +1 by JLC, 7Jul97
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
} else {
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
break;
case 0:
break;
default:
currentParticle.SetDefinitionAndUpdateE( aProton );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,355 @@
// 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: G4LEOmegaMinusInelastic.cc,v 2.4 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: OmegaMinus Inelastic Process
// J.L. Chuma, TRIUMF, 20-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEOmegaMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEOmegaMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
// create the target particle
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
G4double targetMass = originalTarget->GetDefinition()->GetPDGMass();
G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEOmegaMinusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
G4ReactionProduct currentParticle( originalIncident->GetDefinition() );
currentParticle.SetMomentum( originalIncident->GetMomentum() );
currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
G4double ek = originalIncident->GetKineticEnergy();
G4double amas = originalIncident->GetDefinition()->GetPDGMass();
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
currentParticle.SetKineticEnergy( ek );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
// calculate black track energies
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
currentParticle.SetKineticEnergy( ek );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct modifiedOriginal = currentParticle;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1*MeV;
if( currentParticle.GetKineticEnergy() > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEOmegaMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASOM by H. Fesefeldt (31-Jan-1989)
//
// OmegaMinus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
const G4double etOriginal = originalIncident->GetTotalEnergy();
const G4double pOriginal = originalIncident->GetTotalMomentum();
const G4double targetMass = targetParticle.GetMass();
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass() )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.70 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aXiZero = G4XiZero::XiZero();
// energetically possible to produce pion(s) --> inelastic scattering
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
// number of secondary mesons determined by kno distribution
// check for total charge of final state mesons to determine
// the kind of baryons to be produced, taking into account
// charge and strangeness conservation
//
G4int nvefix = 0;
if( targetParticle.GetDefinition() == aProton )
{
if( nm > np )
{
if( nm == np+1 )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
nvefix = 1;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
nvefix = 2;
}
incidentHasChanged = true;
}
else if( nm < np )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else // target is a neutron
{
if( np+1 < nm )
{
if( nm == np+2 )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
nvefix = 1;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
nvefix = 2;
}
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else if( nm == np+1 )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
for( G4int i=0; i<vecLen && nvefix>0; ++i )
{
if( vec[i]->GetDefinition() == aPiMinus )
{
if( nvefix >= 1 )vec[i]->SetDefinitionAndUpdateE( aKaonMinus );
--nvefix;
}
}
return;
}
/* end of file */
@@ -0,0 +1,391 @@
// 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: G4LEPionMinusInelastic.cc,v 2.4 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: PionMinus Inelastic Process
// J.L. Chuma, TRIUMF, 19-Nov-1996
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEPionMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEPionMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
// create the target particle
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
G4double targetMass = originalTarget->GetDefinition()->GetPDGMass();
G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4PionMinusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
G4ReactionProduct currentParticle( originalIncident->GetDefinition() );
currentParticle.SetMomentum( originalIncident->GetMomentum() );
currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
G4double ek = originalIncident->GetKineticEnergy();
G4double amas = originalIncident->GetDefinition()->GetPDGMass();
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
currentParticle.SetKineticEnergy( ek );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
// calculate black track energies
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
currentParticle.SetKineticEnergy( ek );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct modifiedOriginal = currentParticle;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1*MeV;
if( currentParticle.GetKineticEnergy() > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEPionMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASPIM by H. Fesefeldt (13-Sep-1987)
//
// pi- undergoes interaction with nucleon within nucleus.
// Check if energetically possible to produce pions/kaons.
// If not assume nuclear excitation occurs and input particle
// is degraded in energy. No other particles produced.
// If reaction is possible find correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data.
// Replace some pions or protons/neutrons by kaons or strange baryons
// according to average multiplicity per inelastic reactions.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
const G4double etOriginal = originalIncident->GetTotalEnergy();
const G4double pOriginal = originalIncident->GetTotalMomentum();
const G4double targetMass = targetParticle.GetMass();
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionMinus::PionMinus()->GetPDGMass() )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.70 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
G4int ieab = availableEnergy*5.0/GeV;
const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
G4double test, w0, wp, wt, wm;
if( (availableEnergy<2.0*GeV) && (G4UniformRand()>=supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one pion will be produced
// charge exchange reaction is included in inelastic cross section
const G4double cech[] = {1.,0.95,0.79,0.32,0.19,0.16,0.14,0.12,0.10,0.08};
G4int iplab = min( 9.0, pOriginal/GeV*5.0 );
if( G4UniformRand() <= cech[iplab] )
{
if( targetParticle.GetDefinition() == aProton )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero ); // charge exchange
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
}
else quasiElastic = true;
return;
}
nm = np = nz = 0;
if( targetParticle.GetDefinition() == aProton )
{
test = exp( min( expxu, max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test;
wp = 10.0*test;
test = exp( min( expxu, max( expxl, -(-1.0+b[0])*(-1.0+b[0])/(2.0*c*c) ) ) );
wm = test;
wt = w0+wp+wm;
wp += w0;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
else // target is a neutron
{
test = exp( min( expxu, max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test;
test = exp( min( expxu, max( expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
wm = test;
G4double ran = G4UniformRand();
if( ran < w0/(w0+wm) )
nz = 1;
else
nm = 1;
}
}
else
{
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
for( nm=max(0,np-1); (nm<=(np+1)) && (ran>=excs); ++nm )
{
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt > 0 )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
else // target must be a neutron
{
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np )
{
for( nm=np; (nm<=(np+2)) && (ran>=excs); ++nm )
{
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
}
}
if( targetParticle.GetDefinition() == aProton )
{
switch( np-nm )
{
case 0:
if( G4UniformRand() >= 0.75 )
{
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
default:
currentParticle.SetDefinitionAndUpdateE( aPiZero );
incidentHasChanged = true;
break;
}
}
else
{
switch( np-nm )
{
case -1:
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
} else {
currentParticle.SetDefinitionAndUpdateE( aPiZero );
incidentHasChanged = true;
}
break;
case 0:
break;
default:
currentParticle.SetDefinitionAndUpdateE( aPiZero );
incidentHasChanged = true;
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,335 @@
// 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: G4LEPionPlusInelastic.cc,v 2.4 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: PionPlus Inelastic Process
// J.L. Chuma, TRIUMF, 19-Nov-1996
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEPionPlusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEPionPlusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
// create the target particle
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
G4double targetMass = originalTarget->GetDefinition()->GetPDGMass();
G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEPionPlusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
G4ReactionProduct currentParticle( originalIncident->GetDefinition() );
currentParticle.SetMomentum( originalIncident->GetMomentum() );
currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
G4double ek = originalIncident->GetKineticEnergy();
G4double amas = originalIncident->GetDefinition()->GetPDGMass();
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
currentParticle.SetKineticEnergy( ek );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
// calculate black track energies
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
currentParticle.SetKineticEnergy( ek );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = currentParticle.GetMomentum().mag();
if( pp > 0.0 )
{
G4ThreeVector momentum = currentParticle.GetMomentum();
currentParticle.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct modifiedOriginal = currentParticle;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1*MeV;
if( currentParticle.GetKineticEnergy() > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEPionPlusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASPIP by H. Fesefeldt (18-Sep-1987)
//
// pi+ undergoes interaction with nucleon within nucleus.
// Check if energetically possible to produce pions/kaons.
// If not assume nuclear excitation occurs and input particle
// is degraded in energy. No other particles produced.
// If reaction is possible find correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data.
// Replace some pions or protons/neutrons by kaons or strange baryons
// according to average multiplicity per inelastic reactions.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
const G4double etOriginal = originalIncident->GetTotalEnergy();
const G4double targetMass = targetParticle.GetMass();
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass() )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.70 };
if( first ) { // compute normalization constants, this will only be Done once
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np ) {
for( nm=max(0,np-2); nm<=np; ++nm ) {
for( nz=0; nz<numSec/3; ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( nt > 0 ) {
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np ) {
for( nm=max(0,np-1); nm<=(np+1); ++nm ) {
for( nz=0; nz<numSec/3; ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) ) {
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i ) {
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
G4int ieab = availableEnergy*5.0/GeV;
const G4double supp[] = {0.,0.2,0.45,0.55,0.65,0.75,0.85,0.90,0.94,0.98};
G4double test, w0, wp, wt, wm;
if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one pion will be produced
nm = np = nz = 0;
if( targetParticle.GetDefinition() == aProton ) {
test = exp( min( expxu, max( expxl, -sqr(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test;
wp = test;
if( G4UniformRand() < w0/(w0+wp) )
nz =1;
else
np = 1;
} else { // target is a neutron
test = exp( min( expxu, max( expxl, -sqr(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test;
wp = test;
test = exp( min( expxu, max( expxl, -sqr(-1.0+b[1])/(2.0*c*c) ) ) );
wm = test;
wt = w0+wp+wm;
wp = w0+wp;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
} else {
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton ) {
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np ) {
for( nm=max(0,np-2); (nm<=np) && (ran>=excs); ++nm ) {
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( nt > 0 ) {
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 ) {
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs )
{
quasiElastic = true;
return; // 3 previous loops continued to the end
}
np--; nm--; nz--;
} else { // target must be a neutron
counter = -1;
for( np=0; (np<numSec/3) && (ran>=excs); ++np ) {
for( nm=max(0,np-1); (nm<=(np+1)) && (ran>=excs); ++nm ) {
for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz ) {
if( ++counter < numMul ) {
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) ) {
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 ) {
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return; // 3 previous loops continued to the end
}
np--; nm--; nz--;
}
}
if( targetParticle.GetDefinition() == aProton ) {
switch( np-nm ) {
case 1:
if( G4UniformRand() < 0.5 ) {
currentParticle.SetDefinitionAndUpdateE( aPiZero );
incidentHasChanged = true;
} else {
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
break;
case 2:
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
break;
default:
break;
}
} else {
switch( np-nm ) {
case 0:
if( G4UniformRand() < 0.25 ) {
currentParticle.SetDefinitionAndUpdateE( aPiZero );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
currentParticle.SetDefinitionAndUpdateE( aPiZero );
incidentHasChanged = true;
break;
default:
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,430 @@
// 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: G4LEProtonInelastic.cc,v 2.9 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Low Energy Proton Inelastic Process
// J.L. Chuma, TRIUMF, 19-Nov-1996
#include "G4LEProtonInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEProtonInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEProtonInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
if( originalIncident->GetKineticEnergy()/GeV < 0.01+2.*G4UniformRand()/9. )
{
SlowProton( originalIncident, targetNucleus );
delete originalTarget;
return &theParticleChange;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
const G4double cutOff = 0.1;
if( modifiedOriginal.GetKineticEnergy()/MeV <= cutOff )
{
SlowProton( originalIncident, targetNucleus );
delete originalTarget;
return &theParticleChange;
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the sec. particles
G4int vecLen = 0;
vec.Initialize( 0 );
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEProtonInelastic::SlowProton(
const G4DynamicParticle *originalIncident,
G4Nucleus &targetNucleus )
{
const G4double N = targetNucleus.GetN(); // atomic weight
const G4double Z = targetNucleus.GetZ(); // atomic number
G4double currentKinetic = originalIncident->GetKineticEnergy()/MeV;
//
// calculate Q-value of reactions
//
G4double theAtomicMass = targetNucleus.AtomicMass( N, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
G4double massVec[9];
massVec[0] = targetNucleus.AtomicMass( N+1.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[1] = targetNucleus.AtomicMass( N , Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[2] = theAtomicMass;
massVec[3] = targetNucleus.AtomicMass( N-1.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
massVec[4] = targetNucleus.AtomicMass( N-2.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
massVec[5] = targetNucleus.AtomicMass( N-3.0, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
massVec[6] = targetNucleus.AtomicMass( N-1.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[7] = massVec[3];
massVec[8] = targetNucleus.AtomicMass( N-1.0, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
G4FastVector<G4ReactionProduct,3> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
theReactionDynamics.NuclearReaction( vec, vecLen, originalIncident,
targetNucleus, theAtomicMass, massVec );
theParticleChange.SetStatusChange( fStopAndKill );
theParticleChange.SetEnergyChange( 0.0 );
theParticleChange.SetNumberOfSecondaries( vecLen );
G4DynamicParticle *pd;
for( G4int i=0; i<vecLen; ++i )
{
pd = new G4DynamicParticle();
pd->SetDefinition( vec[i]->GetDefinition() );
pd->SetMomentum( vec[i]->GetMomentum() );
theParticleChange.AddSecondary( pd );
}
}
void
G4LEProtonInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int &vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASP by H. Fesefeldt (13-Sep-1987)
//
// Proton undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
// the center of mass energy is based on the initial energy, before
// Fermi motion and evaporation effects are taken into account
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{ // not energetically possible to produce pion(s)
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.35 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-2); nm<=np; ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c) /
( theReactionDynamics.Factorial(2-np+nm)*
theReactionDynamics.Factorial(np-nm) );
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c) /
( theReactionDynamics.Factorial(1-np+nm)*
theReactionDynamics.Factorial(1+np-nm) );
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4int ieab = availableEnergy*5.0/GeV;
const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
G4double test, w0, wp, wt, wm;
if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one pion will be produced
np = nm = nz = 0;
if( targetParticle.GetDefinition() == aProton )
{
test = exp( min( expxu, max(
expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
w0 = test/2.0;
wp = test;
if( G4UniformRand() < w0/(w0+wp) )
nz = 1;
else
np = 1;
}
else // target is a neutron
{
test = exp( min( expxu, max(
expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
w0 = test;
wp = test/2.0;
test = exp( min( expxu, max(
expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
wm = test/2.0;
wt = w0+wp+wm;
wp += w0;
G4double ran = G4UniformRand();
if( ran < w0/wt )
nz = 1;
else if( ran < wp/wt )
np = 1;
else
nm = 1;
}
}
else // (availableEnergy >= 2.0*GeV) || (random number < supp[ieab])
{
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-2); nm<=np && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
} else {
excs += dum*test;
}
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
}
np--; nm--; nz--;
}
if( targetParticle.GetDefinition() == aProton )
{
switch( np-nm )
{
case 1:
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
} else {
currentParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
}
break;
case 2:
currentParticle.SetDefinitionAndUpdateE( aNeutron );
targetParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
targetHasChanged = true;
break;
default:
break;
}
}
else // target is a neutron
{
switch( np-nm )
{
case 0:
if( G4UniformRand() < 0.333333 )
{
currentParticle.SetDefinitionAndUpdateE( aNeutron );
targetParticle.SetDefinitionAndUpdateE( aProton );
incidentHasChanged = true;
targetHasChanged = true;
}
break;
case 1:
currentParticle.SetDefinitionAndUpdateE( aNeutron );
incidentHasChanged = true;
break;
default:
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,345 @@
// 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: G4LESigmaMinusInelastic.cc,v 2.4 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: SigmaMinus Inelastic Process
// J.L. Chuma, TRIUMF, 19-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LESigmaMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LESigmaMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LESigmaMinusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
if( originalIncident->GetKineticEnergy()/MeV > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LESigmaMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASSM by H. Fesefeldt (13-Sep-1987)
//
// SigmaMinus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per Inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.70, 0.70 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aLambda = G4Lambda::Lambda();
G4ParticleDefinition *aSigmaZero = G4SigmaZero::SigmaZero();
// energetically possible to produce pion(s) --> inelastic scattering
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = max( 1, np-nm+2 );
switch( ncht )
{
case 1:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aLambda );
else
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
break;
case 2:
if( G4UniformRand() >= 0.5 )
{
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aLambda );
else
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
break;
default:
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
G4int ncht = max( 1, np-nm+3 );
switch( ncht )
{
case 1:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aLambda );
else
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aLambda );
else
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
break;
default:
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,358 @@
// 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: G4LESigmaPlusInelastic.cc,v 2.4 1998/12/14 15:33:15 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: SigmaPlus Inelastic Process
// J.L. Chuma, TRIUMF, 19-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LESigmaPlusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LESigmaPlusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LESigmaPlusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
if( currentParticle.GetKineticEnergy()/MeV > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LESigmaPlusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASSP by H. Fesefeldt (30-Nov-1987)
//
// SigmaPlus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aLambda = G4Lambda::Lambda();
G4ParticleDefinition *aSigmaZero = G4SigmaZero::SigmaZero();
//
// energetically possible to produce pion(s) --> inelastic scattering
//
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
switch( min( 3, max( 1, np-nm+3 ) ) )
{
case 1:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aLambda );
else
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
else
{
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aLambda );
else
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
}
break;
case 3:
break;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
switch( min( 3, max( 1, np-nm+2 ) ) )
{
case 1:
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
break;
case 2:
if( G4UniformRand() < 0.5 )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aLambda );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
break;
case 3:
if( G4UniformRand() < 0.5 )
currentParticle.SetDefinitionAndUpdateE( aLambda );
else
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
incidentHasChanged = true;
break;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,79 @@
// 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: G4LETritonInelastic.cc,v 2.8 1998/12/14 15:33:16 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: Triton Inelastic Process
// J.L. Chuma, TRIUMF, 25-Feb-1997
// Last modified: 27-Mar-1997
#include "G4LETritonInelastic.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
G4VParticleChange *
G4LETritonInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LETritonInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
}
// Work-around for lack of model above 100 MeV
if (originalIncident->GetKineticEnergy()/MeV > 100. ||
originalIncident->GetKineticEnergy() <= 0.) return &theParticleChange;
G4double N = targetNucleus.GetN();
G4double Z = targetNucleus.GetZ();
G4double theAtomicMass = targetNucleus.AtomicMass( N, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
G4double massVec[9];
massVec[0] = targetNucleus.AtomicMass( N+3.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[1] = targetNucleus.AtomicMass( N+2.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[2] = targetNucleus.AtomicMass( N+2.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
massVec[3] = targetNucleus.AtomicMass( N+1.0, Z )-(Z)*G4Electron::Electron()->GetPDGMass();
massVec[4] = theAtomicMass;
massVec[5] = targetNucleus.AtomicMass( N-1.0, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
massVec[6] = targetNucleus.AtomicMass( N+1.0, Z+1.0 )-(Z+1.0)*G4Electron::Electron()->GetPDGMass();
massVec[7] = massVec[3];
massVec[8] = targetNucleus.AtomicMass( N+1.0, Z-1.0 )-(Z-1.0)*G4Electron::Electron()->GetPDGMass();
G4FastVector<G4ReactionProduct,3> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
theReactionDynamics.NuclearReaction( vec, vecLen, originalIncident,
targetNucleus, theAtomicMass, massVec );
G4double p = originalIncident->GetTotalMomentum();
theParticleChange.SetMomentumChange( originalIncident->GetMomentum() * (1.0/p) );
theParticleChange.SetEnergyChange( originalIncident->GetKineticEnergy() );
theParticleChange.SetNumberOfSecondaries( vecLen );
G4DynamicParticle *pd;
for( G4int i=0; i<vecLen; ++i )
{
pd = new G4DynamicParticle();
pd->SetDefinition( vec[i]->GetDefinition() );
pd->SetMomentum( vec[i]->GetMomentum() );
theParticleChange.AddSecondary( pd );
}
return &theParticleChange;
}
/* end of file */
@@ -0,0 +1,371 @@
// 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: G4LEXiMinusInelastic.cc,v 2.4 1998/12/14 15:33:16 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: XiMinus Inelastic Process
// J.L. Chuma, TRIUMF, 20-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEXiMinusInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEXiMinusInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEXiMinusInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
if( currentParticle.GetKineticEnergy()/MeV > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEXiMinusInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASXM by H. Fesefeldt (17-Jan-1989)
//
// XiMinus undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-1); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=np; nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aXiZero = G4XiZero::XiZero();
//
// energetically possible to produce pion(s) --> inelastic scattering
//
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
//
// number of secondary mesons determined by kno distribution
// check for total charge of final state mesons to determine
// the kind of baryons to be produced, taking into account
// charge and strangeness conservation
//
if( np < nm )
{
if( np+1 == nm )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np == nm )
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
if( np+1 < nm )
{
if( np+2 == nm )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np+1 == nm )
{
if( G4UniformRand() < 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aXiZero );
incidentHasChanged = true;
}
else
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,371 @@
// 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: G4LEXiZeroInelastic.cc,v 2.4 1998/12/14 15:33:16 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Hadronic Process: XiZero Inelastic Process
// J.L. Chuma, TRIUMF, 20-Feb-1997
// Last modified: 27-Mar-1997
// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
#include "G4LEXiZeroInelastic.hh"
#include "Randomize.hh"
G4VParticleChange *
G4LEXiZeroInelastic::ApplyYourself( const G4Track &aTrack,
G4Nucleus &targetNucleus )
{
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *originalIncident = aTrack.GetDynamicParticle();
if (originalIncident->GetKineticEnergy()<= 0.1*MeV) return &theParticleChange;
//
// create the target particle
//
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
if( verboseLevel > 1 )
{
G4Material *targetMaterial = aTrack.GetMaterial();
G4cout << "G4LEXiZeroInelastic::ApplyYourself called" << endl;
G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
G4cout << "target material = " << targetMaterial->GetName() << ", ";
G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
<< endl;
}
//
// Fermi motion and evaporation
// As of Geant3, the Fermi energy calculation had not been Done
//
G4double ek = originalIncident->GetKineticEnergy()/MeV;
G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
G4ReactionProduct modifiedOriginal;
modifiedOriginal = *originalIncident;
G4double tkin = targetNucleus.Cinema( ek );
ek += tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
G4double et = ek + amas;
G4double p = sqrt( abs((et-amas)*(et+amas)) );
G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
//
// calculate black track energies
//
tkin = targetNucleus.EvaporationEffects( ek );
ek -= tkin;
modifiedOriginal.SetKineticEnergy( ek*MeV );
et = ek + amas;
p = sqrt( abs((et-amas)*(et+amas)) );
pp = modifiedOriginal.GetMomentum().mag()/MeV;
if( pp > 0.0 )
{
G4ThreeVector momentum = modifiedOriginal.GetMomentum();
modifiedOriginal.SetMomentum( momentum * (p/pp) );
}
G4ReactionProduct currentParticle = modifiedOriginal;
G4ReactionProduct targetParticle;
targetParticle = *originalTarget;
currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
G4bool incidentHasChanged = false;
G4bool targetHasChanged = false;
G4bool quasiElastic = false;
G4FastVector<G4ReactionProduct,128> vec; // vec will contain the secondary particles
G4int vecLen = 0;
vec.Initialize( 0 );
const G4double cutOff = 0.1;
if( currentParticle.GetKineticEnergy()/MeV > cutOff )
Cascade( vec, vecLen,
originalIncident, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
CalculateMomenta( vec, vecLen,
originalIncident, originalTarget, modifiedOriginal,
targetNucleus, currentParticle, targetParticle,
incidentHasChanged, targetHasChanged, quasiElastic );
SetUpChange( vec, vecLen,
currentParticle, targetParticle,
incidentHasChanged );
delete originalTarget;
return &theParticleChange;
}
void
G4LEXiZeroInelastic::Cascade(
G4FastVector<G4ReactionProduct,128> &vec,
G4int& vecLen,
const G4DynamicParticle *originalIncident,
G4ReactionProduct &currentParticle,
G4ReactionProduct &targetParticle,
G4bool &incidentHasChanged,
G4bool &targetHasChanged,
G4bool &quasiElastic )
{
// derived from original FORTRAN code CASX0 by H. Fesefeldt (20-Jan-1989)
//
// XiZero undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
//
const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
const G4double targetMass = targetParticle.GetMass()/MeV;
G4double centerofmassEnergy = sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal );
G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
{
quasiElastic = true;
return;
}
static G4bool first = true;
const G4int numMul = 1200;
const G4int numSec = 60;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int counter, nt=0, np=0, nm=0, nz=0;
G4double test;
const G4double c = 1.25;
const G4double b[] = { 0.7, 0.7 };
if( first ) // compute normalization constants, this will only be Done once
{
first = false;
G4int i;
for( i=0; i<numMul; ++i )protmul[i] = 0.0;
for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); ++np )
{
for( nm=max(0,np-2); nm<=(np+1); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; ++np )
{
for( nm=max(0,np-1); nm<=(np+2); ++nm )
{
for( nz=0; nz<numSec/3; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; ++i )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
const G4double expxu = 82.; // upper bound for arg. of exp
const G4double expxl = -expxu; // lower bound for arg. of exp
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aXiMinus = G4XiMinus::XiMinus();
//
// energetically possible to produce pion(s) --> inelastic scattering
//
G4double n, anpn;
GetNormalizationConstant( availableEnergy, n, anpn );
G4double ran = G4UniformRand();
G4double dum, excs = 0.0;
if( targetParticle.GetDefinition() == aProton )
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-2); nm<=(np+1) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
//
// number of secondary mesons determined by kno distribution
// check for total charge of final state mesons to determine
// the kind of baryons to be produced, taking into account
// charge and strangeness conservation
//
if( np < nm+1 )
{
if( np != nm ) // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np == nm+1 )
{
if( G4UniformRand() < 0.5 )
{
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
else
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
}
}
else
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aNeutron );
targetHasChanged = true;
}
}
else // target must be a neutron
{
counter = -1;
for( np=0; np<numSec/3 && ran>=excs; ++np )
{
for( nm=max(0,np-1); nm<=(np+2) && ran>=excs; ++nm )
{
for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( nt>0 && nt<=numSec )
{
test = exp( min( expxu, max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
{
if( test >= 1.0e-10 )excs += dum*test;
}
else
excs += dum*test;
}
}
}
}
}
if( ran >= excs ) // 3 previous loops continued to the end
{
quasiElastic = true;
return;
}
np--; nm--; nz--;
if( np < nm )
{
if( np+1 == nm )
{
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
else // charge mismatch
{
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
//
// correct the strangeness by replacing a pi- by a kaon-
//
vec.Initialize( 1 );
G4ReactionProduct *p = new G4ReactionProduct;
p->SetDefinition( aKaonMinus );
(G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
vec.SetElement( vecLen++, p );
--nm;
}
}
else if( np == nm )
{
if( G4UniformRand() >= 0.5 )
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
targetParticle.SetDefinitionAndUpdateE( aProton );
targetHasChanged = true;
}
}
else
{
currentParticle.SetDefinitionAndUpdateE( aXiMinus );
incidentHasChanged = true;
}
}
SetUpPions( np, nm, nz, vec, vecLen );
return;
}
/* end of file */
@@ -0,0 +1,363 @@
// 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: G4LElastic.cc,v 2.4 1998/12/14 15:33:16 hpw Exp $
// GEANT4 tag $Name: geant4-00 $
//
// Physics model class G4LElastic
//
//
// G4 Model: Low-energy Elastic scattering
// F.W. Jones, TRIUMF, 04-JUN-96
//
// use -scheme for elastic scattering: HPW, 20th June 1997
// most of the code comes from the old Low-energy Elastic class
//
// 25-JUN-98 FWJ: replaced missing Initialize for ParticleChange.
//
#include "G4LElastic.hh"
#include "Randomize.hh"
G4VParticleChange*
G4LElastic::ApplyYourself(const G4Track& aTrack, G4Nucleus& targetNucleus)
{
theParticleChange.Initialize(aTrack);
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
G4double Z = targetNucleus.GetZ();
G4double atno2 = targetNucleus.GetN();
// Elastic scattering off Hydrogen
G4DynamicParticle* aSecondary = 0;
if (atno2 < 1.5) {
G4ParticleDefinition* aParticleType = aParticle->GetDefinition();
if (aParticleType == G4PionPlus::PionPlus())
aSecondary = LightMedia.PionPlusExchange(aParticle, targetNucleus);
else if (aParticleType == G4PionMinus::PionMinus())
aSecondary = LightMedia.PionMinusExchange(aParticle, targetNucleus);
else if (aParticleType == G4KaonPlus::KaonPlus())
aSecondary = LightMedia.KaonPlusExchange(aParticle, targetNucleus);
else if (aParticleType == G4KaonZeroShort::KaonZeroShort())
aSecondary = LightMedia.KaonZeroShortExchange(aParticle,targetNucleus);
else if (aParticleType == G4KaonZeroLong::KaonZeroLong())
aSecondary = LightMedia.KaonZeroLongExchange(aParticle, targetNucleus);
else if (aParticleType == G4KaonMinus::KaonMinus())
aSecondary = LightMedia.KaonMinusExchange(aParticle, targetNucleus);
else if (aParticleType == G4Proton::Proton())
aSecondary = LightMedia.ProtonExchange(aParticle, targetNucleus);
else if (aParticleType == G4AntiProton::AntiProton())
aSecondary = LightMedia.AntiProtonExchange(aParticle, targetNucleus);
else if (aParticleType == G4Neutron::Neutron())
aSecondary = LightMedia.NeutronExchange(aParticle, targetNucleus);
else if (aParticleType == G4AntiNeutron::AntiNeutron())
aSecondary = LightMedia.AntiNeutronExchange(aParticle, targetNucleus);
else if (aParticleType == G4Lambda::Lambda())
aSecondary = LightMedia.LambdaExchange(aParticle, targetNucleus);
else if (aParticleType == G4AntiLambda::AntiLambda())
aSecondary = LightMedia.AntiLambdaExchange(aParticle, targetNucleus);
else if (aParticleType == G4SigmaPlus::SigmaPlus())
aSecondary = LightMedia.SigmaPlusExchange(aParticle, targetNucleus);
else if (aParticleType == G4SigmaMinus::SigmaMinus())
aSecondary = LightMedia.SigmaMinusExchange(aParticle, targetNucleus);
else if (aParticleType == G4AntiSigmaPlus::AntiSigmaPlus())
aSecondary = LightMedia.AntiSigmaPlusExchange(aParticle,targetNucleus);
else if (aParticleType == G4AntiSigmaMinus::AntiSigmaMinus())
aSecondary= LightMedia.AntiSigmaMinusExchange(aParticle,targetNucleus);
else if (aParticleType == G4XiZero::XiZero())
aSecondary = LightMedia.XiZeroExchange(aParticle, targetNucleus);
else if (aParticleType == G4XiMinus::XiMinus())
aSecondary = LightMedia.XiMinusExchange(aParticle, targetNucleus);
else if (aParticleType == G4AntiXiZero::AntiXiZero())
aSecondary = LightMedia.AntiXiZeroExchange(aParticle, targetNucleus);
else if (aParticleType == G4AntiXiMinus::AntiXiMinus())
aSecondary = LightMedia.AntiXiMinusExchange(aParticle, targetNucleus);
else if (aParticleType == G4OmegaMinus::OmegaMinus())
aSecondary = LightMedia.OmegaMinusExchange(aParticle, targetNucleus);
else if (aParticleType == G4AntiOmegaMinus::AntiOmegaMinus())
aSecondary= LightMedia.AntiOmegaMinusExchange(aParticle,targetNucleus);
else if (aParticleType == G4KaonPlus::KaonPlus())
aSecondary = LightMedia.KaonPlusExchange(aParticle, targetNucleus);
}
// Has a charge or strangeness exchange occurred?
if (aSecondary) {
aSecondary->SetMomentum(aParticle->GetMomentum());
theParticleChange.SetStatusChange(fStopAndKill);
theParticleChange.AddSecondary(aSecondary);
}
G4double p = aParticle->GetTotalMomentum()/GeV;
if (verboseLevel > 1)
G4cout << "G4LElastic::DoIt: Incident particle p=" << p << " GeV" << endl;
if (p < 0.01) return &theParticleChange;
// Compute the direction of elastic scattering.
// It is planned to replace this code with a method based on
// parameterized functions and a Monte Carlo method to invert the CDF.
G4double ran = G4UniformRand();
G4double aa, bb, cc, dd, rr;
if (atno2 <= 62.) {
aa = pow(atno2, 1.63);
bb = 14.5*pow(atno2, 0.66);
cc = 1.4*pow(atno2, 0.33);
dd = 10.;
}
else {
aa = pow(atno2, 1.33);
bb = 60.*pow(atno2, 0.33);
cc = 0.4*pow(atno2, 0.40);
dd = 10.;
}
aa = aa/bb;
cc = cc/dd;
rr = (aa + cc)*ran;
if (verboseLevel > 1) {
G4cout << "DoIt: aa,bb,cc,dd,rr" << endl;
G4cout << aa << " " << bb << " " << cc << " " << dd << " " << rr << endl;
}
G4double t1 = -log(ran)/bb;
G4double t2 = -log(ran)/dd;
if (verboseLevel > 1) {
G4cout << "log(FLT_MAX)=" << log(FLT_MAX) << endl;
G4cout << "t1,Fctcos " << t1 << " " << Fctcos(t1, aa, bb, cc, dd, rr) <<
endl;
G4cout << "t2,Fctcos " << t2 << " " << Fctcos(t2, aa, bb, cc, dd, rr) <<
endl;
}
G4double eps = 0.001;
G4int ind1 = 10;
G4double t, val;
G4int ier1;
ier1 = Rtmi(&t, t1, t2, eps, ind1,
aa, bb, cc, dd, rr);
if (verboseLevel > 1) {
G4cout << "From Rtmi, ier1=" << ier1 << endl;
G4cout << "t, Fctcos " << t << " " << Fctcos(t, aa, bb, cc, dd, rr) <<
endl;
}
if (ier1 != 0) t = 0.25*(3.*t1 + t2);
if (verboseLevel > 1) {
G4cout << "t, Fctcos " << t << " " << Fctcos(t, aa, bb, cc, dd, rr) <<
endl;
}
G4double phi = G4UniformRand()*twopi;
rr = 0.5*t/(p*p);
if (rr > 1.) rr = 0.;
if (verboseLevel > 1)
G4cout << "rr=" << rr << endl;
G4double cost = 1. - rr;
G4double sint = sqrt(max(rr*(2. - rr), 0.));
if (sint == 0.) return &theParticleChange;
if (verboseLevel > 1)
G4cout << "cos(t)=" << cost << " sin(t)=" << sint << endl;
// Scattered particle referred to axis of incident particle
G4double px = p*sint*sin(phi);
G4double py = p*sint*cos(phi);
G4double pz = p*cost;
// Incident particle
G4double pxinc = p*(aParticle->GetMomentumDirection().x());
G4double pyinc = p*(aParticle->GetMomentumDirection().y());
G4double pzinc = p*(aParticle->GetMomentumDirection().z());
if (verboseLevel > 1) {
G4cout << "NOM SCAT " << px << " " << py << " " << pz << endl;
G4cout << "INCIDENT " << pxinc << " " << pyinc << " " << pzinc << endl;
}
// Transform scattered particle to reflect direction of incident particle
G4double pxnew, pynew, pznew;
Defs1(p, px, py, pz, pxinc, pyinc, pzinc, &pxnew, &pynew, &pznew);
// Normalize:
pxnew = pxnew/p;
pynew = pynew/p;
pznew = pznew/p;
if (verboseLevel > 1) {
G4cout << "DoIt: returning new momentum vector" << endl;
G4cout << pxnew << " " << pynew << " " << pznew << endl;
}
if (aSecondary)
aSecondary->SetMomentumDirection(pxnew, pynew, pznew);
else
theParticleChange.SetMomentumChange(pxnew, pynew, pznew);
return &theParticleChange;
}
// The following is a "translation" of a root-finding routine
// from GEANT3.21/GHEISHA. Some of the labelled block structure has
// been retained for clarity. This routine will not be needed after
// the planned revisions to DoIt().
G4int
G4LElastic::Rtmi(G4double* x, G4double xli, G4double xri, G4double eps,
G4int iend,
G4double aa, G4double bb, G4double cc, G4double dd,
G4double rr)
{
G4int ier = 0;
G4double xl = xli;
G4double xr = xri;
*x = xl;
G4double tol = *x;
G4double f = Fctcos(tol, aa, bb, cc, dd, rr);
if (f == 0.) return ier;
G4double fl, fr;
fl = f;
*x = xr;
tol = *x;
f = Fctcos(tol, aa, bb, cc, dd, rr);
if (f == 0.) return ier;
fr = f;
// Error return in case of wrong input data
if (fl*fr >= 0.) {
ier = 2;
return ier;
}
// Basic assumption fl*fr less than 0 is satisfied.
// Generate tolerance for function values.
G4int i = 0;
G4double tolf = 100.*eps;
// Start iteration loop
label4:
i++;
// Start bisection loop
for (G4int k = 1; k <= iend; k++) {
*x = 0.5*(xl + xr);
tol = *x;
f = Fctcos(tol, aa, bb, cc, dd, rr);
if (f == 0.) return 0;
if (f*fr < 0.) { // Interchange xl and xr in order to get the
tol = xl; // same Sign in f and fr
xl = xr;
xr = tol;
tol = fl;
fl = fr;
fr = tol;
}
tol = f - fl;
G4double a = f*tol;
a = a + a;
if (a < fr*(fr - fl) && i <= iend) goto label17;
xr = *x;
fr = f;
// Test on satisfactory accuracy in bisection loop
tol = eps;
a = abs(xr);
if (a > 1.) tol = tol*a;
if (abs(xr - xl) <= tol && abs(fr - fl) <= tolf) goto label14;
}
// End of bisection loop
// No convergence after iend iteration steps followed by iend
// successive steps of bisection or steadily increasing function
// values at right bounds. Error return.
ier = 1;
label14:
if (abs(fr) > abs(fl)) {
*x = xl;
f = fl;
}
return ier;
// Computation of iterated x-value by inverse parabolic interp
label17:
G4double a = fr - f;
G4double dx = (*x - xl)*fl*(1. + f*(a - tol)/(a*(fr - fl)))/tol;
G4double xm = *x;
G4double fm = f;
*x = xl - dx;
tol = *x;
f = Fctcos(tol, aa, bb, cc, dd, rr);
if (f == 0.) return ier;
// Test on satisfactory accuracy in iteration loop
tol = eps;
a = abs(*x);
if (a > 1) tol = tol*a;
if (abs(dx) <= tol && abs(f) <= tolf) return ier;
// Preparation of next bisection loop
if (f*fl < 0.) {
xr = *x;
fr = f;
}
else {
xl = *x;
fl = f;
xr = xm;
fr = fm;
}
goto label4;
}
// Test function for root-finder
G4double
G4LElastic::Fctcos(G4double t,
G4double aa, G4double bb, G4double cc, G4double dd,
G4double rr)
{
const G4double expxl = -82.;
const G4double expxu = 82.;
G4double test1 = -bb*t;
if (test1 > expxu) test1 = expxu;
if (test1 < expxl) test1 = expxl;
G4double test2 = -dd*t;
if (test2 > expxu) test2 = expxu;
if (test2 < expxl) test2 = expxl;
return aa*exp(test1) + cc*exp(test2) - rr;
}
void
G4LElastic::Defs1(G4double p, G4double px, G4double py, G4double pz,
G4double pxinc, G4double pyinc, G4double pzinc,
G4double* pxnew, G4double* pynew, G4double* pznew)
{
// Transform scattered particle to reflect direction of incident particle
G4double pt2 = pxinc*pxinc + pyinc*pyinc;
if (pt2 > 0.) {
G4double cost = pzinc/p;
G4double sint1 = sqrt(abs((1. - cost )*(1.+cost)));
G4double sint2 = sqrt(pt2)/p;
G4double sint = 0.5*(sint1 + sint2);
G4double ph = pi*0.5;
if (pyinc < 0.) ph = pi*1.5;
if (abs(pxinc) > 1.e-6) ph = atan2(pyinc, pxinc);
G4double cosp = cos(ph);
G4double sinp = sin(ph);
if (verboseLevel > 1) {
G4cout << "cost sint " << cost << " " << sint << endl;
G4cout << "cosp sinp " << cosp << " " << sinp << endl;
}
*pxnew = cost*cosp*px - sinp*py + sint*cosp*pz;
*pynew = cost*sinp*px + cosp*py + sint*sinp*pz;
*pznew = -sint*px +cost*pz;
}
else {
*pxnew = px;
*pynew = py;
*pznew = pz;
}
}
@@ -0,0 +1,257 @@
// 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: G4LFission.cc,v 2.3 1998/07/13 17:24:44 urbi Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
// G4 Model: Low Energy Fission
// F.W. Jones, TRIUMF, 03-DEC-96
//
// This is a prototype of a low-energy fission process.
// Currently it is based on the GHEISHA routine FISSIO,
// and conforms fairly closely to the original Fortran.
// Note: energy is in MeV and momentum is in MeV/c.
//
// use -scheme for elastic scattering: HPW, 20th June 1997
// the code comes mostly from the old Low-energy Fission class
//
// 25-JUN-98 FWJ: replaced missing Initialize for ParticleChange.
//
#include "G4LFission.hh"
#include "Randomize.hh"
G4LFission::G4LFission() :
G4HadronicInteraction()
{
init();
theParticleChange.SetNumberOfSecondaries(1000);
SetMinEnergy( 0.0*GeV );
SetMaxEnergy( DBL_MAX );
}
G4LFission::~G4LFission()
{
theParticleChange.Clear();
}
void
G4LFission::init()
{
G4int i;
G4double xx = 1. - 0.5;
G4double xxx = sqrt(2.29*xx);
spneut[0] = exp(-xx/0.965)*(exp(xxx) - exp(-xxx))/2.;
for (i = 2; i <= 10; i++) {
xx = i*1. - 0.5;
xxx = sqrt(2.29*xx);
spneut[i-1] = spneut[i-2] + exp(-xx/0.965)*(exp(xxx) - exp(-xxx))/2.;
}
for (i = 1; i <= 10; i++) {
spneut[i-1] = spneut[i-1]/spneut[9];
if (verboseLevel > 1) G4cout << "G4LFission::init: i=" << i <<
" spneut=" << spneut[i-1] << endl;
}
}
G4VParticleChange*
G4LFission::ApplyYourself(const G4Track & aTrack,G4Nucleus & targetNucleus)
{
theParticleChange.Initialize(aTrack);
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
const G4Material* aMaterial = aTrack.GetMaterial();
G4double N = targetNucleus.GetN();
G4double Z = targetNucleus.GetZ();
// theParticleChange.SetKillSignal(1);
theParticleChange.SetStatusChange(fStopAndKill);
G4double P = aParticle->GetTotalMomentum()/MeV;
G4double Px = P*(aParticle->GetMomentumDirection().x());
G4double Py = P*(aParticle->GetMomentumDirection().y());
G4double Pz = P*(aParticle->GetMomentumDirection().z());
G4double E = aParticle->GetTotalEnergy()/MeV;
G4double E0 = aParticle->GetDefinition()->GetPDGMass()/MeV;
G4double Q = aParticle->GetDefinition()->GetPDGCharge();
if (verboseLevel > 1) {
G4cout << "G4LFission:ApplyYourself: incident particle:" << endl;
G4cout << "P " << P << " MeV/c" << endl;
G4cout << "Px " << Px << " MeV/c" << endl;
G4cout << "Py " << Py << " MeV/c" << endl;
G4cout << "Pz " << Pz << " MeV/c" << endl;
G4cout << "E " << E << " MeV" << endl;
G4cout << "mass " << E0 << " MeV" << endl;
G4cout << "charge " << Q << endl;
}
// GHEISHA ADD operation to get total energy, mass, charge:
if (verboseLevel > 1) {
G4cout << "G4LFission:ApplyYourself: material:" << endl;
G4cout << "A " << N << endl;
G4cout << "Z " << Z << endl;
G4cout << "atomic mass " <<
Atomas(N, Z) << "MeV" << endl;
}
E = E + Atomas(N, Z);
G4double E02 = E*E - P*P;
E0 = sqrt(abs(E02));
if (E02 < 0) E0 = -E0;
Q = Q + Z;
if (verboseLevel > 1) {
G4cout << "G4LFission:ApplyYourself: total:" << endl;
G4cout << "E " << E << " MeV" << endl;
G4cout << "mass " << E0 << " MeV" << endl;
G4cout << "charge " << Q << endl;
}
Px = -Px;
Py = -Py;
Pz = -Pz;
G4double e1 = aParticle->GetKineticEnergy()/MeV;
if (e1 < 1.) e1 = 1.;
// Average number of neutrons
G4double avern = 2.569 + 0.559*log(e1);
G4bool photofission = 0; // For now
// Take the following value if photofission is not included
if (!photofission) avern = 2.569 + 0.900*log(e1);
// Average number of gammas
G4double averg = 9.500 + 0.600*log(e1);
G4double ran = RandGauss::shoot();
// Number of neutrons
G4int nn = avern + ran*1.23 + 0.5;
ran = RandGauss::shoot();
// Number of gammas
G4int ng = averg + ran*3. + 0.5;
if (nn < 1) nn = 1;
if (ng < 1) ng = 1;
G4double exn = 0.;
G4double exg = 0.;
// Make secondary neutrons and distribute kinetic energy
G4DynamicParticle* aNeutron;
G4int i;
for (i = 1; i <= nn; i++) {
ran = G4UniformRand();
G4int j;
for (j = 1; j <= 10; j++) {
if (ran < spneut[j-1]) goto label12;
}
j = 10;
label12:
ran = G4UniformRand();
G4double ekin = (j - 1)*1. + ran;
exn = exn + ekin;
aNeutron = new G4DynamicParticle(G4Neutron::NeutronDefinition(),
G4ParticleMomentum(1.,0.,0.),
ekin*MeV);
theParticleChange.AddSecondary(aNeutron);
}
// Make secondary gammas and distribute kinetic energy
G4DynamicParticle* aGamma;
for (i = 1; i <= ng; i++) {
ran = G4UniformRand();
G4double ekin = -0.87*log(ran);
exg = exg + ekin;
aGamma = new G4DynamicParticle(G4Gamma::GammaDefinition(),
G4ParticleMomentum(1.,0.,0.),
ekin*MeV);
theParticleChange.AddSecondary(aGamma);
}
G4double ex = exn + exg;
// Distribute momentum vectors and do Lorentz transformation
G4Track* theSecondary;
for (i = 1; i <= nn + ng; i++) {
G4double ran1 = G4UniformRand();
G4double ran2 = G4UniformRand();
G4double cost = -1. + 2.*ran1;
G4double sint = sqrt(abs(1. - cost*cost));
G4double phi = ran2*twopi;
// G4cout << ran1 << " " << ran2 << endl;
// G4cout << cost << " " << sint << " " << phi << endl;
theSecondary = theParticleChange.GetSecondary(i - 1);
G4double pp = theSecondary->GetDynamicParticle()->GetTotalMomentum()/MeV;
G4double px = pp*sint*sin(phi);
G4double py = pp*sint*cos(phi);
G4double pz = pp*cost;
// G4cout << pp << endl;
// G4cout << px << " " << py << " " << pz << endl;
G4double e = theSecondary->GetTotalEnergy()/MeV;
G4double e0 = theSecondary->GetDefinition()->GetPDGMass()/MeV;
G4double a = px*Px + py*Py + pz*Pz;
a = (a/(E + E0) - e)/E0;
px = px + a*Px;
py = py + a*Py;
pz = pz + a*Pz;
G4double p2 = px*px + py*py + pz*pz;
pp = sqrt(p2);
e = sqrt(e0*e0 + p2);
G4double ekin = e - theSecondary->GetDefinition()->GetPDGMass()/MeV;
theSecondary->SetMomentumDirection(G4ParticleMomentum(px/pp,
py/pp,
pz/pp));
theSecondary->SetKineticEnergy(ekin*MeV);
}
return &theParticleChange;
}
// Computes atomic mass in MeV (translation of GHEISHA routine ATOMAS)
// Not optimized: conforms closely to original Fortran.
G4double
G4LFission::Atomas(const G4double A, const G4double Z)
{
G4double rmel = G4Electron::ElectronDefinition()->GetPDGMass()/MeV;
G4double rmp = G4Proton::ProtonDefinition()->GetPDGMass()/MeV;
G4double rmn = G4Neutron::NeutronDefinition()->GetPDGMass()/MeV;
G4double rmd = G4Deuteron::DeuteronDefinition()->GetPDGMass()/MeV;
G4double rma = G4Alpha::AlphaDefinition()->GetPDGMass()/MeV;
G4int ia = A + 0.5;
if (ia < 1) return 0;
G4int iz = Z + 0.5;
if (iz < 0) return 0;
if (iz > ia) return 0;
if (ia == 1) {
if (iz == 0) return rmn; //neutron
if (iz == 1) return rmp + rmel; //Hydrogen
}
else if (ia == 2 && iz == 1) {
return rmd; //Deuteron
}
else if (ia == 4 && iz == 2) {
return rma; //Alpha
}
G4double mass = (A - Z)*rmn + Z*rmp + Z*rmel
- 15.67*A
+ 17.23*pow(A, 2./3.)
+ 93.15*(A/2. - Z)*(A/2. - Z)/A
+ 0.6984523*Z*Z/pow(A, 1./3.);
G4int ipp = (ia - iz)%2;
G4int izz = iz%2;
if (ipp == izz) mass = mass + (ipp + izz -1)*12.*pow(A, -0.5);
return mass;
}