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
@@ -6,6 +6,19 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-11-15 Vladimir Ivanchenko (hadr-cohe-V11-02-03)
- G4ChargeExchange - fixed problem of the Hydrogen target; change event weight
if cross section biasing factor is applied
- G4ChargeExchangeProcess - added warning
## 2024-09-22 Vladimir Ivanchenko (hadr-cohe-V11-02-02)
- G4ChargeExchange - fixed problem 2618 - implemented production and decay of
omega(780) and f2(1270) for pion projectile, implemented decay of unstable
isomeres if recoil nucleus if not a natural isotope
## 2024-07-30 Vladimir Ivanchenko (hadr-cohe-V11-02-01)
- G4ChargeExchange - fixed problem 2617 - do not allow unphysical final state
## 2024-05-02 Gabriele Cosmo (hadr-cohe-V11-02-00)
- Fixed compilation warnings for potentially initialised local variables in
SampleThetaCMS() for G4DiffuseElastic and G4NuclNuclDiffuseElastic.
@@ -45,13 +45,15 @@
class G4ParticleDefinition;
class G4ChargeExchangeXS;
class G4ExcitationHandler;
class G4NistManager;
class G4ChargeExchange : public G4HadronicInteraction
{
public:
explicit G4ChargeExchange(G4ChargeExchangeXS*);
~G4ChargeExchange() override = default;
~G4ChargeExchange() override;
G4ChargeExchange( const G4ChargeExchange &right ) = delete;
const G4ChargeExchange & operator=( const G4ChargeExchange &right ) = delete;
@@ -66,10 +68,15 @@ public:
private:
G4bool SampleMass(G4double& mass, const G4double width, const G4double elim);
G4ChargeExchangeXS* fXSection;
G4ExcitationHandler* fHandler;
G4NistManager* nist;
G4int secID; // Creator model ID for the secondaries created by this model
G4double lowEnergyLimit; // lowest limit to avoid numerical problems
G4double fXSWeightFactor;
};
#endif
@@ -53,6 +53,7 @@ geant4_module_link_libraries(G4hadronic_coherent_elastic
PRIVATE
G4baryons
G4cuts
G4hadronic_deex_handler
G4heprandom
G4ions
G4leptons
@@ -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;