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