Import Geant4 11.3.1 source tree

This commit is contained in:
Gabriele Cosmo
2025-03-24 16:45:22 +01:00
parent 32390e802b
commit df176550b3
388 changed files with 29491 additions and 29435 deletions
+5
View File
@@ -6,6 +6,11 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-03-25 Ivana Hrivnacova (proccuts-V11-02-00)
- In G4ProductionCutsTable::UpdateCoupleTable:
Make sure that the couple tables are updated if userEnergyCuts
vectors are set
## 2023-10-24 Ivana Hrivnacova (proccuts-V11-01-01)
- G4ProductionCutsTable - Added method CreateCoupleTables()
separated from UpdateCoupleTable() needed to prepare
@@ -270,6 +270,15 @@ void G4ProductionCutsTable::UpdateCoupleTable(G4VPhysicalVolume* /*currWorld*/)
firstUse = false;
}
// Force update of coupleTable if userEnergyCuts vectors are set
G4bool isRecalcNeeded = false;
for (const auto* userVector : userEnergyCuts) {
if (userVector != nullptr) {
isRecalcNeeded = true;
break;
}
}
// Update RangeEnergy cuts tables
std::size_t idx = 0;
G4Timer timer;
@@ -281,7 +290,7 @@ void G4ProductionCutsTable::UpdateCoupleTable(G4VPhysicalVolume* /*currWorld*/)
{
G4ProductionCuts* aCut = (*cItr)->GetProductionCuts();
const G4Material* aMat = (*cItr)->GetMaterial();
if((*cItr)->IsRecalcNeeded())
if((*cItr)->IsRecalcNeeded() || isRecalcNeeded)
{
for(std::size_t ptcl=0; ptcl< NumberOfG4CutIndex; ++ptcl)
{
@@ -6,6 +6,9 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-01-14 Ben Morgan (emdna-V11-02-18)
- Remove obsolete/commented references to G4AllocatorList.
## 2024-10-31 Hoang Tran (emdna-V11-02-17)
- missing value in DNA PTB Ionization Structure;
- missing GetMaterial() in DNA PTB Excitation and Elastic models (PR#78,by mjpietrzak)
@@ -48,7 +48,6 @@
#include "G4FastList.hh"
#include "G4ManyFastLists.hh"
#include "G4AllocatorList.hh"
#include "G4Track.hh"
#include "G4IT.hh"
@@ -64,8 +64,6 @@ G4FastListNode<G4Track>* G4FastList<G4Track>::__GetNode(G4Track* __track)
template<>
void G4FastList<G4Track>::DeleteObject(G4Track* __track)
{
if (G4AllocatorList::GetAllocatorListIfExist() == nullptr) return;
auto __step = const_cast<G4Step*>(__track->GetStep());
if (__step != nullptr)
{
@@ -35,7 +35,6 @@
#include "G4MolecularConfiguration.hh"
#include "G4MoleculeDefinition.hh"
#include "G4UIcommand.hh"
#include "G4AllocatorList.hh"
#include "G4AutoLock.hh"
#include "G4MoleculeTable.hh"
#include "G4Serialize.hh"
@@ -147,10 +146,6 @@ G4MolecularConfiguration::GetManager()
G4MolecularConfiguration::
G4MolecularConfigurationManager::~G4MolecularConfigurationManager()
{
// G4cout << "Does G4AllocatorList exists= ";
// G4cout << (G4AllocatorList::GetAllocatorListIfExist() ? "true":"false")
// << G4endl;
G4MolecularConfigurationManager::MolElectronConfTable::iterator it1;
G4MolecularConfigurationManager::ElectronOccupancyTable::
iterator it2;
@@ -507,15 +502,6 @@ G4MolecularConfiguration(const G4MoleculeDefinition* moleculeDef,
G4MolecularConfiguration::~G4MolecularConfiguration()
{
if (fgManager != nullptr) fgManager->RemoveMolecularConfigurationFromTable(this);
// if (G4AllocatorList::GetAllocatorListIfExist())
// {
// if (fElectronOccupancy)
// {
// delete fElectronOccupancy;
// fElectronOccupancy = 0;
// }
// }
}
//______________________________________________________________________________
@@ -6,6 +6,13 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-02-07 L. Pandola (emlowen-V11-02-08)
- Fix residual Coverity defect on G4ShellData
## 2025-01-09 L. Pandola
- Fix Coverity warnings in Penenelope models, G4ShellData, G4FluoData and
G4AugerTransition
## 2024-12-02 A. Ribon (emlowen-V11-02-07)
- G4UAtomicDeexcitation : clear vector (vacancyArray) in the method
G4UAtomicDeexcitation::GenerateParticles, to avoid rare non-reproducibility
@@ -64,10 +64,16 @@ G4AugerTransition::~G4AugerTransition()
const std::vector<G4int>* G4AugerTransition::AugerOriginatingShellIds(G4int startShellId) const
{
auto shellId = augerOriginatingShellIdsMap.find(startShellId);
if (shellId == augerOriginatingShellIdsMap.end())
{
G4Exception("G4AugerTransition::AugerOriginatingShellIds()",
"em2199",JustWarning,"Error: no Auger ID found");
return nullptr;
}
const std::vector<G4int>* dataSet = &(*shellId).second;
if (dataSet->empty())
G4cout << "Error: no auger Id found"<< G4endl;
G4Exception("G4AugerTransition::AugerOriginatingShellIds()",
"em2198",JustWarning,"Error: no Auger ID found");
return dataSet;
}
@@ -157,13 +157,15 @@ G4double G4FluoData::StartShellEnergy(G4int initIndex, G4int vacancyIndex) const
else
{
auto pos = energyMap.find(vacancyIndex);
G4DataVector dataSet = *((*pos).second);
G4int nData = (G4int)dataSet.size();
if (initIndex >= 0 && initIndex < nData)
if (pos != energyMap.end())
{
n = dataSet[initIndex];
G4DataVector dataSet = *((*pos).second);
G4int nData = (G4int)dataSet.size();
if (initIndex >= 0 && initIndex < nData)
{
n = dataSet[initIndex];
}
}
}
return n;
@@ -184,13 +186,15 @@ G4double G4FluoData::StartShellProb(G4int initIndex, G4int vacancyIndex) const
else
{
auto pos = probabilityMap.find(vacancyIndex);
G4DataVector dataSet = *((*pos).second);
G4int nData = (G4int)dataSet.size();
if (initIndex >= 0 && initIndex < nData)
if (pos != probabilityMap.end())
{
n = dataSet[initIndex];
G4DataVector dataSet = *((*pos).second);
G4int nData = (G4int)dataSet.size();
if (initIndex >= 0 && initIndex < nData)
{
n = dataSet[initIndex];
}
}
}
return n;
@@ -497,7 +497,8 @@ G4double G4PenelopeBremsstrahlungAngular::CalculateEffectiveZ(const G4Material*
}
//Normalize
for (G4int i=0;i<nElements;++i)
(*StechiometricFactors)[i] /= MaxStechiometricFactor;
if (MaxStechiometricFactor > 0.)
(*StechiometricFactors)[i] /= MaxStechiometricFactor;
G4double sumz2 = 0;
G4double sums = 0;
@@ -509,7 +510,7 @@ G4double G4PenelopeBremsstrahlungAngular::CalculateEffectiveZ(const G4Material*
}
delete StechiometricFactors;
G4double ZBR = std::sqrt(sumz2/sums);
G4double ZBR = (sums > 0.) ? std::sqrt(sumz2/sums) : 0.;
fEffectiveZSq->insert(std::make_pair(material,ZBR));
return ZBR;
@@ -232,7 +232,8 @@ void G4PenelopeBremsstrahlungFS::BuildScaledXSTable(const G4Material* material,
}
//Normalize
for (std::size_t i=0;i<nElements;i++)
(*StechiometricFactors)[i] /= MaxStechiometricFactor;
if (MaxStechiometricFactor > 0.)
(*StechiometricFactors)[i] /= MaxStechiometricFactor;
G4double sumz2 = 0;
G4double sums = 0;
@@ -604,14 +605,14 @@ G4double G4PenelopeBremsstrahlungFS::SampleGammaEnergy(G4double energy,const G4M
const G4double cut) const
{
std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
if (!(fSamplingTable->count(theKey)) || !(fPBcut->count(theKey)))
if (!(fSamplingTable->count(theKey)) || !(fPBcut->count(theKey)) ||
!(fReducedXSTable->count(theKey)))
{
G4ExceptionDescription ed;
ed << "Unable to retrieve the SamplingTable: " <<
fSamplingTable->count(theKey) << " " <<
fPBcut->count(theKey) << G4endl;
ed << "Unable to retrieve the SamplingTable for " << mat->GetName() << G4endl;
G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()",
"em2014",FatalException,ed);
return 0.;
}
const G4PhysicsTable* theTableInte = fSamplingTable->find(theKey)->second;
const G4PhysicsTable* theTableRed = fReducedXSTable->find(theKey)->second;
@@ -257,7 +257,8 @@ G4double G4PenelopeBremsstrahlungModel::CrossSectionPerVolume(const G4Material*
{
G4cout << "G4PenelopeBremsstrahlungModel " << G4endl;
G4cout << "Mean free path for gamma emission > " << cutEnergy/keV << " keV at " <<
energy/keV << " keV = " << (1./crossPerVolume)/mm << " mm" << G4endl;
energy/keV << " keV = " <<
(crossPerVolume? (1./crossPerVolume)/mm : DBL_MAX) << " mm" << G4endl;
}
return crossPerVolume;
@@ -236,7 +236,8 @@ G4double G4PenelopeComptonModel::CrossSectionPerVolume(const G4Material* materia
if (fVerboseLevel > 2)
G4cout << "Compton mean free path at " << energy/keV << " keV for material " <<
material->GetName() << " = " << (1./csvolume)/mm << " mm" << G4endl;
material->GetName() << " = " <<
(csvolume ? (1./csvolume)/mm : DBL_MAX) << " mm" << G4endl;
return csvolume;
}
@@ -323,11 +323,13 @@ G4double G4PenelopeIonisationModel::CrossSectionPerVolume(const G4Material* mate
{
G4cout << "G4PenelopeIonisationModel " << G4endl;
G4cout << "Mean free path for delta emission > " << cutEnergy/keV << " keV at " <<
energy/keV << " keV = " << (1./crossPerVolume)/mm << " mm" << G4endl;
energy/keV << " keV = " <<
(crossPerVolume ? (1./crossPerVolume)/mm : DBL_MAX) << " mm" << G4endl;
if (theXS)
totalCross = (theXS->GetTotalCrossSection(energy))*moleculeDensity;
G4cout << "Total free path for ionisation (no threshold) at " <<
energy/keV << " keV = " << (1./totalCross)/mm << " mm" << G4endl;
energy/keV << " keV = " <<
(totalCross ? (1./totalCross)/mm : DBL_MAX) << " mm" << G4endl;
}
return crossPerVolume;
}
@@ -493,7 +493,8 @@ G4double G4PenelopeRayleighModelMI::CrossSectionPerVolume(const G4Material* mate
MaxStoichiometricFactor = (*StoichiometricFactors)[i];
}
for (std::size_t i=0;i<nElements;++i) {
(*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
if (MaxStoichiometricFactor > 0.)
(*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
}
//Equivalent atoms per molecule
@@ -192,31 +192,38 @@ void G4ShellData::PrintData() const
auto posId = idMap.find(Z);
std::vector<G4double>* ids = (*posId).second;
auto posE = bindingMap.find(Z);
G4DataVector* energies = (*posE).second;
for (G4int i=0; i<nSh; ++i)
if (posE != bindingMap.end())
{
G4int id = (G4int) (*ids)[i];
G4double e = (*energies)[i] / keV;
G4cout << i << ") ";
G4DataVector* energies = (*posE).second;
for (G4int i=0; i<nSh; ++i)
{
G4int id = (G4int) (*ids)[i];
G4double e = (*energies)[i] / keV;
G4cout << i << ") ";
if (occupancyData)
{
G4cout << " Occupancy: ";
if (occupancyData)
{
G4cout << " Occupancy: ";
}
else
{
G4cout << " Shell id: ";
}
G4cout << id << " - Binding energy = "
<< e << " keV ";
if (occupancyData)
{
auto posOcc = occupancyPdfMap.find(Z);
G4double prob = 0.;
if (posOcc != occupancyPdfMap.end())
{
std::vector<G4double> probs = *((*posOcc).second);
prob = probs[i];
}
G4cout << "- Probability = " << prob;
}
G4cout << G4endl;
}
else
{
G4cout << " Shell id: ";
}
G4cout << id << " - Binding energy = "
<< e << " keV ";
if (occupancyData)
{
auto posOcc = occupancyPdfMap.find(Z);
std::vector<G4double> probs = *((*posOcc).second);
G4double prob = probs[i];
G4cout << "- Probability = " << prob;
}
G4cout << G4endl;
}
G4cout << "-------------------------------------------------"
<< G4endl;
@@ -6,6 +6,10 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-02-07 Igor Semeniouk (emstand-V11-02-22)
- G4OrePowellAtRestModel - Add missing decay plane rotation
( random x axis phi )
## 2024-11-08 V.Ivanchenko (emstand-V11-02-21)
- G4BraggModel - fixed problem of 4.12 MeV mu+ range reported in
the Forum #12312.
@@ -103,6 +103,13 @@ void G4OrePowellAtRestModel::SampleSecondaries(
G4ThreeVector PhotonMomentum2(0.,sin12,cos12);
G4ThreeVector PhotonMomentum3(0.,sin13,cos13);
// Random x direction ( rotate decay plane along Z axis)
G4double phi = CLHEP::twopi * G4UniformRand();
PhotonMomentum2.rotateZ(phi);
PhotonMomentum3.rotateZ(phi);
// First Gamma direction
G4ThreeVector dir1 = G4RandomDirection();
@@ -6,6 +6,10 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-12-22 Vladimir Ivanchenko (hadr-deex-V11-02-19)
- G4ExcitationHandler, G4GammaTransition, G4PhotonEvaporation fixed problem
#2584 - removed production of unphysical states
## 2024-10-29 Vladimir Ivanchenko (hadr-deex-V11-02-18)
- G4LevelReader - reduced printouts on problems in nuclear level data
- G4PolarizationTransition - use optimized G4LegendrePolinomial from
@@ -383,7 +383,7 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
}
// In case A <= 1 the fragment will not perform any nucleon emission
if (A <= 1 || !isActive) {
if (A <= 1 || !isActive || theInitialStatePtr->IsLongLived()) {
theResults.push_back( theInitialStatePtr );
// check if a fragment is stable
@@ -435,7 +435,7 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
std::size_t kk;
for (kk=0; kk<theEvapList.size(); ++kk) {
G4Fragment* frag = theEvapList[kk];
if (fVerbose > 3) {
if (fVerbose > 3) {
G4cout << "Next evaporate: " << G4endl;
G4cout << *frag << G4endl;
}
@@ -475,8 +475,13 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
// apply Evaporation, residual nucleus is always added to the results
// photon evaporation is possible
theEvaporation->BreakFragment(&results, frag);
if (fVerbose > 3) {
G4cout << "Evaporation Nsec= " << results.size() << G4endl;
if (fVerbose > 3) {
G4cout << kk << ". Evaporation: Nsec=" << results.size()
<< " Z=" << frag->GetZ_asInt()
<< " A=" << frag->GetA_asInt()
<< " Eex=" << frag->GetExcitationEnergy()
<< " stable=" << frag->IsLongLived()
<< G4endl;
}
if (0 == results.size()) {
theResults.push_back(frag);
@@ -120,7 +120,6 @@ private:
G4int theZ{0};
G4int theA{0};
G4int fPoints{0};
G4int fCode{0};
G4int vShellNumber{-1};
G4int MAXDEPOINT{10};
std::size_t fIndex{0};
@@ -132,7 +131,8 @@ private:
G4double fProbability{0.0};
G4double fStep{0.0};
G4double fMaxLifeTime{DBL_MAX};
G4double fLocalTimeLimit{DBL_MAX};
G4double fTolerance;
G4bool fICM{true};
@@ -161,7 +161,7 @@ G4PhotonEvaporation::InitialiseLevelManager(G4int Z, G4int A)
theA = A;
fIndex = 0;
fLevelManager = fNuclearLevelData->GetLevelManager(theZ, theA);
fLevelEnergyMax = fLevelManager ? fLevelManager->MaxLevelEnergy() : 0.0;
fLevelEnergyMax = (nullptr != fLevelManager) ? fLevelManager->MaxLevelEnergy() : 0.0;
}
}
@@ -89,6 +89,8 @@ G4GammaTransition::SampleTransition(G4Fragment* nucleus,
// Do complete Lorentz computation
G4LorentzVector lv = nucleus->GetMomentum();
// final mass
G4double mass = nucleus->GetGroundStateMass() + newExcEnergy;
// select secondary
@@ -110,8 +112,11 @@ G4GammaTransition::SampleTransition(G4Fragment* nucleus,
G4double emass = part->GetPDGMass();
// 2-body decay in rest frame
G4double ecm = lv.mag();
G4ThreeVector bst = lv.boostVector();
G4double ecm = lv.mag();
const G4double elim2 = 100.*CLHEP::eV*CLHEP::eV;
G4bool atRest = (lv.vect().mag2() < elim2);
G4ThreeVector bst(0.0, 0.0, 0.0);
if (!atRest) { bst = lv.boostVector(); }
if(!isGamma) { ecm += (CLHEP::electron_mass_c2 - bond_energy); }
//G4cout << "Ecm= " << ecm << " mass= " << mass << " emass= " << emass << G4endl;
@@ -127,16 +132,19 @@ G4GammaTransition::SampleTransition(G4Fragment* nucleus,
mom * fDirection.z(), energy);
// residual
energy = std::max(ecm - energy, mass);
mom = std::sqrt(energy*energy - mass*mass);
lv.set(-mom*fDirection.x(), -mom*fDirection.y(), -mom*fDirection.z(), energy);
// Lab system transform for short lived level
lv.boost(bst);
if (!atRest) {
lv.boost(bst);
res4mom.boost(bst);
}
// modified primary fragment
nucleus->SetExcEnergyAndMomentum(newExcEnergy, lv);
// gamma or e- are produced
res4mom.boost(bst);
result = new G4Fragment(res4mom, part);
//G4cout << " DeltaE= " << e0 - lv.e() - res4mom.e() + emass
@@ -50,14 +50,14 @@
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"
#include "G4PhysicsModelCatalog.hh"
#include "G4AutoLock.hh"
G4float G4PhotonEvaporation::GREnergy[] = {0.0f};
G4float G4PhotonEvaporation::GRWidth[] = {0.0f};
namespace
{
G4Mutex photEvaporationMutex = G4MUTEX_INITIALIZER;
constexpr G4double timeLimit = 10*CLHEP::ns;
constexpr G4double eLimit = 200*CLHEP::keV;
}
G4PhotonEvaporation::G4PhotonEvaporation(G4GammaTransition* p)
@@ -68,7 +68,7 @@ G4PhotonEvaporation::G4PhotonEvaporation(G4GammaTransition* p)
}
fNuclearLevelData = G4NuclearLevelData::GetInstance();
fTolerance = 20*CLHEP::eV;
fCummProbability[0] = 0.0;
if(nullptr == fTransition) { fTransition = new G4GammaTransition(); }
fSecID = G4PhysicsModelCatalog::GetModelID("model_G4PhotonEvaporation");
@@ -89,6 +89,7 @@ void G4PhotonEvaporation::Initialise()
G4DeexPrecoParameters* param = fNuclearLevelData->GetParameters();
fTolerance = param->GetMinExcitation();
fMaxLifeTime = param->GetMaxLifeTime();
fLocalTimeLimit = fRDM ? fMaxLifeTime : std::max(fMaxLifeTime, timeLimit);
fCorrelatedGamma = param->CorrelatedGamma();
fICM = param->GetInternalConversionFlag();
fVerbose = param->GetVerbose();
@@ -103,7 +104,6 @@ void G4PhotonEvaporation::Initialise()
void G4PhotonEvaporation::InitialiseGRData()
{
G4AutoLock l(&photEvaporationMutex);
if(0.0f == GREnergy[2]) {
G4Pow* g4calc = G4Pow::GetInstance();
const G4float GRWfactor = 0.3f;
@@ -112,7 +112,6 @@ void G4PhotonEvaporation::InitialiseGRData()
GRWidth[A] = GRWfactor*GREnergy[A];
}
}
l.unlock();
}
G4Fragment*
@@ -138,7 +137,7 @@ G4PhotonEvaporation::EmittedFragment(G4Fragment* nucleus)
if(fVerbose > 2) {
G4cout << "G4PhotonEvaporation::EmittedFragment: "
<< *nucleus << G4endl;
if(fPolarization) { G4cout << "NucPolar: " << fPolarization << G4endl; }
if (nullptr != fPolarization) { G4cout << "NucPolar: " << fPolarization << G4endl; }
G4cout << " CorrGamma: " << fCorrelatedGamma << " RDM: " << fRDM
<< " fPolarization: " << fPolarization << G4endl;
}
@@ -147,7 +146,7 @@ G4PhotonEvaporation::EmittedFragment(G4Fragment* nucleus)
if(gamma != nullptr) { gamma->SetCreatorModelID(fSecID); }
// remove G4NuclearPolarizaton when reach ground state
if(fNucPStore && fPolarization && 0 == fIndex) {
if (nullptr != fNucPStore && nullptr != fPolarization && 0 == fIndex) {
if(fVerbose > 3) {
G4cout << "G4PhotonEvaporation::EmittedFragment: remove "
<< fPolarization << G4endl;
@@ -201,19 +200,20 @@ G4bool G4PhotonEvaporation::BreakUpChain(G4FragmentVector* products,
do {
gamma = GenerateGamma(nucleus);
if(gamma) {
if (nullptr != gamma) {
gamma->SetCreatorModelID(fSecID);
products->push_back(gamma);
if(fVerbose > 2) {
G4cout << "G4PhotonEvaporation::BreakUpChain: "
<< *gamma << G4endl;
G4cout << " Residual: " << *nucleus << G4endl;
}
// for next decays in the chain always sample time
fSampleTime = true;
}
// Loop checking, 05-Aug-2015, Vladimir Ivanchenko
} while(gamma);
}
// for next decays in the chain always sample time
fSampleTime = true;
if (fVerbose > 2) {
G4cout << "G4PhotonEvaporation::BreakUpChain: next decay" << G4endl;
if (nullptr != gamma) { G4cout << " " << *gamma << G4endl; }
else { G4cout << " not possible" << G4endl; }
G4cout << " Residual: " << *nucleus << G4endl;
}
// Loop checking, 22-Dec-2024, Vladimir Ivanchenko
} while (!(nucleus->IsLongLived() || nucleus->GetExcitationEnergy() <= fTolerance));
// clear nuclear polarization end of chain
if(nullptr != fPolarization) {
@@ -232,7 +232,6 @@ G4PhotonEvaporation::GetEmissionProbability(G4Fragment* nucleus)
fExcEnergy = nucleus->GetExcitationEnergy();
G4int Z = nucleus->GetZ_asInt();
G4int A = nucleus->GetA_asInt();
fCode = 1000*Z + A;
if(fVerbose > 2) {
G4cout << "G4PhotonEvaporation::GetEmissionProbability: Z="
<< Z << " A=" << A << " Eexc(MeV)= " << fExcEnergy << G4endl;
@@ -244,54 +243,60 @@ G4PhotonEvaporation::GetEmissionProbability(G4Fragment* nucleus)
// ignore gamma de-excitation for highly excited levels
if(A >= MAXGRDATA) { A = MAXGRDATA-1; }
//G4cout<<" GREnergy= "<< GREnergy[A]<<" GRWidth= "<<GRWidth[A]<<G4endl;
static const G4float GREfactor = 5.0f;
if(fExcEnergy >= (G4double)(GREfactor*GRWidth[A] + GREnergy[A])) {
G4double edelta = (G4double)(GREfactor*GRWidth[A] + GREnergy[A]);
if (fVerbose > 2)
G4cout << " GREnergy=" << GREnergy[A] << " GRWidth="<<GRWidth[A]
<< " Edelta=" << edelta <<G4endl;
if (fExcEnergy >= edelta) {
return fProbability;
}
// probability computed assuming continium transitions
// VI: continium transition are limited only to final states
// below Fermi energy (this approach needs further evaluation)
G4double emax = std::max(0.0, nucleus->ComputeGroundStateMass(Z, A-1)
+ CLHEP::neutron_mass_c2 - nucleus->GetGroundStateMass());
// max energy level for continues transition
emax = std::min(emax, fExcEnergy);
const G4double eexcfac = 0.99;
if(0.0 == emax || fExcEnergy*eexcfac <= emax) { emax = fExcEnergy*eexcfac; }
fStep = emax;
// probability computed assuming continium transitions in the frame of the nucleus
fStep = fExcEnergy;
const G4double MaxDeltaEnergy = CLHEP::MeV;
fPoints = std::min((G4int)(fStep/MaxDeltaEnergy) + 2, MAXDEPOINT);
fStep /= ((G4double)(fPoints - 1));
if(fVerbose > 2) {
G4cout << "Emax= " << emax << " Npoints= " << fPoints
<< " Eex= " << fExcEnergy << G4endl;
G4cout << " Npoints= " << fPoints
<< " Eex=" << fExcEnergy << " Estep=" << fStep << G4endl;
}
// integrate probabilities
G4double eres = (G4double)GREnergy[A];
G4double wres = (G4double)GRWidth[A];
G4double eres2= eres*eres;
G4double wres2= wres*wres;
G4double levelDensity = fNuclearLevelData->GetLevelDensity(Z,A,fExcEnergy);
G4double xsqr = std::sqrt(levelDensity*fExcEnergy);
// initial state
G4double levelDensity = fNuclearLevelData->GetLevelDensity(Z,A,fExcEnergy);
G4double xdrt = G4Exp(2*std::sqrt(levelDensity*fExcEnergy));
// the loop over excitation energy of the residual nucleus
// from 0 to fExcEnergy
// gamma energy is defined via non-relativistic formula
G4double egam = fExcEnergy;
G4double gammaE2 = egam*egam;
G4double gammaR2 = gammaE2*wres2;
G4double egdp2 = gammaE2 - eres2;
G4double p0 = G4Exp(-2.0*xsqr)*gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
G4double p1(0.0);
G4double p0 = egam*gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
G4double p1, e;
for(G4int i=1; i<fPoints; ++i) {
egam -= fStep;
gammaE2 = egam*egam;
gammaR2 = gammaE2*wres2;
egdp2 = gammaE2 - eres2;
p1 = G4Exp(2.0*(std::sqrt(levelDensity*std::abs(fExcEnergy - egam)) - xsqr))
*gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
if (i + 1 == fPoints) {
p1 = 0.0;
} else {
gammaE2 = egam*egam;
gammaR2 = gammaE2*wres2;
egdp2 = gammaE2 - eres2;
e = fExcEnergy - egam;
levelDensity = fNuclearLevelData->GetLevelDensity(Z, A, e);
p1 = egam*G4Exp(2.0*(std::sqrt(levelDensity*e)))*gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
}
fProbability += (p1 + p0);
fCummProbability[i] = fProbability;
if(fVerbose > 3) {
@@ -304,7 +309,7 @@ G4PhotonEvaporation::GetEmissionProbability(G4Fragment* nucleus)
static const G4double NormC = 1.25*CLHEP::millibarn
/(CLHEP::pi2*CLHEP::hbarc*CLHEP::hbarc);
fProbability *= fStep*NormC*A;
fProbability *= fStep*NormC*A/xdrt;
if(fVerbose > 1) { G4cout << "prob= " << fProbability << G4endl; }
return fProbability;
}
@@ -326,7 +331,7 @@ G4PhotonEvaporation::GetFinalLevelEnergy(G4int Z, G4int A, G4double energy)
{
G4double E = energy;
InitialiseLevelManager(Z, A);
if(fLevelManager) {
if (nullptr != fLevelManager) {
E = fLevelManager->NearestLevelEnergy(energy, fIndex);
if(E > fLevelEnergyMax + fTolerance) { E = energy; }
}
@@ -344,14 +349,20 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
{
if(!isInitialised) { Initialise(); }
G4Fragment* result = nullptr;
G4double eexc = nucleus->GetExcitationEnergy();
if(eexc <= fTolerance) { return result; }
// initial level
G4double eexc = nucleus->GetExcitationEnergy();
InitialiseLevelManager(nucleus->GetZ_asInt(), nucleus->GetA_asInt());
nucleus->SetLongLived(false);
// long life time flag - "true" for a fragment, which will be tracked
G4bool isLL = false;
// lifetime of the fragment
G4double ltime = 0.0;
fExcEnergy = eexc;
// index is unknown - default is the ground state
fIndex = 0;
G4double time = nucleus->GetCreationTime();
G4double elevel = eexc;
G4double efinal = 0.0;
G4double ratio = 0.0;
vShellNumber = -1;
@@ -360,69 +371,82 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
G4int multiP = 0;
G4bool isGamma = true;
G4bool isDiscrete = false;
G4bool finalDiscrete = false;
const G4NucLevel* level = nullptr;
std::size_t ntrans = 0;
if(fVerbose > 2) {
G4cout << "GenerateGamma: " << " Eex= " << eexc
G4cout << "## GenerateGamma: Z=" << theZ << " A=" << theA << " Eex= " << eexc
<< " Eexmax= " << fLevelEnergyMax << G4endl;
}
// initial discrete state
if(nullptr != fLevelManager && eexc <= fLevelEnergyMax + fTolerance) {
// initial discrete state is ground level
if (eexc <= fTolerance) {
isDiscrete = true;
// initial state may be a discrete level
} else if (nullptr != fLevelManager && eexc <= fLevelEnergyMax + fTolerance) {
fIndex = fLevelManager->NearestLevelIndex(eexc);
G4double elevel = fLevelManager->LevelEnergy(fIndex);
elevel = fLevelManager->LevelEnergy(fIndex);
isDiscrete = (std::abs(elevel - eexc) < fTolerance);
if(fVerbose > 2) {
G4cout << " index= " << fIndex
<< " lTime= " << fLevelManager->LifeTime(fIndex) << G4endl;
G4cout << " Level index=" << fIndex
<< " lTime=" << fLevelManager->LifeTime(fIndex)
<< " Elevel=" << elevel
<< " isDiscrete:" << isDiscrete << G4endl;
}
if(isDiscrete && 0 < fIndex) {
// for discrete transition
level = fLevelManager->GetLevel(fIndex);
if(nullptr != level) {
if(fVerbose > 2) {
G4cout << " ntrans= " << ntrans << " JP= " << JP1
<< " RDM: " << fRDM << G4endl;
}
ntrans = level->NumberOfTransitions();
G4int idxfl = fLevelManager->FloatingLevel(fIndex);
// for floating level check levels with the same energy
if(fLevelManager->FloatingLevel(fIndex) > 0 && 0 == ntrans &&
std::abs(elevel - fLevelManager->LevelEnergy(fIndex-1)) < fTolerance) {
if (idxfl > 0) {
auto newlevel = fLevelManager->GetLevel(fIndex-1);
if(nullptr != newlevel && newlevel->NumberOfTransitions() > 0) {
--fIndex;
level = newlevel;
ntrans = level->NumberOfTransitions();
G4double newenergy = fLevelManager->LevelEnergy(fIndex-1);
if (nullptr != newlevel && std::abs(elevel - newenergy) < fTolerance) {
std::size_t newntrans = newlevel->NumberOfTransitions();
if (newntrans > 0) {
--fIndex;
level = newlevel;
elevel = newenergy;
ntrans = newntrans;
}
}
}
JP1 = std::abs(fLevelManager->TwoSpinParity(fIndex));
if(fVerbose > 2) {
G4cout << " ntrans= " << ntrans << " JP= " << JP1
<< " RDM: " << fRDM << G4endl;
}
}
}
// if a level has no defined transitions
if (0 == ntrans) {
isDiscrete = false;
// if a level has no defined transitions
if (0 == ntrans) {
isDiscrete = false;
}
// transition from continues spectrum to the ground state
} else if (0 == fIndex) {
isDiscrete = true;
}
}
if(fVerbose > 2) {
G4long prec = G4cout.precision(4);
G4cout << "GenerateGamma: Z= " << nucleus->GetZ_asInt()
<< " A= " << nucleus->GetA_asInt()
<< " Exc= " << eexc << " Emax= "
<< fLevelEnergyMax << " idx= " << fIndex
<< " fCode= " << fCode << " fPoints= " << fPoints
<< " Ntr= " << ntrans << " discrete: " << isDiscrete
<< " fProb= " << fProbability << G4endl;
G4cout << " Z=" << nucleus->GetZ_asInt()
<< " A=" << nucleus->GetA_asInt()
<< " Exc=" << eexc << " Emax="
<< fLevelEnergyMax << " idx=" << fIndex
<< " fPoints= " << fPoints
<< " Ntr=" << ntrans << " discrete:" << isDiscrete
<< G4endl;
G4cout.precision(prec);
}
// continues part
if(!isDiscrete) {
// we compare current excitation versus value used for probability
// computation and also Z and A used for probability computation
if(fCode != 1000*theZ + theA || eexc != fExcEnergy) {
GetEmissionProbability(nucleus);
}
// primary fragment is in continium
GetEmissionProbability(nucleus);
if(fProbability == 0.0) {
fPoints = 1;
efinal = 0.0;
@@ -440,60 +464,64 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
}
}
}
// final discrete level
// final discrete level or continues exitation energy
if(fVerbose > 2) {
G4cout << "Continues proposes Efinal= " << efinal << G4endl;
G4cout << "Continues proposes Efinal=" << efinal
<< " Initial Idx=" << fIndex << G4endl;
}
if(nullptr != fLevelManager) {
if(efinal < fLevelEnergyMax) {
fIndex = fLevelManager->NearestLevelIndex(efinal, fIndex);
efinal = fLevelManager->LevelEnergy(fIndex);
// protection - take level below
if(efinal >= eexc && 0 < fIndex) {
--fIndex;
efinal = fLevelManager->LevelEnergy(fIndex);
}
nucleus->SetFloatingLevelNumber(fLevelManager->FloatingLevel(fIndex));
// not allowed to have final energy above max energy
// if G4LevelManager exist
} else {
efinal = fLevelEnergyMax;
// final discrete level
if (efinal < fLevelEnergyMax + fTolerance) {
fIndex = fLevelManager->NearestLevelIndex(efinal, fIndex);
G4double el = fLevelManager->LevelEnergy(fIndex);
// protection - take level below
if (el >= eexc + fTolerance && 0 < fIndex) {
--fIndex;
el = fLevelManager->LevelEnergy(fIndex);
}
// further decays will be discrete
if (std::abs(efinal - el) <= eLimit) {
efinal = el;
finalDiscrete = true;
} else {
fIndex = 0;
}
}
}
if (fVerbose > 2) {
G4cout << "Continues emission efinal(MeV)= " << efinal << G4endl;
G4cout << "Continues emission efinal(MeV)= " << efinal
<< " idxFinal=" << fIndex << " isdiscrete:" << isDiscrete << G4endl;
}
//discrete part ground state
} else if (0 == fIndex) {
G4bool isLL = false;
if (nullptr != fLevelManager) {
G4double ltime = fLevelManager->LifeTime(0);
if(ltime > fMaxLifeTime) { isLL = true; }
}
nucleus->SetLongLived(isLL);
return result;
//discrete part
// initial continues and final ground state
} else if (0 == fIndex) {
efinal = 0.0;
isDiscrete = false;
if (nullptr != fLevelManager) { finalDiscrete = true; }
// discrete part for excited nucleus
} else {
if(fVerbose > 2) {
G4cout << "Discrete emission from level Index= " << fIndex
<< " Elevel= " << fLevelManager->LevelEnergy(fIndex)
<< " Ltime= " << fLevelManager->LifeTime(fIndex)
<< " LtimeMax= " << fMaxLifeTime
<< " RDM= " << fRDM << " ICM= " << fICM << G4endl;
if (fVerbose > 2) {
G4cout << "Discrete emission from level Index=" << fIndex
<< " Elevel=" << fLevelManager->LevelEnergy(fIndex)
<< " Ltime=" << fLevelManager->LifeTime(fIndex)
<< " LtimeMax=" << fLocalTimeLimit
<< " RDM=" << fRDM << " ICM=" << fICM << G4endl;
}
// stable fragment has life time -1 or above the limit
// if is called from the radioactive decay the life time is not checked
G4double ltime = fLevelManager->LifeTime(fIndex);
if (!fRDM && ltime > fMaxLifeTime) {
// stable fragment has life time DBL_MAX
ltime = fLevelManager->LifeTime(fIndex);
// stable isomer - no sampling of transition
if (ltime == DBL_MAX) {
nucleus->SetFloatingLevelNumber(0);
nucleus->SetLongLived(true);
return result;
}
// sampling index of a final level
std::size_t idx = 0;
if(1 < ntrans) {
idx = level->SampleGammaTransition(G4UniformRand());
@@ -502,7 +530,10 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
G4cout << "Ntrans= " << ntrans << " idx= " << idx
<< " ICM= " << fICM << " abs(JP1)= " << JP1 << G4endl;
}
G4double prob = level->GammaProbability(idx);
// sampling IC or gamma transition
G4double prob = (G4double)level->GammaProbability(idx);
// prob = 0 means that there is only internal conversion
if (prob < 1.0) {
G4double rndm = G4UniformRand();
@@ -514,53 +545,57 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
}
}
}
// it is discrete transition with possible gamma correlation
// it is a discrete transition with possible gamma correlation
ratio = level->MultipolarityRatio(idx);
multiP = level->TransitionType(idx);
fIndex = level->FinalExcitationIndex(idx);
JP2 = std::abs(fLevelManager->TwoSpinParity(fIndex));
finalDiscrete = true;
// final energy and time
// final level parameters
efinal = fLevelManager->LevelEnergy(fIndex);
// time is sampled if decay not prompt and this class called not
// from radioactive decay and isomer production is enabled
if(fSampleTime && ltime < DBL_MAX) {
if(fSampleTime && ltime > 0.0) {
time -= ltime*G4Log(G4UniformRand());
}
nucleus->SetFloatingLevelNumber(fLevelManager->FloatingLevel(fIndex));
}
G4bool isLL = false;
if(nullptr != fLevelManager) {
G4double ltime = fLevelManager->LifeTime(fIndex);
if(ltime > fMaxLifeTime) { isLL = true; }
ltime = 0.0;
if (finalDiscrete) {
ltime = fLevelManager->LifeTime(fIndex);
JP2 = fLevelManager->TwoSpinParity(fIndex);
}
nucleus->SetLongLived(isLL);
// protection for floating levels
if(std::abs(efinal - eexc) <= fTolerance) { return result; }
result = fTransition->SampleTransition(nucleus, efinal, ratio, JP1,
JP2, multiP, vShellNumber,
isDiscrete, isGamma);
if(nullptr != result) { result->SetCreationTime(time); }
// updated residual nucleus
// sample continues or discrete transition if transition
// is above distance between floating level
if (std::abs(efinal - eexc) > fTolerance) {
result = fTransition->SampleTransition(nucleus, efinal, ratio, JP1,
std::abs(JP2), multiP, vShellNumber,
isDiscrete, isGamma);
if (nullptr != result) { result->SetCreationTime(time); }
}
// update parameters of the fragment
nucleus->SetCreationTime(time);
nucleus->SetSpin(0.5*JP2);
if(nullptr != fPolarization) { fPolarization->SetExcitationEnergy(efinal); }
if (nullptr != fPolarization) { fPolarization->SetExcitationEnergy(efinal); }
if (finalDiscrete) {
G4int idxfl = fLevelManager->FloatingLevel(fIndex);
nucleus->SetFloatingLevelNumber(idxfl);
// ignore the floating levels with zero energy and create ground state
if(efinal == 0.0 && fIndex > 0) {
fIndex = 0;
nucleus->SetFloatingLevelNumber(fLevelManager->FloatingLevel(0));
if (ltime > fLocalTimeLimit) { isLL = true; }
}
nucleus->SetLongLived(isLL);
if(fVerbose > 2) {
G4cout << "Final level E= " << efinal << " time= " << time
<< " idxFinal= " << fIndex << " isDiscrete: " << isDiscrete
<< " isGamma: " << isGamma << " multiP= " << multiP
<< " shell= " << vShellNumber
if (fVerbose > 2) {
G4String ss = "## ";
if (isLL && efinal > 0.0 && efinal < MeV) { ss += "=I="; }
if (isLL && efinal >= MeV) { ss += "=J="; }
if (efinal >= 6*MeV) { ss += "=K="; }
G4cout << " " << ss << " Efinal=" << efinal
<< " Efrag=" << nucleus->GetExcitationEnergy()
<< " lt=" << ltime
<< " idxFin=" << fIndex << " isDiscrete:" << isDiscrete
<< " isGamma:" << isGamma << " isStable:" << isLL
<< " multiP=" << multiP << " shell=" << vShellNumber
<< " abs(JP1)= " << JP1 << " abs(JP2)= " << JP2 << G4endl;
}
return result;
@@ -6,6 +6,9 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-01-10 Vladimir Ivanchenko (radioactive_decay-V11-02-06)
- G4RadioactiveDecay - fixed problem 2592 - enable biasing in radioactive decay
## 2024-08-14 Gabriele Cosmo (radioactive_decay-V11-02-05)
- Fixed reported Coverity defects for use of std::move().
@@ -877,6 +877,8 @@ G4RadioactiveDecay::DecayIt(const G4Track& theTrack, const G4Step&)
G4ThreeVector currentPosition;
currentPosition = theTrack.GetPosition();
fParticleChangeForRadDecay.SetSecondaryWeightByProcess(true);
G4IonTable* theIonTable;
G4ParticleDefinition* parentNucleus;
+8
View File
@@ -7,6 +7,14 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-03-05 Vladimir Ivanchenko (hadr-util-V11-02-06)
- G4HadronicDeveloperParameters - added limitation of warning printout on
change of parameters (NA64 request).
## 2025-01-09 Vladimir Ivanchenko
- G4Fragment - added protection against precision loss in computation of a boost
vector at rest
## 2024-10-29 Vladimir Ivanchenko (hadr-util-V11-02-05)
- G4LegendrePolynomial - optimized implementation by Isaac Kunen GitHub PR #70
@@ -89,6 +89,9 @@ class G4HadronicDeveloperParameters
void issue_non_eligible_value( const G4String& name );
void issue_is_already_defined( const G4String& name );
void issue_is_modified( const G4String& name );
G4int nWarn{0};
G4int nWarnMax{5};
};
#endif
@@ -205,7 +205,9 @@ void G4Fragment::SetExcEnergyAndMomentum(G4double eexc,
{
theExcitationEnergy = eexc;
theMomentum.set(0.0, 0.0, 0.0, theGroundStateMass + eexc);
theMomentum.boost(v.boostVector());
const G4double elim2 = 100.*CLHEP::eV*CLHEP::eV;
if (v.vect().mag2() > elim2)
theMomentum.boost(v.boostVector());
}
G4double G4Fragment::GetBindingEnergy() const
@@ -332,6 +332,8 @@ void G4HadronicDeveloperParameters::issue_is_already_defined( const G4String& na
G4Exception( "G4HadronicDeveloperParameters" , "HadDevPara_004", FatalException , text );
}
void G4HadronicDeveloperParameters::issue_is_modified( const G4String& name ) {
if (nWarn > nWarnMax) { return; }
++nWarn;
G4String text("Parameter ");
text += name;
text += " has changed from default value.";
+6
View File
@@ -6,6 +6,12 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2025-02-12 Ben Morgan (procscore-V11-02-01)
- Apply [GitHub PR 80](https://github.com/Geant4/geant4/pull/80)
- Changes to `G4EnergySplitter` to ensure that each call to `SplitEnergyInVolumes()`
utilizes the correct phantom parameterization.
- Fixes [Bugzilla 2636](https://bugzilla-geant4.kek.jp/show_bug.cgi?id=2636)
## 2024-10-10 Pedro Arce (procscore-V11-02-00)
- Safeguard for 0 energy deposited in G4EnergySplitter
- Fix bug #2629
@@ -72,7 +72,6 @@ class G4EnergySplitter
private:
void GetStepLength(G4int stepNo, G4double& stepLength);
void GetPhantomParam(G4bool mustExist);
G4bool IsPhantomVolume(G4VPhysicalVolume* pv);
G4EnergyLossForExtrapolator* theElossExt;
@@ -66,7 +66,10 @@ inline void G4EnergySplitter::SetNIterations(G4int niter)
//-----------------------------------------------------------------------
inline G4Material* G4EnergySplitter::GetVoxelMaterial(G4int stepNo)
{
if (thePhantomParam == nullptr) GetPhantomParam(true);
if (thePhantomParam == nullptr) {
G4Exception("G4EnergySplitter::GetVoxelMaterial()", "PhantomParamError",
FatalException, "Phantom parameterisation not set -- SplitEnergyInVolumes() must be called first");
}
G4int voxelID;
GetVoxelID(stepNo, voxelID);
return thePhantomParam->GetMaterial(voxelID);
@@ -82,7 +82,14 @@ G4int G4EnergySplitter::SplitEnergyInVolumes(const G4Step* aStep)
return (G4int)theEnergies.size();
}
if (thePhantomParam == nullptr) GetPhantomParam(true);
//----- Get the phantom parameterisation from the G4Step
auto preStepPhysVol = aStep->GetPreStepPoint()->GetPhysicalVolume();
if (!IsPhantomVolume(preStepPhysVol)) {
G4Exception("G4EnergySplitter::SplitEnergyInVolumes", "PhantomParamError", FatalException,
"SplitEnergyInVolumes() called for a step not in a phantom volume");
}
auto phantomVol = static_cast<G4PVParameterised*>(preStepPhysVol);
thePhantomParam = static_cast<G4PhantomParameterisation*>(phantomVol->GetParameterisation());
//----- Distribute energy deposited in voxels
std::vector<std::pair<G4int, G4double>> rnsl =
@@ -278,23 +285,6 @@ G4int G4EnergySplitter::SplitEnergyInVolumes(const G4Step* aStep)
return (G4int)theEnergies.size();
}
//-----------------------------------------------------------------------
void G4EnergySplitter::GetPhantomParam(G4bool mustExist)
{
G4PhysicalVolumeStore* pvs = G4PhysicalVolumeStore::GetInstance();
for (const auto pv : *pvs) {
if (IsPhantomVolume(pv)) {
const auto pvparam = static_cast<const G4PVParameterised*>(pv);
G4VPVParameterisation* param = pvparam->GetParameterisation();
thePhantomParam = static_cast<G4PhantomParameterisation*>(param);
}
}
if ((thePhantomParam == nullptr) && mustExist)
G4Exception("G4EnergySplitter::GetPhantomParam", "PhantomParamError", FatalException,
"No G4PhantomParameterisation found !");
}
//-----------------------------------------------------------------------
G4bool G4EnergySplitter::IsPhantomVolume(G4VPhysicalVolume* pv)
{