Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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// 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 G4INCLInteractionAvatar.cc
39 * \brief Virtual class for interaction avatars.
40 *
41 * This class is inherited by decay and collision avatars. The goal is to
42 * provide a uniform treatment of common physics, such as Pauli blocking,
43 * enforcement of energy conservation, etc.
44 *
45 * \date Mar 1st, 2011
46 * \author Davide Mancusi
47 */
48
53#include "G4INCLRootFinder.hh"
54#include "G4INCLLogger.hh"
55#include "G4INCLConfigEnums.hh"
56#include "G4INCLConfig.hh"
57#include "G4INCLEventInfo.hh"
58// #include <cassert>
59
60namespace G4INCL {
61
66 G4ThreadLocal Particle *InteractionAvatar::backupPartner = NULL;
67 ThreeVector InteractionAvatar::mbackupPartner;
68
69 G4ThreadLocal InteractionAvatar *InteractionAvatar::interactionAvatar = 0;
70
72 : IAvatar(time), theNucleus(n),
73 particle1(p1), particle2(NULL),
74 isPiN(false),
75 weight(1.),
76 violationEFunctor(NULL)
77 {
78 interactionAvatar = this;
79 }
80
83 : IAvatar(time), theNucleus(n),
84 particle1(p1), particle2(p2),
85 isPiN((p1->isPion() && p2->isNucleon()) || (p2->isPion() && p1->isNucleon())),
86 weight(1.),
87 violationEFunctor(NULL)
88 {
89 interactionAvatar = this;
90 }
91
92 InteractionAvatar *InteractionAvatar::Instance() { return interactionAvatar; }
93
96
98
99 if (backupPartner) {
100 (*backupPartner) = (*p);
101 } else {
102 backupPartner = new Particle(*p);
103 }
104 INCL_DEBUG("setSrcPartner:" << backupPartner->print());
105
106 return;
107 }
108
110 delete backupParticle1;
112 delete backupParticle2;
113 if (backupPartner)
114 delete backupPartner;
115 backupParticle1 = NULL;
116 backupParticle2 = NULL;
117 backupPartner = NULL;
118 }
119
122 (*backupParticle1) = (*particle1);
123 else
125
126 if(particle2) {
128 (*backupParticle2) = (*particle2);
129 else
131
132 oldTotalEnergy = particle1->getEnergy() + particle2->getEnergy()
133 - particle1->getPotentialEnergy() - particle2->getPotentialEnergy();
135 } else {
136 oldTotalEnergy = particle1->getEnergy() - particle1->getPotentialEnergy();
137 }
138 }
139
141 if(!theNucleus || p->isMeson() || p->isPhoton() || p->isAntiNucleon()) return; // Local energy does not make any sense without a nucleus
142
145 }
146
161
163 if(!theNucleus)
164 return false;
165
166 ThreeVector pos = p->getPosition();
167 p->rpCorrelate();
168 G4double pos2 = pos.mag2();
169 const G4double r = theNucleus->getSurfaceRadius(p);
170 short iterations=0;
171 const short maxIterations=50;
172
173 if(pos2 < r*r) return true;
174
175 while( pos2 >= r*r && iterations<maxIterations ) /* Loop checking, 10.07.2015, D.Mancusi */
176 {
177 pos *= std::sqrt(r*r*0.9801/pos2); // 0.9801 == 0.99*0.99
178 pos2 = pos.mag2();
179 iterations++;
180 }
181 if( iterations < maxIterations)
182 {
183 INCL_DEBUG("Particle position vector length was : " << p->getPosition().mag() << ", rescaled to: " << pos.mag() << '\n');
184 p->setPosition(pos);
185 return true;
186 }
187 else
188 return false;
189 }
190
192 INCL_DEBUG("postInteraction: final state: " << '\n' << fs->print() << '\n');
197 modifiedAndCreated.insert(modifiedAndCreated.end(), created.begin(), created.end());
199 ModifiedAndDestroyed.insert(ModifiedAndDestroyed.end(), Destroyed.begin(), Destroyed.end());
200
201 // Boost back to lab
202 //modifiedAndCreated.boost(-boostVector);
203
204 for (ParticleIter i = modifiedAndCreated.begin(),
205 e = modifiedAndCreated.end();
206 i != e; ++i)
207 if ((*i)->isSrcPartner() == false){
208 (*i)->boost(-boostVector);
209 }
210
211 // If there is no Nucleus, just return
212 if(!theNucleus) return;
213
214 // Mark pions and kaons that have been created outside their well (we will force them
215 // to be emitted later).
216 for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
217 if(((*i)->isPion() || (*i)->isKaon() || (*i)->isAntiKaon()) && (*i)->getPosition().mag() > theNucleus->getSurfaceRadius(*i)) {
218 (*i)->makeParticipant();
219 (*i)->setOutOfWell();
220 fs->addOutgoingParticle(*i);
221 INCL_DEBUG("Pion was created outside its potential well." << '\n'
222 << (*i)->print());
223 }
224
225 // Try to enforce energy conservation
226 G4int check = 0;
227 G4double oldTotalEnergy2 = 0.;
228 if (modifiedAndCreated.size() == 3 &&
229 theNucleus->getStore()->getBook().getAcceptedSrcCollisions() == 1) {
230 for (ParticleIter i = modifiedAndCreated.begin(),
231 e = modifiedAndCreated.end();
232 i != e; ++i) {
233 if ((*i)->getSrcPair() > 0.) {
234 check++;
235 }
236 }
237 }
238
239 G4double ediff = 0., partnerE = 0.;
240 if (check == 2) {
241 G4double oldTotalEnergy3 = 0.;
242 partnerE = backupPartner->getEnergy() - backupPartner->getPotentialEnergy();
243 for (ParticleIter i = modifiedAndCreated.begin(),
244 e = modifiedAndCreated.end();
245 i != e; ++i) {
246 if ((*i)->isNucleon())
247 oldTotalEnergy3 += (*i)->getEnergy() - (*i)->getPotentialEnergy();
248 else if ((*i)->isResonance())
249 oldTotalEnergy3 += (*i)->getEnergy() - (*i)->getPotentialEnergy() -
251 }
252
253 INCL_DEBUG("check initial energies: "
254 << backupParticle1->getEnergy() << " , "
255 << backupParticle2->getEnergy() << " , "
256 << backupPartner->getEnergy() << '\n');
257
258 INCL_DEBUG("check initial energies total: "
259 << backupParticle1->getEnergy() -
260 backupParticle1->getPotentialEnergy() +
261 backupParticle2->getEnergy() -
262 backupParticle2->getPotentialEnergy() +
263 backupPartner->getEnergy() -
264 backupPartner->getPotentialEnergy()
265 << '\n');
266
267 ediff =
268 oldTotalEnergy3 -
269 (backupParticle1->getEnergy() - backupParticle1->getPotentialEnergy() +
270 backupParticle2->getEnergy() - backupParticle2->getPotentialEnergy() +
271 backupPartner->getEnergy() - backupPartner->getPotentialEnergy());
272
273 INCL_DEBUG("check diff. src energies: " << oldTotalEnergy3 << " , " << ediff
274 << '\n');
275 }
276
277 // Try to enforce energy conservation
278 fs->setTotalEnergyBeforeInteraction(oldTotalEnergy + ediff + partnerE);
279
280 INCL_DEBUG("postInteraction before enforceEnergyConservation final state: "
281 << oldTotalEnergy + oldTotalEnergy2 << " \n Einit= "
282 << oldTotalEnergy << " \n Ecor= " << oldTotalEnergy2 << '\n'
283 << fs->print() << '\n');
284 G4bool success = enforceEnergyConservation(fs);
285 INCL_DEBUG("enforceEnergyConservation finish " << success << '\n');
286
287 if(!success) {
288 INCL_DEBUG("Enforcing energy conservation: failed!" << '\n');
289
290 // Restore the state of the initial particles
292
293 if (check == 2) {
294 INCL_DEBUG("Enforcing energy conservation: failed for SRC"
295 << " , eventnb: " << theEventInfo.eventNumber << '\n');
297 }
298
299 // Delete newly created particles
300 for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
301 delete *i;
302
303 fs->reset();
306
307 return; // Interaction is blocked. Return an empty final state.
308 }
309 INCL_DEBUG("Enforcing energy conservation: success!" << '\n');
310
311 INCL_DEBUG("postInteraction after energy conservation: final state: " << '\n' << fs->print() << '\n');
312
313 // Check that outgoing delta resonances can decay to pi-N
314 for(ParticleIter i=modified.begin(), e=modified.end(); i!=e; ++i )
315 if((*i)->isDelta() &&
316 (*i)->getMass() < ParticleTable::minDeltaMass) {
317 INCL_DEBUG("Mass of the produced delta below decay threshold; forbidding collision. deltaMass=" <<
318 (*i)->getMass() << '\n');
319
320 // Restore the state of the initial particles
322
323 if (check == 2) {
324 INCL_DEBUG("Mass of the produced delta below decay threshold for SRC"
325 << " , eventnb: " << theEventInfo.eventNumber << '\n');
327 }
328
329 // Delete newly created particles
330 for(ParticleIter j=created.begin(), end=created.end(); j!=end; ++j )
331 delete *j;
332
333 fs->reset();
336
337 return; // Interaction is blocked. Return an empty final state.
338 }
339
340 INCL_DEBUG("Random seeds before Pauli blocking: " << Random::getSeeds() << '\n');
341 // Test Pauli blocking
343
344 if (isBlocked && check < 2) {
345 INCL_DEBUG("Pauli: Blocked!" << '\n');
346
347 // Restore the state of the initial particles
349
350 if (check == 2) {
351 INCL_DEBUG("Pauli: Blocked SRC!"
352 << " , eventnb: " << theEventInfo.eventNumber << '\n');
354 }
355
356 // Delete newly created particles
357 for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
358 delete *i;
359
360 fs->reset();
361 fs->makePauliBlocked();
363
364 return; // Interaction is blocked. Return an empty final state.
365 }
366 INCL_DEBUG("Pauli: Allowed!" << '\n');
367
368 // Test CDPP blocking
370 G4int cntB = 0; //Do not pass through CDPP if Nbar annihilation
371 for(ParticleIter i=modifiedAndCreated.begin(), e=modifiedAndCreated.end(); i!=e; ++i ){
372 if((*i)->isBaryon())
373 cntB++;
374 }
375 if(cntB==0)
376 isCDPPBlocked=false;
377
378 if(isCDPPBlocked) {
379 INCL_DEBUG("CDPP: Blocked!" << '\n');
380
381 // Restore the state of the initial particles
383
384 if (check == 2) {
385 INCL_DEBUG("CDPP: Blocked for SRC"
386 << " , eventnb: " << theEventInfo.eventNumber << '\n');
388 }
389
390 // Delete newly created particles
391 for(ParticleIter i=created.begin(), e=created.end(); i!=e; ++i )
392 delete *i;
393
394 fs->reset();
395 fs->makePauliBlocked();
397
398 return; // Interaction is blocked. Return an empty final state.
399 }
400 INCL_DEBUG("CDPP: Allowed!" << '\n');
401
402 // If all went well, try to bring particles inside the nucleus...
403 for(ParticleIter i=modifiedAndCreated.begin(), e=modifiedAndCreated.end(); i!=e; ++i )
404 {
405 // ...except for pions beyond their surface radius.
406 if((*i)->isOutOfWell()) continue;
407
408 const G4bool successBringParticlesInside = bringParticleInside(*i);
409 if( !successBringParticlesInside ) {
410 INCL_ERROR("Failed to bring particle inside the nucleus!" << '\n');
411 }
412 }
413
414 // Collision accepted!
415 // Biasing of the final state
416 std::vector<G4int> newBiasCollisionVector;
417 newBiasCollisionVector = ModifiedAndDestroyed.getParticleListBiasVector();
418 if(std::fabs(weight-1.) > 1E-6){
419 newBiasCollisionVector.push_back(Particle::nextBiasedCollisionID);
421 weight = 1.; // useless?
422 }
423 for(ParticleIter i=modifiedAndCreated.begin(), e=modifiedAndCreated.end(); i!=e; ++i ) {
424 (*i)->setBiasCollisionVector(newBiasCollisionVector);
425 if(!(*i)->isOutOfWell()) {
426 // Decide if the particle should be made into a spectator
427 // (Back to spectator)
428 G4bool goesBackToSpectator = false;
429 if((*i)->isNucleon() && theNucleus->getStore()->getConfig()->getBackToSpectator()) {
430 G4double threshold = (*i)->getPotentialEnergy();
431 if((*i)->getType()==Proton)
432 threshold += Math::twoThirds*theNucleus->getTransmissionBarrier(*i);
433 if((*i)->getKineticEnergy() < threshold)
434 goesBackToSpectator = true;
435 }
436 // Thaw the particle propagation
437 (*i)->thawPropagation();
438
439 // Increment or decrement the participant counters
440 if(goesBackToSpectator) {
441 INCL_DEBUG("The following particle goes back to spectator:" << '\n'
442 << (*i)->print() << '\n');
443 if(!(*i)->isTargetSpectator()) {
444 theNucleus->getStore()->getBook().decrementCascading();
445 }
446 (*i)->makeTargetSpectator();
447 } else {
448 if((*i)->isTargetSpectator()) {
449 theNucleus->getStore()->getBook().incrementCascading();
450 }
451 (*i)->makeParticipant();
452 }
453 }
454 (*i)->resetSrcPartner();
455 }
456 ParticleList destroyed = fs->getDestroyedParticles();
457 for(ParticleIter i=destroyed.begin(), e=destroyed.end(); i!=e; ++i )
458 if(!(*i)->isTargetSpectator())
459 theNucleus->getStore()->getBook().decrementCascading();
460
461 if (check == 2) {
462 theNucleus->setSrcInternalEnergy(ediff);
463 for (ParticleIter i = modifiedAndCreated.begin(),
464 e = modifiedAndCreated.end();
465 i != e; ++i) {
466 (*i)->resetSrcPartner();
467 }
468 INCL_DEBUG("postInteraction end, src energy: "
469 << ediff << " , eventnb: " << theEventInfo.eventNumber << '\n');
470 }
471 return;
472 }
473
475 (*particle1) = (*backupParticle1);
476 particle1->resetSrcPartner();
477 if(particle2){
478 (*particle2) = (*backupParticle2);
479 particle2->resetSrcPartner();
480 }
481 }
482
484
485 theNucleus->getStore()->getBook().setAcceptedSrcCollisions(0);
486
487 auto m = fs->getSrcModifiedParticles();
488
489 if (backupPartner) {
490 for (ParticleIter i = m.begin(), e = m.end(); i != e; ++i) {
491 if ((*i)->getType() == backupPartner->getType() &&
492 (*i)->getSrcPair() == backupPartner->getSrcPair()) {
493 (*i)->setPosition(backupPartner->getPosition());
494 (*i)->setMomentum(backupPartner->getMomentum());
495 (*i)->adjustEnergyFromMomentum();
496 (*i)->resetSrcPartner();
497 theNucleus->updatePotentialEnergy(*i);
498 }
499 }
500 }
501 theNucleus->setSrcInternalEnergy(0.0);
502 }
503
505 if(!theNucleus) return false;
506 LocalEnergyType theLocalEnergyType;
507 if(theNucleus->getStore()->getConfig()->getProjectileType()==antiProton ||
508 theNucleus->getStore()->getConfig()->getProjectileType()==antiNeutron||
509 theNucleus->getStore()->getConfig()->getProjectileType()==antiComposite){
510 return false;
511 }
513 theLocalEnergyType = theNucleus->getStore()->getConfig()->getLocalEnergyPiType();
514 else
515 theLocalEnergyType = theNucleus->getStore()->getConfig()->getLocalEnergyBBType();
516
517 const G4bool firstAvatar = (theNucleus->getStore()->getBook().getAcceptedCollisions() == 0);
518 return ((theLocalEnergyType == FirstCollisionLocalEnergy && firstAvatar) ||
519 theLocalEnergyType == AlwaysLocalEnergy);
520 }
521
523 // Set up the violationE calculation
524 const G4bool manyBodyFinalState = (modifiedAndCreated.size() > 1);
525
526 if(manyBodyFinalState)
527 violationEFunctor = new ViolationEMomentumFunctor(theNucleus, modifiedAndCreated, fs->getTotalEnergyBeforeInteraction(), boostVector, shouldUseLocalEnergy());
528 else {
529 if (modified.empty()) {
530 Particle * const p1 = created.front(); //we destroy all nucleons during annihilation in NNbar case
531 // The following condition is necessary for the functor to work
532 // correctly. A similar condition exists in INCL4.6.
534 return false;
535 violationEFunctor = new ViolationEEnergyFunctor(theNucleus, p1, fs->getTotalEnergyBeforeInteraction(), shouldUseLocalEnergy());
536 }
537 else{
538 Particle * const p2 = modified.front(); // normal situation
539 // The following condition is necessary for the functor to work
540 // correctly. A similar condition exists in INCL4.6.
542 return false;
543 violationEFunctor = new ViolationEEnergyFunctor(theNucleus, p2, fs->getTotalEnergyBeforeInteraction(), shouldUseLocalEnergy());
544 }
545 }
546
547 // Apply the root-finding algorithm
548 const RootFinder::Solution theSolution = RootFinder::solve(violationEFunctor, 1.0);
549 if(theSolution.success) { // Apply the solution
550 (*violationEFunctor)(theSolution.x);
551 } else if(theNucleus){
552 INCL_DEBUG("Couldn't enforce energy conservation after an interaction, root-finding algorithm failed." << '\n');
553 theNucleus->getStore()->getBook().incrementEnergyViolationInteraction();
554 }
555 delete violationEFunctor;
556 violationEFunctor = NULL;
557 return theSolution.success;
558 }
559
560 /* *** ***
561 * *** InteractionAvatar::ViolationEMomentumFunctor methods ***
562 * *** ***/
563
564 InteractionAvatar::ViolationEMomentumFunctor::ViolationEMomentumFunctor(Nucleus * const nucleus, ParticleList const &modAndCre, const G4double totalEnergyBeforeInteraction, ThreeVector const &boost, const G4bool localE) :
565 RootFunctor(0., 1E6),
566 finalParticles(modAndCre),
567 initialEnergy(totalEnergyBeforeInteraction),
568 theNucleus(nucleus),
569 boostVector(boost),
570 shouldUseLocalEnergy(localE)
571 {
572 // Store the particle momenta (necessary for the calls to
573 // scaleParticleMomenta() to work)
574 for(ParticleIter i=finalParticles.begin(), e=finalParticles.end(); i!=e; ++i) {
575 if ((*i)->isSrcPartner() == false){
576 (*i)->boost(boostVector);
577 }
578 particleMomenta.push_back((*i)->getMomentum());
579 }
580 }
581
582 InteractionAvatar::ViolationEMomentumFunctor::~ViolationEMomentumFunctor() {
583 particleMomenta.clear();
584 }
585
586 G4double InteractionAvatar::ViolationEMomentumFunctor::operator()(const G4double alpha) const {
587 scaleParticleMomenta(alpha);
588
589 G4double deltaE = 0.0;
590 for(ParticleIter i=finalParticles.begin(), e=finalParticles.end(); i!=e; ++i)
591 deltaE += (*i)->getEnergy() - (*i)->getPotentialEnergy();
592 deltaE -= initialEnergy;
593 return deltaE;
594 }
595
596 void InteractionAvatar::ViolationEMomentumFunctor::scaleParticleMomenta(const G4double alpha) const {
597
598 std::vector<ThreeVector>::const_iterator iP = particleMomenta.begin();
599 for(ParticleIter i=finalParticles.begin(), e=finalParticles.end(); i!=e; ++i, ++iP) {
600 (*i)->setMomentum((*iP)*alpha);
601 (*i)->adjustEnergyFromMomentum();
602 if ((*i)->isSrcPartner() == false) {
603 (*i)->rpCorrelate();
604 (*i)->boost(-boostVector);
605 }
606 if(theNucleus){
607 theNucleus->updatePotentialEnergy(*i);
608 } else {
609 (*i)->setPotentialEnergy(0.);
610 }
611
612 if(shouldUseLocalEnergy && !(*i)->isPion() && !(*i)->isEta() && !(*i)->isOmega() &&
613 !(*i)->isKaon() && !(*i)->isAntiKaon() && !(*i)->isSigma() && !(*i)->isPhoton() && !(*i)->isLambda() && !(*i)->isAntiBaryon() && !(*i)->isSrcPartner()) { // This translates AECSVT's loops 1, 3 and 4
614// assert(theNucleus); // Local energy without a nucleus doesn't make sense
615 const G4double energy = (*i)->getEnergy(); // Store the energy of the particle
616 G4double locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // Initial value of local energy
617 G4double locEOld;
618 G4double deltaLocE = InteractionAvatar::locEAccuracy + 1E3;
619 for(G4int iterLocE=0;
620 deltaLocE>InteractionAvatar::locEAccuracy && iterLocE<InteractionAvatar::maxIterLocE;
621 ++iterLocE) {
622 locEOld = locE;
623 (*i)->setEnergy(energy + locE); // Update the energy of the particle...
624 (*i)->adjustMomentumFromEnergy();
625 theNucleus->updatePotentialEnergy(*i); // ...update its potential energy...
626 locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // ...and recompute locE.
627 deltaLocE = std::abs(locE-locEOld);
628 }
629 }
630
631//jlrs For lambdas and nuclei with masses higher than 19 also local energy
632 if(shouldUseLocalEnergy && (*i)->isLambda() && theNucleus->getA()>19 && !(*i)->isSrcPartner()) {
633// assert(theNucleus); // Local energy without a nucleus doesn't make sense
634 const G4double energy = (*i)->getEnergy(); // Store the energy of the particle
635 G4double locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // Initial value of local energy
636 G4double locEOld;
637 G4double deltaLocE = InteractionAvatar::locEAccuracy + 1E3;
638 for(G4int iterLocE=0;
639 deltaLocE>InteractionAvatar::locEAccuracy && iterLocE<InteractionAvatar::maxIterLocE;
640 ++iterLocE) {
641 locEOld = locE;
642 (*i)->setEnergy(energy + locE); // Update the energy of the particle...
643 (*i)->adjustMomentumFromEnergy();
644 theNucleus->updatePotentialEnergy(*i); // ...update its potential energy...
645 locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // ...and recompute locE.
646 deltaLocE = std::abs(locE-locEOld);
647 }
648 }
649 }
650 }
651
652 void InteractionAvatar::ViolationEMomentumFunctor::cleanUp(const G4bool success) const {
653 if(!success)
654 scaleParticleMomenta(1.);
655 }
656
657 /* *** ***
658 * *** InteractionAvatar::ViolationEEnergyFunctor methods ***
659 * *** ***/
660
661 InteractionAvatar::ViolationEEnergyFunctor::ViolationEEnergyFunctor(Nucleus * const nucleus, Particle * const aParticle, const G4double totalEnergyBeforeInteraction, const G4bool localE) :
662 RootFunctor(0., 1E6),
663 initialEnergy(totalEnergyBeforeInteraction),
664 theNucleus(nucleus),
665 theParticle(aParticle),
666 theEnergy(theParticle->getEnergy()),
667 theMomentum(theParticle->getMomentum()),
668 energyThreshold(KinematicsUtils::energy(theMomentum,ParticleTable::minDeltaMass)),
669 shouldUseLocalEnergy(localE)
670 {
671// assert(theParticle->isDelta());
672 }
673
674 G4double InteractionAvatar::ViolationEEnergyFunctor::operator()(const G4double alpha) const {
675 setParticleEnergy(alpha);
676 return theParticle->getEnergy() - theParticle->getPotentialEnergy() - initialEnergy;
677 }
678
679 void InteractionAvatar::ViolationEEnergyFunctor::setParticleEnergy(const G4double alpha) const {
680
681 G4double locE;
683// assert(theNucleus); // Local energy without a nucleus doesn't make sense
684 locE = KinematicsUtils::getLocalEnergy(theNucleus, theParticle); // Initial value of local energy
685 } else
686 locE = 0.;
687 G4double locEOld;
689 for(G4int iterLocE=0;
691 ++iterLocE) {
692 locEOld = locE;
693 G4double particleEnergy = energyThreshold + locE + alpha*(theEnergy-energyThreshold);
694 const G4double theMass2 = std::pow(particleEnergy,2.)-theMomentum.mag2();
695 G4double theMass;
697 theMass = std::sqrt(theMass2);
698 else {
700 particleEnergy = energyThreshold;
701 }
702 theParticle->setMass(theMass);
703 theParticle->setEnergy(particleEnergy); // Update the energy of the particle...
704 if(theNucleus) {
705 theNucleus->updatePotentialEnergy(theParticle); // ...update its potential energy...
707 locE = KinematicsUtils::getLocalEnergy(theNucleus, theParticle); // ...and recompute locE.
708 else
709 locE = 0.;
710 } else
711 locE = 0.;
712 deltaLocE = std::abs(locE-locEOld);
713 }
714
715 }
716
717 void InteractionAvatar::ViolationEEnergyFunctor::cleanUp(const G4bool success) const {
718 if(!success)
719 setParticleEnergy(1.);
720 }
721
722}
Simple container for output of event results.
#define INCL_ERROR(x)
#define INCL_DEBUG(x)
Static root-finder algorithm.
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
ParticleList & getSrcModifiedParticles()
std::string print() const
ParticleList const & getModifiedParticles() const
void setTotalEnergyBeforeInteraction(G4double E)
void addOutgoingParticle(Particle *p)
ParticleList const & getDestroyedParticles() const
G4double getTotalEnergyBeforeInteraction() const
ParticleList const & getCreatedParticles() const
AvatarType getType() const
static const G4int maxIterLocE
Max number of iterations for the determination of the local-energy Q-value.
void restoreParticles() const
Restore the state of both particles.
static InteractionAvatar * Instance()
G4bool enforceEnergyConservation(FinalState *const fs)
Enforce energy conservation.
static void deleteBackupParticles()
Release the memory allocated for the backup particles.
void preInteractionBlocking()
Store the state of the particles before the interaction.
static const G4double locEAccuracy
Target accuracy in the determination of the local-energy Q-value.
InteractionAvatar(G4double, G4INCL::Nucleus *, G4INCL::Particle *)
static G4ThreadLocal Particle * backupParticle2
G4bool shouldUseLocalEnergy() const
true if the given avatar should use local energy
static G4ThreadLocal Particle * backupParticle1
G4bool bringParticleInside(Particle *const p)
void preInteractionLocalEnergy(Particle *const p)
Apply local-energy transformation, if appropriate.
G4bool isPhoton() const
Is this a photon?
G4bool isMeson() const
Is this a Meson?
void rpCorrelate()
Make the particle follow a strict r-p correlation.
static void FillINCLBiasVector(G4double newBias)
const G4INCL::ThreeVector & getPosition() const
G4bool isAntiNucleon() const
Is this an antinucleon?
G4double getMass() const
Get the cached particle mass.
static G4ThreadLocal G4int nextBiasedCollisionID
virtual void setPosition(const G4INCL::ThreeVector &position)
G4double total(Particle const *const p1, Particle const *const p2)
G4double energy(const ThreeVector &p, const G4double m)
ThreeVector makeBoostVector(Particle const *const p1, Particle const *const p2)
void transformToLocalEnergyFrame(Nucleus const *const n, Particle *const p)
G4double getLocalEnergy(Nucleus const *const n, Particle *const p)
const G4double twoThirds
G4ThreadLocal G4double minDeltaMass2
G4ThreadLocal G4double minDeltaMass
const G4double effectiveNucleonMass
G4bool isBlocked(ParticleList const &p, Nucleus const *const n)
Check Pauli blocking.
G4bool isCDPPBlocked(ParticleList const &p, Nucleus const *const n)
Check CDPP blocking.
SeedVector getSeeds()
Solution solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.
ParticleList::const_iterator ParticleIter
@ DecayAvatarType
@ FirstCollisionLocalEnergy
#define G4ThreadLocal
Definition tls.hh:77