Import Geant4 10.6.0 source tree

This commit is contained in:
Gabriele Cosmo
2019-12-06 15:12:28 +01:00
parent b2a62ae692
commit 5baee230e9
2997 changed files with 141580 additions and 98673 deletions
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
@@ -43,16 +42,18 @@
#include "G4ComponentGGHadronNucleusXsc.hh"
#include "G4NucleonNuclearCrossSection.hh"
#include "G4HadronNucleonXsc.hh"
#include "G4NuclearRadii.hh"
#include "G4Proton.hh"
#include "G4Neutron.hh"
#include "G4NistManager.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
#include "G4NuclearRadii.hh"
#include "G4CrossSectionDataSetRegistry.hh"
G4double G4BGGNucleonElasticXS::theGlauberFac[93] = {0.0};
G4double G4BGGNucleonElasticXS::theCoulombFac[93] = {0.0};
G4double G4BGGNucleonElasticXS::theGlauberFacP[93] = {0.0};
G4double G4BGGNucleonElasticXS::theCoulombFacP[93] = {0.0};
G4double G4BGGNucleonElasticXS::theGlauberFacN[93] = {0.0};
G4double G4BGGNucleonElasticXS::theCoulombFacN[93] = {0.0};
G4int G4BGGNucleonElasticXS::theA[93] = {0};
#ifdef G4MULTITHREADED
@@ -64,13 +65,13 @@ G4BGGNucleonElasticXS::G4BGGNucleonElasticXS(const G4ParticleDefinition* p)
{
verboseLevel = 0;
fGlauberEnergy = 91.*GeV;
fLowEnergy = 0.75*MeV;
fLowEnergy = 14.0*MeV;
fNucleon = nullptr;
fGlauber = nullptr;
fHadron = nullptr;
particle = p;
theProton= G4Proton::Proton();
isProton = (theProton == p) ? true : false;
isProton = (theProton == p);
isMaster = false;
SetForAllAtomsAndEnergies(true);
}
@@ -86,7 +87,7 @@ G4BGGNucleonElasticXS::~G4BGGNucleonElasticXS()
G4bool
G4BGGNucleonElasticXS::IsElementApplicable(const G4DynamicParticle*, G4int,
const G4Material*)
const G4Material*)
{
return true;
}
@@ -94,9 +95,9 @@ G4BGGNucleonElasticXS::IsElementApplicable(const G4DynamicParticle*, G4int,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4BGGNucleonElasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4int Z, G4int,
const G4Element*,
const G4Material*)
G4int Z, G4int,
const G4Element*,
const G4Material*)
{
return (1 == Z);
}
@@ -105,7 +106,7 @@ G4bool G4BGGNucleonElasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4double
G4BGGNucleonElasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4int ZZ, const G4Material*)
G4int ZZ, const G4Material*)
{
// this method should be called only for Z > 1
@@ -116,20 +117,22 @@ G4BGGNucleonElasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
cross = 1.0115*GetIsoCrossSection(dp,1,1);
} else {
if(ekin <= fLowEnergy) {
cross = theCoulombFac[Z]*CoulombFactor(ekin, Z);
cross = (isProton) ? theCoulombFacP[Z] : theCoulombFacN[Z];
cross *= CoulombFactor(ekin, Z);
} else if(ekin > fGlauberEnergy) {
cross = theGlauberFac[Z]*fGlauber->GetElasticGlauberGribov(dp, Z, theA[Z]);
cross = (isProton) ? theGlauberFacP[Z] : theGlauberFacN[Z];
cross *= fGlauber->GetElasticGlauberGribov(dp, Z, theA[Z]);
} else {
cross = fNucleon->GetElasticCrossSection(dp, Z);
}
}
if(verboseLevel > 1) {
G4cout << "G4BGGNucleonElasticXS::GetElementCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
@@ -138,23 +141,23 @@ G4BGGNucleonElasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4double
G4BGGNucleonElasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
{
// this method should be called only for Z = 1
fHadron->HadronNucleonXscNS(dp->GetDefinition(), theProton,
dp->GetKineticEnergy());
dp->GetKineticEnergy());
G4double cross = A*fHadron->GetElasticHadronNucleonXsc();
if(verboseLevel > 1) {
G4cout << "G4BGGNucleonElasticXS::GetIsoCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << A
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << A
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
@@ -163,26 +166,24 @@ G4BGGNucleonElasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
void G4BGGNucleonElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
{
if(fNucleon) { return; }
if(&p == theProton || &p == G4Neutron::Neutron()) {
particle = &p;
isProton = (theProton == particle) ? true : false;
isProton = (theProton == &p);
} else {
G4ExceptionDescription ed;
ed << "This BGG cross section is applicable only to nucleons and not to "
<< p.GetParticleName() << G4endl;
G4Exception("G4BGGNucleonElasticXS::BuildPhysicsTable", "had001",
FatalException, ed);
FatalException, ed);
return;
}
if(!fNucleon) {
fNucleon = (G4NucleonNuclearCrossSection*)G4CrossSectionDataSetRegistry::Instance()->GetCrossSectionDataSet(G4NucleonNuclearCrossSection::Default_Name());
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
}
fNucleon->BuildPhysicsTable(*particle);
fGlauber->BuildPhysicsTable(*particle);
fNucleon = new G4NucleonNuclearCrossSection();
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
fNucleon->BuildPhysicsTable(p);
if(0 == theA[0]) {
#ifdef G4MULTITHREADED
@@ -194,45 +195,63 @@ void G4BGGNucleonElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
}
G4MUTEXUNLOCK(&nucleonElasticXSMutex);
#endif
} else {
return;
}
if(isMaster && 0 == theA[0]) {
theA[0] = 1;
theA[0] = theA[1] = 1;
G4ThreeVector mom(0.0,0.0,1.0);
G4DynamicParticle dp(particle, mom, fGlauberEnergy);
G4DynamicParticle dp(theProton, mom, fGlauberEnergy);
G4NistManager* nist = G4NistManager::Instance();
G4double csup, csdn;
if(verboseLevel > 0) {
G4cout << "### G4BGGNucleonElasticXS::Initialise for "
<< particle->GetParticleName() << G4endl;
<< p.GetParticleName() << G4endl;
}
for(G4int iz=2; iz<93; iz++) {
for(G4int iz=2; iz<93; ++iz) {
G4int A = G4lrint(nist->GetAtomicMassAmu(iz));
theA[iz] = A;
csup = fGlauber->GetElasticGlauberGribov(&dp, iz, A);
csdn = fNucleon->GetElasticCrossSection(&dp, iz);
theGlauberFacP[iz] = csdn/csup;
}
dp.SetDefinition(G4Neutron::Neutron());
for(G4int iz=2; iz<93; ++iz) {
csup = fGlauber->GetElasticGlauberGribov(&dp, iz, theA[iz]);
csdn = fNucleon->GetElasticCrossSection(&dp, iz);
theGlauberFacN[iz] = csdn/csup;
theGlauberFac[iz] = csdn/csup;
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << A
<< " factor= " << theGlauberFac[iz] << G4endl;
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " GFactorP= " << theGlauberFacP[iz]
<< " GFactorN= " << theGlauberFacN[iz] << G4endl;
}
}
theCoulombFac[0] = theCoulombFac[1] = 1.0;
theCoulombFacP[0] = theCoulombFacP[1] =
theCoulombFacN[0] = theCoulombFacN[1] = 1.0;
dp.SetDefinition(theProton);
dp.SetKineticEnergy(fLowEnergy);
for(G4int iz=2; iz<93; ++iz) {
theCoulombFac[iz] =
fNucleon->GetElasticCrossSection(&dp, iz)/CoulombFactor(fLowEnergy, iz);
theCoulombFacP[iz] = fNucleon->GetElasticCrossSection(&dp, iz)
/CoulombFactor(fLowEnergy, iz);
}
dp.SetDefinition(G4Neutron::Neutron());
for(G4int iz=2; iz<93; ++iz) {
theCoulombFacN[iz] = fNucleon->GetElasticCrossSection(&dp, iz)
/CoulombFactor(fLowEnergy, iz);
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " factor= " << theCoulombFac[iz] << G4endl;
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " CFactorP= " << theCoulombFacP[iz]
<< " CFactorN= " << theCoulombFacN[iz] << G4endl;
}
}
}
@@ -243,26 +262,9 @@ void G4BGGNucleonElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
G4double G4BGGNucleonElasticXS::CoulombFactor(G4double kinEnergy, G4int Z)
{
G4double res= 1.0;
// from G4ProtonInelasticCrossSection
if(isProton) {
if (Z <= 1) { return kinEnergy*kinEnergy; }
static const G4double llog10 = G4Log(10.);
G4double elog = G4Log(kinEnergy/GeV)/llog10;
G4double aa = theA[Z];
G4double ff1 = 5.6 - 0.016*aa; // slope of the drop at medium energies.
G4double ff2 = 1.37 + 1.37/aa; // start of the slope.
G4double ff3 = 0.8 + 18./aa - 0.002*aa; // stephight
res = 1.0 + ff3*(1.0 - (1.0/(1+G4Exp(-ff1*(elog + ff2)))));
ff1 = 8. - 8./aa - 0.008*aa; // slope of the rise
ff2 = 2.34 - 5.4/aa - 0.0028*aa; // start of the rise
res /= (1.0 + G4Exp(-ff1*(elog + ff2)));
}
res = G4NuclearRadii::CoulombFactor(Z, theA[Z], theProton, kinEnergy);
}
return res;
}
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
@@ -54,6 +53,7 @@
#include "G4Isotope.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
#include "G4NuclearRadii.hh"
#include "G4CrossSectionDataSetRegistry.hh"
@@ -61,8 +61,10 @@
const G4double llog10 = G4Log(10.);
G4double G4BGGNucleonInelasticXS::theGlauberFac[93] = {0.0};
G4double G4BGGNucleonInelasticXS::theCoulombFac[93] = {0.0};
G4double G4BGGNucleonInelasticXS::theGlauberFacP[93] = {0.0};
G4double G4BGGNucleonInelasticXS::theCoulombFacP[93] = {0.0};
G4double G4BGGNucleonInelasticXS::theGlauberFacN[93] = {0.0};
G4double G4BGGNucleonInelasticXS::theCoulombFacN[93] = {0.0};
G4int G4BGGNucleonInelasticXS::theA[93] = {0};
#ifdef G4MULTITHREADED
@@ -75,15 +77,13 @@ G4BGGNucleonInelasticXS::G4BGGNucleonInelasticXS(const G4ParticleDefinition* p)
verboseLevel = 0;
fGlauberEnergy = 91.*GeV;
fLowEnergy = 14.*MeV;
fHighEnergy = 5.*GeV;
fNucleon = nullptr;
fGlauber = nullptr;
fHadron = nullptr;
particle = p;
theProton= G4Proton::Proton();
isProton = (theProton == p) ? true : false;
isProton = (theProton == p);
isMaster = false;
SetForAllAtomsAndEnergies(true);
}
@@ -98,7 +98,7 @@ G4BGGNucleonInelasticXS::~G4BGGNucleonInelasticXS()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4BGGNucleonInelasticXS::IsElementApplicable(const G4DynamicParticle*,
G4int, const G4Material*)
G4int, const G4Material*)
{
return true;
}
@@ -106,9 +106,9 @@ G4bool G4BGGNucleonInelasticXS::IsElementApplicable(const G4DynamicParticle*,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4BGGNucleonInelasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4int Z, G4int,
const G4Element*,
const G4Material*)
G4int Z, G4int,
const G4Element*,
const G4Material*)
{
return (1 == Z);
}
@@ -117,24 +117,20 @@ G4bool G4BGGNucleonInelasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4double
G4BGGNucleonInelasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4int ZZ, const G4Material*)
G4int ZZ, const G4Material*)
{
G4double cross = 0.0;
G4double ekin = dp->GetKineticEnergy();
G4int Z = std::min(ZZ, 92);
if(1 == Z) {
cross = 1.0115*GetIsoCrossSection(dp,1,1);
} else if(2 == Z) {
if(ekin > fGlauberEnergy) {
cross = theGlauberFac[Z]*fGlauber->GetInelasticGlauberGribov(dp, Z, theA[Z]);
} else {
cross = fNucleon->GetElementCrossSection(dp, Z);
}
} else {
if(ekin <= fLowEnergy) {
cross = theCoulombFac[Z]*CoulombFactor(ekin, Z);
cross = (isProton) ? theCoulombFacP[Z] : theCoulombFacN[Z];
cross *= CoulombFactor(ekin, Z);
} else if(ekin > fGlauberEnergy) {
cross = theGlauberFac[Z]*fGlauber->GetInelasticGlauberGribov(dp, Z, theA[Z]);
cross = (isProton) ? theGlauberFacP[Z] : theGlauberFacN[Z];
cross *= fGlauber->GetInelasticGlauberGribov(dp, Z, theA[Z]);
} else {
cross = fNucleon->GetElementCrossSection(dp, Z);
}
@@ -142,11 +138,11 @@ G4BGGNucleonInelasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
if(verboseLevel > 1) {
G4cout << "G4BGGNucleonInelasticXS::GetCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
@@ -155,23 +151,23 @@ G4BGGNucleonInelasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4double
G4BGGNucleonInelasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
{
// this method should be called only for Z = 1
fHadron->HadronNucleonXscNS(dp->GetDefinition(), theProton,
dp->GetKineticEnergy());
dp->GetKineticEnergy());
G4double cross = A*fHadron->GetInelasticHadronNucleonXsc();
if(verboseLevel > 1) {
G4cout << "G4BGGNucleonInelasticXS::GetIsoCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()/CLHEP::GeV
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
@@ -180,26 +176,23 @@ G4BGGNucleonInelasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
void G4BGGNucleonInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
{
if(fNucleon) { return; }
if(&p == theProton || &p == G4Neutron::Neutron()) {
particle = &p;
isProton = (theProton == particle) ? true : false;
isProton = (theProton == &p);
} else {
G4ExceptionDescription ed;
ed << "This BGG cross section is applicable only to nucleons and not to "
<< p.GetParticleName() << G4endl;
G4Exception("G4BGGNucleonInelasticXS::BuildPhysicsTable", "had001",
FatalException, ed);
FatalException, ed);
return;
}
if(!fNucleon) {
fNucleon = (G4NucleonNuclearCrossSection*)G4CrossSectionDataSetRegistry::Instance()->GetCrossSectionDataSet(G4NucleonNuclearCrossSection::Default_Name());
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
}
fNucleon = new G4NucleonNuclearCrossSection();
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
fNucleon->BuildPhysicsTable(*particle);
fGlauber->BuildPhysicsTable(*particle);
fNucleon->BuildPhysicsTable(p);
if(0 == theA[0]) {
#ifdef G4MULTITHREADED
@@ -211,44 +204,61 @@ void G4BGGNucleonInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
}
G4MUTEXUNLOCK(&nucleonInelasticXSMutex);
#endif
} else {
return;
}
if(isMaster && 0 == theA[0]) {
theA[0] = 1;
theA[0] = theA[1] = 1;
G4ThreeVector mom(0.0,0.0,1.0);
G4DynamicParticle dp(particle, mom, fGlauberEnergy);
G4DynamicParticle dp(theProton, mom, fGlauberEnergy);
G4NistManager* nist = G4NistManager::Instance();
G4double csup, csdn;
if(verboseLevel > 0) {
G4cout << "### G4BGGNucleonInelasticXS::Initialise for "
<< particle->GetParticleName() << G4endl;
<< p.GetParticleName() << G4endl;
}
for(G4int iz=2; iz<93; iz++) {
for(G4int iz=2; iz<93; ++iz) {
G4int A = G4lrint(nist->GetAtomicMassAmu(iz));
theA[iz] = A;
csup = fGlauber->GetInelasticGlauberGribov(&dp, iz, A);
csdn = fNucleon->GetElementCrossSection(&dp, iz);
theGlauberFacP[iz] = csdn/csup;
}
dp.SetDefinition(G4Neutron::Neutron());
for(G4int iz=2; iz<93; ++iz) {
csup = fGlauber->GetInelasticGlauberGribov(&dp, iz, theA[iz]);
csdn = fNucleon->GetElementCrossSection(&dp, iz);
theGlauberFacN[iz] = csdn/csup;
theGlauberFac[iz] = csdn/csup;
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << A
<< " GlauberFactor= " << theGlauberFac[iz] << G4endl;
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " GFactorP= " << theGlauberFacP[iz]
<< " GFactorN= " << theGlauberFacN[iz] << G4endl;
}
}
theCoulombFac[1] = 1.0;
theCoulombFacP[1] = theCoulombFacN[1] = 1.0;
dp.SetDefinition(theProton);
dp.SetKineticEnergy(fLowEnergy);
for(G4int iz=2; iz<93; ++iz) {
theCoulombFac[iz] =
fNucleon->GetElementCrossSection(&dp, iz)/CoulombFactor(fLowEnergy, iz);
theCoulombFacP[iz] = fNucleon->GetElementCrossSection(&dp, iz)
/CoulombFactor(fLowEnergy, iz);
}
dp.SetDefinition(G4Neutron::Neutron());
for(G4int iz=2; iz<93; ++iz) {
theCoulombFacN[iz] = fNucleon->GetElementCrossSection(&dp, iz)
/CoulombFactor(fLowEnergy, iz);
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " CoulombFactor= " << theCoulombFac[iz] << G4endl;
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " CFactorP= " << theCoulombFacP[iz]
<< " CFactorN= " << theCoulombFacN[iz] << G4endl;
}
}
}
@@ -258,27 +268,28 @@ void G4BGGNucleonInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
G4double G4BGGNucleonInelasticXS::CoulombFactor(G4double kinEnergy, G4int Z)
{
G4double res= 0.0;
G4double res = 0.0;
if(kinEnergy <= 0.0) { return res; }
else if (Z <= 1) { return kinEnergy*kinEnergy; }
G4double elog = G4Log(kinEnergy/GeV)/llog10;
G4double aa = theA[Z];
if(isProton) {
// from G4ProtonInelasticCrossSection
if(isProton) {
G4double ff1 = 5.6 - 0.016*aa; // slope of the drop at medium energies.
G4double ff2 = 1.37 + 1.37/aa; // start of the slope.
G4double ff3 = 0.8 + 18./aa - 0.002*aa; // stephight
res = 1.0 + ff3*(1.0 - (1.0/(1+G4Exp(-ff1*(elog + ff2)))));
ff1 = 8. - 8./aa - 0.008*aa; // slope of the rise
ff2 = 2.34 - 5.4/aa - 0.0028*aa; // start of the rise
res /= (1.0 + G4Exp(-ff1*(elog + ff2)));
res = G4NuclearRadii::CoulombFactor(Z, theA[Z], theProton, kinEnergy);
// from G4ProtonInelasticCrossSection
if(res > 0.0) {
G4double ff1 = 5.6 - 0.016*aa; // slope of the drop at medium energies.
G4double ff2 = 1.37 + 1.37/aa; // start of the slope.
G4double ff3 = 0.8 + 18./aa - 0.002*aa; // stephight
res *= (1.0 + ff3*(1.0 - (1.0/(1+G4Exp(-ff1*(elog + ff2))))));
ff1 = 8. - 8./aa - 0.008*aa; // slope of the rise
ff2 = 2.34 - 5.4/aa - 0.0028*aa; // start of the rise
res /= (1.0 + G4Exp(-ff1*(elog + ff2)));
}
} else {
// from G4NeutronInelasticCrossSection
G4double p3 = 0.6 + 13./aa - 0.0005*aa;
G4double p4 = 7.2449 - 0.018242*aa;
@@ -290,7 +301,6 @@ G4double G4BGGNucleonInelasticXS::CoulombFactor(G4double kinEnergy, G4int Z)
G4double secondexp = G4Exp(-p6*(elog + p7));
res = (1.+p3*firstexp/(1. + firstexp))/(1. + secondexp);
}
return res;
}
@@ -44,11 +44,14 @@
#include "G4ComponentGGHadronNucleusXsc.hh"
#include "G4UPiNuclearCrossSection.hh"
#include "G4HadronNucleonXsc.hh"
#include "G4NuclearRadii.hh"
#include "G4Proton.hh"
#include "G4PionPlus.hh"
#include "G4PionMinus.hh"
#include "G4NistManager.hh"
#include "G4HadronicParameters.hh"
#include "G4Pow.hh"
G4double G4BGGPionElasticXS::theGlauberFacPiPlus[93] = {0.0};
G4double G4BGGPionElasticXS::theCoulombFacPiPlus[93] = {0.0};
@@ -67,16 +70,20 @@ G4BGGPionElasticXS::G4BGGPionElasticXS(const G4ParticleDefinition* p)
{
verboseLevel = 0;
fGlauberEnergy = 91.*GeV;
fLowEnergy = 1.*MeV;
fLowEnergy = 20.*MeV;
fLowestEnergy = 1.*MeV;
SetMinKinEnergy(0.0);
SetMaxKinEnergy( G4HadronicParameters::Instance()->GetMaxEnergy() );
fPion = nullptr;
fGlauber = nullptr;
fHadron = nullptr;
particle = p;
fG4pow = G4Pow::GetInstance();
theProton= G4Proton::Proton();
isPiplus = (p == G4PionPlus::PionPlus()) ? true : false;
thePiPlus= G4PionPlus::PionPlus();
isPiplus = (p == thePiPlus);
isMaster = false;
SetForAllAtomsAndEnergies(true);
}
@@ -92,7 +99,7 @@ G4BGGPionElasticXS::~G4BGGPionElasticXS()
G4bool
G4BGGPionElasticXS::IsElementApplicable(const G4DynamicParticle*, G4int,
const G4Material*)
const G4Material*)
{
return true;
}
@@ -100,7 +107,7 @@ G4BGGPionElasticXS::IsElementApplicable(const G4DynamicParticle*, G4int,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4BGGPionElasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4int Z, G4int,
G4int Z, G4int,
const G4Element*, const G4Material*)
{
return (1 == Z);
@@ -110,18 +117,18 @@ G4bool G4BGGPionElasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4double
G4BGGPionElasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4int ZZ, const G4Material*)
G4int ZZ, const G4Material*)
{
// this method should be called only for Z > 1
G4double cross = 0.0;
G4double ekin = dp->GetKineticEnergy();
G4double ekin = std::max(dp->GetKineticEnergy(), fLowestEnergy);
G4int Z = std::min(ZZ, 92);
if(1 == Z) {
cross = 1.0115*GetIsoCrossSection(dp,1,1);
} else {
if(ekin <= fLowEnergy) {
cross = (isPiplus) ? theCoulombFacPiPlus[Z] : theCoulombFacPiMinus[Z];
cross = (isPiplus) ? theCoulombFacPiPlus[Z]*CoulombFactorPiPlus(ekin, Z)
: theCoulombFacPiMinus[Z]*FactorPiMinus(ekin);
} else if(ekin > fGlauberEnergy) {
cross = (isPiplus) ? theGlauberFacPiPlus[Z] : theGlauberFacPiMinus[Z];
cross *= fGlauber->GetElasticGlauberGribov(dp, Z, theA[Z]);
@@ -131,34 +138,34 @@ G4BGGPionElasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
}
if(verboseLevel > 1) {
G4cout << "G4BGGPionElasticXS::GetElementCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
G4double
G4BGGPionElasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
{
// this method should be called only for Z = 1
fHadron->HadronNucleonXscNS(dp->GetDefinition(), theProton,
dp->GetKineticEnergy());
dp->GetKineticEnergy());
G4double cross = A*fHadron->GetElasticHadronNucleonXsc();
if(verboseLevel > 1) {
G4cout << "G4BGGPionElasticXS::GetIsoCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << A
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << A
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
@@ -167,25 +174,27 @@ G4BGGPionElasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
void G4BGGPionElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
{
if(fPion) { return; }
if(verboseLevel > 1) {
G4cout << "G4BGGPionElasticXS::BuildPhysicsTable for "
<< p.GetParticleName() << G4endl;
}
if(&p == G4PionPlus::PionPlus() || &p == G4PionMinus::PionMinus()) {
particle = &p;
isPiplus = (particle == G4PionPlus::PionPlus()) ? true : false;
isPiplus = (&p == G4PionPlus::PionPlus());
} else {
G4ExceptionDescription ed;
ed << "This BGG cross section is applicable only to pions and not to "
<< p.GetParticleName() << G4endl;
G4Exception("G4BGGPionElasticXS::BuildPhysicsTable", "had001",
FatalException, ed);
FatalException, ed);
return;
}
if(!fPion) {
fPion = new G4UPiNuclearCrossSection();
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
}
fPion = new G4UPiNuclearCrossSection();
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
fPion->BuildPhysicsTable(*particle);
fPion->BuildPhysicsTable(p);
if(0 == theA[0]) {
#ifdef G4MULTITHREADED
@@ -197,13 +206,15 @@ void G4BGGPionElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
}
G4MUTEXUNLOCK(&pionElasticXSMutex);
#endif
} else {
return;
}
if(isMaster && 0 == theA[0]) {
theA[0] = 1;
theA[0] = theA[1] = 1;
G4ThreeVector mom(0.0,0.0,1.0);
G4DynamicParticle dp(particle, mom, fGlauberEnergy);
G4DynamicParticle dp(thePiPlus, mom, fGlauberEnergy);
G4NistManager* nist = G4NistManager::Instance();
@@ -213,43 +224,64 @@ void G4BGGPionElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
G4int A = G4lrint(nist->GetAtomicMassAmu(iz));
theA[iz] = A;
dp.SetDefinition(G4PionPlus::PionPlus());
csup = fGlauber->GetElasticGlauberGribov(&dp, iz, A);
csdn = fPion->GetElasticCrossSection(&dp, iz, A);
theGlauberFacPiPlus[iz] = csdn/csup;
}
dp.SetDefinition(G4PionMinus::PionMinus());
csup = fGlauber->GetElasticGlauberGribov(&dp, iz, A);
csdn = fPion->GetElasticCrossSection(&dp, iz, A);
dp.SetDefinition(G4PionMinus::PionMinus());
for(G4int iz=2; iz<93; ++iz) {
csup = fGlauber->GetElasticGlauberGribov(&dp, iz, theA[iz]);
csdn = fPion->GetElasticCrossSection(&dp, iz, theA[iz]);
theGlauberFacPiMinus[iz] = csdn/csup;
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << A
<< " factorPiPlus= " << theGlauberFacPiPlus[iz]
<< " factorPiMinus= " << theGlauberFacPiMinus[iz]
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " factorPiPlus= " << theGlauberFacPiPlus[iz]
<< " factorPiMinus= " << theGlauberFacPiMinus[iz]
<< G4endl;
}
}
theCoulombFacPiPlus[1] = 1.0;
theCoulombFacPiMinus[1]= 1.0;
dp.SetKineticEnergy(fLowEnergy);
dp.SetDefinition(thePiPlus);
for(G4int iz=2; iz<93; ++iz) {
dp.SetDefinition(G4PionPlus::PionPlus());
theCoulombFacPiPlus[iz] = fPion->GetElasticCrossSection(&dp, iz, theA[iz]);
dp.SetDefinition(G4PionMinus::PionMinus());
theCoulombFacPiMinus[iz] = fPion->GetElasticCrossSection(&dp, iz, theA[iz]);
theCoulombFacPiPlus[iz] = fPion->GetElasticCrossSection(&dp, iz, theA[iz])
/CoulombFactorPiPlus(fLowEnergy, iz);
}
dp.SetDefinition(G4PionMinus::PionMinus());
for(G4int iz=2; iz<93; ++iz) {
theCoulombFacPiMinus[iz] = fPion->GetElasticCrossSection(&dp, iz, theA[iz])
/FactorPiMinus(fLowEnergy);
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " CoulombFactorPiPlus= " << theCoulombFacPiPlus[iz]
<< " CoulombFactorPiMinus= " << theCoulombFacPiMinus[iz]
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " CoulombFactorPiPlus= " << theCoulombFacPiPlus[iz]
<< " CoulombFactorPiMinus= " << theCoulombFacPiMinus[iz]
<< G4endl;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4BGGPionElasticXS::CoulombFactorPiPlus(G4double kinEnergy, G4int Z)
{
return (kinEnergy > 0.0) ?
G4NuclearRadii::CoulombFactor(Z, theA[Z], thePiPlus, kinEnergy) : 0.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4BGGPionElasticXS::FactorPiMinus(G4double kinEnergy)
{
return 1.0/std::sqrt(kinEnergy);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void
G4BGGPionElasticXS::CrossSectionDescription(std::ostream& outFile) const
{
@@ -258,3 +290,5 @@ G4BGGPionElasticXS::CrossSectionDescription(std::ostream& outFile) const
<< "Barashenkov parameterization is used below 91 GeV and the\n"
<< "Glauber-Gribov parameterization is used above 91 GeV.\n";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
@@ -44,6 +43,7 @@
#include "G4ComponentGGHadronNucleusXsc.hh"
#include "G4UPiNuclearCrossSection.hh"
#include "G4HadronNucleonXsc.hh"
#include "G4NuclearRadii.hh"
#include "G4Proton.hh"
#include "G4PionPlus.hh"
@@ -67,8 +67,9 @@ G4BGGPionInelasticXS::G4BGGPionInelasticXS(const G4ParticleDefinition* p)
: G4VCrossSectionDataSet("BarashenkovGlauberGribov")
{
verboseLevel = 0;
fGlauberEnergy = 91.*GeV;
fLowEnergy = 20.*MeV;
fGlauberEnergy = 91.*CLHEP::GeV;
fLowEnergy = 20.*CLHEP::MeV;
fLowestEnergy = 1.*CLHEP::MeV;
SetMinKinEnergy(0.0);
SetMaxKinEnergy( G4HadronicParameters::Instance()->GetMaxEnergy() );
@@ -78,10 +79,10 @@ G4BGGPionInelasticXS::G4BGGPionInelasticXS(const G4ParticleDefinition* p)
fG4pow = G4Pow::GetInstance();
particle = p;
theProton= G4Proton::Proton();
isPiplus = (p == G4PionPlus::PionPlus()) ? true : false;
isMaster = false;
theProton = G4Proton::Proton();
thePiPlus = G4PionPlus::PionPlus();
isPiplus = (p == thePiPlus);
isMaster = false;
SetForAllAtomsAndEnergies(true);
}
@@ -96,7 +97,7 @@ G4BGGPionInelasticXS::~G4BGGPionInelasticXS()
G4bool
G4BGGPionInelasticXS::IsElementApplicable(const G4DynamicParticle*, G4int,
const G4Material*)
const G4Material*)
{
return true;
}
@@ -104,9 +105,9 @@ G4BGGPionInelasticXS::IsElementApplicable(const G4DynamicParticle*, G4int,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4BGGPionInelasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4int Z, G4int,
const G4Element*,
const G4Material*)
G4int Z, G4int,
const G4Element*,
const G4Material*)
{
return (1 == Z);
}
@@ -115,19 +116,19 @@ G4bool G4BGGPionInelasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4double
G4BGGPionInelasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4int ZZ, const G4Material*)
G4int ZZ, const G4Material*)
{
// this method should be called only for Z > 1
G4double cross = 0.0;
G4double ekin = dp->GetKineticEnergy();
G4double ekin = std::max(dp->GetKineticEnergy(), fLowestEnergy);
G4int Z = std::min(ZZ, 92);
if(1 == Z) {
cross = 1.0115*GetIsoCrossSection(dp,1,1);
} else if(ekin <= fLowEnergy) {
cross = (isPiplus) ? theLowEPiPlus[Z]*CoulombFactor(ekin, Z)
: theLowEPiMinus[Z];
} else if(ekin < fLowEnergy) {
cross = (isPiplus) ? theLowEPiPlus[Z]*CoulombFactorPiPlus(ekin, Z)
: theLowEPiMinus[Z]*FactorPiMinus(ekin);
} else if(ekin > fGlauberEnergy) {
cross = (isPiplus) ? theGlauberFacPiPlus[Z] : theGlauberFacPiMinus[Z];
cross *= fGlauber->GetInelasticGlauberGribov(dp, Z, theA[Z]);
@@ -136,11 +137,11 @@ G4BGGPionInelasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
}
if(verboseLevel > 1) {
G4cout << "G4BGGPionInelasticXS::GetCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << theA[Z]
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
@@ -149,23 +150,23 @@ G4BGGPionInelasticXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4double
G4BGGPionInelasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
G4int Z, G4int A,
const G4Isotope*,
const G4Element*,
const G4Material*)
{
// this method should be called only for Z = 1
fHadron->HadronNucleonXscNS(dp->GetDefinition(), theProton,
dp->GetKineticEnergy());
dp->GetKineticEnergy());
G4double cross = A*fHadron->GetInelasticHadronNucleonXsc();
if(verboseLevel > 1) {
G4cout << "G4BGGPionInelasticXS::GetCrossSection for "
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << A
<< " XS(b)= " << cross/barn
<< G4endl;
<< dp->GetDefinition()->GetParticleName()
<< " Ekin(GeV)= " << dp->GetKineticEnergy()
<< " in nucleus Z= " << Z << " A= " << A
<< " XS(b)= " << cross/barn
<< G4endl;
}
return cross;
}
@@ -174,25 +175,27 @@ G4BGGPionInelasticXS::GetIsoCrossSection(const G4DynamicParticle* dp,
void G4BGGPionInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
{
if(fPion) { return; }
if(verboseLevel > 1) {
G4cout << "G4BGGPionInelasticXS::BuildPhysicsTable for "
<< p.GetParticleName() << G4endl;
}
if(&p == G4PionPlus::PionPlus() || &p == G4PionMinus::PionMinus()) {
particle = &p;
isPiplus = (particle == G4PionPlus::PionPlus()) ? true : false;
isPiplus = (&p == G4PionPlus::PionPlus());
} else {
G4ExceptionDescription ed;
ed << "This BGG cross section is applicable only to pions and not to "
<< p.GetParticleName() << G4endl;
G4Exception("G4BGGPionInelasticXS::BuildPhysicsTable", "had001",
FatalException, ed);
FatalException, ed);
return;
}
if(!fPion) {
fPion = new G4UPiNuclearCrossSection();
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
}
fPion = new G4UPiNuclearCrossSection();
fGlauber = new G4ComponentGGHadronNucleusXsc();
fHadron = new G4HadronNucleonXsc();
fPion->BuildPhysicsTable(*particle);
fPion->BuildPhysicsTable(p);
if(0 == theA[0]) {
#ifdef G4MULTITHREADED
@@ -204,62 +207,65 @@ void G4BGGPionInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
}
G4MUTEXUNLOCK(&pionInelasticXSMutex);
#endif
} else {
return;
}
if(isMaster && 0 == theA[0]) {
theA[0] = 1;
theA[1] = 1;
theA[0] = theA[1] = 1;
G4ThreeVector mom(0.0,0.0,1.0);
G4DynamicParticle dp(particle, mom, fGlauberEnergy);
G4DynamicParticle dp(thePiPlus, mom, fGlauberEnergy);
G4NistManager* nist = G4NistManager::Instance();
G4double csup, csdn;
if(verboseLevel > 0) {
G4cout << "### G4BGGPionInelasticXS::Initialise for "
<< particle->GetParticleName()
<< " isPiplus: " << isPiplus
<< G4endl;
<< p.GetParticleName()
<< " isPiplus: " << isPiplus
<< G4endl;
}
for(G4int iz=2; iz<93; ++iz) {
G4int A = G4lrint(nist->GetAtomicMassAmu(iz));
theA[iz] = A;
dp.SetDefinition(G4PionPlus::PionPlus());
csup = fGlauber->GetInelasticGlauberGribov(&dp, iz, A);
csdn = fPion->GetInelasticCrossSection(&dp, iz, A);
theGlauberFacPiPlus[iz] = csdn/csup;
}
dp.SetDefinition(G4PionMinus::PionMinus());
csup = fGlauber->GetInelasticGlauberGribov(&dp, iz, A);
csdn = fPion->GetInelasticCrossSection(&dp, iz, A);
dp.SetDefinition(G4PionMinus::PionMinus());
for(G4int iz=2; iz<93; ++iz) {
csup = fGlauber->GetInelasticGlauberGribov(&dp, iz, theA[iz]);
csdn = fPion->GetInelasticCrossSection(&dp, iz, theA[iz]);
theGlauberFacPiMinus[iz] = csdn/csup;
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << A
<< " factorPiPlus= " << theGlauberFacPiPlus[iz]
<< " factorPiMinus= " << theGlauberFacPiMinus[iz]
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " factorPiPlus= " << theGlauberFacPiPlus[iz]
<< " factorPiMinus= " << theGlauberFacPiMinus[iz]
<< G4endl;
}
}
theLowEPiPlus[1] = 1.0;
theLowEPiMinus[1]= 1.0;
dp.SetKineticEnergy(fLowEnergy);
theLowEPiPlus[1] = theLowEPiMinus[1]= 1.0;
dp.SetDefinition(thePiPlus);
dp.SetKineticEnergy(fLowEnergy);
for(G4int iz=2; iz<93; ++iz) {
dp.SetDefinition(G4PionPlus::PionPlus());
theLowEPiPlus[iz] = fPion->GetInelasticCrossSection(&dp, iz, theA[iz])
/CoulombFactor(fLowEnergy, iz);
dp.SetDefinition(G4PionMinus::PionMinus());
theLowEPiMinus[iz] = fPion->GetInelasticCrossSection(&dp, iz, theA[iz]);
/CoulombFactorPiPlus(fLowEnergy, iz);
}
dp.SetDefinition(G4PionMinus::PionMinus());
for(G4int iz=2; iz<93; ++iz) {
theLowEPiMinus[iz] = fPion->GetInelasticCrossSection(&dp, iz, theA[iz])
/FactorPiMinus(fLowEnergy);
if(verboseLevel > 0) {
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " LowEtorPiPlus= " << theLowEPiPlus[iz]
<< " LowEtorPiMinus= " << theLowEPiMinus[iz]
G4cout << "Z= " << iz << " A= " << theA[iz]
<< " LowEtorPiPlus= " << theLowEPiPlus[iz]
<< " LowEtorPiMinus= " << theLowEPiMinus[iz]
<< G4endl;
}
}
@@ -268,26 +274,17 @@ void G4BGGPionInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4BGGPionInelasticXS::CoulombFactor(G4double kinEnergy, G4int Z)
G4double G4BGGPionInelasticXS::CoulombFactorPiPlus(G4double kinEnergy, G4int Z)
{
G4int A = theA[Z];
G4double res= 0.0;
if(kinEnergy <= DBL_MIN) { return res; }
else if(A < 2) { return kinEnergy*kinEnergy; }
G4double elog = fG4pow->log10A(6.7*kinEnergy/GeV);
G4double aa = A;
return (kinEnergy > 0.0) ?
G4NuclearRadii::CoulombFactor(Z, theA[Z], thePiPlus, kinEnergy) : 0.0;
}
// from G4ProtonInelasticCrossSection
G4double ff1 = 0.70 - 0.002*aa; // slope of the drop at medium energies.
G4double ff2 = 1.00 + 1/aa; // start of the slope.
G4double ff3 = 0.8 + 18/aa - 0.002*aa; // stephight
res = 1.0 + ff3*(1.0 - (1.0/(1+fG4pow->expA(-8*ff1*(elog + 1.37*ff2)))));
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
ff1 = 1. - 1./aa - 0.001*aa; // slope of the rise
ff2 = 1.17 - 2.7/aa-0.0014*aa; // start of the rise
res /= (1 + fG4pow->expA(-8.*ff1*(elog + 2*ff2)));
return res;
G4double G4BGGPionInelasticXS::FactorPiMinus(G4double kinEnergy)
{
return 1.0/std::sqrt(kinEnergy);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -140,7 +140,7 @@ G4double G4ComponentBarNucleonNucleusXsc::GetElasticIsotopeCrossSection(
////////////////////////////////////////////////////////////////////////////
void G4ComponentBarNucleonNucleusXsc::ComputeCrossSections(
const G4ParticleDefinition* aParticle, G4double kineticEnergy, G4int ZZ)
const G4ParticleDefinition* aParticle, G4double kineticEnergy, G4int ZZ)
{
G4int Z = std::min(ZZ, 92);
G4int it = 0;
@@ -164,7 +164,7 @@ void G4ComponentBarNucleonNucleusXsc::ComputeCrossSections(
fInelasticXsc = Interpolate(Z1, Z2, Z, x1, x2);
fTotalXsc = Interpolate(Z1, Z2, Z, xt1, xt2);
}
fElasticXsc = std::max(fTotalXsc - fInelasticXsc, 0.0);
}
@@ -212,11 +212,11 @@ void G4ComponentGGHadronNucleusXsc::ComputeCrossSections(
}
else
{
sigma = Z*hnXsc->HadronNucleonXscNS(aParticle, theProton, kinEnergy);
sigma = Z*hnXsc->HadronNucleonXsc(aParticle, theProton, kinEnergy);
hpInXsc = hnXsc->GetInelasticHadronNucleonXsc();
if(N > 0) {
sigma += N*hnXsc->HadronNucleonXscNS(aParticle, theNeutron, kinEnergy);
sigma += N*hnXsc->HadronNucleonXsc(aParticle, theNeutron, kinEnergy);
hnInXsc = hnXsc->GetInelasticHadronNucleonXsc();
}
R = G4NuclearRadii::RadiusHNGG(A);
@@ -250,9 +250,11 @@ void G4ComponentGGHadronNucleusXsc::ComputeCrossSections(
fTotalXsc = sigma;
fInelasticXsc = hpInXsc;
fElasticXsc = std::max(fTotalXsc - fInelasticXsc, 0.);
G4double xratio = hpInXsc/nucleusSquare;
fProductionXsc = nucleusSquare*G4Log(1. + cofInelastic*xratio)/cofInelastic;
fProductionXsc = std::min(fProductionXsc, fInelasticXsc);
fProductionXsc = fInelasticXsc;
fDiffractionXsc = 0.2*fInelasticXsc;
// G4double xratio = hpInXsc/nucleusSquare;
// fProductionXsc = nucleusSquare*G4Log(1. + cofInelastic*xratio)/cofInelastic;
// fProductionXsc = std::min(fProductionXsc, fInelasticXsc);
}
/*
G4cout << "GGXsc: Z= " << Z << " A= " << A << " E= " << kinEnergy
@@ -221,7 +221,7 @@ void G4ComponentSAIDTotalXS::Initialise(G4SAIDCrossSectionType tp)
#endif
// check environment variable
// Build the complete string identifying the file with the data set
char* path = getenv("G4SAIDXSDATA");
char* path = std::getenv("G4SAIDXSDATA");
if (!path){
G4Exception("G4ComponentSAIDTotalXS::Initialise(..)","had013",
FatalException,
@@ -581,7 +581,7 @@ void G4CrossSectionDataStore::DumpHtml(const G4ParticleDefinition& /* pD */,
G4double ehi = 0;
G4double elo = 0;
G4String physListName(getenv("G4PhysListName"));
G4String physListName(std::getenv("G4PhysListName"));
for (G4int i = nDataSetList-1; i > 0; i--) {
elo = dataSetList[i]->GetMinKinEnergy()/GeV;
ehi = dataSetList[i]->GetMaxKinEnergy()/GeV;
@@ -607,8 +607,8 @@ void G4CrossSectionDataStore::DumpHtml(const G4ParticleDefinition& /* pD */,
void G4CrossSectionDataStore::PrintCrossSectionHtml(const G4VCrossSectionDataSet *cs) const
{
G4String dirName(getenv("G4PhysListDocDir"));
G4String physListName(getenv("G4PhysListName"));
G4String dirName(std::getenv("G4PhysListDocDir"));
G4String physListName(std::getenv("G4PhysListName"));
G4String pathName = dirName + "/" + physListName + "_" + HtmlFileName(cs->GetName());
std::ofstream outCS;
@@ -40,6 +40,7 @@
#include "G4Log.hh"
#include "G4Exp.hh"
#include "G4Pow.hh"
#include "G4NuclearRadii.hh"
#include "G4LambdacPlus.hh"
#include "G4AntiLambdacPlus.hh"
@@ -119,6 +120,7 @@ static const G4double cofLogE = .0557; // elastic (lnP-minLogP)^2
static const G4double cofLogT = .3; // total (lnP-minLogP)^2
static const G4double pMin = .1; // fast LE calculation
static const G4double pMax = 1000.; // fast HE calculation
static const G4double ekinmin = 0.1*CLHEP::MeV; // protection against zero ekin
G4HadronNucleonXsc::G4HadronNucleonXsc()
: fTotalXsc(0.0), fElasticXsc(0.0), fInelasticXsc(0.0)
@@ -222,6 +224,48 @@ void G4HadronNucleonXsc::CrossSectionDescription(std::ostream& outFile) const
<< "is to be used to build a cross section data set.\n";
}
G4double G4HadronNucleonXsc::HadronNucleonXsc( const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin)
{
G4double xsc(0.);
G4int pdg = std::abs( theParticle->GetPDGEncoding() );
if ( pdg == 2212 || pdg == 2112 || pdg == 211 ) // p, n, pi+-
{
xsc = HadronNucleonXscNS( theParticle, nucleon, ekin);
}
else if ( pdg == 321 || pdg == 310 || pdg == 130 ) // K+-, K0, Ks
{
xsc = KaonNucleonXscNS( theParticle, nucleon, ekin);
}
else if ( pdg == 3122 || pdg == 3222 || pdg == 3112 || pdg == 3212 || pdg == 3322 || pdg == 3312 || pdg == 3324 ||
pdg == 4122 || pdg == 4332 || pdg == 4122 || pdg == 4212 || pdg == 4222 || pdg == 4112 || pdg == 4232 || pdg == 4132 ||
pdg == 5122 || pdg == 5332 || pdg == 5122 || pdg == 5112 || pdg == 5222 || pdg == 5212 || pdg == 5132 || pdg == 5232
) // heavy s-,c-,b-hyperons
{
xsc = HyperonNucleonXscNS( theParticle, nucleon, ekin);
}
else if ( pdg == 511 || pdg == 421 || pdg == 531 || pdg == 541 || pdg == 431 || pdg == 411 || pdg == 521 ||
pdg == 221 || pdg == 331 || pdg == 441 || pdg == 443 || pdg == 543
) // s-,c-,b-mesons
{
xsc = SCBMesonNucleonXscNS( theParticle, nucleon, ekin);
}
else
{
xsc = HadronNucleonXscNS( theParticle, nucleon, ekin);
}
return xsc;
}
//////////////////////////////////////////////////////////////////////////////
//
// Returns hadron-nucleon Xsc according to PDG parametrisation (2017):
@@ -415,8 +459,9 @@ G4double G4HadronNucleonXsc::HadronNucleonXscPDG(
G4double G4HadronNucleonXsc::HadronNucleonXscNS(
const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin)
const G4ParticleDefinition* nucleon, G4double ekin0)
{
const G4double ekin = std::max(ekin0, ekinmin);
/*
G4cout<< "HadronNucleonXscNS: Ekin(GeV)= " << ekin/GeV << " "
<< theParticle->GetParticleName() << " + "
@@ -426,57 +471,7 @@ G4double G4HadronNucleonXsc::HadronNucleonXscNS(
return HadronNucleonXscPDG(theParticle, nucleon, ekin);
}
G4double pM = theParticle->GetPDGMass();
///////////////////////////// strange hyperons
if(pM > CLHEP::GeV) {
if( theParticle == theL || theParticle == theSPlus ||
theParticle == theSMinus || theParticle == theS0) {
fTotalXsc = HadronNucleonXscNS( theProton, nucleon, ekin);
fTotalXsc *= fHypTotXscCof;
fInelasticXsc *= fHypTotXscCof;
fElasticXsc *= fHypTotXscCof;
return fTotalXsc;
} else if( theParticle == theAntiL || theParticle == theASPlus ||
theParticle == theASMinus || theParticle == theAS0) {
fTotalXsc = HadronNucleonXscNS( theProton, nucleon, ekin);
fTotalXsc *= fHypTotXscCof;
fInelasticXsc *= fHypTotXscCof;
fElasticXsc *= fHypTotXscCof;
return fTotalXsc;
} else if( theParticle == theXiMinus || theParticle == theXi0) {
fTotalXsc = HadronNucleonXscNS( theProton, nucleon, ekin);
G4double cof2 = fHypTotXscCof*fHypTotXscCof;
fTotalXsc *= cof2;
fInelasticXsc *= cof2;
fElasticXsc *= cof2;
return fTotalXsc;
} else if( theParticle == theAXiMinus || theParticle == theAXi0) {
fTotalXsc = HadronNucleonXscNS( theProton, nucleon, ekin);
G4double cof2 = fHypTotXscCof*fHypTotXscCof;
fTotalXsc *= cof2;
fInelasticXsc *= cof2;
fElasticXsc *= cof2;
return fTotalXsc;
} else if( theParticle == theOmega ) {
fTotalXsc = HadronNucleonXscNS( theProton, nucleon, ekin);
G4double cof3 = fHypTotXscCof*fHypTotXscCof*fHypTotXscCof;
fTotalXsc *= cof3;
fInelasticXsc *= cof3;
fElasticXsc *= cof3;
return fTotalXsc;
} else if( theParticle == theAOmega ) {
fTotalXsc = HadronNucleonXscNS( theProton, nucleon, ekin);
G4double cof3 = fHypTotXscCof*fHypTotXscCof*fHypTotXscCof;
fTotalXsc *= cof3;
fInelasticXsc *= cof3;
fElasticXsc *= cof3;
return fTotalXsc;
} else {
return HadronNucleonXscPDG( theProton, nucleon, ekin);
}
}
G4double pM = theParticle->GetPDGMass();
G4double tM = nucleon->GetPDGMass();
G4double pE = ekin + pM;
G4double pLab = std::sqrt(ekin*(ekin + 2*pM));
@@ -489,6 +484,7 @@ G4double G4HadronNucleonXsc::HadronNucleonXscNS(
if(pLab >= 10.) {
fTotalXsc = HadronNucleonXscPDG(theParticle, nucleon, ekin)/CLHEP::millibarn;
} else { fTotalXsc = 0.0; }
fElasticXsc = 0.0;
//G4cout << "Stot(mb)= " << fTotalXsc << " pLab= " << pLab
// << " Smand= " << sMand <<G4endl;
G4double logP = G4Log(pLab);
@@ -643,7 +639,7 @@ G4double G4HadronNucleonXsc::HadronNucleonXscNS(
}
else if( pLab < 0.68 )
{
fTotalXsc = 14./( (logP + 1.273)*(logP + 1.273) + 0.07);
fTotalXsc = 14./((logP + 1.273)*(logP + 1.273) + 0.07);
fElasticXsc = fTotalXsc;
}
else if( pLab < 0.85 )
@@ -880,16 +876,15 @@ G4double G4HadronNucleonXsc::HadronNucleonXscNS(
}
fTotalXsc *= CLHEP::millibarn;
fElasticXsc *= CLHEP::millibarn;
fElasticXsc = std::min(fElasticXsc, fTotalXsc);
fInelasticXsc = std::max(fTotalXsc - fElasticXsc,0.0);
fElasticXsc = std::min(fElasticXsc, fTotalXsc);
if( proton && theParticle->GetPDGCharge() > 0. && ekin < 100*MeV)
{
G4double cB = CoulombBarrier(theParticle, nucleon, ekin);
G4double cB = G4NuclearRadii::CoulombFactor(theParticle, nucleon, ekin);
fTotalXsc *= cB;
fElasticXsc *= cB;
fInelasticXsc *= cB;
}
fInelasticXsc = std::max(fTotalXsc - fElasticXsc,0.0);
/*
G4cout<< "HNXsc: Ekin(GeV)= " << ekin/GeV << "; tot(mb)= " << fTotalXsc/millibarn
<<"; el(mb)= " <<fElasticXsc/millibarn
@@ -1075,11 +1070,10 @@ G4double G4HadronNucleonXsc::KaonNucleonXscVG(
G4double sp = std::sqrt(pLab);
G4double p2 = pLab*pLab;
G4double p4 = p2*p2;
G4double lm = pLab - 0.8; // vg version
G4double md = lm*lm + .652; // vg version
G4double lm = pLab - 0.94;
G4double md = lm*lm + .392;
fElasticXsc = (cofLogE*ld2 + 2.23)/(1. - .7/sp + .1/p4) + 2./md;
fTotalXsc = (cofLogT*ld2 + 19.5)/(1. + .46/sp + 1.6/p4)
+ 7.6/md; // vg version
fTotalXsc = (cofLogT*ld2 + 19.5)/(1. + .46/sp + 1.6/p4) + 4.6/md;
}
}
@@ -1088,7 +1082,7 @@ G4double G4HadronNucleonXsc::KaonNucleonXscVG(
if( proton && theParticle->GetPDGCharge() > 0. )
{
G4double cB = CoulombBarrier(theParticle, nucleon, ekin);
G4double cB = G4NuclearRadii::CoulombFactor(theParticle, nucleon, ekin);
fTotalXsc *= cB;
fElasticXsc *= cB;
}
@@ -1108,18 +1102,18 @@ G4double G4HadronNucleonXsc::KaonNucleonXscVG(
// Returns hyperon-nucleon cross-section using NS x-section for protons
G4double G4HadronNucleonXsc::HyperonNucleonXscNS(
const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin)
const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin)
{
G4double coeff = 1.0;
static const G4double lBarCof1S = 0.88;
static const G4double lBarCof1S = 0.88;
static const G4double lBarCof2S = 0.76;
static const G4double lBarCof3S = 0.64;
static const G4double lBarCof1C = 0.784378;
static const G4double lBarCofSC = 0.664378;
static const G4double lBarCof2SC = 0.544378;
static const G4double lBarCof1B = 0.740659;
static const G4double lBarCof1B = 0.740659;
static const G4double lBarCofSB = 0.620659;
static const G4double lBarCof2SB = 0.500659;
@@ -1184,8 +1178,9 @@ G4double G4HadronNucleonXsc::HyperonNucleonXscNS(
//
// Returns hyperon-nucleon cross-section using NS x-section for protons
G4double G4HadronNucleonXsc::SCBMesonNucleonXscNS( const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin )
G4double G4HadronNucleonXsc::SCBMesonNucleonXscNS(
const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin )
{
G4double coeff(1.0);
// static const G4double lMesCof1S = 0.82; // Kp/piP
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
@@ -41,11 +40,12 @@
#include "G4SystemOfUnits.hh"
#include "G4NeutronCaptureXS.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementTable.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsVector.hh"
#include "G4DynamicParticle.hh"
#include "G4ProductionCutsTable.hh"
#include "Randomize.hh"
#include "G4Log.hh"
@@ -82,6 +82,7 @@ const G4int G4NeutronCaptureXS::amax[] = {
0, 238};
G4ElementData* G4NeutronCaptureXS::data = nullptr;
G4String G4NeutronCaptureXS::gDataDirectory = "";
#ifdef G4MULTITHREADED
G4Mutex G4NeutronCaptureXS::neutronCaptureXSMutex = G4MUTEX_INITIALIZER;
@@ -98,7 +99,7 @@ G4NeutronCaptureXS::G4NeutronCaptureXS()
}
logElimit = G4Log(elimit);
isMaster = false;
fIdxXSTable = 0;
temp.resize(13,0.0);
}
G4NeutronCaptureXS::~G4NeutronCaptureXS()
@@ -142,19 +143,19 @@ G4NeutronCaptureXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
G4double logEkin = aParticle->GetLogKineticEnergy();
if(ekin < elimit) { ekin = elimit; logEkin = logElimit; }
// element was not initialised
G4PhysicsVector* pv = data->GetElementData(Z);
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
G4double e1 = pv->Energy(0);
if(ekin < e1) {
xs = (*pv)[0]*std::sqrt(e1/ekin);
} else if(ekin <= pv->GetMaxEnergy()) {
xs = pv->Value(ekin, logEkin, fIdxXSTable);
xs = pv->LogVectorValue(ekin, logEkin);
}
if(verboseLevel > 0){
G4cout << "ekin= " << ekin << ", xs= " << xs << G4endl;
if(verboseLevel > 1){
G4cout << "Ekin= " << ekin/CLHEP::MeV
<< " ElmXScap(b)= " << xs/CLHEP::barn << G4endl;
}
return xs;
}
@@ -184,34 +185,37 @@ G4double G4NeutronCaptureXS::IsoCrossSection(G4double eKin, G4double logE,
logEkin = logElimit;
}
if(amin[Z] > 0) {
if(A >= amin[Z] && A <= amax[Z]) {
G4PhysicsVector* pviso = data->GetComponentDataByID(Z, A - amin[Z]);
if(pviso) {
G4double e1 = pviso->Energy(1);
if(ekin < e1) {
xs = (*pviso)[1]*std::sqrt(e1/ekin);
} else if(ekin <= pviso->GetMaxEnergy()) {
xs = pviso->Value(ekin, logEkin, fIdxXSTable);
}
}
}
} else {
// isotope data are not available or applicable
G4PhysicsVector* pv = data->GetElementData(Z);
if(pv) {
G4double e1 = pv->Energy(1);
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
if(amin[Z] > 0 && A >= amin[Z] && A <= amax[Z]) {
G4PhysicsVector* pviso = data->GetComponentDataByID(Z, A - amin[Z]);
if(pviso) {
G4double e1 = pviso->Energy(1);
if(ekin < e1) {
xs = (*pv)[1]*std::sqrt(e1/ekin);
} else if(ekin <= pv->GetMaxEnergy()) {
xs = pv->Value(ekin, logEkin, fIdxXSTable);
xs = (*pviso)[1]*std::sqrt(e1/ekin);
} else if(ekin <= pviso->GetMaxEnergy()) {
xs = pviso->LogVectorValue(ekin, logEkin);
}
if(verboseLevel > 0) {
G4cout << "G4NeutronCaptureXS::IsoXS: Ekin(MeV)= " << ekin/MeV
<< " xs(b)= " << xs/barn
<< " Z= " << Z << " A= " << A << G4endl;
}
return xs;
}
}
// isotope data are not available or applicable
G4double e1 = pv->Energy(1);
if(ekin < e1) {
xs = (*pv)[1]*std::sqrt(e1/ekin);
} else if(ekin <= pv->GetMaxEnergy()) {
xs = pv->LogVectorValue(ekin, logEkin);
}
if(verboseLevel > 0) {
G4cout << "G4NeutronCaptureXS::IsoXS: Ekin(MeV)= " << ekin/MeV
<< " xs(b)= " << xs/barn
<< " Z= " << Z << " A= " << A << G4endl;
<< " Z= " << Z << " A= " << A << " no iso XS" << G4endl;
}
return xs;
}
@@ -223,40 +227,41 @@ G4NeutronCaptureXS::SelectIsotope(const G4Element* anElement,
size_t nIso = anElement->GetNumberOfIsotopes();
const G4Isotope* iso = anElement->GetIsotope(0);
//G4cout << "SelectIsotope NIso= " << nIso << G4endl;
if(1 == nIso) { return iso; }
// more than 1 isotope
if(1 < nIso) {
G4int Z = anElement->GetZasInt();
G4int Z = anElement->GetZasInt();
const G4double* abundVector = anElement->GetRelativeAbundanceVector();
G4double q = G4UniformRand();
G4double sum = 0.0;
const G4double* abundVector = anElement->GetRelativeAbundanceVector();
G4double q = G4UniformRand();
G4double sum = 0.0;
// is there isotope wise cross section?
size_t j;
if(0 == amin[Z] || Z >= MAXZCAPTURE) {
for (j = 0; j<nIso; ++j) {
sum += abundVector[j];
if(q <= sum) {
iso = anElement->GetIsotope(j);
break;
}
// is there isotope wise cross section?
size_t j;
if(0 == amin[Z] || Z >= MAXZCAPTURE) {
for (j = 0; j<nIso; ++j) {
sum += abundVector[j];
if(q <= sum) {
iso = anElement->GetIsotope(j);
break;
}
} else {
size_t nn = temp.size();
if(nn < nIso) { temp.resize(nIso, 0.); }
}
return iso;
}
size_t nn = temp.size();
if(nn < nIso) { temp.resize(nIso, 0.); }
for (j=0; j<nIso; ++j) {
sum += abundVector[j]*IsoCrossSection(kinEnergy, logE, Z,
anElement->GetIsotope(j)->GetN());
temp[j] = sum;
}
sum *= q;
for (j = 0; j<nIso; ++j) {
if(temp[j] >= sum) {
iso = anElement->GetIsotope(j);
break;
}
}
for (j=0; j<nIso; ++j) {
sum += abundVector[j]*IsoCrossSection(kinEnergy, logE, Z,
anElement->GetIsotope(j)->GetN());
temp[j] = sum;
}
sum *= q;
for (j = 0; j<nIso; ++j) {
if(temp[j] >= sum) {
iso = anElement->GetIsotope(j);
break;
}
}
return iso;
@@ -286,7 +291,7 @@ G4NeutronCaptureXS::BuildPhysicsTable(const G4ParticleDefinition& p)
isMaster = true;
data = new G4ElementData();
data->SetName("NeutronCapture");
temp.resize(13,0.0);
FindDirectoryPath();
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&neutronCaptureXSMutex);
@@ -296,39 +301,70 @@ G4NeutronCaptureXS::BuildPhysicsTable(const G4ParticleDefinition& p)
// it is possible re-initialisation for the second run
if(isMaster) {
// check environment variable
// Build the complete string identifying the file with the data set
char* path = getenv("G4PARTICLEXSDATA");
// Access to elements
const G4ElementTable* theElmTable = G4Element::GetElementTable();
size_t numOfElm = G4Element::GetNumberOfElements();
for(size_t i=0; i<numOfElm; ++i) {
G4int Z = std::min(((*theElmTable)[i])->GetZasInt(),MAXZCAPTURE-1);
if(!data->GetElementData(Z)) { Initialise(Z, path); }
auto theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for(size_t j=0; j<numOfCouples; ++j) {
auto mat = theCoupleTable->GetMaterialCutsCouple(j)->GetMaterial();
auto elmVec = mat->GetElementVector();
size_t numOfElem = mat->GetNumberOfElements();
for (size_t ie = 0; ie < numOfElem; ++ie) {
G4int Z = std::max(1,std::min(((*elmVec)[ie])->GetZasInt(), MAXZCAPTURE-1));
if(!data->GetElementData(Z)) { Initialise(Z); }
}
}
}
}
void
G4NeutronCaptureXS::Initialise(G4int Z, const char* p)
const G4PhysicsVector* G4NeutronCaptureXS::GetPhysicsVector(G4int Z)
{
if(data->GetElementData(Z) || Z < 1 || Z >= MAXZCAPTURE) { return; }
const char* path = p;
const G4PhysicsVector* pv = data->GetElementData(Z);
if(!pv) {
InitialiseOnFly(Z);
pv = data->GetElementData(Z);
}
return pv;
}
// check environment variable
if(!p) {
path = getenv("G4PARTICLEXSDATA");
if (!path) {
G4Exception("G4NeutronCaptureXS::Initialise(..)","had013",FatalException,
"Environment variable G4PARTICLEXSDATA is not defined");
return;
const G4String& G4NeutronCaptureXS::FindDirectoryPath()
{
// check environment variable
// build the complete string identifying the file with the data set
if(gDataDirectory.empty()) {
char* path = std::getenv("G4PARTICLEXSDATA");
if (path) {
std::ostringstream ost;
ost << path << "/neutron/cap";
gDataDirectory = ost.str();
} else {
G4Exception("G4NeutronCaptureXS::Initialise(..)","had013",
FatalException,
"Environment variable G4PARTICLEXSDATA is not defined");
}
}
return gDataDirectory;
}
void G4NeutronCaptureXS::InitialiseOnFly(G4int Z)
{
#ifdef G4MULTITHREADED
G4MUTEXLOCK(&neutronCaptureXSMutex);
if(!data->GetElementData(Z)) {
#endif
Initialise(Z);
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&neutronCaptureXSMutex);
#endif
}
void G4NeutronCaptureXS::Initialise(G4int Z)
{
if(data->GetElementData(Z)) { return; }
// upload element data
std::ostringstream ost;
ost << path << "/neutron/cap" << Z ;
ost << FindDirectoryPath() << Z ;
G4PhysicsVector* v = RetrieveVector(ost, true);
data->InitialiseForElement(Z, v);
@@ -339,7 +375,7 @@ G4NeutronCaptureXS::Initialise(G4int Z, const char* p)
for(G4int A=amin[Z]; A<=amax[Z]; ++A) {
std::ostringstream ost1;
ost1 << path << "/neutron/cap" << Z << "_" << A;
ost1 << gDataDirectory << Z << "_" << A;
v = RetrieveVector(ost1, false);
data->AddComponent(Z, A, v);
}
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
@@ -39,15 +38,15 @@
#include "G4NeutronElasticXS.hh"
#include "G4Neutron.hh"
#include "G4DynamicParticle.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementTable.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsVector.hh"
#include "G4ComponentGGHadronNucleusXsc.hh"
#include "G4NistManager.hh"
#include "G4Neutron.hh"
#include "G4SystemOfUnits.hh"
#include <iostream>
#include <fstream>
#include <sstream>
@@ -60,6 +59,8 @@ using namespace std;
G4PhysicsVector* G4NeutronElasticXS::data[] = {nullptr};
G4double G4NeutronElasticXS::coeff[] = {0.0};
G4double G4NeutronElasticXS::aeff[] = {1.0};
G4String G4NeutronElasticXS::gDataDirectory = "";
#ifdef G4MULTITHREADED
G4Mutex G4NeutronElasticXS::neutronElasticXSMutex = G4MUTEX_INITIALIZER;
@@ -69,7 +70,6 @@ G4NeutronElasticXS::G4NeutronElasticXS()
: G4VCrossSectionDataSet(Default_Name()),
ggXsection(nullptr),
neutron(G4Neutron::Neutron()),
fIdxXSTable(0),
isMaster(false)
{
// verboseLevel = 0;
@@ -80,6 +80,7 @@ G4NeutronElasticXS::G4NeutronElasticXS()
nist = G4NistManager::Instance();
ggXsection = new G4ComponentGGHadronNucleusXsc();
SetForAllAtomsAndEnergies(true);
temp.resize(13,0.0);
}
G4NeutronElasticXS::~G4NeutronElasticXS()
@@ -108,6 +109,13 @@ G4NeutronElasticXS::IsElementApplicable(const G4DynamicParticle*,
return true;
}
G4bool G4NeutronElasticXS::IsIsoApplicable(const G4DynamicParticle*,
G4int, G4int,
const G4Element*, const G4Material*)
{
return true;
}
G4double
G4NeutronElasticXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
G4int ZZ, const G4Material*)
@@ -117,30 +125,125 @@ G4NeutronElasticXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
G4int Z = (ZZ >= MAXZEL) ? MAXZEL - 1 : ZZ;
G4PhysicsVector* pv = data[Z];
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
// G4cout << "G4NeutronElasticXS::GetCrossSection e= " << ekin
// << " Z= " << Z << G4endl;
// element was not initialised
if(ekin <= pv->Energy(0)) {
xs = (*pv)[0];
} else if(ekin <= pv->GetMaxEnergy()) {
xs = pv->LogVectorValue(ekin, aParticle->GetLogKineticEnergy());
} else {
xs = coeff[Z]*ggXsection->GetElasticElementCrossSection(neutron,
ekin, Z, aeff[Z]);
}
if(verboseLevel > 1) {
G4cout << "Z= " << Z << " Ekin(MeV)= " << ekin/CLHEP::MeV
<< ", nElmXSel(b)= " << xs/CLHEP::barn
<< G4endl;
}
return xs;
}
G4double G4NeutronElasticXS::GetIsoCrossSection(
const G4DynamicParticle* aParticle,
G4int Z, G4int A,
const G4Isotope*, const G4Element*,
const G4Material*)
{
return IsoCrossSection(aParticle->GetKineticEnergy(),
aParticle->GetLogKineticEnergy(), Z, A);
}
G4double
G4NeutronElasticXS::IsoCrossSection(G4double ekin, G4double logekin,
G4int ZZ, G4int A)
{
G4double xs = 0.0;
G4int Z = (ZZ >= MAXZEL) ? MAXZEL - 1 : ZZ;
// tritium and He3
if(3 == A) {
return ggXsection->GetElasticElementCrossSection(neutron, ekin, Z, A);
}
/*
G4cout << "IsoCrossSection Z= " << Z << " A= " << A
<< " Amin= " << amin[Z] << " Amax= " << amax[Z]
<< " E(MeV)= " << ekin << G4endl;
*/
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
if(ekin <= pv->Energy(0)) {
xs = (*pv)[0];
} else if(ekin <= pv->GetMaxEnergy()) {
xs = pv->Value(ekin, aParticle->GetLogKineticEnergy(), fIdxXSTable);
xs = pv->LogVectorValue(ekin, logekin);
} else {
xs = coeff[Z]*ggXsection->GetElasticElementCrossSection(neutron,
ekin, Z, nist->GetAtomicMassAmu(Z));
ekin, Z, aeff[Z]);
}
if(verboseLevel > 0){
G4cout << "Z= " << Z << " Ekin(MeV)= " << ekin/CLHEP::MeV
<< ", nElmXSel(bn)= " << xs/CLHEP::barn
<< G4endl;
xs *= A/aeff[Z];
if(verboseLevel > 1) {
G4cout << "G4NeutronElasticXS::IsoXS: Z= " << Z << " A= " << A
<< " Ekin(MeV)= " << ekin/CLHEP::MeV
<< ", ElmXS(b)= " << xs/CLHEP::barn << G4endl;
}
return xs;
}
const G4Isotope* G4NeutronElasticXS::SelectIsotope(
const G4Element* anElement, G4double kinEnergy, G4double logE)
{
size_t nIso = anElement->GetNumberOfIsotopes();
const G4Isotope* iso = anElement->GetIsotope(0);
//G4cout << "SelectIsotope NIso= " << nIso << G4endl;
if(1 == nIso) { return iso; }
// more than 1 isotope
G4int Z = anElement->GetZasInt();
//G4cout << "SelectIsotope Z= " << Z << G4endl;
const G4double* abundVector = anElement->GetRelativeAbundanceVector();
G4double q = G4UniformRand();
G4double sum = 0.0;
size_t j;
// isotope wise cross section not used
if(anElement->GetNaturalAbundanceFlag()) {
for (j=0; j<nIso; ++j) {
sum += abundVector[j];
if(q <= sum) {
iso = anElement->GetIsotope(j);
break;
}
}
return iso;
}
// use isotope cross sections
size_t nn = temp.size();
if(nn < nIso) { temp.resize(nIso, 0.); }
for (j=0; j<nIso; ++j) {
//G4cout << j << "-th isotope " << (*isoVector)[j]->GetN()
// << " abund= " << abundVector[j] << G4endl;
sum += abundVector[j]*IsoCrossSection(kinEnergy, logE, Z,
anElement->GetIsotope(j)->GetN());
temp[j] = sum;
}
sum *= q;
for (j = 0; j<nIso; ++j) {
if(temp[j] >= sum) {
iso = anElement->GetIsotope(j);
break;
}
}
return iso;
}
void
G4NeutronElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
{
@@ -161,7 +264,7 @@ G4NeutronElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
G4MUTEXLOCK(&neutronElasticXSMutex);
if(0. == coeff[0]) {
#endif
for(G4int i=0; i<MAXZEL; ++i) { coeff[i] = 1.0; }
coeff[0] = 1.0;
isMaster = true;
#ifdef G4MULTITHREADED
}
@@ -172,41 +275,68 @@ G4NeutronElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
// it is possible re-initialisation for the second run
if(isMaster) {
// check environment variable
// Build the complete string identifying the file with the data set
char* path = getenv("G4PARTICLEXSDATA");
// Access to elements
const G4ElementTable* theElmTable = G4Element::GetElementTable();
size_t numOfElm = G4Element::GetNumberOfElements();
for(size_t i=0; i<numOfElm; ++i) {
G4int Z = std::min(((*theElmTable)[i])->GetZasInt(),MAXZEL-1);
if(!data[Z]) { Initialise(Z, path); }
auto theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for(size_t j=0; j<numOfCouples; ++j) {
auto mat = theCoupleTable->GetMaterialCutsCouple(j)->GetMaterial();
auto elmVec = mat->GetElementVector();
size_t numOfElem = mat->GetNumberOfElements();
for (size_t ie = 0; ie < numOfElem; ++ie) {
G4int Z = std::max(1,std::min(((*elmVec)[ie])->GetZasInt(), MAXZEL-1));
if(!data[Z]) { Initialise(Z); }
}
}
}
}
void G4NeutronElasticXS::Initialise(G4int Z, const char* p)
G4PhysicsVector* G4NeutronElasticXS::GetPhysicsVector(G4int Z)
{
if(data[Z]) { return; }
const char* path = p;
if(!p) {
// check environment variable
// Build the complete string identifying the file with the data set
path = getenv("G4PARTICLEXSDATA");
if (!path) {
if(!data[Z]) { InitialiseOnFly(Z); }
return data[Z];
}
const G4String& G4NeutronElasticXS::FindDirectoryPath()
{
// check environment variable
// build the complete string identifying the file with the data set
if(gDataDirectory.empty()) {
char* path = std::getenv("G4PARTICLEXSDATA");
if (path) {
std::ostringstream ost;
ost << path << "/neutron/el";
gDataDirectory = ost.str();
} else {
G4Exception("G4NeutronElasticXS::Initialise(..)","had013",
FatalException,
"Environment variable G4PARTICLEXSDATA is not defined");
return;
"Environment variable G4PARTICLEXSDATA is not defined");
}
}
return gDataDirectory;
}
void G4NeutronElasticXS::InitialiseOnFly(G4int Z)
{
#ifdef G4MULTITHREADED
G4MUTEXLOCK(&neutronElasticXSMutex);
if(!data[Z]) {
#endif
Initialise(Z);
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&neutronElasticXSMutex);
#endif
}
void G4NeutronElasticXS::Initialise(G4int Z)
{
if(data[Z]) { return; }
// upload data from file
data[Z] = new G4PhysicsLogVector();
std::ostringstream ost;
ost << path << "/neutron/el" << Z ;
ost << FindDirectoryPath() << Z ;
std::ifstream filein(ost.str().c_str());
if (!(filein)) {
G4ExceptionDescription ed;
@@ -215,26 +345,26 @@ void G4NeutronElasticXS::Initialise(G4int Z, const char* p)
G4Exception("G4NeutronElasticXS::Initialise(..)","had014",
FatalException, ed, "Check G4PARTICLEXSDATA");
return;
} else {
if(verboseLevel > 1) {
G4cout << "file " << ost.str()
<< " is opened by G4NeutronElasticXS" << G4endl;
}
}
if(verboseLevel > 1) {
G4cout << "file " << ost.str()
<< " is opened by G4NeutronElasticXS" << G4endl;
}
// retrieve data from DB
if(!data[Z]->Retrieve(filein, true)) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not retrieved!";
G4Exception("G4NeutronElasticXS::Initialise(..)","had015",
FatalException, ed, "Check G4PARTICLEXSDATA");
return;
}
// smooth transition
G4double sig1 = (*(data[Z]))[data[Z]->GetVectorLength()-1];
G4double ehigh = data[Z]->GetMaxEnergy();
G4double sig2 = ggXsection->GetElasticElementCrossSection(neutron,
ehigh, Z, nist->GetAtomicMassAmu(Z));
if(sig2 > 0.) { coeff[Z] = sig1/sig2; }
}
// retrieve data from DB
if(!data[Z]->Retrieve(filein, true)) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not retrieved!";
G4Exception("G4NeutronElasticXS::Initialise(..)","had015",
FatalException, ed, "Check G4PARTICLEXSDATA");
return;
}
// smooth transition
G4double sig1 = (*(data[Z]))[data[Z]->GetVectorLength()-1];
G4double ehigh = data[Z]->GetMaxEnergy();
aeff[Z] = nist->GetAtomicMassAmu(Z);
G4double sig2 = ggXsection->GetElasticElementCrossSection(neutron,
ehigh, Z, aeff[Z]);
if(sig2 > 0.) { coeff[Z] = sig1/sig2; }
}
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
@@ -38,15 +37,16 @@
#include "G4NeutronInelasticXS.hh"
#include "G4Neutron.hh"
#include "G4DynamicParticle.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementTable.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsVector.hh"
#include "G4ComponentGGHadronNucleusXsc.hh"
#include "G4NistManager.hh"
#include "Randomize.hh"
#include "G4SystemOfUnits.hh"
#include <iostream>
#include <fstream>
#include <sstream>
@@ -83,8 +83,9 @@ const G4int G4NeutronInelasticXS::amax[] = {
0, 238};
G4double G4NeutronInelasticXS::coeff[] = {1.0};
G4double G4NeutronInelasticXS::aeff[] = {1.0};
G4ElementData* G4NeutronInelasticXS::data = nullptr;
G4String G4NeutronInelasticXS::gDataDirectory = "";
#ifdef G4MULTITHREADED
G4Mutex G4NeutronInelasticXS::neutronInelasticXSMutex = G4MUTEX_INITIALIZER;
@@ -92,8 +93,7 @@ G4ElementData* G4NeutronInelasticXS::data = nullptr;
G4NeutronInelasticXS::G4NeutronInelasticXS()
: G4VCrossSectionDataSet(Default_Name()),
neutron(G4Neutron::Neutron()),
emax(20*CLHEP::MeV)
neutron(G4Neutron::Neutron())
{
// verboseLevel = 0;
if(verboseLevel > 0){
@@ -104,7 +104,7 @@ G4NeutronInelasticXS::G4NeutronInelasticXS()
nist = G4NistManager::Instance();
SetForAllAtomsAndEnergies(true);
isMaster = false;
fIdxXSTable = 0;
temp.resize(13,0.0);
}
G4NeutronInelasticXS::~G4NeutronInelasticXS()
@@ -145,23 +145,24 @@ G4double G4NeutronInelasticXS::GetElementCrossSection(
G4int Z = (ZZ >= MAXZINEL) ? MAXZINEL - 1 : ZZ;
const G4PhysicsVector* pv = data->GetElementData(Z);
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
// G4cout << "G4NeutronInelasticXS::GetCrossSection e= " << ekin
// << " Z= " << Z << G4endl;
// element was not initialised or low energy
if(!pv || ekin <= pv->Energy(0)) { return xs; }
// below threshold
if(ekin <= pv->Energy(0)) { return xs; }
if(ekin <= pv->GetMaxEnergy()) {
xs = pv->Value(ekin, aParticle->GetLogKineticEnergy(), fIdxXSTable);
xs = pv->LogVectorValue(ekin, aParticle->GetLogKineticEnergy());
} else {
xs = coeff[Z]*ggXsection->GetInelasticElementCrossSection(neutron,
ekin, Z, nist->GetAtomicMassAmu(Z));
ekin, Z, aeff[Z]);
}
if(verboseLevel > 0) {
if(verboseLevel > 1) {
G4cout << "Z= " << Z << " Ekin(MeV)= " << ekin/CLHEP::MeV
<< ", nElmXSinel(bn)= " << xs/CLHEP::barn
<< ", ElmXSinel(b)= " << xs/CLHEP::barn
<< G4endl;
}
return xs;
@@ -184,26 +185,50 @@ G4NeutronInelasticXS::IsoCrossSection(G4double ekin, G4double logekin,
G4double xs = 0.0;
G4int Z = (ZZ >= MAXZINEL) ? MAXZINEL - 1 : ZZ;
// tritium and He3
if(3 == A) {
return ggXsection->GetInelasticElementCrossSection(neutron, ekin, Z, A);
}
/*
G4cout << "IsoCrossSection Z= " << Z << " A= " << A
<< " Amin= " << amin[Z] << " Amax= " << amax[Z]
<< " E(MeV)= " << ekin << G4endl;
*/
// compute isotope cross section if applicable
if(ekin <= emax && amin[Z] > 0) {
if(A >= amin[Z] && A <= amax[Z]) {
G4PhysicsVector* pviso = data->GetComponentDataByIndex(Z, A - amin[Z]);
if(pviso) { xs = pviso->Value(ekin, logekin, fIdxXSTable); }
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
// below threshold
if(ekin <= pv->Energy(0)) { return xs; }
// compute isotope cross section if applicable
G4double emax = pv->GetMaxEnergy();
if(ekin <= emax && amin[Z] > 0 && A >= amin[Z] && A <= amax[Z]) {
auto pviso = data->GetComponentDataByIndex(Z, A - amin[Z]);
if(pviso) {
xs = pviso->LogVectorValue(ekin, logekin);
if(verboseLevel > 1) {
G4cout << "G4NeutronInelasticXS::IsoXS: Ekin(MeV)= "
<< ekin/CLHEP::MeV
<< " xs(b)= " << xs/CLHEP::barn
<< " Z= " << Z << " A= " << A << G4endl;
}
return xs;
}
} else {
// isotope data are not available or applicable
G4PhysicsVector* pv = data->GetElementData(Z);
if(pv) { xs = pv->Value(ekin, logekin, fIdxXSTable); }
}
if(verboseLevel > 0) {
G4cout << "IsoXS: Z= " << Z << " A= " << A
// use element x-section
if(ekin <= emax) {
xs = pv->LogVectorValue(ekin, logekin);
} else {
xs = coeff[Z]*ggXsection->GetInelasticElementCrossSection(neutron,
ekin, Z, aeff[Z]);
}
xs *= A/aeff[Z];
if(verboseLevel > 1) {
G4cout << "G4NeutronInelasticXS::IsoXS: Z= " << Z << " A= " << A
<< " Ekin(MeV)= " << ekin/CLHEP::MeV
<< ", nElmXSinel(bn)= " << xs/CLHEP::barn << G4endl;
<< ", ElmXS(b)= " << xs/CLHEP::barn << G4endl;
}
return xs;
}
@@ -224,11 +249,11 @@ const G4Isotope* G4NeutronInelasticXS::SelectIsotope(
const G4double* abundVector = anElement->GetRelativeAbundanceVector();
G4double q = G4UniformRand();
G4double sum = 0.0;
size_t j;
// isotope wise cross section not available
size_t j;
if(kinEnergy > emax || 0 == amin[Z] || Z >= MAXZINEL) {
for (j = 0; j<nIso; ++j) {
if(0 == amin[Z] || Z >= MAXZINEL) {
for (j=0; j<nIso; ++j) {
sum += abundVector[j];
if(q <= sum) {
iso = anElement->GetIsotope(j);
@@ -262,7 +287,7 @@ const G4Isotope* G4NeutronInelasticXS::SelectIsotope(
void
G4NeutronInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
{
if(verboseLevel > 0){
if(verboseLevel > 0) {
G4cout << "G4NeutronInelasticXS::BuildPhysicsTable for "
<< p.GetParticleName() << G4endl;
}
@@ -283,7 +308,7 @@ G4NeutronInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
isMaster = true;
data = new G4ElementData();
data->SetName("NeutronInelastic");
temp.resize(13,0.0);
FindDirectoryPath();
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&neutronInelasticXSMutex);
@@ -293,43 +318,70 @@ G4NeutronInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
// it is possible re-initialisation for the new run
if(isMaster) {
// check environment variable
// Build the complete string identifying the file with the data set
char* path = getenv("G4PARTICLEXSDATA");
// Access to elements
const G4ElementTable* theElmTable = G4Element::GetElementTable();
size_t numOfElm = G4Element::GetNumberOfElements();
for(size_t i=0; i<numOfElm; ++i) {
G4int Z = ((*theElmTable)[i])->GetZasInt();
if(Z >= MAXZINEL) { Z = MAXZINEL-1; }
// Initialisation
if(!(data->GetElementData(Z))) {
Initialise(Z, path);
auto theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for(size_t j=0; j<numOfCouples; ++j) {
auto mat = theCoupleTable->GetMaterialCutsCouple(j)->GetMaterial();
auto elmVec = mat->GetElementVector();
size_t numOfElem = mat->GetNumberOfElements();
for (size_t ie = 0; ie < numOfElem; ++ie) {
G4int Z = std::max(1,std::min(((*elmVec)[ie])->GetZasInt(), MAXZINEL-1));
if(!data->GetElementData(Z)) { Initialise(Z); }
}
}
}
}
}
void
G4NeutronInelasticXS::Initialise(G4int Z, const char* p)
const G4PhysicsVector* G4NeutronInelasticXS::GetPhysicsVector(G4int Z)
{
if(data->GetElementData(Z) || Z < 1 || Z >= MAXZINEL) { return; }
const char* path = p;
if(!p) {
// check environment variable
// Build the complete string identifying the file with the data set
path = getenv("G4PARTICLEXSDATA");
if (!path) {
const G4PhysicsVector* pv = data->GetElementData(Z);
if(!pv) {
InitialiseOnFly(Z);
pv = data->GetElementData(Z);
}
return pv;
}
const G4String& G4NeutronInelasticXS::FindDirectoryPath()
{
// check environment variable
// build the complete string identifying the file with the data set
if(gDataDirectory.empty()) {
char* path = std::getenv("G4PARTICLEXSDATA");
if (path) {
std::ostringstream ost;
ost << path << "/neutron/inel";
gDataDirectory = ost.str();
} else {
G4Exception("G4NeutronInelasticXS::Initialise(..)","had013",
FatalException,
"Environment variable G4PARTICLEXSDATA is not defined");
return;
"Environment variable G4PARTICLEXSDATA is not defined");
}
}
return gDataDirectory;
}
void G4NeutronInelasticXS::InitialiseOnFly(G4int Z)
{
#ifdef G4MULTITHREADED
G4MUTEXLOCK(&neutronInelasticXSMutex);
if(!data->GetElementData(Z)) {
#endif
Initialise(Z);
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&neutronInelasticXSMutex);
#endif
}
void G4NeutronInelasticXS::Initialise(G4int Z)
{
if(data->GetElementData(Z)) { return; }
// upload element data
std::ostringstream ost;
ost << path << "/neutron/inel" << Z ;
ost << FindDirectoryPath() << Z;
G4PhysicsVector* v = RetrieveVector(ost, true);
data->InitialiseForElement(Z, v);
/*
@@ -344,7 +396,7 @@ G4NeutronInelasticXS::Initialise(G4int Z, const char* p)
for(G4int A=amin[Z]; A<=amax[Z]; ++A) {
std::ostringstream ost1;
ost1 << path << "/neutron/inel" << Z << "_" << A;
ost1 << gDataDirectory << Z << "_" << A;
G4PhysicsVector* v1 = RetrieveVector(ost1, false);
data->AddComponent(Z, A, v1);
}
@@ -353,8 +405,9 @@ G4NeutronInelasticXS::Initialise(G4int Z, const char* p)
// smooth transition
G4double sig1 = (*v)[v->GetVectorLength()-1];
G4double ehigh= v->GetMaxEnergy();
aeff[Z] = nist->GetAtomicMassAmu(Z);
G4double sig2 = ggXsection->GetInelasticElementCrossSection(neutron,
ehigh, Z, nist->GetAtomicMassAmu(Z));
ehigh, Z, aeff[Z]);
if(sig2 > 0.) { coeff[Z] = sig1/sig2; }
}
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
@@ -39,8 +38,9 @@
#include "G4ParticleInelasticXS.hh"
#include "G4Neutron.hh"
#include "G4DynamicParticle.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementTable.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsVector.hh"
#include "G4ComponentGGHadronNucleusXsc.hh"
@@ -48,8 +48,8 @@
#include "G4NistManager.hh"
#include "G4Proton.hh"
#include "Randomize.hh"
#include "G4SystemOfUnits.hh"
#include <iostream>
#include <fstream>
#include <sstream>
@@ -81,8 +81,9 @@ const G4int G4ParticleInelasticXS::amax[] = {
0, 238};
G4double G4ParticleInelasticXS::coeff[] = {1.0};
G4double G4ParticleInelasticXS::aeff[] = {1.0};
G4ElementData* G4ParticleInelasticXS::data = nullptr;
G4String G4ParticleInelasticXS::gDataDirectory = "";
#ifdef G4MULTITHREADED
G4Mutex G4ParticleInelasticXS::particleInelasticXSMutex = G4MUTEX_INITIALIZER;
@@ -94,8 +95,6 @@ G4ParticleInelasticXS::G4ParticleInelasticXS(const G4ParticleDefinition* part)
nnXsection(nullptr),
particle(part),
proton(G4Proton::Proton()),
emax(20*CLHEP::MeV),
fIdxXSTable(0),
isMaster(false)
{
if(!part) {
@@ -116,6 +115,7 @@ G4ParticleInelasticXS::G4ParticleInelasticXS(const G4ParticleDefinition* part)
}
SetForAllAtomsAndEnergies(true);
fNist = G4NistManager::Instance();
temp.resize(13,0.0);
}
G4ParticleInelasticXS::~G4ParticleInelasticXS()
@@ -156,23 +156,23 @@ G4double G4ParticleInelasticXS::GetElementCrossSection(
G4int Z = (ZZ >= MAXZINELP) ? MAXZINELP - 1 : ZZ;
G4PhysicsVector* pv = data->GetElementData(Z);
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
// G4cout << "G4ParticleInelasticXS::GetCrossSection e= " << ekin
// << " Z= " << Z << G4endl;
// element was not initialised or below threshold
if(!pv || ekin <= pv->Energy(0)) { return xs; }
// below threshold
if(ekin <= pv->Energy(0)) { return xs; }
if(ekin <= pv->GetMaxEnergy()) {
xs = pv->Value(ekin, aParticle->GetLogKineticEnergy(), fIdxXSTable);
xs = pv->LogVectorValue(ekin, aParticle->GetLogKineticEnergy());
} else {
G4double Amean = fNist->GetAtomicMassAmu(Z);
if(ggXsection) {
xs = coeff[Z]*ggXsection->GetInelasticElementCrossSection(particle,
ekin, Z, Amean);
ekin, Z, aeff[Z]);
} else {
xs = coeff[Z]*nnXsection->GetInelasticElementCrossSection(particle,
ekin, Z, Amean);
ekin, Z, aeff[Z]);
}
}
@@ -200,23 +200,56 @@ G4ParticleInelasticXS::IsoCrossSection(G4double ekin, G4double logE,
{
G4double xs = 0.0;
G4int Z = (ZZ >= MAXZINELP) ? MAXZINELP - 1 : ZZ;
// tritium and He3
if(3 == A) {
if(ggXsection) {
xs = ggXsection->GetInelasticElementCrossSection(particle, ekin, Z, A);
} else {
xs = nnXsection->GetInelasticElementCrossSection(particle, ekin, Z, A);
}
return xs;
}
/*
G4cout << "IsoCrossSection Z= " << Z << " A= " << A
<< " Amin= " << amin[Z] << " Amax= " << amax[Z]
<< " E(MeV)= " << ekin << G4endl;
*/
auto pv = GetPhysicsVector(Z);
if(!pv) { return xs; }
// below threshold
if(ekin <= pv->Energy(0)) { return xs; }
// compute isotope cross section if applicable
if(ekin <= emax && amin[Z]>0) {
if(A >= amin[Z] && A <= amax[Z]) {
G4PhysicsVector* pviso = data->GetComponentDataByIndex(Z, A - amin[Z]);
if(pviso) { xs = pviso->Value(ekin, logE, fIdxXSTable); }
G4double emax = pv->GetMaxEnergy();
if(ekin <= emax && amin[Z]>0 && A >= amin[Z] && A <= amax[Z]) {
auto pviso = data->GetComponentDataByIndex(Z, A - amin[Z]);
if(pviso) {
xs = pviso->LogVectorValue(ekin, logE);
if(verboseLevel > 1) {
G4cout << "G4ParticleInelasticXS::IsoXS: for "
<< particle->GetParticleName() << " Ekin(MeV)= "
<< ekin/CLHEP::MeV << " xs(b)= " << xs/CLHEP::barn
<< " Z= " << Z << " A= " << A << G4endl;
}
return xs;
}
} else {
// isotope data are not available or applicable
G4PhysicsVector* pv = data->GetElementData(Z);
if(pv) { xs = pv->Value(ekin, logE, fIdxXSTable); }
}
if(verboseLevel > 0) {
// use element x-section
if(ekin <= emax) {
xs = pv->LogVectorValue(ekin, logE);
} else {
if(ggXsection) {
xs = coeff[Z]*ggXsection->GetInelasticElementCrossSection(particle,
ekin, Z, aeff[Z]);
} else {
xs = coeff[Z]*nnXsection->GetInelasticElementCrossSection(particle,
ekin, Z, aeff[Z]);
}
}
xs *= A/aeff[Z];
if(verboseLevel > 1) {
G4cout << "IsoXS for " << particle->GetParticleName()
<< " Target Z= " << Z << " A= " << A
<< " Ekin(MeV)= " << ekin/CLHEP::MeV
@@ -241,11 +274,11 @@ const G4Isotope* G4ParticleInelasticXS::SelectIsotope(
const G4double* abundVector = anElement->GetRelativeAbundanceVector();
G4double q = G4UniformRand();
G4double sum = 0.0;
// is there isotope wise cross section?
size_t j;
if(kinEnergy > emax || 0 == amin[Z] || Z >= MAXZINELP) {
for (j = 0; j<nIso; ++j) {
// isotope wise cross section not available
if(0 == amin[Z] || Z >= MAXZINELP) {
for (j=0; j<nIso; ++j) {
sum += abundVector[j];
if(q <= sum) {
iso = anElement->GetIsotope(j);
@@ -266,7 +299,7 @@ const G4Isotope* G4ParticleInelasticXS::SelectIsotope(
temp[j] = sum;
}
sum *= q;
for (j = 0; j<nIso; ++j) {
for (j=0; j<nIso; ++j) {
if(temp[j] >= sum) {
iso = anElement->GetIsotope(j);
break;
@@ -299,7 +332,6 @@ G4ParticleInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
isMaster = true;
data = new G4ElementData();
data->SetName(particle->GetParticleName() + "Inelastic");
temp.resize(13,0.0);
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&particleInelasticXSMutex);
@@ -309,40 +341,70 @@ G4ParticleInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
// it is possible re-initialisation for the new run
if(isMaster) {
// check environment variable
// Build the complete string identifying the file with the data set
char* path = getenv("G4PARTICLEXSDATA");
// Access to elements
const G4ElementTable* theElmTable = G4Element::GetElementTable();
size_t numOfElm = G4Element::GetNumberOfElements();
for(size_t i=0; i<numOfElm; ++i) {
G4int Z = std::min(((*theElmTable)[i])->GetZasInt(), MAXZINELP-1);
if(!(data->GetElementData(Z))) { Initialise(Z, path); }
auto theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for(size_t j=0; j<numOfCouples; ++j) {
auto mat = theCoupleTable->GetMaterialCutsCouple(j)->GetMaterial();
auto elmVec = mat->GetElementVector();
size_t numOfElem = mat->GetNumberOfElements();
for (size_t ie = 0; ie < numOfElem; ++ie) {
G4int Z = std::max(1,std::min(((*elmVec)[ie])->GetZasInt(), MAXZINELP-1));
if(!data->GetElementData(Z)) { Initialise(Z); }
}
}
}
}
void G4ParticleInelasticXS::Initialise(G4int Z, const char* p)
const G4PhysicsVector* G4ParticleInelasticXS::GetPhysicsVector(G4int Z)
{
if(data->GetElementData(Z)) { return; }
const char* path = p;
if(!p) {
// check environment variable
// Build the complete string identifying the file with the data set
path = getenv("G4PARTICLEXSDATA");
if (!path) {
G4Exception("G4ParticleInelasticXS::Initialise(..)","had013",
const G4PhysicsVector* pv = data->GetElementData(Z);
if(!pv) {
InitialiseOnFly(Z);
pv = data->GetElementData(Z);
}
return pv;
}
const G4String& G4ParticleInelasticXS::FindDirectoryPath()
{
// check environment variable
// build the complete string identifying the file with the data set
if(gDataDirectory.empty()) {
char* path = std::getenv("G4PARTICLEXSDATA");
if (path) {
std::ostringstream ost;
ost << path << "/" << particle->GetParticleName() << "/inel";
gDataDirectory = ost.str();
} else {
G4Exception("G4NeutronInelasticXS::Initialise(..)","had013",
FatalException,
"Environment variable G4PARTICLEXSDATA is not defined");
return;
"Environment variable G4PARTICLEXSDATA is not defined");
}
}
return gDataDirectory;
}
void G4ParticleInelasticXS::InitialiseOnFly(G4int Z)
{
#ifdef G4MULTITHREADED
G4MUTEXLOCK(&particleInelasticXSMutex);
if(!data->GetElementData(Z)) {
#endif
Initialise(Z);
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&particleInelasticXSMutex);
#endif
}
void G4ParticleInelasticXS::Initialise(G4int Z)
{
if(data->GetElementData(Z)) { return; }
// upload element data
G4String particleName = particle->GetParticleName();
std::ostringstream ost;
ost << path << "/" << particleName << "/inel" << Z ;
ost << FindDirectoryPath() << Z ;
G4PhysicsVector* v = RetrieveVector(ost, true);
data->InitialiseForElement(Z, v);
/*
@@ -357,7 +419,7 @@ void G4ParticleInelasticXS::Initialise(G4int Z, const char* p)
for(G4int A=amin[Z]; A<=amax[Z]; ++A) {
std::ostringstream ost1;
ost1 << path << "/" << particleName << "/inel" << Z << "_" << A;
ost1 << gDataDirectory << Z << "_" << A;
G4PhysicsVector* v1 = RetrieveVector(ost1, false);
data->AddComponent(Z, A, v1);
}
@@ -366,13 +428,13 @@ void G4ParticleInelasticXS::Initialise(G4int Z, const char* p)
G4double sig1 = (*v)[v->GetVectorLength()-1];
G4double sig2 = 0.0;
G4double ehigh = v->GetMaxEnergy();
G4double Amean = fNist->GetAtomicMassAmu(Z);
aeff[Z] = fNist->GetAtomicMassAmu(Z);
if(ggXsection) {
sig2 = ggXsection->GetInelasticElementCrossSection(particle,
ehigh, Z, Amean);
ehigh, Z, aeff[Z]);
} else {
sig2 = nnXsection->GetInelasticElementCrossSection(particle,
ehigh, Z, Amean);
ehigh, Z, aeff[Z]);
}
if(sig2 > 0.) { coeff[Z] = sig1/sig2; }
}
@@ -45,6 +45,7 @@
G4int G4UPiNuclearCrossSection::theZ[NZ] =
{2,4,6,7,8,11,13,20,26,29,42,48,50,74,82,92};
G4int G4UPiNuclearCrossSection::idxZ[93] = {0};
G4double G4UPiNuclearCrossSection::theA[NZ] = {0.0};
G4double G4UPiNuclearCrossSection::APower[93] = {0.0};
@@ -65,13 +66,7 @@ G4UPiNuclearCrossSection::G4UPiNuclearCrossSection()
piMinus = G4PionMinus::PionMinus();
aPower = 0.75;
elow = 20.0*MeV;
elowest = MeV;
G4NistManager* nist = G4NistManager::Instance();
G4Pow* g4pow = G4Pow::GetInstance();
for(G4int i=1; i<93; ++i) {
APower[i] = g4pow->powA(nist->GetAtomicMassAmu(i),aPower);
}
elow = 20.0*CLHEP::MeV;
}
G4UPiNuclearCrossSection::~G4UPiNuclearCrossSection()
@@ -107,74 +102,29 @@ G4UPiNuclearCrossSection::IsElementApplicable(const G4DynamicParticle*,
return (1 < Z);
}
G4double
G4UPiNuclearCrossSection::GetElasticCrossSection(const G4DynamicParticle* dp,
G4int Z, G4int A) const
{
G4double cross = 0.0;
const G4ParticleDefinition* part = dp->GetDefinition();
G4PhysicsTable* table = (part == piPlus) ? piPlusElastic : piMinusElastic;
if(table) {
cross = Interpolate(Z, A, dp->GetKineticEnergy(),table);
}
return cross;
}
G4double
G4UPiNuclearCrossSection::GetInelasticCrossSection(const G4DynamicParticle* dp,
G4int Z, G4int A) const
{
G4double cross = 0.0;
G4double fact = 1.0;
G4double ekin = dp->GetKineticEnergy();
G4PhysicsTable* table = nullptr;
const G4ParticleDefinition* part = dp->GetDefinition();
// Coulomb barrier
if(part == piPlus) {
if(ekin > elowest) {
table = piPlusInelastic;
if(ekin < elow) {
fact = std::sqrt((ekin-elowest)/(elow-elowest));
ekin = elow;
}
}
} else if(part == piMinus) {
table = piMinusInelastic;
ekin = std::max(ekin,elow);
}
if(table) {
cross = fact*Interpolate(Z, A, ekin, table);
}
return cross;
}
G4double G4UPiNuclearCrossSection::Interpolate(
G4int Z, G4int A, G4double ekin, G4PhysicsTable* table) const
G4int Z, G4int A, G4double e, const G4PhysicsTable* table) const
{
G4double res = 0.0;
G4int idx;
G4int iz = std::min(Z, 92);
for(idx=0; idx<NZ; ++idx) { if(theZ[idx] >= iz) break; }
if(idx >= NZ) { idx = NZ - 1; }
G4int iz2 = theZ[idx];
// G4cout << "U: iz= " << iz << " iz2= " << iz2 << " "
// << APower[iz] << " " << APower[iz2]<<G4endl;
G4double x2 = (((*table)[idx])->Value(ekin))*APower[iz]/APower[iz2];
// use only one Z
if(iz >= theZ[idx] || idx == 0) {
res = x2;
// Interpolation between Z
G4double ekin = std::max(e, elow);
G4int iz = std::min(Z, 92);
G4int idx = idxZ[iz];
size_t jdx = (size_t)(std::max(ekin - elow, 0.0)*0.06);
//G4cout << "Interpolate: Z= " << iz << " A= " << A << " idx= " << idx
// << " jdx= " << jdx << " Ekin= " << ekin << G4endl;
if(idx < 0 || 2 == iz) {
res = ((*table)[std::abs(idx)])->Value(ekin, jdx);
//G4cout << "1: jdx= " << jdx << G4endl;
} else {
G4int iz2 = theZ[idx];
G4double x2 = (((*table)[idx])->Value(ekin, jdx))*APower[iz]/APower[iz2];
//G4cout << "2: jdx= " << jdx << G4endl;
G4int iz1 = theZ[idx-1];
G4double x1 = (((*table)[idx-1])->Value(ekin))*APower[iz]/APower[iz1];
G4double w1 = G4double(A) - theA[idx-1];
G4double w2 = theA[idx] - G4double(A);
res = (w1*x2 + w2*x1)/(w1 + w2);
G4double x1 = (((*table)[idx-1])->Value(ekin, jdx))*APower[iz]/APower[iz1];
G4double w1 = ((G4double)A - theA[idx-1])/(theA[idx] - theA[idx-1]);
res = w1*x2 + (1.0 - w1)*x1;
}
//G4cout << " res(nb)= " << res/CLHEP::barn << G4endl;
return res;
}
@@ -218,6 +168,8 @@ void G4UPiNuclearCrossSection::DumpPhysicsTable(const G4ParticleDefinition& p)
void G4UPiNuclearCrossSection::BuildPhysicsTable(const G4ParticleDefinition& p)
{
//G4cout << "G4UPiNuclearCrossSection::BuildPhysicsTable for "
// << p.GetParticleName() << " " << piPlusElastic << G4endl;
if(piPlusElastic) { return; }
if(&p != piPlus && &p != piMinus) {
@@ -243,9 +195,22 @@ void G4UPiNuclearCrossSection::BuildPhysicsTable(const G4ParticleDefinition& p)
if(!isMaster) { return; }
G4NistManager* nist = G4NistManager::Instance();
G4Pow* g4pow = G4Pow::GetInstance();
for(G4int i=0; i<NZ; ++i) {
theA[i] = nist->GetAtomicMassAmu(theZ[i]);
}
for(G4int i=1; i<93; ++i) {
APower[i] = g4pow->powA(nist->GetAtomicMassAmu(i),aPower);
}
G4int idx = 1;
for(G4int i=3; i<93; ++i) {
if(theZ[idx] == i) {
idxZ[i] = -idx;
++idx;
} else {
idxZ[i] = idx;
}
}
piPlusElastic = new G4PhysicsTable();
piPlusInelastic = new G4PhysicsTable();
@@ -253,6 +218,7 @@ void G4UPiNuclearCrossSection::BuildPhysicsTable(const G4ParticleDefinition& p)
piMinusInelastic = new G4PhysicsTable();
LoadData();
//G4cout << "### Initialisation done " << G4endl;
}
void G4UPiNuclearCrossSection::LoadData()