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
@@ -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.";