54G4float G4PhotonEvaporation::GREnergy[] = {0.0f};
55G4float G4PhotonEvaporation::GRWidth[] = {0.0f};
59 constexpr G4double timeLimit = 10*CLHEP::ns;
60 constexpr G4double eLimit = 200*CLHEP::keV;
64 : fTransition(p), fPolarization(nullptr), fVerbose(1)
67 G4cout <<
"### New G4PhotonEvaporation() " <<
this <<
G4endl;
70 fTolerance = 20*CLHEP::eV;
71 fCummProbability[0] = 0.0;
76 if(0.0f == GREnergy[2]) { InitialiseGRData(); }
86 if (isInitialised) {
return; }
92 fLocalTimeLimit = fRDM ? fMaxLifeTime : std::max(fMaxLifeTime, timeLimit);
97 fTransition->SetPolarizationFlag(fCorrelatedGamma);
99 fTransition->SetVerbose(fVerbose);
101 G4cout <<
"### G4PhotonEvaporation is initialized " <<
this <<
G4endl;
105void G4PhotonEvaporation::InitialiseGRData()
107 if(0.0f == GREnergy[2]) {
109 const G4float GRWfactor = 0.3f;
111 GREnergy[
A] = (
G4float)(40.3*CLHEP::MeV/g4calc->
powZ(
A,0.2));
112 GRWidth[
A] = GRWfactor*GREnergy[
A];
123 nucleus->SetNumberOfElectrons(nucleus->GetZ_asInt());
129 if(fCorrelatedGamma && fRDM) {
131 auto nucp = nucleus->GetNuclearPolarization();
132 if(
nullptr != nucp) {
135 fPolarization = fNucPStore->
FindOrBuild(nucleus->GetZ_asInt(),
136 nucleus->GetA_asInt(),
137 nucleus->GetExcitationEnergy());
138 nucleus->SetNuclearPolarization(fPolarization);
141 G4cout <<
"G4PhotonEvaporation::EmittedFragment: "
143 if (
nullptr != fPolarization) {
G4cout <<
"NucPolar: " << fPolarization <<
G4endl; }
144 G4cout <<
" CorrGamma: " << fCorrelatedGamma <<
" RDM: " << fRDM
145 <<
" fPolarization: " << fPolarization <<
G4endl;
152 if (
nullptr != fNucPStore &&
nullptr != fPolarization && 0 == fIndex) {
154 G4cout <<
"G4PhotonEvaporation::EmittedFragment: remove "
155 << fPolarization <<
G4endl;
157 fNucPStore->
RemoveMe(fPolarization);
158 fPolarization =
nullptr;
159 nucleus->SetNuclearPolarization(fPolarization);
163 G4cout <<
"G4PhotonEvaporation::EmittedFragment: RDM= "
164 << fRDM <<
" done:" <<
G4endl;
181 products->push_back(aNucleus);
190 G4cout <<
"G4PhotonEvaporation::BreakUpChain RDM= " << fRDM <<
" "
197 if(fCorrelatedGamma) {
199 nucleus->GetA_asInt(),
200 nucleus->GetExcitationEnergy());
201 nucleus->SetNuclearPolarization(fPolarization);
205 gamma = GenerateGamma(nucleus);
206 if (
nullptr != gamma) {
208 products->push_back(gamma);
213 G4cout <<
"G4PhotonEvaporation::BreakUpChain: next decay" <<
G4endl;
214 if (
nullptr != gamma) {
G4cout <<
" " << *gamma <<
G4endl; }
219 }
while (!(nucleus->IsLongLived() || nucleus->GetExcitationEnergy() <= fTolerance));
222 if(
nullptr != fPolarization) {
223 delete fPolarization;
224 fPolarization =
nullptr;
225 nucleus->SetNuclearPolarization(fPolarization);
235 fExcEnergy = nucleus->GetExcitationEnergy();
236 G4int Z = nucleus->GetZ_asInt();
237 G4int A = nucleus->GetA_asInt();
239 G4cout <<
"G4PhotonEvaporation::GetEmissionProbability: Z="
240 << Z <<
" A=" <<
A <<
" Eexc(MeV)= " << fExcEnergy <<
G4endl;
244 if(0 >= Z || 1 >=
A || Z ==
A || fTolerance >= fExcEnergy)
245 {
return fProbability; }
248 if(
A >= MAXGRDATA) {
A = MAXGRDATA-1; }
250 static const G4double GREfactor = 5.0;
253 G4cout <<
" GREnergy=" << GREnergy[
A] <<
" GRWidth="<<GRWidth[
A]
254 <<
" Edelta=" << edelta <<
G4endl;
255 if (fExcEnergy >= edelta) {
261 const G4double MaxDeltaEnergy = CLHEP::MeV;
262 fPoints = std::min((
G4int)(fStep/MaxDeltaEnergy) + 2, MAXDEPOINT);
266 G4cout <<
" Npoints= " << fPoints
267 <<
" Eex=" << fExcEnergy <<
" Estep=" << fStep <<
G4endl;
277 G4double levelDensity = fNuclearLevelData->GetLevelDensity(Z,
A,fExcEnergy);
288 G4double p0 = egam*gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
291 for(
G4int i=1; i<fPoints; ++i) {
293 if (i + 1 == fPoints) {
297 gammaR2 = gammaE2*wres2;
298 egdp2 = gammaE2 - eres2;
299 e = fExcEnergy - egam;
300 levelDensity = fNuclearLevelData->GetLevelDensity(Z,
A, e);
301 p1 = egam*
G4Exp(2.0*(std::sqrt(levelDensity*e)))*gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
303 fProbability += (p1 + p0);
304 fCummProbability[i] = fProbability;
306 G4cout <<
"Egamma= " << egam <<
" Eex= " << fExcEnergy
307 <<
" p0= " << p0 <<
" p1= " << p1 <<
" sum= "
308 << fCummProbability[i] <<
G4endl;
313 static const G4double NormC = 1.25*CLHEP::millibarn
314 /(CLHEP::pi2*CLHEP::hbarc*CLHEP::hbarc);
315 fProbability *= fStep*NormC*
A/xdrt;
316 if(fVerbose > 1) {
G4cout <<
"prob= " << fProbability <<
G4endl; }
336 InitialiseLevelManager(Z,
A);
337 if (
nullptr != fLevelManager) {
338 E = fLevelManager->NearestLevelEnergy(energy, fIndex);
339 if(E > fLevelEnergyMax + fTolerance) { E = energy; }
346 InitialiseLevelManager(Z,
A);
347 return fLevelEnergyMax;
351G4PhotonEvaporation::GenerateGamma(
G4Fragment* nucleus)
354 G4Fragment* result =
nullptr;
358 InitialiseLevelManager(
nucleus->GetZ_asInt(),
nucleus->GetA_asInt());
376 G4bool isDiscrete =
false;
377 G4bool finalDiscrete =
false;
379 const G4NucLevel* level =
nullptr;
380 std::size_t ntrans = 0;
383 G4cout <<
"## GenerateGamma: Z=" << theZ <<
" A=" << theA <<
" Eex= " << eexc
384 <<
" Eexmax= " << fLevelEnergyMax <<
G4endl;
387 if (eexc <= fTolerance) {
391 }
else if (
nullptr != fLevelManager && eexc <= fLevelEnergyMax + fTolerance) {
392 fIndex = fLevelManager->NearestLevelIndex(eexc);
393 elevel = fLevelManager->LevelEnergy(fIndex);
394 isDiscrete = (std::abs(elevel - eexc) < fTolerance);
396 G4cout <<
" Level index=" << fIndex
397 <<
" lTime=" << fLevelManager->LifeTime(fIndex)
398 <<
" Elevel=" << elevel
399 <<
" isDiscrete:" << isDiscrete <<
G4endl;
401 if(isDiscrete && 0 < fIndex) {
403 level = fLevelManager->GetLevel(fIndex);
404 if(
nullptr != level) {
406 G4int idxfl = fLevelManager->FloatingLevel(fIndex);
409 auto newlevel = fLevelManager->GetLevel(fIndex-1);
410 G4double newenergy = fLevelManager->LevelEnergy(fIndex-1);
411 if (
nullptr != newlevel && std::abs(elevel - newenergy) < fTolerance) {
412 std::size_t newntrans = newlevel->NumberOfTransitions();
421 JP1 = std::abs(fLevelManager->TwoSpinParity(fIndex));
423 G4cout <<
" ntrans= " << ntrans <<
" JP= " << JP1
424 <<
" RDM: " << fRDM <<
G4endl;
432 }
else if (0 == fIndex) {
440 <<
" A=" <<
nucleus->GetA_asInt()
441 <<
" Exc=" << eexc <<
" Emax="
442 << fLevelEnergyMax <<
" idx=" << fIndex
443 <<
" fPoints= " << fPoints
444 <<
" Ntr=" << ntrans <<
" discrete:" << isDiscrete
453 if(fProbability == 0.0) {
458 for(
G4int i=1; i<fPoints; ++i) {
460 G4cout <<
"y= " << y <<
" cummProb= " << fCummProbability[i]
461 <<
" fPoints= " << fPoints <<
" fStep= " << fStep <<
G4endl;
463 if(y <= fCummProbability[i]) {
464 efinal = fStep*((i - 1) + (y - fCummProbability[i-1])
465 /(fCummProbability[i] - fCummProbability[i-1]));
472 G4cout <<
"Continues proposes Efinal=" << efinal
473 <<
" Initial Idx=" << fIndex <<
G4endl;
476 if(
nullptr != fLevelManager) {
478 if (efinal < fLevelEnergyMax + fTolerance) {
479 fIndex = fLevelManager->NearestLevelIndex(efinal, fIndex);
480 G4double el = fLevelManager->LevelEnergy(fIndex);
482 if (el >= eexc + fTolerance && 0 < fIndex) {
484 el = fLevelManager->LevelEnergy(fIndex);
487 ltime = fLevelManager->LifeTime(fIndex);
488 if (fIndex <= 1 || std::abs(efinal - el) <= eLimit || ltime >= fLocalTimeLimit) {
490 finalDiscrete =
true;
497 G4cout <<
"Continues emission efinal(MeV)= " << efinal
498 <<
" idxFinal=" << fIndex <<
" isdiscrete:" << isDiscrete <<
G4endl;
502 }
else if (0 == fIndex) {
505 if (
nullptr != fLevelManager) { finalDiscrete =
true; }
511 G4cout <<
"Discrete emission from level Index=" << fIndex
512 <<
" Elevel=" << fLevelManager->LevelEnergy(fIndex)
513 <<
" Ltime=" << fLevelManager->LifeTime(fIndex)
514 <<
" LtimeMax=" << fLocalTimeLimit
515 <<
" RDM=" << fRDM <<
" ICM=" << fICM <<
G4endl;
519 ltime = fLevelManager->LifeTime(fIndex);
523 nucleus->SetFloatingLevelNumber(0);
534 G4cout <<
"Ntrans= " << ntrans <<
" idx= " << idx
535 <<
" ICM= " << fICM <<
" abs(JP1)= " << JP1 <<
G4endl;
547 rndm = (rndm - prob)/(1.0 - prob);
556 finalDiscrete =
true;
559 efinal = fLevelManager->LevelEnergy(fIndex);
562 if(fSampleTime && ltime > 0.0) {
568 ltime = fLevelManager->LifeTime(fIndex);
569 JP2 = fLevelManager->TwoSpinParity(fIndex);
573 if (std::abs(efinal - eexc) > fTolerance) {
574 result = fTransition->SampleTransition(nucleus, efinal, ratio, JP1,
575 std::abs(JP2), multiP, vShellNumber,
576 isDiscrete, isGamma);
580 nucleus->SetCreationTime(time);
582 if (
nullptr != fPolarization) { fPolarization->SetExcitationEnergy(efinal); }
585 G4int idxfl = fLevelManager->FloatingLevel(fIndex);
586 nucleus->SetFloatingLevelNumber(idxfl);
588 if (ltime > fLocalTimeLimit) { isLL =
true; }
594 if (isLL && efinal > 0.0 && efinal < MeV) { ss +=
"=I="; }
595 if (isLL && efinal >= MeV) { ss +=
"=J="; }
596 if (efinal >= 6*MeV) { ss +=
"=K="; }
597 G4cout <<
" " << ss <<
" Efinal=" << efinal
598 <<
" Efrag=" <<
nucleus->GetExcitationEnergy()
600 <<
" idxFin=" << fIndex <<
" isDiscrete:" << isDiscrete
601 <<
" isGamma:" << isGamma <<
" isStable:" << isLL
602 <<
" multiP=" << multiP <<
" shell=" << vShellNumber
603 <<
" abs(JP1)= " << JP1 <<
" abs(JP2)= " << JP2 <<
G4endl;
610 if(p != fTransition) {
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
std::vector< G4Fragment * > G4FragmentVector
G4double G4Log(G4double x)
G4GLOB_DLL std::ostream G4cout
G4bool CorrelatedGamma() const
G4double GetMaxLifeTime() const
G4double GetMinExcitation() const
G4bool GetInternalConversionFlag() const
void SetCreatorModelID(G4int value)
void SetCreationTime(G4double time)
std::size_t NumberOfTransitions() const
G4int SampleShell(const std::size_t idx, const G4double rndm) const
G4float MultipolarityRatio(const std::size_t idx) const
G4int TransitionType(const std::size_t idx) const
G4float GammaProbability(std::size_t idx) const
std::size_t FinalExcitationIndex(const std::size_t idx) const
std::size_t SampleGammaTransition(const G4double rndm) const
static G4NuclearLevelData * GetInstance()
static G4NuclearPolarizationStore * GetInstance()
void RemoveMe(G4NuclearPolarization *ptr)
G4NuclearPolarization * FindOrBuild(G4int Z, G4int A, G4double Eexc)
void RDMForced(G4bool) override
G4double GetEmissionProbability(G4Fragment *theNucleus) override
G4double GetUpperLevelEnergy(G4int Z, G4int A)
void SetICM(G4bool) override
G4double ComputeProbability(G4Fragment *theNucleus, G4double kinEnergy) override
G4double ComputeInverseXSection(G4Fragment *theNucleus, G4double kinEnergy) override
G4double GetFinalLevelEnergy(G4int Z, G4int A, G4double energy)
G4bool BreakUpChain(G4FragmentVector *theResult, G4Fragment *theNucleus) override
~G4PhotonEvaporation() override
void SetGammaTransition(G4GammaTransition *)
G4PhotonEvaporation(G4GammaTransition *ptr=nullptr)
G4FragmentVector * BreakItUp(const G4Fragment &theNucleus)
void Initialise() override
G4Fragment * EmittedFragment(G4Fragment *theNucleus) override
static G4int GetModelID(const G4int modelIndex)
static G4Pow * GetInstance()
G4double powZ(G4int Z, G4double y) const