Import Geant4 11.4.0 source tree

This commit is contained in:
Gabriele Cosmo
2025-12-05 08:54:02 +01:00
parent a499fb82e9
commit b4a16de652
6484 changed files with 232674 additions and 221097 deletions
@@ -6,6 +6,27 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-11-24 Vladimir Ivanchenko (hadr-cross-V11-03-09)
- G4EMDissociationCrossSection - fixed compilation warning
## 2025-11-06 Vladimir Ivanchenko (hadr-cross-V11-03-08)
- G4ChargeExchangeXS - fixed units inside SampleTforPion(..) method
- G4NeutronInelasticXS, G4NeutronElasticXS, G4NeutronCaptureXS - added extra
flag to enable/disable reading and usage of precise data in resonance
region, which will allow to reduce RSS memory for simple applications,
for applications required higher precision of neutron transport the
flag should be defined via G4HadronicParameters::SetUseRFilesForXS(true).
## 2025-10-27 Vladimir Ivanchenko (hadr-cross-V11-03-07)
- G4ChargeExchangeXS - added extra method SampleTforPion(..), which is based on
the V. Lyubovitsky parameterisation for different reaction channels.
## 2025-09-30 Vladimir Ivanchenko (hadr-cross-V11-03-06)
- G4NeutronInelasticXS, G4NeutronElasticXS, G4NeutronCaptureXS - split data
tables on two parts: low-energy for neutron resonance region and high
energy above this region. This allows increase accuracy of neutron cross
sections for non HP (for example, HEP) applications.
## 2025-05-24 Vladimir Ivanchenko (hadr-cross-V11-03-05)
- G4CrossSectionFactory, G4CrossSectionFactoryRegistry, G4CrossSectionFactory,
G4ElectroNuclearCrossSection, G4ChipsAntiBaryonElasticXS - fixed memory leak
@@ -82,32 +82,36 @@ public:
SampleSecondaryType(const G4ParticleDefinition*, const G4Material*,
G4int Z, G4int A, G4double etot);
G4double GetPartialPionXS(G4int idx);
G4double GetPionTFactor(G4int idx, const G4ParticleDefinition* part,
G4double pEtot);
G4double GetPartialPionXS(G4int idx) const;
void SetEnergyLimit(G4double val) { fEnergyLimit = val; };
void SetCrossSectionFactor(G4double val) { fFactor = val; };
G4double GetCrossSectionFactor() const { return fFactor; };
G4bool isPion() const { return findex >= 0; };
G4double SampleTforPion(const G4double etot,
const G4double tmax) const;
G4ChargeExchangeXS & operator=(const G4ChargeExchangeXS &right) = delete;
G4ChargeExchangeXS(const G4ChargeExchangeXS&) = delete;
private:
G4double GetCrossSection(const G4ParticleDefinition*, const G4Material*,
G4int Z, G4double etot);
G4double ComputeDeuteronFraction(const G4Material*);
G4double ComputeDeuteronFraction(const G4Material*) const;
G4Pow* g4calc;
G4int findex{-1};
const G4ParticleDefinition* fPionSecPD[5];
G4double fXSecPion[5] = {0.0, 0.0, 0.0, 0.0, 0.0};
G4double fEnergyLimit{0.0};
G4double fFactor{1.0};
G4double fMassPi;
};
#endif
@@ -114,6 +114,8 @@ private:
inline const G4PhysicsVector* GetPhysicsVector(G4int Z);
inline const G4PhysicsVector* GetPhysicsVectorR(G4int Z);
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
G4double emax;
@@ -123,8 +125,10 @@ private:
std::vector<G4double> temp;
G4bool isInitializer{false};
G4bool fRfilesEnabled{false};
static G4ElementData* data;
static G4ElementData* dataR;
static G4String gDataDirectory;
};
@@ -132,11 +136,22 @@ inline
const G4PhysicsVector* G4NeutronCaptureXS::GetPhysicsVector(G4int Z)
{
const G4PhysicsVector* pv = data->GetElementData(Z);
if(pv == nullptr) {
if (pv == nullptr) {
InitialiseOnFly(Z);
pv = data->GetElementData(Z);
}
return pv;
}
inline
const G4PhysicsVector* G4NeutronCaptureXS::GetPhysicsVectorR(G4int Z)
{
const G4PhysicsVector* pv = dataR->GetElementData(Z);
if (pv == nullptr) {
InitialiseOnFly(Z);
pv = dataR->GetElementData(Z);
}
return pv;
}
#endif
@@ -110,15 +110,19 @@ private:
inline const G4PhysicsVector* GetPhysicsVector(G4int Z);
inline const G4PhysicsVector* GetPhysicsVectorR(G4int Z);
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
G4VComponentCrossSection* ggXsection{nullptr};
const G4ParticleDefinition* neutron;
G4bool isInitializer{false};
G4bool fRfilesEnabled{false};
static const G4int MAXZEL = 93;
static G4ElementData* data;
static G4ElementData* dataR;
static G4double coeff[MAXZEL];
static G4String gDataDirectory;
};
@@ -134,4 +138,15 @@ G4PhysicsVector* G4NeutronElasticXS::GetPhysicsVector(G4int Z)
return pv;
}
inline
const G4PhysicsVector* G4NeutronElasticXS::GetPhysicsVectorR(G4int Z)
{
const G4PhysicsVector* pv = dataR->GetElementData(Z);
if (pv == nullptr) {
InitialiseOnFly(Z);
pv = dataR->GetElementData(Z);
}
return pv;
}
#endif
@@ -112,6 +112,8 @@ private:
inline const G4PhysicsVector* GetPhysicsVector(G4int Z);
inline const G4PhysicsVector* GetPhysicsVectorR(G4int Z);
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
G4VComponentCrossSection* ggXsection = nullptr;
@@ -120,14 +122,15 @@ private:
std::vector<G4double> temp;
G4double elimit;
G4double lowElimit;
G4double loglowElimit;
G4bool isInitializer{false};
G4bool fRfilesEnabled{false};
static const G4int MAXZINEL = 93;
static G4ElementData* data;
static G4ElementData* dataR;
static G4double coeff[MAXZINEL];
static G4double lowcoeff[MAXZINEL];
static G4String gDataDirectory;
@@ -144,4 +147,15 @@ const G4PhysicsVector* G4NeutronInelasticXS::GetPhysicsVector(G4int Z)
return pv;
}
inline
const G4PhysicsVector* G4NeutronInelasticXS::GetPhysicsVectorR(G4int Z)
{
const G4PhysicsVector* pv = dataR->GetElementData(Z);
if (pv == nullptr) {
InitialiseOnFly(Z);
pv = dataR->GetElementData(Z);
}
return pv;
}
#endif
@@ -44,16 +44,18 @@
#include "G4Pow.hh"
#include "G4PionZero.hh"
#include "G4PionPlus.hh"
#include "G4Eta.hh"
#include "G4KaonZeroLong.hh"
#include "G4KaonZeroShort.hh"
#include "G4KaonPlus.hh"
#include "G4KaonMinus.hh"
#include "G4ParticleTable.hh"
#include "G4ThreeVector.hh"
namespace {
// V. Lyubovitsky parameterisation
const G4double piA[5] = {122., 78.8, 59.4, 24.0, 213.5}; // A
const G4double piA[5] = {122., 78.8, 59.4, 24.0, 213.5};// A
const G4double pAP[5] = {1.23, 1.53, 1.35, 0.94, 0.94}; // 2 - 2alphaP
const G4double pC0[5] = {12.7, 6.0, 6.84, 6.5, 8.0}; // c0
const G4double pC1[5] = {1.57, 1.6, 1.7, 1.23, 2.6}; // c1
@@ -63,8 +65,9 @@ namespace {
// parameterisation of intranuclear absorption
const G4double beta_prime_pi = 0.0036;
// For unit conversion
const G4double inv1e7 = 0.1/(CLHEP::GeV*CLHEP::GeV);
// For unit conversion
const G4double GeV2 = (CLHEP::GeV*CLHEP::GeV);
const G4double inv1e7 = 0.1/GeV2;
const G4double fact = 1e-30*CLHEP::cm2;
const G4double pfact = 0.1/CLHEP::GeV;
const G4double kfact = 56.3*fact;
@@ -76,6 +79,7 @@ G4ChargeExchangeXS::G4ChargeExchangeXS()
if (verboseLevel > 1) {
G4cout << "G4ChargeExchangeXS::G4ChargeExchangeXS" << G4endl;
}
fMassPi = G4PionPlus::PionPlus()->GetPDGMass();
g4calc = G4Pow::GetInstance();
auto table = G4ParticleTable::GetParticleTable();
const G4String nam[5] = {"pi0", "eta", "eta_prime", "omega", "f2(1270)"};
@@ -123,6 +127,7 @@ G4double G4ChargeExchangeXS::GetCrossSection(const G4ParticleDefinition* part,
G4double tM = CLHEP::proton_mass_c2;
G4double pM = part->GetPDGMass();
G4double lorentz_s = tM*tM + 2*tM*pEtot + pM*pM;
if (lorentz_s <= (tM + pM)*(tM + pM)) { return result; }
const G4int Z = std::min(ZZ, ZMAXNUCLEARDATA);
@@ -131,11 +136,9 @@ G4double G4ChargeExchangeXS::GetCrossSection(const G4ParticleDefinition* part,
if (verboseLevel > 1) {
G4cout << "### G4ChargeExchangeXS: " << part->GetParticleName()
<< " Z=" << Z << " A=" << A << " Etot(GeV)=" << pEtot/CLHEP::GeV
<< " s(GeV^2)=" << lorentz_s/(CLHEP::GeV*CLHEP::GeV) << G4endl;
<< " s(GeV^2)=" << lorentz_s/GeV2 << G4endl;
}
// The approximation of Glauber-Gribov formula -> extend it from interaction with
// proton to nuclei Z^(2/3). The factor g4calc->powA(A,-beta_prime_pi*G4Log(A))
// takes into account absorption of mesons within the nucleus
@@ -218,19 +221,21 @@ G4ChargeExchangeXS::SampleSecondaryType(const G4ParticleDefinition* part,
const G4Material* mat,
G4int Z, G4int A, G4double etot)
{
// index of pion partial x-section
findex = -1;
// recompute x-section for the element in complex material
GetCrossSection(part, mat, Z, etot);
const G4ParticleDefinition* pd = nullptr;
G4int pdg = std::abs(part->GetPDGEncoding());
G4cout << pdg << G4endl;
// pi- + p / pi+ + n
if (pdg == 211) {
pd = fPionSecPD[0];
G4double x = fXSecPion[4]*G4UniformRand();
for (G4int i=0; i<5; ++i) {
if (x <= fXSecPion[i]) {
pd = fPionSecPD[i];
for (findex = 0; findex < 5; ++findex) {
if (x <= fXSecPion[findex]) {
pd = fPionSecPD[findex];
break;
}
}
@@ -257,12 +262,39 @@ G4ChargeExchangeXS::SampleSecondaryType(const G4ParticleDefinition* part,
pd = G4KaonPlus::KaonPlus();
}
}
if (verboseLevel > 1) {
G4cout << "G4ChargeExchangeXS::SampleSecondaryType for "
<< pd->GetParticleName() << " findex=" << findex
<< G4endl;
}
return pd;
}
G4double G4ChargeExchangeXS::SampleTforPion(const G4double etot,
const G4double ltmax) const
{
G4double tmax = ltmax/GeV2;
G4double tM = CLHEP::proton_mass_c2;
G4double logX = G4Log((tM*tM + 2*tM*etot + fMassPi*fMassPi)*inv1e7);
G4double gl = pG0[findex] + pG1[findex]*logX;
G4double cl = pC0[findex] + pC1[findex]*logX;
G4double gc = gl*cl;
G4double t{0};
G4double sigmaMax = (gc > 0.0) ? gl*G4Exp(-(gl - 1.0)/gl) : 1.0;
for (G4int i = 0; i < 100000; ++i) {
t = tmax*G4UniformRand();
G4double sigma = (1.0 + gc*t)*G4Exp(-cl*t);
if (G4UniformRand()*sigmaMax <= sigma) {
return t*GeV2;
}
}
return 0.0;
}
G4double
G4ChargeExchangeXS::ComputeDeuteronFraction(const G4Material* mat)
G4ChargeExchangeXS::ComputeDeuteronFraction(const G4Material* mat) const
{
for (auto const & elm : *mat->GetElementVector()) {
if (1 == elm->GetZasInt()) {
@@ -279,7 +311,7 @@ G4ChargeExchangeXS::ComputeDeuteronFraction(const G4Material* mat)
return 0.0;
}
G4double G4ChargeExchangeXS::GetPartialPionXS(G4int idx)
G4double G4ChargeExchangeXS::GetPartialPionXS(G4int idx) const
{
G4double res = 0.0;
if (0 == idx) { res = fXSecPion[0]; }
@@ -288,16 +320,3 @@ G4double G4ChargeExchangeXS::GetPartialPionXS(G4int idx)
}
return res;
}
G4double G4ChargeExchangeXS::GetPionTFactor(G4int idx,
const G4ParticleDefinition* p,
G4double pEtot)
{
if (idx < 0 || idx > 4) { return 0.0; }
G4double tM = CLHEP::proton_mass_c2;
G4double pM = p->GetPDGMass();
G4double logX = G4Log((tM*tM + 2*tM*pEtot + pM*pM)*inv1e7);
G4double xg = std::max(pG0[idx] + pG1[idx]*logX, -1.0);
G4double xc = std::max(pC0[idx] + pC1[idx]*logX, 0.0);
return xc*xg;
}
@@ -128,7 +128,7 @@ G4double G4EMDissociationCrossSection::GetElementCrossSection
G4double AP = definitionP->GetBaryonNumber();
G4double ZP = definitionP->GetPDGCharge();
G4double b = theDynamicParticle->GetBeta();
if (b <= 0.0 && b >= 1.0) { return 0.0; }
if (b <= 0.0) { return 0.0; }
G4double AT = G4NistManager::Instance()->GetAtomicMassAmu(Z);
G4double ZT = (G4double)Z;
@@ -53,6 +53,7 @@
#include "G4AutoLock.hh"
G4ElementData* G4NeutronCaptureXS::data = nullptr;
G4ElementData* G4NeutronCaptureXS::dataR = nullptr;
G4String G4NeutronCaptureXS::gDataDirectory = "";
static std::once_flag applyOnce;
@@ -76,6 +77,8 @@ G4NeutronCaptureXS::G4NeutronCaptureXS()
if (nullptr == data) {
data = new G4ElementData(MAXZCAPTURE+1);
data->SetName("nCapture");
dataR = new G4ElementData(MAXZCAPTURE+1);
dataR->SetName("nRCapture");
FindDirectoryPath();
}
}
@@ -141,15 +144,31 @@ G4NeutronCaptureXS::ElementCrossSection(G4double eKin, G4double logE, G4int ZZ)
logEkin = logElimit;
}
auto pv = GetPhysicsVector(Z);
const G4double e0 = pv->Energy(0);
G4double xs = (ekin >= e0) ? pv->LogVectorValue(ekin, logEkin)
: (*pv)[0]*std::sqrt(e0/ekin);
G4double xs;
G4bool done{false};
// data from the resonance region
if (fRfilesEnabled) {
auto pv = GetPhysicsVectorR(Z);
if (nullptr != pv && ekin < cap_max_r_e[Z]) {
const G4double e0 = pv->Energy(0);
xs = (ekin >= e0) ? pv->LogVectorValue(ekin, logEkin)
: (*pv)[0]*std::sqrt(e0/ekin);
done = true;
}
}
// data above the resonance region
if (!done) {
auto pv = GetPhysicsVector(Z);
const G4double e0 = pv->Energy(0);
xs = (ekin >= e0) ? pv->LogVectorValue(ekin, logEkin)
: (*pv)[0]*std::sqrt(e0/ekin);
}
#ifdef G4VERBOSE
if (verboseLevel > 1){
G4cout << "Ekin= " << ekin/CLHEP::MeV
<< " ElmXScap(b)= " << xs/CLHEP::barn << G4endl;
G4cout << "Ekin= " << ekin/CLHEP::MeV
<< " ElmXScap(b)= " << xs/CLHEP::barn << G4endl;
}
#endif
return xs;
@@ -190,34 +209,55 @@ G4double G4NeutronCaptureXS::IsoCrossSection(G4double eKin, G4double logE,
logEkin = logElimit;
}
auto pv = GetPhysicsVector(Z);
if (pv == nullptr) { return xs; }
G4bool done{false};
// use isotope x-section if possible
if (data->GetNumberOfComponents(Z) > 0) {
G4PhysicsVector* pviso = data->GetComponentDataByID(Z, A);
if(pviso != nullptr) {
const G4double e0 = pviso->Energy(0);
xs = (ekin >= e0) ? pviso->LogVectorValue(ekin, logEkin)
: (*pviso)[0]*std::sqrt(e0/ekin);
#ifdef G4VERBOSE
if(verboseLevel > 0) {
G4cout << "G4NeutronCaptureXS::IsoXS: Ekin(MeV)= " << ekin/MeV
<< " xs(b)= " << xs/barn
<< " Z= " << Z << " A= " << A << G4endl;
// data from the resonance region
if (fRfilesEnabled) {
auto pv = GetPhysicsVectorR(Z);
if (nullptr != pv && ekin < cap_max_r_e[Z]) {
// use isotope x-section if possible
if (dataR->GetNumberOfComponents(Z) > 0) {
auto pviso = dataR->GetComponentDataByID(Z, A);
if (pviso != nullptr) {
const G4double e0 = pviso->Energy(0);
xs = (ekin >= e0) ? pviso->LogVectorValue(ekin, logEkin)
: (*pviso)[0]*std::sqrt(e0/ekin);
done = true;
}
}
// isotope data are not available or applicable
if (!done) {
const G4double e0 = pv->Energy(0);
xs = (ekin >= e0) ? pv->LogVectorValue(ekin, logEkin)
: (*pv)[0]*std::sqrt(e0/ekin);
done = true;
}
#endif
return xs;
}
}
// isotope data are not available or applicable
const G4double e0 = pv->Energy(0);
xs = (ekin >= e0) ? pv->LogVectorValue(ekin, logEkin)
: (*pv)[0]*std::sqrt(e0/ekin);
// data above the resonance region
if (!done) {
auto pv = GetPhysicsVector(Z);
// use isotope x-section if possible
if (data->GetNumberOfComponents(Z) > 0) {
auto pviso = data->GetComponentDataByID(Z, A);
if (pviso != nullptr) {
const G4double e0 = pviso->Energy(0);
xs = (ekin >= e0) ? pviso->LogVectorValue(ekin, logEkin)
: (*pviso)[0]*std::sqrt(e0/ekin);
done = true;
}
}
// isotope data are not available or applicable
if (!done) {
const G4double e0 = pv->Energy(0);
xs = (ekin >= e0) ? pv->LogVectorValue(ekin, logEkin)
: (*pv)[0]*std::sqrt(e0/ekin);
}
}
#ifdef G4VERBOSE
if (verboseLevel > 0) {
G4cout << "G4NeutronCaptureXS::IsoXS: Ekin(MeV)= " << ekin/MeV
<< " xs(b)= " << xs/barn
<< " xs(b)= " << xs/CLHEP::barn
<< " Z= " << Z << " A= " << A << " no iso XS" << G4endl;
}
#endif
@@ -247,7 +287,7 @@ G4NeutronCaptureXS::SelectIsotope(const G4Element* anElement,
if (Z > MAXZCAPTURE || 0 == data->GetNumberOfComponents(Z)) {
for (j = 0; j<nIso; ++j) {
sum += abundVector[j];
if(q <= sum) {
if (q <= sum) {
iso = anElement->GetIsotope(j);
break;
}
@@ -288,6 +328,8 @@ G4NeutronCaptureXS::BuildPhysicsTable(const G4ParticleDefinition& p)
return;
}
fRfilesEnabled = G4HadronicParameters::Instance()->UseRFilesForXS();
// it is possible re-initialisation for the second run
const G4ElementTable* table = G4Element::GetElementTable();
@@ -318,7 +360,7 @@ const G4String& G4NeutronCaptureXS::FindDirectoryPath()
// build the complete string identifying the file with the data set
if(gDataDirectory.empty()) {
std::ostringstream ost;
ost << G4HadronicParameters::Instance()->GetDirPARTICLEXS() << "/neutron/cap";
ost << G4HadronicParameters::Instance()->GetDirPARTICLEXS() << "/neutron/";
gDataDirectory = ost.str();
}
return gDataDirectory;
@@ -337,16 +379,24 @@ void G4NeutronCaptureXS::Initialise(G4int Z)
// upload element data
std::ostringstream ost;
ost << FindDirectoryPath() << Z ;
ost << FindDirectoryPath() << "cap" << Z;
G4PhysicsVector* v = RetrieveVector(ost, true);
data->InitialiseForElement(Z, v);
G4PhysicsVector* vr = nullptr;
if (fRfilesEnabled) {
std::ostringstream ostr;
ostr << FindDirectoryPath() << "Rcap" << Z;
vr = RetrieveVector(ostr, false);
dataR->InitialiseForElement(Z, vr);
}
// upload isotope data
G4bool noComp = true;
G4bool noCompR = true;
if (amin[Z] < amax[Z]) {
for(G4int A=amin[Z]; A<=amax[Z]; ++A) {
for (G4int A=amin[Z]; A<=amax[Z]; ++A) {
std::ostringstream ost1;
ost1 << gDataDirectory << Z << "_" << A;
ost1 << gDataDirectory << "cap" << Z << "_" << A;
G4PhysicsVector* v1 = RetrieveVector(ost1, false);
if (nullptr != v1) {
if (noComp) {
@@ -356,10 +406,24 @@ void G4NeutronCaptureXS::Initialise(G4int Z)
}
data->AddComponent(Z, A, v1);
}
if (nullptr != vr) {
std::ostringstream ost2;
ost2 << gDataDirectory << "Rcap" << Z << "_" << A;
G4PhysicsVector* v2 = RetrieveVector(ost2, false);
if (nullptr != v2) {
if (noCompR) {
G4int nmax = amax[Z] - A + 1;
dataR->InitialiseForComponent(Z, nmax);
noCompR = false;
}
dataR->AddComponent(Z, A, v2);
}
}
}
}
// no components case
if (noComp) { data->InitialiseForComponent(Z, 0); }
if (noCompR && nullptr != vr) { dataR->InitialiseForComponent(Z, 0); }
}
G4PhysicsVector*
@@ -54,6 +54,7 @@
#include <sstream>
G4ElementData* G4NeutronElasticXS::data = nullptr;
G4ElementData* G4NeutronElasticXS::dataR = nullptr;
G4double G4NeutronElasticXS::coeff[] = {1.0};
G4String G4NeutronElasticXS::gDataDirectory = "";
@@ -80,6 +81,8 @@ G4NeutronElasticXS::G4NeutronElasticXS()
if (nullptr == data) {
data = new G4ElementData(MAXZEL);
data->SetName("nElastic");
dataR = new G4ElementData(MAXZEL);
dataR->SetName("nRElastic");
FindDirectoryPath();
}
}
@@ -128,14 +131,27 @@ G4double
G4NeutronElasticXS::ElementCrossSection(G4double ekin, G4double loge, G4int ZZ)
{
G4int Z = std::min(ZZ, MAXZEL-1);
auto pv = GetPhysicsVector(Z);
G4double xs = (ekin <= pv->GetMaxEnergy()) ? pv->LogVectorValue(ekin, loge)
: coeff[Z]*ggXsection->GetElasticElementCrossSection(neutron, ekin,
Z, aeff[Z]);
G4double xs;
G4bool done{false};
// data from the resonance region
if (fRfilesEnabled) {
auto pv = GetPhysicsVectorR(Z);
if (nullptr != pv && ekin < el_max_r_e[Z]) {
xs = pv->LogVectorValue(ekin, loge);
done = true;
}
}
// data above the resonance region
if (!done) {
auto pv = GetPhysicsVector(Z);
xs = (ekin <= pv->GetMaxEnergy()) ? pv->LogVectorValue(ekin, loge)
: coeff[Z]*ggXsection->GetElasticElementCrossSection(neutron, ekin,
Z, aeff[Z]);
}
#ifdef G4VERBOSE
if(verboseLevel > 1) {
if (verboseLevel > 1) {
G4cout << "Z= " << Z << " Ekin(MeV)= " << ekin/CLHEP::MeV
<< ", nElmXSel(b)= " << xs/CLHEP::barn
<< G4endl;
@@ -205,6 +221,9 @@ G4NeutronElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
FatalException, ed, "");
return;
}
fRfilesEnabled = G4HadronicParameters::Instance()->UseRFilesForXS();
// initialise static tables only once
std::call_once(applyOnce, [this]() { isInitializer = true; });
@@ -226,7 +245,7 @@ const G4String& G4NeutronElasticXS::FindDirectoryPath()
// build the complete string identifying the file with the data set
if (gDataDirectory.empty()) {
std::ostringstream ost;
ost << G4HadronicParameters::Instance()->GetDirPARTICLEXS() << "/neutron/el";
ost << G4HadronicParameters::Instance()->GetDirPARTICLEXS() << "/neutron/";
gDataDirectory = ost.str();
}
return gDataDirectory;
@@ -245,10 +264,18 @@ void G4NeutronElasticXS::Initialise(G4int Z)
// upload element data
std::ostringstream ost;
ost << FindDirectoryPath() << Z;
ost << FindDirectoryPath() << "el" << Z;
G4PhysicsVector* v = RetrieveVector(ost, true);
data->InitialiseForElement(Z, v);
G4PhysicsVector* vr = nullptr;
if (fRfilesEnabled) {
std::ostringstream ostr;
ostr << FindDirectoryPath() << "Rel" << Z;
vr = RetrieveVector(ostr, false);
dataR->InitialiseForElement(Z, vr);
}
// smooth transition
G4double sig1 = (*v)[v->GetVectorLength()-1];
G4double ehigh = v->GetMaxEnergy();
@@ -57,6 +57,7 @@
G4double G4NeutronInelasticXS::coeff[] = {1.0};
G4double G4NeutronInelasticXS::lowcoeff[] = {1.0};
G4ElementData* G4NeutronInelasticXS::data = nullptr;
G4ElementData* G4NeutronInelasticXS::dataR = nullptr;
G4String G4NeutronInelasticXS::gDataDirectory = "";
static std::once_flag applyOnce;
@@ -69,7 +70,6 @@ namespace
G4NeutronInelasticXS::G4NeutronInelasticXS()
: G4VCrossSectionDataSet(Default_Name()),
neutron(G4Neutron::Neutron()),
elimit(20*CLHEP::MeV),
lowElimit(1.0e-7*CLHEP::eV)
{
verboseLevel = 0;
@@ -86,6 +86,8 @@ G4NeutronInelasticXS::G4NeutronInelasticXS()
if (nullptr == data) {
data = new G4ElementData(MAXZINEL);
data->SetName("nInelastic");
dataR = new G4ElementData(MAXZINEL);
dataR->SetName("nRInelastic");
FindDirectoryPath();
for (G4int Z=1; Z<MAXZINEL; ++Z) { Initialise(Z); }
}
@@ -140,25 +142,33 @@ G4NeutronInelasticXS::ElementCrossSection(G4double eKin, G4double logE, G4int ZZ
G4int Z = std::min(ZZ, MAXZINEL-1);
G4double ekin = eKin;
G4double loge = logE;
G4double xs;
G4double xs{0.0};
G4bool done{false};
// very low energy limit
if (ekin < lowElimit) {
ekin = lowElimit;
loge = loglowElimit;
}
// pv should exist
auto pv = GetPhysicsVector(Z);
const G4double e0 = pv->Energy(0);
if (ekin <= e0) {
xs = (*pv)[0];
if (xs > 0.0) { xs *= std::sqrt(e0/ekin); }
} else if (ekin <= pv->GetMaxEnergy()) {
xs = pv->LogVectorValue(ekin, loge);
} else {
xs = coeff[Z]*ggXsection->GetInelasticElementCrossSection(neutron, ekin,
Z, aeff[Z]);
// data from the resonance region
if (fRfilesEnabled) {
auto pv = GetPhysicsVectorR(Z);
if (nullptr != pv && ekin < inel_max_r_e[Z]) {
xs = pv->LogVectorValue(ekin, loge);
done = true;
}
}
// data above the resonance region pv should always defined
if (!done) {
auto pv = GetPhysicsVector(Z);
if (ekin <= pv->GetMaxEnergy()) {
xs = pv->LogVectorValue(ekin, loge);
}
else {
xs = coeff[Z]*ggXsection->GetInelasticElementCrossSection(neutron, ekin,
Z, aeff[Z]);
}
}
#ifdef G4VERBOSE
@@ -193,60 +203,59 @@ G4NeutronInelasticXS::GetIsoCrossSection(const G4DynamicParticle* aParticle,
}
G4double
G4NeutronInelasticXS::IsoCrossSection(G4double eKin, G4double logE,
G4NeutronInelasticXS::IsoCrossSection(G4double ekin, G4double loge,
G4int ZZ, G4int A)
{
G4double xs;
G4double xs{0.0};
G4int Z = std::min(ZZ, MAXZINEL-1);
G4double ekin = eKin;
G4double loge = logE;
G4bool done{false};
// Check initialisation
GetPhysicsVector(Z);
#ifdef G4VERBOSE
if (verboseLevel > 2) {
G4cout << "G4NeutronInelasticXS::IsoCrossSection Z= "
<< Z << " A= " << A << G4endl;
G4cout << " Amin= " << amin[Z] << " Amax= " << amax[Z]
<< " E(MeV)= " << ekin << " Ncomp="
<< data->GetNumberOfComponents(Z) << G4endl;
// data from the resonance region
if (fRfilesEnabled) {
auto pv = GetPhysicsVectorR(Z);
if (nullptr != pv && ekin < inel_max_r_e[Z]) {
// use isotope x-section if possible
if (dataR->GetNumberOfComponents(Z) > 0) {
auto pviso = dataR->GetComponentDataByID(Z, A);
if (pviso != nullptr) {
xs = pviso->LogVectorValue(ekin, loge);
done = true;
}
}
// isotope data are not available or applicable
if (!done) {
xs = pv->LogVectorValue(ekin, loge);
done = true;
}
}
}
#endif
// use isotope cross section if applicable
if (ekin <= elimit && data->GetNumberOfComponents(Z) > 0) {
auto pviso = data->GetComponentDataByID(Z, A);
if (nullptr != pviso) {
// very low energy limit
if (ekin < lowElimit) {
ekin = lowElimit;
loge = loglowElimit;
// data above the resonance region
if (!done) {
auto pv = GetPhysicsVector(Z);
// use isotope x-section if possible
if (data->GetNumberOfComponents(Z) > 0) {
auto pviso = data->GetComponentDataByID(Z, A);
if (pviso != nullptr && ekin <= pviso->GetMaxEnergy()) {
xs = pviso->LogVectorValue(ekin, loge);
done = true;
}
const G4double e0 = pviso->Energy(0);
if (ekin > e0) {
xs = pviso->LogVectorValue(ekin, loge);
} else {
xs = (*pviso)[0];
if (xs > 0.0) { xs *= std::sqrt(e0/ekin); }
}
// isotope data are not available or applicable
// use element x-section
if (!done) {
if (ekin <= pv->GetMaxEnergy()) {
xs = pv->LogVectorValue(ekin, loge);
}
#ifdef G4VERBOSE
if(verboseLevel > 1) {
G4cout << "G4NeutronInelasticXS::IsoXS: Ekin(MeV)= "
<< ekin/CLHEP::MeV
<< " xs(b)= " << xs/CLHEP::barn
<< " Z= " << Z << " A= " << A << G4endl;
else {
xs = coeff[Z]*
ggXsection->GetInelasticElementCrossSection(neutron, ekin,
Z, aeff[Z]);
}
#endif
return xs;
}
}
// use element x-section
xs = ElementCrossSection(ekin, loge, Z)*A/aeff[Z];
#ifdef G4VERBOSE
if(verboseLevel > 1) {
if (verboseLevel > 1) {
G4cout << "G4NeutronInelasticXS::IsoXS: Z= " << Z << " A= " << A
<< " Ekin(MeV)= " << ekin/CLHEP::MeV
<< ", ElmXS(b)= " << xs/CLHEP::barn << G4endl;
@@ -289,7 +298,7 @@ const G4Isotope* G4NeutronInelasticXS::SelectIsotope(
for (j=0; j<nIso; ++j) {
sum += abundVector[j]*IsoCrossSection(kinEnergy, logE, Z,
anElement->GetIsotope((G4int)j)->GetN());
anElement->GetIsotope((G4int)j)->GetN());
temp[j] = sum;
}
sum *= q;
@@ -317,6 +326,9 @@ G4NeutronInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
FatalException, ed, "");
return;
}
fRfilesEnabled = G4HadronicParameters::Instance()->UseRFilesForXS();
// it is possible re-initialisation for the new run
const G4ElementTable* table = G4Element::GetElementTable();
@@ -347,7 +359,7 @@ const G4String& G4NeutronInelasticXS::FindDirectoryPath()
// build the complete string identifying the file with the data set
if (gDataDirectory.empty()) {
std::ostringstream ost;
ost << G4HadronicParameters::Instance()->GetDirPARTICLEXS() << "/neutron/inel";
ost << G4HadronicParameters::Instance()->GetDirPARTICLEXS() << "/neutron/";
gDataDirectory = ost.str();
}
return gDataDirectory;
@@ -366,21 +378,26 @@ void G4NeutronInelasticXS::Initialise(G4int Z)
// upload element data
std::ostringstream ost;
ost << FindDirectoryPath() << Z;
ost << FindDirectoryPath() << "inel" << Z;
G4PhysicsVector* v = RetrieveVector(ost, true);
data->InitialiseForElement(Z, v);
if (verboseLevel > 1) {
G4cout << "G4NeutronInelasticXS::Initialise for Z= " << Z
<< " A= " << aeff[Z] << " Amin= " << amin[Z]
<< " Amax= " << amax[Z] << G4endl;
G4PhysicsVector* vr = nullptr;
if (fRfilesEnabled) {
std::ostringstream ostr;
ostr << FindDirectoryPath() << "Rinel" << Z;
vr = RetrieveVector(ostr, false);
dataR->InitialiseForElement(Z, vr);
}
// upload isotope data
G4bool noComp = true;
G4bool noCompR = true;
if (amin[Z] < amax[Z]) {
for (G4int A=amin[Z]; A<=amax[Z]; ++A) {
std::ostringstream ost1;
ost1 << gDataDirectory << Z << "_" << A;
ost1 << gDataDirectory << "inel" << Z << "_" << A;
G4PhysicsVector* v1 = RetrieveVector(ost1, false);
if (nullptr != v1) {
if (noComp) {
@@ -390,10 +407,24 @@ void G4NeutronInelasticXS::Initialise(G4int Z)
}
data->AddComponent(Z, A, v1);
}
if (nullptr != vr) {
std::ostringstream ost2;
ost2 << gDataDirectory << "Rinel" << Z << "_" << A;
G4PhysicsVector* v2 = RetrieveVector(ost2, false);
if (nullptr != v2) {
if (noCompR) {
G4int nmax = amax[Z] - A + 1;
dataR->InitialiseForComponent(Z, nmax);
noCompR = false;
}
dataR->AddComponent(Z, A, v2);
}
}
}
}
// no components case
if (noComp) { data->InitialiseForComponent(Z, 0); }
if (noCompR) { dataR->InitialiseForComponent(Z, 0); }
// smooth transition
G4double sig1 = (*v)[v->GetVectorLength()-1];
@@ -409,7 +440,7 @@ G4NeutronInelasticXS::RetrieveVector(std::ostringstream& ost, G4bool warn)
G4PhysicsLogVector* v = nullptr;
std::ifstream filein(ost.str().c_str());
if (!filein.is_open()) {
if(warn) {
if (warn) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not opened!";
@@ -417,13 +448,13 @@ G4NeutronInelasticXS::RetrieveVector(std::ostringstream& ost, G4bool warn)
FatalException, ed, "Check G4PARTICLEXSDATA");
}
} else {
if(verboseLevel > 1) {
if (verboseLevel > 1) {
G4cout << "File " << ost.str()
<< " is opened by G4NeutronInelasticXS" << G4endl;
}
// retrieve data from DB
v = new G4PhysicsLogVector();
if(!v->Retrieve(filein, true)) {
if (!v->Retrieve(filein, true)) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not retrieved!";