Geant4 9.6.0
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// 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#ifndef G4INCLCluster_hh
40#define G4INCLCluster_hh 1
41
42#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 G4bool createParticleSampler=true) :
61 Particle(),
63 theSpin(0.,0.,0.),
65 {
67 theZ = Z;
68 theA = A;
70 if(createParticleSampler)
72 }
73
74 /**
75 * A cluster can be directly built from a list of particles.
76 */
77 template<class Iterator>
78 Cluster(Iterator begin, Iterator end) :
79 Particle(),
81 theSpin(0.,0.,0.),
83 {
85 for(Iterator i = begin; i != end; ++i) {
86 addParticle(*i);
87 }
91 }
92
93 virtual ~Cluster() {
94 delete theParticleSampler;
95 }
96
97 /// \brief Copy constructor
98 Cluster(const Cluster &rhs) :
99 Particle(rhs),
101 {
103 for(ParticleIter p=rhs.particles.begin(); p!=rhs.particles.end(); ++p) {
104 particles.push_back(new Particle(**p));
105 }
106 }
107
108 /// \brief Assignment operator
109 Cluster &operator=(const Cluster &rhs) {
110 Cluster temporaryCluster(rhs);
111 Particle::operator=(temporaryCluster);
112 swap(temporaryCluster);
113 return *this;
114 }
115
116 /// \brief Helper method for the assignment operator
117 void swap(Cluster &rhs) {
118 Particle::swap(rhs);
120 std::swap(theSpin, rhs.theSpin);
121 // std::swap is overloaded by std::list and guaranteed to operate in
122 // constant time
123 std::swap(particles, rhs.particles);
125 }
126
128 return ParticleSpecies(theA, theZ);
129 }
130
132 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
133 delete (*p);
134 }
136 }
137
138 void clearParticles() { particles.clear(); }
139
140 /// \brief Set the charge number of the cluster
141 void setZ(const G4int Z) { theZ = Z; }
142
143 /// \brief Set the mass number of the cluster
144 void setA(const G4int A) { theA = A; }
145
146 /// \brief Get the excitation energy of the cluster.
148
149 /// \brief Set the excitation energy of the cluster.
151
152 /** \brief Get the real particle mass.
153 *
154 * Overloads the Particle method.
155 */
156 inline virtual G4double getTableMass() const { return getRealMass(); }
157
158 /**
159 * Get the list of particles in the cluster.
160 */
161 ParticleList const &getParticles() const { return particles; }
162
163 /// \brief Remove a particle from the cluster components.
164 void removeParticle(Particle * const p) { particles.remove(p); }
165
166 /**
167 * Add one particle to the cluster. This updates the cluster mass,
168 * energy, size, etc.
169 */
170 void addParticle(Particle * const p) {
171// assert(p->isNucleon());
172 particles.push_back(p);
173 theEnergy += p->getEnergy();
175 theMomentum += p->getMomentum();
176 thePosition += p->getPosition();
177 theA += p->getA();
178 theZ += p->getZ();
180 }
181
182 /// \brief Add a list of particles to the cluster
183 void addParticles(ParticleList const &pL) {
184 for(ParticleIter p=pL.begin(); p!=pL.end(); ++p)
185 addParticle(*p);
186 }
187
188 /// \brief Returns the list of particles that make up the cluster
190
191 std::string print() const {
192 std::stringstream ss;
193 ss << "Cluster (ID = " << ID << ") type = ";
195 ss << std::endl
196 << " A = " << theA << std::endl
197 << " Z = " << theZ << std::endl
198 << " mass = " << getMass() << std::endl
199 << " energy = " << theEnergy << std::endl
200 << " momentum = "
201 << theMomentum.print()
202 << std::endl
203 << " position = "
204 << thePosition.print()
205 << std::endl
206 << "Contains the following particles:"
207 << std::endl;
208 for(ParticleIter i=particles.begin(); i!=particles.end(); ++i)
209 ss << (*i)->print();
210 ss << std::endl;
211 return ss.str();
212 }
213
214 /// \brief Initialise the NuclearDensity pointer and sample the particles
215 virtual void initializeParticles();
216
217 /** \brief Boost to the CM of the component particles
218 *
219 * The position of all particles in the particles list is shifted so that
220 * their centre of mass is in the origin and their total momentum is
221 * zero.
222 */
224
225 // First compute the current CM position and total momentum
226 ThreeVector theCMPosition, theTotalMomentum;
227 G4double theTotalEnergy = 0.0;
228 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
229 theCMPosition += (*p)->getPosition();
230 theTotalMomentum += (*p)->getMomentum();
231 theTotalEnergy += (*p)->getEnergy();
232 }
233 theCMPosition /= theA;
234// assert((unsigned int)theA==particles.size());
235
236 // Now determine the CM velocity of the particles
237 // commented out because currently unused, see below
238 // ThreeVector betaCM = theTotalMomentum / theTotalEnergy;
239
240 // The new particle positions and momenta are scaled by a factor of
241 // \f$\sqrt{A/(A-1)}\f$, so that the resulting density distributions in
242 // the CM have the same variance as the one we started with.
243 const G4double rescaling = std::sqrt(((G4double)theA)/((G4double)(theA-1)));
244
245 // Loop again to boost and reposition
246 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
247 // \bug{We should do the following, but the Fortran version actually
248 // does not!
249 // (*p)->boost(betaCM);
250 // Here is what the Fortran version does:}
251 (*p)->setMomentum(((*p)->getMomentum()-theTotalMomentum/theA)*rescaling);
252
253 // Set the CM position of the particles
254 (*p)->setPosition(((*p)->getPosition()-theCMPosition)*rescaling);
255 }
256
257 // Set the global cluster kinematic variables
258 thePosition.setX(0.0);
259 thePosition.setY(0.0);
260 thePosition.setZ(0.0);
261 theMomentum.setX(0.0);
262 theMomentum.setY(0.0);
263 theMomentum.setZ(0.0);
264 theEnergy = getMass();
265
266 DEBUG("Cluster boosted to internal CM:" << std::endl << print());
267
268 }
269
270 /** \brief Put the cluster components off shell
271 *
272 * The Cluster components are put off shell in such a way that their total
273 * energy equals the cluster mass.
274 */
276 // Compute the dynamical potential
277 const G4double theDynamicalPotential = computeDynamicalPotential();
278 DEBUG("The dynamical potential is " << theDynamicalPotential << " MeV" << std::endl);
279
280 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
281 const G4double energy = (*p)->getEnergy() - theDynamicalPotential;
282 const ThreeVector &momentum = (*p)->getMomentum();
283 // Here particles are put off-shell so that we can satisfy the energy-
284 // and momentum-conservation laws
285 (*p)->setEnergy(energy);
286 (*p)->setMass(std::sqrt(energy*energy - momentum.mag2()));
287 DEBUG("Cluster components are now off shell:" << std::endl
288 << print());
289 }
290 }
291
292 /** \brief Set the position of the cluster
293 *
294 * This overloads the Particle method to take into account that the
295 * positions of the cluster members must be updated as well.
296 */
300 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
301 (*p)->setPosition((*p)->getPosition()+shift);
302 }
303 }
304
305 /** \brief Boost the cluster with the indicated velocity
306 *
307 * The Cluster is boosted as a whole, just like any Particle object;
308 * moreover, the internal components (particles list) are also boosted,
309 * according to Alain Boudard's off-shell recipe.
310 *
311 * \param aBoostVector the velocity to boost to [c]
312 */
313 void boost(const ThreeVector &aBoostVector) {
314 Particle::boost(aBoostVector);
315 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
316 (*p)->boost(aBoostVector);
317 // Apply Lorentz contraction to the particle position
318 (*p)->lorentzContract(aBoostVector,thePosition);
319 }
320
321 DEBUG("Cluster was boosted with (bx,by,bz)=("
322 << aBoostVector.getX() << ", " << aBoostVector.getY() << ", " << aBoostVector.getZ() << "):"
323 << std::endl << print());
324
325 }
326
327 /** \brief Freeze the internal motion of the particles
328 *
329 * Each particle is assigned a frozen momentum four-vector determined by
330 * the collective cluster velocity. This is used for propagation, but not
331 * for dynamics. Normal propagation is restored by calling the
332 * Particle::thawPropagation() method, which should be done in
333 * InteractionAvatar::postInteraction.
334 */
336 const ThreeVector &normMomentum = theMomentum / getMass();
337 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
338 const G4double pMass = (*p)->getMass();
339 const ThreeVector frozenMomentum = normMomentum * pMass;
340 const G4double frozenEnergy = std::sqrt(frozenMomentum.mag2()+pMass*pMass);
341 (*p)->setFrozenMomentum(frozenMomentum);
342 (*p)->setFrozenEnergy(frozenEnergy);
343 (*p)->freezePropagation();
344 }
345 }
346
347 /** \brief Rotate position and momentum of all the particles
348 *
349 * This includes the cluster components. Overloads Particle::rotate().
350 *
351 * \param angle the rotation angle
352 * \param axis a unit vector representing the rotation axis
353 */
354 virtual void rotate(const G4double angle, const ThreeVector &axis) {
355 Particle::rotate(angle, axis);
356 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
357 (*p)->rotate(angle, axis);
358 }
359 }
360
361 /// \brief Make all the components projectile spectators, too
362 virtual void makeProjectileSpectator() {
364 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
365 (*p)->makeProjectileSpectator();
366 }
367 }
368
369 /// \brief Make all the components target spectators, too
370 virtual void makeTargetSpectator() {
372 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
373 (*p)->makeTargetSpectator();
374 }
375 }
376
377 /// \brief Make all the components participants, too
378 virtual void makeParticipant() {
380 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
381 (*p)->makeParticipant();
382 }
383 }
384
385 /// \brief Get the spin of the nucleus.
386 ThreeVector const &getSpin() const { return theSpin; }
387
388 /// \brief Set the spin of the nucleus.
389 void setSpin(const ThreeVector &j) { theSpin = j; }
390
391 /// \brief Get the total angular momentum (orbital + spin)
394 }
395
396 private:
397 /** \brief Compute the dynamical cluster potential
398 *
399 * Alain Boudard's boost prescription for low-energy beams requires to
400 * define a "dynamical potential" that allows us to conserve momentum and
401 * energy when boosting the projectile cluster.
402 */
403 G4double computeDynamicalPotential() {
404 G4double theDynamicalPotential = 0.0;
405 for(ParticleIter p=particles.begin(); p!=particles.end(); ++p) {
406 theDynamicalPotential += (*p)->getEnergy();
407 }
408 theDynamicalPotential -= getTableMass();
409 theDynamicalPotential /= theA;
410
411 return theDynamicalPotential;
412 }
413
414 protected:
419
420 };
421
422}
423
424#endif
#define DEBUG(x)
Class for sampling particles in a nucleus.
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
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.
virtual ~Cluster()
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.
Cluster(const G4int Z, const G4int A, const G4bool createParticleSampler=true)
Standard Cluster constructor.
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.
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.
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 freezeInternalMotion()
Freeze the internal motion of the particles.
virtual void rotate(const G4double angle, const ThreeVector &axis)
Rotate position and momentum of all 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.
static ParticleSampler * createParticleSampler(const G4int A, const G4int Z)
static std::string getName(const ParticleType t)
Get the native INCL name of the particle.
G4INCL::ThreeVector theMomentum
virtual G4INCL::ThreeVector getAngularMomentum() const
G4double getEnergy() const
G4double getPotentialEnergy() const
Get the particle potential energy.
virtual void makeTargetSpectator()
G4double thePotentialEnergy
virtual void rotate(const G4double angle, const ThreeVector &axis)
Rotate the particle position and momentum.
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::list< G4INCL::Particle * > ParticleList
std::list< G4INCL::Particle * >::const_iterator ParticleIter