ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4FermiBreakUpVI.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4FermiBreakUpVI.cc
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"
37 #include "G4PhysicalConstants.hh"
38 #include "Randomize.hh"
39 
41 
42 #ifdef G4MULTITHREADED
43 G4Mutex 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;
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(); }
75 }
76 
78 {
79 #ifdef G4MULTITHREADED
80  G4MUTEXLOCK(&G4FermiBreakUpVI::FermiBreakUpVIMutex);
81 #endif
82  if(thePool == nullptr) {
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 
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
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