Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4INCLProjectileRemnant.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 // INCL++ intra-nuclear cascade model
27 // Pekka Kaitaniemi, CEA and Helsinki Institute of Physics
28 // Davide Mancusi, CEA
29 // Alain Boudard, CEA
30 // Sylvie Leray, CEA
31 // Joseph Cugnon, University of Liege
32 //
33 #define INCLXX_IN_GEANT4_MODE 1
34 
35 #include "globals.hh"
36 
45 #include <algorithm>
46 #include <numeric>
47 
48 namespace G4INCL {
49 
51  return (G4int)(Random::shoot1()*range);
52  }
53 
58  theEnergy = 0.0;
59  thePotentialEnergy = 0.0;
60  theA = 0;
61  theZ = 0;
62  nCollisions = 0;
63 
64  for(std::map<long, Particle*>::const_iterator i=storedComponents.begin(); i!=storedComponents.end(); ++i) {
65  Particle *p = new Particle(*(i->second));
66  EnergyLevelMap::iterator energyIter = theInitialEnergyLevels.find(i->first);
67 // assert(energyIter!=theInitialEnergyLevels.end());
68  const G4double energyLevel = energyIter->second;
69  theInitialEnergyLevels.erase(energyIter);
70  theInitialEnergyLevels[p->getID()] = energyLevel;
71  addParticle(p);
72  }
73  thePosition /= theA;
74  setTableMass();
75  DEBUG("ProjectileRemnant object was reset:" << std::endl << print());
76  }
77 
78  void ProjectileRemnant::removeParticle(Particle * const p, const G4double theProjectileCorrection) {
79 // assert(p->isNucleon());
80 
81  DEBUG("The following Particle is about to be removed from the ProjectileRemnant:"
82  << std::endl << p->print()
83  << "theProjectileCorrection=" << theProjectileCorrection << std::endl);
84  // Update A, Z, momentum and energy of the projectile remnant
85  theA -= p->getA();
86  theZ -= p->getZ();
87 
88  ThreeVector const &oldMomentum = p->getMomentum();
89  const G4double oldEnergy = p->getEnergy();
91 
92 #if !defined(NDEBUG) && !defined(INCLXX_IN_GEANT4_MODE)
93  ThreeVector theTotalMomentum;
94  G4double theTotalEnergy = 0.;
95  const G4double theThreshold = 0.1;
96 #endif
97 
98  if(getA()>0) { // if there are any particles left
99 // assert((unsigned int)getA()==particles.size());
100 
101  const G4double theProjectileCorrectionPerNucleon = theProjectileCorrection / particles.size();
102 
103  // Update the kinematics of the components
104  for(ParticleIter i=particles.begin(); i!=particles.end(); ++i) {
105  (*i)->setEnergy((*i)->getEnergy() + theProjectileCorrectionPerNucleon);
106  (*i)->setMass((*i)->getInvariantMass());
107 #if !defined(NDEBUG) && !defined(INCLXX_IN_GEANT4_MODE)
108  theTotalMomentum += (*i)->getMomentum();
109  theTotalEnergy += (*i)->getEnergy();
110 #endif
111  }
112  }
113 
114  theMomentum -= oldMomentum;
115  theEnergy -= oldEnergy - theProjectileCorrection;
116 
117 // assert(std::abs((theTotalMomentum-theMomentum).mag())<theThreshold);
118 // assert(std::abs(theTotalEnergy-theEnergy)<theThreshold);
119  DEBUG("After Particle removal, the ProjectileRemnant looks like this:"
120  << std::endl << print());
121  }
122 
124  // Try as hard as possible to add back all the dynamical spectators.
125  // Don't add spectators that lead to negative excitation energies, but
126  // iterate over the spectators as many times as possible, until
127  // absolutely sure that all of them were rejected.
128  unsigned int accepted;
129  do {
130  accepted = 0;
131  ParticleList toBeAdded = pL;
132  for(ParticleIter p=toBeAdded.begin(); p!=toBeAdded.end(); ++p) {
133  G4bool isAccepted = addDynamicalSpectator(*p);
134  if(isAccepted) {
135  pL.remove(*p);
136  accepted++;
137  }
138  }
139  } while(accepted > 0);
140  return pL;
141  }
142 
144  // Try as hard as possible to add back all the dynamical spectators.
145  // Don't add spectators that lead to negative excitation energies. Start by
146  // adding all of them, and repeatedly remove the most troublesome one until
147  // the excitation energy becomes non-negative.
148 
149  // Put all the spectators in the projectile
150  ThreeVector theNewMomentum = theMomentum;
151  G4double theNewEnergy = theEnergy;
152  G4int theNewA = theA;
153  G4int theNewZ = theZ;
154  for(ParticleIter p=pL.begin(); p!=pL.end(); ++p) {
155 // assert((*p)->isNucleon());
156  // Add the initial (off-shell) momentum and energy to the projectile remnant
157  theNewMomentum += getStoredMomentum(*p);
158  theNewEnergy += (*p)->getEnergy();
159  theNewA += (*p)->getA();
160  theNewZ += (*p)->getZ();
161  }
162 
163  // Check that the excitation energy of the new projectile remnant is non-negative
164  const G4double theNewMass = ParticleTable::getTableMass(theNewA,theNewZ);
165  const G4double theNewInvariantMassSquared = theNewEnergy*theNewEnergy-theNewMomentum.mag2();
166 
167  G4bool positiveExcitationEnergy = false;
168  if(theNewInvariantMassSquared>=0.) {
169  const G4double theNewInvariantMass = std::sqrt(theNewInvariantMassSquared);
170  positiveExcitationEnergy = (theNewInvariantMass-theNewMass>-1.e-5);
171  }
172 
173  // Keep removing nucleons from the projectile remnant until we achieve a
174  // non-negative excitation energy.
175  ParticleList rejected;
176  while(!positiveExcitationEnergy && !pL.empty()) {
177  G4double maxExcitationEnergy = -1.E30;
178  ParticleList::iterator best = pL.end();
179  ThreeVector bestMomentum;
180  G4double bestEnergy = -1.;
181  G4int bestA = -1, bestZ = -1;
182  for(ParticleList::iterator p=pL.begin(); p!=pL.end(); ++p) {
183  // Subtract the initial (off-shell) momentum and energy from the new
184  // projectile remnant
185  const ThreeVector theNewerMomentum = theNewMomentum - getStoredMomentum(*p);
186  const G4double theNewerEnergy = theNewEnergy - (*p)->getEnergy();
187  const G4int theNewerA = theNewA - (*p)->getA();
188  const G4int theNewerZ = theNewZ - (*p)->getZ();
189 
190  const G4double theNewerMass = ParticleTable::getTableMass(theNewerA,theNewerZ);
191  const G4double theNewerInvariantMassSquared = theNewerEnergy*theNewerEnergy-theNewerMomentum.mag2();
192 
193  if(theNewerInvariantMassSquared>=-1.e-5) {
194  const G4double theNewerInvariantMass = std::sqrt(std::max(0.,theNewerInvariantMassSquared));
195  const G4double theNewerExcitationEnergy = theNewerInvariantMass-theNewerMass;
196  // Pick the nucleon that maximises the excitation energy of the
197  // ProjectileRemnant
198  if(theNewerExcitationEnergy>maxExcitationEnergy) {
199  best = p;
200  maxExcitationEnergy = theNewerExcitationEnergy;
201  bestMomentum = theNewerMomentum;
202  bestEnergy = theNewerEnergy;
203  bestA = theNewerA;
204  bestZ = theNewerZ;
205  }
206  }
207  }
208 
209  // If we couldn't even calculate the excitation energy, fail miserably
210  if(best==pL.end())
211  return pL;
212 
213  rejected.push_back(*best);
214  pL.erase(best);
215  theNewMomentum = bestMomentum;
216  theNewEnergy = bestEnergy;
217  theNewA = bestA;
218  theNewZ = bestZ;
219 
220  if(maxExcitationEnergy>0.) {
221  // Stop here
222  positiveExcitationEnergy = true;
223  }
224  }
225 
226  // Add the accepted participants to the projectile remnant
227  for(ParticleIter p=pL.begin(); p!=pL.end(); ++p) {
228  particles.push_back(*p);
229  }
230  theA = theNewA;
231  theZ = theNewZ;
232  theMomentum = theNewMomentum;
233  theEnergy = theNewEnergy;
234 
235  return rejected;
236  }
237 
238  G4bool ProjectileRemnant::addDynamicalSpectator(Particle * const p) {
239 // assert(p->isNucleon());
240 
241  // Add the initial (off-shell) momentum and energy to the projectile remnant
242  ThreeVector const &oldMomentum = getStoredMomentum(p);
243  const ThreeVector theNewMomentum = theMomentum + oldMomentum;
244  const G4double oldEnergy = p->getEnergy();
245  const G4double theNewEnergy = theEnergy + oldEnergy;
246 
247  // Check that the excitation energy of the new projectile remnant is non-negative
248  const G4double theNewMass = ParticleTable::getTableMass(theA+p->getA(),theZ+p->getZ());
249  const G4double theNewInvariantMassSquared = theNewEnergy*theNewEnergy-theNewMomentum.mag2();
250 
251  if(theNewInvariantMassSquared<0.)
252  return false;
253 
254  const G4double theNewInvariantMass = std::sqrt(theNewInvariantMassSquared);
255 
256  if(theNewInvariantMass-theNewMass<-1.e-5)
257  return false; // negative excitation energy here
258 
259  // Add the spectator to the projectile remnant
260  theA += p->getA();
261  theZ += p->getZ();
262  theMomentum = theNewMomentum;
263  theEnergy = theNewEnergy;
264  particles.push_back(p);
265  return true;
266  }
267 
269  // The ground-state energy is the sum of the A smallest initial projectile
270  // energies.
271  // For the last nucleon, return 0 so that the algorithm will just put it on
272  // shell.
273  if(theA==1)
274  return 0.;
275 
276  const G4double groundState = theGroundStateEnergies.at(theA-2);
277 
278  // Compute the sum of the presently occupied energy levels
279  const EnergyLevels theEnergyLevels = getPresentEnergyLevels(exceptID);
280  const G4double excitedState = std::accumulate(
281  theEnergyLevels.begin(),
282  theEnergyLevels.end(),
283  0.);
284 
285  return excitedState-groundState;
286  }
287 
288 }
289