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,6 +23,7 @@ CPPFLAGS += -I$(G4BASE)/global/management/include \
-I$(G4BASE)/particles/hadrons/mesons/include \
-I$(G4BASE)/particles/hadrons/barions/include \
-I$(G4BASE)/particles/hadrons/ions/include \
-I$(G4BASE)/processes/cuts/include \
-I$(G4BASE)/processes/management/include \
-I$(G4BASE)/processes/hadronic/models/management/include/ \
-I$(G4BASE)/processes/hadronic/util/include \
@@ -14,6 +14,79 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
19 November 2019 - G. Folger (hadr-cross-V10-05-31)
- remove using namespace std and using namespace CLHEP from header file G4NeutronElectronElXsc.hh
07 November 2019 - Alberto Ribon (hadr-cross-V10-05-30)
- G4HadronNucleonXsc : set protection against division by zero by introducing
a minimum energy cutoff (100 keV), below which the cross section is
considered constant.
06 November 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-29)
- G4NeutronInelasticXS, G4ParticleInelasticXS, G4NeutronElasticXS,
G4NeutronCaptureXS, G4ComponentSAIDTotalXS, G4CrossSectionDataStore
getenv -> std::getenv
10 October 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-28)
- G4BGGPionInelasticXS, G4BGGPionElasticXS - clean-up pi+ x-section
below 20 MeV
27 September 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-27)
- G4BGGNucleonInelasticXS, G4BGGNucleonElasticXS,
G4BGGPionInelasticXS, G4BGGPionElasticXS - clean-up low-energy
- G4UPiNuclearCrossSection - below 20 MeV cross section is now
const, BGGPion cross section inplement low-energy part
16 September 2019 - V. Grichine (hadr-cross-V10-05-26)
- G4HadronNucleonXsc.hh/cc - new interface to G4ComponentGGHadronNucleonXsc
including s-,c-,b-, particles
27 August 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-25)
- G4BGGNucleonInelasticXS, G4BGGNucleonElasticXS - use coherent
low-energy threshold 14 MeV; code clean-up
- G4BGGPionInelasticXS, G4BGGPionElasticXS,
G4ComponentBarNucleonNucleusXsc - cosmetic clean-up
23 August 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-24)
- G4BGGPionInelasticXS, G4BGGPionElasticXS - use coherent low-energy
limit 1 MeV
- G4BGGNucleonInelasticXS, G4BGGNucleonElasticXS - minor clean-up
- G4UPiNuclearCrossSection - cleaned-up and optimise interpolation
method, moved two run time methods to inline, improve low-energy
parameterisation
19 August 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-23)
- G4HadronNucleonXsc - fixed K+p and K+n parameterisations (NS and VG)
07 August 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-22)
- G4NeutronInelasticXS, G4ParticleInelasticXS, G4NeutronElasticXS - added
special method for tritium and He3 targets (fixed problem #2162),
upload data only for elements used in geometry, code clean-up, use C++11
- G4NeutronElasticXS - implemented isotope cross section
- G4NeutronCaptureXS - code clean-up, use C++11
25 July 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-21)
- G4NeutronCaptureXS - upload data only for elements used in geometry
21 July 2019 - Mihaly Novak (hadr-cross-V10-05-20)
- G4ParticleInelasticXS - use the new, optimised log-vector access method
17 July 2019 - Mihaly Novak (hadr-cross-V10-05-19)
- G4NeutronElasticXS, G4NeutronInelasticXS, G4NeutronCaptureXS - utilise the new
G4PhysicsVector::LogVectorValue optimised (for log-vector) method
13 July 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-18)
- G4NeutronCaptureXS - restore computation of isotope x-section as
it was in 10.5
28 June 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-17)
- G4BGGNucleonElasticXS, G4BGGNucleonInelasticXS - fixed initialisation
for protons and neutrons by usage of separate vectors of correction
coeffitients
- G4BGGPionInelasticXS - fixed low-energy parameterisation (restore
one from Geant4 10.5, where low-energy limits were different for
pi+ and pi-)
12 June 2019 - Vladimir Ivanchenko (hadr-cross-V10-05-16)
- G4BGGPionElasticXS, G4BGGPionInelasticXS - fixed initialisation for
pi+- by usage of separate vectors of correction factors; fixed
@@ -97,11 +97,12 @@ private:
G4double fGlauberEnergy;
G4double fLowEnergy;
static G4double theGlauberFac[93];
static G4double theCoulombFac[93];
static G4double theGlauberFacP[93];
static G4double theCoulombFacP[93];
static G4double theGlauberFacN[93];
static G4double theCoulombFacN[93];
static G4int theA[93];
const G4ParticleDefinition* particle;
const G4ParticleDefinition* theProton;
G4ComponentGGHadronNucleusXsc* fGlauber;
G4NucleonNuclearCrossSection* fNucleon;
@@ -96,13 +96,13 @@ private:
G4double fGlauberEnergy;
G4double fLowEnergy;
G4double fHighEnergy;
static G4double theGlauberFac[93];
static G4double theCoulombFac[93];
static G4double theGlauberFacP[93];
static G4double theCoulombFacP[93];
static G4double theGlauberFacN[93];
static G4double theCoulombFacN[93];
static G4int theA[93];
const G4ParticleDefinition* particle;
const G4ParticleDefinition* theProton;
G4ComponentGGHadronNucleusXsc* fGlauber;
@@ -59,6 +59,7 @@ class G4HadronNucleonXsc;
class G4Material;
class G4Element;
class G4Isotope;
class G4Pow;
class G4BGGPionElasticXS : public G4VCrossSectionDataSet
{
@@ -89,11 +90,16 @@ public:
private:
G4double CoulombFactorPiPlus(G4double kinEnergy, G4int Z);
G4double FactorPiMinus(G4double kinEnergy);
G4BGGPionElasticXS & operator=(const G4BGGPionElasticXS &right);
G4BGGPionElasticXS(const G4BGGPionElasticXS&);
G4double fGlauberEnergy;
G4double fLowEnergy;
G4double fLowestEnergy;
static G4double theGlauberFacPiPlus[93];
static G4double theCoulombFacPiPlus[93];
@@ -101,8 +107,11 @@ private:
static G4double theCoulombFacPiMinus[93];
static G4int theA[93];
const G4ParticleDefinition* particle;
const G4ParticleDefinition* theProton;
const G4ParticleDefinition* thePiPlus;
G4Pow* fG4pow;
G4ComponentGGHadronNucleusXsc* fGlauber;
G4UPiNuclearCrossSection* fPion;
G4HadronNucleonXsc* fHadron;
@@ -91,13 +91,16 @@ public:
private:
G4double CoulombFactor(G4double kinEnergy, G4int Z);
G4double CoulombFactorPiPlus(G4double kinEnergy, G4int Z);
G4double FactorPiMinus(G4double kinEnergy);
G4BGGPionInelasticXS & operator=(const G4BGGPionInelasticXS &right);
G4BGGPionInelasticXS(const G4BGGPionInelasticXS&);
G4double fGlauberEnergy;
G4double fLowEnergy;
G4double fGlauberEnergy;
G4double fLowEnergy;
G4double fLowestEnergy;
static G4double theGlauberFacPiPlus[93];
static G4double theGlauberFacPiMinus[93];
@@ -105,8 +108,8 @@ private:
static G4double theLowEPiMinus[93];
static G4int theA[93];
const G4ParticleDefinition* particle;
const G4ParticleDefinition* theProton;
const G4ParticleDefinition* thePiPlus;
G4Pow* fG4pow;
@@ -55,6 +55,10 @@ public:
~G4HadronNucleonXsc ();
// Xsc parametrisations return total x-section
G4double HadronNucleonXsc(const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin);
G4double HadronNucleonXscPDG(const G4ParticleDefinition* theParticle,
const G4ParticleDefinition* nucleon, G4double ekin);
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class header file
@@ -91,7 +90,13 @@ public:
private:
void Initialise(G4int Z, const char*);
void Initialise(G4int Z);
void InitialiseOnFly(G4int Z);
const G4String& FindDirectoryPath();
const G4PhysicsVector* GetPhysicsVector(G4int Z);
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
@@ -104,14 +109,14 @@ private:
G4double elimit;
G4double logElimit;
size_t fIdxXSTable;
std::vector<G4double> temp;
G4bool isMaster;
static G4ElementData* data;
std::vector<G4double> temp;
static const G4int amin[MAXZCAPTURE];
static const G4int amax[MAXZCAPTURE];
static G4String gDataDirectory;
#ifdef G4MULTITHREADED
static G4Mutex neutronCaptureXSMutex;
@@ -46,7 +46,6 @@
#include "globals.hh"
#include "G4Threading.hh"
#include <vector>
#include <iostream>
const G4int MAXZEL = 93;
@@ -70,16 +69,35 @@ public:
G4bool IsElementApplicable(const G4DynamicParticle*,
G4int Z, const G4Material*) final;
G4bool IsIsoApplicable(const G4DynamicParticle*, G4int Z, G4int A,
const G4Element*, const G4Material*) final;
G4double GetElementCrossSection(const G4DynamicParticle*,
G4int Z, const G4Material*) final;
G4double GetIsoCrossSection(const G4DynamicParticle*, G4int Z, G4int A,
const G4Isotope* iso,
const G4Element* elm,
const G4Material* mat) final;
const G4Isotope* SelectIsotope(const G4Element*,
G4double kinEnergy, G4double logE) final;
void BuildPhysicsTable(const G4ParticleDefinition&) final;
void CrossSectionDescription(std::ostream&) const final;
G4double IsoCrossSection(G4double ekin, G4double logE, G4int Z, G4int A);
private:
void Initialise(G4int Z, const char*);
void Initialise(G4int Z);
void InitialiseOnFly(G4int Z);
const G4String& FindDirectoryPath();
G4PhysicsVector* GetPhysicsVector(G4int Z);
G4NeutronElasticXS & operator=(const G4NeutronElasticXS &right);
G4NeutronElasticXS(const G4NeutronElasticXS&);
@@ -88,10 +106,13 @@ private:
G4ComponentGGHadronNucleusXsc* ggXsection;
const G4ParticleDefinition* neutron;
std::vector<G4double> temp;
static G4PhysicsVector* data[MAXZEL];
static G4double coeff[MAXZEL];
static G4double aeff[MAXZEL];
static G4String gDataDirectory;
size_t fIdxXSTable;
G4bool isMaster;
#ifdef G4MULTITHREADED
@@ -38,9 +38,6 @@
#include "G4VCrossSectionDataSet.hh"
#include "G4DynamicParticle.hh"
using namespace std;
using namespace CLHEP;
// class G4ParticleDefinition;
class G4PhysicsLogVector;
class G4PhysicsTable;
@@ -119,10 +116,10 @@ GetElementNonRelXsc(const G4DynamicParticle* aPart, G4int ZZ,
G4double result(0.), te(0.), momentum(0.);
te = aPart->GetKineticEnergy()*fme/fM;
momentum = sqrt( te*(te + 2.*fme) );
momentum = std::sqrt( te*(te + 2.*fme) );
fAm = CalculateAm(momentum);
result = 1. + log(1. +1./fAm);
result = 1. + std::log(1. +1./fAm);
result *= fCofXsc; //*energy;
result *= ZZ; // incoherent sum over all element electrons
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class header file
@@ -47,7 +46,6 @@
#include "G4ElementData.hh"
#include "G4Threading.hh"
#include <vector>
#include <iostream>
const G4int MAXZINEL = 93;
@@ -75,8 +73,7 @@ public:
const G4Element*, const G4Material*) final;
G4double GetElementCrossSection(const G4DynamicParticle*,
G4int Z,
const G4Material* mat=nullptr) final;
G4int Z, const G4Material*) final;
G4double GetIsoCrossSection(const G4DynamicParticle*, G4int Z, G4int A,
const G4Isotope* iso,
@@ -92,7 +89,13 @@ public:
private:
void Initialise(G4int Z, const char*);
void Initialise(G4int Z);
void InitialiseOnFly(G4int Z);
const G4String& FindDirectoryPath();
const G4PhysicsVector* GetPhysicsVector(G4int Z);
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
@@ -106,17 +109,16 @@ private:
const G4ParticleDefinition* neutron;
G4double emax;
std::vector<G4double> temp;
size_t fIdxXSTable;
G4bool isMaster;
static G4ElementData* data;
static G4double coeff[MAXZINEL];
static G4double aeff[MAXZINEL];
static const G4int amin[MAXZINEL];
static const G4int amax[MAXZINEL];
static G4String gDataDirectory;
#ifdef G4MULTITHREADED
static G4Mutex neutronInelasticXSMutex;
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class header file
@@ -92,7 +91,13 @@ public:
private:
void Initialise(G4int Z, const char*);
void Initialise(G4int Z);
void InitialiseOnFly(G4int Z);
const G4String& FindDirectoryPath();
const G4PhysicsVector* GetPhysicsVector(G4int Z);
G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn);
@@ -106,18 +111,16 @@ private:
const G4ParticleDefinition* particle;
const G4ParticleDefinition* proton;
G4double emax;
std::vector<G4double> temp;
size_t fIdxXSTable;
G4bool isMaster;
static G4double coeff[MAXZINELP];
static G4ElementData* data;
static G4double coeff[MAXZINELP];
static G4double aeff[MAXZINELP];
static const G4int amin[MAXZINELP];
static const G4int amax[MAXZINELP];
static G4ElementData* data;
static G4String gDataDirectory;
#ifdef G4MULTITHREADED
static G4Mutex particleInelasticXSMutex;
@@ -31,12 +31,12 @@
// 05.03.07 V.Ivanchenko - add IfZAApplicable
//
#ifndef G4UPiNuclearCrossSection_h
#define G4UPiNuclearCrossSection_h
#include "G4VCrossSectionDataSet.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "globals.hh"
#include "G4Threading.hh"
@@ -53,9 +53,11 @@ public:
G4bool IsElementApplicable(const G4DynamicParticle* aParticle,
G4int Z, const G4Material*) final;
inline
G4double GetElasticCrossSection(const G4DynamicParticle* aParticle,
G4int Z, G4int A) const;
inline
G4double GetInelasticCrossSection(const G4DynamicParticle* aParticle,
G4int Z, G4int A) const;
@@ -67,7 +69,8 @@ public:
private:
G4double Interpolate(G4int Z, G4int A, G4double ekin, G4PhysicsTable*) const;
G4double Interpolate(G4int Z, G4int A, G4double ekin,
const G4PhysicsTable*) const;
void AddDataSet(const G4String& p, const G4double* tot,
const G4double* in, const G4double* e, G4int n);
@@ -79,6 +82,7 @@ private:
static const G4int NZ = 16;
static G4int theZ[NZ];
static G4int idxZ[93];
static G4double theA[NZ];
static G4double APower[93];
@@ -90,7 +94,6 @@ private:
G4double aPower;
G4double elow;
G4double elowest;
G4bool isMaster;
@@ -99,4 +102,22 @@ private:
#endif
};
inline G4double
G4UPiNuclearCrossSection::GetElasticCrossSection(
const G4DynamicParticle* dp, G4int Z, G4int A) const
{
const G4PhysicsTable* table =
(dp->GetDefinition() == piPlus) ? piPlusElastic : piMinusElastic;
return Interpolate(Z, A, dp->GetKineticEnergy(), table);
}
inline G4double
G4UPiNuclearCrossSection::GetInelasticCrossSection(
const G4DynamicParticle* dp, G4int Z, G4int A) const
{
const G4PhysicsTable* table =
(dp->GetDefinition() == piPlus) ? piPlusInelastic : piMinusInelastic;
return Interpolate(Z, A, dp->GetKineticEnergy(), table);
}
#endif
@@ -30,6 +30,7 @@ include_directories(${CMAKE_SOURCE_DIR}/source/particles/hadrons/ions/include)
include_directories(${CMAKE_SOURCE_DIR}/source/particles/hadrons/mesons/include)
include_directories(${CMAKE_SOURCE_DIR}/source/particles/leptons/include)
include_directories(${CMAKE_SOURCE_DIR}/source/particles/management/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/cuts/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/hadronic/models/management/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/hadronic/models/util/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/hadronic/util/include)
@@ -197,6 +198,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_xsect
GRANULAR_DEPENDENCIES
G4baryons
G4bosons
G4cuts
G4geometrymng
G4globman
G4had_mod_man
@@ -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()
@@ -14,6 +14,36 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
11 November 2019 A. Ribon (hadr-man-V10-05-07)
---------------------------------------------------
- G4HadronicProcess : in the method CheckResult, a short-lived secondary
particle is allowed to have a dynamic mass which differ from the PDG mass
by less than three times the particle's width.
17 October 2019 V. Ivanchenko (hadr-man-V10-05-06)
---------------------------------------------------
- G4HadronicProcess : for particle out of the mass shell correct
kinetic energy in a way, that it is always above 10 keV;
use std::getenv method recommended for concurrency
12 September 2019 V. Ivanchenko (hadr-man-V10-05-05)
---------------------------------------------------
- G4HadronicProcess : fixed Coverity warnings
21 August 2019 V. Ivanchenko (hadr-man-V10-05-04)
---------------------------------------------------
- G4EnergyRangeManager : move operators to be private, removed
obsolete method, removed G4HadronicException, instead in case of
problem return nullptr
- G4HadronicProcess : do not use try/catch pattern to choose hadronic
interaction; decrease limit on check of offshell mass from 1.5 MeV
to 10 keV - fixed problem 2175; removed unused headers
13 July 2019 V. Ivanchenko (hadr-man-V10-05-03)
---------------------------------------------------
- G4EnergyRangeManager : added short cut - if only one model registered
for a process no check is applied; implemented C++11 paterns
11 June 2019 A. Ribon (hadr-man-V10-05-02)
---------------------------------------------------
- G4EnergyRangeManager : fixed bug regarding the kinetic energy per nucleon
@@ -43,29 +43,13 @@ public:
explicit G4EnergyRangeManager();
~G4EnergyRangeManager();
void RegisterMe(G4HadronicInteraction* a);
G4EnergyRangeManager(const G4EnergyRangeManager& right);
G4EnergyRangeManager& operator=( const G4EnergyRangeManager &right );
inline G4bool operator==( const G4EnergyRangeManager &right ) const
{ return ( this == (G4EnergyRangeManager *) &right ); }
inline G4bool operator!=( const G4EnergyRangeManager &right ) const
{ return ( this != (G4EnergyRangeManager *) &right ); }
void RegisterMe( G4HadronicInteraction *a );
G4HadronicInteraction *GetHadronicInteraction(const G4HadProjectile & aHadProjectile,
G4HadronicInteraction* GetHadronicInteraction(const G4HadProjectile & aHadProjectile,
G4Nucleus & aTargetNucleus,
const G4Material *aMaterial,
const G4Element *anElement ) const;
// This is the new one to be used.
G4HadronicInteraction *GetHadronicInteraction(const G4double kineticEnergy,
const G4Material *aMaterial,
const G4Element *anElement ) const;
// This is the old, deprecated one, which will be removed later on.
std::vector<G4HadronicInteraction*>& GetHadronicInteractionList();
@@ -74,6 +58,11 @@ public:
void BuildPhysicsTable(const G4ParticleDefinition&);
private:
G4EnergyRangeManager(const G4EnergyRangeManager& right);
G4EnergyRangeManager& operator=( const G4EnergyRangeManager &right );
G4bool operator==( const G4EnergyRangeManager &right ) const;
G4bool operator!=( const G4EnergyRangeManager &right ) const;
G4int theHadronicInteractionCounter;
std::vector<G4HadronicInteraction*> theHadronicInteraction;
@@ -204,8 +204,8 @@ private:
G4double XBiasSecondaryWeight();
// hide assignment operator as private
G4HadronicProcess& operator=(const G4HadronicProcess& right) = delete;
G4HadronicProcess(const G4HadronicProcess&) = delete;
G4HadronicProcess& operator=(const G4HadronicProcess& right);
G4HadronicProcess(const G4HadronicProcess&);
// Set E/p conservation check levels from environment variables
void GetEnergyMomentumCheckEnvvars();
@@ -34,6 +34,7 @@
#include "G4EnergyRangeManager.hh"
#include "Randomize.hh"
#include "G4HadronicException.hh"
#include "G4SystemOfUnits.hh"
G4EnergyRangeManager::G4EnergyRangeManager()
: theHadronicInteractionCounter(0)
@@ -42,22 +43,6 @@ G4EnergyRangeManager::G4EnergyRangeManager()
G4EnergyRangeManager::~G4EnergyRangeManager()
{}
G4EnergyRangeManager::G4EnergyRangeManager(const G4EnergyRangeManager& right)
{
theHadronicInteractionCounter = right.theHadronicInteractionCounter;
theHadronicInteraction = right.theHadronicInteraction;
}
G4EnergyRangeManager& G4EnergyRangeManager::operator=(
const G4EnergyRangeManager& right)
{
if (this != &right) {
theHadronicInteractionCounter = right.theHadronicInteractionCounter;
theHadronicInteraction = right.theHadronicInteraction;
}
return *this;
}
void G4EnergyRangeManager::RegisterMe(G4HadronicInteraction* a)
{
if(!a) { return; }
@@ -70,16 +55,18 @@ void G4EnergyRangeManager::RegisterMe(G4HadronicInteraction* a)
++theHadronicInteractionCounter;
}
G4HadronicInteraction*
G4EnergyRangeManager::GetHadronicInteraction(const G4HadProjectile & aHadProjectile,
G4Nucleus & aTargetNucleus,
const G4Material* aMaterial,
const G4Element* anElement) const
{
if(0 == theHadronicInteractionCounter) {
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: NO MODELS STORED");
// VI shortcut: if only one interaction is registered skip all checks
if(1 == theHadronicInteractionCounter) { return theHadronicInteraction[0]; }
else if(0 == theHadronicInteractionCounter) {
G4cout << "G4EnergyRangeManager::GetHadronicInteraction: "
<< "no models defined for a process" << G4endl;
return nullptr;
}
G4double kineticEnergy = aHadProjectile.GetKineticEnergy();
@@ -94,11 +81,8 @@ G4EnergyRangeManager::GetHadronicInteraction(const G4HadProjectile & aHadProject
for (G4int i = 0; i<theHadronicInteractionCounter; ++i) {
if ( theHadronicInteraction[i]->IsApplicable( aHadProjectile, aTargetNucleus ) ) {
G4double low = theHadronicInteraction[i]->GetMinEnergy( aMaterial, anElement );
// Work-around for particles with 0 kinetic energy, which still
// require a model to return a ParticleChange
//if (low == 0.) low = -DBL_MIN;
G4double high = theHadronicInteraction[i]->GetMaxEnergy( aMaterial, anElement );
if (low <= kineticEnergy && high > kineticEnergy) {
if (low <= kineticEnergy && high >= kineticEnergy) {
++cou;
emi2 = emi1;
ema2 = ema1;
@@ -110,158 +94,62 @@ G4EnergyRangeManager::GetHadronicInteraction(const G4HadProjectile & aHadProject
}
}
G4int mem = -1;
G4double rand;
G4HadronicInteraction* hi = nullptr;
switch (cou) {
case 0:
G4cout<<"G4EnergyRangeManager:GetHadronicInteraction: counter="
<<theHadronicInteractionCounter<<", Ek="
<<kineticEnergy<<", Material = "<<aMaterial->GetName()
<<", Element = "
<<anElement->GetName()<<G4endl;
for( G4int j=0; j<theHadronicInteractionCounter; ++j)
{
G4HadronicInteraction* HInt=theHadronicInteraction[j];
G4cout<<"*"<<j<<"* low=" <<HInt->GetMinEnergy(aMaterial,anElement)
<<", high="<<HInt->GetMaxEnergy(aMaterial,anElement)<<G4endl;
}
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: No Model found");
return 0;
G4cout << "No model found out of " << theHadronicInteractionCounter << G4endl;
for( G4int j=0; j<theHadronicInteractionCounter; ++j) {
G4HadronicInteraction* hint=theHadronicInteraction[j];
G4cout << " "<< j << ". Elow= " << hint->GetMinEnergy(aMaterial,anElement)
<<", Ehigh= " << hint->GetMaxEnergy(aMaterial,anElement)
<<" " << hint->GetModelName() << G4endl;
}
break;
case 1:
mem = memory;
break;
hi = theHadronicInteraction[memory];
break;
case 2:
if( (emi2<=emi1 && ema2>=ema1) || (emi2>=emi1 && ema2<=ema1) )
{
G4cout<<"G4EnergyRangeManager:GetHadronicInteraction: counter="
<<theHadronicInteractionCounter<<", Ek="
<<kineticEnergy<<", Material = "<<aMaterial->GetName()
<<", Element = "
<<anElement->GetName()<<G4endl;
for( G4int j=0; j<theHadronicInteractionCounter; ++j)
{
G4HadronicInteraction* HInt=theHadronicInteraction[j];
G4cout<<"*"<<j<<"* low=" <<HInt->GetMinEnergy(aMaterial,anElement)
<<", high="<<HInt->GetMaxEnergy(aMaterial,anElement)<<G4endl;
}
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: Energy ranges of two models fully overlapping");
}
rand = G4UniformRand();
if( emi1 < emi2 )
{
if( (ema1-kineticEnergy) < rand*(ema1-emi2) ) {
mem = memor2;
} else {
mem = memory;
}
} else {
if( (ema2-kineticEnergy) < rand*(ema2-emi1) ) {
mem = memory;
} else {
mem = memor2;
}
}
break;
if( (emi2<=emi1 && ema2>=ema1) || (emi2>=emi1 && ema2<=ema1) ) {
G4cout << "Energy ranges of two models fully overlapping " << G4endl;
for( G4int j=0; j<theHadronicInteractionCounter; ++j) {
G4HadronicInteraction* hint=theHadronicInteraction[j];
G4cout << " "<< j << ". Elow= " << hint->GetMinEnergy(aMaterial,anElement)
<<", Ehigh= " << hint->GetMaxEnergy(aMaterial,anElement)
<<" " << hint->GetModelName() << G4endl;
}
} else {
G4double rand = G4UniformRand();
G4int mem;
if( emi1 < emi2 ) {
if( (ema1-kineticEnergy) < rand*(ema1-emi2) ) {
mem = memor2;
} else {
mem = memory;
}
} else {
if( (ema2-kineticEnergy) < rand*(ema2-emi1) ) {
mem = memory;
} else {
mem = memor2;
}
}
hi = theHadronicInteraction[mem];
}
break;
default:
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: More than two competing models in this energy range");
G4cout << "More than two competing models for this energy" << G4endl;
for( G4int j=0; j<theHadronicInteractionCounter; ++j) {
G4HadronicInteraction* hint=theHadronicInteraction[j];
G4cout << " "<< j << ". Elow= " << hint->GetMinEnergy(aMaterial,anElement)
<<", Ehigh= " << hint->GetMaxEnergy(aMaterial,anElement)
<<" " << hint->GetModelName() << G4endl;
}
break;
}
return theHadronicInteraction[mem];
}
G4HadronicInteraction*
G4EnergyRangeManager::GetHadronicInteraction(const G4double kineticEnergy,
const G4Material* aMaterial,
const G4Element* anElement) const
{
if(0 == theHadronicInteractionCounter) {
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: NO MODELS STORED");
}
G4int cou = 0, memory = 0, memor2 = 0;
G4double emi1 = 0.0, ema1 = 0.0, emi2 = 0.0, ema2 = 0.0;
for (G4int i = 0; i<theHadronicInteractionCounter; ++i) {
G4double low = theHadronicInteraction[i]->GetMinEnergy( aMaterial, anElement );
// Work-around for particles with 0 kinetic energy, which still
// require a model to return a ParticleChange
//if (low == 0.) low = -DBL_MIN;
G4double high = theHadronicInteraction[i]->GetMaxEnergy( aMaterial, anElement );
if (low <= kineticEnergy && high > kineticEnergy) {
++cou;
emi2 = emi1;
ema2 = ema1;
emi1 = low;
ema1 = high;
memor2 = memory;
memory = i;
}
}
G4int mem = -1;
G4double rand;
switch (cou) {
case 0:
G4cout<<"G4EnergyRangeManager:GetHadronicInteraction: counter="
<<theHadronicInteractionCounter<<", Ek="
<<kineticEnergy<<", Material = "<<aMaterial->GetName()
<<", Element = "
<<anElement->GetName()<<G4endl;
for( G4int j=0; j<theHadronicInteractionCounter; ++j)
{
G4HadronicInteraction* HInt=theHadronicInteraction[j];
G4cout<<"*"<<j<<"* low=" <<HInt->GetMinEnergy(aMaterial,anElement)
<<", high="<<HInt->GetMaxEnergy(aMaterial,anElement)<<G4endl;
}
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: No Model found");
return 0;
case 1:
mem = memory;
break;
case 2:
if( (emi2<=emi1 && ema2>=ema1) || (emi2>=emi1 && ema2<=ema1) )
{
G4cout<<"G4EnergyRangeManager:GetHadronicInteraction: counter="
<<theHadronicInteractionCounter<<", Ek="
<<kineticEnergy<<", Material = "<<aMaterial->GetName()
<<", Element = "
<<anElement->GetName()<<G4endl;
for( G4int j=0; j<theHadronicInteractionCounter; ++j)
{
G4HadronicInteraction* HInt=theHadronicInteraction[j];
G4cout<<"*"<<j<<"* low=" <<HInt->GetMinEnergy(aMaterial,anElement)
<<", high="<<HInt->GetMaxEnergy(aMaterial,anElement)<<G4endl;
}
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: Energy ranges of two models fully overlapping");
}
rand = G4UniformRand();
if( emi1 < emi2 )
{
if( (ema1-kineticEnergy) < rand*(ema1-emi2) ) {
mem = memor2;
} else {
mem = memory;
}
} else {
if( (ema2-kineticEnergy) < rand*(ema2-emi1) ) {
mem = memory;
} else {
mem = memor2;
}
}
break;
default:
throw G4HadronicException(__FILE__, __LINE__,
"GetHadronicInteraction: More than two competing models in this energy range");
}
return theHadronicInteraction[mem];
return hi;
}
std::vector<G4HadronicInteraction*>&
@@ -270,7 +158,6 @@ G4EnergyRangeManager::GetHadronicInteractionList()
return theHadronicInteraction;
}
#include "G4SystemOfUnits.hh"
void G4EnergyRangeManager::Dump( G4int verbose )
{
G4cout << "G4EnergyRangeManager " << this << G4endl;
@@ -290,10 +177,9 @@ void G4EnergyRangeManager::Dump( G4int verbose )
void
G4EnergyRangeManager::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
for ( std::vector<G4HadronicInteraction*>::iterator
it = theHadronicInteraction.begin() ; it != theHadronicInteraction.end() ; it++ ) {
(*it)->BuildPhysicsTable( aParticleType );
}
for (auto & hadi : theHadronicInteraction) {
hadi->BuildPhysicsTable( aParticleType );
}
}
/* end of file */
@@ -45,6 +45,7 @@
// configure base-class
// 28-Sep-2012 Restore inheritance from G4VDiscreteProcess, remove enable-flag
// changing, remove warning message from original ctor.
// 21-Aug-2019 V.Ivanchenko leave try/catch only for ApplyYourself(..), cleanup
#include "G4HadronicProcess.hh"
@@ -56,19 +57,14 @@
#include "G4Step.hh"
#include "G4Element.hh"
#include "G4ParticleChange.hh"
#include "G4TransportationManager.hh"
#include "G4Navigator.hh"
#include "G4ProcessVector.hh"
#include "G4ProcessManager.hh"
#include "G4StableIsotopes.hh"
#include "G4HadTmpUtil.hh"
#include "G4NucleiProperties.hh"
#include "G4HadronicException.hh"
#include "G4HadronicProcessStore.hh"
#include "G4VCrossSectionDataSet.hh"
#include "G4AutoLock.hh"
#include "G4NistManager.hh"
#include "G4PhysicsModelCatalog.hh"
#include "G4VLeadingParticleBiasing.hh"
@@ -78,11 +74,9 @@
#include <sstream>
#include <iostream>
#include <stdlib.h>
// File-scope variable to capture environment variable at startup
static const char* G4Hadronic_Random_File = getenv("G4HADRONIC_RANDOM_FILE");
static const char* G4Hadronic_Random_File = std::getenv("G4HADRONIC_RANDOM_FILE");
//////////////////////////////////////////////////////////////////
@@ -134,14 +128,14 @@ void G4HadronicProcess::InitialiseLocal() {
void G4HadronicProcess::GetEnergyMomentumCheckEnvvars() {
levelsSetByProcess = false;
epReportLevel = getenv("G4Hadronic_epReportLevel") ?
strtol(getenv("G4Hadronic_epReportLevel"),0,10) : 0;
epReportLevel = std::getenv("G4Hadronic_epReportLevel") ?
std::strtol(std::getenv("G4Hadronic_epReportLevel"),0,10) : 0;
epCheckLevels.first = getenv("G4Hadronic_epCheckRelativeLevel") ?
strtod(getenv("G4Hadronic_epCheckRelativeLevel"),0) : DBL_MAX;
epCheckLevels.first = std::getenv("G4Hadronic_epCheckRelativeLevel") ?
std::strtod(std::getenv("G4Hadronic_epCheckRelativeLevel"),0) : DBL_MAX;
epCheckLevels.second = getenv("G4Hadronic_epCheckAbsoluteLevel") ?
strtod(getenv("G4Hadronic_epCheckAbsoluteLevel"),0) : DBL_MAX;
epCheckLevels.second = std::getenv("G4Hadronic_epCheckAbsoluteLevel") ?
std::strtod(std::getenv("G4Hadronic_epCheckAbsoluteLevel"),0) : DBL_MAX;
}
void G4HadronicProcess::RegisterMe( G4HadronicInteraction *a )
@@ -185,7 +179,7 @@ G4HadronicProcess::GetElementCrossSection(const G4DynamicParticle * part,
void G4HadronicProcess::PreparePhysicsTable(const G4ParticleDefinition& p)
{
if(getenv("G4HadronicProcess_debug")) {
if(std::getenv("G4HadronicProcess_debug")) {
G4HadronicProcess_debug_flag = true;
}
theProcessStore->RegisterParticle(this, &p);
@@ -261,27 +255,29 @@ G4HadronicProcess::PostStepDoIt(const G4Track& aTrack, const G4Step&)
// Initialize the hadronic projectile from the track
thePro.Initialise(aTrack);
try
{
theInteraction =
ChooseHadronicInteraction( thePro, targetNucleus, aMaterial, anElement );
}
catch(G4HadronicException & aE)
{
theInteraction = ChooseHadronicInteraction(thePro, targetNucleus,
aMaterial, anElement);
if(!theInteraction) {
G4ExceptionDescription ed;
aE.Report(ed);
ed << "Target element "<<anElement->GetName()<<" Z= "
<< targetNucleus.GetZ_asInt() << " A= "
<< targetNucleus.GetA_asInt() << G4endl;
DumpState(aTrack,"ChooseHadronicInteraction",ed);
ed << " No HadronicInteraction found out" << G4endl;
G4Exception("G4HadronicProcess::PostStepDoIt", "had005", FatalException,
ed);
G4Exception("G4HadronicProcess::PostStepDoIt", "had005", FatalException, ed);
return theTotalResult;
}
G4HadFinalState* result = nullptr;
G4int reentryCount = 0;
/*
G4cout << "### " << aParticle->GetDefinition()->GetParticleName()
<< " Ekin(MeV)= " << aParticle->GetKineticEnergy()
<< " Z= " << targetNucleus.GetZ_asInt()
<< " A= " << targetNucleus.GetA_asInt()
<< " by " << theInteraction->GetModelName()
<< G4endl;
*/
do
{
try
@@ -442,8 +438,10 @@ G4HadronicProcess::FillResult(G4HadFinalState * aR, const G4Track & aT)
const G4ParticleDefinition* part = dynParticle->GetDefinition();
G4double mass = part->GetPDGMass();
G4double dmass= dynParticle->GetMass();
if(std::abs(dmass - mass) > 1.5*CLHEP::MeV) {
G4double e = std::max(dynParticle->GetKineticEnergy() + dmass - mass, 0.0);
const G4double delta_mass_lim = 1.0*CLHEP::keV;
const G4double delta_ekin = 0.001*CLHEP::eV;
if(std::abs(dmass - mass) > delta_mass_lim) {
G4double e = std::max(dynParticle->GetKineticEnergy() + dmass - mass, delta_ekin);
if(G4HadronicProcess_debug_flag) {
G4ExceptionDescription ed;
ed << "TrackID= "<< aT.GetTrackID()
@@ -538,7 +536,12 @@ G4HadFinalState* G4HadronicProcess::CheckResult(const G4HadProjectile & aPro,
finalE += pdyn->GetTotalEnergy();
G4double mass_pdg=pdyn->GetDefinition()->GetPDGMass();
G4double mass_dyn=pdyn->GetMass();
if ( std::abs(mass_pdg - mass_dyn) > 0.1*mass_pdg + 1.*MeV){
if ( std::abs(mass_pdg - mass_dyn) > 0.1*mass_pdg + 1.*MeV ) {
// If it is shortlived, then a difference less than 3 times the width is acceptable
if ( pdyn->GetDefinition()->IsShortLived() &&
std::abs(mass_pdg - mass_dyn) < 3.0*pdyn->GetDefinition()->GetPDGWidth() ) {
continue;
}
result->Clear();
result = nullptr;
G4ExceptionDescription desc;
@@ -615,28 +618,27 @@ G4HadronicProcess::CheckEnergyMomentumConservation(const G4Track& aTrack,
G4int nSec = theTotalResult->GetNumberOfSecondaries();
if (theTotalResult->GetTrackStatus() != fStopAndKill) { // If it is Alive
// Either interaction didn't complete, returned "do nothing" state
// or the primary survived the interaction (e.g. electro-nucleus )
G4Track temp(aTrack);
// Either interaction didn't complete, returned "do nothing" state
// or the primary survived the interaction (e.g. electro-nucleus )
// Use the final energy / momentum
temp.SetMomentumDirection(*theTotalResult->GetMomentumDirection());
temp.SetKineticEnergy(theTotalResult->GetEnergy());
// Interaction didn't complete, returned "do nothing" state
// - or suppressed recoil (e.g. Neutron elastic )
final4mom = initial4mom;
final_A = initial_A;
final_Z = initial_Z;
if (nSec > 0 && aTrack.GetDynamicParticle()) {
// The primary remains in final state (e.g. electro-nucleus )
G4Track temp(aTrack);
if( nSec == 0 ){
// Interaction didn't complete, returned "do nothing" state
// - or suppressed recoil (e.g. Neutron elastic )
final4mom = temp.GetDynamicParticle()->Get4Momentum() + target4mom;
final_A = initial_A;
final_Z = initial_Z;
}else{
// The primary remains in final state (e.g. electro-nucleus )
final4mom = temp.GetDynamicParticle()->Get4Momentum();
final_A = track_A;
final_Z = track_Z;
// Expect that the target nucleus will have interacted,
// and its products, including recoil, will be included in secondaries.
}
// Use the final energy / momentum
temp.SetMomentumDirection(*theTotalResult->GetMomentumDirection());
temp.SetKineticEnergy(theTotalResult->GetEnergy());
final4mom = temp.GetDynamicParticle()->Get4Momentum();
final_A = track_A;
final_Z = track_Z;
// Expect that the target nucleus will have interacted,
// and its products, including recoil, will be included in secondaries.
}
}
if( nSec > 0 ) {
G4Track* sec;
@@ -577,7 +577,7 @@ void G4HadronicProcessStore::PrintInfo(const G4ParticleDefinition* part)
if(buildTableStart && part == particle[n_part - 1]) {
buildTableStart = false;
Dump(verbose);
if (getenv("G4PhysListDocDir") ) DumpHtml();
if (std::getenv("G4PhysListDocDir") ) DumpHtml();
G4HadronicInteractionRegistry::Instance()->InitialiseModels();
}
}
@@ -590,8 +590,8 @@ void G4HadronicProcessStore::DumpHtml()
// List processes, models and cross sections for the most important
// particles in descending order of importance
char* dirName = getenv("G4PhysListDocDir");
char* physListName = getenv("G4PhysListName");
char* dirName = std::getenv("G4PhysListDocDir");
char* physListName = std::getenv("G4PhysListName");
if (dirName && physListName) {
// Open output file with path name
@@ -668,7 +668,7 @@ void G4HadronicProcessStore::PrintHtml(const G4ParticleDefinition* theParticle,
m_map.equal_range(theProcess);
outFile << " <ul>\n";
G4String physListName(getenv("G4PhysListName"));
G4String physListName(std::getenv("G4PhysListName"));
for (HPHImap::iterator jt = itmod.first; jt != itmod.second; ++jt) {
outFile << " <li><b><a href=\"" << physListName << "_"
@@ -720,8 +720,8 @@ void G4HadronicProcessStore::PrintHtml(const G4ParticleDefinition* theParticle,
void
G4HadronicProcessStore::PrintModelHtml(const G4HadronicInteraction * mod) const
{
G4String dirName(getenv("G4PhysListDocDir"));
G4String physListName(getenv("G4PhysListName"));
G4String dirName(std::getenv("G4PhysListDocDir"));
G4String physListName(std::getenv("G4PhysListName"));
G4String pathName = dirName + "/" + physListName + "_" + HtmlFileName(mod->GetModelName());
std::ofstream outModel;
outModel.open(pathName);
@@ -95,4 +95,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_abla_abla
G4track
G4intercoms
SOURCES_EXCLUDE_FORMAT
G4Abla.cc
LINK_LIBRARIES)# List any source specific properties here
@@ -68,7 +68,7 @@ G4AblaDataFile::~G4AblaDataFile()
bool G4AblaDataFile::readData()
{
#ifdef ABLAXX_IN_GEANT4_MODE
if(!getenv("G4ABLADATA")) {
if(!std::getenv("G4ABLADATA")) {
// throw G4HadronicException(__FILE__, __LINE__, "ERROR: Data
// missing. Set environment variable G4ABLA3.0 to point to the
// directory containing data files needed by INCL and ABLA
@@ -85,7 +85,7 @@ bool G4AblaDataFile::readData()
G4Exception("G4AblaDataFile::readData()","ABLA_001",
FatalException, ed);
}
G4String dataPath(getenv("G4ABLADATA"));
G4String dataPath(std::getenv("G4ABLADATA"));
#else
G4String dataPath(theConfig->getABLAXXDataFilePath().c_str());
#endif
@@ -13,6 +13,16 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
06-Nov-2019, Alberto Ribon had-binary-V10-05-01
- G4GeneratorPrecompoundInterface: trivial fix.
15-Oct-2019, Alberto Ribon had-binary-V10-05-00
- G4GeneratorPrecompoundInterface: extended by Vladimir Uzhinsky to
include a simple coalescence model for nucleus-nucleus interactions
(in the interface between string and precompound models).
This allows to improve the nucleon spectra and produce fast deuterons
in ion-ion collisions.
09-Nov-2018, Gabriele Cosmo had-binary-V10-04-00
- G4GeneratorPrecompoundInterface: fixed printout typo.
@@ -69,12 +69,17 @@ public:
virtual G4ReactionProductVector*
Propagate(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus);
virtual G4ReactionProductVector* // Uzhi Nov. 2012
virtual G4ReactionProductVector*
PropagateNuclNucl(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus,
G4V3DNucleus* theProjectileNucleus);
inline void SetCaptureThreshold(G4double);
inline void SetDeltaM(G4double);
inline void SetDeltaR(G4double);
void MakeCoalescence(G4KineticTrackVector* theSecondaries);
virtual void PropagateModelDescription(std::ostream&) const;
private:
@@ -85,6 +90,9 @@ private:
G4bool operator!=(G4GeneratorPrecompoundInterface& right) {return (this != &right);}
G4double CaptureThreshold;
G4double DeltaM;
G4double DeltaR;
const G4ParticleDefinition* proton;
const G4ParticleDefinition* neutron;
@@ -105,9 +113,20 @@ private:
inline
void G4GeneratorPrecompoundInterface::SetCaptureThreshold(G4double value)
{
CaptureThreshold=value;
CaptureThreshold = value;
}
inline
void G4GeneratorPrecompoundInterface::SetDeltaM(G4double value)
{
DeltaM = value;
}
inline
void G4GeneratorPrecompoundInterface::SetDeltaR(G4double value)
{
DeltaR = value;
}
#endif // G4GeneratorPrecompoundInterface_h
@@ -271,7 +271,7 @@ G4HadFinalState * G4BinaryCascade::ApplyYourself(const G4HadProjectile & aTrack,
G4Nucleus & aNucleus)
//----------------------------------------------------------------------------
{
if(getenv("BCDEBUG") ) G4cerr << " ######### Binary Cascade Reaction starts ######### "<< G4endl;
if(std::getenv("BCDEBUG") ) G4cerr << " ######### Binary Cascade Reaction starts ######### "<< G4endl;
G4LorentzVector initial4Momentum = aTrack.Get4Momentum();
const G4ParticleDefinition * definition = aTrack.GetDefinition();
@@ -290,7 +290,7 @@ G4HadFinalState * G4BinaryCascade::ApplyYourself(const G4HadProjectile & aTrack,
G4KineticTrackVector * secondaries;// = new G4KineticTrackVector;
G4ThreeVector initialPosition(0., 0., 0.); // will be set later
if(!getenv("I_Am_G4BinaryCascade_Developer") )
if(!std::getenv("I_Am_G4BinaryCascade_Developer") )
{
if(definition!=G4Neutron::NeutronDefinition() &&
definition!=G4Proton::ProtonDefinition() &&
@@ -380,7 +380,7 @@ G4HadFinalState * G4BinaryCascade::ApplyYourself(const G4HadProjectile & aTrack,
} else { // no interaction, return primary
if(getenv("BCDEBUG") ) G4cerr << " ######### Binary Cascade Reaction void, return intial state ######### "<< G4endl;
if(std::getenv("BCDEBUG") ) G4cerr << " ######### Binary Cascade Reaction void, return intial state ######### "<< G4endl;
theParticleChange.SetStatusChange(isAlive);
theParticleChange.SetEnergyChange(aTrack.GetKineticEnergy());
theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
@@ -395,7 +395,7 @@ G4HadFinalState * G4BinaryCascade::ApplyYourself(const G4HadProjectile & aTrack,
delete the3DNucleus;
the3DNucleus = NULL;
if(getenv("BCDEBUG") ) G4cerr << " ######### Binary Cascade Reaction ends ######### "<< G4endl;
if(std::getenv("BCDEBUG") ) G4cerr << " ######### Binary Cascade Reaction ends ######### "<< G4endl;
return &theParticleChange;
}
@@ -82,7 +82,7 @@ G4BinaryLightIonReaction::G4BinaryLightIonReaction(G4VPreCompoundModel* ptr)
}
debug_G4BinaryLightIonReactionResults=getenv("debug_G4BinaryLightIonReactionResults")!=0;
debug_G4BinaryLightIonReactionResults=std::getenv("debug_G4BinaryLightIonReactionResults")!=0;
}
G4BinaryLightIonReaction::~G4BinaryLightIonReaction()
@@ -106,7 +106,7 @@ struct ReactionProduct4Mom
G4HadFinalState *G4BinaryLightIonReaction::
ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus & targetNucleus )
{
if(getenv("BLICDEBUG") ) G4cerr << " ######### Binary Light Ion Reaction starts ######### " << G4endl;
if(std::getenv("BLICDEBUG") ) G4cerr << " ######### Binary Light Ion Reaction starts ######### " << G4endl;
G4ping debug("debug_G4BinaryLightIonReaction");
pA=aTrack.GetDefinition()->GetBaryonNumber();
pZ=G4lrint(aTrack.GetDefinition()->GetPDGCharge()/eplus);
@@ -358,7 +358,7 @@ ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus & targetNucleus )
<< " 3mom.mag() " << (aTrack.Get4Momentum()+ G4LorentzVector(m_nucl) - ptot).vect().mag() << G4endl;
#endif
if(getenv("BLICDEBUG") ) G4cerr << " ######### Binary Light Ion Reaction number ends ######### " << G4endl;
if(std::getenv("BLICDEBUG") ) G4cerr << " ######### Binary Light Ion Reaction number ends ######### " << G4endl;
return &theResult;
}
@@ -76,7 +76,7 @@
//#define debugPrecoInt
G4GeneratorPrecompoundInterface::G4GeneratorPrecompoundInterface(G4VPreCompoundModel* preModel)
: CaptureThreshold(70*MeV) // Uzhi 1.05.2015 10 ->70
: CaptureThreshold(70*MeV), DeltaM(5.0*MeV), DeltaR(0.0)
{
proton = G4Proton::Proton();
neutron = G4Neutron::Neutron();
@@ -149,24 +149,23 @@ Propagate(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus)
G4double mass = (*iter)->Get4Momentum().mag();
G4ThreeVector mom = (*iter)->Get4Momentum().vect();
if((part != proton && part != neutron) ||
// Uzhi 2.05.2015 (e > mass + CaptureThreshold) ||
((*iter)->GetPosition().mag() > R)) {
G4ReactionProduct * theNew = new G4ReactionProduct(part);
theNew->SetMomentum(mom);
theNew->SetTotalEnergy(e);
theTotalResult->push_back(theNew);
Secondary4Momentum += (*iter)->Get4Momentum(); // Uzhi 29 April
Secondary4Momentum += (*iter)->Get4Momentum();
#ifdef debugPrecoInt
G4cout<<"Secondary 4Mom "<<part->GetParticleName()<<" "<<(*iter)->Get4Momentum()<<" "
<<(*iter)->Get4Momentum().mag()<<G4endl;
#endif
} else {
if( e-mass > -CaptureThreshold*G4Log( G4UniformRand()) ) { // Added by Uzhi 2.05.2015
if( e-mass > -CaptureThreshold*G4Log( G4UniformRand()) ) {
G4ReactionProduct * theNew = new G4ReactionProduct(part);
theNew->SetMomentum(mom);
theNew->SetTotalEnergy(e);
theTotalResult->push_back(theNew);
Secondary4Momentum += (*iter)->Get4Momentum(); // Uzhi 29 April
Secondary4Momentum += (*iter)->Get4Momentum();
#ifdef debugPrecoInt
G4cout<<"Secondary 4Mom "<<part->GetParticleName()<<" "<<(*iter)->Get4Momentum()<<" "
<<(*iter)->Get4Momentum().mag()<<G4endl;
@@ -240,7 +239,7 @@ Propagate(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus)
if(anA == 0) return theTotalResult;
G4LorentzVector exciton4Momentum(0.,0.,0.,0.); // Uzhi 29 April
G4LorentzVector exciton4Momentum(0.,0.,0.,0.);
if(anA >= aZ)
{
if(!QGSM)
@@ -251,13 +250,13 @@ Propagate(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus)
exciton4Momentum = Residual4Momentum + captured4Momentum;
//exciton4Momentum.setE(std::sqrt(exciton4Momentum.vect().mag2()+sqr(fMass)));
G4double ActualMass = exciton4Momentum.mag();
if(ActualMass <= fMass ) { //E*<=0, Uzhi 5.05.2015
exciton4Momentum.setE(std::sqrt(exciton4Momentum.vect().mag2()+sqr(fMass))); // Uzhi 13.05.2015
if(ActualMass <= fMass ) {
exciton4Momentum.setE(std::sqrt(exciton4Momentum.vect().mag2()+sqr(fMass)));
}
#ifdef debugPrecoInt
G4double exEnergy = 0.0;
if(ActualMass <= fMass ) {exEnergy = 0.;} // Uzhi 5.05.2015
if(ActualMass <= fMass ) {exEnergy = 0.;}
else {exEnergy = ActualMass - fMass;}
G4cout<<"Ground state residual Mass "<<fMass<<" E* "<<exEnergy<<G4endl;
#endif
@@ -344,7 +343,7 @@ void G4GeneratorPrecompoundInterface::PropagateModelDescription(std::ostream& ou
}
// Uzhi Nov. 2012 ------------------------------------------------
G4ReactionProductVector* G4GeneratorPrecompoundInterface::
PropagateNuclNucl(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus,
G4V3DNucleus* theProjectileNucleus)
@@ -445,6 +444,9 @@ PropagateNuclNucl(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus
// decay the strong resonances
G4ReactionProductVector * theTotalResult = new G4ReactionProductVector;
G4DecayKineticTracks decay(theSecondaries);
MakeCoalescence(theSecondaries);
#ifdef debugPrecoInt
G4cout<<"Secondary stable particles number "<<theSecondaries->size()<<G4endl;
#endif
@@ -644,24 +646,21 @@ PropagateNuclNucl(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus
if(0!=anAb)
{
// G4ThreeVector bstToCM =Projectile4Momentum.findBoostToCM(); // Uzhi Apr. 2015
// Projectile4Momentum.boost(bstToCM); // Uzhi Apr. 2015
G4double fMass = G4NucleiProperties::GetNuclearMass(anAb, aZb);
G4double RemnMass=Projectile4Momentum.mag();
if(RemnMass < fMass)
{
RemnMass=fMass + exEnergyB;
Projectile4Momentum.setE(std::sqrt(Projectile4Momentum.vect().mag2() + // Uzhi 8.05.2015
RemnMass*RemnMass)); // Uzhi 8.05.2015
Projectile4Momentum.setE(std::sqrt(Projectile4Momentum.vect().mag2() +
RemnMass*RemnMass));
} else
{ exEnergyB=RemnMass-fMass;}
if( exEnergyB < 0.) exEnergyB=0.;
G4ThreeVector bstToCM =Projectile4Momentum.findBoostToCM(); // Uzhi Apr. 2015
Projectile4Momentum.boost(bstToCM); // Uzhi Apr. 2015
G4ThreeVector bstToCM =Projectile4Momentum.findBoostToCM();
Projectile4Momentum.boost(bstToCM);
// Need to de-excite the remnant nucleus
G4Fragment anInitialState(anAb, aZb, Projectile4Momentum);
@@ -679,11 +678,11 @@ PropagateNuclNucl(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus
// fill pre-compound part into the result, and return
for(unsigned int ll=0; ll<aPrecoResult->size(); ++ll)
{
G4LorentzVector tmp=G4LorentzVector(aPrecoResult->operator[](ll)->GetMomentum(), // Uzhi 2015
aPrecoResult->operator[](ll)->GetTotalEnergy());// Uzhi 2015
tmp.boost(-bstToCM); // Transformation to the system of original remnant // Uzhi 2015
aPrecoResult->operator[](ll)->SetMomentum(tmp.vect()); // Uzhi 2015
aPrecoResult->operator[](ll)->SetTotalEnergy(tmp.e()); // Uzhi 2015
G4LorentzVector tmp=G4LorentzVector(aPrecoResult->operator[](ll)->GetMomentum(),
aPrecoResult->operator[](ll)->GetTotalEnergy());
tmp.boost(-bstToCM); // Transformation to the system of original remnant
aPrecoResult->operator[](ll)->SetMomentum(tmp.vect());
aPrecoResult->operator[](ll)->SetTotalEnergy(tmp.e());
if(ProjectileIsAntiNucleus)
{
@@ -707,7 +706,7 @@ PropagateNuclNucl(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus
<<aPrecoResult->operator[](ll)->GetTotalEnergy()<<" "
<<aPrecoResult->operator[](ll)->GetMass()<<G4endl;
#endif
//Uzhi
theTotalResult->push_back(aPrecoResult->operator[](ll));
}
@@ -718,3 +717,49 @@ PropagateNuclNucl(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus
}
void G4GeneratorPrecompoundInterface::MakeCoalescence(G4KineticTrackVector *tracks) {
if (!tracks) return;
G4double MassCut = deuteron->GetPDGMass() + DeltaM; // In MeV
for ( size_t i = 0; i < tracks->size(); ++i ) { // search for protons
G4KineticTrack* trackP = (*tracks)[i];
if ( ! trackP ) continue;
if (trackP->GetDefinition() != proton) continue;
G4LorentzVector Prot4Mom = trackP->Get4Momentum();
G4LorentzVector ProtSPposition = G4LorentzVector(trackP->GetPosition(), trackP->GetFormationTime());
for ( size_t j = 0; j < tracks->size(); ++j ) { // search for neutron
G4KineticTrack* trackN = (*tracks)[j];
if (! trackN ) continue;
if (trackN->GetDefinition() != neutron) continue;
G4LorentzVector Neut4Mom = trackN->Get4Momentum();
G4LorentzVector NeutSPposition = G4LorentzVector( trackN->GetPosition(), trackN->GetFormationTime()*hbarc/fermi);
G4double EffMass = (Prot4Mom + Neut4Mom).mag();
if ( EffMass <= MassCut ) { // && (EffDistance <= SpaceCut)) { // Create deuteron
G4KineticTrack* aDeuteron =
new G4KineticTrack( deuteron,
(trackP->GetFormationTime() + trackN->GetFormationTime())/2.0,
(trackP->GetPosition() + trackN->GetPosition() )/2.0,
( Prot4Mom + Neut4Mom ));
tracks->push_back(aDeuteron);
delete trackP; delete trackN;
(*tracks)[i] = nullptr; (*tracks)[j] = nullptr;
break;
}
}
}
// Find and remove null pointers created by decays above
for ( int jj = tracks->size()-1; jj >= 0; --jj ) {
if ( ! (*tracks)[jj] ) tracks->erase(tracks->begin()+jj);
}
}
@@ -14,6 +14,17 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
7 November 2019 Dennis Wright (hadr-casc-V10-05-02)
-----------------------------------------------------
- G4LightTargetCollider: fix crash when gamma energy below deuteron
disintegration threshold and improve exception handling
5 November 2019 Dennis Wright (hadr-casc-V10-05-01)
-----------------------------------------------------
- new class G4LightTargetCollider to more accurately handle collisons
on p, d, t, 3He. Currently only gamma on protons and deuterons is
implemented.
29 May 2019 Dennis Wright (hadr-casc-V10-05-00)
------------------------------------------------
- fix bug found in biasing/B03 example due to FPE from unprotected sqrt
@@ -79,6 +79,7 @@ class G4CollisionOutput;
class G4DynamicParticle;
class G4HadFinalState;
class G4InuclCollider;
class G4LightTargetCollider;
class G4InuclParticle;
class G4ParticleDefinition;
class G4V3DNucleus;
@@ -166,6 +167,8 @@ private:
G4InuclCollider* collider;
G4CascadeCheckBalance* balance;
G4LightTargetCollider* ltcollider;
G4InuclParticle* bullet; // Pointers to last filled versions
G4InuclParticle* target;
@@ -0,0 +1,89 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// //
// File: G4LightTargetCollider.hh //
// Date: 30 September 2019 //
// Author: Dennis Wright (SLAC) //
// //
// Description: model for collision of elementary particles with light //
// targets (H, D, T, 3He) //
// //
////////////////////////////////////////////////////////////////////////////////
#ifndef G4LIGHT_TARGET_COLLIDER_HH
#define G4LIGHT_TARGET_COLLIDER_HH
#include "G4CascadeColliderBase.hh"
#include "G4CascadeFinalStateGenerator.hh"
#include "G4CollisionOutput.hh"
class G4CascadParticle;
class G4ElementaryParticleCollider;
class G4InuclParticle;
class G4KineticTrackVector;
typedef std::pair<G4InuclElementaryParticle, G4InuclElementaryParticle> NucleonPair;
typedef std::vector<G4InuclElementaryParticle> ScatteringProducts;
class G4LightTargetCollider : public G4CascadeColliderBase {
public:
G4LightTargetCollider();
virtual ~G4LightTargetCollider();
void collide(G4InuclParticle* bullet, G4InuclParticle* target,
G4CollisionOutput& globalOutput);
void setVerboseLevel(G4int verbose=0);
private:
G4ElementaryParticleCollider* theElementaryParticleCollider;
G4CollisionOutput output; // Secondaries from main cascade
private:
// Copying of modules is forbidden
G4LightTargetCollider(const G4LightTargetCollider&);
G4LightTargetCollider& operator=(const G4LightTargetCollider&);
G4double GammaDCrossSection(G4double /*kineticEnergy*/);
G4CascadeFinalStateGenerator fsGen;
NucleonPair AbsorptionOnDeuteron(G4InuclParticle* bullet);
ScatteringProducts SingleNucleonScattering(const G4InuclElementaryParticle& projectile,
const G4InuclElementaryParticle& targetNucleon);
G4double mP; // proton mass
G4double mN; // neutron mass
G4double mD; // deuteron mass
G4double pFermiD; // deuteron Fermi momentum (GeV/c)
};
#endif /* G4LIGHT_TARGET_COLLIDER_HH */
@@ -161,6 +161,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_bert_cascade
G4InteractionCase.hh
G4IntraNucleiCascader.hh
G4InuclCollider.hh
G4LightTargetCollider.hh
G4InuclElementaryParticle.hh
G4InuclEvaporation.hh
G4InuclNuclei.hh
@@ -274,6 +275,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_bert_cascade
G4InteractionCase.cc
G4IntraNucleiCascader.cc
G4InuclCollider.cc
G4LightTargetCollider.cc
G4InuclElementaryParticle.cc
G4InuclEvaporation.cc
G4InuclNuclei.cc
@@ -116,6 +116,7 @@
#include "G4DynamicParticle.hh"
#include "G4HadronicException.hh"
#include "G4InuclCollider.hh"
#include "G4LightTargetCollider.hh"
#include "G4InuclElementaryParticle.hh"
#include "G4InuclNuclei.hh"
#include "G4InuclParticle.hh"
@@ -143,11 +144,13 @@ typedef std::vector<G4InuclNuclei>::const_iterator nucleiIterator;
// Constructor and destrutor
G4CascadeInterface::G4CascadeInterface(const G4String& name)
: G4VIntraNuclearTransportModel(name),
randomFile(G4CascadeParameters::randomFile()),
maximumTries(20), numberOfTries(0),
collider(new G4InuclCollider), balance(new G4CascadeCheckBalance(name)),
bullet(0), target(0), output(new G4CollisionOutput) {
: G4VIntraNuclearTransportModel(name),
randomFile(G4CascadeParameters::randomFile()),
maximumTries(20), numberOfTries(0),
collider(new G4InuclCollider), balance(new G4CascadeCheckBalance(name)),
ltcollider(new G4LightTargetCollider),
bullet(0), target(0), output(new G4CollisionOutput)
{
// Set up global objects for master thread or sequential build
if (G4Threading::IsMasterThread()) Initialize();
@@ -278,55 +281,71 @@ G4CascadeInterface::ApplyYourself(const G4HadProjectile& aTrack,
return NoInteraction(aTrack, theNucleus);
}
// Make conversion between native Geant4 and Bertini cascade classes.
if (!createBullet(aTrack)) {
if (verboseLevel) G4cerr << " Unable to create usable bullet" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// If target A < 3 skip all cascade machinery and do scattering on
// nucleons
if (!createTarget(theNucleus)) {
if (verboseLevel) G4cerr << " Unable to create usable target" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Different retry conditions for proton target vs. nucleus
const G4bool isHydrogen = (theNucleus.GetA_asInt() == 1);
numberOfTries = 0;
do { // we try to create inelastic interaction
if (verboseLevel > 1)
G4cout << " Generating cascade attempt " << numberOfTries << G4endl;
if (aTrack.GetDefinition() == G4Gamma::Gamma() &&
theNucleus.GetA_asInt() < 3) {
output->reset();
collider->collide(bullet, target, *output);
balance->collide(bullet, target, *output);
createBullet(aTrack);
createTarget(theNucleus);
// Due to binning, gamma-p cross sections between 130 MeV and the inelastic threshold
// (144 for pi0 p, 152 for pi+ n) are non-zero, causing energy non-conservation
// So, if Egamma is between 144 and 152, only pi0 p is allowed.
// Also, inelastic gamma-p cross section from G4PhotoNuclearCrossSection seems to be
// non-zero below between pi0 mass (135 MeV) and threshold (144 MeV)
ltcollider->collide(bullet, target, *output);
} else {
// Make conversion between native Geant4 and Bertini cascade classes.
if (!createBullet(aTrack)) {
if (verboseLevel) G4cerr << " Unable to create usable bullet" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
if (!createTarget(theNucleus)) {
if (verboseLevel) G4cerr << " Unable to create usable target" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Different retry conditions for proton target vs. nucleus
const G4bool isHydrogen = (theNucleus.GetA_asInt() == 1);
numberOfTries = 0;
do { // we try to create inelastic interaction
if (verboseLevel > 1)
G4cout << " Generating cascade attempt " << numberOfTries << G4endl;
numberOfTries++;
/* Loop checking 08.06.2015 MHK */
} while ( isHydrogen ? retryInelasticProton() : retryInelasticNucleus() );
output->reset();
collider->collide(bullet, target, *output);
balance->collide(bullet, target, *output);
numberOfTries++;
/* Loop checking 08.06.2015 MHK */
} while ( isHydrogen ? retryInelasticProton() : retryInelasticNucleus() );
// Null event if unsuccessful
if (numberOfTries >= maximumTries) {
if (verboseLevel)
G4cout << " Cascade aborted after trials " << numberOfTries << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Null event if unsuccessful
if (numberOfTries >= maximumTries) {
if (verboseLevel)
G4cout << " Cascade aborted after trials " << numberOfTries << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Abort job if energy or momentum are not conserved
if (!balance->okay()) {
throwNonConservationFailure();
return NoInteraction(aTrack, theNucleus);
}
// Abort job if energy or momentum are not conserved
if (!balance->okay()) {
throwNonConservationFailure();
return NoInteraction(aTrack, theNucleus);
}
// Successful cascade -- clean up and return
if (verboseLevel) {
G4cout << " Cascade output after trials " << numberOfTries << G4endl;
if (verboseLevel > 1) output->printCollisionOutput();
}
// Successful cascade -- clean up and return
if (verboseLevel) {
G4cout << " Cascade output after trials " << numberOfTries << G4endl;
if (verboseLevel > 1) output->printCollisionOutput();
}
// Rotate event to put Z axis along original projectile direction
// Removed by DHW to fix bug #1990
// output->rotateEvent(bulletInLabFrame);
} // end cascade-style collisions
copyOutputToHadronicResult();
@@ -84,27 +84,27 @@ const G4CascadeParameters* G4CascadeParameters::Instance() {
//#define OLD_RADIUS_UNITS (3.3836/1.2) // Used with NucModel params
G4CascadeParameters::G4CascadeParameters()
: G4CASCADE_VERBOSE(getenv("G4CASCADE_VERBOSE")),
G4CASCADE_CHECK_ECONS(getenv("G4CASCADE_CHECK_ECONS")),
G4CASCADE_USE_PRECOMPOUND(getenv("G4CASCADE_USE_PRECOMPOUND")),
G4CASCADE_DO_COALESCENCE(getenv("G4CASCADE_DO_COALESCENCE")),
G4CASCADE_SHOW_HISTORY(getenv("G4CASCADE_SHOW_HISTORY")),
G4CASCADE_USE_3BODYMOM(getenv("G4CASCADE_USE_3BODYMOM")),
G4CASCADE_USE_PHASESPACE(getenv("G4CASCADE_USE_PHASESPACE")),
G4CASCADE_PIN_ABSORPTION(getenv("G4CASCADE_PIN_ABSORPTION")),
G4CASCADE_RANDOM_FILE(getenv("G4CASCADE_RANDOM_FILE")),
G4NUCMODEL_USE_BEST(getenv("G4NUCMODEL_USE_BEST")),
G4NUCMODEL_RAD_2PAR(getenv("G4NUCMODEL_RAD_2PAR")),
G4NUCMODEL_RAD_SCALE(getenv("G4NUCMODEL_RAD_SCALE")),
G4NUCMODEL_RAD_SMALL(getenv("G4NUCMODEL_RAD_SMALL")),
G4NUCMODEL_RAD_ALPHA(getenv("G4NUCMODEL_RAD_ALPHA")),
G4NUCMODEL_RAD_TRAILING(getenv("G4NUCMODEL_RAD_TRAILING")),
G4NUCMODEL_FERMI_SCALE(getenv("G4NUCMODEL_FERMI_SCALE")),
G4NUCMODEL_XSEC_SCALE(getenv("G4NUCMODEL_XSEC_SCALE")),
G4NUCMODEL_GAMMAQD(getenv("G4NUCMODEL_GAMMAQD")),
DPMAX_2CLUSTER(getenv("DPMAX_2CLUSTER")),
DPMAX_3CLUSTER(getenv("DPMAX_3CLUSTER")),
DPMAX_4CLUSTER(getenv("DPMAX_4CLUSTER")),
: G4CASCADE_VERBOSE(std::getenv("G4CASCADE_VERBOSE")),
G4CASCADE_CHECK_ECONS(std::getenv("G4CASCADE_CHECK_ECONS")),
G4CASCADE_USE_PRECOMPOUND(std::getenv("G4CASCADE_USE_PRECOMPOUND")),
G4CASCADE_DO_COALESCENCE(std::getenv("G4CASCADE_DO_COALESCENCE")),
G4CASCADE_SHOW_HISTORY(std::getenv("G4CASCADE_SHOW_HISTORY")),
G4CASCADE_USE_3BODYMOM(std::getenv("G4CASCADE_USE_3BODYMOM")),
G4CASCADE_USE_PHASESPACE(std::getenv("G4CASCADE_USE_PHASESPACE")),
G4CASCADE_PIN_ABSORPTION(std::getenv("G4CASCADE_PIN_ABSORPTION")),
G4CASCADE_RANDOM_FILE(std::getenv("G4CASCADE_RANDOM_FILE")),
G4NUCMODEL_USE_BEST(std::getenv("G4NUCMODEL_USE_BEST")),
G4NUCMODEL_RAD_2PAR(std::getenv("G4NUCMODEL_RAD_2PAR")),
G4NUCMODEL_RAD_SCALE(std::getenv("G4NUCMODEL_RAD_SCALE")),
G4NUCMODEL_RAD_SMALL(std::getenv("G4NUCMODEL_RAD_SMALL")),
G4NUCMODEL_RAD_ALPHA(std::getenv("G4NUCMODEL_RAD_ALPHA")),
G4NUCMODEL_RAD_TRAILING(std::getenv("G4NUCMODEL_RAD_TRAILING")),
G4NUCMODEL_FERMI_SCALE(std::getenv("G4NUCMODEL_FERMI_SCALE")),
G4NUCMODEL_XSEC_SCALE(std::getenv("G4NUCMODEL_XSEC_SCALE")),
G4NUCMODEL_GAMMAQD(std::getenv("G4NUCMODEL_GAMMAQD")),
DPMAX_2CLUSTER(std::getenv("DPMAX_2CLUSTER")),
DPMAX_3CLUSTER(std::getenv("DPMAX_3CLUSTER")),
DPMAX_4CLUSTER(std::getenv("DPMAX_4CLUSTER")),
messenger(0) {
messenger = new G4CascadeParamMessenger(this);
Initialize();
@@ -246,7 +246,7 @@ void G4InuclCollider::collide(G4InuclParticle* bullet, G4InuclParticle* target,
output.removeRecoilFragment();
//*** TEMPORARY, USE ENVVAR TO ENABLE/DISABLE THIS TEST ***
if (getenv("G4CASCADE_CHECK_PHOTONUCLEAR"))
if (std::getenv("G4CASCADE_CHECK_PHOTONUCLEAR"))
if (!photonuclearOkay(output)) continue;
if (verboseLevel > 2)
@@ -0,0 +1,369 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// //
// File: G4LightTargetCollider.cc //
// Date: 30 September 2019 //
// Author: Dennis Wright (SLAC) //
// //
// Description: model for collision of elementary particles with light //
// targets (H, D, T, 3He) //
// //
////////////////////////////////////////////////////////////////////////////////
#include "G4LightTargetCollider.hh"
#include "G4CascadeChannel.hh"
#include "G4CascadeChannelTables.hh"
#include "G4CascadeCheckBalance.hh"
#include "G4CollisionOutput.hh"
#include "G4ElementaryParticleCollider.hh"
#include "G4InuclElementaryParticle.hh"
#include "G4InuclNuclei.hh"
#include "G4NucleiModel.hh"
#include "G4LorentzConvertor.hh"
#include "G4Deuteron.hh"
#include "G4Gamma.hh"
#include "G4PionZero.hh"
#include "G4PionPlus.hh"
#include "G4PionMinus.hh"
#include "G4RandomDirection.hh"
G4LightTargetCollider::G4LightTargetCollider()
: G4CascadeColliderBase("G4LightTargetCollider"),
theElementaryParticleCollider(new G4ElementaryParticleCollider)
{
mP = G4Proton::Proton()->GetPDGMass()/CLHEP::GeV;
mN = G4Neutron::Neutron()->GetPDGMass()/CLHEP::GeV;
mD = G4Deuteron::Deuteron()->GetPDGMass()/CLHEP::GeV;
pFermiD = 0.045; // Fermi momentum of nucleon in deuteron Hulthen potential
}
G4LightTargetCollider::~G4LightTargetCollider() {
delete theElementaryParticleCollider;
}
// Set verbosity and pass on to member objects
void G4LightTargetCollider::setVerboseLevel(G4int verbose) {
G4CascadeColliderBase::setVerboseLevel(verbose);
theElementaryParticleCollider->setVerboseLevel(verboseLevel);
output.setVerboseLevel(verboseLevel);
}
void G4LightTargetCollider::collide(G4InuclParticle* bullet,
G4InuclParticle* target,
G4CollisionOutput& globalOutput)
{
if (verboseLevel) {
G4cout << " >>> G4LightTargetCollider::collide" << G4endl;
G4cout << " Projectile: " << bullet->getDefinition()->GetParticleName() << G4endl;
G4cout << " Target: " << target->getDefinition()->GetParticleName() << G4endl;
}
// Particle-on-particle collision
// No nucleus involved, just a proton in this case
if (useEPCollider(bullet,target)) {
if (verboseLevel > 2)
G4cout << " InuclCollider -> particle on particle collision" << G4endl;
theElementaryParticleCollider->collide(bullet, target, globalOutput);
return;
}
G4double ke = bullet->getKineticEnergy();
if (target->getDefinition() == G4Deuteron::Deuteron()) {
if (ke < mP + mN - mD) {
// Should not happen as long as inelastic cross section is zero
G4Exception("G4LightTargetCollider::collide()","HAD_BERT_201",
JustWarning, "Projectile energy below reaction threshold");
globalOutput.trivialise(bullet, target);
} else {
// Get p, n and deuteron cross sections; use lab energy to access
G4double gammaPXS = G4CascadeChannelTables::GetTable(9)->getCrossSection(ke);
G4double gammaNXS = G4CascadeChannelTables::GetTable(18)->getCrossSection(ke);
G4double gammaDXS = GammaDCrossSection(ke);
G4double probP = 0.0;
G4double probN = 0.0;
// Highest threshold is 0.152 (for gamma p -> n pi+)
// Because of Fermi momentum in deuteron, raise this to 0.159
if (ke > 0.159) {
G4double totalDXS = gammaPXS + gammaNXS + gammaDXS;
probP = gammaPXS/totalDXS;
probN = (gammaPXS+gammaNXS)/totalDXS;
}
G4double rndm = G4UniformRand();
if (rndm < probP) {
// Generate Fermi momenta of bullet and target
G4ThreeVector fermiMomentum = pFermiD*G4RandomDirection();
G4LorentzVector protonMomentum(fermiMomentum, std::sqrt(mP*mP + pFermiD*pFermiD) );
G4LorentzVector neutronMomentum(-fermiMomentum, std::sqrt(mN*mN + pFermiD*pFermiD) );
G4LorentzVector bulletMomentum = bullet->getMomentum();
G4ThreeVector betacm = bulletMomentum.findBoostToCM(protonMomentum);
// First boost bullet and target so that target is at rest
G4ThreeVector toProtonRest = -protonMomentum.boostVector();
protonMomentum.boost(toProtonRest);
bulletMomentum.boost(toProtonRest);
G4InuclElementaryParticle projectile(bulletMomentum, bullet->getDefinition() );
G4InuclElementaryParticle targetNucleon(protonMomentum, G4Proton::Proton() );
G4InuclElementaryParticle spectatorNucleon(neutronMomentum, G4Neutron::Neutron() );
ScatteringProducts products = SingleNucleonScattering(projectile, targetNucleon);
// Particles from SingleNucleonScattering are in CM frame of projectile
// and moving proton. Transform back to lab frame with -betacm, then
// add them to outgoing list.
globalOutput.reset();
G4LorentzVector temp;
for (G4int i = 0; i < G4int(products.size()); i++) {
temp = products[i].getMomentum();
temp.boost(-betacm);
products[i].setMomentum(temp);
globalOutput.addOutgoingParticle(products[i]);
}
// Add the recoil nucleon unmodified
globalOutput.addOutgoingParticle(spectatorNucleon);
} else if (rndm < probN) {
G4ThreeVector fermiMomentum = pFermiD*G4RandomDirection();
G4LorentzVector protonMomentum(fermiMomentum, std::sqrt(mP*mP + pFermiD*pFermiD) );
G4LorentzVector neutronMomentum(-fermiMomentum, std::sqrt(mN*mN + pFermiD*pFermiD) );
G4LorentzVector bulletMomentum = bullet->getMomentum();
G4ThreeVector betacm = bulletMomentum.findBoostToCM(neutronMomentum);
// First boost bullet and target so that target is at rest
G4ThreeVector toNeutronRest = -neutronMomentum.boostVector();
neutronMomentum.boost(toNeutronRest);
bulletMomentum.boost(toNeutronRest);
G4InuclElementaryParticle projectile(bulletMomentum, bullet->getDefinition() );
G4InuclElementaryParticle targetNucleon(neutronMomentum, G4Neutron::Neutron() );
G4InuclElementaryParticle spectatorNucleon(protonMomentum, G4Proton::Proton() );
ScatteringProducts products = SingleNucleonScattering(projectile, targetNucleon);
// Particles from SingleNucleonScattering are in CM frame of projectile
// and moving neutron. Transform back to lab frame with -betacm, then add
// them to outgoing list
globalOutput.reset();
G4LorentzVector temp;
for (G4int i = 0; i < G4int(products.size()); i++) {
temp = products[i].getMomentum();
temp.boost(-betacm);
products[i].setMomentum(temp);
globalOutput.addOutgoingParticle(products[i]);
}
// Add the recoil nucleon unmodified
globalOutput.addOutgoingParticle(spectatorNucleon);
} else {
NucleonPair products = AbsorptionOnDeuteron(bullet);
globalOutput.reset();
globalOutput.addOutgoingParticle(products.first);
globalOutput.addOutgoingParticle(products.second);
}
} // Energy above threshold ?
// Test code
// G4int numPart = globalOutput.numberOfOutgoingParticles();
// std::vector<G4InuclElementaryParticle> testList = globalOutput.getOutgoingParticles();
// G4LorentzVector sumP;
// G4cout << " Global output " << G4endl;
// for (G4int i = 0; i < numPart; i++) {
// sumP += testList[i].getMomentum();
// G4cout << testList[i] << G4endl;
// }
// G4cout << " Global 4-momentum sum = " << sumP << G4endl;
// G4cout << " Initial lab energy = " << mD + bullet->getEnergy() << G4endl;
} else {
G4Exception("G4LightTargetCollider::collide()","HAD_BERT_203",
FatalException, "Scattering from this target not implemented");
}
return;
}
G4double G4LightTargetCollider::GammaDCrossSection(G4double gammaEnergy)
{
// Gamma deuteron cross section in mb parameterized from JLab data
// No parameterization needed below pi0 threshold where cross section
// is 100% disintegration
G4double sigma = 1000.0;
G4double term = 0.;
if (gammaEnergy > 0.144 && gammaEnergy < 0.42) {
term = (gammaEnergy - 0.24)/0.155;
sigma = 0.065*std::exp(-term*term);
} else if (gammaEnergy >= 0.42) {
sigma = 0.000526/gammaEnergy/gammaEnergy/gammaEnergy/gammaEnergy;
}
return sigma;
}
NucleonPair G4LightTargetCollider::AbsorptionOnDeuteron(G4InuclParticle* bullet)
{
// Do break-up in center of mass, convert to lab frame before returning
// particles
G4double bulletMass = bullet->getMass();
G4double bulletE = bullet->getEnergy();
G4double S = bulletMass*bulletMass + mD*mD + 2.*mD*bulletE;
G4double qcm = 0.;
G4int outType1 = 0;
G4int outType2 = 0;
G4LorentzVector Mom1;
G4LorentzVector Mom2;
// Set up outgoing particle types
if (bullet->getDefinition() == G4Gamma::Gamma() ||
bullet->getDefinition() == G4PionZero::PionZero() ) {
qcm = std::sqrt( (S - (mP + mN)*(mP + mN)) * (S - (mP - mN)*(mP - mN))/S/4.);
Mom1.setE(std::sqrt(mP*mP + qcm*qcm) );
outType1 = G4InuclParticleNames::proton;
Mom2.setE(std::sqrt(mN*mN + qcm*qcm) );
outType2 = G4InuclParticleNames::neutron;
} else if (bullet->getDefinition() == G4PionPlus::PionPlus() ) {
qcm = std::sqrt( (S - 4.*mP*mP)/4.);
Mom1.setE(std::sqrt(mP*mP + qcm*qcm) );
outType1 = G4InuclParticleNames::proton;
Mom2.setE(std::sqrt(mP*mP + qcm*qcm) );
outType2 = G4InuclParticleNames::proton;
} else if (bullet->getDefinition() == G4PionMinus::PionMinus() ) {
qcm = std::sqrt( (S - 4.*mN*mN)/4.);
Mom1.setE(std::sqrt(mN*mN + qcm*qcm) );
outType1 = G4InuclParticleNames::neutron;
Mom2.setE(std::sqrt(mN*mN + qcm*qcm) );
outType2 = G4InuclParticleNames::neutron;
} else {
G4Exception("G4LightTargetCollider::collide()","HAD_BERT_204",
FatalException, "Illegal bullet type");
}
// Sample angular distribution, assuming 100% S wave (no D-wave)
G4ThreeVector qVect = qcm*G4RandomDirection();
Mom1.setVect(qVect);
Mom2.setVect(-qVect);
// Boost to lab frame
G4ThreeVector betacm(0., 0., bullet->getMomModule()/(bulletE + mD) );
Mom1.boost(betacm);
Mom2.boost(betacm);
G4InuclElementaryParticle particle1(Mom1, outType1);
G4InuclElementaryParticle particle2(Mom2, outType2);
NucleonPair nucleon_pair(particle1, particle2);
// if pion, use parameterization of B.G. Ritchie, PRC 44, 533 (1991)
// Total cross section: 1/E + Lorentzian
return nucleon_pair;
}
ScatteringProducts
G4LightTargetCollider::SingleNucleonScattering(const G4InuclElementaryParticle& projectile,
const G4InuclElementaryParticle& nucleon)
{
// At this point projectile and nucleon momenta are in nucleon rest frame
G4int reactionIndex = G4InuclElementaryParticle::type(projectile.getDefinition() )
* G4InuclElementaryParticle::type(nucleon.getDefinition() );
const G4CascadeChannel* xsecTable = G4CascadeChannelTables::GetTable(reactionIndex);
G4double ke = projectile.getKineticEnergy();
G4int mult = xsecTable->getMultiplicity(ke);
std::vector<G4double> masses;
G4double mass = 0.0;
G4LorentzVector totalMom = projectile.getMomentum() + nucleon.getMomentum();
G4double Ecm = totalMom.mag();
std::vector<G4LorentzVector> cmMomenta;
std::vector<G4int> particle_kinds;
G4int itry = 0;
G4int itry_max = 200;
G4bool generate = true;
while (mult > 1) {
itry = 0;
generate = true;
while (generate && itry < itry_max) {
particle_kinds.clear();
xsecTable->getOutgoingParticleTypes(particle_kinds, mult, ke);
masses.clear();
for (G4int i = 0; i < mult; i++) {
mass = G4InuclElementaryParticle::getParticleMass(particle_kinds[i]);
masses.push_back(mass);
}
fsGen.Configure(const_cast<G4InuclElementaryParticle*>(&projectile),
const_cast<G4InuclElementaryParticle*>(&nucleon),
particle_kinds);
// Generate final state in CM of projectile and at-rest nucleon
cmMomenta.clear();
generate = !fsGen.Generate(Ecm, masses, cmMomenta);
itry++;
} // while
if (itry == itry_max) mult--;
else break;
} // while mult
ScatteringProducts finalState;
if (mult < 2) {
G4Exception("G4LightTargetCollider::SingleNucleonScattering()","HAD_BERT_202",
JustWarning, "Failed to generate final state");
// Final state particles not in CM - just using them as dummies
finalState.push_back(projectile);
finalState.push_back(nucleon);
} else {
for (G4int i = 0; i < mult; i++) {
G4InuclElementaryParticle fsPart(cmMomenta[i], particle_kinds[i]);
finalState.push_back(fsPart);
}
}
return finalState;
}
@@ -18,6 +18,7 @@ CPPFLAGS += -I$(G4BASE)/global/management/include \
-I$(G4BASE)/track/include \
-I$(G4BASE)/geometry/volumes/include \
-I$(G4BASE)/geometry/management/include \
-I$(G4BASE)/processes/cuts/include \
-I$(G4BASE)/processes/management/include \
-I$(G4BASE)/processes/hadronic/management/include/ \
-I$(G4BASE)/processes/hadronic/util/include/ \
@@ -14,6 +14,41 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
26 November 2019 - V.Ivanchenko (hadr-cohe-V10-05-10)
---------------------------------------------------------------
- G4HadronElastic : Added limit on number of warning printouts
19 November 2019 - G. Folger (hadr-cohe-V10-05-09)
---------------------------------------------------------------
- remove using namespace std and using namespace CLHEP from header file
G4NeutronElectronElModel.hh
15 November 2019 - V.Ivanchenko (hadr-cohe-V10-05-08)
---------------------------------------------------------------
- G4HadronElastic : Change warning printout, in the case if sampled
t>tmax resample using simple algorithm, protect this warning
by G4VERBOSE, this is a partial fix of #2204
06 November 2019 - A.Ribon (hadr-cohe-V10-05-07)
---------------------------------------------------------------
- G4HadronElastic : Coverity fix in the unused method GetSlopeCof.
31 October 2019 - V.Ivanchenko (hadr-cohe-V10-05-06)
--------------------------------------------------------
- G4ElasticHadrNucleusHE - reduction of size of data structure and
time for initialisation ~2 times; general code clean-up; addition
of protections
07 October 2019 - V.Grichine (hadr-cohe-V10-05-05)
---------------------------------------------------------------
- G4hadronElstic - new method for s-,c-,b-particle
- ds/dt slope modifications in preparation
03 July 2019 - V.Ivanchenko (hadr-cohe-V10-05-04)
--------------------------------------------------------
- G4ElasticHadrNucleusHE - general clean-up of the code
- G4HadronElastic - added new parameterisation of A.Yeltokov
14 May 2019 - A.Ribon (hadr-cohe-V10-05-03)
--------------------------------------------------------
- G4HadronElastic : numerically safer treatment of the very rare cases
@@ -23,15 +23,12 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4ElasticHadrNucleusHe.hh
// The generator of high energy hadron-nucleus elastic scattering
// The hadron kinetic energy T > 1 GeV
// N. Starkov 2003.
// N.Starkov 2003.
//
// 19.05.04 Variant for G4 6.1: The 'ApplyYourself' was changed
// 19.11.05 The HE elastic scattering on proton is added (N.Starkov)
// 16.11.06 General redesign (N.Starkov)
// 23.11.06 General cleanup, ONQ0=3 (V.Ivanchenko)
@@ -55,43 +52,39 @@
class G4NistManager;
static const G4int NHADRONS = 26; // Number of hadrons
static const G4int ONQ0 = 5; // The initial number of steps on Q2
static const G4int ONQ2 = 100; // The total number of steps on Q2
static const G4int NENERGY = 30;
static const G4int ZMAX = 93;
static const G4int NQTABLE = NENERGY*ONQ2;
static const G4int NHADRONS = 26; // Number of allowed hadrons
static const G4int ONQ2 = 102; // Number of points on Q2
static const G4int NENERGY = 24;
static const G4int ZMAX = 93;
///////////////////////////////////////////////////////////////////////
class G4ElasticData
{
friend class G4ElasticHadrNucleusHE;
public:
G4ElasticData(const G4ParticleDefinition* h, G4int Z, G4int A, G4double* e);
G4ElasticData(const G4ParticleDefinition* h, G4int Z, G4int A,
const G4double* e);
~G4ElasticData(){}
const G4ParticleDefinition* Hadron() {return hadr;}
~G4ElasticData() {}
private:
void DefineNucleusParameters(G4int A);
const G4ParticleDefinition* hadr;
// hide assignment operator
G4ElasticData & operator=(const G4ElasticData &right);
G4ElasticData(const G4ElasticData&);
public:
G4double R1, R2, Pnucl, Aeff;
G4double limitQ2;
G4double dQ2;
G4double massA;
G4double massA2;
G4int dnkE[NENERGY];
G4double maxQ2[NENERGY];
G4double TableQ2[ONQ2];
G4double TableCrossSec[NQTABLE];
std::vector<G4double> fCumProb[NENERGY];
};
/////////////////////////////////////////////////////////////////////
@@ -113,97 +106,81 @@ public:
private:
G4double HadronNucleusQ2_2(G4ElasticData * pElD, G4int Z,
G4double plabGeV, G4double tmax);
G4double HadronNucleusQ2_2(const G4ElasticData *pElD, G4double plabGeV,
G4double tmax);
void DefineHadronValues(G4int Z);
G4int FillFq2(G4int A);
G4double GetLightFq2(G4int Z, G4int A, G4double Q);
G4double GetHeavyFq2(G4int Z, G4int Nucleus, G4double *LineFq2);
G4double GetQ2_2(G4int N, G4double* Q, G4double* F, G4double R);
G4double GetQ2_2(G4int N, G4int Nmax,
const std::vector<G4double>& F, G4double rand);
G4double LineInterpol(G4double p0, G4double p2,
G4double c1, G4double c2,
G4double p);
G4double HadrNucDifferCrSec(G4int Z, G4int Nucleus, G4double Q2);
G4double HadrNucDifferCrSec(G4int A, G4double Q2);
void InterpolateHN(G4int n, const G4double EnP[],
const G4double C0P[], const G4double C1P[],
const G4double B0P[], const G4double B1P[]);
// hide assignment operator
G4ElasticHadrNucleusHE & operator=(const G4ElasticHadrNucleusHE &right);
G4ElasticHadrNucleusHE(const G4ElasticHadrNucleusHE&);
G4double GetBinomCof( G4int n, G4int m );
G4double GetFt(G4double Q2);
G4double GetDistrFun(G4double Q2);
G4double GetQ2(G4double Ran);
G4double HadronProtonQ2(const G4ParticleDefinition * aHadron,
G4double inLabMom);
void GetKinematics(const G4ParticleDefinition * aHadron,
G4double MomentumH);
G4double HadronProtonQ2(G4double plab, G4double tmax);
void Binom();
void FillData(const G4ParticleDefinition* p, G4int idx, G4int Z);
inline G4double LineInterpol(G4double p0, G4double p2,
G4double c1, G4double c2, G4double p);
inline G4double GetBinomCof( G4int n, G4int m );
// hide assignment operator
G4ElasticHadrNucleusHE & operator=(const G4ElasticHadrNucleusHE &right);
G4ElasticHadrNucleusHE(const G4ElasticHadrNucleusHE&);
// fields
G4int iHadrCode;
G4int iHadron;
static const G4int HadronCode[NHADRONS];
static const G4int HadronType[NHADRONS];
static const G4int HadronType1[NHADRONS];
G4int iHadron1;
static const G4int fHadronCode[NHADRONS];
static const G4int fHadronType[NHADRONS];
static const G4int fHadronType1[NHADRONS];
// momemtum limits
G4double plabLowLimit;
G4double dQ2;
// transition between internal and CLHEP units
G4double MbToGeV2;
G4double sqMbToGeV;
G4double Fm2ToGeV2;
G4double GeV2;
G4double protonM; // GeV
G4double protonM2; // GeV^2
// projectile kinematics in GeV
G4double hMass;
G4double hMass2;
G4double hLabMomentum;
G4double hLabMomentum2;
G4double MomentumCM;
G4double HadrEnergy;
// elastic parameters
G4double HadrTot, HadrSlope, HadrReIm, TotP,
DDSect2, DDSect3, ConstU, FmaxT;
G4double HadrTot, HadrSlope, HadrReIm, TotP;
G4double DDSect2, DDSect3, ConstU;
// momentum limits for different models of hadron/nucleon scatetring
G4double BoundaryP[7], BoundaryTL[7], BoundaryTG[7];
// parameterisation of scattering
G4double Slope1, Slope2, Coeff1, Coeff2, MaxTR;
G4double Slope1, Slope2, Coeff1, Coeff2;
G4double Slope0, Coeff0;
G4double aAIm, aDIm, Dtot11;
// nucleaus parameters
G4double R1, R2, Pnucl, Aeff;
G4int NumbN;
G4double R1, R2, Pnucl, Aeff, Q2max;
static G4double Energy[NENERGY];
static G4double LowEdgeEnergy[NENERGY];
static G4double ABinom[240][240];
static G4double fLineF[ONQ2];
static G4double fEnergy[NENERGY];
static G4double fLowEdgeEnergy[NENERGY];
static G4double fBinom[240][240];
static G4ElasticData* SetOfElasticData[NHADRONS][ZMAX];
static G4ElasticData* fElasticData[NHADRONS][ZMAX];
G4NistManager* nistManager;
G4bool isMaster;
@@ -228,15 +205,7 @@ G4double G4ElasticHadrNucleusHE::LineInterpol(G4double p1, G4double p2,
inline
G4double G4ElasticHadrNucleusHE::GetBinomCof(G4int numN, G4int numM)
{
return (numN >= numM && numN < 240) ? ABinom[numN][numM] : 0.0;
}
////////////////////////////////////////////////////////////////
inline
G4double G4ElasticHadrNucleusHE::GetDistrFun(G4double Q2)
{
return GetFt(Q2)/FmaxT;
return (numN >= numM && numN < 240) ? fBinom[numN][numM] : 0.0;
}
////////////////////////////////////////////////////////////////
@@ -60,6 +60,8 @@ public:
// sample momentum transfer using Lab. momentum
G4double SampleInvariantT(const G4ParticleDefinition* p, G4double plab,
G4int Z, G4int A) override;
G4double GetSlopeCof( const G4int pdg );
inline void SetLowestEnergyLimit(G4double value);
@@ -82,6 +84,7 @@ private:
G4ParticleDefinition* theAlpha;
G4double lowestEnergyLimit;
G4int nwarn;
};
inline void G4HadronElastic::SetLowestEnergyLimit(G4double value)
@@ -44,9 +44,6 @@
#include "G4Nucleus.hh"
#include "G4NucleiProperties.hh"
using namespace std;
using namespace CLHEP;
class G4ParticleDefinition;
class G4PhysicsLogVector;
class G4PhysicsTable;
@@ -106,7 +103,7 @@ inline G4double G4NeutronElectronElModel::CalculateAm( G4double Tkin)
fee = (Tkin+fM)*fme/fM;
// G4cout<<"fee = "<<fee<<" MeV"<<G4endl;
fee2 = fee*fee;
G4double momentum = sqrt( fee2 - fme2 );
G4double momentum = std::sqrt( fee2 - fme2 );
G4double k = momentum/CLHEP::hbarc;
G4double ch = 1.13;
G4double zn = 1.77*k*CLHEP::Bohr_radius;
@@ -31,6 +31,7 @@ include_directories(${CMAKE_SOURCE_DIR}/source/particles/hadrons/ions/include)
include_directories(${CMAKE_SOURCE_DIR}/source/particles/hadrons/mesons/include)
include_directories(${CMAKE_SOURCE_DIR}/source/particles/leptons/include)
include_directories(${CMAKE_SOURCE_DIR}/source/particles/management/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/cuts/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/hadronic/cross_sections/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/hadronic/management/include)
include_directories(${CMAKE_SOURCE_DIR}/source/processes/hadronic/models/management/include)
@@ -84,6 +85,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_coherent_elastic
GRANULAR_DEPENDENCIES
G4baryons
G4bosons
G4cuts
G4geometrymng
G4globman
G4had_mod_man
File diff suppressed because it is too large Load Diff
@@ -50,7 +50,9 @@ G4HadronElastic::G4HadronElastic(const G4String& name)
{
SetMinEnergy( 0.0*GeV );
SetMaxEnergy( G4HadronicParameters::Instance()->GetMaxEnergy() );
lowestEnergyLimit= 1.e-6*eV;
lowestEnergyLimit= 1.e-6*eV;
pLocalTmax = 0.0;
nwarn = 0;
theProton = G4Proton::Proton();
theNeutron = G4Neutron::Neutron();
@@ -115,38 +117,31 @@ G4HadFinalState* G4HadronElastic::ApplyYourself(
pLocalTmax = 4.0*momentumCMS*momentumCMS;
// Sampling in CM system
G4double t = SampleInvariantT(theParticle, plab, Z, A);
G4double t = SampleInvariantT(theParticle, plab, Z, A);
if(t < 0.0 || t > pLocalTmax) {
// For the very rare cases where cos(theta) is greater than 1 or smaller than -1,
// print some debugging information via a "JustWarning" exception, and resample
// using the default algorithm
#ifdef G4VERBOSE
if(nwarn < 2) {
G4ExceptionDescription ed;
ed << GetModelName() << " wrong sampling t= " << t << " tmax= " << pLocalTmax
<< " for " << aParticle->GetDefinition()->GetParticleName()
<< " ekin=" << ekin << " MeV"
<< " off (Z,A)=(" << Z << "," << A << ") - will be resampled" << G4endl;
G4Exception( "G4HadronElastic::ApplyYourself", "hadEla001", JustWarning, ed);
++nwarn;
}
#endif
t = G4HadronElastic::SampleInvariantT(theParticle, plab, Z, A);
}
G4double phi = G4UniformRand()*CLHEP::twopi;
G4double cost = 1. - 2.0*t/pLocalTmax;
// For the very rare cases where cos(theta) is greater than 1 or smaller than -1,
// print some debugging information via a "JustWarning" exception, and safely
// return (simply setting "cost=1.0" or "cost=-1.0" can sometimes cause a crash,
// due to numerical imprecisions, e.g. 3-momentum = (0.0, 0.0, 0.0) but
// Ekin very small but not 0.0).
if ( std::abs( cost ) > 1.0 ) {
G4ExceptionDescription ed;
ed << " LARGE cost ! cost=" << cost << " for " << aParticle->GetDefinition()->GetParticleName()
<< " ekin=" << ekin << " MeV" << " on (Z,A)=(" << Z << "," << A << ")" << G4endl;
if ( cost > 1.0 ) {
// We assume here no interaction and let the projectile keep going unchanged.
theParticleChange.SetEnergyChange( ekin );
theParticleChange.SetMomentumChange( aParticle->Get4Momentum().vect().unit() );
ed << "\t No interaction: the projectile keeps going unchanged!" << G4endl;
G4Exception( "G4HadronElastic::ApplyYourself", "hadEla001", JustWarning, ed );
return &theParticleChange;
} else { // cost < -1.0 ) {
// We assume here that the projectile stops and its energy is deposited locally
// (for simplicity, given that this condition should happen rarely, we neglect
// the recoil of the target nucleus).
theParticleChange.SetEnergyChange( 0.0 );
theParticleChange.SetLocalEnergyDeposit( ekin );
ed << "\t Projectile stops and its energy is deposited locally:" << G4endl
<< "\t neglected recoil of the target nucleus!" << G4endl;
G4Exception( "G4HadronElastic::ApplyYourself", "hadEla002", JustWarning, ed );
return &theParticleChange;
}
}
if (cost > 1.0) { cost = 1.0; }
else if(cost < -1.0) { cost = -1.0; }
G4double sint = std::sqrt((1.0-cost)*(1.0+cost));
@@ -207,22 +202,58 @@ G4HadFinalState* G4HadronElastic::ApplyYourself(
// sample momentum transfer in the CMS system
G4double
G4HadronElastic::SampleInvariantT(const G4ParticleDefinition*,
G4double, G4int, G4int A)
G4HadronElastic::SampleInvariantT(const G4ParticleDefinition* part,
G4double mom, G4int, G4int A)
{
static const G4double GeV2 = GeV*GeV;
const G4double plabLowLimit = 400.0*CLHEP::MeV;
const G4double GeV2 = GeV*GeV;
const G4double z07in13 = std::pow(0.7, 0.3333333333);
G4int pdg = std::abs(part->GetPDGEncoding());
G4double tmax = pLocalTmax/GeV2;
G4double aa, bb, cc;
static const G4double dd = 10.;
G4double aa, bb, cc, dd;
G4Pow* g4pow = G4Pow::GetInstance();
if (A <= 62) {
bb = 14.5*g4pow->Z23(A);
aa = g4pow->powZ(A, 1.63)/bb;
cc = 1.4*g4pow->Z13(A)/dd;
} else {
bb = 60.*g4pow->Z13(A);
aa = g4pow->powZ(A, 1.33)/bb;
cc = 0.4*g4pow->powZ(A, 0.4)/dd;
if (pdg == 211){ //Pions
if(mom >= plabLowLimit){ //High energy
bb = 14.5*g4pow->Z23(A);/*14.5*/
dd = 10.;
cc = 0.075*g4pow->Z13(A)/dd;//1.4
//aa = g4pow->powZ(A, 1.93)/bb;//1.63
aa = (A*A)/bb;//1.63
} else { //Low energy
bb = 29.*z07in13*z07in13*g4pow->Z23(A);
dd = 15.;
cc = 0.04*g4pow->Z13(A)/dd;//1.4
aa = g4pow->powZ(A, 1.63)/bb;//1.63
}
} else { //Other particles
bb = 14.5*g4pow->Z23(A);
dd = 20.;
aa = (A*A)/bb;//1.63
cc = 1.4*g4pow->Z13(A)/dd;
}
//===========================
} else { //(A>62)
if (pdg == 211) {
if(mom >= plabLowLimit){ //high
bb = 60.*z07in13*g4pow->Z13(A);//60
dd = 30.;
aa = 0.5*(A*A)/bb;//1.33
cc = 4.*g4pow->powZ(A,0.4)/dd;//1:0.4 --- 2: 0.4
} else { //low
bb = 120.*z07in13*g4pow->Z13(A);//60
dd = 30.;
aa = 2.*g4pow->powZ(A,1.33)/bb;
cc = 4.*g4pow->powZ(A,0.4)/dd;//1:0.4 --- 2: 0.4
}
} else {
bb = 60.*g4pow->Z13(A);
dd = 25.;
aa = g4pow->powZ(A,1.33)/bb;//1.33
cc = 0.2*g4pow->powZ(A,0.4)/dd;//1:0.4 --- 2: 0.4
}
}
G4double q1 = 1.0 - G4Exp(-bb*tmax);
G4double q2 = 1.0 - G4Exp(-dd*tmax);
@@ -234,3 +265,119 @@ G4HadronElastic::SampleInvariantT(const G4ParticleDefinition*,
}
return -GeV2*G4Log(1.0 - G4UniformRand()*q1)/bb;
}
//////////////////////////////////////////////
//
// Cofs for s-,c-,b-particles ds/dt slopes
G4double G4HadronElastic::GetSlopeCof(const G4int pdg )
{
// The input parameter "pdg" should be the absolute value of the PDG code
// (i.e. the same value for a particle and its antiparticle).
G4double coeff = 1.0;
// heavy barions
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 lBarCofSB = 0.620659;
static const G4double lBarCof2SB = 0.500659;
if( pdg == 3122 || pdg == 3222 || pdg == 3112 || pdg == 3212 )
{
coeff = lBarCof1S; // Lambda, Sigma+, Sigma-, Sigma0
} else if( pdg == 3322 || pdg == 3312 )
{
coeff = lBarCof2S; // Xi-, Xi0
}
else if( pdg == 3324)
{
coeff = lBarCof3S; // Omega
}
else if( pdg == 4122 || pdg == 4212 || pdg == 4222 || pdg == 4112 )
{
coeff = lBarCof1C; // LambdaC+, SigmaC+, SigmaC++, SigmaC0
}
else if( pdg == 4332 )
{
coeff = lBarCof2SC; // OmegaC
}
else if( pdg == 4232 || pdg == 4132 )
{
coeff = lBarCofSC; // XiC+, XiC0
}
else if( pdg == 5122 || pdg == 5222 || pdg == 5112 || pdg == 5212 )
{
coeff = lBarCof1B; // LambdaB, SigmaB+, SigmaB-, SigmaB0
}
else if( pdg == 5332 )
{
coeff = lBarCof2SB; // OmegaB-
}
else if( pdg == 5132 || pdg == 5232 ) // XiB-, XiB0
{
coeff = lBarCofSB;
}
// heavy mesons Kaons?
static const G4double lMesCof1S = 0.82; // Kp/piP kaons?
static const G4double llMesCof1C = 0.676568;
static const G4double llMesCof1B = 0.610989;
static const G4double llMesCof2C = 0.353135;
static const G4double llMesCof2B = 0.221978;
static const G4double llMesCofSC = 0.496568;
static const G4double llMesCofSB = 0.430989;
static const G4double llMesCofCB = 0.287557;
static const G4double llMesCofEtaP = 0.88;
static const G4double llMesCofEta = 0.76;
if( pdg == 321 || pdg == 311 || pdg == 310 )
{
coeff = lMesCof1S; //K+-0
}
else if( pdg == 511 || pdg == 521 )
{
coeff = llMesCof1B; // BMeson0, BMeson+
}
else if(pdg == 421 || pdg == 411 )
{
coeff = llMesCof1C; // DMeson+, DMeson0
}
else if( pdg == 531 )
{
coeff = llMesCofSB; // BSMeson0
}
else if( pdg == 541 )
{
coeff = llMesCofCB; // BCMeson+-
}
else if(pdg == 431 )
{
coeff = llMesCofSC; // DSMeson+-
}
else if(pdg == 441 || pdg == 443 )
{
coeff = llMesCof2C; // Etac, JPsi
}
else if(pdg == 553 )
{
coeff = llMesCof2B; // Upsilon
}
else if(pdg == 221 )
{
coeff = llMesCofEta; // Eta
}
else if(pdg == 331 )
{
coeff = llMesCofEtaP; // Eta'
}
return coeff;
}
@@ -14,6 +14,118 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
25 November 2019 Vladimir Ivanchenko (hadr-deex-V10-05-21)
- G4PhotonEvaporation - fixed Coverity problem
16 November 2019 Vladimir Ivanchenko (hadr-deex-V10-05-20)
- G4PhotonEvaporation - access G4NuclearPolarizationStore only
if correlated gamma decay is enabled
11 November 2019 Vladimir Ivanchenko (hadr-deex-V10-05-19)
- G4CompetitiveFission, G4FissionBarrier, G4FissionParameters - added
numerical protections; cleanup C++11 keywords; move headers to
source code
05 November 2019 Vladimir Ivanchenko (hadr-deex-V10-05-18)
- G4NuclearLevelData, G4LevelManager, G4GEMChannel, G4GEMProbability,
G4GEMProbabilityVI, G4EvaporationChannel, G4EvaporationProbability
use consistently pairing correction from G4NuclearLevelData and
verbosity level for debigging
- G4FermiBreakUpVI - use consistently verbosity from de-excitation
module, simplified decay kinematics
- G4VEmissionProbability, G4Evaporation, G4UnstableFragmentBreakUp
consistently used decay channels in all components of the
de-excitation module
- G4ExcitationHandler - fixed problem seen in medical test of
fragmentation - provide full de-excitation of excited light
fragments
- G4PhotonEvaporation - fixed gamma de-excitation when initial
excitation energy is between ground and 1st levels
19 October 2019 Vladimir Ivanchenko (hadr-deex-V10-05-17)
- G4ExcitationHandler, G4Evaporation - attempt to reduce CPU
16 October 2019 Vladimir Ivanchenko (hadr-deex-V10-05-16)
- G4ExcitationHandler, G4Evaporation - improved debug printout
- G4UnstableFragmentBreakUp - allowed only residual fragments, which
are present in the nuclear level DB; those fragments which are not
in the DB are forced to decay on fragments from the DB;
improved debug printout
02 October 2019 Vladimir Ivanchenko (hadr-deex-V10-05-15)
- G4ExcitationHandler - removed warning on high excitation
- G4NuclearLevelData - added new public interface to enable
upload of nuclear level data before 1st event with the signature:
UploadNuclearLevelData(G4int maxZ)
- G4LevelReader - small reduction of memory churn
- G4DeexPrecoParameters - added two new parameters
- G4DeexParametersMessenger - added UI command
- G4VEmissionProbability - implemented option to force a residual
nucleus to be at one of known discrete levels
- G4FermiFragmentsPoolVI - removed unphysical fragments and corresponding
data structures
- G4FermiFragment - removed unused boolean members
- G4FermiBreakUpVI - clean internal data after decay loop and not before
18 September 2019 Vladimir Ivanchenko (hadr-deex-V10-05-14)
- G4ExcitationHandler - removed second photon evaporation loop,
because since long all gamma decay are already happens in the
1st loop; use more C++11 constructions
- G4FermiFragmentsPoolVI - implement new method HasChannels(..)
- G4FermiBreakUpVI - use new HasChannels(..) inside IsAPplicable(..)
- G4Evaporation - make coherent use of IsApplicable(..)
from FermiBreakUp and force simplified decay of exotic fragments
with G4UnstableFragmentBreakUp
- G4UnstableFragmentBreakUp - change logic allowing decay of an
exotic fragment (fragment is not known in gamma level DB) and
never release it
11 September 2019 Vladimir Ivanchenko (hadr-deex-V10-05-13)
- G4ExcitationHandler - added limit on number of warnings on high
excitation of input fragment; fixed Coverity warnings
14 August 2019 Vladimir Ivanchenko (hadr-deex-V10-05-12)
- G4ExcitationHandler - added check on upper limit of excitations
- G4DeexPrecoParameters - added upper limit 30 MeV on excitation
per nucleon
08 August 2019 Vladimir Ivanchenko (hadr-deex-V10-05-11)
- G4ExcitationHandler - fixed initialisation sequence
23 July 2019 Vladimir Ivanchenko (hadr-deex-V10-05-10)
- G4ExcitationHandler, G4Evaporation - optimise initialisation reducing
memory churn
- G4VEvaporationChannel, G4VEmissionProbability, G4EvaporationChannel,
G4EvaporationProbability - clean-up private and protected members and
methods
- G4AlphaEvaporationChannel, G4AlphaEvaporationProbability,
G4DeuteronEvaporationChannel, G4DeuteronEvaporationProbability,
G4He3EvaporationChannel, G4He3EvaporationProbability,
G4NeutronEvaporationChannel, G4NeutronEvaporationProbability,
G4ProtonEvaporationChannel, G4ProtonEvaporationProbability,
G4TritonEvaporationChannel, G4TritonEvaporationProbability - clean-up
- G4GEMChannelVI, G4GEMProbabilityVI - new GEM model
17 July 2019 Vladimir Ivanchenko (hadr-deex-V10-05-09)
- G4VEvaporationChannel, G4VEmissionProbability, G4VEvaporationFactory,
G4EvaporationGEMFactory, G4EvaporationGEMFactoryVI, G4GEMChannelVI,
G4EvaporationDefaultGEMFactory, G4EvaporationFactory,
G4EvaporationChannel, G4EvaporationProbability,
G4EvaporationProbabilityVI - a modification of internal interfaces
allowing reuse code established for evaporation in the new GEM
evaporation model, use more C++11 patterns
- G4FermiFragmentsPoolVI, G4NuclearLevelData - reduce number of locks
at initialisation, use more C++11 patterns
10 July 2019 Vladimir Ivanchenko (hadr-deex-V10-05-08)
- G4EvaporationChannel, G4EvaporationProbability,
G4NeutronEvaporationProbability, G4VEmissionProbability,
G4VEvaporationChannel - preparation for development of new GEM model,
for evaporation improved selection of final excitation level for
residual fragment
- G4LevelReader - attempt to reduce memory churn at initialisation
04 June 2019 Vladimir Ivanchenko (hadr-deex-V10-05-07)
- G4ExcitationHandler - removed debug cout
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
@@ -34,29 +32,25 @@
#define G4AlphaEvaporationChannel_h 1
#include "G4EvaporationChannel.hh"
#include "G4AlphaCoulombBarrier.hh"
#include "G4AlphaEvaporationProbability.hh"
class G4AlphaEvaporationChannel : public G4EvaporationChannel
{
public:
// only available constructor
G4AlphaEvaporationChannel();
explicit G4AlphaEvaporationChannel();
// destructor
virtual ~G4AlphaEvaporationChannel();
~G4AlphaEvaporationChannel() override;
private:
const G4AlphaEvaporationChannel & operator=(const G4AlphaEvaporationChannel & right);
const G4AlphaEvaporationChannel & operator=
(const G4AlphaEvaporationChannel & right);
G4AlphaEvaporationChannel(const G4AlphaEvaporationChannel & right);
G4bool operator==(const G4AlphaEvaporationChannel & right) const;
G4bool operator!=(const G4AlphaEvaporationChannel & right) const;
G4AlphaCoulombBarrier theCoulombBarrier;
G4AlphaEvaporationProbability theEvaporationProbability;
G4AlphaEvaporationProbability pr;
};
#endif
@@ -37,33 +37,29 @@
#include "G4EvaporationProbability.hh"
#include "G4AlphaCoulombBarrier.hh"
class G4AlphaEvaporationProbability : public G4EvaporationProbability
{
public:
G4AlphaEvaporationProbability();
explicit G4AlphaEvaporationProbability();
virtual ~G4AlphaEvaporationProbability();
~G4AlphaEvaporationProbability() override;
protected:
virtual G4double CalcAlphaParam(const G4Fragment & fragment);
G4double CalcAlphaParam(const G4Fragment & fragment) override;
virtual G4double CalcBetaParam(const G4Fragment & fragment);
G4double CalcBetaParam(const G4Fragment & fragment) override;
private:
G4AlphaEvaporationProbability(const G4AlphaEvaporationProbability &right);
const G4AlphaEvaporationProbability & operator=(const G4AlphaEvaporationProbability &right);
const G4AlphaEvaporationProbability & operator=
(const G4AlphaEvaporationProbability &right);
G4bool operator==(const G4AlphaEvaporationProbability &right) const;
G4bool operator!=(const G4AlphaEvaporationProbability &right) const;
G4AlphaCoulombBarrier theCoulombBarrier;
};
#endif
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
@@ -34,29 +32,25 @@
#define G4DeuteronEvaporationChannel_h 1
#include "G4EvaporationChannel.hh"
#include "G4DeuteronCoulombBarrier.hh"
#include "G4DeuteronEvaporationProbability.hh"
class G4DeuteronEvaporationChannel : public G4EvaporationChannel
{
public:
// only available constructor
G4DeuteronEvaporationChannel();
explicit G4DeuteronEvaporationChannel();
// destructor
virtual ~G4DeuteronEvaporationChannel();
~G4DeuteronEvaporationChannel() override;
private:
const G4DeuteronEvaporationChannel & operator=(const G4DeuteronEvaporationChannel & right);
const G4DeuteronEvaporationChannel & operator=
(const G4DeuteronEvaporationChannel & right);
G4DeuteronEvaporationChannel(const G4DeuteronEvaporationChannel & right);
G4bool operator==(const G4DeuteronEvaporationChannel & right) const;
G4bool operator!=(const G4DeuteronEvaporationChannel & right) const;
G4DeuteronCoulombBarrier theCoulombBarrier;
G4DeuteronEvaporationProbability theEvaporationProbability;
G4DeuteronEvaporationProbability pr;
};
#endif
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// J.M. Quesada (August2008). Based on:
//
// Hadronic Process: Nuclear De-excitations
@@ -44,28 +43,25 @@ class G4DeuteronEvaporationProbability : public G4EvaporationProbability
{
public:
G4DeuteronEvaporationProbability();
explicit G4DeuteronEvaporationProbability();
virtual ~G4DeuteronEvaporationProbability();
~G4DeuteronEvaporationProbability() override;
protected:
virtual G4double CalcAlphaParam(const G4Fragment & fragment);
G4double CalcAlphaParam(const G4Fragment & fragment) override;
virtual G4double CalcBetaParam(const G4Fragment & fragment);
G4double CalcBetaParam(const G4Fragment & fragment) override;
private:
G4DeuteronEvaporationProbability(const G4DeuteronEvaporationProbability &right);
const G4DeuteronEvaporationProbability & operator=(const G4DeuteronEvaporationProbability &right);
const G4DeuteronEvaporationProbability & operator=
(const G4DeuteronEvaporationProbability &right);
G4bool operator==(const G4DeuteronEvaporationProbability &right) const;
G4bool operator!=(const G4DeuteronEvaporationProbability &right) const;
G4DeuteronCoulombBarrier theCoulombBarrier;
};
#endif
@@ -56,6 +56,7 @@ class G4NistManager;
class G4IonTable;
class G4VFermiBreakUp;
class G4UnstableFragmentBreakUp;
class G4NuclearLevelData;
class G4Evaporation : public G4VEvaporation
{
@@ -74,22 +75,24 @@ public:
void SetDefaultChannel();
void SetGEMChannel();
void SetGEMVIChannel();
void SetCombinedChannel();
private:
void InitialiseChannelFactory();
G4Evaporation(const G4Evaporation &right) = delete;
const G4Evaporation & operator=(const G4Evaporation &right) = delete;
G4bool operator==(const G4Evaporation &right) const = delete;
G4bool operator!=(const G4Evaporation &right) const = delete;
G4Evaporation(const G4Evaporation &right);
const G4Evaporation & operator=(const G4Evaporation &right);
G4bool operator==(const G4Evaporation &right) const;
G4bool operator!=(const G4Evaporation &right) const;
G4int fVerbose;
size_t nChannels;
G4double minExcitation;
G4NistManager* nist;
G4IonTable* theTableOfIons;
G4NuclearLevelData* fLevelData;
G4UnstableFragmentBreakUp* unstableBreakUp;
G4bool isInitialised;
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
//J.M. Quesada (August2008). Based on:
//
// Hadronic Process: Nuclear De-excitations
@@ -33,81 +31,59 @@
// 17-11-2010 V.Ivanchenko in constructor replace G4VEmissionProbability by
// G4EvaporationProbability and do not new and delete probability
// object at each call; use G4Pow
// 16-07-2019 V.Ivanchenko use C++11
#ifndef G4EvaporationChannel_h
#define G4EvaporationChannel_h 1
#include "G4VEvaporationChannel.hh"
#include "G4EvaporationProbability.hh"
#include "G4VCoulombBarrier.hh"
class G4PairingCorrection;
class G4EvaporationProbability;
class G4CoulombBarrier;
class G4NuclearLevelData;
class G4EvaporationChannel : public G4VEvaporationChannel
{
public:
explicit G4EvaporationChannel(G4int A, G4int Z,
const G4String & aName,
G4EvaporationProbability*,
G4VCoulombBarrier*);
G4EvaporationProbability*);
virtual ~G4EvaporationChannel();
~G4EvaporationChannel() override;
void Initialise();
void Initialise() override;
virtual G4double GetEmissionProbability(G4Fragment* fragment);
G4double GetEmissionProbability(G4Fragment* fragment) override;
virtual G4Fragment* EmittedFragment(G4Fragment* theNucleus);
G4Fragment* EmittedFragment(G4Fragment* theNucleus) override;
private:
G4EvaporationChannel(const G4EvaporationChannel & right) = delete;
const G4EvaporationChannel & operator=
(const G4EvaporationChannel & right) = delete;
G4bool operator==(const G4EvaporationChannel & right) const = delete;
G4bool operator!=(const G4EvaporationChannel & right) const = delete;
private:
G4EvaporationChannel(const G4EvaporationChannel & right);
const G4EvaporationChannel & operator=(const G4EvaporationChannel & right);
G4bool operator==(const G4EvaporationChannel & right) const;
G4bool operator!=(const G4EvaporationChannel & right) const;
// This data member define the channel.
// They are intializated at object creation (constructor) time.
G4int theA;
G4int theZ;
G4int resA;
G4int resZ;
G4double EvapMass;
G4double CoulombBarrier;
G4double mass;
G4double resMass;
G4double evapMass;
G4double evapMass2;
// For evaporation probability calcualation
G4EvaporationProbability * theProbability;
G4EvaporationProbability* theProbability;
// For Coulomb Barrier calculation
G4VCoulombBarrier * theCoulombBarrier;
// For pairing correction calculation
G4PairingCorrection* pairingCorrection;
//---------------------------------------------------
// These values depend on the nucleus that is being evaporated.
// They are calculated through the Initialize method which
// takes as parameters
// the atomic number, charge and excitation energy of nucleus.
G4int ResA;
G4int ResZ;
G4double Mass;
// Emission Probability
G4double EmissionProbability;
// Kinetic Energy that can be carried by fragment
G4double MinKinEnergy;
G4double MaxKinEnergy;
G4CoulombBarrier* theCoulombBarrier;
G4NuclearLevelData* theLevelData;
};
#endif
@@ -29,82 +29,75 @@
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Oct 1998)
//
// V.Ivanchenko general clean-up since 2010
//
#ifndef G4EvaporationProbability_h
#define G4EvaporationProbability_h 1
#include "G4VEmissionProbability.hh"
class G4VCoulombBarrier;
class G4NuclearLevelData;
class G4EvaporationProbability : public G4VEmissionProbability
{
public:
explicit G4EvaporationProbability(G4int anA, G4int aZ,
G4double aGamma,
G4VCoulombBarrier *);
G4double aGamma);
virtual ~G4EvaporationProbability();
// not used for evaporation
virtual G4double EmissionProbability(const G4Fragment& fragment,
G4double maxKineticEnergy);
~G4EvaporationProbability() override;
// general method used for evaporation
G4double TotalProbability(const G4Fragment& fragment,
G4double minKineticEnergy,
G4double maxKineticEnergy,
G4double CoulombBarrier = 0.0);
virtual G4double TotalProbability(const G4Fragment& fragment,
G4double minKinEnergy,
G4double maxKinEnergy,
G4double CB, G4double exEnergy);
/*
virtual G4double TotalProbability(const G4Fragment& fragment,
G4double minKinEnergy,
G4double maxKinEnergy,
G4double CB);
*/
// main method to compute full probability for OPTx > 2
virtual G4double ComputeProbability(G4double K, G4double kBarrier);
G4double ComputeProbability(G4double K, G4double CB) override;
// Samples fragment kinetic energy and excitation energy
// of the residual nucleaus
G4double SampleKineticEnergy(G4double minKineticEnergy,
G4double maxKineticEnergy,
G4double CoulombBarrier = 0.0);
G4double SampleKineticEnergy(G4double minKinEnergy,
G4double maxKinEnergy,
G4double CB);
protected:
virtual G4double CalcAlphaParam(const G4Fragment & fragment)=0 ;
virtual G4double CalcAlphaParam(const G4Fragment& fragment);
virtual G4double CalcBetaParam(const G4Fragment & fragment)=0 ;
virtual G4double CalcBetaParam(const G4Fragment& fragment);
private:
G4double CrossSection(G4double K, G4double CoulombBarrier);
G4double CrossSection(G4double K, G4double CB);
// Copy constructor
G4EvaporationProbability(const G4EvaporationProbability &right) = delete;
G4EvaporationProbability(const G4EvaporationProbability &right);
const G4EvaporationProbability & operator=
(const G4EvaporationProbability &right) = delete;
G4bool operator==(const G4EvaporationProbability &right) const = delete;
G4bool operator!=(const G4EvaporationProbability &right) const = delete;
(const G4EvaporationProbability &right);
G4bool operator==(const G4EvaporationProbability &right) const;
G4bool operator!=(const G4EvaporationProbability &right) const;
G4NuclearLevelData* fLevelData;
G4int fragA;
G4int fragZ;
G4int resA;
G4int resZ;
//G4int fragA;
//G4int fragZ;
G4int index;
G4double resA13;
G4double muu;
G4double partMass;
G4double resMass;
G4double Mass;
G4double U, delta0, delta1, a0;
G4double freeU;
G4double a0;
G4double delta1;
// Gamma is A_f(2S_f+1) factor, where A_f is fragment atomic
// number and S_f is fragment spin
G4double Gamma;
G4double fGamma;
G4double pcoeff;
G4double probmax;
};
#endif
@@ -24,40 +24,35 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
// 17-11-2010 V.Ivanchenko moved constructor and destructor to source and cleanup
// 17-11-2010 V.Ivanchenko cleanup
#ifndef G4He3EvaporationChannel_h
#define G4He3EvaporationChannel_h 1
#include "G4EvaporationChannel.hh"
#include "G4He3CoulombBarrier.hh"
#include "G4He3EvaporationProbability.hh"
class G4He3EvaporationChannel : public G4EvaporationChannel
{
public:
// only available constructor
G4He3EvaporationChannel();
explicit G4He3EvaporationChannel();
// destructor
virtual ~G4He3EvaporationChannel();
~G4He3EvaporationChannel() override;
private:
const G4He3EvaporationChannel & operator=(const G4He3EvaporationChannel & right);
const G4He3EvaporationChannel & operator=
(const G4He3EvaporationChannel & right);
G4He3EvaporationChannel(const G4He3EvaporationChannel & right);
G4bool operator==(const G4He3EvaporationChannel & right) const;
G4bool operator!=(const G4He3EvaporationChannel & right) const;
G4He3CoulombBarrier theCoulombBarrier;
G4He3EvaporationProbability theEvaporationProbability;
G4He3EvaporationProbability pr;
};
#endif
@@ -35,33 +35,29 @@
#ifndef G4He3EvaporationProbability_h
#define G4He3EvaporationProbability_h 1
#include "G4EvaporationProbability.hh"
#include "G4He3CoulombBarrier.hh"
class G4He3EvaporationProbability : public G4EvaporationProbability
{
public:
G4He3EvaporationProbability();
explicit G4He3EvaporationProbability();
virtual ~G4He3EvaporationProbability();
~G4He3EvaporationProbability() override;
protected:
virtual G4double CalcAlphaParam(const G4Fragment & fragment);
G4double CalcAlphaParam(const G4Fragment & fragment) override;
virtual G4double CalcBetaParam(const G4Fragment & fragment);
G4double CalcBetaParam(const G4Fragment & fragment) override;
private:
G4He3EvaporationProbability(const G4He3EvaporationProbability &right);
const G4He3EvaporationProbability & operator=(const G4He3EvaporationProbability &right);
const G4He3EvaporationProbability & operator=
(const G4He3EvaporationProbability &right);
G4bool operator==(const G4He3EvaporationProbability &right) const;
G4bool operator!=(const G4He3EvaporationProbability &right) const;
G4He3CoulombBarrier theCoulombBarrier;
};
@@ -24,7 +24,6 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
@@ -34,30 +33,26 @@
#define G4NeutronEvaporationChannel_h 1
#include "G4EvaporationChannel.hh"
#include "G4NeutronCoulombBarrier.hh"
#include "G4NeutronEvaporationProbability.hh"
class G4NeutronEvaporationChannel : public G4EvaporationChannel
{
public:
// only available constructor
G4NeutronEvaporationChannel();
explicit G4NeutronEvaporationChannel();
// destructor
virtual ~G4NeutronEvaporationChannel();
~G4NeutronEvaporationChannel() override;
private:
const G4NeutronEvaporationChannel & operator=(const G4NeutronEvaporationChannel & right);
const G4NeutronEvaporationChannel & operator=
(const G4NeutronEvaporationChannel & right);
G4NeutronEvaporationChannel(const G4NeutronEvaporationChannel & right);
G4bool operator==(const G4NeutronEvaporationChannel & right) const;
G4bool operator!=(const G4NeutronEvaporationChannel & right) const;
G4NeutronCoulombBarrier theCoulombBarrier;
G4NeutronEvaporationProbability theEvaporationProbability;
G4NeutronEvaporationProbability pr;
};
#endif
@@ -38,31 +38,28 @@
#include "G4EvaporationProbability.hh"
#include "G4NeutronCoulombBarrier.hh"
class G4NeutronEvaporationProbability : public G4EvaporationProbability
{
public:
G4NeutronEvaporationProbability();
explicit G4NeutronEvaporationProbability();
virtual ~G4NeutronEvaporationProbability();
~G4NeutronEvaporationProbability() override;
protected:
virtual G4double CalcAlphaParam(const G4Fragment & fragment);
G4double CalcAlphaParam(const G4Fragment & fragment) override;
virtual G4double CalcBetaParam(const G4Fragment & fragment);
G4double CalcBetaParam(const G4Fragment & fragment) override;
private:
G4NeutronEvaporationProbability(const G4NeutronEvaporationProbability &right);
const G4NeutronEvaporationProbability & operator=(const G4NeutronEvaporationProbability &right);
const G4NeutronEvaporationProbability & operator=
(const G4NeutronEvaporationProbability &right);
G4bool operator==(const G4NeutronEvaporationProbability &right) const;
G4bool operator!=(const G4NeutronEvaporationProbability &right) const;
G4NeutronCoulombBarrier theCoulombBarrier;
};
@@ -24,7 +24,6 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
@@ -34,31 +33,26 @@
#define G4ProtonEvaporationChannel_h 1
#include "G4EvaporationChannel.hh"
#include "G4ProtonCoulombBarrier.hh"
#include "G4ProtonEvaporationProbability.hh"
class G4ProtonEvaporationChannel : public G4EvaporationChannel
{
public:
// only available constructor
G4ProtonEvaporationChannel();
explicit G4ProtonEvaporationChannel();
// destructor
virtual ~G4ProtonEvaporationChannel();
~G4ProtonEvaporationChannel() override;
private:
const G4ProtonEvaporationChannel & operator=(const G4ProtonEvaporationChannel & right);
const G4ProtonEvaporationChannel & operator=
(const G4ProtonEvaporationChannel & right);
G4ProtonEvaporationChannel(const G4ProtonEvaporationChannel & right);
G4bool operator==(const G4ProtonEvaporationChannel & right) const;
G4bool operator!=(const G4ProtonEvaporationChannel & right) const;
G4ProtonCoulombBarrier theCoulombBarrier;
G4ProtonEvaporationProbability theEvaporationProbability;
G4ProtonEvaporationProbability pr;
};
#endif
@@ -37,33 +37,29 @@
#define G4ProtonEvaporationProbability_h 1
#include "G4EvaporationProbability.hh"
#include "G4ProtonCoulombBarrier.hh"
class G4ProtonEvaporationProbability : public G4EvaporationProbability
{
public:
G4ProtonEvaporationProbability();
explicit G4ProtonEvaporationProbability();
virtual ~G4ProtonEvaporationProbability();
~G4ProtonEvaporationProbability() override;
protected:
virtual G4double CalcAlphaParam(const G4Fragment & fragment);
G4double CalcAlphaParam(const G4Fragment & fragment) override;
virtual G4double CalcBetaParam(const G4Fragment & fragment);
G4double CalcBetaParam(const G4Fragment & fragment) override;
private:
G4ProtonEvaporationProbability(const G4ProtonEvaporationProbability &right);
const G4ProtonEvaporationProbability & operator=(const G4ProtonEvaporationProbability &right);
const G4ProtonEvaporationProbability & operator=
(const G4ProtonEvaporationProbability &right);
G4bool operator==(const G4ProtonEvaporationProbability &right) const;
G4bool operator!=(const G4ProtonEvaporationProbability &right) const;
G4ProtonCoulombBarrier theCoulombBarrier;
};
#endif
@@ -28,7 +28,7 @@
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
// 17-11-2010 V.Ivanchenko moved constructor and destructor to source and cleanup
// 17-11-2010 V.Ivanchenko cleanup
#ifndef G4TritonEvaporationChannel_h
#define G4TritonEvaporationChannel_h 1
@@ -41,22 +41,19 @@ class G4TritonEvaporationChannel : public G4EvaporationChannel
{
public:
// only available constructor
G4TritonEvaporationChannel();
explicit G4TritonEvaporationChannel();
// destructor
virtual ~G4TritonEvaporationChannel();
~G4TritonEvaporationChannel() override;
private:
const G4TritonEvaporationChannel & operator=(const G4TritonEvaporationChannel & right);
const G4TritonEvaporationChannel & operator=
(const G4TritonEvaporationChannel & right);
G4TritonEvaporationChannel(const G4TritonEvaporationChannel & right);
G4bool operator==(const G4TritonEvaporationChannel & right) const;
G4bool operator!=(const G4TritonEvaporationChannel & right) const;
G4TritonCoulombBarrier theCoulombBarrier;
G4TritonEvaporationProbability theEvaporationProbability;
G4TritonEvaporationProbability pr;
};
#endif
@@ -62,7 +62,6 @@ private:
G4bool operator==(const G4TritonEvaporationProbability &right) const;
G4bool operator!=(const G4TritonEvaporationProbability &right) const;
G4TritonCoulombBarrier theCoulombBarrier;
};
#endif
@@ -66,19 +66,22 @@ public:
virtual G4double GetEmissionProbability(G4Fragment* fragment) final;
inline void SetVerbose(G4int val) { fVerbose = val; }
private:
G4UnstableFragmentBreakUp(const G4UnstableFragmentBreakUp & right) = delete;
G4UnstableFragmentBreakUp(const G4UnstableFragmentBreakUp & right);
const G4UnstableFragmentBreakUp & operator =
(const G4UnstableFragmentBreakUp & right) = delete;
G4bool operator == (const G4UnstableFragmentBreakUp & right) const = delete;
G4bool operator != (const G4UnstableFragmentBreakUp & right) const = delete;
(const G4UnstableFragmentBreakUp & right);
G4bool operator == (const G4UnstableFragmentBreakUp & right) const;
G4bool operator != (const G4UnstableFragmentBreakUp & right) const;
static const G4int Zfr[6];
static const G4int Afr[6];
G4double masses[6];
G4NuclearLevelData* fLevelData;
G4int fVerbose;
};
#endif
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
@@ -33,7 +31,7 @@
#include "G4AlphaEvaporationChannel.hh"
G4AlphaEvaporationChannel::G4AlphaEvaporationChannel()
: G4EvaporationChannel(4,2,"alpha",&theEvaporationProbability,&theCoulombBarrier)
: G4EvaporationChannel(4,2,&pr)
{}
G4AlphaEvaporationChannel::~G4AlphaEvaporationChannel()
@@ -34,10 +34,9 @@
// 17-11-2010 V.Ivanchenko integer Z and A
#include "G4AlphaEvaporationProbability.hh"
#include "G4SystemOfUnits.hh"
G4AlphaEvaporationProbability::G4AlphaEvaporationProbability() :
G4EvaporationProbability(4,2,1.0,&theCoulombBarrier)
G4EvaporationProbability(4,2,1.0)
{}
G4AlphaEvaporationProbability::~G4AlphaEvaporationProbability()
@@ -24,7 +24,6 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
@@ -33,7 +32,7 @@
#include "G4DeuteronEvaporationChannel.hh"
G4DeuteronEvaporationChannel::G4DeuteronEvaporationChannel()
: G4EvaporationChannel(2,1,"deuteron",&theEvaporationProbability,&theCoulombBarrier)
: G4EvaporationChannel(2,1,&pr)
{}
G4DeuteronEvaporationChannel::~G4DeuteronEvaporationChannel()
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// J.M. Quesada (August2008). Based on:
//
// Hadronic Process: Nuclear De-excitations
@@ -37,7 +36,7 @@
#include "G4DeuteronEvaporationProbability.hh"
G4DeuteronEvaporationProbability::G4DeuteronEvaporationProbability() :
G4EvaporationProbability(2,1,3.0,&theCoulombBarrier)
G4EvaporationProbability(2,1,3.0)
{}
G4DeuteronEvaporationProbability::~G4DeuteronEvaporationProbability()
@@ -24,7 +24,6 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Oct 1998)
//
@@ -51,6 +50,7 @@
#include "G4SystemOfUnits.hh"
#include "G4EvaporationFactory.hh"
#include "G4EvaporationGEMFactory.hh"
#include "G4EvaporationGEMFactoryVI.hh"
#include "G4EvaporationDefaultGEMFactory.hh"
#include "G4NistManager.hh"
#include "G4VFermiBreakUp.hh"
@@ -59,23 +59,29 @@
#include "G4ParticleTable.hh"
#include "G4IonTable.hh"
#include "G4NuclearLevelData.hh"
#include "G4LevelManager.hh"
#include "G4UnstableFragmentBreakUp.hh"
#include "Randomize.hh"
G4Evaporation::G4Evaporation(G4VEvaporationChannel* photoEvaporation)
: G4VEvaporation(),fVerbose(1),nChannels(0),minExcitation(0.1*keV),
: G4VEvaporation(),fVerbose(0),nChannels(0),minExcitation(0.1*keV),
isInitialised(false)
{
if(photoEvaporation) { SetPhotonEvaporation(photoEvaporation); }
else { SetPhotonEvaporation(new G4PhotonEvaporation()); }
channelType = fEvaporation;
theChannelFactory = new G4EvaporationFactory(thePhotonEvaporation);
InitialiseChannelFactory();
channelType = fDummy;
theChannelFactory = nullptr;
fLevelData = G4NuclearLevelData::GetInstance();
theTableOfIons = G4ParticleTable::GetParticleTable()->GetIonTable();
nist = G4NistManager::Instance();
unstableBreakUp = new G4UnstableFragmentBreakUp();
/*
G4cout << "G4Evaporation() " << this << " thePhotonEvaporation: "
<< photoEvaporation << " UnstableFragmentBreakUp: "
<< unstableBreakUp << G4endl;
*/
}
G4Evaporation::~G4Evaporation()
@@ -87,14 +93,16 @@ void G4Evaporation::InitialiseChannels()
{
if(isInitialised) { return; }
G4DeexPrecoParameters* param =
G4NuclearLevelData::GetInstance()->GetParameters();
G4DeexPrecoParameters* param = fLevelData->GetParameters();
minExcitation = param->GetMinExcitation();
fVerbose = param->GetVerbose();
unstableBreakUp->SetVerbose(fVerbose);
G4DeexChannelType type = param->GetDeexChannelsType();
if(type == fCombined) { SetCombinedChannel(); }
else if(type == fGEM) { SetGEMChannel(); }
else if(type == fEvaporation) { SetDefaultChannel(); }
else if(type == fGEMVI) { SetGEMVIChannel(); }
isInitialised = true;
}
@@ -119,8 +127,10 @@ void G4Evaporation::SetDefaultChannel()
{
if(fEvaporation != channelType) {
channelType = fEvaporation;
CleanChannels();
delete theChannelFactory;
if(theChannelFactory) {
CleanChannels();
delete theChannelFactory;
}
theChannelFactory = new G4EvaporationFactory(thePhotonEvaporation);
InitialiseChannelFactory();
}
@@ -130,20 +140,38 @@ void G4Evaporation::SetGEMChannel()
{
if(fGEM != channelType) {
channelType = fCombined;
CleanChannels();
delete theChannelFactory;
if(theChannelFactory) {
CleanChannels();
delete theChannelFactory;
}
theChannelFactory = new G4EvaporationGEMFactory(thePhotonEvaporation);
InitialiseChannelFactory();
}
}
void G4Evaporation::SetGEMVIChannel()
{
if(fGEMVI != channelType) {
channelType = fGEMVI;
if(theChannelFactory) {
CleanChannels();
delete theChannelFactory;
}
theChannelFactory = new G4EvaporationGEMFactoryVI(thePhotonEvaporation);
InitialiseChannelFactory();
}
}
void G4Evaporation::SetCombinedChannel()
{
if(fCombined != channelType) {
channelType = fCombined;
CleanChannels();
delete theChannelFactory;
theChannelFactory = new G4EvaporationDefaultGEMFactory(thePhotonEvaporation);
if(theChannelFactory) {
CleanChannels();
delete theChannelFactory;
}
theChannelFactory =
new G4EvaporationDefaultGEMFactory(thePhotonEvaporation);
InitialiseChannelFactory();
}
}
@@ -157,6 +185,9 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
size_t maxchannel, i;
G4int Amax = theResidualNucleus->GetA_asInt();
if(fVerbose > 1) {
G4cout << "### G4Evaporation::BreakItUp loop" << G4endl;
}
// Starts loop over evaporated particles, loop is limited by number
// of nucleons
@@ -165,6 +196,7 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// g,n,p and light fragments - evaporation is finished
G4int Z = theResidualNucleus->GetZ_asInt();
G4int A = theResidualNucleus->GetA_asInt();
if(A <= 1) { break; }
G4double Eex = theResidualNucleus->GetExcitationEnergy();
// stop deecitation loop if residual can be deexcited by FBU
@@ -172,26 +204,22 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// check if it is stable, then finish evaporation
G4double abun = nist->GetIsotopeAbundance(Z, A);
if(fVerbose > 1) {
G4cout << "### G4Evaporation::BreakItUp step " << ia << " Z= " << Z
<< " A= " << A << " Eex(MeV)= "
<< theResidualNucleus->GetExcitationEnergy()
<< " aban= " << abun << G4endl;
}
// stop deecitation loop in the case of a cold stable fragment
if(Eex <= minExcitation && abun > 0.0) { break; }
if(Eex <= minExcitation &&
(abun > 0.0 || (A == 3 && (Z == 1 || Z == 2)))) { break; }
totprob = 0.0;
maxchannel = nChannels;
if(fVerbose > 2) {
G4cout << "### Evaporation loop #" << ia
<< " Fragment: " << theResidualNucleus << G4endl;
if(fVerbose > 1) {
G4cout << "Evaporation# " << ia << " Z= " << Z << " A= " << A
<< " Eex(MeV)= " << theResidualNucleus->GetExcitationEnergy()
<< " aban= " << abun << G4endl;
}
// loop over evaporation channels
for(i=0; i<nChannels; ++i) {
prob = (*theChannels)[i]->GetEmissionProbability(theResidualNucleus);
if(fVerbose > 2 && prob > 0.0) {
G4cout << " Channel# " << i << " prob= " << prob << G4endl;
G4cout << " Channel# " << i << " prob= " << prob << G4endl;
}
totprob += prob;
probabilities[i] = totprob;
@@ -207,10 +235,10 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
}
// photon evaporation in the case of no other channels available
// do evaporation chain and reset total probability
// do evaporation chain and return back ground state fragment
if(0.0 < totprob && probabilities[0] == totprob) {
if(fVerbose > 2) {
G4cout << "Start chain of gamma evaporation" << G4endl;
if(fVerbose > 1) {
G4cout << "$$$ Start chain of gamma evaporation" << G4endl;
}
(*theChannels)[0]->BreakUpChain(theResult, theResidualNucleus);
totprob = 0.0;
@@ -219,14 +247,19 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// stable fragment - evaporation is finished
if(0.0 == totprob) {
// if fragment is exotic, then force its decay
if(0.0 == abun) {
if(!unstableBreakUp->BreakUpChain(theResult, theResidualNucleus))
{ break; }
if(fVerbose > 2) { G4cout << "$$$ Decay exotic fragment" << G4endl; }
} else {
break;
// release fragment known to DB
if(fLevelData->GetLevelManager(Z, A)) { break; }
// if fragment is exotic, then it forced to decay
// if success, then decay product is added to results
if(fVerbose > 1) {
G4cout << "$$$ Decay exotic fragment" << G4endl;
}
if(unstableBreakUp->BreakUpChain(theResult, theResidualNucleus)) {
continue;
}
// release if it is not possible to decay
break;
}
// select channel
@@ -234,7 +267,7 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// loop over evaporation channels
for(i=0; i<maxchannel; ++i) { if(probabilities[i] >= totprob) { break; } }
if(fVerbose > 2) { G4cout << "Channel # " << i << G4endl; }
if(fVerbose > 1) { G4cout << "$$$ Channel # " << i << G4endl; }
G4Fragment* frag = (*theChannels)[i]->EmittedFragment(theResidualNucleus);
if(fVerbose > 2 && frag) { G4cout << " " << *frag << G4endl; }
@@ -242,6 +275,4 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
if(frag) { theResult->push_back(frag); }
else { break; }
}
// loop is stopped, residual fragment is added to the results
theResult->push_back(theResidualNucleus);
}
@@ -23,7 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//J.M. Quesada (August2008). Based on:
//
// Hadronic Process: Nuclear De-excitations
@@ -38,7 +37,8 @@
// object at each call; use G4Pow
#include "G4EvaporationChannel.hh"
#include "G4PairingCorrection.hh"
#include "G4EvaporationProbability.hh"
#include "G4CoulombBarrier.hh"
#include "G4NuclearLevelData.hh"
#include "G4NucleiProperties.hh"
#include "G4Pow.hh"
@@ -51,23 +51,26 @@
#include "G4Alpha.hh"
G4EvaporationChannel::G4EvaporationChannel(G4int anA, G4int aZ,
const G4String & aName,
G4EvaporationProbability* aprob,
G4VCoulombBarrier* barrier):
G4VEvaporationChannel(aName),
G4EvaporationProbability* aprob):
G4VEvaporationChannel(),
theA(anA),
theZ(aZ),
theProbability(aprob),
theCoulombBarrier(barrier)
theCoulombBarrier(new G4CoulombBarrier(anA, aZ))
{
ResA = ResZ = 0;
Mass = CoulombBarrier = MinKinEnergy = MaxKinEnergy = EmissionProbability = 0.0;
EvapMass = G4NucleiProperties::GetNuclearMass(theA, theZ);
pairingCorrection = G4NuclearLevelData::GetInstance()->GetPairingCorrection();
resA = resZ = 0;
mass = resMass = 0.0;
evapMass = G4NucleiProperties::GetNuclearMass(theA, theZ);
//G4cout << "G4EvaporationChannel: Z= " << theZ << " A= " << theA
// << " M(GeV)= " << evapMass/GeV << G4endl;
evapMass2 = evapMass*evapMass;
theLevelData = G4NuclearLevelData::GetInstance();
}
G4EvaporationChannel::~G4EvaporationChannel()
{}
{
delete theCoulombBarrier;
}
void G4EvaporationChannel::Initialise()
{
@@ -77,76 +80,98 @@ void G4EvaporationChannel::Initialise()
G4double G4EvaporationChannel::GetEmissionProbability(G4Fragment* fragment)
{
G4int FragA = fragment->GetA_asInt();
G4int FragZ = fragment->GetZ_asInt();
ResA = FragA - theA;
ResZ = FragZ - theZ;
G4double FragmentMass = fragment->GetGroundStateMass();
G4double ExEnergy = fragment->GetExcitationEnergy();
Mass = FragmentMass + ExEnergy;
//G4cout << "G4EvaporationChannel::Initialize Z= " << theZ << " A= " << theA
// << " FragZ= " << FragZ << " FragA= " << FragA << G4endl;
EmissionProbability = 0.0;
theProbability->ResetProbability();
G4int fragA = fragment->GetA_asInt();
G4int fragZ = fragment->GetZ_asInt();
resA = fragA - theA;
resZ = fragZ - theZ;
// Only channels which are physically allowed are taken into account
if (ResA >= ResZ && ResZ > 0 && ResA >= theA) {
//Effective excitation energy
G4double ResMass = G4NucleiProperties::GetNuclearMass(ResA, ResZ);
if(resA < theA || resA < resZ || resZ < 0 || (resA == theA && resZ < theZ)
|| ((resA > 1) && (resA == resZ || resZ == 0)))
{ return 0.0; }
CoulombBarrier = (0 == theZ) ? 0.0 :
theCoulombBarrier->GetCoulombBarrier(ResA,ResZ,ExEnergy);
G4double exEnergy = fragment->GetExcitationEnergy();
G4double delta0 = theLevelData->GetPairingCorrection(fragZ,fragA);
/*
G4cout << "G4EvaporationChannel::Initialize Z= "<<theZ<<" A= "<<theA
<< " FragZ= " << fragZ << " FragA= " << fragA
<< " exEnergy= " << exEnergy << " d0= " << delta0 << G4endl;
*/
if(exEnergy < delta0) { return 0.0; }
G4double fragMass = fragment->GetGroundStateMass();
mass = fragMass + exEnergy;
resMass = G4NucleiProperties::GetNuclearMass(resA, resZ);
G4double bCoulomb = 0.0;
G4double elim = 0.0;
if(theZ > 0) {
bCoulomb = theCoulombBarrier->GetCoulombBarrier(resA,resZ,exEnergy);
G4double delta0 =
std::max(0.0,pairingCorrection->GetPairingCorrection(FragA,FragZ));
/*
G4cout << "ExEnergy= " << ExEnergy << " Ec= " << CoulombBarrier
<< " delta0= " << delta0 << " delta1= " << delta1
<< " Free= " << Mass - ResMass - EvapMass
<< G4endl;
*/
// for OPTxs >0 penetration under the barrier is taken into account
G4double elim = (0 == OPTxs) ? CoulombBarrier : CoulombBarrier*0.5;
if(ExEnergy > delta0 && Mass > ResMass + EvapMass + elim) {
G4double twoMass = Mass + Mass;
MaxKinEnergy = std::max(((Mass-ResMass)*(Mass+ResMass)
+ EvapMass*EvapMass)/twoMass - EvapMass,0.0);
MinKinEnergy = (elim == 0.0) ? 0.0
: std::max(((EvapMass + elim)*(twoMass-EvapMass-elim)
+ EvapMass*EvapMass)/twoMass - EvapMass,0.0);
//G4cout << "Emin= " << MinKinEnergy << " Emax= " << MaxKinEnergy << G4endl;
EmissionProbability = theProbability->
TotalProbability(*fragment, MinKinEnergy, MaxKinEnergy, CoulombBarrier);
}
const G4double dCB = 3.5*CLHEP::MeV;
elim = (0 != OPTxs) ?
std::max(bCoulomb*0.5, bCoulomb - dCB*theZ) : bCoulomb;
}
//G4cout<<"G4EvaporationChannel: probability= "<<EmissionProbability<<G4endl;
return EmissionProbability;
/*
G4cout << "exEnergy= " << exEnergy << " Ec= " << bCoulomb
<< " d0= " << delta0
<< " Free= " << mass - resMass - evapMass
<< G4endl;
*/
if(mass <= resMass + evapMass + elim) { return 0.0; }
G4double twoMass = mass + mass;
G4double ekinmax =
((mass-resMass)*(mass+resMass) + evapMass2)/twoMass - evapMass;
G4double ekinmin = 0.0;
if(elim > 0.0) {
G4double resM = std::max(mass - evapMass - elim, resMass);
ekinmin =
std::max(((mass-resM)*(mass+resM) + evapMass2)/twoMass - evapMass,0.0);
}
/*
G4cout << "Emin= " <<ekinmin<<" Emax= "<<ekinmax
<< " mass= " << mass << " resM= " << resMass
<< " evapM= " << evapMass << G4endl;
*/
if(ekinmax <= ekinmin) { return 0.0; }
theProbability->SetDecayKinematics(resZ, resA, resMass, mass);
G4double prob = theProbability->TotalProbability(*fragment, ekinmin,
ekinmax, bCoulomb,
exEnergy - delta0);
/*
G4cout<<"G4EvaporationChannel: prob= "<< prob << " Z= " << theZ
<< " A= " << theA << " E1= " << ekinmin << " E2= " << ekinmax
<< G4endl;
*/
return prob;
}
G4Fragment* G4EvaporationChannel::EmittedFragment(G4Fragment* theNucleus)
{
G4Fragment* evFragment = nullptr;
G4double ekin = 0.0;
if(ResA <= 4 &&
((ResA == 4 && ResZ == 2) || (ResA == 3 && ResZ == 2) ||
(ResA == 3 && ResZ == 1) || (ResA == 2 && ResZ == 1) ||
(ResA == 1 && ResZ == 1) || (ResA == 1 && ResZ == 0) )) {
G4double mres = G4NucleiProperties::GetNuclearMass(ResA, ResZ);
ekin = 0.5*(Mass*Mass - mres*mres + EvapMass*EvapMass)/Mass - EvapMass;
G4double ekin;
// assumed, that TotalProbability(...) was already called
// if value iz zero no possiblity to sample final state
if(resA <= 4 || theProbability->GetProbability() == 0.0) {
ekin = 0.5*(mass*mass - resMass*resMass + evapMass2)/mass - evapMass;
} else {
ekin = theProbability->SampleKineticEnergy(MinKinEnergy, MaxKinEnergy,
CoulombBarrier);
ekin = theProbability->SampleEnergy();
}
ekin = std::max(ekin, 0.0);
G4LorentzVector lv0 = theNucleus->GetMomentum();
G4LorentzVector lv(std::sqrt(ekin*(ekin + 2.0*EvapMass))*G4RandomDirection(),
ekin + EvapMass);
G4LorentzVector lv(std::sqrt(ekin*(ekin + 2.0*evapMass))*G4RandomDirection(),
ekin + evapMass);
lv.boost(lv0.boostVector());
evFragment = new G4Fragment(theA, theZ, lv);
G4Fragment* evFragment = new G4Fragment(theA, theZ, lv);
lv0 -= lv;
theNucleus->SetZandA_asInt(ResZ, ResA);
theNucleus->SetZandA_asInt(resZ, resA);
theNucleus->SetMomentum(lv0);
//G4cout << "Residual: Z= " << resZ << " A= " << resA << " Eex= "
// << theNucleus->GetExcitationEnergy() << G4endl;
return evFragment;
}
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by J. M. Quesada (July 2009) on base of V. Lara code
// V.Ivanchenko cleanup
@@ -196,10 +194,6 @@ std::vector<G4VEvaporationChannel*>* G4EvaporationDefaultGEMFactory::GetChannel(
theChannel->push_back( new G4Mg27GEMChannel() ); // Mg27
theChannel->push_back( new G4Mg28GEMChannel() ); // Mg28
size_t nn = theChannel->size();
for(size_t i=1; i<nn; ++i) {
(*theChannel)[i]->SetPhotonEvaporation(thePhotonEvaporation);
}
return theChannel;
}
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara
//
@@ -66,14 +64,6 @@ std::vector<G4VEvaporationChannel*>* G4EvaporationFactory::GetChannel()
theChannel->push_back( new G4He3EvaporationChannel() ); // He3
theChannel->push_back( new G4AlphaEvaporationChannel() ); // Alpha
size_t nn = theChannel->size();
for(size_t i=1; i<nn; ++i) {
(*theChannel)[i]->SetPhotonEvaporation(thePhotonEvaporation);
}
return theChannel;
}
@@ -36,6 +36,8 @@
// JMQ (14 february 2009) bug fixed in emission width: hbarc instead of
// hbar_Planck in the denominator
//
// V.Ivanchenko general clean-up since 2010
//
#include "G4EvaporationProbability.hh"
#include "G4NuclearLevelData.hh"
#include "G4VCoulombBarrier.hh"
@@ -48,84 +50,78 @@
#include "Randomize.hh"
#include "G4Exp.hh"
#include "G4Log.hh"
#include "G4Pow.hh"
using namespace std;
static const G4double explim = 160.;
G4EvaporationProbability::G4EvaporationProbability(G4int anA, G4int aZ,
G4double aGamma,
G4VCoulombBarrier*)
: G4VEmissionProbability(aZ, anA), Gamma(aGamma)
G4double aGamma)
: G4VEmissionProbability(aZ, anA), fGamma(aGamma)
{
resZ = resA = fragA = fragZ = 0;
resA13 = muu = resMass = Mass = U = delta0 = delta1 = a0 = probmax = 0.0;
partMass = G4NucleiProperties::GetNuclearMass(theA, theZ);
pcoeff = Gamma*partMass*CLHEP::millibarn
resA13 = muu = freeU = a0 = delta1 = 0.0;
pcoeff = fGamma*pEvapMass*CLHEP::millibarn
/((CLHEP::pi*CLHEP::hbarc)*(CLHEP::pi*CLHEP::hbarc));
if(0 == theZ) { index = 0; }
else if(1 == theZ) { index = theA; }
else { index = theA + 1; }
fLevelData = G4NuclearLevelData::GetInstance();
if(0 == aZ) {
ResetIntegrator(30, 0.25*CLHEP::MeV, 0.02);
} else if(1 == aZ && 1 == anA) {
ResetIntegrator(30, 0.5*CLHEP::MeV, 0.03);
} else {
ResetIntegrator(30, 0.5*CLHEP::MeV, 0.03);
}
// G4cout << "G4EvaporationProbability: Z= " << theZ << " A= " << theA
// << " M(GeV)= " << pEvapMass/GeV << G4endl;
}
G4EvaporationProbability::~G4EvaporationProbability()
{}
G4double G4EvaporationProbability::EmissionProbability(
const G4Fragment&, G4double)
G4double G4EvaporationProbability::CalcAlphaParam(const G4Fragment&)
{
return 0.0;
return 1.0;
}
G4double G4EvaporationProbability::CalcBetaParam(const G4Fragment&)
{
return 1.0;
}
G4double G4EvaporationProbability::TotalProbability(
const G4Fragment & fragment, G4double minEnergy, G4double maxEnergy,
G4double CoulombBarrier)
const G4Fragment& fragment, G4double minEnergy, G4double maxEnergy,
G4double CB, G4double exEnergy)
{
fragA = fragment.GetA_asInt();
fragZ = fragment.GetZ_asInt();
resA = fragA - theA;
resZ = fragZ - theZ;
G4double fragMass = fragment.GetGroundStateMass();
U = fragment.GetExcitationEnergy();
Mass = fragMass + U;
delta0 = std::max(0.0, fPairCorr->GetPairingCorrection(fragA,fragZ));
delta1 = std::max(0.0, fPairCorr->GetPairingCorrection(resA,resZ));
resMass = G4NucleiProperties::GetNuclearMass(resA, resZ);
resA13 = fG4pow->Z13(resA);
a0 = fLevelData->GetLevelDensity(fragZ,fragA,U);
/*
G4int fragA = fragment.GetA_asInt();
G4int fragZ = fragment.GetZ_asInt();
G4double U = fragment.GetExcitationEnergy();
a0 = pNuclearLevelData->GetLevelDensity(fragZ,fragA,U);
freeU = exEnergy;
resA13 = pG4pow->Z13(resA);
delta1 = pNuclearLevelData->GetPairingCorrection(resZ,resA);
/*
G4cout << "G4EvaporationProbability: Z= " << theZ << " A= " << theA
<< " resZ= " << resZ << " resA= " << resA
<< " fragZ= " << fragZ << " fragA= " << fragA
<< "\n U= " << U << " d0= " << delta0 << " a0= " << a0
<< " OPT= " << OPTxs << G4endl;
<< "\n freeU= " << freeU
<< " a0= " << a0 << " OPT= " << OPTxs << " emin= "
<< minEnergy << " emax= " << maxEnergy
<< " CB= " << CB << G4endl;
*/
if(U < delta0 || maxEnergy <= minEnergy) { return 0.0; }
G4double Width = 0.0;
if (OPTxs==0 || (OPTxs==4 && U < 10. + delta0)) {
if (OPTxs==0 || (OPTxs==4 && freeU < 10.)) {
G4double SystemEntropy = 2.0*std::sqrt(a0*(U-delta0));
G4double SystemEntropy = 2.0*std::sqrt(a0*freeU);
static const G4double RN2 =
2.25*fermi*fermi/(twopi* hbar_Planck*hbar_Planck);
const G4double RN2 = 2.25*CLHEP::fermi*CLHEP::fermi
/(CLHEP::twopi*CLHEP::hbar_Planck*hbar_Planck);
G4double Alpha = CalcAlphaParam(fragment);
G4double Beta = CalcBetaParam(fragment);
// to be checked where to use a0, where - a1
G4double a1 = fLevelData->GetLevelDensity(resZ,resA,U);
G4double GlobalFactor = Gamma*Alpha*partMass*RN2*resA13*resA13/(a1*a1);
G4double a1 = pNuclearLevelData->GetLevelDensity(resZ,resA,freeU);
G4double GlobalFactor = fGamma*Alpha*pEvapMass*RN2*resA13*resA13/(a1*a1);
G4double maxea = maxEnergy*a1;
G4double Term1 = Beta*a1 - 1.5 + maxea;
@@ -137,7 +133,7 @@ G4double G4EvaporationProbability::TotalProbability(
ExpTerm2 = std::min(ExpTerm2, explim);
ExpTerm2 = G4Exp(ExpTerm2);
Width = GlobalFactor*(Term1*ExpTerm1 + Term2*ExpTerm2);
pProbability = GlobalFactor*(Term1*ExpTerm1 + Term2*ExpTerm2);
} else {
@@ -147,49 +143,52 @@ G4double G4EvaporationProbability::TotalProbability(
}
// if Coulomb barrier cutoff is superimposed for all cross sections
// then the limit is the Coulomb Barrier
Width = IntegrateProbability(minEnergy, maxEnergy, CoulombBarrier);
pProbability = IntegrateProbability(minEnergy, maxEnergy, CB);
}
return Width;
return pProbability;
}
G4double G4EvaporationProbability::ComputeProbability(G4double K, G4double cb)
G4double G4EvaporationProbability::ComputeProbability(G4double K, G4double CB)
{
//G4cout << "### G4EvaporationProbability::ProbabilityDistributionFunction"
// << G4endl;
G4double E0 = std::max(U - delta0, 0.0);
G4double E1 = Mass - partMass - resMass - delta1 - K;
/*
G4cout << "PDF: FragZ= " << fragZ << " FragA= " << fragA
<< " Z= " << theZ << " A= " << theA
<< " K= " << K << " E0= " << E0 << " E1= " << E1 << G4endl;
*/
if(E1 < 0.0) { return 0.0; }
G4double E0 = freeU;
// abnormal case - should never happens
if(pMass < pEvapMass + pResMass) { return 0.0; }
G4double m02 = pMass*pMass;
G4double m12 = pEvapMass*pEvapMass;
G4double mres = sqrt(m02 + m12 - 2.*pMass*(pEvapMass + K));
G4double a1 = fLevelData->GetLevelDensity(resZ,resA,U);
G4double xs = CrossSection(K, cb);
G4double excRes = mres - pResMass;
G4double E1 = excRes - delta1;
if(E1 <= 0.0) { return 0.0; }
G4double a1 = pNuclearLevelData->GetLevelDensity(resZ,resA,excRes);
G4double xs = CrossSection(K, CB);
G4double prob = pcoeff*G4Exp(2.0*(std::sqrt(a1*E1) - std::sqrt(a0*E0)))*K*xs;
/*
G4cout << "Evap prob: " << prob << " FragZ= " << fragZ << " FragA= " << fragA
<< " Z= " << theZ << " A= " << theA
<< "\n K= " << K << " E0= " << E0 << " E1= " << E1
<< " cb= " << cb << " xsec= " << xs << G4endl;
/*
G4cout << "PDF: Z= " << theZ << " A= " << theA
<< " K= " << K << " E0= " << E0 << " E1= " << E1 << G4endl;
G4cout << " prob= " << prob << " pcoeff= " << pcoeff
<< " xs= " << xs << G4endl;
*/
return prob;
}
G4double
G4EvaporationProbability::CrossSection(G4double K, G4double cb)
G4EvaporationProbability::CrossSection(G4double K, G4double CB)
{
G4double res;
if(OPTxs <= 2) {
res = G4ChatterjeeCrossSection::ComputeCrossSection(K, cb, resA13, muu,
res = G4ChatterjeeCrossSection::ComputeCrossSection(K, CB, resA13, muu,
index, theZ, resA);
} else {
res = G4KalbachCrossSection::ComputeCrossSection(K, cb, resA13, muu,
res = G4KalbachCrossSection::ComputeCrossSection(K, CB, resA13, muu,
index, theZ, theA, resA);
}
//G4cout << " K= " << K << " res= " << res << " muu= " << muu << G4endl;
//G4cout << "XS: K= "<<K<<" res= "<<res<<" cb= "<<CB<<" muu= "
// <<muu<<" index= " << index<< G4endl;
return res;
}
@@ -205,8 +204,7 @@ G4EvaporationProbability::SampleKineticEnergy(G4double minKinEnergy,
*/
G4double T = 0.0;
CLHEP::HepRandomEngine* rndm = G4Random::getTheEngine();
static const G4int nmax = 100;
if (OPTxs==0 || (OPTxs==4 && U < 10. + delta0)) {
if (OPTxs==0 || (OPTxs==4 && freeU < 10.)) {
// JMQ:
// It uses Dostrovsky's approximation for the inverse reaction cross
// in the probability for fragment emission
@@ -219,6 +217,8 @@ G4EvaporationProbability::SampleKineticEnergy(G4double minKinEnergy,
G4double Rk = 0.0;
G4double FRk = 0.0;
G4int nn = 0;
const G4int nmax = 100;
const G4double ssqr3 = 1.5*std::sqrt(3.0);
do {
G4double RandNumber = rndm->flat();
Rk = 1.0 + (1./RbSqrt)*G4Log(RandNumber + (1.0-RandNumber)*PEX1);
@@ -230,7 +230,6 @@ G4EvaporationProbability::SampleKineticEnergy(G4double minKinEnergy,
Q2 = Q1*std::sqrt(Q1);
}
static const G4double ssqr3 = 1.5*std::sqrt(3.0);
FRk = ssqr3 * Rk * (Q1 - Rk*Rk)/Q2;
if(nn > nmax) { break; }
++nn;
@@ -240,16 +239,8 @@ G4EvaporationProbability::SampleKineticEnergy(G4double minKinEnergy,
T = std::max(maxKinEnergy * (1.0-Rk*Rk), 0.0) + minKinEnergy;
} else {
if(fVerbose > 1) {
G4cout << "###=== SampleEnergy: " << " Z= " << theZ
<< " A= " << theA << " FragZ= " << fragZ
<< " FragA= " << fragA << G4endl;
}
T = SampleEnergy();
}
//G4cout << "-- new Z= " << theZ << " A= " << theA << " ekin= " << T << G4endl;
//G4cout<<"-- new Z= "<<theZ<<" A= "<< theA << " ekin= " << T << G4endl;
return T;
//return fLevelData->FindLevel(resZ, resA, resMass, Mass, partMass, T);
}
@@ -24,16 +24,15 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
// 17-11-2010 V.Ivanchenko moved constructor and destructor to source and cleanup
// 17-11-2010 V.Ivanchenko cleanup
#include "G4He3EvaporationChannel.hh"
G4He3EvaporationChannel::G4He3EvaporationChannel()
: G4EvaporationChannel(3,2,"He3",&theEvaporationProbability,&theCoulombBarrier)
: G4EvaporationChannel(3,2,&pr)
{}
G4He3EvaporationChannel::~G4He3EvaporationChannel()
@@ -36,7 +36,7 @@
#include "G4He3EvaporationProbability.hh"
G4He3EvaporationProbability::G4He3EvaporationProbability() :
G4EvaporationProbability(3,2,2.0,&theCoulombBarrier)
G4EvaporationProbability(3,2,2.0)
{}
G4He3EvaporationProbability::~G4He3EvaporationProbability()
@@ -24,7 +24,6 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
@@ -33,7 +32,7 @@
#include "G4NeutronEvaporationChannel.hh"
G4NeutronEvaporationChannel::G4NeutronEvaporationChannel()
: G4EvaporationChannel(1,0,"neutron",&theEvaporationProbability,&theCoulombBarrier)
: G4EvaporationChannel(1,0,&pr)
{}
G4NeutronEvaporationChannel::~G4NeutronEvaporationChannel()
@@ -35,9 +35,10 @@
#include "G4NeutronEvaporationProbability.hh"
#include "G4SystemOfUnits.hh"
#include "G4Pow.hh"
G4NeutronEvaporationProbability::G4NeutronEvaporationProbability() :
G4EvaporationProbability(1,0,2.0,&theCoulombBarrier)
G4EvaporationProbability(1,0,2.0)
{}
G4NeutronEvaporationProbability::~G4NeutronEvaporationProbability()
@@ -45,12 +46,11 @@ G4NeutronEvaporationProbability::~G4NeutronEvaporationProbability()
G4double G4NeutronEvaporationProbability::CalcAlphaParam(const G4Fragment& fragment)
{
return 0.76+2.2/fG4pow->Z13(fragment.GetA_asInt() - 1);
return 0.76+2.2/pG4pow->Z13(fragment.GetA_asInt() - 1);
}
G4double G4NeutronEvaporationProbability::CalcBetaParam(const G4Fragment& fragment)
{
return (2.12/fG4pow->Z23(fragment.GetA_asInt() - 1) - 0.05)*CLHEP::MeV/
return (2.12/pG4pow->Z23(fragment.GetA_asInt() - 1) - 0.05)*CLHEP::MeV/
CalcAlphaParam(fragment);
}
@@ -24,16 +24,15 @@
// ********************************************************************
//
//
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
// 17-11-2010 V.Ivanchenko moved constructor and destructor to source and cleanup
// 17-11-2010 V.Ivanchenko cleanup
#include "G4ProtonEvaporationChannel.hh"
G4ProtonEvaporationChannel::G4ProtonEvaporationChannel()
: G4EvaporationChannel(1,1,"proton",&theEvaporationProbability,&theCoulombBarrier)
: G4EvaporationChannel(1,1,&pr)
{}
G4ProtonEvaporationChannel::~G4ProtonEvaporationChannel()
@@ -36,7 +36,7 @@
#include "G4ProtonEvaporationProbability.hh"
G4ProtonEvaporationProbability::G4ProtonEvaporationProbability() :
G4EvaporationProbability(1,1,2.0,&theCoulombBarrier)
G4EvaporationProbability(1,1,2.0)
{}
G4ProtonEvaporationProbability::~G4ProtonEvaporationProbability()
@@ -28,12 +28,12 @@
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Nov. 1999)
//
// 17-11-2010 V.Ivanchenko moved constructor and destructor to source and cleanup
// 17-11-2010 V.Ivanchenko cleanup
#include "G4TritonEvaporationChannel.hh"
G4TritonEvaporationChannel::G4TritonEvaporationChannel()
: G4EvaporationChannel(3,1,"triton",&theEvaporationProbability,&theCoulombBarrier)
: G4EvaporationChannel(3,1,&pr)
{}
G4TritonEvaporationChannel::~G4TritonEvaporationChannel()
@@ -36,7 +36,7 @@
#include "G4TritonEvaporationProbability.hh"
G4TritonEvaporationProbability::G4TritonEvaporationProbability() :
G4EvaporationProbability(3,1,2.0,&theCoulombBarrier)
G4EvaporationProbability(3,1,2.0)
{}
G4TritonEvaporationProbability::~G4TritonEvaporationProbability()
@@ -50,11 +50,12 @@
#include "G4NucleiProperties.hh"
#include "G4NuclearLevelData.hh"
#include "G4LevelManager.hh"
#include "Randomize.hh"
const G4int G4UnstableFragmentBreakUp::Zfr[] = {0, 1, 1, 1, 2, 2};
const G4int G4UnstableFragmentBreakUp::Afr[] = {1, 1, 2, 3, 3, 4};
G4UnstableFragmentBreakUp::G4UnstableFragmentBreakUp()
G4UnstableFragmentBreakUp::G4UnstableFragmentBreakUp() : fVerbose(1)
{
fLevelData = G4NuclearLevelData::GetInstance();
for(G4int i=0; i<6; ++i) {
@@ -74,125 +75,107 @@ G4bool G4UnstableFragmentBreakUp::BreakUpChain(G4FragmentVector* results,
G4int Z = nucleus->GetZ_asInt();
G4int A = nucleus->GetA_asInt();
// if the isotope is in the database it is not exotic
// so, cannot be handled by this class
if(fLevelData->GetLevelManager(Z, A)) { return false; }
G4LorentzVector lv = nucleus->GetMomentum();
G4double time = nucleus->GetCreationTime();
G4double mass1(0.0), mass2(0.0);
// look for the decay channel with normal masses
// without Coulomb barrier and paring corrections
// 1 - recoil, 2 - emitted light ion
if(fVerbose > 1) {
G4cout << "#Unstable decay " << " Z= " << Z << " A= " << A
<< " Eex(MeV)= " << nucleus->GetExcitationEnergy() << G4endl;
}
const G4double tolerance = 10*CLHEP::eV;
const G4double dmlimit = 0.2*CLHEP::MeV;
G4double mass = lv.mag();
G4bool done = false;
G4int Amax = A;
G4int Zres = Z;
G4int Ares = A;
for(G4int k=0; k<Amax; ++k) {
// look for the decay channel with normal masses
// without Coulomb barrier and paring corrections
// 1 - recoil, 2 - emitted light ion
//G4cout << "Unstable decay #" << k << " Z= " << Z << " A= " << A << G4endl;
G4bool isChannel = false;
G4double ekin = 0.0;
G4int i;
for(i=0; i<6; ++i) {
Zres = Z - Zfr[i];
Ares = A - Afr[i];
for(G4int j=0; j<6; ++j) {
if(Zres == Zfr[j] && Ares == Afr[j]) {
/*
G4cout << "i= " << i << " j= " << j << " Zres= " << Zres
<< " Ares= " << Ares << " dm= " << mass - masses[i] - masses[j]
<< G4endl;
*/
if(mass >= masses[i] + masses[j]) {
mass2 = masses[i];
mass1 = masses[j];
ekin = 0.0;
done = true;
isChannel = true;
break;
G4double exca = -1000.0;
G4bool isChannel = false;
G4int idx = -1;
for(G4int i=0; i<6; ++i) {
G4int Zres = Z - Zfr[i];
G4int Ares = A - Afr[i];
if(Zres >= 0 && Ares >= Zres && Ares >= Afr[i]) {
if(Ares <= 4) {
for(G4int j=0; j<6; ++j) {
if(Zres == Zfr[j] && Ares == Afr[j]) {
/*
G4cout << "i= " << i << " j= " << j << " Zres= " << Zres
<< " Ares= " << Ares << " dm= " << mass - masses[i] - masses[j]
<< G4endl;
*/
G4double delm = mass - masses[i] - masses[j];
if(delm > exca) {
mass2 = masses[i]; // emitted
mass1 = masses[j]; // recoil
exca = delm;
idx = i;
if(delm > 0.0) { isChannel = true; }
break;
}
}
}
}
if(isChannel) { break; }
if(Zres >= 0 && Ares >= Zres && Ares > 0) {
G4double mres = G4NucleiProperties::GetNuclearMass(Ares, Zres);
G4double e = mass - mres - masses[i];
// select the most excited state
const G4LevelManager* lman = fLevelData->GetLevelManager(Z, A);
if(lman && e >= ekin) {
mass2 = masses[i];
mass1 = mres;
ekin = lman->NearestLowEdgeLevelEnergy(e);
isChannel = true;
done = true;
break;
}
// no simple channel
G4double mres = G4NucleiProperties::GetNuclearMass(Ares, Zres);
G4double e = mass - mres - masses[i];
// select excited state
const G4LevelManager* lman = fLevelData->GetLevelManager(Zres, Ares);
if(lman && e >= 0.0) {
mass2 = masses[i];
mass1 = mres + e*G4UniformRand();
idx = i;
isChannel = true;
break;
}
// if physical channel is not identified
// check excitation energy
if(e > exca) {
mass2 = masses[i];
mass1 = mres;
if(e > 0.0) { mass1 += e; }
exca = e;
idx = i;
}
}
// no decay channel - assume that primary mass is biased
// only energy will be conserved
if(!isChannel) {
for(i=0; i<6; ++i) {
Zres = Z - Zfr[i];
Ares = A - Afr[i];
if(Zres >= 0 && Ares >= Zres && Ares > 0) {
G4double mres = proton_mass_c2*Zres + neutron_mass_c2*(Ares - Zres);
G4double e = mass - mres - masses[i];
if(e >= ekin) {
mass2 = masses[i];
mass1 = mres;
ekin = e;
isChannel = true;
break;
}
}
}
}
if(!isChannel) {
// further decay impossible
// if no one decay sampled do not update primary
if(0 == k) { return false; }
else { break; }
}
// useful to left max excitation for the residual
mass1 += ekin;
// compute energy of light fragment
G4double e2 = 0.5*((mass - mass1)*(mass + mass1) + mass2*mass2)/mass;
e2 = std::max(e2, mass2);
G4double mom = std::sqrt((e2 - mass2)*(e2 + mass2));
// sample decay
G4ThreeVector bst = lv.boostVector();
G4ThreeVector v = G4RandomDirection();
G4LorentzVector mom2 = G4LorentzVector(v*mom, e2);
mom2.boost(bst);
frag = new G4Fragment(Afr[i], Zfr[i], mom2);
frag->SetCreationTime(time);
results->push_back(frag);
// residual
lv -= mom2;
Z -= Zfr[i];
A -= Afr[i];
mass = lv.mag();
if(done) { break; }
}
G4double massmin = mass1 + mass2;
if(mass < massmin) {
if(mass + dmlimit < massmin) { return false; }
if(fVerbose > 1) {
G4cout << "#Unstable decay correction: Z= " << Z << " A= " << A
<< " idx= " << idx
<< " deltaM(MeV)= " << mass - massmin
<< G4endl;
}
mass = massmin;
G4double e = std::max(lv.e(), mass + tolerance);
G4double mom = std::sqrt((e - mass)*(e + mass));
G4ThreeVector dir = lv.vect().unit();
lv.set(dir*mom, e);
}
// updated primary
// compute energy of light fragment
G4double e2 = 0.5*((mass - mass1)*(mass + mass1) + mass2*mass2)/mass;
e2 = std::max(e2, mass2);
G4double mom = std::sqrt((e2 - mass2)*(e2 + mass2));
// sample decay
G4ThreeVector bst = lv.boostVector();
G4ThreeVector v = G4RandomDirection();
G4LorentzVector mom2 = G4LorentzVector(v*mom, e2);
mom2.boost(bst);
frag = new G4Fragment(Afr[idx], Zfr[idx], mom2);
frag->SetCreationTime(time);
results->push_back(frag);
// residual
lv -= mom2;
Z -= Zfr[idx];
A -= Afr[idx];
nucleus->SetZandA_asInt(Z, A);
nucleus->SetMomentum(lv);
return true;
@@ -48,22 +48,22 @@ class G4FermiBreakUpVI : public G4VFermiBreakUp
public:
explicit G4FermiBreakUpVI();
virtual ~G4FermiBreakUpVI();
~G4FermiBreakUpVI() final;
virtual void Initialise() final;
void Initialise() final;
// check if the Fermi Break Up model can be used
// mass is an effective mass of a fragment
virtual G4bool IsApplicable(G4int ZZ, G4int AA, G4double etot) const final;
G4bool IsApplicable(G4int ZZ, G4int AA, G4double etot) const final;
// new interface - vector of products is added to the provided vector
// primary fragment is deleted or is modified and added to the list
// of products
virtual void BreakFragment(G4FragmentVector*, G4Fragment* theNucleus) final;
void BreakFragment(G4FragmentVector*, G4Fragment* theNucleus) final;
private:
virtual void InitialisePool() final;
void InitialisePool();
G4bool SampleDecay();
@@ -77,7 +77,6 @@ private:
CLHEP::HepRandomEngine* rndmEngine;
G4int verbose;
G4int maxZ;
G4int maxA;
@@ -57,10 +57,10 @@ public:
private:
inline const G4FermiChannels& operator=(const G4FermiChannels&) = delete;
inline G4FermiChannels(const G4FermiChannels &) = delete;
inline G4bool operator==(const G4FermiChannels &) const = delete;
inline G4bool operator!=(const G4FermiChannels &) const = delete;
inline const G4FermiChannels& operator=(const G4FermiChannels&);
inline G4FermiChannels(const G4FermiChannels &);
inline G4bool operator==(const G4FermiChannels &);
inline G4bool operator!=(const G4FermiChannels &);
size_t nch;
G4double excitation;
@@ -39,8 +39,7 @@ class G4FermiFragment
{
public:
explicit G4FermiFragment(G4int anA, G4int aZ, G4int sp,
G4double exc, G4bool stable, G4bool phys = true);
explicit G4FermiFragment(G4int anA, G4int aZ, G4int sp, G4double exc);
~G4FermiFragment();
@@ -74,20 +73,9 @@ public:
return (fragmentMass + excitEnergy);
}
inline G4bool IsStable() const
{
return isStable;
}
inline G4bool IsPhysical() const
{
return isPhysical;
}
inline G4double GetCoulombBarrier(G4int Ares, G4int Zres, G4double Eex) const
{
return cBarrier ? cBarrier->GetCoulombBarrier(Ares, Zres, Eex)
*cBarrier->BarrierPenetrationFactor(Z) : 0.0;
return cBarrier->GetCoulombBarrier(Ares, Zres, Eex);
}
inline G4bool operator==(const G4FermiFragment &right) const
@@ -98,22 +86,18 @@ public:
private:
G4int A;
G4int Z;
G4int spin;
G4bool isStable;
G4bool isPhysical;
G4double excitEnergy;
G4double fragmentMass;
G4CoulombBarrier* cBarrier;
G4FermiFragment(const G4FermiFragment &right) = delete;
const G4FermiFragment & operator=(const G4FermiFragment &right) = delete;
G4bool operator!=(const G4FermiFragment &right) const = delete;
G4int A;
G4int Z;
G4int spin;
G4FermiFragment(const G4FermiFragment &right);
const G4FermiFragment & operator=(const G4FermiFragment &right);
G4bool operator!=(const G4FermiFragment &right) const;
};
@@ -55,11 +55,11 @@ public:
void DumpFragment(const G4FermiFragment*) const;
void Dump() const;
G4bool IsApplicable(G4int Z, G4int A, G4double etot) const;
G4bool IsPhysical(G4int Z, G4int A) const;
G4bool HasChannels(G4int Z, G4int A, G4double exc) const;
inline const G4FermiDecayProbability* FermiDecayProbability() const;
inline G4int GetMaxZ() const;
@@ -92,24 +92,13 @@ private:
// pool
std::vector<const G4FermiFragment*> fragment_pool;
std::vector<const G4FermiFragment*> funstable;
// lists of configurations sorted by A
// "stable" fragments
std::vector<const G4FermiFragment*> list_f[maxA];
// list of channels for "stable" fragments
std::vector<G4FermiChannels*> list_c[maxA];
// pairs of stable fragments
std::vector<const G4FermiPair*> list_p[maxA];
// "unstable" fragments
std::vector<const G4FermiFragment*> list_g[maxA];
// list of channels of stable and unstable fragments
std::vector<G4FermiChannels*> list_d[maxA];
// pairs of stable and unstable fragments
std::vector<const G4FermiPair*> list_u[maxA];
};
inline G4int G4FermiFragmentsPoolVI::GetMaxZ() const
@@ -40,7 +40,7 @@ class G4VFermiBreakUp
{
public:
explicit G4VFermiBreakUp() {};
explicit G4VFermiBreakUp() : verbose(0) {};
virtual ~G4VFermiBreakUp() {};
virtual void Initialise() = 0;
@@ -56,12 +56,18 @@ public:
virtual void BreakFragment(G4FragmentVector* results,
G4Fragment* theNucleus) = 0;
inline void SetVerbose(G4int val) { verbose = val; }
protected:
G4int verbose;
private:
G4VFermiBreakUp(const G4VFermiBreakUp &right) = delete;
const G4VFermiBreakUp & operator=(const G4VFermiBreakUp &right) = delete;
G4bool operator==(const G4VFermiBreakUp &right) const = delete;
G4bool operator!=(const G4VFermiBreakUp &right) const = delete;
G4VFermiBreakUp(const G4VFermiBreakUp &right);
const G4VFermiBreakUp & operator=(const G4VFermiBreakUp &right);
G4bool operator==(const G4VFermiBreakUp &right) const;
G4bool operator!=(const G4VFermiBreakUp &right) const;
};
#endif
@@ -44,9 +44,8 @@ G4Mutex G4FermiBreakUpVI::FermiBreakUpVIMutex = G4MUTEX_INITIALIZER;
#endif
G4FermiBreakUpVI::G4FermiBreakUpVI()
: theDecay(nullptr), rndmEngine(nullptr), verbose(0), maxZ(9), maxA(17)
: theDecay(nullptr), rndmEngine(nullptr), maxZ(9), maxA(17)
{
prob.reserve(10);
frag.reserve(10);
lvect.reserve(10);
Z = A = spin = 0;
@@ -67,13 +66,12 @@ G4FermiBreakUpVI::~G4FermiBreakUpVI()
void G4FermiBreakUpVI::Initialise()
{
if(verbose > 0) {
if(verbose > 1) {
G4cout << "### G4FermiBreakUpVI::Initialise(): " << thePool << G4endl;
}
if(thePool == nullptr) { InitialisePool(); }
theDecay = thePool->FermiDecayProbability();
elim = thePool->GetEnergyLimit();
//tolerance = thePool->GetTolerance();
}
void G4FermiBreakUpVI::InitialisePool()
@@ -91,18 +89,18 @@ void G4FermiBreakUpVI::InitialisePool()
G4bool G4FermiBreakUpVI::IsApplicable(G4int ZZ, G4int AA, G4double eexc) const
{
return (ZZ < maxZ && AA < maxA && AA > 0 && eexc <= elim) ? true : false;
return (ZZ < maxZ && AA < maxA && AA > 0 && eexc <= elim
&& thePool->HasChannels(ZZ, AA, eexc));
}
void G4FermiBreakUpVI::BreakFragment(G4FragmentVector* theResult,
G4Fragment* theNucleus)
{
if(verbose > 0) {
G4cout << "### G4FermiBreakUpVI::BreakFragment start new fragment " << G4endl;
if(verbose > 1) {
G4cout << "### G4FermiBreakUpVI::BreakFragment start new fragment "
<< G4endl;
G4cout << *theNucleus << G4endl;
}
frag.clear();
lvect.clear();
// initial fragment
Z = theNucleus->GetZ_asInt();
@@ -110,16 +108,17 @@ void G4FermiBreakUpVI::BreakFragment(G4FragmentVector* theResult,
excitation = theNucleus->GetExcitationEnergy();
mass = theNucleus->GetGroundStateMass() + excitation;
spin = -1;
G4double time = theNucleus->GetCreationTime();
lv0 = theNucleus->GetMomentum();
rndmEngine = G4Random::getTheEngine();
// sample first decay of an initial state
// if not possible to decay - exit
if(!SampleDecay()) {
theResult->push_back(theNucleus);
return;
}
G4double time = theNucleus->GetCreationTime();
delete theNucleus;
static const G4int imax = 100;
@@ -131,18 +130,15 @@ void G4FermiBreakUpVI::BreakFragment(G4FragmentVector* theResult,
A = frag[i]->GetA();
spin = frag[i]->GetSpin();
mass = frag[i]->GetTotalEnergy();
excitation = 0.0;
if(thePool->IsPhysical(Z, A)) {
excitation = frag[i]->GetExcitationEnergy();
}
lv0 = lvect[i];
if(verbose > 0) {
if(verbose > 1) {
G4cout << "# FermiFrag " << i << ". Z= " << Z << " A= " << A
<< " mass= " << mass << " exc= " << excitation << G4endl;
<< " mass= " << mass << " exc= "
<< frag[i]->GetExcitationEnergy() << G4endl;
}
// stable fragment
if(!SampleDecay()) {
if(verbose > 0) { G4cout << " New G4Fragment" << G4endl; }
if(verbose > 1) { G4cout << " New G4Fragment" << G4endl; }
G4Fragment* f = new G4Fragment(A, Z, lv0);
f->SetSpin(0.5*spin);
f->SetCreationTime(time);
@@ -153,6 +149,8 @@ void G4FermiBreakUpVI::BreakFragment(G4FragmentVector* theResult,
break;
}
}
frag.clear();
lvect.clear();
}
G4bool G4FermiBreakUpVI::SampleDecay()
@@ -160,7 +158,7 @@ G4bool G4FermiBreakUpVI::SampleDecay()
const G4FermiChannels* chan = thePool->ClosestChannels(Z, A, mass);
if(!chan) { return false; }
size_t nn = chan->GetNumberOfChannels();
if(verbose > 0) {
if(verbose > 1) {
G4cout << "== SampleDecay " << nn << " channels Eex= "
<< chan->GetExcitation() << G4endl;
}
@@ -185,7 +183,7 @@ G4bool G4FermiBreakUpVI::SampleDecay()
const std::vector<const G4FermiPair*>& pvect = chan->GetChannels();
if(nn > 12) { prob.resize(nn, 0.0); }
G4double ptot = 0.0;
if(verbose > 1) {
if(verbose > 2) {
G4cout << "Start recompute probabilities" << G4endl;
}
for(size_t i=0; i<nn; ++i) {
@@ -193,7 +191,7 @@ G4bool G4FermiBreakUpVI::SampleDecay()
pvect[i]->GetFragment1(),
pvect[i]->GetFragment2());
prob[i] = ptot;
if(verbose > 1) {
if(verbose > 2) {
G4cout << i << ". " << prob[i]
<< " Z1= " << pvect[i]->GetFragment1()->GetZ()
<< " A1= " << pvect[i]->GetFragment1()->GetA()
@@ -218,7 +216,7 @@ G4bool G4FermiBreakUpVI::SampleDecay()
G4double mass1 = frag1->GetTotalEnergy();
G4double mass2 = frag2->GetTotalEnergy();
if(verbose > 1) {
if(verbose > 2) {
G4cout << " M= " << mass << " M1= " << mass1 << " M2= " << mass2
<< " Exc1= " << frag1->GetExcitationEnergy()
<< " Exc2= " << frag2->GetExcitationEnergy() << G4endl;
@@ -239,13 +237,12 @@ G4bool G4FermiBreakUpVI::SampleDecay()
boostVector = lv0.boostVector();
lv1.boost(boostVector);
G4double e2 = mass - e1;
lv0 -= lv1;
G4double e2 = lv0.e();
if(e2 < mass2) {
e2 = mass2;
p1 = 0.0;
lv0.set(0.,0.,0.,mass2);
}
lv0.set(-v*p1, e2);
lv0.boost(boostVector);
frag.push_back(frag1);
frag.push_back(frag2);
@@ -32,18 +32,11 @@
#include "G4NucleiProperties.hh"
#include "G4PhysicalConstants.hh"
G4FermiFragment::G4FermiFragment(G4int anA, G4int aZ, G4int sp,
G4double exc, G4bool stable, G4bool phys):
A(anA), Z(aZ), spin(sp), isStable(stable), isPhysical(phys),
excitEnergy(exc)
G4FermiFragment::G4FermiFragment(G4int anA, G4int aZ, G4int sp, G4double exc)
: excitEnergy(exc), A(anA), Z(aZ), spin(sp)
{
cBarrier = nullptr;
if(phys) {
fragmentMass = G4NucleiProperties::GetNuclearMass(A, Z);
if(!stable) { cBarrier = new G4CoulombBarrier(A, Z); }
} else {
fragmentMass = Z*proton_mass_c2 + (A-Z)*neutron_mass_c2;
}
cBarrier = new G4CoulombBarrier(A, Z);
fragmentMass = G4NucleiProperties::GetNuclearMass(A, Z);
}
G4FermiFragment::~G4FermiFragment()
@@ -41,178 +41,117 @@ G4FermiFragmentsPoolVI::G4FermiFragmentsPoolVI()
// G4cout << "### G4FermiFragmentsPoolVI is constructed" << G4endl;
G4DeexPrecoParameters* param =
G4NuclearLevelData::GetInstance()->GetParameters();
tolerance = (G4float)param->GetMinExcitation();
tolerance = param->GetMinExcitation();
timelim = (G4float)param->GetMaxLifeTime();
elim = param->GetFBUEnergyLimit();
elimf= (G4float)elim;
/*
G4cout << "G4FermiFragmentsPoolVI: tolerance= " << tolerance
<< " timelim= " << timelim << " elim= " << elim << G4endl;
*/
fragment_pool.reserve(991);
funstable.reserve(80);
Initialise();
}
G4FermiFragmentsPoolVI::~G4FermiFragmentsPoolVI()
{
size_t nn;
for(G4int i=0; i<maxA; ++i) {
nn = list_p[i].size();
for(size_t j=0; j<nn; ++j) { delete (list_p[i])[j]; }
nn = list_c[i].size();
for(size_t j=0; j<nn; ++j) { delete (list_c[i])[j]; }
nn = list_d[i].size();
for(size_t j=0; j<nn; ++j) { delete (list_d[i])[j]; }
nn = list_u[i].size();
for(size_t j=0; j<nn; ++j) { delete (list_u[i])[j]; }
for(auto & ptr : list_p[i]) { delete ptr; ptr = nullptr; }
for(auto & ptr : list_c[i]) { delete ptr; ptr = nullptr; }
}
nn = fragment_pool.size();
for(size_t j=0; j<nn; ++j) { delete fragment_pool[j]; }
nn = funstable.size();
for(size_t j=0; j<nn; ++j) { delete funstable[j]; }
}
G4bool
G4FermiFragmentsPoolVI::IsApplicable(G4int Z, G4int A, G4double etot) const
{
G4bool isInList = false;
size_t nn = list_f[A].size();
for(size_t i=0; i<nn; ++i) {
if(Z == (list_f[A])[i]->GetZ()) {
isInList = true;
if(etot <= (list_f[A])[i]->GetFragmentMass() + elim) { return true; }
}
}
if(isInList) { return false; }
nn = list_g[A].size();
for(size_t i=0; i<nn; ++i) {
if(Z == (list_g[A])[i]->GetZ() &&
etot <= (list_g[A])[i]->GetFragmentMass() + elim) { return true; }
}
return false;
for(auto & ptr : fragment_pool) { delete ptr; ptr = nullptr; }
}
const G4FermiChannels*
G4FermiFragmentsPoolVI::ClosestChannels(G4int Z, G4int A, G4double e) const
{
const G4FermiChannels* res = nullptr;
G4double demax = e;
const G4FermiChannels* res = nullptr;
G4double demax = 1.e+9;
// stable channels;
size_t nn = list_c[A].size();
for(size_t j=0; j<nn; ++j) {
// stable channels
for(size_t j=0; j<(list_c[A]).size(); ++j) {
const G4FermiFragment* frag = (list_f[A])[j];
if(frag->GetZ() != Z) { continue; }
G4double de = e - frag->GetTotalEnergy();
//G4cout << " Stab check " << j << " channel de= " << de << " tol= " << tolerance << G4endl;
//G4cout << " Stab check " << j << " channel de= " << de
// << " tol= " << tolerance << G4endl;
// an excitation coincide with a level
if(std::abs(de) <= tolerance) {
res = (list_c[A])[j];
//G4cout << " Stab chan: " << j << " N= " << res->GetNumberOfChannels() << G4endl;
break;
} else if(de + tolerance > 0.0) {
if(de < demax) {
res = (list_c[A])[j];
demax = de;
//G4cout << " Stab chan: " << j << " N= " << res->GetNumberOfChannels() << G4endl;
break;
} else {
// closest level selected
de += tolerance;
if(de >= 0.0 && de <= demax) {
res = (list_c[A])[j];
demax = de;
}
//G4cout << " Stab chan: " << j << " N= "
//<< res->GetNumberOfChannels() << G4endl;
}
}
// unstable channels
if(!res) {
nn = list_d[A].size();
for(size_t j=0; j<nn; ++j) {
const G4FermiFragment* frag = (list_g[A])[j];
if(frag->GetZ() != Z) { continue; }
G4double de = e - frag->GetTotalEnergy();
//G4cout << " Unst check " << j << " channel de= " << de << " tol= " << tolerance << G4endl;
if(std::abs(de) <= tolerance || de > 0.0) {
res = (list_d[A])[j];
//G4cout << " Unst chan No: " << j << " N= " << res->GetNumberOfChannels() << G4endl;
break;
}
}
}
return res;
}
G4bool G4FermiFragmentsPoolVI::IsPhysical(G4int Z, G4int A) const
{
G4bool res = false;
G4int nn = list_f[A].size();
for(G4int i=0; i<nn; ++i) {
if((list_f[A])[i]->GetZ() == Z) {
res = true;
break;
}
for(auto const& ptr : list_f[A]) {
if(ptr->GetZ() == Z) { return true; }
}
return res;
return false;
}
G4bool G4FermiFragmentsPoolVI::IsInThePool(G4int Z, G4int A,
G4double exc) const
G4double exc) const
{
G4bool res = false;
G4int nfrag = fragment_pool.size();
for(G4int i=0; i<nfrag; ++i) {
const G4FermiFragment* fr = fragment_pool[i];
if(fr->GetZ() == Z && fr->GetA() == A &&
std::abs(exc - fr->GetExcitationEnergy()) < tolerance) {
res = true;
break;
for(auto const& fr : fragment_pool) {
if(fr->GetZ() == Z && fr->GetA() == A &&
std::abs(exc - fr->GetExcitationEnergy()) < tolerance)
{ return true; }
}
return false;
}
G4bool
G4FermiFragmentsPoolVI::HasChannels(G4int Z, G4int A, G4double exc) const
{
// stable fragment
for(size_t j=0; j<(list_f[A]).size(); ++j) {
const G4FermiFragment* frag = (list_f[A])[j];
if(frag->GetZ() == Z) {
if(exc > frag->GetExcitationEnergy() &&
(list_c[A])[j]->GetNumberOfChannels() > 0) { return true; }
}
}
return res;
return false;
}
G4bool G4FermiFragmentsPoolVI::IsInPhysPairs(
const G4FermiFragment* f1, const G4FermiFragment* f2) const
{
G4bool res = false;
G4int A1 = f1->GetA();
G4int A2 = f2->GetA();
G4int A = A1 + A2;
G4int nn = list_p[A].size();
for(G4int i=0; i<nn; ++i) {
if(f1 == (list_p[A])[i]->GetFragment1() &&
f2 == (list_p[A])[i]->GetFragment2()) {
res = true;
break;
const G4int A = f1->GetA() + f2->GetA();
for(auto const& ptr : list_p[A]) {
if(f1 == ptr->GetFragment1() && f2 == ptr->GetFragment2()) {
return true;
}
}
return res;
}
G4bool G4FermiFragmentsPoolVI::IsInUnphysPairs(
const G4FermiFragment* f1, const G4FermiFragment* f2) const
{
G4bool res = false;
G4int A1 = f1->GetA();
G4int A2 = f2->GetA();
G4int A = A1 + A2;
G4int nn = list_u[A].size();
for(G4int i=0; i<nn; ++i) {
if(f1 == (list_u[A])[i]->GetFragment1() &&
f2 == (list_u[A])[i]->GetFragment2()) {
res = true;
break;
}
}
return res;
return false;
}
void G4FermiFragmentsPoolVI::Initialise()
{
static const G4int nmin = 8;
//G4cout << "G4FermiFragmentsPoolVI::Initialise main loop @@@@@@" << G4endl;
// stable particles
fragment_pool.push_back(new G4FermiFragment(1, 0, 1, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(1, 1, 1, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(2, 1, 2, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(3, 1, 1, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(3, 2, 1, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(4, 2, 0, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(5, 2, 3, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(5, 3, 3, 0.0, true, true));
fragment_pool.push_back(new G4FermiFragment(1, 0, 1, 0.0));
fragment_pool.push_back(new G4FermiFragment(1, 1, 1, 0.0));
fragment_pool.push_back(new G4FermiFragment(2, 1, 2, 0.0));
fragment_pool.push_back(new G4FermiFragment(3, 1, 1, 0.0));
fragment_pool.push_back(new G4FermiFragment(3, 2, 1, 0.0));
fragment_pool.push_back(new G4FermiFragment(4, 2, 0, 0.0));
fragment_pool.push_back(new G4FermiFragment(5, 2, 3, 0.0));
fragment_pool.push_back(new G4FermiFragment(5, 3, 3, 0.0));
// use level data and construct the pool
G4NuclearLevelData* ndata = G4NuclearLevelData::GetInstance();
@@ -220,82 +159,51 @@ void G4FermiFragmentsPoolVI::Initialise()
G4int Amin = ndata->GetMinA(Z);
G4int Amax = std::min(maxA, ndata->GetMaxA(Z)+1);
for(G4int A=Amin; A<Amax; ++A) {
const G4LevelManager* man = ndata->GetLevelManager(Z, A);
const G4LevelManager* man = ndata->GetLevelManager(Z, A, true);
if(man) {
size_t nn = man->NumberOfTransitions();
// very unstable state
if(ndata->MaxLevelEnergy(Z, A) == 0.0f && man->LifeTime(0) == 0.0f) {
continue;
}
size_t nn = man->NumberOfTransitions();
// very unstable state
if(ndata->MaxLevelEnergy(Z, A) == 0.0f && man->LifeTime(0) == 0.0f) {
continue;
}
for(size_t i=0; i<=nn; ++i) {
G4float exc = man->LevelEnergy(i);
// only levels below limit are consided
/*
G4cout << "Z= " << Z << " A= " << A << " Eex= " << exc
<< " elimf= " << elimf << " toler= " << tolerance
<< " time= " << man->LifeTime(i) << " i= " << i << G4endl;
*/
// only levels below limit are consided
if(exc >= elimf) { continue; }
G4double excd = (G4double)exc;
G4double excd = (G4double)exc;
// only new are considered
if(IsInThePool(Z, A, excd)) { continue; }
G4float ltime = man->LifeTime(i);
G4bool stable = (ltime < 0.0f || ltime > timelim) ? true : false;
//G4cout << "Z= " << Z << " A= " << A << " Eex= " << exc
// << " t= " << ltime << " tlim= " << timelim
// << " stable: "<< stable << G4endl;
fragment_pool.push_back(new G4FermiFragment(A,Z,man->SpinTwo(i),excd,stable,true));
}
if(IsInThePool(Z, A, excd)) { continue; }
fragment_pool.push_back(new G4FermiFragment(A,Z,man->SpinTwo(i),excd));
}
}
}
}
G4int nfrag = fragment_pool.size();
// prepare structures per A for normal fragments
static const size_t lfmax[maxA] = {
const size_t lfmax[maxA] = {
0, 2, 1, 2, 1, 2, 8, 19, 28, 56, 70, 104, 74, 109, 143, 212, 160};
// 0, 2, 1, 2, 1, 2, 6, 14, 16, 22, 45, 53, 37, 44, 33, 58, 63};
for(G4int A=1; A<maxA; ++A) {
list_f[A].reserve(lfmax[A]);
list_c[A].reserve(lfmax[A]);
}
static const size_t lfch[maxA] = {
0, 0, 0, 0, 0, 1, 4, 8, 8, 15, 33, 48, 36, 27, 66, 69, 39};
// 0, 0, 0, 0, 0, 1, 2, 5, 6, 3, 12, 8, 4, 10, 1, 8, 6};
G4int nfrag = fragment_pool.size();
for(G4int i=0; i<nfrag; ++i) {
const G4FermiFragment* f = fragment_pool[i];
const size_t lfch[maxA] = {
0, 0, 0, 0, 0, 1, 4, 8, 6, 13, 27, 40, 29, 21, 31, 32, 30};
for(auto const& f : fragment_pool) {
G4int A = f->GetA();
G4double exc = f->GetExcitationEnergy();
list_f[A].push_back(f);
list_c[A].push_back(new G4FermiChannels(lfch[A], exc, f->GetTotalEnergy()));
}
// list of unphysical fragments
static const size_t lfun[maxA] = {
0, 0, 2, 2, 4, 4, 6, 6, 6, 6, 6, 6, 7, 6, 7, 6, 6};
for(G4int A=1; A<maxA; ++A) {
list_g[A].reserve(lfun[A]);
list_d[A].reserve(lfun[A]);
}
static const size_t luch[maxA] = {
0, 0, 1, 1, 3, 3, 5, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8};
for(G4int Z=0; Z<maxZ; ++Z) {
G4int A0 = std::max(Z, 1);
for(G4int A=A0; A<maxA; ++A) {
if(IsInThePool(Z, A, 0.0)) { continue; }
const G4FermiFragment* f = new G4FermiFragment(A, Z, -1, 0.0, false, false);
funstable.push_back(f);
list_g[A].push_back(f);
list_d[A].push_back(new G4FermiChannels(luch[A],0.0,f->GetTotalEnergy()));
}
}
static const size_t pphm[maxA] = {
0, 0, 2, 2, 4, 4, 6, 6, 6, 6, 6, 6, 7, 6, 7, 6, 6};
static const size_t punm[maxA] = {
0, 0, 2, 2, 8, 10, 22, 24, 24, 31, 35, 36, 44, 36, 44, 36, 36};
for(G4int A=1; A<maxA; ++A) {
list_p[A].reserve(pphm[A]);
list_u[A].reserve(punm[A]);
}
/*
G4cout << "G4FermiFragmentsPoolVI::Initialise main loop @@@@@@"
<< " Nfrag= " << nfrag << " Nuns= " << funstable.size() << G4endl;
/*
G4cout << "Defined fragments @@@@@@"
<< " PhysicalFrag= " << nfrag
<< " UnphysicalFrag= " << funstable.size() << G4endl;
*/
// list of fragment pairs ordered by A
for(G4int i=0; i<nfrag; ++i) {
@@ -311,120 +219,42 @@ void G4FermiFragmentsPoolVI::Initialise()
G4int Z = Z1 + Z2;
G4int A = A1 + A2;
if(Z >= maxZ || A >= maxA ||
IsInPhysPairs(f1, f2) || IsInUnphysPairs(f1, f2)) { continue; }
if(Z >= maxZ || A >= maxA || IsInPhysPairs(f1, f2)) { continue; }
G4double e2 = f2->GetTotalEnergy();
G4double minE = e1 + e2;
G4double exc = 0.0;
if(IsPhysical(Z, A)) {
minE += f1->GetCoulombBarrier(A2, Z2, 0.0);
exc = minE - G4NucleiProperties::GetNuclearMass(A, Z);
minE += f1->GetCoulombBarrier(A2, Z2, 0.0);
exc = minE - G4NucleiProperties::GetNuclearMass(A, Z);
}
/*
G4cout << "Z= " << Z << " A= " << A
<< " Z1= " << Z1 << " A1= " << A1
<< " Z2= " << Z2 << " A2= " << A2 << " Eex= " << exc
<< " Qb= " << f1->GetCoulombBarrier(A2, Z2, 0.0)
<< " " << e1
<< " " << e2
<< " " << G4NucleiProperties::GetNuclearMass(A, Z)
<< G4endl;
G4cout << "Z= " << Z << " A= " << A
<< " Z1= " << Z1 << " A1= " << A1
<< " Z2= " << Z2 << " A2= " << A2 << " Eex= " << exc
<< " Qb= " << f1->GetCoulombBarrier(A2, Z2, 0.0)
<< " " << e1
<< " " << e2
<< " " << G4NucleiProperties::GetNuclearMass(A, Z)
<< G4endl;
*/
// ignore very excited case
if(exc >= elim) { continue; }
G4FermiPair* fpair = nullptr;
G4int kmax = list_f[A].size();
for(G4int k=0; k<kmax; ++k) {
const G4FermiFragment* f3 = (list_f[A])[k];
if(Z == f3->GetZ() &&
f3->GetTotalEnergy() - minE + tolerance >= 0.0) {
if(!fpair) {
fpair = new G4FermiPair(f1, f2);
list_p[A].push_back(fpair);
}
(list_c[A])[k]->AddChannel(fpair);
}
}
if(fpair) { continue; }
kmax = list_g[A].size();
for(G4int k=0; k<kmax; ++k) {
if((list_d[A])[k]->GetNumberOfChannels() >= nmin) { continue; }
const G4FermiFragment* f3 = (list_g[A])[k];
/*
if(Z==0) {
G4cout << "%%% A= " << A << " isStable: " << f3->IsStable()
<< " de= " << f3->GetTotalEnergy() - minE << G4endl;
}
*/
if(Z == f3->GetZ() &&
f3->GetTotalEnergy() - minE + tolerance >= 0.0) {
if(!fpair) {
fpair = new G4FermiPair(f1, f2);
list_u[A].push_back(fpair);
}
(list_d[A])[k]->AddChannel(fpair);
/*
if(Z==0) {
G4cout << " isAdded Unstable" << G4endl;
}
*/
}
const G4FermiFragment* f3 = (list_f[A])[k];
if(Z == f3->GetZ() &&
f3->GetTotalEnergy() - minE + tolerance >= 0.0) {
if(!fpair) {
fpair = new G4FermiPair(f1, f2);
list_p[A].push_back(fpair);
}
(list_c[A])[k]->AddChannel(fpair);
}
}
}
}
// G4cout << "@@@@@@ sec loop @@@@@@" << G4endl;
// list of fragment pairs (stable+unstable) ordered by A
G4int unphys = funstable.size();
for(G4int i=0; i<nfrag; ++i) {
const G4FermiFragment* f1 = fragment_pool[i];
G4int Z1 = f1->GetZ();
G4int A1 = f1->GetA();
G4double e1 = f1->GetTotalEnergy();
for(G4int j=0; j<unphys; ++j) {
const G4FermiFragment* f2 = funstable[j];
G4int Z2 = f2->GetZ();
G4int A2 = f2->GetA();
G4int Z = Z1 + Z2;
G4int A = A1 + A2;
if(Z >= maxZ || A >= maxA || IsInUnphysPairs(f1, f2) || IsPhysical(Z, A))
{ continue; }
G4double e2 = f2->GetTotalEnergy();
G4double minE = e1 + e2;
/*
G4cout << "Z= " << Z << " A= " << A << " Z1= " << Z1 << " A1= " << A1
<< " Z2= " << Z2 << " A2= " << A2 << G4endl;
*/
// check if this is the list of stable pairs
G4FermiPair* fpair = nullptr;
// check unphysics list
G4int kmax = list_g[A].size();
for(G4int k=0; k<kmax; ++k) {
const G4FermiFragment* f3 = (list_g[A])[k];
/*
if(Z == f3->GetZ())
G4cout << " Unst+ST k= " << k << " Z= " << f3->GetZ()
<< " isStab " << f3->IsStable()
<< " Nch= " << (list_d[A])[k]->GetNumberOfChannels()
<< " de= " << f3->GetTotalEnergy() - minE
<< G4endl;
*/
if(Z == f3->GetZ() &&
(list_d[A])[k]->GetNumberOfChannels() < nmin &&
f3->GetTotalEnergy() - minE + tolerance >= 0.0)
{
fpair = new G4FermiPair(f1, f2);
list_u[A].push_back(fpair);
(list_d[A])[k]->AddChannel(fpair);
// G4cout << " isAdded Unstable" << G4endl;
break;
}
}
}
}
// compute static probabilities
for(G4int A=1; A<maxA; ++A) {
for(size_t j=0; j<list_c[A].size(); ++j) {
@@ -432,51 +262,24 @@ void G4FermiFragmentsPoolVI::Initialise()
const G4FermiFragment* frag = (list_f[A])[j];
size_t nch = ch->GetNumberOfChannels();
if(1 < nch) {
std::vector<G4double>& prob = ch->GetProbabilities();
const std::vector<const G4FermiPair*>& pairs = ch->GetChannels();
std::vector<G4double>& prob = ch->GetProbabilities();
const std::vector<const G4FermiPair*>& pairs = ch->GetChannels();
G4double ptot = 0.0;
for(size_t i=0; i<nch; ++i) {
ptot += theDecay.ComputeProbability(frag->GetZ(), frag->GetA(),
frag->GetSpin(),
frag->GetTotalEnergy(),
pairs[i]->GetFragment1(),
pairs[i]->GetFragment2());
ptot += theDecay.ComputeProbability(frag->GetZ(), frag->GetA(),
frag->GetSpin(),
frag->GetTotalEnergy(),
pairs[i]->GetFragment1(),
pairs[i]->GetFragment2());
prob[i] = ptot;
}
}
if(0.0 == ptot) {
prob[0] = 1.0;
} else {
ptot = 1./ptot;
for(size_t i=0; i<nch-1; ++i) { prob[i] *= ptot; }
prob[nch-1] = 1.0;
}
}
}
}
for(G4int A=1; A<maxA; ++A) {
for(size_t j=0; j<list_d[A].size(); ++j) {
G4FermiChannels* ch = (list_d[A])[j];
const G4FermiFragment* frag = (list_g[A])[j];
size_t nch = ch->GetNumberOfChannels();
if(1 < nch) {
std::vector<G4double>& prob = ch->GetProbabilities();
const std::vector<const G4FermiPair*>& pairs = ch->GetChannels();
G4double ptot = 0.0;
for(size_t i=0; i<nch; ++i) {
ptot += theDecay.ComputeProbability(frag->GetZ(), frag->GetA(),
frag->GetSpin(),
frag->GetTotalEnergy(),
pairs[i]->GetFragment1(),
pairs[i]->GetFragment2());
prob[i] = ptot;
}
if(0.0 == ptot) {
prob[0] = 1.0;
} else {
ptot = 1./ptot;
for(size_t i=0; i<nch-1; ++i) { prob[i] *= ptot; }
prob[nch-1] = 1.0;
}
prob[0] = 1.0;
} else {
ptot = 1./ptot;
for(size_t i=0; i<nch-1; ++i) { prob[i] *= ptot; }
prob[nch-1] = 1.0;
}
}
}
}
@@ -487,10 +290,11 @@ void G4FermiFragmentsPoolVI::DumpFragment(const G4FermiFragment* f) const
if(f) {
G4int prec = G4cout.precision(6);
G4cout << " Z= " << f->GetZ() << " A= " << std::setw(2) << f->GetA()
<< " Mass(GeV)= " << std::setw(8) << f->GetFragmentMass()/GeV
<< " Eexc(MeV)= " << std::setw(7) << f->GetExcitationEnergy()
<< " 2s= " << f->GetSpin() << " IsStable: " << f->IsStable()
<< " IsPhys: " << f->IsPhysical() << G4endl;
<< " Mass(GeV)= " << std::setw(8) << f->GetFragmentMass()/GeV
<< " Eexc(MeV)= " << std::setw(7) << f->GetExcitationEnergy()
<< " 2s= " << f->GetSpin() << " IsStable: "
<< HasChannels(f->GetZ(), f->GetA(), f->GetExcitationEnergy())
<< G4endl;
G4cout.precision(prec);
}
}
@@ -498,12 +302,12 @@ void G4FermiFragmentsPoolVI::DumpFragment(const G4FermiFragment* f) const
void G4FermiFragmentsPoolVI::Dump() const
{
G4cout <<"----------------------------------------------------------------"
<<G4endl;
<<G4endl;
G4cout << "##### List of Fragments in the Fermi Fragment Pool #####"
<< G4endl;
<< G4endl;
G4int nfrag = fragment_pool.size();
G4cout << " For stable " << nfrag << " Elim(MeV) = "
<< elim/CLHEP::MeV << G4endl;
<< elim/CLHEP::MeV << G4endl;
for(G4int i=0; i<nfrag; ++i) {
DumpFragment(fragment_pool[i]);
}
@@ -511,7 +315,7 @@ void G4FermiFragmentsPoolVI::Dump() const
G4cout << "----------------------------------------------------------------"
<< G4endl;
<< G4endl;
G4cout << "### G4FermiFragmentPoolVI: fragments sorted by A" << G4endl;
G4int prec = G4cout.precision(6);
@@ -527,22 +331,22 @@ void G4FermiFragmentsPoolVI::Dump() const
size_t nch = (list_c[A])[j]->GetNumberOfChannels();
am = std::max(am, nch);
G4cout << " ("<<a1<<","<<z1<<"); Eex(MeV)= "
<< f->GetExcitationEnergy()
<< " 2S= " << f->GetSpin()
<< "; Nchannels= " << nch
<< " MassExcess= " << f->GetTotalEnergy() -
(z1*proton_mass_c2 + (a1 - z1)*neutron_mass_c2)
<< G4endl;
<< f->GetExcitationEnergy()
<< " 2S= " << f->GetSpin()
<< "; Nchannels= " << nch
<< " MassExcess= " << f->GetTotalEnergy() -
(z1*proton_mass_c2 + (a1 - z1)*neutron_mass_c2)
<< G4endl;
for(size_t k=0; k<nch; ++k) {
const G4FermiPair* fpair = ((list_c[A])[j]->GetChannels())[k];
G4cout << " (" << fpair->GetFragment1()->GetZ()
<< ", " << fpair->GetFragment1()->GetA()
<< ", " << fpair->GetFragment1()->GetExcitationEnergy()
<< ") ("<< fpair->GetFragment2()->GetZ()
<< ", " << std::setw(3)<< fpair->GetFragment2()->GetA()
<< ", " << std::setw(8)<< fpair->GetFragment2()->GetExcitationEnergy()
<< ") prob= " << ((list_c[A])[j]->GetProbabilities())[k]
<< G4endl;
<< ", " << fpair->GetFragment1()->GetA()
<< ", " << fpair->GetFragment1()->GetExcitationEnergy()
<< ") ("<< fpair->GetFragment2()->GetZ()
<< ", " << std::setw(3)<< fpair->GetFragment2()->GetA()
<< ", " << std::setw(8)<< fpair->GetFragment2()->GetExcitationEnergy()
<< ") prob= " << ((list_c[A])[j]->GetProbabilities())[k]
<< G4endl;
}
}
ama[A] = am;
@@ -563,57 +367,7 @@ void G4FermiFragmentsPoolVI::Dump() const
G4cout << G4endl;
G4cout << "----------------------------------------------------------------"
<< G4endl;
G4cout << "### G4FermiFragmentPoolVI: " << funstable.size()
<< " unphysical fragments" << G4endl;
G4cout << " Number of unphysical fragments per A:" << G4endl;
for(G4int j=0; j<maxA; ++j) { G4cout << list_g[j].size() << ", "; }
G4cout << G4endl;
G4cout << " Number of unphysical fragment pairs per A:" << G4endl;
for(G4int j=0; j<maxA; ++j) { G4cout << list_u[j].size() << ", "; }
G4cout << G4endl;
prec = G4cout.precision(6);
for(G4int A=1; A<maxA; ++A) {
G4cout << " # A= " << A << G4endl;
size_t am(0);
for(size_t j=0; j<list_g[A].size(); ++j) {
const G4FermiFragment* f = (list_g[A])[j];
G4int a1 = f->GetA();
G4int z1 = f->GetZ();
size_t nch = (list_d[A])[j]->GetNumberOfChannels();
am = std::max(am, nch);
G4cout << "("<<a1<<","<<z1<<"); Eex(MeV)= "
<< std::setw(8) << f->GetExcitationEnergy()
<< "; Nchannels= " << nch
<< " MassExcess= " << f->GetTotalEnergy() -
(z1*proton_mass_c2 + (a1 - z1)*neutron_mass_c2)
<< G4endl;
for(size_t k=0; k<nch; ++k) {
const G4FermiPair* fpair = ((list_d[A])[j]->GetChannels())[k];
G4cout << " (" << fpair->GetFragment1()->GetZ()
<< ", " << fpair->GetFragment1()->GetA()
<< ", " << std::setw(8)<< fpair->GetFragment1()->GetExcitationEnergy()
<< ") ("<< fpair->GetFragment2()->GetZ()
<< ", " << std::setw(3)<< fpair->GetFragment2()->GetA()
<< ", " << std::setw(8)<< fpair->GetFragment2()->GetExcitationEnergy()
<< ") prob= " << ((list_d[A])[j]->GetProbabilities())[k]
<< G4endl;
}
}
ama[A] = am;
G4cout << G4endl;
}
G4cout.precision(prec);
G4cout << G4endl;
G4cout << " Max number of unphysical channels per A:" << G4endl;
for (size_t j=0; j<maxA; ++j) { G4cout << ama[j] << ", "; }
G4cout << G4endl;
G4cout << "----------------------------------------------------------------"
<< G4endl;
G4cout << G4endl;
<< G4endl;
G4cout << "### Pairs of stable fragments: " << G4endl;
prec = G4cout.precision(6);
@@ -627,37 +381,14 @@ void G4FermiFragmentsPoolVI::Dump() const
G4int a2 = f2->GetA();
G4int z2 = f2->GetZ();
G4cout << "("<<a1<<","<<z1<<")("<<a2<<","<<z2<<") % Eex(MeV)= "
<< std::setw(8)<< (list_p[A])[j]->GetExcitationEnergy()
<< std::setw(8)<< (list_p[A])[j]->GetExcitationEnergy()
<< " Eex1= " << std::setw(8)<< f1->GetExcitationEnergy()
<< " Eex2= " << std::setw(8)<< f2->GetExcitationEnergy()
<< G4endl;
<< G4endl;
}
G4cout << G4endl;
G4cout <<"----------------------------------------------------------------"
<< G4endl;
}
G4cout.precision(prec);
G4cout << "### Pairs of stable+unstable fragments: " << G4endl;
prec = G4cout.precision(6);
for(G4int A=2; A<maxA; ++A) {
G4cout << " A= " << A << G4endl;
for(size_t j=0; j<list_u[A].size(); ++j) {
const G4FermiFragment* f1 = (list_u[A])[j]->GetFragment1();
const G4FermiFragment* f2 = (list_u[A])[j]->GetFragment2();
G4int a1 = f1->GetA();
G4int z1 = f1->GetZ();
G4int a2 = f2->GetA();
G4int z2 = f2->GetZ();
G4cout << "("<<a1<<","<<z1<<")("<<a2<<","<<z2<<") % Eex(MeV)= "
<< std::setw(8)<< (list_u[A])[j]->GetExcitationEnergy()
<< " Eex1= " << std::setw(8)<< f1->GetExcitationEnergy()
<< " Eex2= " << std::setw(8)<< f2->GetExcitationEnergy()
<< G4endl;
}
G4cout << G4endl;
G4cout << "----------------------------------------------------------------"
<< G4endl;
<< G4endl;
}
G4cout.precision(prec);
}

Some files were not shown because too many files have changed in this diff Show More