Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4INCLStandardPropagationModel.cc
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/*
39 * StandardPropagationModel.cpp
40 *
41 * \date 4 juin 2009
42 * \author Pekka Kaitaniemi
43 */
44
51#include "G4INCLDecayAvatar.hh"
53#include "G4INCLRandom.hh"
54#include <iostream>
55#include <algorithm>
56#include "G4INCLLogger.hh"
57#include "G4INCLGlobals.hh"
64#include "G4INCLIntersection.hh"
65#include <vector>
66
67namespace G4INCL {
68
70 :theNucleus(0), maximumTime(70.0), currentTime(0.0),
71 hadronizationTime(hTime),
72 firstAvatar(true),
73 theLocalEnergyType(localEnergyType),
74 theLocalEnergyDeltaType(localEnergyDeltaType)
75 {
76 }
77
79 {
80 delete theNucleus;
81 }
82
84 {
85 return theNucleus;
86 }
87
88//D
89
90 G4double StandardPropagationModel::shoot(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy, const G4double impactParameter, const G4double phi) {
91 if(projectileSpecies.theType==Composite || projectileSpecies.theType==antiComposite){
92 if(theNucleus->getAnnihilationType()!=Def)
93 return shootCompositeAtrest(projectileSpecies,kineticEnergy);
94 else
95 return shootComposite(projectileSpecies, kineticEnergy, impactParameter, phi);
96 }
97 else if((projectileSpecies.theType==antiProton || projectileSpecies.theType==antiNeutron) && theNucleus->getAnnihilationType()!=Def){
98 return shootAtrest(projectileSpecies.theType, kineticEnergy);
99 }
100 else{
101 return shootParticle(projectileSpecies.theType, kineticEnergy, impactParameter, phi);
102 }
103 }
104
105//D
106
108 theNucleus->setParticleNucleusCollision();
109 currentTime = 0.0;
110
111 // Create final state particles
112 const G4double projectileMass = ParticleTable::getTableParticleMass(t);
113 G4double energy = kineticEnergy + projectileMass;
114 G4double momentumZ = std::sqrt(energy*energy - projectileMass*projectileMass);
115 ThreeVector momentum(0.0, 0.0, momentumZ);
116 Particle *pb = new G4INCL::Particle(t, energy, momentum, ThreeVector());
117 if (t == antiProton){
118 PbarAtrestEntryChannel *obj = new PbarAtrestEntryChannel(theNucleus, pb);
119 ParticleList fslist = obj->makeMesonStar();
120 const G4bool isProton = obj->ProtonIsTheVictim();
121 delete pb;
122
123 //set Stopping time according to highest meson energy of the star
124 G4double temfin;
125 G4double TLab;
126 std::vector<G4double> energies;
127 std::vector<G4double> projections;
128 ThreeVector ab, cd;
129
130 for(ParticleIter pit = fslist.begin(), e = fslist.end(); pit!=e; ++pit){
131 energies.push_back((*pit)->getKineticEnergy());
132 ab = (*pit)->boostVector();
133 cd = (*pit)->getPosition();
134 projections.push_back(ab.dot(cd)); //projection length
135 }// make vector of energies
136
137 temfin = 30.18 * std::pow(theNucleus->getA(), 0.17);
138 TLab = *max_element(energies.begin(), energies.end()); //choose max energy
139
140 // energy-dependent stopping time above 2 AGeV
141 if(TLab>2000.)
142 temfin *= (5.8E4-TLab)/5.6E4;
143
144 maximumTime = temfin;
145
146 // If the incoming particle is slow, use a larger stopping time
147 const G4double rMax = theNucleus->getUniverseRadius();
148 const G4double distance = 2.*rMax;
149 const G4double maxMesonVelocityProjection = *max_element(energies.begin(), energies.end());
150 const G4double traversalTime = distance / maxMesonVelocityProjection;
151 if(maximumTime < traversalTime)
152 maximumTime = traversalTime;
153 INCL_DEBUG("Cascade stopping time is " << maximumTime << '\n');
154
155
156 // Fill in the relevant kinematic variables
157 theNucleus->setIncomingAngularMomentum(G4INCL::ThreeVector(0., 0., 0.));
158 theNucleus->setIncomingMomentum(G4INCL::ThreeVector(0., 0., 0.));
159 if(isProton){
160 theNucleus->setInitialEnergy(pb->getEnergy()
161 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ() + 1,theNucleus->getS()));
162 }
163 else{
164 theNucleus->setInitialEnergy(pb->getEnergy()
165 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ(),theNucleus->getS()));
166 }
167 //kinetic energy excluded from the balance
168
169 for(ParticleIter p = fslist.begin(), e = fslist.end(); p!=e; ++p){
170 (*p)->makeProjectileSpectator();
171 }
172
174 firstAvatar = false;
175
176 // Get the entry avatars for mesons
177 IAvatarList theAvatarList = obj->bringMesonStar(fslist, theNucleus);
178 delete obj;
179 theNucleus->getStore()->addParticleEntryAvatars(theAvatarList);
180 INCL_DEBUG("Avatars added" << '\n');
181
182 } //end (t == antiProton)
183 else if (t == antiNeutron){
184 NbarAtrestEntryChannel *obj = new NbarAtrestEntryChannel(theNucleus, pb);
185 ParticleList fslist = obj->makeMesonStar();
186 const bool isProton = obj->ProtonIsTheVictim();
187 delete pb;
188
189 //set Stopping time according to highest meson energy of the star
190 G4double temfin;
191 G4double TLab;
192 std::vector<double> energies;
193 std::vector<double> projections;
194 ThreeVector ab, cd;
195
196 for(ParticleIter pit = fslist.begin(), e = fslist.end(); pit!=e; ++pit){
197 energies.push_back((*pit)->getKineticEnergy());
198 ab = (*pit)->boostVector();
199 cd = (*pit)->getPosition();
200 projections.push_back(ab.dot(cd)); //projection length
201 }// make vector of energies
202
203 temfin = 30.18 * std::pow(theNucleus->getA(), 0.17);
204 TLab = *max_element(energies.begin(), energies.end()); //choose max energy
205
206 // energy-dependent stopping time above 2 AGeV
207 if(TLab>2000.)
208 temfin *= (5.8E4-TLab)/5.6E4;
209
210 maximumTime = temfin;
211
212 // If the incoming particle is slow, use a larger stopping time
213 const G4double rMax = theNucleus->getUniverseRadius();
214 const G4double distance = 2.*rMax;
215 const G4double maxMesonVelocityProjection = *max_element(energies.begin(), energies.end());
216 const G4double traversalTime = distance / maxMesonVelocityProjection;
217 if(maximumTime < traversalTime)
218 maximumTime = traversalTime;
219 INCL_DEBUG("Cascade stopping time is " << maximumTime << '\n');
220
221
222 // Fill in the relevant kinematic variables
223 theNucleus->setIncomingAngularMomentum(G4INCL::ThreeVector(0., 0., 0.));
224 theNucleus->setIncomingMomentum(G4INCL::ThreeVector(0., 0., 0.));
225 if(isProton){
226 theNucleus->setInitialEnergy(pb->getEnergy()
227 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ() + 1,theNucleus->getS()));
228 }
229 else{
230 theNucleus->setInitialEnergy(pb->getEnergy()
231 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ(),theNucleus->getS()));
232 }
233 //kinetic energy excluded from the balance
234
235 for(ParticleIter p = fslist.begin(), e = fslist.end(); p!=e; ++p){
236 (*p)->makeProjectileSpectator();
237 }
238
240 firstAvatar = false;
241
242 // Get the entry avatars for mesons
243 IAvatarList theAvatarList = obj->bringMesonStar(fslist, theNucleus);
244 delete obj;
245 theNucleus->getStore()->addParticleEntryAvatars(theAvatarList);
246 INCL_DEBUG("Avatars added" << '\n');
247 }
248
249 return 99.;
250 }
251
252//D
253
254 G4double StandardPropagationModel::shootParticle(ParticleType const type, const G4double kineticEnergy, const G4double impactParameter, const G4double phi) {
255 theNucleus->setParticleNucleusCollision();
256 currentTime = 0.0;
257
258 // Create the projectile particle
259 const G4double projectileMass = ParticleTable::getTableParticleMass(type);
260 G4double energy = kineticEnergy + projectileMass;
261 G4double momentumZ = std::sqrt(energy*energy - projectileMass*projectileMass);
262 ThreeVector momentum(0.0, 0.0, momentumZ);
263 Particle *p= new G4INCL::Particle(type, energy, momentum, ThreeVector());
264
265 G4double temfin;
266 G4double TLab;
267 if( p->isMeson()) {
268 temfin = 30.18 * std::pow(theNucleus->getA(), 0.17);
269 TLab = p->getKineticEnergy();
270 } else {
271 temfin = 29.8 * std::pow(theNucleus->getA(), 0.16);
272 TLab = p->getKineticEnergy()/p->getA();
273 }
274
275 // energy-dependent stopping time above 2 AGeV
276 if(TLab>2000.)
277 temfin *= (5.8E4-TLab)/5.6E4;
278
279 maximumTime = temfin;
280
281 // If the incoming particle is slow, use a larger stopping time
282 const G4double rMax = theNucleus->getUniverseRadius();
283 const G4double distance = 2.*rMax;
284 const G4double projectileVelocity = p->boostVector().mag();
285 const G4double traversalTime = distance / projectileVelocity;
286 if(maximumTime < traversalTime)
287 maximumTime = traversalTime;
288 INCL_DEBUG("Cascade stopping time is " << maximumTime << '\n');
289
290 // If the incoming particle is an antinucleon use a larger stopping time
291 if( p->isAntiNucleon()) maximumTime *= 2.;
292
293 // If Coulomb is activated, do not process events with impact
294 // parameter larger than the maximum impact parameter, taking into
295 // account Coulomb distortion.
296 if(impactParameter>CoulombDistortion::maxImpactParameter(p->getSpecies(), kineticEnergy, theNucleus)) {
297 INCL_DEBUG("impactParameter>CoulombDistortion::maxImpactParameter" << '\n');
298 delete p;
299 return -1.;
300 }
301
302 ThreeVector position(impactParameter * std::cos(phi),
303 impactParameter * std::sin(phi),
304 0.);
306
307 // Fill in the relevant kinematic variables
308 theNucleus->setIncomingAngularMomentum(p->getAngularMomentum());
309 theNucleus->setIncomingMomentum(p->getMomentum());
310 theNucleus->setInitialEnergy(p->getEnergy()
311 + ParticleTable::getTableMass(theNucleus->getA(),theNucleus->getZ(),theNucleus->getS()));
312
313 // Reset the particle kinematics to the INCL values
314 p->setINCLMass();
315 p->setEnergy(p->getMass() + kineticEnergy);
317
320 firstAvatar = false;
321
322 // Get the entry avatars from Coulomb and put them in the Store
323 ParticleEntryAvatar *theEntryAvatar = CoulombDistortion::bringToSurface(p, theNucleus);
324 if(theEntryAvatar) {
325 theNucleus->getStore()->addParticleEntryAvatar(theEntryAvatar);
326
327 return p->getTransversePosition().mag();
328 } else {
329 delete p;
330 return -1.;
331 }
332 }
333
334 G4double StandardPropagationModel::shootComposite(ParticleSpecies const &species, const G4double kineticEnergy, const G4double impactParameter, const G4double phi) {
335 theNucleus->setNucleusNucleusCollision();
336 currentTime = 0.0;
337
338 // Create the ProjectileRemnant object
339 ProjectileRemnant *pr = new ProjectileRemnant(species, kineticEnergy);
340
341 // Same stopping time as for nucleon-nucleus
342 maximumTime = 29.8 * std::pow(theNucleus->getA(), 0.16);
343
344 // If the incoming cluster is slow, use a larger stopping
345 G4double rms=0.;
346 if(species.theType == Composite){
348 }
349 else if(species.theType == antiComposite){
350 rms = ParticleTable::getLargestNuclearRadius(-(pr->getA()), -(pr->getZ()));
351 }
352 else {
353 INCL_ERROR("a non-composite try to go through shootComposite : " << species.theType << '\n');
354 }
355 const G4double rMax = theNucleus->getUniverseRadius();
356 const G4double distance = 2.*rMax + 2.725*rms;
357 const G4double projectileVelocity = pr->boostVector().mag();
358 const G4double traversalTime = distance / projectileVelocity;
359 if(maximumTime < traversalTime)
360 maximumTime = traversalTime;
361 INCL_DEBUG("Cascade stopping time is " << maximumTime << '\n');
362
363 // If Coulomb is activated, do not process events with impact
364 // parameter larger than the maximum impact parameter, taking into
365 // account Coulomb distortion.
366 if(impactParameter>CoulombDistortion::maxImpactParameter(pr,theNucleus)) {
367 INCL_DEBUG("impactParameter>CoulombDistortion::maxImpactParameter" << '\n');
368 delete pr;
369 return -1.;
370 }
371
372 // Position the cluster at the right impact parameter
373 ThreeVector position(impactParameter * std::cos(phi),
374 impactParameter * std::sin(phi),
375 0.);
377
378 // Fill in the relevant kinematic variables
379 theNucleus->setIncomingAngularMomentum(pr->getAngularMomentum());
380 theNucleus->setIncomingMomentum(pr->getMomentum());
381 theNucleus->setInitialEnergy(pr->getEnergy()
382 + ParticleTable::getTableMass(theNucleus->getA(),theNucleus->getZ(),theNucleus->getS()));
383
385 firstAvatar = false;
386
387 // Get the entry avatars from Coulomb
388 IAvatarList theAvatarList
389 = CoulombDistortion::bringToSurface(pr, theNucleus);
390
391 if(theAvatarList.empty()) {
392 INCL_DEBUG("No ParticleEntryAvatar found, transparent event" << '\n');
393 delete pr;
394 return -1.;
395 }
396
397 /* Store the internal kinematics of the projectile remnant.
398 *
399 * Note that this is at variance with the Fortran version, which stores
400 * the initial kinematics of the particles *after* putting the spectators
401 * on mass shell, but *before* removing the same energy from the
402 * participants. Due to the different code flow, doing so in the C++
403 * version leads to wrong excitation energies for the forced compound
404 * nucleus.
405 */
406 pr->storeComponents();
407
408 // Tell the Nucleus about the ProjectileRemnant
409 theNucleus->setProjectileRemnant(pr);
410
411 // Register the ParticleEntryAvatars
412 theNucleus->getStore()->addParticleEntryAvatars(theAvatarList);
413
414 return pr->getTransversePosition().mag();
415 }
416
418 if(theNucleus->getAnnihilationType()==PType || theNucleus->getAnnihilationType()==NType){
419 INCL_DEBUG("Antideuteron annihilation Model B chosen, Annihilation of one antinucleon " << '\n');
420 theNucleus->setParticleNucleusCollision();
421 currentTime = 0.0;
422
423 //Dummy Cluster to intialise the anticomposite and distribute the energy and positio
424 Cluster *DummyC = new Cluster(-1,-2,0);
425 DummyC->setTableMass();
426 DummyC->initializeParticles();
427 DummyC->internalBoostToCM();
428 const G4double projectileMass = DummyC->getMass();
429 const G4double energy = kineticEnergy + projectileMass;
430 const G4double momentumZ = std::sqrt(energy*energy - projectileMass*projectileMass);
431 const ThreeVector aBoostVector = ThreeVector(0.0, 0.0, momentumZ / energy);
432 DummyC->boost(-aBoostVector);
433 DummyC->makeProjectileSpectator();
434
437 ParticleList Antis = DummyC->getParticles();
438 for(ParticleIter i = Antis.begin(), e=Antis.end();i!=e;++i){
439 if((*i)->getType()==antiProton){
440 pb = (*i);
441 DummyC->removeParticle((*i));
442 }
443 else if((*i)->getType()==antiNeutron){
444 nb = (*i);
445 DummyC->removeParticle((*i));
446 }
447 }
448 delete DummyC;
449 Config const *theConfig=theNucleus->getStore()->getConfig();
450 if(nb->getKineticEnergy() <= theConfig->getnbAtrestThreshold() && (pb->getEnergy() >= pb->getMass())){
451 INCL_DEBUG("Annihilation of the Antineutron " << '\n');
452 NbarAtrestEntryChannel *obj = new NbarAtrestEntryChannel(theNucleus, nb);
453 ParticleList fslist = obj->makeMesonStar();
454 const G4bool isProton = obj->ProtonIsTheVictim();
455 //delete nb;
456
457 //set Stopping time according to highest meson energy of the star
458 G4double temfin;
459 G4double TLab;
460 std::vector<G4double> energies;
461 std::vector<G4double> projections;
462 ThreeVector ab, cd;
463 for(ParticleIter pit = fslist.begin(), e = fslist.end(); pit!=e; ++pit){
464 energies.push_back((*pit)->getKineticEnergy());
465 ab = (*pit)->boostVector();
466 cd = (*pit)->getPosition();
467 projections.push_back(ab.dot(cd)); //projection length
468 }// make vector of energies
469 temfin = 30.18 * std::pow(theNucleus->getA(), 0.17);
470 TLab = *max_element(energies.begin(), energies.end()); //choose max energy
471 if(TLab>2000.)
472 temfin *= (5.8E4-TLab)/5.6E4;
473 maximumTime = temfin;
474 // If the incoming particle is slow, use a larger stopping time
475 const G4double rMax = theNucleus->getUniverseRadius();
476 const G4double distance = 2.*rMax;
477 const G4double maxMesonVelocityProjection = *max_element(energies.begin(), energies.end());
478 const G4double traversalTime = distance / maxMesonVelocityProjection;
479 if(maximumTime < traversalTime)
480 maximumTime = traversalTime;
481 INCL_DEBUG("Cascade stopping time is " << maximumTime << '\n');
482
483 // Fill in the relevant kinematic variables
484 theNucleus->setIncomingAngularMomentum(pb->getAngularMomentum());
485 theNucleus->setIncomingMomentum(pb->getMomentum());
486 if(isProton){
487 theNucleus->setInitialEnergy(nb->getMass() + pb->getEnergy()
488 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ() + 1,theNucleus->getS()));
489 }
490 else{
491 theNucleus->setInitialEnergy(nb->getMass() + pb->getEnergy()
492 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ(),theNucleus->getS()));
493 }
494 // Reset the particle kinematics to the INCL values
495 for(ParticleIter p = fslist.begin(), e = fslist.end(); p!=e; ++p){
496 (*p)->makeProjectileSpectator();
497 }
499
501 firstAvatar = false;
502
503 // Get the entry avatars for mesons
504 IAvatarList theAvatarList = obj->bringMesonStar(fslist, theNucleus);
505 delete obj;
506 theNucleus->getStore()->addParticleEntryAvatars(theAvatarList);
507 // Get the entry avatars from Coulomb and put them in the Store
508 ParticleEntryAvatar *theEntryAvatar = CoulombDistortion::bringToSurfaceAbar(pb, theNucleus);
509 if(theEntryAvatar) {
510 theNucleus->getStore()->addParticleEntryAvatar(theEntryAvatar);
511 INCL_DEBUG("Avatars added" << '\n');
512 return pb->getTransversePosition().mag();
513 } else {
514 INCL_DEBUG("Antiproton is transparent, not entering the nucleus " << '\n');
515 //Transparent event
516 theNucleus->getStore()->addToMissed(pb);
517 delete nb;
518 return 99.;
519 }
520
521 }
522 else{
523 INCL_DEBUG("Annihilation of the Antiproton " << '\n');
524 PbarAtrestEntryChannel *obj = new PbarAtrestEntryChannel(theNucleus, pb);
525 ParticleList fslist = obj->makeMesonStar();
526 const G4bool isProton = obj->ProtonIsTheVictim();
527 //delete pb;
528
529 //set Stopping time according to highest meson energy of the star
530 G4double temfin;
531 G4double TLab;
532 std::vector<G4double> energies;
533 std::vector<G4double> projections;
534 ThreeVector ab, cd;
535 for(ParticleIter pit = fslist.begin(), e = fslist.end(); pit!=e; ++pit){
536 energies.push_back((*pit)->getKineticEnergy());
537 ab = (*pit)->boostVector();
538 cd = (*pit)->getPosition();
539 projections.push_back(ab.dot(cd)); //projection length
540 }// make vector of energies
541 temfin = 30.18 * std::pow(theNucleus->getA(), 0.17);
542 TLab = *max_element(energies.begin(), energies.end()); //choose max energy
543 if(TLab>2000.)
544 temfin *= (5.8E4-TLab)/5.6E4;
545 maximumTime = temfin;
546 // If the incoming particle is slow, use a larger stopping time
547 const G4double rMax = theNucleus->getUniverseRadius();
548 const G4double distance = 2.*rMax;
549 const G4double maxMesonVelocityProjection = *max_element(energies.begin(), energies.end());
550 const G4double traversalTime = distance / maxMesonVelocityProjection;
551 if(maximumTime < traversalTime)
552 maximumTime = traversalTime;
553 INCL_DEBUG("Cascade stopping time is " << maximumTime << '\n');
554
555
556
557 // Fill in the relevant kinematic variables
558 theNucleus->setIncomingAngularMomentum(nb->getAngularMomentum());
559 theNucleus->setIncomingMomentum(nb->getMomentum());
560 if(isProton){
561 theNucleus->setInitialEnergy(pb->getMass() + nb->getEnergy()
562 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ() + 1,theNucleus->getS()));
563 }
564 else{
565 theNucleus->setInitialEnergy(pb->getMass() + nb->getEnergy()
566 + ParticleTable::getTableMass(theNucleus->getA() + 1,theNucleus->getZ(),theNucleus->getS()));
567 }
568 // Reset the particle kinematics to the INCL values
569 for(ParticleIter p = fslist.begin(), e = fslist.end(); p!=e; ++p){
570 (*p)->makeProjectileSpectator();
571 }
573
575 firstAvatar = false;
576
577 // Get the entry avatars for mesons
578 IAvatarList theAvatarList = obj->bringMesonStar(fslist, theNucleus);
579 delete obj;
580 theNucleus->getStore()->addParticleEntryAvatars(theAvatarList);
581 // Get the entry avatars from Coulomb and put them in the Store
582 ParticleEntryAvatar *theEntryAvatar = CoulombDistortion::bringToSurfaceAbar(nb, theNucleus);
583 if(theEntryAvatar) {
584 theNucleus->getStore()->addParticleEntryAvatar(theEntryAvatar);
585 INCL_DEBUG("Avatars added" << '\n');
586 return nb->getTransversePosition().mag();
587 } else {
588 INCL_DEBUG("Antineutron is transparent, not entering the nucleus " << '\n');
589 theNucleus->setIncomingAngularMomentum(ThreeVector(0.,0.,0.));
590 theNucleus->setIncomingMomentum(ThreeVector(0.,0.,0.));
591 //Transparent event
592 theNucleus->getStore()->addToMissed(nb);
593 delete pb;
594 return 99.;
595 }
596 delete theConfig;
597 }
598 } else{
599 theNucleus->setNucleusNucleusCollision();
600 currentTime =0.0;
601 maximumTime = 29.8 * std::pow(theNucleus->getA(), 0.16);
602
603 ProjectileRemnant *pr = new ProjectileRemnant(species, kineticEnergy);
604 INCL_DEBUG("Antideuteron annihilation Model A chosen, Annihilation of Antideuteron as a whole" << '\n');
606 ParticleList fslist = obj->makeMesonStar();
607 //set Stopping time according to highest meson energy of the star
608 G4double temfin;
609 G4double TLab;
610 std::vector<G4double> energies;
611 std::vector<G4double> projections;
612 ThreeVector ab, cd;
613
614 for(ParticleIter pit = fslist.begin(), e = fslist.end(); pit!=e; ++pit){
615 energies.push_back((*pit)->getKineticEnergy());
616 ab = (*pit)->boostVector();
617 cd = (*pit)->getPosition();
618 projections.push_back(ab.dot(cd)); //projection length
619 }// make vector of energies
620
621 temfin = 30.18 * std::pow(theNucleus->getA(), 0.17);
622 TLab = *max_element(energies.begin(), energies.end()); //choose max energy
623
624 // energy-dependent stopping time above 2 AGeV
625 if(TLab>2000.)
626 temfin *= (5.8E4-TLab)/5.6E4;
627
628 maximumTime = temfin;
629
630 // If the incoming particle is slow, use a larger stopping time
631 const G4double rMax = theNucleus->getUniverseRadius();
632 const G4double distance = 2.*rMax;
633 const G4double maxMesonVelocityProjection = *max_element(energies.begin(), energies.end());
634 const G4double traversalTime = distance / maxMesonVelocityProjection;
635 if(maximumTime < traversalTime)
636 maximumTime = traversalTime;
637 INCL_DEBUG("Cascade stopping time is " << maximumTime << '\n');
638
639 // Fill in the relevant kinematic variables
640 theNucleus->setIncomingAngularMomentum(G4INCL::ThreeVector(0., 0., 0.));
641 theNucleus->setIncomingMomentum(G4INCL::ThreeVector(0.,0.,0.));
642 if(theNucleus->getAnnihilationType()==DNbarNPbarNType)
643 theNucleus->setInitialEnergy(pr->getMass() + ParticleTable::getTableMass(theNucleus->getA() + 2, theNucleus->getZ(), theNucleus->getS()));
644 else if(theNucleus->getAnnihilationType()==DNbarPPbarPType)
645 theNucleus->setInitialEnergy(pr->getMass() + ParticleTable::getTableMass(theNucleus->getA() + 2, theNucleus->getZ() + 2,theNucleus->getS()));
646 else if(theNucleus->getAnnihilationType() == DNbarNPbarPType || theNucleus->getAnnihilationType()==DNbarPPbarNType)
647 theNucleus->setInitialEnergy(pr->getMass() + ParticleTable::getTableMass(theNucleus->getA() + 2, theNucleus->getZ() +1, theNucleus->getS()));
648
649 for(ParticleIter p = fslist.begin(), e = fslist.end(); p!=e; ++p){
650 (*p)->makeProjectileSpectator();
651 }
652
654 firstAvatar = false;
655
656 IAvatarList theAvatarList = obj->bringMesonStar(fslist, theNucleus);
657 delete pr;
658 delete obj;
659 theNucleus->getStore()->addParticleEntryAvatars(theAvatarList);
660 INCL_DEBUG("Avatars added" << '\n');
661 return 99.;
662 }
663 }
664
666 return maximumTime;
667 }
668
670// assert(time>0.0);
671 maximumTime = time;
672 }
673
675 return currentTime;
676 }
677
679 {
680 theNucleus = nucleus;
681 }
682
684 {
685 if(anAvatar) theNucleus->getStore()->add(anAvatar);
686 }
687
689 // Is either particle a participant?
690 if(!p1->isParticipant() && !p2->isParticipant() && p1->getParticipantType()==p2->getParticipantType()) return NULL;
691
692 // Is it a pi-resonance collision (we don't treat them)?
693 if((p1->isResonance() && p2->isPion()) || (p1->isPion() && p2->isResonance()))
694 return NULL;
695
696 // Is it a photon collision (we don't treat them)?
697 if(p1->isPhoton() || p2->isPhoton())
698 return NULL;
699
700 // Will the avatar take place between now and the end of the cascade?
701 G4double minDistOfApproachSquared = 0.0;
702 G4double t = getTime(p1, p2, &minDistOfApproachSquared);
703 if(t>maximumTime || t<currentTime+hadronizationTime) return NULL;
704
705 // Local energy. Jump through some hoops to calculate the cross section
706 // at the collision point, and clean up after yourself afterwards.
707 G4bool hasLocalEnergy;
708 if(p1->isPion() || p2->isPion())
709 hasLocalEnergy = ((theLocalEnergyDeltaType == FirstCollisionLocalEnergy &&
710 theNucleus->getStore()->getBook().getAcceptedCollisions()==0) ||
711 theLocalEnergyDeltaType == AlwaysLocalEnergy);
712 else
713 hasLocalEnergy = ((theLocalEnergyType == FirstCollisionLocalEnergy &&
714 theNucleus->getStore()->getBook().getAcceptedCollisions()==0) ||
715 theLocalEnergyType == AlwaysLocalEnergy);
716 const G4bool p1HasLocalEnergy = (hasLocalEnergy && !p1->isMeson() && !p1->isAntiNucleon());
717 const G4bool p2HasLocalEnergy = (hasLocalEnergy && !p2->isMeson() && !p2->isAntiNucleon());
718
719 if(p1HasLocalEnergy) {
720 backupParticle1 = *p1;
721 p1->propagate(t - currentTime);
722 if(p1->getPosition().mag() > theNucleus->getSurfaceRadius(p1)) {
723 *p1 = backupParticle1;
724 return NULL;
725 }
727 }
728 if(p2HasLocalEnergy) {
729 backupParticle2 = *p2;
730 p2->propagate(t - currentTime);
731 if(p2->getPosition().mag() > theNucleus->getSurfaceRadius(p2)) {
732 *p2 = backupParticle2;
733 if(p1HasLocalEnergy) {
734 *p1 = backupParticle1;
735 }
736 return NULL;
737 }
739 }
740
741 // Compute the total cross section
742 const G4double totalCrossSection = CrossSections::total(p1, p2);
743 const G4double squareTotalEnergyInCM = KinematicsUtils::squareTotalEnergyInCM(p1,p2);
744
745 // Restore particles to their state before the local-energy tweak
746 if(p1HasLocalEnergy) {
747 *p1 = backupParticle1;
748 }
749 if(p2HasLocalEnergy) {
750 *p2 = backupParticle2;
751 }
752
753 // Is the CM energy > cutNN? (no cutNN on the first collision)
754 if(theNucleus->getStore()->getBook().getAcceptedCollisions()>0
755 && p1->isNucleon() && p2->isNucleon()
756 && squareTotalEnergyInCM < BinaryCollisionAvatar::getCutNNSquared()) return NULL;
757
758 // Do the particles come close enough to each other?
759 if(Math::tenPi*minDistOfApproachSquared > totalCrossSection) return NULL;
760
761 // Bomb out if the two collision partners are the same particle
762// assert(p1->getID() != p2->getID());
763
764 // Return a new avatar, then!
765 return new G4INCL::BinaryCollisionAvatar(t, totalCrossSection, theNucleus, p1, p2);
766 }
767
769 Intersection theIntersection(
771 aParticle->getPosition(),
772 aParticle->getPropagationVelocity(),
773 theNucleus->getSurfaceRadius(aParticle)));
774 G4double time;
775 if(theIntersection.exists) {
776 time = currentTime + theIntersection.time;
777 } else {
778 INCL_ERROR("Imaginary reflection time for particle: " << '\n'
779 << aParticle->print());
780 time = 10000.0;
781 }
782 return time;
783 }
784
786 G4INCL::Particle const * const particleB, G4double *minDistOfApproach) const
787 {
788 G4double time;
789
790 // When annihilation is forced for antinucleons below the threshold energy, set the time step at 0.001 (when to have the smallest avatar time)
791 Config const *theConfig=theNucleus->getStore()->getConfig();
792 if (((particleA->getType()==antiProton) && (particleA->getKineticEnergy() <= theConfig->getAtrestThreshold())) ||
793 ((particleB->getType()==antiProton) && (particleB->getKineticEnergy() <= theConfig->getAtrestThreshold())) ||
794 ((particleA->getType()==antiNeutron) && (particleA->getKineticEnergy() <= particleA->getPotentialEnergy())) ||
795 ((particleB->getType()==antiNeutron) && (particleB->getKineticEnergy() <= particleB->getPotentialEnergy())) ||
796 ((particleA->getType()==antiProton && particleA->getEnergy() <= particleA->getINCLMass())) ||
797 ((particleB->getType()==antiProton && particleB->getEnergy() <= particleB->getINCLMass())) ||
798 ((particleA->getType()==antiNeutron && particleA->getEnergy() <= particleA->getINCLMass())) ||
799 ((particleB->getType()==antiNeutron && particleB->getEnergy() <= particleB->getINCLMass())))
800 {
801 return currentTime + 0.001;
802 }
803 G4INCL::ThreeVector t13 = particleA->getPropagationVelocity();
804 t13 -= particleB->getPropagationVelocity();
805 G4INCL::ThreeVector distance = particleA->getPosition();
806 distance -= particleB->getPosition();
807 const G4double t7 = t13.dot(distance);
808 const G4double dt = t13.mag2();
809 if(dt <= 1.0e-10) {
810 (*minDistOfApproach) = 100000.0;
811 return currentTime + 100000.0;
812 } else {
813 time = -t7/dt;
814 }
815 (*minDistOfApproach) = distance.mag2() + time * t7;
816 return currentTime + time;
817 }
818
819 void StandardPropagationModel::generateUpdatedCollisions(const ParticleList &updatedParticles, const ParticleList &particles) {
820
821 // Loop over all the updated particles
822 for(ParticleIter updated=updatedParticles.begin(), e=updatedParticles.end(); updated!=e; ++updated)
823 {
824 // Loop over all the particles
825 for(ParticleIter particle=particles.begin(), end=particles.end(); particle!=end; ++particle)
826 {
827 /* Consider the generation of a collision avatar only if (*particle)
828 * is not one of the updated particles.
829 * The criterion makes sure that you don't generate avatars between
830 * updated particles. */
831 if(updatedParticles.contains(*particle)) continue;
832
834 }
835 }
836 }
837
839 // Loop over all the particles
840 for(ParticleIter p1=particles.begin(), e=particles.end(); p1!=e; ++p1) {
841 // Loop over the rest of the particles
842 for(ParticleIter p2 = p1 + 1; p2 != particles.end(); ++p2) {
844 }
845 }
846 }
847
849
850 const G4bool haveExcept = !except.empty();
851
852 // Loop over all the particles
853 for(ParticleIter p1=particles.begin(), e=particles.end(); p1!=e; ++p1)
854 {
855 // Loop over the rest of the particles
856 ParticleIter p2 = p1;
857 for(++p2; p2 != particles.end(); ++p2)
858 {
859 // Skip the collision if both particles must be excluded
860 if(haveExcept && except.contains(*p1) && except.contains(*p2)) continue;
861
863 }
864 }
865
866 }
867
869
870 for(ParticleIter iter=particles.begin(), e=particles.end(); iter!=e; ++iter) {
871 G4double time = this->getReflectionTime(*iter);
872 if(time <= maximumTime) registerAvatar(new SurfaceAvatar(*iter, time, theNucleus));
873 }
874 ParticleList const &p = theNucleus->getStore()->getParticles();
875 generateUpdatedCollisions(particles, p); // Predict collisions with spectators and participants
876 }
877
879 ParticleList const &particles = theNucleus->getStore()->getParticles();
880// assert(!particles.empty());
881 G4double time;
882 for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i) {
883 time = this->getReflectionTime(*i);
884 if(time <= maximumTime) registerAvatar(new SurfaceAvatar(*i, time, theNucleus));
885 }
886 generateCollisions(particles);
887 generateDecays(particles);
888 }
889
890#ifdef INCL_REGENERATE_AVATARS
891 void StandardPropagationModel::generateAllAvatarsExceptUpdated(FinalState const * const fs) {
892 ParticleList const &particles = theNucleus->getStore()->getParticles();
893// assert(!particles.empty());
894 for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i) {
895 G4double time = this->getReflectionTime(*i);
896 if(time <= maximumTime) registerAvatar(new SurfaceAvatar(*i, time, theNucleus));
897 }
898 ParticleList except = fs->getModifiedParticles();
899 ParticleList const &entering = fs->getEnteringParticles();
900 except.insert(except.end(), entering.begin(), entering.end());
901 generateCollisions(particles,except);
902 generateDecays(particles);
903 }
904#endif
905
907 for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i) {
908 if((*i)->isDelta()) {
909 G4double decayTime = DeltaDecayChannel::computeDecayTime((*i)); // time in fm/c
910 G4double time = currentTime + decayTime;
911 if(time <= maximumTime) {
912 registerAvatar(new DecayAvatar((*i), time, theNucleus));
913 }
914 }
915 else if((*i)->getType() == SigmaZero) {
916 G4double decayTime = SigmaZeroDecayChannel::computeDecayTime((*i)); // time in fm/c
917 G4double time = currentTime + decayTime;
918 if(time <= maximumTime) {
919 registerAvatar(new DecayAvatar((*i), time, theNucleus));
920 }
921 }
922 if((*i)->isOmega()) {
924 G4double timeOmega = currentTime + decayTimeOmega;
925 if(timeOmega <= maximumTime) {
926 registerAvatar(new DecayAvatar((*i), timeOmega, theNucleus));
927 }
928 }
929 }
930 }
931
933 {
934 if(fs) {
935 // We update only the information related to particles that were updated
936 // by the previous avatar.
937#ifdef INCL_REGENERATE_AVATARS
938#warning "The INCL_REGENERATE_AVATARS code has not been tested in a while. Use it at your peril."
939 if(!fs->getModifiedParticles().empty() || !fs->getEnteringParticles().empty() || !fs->getCreatedParticles().empty()) {
940 // Regenerates the entire avatar list, skipping collisions between
941 // updated particles
942 theNucleus->getStore()->clearAvatars();
943 theNucleus->getStore()->initialiseParticleAvatarConnections();
944 generateAllAvatarsExceptUpdated(fs);
945 }
946#else
947 ParticleList const &updatedParticles = fs->getModifiedParticles();
948 if(fs->getValidity()==PauliBlockedFS) {
949 // This final state might represents the outcome of a Pauli-blocked delta
950 // decay
951// assert(updatedParticles.empty() || (updatedParticles.size()==1 && updatedParticles.front()->isResonance()));
952// assert(fs->getEnteringParticles().empty() && fs->getCreatedParticles().empty() && fs->getOutgoingParticles().empty() && fs->getDestroyedParticles().empty());
953 generateDecays(updatedParticles);
954 } else {
955 ParticleList const &entering = fs->getEnteringParticles();
956 generateDecays(updatedParticles);
957 generateDecays(entering);
958
959 ParticleList const &created = fs->getCreatedParticles();
960 if(created.empty() && entering.empty())
961 updateAvatars(updatedParticles);
962 else {
963 ParticleList updatedParticlesCopy = updatedParticles;
964 updatedParticlesCopy.insert(updatedParticlesCopy.end(), entering.begin(), entering.end());
965 updatedParticlesCopy.insert(updatedParticlesCopy.end(), created.begin(), created.end());
966 updateAvatars(updatedParticlesCopy);
967 }
968 }
969#endif
970 }
971
972 G4INCL::IAvatar *theAvatar = theNucleus->getStore()->findSmallestTime();
973 if(theAvatar == 0) return 0; // Avatar list is empty
974 // theAvatar->dispose();
975
976 if(theAvatar->getTime() < currentTime) {
977 INCL_ERROR("Avatar time = " << theAvatar->getTime() << ", currentTime = " << currentTime << '\n');
978 return 0;
979 } else if(theAvatar->getTime() > currentTime) {
980 theNucleus->getStore()->timeStep(theAvatar->getTime() - currentTime);
981
982 currentTime = theAvatar->getTime();
983 theNucleus->getStore()->getBook().setCurrentTime(currentTime);
984 }
985
986 return theAvatar;
987 }
988}
Static class for selecting Coulomb distortion.
Simple class for computing intersections between a straight line and a sphere.
#define INCL_ERROR(x)
#define INCL_DEBUG(x)
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
IAvatarList bringMesonStar(ParticleList const &pL, Nucleus *const n)
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.
ParticleList const & getParticles() const
virtual void makeProjectileSpectator()
Make all the components projectile spectators, too.
virtual void initializeParticles()
Initialise the NuclearDensity pointer and sample the particles.
G4INCL::ThreeVector getAngularMomentum() const
Get the total angular momentum (orbital + spin).
void setPosition(const ThreeVector &position)
Set the position of the cluster.
G4double getAtrestThreshold() const
Get the pbar at rest annihilation threshold.
G4double getnbAtrestThreshold() const
Get the nbar at rest annihilation threshold.
static G4double computeDecayTime(Particle *p)
ParticleList const & getEnteringParticles() const
ParticleList const & getModifiedParticles() const
FinalStateValidity getValidity() const
ParticleList const & getCreatedParticles() const
G4double getTime() const
IAvatarList bringMesonStar(ParticleList const &pL, Nucleus *const n)
Store * getStore() const
ThreeVector boostVector() const
G4double getINCLMass() const
Get the INCL particle mass.
virtual G4INCL::ParticleSpecies getSpecies() const
Get the particle species.
G4bool isPhoton() const
Is this a photon?
G4bool isMeson() const
Is this a Meson?
virtual G4INCL::ThreeVector getAngularMomentum() const
G4double getEnergy() const
G4double getPotentialEnergy() const
Get the particle potential energy.
ParticipantType getParticipantType() const
ThreeVector getPropagationVelocity() const
Get the propagation velocity of the particle.
void propagate(G4double step)
G4int getZ() const
Returns the charge number.
const G4INCL::ThreeVector & getPosition() const
G4bool isParticipant() const
G4double getKineticEnergy() const
Get the particle kinetic energy.
G4bool isAntiNucleon() const
Is this an antinucleon?
virtual void makeProjectileSpectator()
const ThreeVector & adjustMomentumFromEnergy()
Rescale the momentum to match the total energy.
G4bool isPion() const
Is this a pion?
void setINCLMass()
Set the mass of the Particle to its table mass.
const G4INCL::ThreeVector & getMomentum() const
G4INCL::ParticleType getType() const
G4bool isResonance() const
Is it a resonance?
void setEnergy(G4double energy)
std::string print() const
ThreeVector getTransversePosition() const
Transverse component of the position w.r.t. the momentum.
G4double getMass() const
Get the cached particle mass.
virtual void setPosition(const G4INCL::ThreeVector &position)
void setTableMass()
Set the mass of the Particle to its table mass.
G4int getA() const
Returns the baryon number.
G4bool isNucleon() const
IAvatarList bringMesonStar(ParticleList const &pL, Nucleus *const n)
void storeComponents()
Store the projectile components.
static G4double computeDecayTime(Particle *p)
G4double getReflectionTime(G4INCL::Particle const *const aParticle)
Get the reflection time.
G4INCL::IAvatar * propagate(FinalState const *const fs)
G4double getTime(G4INCL::Particle const *const particleA, G4INCL::Particle const *const particleB, G4double *minDistOfApproach) const
void generateCollisions(const ParticleList &particles)
Generate and register collisions among particles in a list, except between those in another list.
G4double shootAtrest(ParticleType const t, const G4double kineticEnergy)
StandardPropagationModel(LocalEnergyType localEnergyType, LocalEnergyType localEnergyDeltaType, const G4double hTime=0.0)
void registerAvatar(G4INCL::IAvatar *anAvatar)
void updateAvatars(const ParticleList &particles)
void generateAllAvatars()
(Re)Generate all possible avatars.
G4double shoot(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy, const G4double impactParameter, const G4double phi)
IAvatar * generateBinaryCollisionAvatar(Particle *const p1, Particle *const p2)
Generate a two-particle avatar.
G4double shootCompositeAtrest(ParticleSpecies const &s, const G4double kineticEnergy)
void generateUpdatedCollisions(const ParticleList &updatedParticles, const ParticleList &particles)
Generate and register collisions between a list of updated particles and all the other particles.
G4double shootComposite(ParticleSpecies const &s, const G4double kineticEnergy, const G4double impactParameter, const G4double phi)
void generateDecays(const ParticleList &particles)
Generate decays for particles that can decay.
G4double shootParticle(ParticleType const t, const G4double kineticEnergy, const G4double impactParameter, const G4double phi)
ParticleList const & getParticles() const
G4double dot(const ThreeVector &v) const
G4double mag2() const
G4bool contains(const T &t) const
ParticleEntryAvatar * bringToSurfaceAbar(Particle *p, Nucleus *const n)
ParticleEntryAvatar * bringToSurface(Particle *p, Nucleus *const n)
Modify the momentum of an incoming particle and position it on the surface of the nucleus.
G4double maxImpactParameter(ParticleSpecies const &p, const G4double kinE, Nucleus const *const n)
Return the maximum impact parameter for Coulomb-distorted trajectories.
G4double total(Particle const *const p1, Particle const *const p2)
Intersection getLaterTrajectoryIntersection(const ThreeVector &x0, const ThreeVector &p, const G4double r)
Compute the second intersection of a straight particle trajectory with a sphere.
G4double squareTotalEnergyInCM(Particle const *const p1, Particle const *const p2)
void transformToLocalEnergyFrame(Nucleus const *const n, Particle *const p)
const G4double tenPi
G4ThreadLocal NuclearMassFn getTableMass
Static pointer to the mass function for nuclei.
G4ThreadLocal ParticleMassFn getTableParticleMass
Static pointer to the mass function for particles.
G4double getLargestNuclearRadius(const G4int A, const G4int Z)
ParticleList::const_iterator ParticleIter
@ FirstCollisionLocalEnergy
UnorderedVector< IAvatar * > IAvatarList
@ DNbarNPbarNType
@ DNbarNPbarPType
@ DNbarPPbarPType
@ DNbarPPbarNType
Intersection-point structure.