Geant4.10
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4INCLInteractionAvatar.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 // Pekka Kaitaniemi, CEA and Helsinki Institute of Physics
28 // Davide Mancusi, CEA
29 // Alain Boudard, CEA
30 // Sylvie Leray, CEA
31 // Joseph Cugnon, University of Liege
32 //
33 #define INCLXX_IN_GEANT4_MODE 1
34 
35 #include "globals.hh"
36 
37 /* \file G4INCLInteractionAvatar.cc
38  * \brief Virtual class for interaction avatars.
39  *
40  * This class is inherited by decay and collision avatars. The goal is to
41  * provide a uniform treatment of common physics, such as Pauli blocking,
42  * enforcement of energy conservation, etc.
43  *
44  * \date Mar 1st, 2011
45  * \author Davide Mancusi
46  */
47 
49 #include "G4INCLKinematicsUtils.hh"
50 #include "G4INCLCrossSections.hh"
51 #include "G4INCLPauliBlocking.hh"
52 #include "G4INCLRootFinder.hh"
53 #include "G4INCLLogger.hh"
54 #include "G4INCLConfigEnums.hh"
55 // #include <cassert>
56 
57 namespace G4INCL {
58 
63 
65  : IAvatar(time), theNucleus(n),
66  particle1(p1), particle2(NULL),
67  isPiN(false),
68  violationEFunctor(NULL)
69  {
70  }
71 
73  G4INCL::Particle *p2)
74  : IAvatar(time), theNucleus(n),
75  particle1(p1), particle2(p2),
76  isPiN((p1->isPion() && p2->isNucleon()) || (p2->isPion() && p1->isNucleon())),
77  violationEFunctor(NULL)
78  {
79  }
80 
82  }
83 
85  delete backupParticle1;
86  if(backupParticle2)
87  delete backupParticle2;
88  backupParticle1 = NULL;
89  backupParticle2 = NULL;
90  }
91 
93  if(backupParticle1)
94  (*backupParticle1) = (*particle1);
95  else
97 
98  if(particle2) {
99  if(backupParticle2)
100  (*backupParticle2) = (*particle2);
101  else
103 
107  } else {
109  }
110  }
111 
113  if(!theNucleus || p->isPion()) return; // Local energy does not make any sense without a nucleus
114 
117  }
118 
121 
123 
124  if(particle2) {
126  if(!isPiN) {
129  }
130  } else {
132  }
133  if(!isPiN)
135  }
136 
138  if(!theNucleus)
139  return false;
140 
141  ThreeVector pos = p->getPosition();
142  p->rpCorrelate();
143  G4double pos2 = pos.mag2();
144  const G4double r = theNucleus->getSurfaceRadius(p);
145  short iterations=0;
146  const short maxIterations=50;
147 
148  if(pos2 < r*r) return true;
149 
150  while( pos2 >= r*r && iterations<maxIterations )
151  {
152  pos *= std::sqrt(r*r*0.99/pos2);
153  pos2 = pos.mag2();
154  iterations++;
155  }
156  if( iterations < maxIterations)
157  {
158  INCL_DEBUG("Particle position vector length was : " << p->getPosition().mag() << ", rescaled to: " << pos.mag() << std::endl);
159  p->setPosition(pos);
160  return true;
161  }
162  else
163  return false;
164  }
165 
167  INCL_DEBUG("postInteraction: final state: " << std::endl << fs->print() << std::endl);
168  ParticleList modified = fs->getModifiedParticles();
169  ParticleList modifiedAndCreated = modified;
170  ParticleList created = fs->getCreatedParticles();
171  modifiedAndCreated.insert(modifiedAndCreated.end(), created.begin(), created.end());
172 
173  if(!isPiN) {
174  // Boost back to lab
175  for(ParticleIter i=modifiedAndCreated.begin(), e=modifiedAndCreated.end(); i!=e; ++i )
176  (*i)->boost(-boostVector);
177  }
178 
179  // If there is no Nucleus, just return
180  if(!theNucleus) return fs;
181 
182  // Mark pions that have been created outside their well (we will force them
183  // to be emitted later).
184  for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
185  if((*i)->isPion() && (*i)->getPosition().mag() > theNucleus->getSurfaceRadius(*i)) {
186  (*i)->makeParticipant();
187  (*i)->setOutOfWell();
188  fs->addOutgoingParticle(*i);
189  INCL_DEBUG("Pion was created outside its potential well." << std::endl
190  << (*i)->print());
191  }
192 
193  // Try to enforce energy conservation
195  G4bool success = true;
196  if(!isPiN || shouldUseLocalEnergy())
197  success = enforceEnergyConservation(fs);
198  if(!success) {
199  INCL_DEBUG("Enforcing energy conservation: failed!" << std::endl);
200 
201  // Restore the state of the initial particles
203 
204  // Delete newly created particles
205  for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
206  delete *i;
207 
208  FinalState *fsBlocked = new FinalState;
209  delete fs;
210  fsBlocked->makeNoEnergyConservation();
211  fsBlocked->setTotalEnergyBeforeInteraction(0.0);
212 
213  return fsBlocked; // Interaction is blocked. Return an empty final state.
214  }
215  INCL_DEBUG("Enforcing energy conservation: success!" << std::endl);
216 
217  INCL_DEBUG("postInteraction after energy conservation: final state: " << std::endl << fs->print() << std::endl);
218 
219  // Check that outgoing delta resonances can decay to pi-N
220  for(ParticleIter i=modified.begin(), e=modified.end(); i!=e; ++i )
221  if((*i)->isDelta() &&
223  INCL_DEBUG("Mass of the produced delta below decay threshold; forbidding collision. deltaMass=" <<
224  (*i)->getMass() << std::endl);
225 
226  // Restore the state of the initial particles
228 
229  // Delete newly created particles
230  for(ParticleIter j=created.begin(), end=created.end(); j!=end; ++j )
231  delete *j;
232 
233  FinalState *fsBlocked = new FinalState;
234  delete fs;
235  fsBlocked->makeNoEnergyConservation();
236  fsBlocked->setTotalEnergyBeforeInteraction(0.0);
237 
238  return fsBlocked; // Interaction is blocked. Return an empty final state.
239  }
240 
241  INCL_DEBUG("Random seeds before Pauli blocking: " << Random::getSeeds() << std::endl);
242  // Test Pauli blocking
243  G4bool isBlocked = Pauli::isBlocked(modifiedAndCreated, theNucleus);
244 
245  if(isBlocked) {
246  INCL_DEBUG("Pauli: Blocked!" << std::endl);
247 
248  // Restore the state of the initial particles
250 
251  // Delete newly created particles
252  for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
253  delete *i;
254 
255  FinalState *fsBlocked = new FinalState;
256  delete fs;
257  fsBlocked->makePauliBlocked();
258  fsBlocked->setTotalEnergyBeforeInteraction(0.0);
259 
260  return fsBlocked; // Interaction is blocked. Return an empty final state.
261  }
262  INCL_DEBUG("Pauli: Allowed!" << std::endl);
263 
264  // Test CDPP blocking
265  G4bool isCDPPBlocked = Pauli::isCDPPBlocked(created, theNucleus);
266 
267  if(isCDPPBlocked) {
268  INCL_DEBUG("CDPP: Blocked!" << std::endl);
269 
270  // Restore the state of the initial particles
272 
273  // Delete newly created particles
274  for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
275  delete *i;
276 
277  FinalState *fsBlocked = new FinalState;
278  delete fs;
279  fsBlocked->makePauliBlocked();
280  fsBlocked->setTotalEnergyBeforeInteraction(0.0);
281 
282  return fsBlocked; // Interaction is blocked. Return an empty final state.
283  }
284  INCL_DEBUG("CDPP: Allowed!" << std::endl);
285 
286  // If all went well, try to bring particles inside the nucleus...
287  for(ParticleIter i=modifiedAndCreated.begin(), e=modifiedAndCreated.end(); i!=e; ++i )
288  {
289  // ...except for pions beyond their surface radius.
290  if((*i)->isOutOfWell()) continue;
291 
292  const G4bool successBringParticlesInside = bringParticleInside(*i);
293  if( !successBringParticlesInside ) {
294  INCL_ERROR("Failed to bring particle inside the nucleus!" << std::endl);
295  }
296  }
297 
298  // Collision accepted!
299  for(ParticleIter i=modifiedAndCreated.begin(), e=modifiedAndCreated.end(); i!=e; ++i ) {
300  if(!(*i)->isOutOfWell()) {
301  // Decide if the particle should be made into a spectator
302  // (Back to spectator)
303  G4bool goesBackToSpectator = false;
304  if((*i)->isNucleon() && theNucleus->getStore()->getConfig()->getBackToSpectator()) {
305  G4double threshold = (*i)->getPotentialEnergy();
306  if((*i)->getType()==Proton)
308  if((*i)->getKineticEnergy() < threshold)
309  goesBackToSpectator = true;
310  }
311 
312  // Thaw the particle propagation
313  (*i)->thawPropagation();
314 
315  // Increment or decrement the participant counters
316  if(goesBackToSpectator) {
317  INCL_DEBUG("The following particle goes back to spectator:" << std::endl
318  << (*i)->print() << std::endl);
319  if(!(*i)->isTargetSpectator()) {
321  }
322  (*i)->makeTargetSpectator();
323  } else {
324  if((*i)->isTargetSpectator()) {
326  }
327  (*i)->makeParticipant();
328  }
329  }
330  }
331  ParticleList destroyed = fs->getDestroyedParticles();
332  for(ParticleIter i=destroyed.begin(), e=destroyed.end(); i!=e; ++i )
333  if(!(*i)->isTargetSpectator())
335 
336  return fs;
337  }
338 
340  (*particle1) = (*backupParticle1);
341  if(particle2)
342  (*particle2) = (*backupParticle2);
343  }
344 
346  // Set up the violationE calculation
347  ParticleList modified = fs->getModifiedParticles();
348  const G4bool manyBodyFinalState = (modified.size() + fs->getCreatedParticles().size() > 1);
349  if(manyBodyFinalState)
350  violationEFunctor = new ViolationEMomentumFunctor(theNucleus, fs, &boostVector, shouldUseLocalEnergy());
351  else {
352  Particle const * const p = modified.front();
353  // The following condition is necessary for the functor to work
354  // correctly. A similar condition exists in INCL4.6.
356  return false;
357  violationEFunctor = new ViolationEEnergyFunctor(theNucleus, fs, shouldUseLocalEnergy());
358  }
359 
360  // Apply the root-finding algorithm
361  const RootFinder::Solution theSolution = RootFinder::solve(violationEFunctor, 1.0);
362  if(theSolution.success) { // Apply the solution
363  (*violationEFunctor)(theSolution.x);
364  } else if(theNucleus){
365  INCL_DEBUG("Couldn't enforce energy conservation after an interaction, root-finding algorithm failed." << std::endl);
367  }
368  delete violationEFunctor;
369  violationEFunctor = NULL;
370  return theSolution.success;
371  }
372 
373  /* *** ***
374  * *** InteractionAvatar::ViolationEMomentumFunctor methods ***
375  * *** ***/
376 
377  InteractionAvatar::ViolationEMomentumFunctor::ViolationEMomentumFunctor(Nucleus * const nucleus, FinalState const * const finalState, ThreeVector const * const boost, const G4bool localE) :
378  RootFunctor(0., 1E6),
379  initialEnergy(finalState->getTotalEnergyBeforeInteraction()),
380  theNucleus(nucleus),
381  boostVector(boost),
382  shouldUseLocalEnergy(localE)
383  {
384  // Set up the finalParticles list
385  finalParticles = finalState->getModifiedParticles();
386  ParticleList const &created = finalState->getCreatedParticles();
387  finalParticles.insert(finalParticles.end(), created.begin(), created.end());
388 
389  // Store the particle momenta (necessary for the calls to
390  // scaleParticleMomenta() to work)
391  particleMomenta.clear();
392  for(ParticleIter i=finalParticles.begin(), e=finalParticles.end(); i!=e; ++i) {
393  (*i)->boost(*boostVector);
394  particleMomenta.push_back((*i)->getMomentum());
395  }
396  }
397 
398  G4double InteractionAvatar::ViolationEMomentumFunctor::operator()(const G4double alpha) const {
399  scaleParticleMomenta(alpha);
400 
401  G4double deltaE = 0.0;
402  for(ParticleIter i=finalParticles.begin(), e=finalParticles.end(); i!=e; ++i)
403  deltaE += (*i)->getEnergy() - (*i)->getPotentialEnergy();
404  deltaE -= initialEnergy;
405  return deltaE;
406  }
407 
408  void InteractionAvatar::ViolationEMomentumFunctor::scaleParticleMomenta(const G4double alpha) const {
409 
410  std::list<ThreeVector>::const_iterator iP = particleMomenta.begin();
411  for(ParticleIter i=finalParticles.begin(), e=finalParticles.end(); i!=e; ++i, ++iP) {
412  (*i)->setMomentum((*iP)*alpha);
413  (*i)->adjustEnergyFromMomentum();
414  (*i)->rpCorrelate();
415  (*i)->boost(-(*boostVector));
416  if(theNucleus)
417  theNucleus->updatePotentialEnergy(*i);
418  else
419  (*i)->setPotentialEnergy(0.);
420 
421  if(shouldUseLocalEnergy && !(*i)->isPion()) { // This translates AECSVT's loops 1, 3 and 4
422 // assert(theNucleus); // Local energy without a nucleus doesn't make sense
423  const G4double energy = (*i)->getEnergy(); // Store the energy of the particle
424  G4double locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // Initial value of local energy
425  G4double locEOld;
426  G4double deltaLocE = InteractionAvatar::locEAccuracy + 1E3;
427  for(G4int iterLocE=0;
429  ++iterLocE) {
430  locEOld = locE;
431  (*i)->setEnergy(energy + locE); // Update the energy of the particle...
432  (*i)->adjustMomentumFromEnergy();
433  theNucleus->updatePotentialEnergy(*i); // ...update its potential energy...
434  locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // ...and recompute locE.
435  deltaLocE = std::abs(locE-locEOld);
436  }
437  }
438  }
439  }
440 
441  void InteractionAvatar::ViolationEMomentumFunctor::cleanUp(const G4bool success) const {
442  if(!success)
443  scaleParticleMomenta(1.);
444  }
445 
446  /* *** ***
447  * *** InteractionAvatar::ViolationEEnergyFunctor methods ***
448  * *** ***/
449 
450  InteractionAvatar::ViolationEEnergyFunctor::ViolationEEnergyFunctor(Nucleus * const nucleus, FinalState const * const finalState, const G4bool localE) :
451  RootFunctor(0., 1E6),
452  initialEnergy(finalState->getTotalEnergyBeforeInteraction()),
453  theNucleus(nucleus),
454  theParticle(finalState->getModifiedParticles().front()),
455  theEnergy(theParticle->getEnergy()),
456  theMomentum(theParticle->getMomentum()),
457  energyThreshold(KinematicsUtils::energy(theMomentum,ParticleTable::effectiveDeltaDecayThreshold)),
458  shouldUseLocalEnergy(localE)
459  {
460 // assert(finalState->getModifiedParticles().size()==1);
461 // assert(theParticle->isDelta());
462  }
463 
464  G4double InteractionAvatar::ViolationEEnergyFunctor::operator()(const G4double alpha) const {
465  setParticleEnergy(alpha);
466  return theParticle->getEnergy() - theParticle->getPotentialEnergy() - initialEnergy;
467  }
468 
469  void InteractionAvatar::ViolationEEnergyFunctor::setParticleEnergy(const G4double alpha) const {
470 
471  G4double locE;
472  if(shouldUseLocalEnergy) {
473 // assert(theNucleus); // Local energy without a nucleus doesn't make sense
474  locE = KinematicsUtils::getLocalEnergy(theNucleus, theParticle); // Initial value of local energy
475  } else
476  locE = 0.;
477  G4double locEOld;
478  G4double deltaLocE = InteractionAvatar::locEAccuracy + 1E3;
479  for(G4int iterLocE=0;
481  ++iterLocE) {
482  locEOld = locE;
483  const G4double particleEnergy = energyThreshold + alpha*(theEnergy-energyThreshold);
484  const G4double theMass = std::sqrt(std::pow(particleEnergy,2.)-theMomentum.mag2());
485  theParticle->setMass(theMass);
486  theParticle->setEnergy(particleEnergy + locE); // Update the energy of the particle...
487  theParticle->adjustMomentumFromEnergy();
488  if(theNucleus) {
489  theNucleus->updatePotentialEnergy(theParticle); // ...update its potential energy...
490  if(shouldUseLocalEnergy)
491  locE = KinematicsUtils::getLocalEnergy(theNucleus, theParticle); // ...and recompute locE.
492  else
493  locE = 0.;
494  } else
495  locE = 0.;
496  deltaLocE = std::abs(locE-locEOld);
497  }
498 
499  }
500 
501  void InteractionAvatar::ViolationEEnergyFunctor::cleanUp(const G4bool success) const {
502  if(!success)
503  setParticleEnergy(1.);
504  }
505 
506 }
static const G4double locEAccuracy
Target accuracy in the determination of the local-energy Q-value.
G4double getMass() const
Get the cached particle mass.
static G4bool isCDPPBlocked(ParticleList const &p, Nucleus const *const n)
Check CDPP blocking.
void transformToLocalEnergyFrame(Nucleus const *const n, Particle *const p)
void preInteractionLocalEnergy(Particle *const p)
Apply local-energy transformation, if appropriate.
G4bool shouldUseLocalEnergy() const
true if the given avatar should use local energy
ParticleList const & getModifiedParticles() const
static const G4int maxIterLocE
Max number of iterations for the determination of the local-energy Q-value.
const char * p
Definition: xmltok.h:285
#define INCL_ERROR(x)
void boost(const ThreeVector &aBoostVector)
const G4INCL::ThreeVector & getMomentum() const
Config const * getConfig()
Definition: G4INCLStore.hh:251
Store * getStore() const
G4double getEnergy() const
G4double getSurfaceRadius(Particle const *const particle) const
Get the maximum allowed radius for a given particle.
#define G4ThreadLocal
Definition: tls.hh:52
ThreeVector makeBoostVector(Particle const *const p1, Particle const *const p2)
int G4int
Definition: G4Types.hh:78
G4double mag2() const
G4double getPotentialEnergy() const
Get the particle potential energy.
static G4ThreadLocal Particle * backupParticle2
void rpCorrelate()
Make the particle follow a strict r-p correlation.
InteractionAvatar(G4double, G4INCL::Nucleus *, G4INCL::Particle *)
SeedVector getSeeds()
Definition: G4INCLRandom.cc:70
ParticleList const & getCreatedParticles() const
double precision function energy(A, Z)
Definition: dpm25nuc6.f:4106
static void deleteBackupParticles()
Release the memory allocated for the backup particles.
static G4bool isBlocked(ParticleList const &p, Nucleus const *const n)
Check Pauli blocking.
Book & getBook()
Definition: G4INCLStore.hh:237
G4bool getBackToSpectator() const
Get back-to-spectator.
bool G4bool
Definition: G4Types.hh:79
virtual void setPosition(const G4INCL::ThreeVector &position)
void addOutgoingParticle(Particle *p)
void incrementEnergyViolationInteraction()
Definition: G4INCLBook.hh:79
FinalState * postInteraction(FinalState *)
void preInteractionBlocking()
Store the state of the particles before the interaction.
static G4ThreadLocal Particle * backupParticle1
const G4int n
void setTotalEnergyBeforeInteraction(G4double E)
void incrementCascading()
Definition: G4INCLBook.hh:76
void decrementCascading()
Definition: G4INCLBook.hh:77
G4double total(Particle const *const p1, Particle const *const p2)
std::string print() const
G4double getTransmissionBarrier(Particle const *const p)
Get the transmission barrier.
ParticleList const & getDestroyedParticles() const
const G4INCL::ThreeVector & getPosition() const
Solution solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.
G4bool enforceEnergyConservation(FinalState *const fs)
Enforce energy conservation.
void restoreParticles() const
Restore the state of both particles.
const G4double twoThirds
G4double mag() const
double G4double
Definition: G4Types.hh:76
G4ThreadLocal G4double effectiveDeltaDecayThreshold
G4bool bringParticleInside(Particle *const p)
#define INCL_DEBUG(x)
G4bool isPion() const
Is this a pion?
ParticleList::const_iterator ParticleIter
Static root-finder algorithm.
G4double getLocalEnergy(Nucleus const *const n, Particle *const p)