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