Import Geant4 11.4.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2025-06-26 09:17:29 +02:00
parent 20a218bbe1
commit a499fb82e9
1941 changed files with 203285 additions and 95593 deletions
@@ -6,6 +6,41 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-05-24 Vladimir Ivanchenko (hadr-cross-V11-03-05)
- G4CrossSectionFactory, G4CrossSectionFactoryRegistry, G4CrossSectionFactory,
G4ElectroNuclearCrossSection, G4ChipsAntiBaryonElasticXS - fixed memory leak
at exit; value of memory leak is limited but may shadow real problem.
## 2025-05-22 Vladimir Ivanchenko (hadr-cross-V11-03-04)
- G4ChargeExchangeXS - added extra method for sampling of scattering angle,
update parameterisation using new fit to data.
## 2025-04-15 Vladimir Ivanchenko (hadr-cross-V11-03-03)
- G4ChargeExchangeXS - fixed selection of reaction for compound materials,
for that extra public and private methods are added.
## 2025-03-31 Vladimir Ivanchenko (hadr-cross-V11-03-02)
- G4ParticleInelasticXS - fixed trivial Coverity warning.
- G4EMDissociationCrossSection - fixed several technical inaccuracy of the
code to address Coverity warning and to use G4Pow correctly.
- G4EMDissociationSpectrum - added protection against beta=0, which should never
happen but needed for Coverity; use G4Pow more correctly.
## 2025-03-20 Vladimir Ivanchenko (hadr-cross-V11-03-01)
- G4NeutronInelasticXS, G4ParticleInelasticXS - enabled option for initialisation
for all Z values, which remove possible lazy initialisation if these cross
sections are used by any other model.
- G4NeutronElasticXS, G4NeutronCaptureXS - removed option to initilise all
data, because these cross sections are not used by other hadronic model.
In summary, for simple applications initialisation CPU time is increased
for about 10%, for complex applications this increase will not be seen.
No locks will be set by these cross section classes in the run time.
## 2025-02-10 Vladimir Ivanchenko (hadr-cross-V11-03-00)
- G4NeutronElasticXS, G4NeutronInelasticXS, G4ParticleInelasticXS - added
an option to download data for all elements in class constructor
avoiding lazy initialisation in run time
## 2024-11-15 Vladimir Ivanchenko (hadr-cross-V11-02-18)
- G4ChargeExchangeXS - handle special case of positive meson scattering off
Hydrogen, the cross section is propotional to the percent of deuterons
@@ -79,8 +79,13 @@ public:
void CrossSectionDescription(std::ostream&) const final;
const G4ParticleDefinition*
SampleSecondaryType(const G4ParticleDefinition*,
const G4int Z, const G4int A);
SampleSecondaryType(const G4ParticleDefinition*, const G4Material*,
G4int Z, G4int A, G4double etot);
G4double GetPartialPionXS(G4int idx);
G4double GetPionTFactor(G4int idx, const G4ParticleDefinition* part,
G4double pEtot);
void SetEnergyLimit(G4double val) { fEnergyLimit = val; };
@@ -93,6 +98,9 @@ public:
private:
G4double GetCrossSection(const G4ParticleDefinition*, const G4Material*,
G4int Z, G4double etot);
G4double ComputeDeuteronFraction(const G4Material*);
G4Pow* g4calc;
@@ -34,24 +34,31 @@
class G4VBaseXSFactory
{
public:
G4VBaseXSFactory()
{
fRegistry = G4CrossSectionFactoryRegistry::Instance();
}
virtual ~G4VBaseXSFactory() = default;
virtual G4VCrossSectionDataSet* Instantiate() = 0;
protected:
G4CrossSectionFactoryRegistry* fRegistry;
};
//Generic template XS-factory
template <typename T, int mode> class G4CrossSectionFactory : public G4VBaseXSFactory
{
public:
G4CrossSectionFactory(const G4String& name)
{
G4CrossSectionFactoryRegistry::Instance()->Register(name,this);
fRegistry->Register(name, this);
}
virtual G4VCrossSectionDataSet* Instantiate()
G4VCrossSectionDataSet* Instantiate() override
{
G4ExceptionDescription msg;
msg<<"Factory mode: "<<mode<<" not supported!";
@@ -66,15 +73,15 @@ template <typename T> class G4CrossSectionFactory<T,0> : public G4VBaseXSFactory
{
public:
G4CrossSectionFactory(const G4String& name)
{
G4CrossSectionFactoryRegistry::Instance()->Register(name,this);
}
virtual G4VCrossSectionDataSet* Instantiate()
{
return new T();
}
G4CrossSectionFactory(const G4String& name)
{
fRegistry->Register(name, this);
}
G4VCrossSectionDataSet* Instantiate() override
{
return new T();
}
};
//Partial specialized template for singleton, shared factory
@@ -82,32 +89,32 @@ public:
template <typename T> class G4CrossSectionFactory<T,1> : public G4VBaseXSFactory
{
public:
G4CrossSectionFactory(const G4String& name)
{
G4CrossSectionFactoryRegistry::Instance()->Register(name,this);
}
virtual G4VCrossSectionDataSet* Instantiate()
{
static T* shared = new T();
return shared;
}
G4CrossSectionFactory(const G4String& name)
{
fRegistry->Register(name,this);
}
G4VCrossSectionDataSet* Instantiate() override
{
static T* shared = new T();
return shared;
}
};
//Partial specialized template for singleton, shared factory
// each call to Instantiate returns pointer to static thread-local object
template <typename T> class G4CrossSectionFactory<T,2> : public G4VBaseXSFactory
{
G4CrossSectionFactory(const G4String& name)
{
G4CrossSectionFactoryRegistry::Instance()->Register(name,this);
}
virtual G4VCrossSectionDataSet* Instantiate()
{
static G4ThreadLocal T* shared = new T();
return shared;
}
G4CrossSectionFactory(const G4String& name)
{
fRegistry->Register(name,this);
}
G4VCrossSectionDataSet* Instantiate() override
{
static G4ThreadLocal T* shared = new T();
return shared;
}
};
@@ -47,19 +47,27 @@ class G4VBaseXSFactory;
class G4CrossSectionFactoryRegistry
{
friend std::ostream& operator<<(std::ostream&, const G4CrossSectionFactoryRegistry&);
private:
std::map<G4String, G4VBaseXSFactory*> factories;
static G4CrossSectionFactoryRegistry* instance; //Note this is shared among threads
G4CrossSectionFactoryRegistry();
G4CrossSectionFactoryRegistry(const G4CrossSectionFactoryRegistry& );
G4CrossSectionFactoryRegistry& operator=(const G4CrossSectionFactoryRegistry&);
//Disable copy-ctr and assignement operator
friend std::ostream& operator<<(std::ostream&, const G4CrossSectionFactoryRegistry&);
public:
static G4CrossSectionFactoryRegistry* Instance();
G4VBaseXSFactory* GetFactory( const G4String& name , G4bool abortIfNotFound = true) const;
//Search a cross-section factory by name, by default rise an exception if factory is not found
void Register( const G4String& name , G4VBaseXSFactory* factory );
static G4CrossSectionFactoryRegistry* Instance();
~G4CrossSectionFactoryRegistry() = default;
G4VBaseXSFactory* GetFactory( const G4String& name, G4bool abortIfNotFound = true) const;
//Search a cross-section factory by name, by default rise an exception if factory is not found
void Register( const G4String& name, G4VBaseXSFactory* factory );
void DeRegister( G4VBaseXSFactory* factory );
G4CrossSectionFactoryRegistry(const G4CrossSectionFactoryRegistry&) = delete;
G4CrossSectionFactoryRegistry& operator=(const G4CrossSectionFactoryRegistry&) = delete;
private:
G4CrossSectionFactoryRegistry();
std::map<G4String, G4VBaseXSFactory*> factories;
static G4CrossSectionFactoryRegistry* instance; //Note this is shared among threads
};
std::ostream& operator<<(std::ostream& msg, const G4CrossSectionFactoryRegistry& rhs);
@@ -60,16 +60,16 @@ class G4ElectroNuclearCrossSection : public G4VCrossSectionDataSet
public:
G4ElectroNuclearCrossSection();
virtual ~G4ElectroNuclearCrossSection();
~G4ElectroNuclearCrossSection() override;
static const char* Default_Name() {return "ElectroNuclearXS";}
virtual void CrossSectionDescription(std::ostream&) const;
void CrossSectionDescription(std::ostream&) const override;
virtual G4bool IsElementApplicable(const G4DynamicParticle*, G4int Z,
const G4Material*);
virtual G4double GetElementCrossSection(const G4DynamicParticle*, G4int Z,
const G4Material* mat);
G4bool IsElementApplicable(const G4DynamicParticle*, G4int Z,
const G4Material*) override;
G4double GetElementCrossSection(const G4DynamicParticle*, G4int Z,
const G4Material* mat) override;
G4double GetEquivalentPhotonEnergy();
@@ -77,6 +77,10 @@ public:
G4double GetEquivalentPhotonQ2(G4double nu);
G4ElectroNuclearCrossSection& operator=
(const G4ElectroNuclearCrossSection &right) = delete;
G4ElectroNuclearCrossSection(const G4ElectroNuclearCrossSection&) = delete;
private:
G4int GetFunctions(G4double a, G4double* x, G4double* y, G4double* z);
@@ -44,8 +44,8 @@
#include "G4VCrossSectionDataSet.hh"
#include "globals.hh"
#include "G4ElementData.hh"
#include "G4PhysicsVector.hh"
#include <vector>
class G4DynamicParticle;
class G4ParticleDefinition;
@@ -58,7 +58,7 @@ public:
G4NeutronElasticXS();
~G4NeutronElasticXS() final;
~G4NeutronElasticXS() override = default;
static const char* Default_Name() {return "G4NeutronElasticXS";}
@@ -97,7 +97,7 @@ public:
G4double ElementCrossSection(G4double kinEnergy, G4double loge, G4int Z);
G4NeutronElasticXS & operator=(const G4NeutronElasticXS &right) = delete;
G4NeutronElasticXS& operator=(const G4NeutronElasticXS &right) = delete;
G4NeutronElasticXS(const G4NeutronElasticXS&) = delete;
private:
@@ -108,25 +108,30 @@ private:
const G4String& FindDirectoryPath();
inline G4PhysicsVector* GetPhysicsVector(G4int Z);
inline const G4PhysicsVector* GetPhysicsVector(G4int Z);
G4VComponentCrossSection* ggXsection = nullptr;
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
G4VComponentCrossSection* ggXsection{nullptr};
const G4ParticleDefinition* neutron;
G4bool isFirst = false;
G4bool isInitializer{false};
static const G4int MAXZEL = 93;
static G4PhysicsVector* data[MAXZEL];
static G4ElementData* data;
static G4double coeff[MAXZEL];
static G4String gDataDirectory;
static G4bool fLock;
};
inline
inline const
G4PhysicsVector* G4NeutronElasticXS::GetPhysicsVector(G4int Z)
{
if(nullptr == data[Z]) { InitialiseOnFly(Z); }
return data[Z];
const G4PhysicsVector* pv = data->GetElementData(Z);
if (pv == nullptr) {
InitialiseOnFly(Z);
pv = data->GetElementData(Z);
}
return pv;
}
#endif
@@ -107,6 +107,8 @@ private:
void Initialise(G4int Z);
void InitialiseOnFly(G4int Z);
inline const G4PhysicsVector* GetPhysicsVector(G4int Z);
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
@@ -130,7 +132,7 @@ const G4PhysicsVector* G4ParticleInelasticXS::GetPhysicsVector(G4int Z)
{
const G4PhysicsVector* pv = data[index]->GetElementData(Z);
if (pv == nullptr) {
Initialise(Z);
InitialiseOnFly(Z);
pv = data[index]->GetElementData(Z);
}
return pv;
@@ -53,14 +53,22 @@
namespace {
// V. Lyubovitsky parameterisation
const G4double piA[5] = {430., 36., 1.37, 2.0, 60.}; // A
const G4double pAP[5] = {1.04, 1.26, 1.35, 0.94, 0.94}; // 2 - 2alphaP
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
const G4double pG0[5] = {2.55, 4.6, 3.7, 5.5, 4.6}; // g0
const G4double pG1[5] = {-0.23, -0.5, 0., 0., -2.}; // g1
const G4double beta_prime_pi = 0.0410;
// parameterisation of intranuclear absorption
const G4double beta_prime_pi = 0.0036;
// For unit conversion
const G4double inv1e7 = 0.1/(CLHEP::GeV*CLHEP::GeV);
const G4double fact = 1e-30*CLHEP::cm2;
const G4double pfact = 0.1/CLHEP::GeV;
const G4double kfact = 56.3*fact;
const G4double csmax = 1e-16;
}
G4ChargeExchangeXS::G4ChargeExchangeXS()
@@ -96,20 +104,25 @@ G4bool G4ChargeExchangeXS::IsElementApplicable(const G4DynamicParticle*,
}
G4double
G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
G4int ZZ, const G4Material* mat)
G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* dp,
G4int Z, const G4Material* mat)
{
G4double pE = dp->GetTotalEnergy();
return (pE > fEnergyLimit) ?
GetCrossSection(dp->GetDefinition(), mat, Z, pE) : 0.0;
}
G4double G4ChargeExchangeXS::GetCrossSection(const G4ParticleDefinition* part,
const G4Material* mat,
G4int ZZ, G4double pEtot)
{
G4double result = 0.0;
const G4double pE = aParticle->GetTotalEnergy();
if (pE <= fEnergyLimit) { return result; }
auto part = aParticle->GetDefinition();
G4int pdg = part->GetPDGEncoding();
// Get or calculate the proton mass, particle mass, and s(Lorentz invariant)
G4double tM = CLHEP::proton_mass_c2;
G4double pM = part->GetPDGMass();
G4double lorentz_s = tM*tM + 2*tM*pE + pM*pM;
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);
@@ -117,20 +130,15 @@ G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
if (verboseLevel > 1) {
G4cout << "### G4ChargeExchangeXS: " << part->GetParticleName()
<< " Z=" << Z << " A=" << A << " Etot(GeV)=" << pE/CLHEP::GeV
<< " Z=" << Z << " A=" << A << " Etot(GeV)=" << pEtot/CLHEP::GeV
<< " s(GeV^2)=" << lorentz_s/(CLHEP::GeV*CLHEP::GeV) << G4endl;
}
// For unit conversion
const G4double inv1e7 = 0.1/(CLHEP::GeV*CLHEP::GeV);
const G4double fact = 1e-30*CLHEP::cm2;
const G4double pfact = 0.1/CLHEP::GeV;
const G4double kfact = 56.3*fact;
const G4double csmax = 1e-16;
// 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 pi0 and eta
// takes into account absorption of mesons within the nucleus
// pi- + p -> n + meson (0- pi0, 1- eta, 2- eta', 3- omega, 4- f2(1270))
if (pdg == -211) {
@@ -138,7 +146,7 @@ G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
G4double x = lorentz_s*inv1e7;
G4double logX = G4Log(x);
G4double logA = g4calc->logZ(A);
G4double xf = g4calc->powZ(A, -beta_prime_pi*logA);
G4double xf = fact*g4calc->powZ(A, -beta_prime_pi*(logA + 2*logA));
G4double sum = 0.0;
for (G4int i=0; i<5; ++i) {
G4double xg = std::max(1.0 + pG0[i] + pG1[i]*logX, 0.0);
@@ -147,7 +155,7 @@ G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
sum += xs;
fXSecPion[i] = sum;
}
result = sum*fact;
result = sum;
}
// pi+ + n -> p + meson (0- pi0, 1- eta, 2- eta', 3- omega, 4- f2(1270))
@@ -156,7 +164,7 @@ G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
G4double x = lorentz_s*inv1e7;
G4double logX = G4Log(x);
G4double logA = g4calc->logZ(A);
G4double xf = g4calc->powZ(A, -beta_prime_pi*logA);
G4double xf = fact*g4calc->powZ(A, -beta_prime_pi*(logA + 2*logA));
// hydrogen target case Z = A = 1
// the cross section is defined by fraction of deuteron and tritium
@@ -169,19 +177,19 @@ G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
sum += xs;
fXSecPion[i] = sum;
}
result = sum*fact;
result = sum;
}
// Kaon x-sections depend on the primary particles momentum
// K- + p -> Kbar + n
else if (pdg == -321) {
G4double p_momentum = std::sqrt(pE*pE - pM*pM)*pfact;
G4double p_momentum = std::sqrt(pEtot*pEtot - pM*pM)*pfact;
result = g4calc->Z23(Z)*g4calc->powA(p_momentum, -1.60)*kfact;
}
// K+ + n -> Kbar + p
else if (pdg == 321) {
G4double p_momentum = std::sqrt(pE*pE - pM*pM)*pfact;
G4double p_momentum = std::sqrt(pEtot*pEtot - pM*pM)*pfact;
G4double n23 = g4calc->Z23(A-Z);
// hydrogen target case Z = A = 1
// the cross section is defined by fraction of deuteron and tritium
@@ -192,13 +200,14 @@ G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
// KL
else if (pdg == 130) {
// Cross section of KL = 0.5*(Cross section of K+ + Cross section of K-)
const G4double p_momentum = std::sqrt(pE*pE - pM*pM)*pfact;
const G4double p_momentum = std::sqrt(pEtot*pEtot - pM*pM)*pfact;
result = 0.5*(g4calc->Z23(Z) + g4calc->Z23(A-Z))*
g4calc->powA(p_momentum, -1.60)*kfact;
}
result *= fFactor;
if (verboseLevel > 1) {
G4cout << " Done for " << part->GetParticleName() << " Etot(GeV)=" << pE/CLHEP::GeV
G4cout << " Done for " << part->GetParticleName() << " Etot(GeV)="
<< pEtot/CLHEP::GeV
<< " res(mb)=" << result/CLHEP::millibarn << G4endl;
}
return result;
@@ -206,8 +215,12 @@ G4ChargeExchangeXS::GetElementCrossSection(const G4DynamicParticle* aParticle,
const G4ParticleDefinition*
G4ChargeExchangeXS::SampleSecondaryType(const G4ParticleDefinition* part,
const G4int Z, const G4int A)
const G4Material* mat,
G4int Z, G4int A, G4double etot)
{
// recompute x-section for the element in complex material
GetCrossSection(part, mat, Z, etot);
const G4ParticleDefinition* pd = nullptr;
G4int pdg = std::abs(part->GetPDGEncoding());
@@ -265,3 +278,26 @@ G4ChargeExchangeXS::ComputeDeuteronFraction(const G4Material* mat)
}
return 0.0;
}
G4double G4ChargeExchangeXS::GetPartialPionXS(G4int idx)
{
G4double res = 0.0;
if (0 == idx) { res = fXSecPion[0]; }
else if (0 < idx && 5 > idx) {
res = fXSecPion[idx] - fXSecPion[idx - 1];
}
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;
}
@@ -64,7 +64,6 @@ G4_REFERENCE_XS_FACTORY(G4ChipsPionMinusInelasticXS);
G4_REFERENCE_XS_FACTORY(G4ChipsPionMinusElasticXS);
G4_REFERENCE_XS_FACTORY(G4ChipsAntiBaryonInelasticXS);
G4_REFERENCE_XS_FACTORY(G4ChipsAntiBaryonElasticXS);
G4_REFERENCE_XS_FACTORY(G4ElectroNuclearCrossSection);
G4ThreadLocal G4CrossSectionDataSetRegistry* G4CrossSectionDataSetRegistry::instance = nullptr;
@@ -164,8 +163,8 @@ G4VCrossSectionDataSet*
G4CrossSectionDataSetRegistry::GetCrossSectionDataSet(const G4String& name,
G4bool warning)
{
for (auto & xsec : xSections) {
if(nullptr != xsec && xsec->GetName() == name) { return xsec; }
for (auto const & xsec : xSections) {
if (nullptr != xsec && xsec->GetName() == name) { return xsec; }
}
// check if factory exists...
//
@@ -174,7 +173,7 @@ G4CrossSectionDataSetRegistry::GetCrossSectionDataSet(const G4String& name,
// This throws if factory is not found, add second parameter
// to false to avoid this
G4VBaseXSFactory* factory = factories->GetFactory(name, warning );
if ( factory ) {
if (nullptr != factory ) {
return factory->Instantiate();
} else {
G4VCrossSectionDataSet* ptr = nullptr;
@@ -32,73 +32,63 @@
#include "G4AutoLock.hh"
#include "globals.hh"
//This is used to lock on shared resource
// G4TypeMutex<G4CrossSectionFactoryRegistry>()
namespace
{
G4Mutex regMutex = G4MUTEX_INITIALIZER;
}
G4CrossSectionFactoryRegistry* G4CrossSectionFactoryRegistry::instance = 0;
G4CrossSectionFactoryRegistry* G4CrossSectionFactoryRegistry::Instance()
{
G4AutoLock l(G4TypeMutex<G4CrossSectionFactoryRegistry>());
if (!instance)
new G4CrossSectionFactoryRegistry();
return instance;
static G4CrossSectionFactoryRegistry reg;
return &reg;
}
G4CrossSectionFactoryRegistry::G4CrossSectionFactoryRegistry()
{
instance = this;
}
G4CrossSectionFactoryRegistry::G4CrossSectionFactoryRegistry(const G4CrossSectionFactoryRegistry&)
{
G4Exception("G4CrossSectionFactoryRegistry::G4CrossSectionFactoryRegistry",
"CrossSection004",FatalException,"Use of copy constructor not allowed");
}
G4CrossSectionFactoryRegistry& G4CrossSectionFactoryRegistry::operator=(const G4CrossSectionFactoryRegistry&)
{
G4Exception("G4CrossSectionFactoryRegistry::G4CrossSectionFactoryRegistry",
"CrossSection004",FatalException,"Use of assignment operator not allowed");
return *this;
}
{}
void G4CrossSectionFactoryRegistry::Register( const G4String& name, G4VBaseXSFactory* factory )
{
G4AutoLock l(G4TypeMutex<G4CrossSectionFactoryRegistry>());
if ( factories.find(name) != factories.end() )
{
G4ExceptionDescription msg;
msg <<"Cross section factory with name: "<<name
<<" already existing, old factory has been replaced";
G4Exception("G4CrossSectionFactoryRegistry::Register(...)",
"CrossSection002",JustWarning,msg);
if ( factories.find(name) == factories.end() ) {
G4AutoLock l(regMutex);
if ( factories.find(name) == factories.end() ) {
factories[name] = factory;
}
factories[name] = factory;
l.unlock();
}
}
G4VBaseXSFactory* G4CrossSectionFactoryRegistry::GetFactory( const G4String& name, G4bool abortIfNotFound ) const
void G4CrossSectionFactoryRegistry::DeRegister( G4VBaseXSFactory* factory )
{
G4AutoLock l(G4TypeMutex<G4CrossSectionFactoryRegistry>());
std::map<G4String,G4VBaseXSFactory*>::const_iterator it = factories.find(name);
if ( it != factories.end() ) return it->second;
else
{
if ( abortIfNotFound )
{
G4ExceptionDescription msg;
msg <<"Cross section factory with name: "<<name
<<" not found.";
G4Exception("G4CrossSectionFactoryRegistry::Register(...)",
"CrossSection003",FatalException,msg);
}
if ( nullptr == factory || factories.empty() ) { return; }
G4AutoLock l(regMutex);
for ( auto const & f : factories ) {
if ( factory == f.second ) {
factories[f.first] = nullptr;
}
return static_cast<G4VBaseXSFactory*>(0);
}
l.unlock();
}
G4VBaseXSFactory*
G4CrossSectionFactoryRegistry::GetFactory( const G4String& name, G4bool abortIfNotFound ) const
{
G4VBaseXSFactory* ptr = nullptr;
auto it = factories.find(name);
if ( it != factories.end() ) {
ptr = it->second;
} else if ( abortIfNotFound ) {
G4ExceptionDescription msg;
msg << "Cross section factory with name: " << name << " not found.";
G4Exception("G4CrossSectionFactoryRegistry::GetFactory(...)",
"CrossSection003", FatalException, msg);
}
return ptr;
}
std::ostream& operator<<(std::ostream& msg, const G4CrossSectionFactoryRegistry& rhs) {
msg<<"Factory Registry "<<&rhs<<" has factories: [";
for ( std::map<G4String,G4VBaseXSFactory*>::const_iterator it =rhs.factories.begin() ;
it != rhs.factories.end() ; ++it )
msg<<"Factory Registry "<<&rhs<<" has factories: [";
for ( std::map<G4String,G4VBaseXSFactory*>::const_iterator it =rhs.factories.begin();
it != rhs.factories.end() ; ++it )
{
msg<<(*it).first<<":"<<(*it).second<<",";
}
@@ -102,28 +102,16 @@ G4EMDissociationCrossSection::~G4EMDissociationCrossSection()
/////////////////////////////////////////////////////////////////////////////
//
G4bool
G4EMDissociationCrossSection::IsElementApplicable(const G4DynamicParticle* part,
G4EMDissociationCrossSection::IsElementApplicable(const G4DynamicParticle*,
G4int /*ZZ*/, const G4Material*)
{
//
// The condition for the applicability of this class is that the projectile
// must be an ion and the target must have more than one nucleon. In reality
// the value of A for either the projectile or target could be much higher,
// since for cases where both he projectile and target are medium to small
// Z, the probability of the EMD process is, I think, VERY small.
//
if (G4ParticleTable::GetParticleTable()->GetIonTable()->IsIon(part->GetDefinition())) {
return true;
} else {
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////
//
G4double G4EMDissociationCrossSection::GetElementCrossSection
(const G4DynamicParticle* theDynamicParticle, G4int Z,
const G4Material*)
(const G4DynamicParticle* theDynamicParticle, G4int Z, const G4Material*)
{
// VI protection for Hydrogen
if(1 >= Z) { return 0.0; }
@@ -79,44 +79,46 @@ G4EMDissociationSpectrum::~G4EMDissociationSpectrum ()
////////////////////////////////////////////////////////////////////////////////
//
G4double G4EMDissociationSpectrum::GetGeneralE1Spectrum
(G4double Eg, G4double b, G4double bmin)
(G4double Eg, G4double b0, G4double bmin)
{
G4double b = std::max(b0, 1.e-6);
G4double b2 = b*b;
G4double gg = 1.0/std::sqrt(1.0-b2);
G4double xi = Eg * bmin / gg / b / hbarc;
G4double gg = 1.0/std::sqrt(1.0 - b2);
G4double xi = Eg * bmin / (gg * b * hbarc);
G4double K0 = bessel->K0(xi);
G4double K1 = bessel->K1(xi);
G4double n = 2.0 * fine_structure_const / pi / b2 / Eg *
G4double n = 2.0 * fine_structure_const / (pi * b2 * Eg) *
(xi*K0*K1 - xi*xi*b2/2.0*(K1*K1-K0*K0));
return n;
}
////////////////////////////////////////////////////////////////////////////////
//
G4double G4EMDissociationSpectrum::GetGeneralE2Spectrum
(G4double Eg, G4double b, G4double bmin)
(G4double Eg, G4double b0, G4double bmin)
{
G4double b = std::max(b0, 1.e-6);
G4double b2 = b * b;
G4double b4 = b2 * b2;
G4double gg = 1.0/std::sqrt(1.0-b2);
G4double xi = Eg * bmin / gg / b / hbarc;
G4double gg = 1.0/std::sqrt(1.0-b2);
G4double xi = Eg * bmin / (gg * b * hbarc);
G4double K0 = bessel->K0(xi);
G4double K1 = bessel->K1(xi);
G4double n = 2.0 * fine_structure_const / pi / b4 / Eg *
(2.0*(1.0-b2)*K1*K1 + xi*G4Pow::GetInstance()->powA((2.0-b2),2.0)*K0*K1 -
G4double n = 2.0 * fine_structure_const / (pi * b4 * Eg) *
(2.0*(1.0-b2)*K1*K1 + xi*(2.0-b2)*(2.0-b2)*K0*K1 -
xi*xi*b4/2.0*(K1*K1-K0*K0));
return n;
}
////////////////////////////////////////////////////////////////////////////////
//
G4double G4EMDissociationSpectrum::GetClosestApproach
(const G4double AP, const G4double ZP, G4double AT, G4double ZT, G4double b)
(const G4double AP, const G4double ZP, G4double AT, G4double ZT, G4double b0)
{
G4double bsq = b * b;
G4double gg = 1.0/std::sqrt(1-bsq);
G4double AProot3 = G4Pow::GetInstance()->powA(AP,1.0/3.0);
G4double ATroot3 = G4Pow::GetInstance()->powA(AT,1.0/3.0);
G4double b = std::max(b0, 1.e-6);
G4double bsq = b * b;
G4double gg = 1.0/std::sqrt(1. - bsq);
G4double AProot3 = G4Pow::GetInstance()->A13(AP);
G4double ATroot3 = G4Pow::GetInstance()->A13(AT);
G4double bc = 1.34 * fermi * (AProot3+ATroot3 - 0.75 *(1.0/AProot3+1.0/ATroot3));
// G4double a0 = ZP * ZT * classic_electr_radius/bsq;
G4double a0 = ZP * ZT * elm_coupling / (AT*AP*amu_c2/(AT+AP)) / bsq;
G4double bmin = 1.25 * bc + halfpi*a0/gg;
return bmin;
@@ -46,9 +46,9 @@
#include "G4ElectroNuclearCrossSection.hh"
// factory
#include "G4CrossSectionFactory.hh"
//#include "G4CrossSectionFactory.hh"
//
G4_DECLARE_XS_FACTORY(G4ElectroNuclearCrossSection);
//G4_DECLARE_XS_FACTORY(G4ElectroNuclearCrossSection);
//
//A. Dotti 2-May-2013
@@ -53,10 +53,11 @@
#include <fstream>
#include <sstream>
G4PhysicsVector* G4NeutronElasticXS::data[] = {nullptr};
G4double G4NeutronElasticXS::coeff[] = {0.0};
G4ElementData* G4NeutronElasticXS::data = nullptr;
G4double G4NeutronElasticXS::coeff[] = {1.0};
G4String G4NeutronElasticXS::gDataDirectory = "";
G4bool G4NeutronElasticXS::fLock = true;
static std::once_flag applyOnce;
namespace
{
@@ -67,8 +68,7 @@ G4NeutronElasticXS::G4NeutronElasticXS()
: G4VCrossSectionDataSet(Default_Name()),
neutron(G4Neutron::Neutron())
{
// verboseLevel = 0;
if (verboseLevel > 0){
if (verboseLevel > 0) {
G4cout << "G4NeutronElasticXS::G4NeutronElasticXS Initialise for Z < "
<< MAXZEL << G4endl;
}
@@ -77,16 +77,10 @@ G4NeutronElasticXS::G4NeutronElasticXS()
if (ggXsection == nullptr)
ggXsection = new G4ComponentGGHadronNucleusXsc();
SetForAllAtomsAndEnergies(true);
FindDirectoryPath();
}
G4NeutronElasticXS::~G4NeutronElasticXS()
{
if (isFirst) {
for(G4int i=0; i<MAXZEL; ++i) {
delete data[i];
data[i] = nullptr;
}
if (nullptr == data) {
data = new G4ElementData(MAXZEL);
data->SetName("nElastic");
FindDirectoryPath();
}
}
@@ -130,9 +124,10 @@ G4NeutronElasticXS::ComputeCrossSectionPerElement(G4double ekin, G4double loge,
return ElementCrossSection(ekin, loge, elm->GetZasInt());
}
G4double G4NeutronElasticXS::ElementCrossSection(G4double ekin, G4double loge, G4int ZZ)
G4double
G4NeutronElasticXS::ElementCrossSection(G4double ekin, G4double loge, G4int ZZ)
{
G4int Z = (ZZ >= MAXZEL) ? MAXZEL - 1 : ZZ;
G4int Z = std::min(ZZ, MAXZEL-1);
auto pv = GetPhysicsVector(Z);
G4double xs = (ekin <= pv->GetMaxEnergy()) ? pv->LogVectorValue(ekin, loge)
@@ -152,19 +147,21 @@ G4double G4NeutronElasticXS::ElementCrossSection(G4double ekin, G4double loge, G
G4double
G4NeutronElasticXS::ComputeIsoCrossSection(G4double ekin, G4double loge,
const G4ParticleDefinition*,
G4int Z, G4int A,
G4int ZZ, G4int A,
const G4Isotope*, const G4Element*,
const G4Material*)
{
G4int Z = std::min(ZZ, MAXZEL-1);
return ElementCrossSection(ekin, loge, Z)*A/aeff[Z];
}
G4double
G4NeutronElasticXS::GetIsoCrossSection(const G4DynamicParticle* aParticle,
G4int Z, G4int A,
G4int ZZ, G4int A,
const G4Isotope*, const G4Element*,
const G4Material*)
{
G4int Z = std::min(ZZ, MAXZEL-1);
return ElementCrossSection(aParticle->GetKineticEnergy(),
aParticle->GetLogKineticEnergy(), Z)*A/aeff[Z];
@@ -176,7 +173,6 @@ const G4Isotope* G4NeutronElasticXS::SelectIsotope(
G4int nIso = (G4int)anElement->GetNumberOfIsotopes();
const G4Isotope* iso = anElement->GetIsotope(0);
//G4cout << "SelectIsotope NIso= " << nIso << G4endl;
if(1 == nIso) { return iso; }
const G4double* abundVector = anElement->GetRelativeAbundanceVector();
@@ -209,19 +205,17 @@ G4NeutronElasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
FatalException, ed, "");
return;
}
if (fLock || isFirst) {
// initialise static tables only once
std::call_once(applyOnce, [this]() { isInitializer = true; });
if (isInitializer) {
G4AutoLock l(&nElasticXSMutex);
if (fLock) {
isFirst = true;
fLock = false;
FindDirectoryPath();
}
// Access to elements
const G4ElementTable* table = G4Element::GetElementTable();
for ( auto & elm : *table ) {
for ( auto const & elm : *table ) {
G4int Z = std::max( 1, std::min( elm->GetZasInt(), MAXZEL-1) );
if ( nullptr == data[Z] ) { Initialise(Z); }
if ( nullptr == data->GetElementData(Z) ) { Initialise(Z); }
}
l.unlock();
}
@@ -247,40 +241,49 @@ void G4NeutronElasticXS::InitialiseOnFly(G4int Z)
void G4NeutronElasticXS::Initialise(G4int Z)
{
if(data[Z] != nullptr) { return; }
// upload data from file
data[Z] = new G4PhysicsLogVector();
if (nullptr != data->GetElementData(Z)) { return; }
// upload element data
std::ostringstream ost;
ost << FindDirectoryPath() << Z ;
std::ifstream filein(ost.str().c_str());
if (!filein.is_open()) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not opened!";
G4Exception("G4NeutronElasticXS::Initialise(..)","had014",
FatalException, ed, "Check G4PARTICLEXSDATA");
return;
}
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;
}
ost << FindDirectoryPath() << Z;
G4PhysicsVector* v = RetrieveVector(ost, true);
data->InitialiseForElement(Z, v);
// smooth transition
G4double sig1 = (*(data[Z]))[data[Z]->GetVectorLength()-1];
G4double ehigh = data[Z]->GetMaxEnergy();
G4double sig2 = ggXsection->GetElasticElementCrossSection(neutron,
ehigh, Z, aeff[Z]);
G4double sig1 = (*v)[v->GetVectorLength()-1];
G4double ehigh = v->GetMaxEnergy();
G4double sig2 =
ggXsection->GetElasticElementCrossSection(neutron, ehigh, Z, aeff[Z]);
coeff[Z] = (sig2 > 0.) ? sig1/sig2 : 1.0;
}
G4PhysicsVector*
G4NeutronElasticXS::RetrieveVector(std::ostringstream& ost, G4bool warn)
{
G4PhysicsLogVector* v = nullptr;
std::ifstream filein(ost.str().c_str());
if (!filein.is_open()) {
if (warn) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not opened!";
G4Exception("G4NeutronElasticXS::RetrieveVector(..)","had014",
FatalException, ed, "Check G4PARTICLEXSDATA");
}
} else {
if (verboseLevel > 1) {
G4cout << "File " << ost.str()
<< " is opened by G4NeutronElasticXS" << G4endl;
}
// retrieve data from DB
v = new G4PhysicsLogVector();
if (!v->Retrieve(filein, true)) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not retrieved!";
G4Exception("G4NeutronElasticXS::RetrieveVector(..)","had015",
FatalException, ed, "Check G4PARTICLEXSDATA");
}
}
return v;
}
@@ -78,15 +78,17 @@ G4NeutronInelasticXS::G4NeutronInelasticXS()
<< MAXZINEL << G4endl;
}
loglowElimit = G4Log(lowElimit);
ggXsection =
G4CrossSectionDataSetRegistry::Instance()->GetComponentCrossSection("Glauber-Gribov");
if (ggXsection == nullptr)
ggXsection = new G4ComponentGGHadronNucleusXsc();
if (nullptr == data) {
data = new G4ElementData(MAXZINEL);
data->SetName("nInelastic");
FindDirectoryPath();
for (G4int Z=1; Z<MAXZINEL; ++Z) { Initialise(Z); }
}
ggXsection =
G4CrossSectionDataSetRegistry::Instance()->GetComponentCrossSection("Glauber-Gribov");
if(ggXsection == nullptr)
ggXsection = new G4ComponentGGHadronNucleusXsc();
SetForAllAtomsAndEnergies(true);
}
@@ -199,19 +201,28 @@ G4NeutronInelasticXS::IsoCrossSection(G4double eKin, G4double logE,
G4double ekin = eKin;
G4double loge = logE;
/*
G4cout << "G4NeutronInelasticXS::IsoCrossSection Z= "
<< Z << " A= " << A << G4endl;
G4cout << " Amin= " << amin[Z] << " Amax= " << amax[Z]
<< " E(MeV)= " << ekin << " Ncomp="
<< data->GetNumberOfComponents(Z) << G4endl;
*/
// 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;
}
#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;
}
const G4double e0 = pviso->Energy(0);
if (ekin > e0) {
xs = pviso->LogVectorValue(ekin, loge);
@@ -277,8 +288,6 @@ const G4Isotope* G4NeutronInelasticXS::SelectIsotope(
if(nn < nIso) { temp.resize(nIso, 0.); }
for (j=0; j<nIso; ++j) {
// G4cout << j << "-th isotope " << anElement->GetIsotope(j)->GetN()
// << " abund= " << abundVector[j] << G4endl;
sum += abundVector[j]*IsoCrossSection(kinEnergy, logE, Z,
anElement->GetIsotope((G4int)j)->GetN());
temp[j] = sum;
@@ -71,6 +71,7 @@ G4ParticleInelasticXS::G4ParticleInelasticXS(const G4ParticleDefinition* part)
particle(part),
elimit(20*CLHEP::MeV)
{
auto xsr = G4CrossSectionDataSetRegistry::Instance();
if (nullptr == part) {
G4Exception("G4ParticleInelasticXS::G4ParticleInelasticXS(..)","had015",
FatalException, "NO particle definition in constructor");
@@ -81,7 +82,6 @@ G4ParticleInelasticXS::G4ParticleInelasticXS(const G4ParticleDefinition* part)
G4cout << "G4ParticleInelasticXS::G4ParticleInelasticXS for "
<< particleName << " on atoms with Z < " << MAXZINELP << G4endl;
}
auto xsr = G4CrossSectionDataSetRegistry::Instance();
if (particleName == "proton") {
highEnergyXsection = xsr->GetComponentCrossSection("Glauber-Gribov");
if(highEnergyXsection == nullptr) {
@@ -100,6 +100,10 @@ G4ParticleInelasticXS::G4ParticleInelasticXS(const G4ParticleDefinition* part)
if (1 < index) { SetMaxKinEnergy(25.6*CLHEP::PeV); }
}
}
// this should never happens but ...
if (nullptr == highEnergyXsection) {
highEnergyXsection = xsr->GetComponentCrossSection("Glauber-Gribov");
}
SetForAllAtomsAndEnergies(true);
if (gDataDirectory.empty()) {
gDataDirectory = G4HadronicParameters::Instance()->GetDirPARTICLEXS();
@@ -109,6 +113,7 @@ G4ParticleInelasticXS::G4ParticleInelasticXS(const G4ParticleDefinition* part)
if (data[index] == nullptr) {
data[index] = new G4ElementData(MAXZINELP);
data[index]->SetName(pname[index] + "PartInel");
for (G4int Z=1; Z<MAXZINELP; ++Z) { Initialise(Z); }
}
}
@@ -320,53 +325,55 @@ G4ParticleInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p)
if (n > nIso) { nIso = n; }
G4int Z = std::min( elm->GetZasInt(), MAXZINELP-1);
if ( nullptr == (data[index])->GetElementData(Z) ) {
Initialise(Z);
InitialiseOnFly(Z);
}
}
temp.resize(nIso, 0.0);
}
void G4ParticleInelasticXS::InitialiseOnFly(G4int Z)
{
G4AutoLock l(&pInelasticXSMutex);
Initialise(Z);
l.unlock();
}
void G4ParticleInelasticXS::Initialise(G4int Z)
{
if ( nullptr != (data[index])->GetElementData(Z) ) { return; }
G4AutoLock l(&pInelasticXSMutex);
if ( nullptr == (data[index])->GetElementData(Z) ) {
// upload element data
std::ostringstream ost;
ost << gDataDirectory << "/" << pname[index] << "/inel" << Z;
G4PhysicsVector* v = RetrieveVector(ost, true);
data[index]->InitialiseForElement(Z, v);
// upload element data
std::ostringstream ost;
ost << gDataDirectory << "/" << pname[index] << "/inel" << Z;
G4PhysicsVector* v = RetrieveVector(ost, true);
data[index]->InitialiseForElement(Z, v);
// upload isotope data
G4bool noComp = true;
if (amin[Z] < amax[Z]) {
for (G4int A=amin[Z]; A<=amax[Z]; ++A) {
std::ostringstream ost1;
ost1 << gDataDirectory << "/" << pname[index] << "/inel" << Z << "_" << A;
G4PhysicsVector* v1 = RetrieveVector(ost1, false);
if (nullptr != v1) {
if (noComp) {
G4int nmax = amax[Z] - A + 1;
data[index]->InitialiseForComponent(Z, nmax);
noComp = false;
}
data[index]->AddComponent(Z, A, v1);
// upload isotope data
G4bool noComp = true;
if (amin[Z] < amax[Z]) {
for (G4int A=amin[Z]; A<=amax[Z]; ++A) {
std::ostringstream ost1;
ost1 << gDataDirectory << "/" << pname[index] << "/inel" << Z << "_" << A;
G4PhysicsVector* v1 = RetrieveVector(ost1, false);
if (nullptr != v1) {
if (noComp) {
G4int nmax = amax[Z] - A + 1;
data[index]->InitialiseForComponent(Z, nmax);
noComp = false;
}
data[index]->AddComponent(Z, A, v1);
}
}
// no components case
if (noComp) { data[index]->InitialiseForComponent(Z, 0); }
// smooth transition
G4double sig1 = (*v)[v->GetVectorLength()-1];
G4double ehigh = v->GetMaxEnergy();
G4double sig2 = highEnergyXsection->GetInelasticElementCrossSection(
particle, ehigh, Z, aeff[Z]);
coeff[Z][index] = (sig2 > 0.) ? sig1/sig2 : 1.0;
}
l.unlock();
// no components case
if (noComp) { data[index]->InitialiseForComponent(Z, 0); }
// smooth transition
G4double sig1 = (*v)[v->GetVectorLength()-1];
G4double ehigh = v->GetMaxEnergy();
G4double sig2 = highEnergyXsection->GetInelasticElementCrossSection(
particle, ehigh, Z, aeff[Z]);
coeff[Z][index] = (sig2 > 0.) ? sig1/sig2 : 1.0;
}
G4PhysicsVector*