Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Fissioner.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$
27 //
28 // 20100114 M. Kelsey -- Remove G4CascadeMomentum, use G4LorentzVector directly
29 // 20100318 M. Kelsey -- Bug fix setting mass with G4LV
30 // 20100319 M. Kelsey -- Use new generateWithRandomAngles for theta,phi stuff;
31 // eliminate some unnecessary std::pow()
32 // 20100413 M. Kelsey -- Pass G4CollisionOutput by ref to ::collide()
33 // 20100517 M. Kelsey -- Inherit from common base class
34 // 20100622 M. Kelsey -- Use local "bindingEnergy()" to call through
35 // 20100711 M. Kelsey -- Add energy-conservation checking, reduce if-cascades
36 // 20100713 M. Kelsey -- Don't add excitation energy to mass (already there)
37 // 20100714 M. Kelsey -- Move conservation checking to base class
38 // 20100728 M. Kelsey -- Make fixed arrays static, move G4FissionStore to data
39 // member and reuse
40 // 20100914 M. Kelsey -- Migrate to integer A and Z
41 // 20110214 M. Kelsey -- Follow G4InuclParticle::Model enumerator migration
42 // 20110801 M. Kelsey -- Replace constant-size std::vector's w/C arrays
43 // 20110922 M. Kelsey -- Follow G4InuclParticle::print(ostream&) migration
44 // 20120517 A. Ribon -- Removed static in local vectors for reproducibility
45 
46 #include "G4Fissioner.hh"
47 #include "G4CollisionOutput.hh"
48 #include "G4HadTmpUtil.hh"
49 #include "G4InuclNuclei.hh"
50 #include "G4InuclParticle.hh"
51 #include "G4FissionStore.hh"
54 
55 using namespace G4InuclSpecialFunctions;
56 
57 
59 
62  G4CollisionOutput& output) {
63  if (verboseLevel) {
64  G4cout << " >>> G4Fissioner::collide" << G4endl;
65  }
66 
67  // const G4int itry_max = 1000;
68 
69  G4InuclNuclei* nuclei_target = dynamic_cast<G4InuclNuclei*>(target);
70  if (!nuclei_target) {
71  G4cerr << " >>> G4Fissioner -> target is not nuclei " << G4endl;
72  return;
73  }
74 
75  if (verboseLevel > 1)
76  G4cout << " Fissioner input\n" << *nuclei_target << G4endl;
77 
78  // Initialize buffer for fission possibilities
79  fissionStore.setVerboseLevel(verboseLevel);
80  fissionStore.clear();
81 
82  G4int A = nuclei_target->getA();
83  G4int Z = nuclei_target->getZ();
84 
85  G4double EEXS = nuclei_target->getExitationEnergy();
86  G4double mass_in = nuclei_target->getMass();
87  G4double e_in = mass_in; // Mass includes excitation
88  G4double PARA = 0.055 * G4cbrt(A*A) * (G4cbrt(A-Z) + G4cbrt(Z));
89  G4double TEM = std::sqrt(EEXS / PARA);
90  G4double TETA = 0.494 * G4cbrt(A) * TEM;
91 
92  TETA = TETA / std::sinh(TETA);
93 
94  if (A < 246) PARA += (nucleiLevelDensity(A) - PARA) * TETA;
95 
96  G4int A1 = A/2 + 1;
97  G4int Z1;
98  G4int A2 = A - A1;
99 
100  G4double ALMA = -1000.0;
101  G4double DM1 = bindingEnergy(A,Z);
102  G4double EVV = EEXS - DM1;
103  G4double DM2 = bindingEnergyAsymptotic(A, Z);
104  G4double DTEM = (A < 220 ? 0.5 : 1.15);
105 
106  TEM += DTEM;
107 
108  G4double AL1[2] = { -0.15, -0.15 };
109  G4double BET1[2] = { 0.05, 0.05 };
110 
111  G4double R12 = G4cbrt(A1) + G4cbrt(A2);
112 
113  for (G4int i = 0; i < 50 && A1 > 30; i++) {
114  A1--;
115  A2 = A - A1;
116  G4double X3 = 1.0 / G4cbrt(A1);
117  G4double X4 = 1.0 / G4cbrt(A2);
118  Z1 = G4lrint(getZopt(A1, A2, Z, X3, X4, R12) - 1.);
119  G4double EDEF1[2];
120  G4int Z2 = Z - Z1;
121  G4double VPOT, VCOUL;
122 
123  potentialMinimization(VPOT, EDEF1, VCOUL, A1, A2, Z1, Z2, AL1, BET1, R12);
124 
125  G4double DM3 = bindingEnergy(A1,Z1);
126  G4double DM4 = bindingEnergyAsymptotic(A1, Z1);
127  G4double DM5 = bindingEnergy(A2,Z2);
128  G4double DM6 = bindingEnergyAsymptotic(A2, Z2);
129  G4double DMT1 = DM4 + DM6 - DM2;
130  G4double DMT = DM3 + DM5 - DM1;
131  G4double EZL = EEXS + DMT - VPOT;
132 
133  if(EZL > 0.0) { // generate fluctuations
134  // faster, using randomGauss
135  G4double C1 = std::sqrt(getC2(A1, A2, X3, X4, R12) / TEM);
136  G4double DZ = randomGauss(C1);
137 
138  DZ = DZ > 0.0 ? DZ + 0.5 : -std::fabs(DZ - 0.5);
139  Z1 += G4int(DZ);
140  Z2 -= G4int(DZ);
141 
142  G4double DEfin = randomGauss(TEM);
143  G4double EZ = (DMT1 + (DMT - DMT1) * TETA - VPOT + DEfin) / TEM;
144 
145  if (EZ >= ALMA) ALMA = EZ;
146  G4double EK = VCOUL + DEfin + 0.5 * TEM;
147  G4double EV = EVV + bindingEnergy(A1,Z1) + bindingEnergy(A2,Z2) - EK;
148 
149  if (EV > 0.0) fissionStore.addConfig(A1, Z1, EZ, EK, EV);
150  };
151  };
152 
153  G4int store_size = fissionStore.size();
154  if (store_size == 0) return; // No fission products
155 
157  fissionStore.generateConfiguration(ALMA, inuclRndm());
158 
159  A1 = G4int(config.afirst);
160  A2 = A - A1;
161  Z1 = G4int(config.zfirst);
162 
163  G4int Z2 = Z - Z1;
164 
165  G4double mass1 = G4InuclNuclei::getNucleiMass(A1,Z1);
166  G4double mass2 = G4InuclNuclei::getNucleiMass(A2,Z2);
167  G4double EK = config.ekin;
168  G4double pmod = std::sqrt(0.001 * EK * mass1 * mass2 / mass_in);
169 
170  G4LorentzVector mom1 = generateWithRandomAngles(pmod, mass1);
171  G4LorentzVector mom2; mom2.setVectM(-mom1.vect(), mass2);
172 
173  G4double e_out = mom1.e() + mom2.e();
174  G4double EV = 1000.0 * (e_in - e_out) / A;
175  if (EV <= 0.0) return; // No fission energy
176 
177  G4double EEXS1 = EV*A1;
178  G4double EEXS2 = EV*A2;
179 
180  G4InuclNuclei nuclei1(mom1, A1, Z1, EEXS1, G4InuclParticle::Fissioner);
181  G4InuclNuclei nuclei2(mom2, A2, Z2, EEXS2, G4InuclParticle::Fissioner);
182 
183  // Pass only last two nuclear fragments
184  static std::vector<G4InuclNuclei> frags(2); // Always the same size!
185  frags[0] = nuclei1;
186  frags[1] = nuclei2;
187  validateOutput(0, target, frags); // Check energy conservation
188 
189  output.addOutgoingNuclei(frags);
190 }
191 
192 G4double G4Fissioner::getC2(G4int A1,
193  G4int A2,
194  G4double X3,
195  G4double X4,
196  G4double R12) const {
197 
198  if (verboseLevel > 3) {
199  G4cout << " >>> G4Fissioner::getC2" << G4endl;
200  }
201 
202  G4double C2 = 124.57 * (1.0 / A1 + 1.0 / A2) + 0.78 * (X3 + X4) - 176.9 *
203  ((X3*X3*X3*X3) + (X4*X4*X4*X4)) + 219.36 * (1.0 / (A1 * A1) + 1.0 / (A2 * A2)) - 1.108 / R12;
204 
205  return C2;
206 }
207 
208 G4double G4Fissioner::getZopt(G4int A1,
209  G4int A2,
210  G4int ZT,
211  G4double X3,
212  G4double X4,
213  G4double R12) const {
214 
215  if (verboseLevel > 3) {
216  G4cout << " >>> G4Fissioner::getZopt" << G4endl;
217  }
218 
219  G4double Zopt = (87.7 * (X4 - X3) * (1.0 - 1.25 * (X4 + X3)) +
220  ZT * ((124.57 / A2 + 0.78 * X4 - 176.9 * (X4*X4*X4*X4) + 219.36 / (A2 * A2)) - 0.554 / R12)) /
221  getC2(A1, A2, X3, X4, R12);
222 
223  return Zopt;
224 }
225 
226 void G4Fissioner::potentialMinimization(G4double& VP,
227  G4double( &ED)[2],
228  G4double& VC,
229  G4int AF,
230  G4int AS,
231  G4int ZF,
232  G4int ZS,
233  G4double AL1[2],
234  G4double BET1[2],
235  G4double& R12) const {
236 
237  if (verboseLevel > 3) {
238  G4cout << " >>> G4Fissioner::potentialMinimization" << G4endl;
239  }
240 
241  const G4double huge_num = 2.0e35;
242  const G4int itry_max = 2000;
243  const G4double DSOL1 = 1.0e-6;
244  const G4double DS1 = 0.3;
245  const G4double DS2 = 1.0 / DS1 / DS1;
246  G4int A1[2] = { AF, AS };
247  G4int Z1[2] = { ZF, ZS };
248  G4double D = 1.01844 * ZF * ZS;
249  G4double D0 = 1.0e-3 * D;
250  G4double R[2];
251  R12 = 0.0;
252  G4double C[2];
253  G4double F[2];
254  G4double Y1;
255  G4double Y2;
256  G4int i;
257 
258  for (i = 0; i < 2; i++) {
259  R[i] = G4cbrt(A1[i]);
260  Y1 = R[i] * R[i];
261  Y2 = Z1[i] * Z1[i] / R[i];
262  C[i] = 6.8 * Y1 - 0.142 * Y2;
263  F[i] = 12.138 * Y1 - 0.145 * Y2;
264  };
265 
266  G4double SAL[2];
267  G4double SBE[2];
268  G4double X[2];
269  G4double X1[2];
270  G4double X2[2];
271  G4double RAL[2];
272  G4double RBE[2];
273  G4double A[4][4];
274  G4double B[4];
275  G4int itry = 0;
276 
277  while (itry < itry_max) {
278  itry++;
279  G4double S = 0.0;
280 
281  for (i = 0; i < 2; i++) {
282  S += R[i] * (1.0 + AL1[i] + BET1[i] - 0.257 * AL1[i] * BET1[i]);
283  };
284  R12 = 0.0;
285  Y1 = 0.0;
286  Y2 = 0.0;
287 
288  for (i = 0; i < 2; i++) {
289  SAL[i] = R[i] * (1.0-0.257 * BET1[i]);
290  SBE[i] = R[i] * (1.0-0.257 * AL1[i]);
291  X[i] = R[i] / S;
292  X1[i] = X[i] * X[i];
293  X2[i] = X[i] * X1[i];
294  Y1 += AL1[i] * X1[i];
295  Y2 += BET1[i] * X2[i];
296  R12 += R[i] * (1.0 - AL1[i] * (1.0 - 0.6 * X[i]) + BET1[i] * (1.0 - 0.429 * X1[i]));
297  };
298 
299  G4double Y3 = -0.6 * Y1 + 0.857 * Y2;
300  G4double Y4 = (1.2 * Y1 - 2.571 * Y2) / S;
301  G4double R2 = D0 / (R12 * R12);
302  G4double R3 = 2.0 * R2 / R12;
303 
304  for (i = 0; i < 2; i++) {
305  RAL[i] = -R[i] * (1.0 - 0.6 * X[i]) + SAL[i] * Y3;
306  RBE[i] = R[i] * (1.0 - 0.429 * X1[i]) + SBE[i] * Y3;
307  };
308 
309  G4double DX1;
310  G4double DX2;
311 
312  for (i = 0; i < 2; i++) {
313 
314  for (G4int j = 0; j < 2; j++) {
315  G4double DEL1 = i == j ? 1.0 : 0.0;
316  DX1 = 0.0;
317  DX2 = 0.0;
318 
319  if (std::fabs(AL1[i]) >= DS1) {
320  G4double XXX = AL1[i] * AL1[i] * DS2;
321  G4double DEX = XXX > 100.0 ? huge_num : std::exp(XXX);
322  DX1 = 2.0 * (1.0 + 2.0 * AL1[i] * AL1[i] * DS2) * DEX * DS2;
323  };
324 
325  if (std::fabs(BET1[i]) >= DS1) {
326  G4double XXX = BET1[i] * BET1[i] * DS2;
327  G4double DEX = XXX > 100.0 ? huge_num : std::exp(XXX);
328  DX2 = 2.0 * (1.+2.0 * BET1[i] * BET1[i] * DS2) * DEX * DS2;
329  };
330 
331  G4double DEL = 2.0e-3 * DEL1;
332  A[i][j] = R3 * RBE[i] * RBE[j] -
333  R2 * (-0.6 *
334  (X1[i] * SAL[j] +
335  X1[j] * SAL[i]) + SAL[i] * SAL[j] * Y4) +
336  DEL * C[i] + DEL1 * DX1;
337  G4int i1 = i + 2;
338  G4int j1 = j + 2;
339  A[i1][j1] = R3 * RBE[i] * RBE[j]
340  - R2 * (0.857 *
341  (X2[i] * SBE[j] +
342  X2[j] * SBE[i]) + SBE[i] * SBE[j] * Y4) +
343  DEL * F[i] + DEL1 * DX2;
344  A[i][j1] = R3 * RAL[i] * RBE[j] -
345  R2 * (0.857 *
346  (X2[j] * SAL[i] -
347  0.6 * X1[i] * SBE[j]) + SBE[j] * SAL[i] * Y4 -
348  0.257 * R[i] * Y3 * DEL1);
349  A[j1][i] = A[i][j1];
350  };
351  };
352 
353  for (i = 0; i < 2; i++) {
354  DX1 = 0.0;
355  DX2 = 0.0;
356 
357  if (std::fabs(AL1[i]) >= DS1) DX1 = 2.0 * AL1[i] * DS2 * std::exp(AL1[i] * AL1[i] * DS2);
358 
359  if (std::fabs(BET1[i]) >= DS1) DX2 = 2.0 * BET1[i] * DS2 * std::exp(BET1[i] * BET1[i] * DS2);
360  B[i] = R2 * RAL[i] - 2.0e-3 * C[i] * AL1[i] + DX1;
361  B[i + 2] = R2 * RBE[i] - 2.0e-3 * F[i] * BET1[i] + DX2;
362  };
363 
364  G4double ST = 0.0;
365  G4double ST1 = 0.0;
366 
367  for (i = 0; i < 4; i++) {
368  ST += B[i] * B[i];
369 
370  for (G4int j = 0; j < 4; j++) ST1 += A[i][j] * B[i] * B[j];
371  };
372 
373  G4double STEP = ST / ST1;
374  G4double DSOL = 0.0;
375 
376  for (i = 0; i < 2; i++) {
377  AL1[i] += B[i] * STEP;
378  BET1[i] += B[i + 2] * STEP;
379  DSOL += B[i] * B[i] + B[i + 2] * B[i + 2];
380  };
381  DSOL = std::sqrt(DSOL);
382 
383  if (DSOL < DSOL1) break;
384  };
385 
386  if (verboseLevel > 3) {
387  if (itry == itry_max)
388  G4cout << " maximal number of iterations in potentialMinimization " << G4endl
389  << " A1 " << AF << " Z1 " << ZF << G4endl;
390 
391  };
392 
393  for (i = 0; i < 2; i++) ED[i] = F[i] * BET1[i] * BET1[i] + C[i] * AL1[i] * AL1[i];
394 
395  VC = D / R12;
396  VP = VC + ED[0] + ED[1];
397 }