Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4INCLNucleus.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 * G4INCLNucleus.cc
40 *
41 * \date Jun 5, 2009
42 * \author Pekka Kaitaniemi
43 */
44
45#ifndef G4INCLNucleus_hh
46#define G4INCLNucleus_hh 1
47
48#include "G4INCLGlobals.hh"
49#include "G4INCLLogger.hh"
50#include "G4INCLParticle.hh"
51#include "G4INCLIAvatar.hh"
52#include "G4INCLNucleus.hh"
54#include "G4INCLDecayAvatar.hh"
56#include "G4INCLCluster.hh"
57#include "G4INCLClusterDecay.hh"
58#include "G4INCLDeJongSpin.hh"
61#include <iterator>
62#include <cstdlib>
63#include <sstream>
64// #include <cassert>
67
68namespace G4INCL {
69
70 Nucleus::Nucleus(G4int mass, G4int charge, G4int strangess, Config const * const conf, const G4double universeRadius,
71 AnnihilationType AType) //D
72 : Cluster(charge,mass,strangess,true),
73 theInitialZ(charge), theInitialA(mass), theInitialS(strangess),
74 theNpInitial(0), theNnInitial(0),
75 theNlInitial(0),
76 theNSpInitial(0), theNSzInitial(0), theNSmInitial(0),
77 theNpionplusInitial(0), theNpionminusInitial(0),
78 theNkaonplusInitial(0), theNkaonminusInitial(0),
79 theNantiprotonInitial(0),theNantineutronInitial(0),
80 initialInternalEnergy(0.), srcInternalEnergy(0.),
81 incomingAngularMomentum(0.,0.,0.), incomingMomentum(0.,0.,0.),
82 initialCenterOfMass(0.,0.,0.),
83 remnant(true),
84 initialEnergy(0.),
85 tryCN(false),
86 theUniverseRadius(universeRadius),
87 isNucleusNucleus(false),
88 theProjectileRemnant(NULL),
89 theDensity(NULL),
90 thePotential(NULL),
91 theAType(AType)
92 {
93 PotentialType potentialType;
94 G4bool pionPotential;
95 if(conf) {
96 potentialType = conf->getPotentialType();
97 pionPotential = conf->getPionPotential();
98 } else { // By default we don't use energy dependent
99 // potential. This is convenient for some tests.
100 potentialType = IsospinPotential;
101 pionPotential = true;
102 }
103
104 thePotential = NuclearPotential::createPotential(potentialType, theA, theZ, pionPotential);
105
106 ParticleTable::setProtonSeparationEnergy(thePotential->getSeparationEnergy(Proton));
107 ParticleTable::setNeutronSeparationEnergy(thePotential->getSeparationEnergy(Neutron));
108
109 if (theAType==PType) theDensity = NuclearDensityFactory::createDensity(theA+1, theZ+1, theS);
110 else if (theAType==NType) theDensity = NuclearDensityFactory::createDensity(theA+1, theZ, theS);
111 else if (theAType==DNbarNPbarNType) theDensity = NuclearDensityFactory::createDensity(theA+2, theZ, theS);
112 else if (theAType==DNbarPPbarPType) theDensity = NuclearDensityFactory::createDensity(theA+2, theZ+2, theS);
113 else if (theAType==DNbarPPbarNType || theAType==DNbarNPbarPType) theDensity = NuclearDensityFactory::createDensity(theA+2, theZ+1, theS);
114 else
116
117 theParticleSampler->setPotential(thePotential);
118 theParticleSampler->setDensity(theDensity);
119
120 if(theUniverseRadius<0)
121 theUniverseRadius = theDensity->getMaximumRadius();
122 theStore = new Store(conf);
123 }
124
126 delete theStore;
128 /* We don't delete the potential and the density here any more -- Factories
129 * are caching them
130 delete thePotential;
131 delete theDensity;*/
132 }
133
135 return theAType;
136 }
137
139 theAType = type;
140 }
141
143 // Reset the variables connected with the projectile remnant
144 delete theProjectileRemnant;
145 theProjectileRemnant = NULL;
147
148 for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i) {
150 }
151 theStore->add(particles);
152 particles.clear();
153 initialInternalEnergy = computeTotalEnergy();
154 initialCenterOfMass = thePosition;
155 }
156
158 if(!finalstate) // do nothing if no final state was returned
159 return;
160
161 G4double totalEnergy = 0.0;
162
163 FinalStateValidity const validity = finalstate->getValidity();
164 if(validity == ValidFS) {
165
166 ParticleList const &created = finalstate->getCreatedParticles();
167 for(ParticleIter iter=created.begin(), e=created.end(); iter!=e; ++iter) {
168 theStore->add((*iter));
169 if(!(*iter)->isOutOfWell()) {
170 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
171 }
172 }
173
174 ParticleList const &deleted = finalstate->getDestroyedParticles();
175 for(ParticleIter iter=deleted.begin(), e=deleted.end(); iter!=e; ++iter) {
176 theStore->particleHasBeenDestroyed(*iter);
177 }
178
179 ParticleList const &modified = finalstate->getModifiedParticles();
180 for(ParticleIter iter=modified.begin(), e=modified.end(); iter!=e; ++iter) {
181 theStore->particleHasBeenUpdated(*iter);
182 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
183 }
184
185 ParticleList const &out = finalstate->getOutgoingParticles();
186 for(ParticleIter iter=out.begin(), e=out.end(); iter!=e; ++iter) {
187 if((*iter)->isCluster()) {
188 Cluster *clusterOut = dynamic_cast<Cluster*>((*iter));
189// assert(clusterOut);
190#ifdef INCLXX_IN_GEANT4_MODE
191 if(!clusterOut)
192 continue;
193#endif
194 ParticleList const &components = clusterOut->getParticles();
195 for(ParticleIter in=components.begin(), end=components.end(); in!=end; ++in)
196 theStore->particleHasBeenEjected(*in);
197 } else {
198 theStore->particleHasBeenEjected(*iter);
199 }
200 totalEnergy += (*iter)->getEnergy(); // No potential here because the particle is gone
201 theA -= (*iter)->getA();
202 theZ -= (*iter)->getZ();
203 theS -= (*iter)->getS();
204 theStore->addToOutgoing(*iter);
205 (*iter)->setEmissionTime(theStore->getBook().getCurrentTime());
206 }
207
208 ParticleList const &entering = finalstate->getEnteringParticles();
209 for(ParticleIter iter=entering.begin(), e=entering.end(); iter!=e; ++iter) {
210 insertParticle(*iter);
211 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
212 }
213
214 // actually perform the removal of the scheduled avatars
215 theStore->removeScheduledAvatars();
216 } else if(validity == ParticleBelowFermiFS || validity == ParticleBelowZeroFS) {
217 INCL_DEBUG("A Particle is entering below the Fermi sea:" << '\n' << finalstate->print() << '\n');
218 tryCN = true;
219 ParticleList const &entering = finalstate->getEnteringParticles();
220 for(ParticleIter iter=entering.begin(), e=entering.end(); iter!=e; ++iter) {
221 insertParticle(*iter);
222 }
223 }
224
225 if(validity==ValidFS &&
226 std::abs(totalEnergy - finalstate->getTotalEnergyBeforeInteraction()) > 0.1) {
227 INCL_ERROR("Energy nonconservation! Energy at the beginning of the event = "
228 << finalstate->getTotalEnergyBeforeInteraction()
229 <<" and after interaction = "
230 << totalEnergy << '\n'
231 << finalstate->print());
232 }
233 }
234
236 INCL_WARN("Useless Nucleus::propagateParticles -method called." << '\n');
237 }
238
240 G4double totalEnergy = 0.0;
241 ParticleList const &inside = theStore->getParticles();
242 for(ParticleIter p=inside.begin(), e=inside.end(); p!=e; ++p) {
243 if((*p)->isNucleon()) // Ugly: we should calculate everything using total energies!
244 totalEnergy += (*p)->getKineticEnergy() - (*p)->getPotentialEnergy();
245 else if((*p)->isResonance())
246 totalEnergy += (*p)->getEnergy() - (*p)->getPotentialEnergy() - ParticleTable::effectiveNucleonMass;
247 else if((*p)->isHyperon())
248 totalEnergy += (*p)->getEnergy() - (*p)->getPotentialEnergy() - ParticleTable::getRealMass((*p)->getType());
249 //else if((*p)->isAntiLambda())
250 // totalEnergy += (*p)->getEnergy() - (*p)->getPotentialEnergy() + ParticleTable::getRealMass((*p)->getType()) - ParticleTable::getSeparationEnergyINCL(Lambda, theA, theZ);
251 //std::cout << ParticleTable::getRealMass((*p)->getType()) << std::endl;}
252 else
253 totalEnergy += (*p)->getEnergy() - (*p)->getPotentialEnergy();
254 }
255
256 return totalEnergy;
257 }
258
260 // If the remnant consists of only one nucleon, we need to apply a special
261 // procedure to put it on mass shell.
262 if(theA==1) {
264 computeOneNucleonRecoilKinematics();
265 remnant=false;
266 return;
267 }
268
269 // Compute the recoil momentum and angular momentum
270 theMomentum = incomingMomentum;
271 theSpin = incomingAngularMomentum;
272
273 ParticleList const &outgoing = theStore->getOutgoingParticles();
274 for(ParticleIter p=outgoing.begin(), e=outgoing.end(); p!=e; ++p) {
275 theMomentum -= (*p)->getMomentum();
276 theSpin -= (*p)->getAngularMomentum();
277 }
278 if(theProjectileRemnant) {
279 theMomentum -= theProjectileRemnant->getMomentum();
280 theSpin -= theProjectileRemnant->getAngularMomentum();
281 }
282
283 // Subtract orbital angular momentum
285 theSpin -= (thePosition-initialCenterOfMass).vector(theMomentum);
286
289 remnant=true;
290 }
291
293 ThreeVector cm(0.,0.,0.);
294 G4double totalMass = 0.0;
295 ParticleList const &inside = theStore->getParticles();
296 for(ParticleIter p=inside.begin(), e=inside.end(); p!=e; ++p) {
297 const G4double mass = (*p)->getMass();
298 cm += (*p)->getPosition() * mass;
299 totalMass += mass;
300 }
301 cm /= totalMass;
302 return cm;
303 }
304
306 const G4double totalEnergy = computeTotalEnergy();
307 const G4double separationEnergies = computeSeparationEnergyBalance();
308
309 return totalEnergy - initialInternalEnergy - separationEnergies;
310
311 }
312
313//thePotential->getSeparationEnergy(Proton)
314
315 std::string Nucleus::print()
316 {
317 std::stringstream ss;
318 ss << "Particles in the nucleus:" << '\n'
319 << "Inside:" << '\n';
320 G4int counter = 1;
321 ParticleList const &inside = theStore->getParticles();
322 for(ParticleIter p=inside.begin(), e=inside.end(); p!=e; ++p) {
323 ss << "index = " << counter << '\n'
324 << (*p)->print();
325 counter++;
326 }
327 ss <<"Outgoing:" << '\n';
328 ParticleList const &outgoing = theStore->getOutgoingParticles();
329 for(ParticleIter p=outgoing.begin(), e=outgoing.end(); p!=e; ++p)
330 ss << (*p)->print();
331
332 return ss.str();
333 }
334
336
337 std::cout << "restoreSrcPartner: " << particle->print() << std::endl;
338 std::cout << "restoreSrcPartner: " << m.print() << std::endl;
339
340 particle->setMomentum(m);
341 particle->adjustEnergyFromMomentum();
342
343 std::cout << "restoreSrcPartner bis: " << particle->print() << std::endl;
344}
345
347 ParticleList const &out = theStore->getOutgoingParticles();
348 ParticleList deltas;
349 for(ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
350 if((*i)->isDelta()) deltas.push_back((*i));
351 }
352 if(deltas.empty()) return false;
353
354 for(ParticleIter i=deltas.begin(), e=deltas.end(); i!=e; ++i) {
355 INCL_DEBUG("Decay outgoing delta particle:" << '\n'
356 << (*i)->print() << '\n');
357 const ThreeVector beta = -(*i)->boostVector();
358 const G4double deltaMass = (*i)->getMass();
359
360 // Set the delta momentum to zero and sample the decay in the CM frame.
361 // This makes life simpler if we are using real particle masses.
362 (*i)->setMomentum(ThreeVector());
363 (*i)->setEnergy((*i)->getMass());
364
365 // Use a DecayAvatar
366 IAvatar *decay = new DecayAvatar((*i), 0.0, NULL);
367 FinalState *fs = decay->getFinalState();
368 Particle * const pion = fs->getCreatedParticles().front();
369 Particle * const nucleon = fs->getModifiedParticles().front();
370
371 // Adjust the decay momentum if we are using the real masses
372 const G4double decayMomentum = KinematicsUtils::momentumInCM(deltaMass,
373 nucleon->getTableMass(),
374 pion->getTableMass());
375 ThreeVector newMomentum = pion->getMomentum();
376 newMomentum *= decayMomentum / newMomentum.mag();
377
378 pion->setTableMass();
379 pion->setMomentum(newMomentum);
380 pion->adjustEnergyFromMomentum();
381 pion->setEmissionTime(nucleon->getEmissionTime());
382 pion->boost(beta);
383 pion->setBiasCollisionVector(nucleon->getBiasCollisionVector());
384
385 nucleon->setTableMass();
386 nucleon->setMomentum(-newMomentum);
387 nucleon->adjustEnergyFromMomentum();
388 nucleon->boost(beta);
389
390 theStore->addToOutgoing(pion);
391
392 delete fs;
393 delete decay;
394 }
395
396 return true;
397 }
398
400 /* If there is a pion potential, do nothing (deltas will be counted as
401 * excitation energy).
402 * If, however, the remnant is unphysical (Z<0 or Z>A), force the deltas to
403 * decay and get rid of all the pions. In case you're wondering, you can
404 * end up with Z<0 or Z>A if the remnant contains more pi- than protons or
405 * more pi+ than neutrons, respectively.
406 */
407 const G4bool unphysicalRemnant = (theZ<0 || theZ>theA);
408 if(thePotential->hasPionPotential() && !unphysicalRemnant)
409 return false;
410
411 // Build a list of deltas (avoid modifying the list you are iterating on).
412 ParticleList const &inside = theStore->getParticles();
413 ParticleList deltas;
414 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i)
415 if((*i)->isDelta()) deltas.push_back((*i));
416
417 // Loop over the deltas, make them decay
418 for(ParticleIter i=deltas.begin(), e=deltas.end(); i!=e; ++i) {
419 INCL_DEBUG("Decay inside delta particle:" << '\n'
420 << (*i)->print() << '\n');
421 // Create a forced-decay avatar. Note the last boolean parameter. Note
422 // also that if the remnant is unphysical we more or less explicitly give
423 // up energy conservation and CDPP by passing a NULL pointer for the
424 // nucleus.
425 IAvatar *decay;
426 if(unphysicalRemnant) {
427 INCL_WARN("Forcing delta decay inside an unphysical remnant (A=" << theA
428 << ", Z=" << theZ << "). Might lead to energy-violation warnings."
429 << '\n');
430 decay = new DecayAvatar((*i), 0.0, NULL, true);
431 } else
432 decay = new DecayAvatar((*i), 0.0, this, true);
433 FinalState *fs = decay->getFinalState();
434
435 // The pion can be ejected only if we managed to satisfy energy
436 // conservation and if pion emission does not lead to negative excitation
437 // energies.
438 if(fs->getValidity()==ValidFS) {
439 // Apply the final state to the nucleus
440 applyFinalState(fs);
441 }
442 delete fs;
443 delete decay;
444 }
445
446 // If the remnant is unphysical, emit all the pions
447 if(unphysicalRemnant) {
448 INCL_DEBUG("Remnant is unphysical: Z=" << theZ << ", A=" << theA << ", emitting all the pions" << '\n');
450 }
451
452 return true;
453 }
454
456
457 /* Transform each strange particles into a lambda
458 * Every Kaon (KPlus and KZero) are emited
459 */
460 const G4bool unphysicalRemnant = (theZ<0 || theZ>theA);
461 if(unphysicalRemnant){
463 INCL_WARN("Remnant is unphysical: Z=" << theZ << ", A=" << theA << ", too much strange particles? -> all emit" << '\n');
464 return false;
465 }
466
467 /* Build a list of particles with a strangeness == -1 except Lambda,
468 * and two other one for proton and neutron
469 */
470 ParticleList const &inside = theStore->getParticles();
471 ParticleList stranges;
472 ParticleList protons;
473 ParticleList neutrons;
474 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i){
475 if((*i)->isSigma() || (*i)->isAntiKaon()) stranges.push_back((*i));
476 else if((*i)->isNucleon() && (*i)->getZ() == 1) protons.push_back((*i));
477 else if((*i)->isNucleon() && (*i)->getZ() == 0) neutrons.push_back((*i));
478 }
479
480 if((stranges.size() > protons.size()) || (stranges.size() > neutrons.size())){
481 INCL_WARN("Remnant is unphysical: Nproton=" << protons.size() << ", Nneutron=" << neutrons.size() << ", Strange particles : " << stranges.size() << '\n');
483 return false;
484 }
485
486 // Loop over the strange particles, make them absorbe
487 ParticleIter protonIter = protons.begin();
488 ParticleIter neutronIter = neutrons.begin();
489 for(ParticleIter i=stranges.begin(), e=stranges.end(); i!=e; ++i) {
490 INCL_DEBUG("Absorbe inside strange particles:" << '\n'
491 << (*i)->print() << '\n');
492 IAvatar *decay;
493 if((*i)->getType() == SigmaMinus){
494 decay = new DecayAvatar((*protonIter), (*i), 0.0, this, true);
495 ++protonIter;
496 }
497 else if((*i)->getType() == SigmaPlus){
498 decay = new DecayAvatar((*neutronIter), (*i), 0.0, this, true);
499 ++neutronIter;
500 }
501 else if(Random::shoot()*(protons.size() + neutrons.size()) < protons.size()){
502 decay = new DecayAvatar((*protonIter), (*i), 0.0, this, true);
503 ++protonIter;
504 }
505 else {
506 decay = new DecayAvatar((*neutronIter), (*i), 0.0, this, true);
507 ++neutronIter;
508 }
509 FinalState *fs = decay->getFinalState();
510 applyFinalState(fs);
511 delete fs;
512 delete decay;
513 }
514
515 return true;
516 }
517
519 ParticleList const &out = theStore->getOutgoingParticles();
520 ParticleList pionResonances;
521 for(ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
522// if((*i)->isEta() || (*i)->isOmega()) pionResonances.push_back((*i));
523 if(((*i)->isEta() && timeThreshold > ParticleTable::getWidth(Eta)) || ((*i)->isOmega() && timeThreshold > ParticleTable::getWidth(Omega))) pionResonances.push_back((*i));
524 }
525 if(pionResonances.empty()) return false;
526
527 for(ParticleIter i=pionResonances.begin(), e=pionResonances.end(); i!=e; ++i) {
528 INCL_DEBUG("Decay outgoing pionResonances particle:" << '\n'
529 << (*i)->print() << '\n');
530 const ThreeVector beta = -(*i)->boostVector();
531 const G4double pionResonanceMass = (*i)->getMass();
532
533 // Set the pionResonance momentum to zero and sample the decay in the CM frame.
534 // This makes life simpler if we are using real particle masses.
535 (*i)->setMomentum(ThreeVector());
536 (*i)->setEnergy((*i)->getMass());
537
538 // Use a DecayAvatar
539 IAvatar *decay = new DecayAvatar((*i), 0.0, NULL);
540 FinalState *fs = decay->getFinalState();
541
542 Particle * const theModifiedParticle = fs->getModifiedParticles().front();
543 ParticleList const &created = fs->getCreatedParticles();
544 Particle * const theCreatedParticle1 = created.front();
545
546 if (created.size() == 1) {
547
548 // Adjust the decay momentum if we are using the real masses
549 const G4double decayMomentum = KinematicsUtils::momentumInCM(pionResonanceMass,theModifiedParticle->getTableMass(),theCreatedParticle1->getTableMass());
550 ThreeVector newMomentum = theCreatedParticle1->getMomentum();
551 newMomentum *= decayMomentum / newMomentum.mag();
552
553 theCreatedParticle1->setTableMass();
554 theCreatedParticle1->setMomentum(newMomentum);
555 theCreatedParticle1->adjustEnergyFromMomentum();
556 theCreatedParticle1->setEmissionTime((*i)->getEmissionTime());
557 theCreatedParticle1->boost(beta);
558 theCreatedParticle1->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
559
560 theModifiedParticle->setTableMass();
561 theModifiedParticle->setMomentum(-newMomentum);
562 theModifiedParticle->adjustEnergyFromMomentum();
563 theModifiedParticle->boost(beta);
564
565 theStore->addToOutgoing(theCreatedParticle1);
566 }
567 else if (created.size() == 2) {
568 Particle * const theCreatedParticle2 = created.back();
569
570 theCreatedParticle1->boost(beta);
571 theCreatedParticle1->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
572 theCreatedParticle1->setEmissionTime((*i)->getEmissionTime());
573 theCreatedParticle2->boost(beta);
574 theCreatedParticle2->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
575 theCreatedParticle2->setEmissionTime((*i)->getEmissionTime());
576 theModifiedParticle->boost(beta);
577
578 theStore->addToOutgoing(theCreatedParticle1);
579 theStore->addToOutgoing(theCreatedParticle2);
580 }
581 else {
582 INCL_ERROR("Wrong number (< 2) of created particles during the decay of a pion resonance");
583 }
584 delete fs;
585 delete decay;
586 }
587
588 return true;
589 }
590
592 ParticleList const &out = theStore->getOutgoingParticles();
593 ParticleList neutralsigma;
594 for(ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
595 if((*i)->getType() == SigmaZero && timeThreshold > ParticleTable::getWidth(SigmaZero)) neutralsigma.push_back((*i));
596 }
597 if(neutralsigma.empty()) return false;
598
599 for(ParticleIter i=neutralsigma.begin(), e=neutralsigma.end(); i!=e; ++i) {
600 INCL_DEBUG("Decay outgoing neutral sigma:" << '\n'
601 << (*i)->print() << '\n');
602 const ThreeVector beta = -(*i)->boostVector();
603 const G4double neutralsigmaMass = (*i)->getMass();
604
605 // Set the neutral sigma momentum to zero and sample the decay in the CM frame.
606 // This makes life simpler if we are using real particle masses.
607 (*i)->setMomentum(ThreeVector());
608 (*i)->setEnergy((*i)->getMass());
609
610 // Use a DecayAvatar
611 IAvatar *decay = new DecayAvatar((*i), 0.0, NULL);
612 FinalState *fs = decay->getFinalState();
613
614 Particle * const theModifiedParticle = fs->getModifiedParticles().front();
615 ParticleList const &created = fs->getCreatedParticles();
616 Particle * const theCreatedParticle = created.front();
617
618 if (created.size() == 1) {
619
620 // Adjust the decay momentum if we are using the real masses
621 const G4double decayMomentum = KinematicsUtils::momentumInCM(neutralsigmaMass,theModifiedParticle->getTableMass(),theCreatedParticle->getTableMass());
622 ThreeVector newMomentum = theCreatedParticle->getMomentum();
623 newMomentum *= decayMomentum / newMomentum.mag();
624
625 theCreatedParticle->setTableMass();
626 theCreatedParticle->setMomentum(newMomentum);
627 theCreatedParticle->adjustEnergyFromMomentum();
628 theCreatedParticle->boost(beta);
629 theCreatedParticle->setBiasCollisionVector(theModifiedParticle->getBiasCollisionVector());
630
631 theModifiedParticle->setTableMass();
632 theModifiedParticle->setMomentum(-newMomentum);
633 theModifiedParticle->adjustEnergyFromMomentum();
634 theModifiedParticle->boost(beta);
635
636 theStore->addToOutgoing(theCreatedParticle);
637 }
638 else {
639 INCL_ERROR("Wrong number (!= 1) of created particles during the decay of a sigma zero");
640 }
641 delete fs;
642 delete decay;
643 }
644
645 return true;
646 }
647
649 ParticleList const &out = theStore->getOutgoingParticles();
650 ParticleList neutralkaon;
651 for(ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
652 if((*i)->getType() == KZero || (*i)->getType() == KZeroBar) neutralkaon.push_back((*i));
653 }
654 if(neutralkaon.empty()) return false;
655
656 for(ParticleIter i=neutralkaon.begin(), e=neutralkaon.end(); i!=e; ++i) {
657 INCL_DEBUG("Transform outgoing neutral kaon:" << '\n'
658 << (*i)->print() << '\n');
659
660 // Use a DecayAvatar
661 IAvatar *decay = new DecayAvatar((*i), 0.0, NULL);
662 FinalState *fs = decay->getFinalState();
663
664 delete fs;
665 delete decay;
666 }
667
668 return true;
669 }
670
672 ParticleList const &out = theStore->getOutgoingParticles();
673 ParticleList clusters;
674 for(ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
675 if((*i)->isCluster()) clusters.push_back((*i));
676 }
677 if(clusters.empty()) return false;
678
679 for(ParticleIter i=clusters.begin(), e=clusters.end(); i!=e; ++i) {
680 Cluster *cluster = dynamic_cast<Cluster*>(*i); // Can't avoid using a cast here
681// assert(cluster);
682#ifdef INCLXX_IN_GEANT4_MODE
683 if(!cluster)
684 continue;
685#endif
686 cluster->deleteParticles(); // Don't need them
687 ParticleList decayProducts = ClusterDecay::decay(cluster);
688 for(ParticleIter j=decayProducts.begin(), end=decayProducts.end(); j!=end; ++j){
689 (*j)->setBiasCollisionVector(cluster->getBiasCollisionVector());
690 theStore->addToOutgoing(*j);
691 }
692 }
693 return true;
694 }
695
697 // Do the phase-space decay only if Z=0 or N=0
698 if(theA<=1 || (theZ!=0 && (theA+theS)!=theZ))
699 return false;
700
701 ParticleList decayProducts = ClusterDecay::decay(this);
702 for(ParticleIter j=decayProducts.begin(), e=decayProducts.end(); j!=e; ++j){
703 (*j)->setBiasCollisionVector(this->getBiasCollisionVector());
704 theStore->addToOutgoing(*j);
705 }
706
707 return true;
708 }
709
711 /* Forcing emissions of all pions in the nucleus. This probably violates
712 * energy conservation (although the computation of the recoil kinematics
713 * might sweep this under the carpet).
714 */
715 INCL_WARN("Forcing emissions of all pions in the nucleus." << '\n');
716
717 // Emit the pions with this kinetic energy
718 const G4double tinyPionEnergy = 0.1; // MeV
719
720 // Push out the emitted pions
721 ParticleList const &inside = theStore->getParticles();
722 ParticleList toEject;
723 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i) {
724 if((*i)->isPion()) {
725 Particle * const thePion = *i;
726 INCL_DEBUG("Forcing emission of the following particle: "
727 << thePion->print() << '\n');
728 thePion->setEmissionTime(theStore->getBook().getCurrentTime());
729 // Correction for real masses
730 const G4double theQValueCorrection = thePion->getEmissionQValueCorrection(theA,theZ,theS);
731 const G4double kineticEnergyOutside = thePion->getKineticEnergy() - thePion->getPotentialEnergy() + theQValueCorrection;
732 thePion->setTableMass();
733 if(kineticEnergyOutside > 0.0)
734 thePion->setEnergy(thePion->getMass()+kineticEnergyOutside);
735 else
736 thePion->setEnergy(thePion->getMass()+tinyPionEnergy);
737 thePion->adjustMomentumFromEnergy();
738 thePion->setPotentialEnergy(0.);
739 theZ -= thePion->getZ();
740 toEject.push_back(thePion);
741 }
742 }
743 for(ParticleIter i=toEject.begin(), e=toEject.end(); i!=e; ++i) {
744 theStore->particleHasBeenEjected(*i);
745 theStore->addToOutgoing(*i);
746 (*i)->setParticleBias(Particle::getTotalBias());
747 }
748 }
749
751 /* Forcing emissions of Sigmas and antiKaons.
752 * This probably violates energy conservation
753 * (although the computation of the recoil kinematics
754 * might sweep this under the carpet).
755 */
756 INCL_DEBUG("Forcing emissions of all strange particles in the nucleus." << '\n');
757
758 // Emit the strange particles with this kinetic energy
759 const G4double tinyEnergy = 0.1; // MeV
760
761 // Push out the emitted strange particles
762 ParticleList const &inside = theStore->getParticles();
763 ParticleList toEject;
764 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i) {
765 if((*i)->isSigma() || (*i)->isAntiKaon()) {
766 Particle * const theParticle = *i;
767 INCL_DEBUG("Forcing emission of the following particle: "
768 << theParticle->print() << '\n');
769 theParticle->setEmissionTime(theStore->getBook().getCurrentTime());
770 // Correction for real masses
771 const G4double theQValueCorrection = theParticle->getEmissionQValueCorrection(theA,theZ,theS); // Does it work for strange particles? should be check
772 const G4double kineticEnergyOutside = theParticle->getKineticEnergy() - theParticle->getPotentialEnergy() + theQValueCorrection;
773 theParticle->setTableMass();
774 if(kineticEnergyOutside > 0.0)
775 theParticle->setEnergy(theParticle->getMass()+kineticEnergyOutside);
776 else
777 theParticle->setEnergy(theParticle->getMass()+tinyEnergy);
778 theParticle->adjustMomentumFromEnergy();
779 theParticle->setPotentialEnergy(0.);
780 theA -= theParticle->getA();
781 theZ -= theParticle->getZ();
782 theS -= theParticle->getS();
783 toEject.push_back(theParticle);
784 }
785 }
786 for(ParticleIter i=toEject.begin(), e=toEject.end(); i!=e; ++i) {
787 theStore->particleHasBeenEjected(*i);
788 theStore->addToOutgoing(*i);
789 (*i)->setParticleBias(Particle::getTotalBias());
790 }
791 }
792
794 /* Forcing emissions of all Lambda in the nucleus.
795 * This probably violates energy conservation
796 * (although the computation of the recoil kinematics
797 * might sweep this under the carpet).
798 */
799 INCL_DEBUG("Forcing emissions of all Lambda in the nucleus." << '\n');
800
801 // Emit the Lambda with this kinetic energy
802 const G4double tinyEnergy = 0.1; // MeV
803
804 // Push out the emitted Lambda
805 ParticleList const &inside = theStore->getParticles();
806 ParticleList toEject;
807 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i) {
808 if((*i)->isLambda()) {
809 Particle * const theLambda = *i;
810 INCL_DEBUG("Forcing emission of the following particle: "
811 << theLambda->print() << '\n');
812 theLambda->setEmissionTime(theStore->getBook().getCurrentTime());
813 // Correction for real masses
814 const G4double theQValueCorrection = theLambda->getEmissionQValueCorrection(theA,theZ,theS); // Does it work for strange particles? Should be check
815 const G4double kineticEnergyOutside = theLambda->getKineticEnergy() - theLambda->getPotentialEnergy() + theQValueCorrection;
816 theLambda->setTableMass();
817 if(kineticEnergyOutside > 0.0)
818 theLambda->setEnergy(theLambda->getMass()+kineticEnergyOutside);
819 else
820 theLambda->setEnergy(theLambda->getMass()+tinyEnergy);
821 theLambda->adjustMomentumFromEnergy();
822 theLambda->setPotentialEnergy(0.);
823 theA -= theLambda->getA();
824 theS -= theLambda->getS();
825 toEject.push_back(theLambda);
826 }
827 }
828 for(ParticleIter i=toEject.begin(), e=toEject.end(); i!=e; ++i) {
829 theStore->particleHasBeenEjected(*i);
830 theStore->addToOutgoing(*i);
831 (*i)->setParticleBias(Particle::getTotalBias());
832 }
833 return (G4int)toEject.size();
834 }
835
837 /* Forcing emissions of all Antilambdas in the nucleus.
838 * This probably violates energy conservation
839 * (although the computation of the recoil kinematics
840 * might sweep this under the carpet).
841 */
842 INCL_DEBUG("Forcing emissions of all antiLambda in the nucleus." << '\n');
843
844 // Emit the Lambda with this kinetic energy
845 const G4double tinyEnergy = 0.1; // MeV
846
847 // Push out the emitted Lambda
848 ParticleList const &inside = theStore->getParticles();
849 ParticleList toEject;
850 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i) {
851 if((*i)->isAntiLambda()) {
852 Particle * const theAntiLambda = *i;
853 INCL_DEBUG("Forcing emission of the following particle: "
854 << theAntiLambda->print() << '\n');
855 theAntiLambda->setEmissionTime(theStore->getBook().getCurrentTime());
856 // Correction for real masses
857 const G4double theQValueCorrection = theAntiLambda->getEmissionQValueCorrection(theA,theZ,theS); // Does it work for strange particles? Should be check
858 const G4double kineticEnergyOutside = theAntiLambda->getKineticEnergy() - theAntiLambda->getPotentialEnergy() + theQValueCorrection;
859 theAntiLambda->setTableMass();
860 if(kineticEnergyOutside > 0.0)
861 theAntiLambda->setEnergy(theAntiLambda->getMass()+kineticEnergyOutside);
862 else
863 theAntiLambda->setEnergy(theAntiLambda->getMass()+tinyEnergy);
864 theAntiLambda->adjustMomentumFromEnergy();
865 theAntiLambda->setPotentialEnergy(0.);
866 theA -= theAntiLambda->getA();
867 theS -= theAntiLambda->getS();
868 toEject.push_back(theAntiLambda);
869 }
870 }
871 for(ParticleIter i=toEject.begin(), e=toEject.end(); i!=e; ++i) {
872 theStore->particleHasBeenEjected(*i);
873 theStore->addToOutgoing(*i);
874 (*i)->setParticleBias(Particle::getTotalBias());
875 }
876 return (G4int)toEject.size();
877 }
878
880 /* Forcing emissions of all Kaon (not antiKaons) in the nucleus.
881 * This probably violates energy conservation
882 * (although the computation of the recoil kinematics
883 * might sweep this under the carpet).
884 */
885 INCL_DEBUG("Forcing emissions of all Kaon in the nucleus." << '\n');
886
887 // Emit the Kaon with this kinetic energy (not supposed to append
888 const G4double tinyEnergy = 0.1; // MeV
889
890 // Push out the emitted kaon
891 ParticleList const &inside = theStore->getParticles();
892 ParticleList toEject;
893 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i) {
894 if((*i)->isKaon()) {
895 Particle * const theKaon = *i;
896 INCL_DEBUG("Forcing emission of the following particle: "
897 << theKaon->print() << '\n');
898 theKaon->setEmissionTime(theStore->getBook().getCurrentTime());
899 // Correction for real masses
900 const G4double theQValueCorrection = theKaon->getEmissionQValueCorrection(theA,theZ,theS);
901 const G4double kineticEnergyOutside = theKaon->getKineticEnergy() - theKaon->getPotentialEnergy() + theQValueCorrection;
902 theKaon->setTableMass();
903 if(kineticEnergyOutside > 0.0)
904 theKaon->setEnergy(theKaon->getMass()+kineticEnergyOutside);
905 else
906 theKaon->setEnergy(theKaon->getMass()+tinyEnergy);
907 theKaon->adjustMomentumFromEnergy();
908 theKaon->setPotentialEnergy(0.);
909 theZ -= theKaon->getZ();
910 theS -= theKaon->getS();
911 toEject.push_back(theKaon);
912 }
913 }
914 for(ParticleIter i=toEject.begin(), e=toEject.end(); i!=e; ++i) {
915 theStore->particleHasBeenEjected(*i);
916 theStore->addToOutgoing(*i);
917 (*i)->setParticleBias(Particle::getTotalBias());
918 }
919 theNKaon -= 1;
920 return toEject.size() != 0;
921 }
922
924 /* Forcing annihilation of all Antinucleons in the nucleus and emission of the resulting particles.
925 */
926 INCL_DEBUG("Forcing annihilation of all Antinucleons and emission of all produced mesons in the nucleus." << '\n' );
927 const G4double tinyEnergy = 0.1; // MeV
928
929 ParticleList const &inside = theStore->getParticles();
930 ParticleList antinucleons;
931 ParticleList toEject; // mesons from antinucleon annihilations to be ejected
932 G4double theNewZ=theZ;
933
934 // Build a list of remaining antinucleons
935 for(ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i)
936 if((*i)->isAntiNucleon()) antinucleons.push_back((*i));
937
938 // Loop over the antinucleons, build a list of mesons to be ejected
939 for(ParticleIter i=antinucleons.begin(), e=antinucleons.end(); i!=e; ++i) {
940 Particle * theAnnihilated = nullptr;
941 G4double dist_NbarNuc = 1000.; //just a high random beginning
942 G4double temp_dist = 0.;
943 // Nucleon annihilated
944 for (ParticleIter pnuc=inside.begin(), enuc=inside.end(); pnuc!=enuc;++pnuc){
945 if ((*pnuc)->isNucleon()){
946 temp_dist = ((*pnuc)->getPosition() - (*i)->getPosition()).mag(); // calculate distance between the antinucleon and nucleons in the nucleus
947 if(temp_dist < dist_NbarNuc){ //obtain information of the last nucleon that was close enough
948 dist_NbarNuc = temp_dist;
949 theAnnihilated = (*pnuc);
950 }
951 }
952 }
953 // Annihilation (meson production)
954 INCL_DEBUG("Forcing collision of the following particle :" <<'\n' << (*i)->print() << '\n' << theAnnihilated->print() << '\n' );
955 theNewZ = theNewZ - (theAnnihilated->getZ() + ((*i)->getZ()));
956 BinaryCollisionAvatar *collision = new BinaryCollisionAvatar(0.,9999.,this,theAnnihilated,(*i)); //Binary Collision Avatar to annihilate; XS=9999. means force annihilation
957 FinalState *fs = collision->getFinalState();
958 applyFinalState(fs);
959 INCL_DEBUG("Forcing Emission of the resulting particle of the forced annihilation" << '\n');
960 ParticleList modifiedparts = fs->getModifiedParticles();
961 for(ParticleIter outs=modifiedparts.begin(), eouts=modifiedparts.end();outs!=eouts;outs++){
962 toEject.push_back((*outs));
963 }
964 ParticleList const &created = fs->getCreatedParticles();
965 if(created.size() !=0){
966 for(ParticleIter out=created.begin(),eout=created.end();out!=eout;out++){
967 toEject.push_back((*out));
968 }
969 }
970 delete fs;
971 delete collision;
972 }
973
974 // Loop over the mesons to be ejected
975 for(ParticleIter iEject=toEject.begin(),eEject=toEject.end();iEject!=eEject;iEject++){ //Eject all produced mesons
976 (*iEject)->setEmissionTime(theStore->getBook().getCurrentTime());
977 G4double theQValueCorrection = (*iEject)->getEmissionQValueCorrection(theA,theZ,theS);
978 G4double kineticEnergyOutside = (*iEject)->getKineticEnergy() - (*iEject)->getPotentialEnergy() + theQValueCorrection;
979 (*iEject)->setTableMass();
980 if(kineticEnergyOutside > 0.0)
981 (*iEject)->setEnergy((*iEject)->getMass() + kineticEnergyOutside);
982 else
983 (*iEject)->setEnergy((*iEject)->getMass() + tinyEnergy);
984 (*iEject)->adjustMomentumFromEnergy();
985 (*iEject)->setPotentialEnergy(0.);
986 theStore->particleHasBeenEjected(*iEject);
987 theStore->addToOutgoing(*iEject);
988 }
989
990 theZ = theNewZ;
991 return true;
992 }
993
995
996 Book const &theBook = theStore->getBook();
997 const G4int nEventCollisions = theBook.getAcceptedCollisions();
998 const G4int nEventDecays = theBook.getAcceptedDecays();
999 const G4int nEventClusters = theBook.getEmittedClusters();
1000 if(nEventCollisions==0 && nEventDecays==0 && nEventClusters==0)
1001 return true;
1002
1003 return false;
1004
1005 }
1006
1007 void Nucleus::computeOneNucleonRecoilKinematics() {
1008 // We should be here only if the nucleus contains only one nucleon
1009// assert(theStore->getParticles().size()==1);
1010
1011 // No excitation energy!
1012 theExcitationEnergy = 0.0;
1013
1014 // Move the nucleon to the outgoing list
1015 Particle *remN = theStore->getParticles().front();
1016 theA -= remN->getA();
1017 theZ -= remN->getZ();
1018 theS -= remN->getS();
1019 theStore->particleHasBeenEjected(remN);
1020 theStore->addToOutgoing(remN);
1021 remN->setEmissionTime(theStore->getBook().getCurrentTime());
1022
1023 // Treat the special case of a remaining delta
1024 if(remN->isDelta()) {
1025 IAvatar *decay = new DecayAvatar(remN, 0.0, NULL);
1026 FinalState *fs = decay->getFinalState();
1027 // Eject the pion
1028 ParticleList const &created = fs->getCreatedParticles();
1029 for(ParticleIter j=created.begin(), e=created.end(); j!=e; ++j)
1030 theStore->addToOutgoing(*j);
1031 delete fs;
1032 delete decay;
1033 }
1034
1035 // Do different things depending on how many outgoing particles we have
1036 ParticleList const &outgoing = theStore->getOutgoingParticles();
1037 if(outgoing.size() == 2) {
1038
1039 INCL_DEBUG("Two particles in the outgoing channel, applying exact two-body kinematics" << '\n');
1040
1041 // Can apply exact 2-body kinematics here. Keep the CM emission angle of
1042 // the first particle.
1043 Particle *p1 = outgoing.front(), *p2 = outgoing.back();
1044 const ThreeVector aBoostVector = incomingMomentum / initialEnergy;
1045 // Boost to the initial CM
1046 p1->boost(aBoostVector);
1047 const G4double sqrts = std::sqrt(initialEnergy*initialEnergy - incomingMomentum.mag2());
1048 const G4double pcm = KinematicsUtils::momentumInCM(sqrts, p1->getMass(), p2->getMass());
1049 const G4double scale = pcm/(p1->getMomentum().mag());
1050 // Reset the momenta
1051 p1->setMomentum(p1->getMomentum()*scale);
1052 p2->setMomentum(-p1->getMomentum());
1053 p1->adjustEnergyFromMomentum();
1054 p2->adjustEnergyFromMomentum();
1055 // Unboost
1056 p1->boost(-aBoostVector);
1057 p2->boost(-aBoostVector);
1058
1059 } else {
1060
1061 INCL_DEBUG("Trying to adjust final-state momenta to achieve energy and momentum conservation" << '\n');
1062
1063 const G4int maxIterations=8;
1064 G4double totalEnergy, energyScale;
1065 G4double val=1.E+100, oldVal=1.E+100, oldOldVal=1.E+100, oldOldOldVal;
1066 ThreeVector totalMomentum, deltaP;
1067 std::vector<ThreeVector> minMomenta; // use it to store the particle momenta that minimize the merit function
1068
1069 // Reserve the vector size
1070 minMomenta.reserve(outgoing.size());
1071
1072 // Compute the initial total momentum
1073 totalMomentum.setX(0.0);
1074 totalMomentum.setY(0.0);
1075 totalMomentum.setZ(0.0);
1076 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
1077 totalMomentum += (*i)->getMomentum();
1078
1079 // Compute the initial total energy
1080 totalEnergy = 0.0;
1081 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
1082 totalEnergy += (*i)->getEnergy();
1083
1084 // Iterative algorithm starts here:
1085 for(G4int iterations=0; iterations < maxIterations; ++iterations) {
1086
1087 // Save the old merit-function values
1088 oldOldOldVal = oldOldVal;
1089 oldOldVal = oldVal;
1090 oldVal = val;
1091
1092 if(iterations%2 == 0) {
1093 INCL_DEBUG("Momentum step" << '\n');
1094 // Momentum step: modify all the particle momenta
1095 deltaP = incomingMomentum - totalMomentum;
1096 G4double pOldTot = 0.0;
1097 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
1098 pOldTot += (*i)->getMomentum().mag();
1099 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i) {
1100 const ThreeVector mom = (*i)->getMomentum();
1101 (*i)->setMomentum(mom + deltaP*mom.mag()/pOldTot);
1102 (*i)->adjustEnergyFromMomentum();
1103 }
1104 } else {
1105 INCL_DEBUG("Energy step" << '\n');
1106 // Energy step: modify all the particle momenta
1107 energyScale = initialEnergy/totalEnergy;
1108 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i) {
1109 const ThreeVector mom = (*i)->getMomentum();
1110 G4double pScale = ((*i)->getEnergy()*energyScale - std::pow((*i)->getMass(),2))/mom.mag2();
1111 if(pScale>0) {
1112 (*i)->setEnergy((*i)->getEnergy()*energyScale);
1113 (*i)->adjustMomentumFromEnergy();
1114 }
1115 }
1116 }
1117
1118 // Compute the current total momentum and energy
1119 totalMomentum.setX(0.0);
1120 totalMomentum.setY(0.0);
1121 totalMomentum.setZ(0.0);
1122 totalEnergy = 0.0;
1123 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i) {
1124 totalMomentum += (*i)->getMomentum();
1125 totalEnergy += (*i)->getEnergy();
1126 }
1127
1128 // Merit factor
1129 val = std::pow(totalEnergy - initialEnergy,2) +
1130 0.25*(totalMomentum - incomingMomentum).mag2();
1131 INCL_DEBUG("Merit function: val=" << val << ", oldVal=" << oldVal << ", oldOldVal=" << oldOldVal << ", oldOldOldVal=" << oldOldOldVal << '\n');
1132
1133 // Store the minimum
1134 if(val < oldVal) {
1135 INCL_DEBUG("New minimum found, storing the particle momenta" << '\n');
1136 minMomenta.clear();
1137 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
1138 minMomenta.push_back((*i)->getMomentum());
1139 }
1140
1141 // Stop the algorithm if the search diverges
1142 if(val > oldOldVal && oldVal > oldOldOldVal) {
1143 INCL_DEBUG("Search is diverging, breaking out of the iteration loop: val=" << val << ", oldVal=" << oldVal << ", oldOldVal=" << oldOldVal << ", oldOldOldVal=" << oldOldOldVal << '\n');
1144 break;
1145 }
1146 }
1147
1148 // We should have made at least one successful iteration here
1149// assert(minMomenta.size()==outgoing.size());
1150
1151 // Apply the optimal momenta
1152 INCL_DEBUG("Applying the solution" << '\n');
1153 std::vector<ThreeVector>::const_iterator v = minMomenta.begin();
1154 for(ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i, ++v) {
1155 (*i)->setMomentum(*v);
1156 (*i)->adjustEnergyFromMomentum();
1157 INCL_DATABLOCK((*i)->print());
1158 }
1159
1160 }
1161
1162 }
1163
1165 eventInfo->nParticles = 0;
1166 G4bool isNucleonAbsorption = false;
1167 G4bool isPionAbsorption = false;
1168 // It is possible to have pion absorption event only if the
1169 // projectile is pion.
1170 if(eventInfo->projectileType == PiPlus ||
1171 eventInfo->projectileType == PiMinus ||
1172 eventInfo->projectileType == PiZero) {
1173 isPionAbsorption = true;
1174 }
1175
1176 // Forced CN
1177 eventInfo->forcedCompoundNucleus = tryCN;
1178
1179 // Outgoing particles
1180 ParticleList const &outgoingParticles = getStore()->getOutgoingParticles();
1181
1182 // Check if we have a nucleon absorption event: nucleon projectile
1183 // and no ejected particles.
1184 if(outgoingParticles.size() == 0 &&
1185 (eventInfo->projectileType == Proton ||
1186 eventInfo->projectileType == Neutron)) {
1187 isNucleonAbsorption = true;
1188 }
1189
1190 // Reset the remnant counter
1191 eventInfo->nRemnants = 0;
1192 eventInfo->history.clear();
1193
1194 for(ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i ) {
1195 // We have a pion absorption event only if the projectile is
1196 // pion and there are no ejected pions.
1197 if(isPionAbsorption) {
1198 if((*i)->isPion()) {
1199 isPionAbsorption = false;
1200 }
1201 }
1202
1203 eventInfo->ParticleBias[eventInfo->nParticles] = (*i)->getParticleBias();
1204
1205#ifdef INCLXX_IN_GEANT4_MODE
1206 eventInfo->A[eventInfo->nParticles] = (G4INCL::Short_t)(*i)->getA();
1207 eventInfo->Z[eventInfo->nParticles] = (G4INCL::Short_t)(*i)->getZ();
1208 eventInfo->S[eventInfo->nParticles] = (G4INCL::Short_t)(*i)->getS();
1209#else
1210 eventInfo->A[eventInfo->nParticles] = (Short_t)(*i)->getA();
1211 eventInfo->Z[eventInfo->nParticles] = (Short_t)(*i)->getZ();
1212 eventInfo->S[eventInfo->nParticles] = (Short_t)(*i)->getS();
1213#endif
1214 eventInfo->emissionTime[eventInfo->nParticles] = (*i)->getEmissionTime();
1215 eventInfo->EKin[eventInfo->nParticles] = (*i)->getKineticEnergy();
1216 ThreeVector mom = (*i)->getMomentum();
1217 eventInfo->px[eventInfo->nParticles] = mom.getX();
1218 eventInfo->py[eventInfo->nParticles] = mom.getY();
1219 eventInfo->pz[eventInfo->nParticles] = mom.getZ();
1220 eventInfo->theta[eventInfo->nParticles] = Math::toDegrees(mom.theta());
1221 eventInfo->phi[eventInfo->nParticles] = Math::toDegrees(mom.phi());
1222 eventInfo->origin[eventInfo->nParticles] = -1;
1223#ifdef INCLXX_IN_GEANT4_MODE
1224 eventInfo->parentResonancePDGCode[eventInfo->nParticles] = (*i)->getParentResonancePDGCode();
1225 eventInfo->parentResonanceID[eventInfo->nParticles] = (*i)->getParentResonanceID();
1226#endif
1227 eventInfo->history.push_back("");
1228 if ((*i)->getType() != Composite && (*i)->getType() != antiComposite ) {
1229 ParticleSpecies pt((*i)->getType());
1230 eventInfo->PDGCode[eventInfo->nParticles] = pt.getPDGCode();
1231 }
1232 else if((*i)->getType() == Composite) {
1233 ParticleSpecies pt((*i)->getA(), (*i)->getZ(), (*i)->getS());
1234 eventInfo->PDGCode[eventInfo->nParticles] = pt.getPDGCode();
1235 }
1236 else if((*i)->getType() == antiComposite) {
1237 ParticleSpecies pt(-(*i)->getA(), -(*i)->getZ(), (*i)->getS());
1238 eventInfo->PDGCode[eventInfo->nParticles] = pt.getPDGCode();
1239 }
1240 eventInfo->nParticles++;
1241 }
1242 eventInfo->nucleonAbsorption = isNucleonAbsorption;
1243 eventInfo->pionAbsorption = isPionAbsorption;
1244 eventInfo->nCascadeParticles = eventInfo->nParticles;
1245
1246 // Projectile-like remnant characteristics
1247 if(theProjectileRemnant && (theProjectileRemnant->getA()>0 || theProjectileRemnant->getA()<0)) {
1248#ifdef INCLXX_IN_GEANT4_MODE
1249 eventInfo->ARem[eventInfo->nRemnants] = (G4INCL::Short_t)theProjectileRemnant->getA();
1250 eventInfo->ZRem[eventInfo->nRemnants] = (G4INCL::Short_t)theProjectileRemnant->getZ();
1251 eventInfo->SRem[eventInfo->nRemnants] = (G4INCL::Short_t)theProjectileRemnant->getS();
1252#else
1253 eventInfo->ARem[eventInfo->nRemnants] = (Short_t)theProjectileRemnant->getA();
1254 eventInfo->ZRem[eventInfo->nRemnants] = (Short_t)theProjectileRemnant->getZ();
1255 eventInfo->SRem[eventInfo->nRemnants] = (Short_t)theProjectileRemnant->getS();
1256#endif
1257 G4double eStar = theProjectileRemnant->getExcitationEnergy();
1258 if(std::abs(eStar)<1E-10)
1259 eStar = 0.0; // blame rounding and set the excitation energy to zero
1260 eventInfo->EStarRem[eventInfo->nRemnants] = eStar;
1261 if(eventInfo->EStarRem[eventInfo->nRemnants]<0.) {
1262 INCL_WARN("Negative excitation energy in projectile-like remnant! EStarRem = " << eventInfo->EStarRem[eventInfo->nRemnants] << '\n');
1263 }
1264 const ThreeVector &spin = theProjectileRemnant->getSpin();
1265 if(eventInfo->ARem[eventInfo->nRemnants]%2==0) { // even-A nucleus
1266 eventInfo->JRem[eventInfo->nRemnants] = (G4int) (spin.mag()/PhysicalConstants::hc + 0.5);
1267 } else { // odd-A nucleus
1268 eventInfo->JRem[eventInfo->nRemnants] = ((G4int) (spin.mag()/PhysicalConstants::hc)) + 0.5;
1269 }
1270 eventInfo->EKinRem[eventInfo->nRemnants] = theProjectileRemnant->getKineticEnergy();
1271 const ThreeVector &mom = theProjectileRemnant->getMomentum();
1272 eventInfo->pxRem[eventInfo->nRemnants] = mom.getX();
1273 eventInfo->pyRem[eventInfo->nRemnants] = mom.getY();
1274 eventInfo->pzRem[eventInfo->nRemnants] = mom.getZ();
1275 eventInfo->jxRem[eventInfo->nRemnants] = spin.getX() / PhysicalConstants::hc;
1276 eventInfo->jyRem[eventInfo->nRemnants] = spin.getY() / PhysicalConstants::hc;
1277 eventInfo->jzRem[eventInfo->nRemnants] = spin.getZ() / PhysicalConstants::hc;
1278 eventInfo->thetaRem[eventInfo->nRemnants] = Math::toDegrees(mom.theta());
1279 eventInfo->phiRem[eventInfo->nRemnants] = Math::toDegrees(mom.phi());
1280 eventInfo->nRemnants++;
1281 }
1282
1283 // Target-like remnant characteristics
1284 if(hasRemnant()) {
1285#ifdef INCLXX_IN_GEANT4_MODE
1286 eventInfo->ARem[eventInfo->nRemnants] = (G4INCL::Short_t)getA();
1287 eventInfo->ZRem[eventInfo->nRemnants] = (G4INCL::Short_t)getZ();
1288 eventInfo->SRem[eventInfo->nRemnants] = (G4INCL::Short_t)getS();
1289#else
1290 eventInfo->ARem[eventInfo->nRemnants] = (Short_t)getA();
1291 eventInfo->ZRem[eventInfo->nRemnants] = (Short_t)getZ();
1292 eventInfo->SRem[eventInfo->nRemnants] = (Short_t)getS();
1293#endif
1294 eventInfo->EStarRem[eventInfo->nRemnants] = getExcitationEnergy();
1295 if(eventInfo->EStarRem[eventInfo->nRemnants]<0.) {
1296 INCL_WARN("Negative excitation energy in target-like remnant! EStarRem = " << eventInfo->EStarRem[eventInfo->nRemnants] << " eventNumber=" << eventInfo->eventNumber << '\n');
1297 }
1298 const ThreeVector &spin = getSpin();
1299 if(eventInfo->ARem[eventInfo->nRemnants]%2==0) { // even-A nucleus
1300 eventInfo->JRem[eventInfo->nRemnants] = (G4int) (spin.mag()/PhysicalConstants::hc + 0.5);
1301 } else { // odd-A nucleus
1302 eventInfo->JRem[eventInfo->nRemnants] = ((G4int) (spin.mag()/PhysicalConstants::hc)) + 0.5;
1303 }
1304 eventInfo->EKinRem[eventInfo->nRemnants] = getKineticEnergy();
1305 const ThreeVector &mom = getMomentum();
1306 eventInfo->pxRem[eventInfo->nRemnants] = mom.getX();
1307 eventInfo->pyRem[eventInfo->nRemnants] = mom.getY();
1308 eventInfo->pzRem[eventInfo->nRemnants] = mom.getZ();
1309 eventInfo->jxRem[eventInfo->nRemnants] = spin.getX() / PhysicalConstants::hc;
1310 eventInfo->jyRem[eventInfo->nRemnants] = spin.getY() / PhysicalConstants::hc;
1311 eventInfo->jzRem[eventInfo->nRemnants] = spin.getZ() / PhysicalConstants::hc;
1312 eventInfo->thetaRem[eventInfo->nRemnants] = Math::toDegrees(mom.theta());
1313 eventInfo->phiRem[eventInfo->nRemnants] = Math::toDegrees(mom.phi());
1314 eventInfo->nRemnants++;
1315 }
1316
1317 // Global counters, flags, etc.
1318 Book const &theBook = theStore->getBook();
1319 eventInfo->nCollisions = theBook.getAcceptedCollisions();
1320 eventInfo->nBlockedCollisions = theBook.getBlockedCollisions();
1321 eventInfo->nDecays = theBook.getAcceptedDecays();
1322 eventInfo->nBlockedDecays = theBook.getBlockedDecays();
1323 eventInfo->firstCollisionTime = theBook.getFirstCollisionTime();
1324 eventInfo->firstCollisionXSec = theBook.getFirstCollisionXSec();
1328 eventInfo->nReflectionAvatars = theBook.getAvatars(SurfaceAvatarType);
1329 eventInfo->nCollisionAvatars = theBook.getAvatars(CollisionAvatarType);
1330 eventInfo->nDecayAvatars = theBook.getAvatars(DecayAvatarType);
1332 eventInfo->nSrcPairs = theBook.getSrcPairs();
1333 eventInfo->nSrcCollisions = theBook.getAcceptedSrcCollisions();
1334 }
1335
1336
1337
1339 ConservationBalance theBalance;
1340 // Initialise balance variables with the incoming values
1341 INCL_DEBUG("theEventInfo " << theEventInfo.Zt << " " << theEventInfo.At << '\n');
1342 theBalance.Z = theEventInfo.Zp + theEventInfo.Zt;
1343 theBalance.A = theEventInfo.Ap + theEventInfo.At;
1344 theBalance.S = theEventInfo.Sp + theEventInfo.St;
1345 INCL_DEBUG("theBalance Z and A " << theBalance.Z << " " << theBalance.A << '\n');
1346 theBalance.energy = getInitialEnergy() + getSrcInternalEnergy();
1347 theBalance.momentum = getIncomingMomentum();
1348
1349 // Process outgoing particles
1350 ParticleList const &outgoingParticles = theStore->getOutgoingParticles();
1351 for(ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i ) {
1352 theBalance.Z -= (*i)->getZ();
1353 theBalance.A -= (*i)->getA();
1354 theBalance.S -= (*i)->getS();
1355 // For outgoing clusters, the total energy automatically includes the
1356 // excitation energy
1357 theBalance.energy -= (*i)->getEnergy(); // Note that outgoing particles should have the real mass
1358 theBalance.momentum -= (*i)->getMomentum();
1359 }
1360
1361 // Projectile-like remnant contribution, if present
1362 if(theProjectileRemnant && (theProjectileRemnant->getA()>0 || theProjectileRemnant->getA()<0)) {
1363 theBalance.Z -= theProjectileRemnant->getZ();
1364 theBalance.A -= theProjectileRemnant->getA();
1365 theBalance.S -= theProjectileRemnant->getS();
1366 if(theProjectileRemnant->getA()>0)
1367 theBalance.energy -= ParticleTable::getTableMass(theProjectileRemnant->getA(),theProjectileRemnant->getZ(),theProjectileRemnant->getS()) + theProjectileRemnant->getExcitationEnergy();
1368 else if(theProjectileRemnant->getA()<0)
1369 theBalance.energy -= ParticleTable::getTableMass(-(theProjectileRemnant->getA()),-(theProjectileRemnant->getZ()),theProjectileRemnant->getS()) + theProjectileRemnant->getExcitationEnergy();
1370 theBalance.energy -= theProjectileRemnant->getKineticEnergy();
1371 theBalance.momentum -= theProjectileRemnant->getMomentum();
1372 }
1373
1374 //Missed particle contribution, for anticomposite model B
1375 ParticleList const & missedParticles = theStore->getMissedParticles();
1376 for(ParticleIter i=missedParticles.begin(), e=missedParticles.end(); i!=e;++i){
1377 theBalance.Z -= (*i)->getZ();
1378 theBalance.A -= (*i)->getA();
1379 theBalance.S -= (*i)->getS();
1380 theBalance.energy -= (*i)->getEnergy();
1381 //theBalance.momentum -= (*i)->getMomentum();
1382 }
1383
1384 // Target-like remnant contribution, if present
1385 if(hasRemnant()) {
1386 theBalance.Z -= getZ();
1387 theBalance.A -= getA();
1388 theBalance.S -= getS();
1389 theBalance.energy -= ParticleTable::getTableMass(getA(),getZ(),getS()) +
1391 if(afterRecoil)
1392 theBalance.energy -= getKineticEnergy();
1393 theBalance.momentum -= getMomentum();
1394
1395 Book const &theBook = theStore->getBook();
1396
1397 if (getExcitationEnergy() < 0. && theBook.getAcceptedSrcCollisions()) {
1398 INCL_DEBUG("excitation energy negative and afterrecoil "
1399 << afterRecoil << " " << getExcitationEnergy()
1400 << " eventNumber=" << theEventInfo.eventNumber << " "
1401 << getInitialInternalEnergy() << '\n');
1402 INCL_DEBUG("excitation energy negative and afterrecoil "
1404 << " " << initialEnergy << '\n');
1405 }
1406
1407 if (theBook.getAcceptedSrcCollisions() && !afterRecoil) {
1408 INCL_DEBUG("excitation energy " << getExcitationEnergy()
1409 << " and afterrecoil 1 , kinetic energy ="
1410 << getKineticEnergy() << ", eventNumber="
1411 << theEventInfo.eventNumber << '\n');
1412 }
1413 }
1414
1415 return theBalance;
1416 }
1417
1419 setEnergy(initialEnergy);
1420 setMomentum(incomingMomentum);
1421 setSpin(incomingAngularMomentum);
1424 }
1425
1427 // Deal with the projectile remnant
1428 const G4int prA = theProjectileRemnant->getA();
1429 if(prA>=1 || prA<=-1) {
1430 // Set the mass
1431 const G4double aMass = theProjectileRemnant->getInvariantMass();
1432 theProjectileRemnant->setMass(aMass);
1433
1434 // Compute the excitation energy from the invariant
1435 G4double anExcitationEnergy;
1436 if(prA>=1)
1437 anExcitationEnergy = aMass - ParticleTable::getTableMass(prA, theProjectileRemnant->getZ(), theProjectileRemnant->getS());
1438 else
1439 anExcitationEnergy = aMass - ParticleTable::getTableMass(-prA, -(theProjectileRemnant->getZ()), theProjectileRemnant->getS());
1440
1441 // Set the excitation energy
1442 theProjectileRemnant->setExcitationEnergy(anExcitationEnergy);
1443
1444 // No spin!
1445 theProjectileRemnant->setSpin(ThreeVector());
1446
1447 // Set the emission time
1448 theProjectileRemnant->setEmissionTime(anEmissionTime);
1449 }
1450 }
1451
1452}
1453
1454#endif
Static class for carrying out cluster decays.
Simple class implementing De Jong's spin model for nucleus-nucleus collisions.
#define INCL_ERROR(x)
#define INCL_WARN(x)
#define INCL_DATABLOCK(x)
#define INCL_DEBUG(x)
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4int getAcceptedDecays() const
G4int getSrcPairs() const
G4double getFirstCollisionXSec() const
Definition G4INCLBook.hh:90
G4double getFirstCollisionTime() const
Definition G4INCLBook.hh:87
G4int getAvatars(AvatarType type) const
G4double getFirstCollisionSpectatorMomentum() const
Definition G4INCLBook.hh:96
G4double getCurrentTime() const
G4int getAcceptedCollisions() const
G4double getFirstCollisionSpectatorPosition() const
Definition G4INCLBook.hh:93
G4int getBlockedCollisions() const
G4int getAcceptedSrcCollisions() const
G4bool getFirstCollisionIsElastic() const
Definition G4INCLBook.hh:99
G4int getEnergyViolationInteraction() const
G4int getBlockedDecays() const
G4int getEmittedClusters() const
ThreeVector const & getSpin() const
Get the spin of the nucleus.
ParticleList particles
ParticleList const & getParticles() const
void setSpin(const ThreeVector &j)
Set the spin of the nucleus.
virtual void initializeParticles()
Initialise the NuclearDensity pointer and sample the particles.
ParticleSampler * theParticleSampler
Cluster(const G4int Z, const G4int A, const G4int S, const G4bool createParticleSampler=true)
Standard Cluster constructor.
ThreeVector theSpin
virtual G4double getTableMass() const
Get the real particle mass.
G4double theExcitationEnergy
G4bool getPionPotential() const
Do we want the pion potential?
PotentialType getPotentialType() const
Get the type of the potential for nucleons.
ParticleList const & getOutgoingParticles() const
ParticleList const & getEnteringParticles() const
std::string print() const
ParticleList const & getModifiedParticles() const
FinalStateValidity getValidity() const
ParticleList const & getDestroyedParticles() const
G4double getTotalEnergyBeforeInteraction() const
ParticleList const & getCreatedParticles() const
FinalState * getFinalState()
G4int emitInsideAntilambda()
Force emission of all Antilambda.
G4bool decayOutgoingNeutralKaon()
Force the transformation of outgoing Neutral Kaon into propation eigenstate.
G4double computeSeparationEnergyBalance() const
Outgoing - incoming separation energies.
Store * getStore() const
void fillEventInfo(EventInfo *eventInfo)
G4bool decayMe()
Force the phase-space decay of the Nucleus.
G4double computeTotalEnergy() const
Compute the current total energy.
G4bool decayInsideDeltas()
Force the decay of deltas inside the nucleus.
void computeRecoilKinematics()
Compute the recoil momentum and spin of the nucleus.
void finalizeProjectileRemnant(const G4double emissionTime)
Finalise the projectile remnant.
G4bool emitInsideKaon()
Force emission of all Kaon inside the nucleus.
G4bool isEventTransparent() const
Is the event transparent?
void applyFinalState(FinalState *)
void setAType(AnnihilationType type)
void insertParticle(Particle *p)
Insert a new particle (e.g. a projectile) in the nucleus.
G4double getSrcInternalEnergy() const
Nucleus(G4int mass, G4int charge, G4int strangess, Config const *const conf, const G4double universeRadius=-1., AnnihilationType AType=Def)
void emitInsideStrangeParticles()
Force emission of all strange particles inside the nucleus.
void deleteProjectileRemnant()
Delete the projectile remnant.
std::string print()
G4bool decayOutgoingPionResonances(G4double timeThreshold)
Force the decay of outgoing PionResonances (eta/omega).
G4bool emitInsideAnnihilationProducts()
Force emission of all Antinucleon inside the nucleus.
void useFusionKinematics()
Adjust the kinematics for complete-fusion events.
AnnihilationType getAType() const
G4double getInitialInternalEnergy() const
const ThreeVector & getIncomingMomentum() const
Get the incoming momentum vector.
void emitInsidePions()
Force emission of all pions inside the nucleus.
G4double getInitialEnergy() const
Get the initial energy.
void restoreSrcPartner(Particle *particle, ThreeVector m)
ThreeVector computeCenterOfMass() const
Compute the current center-of-mass position.
G4bool decayOutgoingClusters()
Force the decay of unstable outgoing clusters.
G4double getExcitationEnergy() const
Get the excitation energy of the nucleus.
G4int emitInsideLambda()
Force emission of all Lambda (desexitation code with strangeness not implanted yet).
void propagateParticles(G4double step)
G4bool decayInsideStrangeParticles()
Force the transformation of strange particles into a Lambda;.
ConservationBalance getConservationBalance(EventInfo const &theEventInfo, const G4bool afterRecoil) const
Compute charge, mass, energy and momentum balance.
G4bool hasRemnant() const
Does the nucleus give a cascade remnant?
void updatePotentialEnergy(Particle *p) const
Update the particle potential energy.
G4double computeExcitationEnergy() const
Compute the current excitation energy.
G4bool decayOutgoingDeltas()
Force the decay of outgoing deltas.
G4bool decayOutgoingSigmaZero(G4double timeThreshold)
Force the decay of outgoing Neutral Sigma.
G4int getPDGCode() const
Set a PDG Code (MONTE CARLO PARTICLE NUMBERING).
void setPotentialEnergy(G4double v)
Set the particle potential energy.
G4int getS() const
Returns the strangeness number.
G4double getEmissionQValueCorrection(const G4int AParent, const G4int ZParent) const
Computes correction on the emission Q-value.
G4INCL::ThreeVector theMomentum
void setBiasCollisionVector(std::vector< G4int > BiasCollisionVector)
Set the vector list of biased vertices on the particle path.
G4double getPotentialEnergy() const
Get the particle potential energy.
void setMass(G4double mass)
G4int getZ() const
Returns the charge number.
G4double getKineticEnergy() const
Get the particle kinetic energy.
G4int theNKaon
The number of Kaons inside the nucleus (update during the cascade).
std::vector< G4int > getBiasCollisionVector() const
Get the vector list of biased vertices on the particle path.
void setEmissionTime(G4double t)
G4double adjustEnergyFromMomentum()
Recompute the energy to match the momentum.
static G4double getTotalBias()
General bias vector function.
const ThreeVector & adjustMomentumFromEnergy()
Rescale the momentum to match the total energy.
const G4INCL::ThreeVector & getMomentum() const
virtual void setMomentum(const G4INCL::ThreeVector &momentum)
virtual G4double getTableMass() const
Get the tabulated particle mass.
void setEnergy(G4double energy)
std::string print() const
G4double getMass() const
Get the cached particle mass.
void boost(const ThreeVector &aBoostVector)
void setTableMass()
Set the mass of the Particle to its table mass.
G4bool isDelta() const
Is it a Delta?
G4int getA() const
Returns the baryon number.
G4INCL::ThreeVector thePosition
ParticleList const & getOutgoingParticles() const
void addToOutgoing(Particle *p)
add the particle to the outgoing particle list.
Book & getBook()
void particleHasBeenEjected(Particle *const)
ParticleList const & getParticles() const
G4double theta() const
G4double getY() const
G4double getZ() const
G4double mag2() const
G4double getX() const
ParticleList decay(Cluster *const c)
Carries out a cluster decay.
G4double momentumInCM(Particle const *const p1, Particle const *const p2)
gives the momentum in the CM frame of two particles.
G4double toDegrees(G4double radians)
NuclearDensity const * createDensity(const G4int A, const G4int Z, const G4int S)
INuclearPotential const * createPotential(const PotentialType type, const G4int theA, const G4int theZ, const G4bool pionPotential)
Create an INuclearPotential object.
G4ThreadLocal NuclearMassFn getTableMass
Static pointer to the mass function for nuclei.
G4double getRealMass(const G4INCL::ParticleType t)
Get particle mass (in MeV/c^2).
void setNeutronSeparationEnergy(const G4double s)
Setter for protonSeparationEnergy.
const G4double effectiveNucleonMass
void setProtonSeparationEnergy(const G4double s)
Setter for protonSeparationEnergy.
G4double getWidth(const ParticleType t)
Get particle width (in s).
const G4double hc
[MeV*fm]
G4double shoot()
ParticleList::const_iterator ParticleIter
short Short_t
@ SurfaceAvatarType
@ CollisionAvatarType
@ DecayAvatarType
@ DNbarNPbarNType
@ DNbarNPbarPType
@ DNbarPPbarPType
@ DNbarPPbarNType
Bool_t pionAbsorption
True if the event is a pion absorption.
Short_t S[maxSizeParticles]
Particle strangeness number.
Int_t nCollisionAvatars
Number of collision avatars.
Short_t origin[maxSizeParticles]
Origin of the particle.
Short_t At
Mass number of the target nucleus.
Short_t Zp
Charge number of the projectile nucleus.
Int_t parentResonancePDGCode[maxSizeParticles]
Particle's parent resonance PDG code.
Int_t nDecays
Number of accepted Delta decays.
Int_t projectileType
Projectile particle type.
Short_t nCascadeParticles
Number of cascade particles.
Short_t nRemnants
Number of remnants.
Float_t theta[maxSizeParticles]
Particle momentum polar angle [radians].
Short_t A[maxSizeParticles]
Particle mass number.
Float_t EKinRem[maxSizeRemnants]
Remnant kinetic energy [MeV].
Float_t firstCollisionSpectatorMomentum
Momentum of the spectator on the first collision (fm).
Int_t parentResonanceID[maxSizeParticles]
Particle's parent resonance unique ID identifier.
Float_t jzRem[maxSizeRemnants]
Remnant angular momentum, z component [ ].
Bool_t nucleonAbsorption
True if the event is a nucleon absorption.
Float_t emissionTime[maxSizeParticles]
Emission time [fm/c].
Float_t EStarRem[maxSizeRemnants]
Remnant excitation energy [MeV].
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...
Float_t phi[maxSizeParticles]
Particle momentum azimuthal angle [radians].
Int_t nSrcPairs
Number of src pairs.
Short_t Ap
Mass number of the projectile nucleus.
Int_t nReflectionAvatars
Number of reflection avatars.
Int_t nSrcCollisions
Number of accepted SRC collisions.
Float_t firstCollisionSpectatorPosition
Position of the spectator on the first collision (fm).
Short_t Z[maxSizeParticles]
Particle charge number.
Bool_t forcedCompoundNucleus
True if the event is a forced CN.
Float_t JRem[maxSizeRemnants]
Remnant spin [ ].
Float_t thetaRem[maxSizeRemnants]
Remnant momentum polar angle [radians].
std::vector< std::string > history
History of the particle.
Short_t Sp
Strangeness number of the projectile nucleus.
Float_t EKin[maxSizeParticles]
Particle kinetic energy [MeV].
Short_t nParticles
Number of particles in the final state.
Float_t jxRem[maxSizeRemnants]
Remnant angular momentum, x component [ ].
Int_t nBlockedDecays
Number of decays blocked by Pauli or CDPP.
Float_t px[maxSizeParticles]
Particle momentum, x component [MeV/c].
Float_t ParticleBias[maxSizeParticles]
Particle weight due to the bias.
Short_t SRem[maxSizeRemnants]
Remnant strangeness number.
Float_t pxRem[maxSizeRemnants]
Remnant momentum, x component [MeV/c].
Float_t pyRem[maxSizeRemnants]
Remnant momentum, y component [MeV/c].
Float_t firstCollisionTime
Time of the first collision [fm/c].
Short_t Zt
Charge number of the target nucleus.
Float_t phiRem[maxSizeRemnants]
Remnant momentum azimuthal angle [radians].
Float_t pzRem[maxSizeRemnants]
Remnant momentum, z component [MeV/c].
static G4ThreadLocal Int_t eventNumber
Number of the event.
Float_t pz[maxSizeParticles]
Particle momentum, z component [MeV/c].
Int_t nCollisions
Number of accepted two-body collisions.
Int_t PDGCode[maxSizeParticles]
PDG numbering of the particles.
Int_t nBlockedCollisions
Number of two-body collisions blocked by Pauli or CDPP.
Float_t jyRem[maxSizeRemnants]
Remnant angular momentum, y component [ ].
Float_t py[maxSizeParticles]
Particle momentum, y component [MeV/c].
Bool_t firstCollisionIsElastic
True if the first collision was elastic.
Short_t ARem[maxSizeRemnants]
Remnant mass number.
Short_t ZRem[maxSizeRemnants]
Remnant charge number.
Float_t firstCollisionXSec
Cross section of the first collision (mb).
Int_t nDecayAvatars
Number of decay avatars.
Struct for conservation laws.