Import Geant4 11.4.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2025-06-26 09:17:29 +02:00
parent 20a218bbe1
commit a499fb82e9
1941 changed files with 203285 additions and 95593 deletions
@@ -60,7 +60,6 @@
namespace
{
constexpr G4int maxN = 1000;
constexpr G4double emin = 2*136.9*CLHEP::MeV;
}
G4ChargeExchange::G4ChargeExchange(G4ChargeExchangeXS* ptr)
@@ -102,21 +101,25 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
// is not possible on proton, only on deuteron
if (1 == Z && (211 == projPDG || 321 == projPDG)) { A = 2; }
if (verboseLevel > 1)
if (verboseLevel > 1) {
G4cout << "G4ChargeExchange for " << part->GetParticleName()
<< " PDGcode= " << projPDG << " on nucleus Z= " << Z
<< " A= " << A << " N= " << A - Z
<< G4endl;
}
G4double mass1 = G4NucleiProperties::GetNuclearMass(A, Z);
G4LorentzVector lv0 = aTrack.Get4Momentum();
G4double etot = mass1 + lv0.e();
// select final state
const G4ParticleDefinition* theSecondary =
fXSection->SampleSecondaryType(part, Z, A);
fXSection->SampleSecondaryType(part, aTrack.GetMaterial(),
Z, A, aTrack.GetTotalEnergy());
G4int pdg = theSecondary->GetPDGEncoding();
if (verboseLevel > 1)
G4cout << " Secondary " << theSecondary->GetParticleName() << " pdg=" << pdg << G4endl;
// omega(782) and f2(1270)
G4bool isShortLived = (pdg == 223 || pdg == 225);
@@ -141,62 +144,86 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
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);
}
// 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) {
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();
G4double m0 = lv.mag();
const G4double mass0 = theSecondary->GetPDGMass();
G4double mass2 = mass0;
G4double mass3;
G4bool ok = false;
if (verboseLevel > 1) {
G4cout << " Secondary meson " << theSecondary->GetParticleName()
<< " mass(MeV)=" << mass2 << " pdg=" << pdg
<< " Final Z=" << Z << " isShortLived=" << isShortLived
<< " " << lv
<< G4endl;
}
// fixed recoil mass
if (nullptr != theRecoil) {
mass3 = theRecoil->GetPDGMass();
ok = (m0 > mass2 + mass3);
// excited nuclear state
} else {
G4double mass30 = G4NucleiProperties::GetNuclearMass(A, Z);
const G4double eFermi = 10*CLHEP::MeV;
for (G4int i=0; i<10; ++i) {
mass3 = mass30 + eFermi*G4UniformRand();
if (m0 > mass2 + mass3) {
ok = true;
break;
}
}
}
if (isShortLived) {
const G4double elim = 300*CLHEP::MeV;
ok = false;
for (G4int i=0; i<10; ++i) {
if (SampleMass(mass2, theSecondary->GetPDGWidth(), elim)) {
if (m0 > mass2 + mass3) {
ok = true;
break;
}
}
}
}
// not possible kinematically
if (!ok) { return &theParticleChange; }
// tmax = 4*momCMS^2
G4double e2 = ss + mass2*mass2 - mass3*mass3;
G4double tmax = e2*e2/ss - 4*mass2*mass2;
G4double e2 = (m0*m0 + mass2*mass2 - mass3*mass3)/(2*m0);
G4double momentumCMS = std::sqrt(e2*e2 - mass2*mass2);
G4double tmax = 4*(momentumCMS*momentumCMS);
G4double t = SampleT(theSecondary, A, tmax);
G4double phi = G4UniformRand()*CLHEP::twopi;
G4double cost = 1. - 2.0*t/tmax;
if (cost > 1.0) { cost = 1.0; }
else if(cost < -1.0) { cost = -1.0; }
// if cos(theta) negative, there is a numerical problem
// instead of making scattering backward, make in this case
// no scattering
if (std::abs(cost) > 1.0) { cost = 1.0; }
G4double sint = std::sqrt((1.0-cost)*(1.0+cost));
if (verboseLevel>1) {
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));
momentumCMS*cost, e2);
// kinematics in the final state, may be a warning should be added if
G4ThreeVector bst = lv.boostVector();
lv2.boost(bst);
if (lv2.e() < mass2) {
lv2.setE(mass2);
}
lv -= lv2;
if (lv.e() < mass3) {
lv.setE(mass3);
@@ -205,6 +232,7 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
// prepare secondary particles
theParticleChange.SetStatusChange(stopAndKill);
theParticleChange.SetEnergyChange(0.0);
theParticleChange.SetWeightChange(fXSWeightFactor);
if (!isShortLived) {
auto aSec = new G4DynamicParticle(theSecondary, lv2);
@@ -218,8 +246,9 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
auto p = (*products)[i];
auto lvp = p->Get4Momentum();
lvp.boost(bst1);
p->Set4Momentum(lvp);
theParticleChange.AddSecondary(p, secID);
auto pnew = new G4DynamicParticle(*p);
pnew->Set4Momentum(lvp);
theParticleChange.AddSecondary(pnew, secID);
}
delete products;
}
@@ -229,7 +258,7 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
auto aRec = new G4DynamicParticle(theRecoil, lv);
theParticleChange.AddSecondary(aRec, secID);
} else {
// recoil is an unstable fragment
// recoil is a fragment, which may be unstable
G4Fragment frag(A, Z, lv);
auto products = fHandler->BreakItUp(frag);
for (auto & prod : *products) {
@@ -243,43 +272,50 @@ G4HadFinalState* G4ChargeExchange::ApplyYourself(
}
G4double G4ChargeExchange::SampleT(const G4ParticleDefinition*,
const G4int A, const G4double tmax) const
const G4int A, const G4double ltmax) const
{
const G4double GeV2 = CLHEP::GeV*CLHEP::GeV;
const G4double numLimit = 18.;
G4double tmax = ltmax/GeV2;
if (verboseLevel > 1) {
G4cout << "G4ChargeExchange::SampleT tmax(GeV^2)=" << tmax << G4endl;
}
G4double aa, bb, cc, dd;
G4Pow* g4pow = G4Pow::GetInstance();
if (A <= 62.) {
aa = g4pow->powZ(A, 1.63);
bb = 14.5*g4pow->powZ(A, 0.66);
cc = 1.4*g4pow->powZ(A, 0.33);
G4double a13 = g4pow->Z13(A);
if (A <= 62) {
aa = (A*A);
bb = 14.5*a13*a13;
cc = 1.4*a13;
dd = 10.;
} else {
aa = g4pow->powZ(A, 1.33);
bb = 60.*g4pow->powZ(A, 0.33);
bb = 60.*a13;
cc = 0.4*g4pow->powZ(A, 0.40);
dd = 10.;
}
G4double x1 = (1.0 - G4Exp(-tmax*bb))*aa/bb;
G4double x2 = (1.0 - G4Exp(-tmax*dd))*cc/dd;
G4double t;
G4double y = bb;
if(G4UniformRand()*(x1 + x2) < x2) y = dd;
for (G4int i=0; i<maxN; ++i) {
t = -G4Log(G4UniformRand())/y;
if (t <= tmax) { return t; }
G4double q1 = 1.0 - G4Exp(-std::min(bb*tmax, numLimit));
G4double q2 = 1.0 - G4Exp(-std::min(dd*tmax, numLimit));
G4double s1 = q1*aa;
G4double s2 = q2*cc;
if ((s1 + s2)*G4UniformRand() < s2) {
q1 = q2;
bb = dd;
}
return 0.0;
return -GeV2*G4Log(1.0 - G4UniformRand()*q1)/bb;
}
G4bool G4ChargeExchange::SampleMass(G4double& M, const G4double G, const G4double elim)
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;
G4double e1 = std::max(M - 4*G, elim);
G4double e2 = M + 4*G - e1;
if (e2 <= 0.0) { return false; }
const G4double M2 = M*M;
const G4double MG2 = M2*G*G;
G4double M2 = M*M;
G4double MG2 = M2*G*G;
// sampling Breit-Wigner function
for (G4int i=0; i<maxN; ++i) {
@@ -143,8 +143,10 @@ G4HadFinalState* G4HadronElastic::ApplyYourself(
G4double phi = G4UniformRand()*CLHEP::twopi;
G4double cost = 1. - 2.0*t/pLocalTmax;
if (cost > 1.0) { cost = 1.0; }
else if(cost < -1.0) { cost = -1.0; }
// if cos(theta) negative, there is a numerical problem
// instead of making scattering backward, make in this case
// no scattering
if (std::abs(cost) > 1.0) { cost = 1.0; }
G4double sint = std::sqrt((1.0-cost)*(1.0+cost));
@@ -209,7 +211,7 @@ G4HadronElastic::SampleInvariantT(const G4ParticleDefinition* part,
G4double mom, G4int, G4int A)
{
const G4double plabLowLimit = 400.0*CLHEP::MeV;
const G4double GeV2 = GeV*GeV;
const G4double GeV2 = CLHEP::GeV*CLHEP::GeV;
const G4double z07in13 = std::pow(0.7, 0.3333333333);
const G4double numLimit = 18.;
@@ -263,7 +265,7 @@ G4HadronElastic::SampleInvariantT(const G4ParticleDefinition* part,
G4double q2 = 1.0 - G4Exp(-std::min(dd*tmax, numLimit));
G4double s1 = q1*aa;
G4double s2 = q2*cc;
if((s1 + s2)*G4UniformRand() < s2) {
if ((s1 + s2)*G4UniformRand() < s2) {
q1 = q2;
bb = dd;
}