Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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
55using namespace G4InuclSpecialFunctions;
56
57
59
61 G4InuclParticle* target,
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;
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
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
192G4double 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
208G4double 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
226void 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}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
#define C1
void setVectM(const Hep3Vector &spatial, double mass)
Hep3Vector vect() const
virtual G4bool validateOutput(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
void addOutgoingNuclei(const std::vector< G4InuclNuclei > &nuclea)
size_t size() const
void addConfig(G4double a, G4double z, G4double ez, G4double ek, G4double ev)
void setVerboseLevel(G4int verbose=1)
G4FissionConfiguration generateConfiguration(G4double amax, G4double rand) const
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
Definition: G4Fissioner.cc:60
G4double getNucleiMass() const
G4int getZ() const
G4double getExitationEnergy() const
G4int getA() const
G4double getMass() const
G4double bindingEnergy(G4int A, G4int Z)
G4double nucleiLevelDensity(G4int A)
G4LorentzVector generateWithRandomAngles(G4double p, G4double mass=0.)
G4double randomGauss(G4double sigma)
G4double bindingEnergyAsymptotic(G4int A, G4int Z)
int G4lrint(double ad)
Definition: templates.hh:163