Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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