Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4INCLCascade.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/** \file G4INCLCascade.cc
39 *
40 * INCL Cascade
41 */
42#include "G4INCLCascade.hh"
43#include "G4INCLRandom.hh"
46#include "G4INCLParticle.hh"
48#include "G4INCLGlobalInfo.hh"
49#include "G4INCLNucleus.hh"
50#include "G4INCLDecayAvatar.hh"
51#include "G4INCLStore.hh"
52
54
56
58
59#include "G4INCLLogger.hh"
60#include "G4INCLGlobals.hh"
62
64
66
67#include "G4INCLClustering.hh"
68
69#include "G4INCLIntersection.hh"
70
72
75
76#include <cstring>
77#include <cstdlib>
78#include <numeric>
79
81
82namespace G4INCL {
83
84 INCL::INCL(Config const * const config)
85 :propagationModel(0), theA(208), theZ(82), theS(0),
86 targetInitSuccess(false),
87 maxImpactParameter(0.),
88 maxUniverseRadius(0.),
89 maxInteractionDistance(0.),
90 fixedImpactParameter(0.),
91 theConfig(config),
92 nucleus(NULL),
93 forceTransparent(false),
94 minRemnantSize(4)
95 {
96 // Set the logger object.
97#ifdef INCLXX_IN_GEANT4_MODE
99#else // INCLXX_IN_GEANT4_MODE
100 Logger::initialize(theConfig);
101#endif // INCLXX_IN_GEANT4_MODE
102
103 // Set the random number generator algorithm. The system can support
104 // multiple different generator algorithms in a completely
105 // transparent way.
106 Random::initialize(theConfig);
107
108 // Select the Pauli and CDPP blocking algorithms
109 Pauli::initialize(theConfig);
110
111 // Set the cross-section set
112 CrossSections::initialize(theConfig);
113
114 // Set the phase-space generator
116
117 // Select the Coulomb-distortion algorithm:
119
120 // Select the clustering algorithm:
121 Clustering::initialize(theConfig);
122
123 // Initialize the INCL particle table:
124 ParticleTable::initialize(theConfig);
125
126 // Initialize the value of cutNN in BinaryCollisionAvatar
127 BinaryCollisionAvatar::setCutNN(theConfig->getCutNN());
128
129 // Initialize the value of strange cross section bias
130 BinaryCollisionAvatar::setBias(theConfig->getBias());
131
132 // Propagation model is responsible for finding avatars and
133 // transporting the particles. In principle this step is "hidden"
134 // behind an abstract interface and the rest of the system does not
135 // care how the transportation and avatar finding is done. This
136 // should allow us to "easily" experiment with different avatar
137 // finding schemes and even to support things like curved
138 // trajectories in the future.
139 propagationModel = new StandardPropagationModel(theConfig->getLocalEnergyBBType(),theConfig->getLocalEnergyPiType(),theConfig->getHadronizationTime());
140 if(theConfig->getCascadeActionType() == AvatarDumpActionType)
141 cascadeAction = new AvatarDumpAction();
142 else
143 cascadeAction = new CascadeAction();
144 cascadeAction->beforeRunAction(theConfig);
145
146 theGlobalInfo.cascadeModel = theConfig->getVersionString();
147 theGlobalInfo.deexcitationModel = theConfig->getDeExcitationString();
148#ifdef INCL_ROOT_USE
149 theGlobalInfo.rootSelection = theConfig->getROOTSelectionString();
150#endif
151
152#ifndef INCLXX_IN_GEANT4_MODE
153 // Fill in the global information
154 theGlobalInfo.At = theConfig->getTargetA();
155 theGlobalInfo.Zt = theConfig->getTargetZ();
156 theGlobalInfo.St = theConfig->getTargetS();
157 const ParticleSpecies theSpecies = theConfig->getProjectileSpecies();
158 theGlobalInfo.Ap = theSpecies.theA;
159 theGlobalInfo.Zp = theSpecies.theZ;
160 theGlobalInfo.Sp = theSpecies.theS;
161 theGlobalInfo.Ep = theConfig->getProjectileKineticEnergy();
162 theGlobalInfo.biasFactor = theConfig->getBias();
163#endif
164
165 fixedImpactParameter = theConfig->getImpactParameter();
166 }
167
170#ifndef INCLXX_IN_GEANT4_MODE
171 NuclearMassTable::deleteTable();
172#endif
179#ifndef INCLXX_IN_GEANT4_MODE
180 Logger::deleteLoggerSlave();
181#endif
184 cascadeAction->afterRunAction();
185 delete cascadeAction;
186 delete propagationModel;
187 delete theConfig;
188 }
189
190 G4bool INCL::prepareReaction(const ParticleSpecies &projectileSpecies, const G4double kineticEnergy, const G4int A, const G4int Z, const G4int S) {
191 if(A < 0 || A > 300 || Z < 1 || Z > 200) {
192 INCL_ERROR("Unsupported target: A = " << A << " Z = " << Z << " S = " << S << '\n'
193 << "Target configuration rejected." << '\n');
194 return false;
195 }
196 if((projectileSpecies.theType==Composite || projectileSpecies.theType == antiComposite)&&
197 (projectileSpecies.theZ==projectileSpecies.theA || projectileSpecies.theZ==0)) {
198 INCL_ERROR("Unsupported projectile: A = " << projectileSpecies.theA << " Z = " << projectileSpecies.theZ << " S = " << projectileSpecies.theS << '\n'
199 << "Projectile configuration rejected." << '\n');
200 return false;
201 }
202
203 // Reset the forced-transparent flag
204 forceTransparent = false;
205
206 // Initialise the maximum universe radius
207 initUniverseRadius(projectileSpecies, kineticEnergy, A, Z);
208 // Initialise the nucleus
209
210//D
211 //reset
212 G4bool ProtonIsTheVictim = false;
213 G4bool NeutronIsTheVictim = false;
214 G4bool DNbProtonIsTheVictim = false;
215 G4bool DPbProtonIsTheVictim = false;
216 theEventInfo.annihilationP = false;
217 theEventInfo.annihilationN = false;
218 G4bool isModelA = true; //Antideuteron
219
220 //G4double AnnihilationBarrier = kineticEnergy;
221 if((projectileSpecies.theType == antiProton && kineticEnergy <= theConfig->getAtrestThreshold()) || (projectileSpecies.theType == antiNeutron && kineticEnergy <= theConfig->getnbAtrestThreshold())){
222 double SpOverSn;
223 if(projectileSpecies.theType == antiProton)
224 SpOverSn = 1.331;//from experiments with deuteron (E.Klempt)
225 else if(projectileSpecies.theType == antiNeutron)
226 SpOverSn = 1./1.331; //Opposite for antineutron
227 else{
228 SpOverSn = 1;
229 INCL_ERROR("Neither antiProton nor antiNeutron annihilated");
230 }
231 //INCL_WARN("theA number set to A-1 from " << A <<'\n');
232
233 G4double neutronprob;
234 if(theConfig->isNaturalTarget()){ // A = 0 in this case
235 theA = ParticleTable::drawRandomNaturalIsotope(Z) - 1; //43 and 61 are ok (Technetium and Promethium)
236 neutronprob = (theA + 1 - Z)/(theA + 1 - Z + SpOverSn*Z);
237 }
238 else{
239 theA = A - 1;
240 neutronprob = (A - Z)/(A - Z + SpOverSn*Z); //from experiments with deuteron (E.Klempt)
241 }
242
243 theS = S;
244
245 G4double rndm = Random::shoot();
246 if(rndm >= neutronprob){ //proton is annihilated
247 theEventInfo.annihilationP = true;
248 theZ = Z - 1;
249 ProtonIsTheVictim = true;
250 //INCL_WARN("theZ number set to Z-1 from " << Z << '\n');
251 }
252 else{ //neutron is annihilated
253 theEventInfo.annihilationN = true;
254 theZ = Z;
255 NeutronIsTheVictim = true;
256 }
257 } else if(projectileSpecies.theType == antiComposite && kineticEnergy <= theConfig->getdbAtrestThreshold()){
258 if(Z > 30)
259 isModelA=false;
260 else if(Z > 9 && Z <=30){ //Maybe change and add another dependance than Z
261 double rndmA = Random::shoot();
262 if(rndmA > 0.5)//Random threshold : should be improved to take into account the orbit in which the separation takes place.
263 isModelA=false;
264 }
265 if(isModelA){
266 //Antideuteron Model A case : 2 annihilation at the same time
267 double pbarSpOverSn = 1.331;
268 double nbarSpOverSn = 1./1.331;
269 double pbarneutronprob;
270 double nbarneutronprob;
271 if(theConfig->isNaturalTarget()){
273 nbarneutronprob = (theA + 2 - Z)/(theA + 2 - Z + nbarSpOverSn*Z);
274 pbarneutronprob = (theA + 2 - Z)/(theA + 2 - Z + pbarSpOverSn*Z);
275 }
276 else{
277 theA = A - 2;
278 nbarneutronprob = (A - Z)/(A - Z + nbarSpOverSn*Z);
279 pbarneutronprob = (A - Z)/(A - Z + pbarSpOverSn*Z);
280 }
281 theS = S;
282 G4double rndm = Random::shoot(); //for nbar
283 G4double rndm2 = Random::shoot(); //for pbar
284
285 if (rndm >= nbarneutronprob){ // nbarp
286 DNbProtonIsTheVictim = true;
287 if(rndm2 >= pbarneutronprob){ // pbarp
288 theZ = Z - 2;
289 DPbProtonIsTheVictim = true;
290 } else if(rndm2 < pbarneutronprob){ //pbarn
291 theZ = Z - 1;
292 }
293 } else if(rndm < nbarneutronprob){//nbarn
294 if(rndm2 >= pbarneutronprob){ // pbarp
295 theZ = Z - 1;
296 DPbProtonIsTheVictim = true;
297 } else if(rndm2 < pbarneutronprob){ //pbarn
298 theZ = Z;
299 }
300 }
301 } else if (!isModelA){//Model B : Antiproton is detached from antideuteron
302 double SpOverSn = 1.331;
303 double neutronprob;
304 if(theConfig->isNaturalTarget()){
306 neutronprob = (theA + 1 - Z)/(theA + 1 - Z + SpOverSn*Z);
307 }
308 else{
309 theA = A - 1;
310 neutronprob = (A - Z)/(A - Z + SpOverSn*Z);
311 }
312
313 theS = S;
314
315 double rndm = Random::shoot();
316 if(rndm >= neutronprob){ //proton is annihilated
317 theEventInfo.annihilationP = true;
318 theZ = Z - 1;
319 ProtonIsTheVictim = true;
320 }
321 else{ //neutron is annihilated
322 theEventInfo.annihilationN = true;
323 theZ = Z;
324 NeutronIsTheVictim = true;
325 }
326 }
327 }
328 else{ // not annihilation of pbar, nbar, dbar
329 theZ = Z;
330 theS = S;
331 if(theConfig->isNaturalTarget())
332 theA = ParticleTable::drawRandomNaturalIsotope(Z); //change order
333 else
334 theA = A;
335 }
336
337 AnnihilationType theAType = Def;
338 if(ProtonIsTheVictim == true && NeutronIsTheVictim == false)
339 theAType = PType;
340 if(NeutronIsTheVictim == true && ProtonIsTheVictim == false)
341 theAType = NType;
342 if(projectileSpecies.theType == antiComposite && kineticEnergy <= theConfig->getdbAtrestThreshold() && isModelA){
343 if(DNbProtonIsTheVictim == true && DPbProtonIsTheVictim ==true)
344 theAType = DNbarPPbarPType;
345 else if(DNbProtonIsTheVictim == false && DPbProtonIsTheVictim ==true)
346 theAType = DNbarNPbarPType;
347 else if(DNbProtonIsTheVictim == false && DPbProtonIsTheVictim == false)
348 theAType = DNbarNPbarNType;
349 else if(DNbProtonIsTheVictim == true && DPbProtonIsTheVictim ==false)
350 theAType = DNbarPPbarNType;
351 } else if (projectileSpecies.theType == antiComposite && kineticEnergy <= theConfig->getdbAtrestThreshold() && !isModelA){
352 if(ProtonIsTheVictim == true && NeutronIsTheVictim == false)
353 theAType = PType;
354 if(NeutronIsTheVictim == true && ProtonIsTheVictim == false)
355 theAType = NType;
356 }
357
358//D
359
360 initializeTarget(theA, theZ, theS, theAType);
361
362 // Set the maximum impact parameter
363 maxImpactParameter = CoulombDistortion::maxImpactParameter(projectileSpecies, kineticEnergy, nucleus);
364 INCL_DEBUG("Maximum impact parameter initialised: " << maxImpactParameter << '\n');
365
366 // For forced CN events
367 initMaxInteractionDistance(projectileSpecies, kineticEnergy);
368// Set the geometric cross sectiony section
369 if((projectileSpecies.theType == antiProton && kineticEnergy <= theConfig->getAtrestThreshold()) || (projectileSpecies.theType == antiNeutron && kineticEnergy <= theConfig->getnbAtrestThreshold())
370 || (projectileSpecies.theType == antiComposite && kineticEnergy <= theConfig->getdbAtrestThreshold()) ){
371 G4int currentA = A;
372 if(theConfig->isNaturalTarget()){
374 }
375 G4double kineticEnergy2=kineticEnergy;
376 if (kineticEnergy2 <= 0.) kineticEnergy2=0.001;
377 theGlobalInfo.geometricCrossSection = 9.7* //normalization factor from Corradini
378 Math::pi*std::pow((1.840 + 1.120*std::pow(currentA,(1./3.))),2)*
379 (1. + (Z*G4INCL::PhysicalConstants::eSquared*(currentA+1))/(currentA*kineticEnergy2*(1.840 + 1.120*std::pow(currentA,(1./3.)))));
380 //xsection formula was borrowed from Corradini et al. https://doi.org/10.1016/j.physletb.2011.09.069
381 }
382 else{
383 theGlobalInfo.geometricCrossSection =
384 Math::tenPi*std::pow(maxImpactParameter,2);
385 }
386
387 // Set the minimum remnant size
388 if(projectileSpecies.theA > 0)
389 minRemnantSize = std::min(theA, 4);
390 else
391 minRemnantSize = std::min(theA-1, 4);
392 return true;
393 }
394
395 G4bool INCL::initializeTarget(const G4int A, const G4int Z, const G4int S, AnnihilationType theAType) {
396 delete nucleus;
397
398 if (theAType==PType || theAType==NType || theAType==DNbarNPbarPType || theAType==DNbarNPbarNType ||theAType==DNbarPPbarPType || theAType==DNbarPPbarNType) {
399 G4double newmaxUniverseRadius=0.;
400 if (theAType==PType) newmaxUniverseRadius=initUniverseRadiusForAntiprotonAtRest(A+1, Z+1);
401 else if (theAType==NType) newmaxUniverseRadius=initUniverseRadiusForAntiprotonAtRest(A+1, Z);
402 else if (theAType==DNbarPPbarPType) newmaxUniverseRadius=initUniverseRadiusForAntiprotonAtRest(A+2, Z+2);
403 else if (theAType==DNbarNPbarNType) newmaxUniverseRadius=initUniverseRadiusForAntiprotonAtRest(A+2, Z);
404 else if (theAType==DNbarNPbarPType || theAType==DNbarPPbarNType) newmaxUniverseRadius=initUniverseRadiusForAntiprotonAtRest(A+2, Z+1);
405 nucleus = new Nucleus(A, Z, S, theConfig, newmaxUniverseRadius, theAType);
406 }
407 else{
408 nucleus = new Nucleus(A, Z, S, theConfig, maxUniverseRadius, theAType);
409 }
410 nucleus->getStore()->getBook().reset();
411 nucleus->initializeParticles();
412 propagationModel->setNucleus(nucleus);
413 return true;
414 }
415
417 ParticleSpecies const &projectileSpecies,
418 const G4double kineticEnergy,
419 const G4int targetA,
420 const G4int targetZ,
421 const G4int targetS
422 ) {
423
424 ParticleList starlistH2;
425
426 if (projectileSpecies.theType==antiProton && (targetA==1 || targetA==2) && targetZ==1 && targetS==0) {
427
428 if (targetA==1) {
429 preCascade_pbarH1(projectileSpecies, kineticEnergy);
430 } else {
431 preCascade_pbarH2(projectileSpecies, kineticEnergy);
432 theEventInfo.annihilationP = false;
433 theEventInfo.annihilationN = false;
434
435 G4double SpOverSn = 1.331; //from experiments with deuteron (E.Klempt)
436
437 ThreeVector dummy(0.,0.,0.);
438 G4double rndm = Random::shoot()*(SpOverSn+1);
439 if (rndm <= SpOverSn) { //proton is annihilated
440 theEventInfo.annihilationP = true;
441 Particle *p2 = new Particle(Neutron, dummy, dummy);
442 starlistH2.push_back(p2);
443 //delete p2;
444 } else { //neutron is annihilated
445 theEventInfo.annihilationN = true;
446 Particle *p2 = new Particle(Proton, dummy, dummy);
447 starlistH2.push_back(p2);
448 //delete p2;
449 }
450 }
451
452 // File names
453#ifdef INCLXX_IN_GEANT4_MODE
454 if (!G4FindDataDir("G4INCLDATA") ) {
456 ed << " Data missing: set environment variable G4INCLDATA\n"
457 << " to point to the directory containing data files needed\n"
458 << " by the INCL++ model" << G4endl;
459 G4Exception("G4INCLDataFile::readData()","rawppbarFS.dat, ...", FatalException, ed);
460 }
461 const G4String& dataPath0(G4FindDataDir("G4INCLDATA"));
462 const G4String& dataPathppbar(dataPath0 + "/rawppbarFS.dat");
463 const G4String& dataPathnpbar(dataPath0 + "/rawnpbarFS.dat");
464 const G4String& dataPathppbark(dataPath0 + "/rawppbarFSkaonic.dat");
465 const G4String& dataPathnpbark(dataPath0 + "/rawnpbarFSkaonic.dat");
466
467 const G4String dataPathnbarp(dataPath0 + "/rawnbarpFS.dat");
468 const G4String dataPathnbarn(dataPath0 + "/rawnbarnFS.dat");
469#else
470 std::string path;
471 if (theConfig) path = theConfig->getINCLXXDataFilePath();
472 const std::string& dataPathppbar(path + "/rawppbarFS.dat");
473 INCL_DEBUG("Reading https://doi.org/10.1016/0375-9474(92)90362-N ppbar final states" << dataPathppbar << '\n');
474 const std::string& dataPathnpbar(path + "/rawnpbarFS.dat");
475 INCL_DEBUG("Reading https://doi.org/10.1016/0375-9474(92)90362-N npbar final states" << dataPathnpbar << '\n');
476 const std::string& dataPathppbark(path + "/rawppbarFSkaonic.dat");
477 INCL_DEBUG("Reading https://doi.org/10.1016/j.physrep.2005.03.002 ppbar kaonic final states" << dataPathppbark << '\n');
478 const std::string& dataPathnpbark(path + "/rawnpbarFSkaonic.dat");
479 INCL_DEBUG("Reading https://doi.org/10.1007/BF02818764 and https://link.springer.com/article/10.1007/BF02754930 npbar kaonic final states" << dataPathnpbark << '\n');
480
481 const std::string& dataPathnbarp(path + "/rawnnbarpFS.dat ");
482 INCL_DEBUG("Reading nbarp final states" << dataPathnbarp << '\n');
483 const std::string& dataPathnbarpk(path + "/rawnbarpFSkaonic.dat");
484 INCL_DEBUG("Reading nbarp kaonic final states");
485 const std::string& dataPathnbarn(path + "/rawnbarnFS.dat");
486 INCL_DEBUG("Reading nbarn final states" << dataPathnbarn << '\n');
487#endif
488
489 //read probabilities and particle types from file
490 std::vector<G4double> probabilities; //will store each FS yield
491 std::vector<std::vector<G4String>> particle_types; //will store particle names
492 G4double sum = 0.0; //will contain a sum of probabilities of all FS in the file
493 G4double kaonicFSprob=0.05; //probability to kave kaonic FS
494
495 ParticleList starlist;
496 ThreeVector mommy; //momentum to be assigned later
497
498 G4double rdm = Random::shoot();
499 ThreeVector annihilationPosition(0.,0.,0.);
500 if (rdm < (1.-kaonicFSprob)) { // pionic FS was chosen
501 INCL_DEBUG("pionic pp final state chosen" << '\n');
502 if (targetA==1 || (targetA==2 && theEventInfo.annihilationP))
503 {sum = read_file(dataPathppbar, probabilities, particle_types);}
504 else
505 {sum = read_file(dataPathnpbar, probabilities, particle_types);}
506 rdm = (rdm/(1.-kaonicFSprob))*sum; //99.88 normalize by the sum of probabilities in the file
507 //now get the line number in the file where the FS particles are stored:
508 G4int n = findStringNumber(rdm, std::move(probabilities))-1;
509 if ( n < 0 ) return theEventInfo;
510 for (G4int j = 0; j < static_cast<G4int>(particle_types[n].size()); j++) {
511 if (particle_types[n][j] == "pi0") {
512 Particle *p = new Particle(PiZero, mommy, annihilationPosition);
513 starlist.push_back(p);
514 } else if (particle_types[n][j] == "pi-") {
515 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
516 starlist.push_back(p);
517 } else if (particle_types[n][j] == "pi+") {
518 Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
519 starlist.push_back(p);
520 } else if (particle_types[n][j] == "omega") {
521 Particle *p = new Particle(Omega, mommy, annihilationPosition);
522 starlist.push_back(p);
523 } else if (particle_types[n][j] == "eta") {
524 Particle *p = new Particle(Eta, mommy, annihilationPosition);
525 starlist.push_back(p);
526 } else if (particle_types[n][j] == "rho-") {
527 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
528 starlist.push_back(p);
529 Particle *pp = new Particle(PiZero, mommy, annihilationPosition);
530 starlist.push_back(pp);
531 } else if (particle_types[n][j] == "rho+") {
532 Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
533 starlist.push_back(p);
534 Particle *pp = new Particle(PiZero, mommy, annihilationPosition);
535 starlist.push_back(pp);
536 } else if (particle_types[n][j] == "rho0") {
537 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
538 starlist.push_back(p);
539 Particle *pp = new Particle(PiPlus, mommy, annihilationPosition);
540 starlist.push_back(pp);
541 } else {
542 INCL_ERROR("Some non-existing FS particle detected when reading pbar FS files");
543 for (G4int jj = 0; jj < static_cast<G4int>(particle_types[n].size()); jj++) {
544#ifdef INCLXX_IN_GEANT4_MODE
545 G4cout << "gotcha! " << particle_types[n][jj] << G4endl;
546#else
547 std::cout << "gotcha! " << particle_types[n][jj] << std::endl;
548#endif
549 }
550#ifdef INCLXX_IN_GEANT4_MODE
551 G4cout << "Some non-existing FS particle detected when reading pbar FS files" << G4endl;
552#else
553 std::cout << "Some non-existing FS particle detected when reading pbar FS files" << std::endl;
554#endif
555 }
556 }
557 } else {
558 INCL_DEBUG("kaonic pp final state chosen" << '\n');
559 if (targetA==1 || (targetA==2 && theEventInfo.annihilationP))
560 {sum = read_file(dataPathppbark, probabilities, particle_types);}
561 else
562 {sum = read_file(dataPathnpbark, probabilities, particle_types);}
563 rdm = ((1.-rdm)/kaonicFSprob)*sum; //2670 normalize by the sum of probabilities in the file
564 //now get the line number in the file where the FS particles are stored:
565 G4int n = findStringNumber(rdm, std::move(probabilities))-1;
566 if ( n < 0 ) return theEventInfo;
567 for (G4int j = 0; j < static_cast<G4int>(particle_types[n].size()); j++) {
568 if (particle_types[n][j] == "pi0") {
569 Particle *p = new Particle(PiZero, mommy, annihilationPosition);
570 starlist.push_back(p);
571 } else if (particle_types[n][j] == "pi-") {
572 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
573 starlist.push_back(p);
574 } else if (particle_types[n][j] == "pi+") {
575 Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
576 starlist.push_back(p);
577 } else if (particle_types[n][j] == "omega") {
578 Particle *p = new Particle(Omega, mommy, annihilationPosition);
579 starlist.push_back(p);
580 } else if (particle_types[n][j] == "eta") {
581 Particle *p = new Particle(Eta, mommy, annihilationPosition);
582 starlist.push_back(p);
583 } else if (particle_types[n][j] == "K-") {
584 Particle *p = new Particle(KMinus, mommy, annihilationPosition);
585 starlist.push_back(p);
586 } else if (particle_types[n][j] == "K+") {
587 Particle *p = new Particle(KPlus, mommy, annihilationPosition);
588 starlist.push_back(p);
589 } else if (particle_types[n][j] == "K0") {
590 Particle *p = new Particle(KZero, mommy, annihilationPosition);
591 starlist.push_back(p);
592 } else if (particle_types[n][j] == "K0b") {
593 Particle *p = new Particle(KZeroBar, mommy, annihilationPosition);
594 starlist.push_back(p);
595 } else {
596 INCL_ERROR("Some non-existing FS particle detected when reading pbar FS files");
597 for (G4int jj = 0; jj < static_cast<G4int>(particle_types[n].size()); jj++) {
598#ifdef INCLXX_IN_GEANT4_MODE
599 G4cout << "gotcha! " << particle_types[n][jj] << G4endl;
600#else
601 std::cout << "gotcha! " << particle_types[n][jj] << std::endl;
602#endif
603 }
604#ifdef INCLXX_IN_GEANT4_MODE
605 G4cout << "Some non-existing FS particle detected when reading pbar FS files" << G4endl;
606#else
607 std::cout << "Some non-existing FS particle detected when reading pbar FS files" << std::endl;
608#endif
609 }
610 }
611 }
612
613 //compute energies of mesons with a phase-space model
615 if (starlist.size() < 2) {
616 INCL_ERROR("should never happen, at least 2 final state particles!" << '\n');
617 } else if (starlist.size() == 2) {
618 ParticleIter first = starlist.begin();
619 ParticleIter last = std::next(first, 1);
620 G4double m1 = (*first)->getMass();
621 G4double m2 = (*last)->getMass();
622 G4double s = energyOfMesonStar*energyOfMesonStar;
623 G4double mom1 = std::sqrt(s/4. - (std::pow(m1,2) + std::pow(m2,2))/2. - std::pow(m1,2)*std::pow(m2,2)/s + (std::pow(m1,4) + 2.*std::pow(m1*m2,2) + std::pow(m2,4))/(4.*s));
624 ThreeVector momentello = Random::normVector(mom1);
625 (*first)->setMomentum(momentello);
626 (*first)->adjustEnergyFromMomentum();
627 (*last)->setMomentum(-momentello);
628 (*last)->adjustEnergyFromMomentum();
629 } else {
630 PhaseSpaceGenerator::generate(energyOfMesonStar, starlist);
631 }
632
633 if (targetA==1) postCascade_pbarH1(starlist);
634 else postCascade_pbarH2(starlist,starlistH2);
635
636 theGlobalInfo.nShots++;
637 return theEventInfo;
638 } // pbar on H1/H2
639
640 if ((projectileSpecies.theType==antiNeutron)&& (targetA==1 || targetA==2) && targetZ==1 && targetS==0) {
641
642 if (targetA==1) {
643 preCascade_nbarH1(projectileSpecies, kineticEnergy);
644 } else {
645 preCascade_nbarH2(projectileSpecies, kineticEnergy);
646 theEventInfo.annihilationP = false;
647 theEventInfo.annihilationN = false;
648
649 G4double SpOverSn = 1./1.331; //from experiments with deuteron (E.Klempt)
650
651 ThreeVector dummy(0.,0.,0.);
652 double rndm = Random::shoot()*(SpOverSn+1);
653 if (rndm <= SpOverSn) { //proton is annihilated
654 theEventInfo.annihilationP = true;
655 Particle *p2 = new Particle(Neutron, dummy, dummy);
656 starlistH2.push_back(p2);
657 //delete p2;
658 } else { //neutron is annihilated
659 theEventInfo.annihilationN = true;
660 Particle *p2 = new Particle(Proton, dummy, dummy);
661 starlistH2.push_back(p2);
662 //delete p2;
663 }
664 }
665
666 // File names
667#ifdef INCLXX_IN_GEANT4_MODE
668 if (!G4FindDataDir("G4INCLDATA") ) {
670 ed << " Data missing: set environment variable G4INCLDATA\n"
671 << " to point to the directory containing data files needed\n"
672 << " by the INCL++ model" << G4endl;
673 G4Exception("G4INCLDataFile::readData()","rawpnbarFS.dat, ...", FatalException, ed);
674 }
675 G4String dataPath0{G4FindDataDir("G4INCLDATA")};
676 G4String dataPathnbarp(dataPath0 + "/rawnbarpFS.dat");
677 G4String dataPathnbarn(dataPath0 + "/rawnbarnFS.dat");
678 G4String dataPathnbarnk(dataPath0 + "/rawppbarFSkaonic.dat");
679 G4String dataPathnbarpk(dataPath0 + "/rawnbarpFSkaonic.dat");
680#else
681 G4String path;
682 if (theConfig) path = theConfig->getINCLXXDataFilePath();
683 std::string dataPathnbarn(path + "/rawnbarnFS.dat");
684 INCL_DEBUG("Reading nbarn final states" << dataPathnbarn << '\n');
685 std::string dataPathnbarp(path + "/rawnbarpFS.dat");
686 INCL_DEBUG("Reading nbarp final states" << dataPathnbarp << '\n');
687 std::string dataPathnbarnk(path + "/rawppbarFSkaonic.dat");
688 INCL_DEBUG("Reading nbarn kaonic final states" << dataPathnbarnk << '\n');
689 std::string dataPathnbarpk(path + "/rawnbarpFSkaonic.dat");
690 INCL_DEBUG("Reading nbarp kaonic final states" << dataPathnbarpk << '\n');
691#endif
692 //read probabilities and particle types from file
693 std::vector<double> probabilities; //will store each FS yield
694 std::vector<std::vector<G4String>> particle_types; //will store particle names
695 double sum = 0.0; //will contain a sum of probabilities of all FS in the file
696 double kaonicFSprob=0.05; //probability to kave kaonic FS
697
698 ParticleList starlist;
699 ThreeVector mommy; //momentum to be assigned later
700
701 double rdm = Random::shoot();
702 ThreeVector annihilationPosition(0.,0.,0.);
703 if (rdm < (1.-kaonicFSprob)) { // pionic FS was chosen
704 INCL_DEBUG("pionic nn final state chosen" << '\n');
705 if (targetA==1 || (targetA==2 && theEventInfo.annihilationP))
706 {sum = read_file(dataPathnbarp, probabilities, particle_types);}
707 else
708 {sum = read_file(dataPathnbarn, probabilities, particle_types);}
709 rdm = (rdm/(1.-kaonicFSprob))*sum; //99.88 normalize by the sum of probabilities in the file
710 //now get the line number in the file where the FS particles are stored:
711 G4int n = findStringNumber(rdm, probabilities)-1;
712 if ( n < 0 ) return theEventInfo;
713 for (G4int j = 0; j < static_cast<int>(particle_types[n].size()); j++) {
714 if (particle_types[n][j] == "pi0") {
715 Particle *p = new Particle(PiZero, mommy, annihilationPosition);
716 starlist.push_back(p);
717 } else if (particle_types[n][j] == "pi-") {
718 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
719 starlist.push_back(p);
720 } else if (particle_types[n][j] == "pi+") {
721 Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
722 starlist.push_back(p);
723 } else if (particle_types[n][j] == "omega") {
724 Particle *p = new Particle(Omega, mommy, annihilationPosition);
725 starlist.push_back(p);
726 } else if (particle_types[n][j] == "eta") {
727 Particle *p = new Particle(Eta, mommy, annihilationPosition);
728 starlist.push_back(p);
729 } else if (particle_types[n][j] == "rho-") {
730 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
731 starlist.push_back(p);
732 Particle *pp = new Particle(PiZero, mommy, annihilationPosition);
733 starlist.push_back(pp);
734 } else if (particle_types[n][j] == "rho+") {
735 Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
736 starlist.push_back(p);
737 Particle *pp = new Particle(PiZero, mommy, annihilationPosition);
738 starlist.push_back(pp);
739 } else if (particle_types[n][j] == "rho0") {
740 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
741 starlist.push_back(p);
742 Particle *pp = new Particle(PiPlus, mommy, annihilationPosition);
743 starlist.push_back(pp);
744 } else {
745 INCL_ERROR("Some non-existing FS particle detected when reading pbar FS files");
746 for (int jj = 0; jj < static_cast<int>(particle_types[n].size()); jj++) {
747#ifdef INCLXX_IN_GEANT4_MODE
748 G4cout << "gotcha! " << particle_types[n][jj] << G4endl;
749#else
750 std::cout << "gotcha! " << particle_types[n][jj] << std::endl;
751#endif
752 }
753#ifdef INCLXX_IN_GEANT4_MODE
754 G4cout << "Some non-existing FS particle detected when reading pbar FS files" << G4endl;
755#else
756 std::cout << "Some non-existing FS particle detected when reading pbar FS files" << std::endl;
757#endif
758 }
759 }
760 } else {
761 INCL_DEBUG("kaonic pp final state chosen" << '\n');
762 if (targetA==1 || (targetA==2 && theEventInfo.annihilationP))
763 {sum = read_file(dataPathnbarpk, probabilities, particle_types);}
764 else
765 {sum = read_file(dataPathnbarnk, probabilities, particle_types);}
766 rdm = ((1.-rdm)/kaonicFSprob)*sum; //2670 normalize by the sum of probabilities in the file
767 //now get the line number in the file where the FS particles are stored:
768 G4int n = findStringNumber(rdm, probabilities)-1;
769 if ( n < 0 ) return theEventInfo;
770 for (G4int j = 0; j < static_cast<int>(particle_types[n].size()); j++) {
771 if (particle_types[n][j] == "pi0") {
772 Particle *p = new Particle(PiZero, mommy, annihilationPosition);
773 starlist.push_back(p);
774 } else if (particle_types[n][j] == "pi-") {
775 Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
776 starlist.push_back(p);
777 } else if (particle_types[n][j] == "pi+") {
778 Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
779 starlist.push_back(p);
780 } else if (particle_types[n][j] == "omega") {
781 Particle *p = new Particle(Omega, mommy, annihilationPosition);
782 starlist.push_back(p);
783 } else if (particle_types[n][j] == "eta") {
784 Particle *p = new Particle(Eta, mommy, annihilationPosition);
785 starlist.push_back(p);
786 } else if (particle_types[n][j] == "K-") {
787 Particle *p = new Particle(KMinus, mommy, annihilationPosition);
788 starlist.push_back(p);
789 } else if (particle_types[n][j] == "K+") {
790 Particle *p = new Particle(KPlus, mommy, annihilationPosition);
791 starlist.push_back(p);
792 } else if (particle_types[n][j] == "K0") {
793 Particle *p = new Particle(KZero, mommy, annihilationPosition);
794 starlist.push_back(p);
795 } else if (particle_types[n][j] == "K0b") {
796 Particle *p = new Particle(KZeroBar, mommy, annihilationPosition);
797 starlist.push_back(p);
798 } else {
799 INCL_ERROR("Some non-existing FS particle detected when reading pbar FS files");
800 for (int jj = 0; jj < static_cast<int>(particle_types[n].size()); jj++) {
801#ifdef INCLXX_IN_GEANT4_MODE
802 G4cout << "gotcha! " << particle_types[n][jj] << G4endl;
803#else
804 std::cout << "gotcha! " << particle_types[n][jj] << std::endl;
805#endif
806 }
807#ifdef INCLXX_IN_GEANT4_MODE
808 G4cout << "Some non-existing FS particle detected when reading pbar FS files" << G4endl;
809#else
810 std::cout << "Some non-existing FS particle detected when reading pbar FS files" << std::endl;
811#endif
812 }
813 }
814 }
815
816 //compute energies of mesons with a phase-space model
818 if (starlist.size() < 2) {
819 INCL_ERROR("should never happen, at least 2 final state particles!" << '\n');
820 } else if (starlist.size() == 2) {
821 ParticleIter first = starlist.begin();
822 ParticleIter last = std::next(first, 1);
823 G4double m1 = (*first)->getMass();
824 G4double m2 = (*last)->getMass();
825 G4double s = energyOfMesonStar*energyOfMesonStar;
826 G4double mom1 = std::sqrt(s/4. - (std::pow(m1,2) + std::pow(m2,2))/2. - std::pow(m1,2)*std::pow(m2,2)/s + (std::pow(m1,4) + 2.*std::pow(m1*m2,2) + std::pow(m2,4))/(4.*s));
827 ThreeVector momentello = Random::normVector(mom1);
828 (*first)->setMomentum(momentello);
829 (*first)->adjustEnergyFromMomentum();
830 (*last)->setMomentum(-momentello);
831 (*last)->adjustEnergyFromMomentum();
832 } else {
833 PhaseSpaceGenerator::generate(energyOfMesonStar, starlist);
834 }
835
836 if (targetA==1) postCascade_pbarH1(starlist);
837 else postCascade_pbarH2(starlist,starlistH2);
838
839 theGlobalInfo.nShots++;
840 return theEventInfo;
841 } // nbar on H1/H2
842
843 // ReInitialize the bias vector
845 //Particle::INCLBiasVector.Clear();
847
848 // Set the target and the projectile
849 targetInitSuccess = prepareReaction(projectileSpecies, kineticEnergy, targetA, targetZ, targetS);
850
851 if(!targetInitSuccess) {
852 INCL_WARN("Target initialisation failed for A=" << targetA << ", Z=" << targetZ << ", S=" << targetS << '\n');
853 theEventInfo.transparent=true;
854 return theEventInfo;
855 }
856
857 cascadeAction->beforeCascadeAction(propagationModel);
858
859 const G4bool canRunCascade = preCascade(projectileSpecies, kineticEnergy);
860 if(canRunCascade) {
861 cascade();
862 postCascade(projectileSpecies, kineticEnergy);
863 cascadeAction->afterCascadeAction(nucleus);
864 }
865 updateGlobalInfo();
866 return theEventInfo;
867 }
868
869 G4bool INCL::preCascade(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
870 // Reset theEventInfo
871 theEventInfo.reset();
872
874
875 // Fill in the event information
876 theEventInfo.projectileType = projectileSpecies.theType;
877 theEventInfo.Ap = (Short_t)projectileSpecies.theA;
878 theEventInfo.Zp = (Short_t)projectileSpecies.theZ;
879 theEventInfo.Sp = (Short_t)projectileSpecies.theS;
880 theEventInfo.Ep = kineticEnergy;
881 theEventInfo.St = (Short_t)nucleus->getS();
882
883 if(nucleus->getAnnihilationType()==PType){
884 theEventInfo.annihilationP = true;
885 theEventInfo.At = (Short_t)nucleus->getA()+1;
886 theEventInfo.Zt = (Short_t)nucleus->getZ()+1;
887 }
888 else if(nucleus->getAnnihilationType()==NType){
889 theEventInfo.annihilationN = true;
890 theEventInfo.At = (Short_t)nucleus->getA()+1;
891 theEventInfo.Zt = (Short_t)nucleus->getZ();
892 }
893 else if(nucleus->getAnnihilationType()==DNbarNPbarNType ){
894 theEventInfo.annihilationN = true;
895 theEventInfo.At = (Short_t)nucleus->getA()+2;
896 theEventInfo.Zt = (Short_t)nucleus->getZ();
897 }
898 else if(nucleus->getAnnihilationType()==DNbarPPbarPType ){
899 theEventInfo.annihilationP = true;
900 theEventInfo.At = (Short_t)nucleus->getA()+2;
901 theEventInfo.Zt = (Short_t)nucleus->getZ()+2;
902 }
903 else if(nucleus->getAnnihilationType()==DNbarPPbarNType || nucleus->getAnnihilationType()==DNbarNPbarPType ){
904 theEventInfo.annihilationN = true;
905 theEventInfo.annihilationP = true;
906 theEventInfo.At = (Short_t)nucleus->getA()+2;
907 theEventInfo.Zt = (Short_t)nucleus->getZ()+1;
908 }
909 else {
910 theEventInfo.At = (Short_t)nucleus->getA();
911 theEventInfo.Zt = (Short_t)nucleus->getZ();
912 }
913 // Do nothing below the Coulomb barrier
914 if(maxImpactParameter<=0.) {
915 // Fill in the event information
916 //Particle *pbar = new Particle;
917 //PbarAtrestEntryChannel *obj = new PbarAtrestEntryChannel(nucleus, pbar);
918 if((projectileSpecies.theType == antiProton && kineticEnergy <= theConfig->getAtrestThreshold()) || (projectileSpecies.theType==antiNeutron && kineticEnergy <= theConfig->getnbAtrestThreshold())
919 || (projectileSpecies.theType == antiComposite && kineticEnergy <= theConfig->getdbAtrestThreshold())){ //D
920 INCL_DEBUG("at rest annihilation" << '\n');
921 //theEventInfo.transparent = false;
922 } else {
923 theEventInfo.transparent = true;
924 return false;
925 }
926 }
927
928
929 // Randomly draw an impact parameter or use a fixed value, depending on the
930 // Config option
931 G4double impactParameter, phi;
932 if(fixedImpactParameter<0.) {
933 impactParameter = maxImpactParameter * std::sqrt(Random::shoot0());
934 phi = Random::shoot() * Math::twoPi;
935 } else {
936 impactParameter = fixedImpactParameter;
937 phi = 0.;
938 }
939 INCL_DEBUG("Selected impact parameter: " << impactParameter << '\n');
940
941 // Fill in the event information
942 theEventInfo.impactParameter = impactParameter;
943
944 const G4double effectiveImpactParameter = propagationModel->shoot(projectileSpecies, kineticEnergy, impactParameter, phi);
945 if(effectiveImpactParameter < 0.) {
946 // Fill in the event information
947 theEventInfo.transparent = true;
948 return false;
949 }
950
951 // Fill in the event information
952 theEventInfo.transparent = false;
953 theEventInfo.effectiveImpactParameter = effectiveImpactParameter;
954
955 return true;
956 }
957
958 void INCL::cascade() {
959 FinalState *finalState = new FinalState;
960
961 unsigned long loopCounter = 0;
962 const unsigned long maxLoopCounter = 10000000;
963 do {
964 // Run book keeping actions that should take place before propagation:
965 cascadeAction->beforePropagationAction(propagationModel);
966
967 // Get the avatar with the smallest time and propagate particles
968 // to that point in time.
969 IAvatar *avatar = propagationModel->propagate(finalState);
970
971 finalState->reset();
972
973 // Run book keeping actions that should take place after propagation:
974 cascadeAction->afterPropagationAction(propagationModel, avatar);
975
976 if(avatar == 0) break; // No more avatars in the avatar list.
977
978 // Run book keeping actions that should take place before avatar:
979 cascadeAction->beforeAvatarAction(avatar, nucleus);
980
981 // Channel is responsible for calculating the outcome of the
982 // selected avatar. There are different kinds of channels. The
983 // class IChannel is, again, an abstract interface that defines
984 // the externally observable behavior of all interaction
985 // channels.
986 // The handling of the channel is transparent to the API.
987 // Final state tells what changed...
988 avatar->fillFinalState(finalState);
989 // Run book keeping actions that should take place after avatar:
990 cascadeAction->afterAvatarAction(avatar, nucleus, finalState);
991
992 // So now we must give this information to the nucleus
993 nucleus->applyFinalState(finalState);
994 // and now we are ready to process the next avatar!
995
996 delete avatar;
997
998 ++loopCounter;
999 } while(continueCascade() && loopCounter<maxLoopCounter); /* Loop checking, 10.07.2015, D.Mancusi */
1000
1001 delete finalState;
1002 }
1003
1004 void INCL::postCascade(const ParticleSpecies &projectileSpecies, const G4double kineticEnergy) {
1005 // Fill in the event information
1006 theEventInfo.stoppingTime = propagationModel->getCurrentTime();
1007
1008 // The event bias
1009 theEventInfo.eventBias = (Double_t) Particle::getTotalBias();
1010
1011 // Forced CN?
1012 if(!(projectileSpecies.theType==antiProton && kineticEnergy<=theConfig->getAtrestThreshold()) && !(projectileSpecies.theType == antiNeutron && kineticEnergy<=theConfig->getnbAtrestThreshold())
1013 && !(projectileSpecies.theType==antiComposite && kineticEnergy <= theConfig->getdbAtrestThreshold()) ){
1014 if(nucleus->getTryCompoundNucleus()) {
1015 INCL_DEBUG("Trying compound nucleus" << '\n');
1016 makeCompoundNucleus();
1017 theEventInfo.transparent = forceTransparent;
1018 // Global checks of conservation laws
1019#ifndef INCLXX_IN_GEANT4_MODE
1020 if(!theEventInfo.transparent) globalConservationChecks(true);
1021#endif
1022 return;
1023 }
1024 }
1025
1026 if(!(projectileSpecies.theType==antiProton && kineticEnergy<=theConfig->getAtrestThreshold()) && !(projectileSpecies.theType == antiNeutron && kineticEnergy<=theConfig->getnbAtrestThreshold())
1027 && !(projectileSpecies.theType==antiComposite && kineticEnergy <= theConfig->getdbAtrestThreshold())){
1028 theEventInfo.transparent = forceTransparent || nucleus->isEventTransparent();
1029 }
1030
1031 if(theEventInfo.transparent) {
1032 ProjectileRemnant * const projectileRemnant = nucleus->getProjectileRemnant();
1033 if(projectileRemnant) {
1034 // Clear the incoming list (particles will be deleted by the ProjectileRemnant)
1035 nucleus->getStore()->clearIncoming();
1036 } else {
1037 // Delete particles in the incoming list
1038 nucleus->getStore()->deleteIncoming();
1039 }
1040 } else {
1041 //Check if the nucleus contains antinucleons
1042 theEventInfo.antinucleonsInside = nucleus->containsAntinucleon();
1043 //Annihilate antiparticles still inside the nucleus & emit the resulting particles
1044 if(nucleus->containsAntinucleon())
1045 theEventInfo.emitAntinucleon = nucleus->emitInsideAnnihilationProducts();
1046 if(nucleus->containsAntilambda())
1047 theEventInfo.emitAntilambda = nucleus->emitInsideAntilambda();
1048
1049 // Check if the nucleus contains strange particles
1050 theEventInfo.sigmasInside = nucleus->containsSigma();
1051 theEventInfo.antikaonsInside = nucleus->containsAntiKaon();
1052 theEventInfo.lambdasInside = nucleus->containsLambda();
1053 theEventInfo.kaonsInside = nucleus->containsKaon();
1054
1055 // Capture antiKaons and Sigmas and produce Lambda instead
1056 theEventInfo.absorbedStrangeParticle = nucleus->decayInsideStrangeParticles();
1057
1058 // Emit strange particles still inside the nucleus
1059 nucleus->emitInsideStrangeParticles();
1060 theEventInfo.emitKaon = nucleus->emitInsideKaon();
1061
1062#ifdef INCLXX_IN_GEANT4_MODE
1063 theEventInfo.emitLambda = nucleus->emitInsideLambda();
1064#endif // INCLXX_IN_GEANT4_MODE
1065
1066 // Check if the nucleus contains deltas
1067 theEventInfo.deltasInside = nucleus->containsDeltas();
1068
1069 // Take care of any remaining deltas
1070 theEventInfo.forcedDeltasOutside = nucleus->decayOutgoingDeltas();
1071 theEventInfo.forcedDeltasInside = nucleus->decayInsideDeltas();
1072
1073 // Take care of any remaining etas, omegas, neutral Sigmas and/or neutral kaons
1074 G4double timeThreshold=theConfig->getDecayTimeThreshold();
1075 theEventInfo.forcedPionResonancesOutside = nucleus->decayOutgoingPionResonances(timeThreshold);
1076 nucleus->decayOutgoingSigmaZero(timeThreshold);
1077 nucleus->decayOutgoingNeutralKaon();
1078
1079 // Apply Coulomb distortion, if appropriate
1080 // Note that this will apply Coulomb distortion also on pions emitted by
1081 // unphysical remnants (see decayInsideDeltas). This is at variance with
1082 // what INCL4.6 does, but these events are (should be!) so rare that
1083 // whatever we do doesn't (shouldn't!) make any noticeable difference.
1084 CoulombDistortion::distortOut(nucleus->getStore()->getOutgoingParticles(), nucleus);
1085
1086 // If the normal cascade predicted complete fusion, use the tabulated
1087 // masses to compute the excitation energy, the recoil, etc.
1088 if(nucleus->getStore()->getOutgoingParticles().size()==0
1089 && (!nucleus->getProjectileRemnant()
1090 || nucleus->getProjectileRemnant()->getParticles().size()==0)) {
1091
1092 INCL_DEBUG("Cascade resulted in complete fusion, using realistic fusion kinematics" << '\n');
1093
1094 nucleus->useFusionKinematics();
1095
1096 if(nucleus->getExcitationEnergy()<0.) {
1097 // Complete fusion is energetically impossible, return a transparent
1098 INCL_WARN("Complete-fusion kinematics yields negative excitation energy, returning a transparent!" << '\n');
1099 theEventInfo.transparent = true;
1100 return;
1101 }
1102
1103 } else { // Normal cascade here
1104
1105 // Set the excitation energy
1106 nucleus->setExcitationEnergy(nucleus->computeExcitationEnergy());
1107
1108 // Make a projectile pre-fragment out of the geometrical and dynamical
1109 // spectators
1110 theEventInfo.nUnmergedSpectators = makeProjectileRemnant();
1111
1112 // Compute recoil momentum, energy and spin of the nucleus
1113 if(nucleus->getA()==1 && minRemnantSize>1) {
1114 INCL_ERROR("Computing one-nucleon recoil kinematics. We should never be here nowadays, cascade should stop earlier than this." << '\n');
1115 }
1116 nucleus->computeRecoilKinematics();
1117
1118#ifndef INCLXX_IN_GEANT4_MODE
1119 // Global checks of conservation laws
1120 globalConservationChecks(false);
1121#endif
1122
1123 // Make room for the remnant recoil by rescaling the energies of the
1124 // outgoing particles.
1125 if(nucleus->hasRemnant()) rescaleOutgoingForRecoil();
1126
1127 }
1128
1129 // Cluster decay
1130 theEventInfo.clusterDecay = nucleus->decayOutgoingClusters() || nucleus->decayMe(); //D
1131
1132#ifndef INCLXX_IN_GEANT4_MODE
1133 // Global checks of conservation laws
1134 globalConservationChecks(true);
1135#endif
1136
1137 // Fill the EventInfo structure
1138 nucleus->fillEventInfo(&theEventInfo);
1139
1140 }
1141 }
1142
1143 void INCL::makeCompoundNucleus() {
1144 // If this is not a nucleus-nucleus collision, don't attempt to make a
1145 // compound nucleus.
1146 //
1147 // Yes, even nucleon-nucleus collisions can lead to particles entering
1148 // below the Fermi level. Take e.g. 1-MeV p + He4.
1149 if(!nucleus->isNucleusNucleusCollision()) {
1150 forceTransparent = true;
1151 return;
1152 }
1153
1154 // Reset the internal Nucleus variables
1155 nucleus->getStore()->clearIncoming();
1156 nucleus->getStore()->clearOutgoing();
1157 nucleus->getProjectileRemnant()->reset();
1158 nucleus->setA(theEventInfo.At);
1159 nucleus->setZ(theEventInfo.Zt);
1160
1161 // CN kinematical variables
1162 // Note: the CN orbital angular momentum is neglected in what follows. We
1163 // should actually take it into account!
1164 ThreeVector theCNMomentum = nucleus->getIncomingMomentum();
1165 ThreeVector theCNSpin = nucleus->getIncomingAngularMomentum();
1166 const G4double theTargetMass = ParticleTable::getTableMass(theEventInfo.At, theEventInfo.Zt, theEventInfo.St);
1167 G4int theCNA=theEventInfo.At, theCNZ=theEventInfo.Zt, theCNS=theEventInfo.St;
1168 Cluster * const theProjectileRemnant = nucleus->getProjectileRemnant();
1169 G4double theCNEnergy = theTargetMass + theProjectileRemnant->getEnergy();
1170
1171 // Loop over the potential participants
1172 ParticleList const &initialProjectileComponents = theProjectileRemnant->getParticles();
1173 std::vector<Particle *> shuffledComponents(initialProjectileComponents.begin(), initialProjectileComponents.end());
1174 // Shuffle the list of potential participants
1175 std::shuffle(shuffledComponents.begin(), shuffledComponents.end(), Random::getAdapter());
1176
1177 G4bool success = true;
1178 G4bool atLeastOneNucleonEntering = false;
1179 for(std::vector<Particle*>::const_iterator p=shuffledComponents.begin(), e=shuffledComponents.end(); p!=e; ++p) {
1180 // Skip particles that miss the interaction distance
1181 Intersection intersectionInteractionDistance(IntersectionFactory::getEarlierTrajectoryIntersection(
1182 (*p)->getPosition(),
1183 (*p)->getPropagationVelocity(),
1184 maxInteractionDistance));
1185 if(!intersectionInteractionDistance.exists)
1186 continue;
1187
1188 // Build an entry avatar for this nucleon
1189 atLeastOneNucleonEntering = true;
1190 ParticleEntryAvatar *theAvatar = new ParticleEntryAvatar(0.0, nucleus, *p);
1191 nucleus->getStore()->addParticleEntryAvatar(theAvatar);
1192 FinalState *fs = theAvatar->getFinalState();
1193 nucleus->applyFinalState(fs);
1194 FinalStateValidity validity = fs->getValidity();
1195 delete fs;
1196 switch(validity) {
1197 case ValidFS:
1200 // Add the particle to the CN
1201 theCNA++;
1202 theCNZ += (*p)->getZ();
1203 theCNS += (*p)->getS();
1204 break;
1205 case PauliBlockedFS:
1207 default:
1208 success = false;
1209 break;
1210 }
1211 }
1212
1213 if(!success || !atLeastOneNucleonEntering) {
1214 INCL_DEBUG("No nucleon entering in forced CN, forcing a transparent" << '\n');
1215 forceTransparent = true;
1216 return;
1217 }
1218
1219// assert(theCNA==nucleus->getA());
1220// assert(theCNA<=theEventInfo.At+theEventInfo.Ap);
1221// assert(theCNZ<=theEventInfo.Zt+theEventInfo.Zp);
1222// assert(theCNS>=theEventInfo.St+theEventInfo.Sp);
1223
1224 // Update the kinematics of the CN
1225 theCNEnergy -= theProjectileRemnant->getEnergy();
1226 theCNMomentum -= theProjectileRemnant->getMomentum();
1227
1228 // Deal with the projectile remnant
1229 nucleus->finalizeProjectileRemnant(propagationModel->getCurrentTime());
1230
1231 // Subtract the angular momentum of the projectile remnant
1232// assert(nucleus->getStore()->getOutgoingParticles().empty());
1233 theCNSpin -= theProjectileRemnant->getAngularMomentum();
1234
1235 // Compute the excitation energy of the CN
1236 const G4double theCNMass = ParticleTable::getTableMass(theCNA,theCNZ,theCNS);
1237 const G4double theCNInvariantMassSquared = theCNEnergy*theCNEnergy-theCNMomentum.mag2();
1238 if(theCNInvariantMassSquared<0.) {
1239 // Negative invariant mass squared, return a transparent
1240 forceTransparent = true;
1241 return;
1242 }
1243 const G4double theCNExcitationEnergy = std::sqrt(theCNInvariantMassSquared) - theCNMass;
1244 if(theCNExcitationEnergy<0.) {
1245 // Negative excitation energy, return a transparent
1246 INCL_DEBUG("CN excitation energy is negative, forcing a transparent" << '\n'
1247 << " theCNA = " << theCNA << '\n'
1248 << " theCNZ = " << theCNZ << '\n'
1249 << " theCNS = " << theCNS << '\n'
1250 << " theCNEnergy = " << theCNEnergy << '\n'
1251 << " theCNMomentum = (" << theCNMomentum.getX() << ", "<< theCNMomentum.getY() << ", " << theCNMomentum.getZ() << ")" << '\n'
1252 << " theCNExcitationEnergy = " << theCNExcitationEnergy << '\n'
1253 << " theCNSpin = (" << theCNSpin.getX() << ", "<< theCNSpin.getY() << ", " << theCNSpin.getZ() << ")" << '\n'
1254 );
1255 forceTransparent = true;
1256 return;
1257 } else {
1258 // Positive excitation energy, can make a CN
1259 INCL_DEBUG("CN excitation energy is positive, forcing a CN" << '\n'
1260 << " theCNA = " << theCNA << '\n'
1261 << " theCNZ = " << theCNZ << '\n'
1262 << " theCNS = " << theCNS << '\n'
1263 << " theCNEnergy = " << theCNEnergy << '\n'
1264 << " theCNMomentum = (" << theCNMomentum.getX() << ", "<< theCNMomentum.getY() << ", " << theCNMomentum.getZ() << ")" << '\n'
1265 << " theCNExcitationEnergy = " << theCNExcitationEnergy << '\n'
1266 << " theCNSpin = (" << theCNSpin.getX() << ", "<< theCNSpin.getY() << ", " << theCNSpin.getZ() << ")" << '\n'
1267 );
1268 nucleus->setA(theCNA);
1269 nucleus->setZ(theCNZ);
1270 nucleus->setS(theCNS);
1271 nucleus->setMomentum(theCNMomentum);
1272 nucleus->setEnergy(theCNEnergy);
1273 nucleus->setExcitationEnergy(theCNExcitationEnergy);
1274 nucleus->setMass(theCNMass+theCNExcitationEnergy);
1275 nucleus->setSpin(theCNSpin); // neglects any orbital angular momentum of the CN
1276
1277 // Take care of any remaining deltas
1278 theEventInfo.forcedDeltasOutside = nucleus->decayOutgoingDeltas();
1279
1280 // Take care of any remaining etas and/or omegas
1281 G4double timeThreshold=theConfig->getDecayTimeThreshold();
1282 theEventInfo.forcedPionResonancesOutside = nucleus->decayOutgoingPionResonances(timeThreshold);
1283
1284 // Take care of any remaining Kaons
1285 theEventInfo.emitKaon = nucleus->emitInsideKaon();
1286
1287 // Cluster decay
1288 theEventInfo.clusterDecay = nucleus->decayOutgoingClusters() || nucleus->decayMe(); //D
1289
1290 // Fill the EventInfo structure
1291 nucleus->fillEventInfo(&theEventInfo);
1292 }
1293 }
1294
1295 void INCL::rescaleOutgoingForRecoil() {
1296 RecoilCMFunctor theRecoilFunctor(nucleus, theEventInfo);
1297
1298 // Apply the root-finding algorithm
1299 const RootFinder::Solution theSolution = RootFinder::solve(&theRecoilFunctor, 1.0);
1300 if(theSolution.success) {
1301 theRecoilFunctor(theSolution.x); // Apply the solution
1302 } else {
1303 INCL_WARN("Couldn't accommodate remnant recoil while satisfying energy conservation, root-finding algorithm failed." << '\n');
1304 }
1305 }
1306
1307#ifndef INCLXX_IN_GEANT4_MODE
1308 void INCL::globalConservationChecks(G4bool afterRecoil) {
1309 Nucleus::ConservationBalance theBalance = nucleus->getConservationBalance(theEventInfo,afterRecoil);
1310
1311 // Global conservation checks
1312 const G4double pLongBalance = theBalance.momentum.getZ();
1313 const G4double pTransBalance = theBalance.momentum.perp();
1314 if(theBalance.Z != 0) {
1315 INCL_ERROR("Violation of charge conservation! ZBalance = " << theBalance.Z << " eventNumber=" << theEventInfo.eventNumber << '\n');
1316 }
1317 if(theBalance.A != 0) {
1318 INCL_ERROR("Violation of baryon-number conservation! ABalance = " << theBalance.A << " Emit Lambda=" << theEventInfo.emitLambda << " eventNumber=" << theEventInfo.eventNumber << '\n');
1319 }
1320 if(theBalance.S != 0) {
1321 INCL_ERROR("Violation of strange-number conservation! SBalance = " << theBalance.S << " eventNumber=" << theEventInfo.eventNumber << '\n');
1322 }
1323 G4double EThreshold, pLongThreshold, pTransThreshold;
1324 if(afterRecoil) {
1325 // Less stringent checks after accommodating recoil
1326 EThreshold = 10.; // MeV
1327 pLongThreshold = 1.; // MeV/c
1328 pTransThreshold = 1.; // MeV/c
1329 } else {
1330 // More stringent checks before accommodating recoil
1331 EThreshold = 0.1; // MeV
1332 pLongThreshold = 0.1; // MeV/c
1333 pTransThreshold = 0.1; // MeV/c
1334 }
1335 if(std::abs(theBalance.energy)>EThreshold) {
1336 INCL_WARN("Violation of energy conservation > " << EThreshold << " MeV. EBalance = " << theBalance.energy << " Emit Lambda=" << theEventInfo.emitLambda << " afterRecoil = " << afterRecoil << " SRCevent ="
1337 << nucleus->getStore()->getBook().getAcceptedSrcCollisions()<< " eventNumber=" << theEventInfo.eventNumber << '\n');
1338 }
1339 if(std::abs(pLongBalance)>pLongThreshold) {
1340 INCL_WARN("Violation of longitudinal momentum conservation > " << pLongThreshold << " MeV/c. pLongBalance = " << pLongBalance << " afterRecoil = " << afterRecoil << " eventNumber=" << theEventInfo.eventNumber << '\n');
1341 }
1342 if(std::abs(pTransBalance)>pTransThreshold) {
1343 INCL_WARN("Violation of transverse momentum conservation > " << pTransThreshold << " MeV/c. pTransBalance = " << pTransBalance << " afterRecoil = " << afterRecoil << " eventNumber=" << theEventInfo.eventNumber << '\n');
1344 }
1345
1346 // Feed the EventInfo variables
1347 theEventInfo.EBalance = theBalance.energy;
1348 theEventInfo.pLongBalance = pLongBalance;
1349 theEventInfo.pTransBalance = pTransBalance;
1350 }
1351#endif
1352
1353 G4bool INCL::continueCascade() {
1354 // Stop if we have passed the stopping time
1355 if(propagationModel->getCurrentTime() > propagationModel->getStoppingTime()) {
1356 INCL_DEBUG("Cascade time (" << propagationModel->getCurrentTime()
1357 << ") exceeded stopping time (" << propagationModel->getStoppingTime()
1358 << "), stopping cascade" << '\n');
1359 return false;
1360 }
1361 // Stop if there are no participants and no pions inside the nucleus
1362 if(nucleus->getStore()->getBook().getCascading()==0 &&
1363 nucleus->getStore()->getIncomingParticles().empty()) {
1364 INCL_DEBUG("No participants in the nucleus and no incoming particles left, stopping cascade" << '\n');
1365 return false;
1366 }
1367 // Stop if the remnant is smaller than minRemnantSize
1368 if(nucleus->getA() <= minRemnantSize) {
1369 INCL_DEBUG("Remnant size (" << nucleus->getA()
1370 << ") smaller than or equal to minimum (" << minRemnantSize
1371 << "), stopping cascade" << '\n');
1372 return false;
1373 }
1374 if((nucleus->getZ() <= 2) && (propagationModel->getCurrentTime() != 0)) {
1375 INCL_DEBUG("Remnant size (" << nucleus->getZ()
1376 << ") smaller than or equal to minimum (" << "2"
1377 << "), stopping cascade" << '\n');
1378 return false;
1379 }
1380 // Stop if we have to try and make a compound nucleus or if we have to
1381 // force a transparent
1382 if(nucleus->getTryCompoundNucleus()) {
1383 INCL_DEBUG("Trying to make a compound nucleus, stopping cascade" << '\n');
1384 return false;
1385 }
1386
1387 return true;
1388 }
1389
1391 const G4double normalisationFactor = theGlobalInfo.geometricCrossSection /
1392 ((G4double) theGlobalInfo.nShots);
1393 theGlobalInfo.nucleonAbsorptionCrossSection = normalisationFactor *
1394 ((G4double) theGlobalInfo.nNucleonAbsorptions);
1395 theGlobalInfo.pionAbsorptionCrossSection = normalisationFactor *
1396 ((G4double) theGlobalInfo.nPionAbsorptions);
1397 theGlobalInfo.reactionCrossSection = normalisationFactor *
1398 ((G4double) (theGlobalInfo.nShots - theGlobalInfo.nTransparents));
1399 theGlobalInfo.errorReactionCrossSection = normalisationFactor *
1400 std::sqrt((G4double) (theGlobalInfo.nShots - theGlobalInfo.nTransparents));
1401 theGlobalInfo.forcedCNCrossSection = normalisationFactor *
1402 ((G4double) theGlobalInfo.nForcedCompoundNucleus);
1403 theGlobalInfo.errorForcedCNCrossSection = normalisationFactor *
1404 std::sqrt((G4double) (theGlobalInfo.nForcedCompoundNucleus));
1405 theGlobalInfo.completeFusionCrossSection = normalisationFactor *
1406 ((G4double) theGlobalInfo.nCompleteFusion);
1407 theGlobalInfo.errorCompleteFusionCrossSection = normalisationFactor *
1408 std::sqrt((G4double) (theGlobalInfo.nCompleteFusion));
1409 theGlobalInfo.energyViolationInteractionCrossSection = normalisationFactor *
1410 ((G4double) theGlobalInfo.nEnergyViolationInteraction);
1411
1412 theGlobalInfo.initialRandomSeeds.assign(initialSeeds.begin(), initialSeeds.end());
1413
1415 theGlobalInfo.finalRandomSeeds.assign(theSeeds.begin(), theSeeds.end());
1416 }
1417
1418 G4int INCL::makeProjectileRemnant() {
1419 // Do nothing if this is not a nucleus-nucleus reaction
1420 if(!nucleus->getProjectileRemnant())
1421 return 0;
1422
1423 // Get the spectators (geometrical+dynamical) from the Store
1424 ParticleList geomSpectators(nucleus->getProjectileRemnant()->getParticles());
1425 ParticleList dynSpectators(nucleus->getStore()->extractDynamicalSpectators());
1426
1427 G4int nUnmergedSpectators = 0;
1428
1429 // If there are no spectators, do nothing
1430 if(dynSpectators.empty() && geomSpectators.empty()) {
1431 return 0;
1432 } else if(dynSpectators.size()==1 && geomSpectators.empty()) {
1433 // No geometrical spectators, one dynamical spectator
1434 // Just put it back in the outgoing list
1435 nucleus->getStore()->addToOutgoing(dynSpectators.front());
1436 } else {
1437 // Make a cluster out of the geometrical spectators
1438 ProjectileRemnant *theProjectileRemnant = nucleus->getProjectileRemnant();
1439
1440 // Add the dynamical spectators to the bunch
1441 ParticleList rejected = theProjectileRemnant->addAllDynamicalSpectators(dynSpectators);
1442 // Put back the rejected spectators into the outgoing list
1443 nUnmergedSpectators = (G4int)rejected.size();
1444 nucleus->getStore()->addToOutgoing(rejected);
1445
1446 // Deal with the projectile remnant
1447 nucleus->finalizeProjectileRemnant(propagationModel->getCurrentTime());
1448
1449 }
1450
1451 return nUnmergedSpectators;
1452 }
1453
1454 void INCL::initMaxInteractionDistance(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1455 if(projectileSpecies.theType != Composite && projectileSpecies.theType != antiComposite) {
1456 maxInteractionDistance = 0.;
1457 return;
1458 }
1459
1460 const G4double r0 = std::max(ParticleTable::getNuclearRadius(Proton, theA, theZ),
1462 if (projectileSpecies.theType == Composite){
1463
1464 const G4double theNNDistance = CrossSections::interactionDistanceNN(projectileSpecies, kineticEnergy);
1465 maxInteractionDistance = r0 + theNNDistance;
1466 INCL_DEBUG("Initialised interaction distance: r0 = " << r0 << '\n'
1467 << " theNNDistance = " << theNNDistance << '\n'
1468 << " maxInteractionDistance = " << maxInteractionDistance << '\n');
1469 }
1470 else if (projectileSpecies.theType == antiComposite){
1471 const G4double theNbarNDistance = CrossSections::interactionDistanceNbarN(projectileSpecies, kineticEnergy);
1472 maxInteractionDistance = r0 + theNbarNDistance;
1473 INCL_DEBUG("Initialised interaction distance: r0 = " << r0 << '\n'
1474 << " theNbarNDistance = " << theNbarNDistance << '\n'
1475 << " maxInteractionDistance = " << maxInteractionDistance << '\n');
1476 }
1477
1478 }
1479
1480 void INCL::initUniverseRadius(ParticleSpecies const &p, const G4double kineticEnergy, const G4int A, const G4int Z) {
1481 G4double rMax = 0.0;
1482 if(A==0) {
1483 IsotopicDistribution const &anIsotopicDistribution =
1485 IsotopeVector theIsotopes = anIsotopicDistribution.getIsotopes();
1486 for(IsotopeIter i=theIsotopes.begin(), e=theIsotopes.end(); i!=e; ++i) {
1487 const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, i->theA, Z);
1488 const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, i->theA, Z);
1489 const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1490 rMax = std::max(maximumRadius, rMax);
1491 }
1492 } else {
1493 const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, A, Z);
1494 const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, A, Z);
1495 const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1496 rMax = std::max(maximumRadius, rMax);
1497 }
1498 if(p.theType==Composite || p.theType==Proton || p.theType==Neutron) {
1500 maxUniverseRadius = rMax + interactionDistanceNN;
1501 } else if(p.theType==PiPlus
1502 || p.theType==PiZero
1503 || p.theType==PiMinus) {
1505 maxUniverseRadius = rMax + interactionDistancePiN;
1506 } else if(p.theType==KPlus
1507 || p.theType==KZero) {
1509 maxUniverseRadius = rMax + interactionDistanceKN;
1510 } else if(p.theType==KZeroBar
1511 || p.theType==KMinus) {
1513 maxUniverseRadius = rMax + interactionDistanceKbarN;
1514 } else if(p.theType==Lambda
1515 ||p.theType==SigmaPlus
1516 || p.theType==SigmaZero
1517 || p.theType==SigmaMinus) {
1519 maxUniverseRadius = rMax + interactionDistanceYN;
1520 }
1521 else if(p.theType==antiProton) {
1522 maxUniverseRadius = rMax; //check interaction distance!!!
1523 } else if (p.theType==antiNeutron){
1525 maxUniverseRadius = rMax+ interactionDistancenbarN;
1526 } else if (p.theType==antiComposite){
1528 maxUniverseRadius =rMax + interactionDistanceNbarN;
1529 }
1530 INCL_DEBUG("Initialised universe radius: " << maxUniverseRadius << '\n');
1531 }
1532
1533
1535 G4double rMax = 0.0;
1536 if(A==0) {
1537 IsotopicDistribution const &anIsotopicDistribution =
1539 IsotopeVector theIsotopes = anIsotopicDistribution.getIsotopes();
1540 for(IsotopeIter i=theIsotopes.begin(), e=theIsotopes.end(); i!=e; ++i) {
1541 const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, i->theA, Z);
1542 const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, i->theA, Z);
1543 const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1544 rMax = std::max(maximumRadius, rMax);
1545 }
1546 } else {
1547 const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, A, Z);
1548 const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, A, Z);
1549 const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1550 rMax = std::max(maximumRadius, rMax);
1551 }
1552 return rMax;
1553 }
1554
1555
1556 void INCL::updateGlobalInfo() {
1557 // Increment the global counter for the number of shots
1558 theGlobalInfo.nShots++;
1559
1560 if(theEventInfo.transparent) {
1561 // Increment the global counter for the number of transparents
1562 theGlobalInfo.nTransparents++;
1563 // Increment the global counter for the number of forced transparents
1564 if(forceTransparent)
1565 theGlobalInfo.nForcedTransparents++;
1566 return;
1567 }
1568
1569 // Check if we have an absorption:
1570 if(theEventInfo.nucleonAbsorption) theGlobalInfo.nNucleonAbsorptions++;
1571 if(theEventInfo.pionAbsorption) theGlobalInfo.nPionAbsorptions++;
1572
1573 // Count complete-fusion events
1574 if(theEventInfo.nCascadeParticles==0) theGlobalInfo.nCompleteFusion++;
1575
1576 if(nucleus->getTryCompoundNucleus())
1577 theGlobalInfo.nForcedCompoundNucleus++;
1578
1579 // Counters for the number of violations of energy conservation in
1580 // collisions
1581 theGlobalInfo.nEnergyViolationInteraction += theEventInfo.nEnergyViolationInteraction;
1582 }
1583
1584 G4double INCL::read_file(std::string filename, std::vector<G4double>& probabilities,
1585 std::vector<std::vector<G4String>>& particle_types) {
1586 std::ifstream file(filename);
1587 G4double sum_probs = 0.0;
1588 if (file.is_open()) {
1589 G4String line;
1590 while (getline(file, line)) {
1591 std::istringstream iss(line);
1592 G4double prob;
1593 iss >> prob;
1594 sum_probs += prob;
1595 probabilities.push_back(prob);
1596 std::vector<G4String> types;
1597 G4String type;
1598 while (iss >> type) {
1599 types.push_back(type);
1600 }
1601 particle_types.push_back(std::move(types));
1602 }
1603 } else {
1604#ifdef INCLXX_IN_GEANT4_MODE
1605 G4cout << "ERROR no fread_file " << filename << G4endl;
1606#else
1607 std::cout << "ERROR no fread_file " << filename << std::endl;
1608#endif
1609 }
1610 return sum_probs;
1611 }
1612
1613
1614 G4int INCL::findStringNumber(G4double rdm, std::vector<G4double> yields) {
1615 G4int stringNumber = -1;
1616 G4double smallestsum = 0.0;
1617 G4double biggestsum = yields[0];
1618 //G4cout << "initial input " << rdm << G4endl;
1619 for (G4int i = 0; i < static_cast<G4int>(yields.size()-1); i++) {
1620 if (rdm >= smallestsum && rdm <= biggestsum) {
1621 //G4cout << smallestsum << " and " << biggestsum << G4endl;
1622 stringNumber = i+1;
1623 }
1624 smallestsum += yields[i];
1625 biggestsum += yields[i+1];
1626 }
1627 if(stringNumber==-1) stringNumber = static_cast<G4int>(yields.size());
1628 if(stringNumber==-1){
1629 INCL_ERROR("ERROR in findStringNumber (stringNumber=-1)");
1630#ifdef INCLXX_IN_GEANT4_MODE
1631 G4cout << "ERROR in findStringNumber" << G4endl;
1632#else
1633 std::cout << "ERROR in findStringNumber" << std::endl;
1634#endif
1635 }
1636 return stringNumber;
1637 }
1638
1639
1640 void INCL::preCascade_pbarH1(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1641 // Reset theEventInfo
1642 theEventInfo.reset();
1643
1645
1646 // Fill in the event information
1647 theEventInfo.projectileType = projectileSpecies.theType;
1648 theEventInfo.Ap = -1;
1649 theEventInfo.Zp = -1;
1650 theEventInfo.Sp = 0;
1651 theEventInfo.Ep = kineticEnergy;
1652 theEventInfo.St = 0;
1653 theEventInfo.At = 1;
1654 theEventInfo.Zt = 1;
1655 }
1656
1657 void INCL::preCascade_nbarH1(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1658 // Reset theEventInfo
1659 theEventInfo.reset();
1660
1662
1663 // Fill in the event information
1664 theEventInfo.projectileType = projectileSpecies.theType;
1665 theEventInfo.Ap = -1;
1666 theEventInfo.Zp = 0;
1667 theEventInfo.Sp = 0;
1668 theEventInfo.Ep = kineticEnergy;
1669 theEventInfo.St = 0;
1670 theEventInfo.At = 1;
1671 theEventInfo.Zt = 1;
1672 }
1673
1674 void INCL::postCascade_pbarH1(ParticleList const &outgoingParticles) {
1675 theEventInfo.nParticles = 0;
1676 ParticleList outgoingParticles2;
1677 // Reset the remnant counter
1678 theEventInfo.nRemnants = 0;
1679 theEventInfo.history.clear();
1680
1681 // Decay eta and omega
1682 for(ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i) {
1683 if( (*i)->isEta() || (*i)->isOmega() ) {
1684 INCL_DEBUG("Decay outgoing eta/omega particle:" << '\n'
1685 << (*i)->print() << '\n');
1686 const ThreeVector beta = -(*i)->boostVector();
1687 const G4double pionResonanceMass = (*i)->getMass();
1688
1689 // Set the pionResonance momentum to zero and sample the decay in the CM frame.
1690 // This makes life simpler if we are using real particle masses.
1691 (*i)->setMomentum(ThreeVector());
1692 (*i)->setEnergy((*i)->getMass());
1693
1694 // Use a DecayAvatar
1695 IAvatar *decay = new DecayAvatar((*i), 0.0, NULL);
1696 FinalState *fs = decay->getFinalState();
1697
1698 Particle * const theModifiedParticle = fs->getModifiedParticles().front();
1699 ParticleList const &created = fs->getCreatedParticles();
1700 Particle * const theCreatedParticle1 = created.front();
1701
1702 if (created.size() == 1) {
1703
1704 // Adjust the decay momentum if we are using the real masses
1705 const G4double decayMomentum = KinematicsUtils::momentumInCM(pionResonanceMass,theModifiedParticle->getTableMass(),theCreatedParticle1->getTableMass());
1706 ThreeVector newMomentum = theCreatedParticle1->getMomentum();
1707 newMomentum *= decayMomentum / newMomentum.mag();
1708
1709 theCreatedParticle1->setTableMass();
1710 theCreatedParticle1->setMomentum(newMomentum);
1711 theCreatedParticle1->adjustEnergyFromMomentum();
1712 theCreatedParticle1->setEmissionTime((*i)->getEmissionTime());
1713 theCreatedParticle1->boost(beta);
1714 theCreatedParticle1->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
1715
1716 theModifiedParticle->setTableMass();
1717 theModifiedParticle->setMomentum(-newMomentum);
1718 theModifiedParticle->adjustEnergyFromMomentum();
1719 theModifiedParticle->boost(beta);
1720
1721 outgoingParticles2.push_back(theCreatedParticle1);
1722 outgoingParticles2.push_back(theModifiedParticle);
1723 }
1724 else if (created.size() == 2) {
1725 Particle * const theCreatedParticle2 = created.back();
1726
1727 theCreatedParticle1->boost(beta);
1728 theCreatedParticle1->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
1729 theCreatedParticle1->setEmissionTime((*i)->getEmissionTime());
1730 theCreatedParticle2->boost(beta);
1731 theCreatedParticle2->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
1732 theCreatedParticle2->setEmissionTime((*i)->getEmissionTime());
1733 theModifiedParticle->boost(beta);
1734
1735 outgoingParticles2.push_back(theCreatedParticle1);
1736 outgoingParticles2.push_back(theCreatedParticle2);
1737 outgoingParticles2.push_back(theModifiedParticle);
1738 }
1739 else {
1740 INCL_ERROR("Wrong number (< 2) of created particles during the decay of a pion resonance");
1741 }
1742 delete fs;
1743 delete decay;
1744 }
1745 else {
1746 outgoingParticles2.push_back(*i);
1747 }
1748 }// End of Decay eta and omega
1749
1750 for(ParticleIter i=outgoingParticles2.begin(), e=outgoingParticles2.end(); i!=e; ++i ) {
1751 theEventInfo.A[theEventInfo.nParticles] = (Short_t)(*i)->getA();
1752 theEventInfo.Z[theEventInfo.nParticles] = (Short_t)(*i)->getZ();
1753 theEventInfo.S[theEventInfo.nParticles] = (Short_t)(*i)->getS();
1754 theEventInfo.EKin[theEventInfo.nParticles] = (*i)->getKineticEnergy();
1755 ThreeVector mom = (*i)->getMomentum();
1756 theEventInfo.px[theEventInfo.nParticles] = mom.getX();
1757 theEventInfo.py[theEventInfo.nParticles] = mom.getY();
1758 theEventInfo.pz[theEventInfo.nParticles] = mom.getZ();
1759 theEventInfo.theta[theEventInfo.nParticles] = Math::toDegrees(mom.theta());
1760 theEventInfo.phi[theEventInfo.nParticles] = Math::toDegrees(mom.phi());
1761 theEventInfo.origin[theEventInfo.nParticles] = -1;
1762#ifdef INCLXX_IN_GEANT4_MODE
1763 theEventInfo.parentResonancePDGCode[theEventInfo.nParticles] = (*i)->getParentResonancePDGCode();
1764 theEventInfo.parentResonanceID[theEventInfo.nParticles] = (*i)->getParentResonanceID();
1765#endif
1766 theEventInfo.history.push_back("");
1767 ParticleSpecies pt((*i)->getType());
1768 theEventInfo.PDGCode[theEventInfo.nParticles] = pt.getPDGCode();
1769 theEventInfo.nParticles++;
1770 }
1771 theEventInfo.nCascadeParticles = theEventInfo.nParticles;
1772 }
1773
1774
1775 void INCL::preCascade_pbarH2(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1776 // Reset theEventInfo
1777 theEventInfo.reset();
1778
1780
1781 // Fill in the event information
1782 theEventInfo.projectileType = projectileSpecies.theType;
1783 theEventInfo.Ap = -1;
1784 theEventInfo.Zp = -1;
1785 theEventInfo.Sp = 0;
1786 theEventInfo.Ep = kineticEnergy;
1787 theEventInfo.St = 0;
1788 theEventInfo.At = 2;
1789 theEventInfo.Zt = 1;
1790 }
1791
1792 void INCL::preCascade_nbarH2(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1793 // Reset theEventInfo
1794 theEventInfo.reset();
1795
1797
1798 // Fill in the event information
1799 theEventInfo.projectileType = projectileSpecies.theType;
1800 theEventInfo.Ap = -1;
1801 theEventInfo.Zp = 0;
1802 theEventInfo.Sp = 0;
1803 theEventInfo.Ep = kineticEnergy;
1804 theEventInfo.St = 0;
1805 theEventInfo.At = 2;
1806 theEventInfo.Zt = 1;
1807 }
1808
1809 void INCL::postCascade_pbarH2(ParticleList const &outgoingParticles, ParticleList const &H2Particles) {
1810 theEventInfo.nParticles = 0;
1811 ParticleList outgoingParticles2;
1812
1813 // Reset the remnant counter
1814 theEventInfo.nRemnants = 0;
1815 theEventInfo.history.clear();
1816
1817 // Decay eta and omega
1818 for(ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i) {
1819 if( (*i)->isEta() || (*i)->isOmega() ) {
1820 INCL_DEBUG("Decay outgoing eta/omega particle:" << '\n'
1821 << (*i)->print() << '\n');
1822 const ThreeVector beta = -(*i)->boostVector();
1823 const G4double pionResonanceMass = (*i)->getMass();
1824
1825 // Set the pionResonance momentum to zero and sample the decay in the CM frame.
1826 // This makes life simpler if we are using real particle masses.
1827 (*i)->setMomentum(ThreeVector());
1828 (*i)->setEnergy((*i)->getMass());
1829
1830 // Use a DecayAvatar
1831 IAvatar *decay = new DecayAvatar((*i), 0.0, NULL);
1832 FinalState *fs = decay->getFinalState();
1833
1834 Particle * const theModifiedParticle = fs->getModifiedParticles().front();
1835 ParticleList const &created = fs->getCreatedParticles();
1836 Particle * const theCreatedParticle1 = created.front();
1837
1838 if (created.size() == 1) {
1839
1840 // Adjust the decay momentum if we are using the real masses
1841 const G4double decayMomentum = KinematicsUtils::momentumInCM(pionResonanceMass,theModifiedParticle->getTableMass(),theCreatedParticle1->getTableMass());
1842 ThreeVector newMomentum = theCreatedParticle1->getMomentum();
1843 newMomentum *= decayMomentum / newMomentum.mag();
1844
1845 theCreatedParticle1->setTableMass();
1846 theCreatedParticle1->setMomentum(newMomentum);
1847 theCreatedParticle1->adjustEnergyFromMomentum();
1848 theCreatedParticle1->setEmissionTime((*i)->getEmissionTime());
1849 theCreatedParticle1->boost(beta);
1850 theCreatedParticle1->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
1851
1852 theModifiedParticle->setTableMass();
1853 theModifiedParticle->setMomentum(-newMomentum);
1854 theModifiedParticle->adjustEnergyFromMomentum();
1855 theModifiedParticle->boost(beta);
1856
1857 outgoingParticles2.push_back(theCreatedParticle1);
1858 outgoingParticles2.push_back(theModifiedParticle);
1859 }
1860 else if (created.size() == 2) {
1861 Particle * const theCreatedParticle2 = created.back();
1862
1863 theCreatedParticle1->boost(beta);
1864 theCreatedParticle1->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
1865 theCreatedParticle1->setEmissionTime((*i)->getEmissionTime());
1866 theCreatedParticle2->boost(beta);
1867 theCreatedParticle2->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
1868 theCreatedParticle2->setEmissionTime((*i)->getEmissionTime());
1869 theModifiedParticle->boost(beta);
1870
1871 outgoingParticles2.push_back(theCreatedParticle1);
1872 outgoingParticles2.push_back(theCreatedParticle2);
1873 outgoingParticles2.push_back(theModifiedParticle);
1874 }
1875 else {
1876 INCL_ERROR("Wrong number (< 2) of created particles during the decay of a pion resonance");
1877 }
1878 delete fs;
1879 delete decay;
1880 }
1881 else {
1882 outgoingParticles2.push_back(*i);
1883 }
1884 }// End of Decay eta and omega
1885
1886 for(ParticleIter i=outgoingParticles2.begin(), e=outgoingParticles2.end(); i!=e; ++i ) {
1887 theEventInfo.A[theEventInfo.nParticles] = (Short_t)(*i)->getA();
1888 theEventInfo.Z[theEventInfo.nParticles] = (Short_t)(*i)->getZ();
1889 theEventInfo.S[theEventInfo.nParticles] = (Short_t)(*i)->getS();
1890 theEventInfo.EKin[theEventInfo.nParticles] = (*i)->getKineticEnergy();
1891 ThreeVector mom = (*i)->getMomentum();
1892 theEventInfo.px[theEventInfo.nParticles] = mom.getX();
1893 theEventInfo.py[theEventInfo.nParticles] = mom.getY();
1894 theEventInfo.pz[theEventInfo.nParticles] = mom.getZ();
1895 theEventInfo.theta[theEventInfo.nParticles] = Math::toDegrees(mom.theta());
1896 theEventInfo.phi[theEventInfo.nParticles] = Math::toDegrees(mom.phi());
1897 theEventInfo.origin[theEventInfo.nParticles] = -1;
1898#ifdef INCLXX_IN_GEANT4_MODE
1899 theEventInfo.parentResonancePDGCode[theEventInfo.nParticles] = (*i)->getParentResonancePDGCode();
1900 theEventInfo.parentResonanceID[theEventInfo.nParticles] = (*i)->getParentResonanceID();
1901#endif
1902 theEventInfo.history.push_back("");
1903 ParticleSpecies pt((*i)->getType());
1904 theEventInfo.PDGCode[theEventInfo.nParticles] = pt.getPDGCode();
1905 theEventInfo.nParticles++;
1906 }
1907
1908 for(ParticleIter i=H2Particles.begin(), e=H2Particles.end(); i!=e; ++i ) {
1909 theEventInfo.A[theEventInfo.nParticles] = (Short_t)(*i)->getA();
1910 theEventInfo.Z[theEventInfo.nParticles] = (Short_t)(*i)->getZ();
1911 theEventInfo.S[theEventInfo.nParticles] = (Short_t)(*i)->getS();
1912 theEventInfo.EKin[theEventInfo.nParticles] = (*i)->getKineticEnergy();
1913 ThreeVector mom = (*i)->getMomentum();
1914 theEventInfo.px[theEventInfo.nParticles] = mom.getX();
1915 theEventInfo.py[theEventInfo.nParticles] = mom.getY();
1916 theEventInfo.pz[theEventInfo.nParticles] = mom.getZ();
1917 theEventInfo.theta[theEventInfo.nParticles] = Math::toDegrees(mom.theta());
1918 theEventInfo.phi[theEventInfo.nParticles] = Math::toDegrees(mom.phi());
1919 theEventInfo.origin[theEventInfo.nParticles] = -1;
1920#ifdef INCLXX_IN_GEANT4_MODE
1921 theEventInfo.parentResonancePDGCode[theEventInfo.nParticles] = (*i)->getParentResonancePDGCode();
1922 theEventInfo.parentResonanceID[theEventInfo.nParticles] = (*i)->getParentResonanceID();
1923#endif
1924 theEventInfo.history.push_back("");
1925 ParticleSpecies pt((*i)->getType());
1926 theEventInfo.PDGCode[theEventInfo.nParticles] = pt.getPDGCode();
1927 theEventInfo.nParticles++;
1928 }
1929 theEventInfo.nCascadeParticles = theEventInfo.nParticles;
1930 }
1931
1932}
G4double S(G4double temp)
const char * G4FindDataDir(const char *)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
Alternative CascadeAction for dumping avatars.
Class containing default actions to be performed at intermediate cascade steps.
Static class for cluster formation.
Static class for selecting Coulomb distortion.
Simple container for output of calculation-wide results.
Abstract interface to the nuclear potential.
Simple class for computing intersections between a straight line and a sphere.
#define INCL_ERROR(x)
#define INCL_WARN(x)
#define INCL_DEBUG(x)
Functions that encapsulate a mass table.
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
static void setBias(const G4double b)
Set the global bias factor.
static void setCutNN(const G4double c)
ParticleList const & getParticles() const
void finalizeGlobalInfo(Random::SeedVector const &initialSeeds)
G4bool prepareReaction(const ParticleSpecies &projectileSpecies, const G4double kineticEnergy, const G4int A, const G4int Z, const G4int S)
INCL(Config const *const config)
const EventInfo & processEvent()
G4double initUniverseRadiusForAntiprotonAtRest(const G4int A, const G4int Z)
G4bool initializeTarget(const G4int A, const G4int Z, const G4int S, AnnihilationType theAType)
static void deleteBackupParticles()
Release the memory allocated for the backup particles.
Class that stores isotopic abundances for a given element.
IsotopeVector const & getIsotopes() const
Get the isotope vector.
Store * getStore() const
ProjectileRemnant * getProjectileRemnant() const
Get the projectile remnant.
AnnihilationType getAnnihilationType() const
Getter for theAnnihilationType.
G4bool getTryCompoundNucleus()
G4int getS() const
Returns the strangeness number.
static std::vector< G4double > INCLBiasVector
Time ordered vector of all bias applied.
G4int getZ() const
Returns the charge number.
static G4double getTotalBias()
General bias vector function.
static G4ThreadLocal G4int nextBiasedCollisionID
G4int getA() const
Returns the baryon number.
void addToOutgoing(Particle *p)
add the particle to the outgoing particle list.
ParticleList extractDynamicalSpectators()
Returns a list of dynamical spectators.
struct config_s config
ParticleList decay(Cluster *const c)
Carries out a cluster decay.
void initialize(Config const *const theConfig)
Initialize the clustering model based on the Config object.
void deleteClusteringModel()
Delete the clustering model.
void initialize(Config const *const theConfig)
Initialize the Coulomb-distortion algorithm.
void deleteCoulomb()
Delete the Coulomb-distortion object.
void distortOut(ParticleList const &pL, Nucleus const *const n)
Modify the momentum of an outgoing particle.
G4double maxImpactParameter(ParticleSpecies const &p, const G4double kinE, Nucleus const *const n)
Return the maximum impact parameter for Coulomb-distorted trajectories.
G4double interactionDistanceNbarN(const ParticleSpecies &aSpecies, const G4double kineticEnergy)
G4double interactionDistanceKbarN(const G4double projectileKineticEnergy)
Compute the "interaction distance".
G4double interactionDistancePiN(const G4double projectileKineticEnergy)
Compute the "interaction distance".
G4double interactionDistancenbarN(const ParticleSpecies &aSpecies, const G4double kineticEnergy)
G4double interactionDistanceKN(const G4double projectileKineticEnergy)
Compute the "interaction distance".
G4double interactionDistanceYN(const G4double projectileKineticEnergy)
Compute the "interaction distance".
void initialize(Config const *const theConfig)
G4double interactionDistanceNN(const ParticleSpecies &aSpecies, const G4double kineticEnergy)
Compute the "interaction distance".
Intersection getEarlierTrajectoryIntersection(const ThreeVector &x0, const ThreeVector &p, const G4double r)
Compute the first intersection of a straight particle trajectory with a sphere.
G4double momentumInCM(Particle const *const p1, Particle const *const p2)
gives the momentum in the CM frame of two particles.
void initVerbosityLevelFromEnvvar()
const G4double pi
const G4double twoPi
const G4double tenPi
G4double toDegrees(G4double radians)
void clearCache()
Clear the INuclearPotential cache.
G4ThreadLocal NuclearMassFn getTableMass
Static pointer to the mass function for nuclei.
void initialize(Config const *const theConfig=0)
Initialize the particle table.
G4int drawRandomNaturalIsotope(const G4int Z)
G4double getRealMass(const G4INCL::ParticleType t)
Get particle mass (in MeV/c^2).
G4double getMaximumNuclearRadius(const ParticleType t, const G4int A, const G4int Z)
IsotopicDistribution const & getNaturalIsotopicDistribution(const G4int Z)
G4double getNuclearRadius(const ParticleType t, const G4int A, const G4int Z)
void initialize(Config const *const aConfig)
Initialise blockers according to a Config object.
void deleteBlockers()
Delete blockers.
void initialize(Config const *const theConfig)
void generate(const G4double sqrtS, ParticleList &particles)
Generate an event in the CM system.
const G4double eSquared
Coulomb conversion factor [MeV*fm].
ThreeVector normVector(G4double norm=1.)
SeedVector getSeeds()
G4double shoot0()
Adapter const & getAdapter()
G4double shoot()
void initialize(Config const *const)
Initialize generator according to a Config object.
Solution solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.
ParticleList::const_iterator ParticleIter
short Short_t
IsotopeVector::iterator IsotopeIter
@ NoEnergyConservationFS
G4double Double_t
std::vector< Isotope > IsotopeVector
@ DNbarNPbarNType
@ DNbarNPbarPType
@ DNbarPPbarPType
@ DNbarPPbarNType
std::vector< Base * > ParticleList
Definition PoPI.hpp:186
Bool_t pionAbsorption
True if the event is a pion absorption.
void reset()
Reset the EventInfo members.
Short_t At
Mass number of the target nucleus.
Short_t Zp
Charge number of the projectile nucleus.
Bool_t annihilationP
True if annihilation at rest on a proton.
Int_t projectileType
Projectile particle type.
Float_t Ep
Projectile kinetic energy given as input.
Short_t nCascadeParticles
Number of cascade particles.
Bool_t transparent
True if the event is transparent.
Bool_t nucleonAbsorption
True if the event is a nucleon absorption.
Short_t St
Strangeness number of the target nucleus.
Int_t nEnergyViolationInteraction
Number of attempted collisions/decays for which the energy-conservation algorithm failed to find a so...
Short_t Ap
Mass number of the projectile nucleus.
Short_t Sp
Strangeness number of the projectile nucleus.
Bool_t annihilationN
True if annihilation at rest on a neutron.
Short_t Zt
Charge number of the target nucleus.
static G4ThreadLocal Int_t eventNumber
Number of the event.
Int_t nNucleonAbsorptions
Number of nucleon absorptions (no outcoming particles).
Int_t nEnergyViolationInteraction
Number of attempted collisions/decays for which the energy-conservation algorithm failed to find a so...
Int_t nShots
Number of shots.
Int_t nPionAbsorptions
Number of nucleon absorptions (no outcoming pions).
Int_t nCompleteFusion
Number of complete-fusion events (nParticles==0).
Int_t nTransparents
Number of transparent shots.
Int_t nForcedCompoundNucleus
Number of forced compound-nucleus events.
Int_t nForcedTransparents
Number of forced transparents.