Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4FermiFragmentsPoolVI.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//
27// FermiBreakUp de-excitation model
28// by V. Ivanchenko (July 2016)
29//
30
33#include "G4SystemOfUnits.hh"
34#include "G4NuclearLevelData.hh"
35#include "G4LevelManager.hh"
37#include <iomanip>
38
40{
41 // G4cout << "### G4FermiFragmentsPoolVI is constructed" << G4endl;
42 G4DeexPrecoParameters* param =
44 tolerance = param->GetMinExcitation();
45 timelim = (G4float)param->GetMaxLifeTime();
46
47 elim = param->GetFBUEnergyLimit();
48 elimf= (G4float)elim;
49 /*
50 G4cout << "G4FermiFragmentsPoolVI: tolerance= " << tolerance
51 << " timelim= " << timelim << " elim= " << elim << G4endl;
52 */
53 fragment_pool.reserve(991);
54 Initialise();
55}
56
58{
59 for(G4int i=0; i<maxA; ++i) {
60 for(auto & ptr : list_p[i]) { delete ptr; ptr = nullptr; }
61 for(auto & ptr : list_c[i]) { delete ptr; ptr = nullptr; }
62 }
63 for(auto & ptr : fragment_pool) { delete ptr; ptr = nullptr; }
64}
65
66const G4FermiChannels*
68{
69 const G4FermiChannels* res = nullptr;
70 G4double demax = 1.e+9;
71
72 // stable channels
73 for(std::size_t j=0; j<(list_c[A]).size(); ++j) {
74 const G4FermiFragment* frag = (list_f[A])[j];
75 if(frag->GetZ() != Z) { continue; }
76 G4double de = e - frag->GetTotalEnergy();
77 //G4cout << " Stab check " << j << " channel de= " << de
78 // << " tol= " << tolerance << G4endl;
79 // an excitation coincide with a level
80 if(std::abs(de) <= tolerance) {
81 res = (list_c[A])[j];
82 break;
83 } else {
84 // closest level selected
85 de += tolerance;
86 if(de >= 0.0 && de <= demax) {
87 res = (list_c[A])[j];
88 demax = de;
89 }
90 //G4cout << " Stab chan: " << j << " N= "
91 //<< res->GetNumberOfChannels() << G4endl;
92 }
93 }
94 return res;
95}
96
98{
99 for(auto const& ptr : list_f[A]) {
100 if(ptr->GetZ() == Z) { return true; }
101 }
102 return false;
103}
104
105G4bool G4FermiFragmentsPoolVI::IsInThePool(G4int Z, G4int A,
106 G4double exc) const
107{
108 for(auto const& fr : fragment_pool) {
109 if(fr->GetZ() == Z && fr->GetA() == A &&
110 std::abs(exc - fr->GetExcitationEnergy()) < tolerance)
111 { return true; }
112 }
113 return false;
114}
115
116G4bool
118{
119 // stable fragment
120 for(std::size_t j=0; j<(list_f[A]).size(); ++j) {
121 const G4FermiFragment* frag = (list_f[A])[j];
122 if(frag->GetZ() == Z) {
123 if(exc > frag->GetExcitationEnergy() &&
124 (list_c[A])[j]->GetNumberOfChannels() > 0) { return true; }
125 }
126 }
127 return false;
128}
129
130G4bool G4FermiFragmentsPoolVI::IsInPhysPairs(
131 const G4FermiFragment* f1, const G4FermiFragment* f2) const
132{
133 const G4int A = f1->GetA() + f2->GetA();
134 for(auto const& ptr : list_p[A]) {
135 if(f1 == ptr->GetFragment1() && f2 == ptr->GetFragment2()) {
136 return true;
137 }
138 }
139 return false;
140}
141
142void G4FermiFragmentsPoolVI::Initialise()
143{
144 //G4cout << "G4FermiFragmentsPoolVI::Initialise main loop @@@@@@" << G4endl;
145
146 // stable particles
147 fragment_pool.push_back(new G4FermiFragment(1, 0, 1, 0.0));
148 fragment_pool.push_back(new G4FermiFragment(1, 1, 1, 0.0));
149 fragment_pool.push_back(new G4FermiFragment(2, 1, 2, 0.0));
150 fragment_pool.push_back(new G4FermiFragment(3, 1, 1, 0.0));
151 fragment_pool.push_back(new G4FermiFragment(3, 2, 1, 0.0));
152 fragment_pool.push_back(new G4FermiFragment(4, 2, 0, 0.0));
153 fragment_pool.push_back(new G4FermiFragment(5, 2, 3, 0.0));
154 fragment_pool.push_back(new G4FermiFragment(5, 3, 3, 0.0));
155
156 // use level data and construct the pool
158 for(G4int Z=1; Z<maxZ; ++Z) {
159 G4int Amin = ndata->GetMinA(Z);
160 G4int Amax = std::min(maxA, ndata->GetMaxA(Z)+1);
161 for(G4int A=Amin; A<Amax; ++A) {
162 const G4LevelManager* man = ndata->GetLevelManager(Z, A);
163 if(man) {
164 std::size_t nn = man->NumberOfTransitions();
165 // very unstable state
166 if(ndata->MaxLevelEnergy(Z, A) == 0.0f && man->LifeTime(0) == 0.0f) {
167 continue;
168 }
169 for(std::size_t i=0; i<=nn; ++i) {
170 G4float exc = man->LevelEnergy(i);
171 /*
172 G4cout << "Z= " << Z << " A= " << A << " Eex= " << exc
173 << " elimf= " << elimf << " toler= " << tolerance
174 << " time= " << man->LifeTime(i) << " i= " << i << G4endl;
175 */
176 // only levels below limit are consided
177 if(exc >= elimf) { continue; }
178 G4double excd = (G4double)exc;
179 // only new are considered
180 if(IsInThePool(Z, A, excd)) { continue; }
181 fragment_pool.push_back(new G4FermiFragment(A,Z,man->SpinTwo(i),excd));
182 }
183 }
184 }
185 }
186 G4int nfrag = (G4int)fragment_pool.size();
187 // prepare structures per A for normal fragments
188 const std::size_t lfmax[maxA] = {
189 0, 2, 1, 2, 1, 2, 8, 19, 28, 56, 70, 104, 74, 109, 143, 212, 160};
190 for(G4int A=1; A<maxA; ++A) {
191 list_f[A].reserve(lfmax[A]);
192 list_c[A].reserve(lfmax[A]);
193 }
194 const std::size_t lfch[maxA] = {
195 0, 0, 0, 0, 0, 1, 4, 8, 6, 13, 27, 40, 29, 21, 31, 32, 30};
196
197 for(auto const& f : fragment_pool) {
198 G4int A = f->GetA();
199 G4double exc = f->GetExcitationEnergy();
200 list_f[A].push_back(f);
201 list_c[A].push_back(new G4FermiChannels(lfch[A], exc, f->GetTotalEnergy()));
202 }
203 /*
204 G4cout << "Defined fragments @@@@@@"
205 << " PhysicalFrag= " << nfrag
206 << " UnphysicalFrag= " << funstable.size() << G4endl;
207 */
208 // list of fragment pairs ordered by A
209 for(G4int i=0; i<nfrag; ++i) {
210 const G4FermiFragment* f1 = fragment_pool[i];
211 G4int Z1 = f1->GetZ();
212 G4int A1 = f1->GetA();
213 G4double e1 = f1->GetTotalEnergy();
214 for(G4int j=0; j<nfrag; ++j) {
215 const G4FermiFragment* f2 = fragment_pool[j];
216 G4int Z2 = f2->GetZ();
217 G4int A2 = f2->GetA();
218 if(A2 < A1 || (A2 == A1 && Z2 < Z1)) { continue; }
219 G4int Z = Z1 + Z2;
220 G4int A = A1 + A2;
221
222 if(Z >= maxZ || A >= maxA || IsInPhysPairs(f1, f2)) { continue; }
223
224 G4double e2 = f2->GetTotalEnergy();
225 G4double minE = e1 + e2;
226 G4double exc = 0.0;
227 if(IsPhysical(Z, A)) {
228 minE += f1->GetCoulombBarrier(A2, Z2, 0.0);
230 }
231 /*
232 G4cout << "Z= " << Z << " A= " << A
233 << " Z1= " << Z1 << " A1= " << A1
234 << " Z2= " << Z2 << " A2= " << A2 << " Eex= " << exc
235 << " Qb= " << f1->GetCoulombBarrier(A2, Z2, 0.0)
236 << " " << e1
237 << " " << e2
238 << " " << G4NucleiProperties::GetNuclearMass(A, Z)
239 << G4endl;
240 */
241 // ignore very excited case
242 if(exc >= elim) { continue; }
243 G4FermiPair* fpair = nullptr;
244 std::size_t kmax = list_f[A].size();
245 for(std::size_t k=0; k<kmax; ++k) {
246 const G4FermiFragment* f3 = (list_f[A])[k];
247 if(Z == f3->GetZ() &&
248 f3->GetTotalEnergy() - minE + tolerance >= 0.0) {
249 if(!fpair) {
250 fpair = new G4FermiPair(f1, f2);
251 list_p[A].push_back(fpair);
252 }
253 (list_c[A])[k]->AddChannel(fpair);
254 }
255 }
256 }
257 }
258 // compute static probabilities
259 for(G4int A=1; A<maxA; ++A) {
260 for(std::size_t j=0; j<list_c[A].size(); ++j) {
261 G4FermiChannels* ch = (list_c[A])[j];
262 const G4FermiFragment* frag = (list_f[A])[j];
263 std::size_t nch = ch->GetNumberOfChannels();
264 if(1 < nch) {
265 std::vector<G4double>& prob = ch->GetProbabilities();
266 const std::vector<const G4FermiPair*>& pairs = ch->GetChannels();
267 G4double ptot = 0.0;
268 for(std::size_t i=0; i<nch; ++i) {
269 ptot += theDecay.ComputeProbability(frag->GetZ(), frag->GetA(),
270 frag->GetSpin(),
271 frag->GetTotalEnergy(),
272 pairs[i]->GetFragment1(),
273 pairs[i]->GetFragment2());
274 prob[i] = ptot;
275 }
276 if(0.0 == ptot) {
277 prob[0] = 1.0;
278 } else {
279 ptot = 1./ptot;
280 for(std::size_t i=0; i<nch-1; ++i) { prob[i] *= ptot; }
281 prob[nch-1] = 1.0;
282 }
283 }
284 }
285 }
286}
287
289{
290 if(f) {
291 G4long prec = G4cout.precision(6);
292 G4cout << " Z= " << f->GetZ() << " A= " << std::setw(2) << f->GetA()
293 << " Mass(GeV)= " << std::setw(8) << f->GetFragmentMass()/GeV
294 << " Eexc(MeV)= " << std::setw(7) << f->GetExcitationEnergy()
295 << " 2s= " << f->GetSpin() << " IsStable: "
296 << HasChannels(f->GetZ(), f->GetA(), f->GetExcitationEnergy())
297 << G4endl;
298 G4cout.precision(prec);
299 }
300}
301
303{
304 G4cout <<"----------------------------------------------------------------"
305 <<G4endl;
306 G4cout << "##### List of Fragments in the Fermi Fragment Pool #####"
307 << G4endl;
308 std::size_t nfrag = fragment_pool.size();
309 G4cout << " For stable " << nfrag << " Elim(MeV) = "
310 << elim/CLHEP::MeV << G4endl;
311 for(std::size_t i=0; i<nfrag; ++i) {
312 DumpFragment(fragment_pool[i]);
313 }
314 G4cout << G4endl;
315
316
317 G4cout << "----------------------------------------------------------------"
318 << G4endl;
319 G4cout << "### G4FermiFragmentPoolVI: fragments sorted by A" << G4endl;
320
321 G4long prec = G4cout.precision(6);
322 std::size_t ama[maxA];
323 ama[0] = 0;
324 for(G4int A=1; A<maxA; ++A) {
325 G4cout << " # A= " << A << G4endl;
326 std::size_t am(0);
327 for(std::size_t j=0; j<list_f[A].size(); ++j) {
328 const G4FermiFragment* f = (list_f[A])[j];
329 G4int a1 = f->GetA();
330 G4int z1 = f->GetZ();
331 std::size_t nch = (list_c[A])[j]->GetNumberOfChannels();
332 am = std::max(am, nch);
333 G4cout << " ("<<a1<<","<<z1<<"); Eex(MeV)= "
334 << f->GetExcitationEnergy()
335 << " 2S= " << f->GetSpin()
336 << "; Nchannels= " << nch
337 << " MassExcess= " << f->GetTotalEnergy() -
338 (z1*proton_mass_c2 + (a1 - z1)*neutron_mass_c2)
339 << G4endl;
340 for(std::size_t k=0; k<nch; ++k) {
341 const G4FermiPair* fpair = ((list_c[A])[j]->GetChannels())[k];
342 G4cout << " (" << fpair->GetFragment1()->GetZ()
343 << ", " << fpair->GetFragment1()->GetA()
344 << ", " << fpair->GetFragment1()->GetExcitationEnergy()
345 << ") ("<< fpair->GetFragment2()->GetZ()
346 << ", " << std::setw(3)<< fpair->GetFragment2()->GetA()
347 << ", " << std::setw(8)<< fpair->GetFragment2()->GetExcitationEnergy()
348 << ") prob= " << ((list_c[A])[j]->GetProbabilities())[k]
349 << G4endl;
350 }
351 }
352 ama[A] = am;
353 }
354 G4cout.precision(prec);
355 G4cout << G4endl;
356
357 G4cout << " Number of fragments per A:" << G4endl;
358 for(G4int j=0; j<maxA; ++j) { G4cout << list_f[j].size() << ", "; }
359 G4cout << G4endl;
360
361 G4cout << " Max number of channels per A:" << G4endl;
362 for (std::size_t j=0; j<maxA; ++j) { G4cout << ama[j] << ", "; }
363 G4cout << G4endl;
364
365 G4cout << " Number of fragment pairs per A:" << G4endl;
366 for(G4int j=0; j<maxA; ++j) { G4cout << list_p[j].size() << ", "; }
367 G4cout << G4endl;
368
369 G4cout << "----------------------------------------------------------------"
370 << G4endl;
371 G4cout << "### Pairs of stable fragments: " << G4endl;
372
373 prec = G4cout.precision(6);
374 for(G4int A=2; A<maxA; ++A) {
375 G4cout << " A= " << A<<G4endl;
376 for(std::size_t j=0; j<list_p[A].size(); ++j) {
377 const G4FermiFragment* f1 = (list_p[A])[j]->GetFragment1();
378 const G4FermiFragment* f2 = (list_p[A])[j]->GetFragment2();
379 G4int a1 = f1->GetA();
380 G4int z1 = f1->GetZ();
381 G4int a2 = f2->GetA();
382 G4int z2 = f2->GetZ();
383 G4cout << "("<<a1<<","<<z1<<")("<<a2<<","<<z2<<") % Eex(MeV)= "
384 << std::setw(8)<< (list_p[A])[j]->GetExcitationEnergy()
385 << " Eex1= " << std::setw(8)<< f1->GetExcitationEnergy()
386 << " Eex2= " << std::setw(8)<< f2->GetExcitationEnergy()
387 << G4endl;
388 }
389 G4cout << G4endl;
390 G4cout <<"----------------------------------------------------------------"
391 << G4endl;
392 }
393 G4cout.precision(prec);
394}
395
float G4float
Definition: G4Types.hh:84
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
const G4double A[17]
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
G4double GetFBUEnergyLimit() const
G4double GetMinExcitation() const
size_t GetNumberOfChannels() const
const std::vector< const G4FermiPair * > & GetChannels() const
std::vector< G4double > & GetProbabilities()
G4double ComputeProbability(G4int Z, G4int A, G4int spin, G4double TotalE, const G4FermiFragment *f1, const G4FermiFragment *f2) const
G4double GetExcitationEnergy() const
G4int GetA() const
G4double GetFragmentMass() const
G4int GetSpin() const
G4double GetCoulombBarrier(G4int Ares, G4int Zres, G4double Eex) const
G4int GetZ() const
G4double GetTotalEnergy(void) const
G4bool IsPhysical(G4int Z, G4int A) const
G4bool HasChannels(G4int Z, G4int A, G4double exc) const
const G4FermiChannels * ClosestChannels(G4int Z, G4int A, G4double mass) const
void DumpFragment(const G4FermiFragment *) const
const G4FermiFragment * GetFragment2() const
Definition: G4FermiPair.hh:101
const G4FermiFragment * GetFragment1() const
Definition: G4FermiPair.hh:96
G4double LevelEnergy(const std::size_t i) const
std::size_t NumberOfTransitions() const
G4int SpinTwo(const std::size_t i) const
G4double LifeTime(const std::size_t i) const
G4float MaxLevelEnergy(G4int Z, G4int A) const
G4DeexPrecoParameters * GetParameters()
G4int GetMinA(G4int Z) const
const G4LevelManager * GetLevelManager(G4int Z, G4int A)
static G4NuclearLevelData * GetInstance()
G4int GetMaxA(G4int Z) const
static G4double GetNuclearMass(const G4double A, const G4double Z)