Geant4  10.03
G4PhotonEvaporation.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // $Id: G4PhotonEvaporation.cc 101865 2016-12-02 13:06:50Z gcosmo $
27 //
28 // -------------------------------------------------------------------
29 //
30 // GEANT4 class file
31 //
32 // CERN, Geneva, Switzerland
33 //
34 // File name: G4PhotonEvaporation
35 //
36 // Author: Vladimir Ivantchenko
37 //
38 // Creation date: 20 December 2011
39 //
40 //Modifications:
41 //
42 //
43 // -------------------------------------------------------------------
44 //
45 
46 #include "G4PhotonEvaporation.hh"
47 
48 #include "Randomize.hh"
49 #include "G4Gamma.hh"
50 #include "G4LorentzVector.hh"
51 #include "G4FragmentVector.hh"
52 #include "G4GammaTransition.hh"
53 #include "G4Pow.hh"
54 #include <CLHEP/Units/SystemOfUnits.h>
55 #include <CLHEP/Units/PhysicalConstants.h>
56 
59 
61  : fLevelManager(nullptr), fTransition(p), fVerbose(0), fPoints(0),
62  vShellNumber(-1), fIndex(0), fTimeLimit(DBL_MAX), fMaxLifeTime(DBL_MAX),
63  fICM(false), fRDM(false), fSampleTime(true), isInitialised(false)
64 {
65  //G4cout << "### New G4PhotonEvaporation() " << this << G4endl;
67  LevelDensity = 0.125/CLHEP::MeV;
68  Tolerance = 0.1*CLHEP::keV;
69 
70  if(!fTransition) { fTransition = new G4GammaTransition(); }
71 
72  char* env = getenv("G4AddTimeLimitToPhotonEvaporation");
73  if(env) { fTimeLimit = 1.e-16*CLHEP::second; }
74 
75  theA = theZ = fCode = 0;
77 
78  for(G4int i=0; i<MAXDEPOINT; ++i) { fCummProbability[i] = 0.0; }
79  if(0.0f == GREnergy[1]) {
80  G4Pow* g4calc = G4Pow::GetInstance();
81  static const G4float GRWfactor = 0.3f;
82  for (G4int A=1; A<MAXGRDATA; ++A) {
83  GREnergy[A] = (G4float)(40.3*CLHEP::MeV/g4calc->powZ(A,0.2));
84  GRWidth[A] = GRWfactor*GREnergy[A];
85  }
86  }
87 }
88 
90 {
91  delete fTransition;
92 }
93 
95 {
96  if(isInitialised) { return; }
97  isInitialised = true;
98 
100  LevelDensity = param->GetLevelDensity();
101  Tolerance = param->GetMinExcitation();
102  fMaxLifeTime = param->GetMaxLifeTime();
103 
105 }
106 
107 G4Fragment*
109 {
110  if(fRDM) { fSampleTime = false; }
111  else { fSampleTime = true; }
112 
113  G4Fragment* gamma = GenerateGamma(nucleus);
114  if(fVerbose > 0) {
115  G4cout << "G4PhotonEvaporation::EmittedFragment: RDM= " << fRDM << G4endl;
116  if(gamma) { G4cout << *gamma << G4endl; }
117  G4cout << " Residual: " << *nucleus << G4endl;
118  }
119  return gamma;
120 }
121 
124 {
125  //G4cout << "G4PhotonEvaporation::BreakItUp" << G4endl;
126  G4Fragment* aNucleus = new G4Fragment(nucleus);
127  G4FragmentVector* products = new G4FragmentVector();
128  BreakUpChain(products, aNucleus);
129  products->push_back(aNucleus);
130  return products;
131 }
132 
134  G4Fragment* nucleus)
135 {
136  if(fVerbose > 0) {
137  G4cout << "G4PhotonEvaporation::BreakUpChain RDM= " << fRDM << " "
138  << *nucleus << G4endl;
139  }
140  G4Fragment* gamma = nullptr;
141  if(fRDM) { fSampleTime = false; }
142  else { fSampleTime = true; }
143 
144  do {
145  gamma = GenerateGamma(nucleus);
146  if(gamma) {
147  products->push_back(gamma);
148  if(fVerbose > 0) {
149  G4cout << "G4PhotonEvaporation::BreakUpChain: "
150  << *gamma << G4endl;
151  G4cout << " Residual: " << *nucleus << G4endl;
152  }
153  // for next decays in the chain always sample time
154  fSampleTime = true;
155  }
156  // Loop checking, 05-Aug-2015, Vladimir Ivanchenko
157  } while(gamma);
158  return false;
159 }
160 
161 G4double
163 {
164  if(!isInitialised) { Initialise(); }
165  fProbability = 0.0;
166  fExcEnergy = nucleus->GetExcitationEnergy();
167  G4int Z = nucleus->GetZ_asInt();
168  G4int A = nucleus->GetA_asInt();
169  fCode = 1000*Z + A;
170  if(fVerbose > 1) {
171  G4cout << "G4PhotonEvaporation::GetEmissionProbability: Z="
172  << Z << " A=" << A << " Eexc(MeV)= " << fExcEnergy << G4endl;
173  }
174  // ignore gamma de-excitation for exotic fragments
175  // and for very low excitations
176  if(0 >= Z || 1 >= A || Z == A || Tolerance >= fExcEnergy)
177  { return fProbability; }
178 
179  // ignore gamma de-excitation for highly excited levels
180  if(A >= MAXGRDATA) { A = MAXGRDATA-1; }
181  //G4cout<<" GREnergy= "<< GREnergy[A]<<" GRWidth= "<<GRWidth[A]<<G4endl;
182 
183  static const G4float GREfactor = 5.0f;
184  if(fExcEnergy >= (G4double)(GREfactor*GRWidth[A] + GREnergy[A])) {
185  return fProbability;
186  }
187  // probability computed assuming continium transitions
188  // VI: continium transition are limited only to final states
189  // below Fermi energy (this approach needs further evaluation)
190  G4double emax = std::max(0.0, nucleus->ComputeGroundStateMass(Z, A-1)
191  + CLHEP::neutron_mass_c2 - nucleus->GetGroundStateMass());
192 
193  // max energy level for continues transition
194  emax = std::min(emax, fExcEnergy);
195  const G4double eexcfac = 0.99;
196  if(0.0 == emax || fExcEnergy*eexcfac <= emax) { emax = fExcEnergy*eexcfac; }
197 
198  fStep = emax;
199  static const G4double MaxDeltaEnergy = CLHEP::MeV;
200  fPoints = std::min((G4int)(fStep/MaxDeltaEnergy) + 2, MAXDEPOINT);
201  fStep /= ((G4double)(fPoints - 1));
202  if(fVerbose > 1) {
203  G4cout << "Emax= " << emax << " Npoints= " << fPoints
204  << " Eex= " << fExcEnergy << G4endl;
205  }
206  // integrate probabilities
207  G4double eres = (G4double)GREnergy[A];
208  G4double wres = (G4double)GRWidth[A];
209  G4double eres2= eres*eres;
210  G4double wres2= wres*wres;
211  G4double xsqr = std::sqrt(A*LevelDensity*fExcEnergy);
212 
213  G4double egam = fExcEnergy;
214  G4double gammaE2 = egam*egam;
215  G4double gammaR2 = gammaE2*wres2;
216  G4double egdp2 = gammaE2 - eres2;
217 
218  G4double p0 = G4Exp(-2.0*xsqr)*gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
219  G4double p1(0.0);
220 
221  for(G4int i=1; i<fPoints; ++i) {
222  egam -= fStep;
223  gammaE2 = egam*egam;
224  gammaR2 = gammaE2*wres2;
225  egdp2 = gammaE2 - eres2;
226  p1 = G4Exp(2.0*(std::sqrt(A*LevelDensity*std::abs(fExcEnergy - egam)) - xsqr))
227  *gammaR2*gammaE2/(egdp2*egdp2 + gammaR2);
228  fProbability += (p1 + p0);
230  //G4cout << "Egamma= " << egam << " Eex= " << fExcEnergy
231  //<< " p0= " << p0 << " p1= " << p1 << " sum= " << fCummProbability[i] <<G4endl;
232  p0 = p1;
233  }
234 
235  static const G4double NormC = 1.25*CLHEP::millibarn
236  /(CLHEP::pi2*CLHEP::hbarc*CLHEP::hbarc);
237  fProbability *= fStep*NormC*A;
238  if(fVerbose > 1) { G4cout << "prob= " << fProbability << G4endl; }
239  return fProbability;
240 }
241 
242 G4double
244 {
245  G4double E = energy;
247  if(fLevelManager) {
249  if(E > fLevelEnergyMax + Tolerance) { E = energy; }
250  }
251  return E;
252 }
253 
255 {
257  return fLevelEnergyMax;
258 }
259 
260 G4Fragment*
262 {
263  if(!isInitialised) { Initialise(); }
264  G4Fragment* result = nullptr;
265  G4double eexc = nucleus->GetExcitationEnergy();
266  if(eexc <= Tolerance) { return result; }
267 
268  InitialiseLevelManager(nucleus->GetZ_asInt(), nucleus->GetA_asInt());
269 
270  G4double time = nucleus->GetCreationTime();
271 
272  G4double efinal = 0.0;
273  G4double ratio = 0.0;
274  vShellNumber = -1;
275  size_t shell = 0;
276  G4int JP1 = 0;
277  G4int JP2 = 0;
278  G4int multiP = 0;
279  G4bool isGamma = true;
280  G4bool isLongLived = false;
281  G4bool isDiscrete = false;
282  G4bool icm = fICM;
283 
284  const G4NucLevel* level = nullptr;
285  size_t ntrans = 0;
286  if(fLevelManager && eexc <= fLevelEnergyMax + Tolerance) {
288  if(0 < fIndex) {
289  // for discrete transition
290  level = fLevelManager->GetLevel(fIndex);
291  if(level) {
292  ntrans = level->NumberOfTransitions();
294  if(ntrans > 0) { isDiscrete = true; }
296  --fIndex;
297  level = fLevelManager->GetLevel(fIndex);
298  ntrans = level->NumberOfTransitions();
300  if(ntrans > 0) { isDiscrete = true; }
301  }
302  }
303  }
304  }
305  if(fVerbose > 1) {
306  G4int prec = G4cout.precision(4);
307  G4cout << "GenerateGamma: Z= " << nucleus->GetZ_asInt()
308  << " A= " << nucleus->GetA_asInt()
309  << " Exc= " << eexc << " Emax= "
310  << fLevelEnergyMax << " idx= " << fIndex
311  << " fCode= " << fCode << " fPoints= " << fPoints
312  << " Ntr= " << ntrans << " discrete: " << isDiscrete
313  << " fProb= " << fProbability << G4endl;
314  G4cout.precision(prec);
315  }
316 
317  // continues part
318  if(!isDiscrete) {
319  // G4cout << "Continues fIndex= " << fIndex << G4endl;
320 
321  // we compare current excitation versus value used for probability
322  // computation and also Z and A used for probability computation
323  if(fCode != 1000*theZ + theA || eexc != fExcEnergy) {
324  GetEmissionProbability(nucleus);
325  }
326  if(fProbability == 0.0) { return result; }
328  for(G4int i=1; i<fPoints; ++i) {
329  //G4cout << "y= " << y << " cummProb= " << fCummProbability[i] << G4endl;
330  if(y <= fCummProbability[i]) {
331  efinal = fStep*((i - 1) + (y - fCummProbability[i-1])
332  /(fCummProbability[i] - fCummProbability[i-1]));
333  break;
334  }
335  }
336  // final discrete level
337  if(fLevelManager && efinal <= fLevelEnergyMax + Tolerance) {
338  //G4cout << "Efinal= " << efinal << " idx= " << fIndex << G4endl;
341  // protection
342  if(efinal >= eexc && 0 < fIndex) {
343  --fIndex;
345  }
346  }
347  if(fVerbose > 1) {
348  G4cout << "Continues emission efinal(MeV)= " << efinal << G4endl;
349  }
350  //discrete part
351  } else {
352  if(fVerbose > 1) {
353  G4cout << "Discrete emission from level Index= " << fIndex
354  << " Elevel= " << fLevelManager->LevelEnergy(fIndex)
355  << " RDM= " << fRDM << " ICM= " << fICM << G4endl;
356  }
357  if(0 == fIndex || !level) { return result; }
358 
359  G4double ltime = 0.0;
360  if(fSampleTime) {
361  if(fICM) { ltime = (G4double)fLevelManager->LifeTime(fIndex); }
362  else { ltime = (G4double)fLevelManager->LifeTimeGamma(fIndex); }
363  }
364 
365  if(ltime >= fMaxLifeTime) { return result; }
366  if(ltime > fTimeLimit) {
367  icm = true;
368  isLongLived = true;
369  }
370  size_t idx = 0;
371  if(fVerbose > 1) {
372  G4cout << "Ntrans= " << ntrans << " idx= " << idx
373  << " icm= " << icm << G4endl;
374  }
375  if(1 < ntrans) {
376  G4double rndm = G4UniformRand();
377  if(icm) { idx = level->SampleGammaETransition(rndm); }
378  else { idx = level->SampleGammaTransition(rndm); }
379  //G4cout << "Sampled idx= " << idx << " rndm= " << rndm << G4endl;
380  }
381  if(icm) {
382  G4double rndm = G4UniformRand();
383  G4double prob = level->GammaProbability(idx);
384  if(rndm > prob) {
385  rndm = (rndm - prob)/(1.0 - prob);
386  shell = level->SampleShell(idx, rndm);
387  vShellNumber = shell;
388  isGamma = false;
389  }
390  }
391  // it is discrete transition with possible gamma correlation
392  isDiscrete = true;
393  ratio = level->MixingRatio(idx);
394  multiP = level->TransitionType(idx);
395  fIndex = level->FinalExcitationIndex(idx);
397 
398  // final energy and time
400  if(fSampleTime && ltime > 0.0) {
401  time -= ltime*G4Log(G4UniformRand());
402  }
403  }
404  // protection for floating levels
405  if(std::abs(efinal - eexc) <= Tolerance) { return result; }
406 
407  result = fTransition->SampleTransition(nucleus, efinal, ratio, JP1,
408  JP2, multiP, shell, isDiscrete,
409  isGamma, isLongLived);
410  if(result) { result->SetCreationTime(time); }
411  nucleus->SetCreationTime(time);
412 
413  if(fVerbose > 1) {
414  G4cout << "Final level E= " << efinal << " time= " << time
415  << " idxFinal= " << fIndex << " isDiscrete: " << isDiscrete
416  << " isGamma: " << isGamma << " isLongLived: " << isLongLived
417  << " multiP= " << multiP << " shell= " << shell << G4endl;
418  }
419  return result;
420 }
421 
423 {
424  static const G4double tfact = G4Pow::GetInstance()->logZ(2);
425  fMaxLifeTime = val/tfact;
426 }
427 
429 {
430  if(p != fTransition) {
431  delete fTransition;
432  fTransition = p;
433  }
434 }
435 
437 {
438  fICM = val;
439 }
440 
442 {
443  fRDM = val;
444 }
445 
virtual void SetICM(G4bool)
G4float GammaProbability(size_t idx) const
Definition: G4NucLevel.hh:142
static G4Pow * GetInstance()
Definition: G4Pow.cc:55
void SetMaxHalfLife(G4double)
G4FragmentVector * BreakItUp(const G4Fragment &theNucleus)
G4GammaTransition * fTransition
const G4int MAXGRDATA
virtual G4bool BreakUpChain(G4FragmentVector *theResult, G4Fragment *theNucleus) final
static G4float GREnergy[MAXGRDATA]
G4int SpinParity(size_t i) const
const G4int MAXDEPOINT
Definition: G4Pow.hh:56
virtual void RDMForced(G4bool)
G4PhotonEvaporation(G4GammaTransition *ptr=nullptr)
G4float LifeTime(size_t i) const
float G4float
Definition: G4Types.hh:77
virtual G4Fragment * EmittedFragment(G4Fragment *theNucleus) final
virtual void Initialise() final
static G4float GRWidth[MAXGRDATA]
static constexpr double second
Definition: G4SIunits.hh:157
G4double fCummProbability[MAXDEPOINT]
const G4LevelManager * fLevelManager
G4double GetLevelDensity() const
int G4int
Definition: G4Types.hh:78
const G4NucLevel * GetLevel(size_t i) const
G4float MixingRatio(size_t idx) const
Definition: G4NucLevel.hh:134
G4double GetMaxLifeTime() const
void SetPolarizationFlag(G4bool val)
G4double logZ(G4int Z) const
Definition: G4Pow.hh:166
static const double prec
Definition: RanecuEngine.cc:58
virtual G4double GetEmissionProbability(G4Fragment *theNucleus) final
G4float LevelEnergy(size_t i) const
#define G4UniformRand()
Definition: Randomize.hh:97
G4GLOB_DLL std::ostream G4cout
double A(double temperature)
G4int GetA_asInt() const
Definition: G4Fragment.hh:256
G4double GetCreationTime() const
Definition: G4Fragment.hh:420
bool G4bool
Definition: G4Types.hh:79
G4int IsFloatingLevel(size_t i) const
std::vector< G4Fragment * > G4FragmentVector
Definition: G4Fragment.hh:63
G4DeexPrecoParameters * GetParameters()
void SetGammaTransition(G4GammaTransition *)
G4double GetGroundStateMass() const
Definition: G4Fragment.hh:278
size_t SampleGammaTransition(G4double rndm) const
Definition: G4NucLevel.hh:158
G4float NearestLevelEnergy(G4double energy, size_t index=0) const
size_t NearestLevelIndex(G4double energy, size_t index=0) const
virtual G4Fragment * SampleTransition(G4Fragment *nucleus, G4double newExcEnergy, G4double mpRatio, G4int JP1, G4int JP2, G4int MP, size_t shell, G4bool isDiscrete, G4bool isGamma, G4bool isLongLived)
static const G4double emax
G4double G4Log(G4double x)
Definition: G4Log.hh:230
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:183
void SetCreationTime(G4double time)
Definition: G4Fragment.hh:425
size_t NumberOfTransitions() const
Definition: G4NucLevel.hh:108
T max(const T t1, const T t2)
brief Return the largest of the two arguments
G4double energy(const ThreeVector &p, const G4double m)
G4Fragment * GenerateGamma(G4Fragment *nucleus)
G4int TransitionType(size_t idx) const
Definition: G4NucLevel.hh:126
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4NuclearLevelData * fNuclearLevelData
size_t SampleShell(size_t idx, G4double rndm) const
Definition: G4NucLevel.hh:178
G4int GetZ_asInt() const
Definition: G4Fragment.hh:261
#define G4endl
Definition: G4ios.hh:61
static constexpr double MeV
Definition: G4SIunits.hh:214
size_t SampleGammaETransition(G4double rndm) const
Definition: G4NucLevel.hh:168
G4double powZ(G4int Z, G4double y) const
Definition: G4Pow.hh:254
double G4double
Definition: G4Types.hh:76
G4float LifeTimeGamma(size_t i) const
size_t FinalExcitationIndex(size_t idx) const
Definition: G4NucLevel.hh:118
void InitialiseLevelManager(G4int Z, G4int A)
#define DBL_MAX
Definition: templates.hh:83
static constexpr double keV
Definition: G4SIunits.hh:216
virtual G4double GetUpperLevelEnergy(G4int Z, G4int A) final
G4double ComputeGroundStateMass(G4int Z, G4int A) const
Definition: G4Fragment.hh:246
static G4NuclearLevelData * GetInstance()
G4double GetMinExcitation() const
static constexpr double millibarn
Definition: G4SIunits.hh:106
G4double GetExcitationEnergy() const
Definition: G4Fragment.hh:273
static constexpr double pi2
Definition: G4SIunits.hh:78
virtual G4double GetFinalLevelEnergy(G4int Z, G4int A, G4double energy) final