Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4CascadeInterface.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// $Id$
27//
28// 20100114 M. Kelsey -- Remove G4CascadeMomentum, use G4LorentzVector directly
29// 20100413 M. Kelsey -- Pass G4CollisionOutput by ref to ::collide()
30// 20100414 M. Kelsey -- Check for K0L/K0S before using G4InuclElemPart::type
31// 20100418 M. Kelsey -- Reference output particle lists via const-ref, use
32// const_iterator for both.
33// 20100428 M. Kelsey -- Use G4InuclParticleNames enum
34// 20100429 M. Kelsey -- Change "case gamma:" to "case photon:"
35// 20100517 M. Kelsey -- Follow new ctors for G4*Collider family.
36// 20100520 M. Kelsey -- Simplify collision loop, move momentum rotations to
37// G4CollisionOutput, copy G4DynamicParticle directly from
38// G4InuclParticle, no switch-block required.
39// 20100615 M. Kelsey -- Bug fix: For K0's need ekin in GEANT4 units
40// 20100617 M. Kelsey -- Rename "debug_" preprocessor flag to G4CASCADE_DEBUG,
41// and "BERTDEV" to "G4CASCADE_COULOMB_DEV"
42// 20100617 M. Kelsey -- Make G4InuclCollider a local data member
43// 20100618 M. Kelsey -- Deploy energy-conservation test on final state, with
44// preprocessor flag G4CASCADE_SKIP_ECONS to skip test.
45// 20100620 M. Kelsey -- Use new energy-conservation pseudo-collider
46// 20100621 M. Kelsey -- Fix compiler warning from GCC 4.5
47// 20100624 M. Kelsey -- Fix cascade loop to check nTries every time (had
48// allowed for infinite loop on E-violation); dump event data
49// to output if E-violation exceeds maxTries; use CheckBalance
50// for baryon and charge conservation.
51// 20100701 M. Kelsey -- Pass verbosity through to G4CollisionOutput
52// 20100714 M. Kelsey -- Report number of iterations before success
53// 20100720 M. Kelsey -- Use G4CASCADE_SKIP_ECONS flag for reporting
54// 20100723 M. Kelsey -- Move G4CollisionOutput to .hh file for reuse
55// 20100914 M. Kelsey -- Migrate to integer A and Z
56// 20100916 M. Kelsey -- Simplify ApplyYourself() by encapsulating code blocks
57// into numerous functions; make data-member colliders pointers;
58// provide support for projectile nucleus
59// 20100919 M. Kelsey -- Fix incorrect logic in retryInelasticNucleus()
60// 20100922 M. Kelsey -- Add functions to select de-excitation method
61// 20100924 M. Kelsey -- Migrate to "OutgoingNuclei" names in CollisionOutput
62// 20110224 M. Kelsey -- Add createTarget() for use with Propagate(); split
63// conservation law messages to separate function; begin to add
64// infrastructure code to Propagate. Move verbose
65// setting to .cc file, and apply to all member objects.
66// 20110301 M. Kelsey -- Add copyPreviousCascade() for use with Propagate()
67// along with new buffers and related particle-conversion
68// functions. Encapulate buffer deletion in clear(). Add some
69// diagnostic messages.
70// 20110302 M. Kelsey -- Redo diagnostics inside G4CASCADE_DEBUG_INTERFACE
71// 20110304 M. Kelsey -- Drop conversion of Propagate() arguments; pass
72// directly to collider for processing. Rename makeReactionProduct
73// to makeDynamicParticle.
74// 20110316 M. Kelsey -- Move kaon-mixing for type-code into G4InuclParticle;
75// add placeholders to capture and use bullet in Propagte
76// 20110327 G. Folger -- Set up for E/p checking by G4HadronicProcess in ctor
77// 20110328 M. Kelsey -- Modify balance() initialization to match Gunter's
78// 20110404 M. Kelsey -- Get primary projectile from base class (ref-03)
79// 20110502 M. Kelsey -- Add interface to capture random seeds for user
80// 20110719 M. Kelsey -- Use trivialise() in case maximum retries are reached
81// 20110720 M. Kelsey -- Discard elastic-cut array (no longer needed),
82// discard local "theFinalState" (in base as "theParticleChange"),
83// Modify createBullet() to set null pointer if bullet unusable,
84// return empty final-state on failures.
85// Fix charge violation report before throwing exception.
86// 20110722 M. Kelsey -- In makeDynamicParticle(), allow invalid type codes
87// in order to process, e.g., resonances from Propagate() input
88// 20110728 M. Kelsey -- Per V.Ivantchenko, change NoInteraction to return
89// zero particles, but set kinetic energy from projectile.
90// 20110801 M. Kelsey -- Make bullet, target point to local buffers, no delete
91// 20110802 M. Kelsey -- Use new decay handler for Propagate interface
92// 20110922 M. Kelsey -- Follow migration of G4InuclParticle::print(), use
93// G4ExceptionDescription for reporting before throwing exception
94// 20120125 M. Kelsey -- In retryInelasticProton() check for empty output
95// 20120525 M. Kelsey -- In NoInteraction, check for Ekin<0., set to zero;
96// use SetEnergyChange(0.) explicitly for good final states.
97// 20120822 M. Kelsey -- Move envvars to G4CascadeParameters.
98
99#include <cmath>
100#include <iostream>
101
102#include "G4CascadeInterface.hh"
103#include "globals.hh"
104#include "G4SystemOfUnits.hh"
107#include "G4CascadeParameters.hh"
108#include "G4CollisionOutput.hh"
110#include "G4DynamicParticle.hh"
111#include "G4HadronicException.hh"
112#include "G4InuclCollider.hh"
114#include "G4InuclNuclei.hh"
115#include "G4InuclParticle.hh"
117#include "G4KaonZeroLong.hh"
118#include "G4KaonZeroShort.hh"
119#include "G4KineticTrack.hh"
121#include "G4Nucleus.hh"
124#include "G4Track.hh"
125#include "G4V3DNucleus.hh"
126
127using namespace G4InuclParticleNames;
128
129typedef std::vector<G4InuclElementaryParticle>::const_iterator particleIterator;
130typedef std::vector<G4InuclNuclei>::const_iterator nucleiIterator;
131
132
133// Filename to capture random seed, if specified by user at runtime
134
135const G4String G4CascadeInterface::randomFile = G4CascadeParameters::randomFile();
136
137// Maximum number of iterations allowed for inelastic collision attempts
138
139const G4int G4CascadeInterface::maximumTries = 20;
140
141
142// Constructor and destrutor
143
145 : G4VIntraNuclearTransportModel(name), numberOfTries(0),
146 collider(new G4InuclCollider), balance(new G4CascadeCheckBalance(name)),
147 bullet(0), target(0), output(new G4CollisionOutput) {
148 SetEnergyMomentumCheckLevels(5*perCent, 10*MeV);
149 balance->setLimits(5*perCent, 10*MeV/GeV); // Bertini internal units
150 // Description(); // Model description
151
154}
155
156
158 clear();
159 delete collider; collider=0;
160 delete balance; balance=0;
161 delete output; output=0;
162}
163
164void G4CascadeInterface::ModelDescription(std::ostream& outFile) const
165{
166 outFile << "The Bertini-style cascade implements the inelastic scattering\n"
167 << "of hadrons by nuclei. Nucleons, pions, kaons and hyperons\n"
168 << "from 0 to 15 GeV may be used as projectiles in this model.\n"
169 << "Final state hadrons are produced by a classical cascade\n"
170 << "consisting of individual hadron-nucleon scatterings which use\n"
171 << "free-space partial cross sections, corrected for various\n"
172 << "nuclear medium effects. The target nucleus is modeled as a\n"
173 << "set of 1, 3 or 6 spherical shells, in which scattered hadrons\n"
174 << "travel in straight lines until they are reflected from or\n"
175 << "transmitted through shell boundaries.\n";
176}
177
178void G4CascadeInterface::DumpConfiguration(std::ostream& outFile) const {
180}
181
182
184 bullet=0;
185 target=0;
186}
187
188
189// Select post-cascade processing (default will be CascadeDeexcitation)
190// NOTE: Currently just calls through to Collider, in future will do something
191
193 collider->useCascadeDeexcitation();
194}
195
197 collider->usePreCompoundDeexcitation();
198}
199
200
201// Apply verbosity to all member objects (overrides base class version)
202
205 collider->setVerboseLevel(verbose);
206 balance->setVerboseLevel(verbose);
207 output->setVerboseLevel(verbose);
208}
209
210
211// Test whether inputs are valid for this model
212
214 G4Nucleus& /* theNucleus */) {
215 return IsApplicable(aTrack.GetDefinition());
216}
217
219 if (aPD->GetAtomicMass() > 1) return true; // Nuclei are okay
220
221 // Valid particle and have interactions available
223 return (type>0 && G4CascadeChannelTables::GetTable(type));
224}
225
226
227// Main Actions
228
231 G4Nucleus& theNucleus) {
232 if (verboseLevel)
233 G4cout << " >>> G4CascadeInterface::ApplyYourself" << G4endl;
234
235 if (aTrack.GetKineticEnergy() < 0.) {
236 G4cerr << " >>> G4CascadeInterface got negative-energy track: "
237 << aTrack.GetDefinition()->GetParticleName() << " Ekin = "
238 << aTrack.GetKineticEnergy() << G4endl;
239 }
240
241#ifdef G4CASCADE_DEBUG_INTERFACE
242 static G4int counter(0);
243 counter++;
244 G4cerr << "Reaction number "<< counter << " "
245 << aTrack.GetDefinition()->GetParticleName() << " "
246 << aTrack.GetKineticEnergy() << " MeV" << G4endl;
247#endif
248
249 if (!randomFile.empty()) { // User requested random-seed capture
250 if (verboseLevel>1)
251 G4cout << " Saving random engine state to " << randomFile << G4endl;
253 }
254
256 clear();
257
258 // Abort processing if no interaction is possible
259 if (!IsApplicable(aTrack, theNucleus)) {
260 if (verboseLevel) G4cerr << " No interaction possible " << G4endl;
261 return NoInteraction(aTrack, theNucleus);
262 }
263
264 // Make conversion between native Geant4 and Bertini cascade classes.
265 if (!createBullet(aTrack)) {
266 if (verboseLevel) G4cerr << " Unable to create usable bullet" << G4endl;
267 return NoInteraction(aTrack, theNucleus);
268 }
269
270 if (!createTarget(theNucleus)) {
271 if (verboseLevel) G4cerr << " Unable to create usable target" << G4endl;
272 return NoInteraction(aTrack, theNucleus);
273 }
274
275 // Different retry conditions for proton target vs. nucleus
276 const G4bool isHydrogen = (theNucleus.GetA_asInt() == 1);
277
278 numberOfTries = 0;
279 do { // we try to create inelastic interaction
280 if (verboseLevel > 1)
281 G4cout << " Generating cascade attempt " << numberOfTries << G4endl;
282
283 output->reset();
284 collider->collide(bullet, target, *output);
285 balance->collide(bullet, target, *output);
286
287 numberOfTries++;
288 } while ( isHydrogen ? retryInelasticProton() : retryInelasticNucleus() );
289
290 // Null event if unsuccessful
291 if (numberOfTries >= maximumTries) {
292 if (verboseLevel)
293 G4cout << " Cascade aborted after trials " << numberOfTries << G4endl;
294 return NoInteraction(aTrack, theNucleus);
295 }
296
297 // Abort job if energy or momentum are not conserved
298 if (!balance->okay()) {
300 return NoInteraction(aTrack, theNucleus);
301 }
302
303 // Successful cascade -- clean up and return
304 if (verboseLevel) {
305 G4cout << " Cascade output after trials " << numberOfTries << G4endl;
306 if (verboseLevel > 1) output->printCollisionOutput();
307 }
308
309 // Rotate event to put Z axis along original projectile direction
310 output->rotateEvent(bulletInLabFrame);
311
313
314 // Report violations of conservation laws in original frame
316
317 // Clean up and return final result;
318 clear();
319 return &theParticleChange;
320}
321
324 G4V3DNucleus* theNucleus) {
325 if (verboseLevel) G4cout << " >>> G4CascadeInterface::Propagate" << G4endl;
326
327#ifdef G4CASCADE_DEBUG_INTERFACE
328 if (verboseLevel>1) {
329 G4cout << " G4V3DNucleus A " << theNucleus->GetMassNumber()
330 << " Z " << theNucleus->GetCharge()
331 << "\n " << theSecondaries->size() << " secondaries:" << G4endl;
332 for (size_t i=0; i<theSecondaries->size(); i++) {
333 G4KineticTrack* kt = (*theSecondaries)[i];
334 G4cout << " " << i << ": " << kt->GetDefinition()->GetParticleName()
335 << " p " << kt->Get4Momentum() << " @ " << kt->GetPosition()
336 << " t " << kt->GetFormationTime() << G4endl;
337 }
338 }
339#endif
340
341 if (!randomFile.empty()) { // User requested random-seed capture
342 if (verboseLevel>1)
343 G4cout << " Saving random engine state to " << randomFile << G4endl;
345 }
346
348 clear();
349
350 // Process input secondaries list to eliminate resonances
351 G4DecayKineticTracks decay(theSecondaries);
352
353 // NOTE: Requires 9.4-ref-03 mods to base class and G4TheoFSGenerator
354 const G4HadProjectile* projectile = GetPrimaryProjectile();
355 if (projectile) createBullet(*projectile);
356
357 if (!createTarget(theNucleus)) {
358 if (verboseLevel) G4cerr << " Unable to create usable target" << G4endl;
359 return 0; // FIXME: This will cause a segfault later
360 }
361
362 numberOfTries = 0;
363 do {
364 if (verboseLevel > 1)
365 G4cout << " Generating rescatter attempt " << numberOfTries << G4endl;
366
367 output->reset();
368 collider->rescatter(bullet, theSecondaries, theNucleus, *output);
369 balance->collide(bullet, target, *output);
370
371 numberOfTries++;
372 // FIXME: retry checks will SEGFAULT until we can define the bullet!
373 } while (retryInelasticNucleus());
374
375 // Check whether repeated attempts have all failed; report and exit
376 if (numberOfTries >= maximumTries && !balance->okay()) {
377 throwNonConservationFailure(); // This terminates the job
378 }
379
380 // Successful cascade -- clean up and return
381 if (verboseLevel) {
382 G4cout << " Cascade rescatter after trials " << numberOfTries << G4endl;
383 if (verboseLevel > 1) output->printCollisionOutput();
384 }
385
386 // Does calling code take ownership? I hope so!
388
389 // Clean up and and return final result
390 clear();
391 return propResult;
392}
393
394
395// Replicate input particles onto output
396
399 G4Nucleus& /*theNucleus*/) {
400 if (verboseLevel)
401 G4cout << " >>> G4CascadeInterface::NoInteraction" << G4endl;
402
405
406 G4double ekin = aTrack.GetKineticEnergy()>0. ? aTrack.GetKineticEnergy() : 0.;
407 theParticleChange.SetEnergyChange(ekin); // Protect against rounding
408
409 return &theParticleChange;
410}
411
412
413// Convert input projectile to Bertini internal object
414
416 const G4ParticleDefinition* trkDef = aTrack.GetDefinition();
417
418 G4int bulletType = 0; // For elementary particles
419 G4int bulletA = 0, bulletZ = 0; // For nucleus projectile
420
421 if (trkDef->GetAtomicMass() <= 1) {
422 bulletType = G4InuclElementaryParticle::type(trkDef);
423 } else {
424 bulletA = trkDef->GetAtomicMass();
425 bulletZ = trkDef->GetAtomicNumber();
426 }
427
428 if (0 == bulletType && 0 == bulletA*bulletZ) {
429 if (verboseLevel) {
430 G4cerr << " G4CascadeInterface: " << trkDef->GetParticleName()
431 << " not usable as bullet." << G4endl;
432 }
433 bullet = 0;
434 return false;
435 }
436
437 // Code momentum and energy -- Bertini wants z-axis and GeV units
438 G4LorentzVector projectileMomentum = aTrack.Get4Momentum()/GeV;
439
440 // Rotation/boost to get from z-axis back to original frame
441 bulletInLabFrame = G4LorentzRotation::IDENTITY; // Initialize
442 bulletInLabFrame.rotateZ(-projectileMomentum.phi());
443 bulletInLabFrame.rotateY(-projectileMomentum.theta());
444 bulletInLabFrame.invert();
445
446 G4LorentzVector momentumBullet(0., 0., projectileMomentum.rho(),
447 projectileMomentum.e());
448
449 if (bulletType > 0) {
450 hadronBullet.fill(momentumBullet, bulletType);
451 bullet = &hadronBullet;
452 } else {
453 nucleusBullet.fill(momentumBullet, bulletA, bulletZ);
454 bullet = &nucleusBullet;
455 }
456
457 if (verboseLevel > 2) G4cout << "Bullet: \n" << *bullet << G4endl;
458
459 return true;
460}
461
462
463// Convert input nuclear target to Bertini internal object
464
466 return createTarget(theNucleus.GetA_asInt(), theNucleus.GetZ_asInt());
467}
468
470 return createTarget(theNucleus->GetMassNumber(), theNucleus->GetCharge());
471}
472
474 if (A > 1) {
475 nucleusTarget.fill(A, Z);
476 target = &nucleusTarget;
477 } else {
478 hadronTarget.fill(0., (Z=1?proton:neutron));
479 target = &hadronTarget;
480 }
481
482 if (verboseLevel > 2) G4cout << "Target: \n" << *target << G4endl;
483
484 return true; // Right now, target never fails
485}
486
487
488// Convert Bertini particle to output (G4DynamicParticle)
489
492 G4int outgoingType = iep.type();
493
494 if (iep.quasi_deutron()) {
495 G4cerr << " ERROR: G4CascadeInterface incompatible particle type "
496 << outgoingType << G4endl;
497 return 0;
498 }
499
500 // Copy local G4DynPart to public output (handle kaon mixing specially)
501 if (outgoingType == kaonZero || outgoingType == kaonZeroBar) {
502 G4ThreeVector momDir = iep.getMomentum().vect().unit();
503 G4double ekin = iep.getKineticEnergy()*GeV; // Bertini -> G4 units
504
506 if (G4UniformRand() > 0.5) pd = G4KaonZeroLong::Definition();
507
508 return new G4DynamicParticle(pd, momDir, ekin);
509 } else {
510 return new G4DynamicParticle(iep.getDynamicParticle());
511 }
512
513 return 0; // Should never get here!
514}
515
518 if (verboseLevel > 2) {
519 G4cout << " Nuclei fragment: \n" << inuc << G4endl;
520 }
521
522 // Copy local G4DynPart to public output
523 return new G4DynamicParticle(inuc.getDynamicParticle());
524}
525
526
527// Transfer Bertini internal final state to hadronics interface
528
530 if (verboseLevel > 1)
531 G4cout << " >>> G4CascadeInterface::copyOutputToHadronicResult" << G4endl;
532
533 const std::vector<G4InuclNuclei>& outgoingNuclei = output->getOutgoingNuclei();
534 const std::vector<G4InuclElementaryParticle>& particles = output->getOutgoingParticles();
535
538
539 // Get outcoming particles
540 if (!particles.empty()) {
541 particleIterator ipart = particles.begin();
542 for (; ipart != particles.end(); ipart++) {
544 }
545 }
546
547 // get nuclei fragments
548 if (!outgoingNuclei.empty()) {
549 nucleiIterator ifrag = outgoingNuclei.begin();
550 for (; ifrag != outgoingNuclei.end(); ifrag++) {
552 }
553 }
554}
555
557 if (verboseLevel > 1)
558 G4cout << " >>> G4CascadeInterface::copyOutputToReactionProducts" << G4endl;
559
560 const std::vector<G4InuclElementaryParticle>& particles = output->getOutgoingParticles();
561 const std::vector<G4InuclNuclei>& fragments = output->getOutgoingNuclei();
562
564
565 G4ReactionProduct* rp = 0; // Buffers to create outgoing tracks
566 G4DynamicParticle* dp = 0;
567
568 // Get outcoming particles
569 if (!particles.empty()) {
570 particleIterator ipart = particles.begin();
571 for (; ipart != particles.end(); ipart++) {
572 rp = new G4ReactionProduct;
573 dp = makeDynamicParticle(*ipart);
574 (*rp) = (*dp); // This does all the necessary copying
575 propResult->push_back(rp);
576 delete dp;
577 }
578 }
579
580 // get nuclei fragments
581 if (!fragments.empty()) {
582 nucleiIterator ifrag = fragments.begin();
583 for (; ifrag != fragments.end(); ifrag++) {
584 rp = new G4ReactionProduct;
585 dp = makeDynamicParticle(*ifrag);
586 (*rp) = (*dp); // This does all the necessary copying
587 propResult->push_back(rp);
588 delete dp;
589 }
590 }
591
592 return propResult;
593}
594
595
596// Report violations of conservation laws in original frame
597
599 balance->collide(bullet, target, *output);
600
601 if (verboseLevel > 2) {
602 if (!balance->baryonOkay()) {
603 G4cerr << "ERROR: no baryon number conservation, sum of baryons = "
604 << balance->deltaB() << G4endl;
605 }
606
607 if (!balance->chargeOkay()) {
608 G4cerr << "ERROR: no charge conservation, sum of charges = "
609 << balance->deltaQ() << G4endl;
610 }
611
612 if (std::abs(balance->deltaKE()) > 0.01 ) { // GeV
613 G4cerr << "Kinetic energy conservation violated by "
614 << balance->deltaKE() << " GeV" << G4endl;
615 }
616
617 G4double eInit = bullet->getEnergy() + target->getEnergy();
618 G4double eFinal = eInit + balance->deltaE();
619
620 G4cout << "Initial energy " << eInit << " final energy " << eFinal
621 << "\nTotal energy conservation at level "
622 << balance->deltaE() * GeV << " MeV" << G4endl;
623
624 if (balance->deltaKE() > 5.0e-5 ) { // 0.05 MeV
625 G4cerr << "FATAL ERROR: kinetic energy created "
626 << balance->deltaKE() * GeV << " MeV" << G4endl;
627 }
628 }
629}
630
631
632// Evaluate whether any outgoing particles penetrated Coulomb barrier
633
635 G4bool violated = false; // by default coulomb analysis is OK
636
637 const G4double coulumbBarrier = 8.7 * MeV/GeV; // Bertini uses GeV
638
639 const std::vector<G4InuclElementaryParticle>& p =
640 output->getOutgoingParticles();
641
642 for (particleIterator ipart=p.begin(); ipart != p.end(); ipart++) {
643 if (ipart->type() == proton) {
644 violated |= (ipart->getKineticEnergy() < coulumbBarrier);
645 }
646 }
647
648 return violated;
649}
650
651// Check whether inelastic collision on proton failed
652
654 const std::vector<G4InuclElementaryParticle>& out =
655 output->getOutgoingParticles();
656
657#ifdef G4CASCADE_DEBUG_INTERFACE
658 // Report on all retry conditions, in order of return logic
659 G4cout << " retryInelasticProton: number of Tries "
660 << ((numberOfTries < maximumTries) ? "RETRY (t)" : "EXIT (f)")
661 << "\n retryInelasticProton: AND collision type ";
662 if (out.empty()) G4cout << "FAILED" << G4endl;
663 else {
664 G4cout << (out.size() == 2 ? "ELASTIC (t)" : "INELASTIC (f)")
665 << "\n retryInelasticProton: AND Leading particles bullet "
666 << (out.size() >= 2 &&
667 (out[0].getDefinition() == bullet->getDefinition() ||
668 out[1].getDefinition() == bullet->getDefinition())
669 ? "YES (t)" : "NO (f)")
670 << G4endl;
671 }
672#endif
673
674 return ( (numberOfTries < maximumTries) &&
675 (out.empty() ||
676 (out.size() == 2 &&
677 (out[0].getDefinition() == bullet->getDefinition() ||
678 out[1].getDefinition() == bullet->getDefinition())))
679 );
680}
681
682// Check whether generic inelastic collision failed
683// NOTE: some conditions are set by compiler flags
684
686 // Quantities necessary for conditional block below
687 G4int npart = output->numberOfOutgoingParticles();
688 G4int nfrag = output->numberOfOutgoingNuclei();
689
690 const G4ParticleDefinition* firstOut = (npart == 0) ? 0 :
691 output->getOutgoingParticles().begin()->getDefinition();
692
693#ifdef G4CASCADE_DEBUG_INTERFACE
694 // Report on all retry conditions, in order of return logic
695 G4cout << " retryInelasticNucleus: numberOfTries "
696 << ((numberOfTries < maximumTries) ? "RETRY (t)" : "EXIT (f)")
697 << "\n retryInelasticNucleus: AND outputParticles "
698 << ((npart != 0) ? "NON-ZERO (t)" : "EMPTY (f)")
699#ifdef G4CASCADE_COULOMB_DEV
700 << "\n retryInelasticNucleus: AND coulombBarrier (COULOMB_DEV) "
701 << (coulombBarrierViolation() ? "VIOLATED (t)" : "PASSED (f)")
702 << "\n retryInelasticNucleus: AND collision type (COULOMB_DEV) "
703 << ((npart+nfrag > 2) ? "INELASTIC (t)" : "ELASTIC (f)")
704#else
705 << "\n retryInelasticNucleus: AND collsion type "
706 << ((npart+nfrag < 3) ? "ELASTIC (t)" : "INELASTIC (f)")
707 << "\n retryInelasticNucleus: AND Leading particle bullet "
708 << ((firstOut == bullet->getDefinition()) ? "YES (t)" : "NO (f)")
709#endif
710 << "\n retryInelasticNucleus: OR conservation "
711 << (!balance->okay() ? "FAILED (t)" : "PASSED (f)")
712 << G4endl;
713#endif
714
715 return ( ((numberOfTries < maximumTries) &&
716 (npart != 0) &&
717#ifdef G4CASCADE_COULOMB_DEV
718 (coulombBarrierViolation() && npart+nfrag > 2)
719#else
720 (npart+nfrag < 3 && firstOut == bullet->getDefinition())
721#endif
722 )
723#ifndef G4CASCADE_SKIP_ECONS
724 || (!balance->okay())
725#endif
726 );
727}
728
729
730// Terminate job in case of persistent non-conservation
731// FIXME: Need to migrate to G4ExceptionDescription
732
734 // NOTE: Once G4HadronicException is changed, use the following line!
735 // G4ExceptionDescription errInfo;
736 std::ostream& errInfo = G4cerr;
737
738 errInfo << " >>> G4CascadeInterface has non-conserving"
739 << " cascade after " << numberOfTries << " attempts." << G4endl;
740
741 G4String throwMsg = "G4CascadeInterface - ";
742 if (!balance->energyOkay()) {
743 throwMsg += "Energy";
744 errInfo << " Energy conservation violated by " << balance->deltaE()
745 << " GeV (" << balance->relativeE() << ")" << G4endl;
746 }
747
748 if (!balance->momentumOkay()) {
749 throwMsg += "Momentum";
750 errInfo << " Momentum conservation violated by " << balance->deltaP()
751 << " GeV/c (" << balance->relativeP() << ")" << G4endl;
752 }
753
754 if (!balance->baryonOkay()) {
755 throwMsg += "Baryon number";
756 errInfo << " Baryon number violated by " << balance->deltaB() << G4endl;
757 }
758
759 if (!balance->chargeOkay()) {
760 throwMsg += "Charge";
761 errInfo << " Charge conservation violated by " << balance->deltaQ()
762 << G4endl;
763 }
764
765 errInfo << " Final event output, for debugging:\n"
766 << " Bullet: \n" << *bullet << G4endl
767 << " Target: \n" << *target << G4endl;
768 output->printCollisionOutput(errInfo);
769
770 throwMsg += " non-conservation. More info in output.";
771 throw G4HadronicException(__FILE__, __LINE__, throwMsg); // Job ends here!
772}
std::vector< G4InuclElementaryParticle >::iterator particleIterator
Definition: G4BigBanger.cc:60
std::vector< G4InuclElementaryParticle >::const_iterator particleIterator
std::vector< G4InuclNuclei >::const_iterator nucleiIterator
@ neutron
@ isAlive
@ stopAndKill
std::vector< G4ReactionProduct * > G4ReactionProductVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
Hep3Vector unit() const
static DLL_API const HepLorentzRotation IDENTITY
HepLorentzRotation & rotateY(double delta)
HepLorentzRotation & rotateZ(double delta)
HepLorentzRotation & invert()
double theta() const
Hep3Vector vect() const
static void saveEngineStatus(const char filename[]="Config.conf")
Definition: Random.cc:175
static const G4CascadeChannel * GetTable(G4int initialState)
void setLimits(G4double relative, G4double absolute)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
virtual void ModelDescription(std::ostream &outFile) const
G4bool coulombBarrierViolation() const
G4bool retryInelasticNucleus() const
G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &theNucleus)
G4bool IsApplicable(const G4HadProjectile &aTrack, G4Nucleus &theNucleus)
G4HadFinalState * NoInteraction(const G4HadProjectile &aTrack, G4Nucleus &theNucleus)
G4bool createBullet(const G4HadProjectile &aTrack)
G4bool createTarget(G4Nucleus &theNucleus)
G4ReactionProductVector * copyOutputToReactionProducts()
virtual void DumpConfiguration(std::ostream &outFile) const
void SetVerboseLevel(G4int verbose)
G4ReactionProductVector * Propagate(G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus)
G4bool retryInelasticProton() const
G4DynamicParticle * makeDynamicParticle(const G4InuclElementaryParticle &iep) const
G4CascadeInterface(const G4String &name="BertiniCascade")
static void DumpConfiguration(std::ostream &os)
static G4bool usePreCompound()
static const G4String & randomFile()
G4int numberOfOutgoingParticles() const
const std::vector< G4InuclNuclei > & getOutgoingNuclei() const
void rotateEvent(const G4LorentzRotation &rotate)
void printCollisionOutput(std::ostream &os=G4cout) const
const std::vector< G4InuclElementaryParticle > & getOutgoingParticles() const
void setVerboseLevel(G4int verbose)
G4int numberOfOutgoingNuclei() const
void SetStatusChange(G4HadFinalStateStatus aS)
void AddSecondary(G4DynamicParticle *aP)
void SetEnergyChange(G4double anEnergy)
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
void SetVerboseLevel(G4int value)
void SetEnergyMomentumCheckLevels(G4double relativeLevel, G4double absoluteLevel)
void useCascadeDeexcitation()
void usePreCompoundDeexcitation()
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &globalOutput)
void rescatter(G4InuclParticle *bullet, G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus, G4CollisionOutput &globalOutput)
void setVerboseLevel(G4int verbose=0)
void fill(G4int ityp, Model model=DefaultModel)
void fill(G4int a, G4int z, G4double exc=0., Model model=DefaultModel)
G4ParticleDefinition * getDefinition() const
G4double getKineticEnergy() const
G4LorentzVector getMomentum() const
G4double getEnergy() const
const G4DynamicParticle & getDynamicParticle() const
static G4KaonZeroLong * Definition()
static G4KaonZeroShort * Definition()
G4double GetFormationTime() const
const G4ThreeVector & GetPosition() const
G4ParticleDefinition * GetDefinition() const
const G4LorentzVector & Get4Momentum() const
G4int GetA_asInt() const
Definition: G4Nucleus.hh:109
G4int GetZ_asInt() const
Definition: G4Nucleus.hh:115
G4int GetAtomicNumber() const
G4int GetAtomicMass() const
const G4String & GetParticleName() const
virtual G4int GetCharge()=0
virtual G4int GetMassNumber()=0
virtual void setVerboseLevel(G4int verbose=0)
const G4HadProjectile * GetPrimaryProjectile() const