Import Geant4 11.2.0 source tree
This commit is contained in:
@@ -23,9 +23,6 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// G4 Model: Charge and strangness exchange based on G4LightMedia model
|
||||
// 28 May 2006 V.Ivanchenko
|
||||
//
|
||||
@@ -37,6 +34,7 @@
|
||||
//
|
||||
|
||||
#include "G4ChargeExchange.hh"
|
||||
#include "G4ChargeExchangeXS.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
@@ -53,262 +51,132 @@
|
||||
#include "G4PhysicsModelCatalog.hh"
|
||||
|
||||
|
||||
G4ChargeExchange::G4ChargeExchange() : G4HadronicInteraction("Charge Exchange"), secID(-1)
|
||||
G4ChargeExchange::G4ChargeExchange(G4ChargeExchangeXS* ptr)
|
||||
: G4HadronicInteraction("ChargeExchange"),
|
||||
fXSection(ptr)
|
||||
{
|
||||
SetMinEnergy( 0.0*GeV );
|
||||
SetMaxEnergy( G4HadronicParameters::Instance()->GetMaxEnergy() );
|
||||
|
||||
lowestEnergyLimit = 1.*MeV;
|
||||
|
||||
theProton = G4Proton::Proton();
|
||||
theNeutron = G4Neutron::Neutron();
|
||||
theAProton = G4AntiProton::AntiProton();
|
||||
theANeutron = G4AntiNeutron::AntiNeutron();
|
||||
thePiPlus = G4PionPlus::PionPlus();
|
||||
thePiMinus = G4PionMinus::PionMinus();
|
||||
thePiZero = G4PionZero::PionZero();
|
||||
theKPlus = G4KaonPlus::KaonPlus();
|
||||
theKMinus = G4KaonMinus::KaonMinus();
|
||||
theK0S = G4KaonZeroShort::KaonZeroShort();
|
||||
theK0L = G4KaonZeroLong::KaonZeroLong();
|
||||
theL = G4Lambda::Lambda();
|
||||
theAntiL = G4AntiLambda::AntiLambda();
|
||||
theSPlus = G4SigmaPlus::SigmaPlus();
|
||||
theASPlus = G4AntiSigmaPlus::AntiSigmaPlus();
|
||||
theSMinus = G4SigmaMinus::SigmaMinus();
|
||||
theASMinus = G4AntiSigmaMinus::AntiSigmaMinus();
|
||||
theS0 = G4SigmaZero::SigmaZero();
|
||||
theAS0 = G4AntiSigmaZero::AntiSigmaZero();
|
||||
theXiMinus = G4XiMinus::XiMinus();
|
||||
theXi0 = G4XiZero::XiZero();
|
||||
theAXiMinus = G4AntiXiMinus::AntiXiMinus();
|
||||
theAXi0 = G4AntiXiZero::AntiXiZero();
|
||||
theOmega = G4OmegaMinus::OmegaMinus();
|
||||
theAOmega = G4AntiOmegaMinus::AntiOmegaMinus();
|
||||
theD = G4Deuteron::Deuteron();
|
||||
theT = G4Triton::Triton();
|
||||
theA = G4Alpha::Alpha();
|
||||
theHe3 = G4He3::He3();
|
||||
|
||||
lowEnergyLimit = 1.*CLHEP::MeV;
|
||||
secID = G4PhysicsModelCatalog::GetModelID( "model_ChargeExchange" );
|
||||
}
|
||||
|
||||
G4ChargeExchange::~G4ChargeExchange()
|
||||
{}
|
||||
|
||||
G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
const G4HadProjectile& aTrack, G4Nucleus& targetNucleus)
|
||||
{
|
||||
theParticleChange.Clear();
|
||||
const G4HadProjectile* aParticle = &aTrack;
|
||||
G4double ekin = aParticle->GetKineticEnergy();
|
||||
auto part = aTrack.GetDefinition();
|
||||
G4int pdg = part->GetPDGEncoding();
|
||||
G4double ekin = aTrack.GetKineticEnergy();
|
||||
|
||||
G4int A = targetNucleus.GetA_asInt();
|
||||
G4int Z = targetNucleus.GetZ_asInt();
|
||||
|
||||
if(ekin <= lowestEnergyLimit || A < 3) {
|
||||
theParticleChange.SetEnergyChange(ekin);
|
||||
theParticleChange.SetMomentumChange(0.0,0.0,1.0);
|
||||
if (ekin <= lowEnergyLimit) {
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
G4double plab = aParticle->GetTotalMomentum();
|
||||
|
||||
G4int projPDG = part->GetPDGEncoding();
|
||||
if (verboseLevel > 1)
|
||||
G4cout << "G4ChargeExchange::DoIt: Incident particle plab="
|
||||
<< plab/GeV << " GeV/c "
|
||||
<< " ekin(MeV) = " << ekin/MeV << " "
|
||||
<< aParticle->GetDefinition()->GetParticleName() << G4endl;
|
||||
|
||||
// Scattered particle referred to axis of incident particle
|
||||
const G4ParticleDefinition* theParticle = aParticle->GetDefinition();
|
||||
|
||||
G4int N = A - Z;
|
||||
G4int projPDG = theParticle->GetPDGEncoding();
|
||||
if (verboseLevel > 1)
|
||||
G4cout << "G4ChargeExchange for " << theParticle->GetParticleName()
|
||||
G4cout << "G4ChargeExchange for " << part->GetParticleName()
|
||||
<< " PDGcode= " << projPDG << " on nucleus Z= " << Z
|
||||
<< " A= " << A << " N= " << N
|
||||
<< " A= " << A << " N= " << A - Z
|
||||
<< G4endl;
|
||||
|
||||
const G4ParticleDefinition* theDef = nullptr;
|
||||
G4double mass1 = G4NucleiProperties::GetNuclearMass(A, Z);
|
||||
G4LorentzVector lv0 = aTrack.Get4Momentum();
|
||||
G4double etot = mass1 + lv0.e();
|
||||
|
||||
G4double mass2 = G4NucleiProperties::GetNuclearMass(A, Z);
|
||||
G4LorentzVector lv1 = aParticle->Get4Momentum();
|
||||
G4LorentzVector lv0(0.0,0.0,0.0,mass2);
|
||||
|
||||
G4LorentzVector lv = lv0 + lv1;
|
||||
G4ThreeVector bst = lv.boostVector();
|
||||
lv1.boost(-bst);
|
||||
lv0.boost(-bst);
|
||||
|
||||
// Sample final particles
|
||||
G4bool theHyperon = false;
|
||||
// select final state
|
||||
const G4ParticleDefinition* theRecoil = nullptr;
|
||||
const G4ParticleDefinition* theSecondary = nullptr;
|
||||
const G4ParticleDefinition* theSecondary =
|
||||
fXSection->SampleSecondaryType(part, Z, A);
|
||||
|
||||
if(theParticle == theProton) {
|
||||
theSecondary = theNeutron;
|
||||
Z++;
|
||||
} else if(theParticle == theNeutron) {
|
||||
theSecondary = theProton;
|
||||
Z--;
|
||||
} else if(theParticle == thePiPlus) {
|
||||
theSecondary = thePiZero;
|
||||
Z++;
|
||||
} else if(theParticle == thePiMinus) {
|
||||
theSecondary = thePiZero;
|
||||
Z--;
|
||||
} else if(theParticle == theKPlus) {
|
||||
if(G4UniformRand()<0.5) theSecondary = theK0S;
|
||||
else theSecondary = theK0L;
|
||||
Z++;
|
||||
} else if(theParticle == theKMinus) {
|
||||
if(G4UniformRand()<0.5) theSecondary = theK0S;
|
||||
else theSecondary = theK0L;
|
||||
Z--;
|
||||
} else if(theParticle == theK0S || theParticle == theK0L) {
|
||||
if(G4UniformRand()*A < G4double(Z)) {
|
||||
theSecondary = theKPlus;
|
||||
Z--;
|
||||
} else {
|
||||
theSecondary = theKMinus;
|
||||
Z++;
|
||||
}
|
||||
} else if(theParticle == theANeutron) {
|
||||
theSecondary = theAProton;
|
||||
Z++;
|
||||
} else if(theParticle == theAProton) {
|
||||
theSecondary = theANeutron;
|
||||
Z--;
|
||||
} else if(theParticle == theL) {
|
||||
G4double x = G4UniformRand();
|
||||
if(G4UniformRand()*A < G4double(Z)) {
|
||||
if(x < 0.2) {
|
||||
theSecondary = theS0;
|
||||
} else if (x < 0.4) {
|
||||
theSecondary = theSPlus;
|
||||
Z--;
|
||||
} else if (x < 0.6) {
|
||||
theSecondary = theProton;
|
||||
theRecoil = theL;
|
||||
theHyperon = true;
|
||||
A--;
|
||||
} else if (x < 0.8) {
|
||||
theSecondary = theProton;
|
||||
theRecoil = theS0;
|
||||
theHyperon = true;
|
||||
A--;
|
||||
} else {
|
||||
theSecondary = theNeutron;
|
||||
theRecoil = theSPlus;
|
||||
theHyperon = true;
|
||||
A--;
|
||||
}
|
||||
} else {
|
||||
if(x < 0.2) {
|
||||
theSecondary = theS0;
|
||||
} else if (x < 0.4) {
|
||||
theSecondary = theSMinus;
|
||||
Z++;
|
||||
} else if (x < 0.6) {
|
||||
theSecondary = theNeutron;
|
||||
theRecoil = theL;
|
||||
A--;
|
||||
theHyperon = true;
|
||||
} else if (x < 0.8) {
|
||||
theSecondary = theNeutron;
|
||||
theRecoil = theS0;
|
||||
theHyperon = true;
|
||||
A--;
|
||||
} else {
|
||||
theSecondary = theProton;
|
||||
theRecoil = theSMinus;
|
||||
theHyperon = true;
|
||||
A--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Z == 1 && A == 2) theDef = theD;
|
||||
else if (Z == 1 && A == 3) theDef = theT;
|
||||
else if (Z == 2 && A == 3) theDef = theHe3;
|
||||
else if (Z == 2 && A == 4) theDef = theA;
|
||||
else {
|
||||
theDef =
|
||||
G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon(Z,A,0.0);
|
||||
}
|
||||
if(!theSecondary) { return &theParticleChange; }
|
||||
|
||||
G4double m11 = theSecondary->GetPDGMass();
|
||||
G4double m21 = theDef->GetPDGMass();
|
||||
if(theRecoil) { m21 += theRecoil->GetPDGMass(); }
|
||||
else { theRecoil = theDef; }
|
||||
|
||||
G4double etot = lv0.e() + lv1.e();
|
||||
|
||||
// kinematiacally impossible
|
||||
if(etot < m11 + m21) {
|
||||
theParticleChange.SetEnergyChange(ekin);
|
||||
theParticleChange.SetMomentumChange(0.0,0.0,1.0);
|
||||
// atomic number of the recoil nucleus
|
||||
if (pdg == -211) { --Z; }
|
||||
else if (pdg == 211) { ++Z; }
|
||||
else if (pdg == -321) { --Z; }
|
||||
else if (pdg == 321) { ++Z; }
|
||||
else if (pdg == 130) {
|
||||
if (theSecondary->GetPDGCharge() > 0.0) { --Z; }
|
||||
else { ++Z; }
|
||||
} else {
|
||||
// not ready for other projectile
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
G4ThreeVector p1 = lv1.vect();
|
||||
G4double e1 = 0.5*etot*(1.0 - (m21*m21 - m11*m11)/(etot*etot));
|
||||
// G4double e2 = etot - e1;
|
||||
G4double ptot = std::sqrt(e1*e1 - m11*m11);
|
||||
|
||||
G4double tmax = 4.0*ptot*ptot;
|
||||
G4double g2 = GeV*GeV;
|
||||
|
||||
G4double t = g2*SampleT(tmax/g2, A);
|
||||
|
||||
if(verboseLevel>1) {
|
||||
G4cout <<"## G4ChargeExchange t= " << t << " tmax= " << tmax
|
||||
<< " ptot= " << ptot << G4endl;
|
||||
if (Z == 0 && A == 1) theRecoil = G4Neutron::Neutron();
|
||||
else if (Z == 1 && A == 1) theRecoil = G4Proton::Proton();
|
||||
else if (Z == 1 && A == 2) theRecoil = G4Deuteron::Deuteron();
|
||||
else if (Z == 1 && A == 3) theRecoil = G4Triton::Triton();
|
||||
else if (Z == 2 && A == 3) theRecoil = G4He3::He3();
|
||||
else if (Z == 2 && A == 4) theRecoil = G4Alpha::Alpha();
|
||||
else {
|
||||
theRecoil = G4ParticleTable::GetParticleTable()
|
||||
->GetIonTable()->GetIon(Z, A, 0.0);
|
||||
}
|
||||
// Sampling in CM system
|
||||
G4double phi = G4UniformRand()*twopi;
|
||||
if (nullptr == theRecoil) { return &theParticleChange; }
|
||||
|
||||
G4double mass2 = theSecondary->GetPDGMass();
|
||||
G4double mass3 = theRecoil->GetPDGMass();
|
||||
|
||||
if (etot <= mass2 + mass3) {
|
||||
// not possible kinematically
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
// sample kinematics
|
||||
G4LorentzVector lv1(0.0, 0.0, 0.0, mass1);
|
||||
G4LorentzVector lv = lv0 + lv1;
|
||||
G4ThreeVector bst = lv.boostVector();
|
||||
G4double ss = lv.mag2();
|
||||
|
||||
// tmax = 4*momCMS^2
|
||||
G4double e2 = ss + mass2*mass2 - mass3*mass3;
|
||||
G4double tmax = e2*e2/ss - 4*mass2*mass2;
|
||||
|
||||
G4double t = SampleT(theSecondary, A, tmax);
|
||||
|
||||
G4double phi = G4UniformRand()*CLHEP::twopi;
|
||||
G4double cost = 1. - 2.0*t/tmax;
|
||||
if(std::abs(cost) > 1.0) cost = 1.0;
|
||||
|
||||
if (cost > 1.0) { cost = 1.0; }
|
||||
else if(cost < -1.0) { cost = -1.0; }
|
||||
|
||||
G4double sint = std::sqrt((1.0-cost)*(1.0+cost));
|
||||
|
||||
//if (verboseLevel > 1)
|
||||
// G4cout << "cos(t)=" << cost << " std::sin(t)=" << sint << G4endl;
|
||||
if (verboseLevel>1) {
|
||||
G4cout << " t= " << t << " tmax(GeV^2)= " << tmax/(GeV*GeV)
|
||||
<< " cos(t)=" << cost << " sin(t)=" << sint << G4endl;
|
||||
}
|
||||
G4double momentumCMS = 0.5*std::sqrt(tmax);
|
||||
G4LorentzVector lv2(momentumCMS*sint*std::cos(phi),
|
||||
momentumCMS*sint*std::sin(phi),
|
||||
momentumCMS*cost,
|
||||
std::sqrt(momentumCMS*momentumCMS + mass2*mass2));
|
||||
|
||||
G4ThreeVector v1(sint*std::cos(phi),sint*std::sin(phi),cost);
|
||||
v1 *= ptot;
|
||||
G4LorentzVector nlv1(v1.x(),v1.y(),v1.z(),e1);
|
||||
G4LorentzVector nlv0 = lv0 + lv1 - nlv1;
|
||||
|
||||
nlv0.boost(bst);
|
||||
nlv1.boost(bst);
|
||||
// kinematics in the final stae, may be a warning should be added if
|
||||
lv2.boost(bst);
|
||||
if (lv2.e() < mass2) {
|
||||
lv2.setE(mass2);
|
||||
}
|
||||
lv -= lv2;
|
||||
if (lv.e() < mass3) {
|
||||
lv.setE(mass3);
|
||||
}
|
||||
|
||||
// prepare secondary particles
|
||||
theParticleChange.SetStatusChange(stopAndKill);
|
||||
theParticleChange.SetEnergyChange(0.0);
|
||||
G4DynamicParticle * aSec = new G4DynamicParticle(theSecondary, nlv1);
|
||||
|
||||
G4DynamicParticle * aSec = new G4DynamicParticle(theSecondary, lv2);
|
||||
theParticleChange.AddSecondary(aSec, secID);
|
||||
|
||||
G4double erec = std::max(nlv0.e() - m21, 0.0);
|
||||
|
||||
//G4cout << "erec= " <<erec << " Esec= " << aSec->GetKineticEnergy() << G4endl;
|
||||
|
||||
if(theHyperon) {
|
||||
theParticleChange.SetLocalEnergyDeposit(erec);
|
||||
aSec = new G4DynamicParticle();
|
||||
aSec->SetDefinition(theRecoil);
|
||||
aSec->SetKineticEnergy(0.0);
|
||||
} else if(erec > GetRecoilEnergyThreshold()) {
|
||||
aSec = new G4DynamicParticle(theRecoil, nlv0);
|
||||
theParticleChange.AddSecondary(aSec, secID);
|
||||
} else {
|
||||
theParticleChange.SetLocalEnergyDeposit(erec);
|
||||
}
|
||||
G4DynamicParticle * aRec = new G4DynamicParticle(theRecoil, lv);
|
||||
theParticleChange.AddSecondary(aRec, secID);
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
G4double G4ChargeExchange::SampleT(G4double tmax, G4int A)
|
||||
G4double G4ChargeExchange::SampleT(const G4ParticleDefinition*,
|
||||
G4int A, G4double tmax) const
|
||||
{
|
||||
G4double aa, bb, cc, dd;
|
||||
G4Pow* g4pow = G4Pow::GetInstance();
|
||||
@@ -330,15 +198,14 @@ G4double G4ChargeExchange::SampleT(G4double tmax, G4int A)
|
||||
G4double y = bb;
|
||||
if(G4UniformRand()*(x1 + x2) < x2) y = dd;
|
||||
|
||||
const G4int maxNumberOfLoops = 10000;
|
||||
G4int loopCounter = 0;
|
||||
const G4int maxN = 10000;
|
||||
G4int count = 0;
|
||||
do {
|
||||
t = -G4Log(G4UniformRand())/y;
|
||||
} while ( (t > tmax) &&
|
||||
++loopCounter < maxNumberOfLoops ); /* Loop checking, 10.08.2015, A.Ribon */
|
||||
if ( loopCounter >= maxNumberOfLoops ) {
|
||||
} while ( (t > tmax) && ++count < maxN );
|
||||
/* Loop checking, 10.08.2015, A.Ribon */
|
||||
if ( count >= maxN ) {
|
||||
t = 0.0;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user