Import Geant4 11.3.0 source tree
This commit is contained in:
@@ -42,6 +42,13 @@
|
||||
#include "G4IonTable.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4NucleiProperties.hh"
|
||||
#include "G4DecayTable.hh"
|
||||
#include "G4VDecayChannel.hh"
|
||||
#include "G4DecayProducts.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4Fragment.hh"
|
||||
#include "G4ExcitationHandler.hh"
|
||||
#include "G4ReactionProductVector.hh"
|
||||
|
||||
#include "G4Exp.hh"
|
||||
#include "G4Log.hh"
|
||||
@@ -50,13 +57,28 @@
|
||||
#include "G4HadronicParameters.hh"
|
||||
#include "G4PhysicsModelCatalog.hh"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr G4int maxN = 1000;
|
||||
constexpr G4double emin = 2*136.9*CLHEP::MeV;
|
||||
}
|
||||
|
||||
G4ChargeExchange::G4ChargeExchange(G4ChargeExchangeXS* ptr)
|
||||
: G4HadronicInteraction("ChargeExchange"),
|
||||
fXSection(ptr)
|
||||
fXSection(ptr), fXSWeightFactor(1.0)
|
||||
{
|
||||
lowEnergyLimit = 1.*CLHEP::MeV;
|
||||
secID = G4PhysicsModelCatalog::GetModelID( "model_ChargeExchange" );
|
||||
nist = G4NistManager::Instance();
|
||||
fHandler = new G4ExcitationHandler();
|
||||
if (nullptr != fXSection) {
|
||||
fXSWeightFactor = 1.0/fXSection->GetCrossSectionFactor();
|
||||
}
|
||||
}
|
||||
|
||||
G4ChargeExchange::~G4ChargeExchange()
|
||||
{
|
||||
delete fHandler;
|
||||
}
|
||||
|
||||
G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
@@ -64,7 +86,6 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
{
|
||||
theParticleChange.Clear();
|
||||
auto part = aTrack.GetDefinition();
|
||||
G4int pdg = part->GetPDGEncoding();
|
||||
G4double ekin = aTrack.GetKineticEnergy();
|
||||
|
||||
G4int A = targetNucleus.GetA_asInt();
|
||||
@@ -73,8 +94,14 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
if (ekin <= lowEnergyLimit) {
|
||||
return &theParticleChange;
|
||||
}
|
||||
theParticleChange.SetWeightChange(fXSWeightFactor);
|
||||
|
||||
G4int projPDG = part->GetPDGEncoding();
|
||||
|
||||
// for hydrogen targets and positive projectile change exchange
|
||||
// is not possible on proton, only on deuteron
|
||||
if (1 == Z && (211 == projPDG || 321 == projPDG)) { A = 2; }
|
||||
|
||||
if (verboseLevel > 1)
|
||||
G4cout << "G4ChargeExchange for " << part->GetParticleName()
|
||||
<< " PDGcode= " << projPDG << " on nucleus Z= " << Z
|
||||
@@ -86,16 +113,19 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
G4double etot = mass1 + lv0.e();
|
||||
|
||||
// select final state
|
||||
const G4ParticleDefinition* theRecoil = nullptr;
|
||||
const G4ParticleDefinition* theSecondary =
|
||||
fXSection->SampleSecondaryType(part, Z, A);
|
||||
G4int pdg = theSecondary->GetPDGEncoding();
|
||||
|
||||
// omega(782) and f2(1270)
|
||||
G4bool isShortLived = (pdg == 223 || pdg == 225);
|
||||
|
||||
// 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 (projPDG == -211) { --Z; }
|
||||
else if (projPDG == 211) { ++Z; }
|
||||
else if (projPDG == -321) { --Z; }
|
||||
else if (projPDG == 321) { ++Z; }
|
||||
else if (projPDG == 130) {
|
||||
if (theSecondary->GetPDGCharge() > 0.0) { --Z; }
|
||||
else { ++Z; }
|
||||
} else {
|
||||
@@ -103,23 +133,32 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
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 {
|
||||
// recoil nucleus
|
||||
const G4ParticleDefinition* theRecoil = nullptr;
|
||||
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 if (nist->GetIsotopeAbundance(Z, A) > 0.0) {
|
||||
theRecoil = G4ParticleTable::GetParticleTable()
|
||||
->GetIonTable()->GetIon(Z, A, 0.0);
|
||||
}
|
||||
if (nullptr == theRecoil) { return &theParticleChange; }
|
||||
|
||||
G4double mass2 = theSecondary->GetPDGMass();
|
||||
G4double mass3 = theRecoil->GetPDGMass();
|
||||
// check if there is enough energy for the final state
|
||||
// and sample mass of produced state
|
||||
const G4double mass0 = theSecondary->GetPDGMass();
|
||||
G4double mass3 = (nullptr == theRecoil) ?
|
||||
G4NucleiProperties::GetNuclearMass(A, Z) : theRecoil->GetPDGMass();
|
||||
G4double mass2 = mass0;
|
||||
if (isShortLived &&
|
||||
!SampleMass(mass2, theSecondary->GetPDGWidth(), etot - mass3)) {
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
// not possible kinematically
|
||||
if (etot <= mass2 + mass3) {
|
||||
// not possible kinematically
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
@@ -153,7 +192,7 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
momentumCMS*cost,
|
||||
std::sqrt(momentumCMS*momentumCMS + mass2*mass2));
|
||||
|
||||
// kinematics in the final stae, may be a warning should be added if
|
||||
// kinematics in the final state, may be a warning should be added if
|
||||
lv2.boost(bst);
|
||||
if (lv2.e() < mass2) {
|
||||
lv2.setE(mass2);
|
||||
@@ -167,16 +206,44 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
|
||||
theParticleChange.SetStatusChange(stopAndKill);
|
||||
theParticleChange.SetEnergyChange(0.0);
|
||||
|
||||
G4DynamicParticle * aSec = new G4DynamicParticle(theSecondary, lv2);
|
||||
theParticleChange.AddSecondary(aSec, secID);
|
||||
if (!isShortLived) {
|
||||
auto aSec = new G4DynamicParticle(theSecondary, lv2);
|
||||
theParticleChange.AddSecondary(aSec, secID);
|
||||
} else {
|
||||
auto channel = theSecondary->GetDecayTable()->SelectADecayChannel(mass2);
|
||||
auto products = channel->DecayIt(mass2);
|
||||
G4ThreeVector bst1 = lv2.boostVector();
|
||||
G4int N = products->entries();
|
||||
for (G4int i=0; i<N; ++i) {
|
||||
auto p = (*products)[i];
|
||||
auto lvp = p->Get4Momentum();
|
||||
lvp.boost(bst1);
|
||||
p->Set4Momentum(lvp);
|
||||
theParticleChange.AddSecondary(p, secID);
|
||||
}
|
||||
delete products;
|
||||
}
|
||||
|
||||
G4DynamicParticle * aRec = new G4DynamicParticle(theRecoil, lv);
|
||||
theParticleChange.AddSecondary(aRec, secID);
|
||||
// recoil is a stable isotope
|
||||
if (nullptr != theRecoil) {
|
||||
auto aRec = new G4DynamicParticle(theRecoil, lv);
|
||||
theParticleChange.AddSecondary(aRec, secID);
|
||||
} else {
|
||||
// recoil is an unstable fragment
|
||||
G4Fragment frag(A, Z, lv);
|
||||
auto products = fHandler->BreakItUp(frag);
|
||||
for (auto & prod : *products) {
|
||||
auto dp = new G4DynamicParticle(prod->GetDefinition(), prod->GetMomentum());
|
||||
theParticleChange.AddSecondary(dp, secID);
|
||||
delete prod;
|
||||
}
|
||||
delete products;
|
||||
}
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
G4double G4ChargeExchange::SampleT(const G4ParticleDefinition*,
|
||||
G4int A, G4double tmax) const
|
||||
const G4int A, const G4double tmax) const
|
||||
{
|
||||
G4double aa, bb, cc, dd;
|
||||
G4Pow* g4pow = G4Pow::GetInstance();
|
||||
@@ -198,14 +265,31 @@ G4double G4ChargeExchange::SampleT(const G4ParticleDefinition*,
|
||||
G4double y = bb;
|
||||
if(G4UniformRand()*(x1 + x2) < x2) y = dd;
|
||||
|
||||
const G4int maxN = 10000;
|
||||
G4int count = 0;
|
||||
do {
|
||||
for (G4int i=0; i<maxN; ++i) {
|
||||
t = -G4Log(G4UniformRand())/y;
|
||||
} while ( (t > tmax) && ++count < maxN );
|
||||
/* Loop checking, 10.08.2015, A.Ribon */
|
||||
if ( count >= maxN ) {
|
||||
t = 0.0;
|
||||
if (t <= tmax) { return t; }
|
||||
}
|
||||
return t;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
G4bool G4ChargeExchange::SampleMass(G4double& M, const G4double G, const G4double elim)
|
||||
{
|
||||
// +- 4 width but above 2 pion mass
|
||||
const G4double e1 = std::max(M - 4*G, emin);
|
||||
const G4double e2 = std::min(M + 4*G, elim) - e1;
|
||||
if (e2 <= 0.0) { return false; }
|
||||
const G4double M2 = M*M;
|
||||
const G4double MG2 = M2*G*G;
|
||||
|
||||
// sampling Breit-Wigner function
|
||||
for (G4int i=0; i<maxN; ++i) {
|
||||
G4double e = e1 + e2*G4UniformRand();
|
||||
G4double x = e*e - M2;
|
||||
G4double y = MG2/(x*x + MG2);
|
||||
if (y >= G4UniformRand()) {
|
||||
M = e;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
G4ChargeExchangeProcess::G4ChargeExchangeProcess(const G4String& procName)
|
||||
: G4HadronicProcess(procName,fChargeExchange), first(true)
|
||||
{
|
||||
G4cout << "###=== The class G4ChargeExchangeProcess is obsolete!!!" << G4endl;
|
||||
G4cout << "###=== It will be removed at the next public release" << G4endl;
|
||||
thEnergy = 20.*MeV;
|
||||
pPDG = 0;
|
||||
verboseLevel= 1;
|
||||
|
||||
Reference in New Issue
Block a user