Import Geant4 11.3.0 source tree

This commit is contained in:
Gabriele Cosmo
2024-12-06 11:11:40 +01:00
parent e58e650b32
commit 32390e802b
1984 changed files with 98713 additions and 83996 deletions
@@ -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;