Geant4  10.02.p03
G4EquilibriumEvaporator.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: G4EquilibriumEvaporator.cc 71954 2013-06-29 04:40:40Z mkelsey $
27 //
28 // 20100114 M. Kelsey -- Remove G4CascadeMomentum, use G4LorentzVector directly
29 // 20100308 M. Kelsey -- Bug fix for setting masses of evaporating nuclei
30 // 20100319 M. Kelsey -- Use new generateWithRandomAngles for theta,phi stuff;
31 // eliminate some unnecessary std::pow()
32 // 20100319 M. Kelsey -- Bug fix in new GetBindingEnergy() use right after
33 // goodRemnant() -- Q1 should be outside call.
34 // 20100412 M. Kelsey -- Pass G4CollisionOutput by ref to ::collide()
35 // 20100413 M. Kelsey -- Pass buffers to paraMaker[Truncated]
36 // 20100419 M. Kelsey -- Handle fission output list via const-ref
37 // 20100517 M. Kelsey -- Use G4CascadeInterpolator for QFF
38 // 20100520 M. Kelsey -- Inherit from common base class, make other colliders
39 // simple data members. Rename timeToBigBang() to override
40 // base explosion().
41 // 20100617 M. Kelsey -- Remove "RUN" preprocessor flag and all "#else" code,
42 // pass verbosity to colliders.
43 // 20100620 M. Kelsey -- Use local "bindingEnergy()" function to call through.
44 // 20100701 M. Kelsey -- Don't need to add excitation to nuclear mass; compute
45 // new excitation energies properly (mass differences)
46 // 20100702 M. Kelsey -- Simplify if-cascades, indentation
47 // 20100712 M. Kelsey -- Add conservation checking
48 // 20100714 M. Kelsey -- Move conservation checking to base class. Use
49 // _generated_ evaporate energy (S) to adjust EEXS directly,
50 // and test for S < EEXS before any particle generation; shift
51 // nucleus momentum (PEX) by evaporate momentum directly
52 // 20100719 M. Kelsey -- Remove duplicative EESX_new calculation.
53 // 20100923 M. Kelsey -- Migrate to integer A and Z
54 // 20110214 M. Kelsey -- Follow G4InuclParticle::Model enumerator migration
55 // 20110728 M. Kelsey -- Fix Coverity #22951: check for "icase = -1" after
56 // loop which is supposed to set it. Otherwise indexing is wrong.
57 // 20110801 M. Kelsey -- Move "parms" buffer to data member, allocate in
58 // constructor.
59 // 20110809 M. Kelsey -- Move "foutput" to data member, get list by reference;
60 // create final-state particles within "push_back" to avoid
61 // creation of temporaries.
62 // 20110922 M. Kelsey -- Follow G4InuclParticle::print(ostream&) migration
63 // 20111007 M. Kelsey -- Add G4InuclParticleNames, replace hardcoded numbers
64 // 20120608 M. Kelsey -- Fix variable-name "shadowing" compiler warnings.
65 // 20121009 M. Kelsey -- Improve debugging output
66 // 20130129 M. Kelsey -- Move QF interpolation to global statics for
67 // multi-threaded shared memory.
68 // 20130621 M. Kelsey -- Remove turning off conservation checks after fission
69 // 20130622 Inherit from G4CascadeDeexciteBase, move to deExcite() interface
70 // with G4Fragment
71 // 20130628 Fissioner produces G4Fragment output directly in G4CollisionOutput
72 // 20130808 M. Kelsey -- Use new object-version of paraMaker, for thread safety
73 // 20130924 M. Kelsey -- Use G4Log, G4Exp for CPU speedup
74 // 20150608 M. Kelsey -- Label all while loops as terminating.
75 // 20150622 M. Kelsey -- For new G4cbrt(int), move powers of A outside.
76 
77 #include "G4EquilibriumEvaporator.hh"
78 #include "G4SystemOfUnits.hh"
79 #include "G4BigBanger.hh"
80 #include "G4CascadeInterpolator.hh"
81 #include "G4CollisionOutput.hh"
82 #include "G4Fissioner.hh"
83 #include "G4Fragment.hh"
84 #include "G4InuclNuclei.hh"
85 #include "G4InuclSpecialFunctions.hh"
86 #include "G4InuclParticleNames.hh"
87 #include "G4LorentzConvertor.hh"
88 #include "G4LorentzVector.hh"
89 #include "G4ThreeVector.hh"
90 #include "G4Log.hh"
91 #include "G4Exp.hh"
92 
93 using namespace G4InuclParticleNames;
94 using namespace G4InuclSpecialFunctions;
95 
96 namespace { // Interpolation arrays for QF
97  const G4double QFREP[72] = {
98  // TL201 * * * *
99  // 1 2 3 4 5
100  22.5, 22.0, 21.0, 21.0, 20.0,
101  // BI209 BI207 PO210 AT213 * TH234
102  // 6 7 8 9 10 11
103  20.6, 20.6, 18.6, 15.8, 13.5, 6.5,
104  // TH233 TH232 TH231 TH230 TX229 PA233 PA232 PA231 PA230 U240
105  // 12 13 14 15 16 17 18 19 20 21
106  6.65, 6.22, 6.27, 6.5, 6.7, 6.2, 6.25, 5.9, 6.1, 5.75,
107  // U239 U238 U237 U236 U235 U234 U233 U232 U231
108  // 22 23 24 25 26 27 28 29 30
109  6.46, 5.7, 6.28, 5.8, 6.15, 5.6, 5.8, 5.2, 5.8,
110  // NP238 NP237 NP236 NP235 PU245 NP234 PU244 NP233
111  // 31 32 33 34 35 36 37 38
112  6.2 , 5.9 , 5.9, 6.0, 5.8, 5.7, 5.4, 5.4,
113  // PU242 PU241 PU240 PU239 PU238 AM247 PU236 AM245 AM244 AM243
114  // 39 40 41 42 43 44 45 46 47 48
115  5.6, 6.1, 5.57, 6.3, 5.5, 5.8, 4.7, 6.2, 6.4, 6.2,
116  // AM242 AM241 AM240 CM250 AM239 CM249 CM248 CM247 CM246
117  // 49 50 51 52 53 54 55 56 57
118  6.5, 6.2, 6.5, 5.3, 6.4, 5.7, 5.7, 6.2, 5.7,
119  // CM245 CM244 CM243 CM242 CM241 BK250 CM240
120  // 58 59 60 61 62 63 64
121  6.3, 5.8, 6.7, 5.8, 6.6, 6.1, 4.3,
122  // BK249 CF252 CF250 CF248 CF246 ES254 ES253 FM254
123  // 65 66 67 68 69 70 71 72
124  6.2, 3.8, 5.6, 4.0, 4.0, 4.2, 4.2, 3.5 };
125 
126  static const G4double XREP[72] = {
127  // 1 2 3 4 5
128  0.6761, 0.677, 0.6788, 0.6803, 0.685,
129  // 6 7 8 9 10 11
130  0.6889, 0.6914, 0.6991, 0.7068, 0.725, 0.7391,
131  // 12 13 14 15 16 17 18 19 20 21
132  0.74, 0.741, 0.742, 0.743, 0.744, 0.7509, 0.752, 0.7531, 0.7543, 0.7548,
133  // 22 23 24
134  0.7557, 0.7566, 0.7576,
135  // 25 26 27 28 29 30 31 32 33 34
136  0.7587, 0.7597, 0.7608, 0.762, 0.7632, 0.7644, 0.7675, 0.7686, 0.7697, 0.7709,
137  // 35 36 37 38 39 40 41
138  0.7714, 0.7721, 0.7723, 0.7733, 0.7743, 0.7753, 0.7764,
139  // 42 43 44 45 46 47 48 49
140  0.7775, 0.7786, 0.7801, 0.781, 0.7821, 0.7831, 0.7842, 0.7852,
141  // 50 51 52 53 54 55 56 57 58
142  0.7864, 0.7875, 0.7880, 0.7887, 0.7889, 0.7899, 0.7909, 0.7919, 0.7930,
143  // 59 60 61 62 63 64
144  0.7941, 0.7953, 0.7965, 0.7977, 0.7987, 0.7989,
145  // 65 66 67 68 69 70 71 72
146  0.7997, 0.8075, 0.8097, 0.8119, 0.8143, 0.8164, 0.8174, 0.8274 };
147 }
148 
149 
150 // Constructor and destructor
151 
152 G4EquilibriumEvaporator::G4EquilibriumEvaporator()
153  : G4CascadeDeexciteBase("G4EquilibriumEvaporator"),
154  theParaMaker(verboseLevel), QFinterp(XREP) {
155  parms.first.resize(6,0.);
156  parms.second.resize(6,0.);
157 }
158 
159 G4EquilibriumEvaporator::~G4EquilibriumEvaporator() {}
160 
161 void G4EquilibriumEvaporator::setVerboseLevel(G4int verbose) {
163  theFissioner.setVerboseLevel(verbose);
164  theBigBanger.setVerboseLevel(verbose);
165 }
166 
167 
168 // Main operation
169 
170 void G4EquilibriumEvaporator::deExcite(const G4Fragment& target,
171  G4CollisionOutput& output) {
172  if (verboseLevel) {
173  G4cout << " >>> G4EquilibriumEvaporator::deExcite" << G4endl;
174  }
175 
176  if (verboseLevel>1) G4cout << " evaporating target: \n" << target << G4endl;
177 
178  // simple implementation of the equilibium evaporation a la Dostrowski
179  const G4double huge_num = 50.0;
180  const G4double small = -50.0;
181  const G4double prob_cut_off = 1.0e-15;
182  const G4double Q1[6] = { 0.0, 0.0, 2.23, 8.49, 7.72, 28.3 };
183  const G4int AN[6] = { 1, 1, 2, 3, 3, 4 };
184  const G4int Q[6] = { 0, 1, 1, 1, 2, 2 };
185  const G4double G[6] = { 2.0, 2.0, 6.0, 6.0, 6.0, 4.0 };
186  const G4double BE = 0.0063;
187  const G4double fisssion_cut = 1000.0;
188  const G4double cut_off_energy = 0.1;
189 
190  const G4double BF = 0.0242;
191  const G4int itry_max = 1000;
192  const G4int itry_global_max = 1000;
193  const G4double small_ekin = 1.0e-6;
194  const G4int itry_gam_max = 100;
195 
196  G4double W[8], u[6], V[6], TM[6];
197  G4int A1[6], Z1[6];
198 
199  getTargetData(target);
200  if (verboseLevel > 3) G4cout << " after noeq: eexs " << EEXS << G4endl;
201 
202  G4InuclElementaryParticle dummy(small_ekin, proton);
203  G4LorentzConvertor toTheNucleiSystemRestFrame;
204  //*** toTheNucleiSystemRestFrame.setVerbose(verboseLevel);
205  toTheNucleiSystemRestFrame.setBullet(dummy);
206 
207  G4LorentzVector ppout;
208 
209  // See if fragment should just be dispersed
210  if (explosion(A, Z, EEXS)) {
211  if (verboseLevel > 1) G4cout << " big bang in eql start " << G4endl;
212  theBigBanger.deExcite(target, output);
213 
214  validateOutput(target, output); // Check energy conservation
215  return;
216  }
217 
218  // If nucleus is in ground state, no evaporation
219  if (EEXS < cut_off_energy) {
220  if (verboseLevel > 1) G4cout << " no energy for evaporation" << G4endl;
221  output.addRecoilFragment(target);
222 
223  validateOutput(target, output); // Check energy conservation
224  return;
225  }
226 
227  // Initialize evaporation attempts
228  G4double coul_coeff = (A >= 100.0) ? 1.4 : 1.2;
229 
230  G4LorentzVector pin = PEX; // Save original target for testing
231 
232  G4bool try_again = true;
233  G4bool fission_open = true;
234  G4int itry_global = 0;
235 
236  /* Loop checking 08.06.2015 MHK */
237  while (try_again && itry_global < itry_global_max) {
238  itry_global++;
239 
240  // Set rest frame of current (recoiling) nucleus
241  toTheNucleiSystemRestFrame.setTarget(PEX);
242  toTheNucleiSystemRestFrame.toTheTargetRestFrame();
243 
244  if (verboseLevel > 2) {
245  G4double nuc_mass = G4InuclNuclei::getNucleiMass(A, Z, EEXS);
246  G4cout << " A " << A << " Z " << Z << " mass " << nuc_mass
247  << " EEXS " << EEXS << G4endl;
248  }
249 
250  if (explosion(A, Z, EEXS)) { // big bang
251  if (verboseLevel > 2)
252  G4cout << " big bang in eql step " << itry_global << G4endl;
253 
254  theBigBanger.deExcite(makeFragment(PEX,A,Z,EEXS), output);
255 
256  validateOutput(target, output); // Check energy conservation
257  return;
258  }
259 
260  if (EEXS < cut_off_energy) { // Evaporation not possible
261  if (verboseLevel > 2)
262  G4cout << " no energy for evaporation in eql step " << itry_global
263  << G4endl;
264 
265  try_again = false;
266  break;
267  }
268 
269  // Normal evaporation chain
270  G4double E0 = getE0(A);
271  G4double parlev = getPARLEVDEN(A, Z);
272  G4double u1 = parlev * A;
273 
274  theParaMaker.getParams(Z, parms);
275  const std::vector<G4double>& AK = parms.first;
276  const std::vector<G4double>& CPA = parms.second;
277 
278  G4double DM0 = bindingEnergy(A,Z);
279  G4int i(0);
280 
281  for (i = 0; i < 6; i++) {
282  A1[i] = A - AN[i];
283  Z1[i] = Z - Q[i];
284  u[i] = parlev * A1[i];
285  V[i] = 0.0;
286  TM[i] = -0.1;
287 
288  if (goodRemnant(A1[i], Z1[i])) {
289  G4double QB = DM0 - bindingEnergy(A1[i],Z1[i]) - Q1[i];
290  V[i] = coul_coeff * Z * Q[i] * AK[i] / (1.0 + EEXS / E0) /
291  (G4cbrt(A1[i]) + G4cbrt(AN[i]));
292  TM[i] = EEXS - QB - V[i] * A / A1[i];
293  if (verboseLevel > 3) {
294  G4cout << " i=" << i << " : QB " << QB << " u " << u[i]
295  << " V " << V[i] << " TM " << TM[i] << G4endl;
296  }
297  }
298  }
299 
300  G4double ue = 2.0 * std::sqrt(u1 * EEXS);
301  G4double prob_sum = 0.0;
302 
303  W[0] = 0.0;
304  if (TM[0] > cut_off_energy) {
305  G4double AL = getAL(A);
306  G4double A13 = G4cbrt(A1[0]);
307  W[0] = BE * A13*A13 * G[0] * AL;
308  G4double TM1 = 2.0 * std::sqrt(u[0] * TM[0]) - ue;
309 
310  if (TM1 > huge_num) TM1 = huge_num;
311  else if (TM1 < small) TM1 = small;
312 
313  W[0] *= G4Exp(TM1);
314  prob_sum += W[0];
315  }
316 
317  for (i = 1; i < 6; i++) {
318  W[i] = 0.0;
319  if (TM[i] > cut_off_energy) {
320  G4double A13 = G4cbrt(A1[i]);
321  W[i] = BE * A13*A13 * G[i] * (1.0 + CPA[i]);
322  G4double TM1 = 2.0 * std::sqrt(u[i] * TM[i]) - ue;
323 
324  if (TM1 > huge_num) TM1 = huge_num;
325  else if (TM1 < small) TM1 = small;
326 
327  W[i] *= G4Exp(TM1);
328  prob_sum += W[i];
329  }
330  }
331 
332  // fisson part
333  W[6] = 0.0;
334  if (A >= 100.0 && fission_open) {
335  G4double X2 = Z * Z / A;
336  G4double X1 = 1.0 - 2.0 * Z / A;
337  G4double X = 0.019316 * X2 / (1.0 - 1.79 * X1 * X1);
338  G4double EF = EEXS - getQF(X, X2, A, Z, EEXS);
339 
340  if (EF > 0.0) {
341  G4double AF = u1 * getAF(X, A, Z, EEXS);
342  G4double TM1 = 2.0 * std::sqrt(AF * EF) - ue;
343 
344  if (TM1 > huge_num) TM1 = huge_num;
345  else if (TM1 < small) TM1 = small;
346 
347  W[6] = BF * G4Exp(TM1);
348  if (W[6] > fisssion_cut*W[0]) W[6] = fisssion_cut*W[0];
349 
350  prob_sum += W[6];
351  }
352  }
353 
354  // again time to decide what next
355  if (verboseLevel > 2) {
356  G4cout << " Evaporation probabilities: sum = " << prob_sum
357  << "\n\t n " << W[0] << " p " << W[1] << " d " << W[2]
358  << " He3 " << W[3] << "\n\t t " << W[4] << " alpha " << W[5]
359  << " fission " << W[6] << G4endl;
360  }
361 
362  G4int icase = -1;
363 
364  if (prob_sum < prob_cut_off) { // photon emission chain
365  G4double UCR0 = 2.5 + 150.0 / A;
366  G4double T00 = 1.0 / (std::sqrt(u1 / UCR0) - 1.25 / UCR0);
367 
368  if (verboseLevel > 3)
369  G4cout << " UCR0 " << UCR0 << " T00 " << T00 << G4endl;
370 
371  G4int itry_gam = 0;
372  while (EEXS > cut_off_energy && try_again) {
373  itry_gam++;
374  G4int itry = 0;
375  G4double T04 = 4.0 * T00;
376  G4double FMAX;
377 
378  if (T04 < EEXS) {
379  FMAX = (T04*T04*T04*T04) * G4Exp((EEXS - T04) / T00);
380  } else {
381  FMAX = EEXS*EEXS*EEXS*EEXS;
382  };
383 
384  if (verboseLevel > 3)
385  G4cout << " T04 " << T04 << " FMAX (EEXS^4) " << FMAX << G4endl;
386 
387  G4double S(0), X1(0);
388  while (itry < itry_max) {
389  itry++;
390  S = EEXS * inuclRndm();
391  X1 = (S*S*S*S) * G4Exp((EEXS - S) / T00);
392 
393  if (X1 > FMAX * inuclRndm()) break;
394  };
395 
396  if (itry == itry_max) { // Maximum attempts exceeded
397  try_again = false;
398  break;
399  }
400 
401  if (verboseLevel > 2) G4cout << " photon escape ?" << G4endl;
402 
403  if (S < EEXS) { // Valid evaporate
404  S /= GeV; // Convert to Bertini units
405 
406  G4double pmod = S;
407  G4LorentzVector mom = generateWithRandomAngles(pmod, 0.);
408 
409  // Push evaporated particle into current rest frame
410  mom = toTheNucleiSystemRestFrame.backToTheLab(mom);
411 
412  if (verboseLevel > 3) {
413  G4cout << " nucleus px " << PEX.px() << " py " << PEX.py()
414  << " pz " << PEX.pz() << " E " << PEX.e() << G4endl
415  << " evaporate px " << mom.px() << " py " << mom.py()
416  << " pz " << mom.pz() << " E " << mom.e() << G4endl;
417  }
418 
419  PEX -= mom; // Remaining four-momentum
420  EEXS -= S*GeV; // New excitation energy (in MeV)
421 
422  // NOTE: In-situ construction will be optimized away (no copying)
425 
426  if (verboseLevel > 3)
427  G4cout << output.getOutgoingParticles().back() << G4endl;
428 
429  ppout += mom;
430  } else {
431  if (itry_gam == itry_gam_max) try_again = false;
432  }
433  } // while (EEXS > cut_off
434  try_again = false;
435  } else { // if (prob_sum < prob_cut_off)
436  G4double SL = prob_sum * inuclRndm();
437  if (verboseLevel > 3) G4cout << " random SL " << SL << G4endl;
438 
439  G4double S1 = 0.0;
440  for (i = 0; i < 7; i++) { // Select evaporation scenario
441  S1 += W[i];
442  if (SL <= S1) {
443  icase = i;
444  break;
445  };
446  };
447 
448  if (icase < 0) continue; // Failed to choose scenario, try again
449 
450  if (icase < 6) { // particle or light nuclei escape
451  if (verboseLevel > 2) {
452  G4cout << " particle/light-ion escape ("
453  << (icase==0 ? "neutron" : icase==1 ? "proton" :
454  icase==2 ? "deuteron" : icase==3 ? "He3" :
455  icase==4 ? "triton" : icase==5 ? "alpha" : "ERROR!")
456  << ")?" << G4endl;
457  }
458 
459  G4double uc = 2.0 * std::sqrt(u[icase] * TM[icase]);
460  G4double ur = (uc > huge_num ? G4Exp(huge_num) : G4Exp(uc));
461  G4double d1 = 1.0 / ur;
462  G4double d2 = 1.0 / (ur - 1.0);
463  G4int itry1 = 0;
464  G4bool bad = true;
465 
466  while (itry1 < itry_max && bad) {
467  itry1++;
468  G4int itry = 0;
469  G4double EPR = -1.0;
470  G4double S = 0.0;
471 
472  while (itry < itry_max && EPR < 0.0) {
473  itry++;
474  G4double uu = uc + G4Log((1.0 - d1) * inuclRndm() + d2);
475  S = 0.5 * (uc * uc - uu * uu) / u[icase];
476  EPR = TM[icase] - S * A / (A - 1.0) + V[icase];
477  };
478 
479  if (verboseLevel > 3) {
480  G4cout << " EPR " << EPR << " V " << V[icase]
481  << " S " << S << " EEXS " << EEXS << G4endl;
482  }
483 
484  if (EPR > 0.0 && S > V[icase] && S < EEXS) { // real escape
485  if (verboseLevel > 2)
486  G4cout << " escape itry1 " << itry1 << " icase "
487  << icase << " S (MeV) " << S << G4endl;
488 
489  S /= GeV; // Convert to Bertini units
490 
491  if (icase < 2) { // particle escape
492  G4int ptype = 2 - icase;
493  if (verboseLevel > 2)
494  G4cout << " particle " << ptype << " escape" << G4endl;
495 
496  // generate particle momentum
497  G4double mass =
499 
500  G4double pmod = std::sqrt((2.0 * mass + S) * S);
501  G4LorentzVector mom = generateWithRandomAngles(pmod, mass);
502 
503  // Push evaporated particle into current rest frame
504  mom = toTheNucleiSystemRestFrame.backToTheLab(mom);
505 
506  if (verboseLevel > 2) {
507  G4cout << " nucleus px " << PEX.px() << " py " << PEX.py()
508  << " pz " << PEX.pz() << " E " << PEX.e() << G4endl
509  << " evaporate px " << mom.px() << " py " << mom.py()
510  << " pz " << mom.pz() << " E " << mom.e() << G4endl;
511  }
512 
513  // New excitation energy depends on residual nuclear state
514  G4double mass_new =
515  G4InuclNuclei::getNucleiMass(A1[icase],Z1[icase]);
516 
517  G4double EEXS_new = ((PEX-mom).m() - mass_new)*GeV;
518  if (EEXS_new < 0.0) continue; // Sanity check for new nucleus
519 
520  PEX -= mom; // Remaining four-momentum
521  EEXS = EEXS_new;
522 
523  A = A1[icase];
524  Z = Z1[icase];
525 
526  // NOTE: In-situ construction optimizes away (no copying)
528  ptype, G4InuclParticle::Equilib));
529 
530  if (verboseLevel > 3)
531  G4cout << output.getOutgoingParticles().back() << G4endl;
532 
533  ppout += mom;
534  bad = false;
535  } else { // if (icase < 2)
536  if (verboseLevel > 2) {
537  G4cout << " nucleus A " << AN[icase] << " Z " << Q[icase]
538  << " escape icase " << icase << G4endl;
539  }
540 
541  G4double mass =
542  G4InuclNuclei::getNucleiMass(AN[icase],Q[icase]);
543 
544  // generate particle momentum
545  G4double pmod = std::sqrt((2.0 * mass + S) * S);
546  G4LorentzVector mom = generateWithRandomAngles(pmod,mass);
547 
548  // Push evaporated particle into current rest frame
549  mom = toTheNucleiSystemRestFrame.backToTheLab(mom);
550 
551  if (verboseLevel > 2) {
552  G4cout << " nucleus px " << PEX.px() << " py " << PEX.py()
553  << " pz " << PEX.pz() << " E " << PEX.e() << G4endl
554  << " evaporate px " << mom.px() << " py " << mom.py()
555  << " pz " << mom.pz() << " E " << mom.e() << G4endl;
556  }
557 
558  // New excitation energy depends on residual nuclear state
559  G4double mass_new =
560  G4InuclNuclei::getNucleiMass(A1[icase],Z1[icase]);
561 
562  G4double EEXS_new = ((PEX-mom).m() - mass_new)*GeV;
563  if (EEXS_new < 0.0) continue; // Sanity check for new nucleus
564 
565  PEX -= mom; // Remaining four-momentum
566  EEXS = EEXS_new;
567 
568  A = A1[icase];
569  Z = Z1[icase];
570 
571  // NOTE: In-situ constructor optimizes away (no copying)
573  AN[icase], Q[icase], 0.*GeV,
575 
576  if (verboseLevel > 3)
577  G4cout << output.getOutgoingNuclei().back() << G4endl;
578 
579  ppout += mom;
580  bad = false;
581  } // if (icase < 2)
582  } // if (EPR > 0.0 ...
583  } // while (itry1 ...
584 
585  if (itry1 == itry_max || bad) try_again = false;
586  } else { // if (icase < 6)
587  if (verboseLevel > 2) {
588  G4cout << " fission: A " << A << " Z " << Z << " eexs " << EEXS
589  << " Wn " << W[0] << " Wf " << W[6] << G4endl;
590  }
591 
592  // Catch fission output separately for verification
593  fission_output.reset();
594  theFissioner.deExcite(makeFragment(A,Z,EEXS), fission_output);
595 
596  if (fission_output.numberOfFragments() == 2) { // fission ok
597  if (verboseLevel > 2) G4cout << " fission done in eql" << G4endl;
598 
599  // Move fission fragments to lab frame for processing
600  fission_output.boostToLabFrame(toTheNucleiSystemRestFrame);
601 
602  // Now evaporate the fission fragments individually
603  this->deExcite(fission_output.getRecoilFragment(0), output);
604  this->deExcite(fission_output.getRecoilFragment(1), output);
605 
606  validateOutput(target, output); // Check energy conservation
607  return;
608  } else { // fission forbidden now
609  fission_open = false;
610  }
611  } // End of fission case
612  } // if (prob_sum < prob_cut_off)
613  } // while (try_again
614 
615  // this time it's final nuclei
616 
617  if (itry_global == itry_global_max) {
618  if (verboseLevel > 3) {
619  G4cout << " ! itry_global " << itry_global_max << G4endl;
620  }
621  }
622 
623  G4LorentzVector pnuc = pin - ppout;
624 
625  // NOTE: In-situ constructor will be optimized away (no copying)
626  output.addOutgoingNucleus(G4InuclNuclei(pnuc, A, Z, 0.,
628 
629  if (verboseLevel > 3) {
630  G4cout << " remaining nucleus \n" << output.getOutgoingNuclei().back()
631  << G4endl;
632  }
633 
634 
635  validateOutput(target, output); // Check energy conservation
636  return;
637 }
638 
639 G4bool G4EquilibriumEvaporator::explosion(G4int a,
640  G4int z,
641  G4double e) const {
642  if (verboseLevel > 3) {
643  G4cout << " >>> G4EquilibriumEvaporator::explosion? ";
644  }
645 
646  const G4double be_cut = 3.0;
647 
648  // Different criteria from base class, since nucleus more "agitated"
649  G4bool bigb = (!(a >= 12 && z >= 0 && z < 3*(a-z)) &&
650  (e >= be_cut * bindingEnergy(a,z))
651  );
652 
653  if (verboseLevel > 3) G4cout << bigb << G4endl;
654 
655  return bigb;
656 }
657 
658 G4bool G4EquilibriumEvaporator::goodRemnant(G4int a,
659  G4int z) const {
660  if (verboseLevel > 3) {
661  G4cout << " >>> G4EquilibriumEvaporator::goodRemnant(" << a << "," << z
662  << ")? " << (a>1 && z>0 && a>z) << G4endl;
663  }
664 
665  return a > 1 && z > 0 && a > z;
666 }
667 
668 G4double G4EquilibriumEvaporator::getQF(G4double x,
669  G4double x2,
670  G4int a,
671  G4int /*z*/,
672  G4double ) const {
673  if (verboseLevel > 3) {
674  G4cout << " >>> G4EquilibriumEvaporator::getQF ";
675  }
676 
677  const G4double G0 = 20.4;
678  const G4double XMIN = 0.6761;
679  const G4double XMAX = 0.8274;
680 
681  G4double QFF = 0.0;
682 
683  if (x < XMIN || x > XMAX) {
684  G4double X1 = 1.0 - 0.02 * x2;
685  G4double FX = (0.73 + (3.33 * X1 - 0.66) * X1) * (X1*X1*X1);
686  G4double A13 = G4cbrt(a);
687  QFF = G0 * FX * A13*A13;
688  } else {
689  QFF = QFinterp.interpolate(x, QFREP);
690  }
691 
692  if (QFF < 0.0) QFF = 0.0;
693 
694  if (verboseLevel>3) G4cout << " returns " << QFF << G4endl;
695 
696  return QFF;
697 }
698 
699 G4double G4EquilibriumEvaporator::getAF(G4double ,
700  G4int /*a*/,
701  G4int /*z*/,
702  G4double e) const {
703 
704  if (verboseLevel > 3) {
705  G4cout << " >>> G4EquilibriumEvaporator::getAF" << G4endl;
706  }
707 
708  // ugly parameterisation to fit the experimental fission cs for Hg - Bi nuclei
709  G4double AF = 1.285 * (1.0 - e / 1100.0);
710 
711  if(AF < 1.06) AF = 1.06;
712  // if(AF < 1.08) AF = 1.08;
713 
714  return AF;
715 }
716 
717 G4double G4EquilibriumEvaporator::getPARLEVDEN(G4int /*a*/,
718  G4int /*z*/) const {
719 
720  if (verboseLevel > 3) {
721  G4cout << " >>> G4EquilibriumEvaporator::getPARLEVDEN" << G4endl;
722  }
723 
724  const G4double par = 0.125;
725 
726  return par;
727 }
728 
729 G4double G4EquilibriumEvaporator::getE0(G4int /*a*/) const {
730 
731  if (verboseLevel > 3) {
732  G4cout << " >>> G4EquilibriumEvaporator::getE0" << G4endl;
733  }
734 
735  const G4double e0 = 200.0;
736 
737  return e0;
738 }
virtual void setVerboseLevel(G4int verbose=0)
static const G4double d1
#define A13
Double_t x2[nxs]
double S(double temp)
Double_t X1
static double Q[]
void addOutgoingParticle(const G4InuclElementaryParticle &particle)
Double_t X2
const std::vector< G4InuclElementaryParticle > & getOutgoingParticles() const
static G4double getParticleMass(G4int type)
void setBullet(const G4InuclParticle *bullet)
int G4int
Definition: G4Types.hh:78
Float_t X
G4GLOB_DLL std::ostream G4cout
double A(double temperature)
Float_t Z
bool G4bool
Definition: G4Types.hh:79
G4LorentzVector backToTheLab(const G4LorentzVector &mom) const
static const double GeV
Definition: G4SIunits.hh:214
G4double G4Log(G4double x)
Definition: G4Log.hh:230
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:183
G4double getNucleiMass() const
static const G4double * SL[nLA]
cout<< "-> Edep in the target
Definition: analysis.C:54
#define G4endl
Definition: G4ios.hh:61
static const double m
Definition: G4SIunits.hh:128
void addOutgoingNucleus(const G4InuclNuclei &nuclei)
void addRecoilFragment(const G4Fragment *aFragment)
double G4double
Definition: G4Types.hh:76
const std::vector< G4InuclNuclei > & getOutgoingNuclei() const
static const G4double d2
Double_t Z1
void setTarget(const G4InuclParticle *target)