Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4INCLCluster.hh
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 
37 #ifndef G4INCLCluster_hh
38 #define G4INCLCluster_hh 1
39 
40 #include "G4INCLParticle.hh"
42 #include "G4INCLParticleSampler.hh"
43 
44 namespace G4INCL {
45 
50  class Cluster : public Particle {
51  public:
52 
58  Cluster(const G4int Z, const G4int A, const G4bool createParticleSampler=true) :
59  Particle(),
61  theSpin(0.,0.,0.),
62  theParticleSampler(NULL)
63  {
65  theZ = Z;
66  theA = A;
67  setINCLMass();
68  if(createParticleSampler)
70  }
71 
75  template<class Iterator>
76  Cluster(Iterator begin, Iterator end) :
77  Particle(),
79  theSpin(0.,0.,0.),
80  theParticleSampler(NULL)
81  {
83  for(Iterator i = begin; i != end; ++i) {
84  addParticle(*i);
85  }
86  thePosition /= theA;
87  setINCLMass();
89  }
90 
91  virtual ~Cluster() {
92  delete theParticleSampler;
93  }
94 
96  Cluster(const Cluster &rhs) :
97  Particle(rhs),
99  {
100  deleteParticles();
101  for(ParticleIter p=rhs.particles.begin(); p!=rhs.particles.end(); ++p) {
102  particles.push_back(new Particle(**p));
103  }
104  }
105 
107  Cluster &operator=(const Cluster &rhs) {
108  Cluster temporaryCluster(rhs);
109  Particle::operator=(temporaryCluster);
110  swap(temporaryCluster);
111  return *this;
112  }
113 
115  void swap(Cluster &rhs) {
116  Particle::swap(rhs);
118  std::swap(theSpin, rhs.theSpin);
119  // std::swap is overloaded by std::list and guaranteed to operate in
120  // constant time
123  }
124 
126  return ParticleSpecies(theA, theZ);
127  }
128 
130  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
131  delete (*p);
132  }
133  clearParticles();
134  }
135 
136  void clearParticles() { particles.clear(); }
137 
139  void setZ(const G4int Z) { theZ = Z; }
140 
142  void setA(const G4int A) { theA = A; }
143 
146 
149 
154  inline virtual G4double getTableMass() const { return getRealMass(); }
155 
159  ParticleList const &getParticles() const { return particles; }
160 
162  void removeParticle(Particle * const p) { particles.remove(p); }
163 
168  void addParticle(Particle * const p) {
169 // assert(p->isNucleon());
170  particles.push_back(p);
171  theEnergy += p->getEnergy();
173  theMomentum += p->getMomentum();
174  thePosition += p->getPosition();
175  theA += p->getA();
176  theZ += p->getZ();
178  }
179 
181  void addParticles(ParticleList const &pL) {
182  for(ParticleIter p=pL.begin(); p!=pL.end(); ++p)
183  addParticle(*p);
184  }
185 
188 
189  std::string print() const {
190  std::stringstream ss;
191  ss << "Cluster (ID = " << ID << ") type = ";
193  ss << std::endl
194  << " A = " << theA << std::endl
195  << " Z = " << theZ << std::endl
196  << " mass = " << getMass() << std::endl
197  << " energy = " << theEnergy << std::endl
198  << " momentum = "
199  << theMomentum.print()
200  << std::endl
201  << " position = "
202  << thePosition.print()
203  << std::endl
204  << "Contains the following particles:"
205  << std::endl;
206  for(ParticleIter i=particles.begin(); i!=particles.end(); ++i)
207  ss << (*i)->print();
208  ss << std::endl;
209  return ss.str();
210  }
211 
213  virtual void initializeParticles();
214 
222 
223  // First compute the current CM position and total momentum
224  ThreeVector theCMPosition, theTotalMomentum;
225  G4double theTotalEnergy = 0.0;
226  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
227  theCMPosition += (*p)->getPosition();
228  theTotalMomentum += (*p)->getMomentum();
229  theTotalEnergy += (*p)->getEnergy();
230  }
231  theCMPosition /= theA;
232 // assert((unsigned int)theA==particles.size());
233 
234  // Now determine the CM velocity of the particles
235  // commented out because currently unused, see below
236  // ThreeVector betaCM = theTotalMomentum / theTotalEnergy;
237 
238  // The new particle positions and momenta are scaled by a factor of
239  // \f$\sqrt{A/(A-1)}\f$, so that the resulting density distributions in
240  // the CM have the same variance as the one we started with.
241  const G4double rescaling = std::sqrt(((G4double)theA)/((G4double)(theA-1)));
242 
243  // Loop again to boost and reposition
244  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
245  // \bug{We should do the following, but the Fortran version actually
246  // does not!
247  // (*p)->boost(betaCM);
248  // Here is what the Fortran version does:}
249  (*p)->setMomentum(((*p)->getMomentum()-theTotalMomentum/theA)*rescaling);
250 
251  // Set the CM position of the particles
252  (*p)->setPosition(((*p)->getPosition()-theCMPosition)*rescaling);
253  }
254 
255  // Set the global cluster kinematic variables
256  thePosition.setX(0.0);
257  thePosition.setY(0.0);
258  thePosition.setZ(0.0);
259  theMomentum.setX(0.0);
260  theMomentum.setY(0.0);
261  theMomentum.setZ(0.0);
262  theEnergy = getMass();
263 
264  DEBUG("Cluster boosted to internal CM:" << std::endl << print());
265 
266  }
267 
274  // Compute the dynamical potential
275  const G4double theDynamicalPotential = computeDynamicalPotential();
276  DEBUG("The dynamical potential is " << theDynamicalPotential << " MeV" << std::endl);
277 
278  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
279  const G4double energy = (*p)->getEnergy() - theDynamicalPotential;
280  const ThreeVector &momentum = (*p)->getMomentum();
281  // Here particles are put off-shell so that we can satisfy the energy-
282  // and momentum-conservation laws
283  (*p)->setEnergy(energy);
284  (*p)->setMass(std::sqrt(energy*energy - momentum.mag2()));
285  DEBUG("Cluster components are now off shell:" << std::endl
286  << print());
287  }
288  }
289 
296  ThreeVector shift(position-thePosition);
297  Particle::setPosition(position);
298  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
299  (*p)->setPosition((*p)->getPosition()+shift);
300  }
301  }
302 
311  void boost(const ThreeVector &aBoostVector) {
312  Particle::boost(aBoostVector);
313  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
314  (*p)->boost(aBoostVector);
315  // Apply Lorentz contraction to the particle position
316  (*p)->lorentzContract(aBoostVector,thePosition);
317  }
318 
319  DEBUG("Cluster was boosted with (bx,by,bz)=("
320  << aBoostVector.getX() << ", " << aBoostVector.getY() << ", " << aBoostVector.getZ() << "):"
321  << std::endl << print());
322 
323  }
324 
334  const ThreeVector &normMomentum = theMomentum / getMass();
335  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
336  const G4double pMass = (*p)->getMass();
337  const ThreeVector frozenMomentum = normMomentum * pMass;
338  const G4double frozenEnergy = std::sqrt(frozenMomentum.mag2()+pMass*pMass);
339  (*p)->setFrozenMomentum(frozenMomentum);
340  (*p)->setFrozenEnergy(frozenEnergy);
341  (*p)->freezePropagation();
342  }
343  }
344 
352  virtual void rotate(const G4double angle, const ThreeVector &axis) {
353  Particle::rotate(angle, axis);
354  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
355  (*p)->rotate(angle, axis);
356  }
357  }
358 
360  virtual void makeProjectileSpectator() {
362  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
363  (*p)->makeProjectileSpectator();
364  }
365  }
366 
368  virtual void makeTargetSpectator() {
370  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
371  (*p)->makeTargetSpectator();
372  }
373  }
374 
376  virtual void makeParticipant() {
378  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
379  (*p)->makeParticipant();
380  }
381  }
382 
384  ThreeVector const &getSpin() const { return theSpin; }
385 
387  void setSpin(const ThreeVector &j) { theSpin = j; }
388 
392  }
393 
394  private:
401  G4double computeDynamicalPotential() {
402  G4double theDynamicalPotential = 0.0;
403  for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
404  theDynamicalPotential += (*p)->getEnergy();
405  }
406  theDynamicalPotential -= getTableMass();
407  theDynamicalPotential /= theA;
408 
409  return theDynamicalPotential;
410  }
411 
412  protected:
417 
418  };
419 
420 }
421 
422 #endif