File indexing completed on 2026-09-30 08:56:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #define INCLXX_IN_GEANT4_MODE 1
0035
0036 #include "globals.hh"
0037
0038 #ifndef G4INCLCluster_hh
0039 #define G4INCLCluster_hh 1
0040
0041 #include "G4INCLParticle.hh"
0042 #include "G4INCLNuclearDensityFactory.hh"
0043 #include "G4INCLParticleSampler.hh"
0044 #include "G4INCLAllocationPool.hh"
0045
0046 namespace G4INCL {
0047
0048
0049
0050
0051
0052 class Cluster : public Particle {
0053 public:
0054
0055
0056
0057
0058
0059
0060 Cluster(const G4int Z, const G4int A, const G4int S, const G4bool createParticleSampler=true) :
0061 Particle(),
0062 theExcitationEnergy(0.),
0063 theSpin(0.,0.,0.),
0064 theParticleSampler(NULL)
0065 {
0066 if(A >= 0){
0067 setType(Composite);
0068 theZ = Z;
0069 theA = A;
0070 theS = S;
0071 setINCLMass();
0072 if(createParticleSampler)
0073 theParticleSampler = new ParticleSampler(A,Z,S);
0074 }
0075 else {
0076 setType(antiComposite);
0077 theZ = Z;
0078 theA = A;
0079 theS = S;
0080 setINCLMass();
0081 if(createParticleSampler)
0082 theParticleSampler = new ParticleSampler(A,Z,S);
0083 }
0084 }
0085
0086
0087
0088
0089 template<class Iterator>
0090 Cluster(Iterator begin, Iterator end) :
0091 Particle(),
0092 theExcitationEnergy(0.),
0093 theSpin(0.,0.,0.),
0094 theParticleSampler(NULL)
0095 {
0096 setType(Composite);
0097 for(Iterator i = begin; i != end; ++i) {
0098 addParticle(*i);
0099 }
0100 if (theA < 0){
0101 setType(antiComposite);
0102 thePosition /= (-theA);
0103 }
0104 else
0105 thePosition /= theA;
0106 setINCLMass();
0107 adjustMomentumFromEnergy();
0108 }
0109
0110 virtual ~Cluster() {
0111 delete theParticleSampler;
0112 }
0113
0114
0115 Cluster(const Cluster &rhs) :
0116 Particle(rhs),
0117 theExcitationEnergy(rhs.theExcitationEnergy),
0118 theSpin(rhs.theSpin)
0119 {
0120 for(ParticleIter p=rhs.particles.begin(), e=rhs.particles.end(); p!=e; ++p) {
0121 particles.push_back(new Particle(**p));
0122 }
0123 if(rhs.theParticleSampler)
0124 theParticleSampler = new ParticleSampler(rhs.theA,rhs.theZ,rhs.theS);
0125 else
0126 theParticleSampler = NULL;
0127 }
0128
0129
0130 Cluster &operator=(const Cluster &rhs) {
0131 Cluster temporaryCluster(rhs);
0132 Particle::operator=(temporaryCluster);
0133 swap(temporaryCluster);
0134 return *this;
0135 }
0136
0137
0138 void swap(Cluster &rhs) {
0139 Particle::swap(rhs);
0140 std::swap(theExcitationEnergy, rhs.theExcitationEnergy);
0141 std::swap(theSpin, rhs.theSpin);
0142
0143
0144 std::swap(particles, rhs.particles);
0145 std::swap(theParticleSampler, rhs.theParticleSampler);
0146 }
0147
0148 ParticleSpecies getSpecies() const {
0149 return ParticleSpecies(theA, theZ, theS);
0150 }
0151
0152 void deleteParticles() {
0153 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0154 delete (*p);
0155 }
0156 clearParticles();
0157 }
0158
0159 void clearParticles() { particles.clear(); }
0160
0161
0162 void setZ(const G4int Z) { theZ = Z; }
0163
0164
0165 void setA(const G4int A) { theA = A; }
0166
0167
0168 void setS(const G4int S) { theS = S; }
0169
0170
0171 G4double getExcitationEnergy() const { return theExcitationEnergy; }
0172
0173
0174 void setExcitationEnergy(const G4double e) { theExcitationEnergy=e; }
0175
0176
0177
0178
0179
0180 inline virtual G4double getTableMass() const { return getRealMass(); }
0181
0182
0183
0184
0185 ParticleList const &getParticles() const { return particles; }
0186
0187
0188 void removeParticle(Particle * const p) { particles.remove(p); }
0189
0190
0191
0192
0193
0194 void addParticle(Particle * const p) {
0195 particles.push_back(p);
0196 theEnergy += p->getEnergy();
0197 thePotentialEnergy += p->getPotentialEnergy();
0198 theMomentum += p->getMomentum();
0199 thePosition += p->getPosition();
0200 theA += p->getA();
0201 theZ += p->getZ();
0202 theS += p->getS();
0203 nCollisions += p->getNumberOfCollisions();
0204 }
0205
0206
0207 void updateClusterParameters() {
0208 theEnergy = 0.;
0209 thePotentialEnergy = 0.;
0210 theMomentum = ThreeVector();
0211 thePosition = ThreeVector();
0212 theA = 0;
0213 theZ = 0;
0214 theS = 0;
0215 nCollisions = 0;
0216 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0217 theEnergy += (*p)->getEnergy();
0218 thePotentialEnergy += (*p)->getPotentialEnergy();
0219 theMomentum += (*p)->getMomentum();
0220 thePosition += (*p)->getPosition();
0221 theA += (*p)->getA();
0222 theZ += (*p)->getZ();
0223 theS += (*p)->getS();
0224 nCollisions += (*p)->getNumberOfCollisions();
0225 }
0226 }
0227
0228
0229 void addParticles(ParticleList const &pL) {
0230 particles = pL;
0231 updateClusterParameters();
0232 }
0233
0234
0235 ParticleList getParticleList() const { return particles; }
0236
0237 std::string print() const {
0238 std::stringstream ss;
0239 ss << "Cluster (ID = " << ID << ") type = ";
0240 ss << ParticleTable::getName(theType);
0241 ss << '\n'
0242 << " A = " << theA << '\n'
0243 << " Z = " << theZ << '\n'
0244 << " S = " << theS << '\n'
0245 << " mass = " << getMass() << '\n'
0246 << " energy = " << theEnergy << '\n'
0247 << " momentum = "
0248 << theMomentum.print()
0249 << '\n'
0250 << " position = "
0251 << thePosition.print()
0252 << '\n'
0253 << "Contains the following particles:"
0254 << '\n';
0255 for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i)
0256 ss << (*i)->print();
0257 ss << '\n';
0258 return ss.str();
0259 }
0260
0261
0262 virtual void initializeParticles();
0263
0264
0265
0266
0267
0268
0269
0270 void internalBoostToCM() {
0271
0272
0273 ThreeVector theCMPosition, theTotalMomentum;
0274 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0275 theCMPosition += (*p)->getPosition();
0276 theTotalMomentum += (*p)->getMomentum();
0277
0278 }
0279 if(theA>=0){
0280 theCMPosition /= theA;
0281
0282 } else if (theA < 0){
0283 theCMPosition /= -theA;
0284
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294 G4double rescaling;
0295 if (theA>0)
0296 rescaling = std::sqrt(((G4double)theA)/((G4double)(theA-1)));
0297 else if (theA<0)
0298 rescaling = std::sqrt(((G4double)(-theA))/((G4double)((-theA)-1)));
0299 else
0300 rescaling = 0 ;
0301
0302
0303 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0304
0305
0306
0307
0308 if (theA>0)
0309 (*p)->setMomentum(((*p)->getMomentum()-theTotalMomentum/theA)*rescaling);
0310 else if (theA<0)
0311 (*p)->setMomentum(((*p)->getMomentum()-theTotalMomentum/(-theA))*rescaling);
0312
0313
0314 (*p)->setPosition(((*p)->getPosition()-theCMPosition)*rescaling);
0315 }
0316
0317
0318 thePosition.setX(0.0);
0319 thePosition.setY(0.0);
0320 thePosition.setZ(0.0);
0321 theMomentum.setX(0.0);
0322 theMomentum.setY(0.0);
0323 theMomentum.setZ(0.0);
0324 theEnergy = getMass();
0325
0326 INCL_DEBUG("Cluster boosted to internal CM:" << '\n' << print());
0327
0328 }
0329
0330
0331
0332
0333
0334
0335 void putParticlesOffShell() {
0336
0337 const G4double theDynamicalPotential = computeDynamicalPotential();
0338 INCL_DEBUG("The dynamical potential is " << theDynamicalPotential << " MeV" << '\n');
0339
0340 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0341 const G4double energy = (*p)->getEnergy() - theDynamicalPotential;
0342 const ThreeVector &momentum = (*p)->getMomentum();
0343
0344
0345 (*p)->setEnergy(energy);
0346 (*p)->setMass(std::sqrt(energy*energy - momentum.mag2()));
0347 }
0348 INCL_DEBUG("Cluster components are now off shell:" << '\n'
0349 << print());
0350 }
0351
0352
0353
0354
0355
0356
0357 void setPosition(const ThreeVector &position) {
0358 ThreeVector shift(position-thePosition);
0359 Particle::setPosition(position);
0360 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0361 (*p)->setPosition((*p)->getPosition()+shift);
0362 }
0363 }
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373 void boost(const ThreeVector &aBoostVector) {
0374 Particle::boost(aBoostVector);
0375 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0376 (*p)->boost(aBoostVector);
0377
0378 (*p)->lorentzContract(aBoostVector,thePosition);
0379 (*p)->rpCorrelate();
0380 }
0381
0382 INCL_DEBUG("Cluster was boosted with (bx,by,bz)=("
0383 << aBoostVector.getX() << ", " << aBoostVector.getY() << ", " << aBoostVector.getZ() << "):"
0384 << '\n' << print());
0385
0386 }
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396 void freezeInternalMotion() {
0397 const ThreeVector &normMomentum = theMomentum / getMass();
0398 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0399 const G4double pMass = (*p)->getMass();
0400 const ThreeVector frozenMomentum = normMomentum * pMass;
0401 const G4double frozenEnergy = std::sqrt(frozenMomentum.mag2()+pMass*pMass);
0402 (*p)->setFrozenMomentum(frozenMomentum);
0403 (*p)->setFrozenEnergy(frozenEnergy);
0404 (*p)->freezePropagation();
0405 }
0406 }
0407
0408
0409
0410
0411
0412
0413
0414
0415 virtual void rotatePosition(const G4double angle, const ThreeVector &axis);
0416
0417
0418
0419
0420
0421
0422
0423
0424 virtual void rotateMomentum(const G4double angle, const ThreeVector &axis);
0425
0426
0427 virtual void makeProjectileSpectator() {
0428 Particle::makeProjectileSpectator();
0429 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0430 (*p)->makeProjectileSpectator();
0431 }
0432 }
0433
0434
0435 virtual void makeTargetSpectator() {
0436 Particle::makeTargetSpectator();
0437 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0438 (*p)->makeTargetSpectator();
0439 }
0440 }
0441
0442
0443 virtual void makeParticipant() {
0444 Particle::makeParticipant();
0445 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0446 (*p)->makeParticipant();
0447 }
0448 }
0449
0450
0451 ThreeVector const &getSpin() const { return theSpin; }
0452
0453
0454 void setSpin(const ThreeVector &j) { theSpin = j; }
0455
0456
0457 G4INCL::ThreeVector getAngularMomentum() const {
0458 return Particle::getAngularMomentum() + getSpin();
0459 }
0460
0461 private:
0462
0463
0464
0465
0466
0467
0468 G4double computeDynamicalPotential() {
0469 G4double theDynamicalPotential = 0.0;
0470 for(ParticleIter p=particles.begin(), e=particles.end(); p!=e; ++p) {
0471 theDynamicalPotential += (*p)->getEnergy();
0472 }
0473 theDynamicalPotential -= getTableMass();
0474 theDynamicalPotential /= std::abs(theA);
0475
0476 return theDynamicalPotential;
0477 }
0478
0479 protected:
0480 ParticleList particles;
0481 G4double theExcitationEnergy;
0482 ThreeVector theSpin;
0483 ParticleSampler *theParticleSampler;
0484
0485 INCL_DECLARE_ALLOCATION_POOL(Cluster)
0486 };
0487
0488 }
0489
0490 #endif