Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4FermiBreakUpVI.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
31#include "G4FermiBreakUpVI.hh"
34#include "G4FermiChannels.hh"
35#include "G4FermiPair.hh"
36#include "G4RandomDirection.hh"
38#include "Randomize.hh"
39
40G4FermiFragmentsPoolVI* G4FermiBreakUpVI::thePool = nullptr;
41
42#ifdef G4MULTITHREADED
43G4Mutex G4FermiBreakUpVI::FermiBreakUpVIMutex = G4MUTEX_INITIALIZER;
44#endif
45
47 : theDecay(nullptr), rndmEngine(nullptr), maxZ(9), maxA(17)
48{
49 frag.reserve(10);
50 lvect.reserve(10);
51 Z = A = spin = 0;
52 mass = elim = excitation = 0.0;
53 tolerance = CLHEP::MeV;
54 frag1 = frag2 = nullptr;
55 prob.resize(12,0.0);
56 Initialise();
57}
58
60{
62 delete thePool;
63 thePool = nullptr;
64 }
65}
66
68{
69 if(verbose > 1) {
70 G4cout << "### G4FermiBreakUpVI::Initialise(): " << thePool << G4endl;
71 }
72 if(thePool == nullptr) { InitialisePool(); }
73 theDecay = thePool->FermiDecayProbability();
74 elim = thePool->GetEnergyLimit();
75}
76
77void G4FermiBreakUpVI::InitialisePool()
78{
79#ifdef G4MULTITHREADED
80 G4MUTEXLOCK(&G4FermiBreakUpVI::FermiBreakUpVIMutex);
81#endif
82 if(thePool == nullptr) {
83 thePool = new G4FermiFragmentsPoolVI();
84 }
85#ifdef G4MULTITHREADED
86 G4MUTEXUNLOCK(&G4FermiBreakUpVI::FermiBreakUpVIMutex);
87#endif
88}
89
91{
92 return (ZZ < maxZ && AA < maxA && AA > 0 && eexc <= elim
93 && thePool->HasChannels(ZZ, AA, eexc));
94}
95
97 G4Fragment* theNucleus)
98{
99 if(verbose > 1) {
100 G4cout << "### G4FermiBreakUpVI::BreakFragment start new fragment "
101 << G4endl;
102 G4cout << *theNucleus << G4endl;
103 }
104
105 // initial fragment
106 Z = theNucleus->GetZ_asInt();
107 A = theNucleus->GetA_asInt();
108 excitation = theNucleus->GetExcitationEnergy();
109 mass = theNucleus->GetGroundStateMass() + excitation;
110 spin = -1;
111
112 lv0 = theNucleus->GetMomentum();
113 rndmEngine = G4Random::getTheEngine();
114
115 // sample first decay of an initial state
116 // if not possible to decay - exit
117 if(!SampleDecay()) {
118 return;
119 }
120
121 G4double time = theNucleus->GetCreationTime();
122 delete theNucleus;
123
124 static const G4int imax = 100;
125
126 // loop over vector of Fermi fragments
127 // vector may grow at each iteraction
128 for(size_t i=0; i<frag.size(); ++i) {
129 Z = frag[i]->GetZ();
130 A = frag[i]->GetA();
131 spin = frag[i]->GetSpin();
132 mass = frag[i]->GetTotalEnergy();
133 lv0 = lvect[i];
134 if(verbose > 1) {
135 G4cout << "# FermiFrag " << i << ". Z= " << Z << " A= " << A
136 << " mass= " << mass << " exc= "
137 << frag[i]->GetExcitationEnergy() << G4endl;
138 }
139 // stable fragment
140 if(!SampleDecay()) {
141 if(verbose > 1) { G4cout << " New G4Fragment" << G4endl; }
142 G4Fragment* f = new G4Fragment(A, Z, lv0);
143 f->SetSpin(0.5*spin);
144 f->SetCreationTime(time);
145 theResult->push_back(f);
146 }
147 // limit the loop
148 if(i == imax) {
149 break;
150 }
151 }
152 frag.clear();
153 lvect.clear();
154}
155
156G4bool G4FermiBreakUpVI::SampleDecay()
157{
158 const G4FermiChannels* chan = thePool->ClosestChannels(Z, A, mass);
159 if(!chan) { return false; }
160 size_t nn = chan->GetNumberOfChannels();
161 if(verbose > 1) {
162 G4cout << "== SampleDecay " << nn << " channels Eex= "
163 << chan->GetExcitation() << G4endl;
164 }
165 if(0 == nn) { return false; }
166
167 const G4FermiPair* fpair = nullptr;
168
169 // one unstable fragment
170 if(1 == nn) {
171 fpair = chan->GetPair(0);
172
173 // more pairs
174 } else {
175
176 // in static probabilities may be used
177 if(std::abs(excitation - chan->GetExcitation()) < tolerance) {
178 fpair = chan->SamplePair(rndmEngine->flat());
179
180 } else {
181
182 // recompute probabilities
183 const std::vector<const G4FermiPair*>& pvect = chan->GetChannels();
184 if(nn > 12) { prob.resize(nn, 0.0); }
185 G4double ptot = 0.0;
186 if(verbose > 2) {
187 G4cout << "Start recompute probabilities" << G4endl;
188 }
189 for(size_t i=0; i<nn; ++i) {
190 ptot += theDecay->ComputeProbability(Z, A, -1, mass,
191 pvect[i]->GetFragment1(),
192 pvect[i]->GetFragment2());
193 prob[i] = ptot;
194 if(verbose > 2) {
195 G4cout << i << ". " << prob[i]
196 << " Z1= " << pvect[i]->GetFragment1()->GetZ()
197 << " A1= " << pvect[i]->GetFragment1()->GetA()
198 << " Z2= " << pvect[i]->GetFragment2()->GetZ()
199 << " A2= " << pvect[i]->GetFragment2()->GetA()
200 << G4endl;
201 }
202 }
203 ptot *= rndmEngine->flat();
204 for(size_t i=0; i<nn; ++i) {
205 if(ptot <= prob[i] || i+1 == nn) {
206 fpair = pvect[i];
207 break;
208 }
209 }
210 }
211 }
212 if(!fpair) { return false; }
213
214 frag1 = fpair->GetFragment1();
215 frag2 = fpair->GetFragment2();
216
217 G4double mass1 = frag1->GetTotalEnergy();
218 G4double mass2 = frag2->GetTotalEnergy();
219 if(verbose > 2) {
220 G4cout << " M= " << mass << " M1= " << mass1 << " M2= " << mass2
221 << " Exc1= " << frag1->GetExcitationEnergy()
222 << " Exc2= " << frag2->GetExcitationEnergy() << G4endl;
223 }
224 // sample fragment1
225 G4double e1 = 0.5*(mass*mass - mass2*mass2 + mass1*mass1)/mass;
226 //G4cout << "ekin1= " << e1 - mass1 << G4endl;
227 G4double p1(0.0);
228 if(e1 > mass1) {
229 p1 = std::sqrt((e1 - mass1)*(e1 + mass1));
230 } else {
231 e1 = mass1;
232 }
234 G4LorentzVector lv1 = G4LorentzVector(v*p1, e1);
235
236 // compute kinematics
237 boostVector = lv0.boostVector();
238 lv1.boost(boostVector);
239
240 lv0 -= lv1;
241
242 G4double e2 = lv0.e();
243 if(e2 < mass2) {
244 lv0.set(0.,0.,0.,mass2);
245 }
246
247 frag.push_back(frag1);
248 frag.push_back(frag2);
249 lvect.push_back(lv1);
250 lvect.push_back(lv0);
251
252 return true;
253}
254
std::vector< G4Fragment * > G4FragmentVector
Definition: G4Fragment.hh:63
CLHEP::HepLorentzVector G4LorentzVector
G4ThreeVector G4RandomDirection()
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
#define G4MUTEXLOCK(mutex)
Definition: G4Threading.hh:251
#define G4MUTEXUNLOCK(mutex)
Definition: G4Threading.hh:254
std::mutex G4Mutex
Definition: G4Threading.hh:81
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
Hep3Vector boostVector() const
HepLorentzVector & boost(double, double, double)
void set(double x, double y, double z, double t)
virtual double flat()=0
void Initialise() final
void BreakFragment(G4FragmentVector *, G4Fragment *theNucleus) final
G4bool IsApplicable(G4int ZZ, G4int AA, G4double etot) const final
G4double GetExcitation() const
const G4FermiPair * SamplePair(G4double rand) const
const G4FermiPair * GetPair(size_t idx) const
size_t GetNumberOfChannels() const
const std::vector< const G4FermiPair * > & GetChannels() const
G4double ComputeProbability(G4int Z, G4int A, G4int spin, G4double TotalE, const G4FermiFragment *f1, const G4FermiFragment *f2) const
G4double GetExcitationEnergy(void) const
G4double GetTotalEnergy(void) const
const G4FermiDecayProbability * FermiDecayProbability() const
G4bool HasChannels(G4int Z, G4int A, G4double exc) const
const G4FermiChannels * ClosestChannels(G4int Z, G4int A, G4double mass) const
const G4FermiFragment * GetFragment2() const
Definition: G4FermiPair.hh:101
const G4FermiFragment * GetFragment1() const
Definition: G4FermiPair.hh:96
G4double GetGroundStateMass() const
Definition: G4Fragment.hh:280
G4double GetExcitationEnergy() const
Definition: G4Fragment.hh:275
const G4LorentzVector & GetMomentum() const
Definition: G4Fragment.hh:299
G4double GetCreationTime() const
Definition: G4Fragment.hh:440
G4int GetZ_asInt() const
Definition: G4Fragment.hh:263
void SetCreationTime(G4double time)
Definition: G4Fragment.hh:445
void SetSpin(G4double value)
Definition: G4Fragment.hh:414
G4int GetA_asInt() const
Definition: G4Fragment.hh:258
G4bool IsMasterThread()
Definition: G4Threading.cc:124