Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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// Alain Boudard, CEA-Saclay, France
28// Joseph Cugnon, University of Liege, Belgium
29// Jean-Christophe David, CEA-Saclay, France
30// Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
31// Sylvie Leray, CEA-Saclay, France
32// Davide Mancusi, CEA-Saclay, France
33//
34#define INCLXX_IN_GEANT4_MODE 1
35
36#include "globals.hh"
37
38#ifndef G4INCLCluster_hh
39#define G4INCLCluster_hh 1
40
41#include "G4INCLParticle.hh"
45
46namespace G4INCL {
47
48 /**
49 * Cluster is a particle (inherits from the Particle class) that is
50 * actually a collection of elementary particles.
51 */
52 class Cluster : public Particle {
53 public:
54
55 /** \brief Standard Cluster constructor
56 *
57 * This constructor should mainly be used when constructing Nucleus or
58 * when constructing Clusters to be used as composite projectiles.
59 */
60 Cluster(const G4int Z, const G4int A, const G4int S, const G4bool createParticleSampler=true) :
61 Particle(),
63 theSpin(0.,0.,0.),
65 {
67 theZ = Z;
68 theA = A;
69 theS = S;
71 if(createParticleSampler)
73 }
74
75 /**
76 * A cluster can be directly built from a list of particles.
77 */
78 template<class Iterator>
79 Cluster(Iterator begin, Iterator end) :
80 Particle(),
82 theSpin(0.,0.,0.),
84 {
86 for(Iterator i = begin; i != end; ++i) {
87 addParticle(*i);
88 }
92 }
93
94 virtual ~Cluster() {
95 delete theParticleSampler;
96 }
97
98 /// \brief Copy constructor
99 Cluster(const Cluster &rhs) :
100 Particle(rhs),
102 theSpin(rhs.theSpin)
103 {
104 for(ParticleIter p=rhs.particles.begin(), e=rhs.particles.end(); p!=e; ++p) {
105 particles.push_back(new Particle(**p));
106 }
107 if(rhs.theParticleSampler)
109 else
110 theParticleSampler = NULL;
111 }
112
113 /// \brief Assignment operator
114 Cluster &operator=(const Cluster &rhs) {
115 Cluster temporaryCluster(rhs);
116 Particle::operator=(temporaryCluster);
117 swap(temporaryCluster);
118 return *this;
119 }
120
121 /// \brief Helper method for the assignment operator
122 void swap(Cluster &rhs) {
123 Particle::swap(rhs);
125 std::swap(theSpin, rhs.theSpin);
126 // std::swap is overloaded by std::list and guaranteed to operate in
127 // constant time
128 std::swap(particles, rhs.particles);
130 }
131
133 return ParticleSpecies(theA, theZ, theS);
134 }
135
137 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
138 delete (*p);
139 }
141 }
142
143 void clearParticles() { particles.clear(); }
144
145 /// \brief Set the charge number of the cluster
146 void setZ(const G4int Z) { theZ = Z; }
147
148 /// \brief Set the mass number of the cluster
149 void setA(const G4int A) { theA = A; }
150
151 /// \brief Set the strangess number of the cluster
152 void setS(const G4int S) { theS = S; }
153
154 /// \brief Get the excitation energy of the cluster.
156
157 /// \brief Set the excitation energy of the cluster.
159
160 /** \brief Get the real particle mass.
161 *
162 * Overloads the Particle method.
163 */
164 inline virtual G4double getTableMass() const { return getRealMass(); }
165
166 /**
167 * Get the list of particles in the cluster.
168 */
169 ParticleList const &getParticles() const { return particles; }
170
171 /// \brief Remove a particle from the cluster components.
172 void removeParticle(Particle * const p) { particles.remove(p); }
173
174 /**
175 * Add one particle to the cluster. This updates the cluster mass,
176 * energy, size, etc.
177 */
178 void addParticle(Particle * const p) {
179 particles.push_back(p);
180 theEnergy += p->getEnergy();
182 theMomentum += p->getMomentum();
183 thePosition += p->getPosition();
184 theA += p->getA();
185 theZ += p->getZ();
186 theS += p->getS();
188 }
189
190 /// \brief Set total cluster mass, energy, size, etc. from the particles
192 theEnergy = 0.;
196 theA = 0;
197 theZ = 0;
198 theS = 0;
199 nCollisions = 0;
200 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
201 theEnergy += (*p)->getEnergy();
202 thePotentialEnergy += (*p)->getPotentialEnergy();
203 theMomentum += (*p)->getMomentum();
204 thePosition += (*p)->getPosition();
205 theA += (*p)->getA();
206 theZ += (*p)->getZ();
207 theS += (*p)->getS();
208 nCollisions += (*p)->getNumberOfCollisions();
209 }
210 }
211
212 /// \brief Add a list of particles to the cluster
213 void addParticles(ParticleList const &pL) {
214 particles = pL;
216 }
217
218 /// \brief Returns the list of particles that make up the cluster
220
221 std::string print() const {
222 std::stringstream ss;
223 ss << "Cluster (ID = " << ID << ") type = ";
225 ss << '\n'
226 << " A = " << theA << '\n'
227 << " Z = " << theZ << '\n'
228 << " S = " << theS << '\n'
229 << " mass = " << getMass() << '\n'
230 << " energy = " << theEnergy << '\n'
231 << " momentum = "
232 << theMomentum.print()
233 << '\n'
234 << " position = "
235 << thePosition.print()
236 << '\n'
237 << "Contains the following particles:"
238 << '\n';
239 for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i)
240 ss << (*i)->print();
241 ss << '\n';
242 return ss.str();
243 }
244
245 /// \brief Initialise the NuclearDensity pointer and sample the particles
246 virtual void initializeParticles();
247
248 /** \brief Boost to the CM of the component particles
249 *
250 * The position of all particles in the particles list is shifted so that
251 * their centre of mass is in the origin and their total momentum is
252 * zero.
253 */
255
256 // First compute the current CM position and total momentum
257 ThreeVector theCMPosition, theTotalMomentum;
258 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
259 theCMPosition += (*p)->getPosition();
260 theTotalMomentum += (*p)->getMomentum();
261 //theTotalEnergy += (*p)->getEnergy();
262 }
263 theCMPosition /= theA;
264// assert((unsigned int)theA==particles.size());
265
266 // Now determine the CM velocity of the particles
267 // commented out because currently unused, see below
268 // ThreeVector betaCM = theTotalMomentum / theTotalEnergy;
269
270 // The new particle positions and momenta are scaled by a factor of
271 // \f$\sqrt{A/(A-1)}\f$, so that the resulting density distributions in
272 // the CM have the same variance as the one we started with.
273 const G4double rescaling = std::sqrt(((G4double)theA)/((G4double)(theA-1)));
274
275 // Loop again to boost and reposition
276 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
277 // \bug{We should do the following, but the Fortran version actually
278 // does not!
279 // (*p)->boost(betaCM);
280 // Here is what the Fortran version does:}
281 (*p)->setMomentum(((*p)->getMomentum()-theTotalMomentum/theA)*rescaling);
282
283 // Set the CM position of the particles
284 (*p)->setPosition(((*p)->getPosition()-theCMPosition)*rescaling);
285 }
286
287 // Set the global cluster kinematic variables
288 thePosition.setX(0.0);
289 thePosition.setY(0.0);
290 thePosition.setZ(0.0);
291 theMomentum.setX(0.0);
292 theMomentum.setY(0.0);
293 theMomentum.setZ(0.0);
294 theEnergy = getMass();
295
296 INCL_DEBUG("Cluster boosted to internal CM:" << '\n' << print());
297
298 }
299
300 /** \brief Put the cluster components off shell
301 *
302 * The Cluster components are put off shell in such a way that their total
303 * energy equals the cluster mass.
304 */
306 // Compute the dynamical potential
307 const G4double theDynamicalPotential = computeDynamicalPotential();
308 INCL_DEBUG("The dynamical potential is " << theDynamicalPotential << " MeV" << '\n');
309
310 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
311 const G4double energy = (*p)->getEnergy() - theDynamicalPotential;
312 const ThreeVector &momentum = (*p)->getMomentum();
313 // Here particles are put off-shell so that we can satisfy the energy-
314 // and momentum-conservation laws
315 (*p)->setEnergy(energy);
316 (*p)->setMass(std::sqrt(energy*energy - momentum.mag2()));
317 }
318 INCL_DEBUG("Cluster components are now off shell:" << '\n'
319 << print());
320 }
321
322 /** \brief Set the position of the cluster
323 *
324 * This overloads the Particle method to take into account that the
325 * positions of the cluster members must be updated as well.
326 */
330 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
331 (*p)->setPosition((*p)->getPosition()+shift);
332 }
333 }
334
335 /** \brief Boost the cluster with the indicated velocity
336 *
337 * The Cluster is boosted as a whole, just like any Particle object;
338 * moreover, the internal components (particles list) are also boosted,
339 * according to Alain Boudard's off-shell recipe.
340 *
341 * \param aBoostVector the velocity to boost to [c]
342 */
343 void boost(const ThreeVector &aBoostVector) {
344 Particle::boost(aBoostVector);
345 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
346 (*p)->boost(aBoostVector);
347 // Apply Lorentz contraction to the particle position
348 (*p)->lorentzContract(aBoostVector,thePosition);
349 (*p)->rpCorrelate();
350 }
351
352 INCL_DEBUG("Cluster was boosted with (bx,by,bz)=("
353 << aBoostVector.getX() << ", " << aBoostVector.getY() << ", " << aBoostVector.getZ() << "):"
354 << '\n' << print());
355
356 }
357
358 /** \brief Freeze the internal motion of the particles
359 *
360 * Each particle is assigned a frozen momentum four-vector determined by
361 * the collective cluster velocity. This is used for propagation, but not
362 * for dynamics. Normal propagation is restored by calling the
363 * Particle::thawPropagation() method, which should be done in
364 * InteractionAvatar::postInteraction.
365 */
367 const ThreeVector &normMomentum = theMomentum / getMass();
368 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
369 const G4double pMass = (*p)->getMass();
370 const ThreeVector frozenMomentum = normMomentum * pMass;
371 const G4double frozenEnergy = std::sqrt(frozenMomentum.mag2()+pMass*pMass);
372 (*p)->setFrozenMomentum(frozenMomentum);
373 (*p)->setFrozenEnergy(frozenEnergy);
374 (*p)->freezePropagation();
375 }
376 }
377
378 /** \brief Rotate position of all the particles
379 *
380 * This includes the cluster components. Overloads Particle::rotateMomentum().
381 *
382 * \param angle the rotation angle
383 * \param axis a unit vector representing the rotation axis
384 */
385 virtual void rotatePosition(const G4double angle, const ThreeVector &axis);
386
387 /** \brief Rotate momentum of all the particles
388 *
389 * This includes the cluster components. Overloads Particle::rotateMomentum().
390 *
391 * \param angle the rotation angle
392 * \param axis a unit vector representing the rotation axis
393 */
394 virtual void rotateMomentum(const G4double angle, const ThreeVector &axis);
395
396 /// \brief Make all the components projectile spectators, too
397 virtual void makeProjectileSpectator() {
399 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
400 (*p)->makeProjectileSpectator();
401 }
402 }
403
404 /// \brief Make all the components target spectators, too
405 virtual void makeTargetSpectator() {
407 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
408 (*p)->makeTargetSpectator();
409 }
410 }
411
412 /// \brief Make all the components participants, too
413 virtual void makeParticipant() {
415 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
416 (*p)->makeParticipant();
417 }
418 }
419
420 /// \brief Get the spin of the nucleus.
421 ThreeVector const &getSpin() const { return theSpin; }
422
423 /// \brief Set the spin of the nucleus.
424 void setSpin(const ThreeVector &j) { theSpin = j; }
425
426 /// \brief Get the total angular momentum (orbital + spin)
430
431 private:
432 /** \brief Compute the dynamical cluster potential
433 *
434 * Alain Boudard's boost prescription for low-energy beams requires to
435 * define a "dynamical potential" that allows us to conserve momentum and
436 * energy when boosting the projectile cluster.
437 */
438 G4double computeDynamicalPotential() {
439 G4double theDynamicalPotential = 0.0;
440 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
441 theDynamicalPotential += (*p)->getEnergy();
442 }
443 theDynamicalPotential -= getTableMass();
444 theDynamicalPotential /= theA;
445
446 return theDynamicalPotential;
447 }
448
449 protected:
454
456 };
457
458}
459
460#endif
G4double S(G4double temp)
Singleton for recycling allocation of instances of a given class.
#define INCL_DECLARE_ALLOCATION_POOL(T)
#define INCL_DEBUG(x)
Class for sampling particles in a nucleus.
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
ThreeVector const & getSpin() const
Get the spin of the nucleus.
void boost(const ThreeVector &aBoostVector)
Boost the cluster with the indicated velocity.
void internalBoostToCM()
Boost to the CM of the component particles.
void removeParticle(Particle *const p)
Remove a particle from the cluster components.
ParticleSpecies getSpecies() const
Get the particle species.
ParticleList particles
ParticleList const & getParticles() const
virtual void makeProjectileSpectator()
Make all the components projectile spectators, too.
void setExcitationEnergy(const G4double e)
Set the excitation energy of the cluster.
void setS(const G4int S)
Set the strangess number of the cluster.
virtual void rotateMomentum(const G4double angle, const ThreeVector &axis)
Rotate momentum of all the particles.
void setSpin(const ThreeVector &j)
Set the spin of the nucleus.
virtual void initializeParticles()
Initialise the NuclearDensity pointer and sample the particles.
ParticleSampler * theParticleSampler
G4INCL::ThreeVector getAngularMomentum() const
Get the total angular momentum (orbital + spin)
void addParticles(ParticleList const &pL)
Add a list of particles to the cluster.
Cluster(const G4int Z, const G4int A, const G4int S, const G4bool createParticleSampler=true)
Standard Cluster constructor.
virtual void makeTargetSpectator()
Make all the components target spectators, too.
ThreeVector theSpin
G4double getExcitationEnergy() const
Get the excitation energy of the cluster.
virtual G4double getTableMass() const
Get the real particle mass.
void swap(Cluster &rhs)
Helper method for the assignment operator.
virtual void rotatePosition(const G4double angle, const ThreeVector &axis)
Rotate position of all the particles.
Cluster & operator=(const Cluster &rhs)
Assignment operator.
void setPosition(const ThreeVector &position)
Set the position of the cluster.
void setA(const G4int A)
Set the mass number of the cluster.
Cluster(Iterator begin, Iterator end)
Cluster(const Cluster &rhs)
Copy constructor.
void addParticle(Particle *const p)
virtual void makeParticipant()
Make all the components participants, too.
G4double theExcitationEnergy
void updateClusterParameters()
Set total cluster mass, energy, size, etc. from the particles.
void freezeInternalMotion()
Freeze the internal motion of the particles.
void setZ(const G4int Z)
Set the charge number of the cluster.
ParticleList getParticleList() const
Returns the list of particles that make up the cluster.
std::string print() const
void putParticlesOffShell()
Put the cluster components off shell.
G4int getS() const
Returns the strangeness number.
G4INCL::ThreeVector theMomentum
virtual G4INCL::ThreeVector getAngularMomentum() const
G4double getEnergy() const
G4double getPotentialEnergy() const
Get the particle potential energy.
virtual void makeTargetSpectator()
G4int getZ() const
Returns the charge number.
const G4INCL::ThreeVector & getPosition() const
G4INCL::ParticleType theType
G4int getNumberOfCollisions() const
Return the number of collisions undergone by the particle.
virtual void makeProjectileSpectator()
const ThreeVector & adjustMomentumFromEnergy()
Rescale the momentum to match the total energy.
void setINCLMass()
Set the mass of the Particle to its table mass.
G4double getRealMass() const
Get the real particle mass.
const G4INCL::ThreeVector & getMomentum() const
Particle & operator=(const Particle &rhs)
Assignment operator.
virtual void makeParticipant()
void setType(ParticleType t)
G4double getMass() const
Get the cached particle mass.
void boost(const ThreeVector &aBoostVector)
virtual void setPosition(const G4INCL::ThreeVector &position)
void swap(Particle &rhs)
Helper method for the assignment operator.
G4int getA() const
Returns the baryon number.
G4INCL::ThreeVector thePosition
void setY(G4double ay)
Set the y coordinate.
G4double getY() const
G4double getZ() const
void setZ(G4double az)
Set the z coordinate.
void setX(G4double ax)
Set the x coordinate.
std::string print() const
G4double mag2() const
G4double getX() const
std::string getName(const ParticleType t)
Get the native INCL name of the particle.
ParticleList::const_iterator ParticleIter