Geant4 11.4.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// 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 {
66 if(A >= 0){
68 theZ = Z;
69 theA = A;
70 theS = S;
72 if(createParticleSampler)
74 }
75 else {
77 theZ = Z;
78 theA = A;
79 theS = S;
81 if(createParticleSampler)
83 }
84 }
85
86 /**
87 * A cluster can be directly built from a list of particles.
88 */
89 template<class Iterator>
90 Cluster(Iterator begin, Iterator end) :
91 Particle(),
93 theSpin(0.,0.,0.),
95 {
97 for(Iterator i = begin; i != end; ++i) {
98 addParticle(*i);
99 }
100 if (theA < 0){
102 thePosition /= (-theA);
103 }
104 else
105 thePosition /= theA;
106 setINCLMass();
108 }
109
110 virtual ~Cluster() {
111 delete theParticleSampler;
112 }
113
114 /// \brief Copy constructor
115 Cluster(const Cluster &rhs) :
116 Particle(rhs),
118 theSpin(rhs.theSpin)
119 {
120 for(ParticleIter p=rhs.particles.begin(), e=rhs.particles.end(); p!=e; ++p) {
121 particles.push_back(new Particle(**p));
122 }
123 if(rhs.theParticleSampler)
125 else
126 theParticleSampler = NULL;
127 }
128
129 /// \brief Assignment operator
130 Cluster &operator=(const Cluster &rhs) {
131 Cluster temporaryCluster(rhs);
132 Particle::operator=(temporaryCluster);
133 swap(temporaryCluster);
134 return *this;
135 }
136
137 /// \brief Helper method for the assignment operator
138 void swap(Cluster &rhs) {
139 Particle::swap(rhs);
141 std::swap(theSpin, rhs.theSpin);
142 // std::swap is overloaded by std::list and guaranteed to operate in
143 // constant time
144 std::swap(particles, rhs.particles);
146 }
147
149 return ParticleSpecies(theA, theZ, theS);
150 }
151
153 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
154 delete (*p);
155 }
157 }
158
159 void clearParticles() { particles.clear(); }
160
161 /// \brief Set the charge number of the cluster
162 void setZ(const G4int Z) { theZ = Z; }
163
164 /// \brief Set the mass number of the cluster
165 void setA(const G4int A) { theA = A; }
166
167 /// \brief Set the strangess number of the cluster
168 void setS(const G4int S) { theS = S; }
169
170 /// \brief Get the excitation energy of the cluster.
172
173 /// \brief Set the excitation energy of the cluster.
175
176 /** \brief Get the real particle mass.
177 *
178 * Overloads the Particle method.
179 */
180 inline virtual G4double getTableMass() const { return getRealMass(); }
181
182 /**
183 * Get the list of particles in the cluster.
184 */
185 ParticleList const &getParticles() const { return particles; }
186
187 /// \brief Remove a particle from the cluster components.
188 void removeParticle(Particle * const p) { particles.remove(p); }
189
190 /**
191 * Add one particle to the cluster. This updates the cluster mass,
192 * energy, size, etc.
193 */
194 void addParticle(Particle * const p) {
195 particles.push_back(p);
196 theEnergy += p->getEnergy();
198 theMomentum += p->getMomentum();
199 thePosition += p->getPosition();
200 theA += p->getA();
201 theZ += p->getZ();
202 theS += p->getS();
204 }
205
206 /// \brief Set total cluster mass, energy, size, etc. from the particles
208 theEnergy = 0.;
212 theA = 0;
213 theZ = 0;
214 theS = 0;
215 nCollisions = 0;
216 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
217 theEnergy += (*p)->getEnergy();
218 thePotentialEnergy += (*p)->getPotentialEnergy();
219 theMomentum += (*p)->getMomentum();
220 thePosition += (*p)->getPosition();
221 theA += (*p)->getA();
222 theZ += (*p)->getZ();
223 theS += (*p)->getS();
224 nCollisions += (*p)->getNumberOfCollisions();
225 }
226 }
227
228 /// \brief Add a list of particles to the cluster
229 void addParticles(ParticleList const &pL) {
230 particles = pL;
232 }
233
234 /// \brief Returns the list of particles that make up the cluster
236
237 std::string print() const {
238 std::stringstream ss;
239 ss << "Cluster (ID = " << ID << ") type = ";
241 ss << '\n'
242 << " A = " << theA << '\n'
243 << " Z = " << theZ << '\n'
244 << " S = " << theS << '\n'
245 << " mass = " << getMass() << '\n'
246 << " energy = " << theEnergy << '\n'
247 << " momentum = "
248 << theMomentum.print()
249 << '\n'
250 << " position = "
251 << thePosition.print()
252 << '\n'
253 << "Contains the following particles:"
254 << '\n';
255 for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i)
256 ss << (*i)->print();
257 ss << '\n';
258 return ss.str();
259 }
260
261 /// \brief Initialise the NuclearDensity pointer and sample the particles
262 virtual void initializeParticles();
263
264 /** \brief Boost to the CM of the component particles
265 *
266 * The position of all particles in the particles list is shifted so that
267 * their centre of mass is in the origin and their total momentum is
268 * zero.
269 */
271
272 // First compute the current CM position and total momentum
273 ThreeVector theCMPosition, theTotalMomentum;
274 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
275 theCMPosition += (*p)->getPosition();
276 theTotalMomentum += (*p)->getMomentum();
277 //theTotalEnergy += (*p)->getEnergy();
278 }
279 if(theA>=0){
280 theCMPosition /= theA;
281// assert((unsigned int)theA==particles.size());
282 } else if (theA < 0){
283 theCMPosition /= -theA;
284//assert(-theA==particles.size());
285 }
286
287 // Now determine the CM velocity of the particles
288 // commented out because currently unused, see below
289 // ThreeVector betaCM = theTotalMomentum / theTotalEnergy;
290
291 // The new particle positions and momenta are scaled by a factor of
292 // \f$\sqrt{A/(A-1)}\f$, so that the resulting density distributions in
293 // the CM have the same variance as the one we started with.
294 G4double rescaling;
295 if (theA>0)
296 rescaling = std::sqrt(((G4double)theA)/((G4double)(theA-1)));
297 else if (theA<0)
298 rescaling = std::sqrt(((G4double)(-theA))/((G4double)((-theA)-1)));
299 else
300 rescaling = 0 ;
301
302 // Loop again to boost and reposition
303 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
304 // \bug{We should do the following, but the Fortran version actually
305 // does not!
306 // (*p)->boost(betaCM);
307 // Here is what the Fortran version does:}
308 if (theA>0)
309 (*p)->setMomentum(((*p)->getMomentum()-theTotalMomentum/theA)*rescaling);
310 else if (theA<0)
311 (*p)->setMomentum(((*p)->getMomentum()-theTotalMomentum/(-theA))*rescaling);
312
313 // Set the CM position of the particles
314 (*p)->setPosition(((*p)->getPosition()-theCMPosition)*rescaling);
315 }
316
317 // Set the global cluster kinematic variables
318 thePosition.setX(0.0);
319 thePosition.setY(0.0);
320 thePosition.setZ(0.0);
321 theMomentum.setX(0.0);
322 theMomentum.setY(0.0);
323 theMomentum.setZ(0.0);
324 theEnergy = getMass();
325
326 INCL_DEBUG("Cluster boosted to internal CM:" << '\n' << print());
327
328 }
329
330 /** \brief Put the cluster components off shell
331 *
332 * The Cluster components are put off shell in such a way that their total
333 * energy equals the cluster mass.
334 */
336 // Compute the dynamical potential
337 const G4double theDynamicalPotential = computeDynamicalPotential();
338 INCL_DEBUG("The dynamical potential is " << theDynamicalPotential << " MeV" << '\n');
339
340 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
341 const G4double energy = (*p)->getEnergy() - theDynamicalPotential;
342 const ThreeVector &momentum = (*p)->getMomentum();
343 // Here particles are put off-shell so that we can satisfy the energy-
344 // and momentum-conservation laws
345 (*p)->setEnergy(energy);
346 (*p)->setMass(std::sqrt(energy*energy - momentum.mag2()));
347 }
348 INCL_DEBUG("Cluster components are now off shell:" << '\n'
349 << print());
350 }
351
352 /** \brief Set the position of the cluster
353 *
354 * This overloads the Particle method to take into account that the
355 * positions of the cluster members must be updated as well.
356 */
360 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
361 (*p)->setPosition((*p)->getPosition()+shift);
362 }
363 }
364
365 /** \brief Boost the cluster with the indicated velocity
366 *
367 * The Cluster is boosted as a whole, just like any Particle object;
368 * moreover, the internal components (particles list) are also boosted,
369 * according to Alain Boudard's off-shell recipe.
370 *
371 * \param aBoostVector the velocity to boost to [c]
372 */
373 void boost(const ThreeVector &aBoostVector) {
374 Particle::boost(aBoostVector);
375 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
376 (*p)->boost(aBoostVector);
377 // Apply Lorentz contraction to the particle position
378 (*p)->lorentzContract(aBoostVector,thePosition);
379 (*p)->rpCorrelate();
380 }
381
382 INCL_DEBUG("Cluster was boosted with (bx,by,bz)=("
383 << aBoostVector.getX() << ", " << aBoostVector.getY() << ", " << aBoostVector.getZ() << "):"
384 << '\n' << print());
385
386 }
387
388 /** \brief Freeze the internal motion of the particles
389 *
390 * Each particle is assigned a frozen momentum four-vector determined by
391 * the collective cluster velocity. This is used for propagation, but not
392 * for dynamics. Normal propagation is restored by calling the
393 * Particle::thawPropagation() method, which should be done in
394 * InteractionAvatar::postInteraction.
395 */
397 const ThreeVector &normMomentum = theMomentum / getMass();
398 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
399 const G4double pMass = (*p)->getMass();
400 const ThreeVector frozenMomentum = normMomentum * pMass;
401 const G4double frozenEnergy = std::sqrt(frozenMomentum.mag2()+pMass*pMass);
402 (*p)->setFrozenMomentum(frozenMomentum);
403 (*p)->setFrozenEnergy(frozenEnergy);
404 (*p)->freezePropagation();
405 }
406 }
407
408 /** \brief Rotate position of all the particles
409 *
410 * This includes the cluster components. Overloads Particle::rotateMomentum().
411 *
412 * \param angle the rotation angle
413 * \param axis a unit vector representing the rotation axis
414 */
415 virtual void rotatePosition(const G4double angle, const ThreeVector &axis);
416
417 /** \brief Rotate momentum of all the particles
418 *
419 * This includes the cluster components. Overloads Particle::rotateMomentum().
420 *
421 * \param angle the rotation angle
422 * \param axis a unit vector representing the rotation axis
423 */
424 virtual void rotateMomentum(const G4double angle, const ThreeVector &axis);
425
426 /// \brief Make all the components projectile spectators, too
427 virtual void makeProjectileSpectator() {
429 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
430 (*p)->makeProjectileSpectator();
431 }
432 }
433
434 /// \brief Make all the components target spectators, too
435 virtual void makeTargetSpectator() {
437 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
438 (*p)->makeTargetSpectator();
439 }
440 }
441
442 /// \brief Make all the components participants, too
443 virtual void makeParticipant() {
445 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
446 (*p)->makeParticipant();
447 }
448 }
449
450 /// \brief Get the spin of the nucleus.
451 ThreeVector const &getSpin() const { return theSpin; }
452
453 /// \brief Set the spin of the nucleus.
454 void setSpin(const ThreeVector &j) { theSpin = j; }
455
456 /// \brief Get the total angular momentum (orbital + spin)
460
461 private:
462 /** \brief Compute the dynamical cluster potential
463 *
464 * Alain Boudard's boost prescription for low-energy beams requires to
465 * define a "dynamical potential" that allows us to conserve momentum and
466 * energy when boosting the projectile cluster.
467 */
468 G4double computeDynamicalPotential() {
469 G4double theDynamicalPotential = 0.0;
470 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
471 theDynamicalPotential += (*p)->getEnergy();
472 }
473 theDynamicalPotential -= getTableMass();
474 theDynamicalPotential /= std::abs(theA);
475
476 return theDynamicalPotential;
477 }
478
479 protected:
484
486 };
487
488}
489
490#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
G4double getY() const
G4double getZ() 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
const axis_t axis_to_type< N >::axis
Definition pugixml.cc:9668