Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4BinaryCascade.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
27#include "globals.hh"
29#include "G4SystemOfUnits.hh"
30#include "G4Proton.hh"
31#include "G4Neutron.hh"
32#include "G4LorentzRotation.hh"
33#include "G4BinaryCascade.hh"
37#include "G4Track.hh"
38#include "G4V3DNucleus.hh"
39#include "G4Fancy3DNucleus.hh"
40#include "G4Scatterer.hh"
41#include "G4MesonAbsorption.hh"
42#include "G4ping.hh"
43#include "G4Delete.hh"
44
45#include "G4CollisionManager.hh"
46#include "G4Absorber.hh"
47
49#include "G4ListOfCollisions.hh"
50#include "G4Fragment.hh"
51#include "G4RKPropagation.hh"
52
55#include "G4FermiMomentum.hh"
56
57#include "G4PreCompoundModel.hh"
60
62
63#include "G4PreCompoundModel.hh"
65
66#include <algorithm>
68#include <typeinfo>
69
71
72// turn on general debugging info, and consistency checks
73
74//#define debug_G4BinaryCascade 1
75
76// more detailed debugging -- deprecated
77//#define debug_H1_BinaryCascade 1
78
79// specific debugging info per method or functionality
80//#define debug_BIC_ApplyCollision 1
81//#define debug_BIC_CheckPauli 1
82//#define debug_BIC_CorrectFinalPandE 1
83//#define debug_BIC_Propagate 1
84//#define debug_BIC_Propagate_Excitation 1
85//#define debug_BIC_Propagate_Collisions 1
86//#define debug_BIC_Propagate_finals 1
87//#define debug_BIC_DoTimeStep 1
88//#define debug_BIC_CorrectBarionsOnBoundary 1
89//#define debug_BIC_GetExcitationEnergy 1
90//#define debug_BIC_DeexcitationProducts 1
91//#define debug_BIC_FinalNucleusMomentum 1
92//#define debug_BIC_Final4Momentum 1
93//#define debug_BIC_FillVoidnucleus 1
94//#define debug_BIC_FindFragments 1
95//#define debug_BIC_BuildTargetList 1
96//#define debug_BIC_FindCollision 1
97//#define debug_BIC_return 1
98
99//-------
100//#if defined(debug_G4BinaryCascade)
101#if 0
102 #define _CheckChargeAndBaryonNumber_(val) CheckChargeAndBaryonNumber(val)
103 //#define debugCheckChargeAndBaryonNumberverbose 1
104#else
105 #define _CheckChargeAndBaryonNumber_(val)
106#endif
107//#if defined(debug_G4BinaryCascade)
108#if 0
109 #define _DebugEpConservation(val) DebugEpConservation(val)
110 //#define debugCheckChargeAndBaryonNumberverbose 1
111#else
112 #define _DebugEpConservation(val)
113#endif
114
115G4int G4BinaryCascade::theBIC_ID = -1;
116
117//
118// C O N S T R U C T O R S A N D D E S T R U C T O R S
119//
121G4VIntraNuclearTransportModel("Binary Cascade", ptr)
122{
123 // initialise the resonance sector
124 G4ShortLivedConstructor ShortLived;
125 ShortLived.ConstructParticle();
126
127 theCollisionMgr = new G4CollisionManager;
128 theDecay=new G4BCDecay;
129 theImR.push_back(theDecay);
130 theLateParticle= new G4BCLateParticle;
132 theImR.push_back(aAb);
133 G4Scatterer * aSc=new G4Scatterer;
134 theH1Scatterer = new G4Scatterer;
135 theImR.push_back(aSc);
136
137 thePropagator = new G4RKPropagation;
138 theCurrentTime = 0.;
139 theBCminP = 45*MeV;
140 theCutOnP = 90*MeV;
141 theCutOnPAbsorb= 0*MeV; // No Absorption of slow Mesons, other than above G4MesonAbsorption
142
143 // reuse existing pre-compound model
144 if(!ptr) {
147 G4VPreCompoundModel* pre = static_cast<G4VPreCompoundModel*>(p);
148 if(!pre) { pre = new G4PreCompoundModel(); }
149 SetDeExcitation(pre);
150 }
151 theExcitationHandler = GetDeExcitation()->GetExcitationHandler();
152 SetMinEnergy(0.0*GeV);
153 SetMaxEnergy(10.1*GeV);
154 //PrintWelcomeMessage();
155 thePrimaryEscape = true;
156 thePrimaryType = 0;
157
158 SetEnergyMomentumCheckLevels(1.0*perCent, 1.0*MeV);
159
160 // init data members
161 currentA=currentZ=0;
162 lateA=lateZ=0;
163 initialA=initialZ=0;
164 projectileA=projectileZ=0;
165 currentInitialEnergy=initial_nuclear_mass=0.;
166 massInNucleus=0.;
167 theOuterRadius=0.;
168 theBIC_ID = G4PhysicsModelCatalog::GetModelID("model_G4BinaryCascade");
170}
171
173{
174 ClearAndDestroy(&theTargetList);
175 ClearAndDestroy(&theSecondaryList);
176 ClearAndDestroy(&theCapturedList);
177 delete thePropagator;
178 delete theCollisionMgr;
179 for(auto & ptr : theImR) { delete ptr; }
180 theImR.clear();
181 delete theLateParticle;
182 delete theH1Scatterer;
183}
184
185void G4BinaryCascade::ModelDescription(std::ostream& outFile) const
186{
187 outFile << "G4BinaryCascade is an intra-nuclear cascade model in which\n"
188 << "an incident hadron collides with a nucleon, forming two\n"
189 << "final-state particles, one or both of which may be resonances.\n"
190 << "The resonances then decay hadronically and the decay products\n"
191 << "are then propagated through the nuclear potential along curved\n"
192 << "trajectories until they re-interact or leave the nucleus.\n"
193 << "This model is valid for incident pions up to 1.5 GeV and\n"
194 << "nucleons up to 10 GeV.\n"
195 << "The remaining excited nucleus is handed on to ";
196 if (theDeExcitation) // pre-compound
197 {
198 outFile << theDeExcitation->GetModelName() << " : \n ";
200 }
201 else if (theExcitationHandler) // de-excitation
202 {
203 outFile << "G4ExcitationHandler"; //theExcitationHandler->GetModelName();
204 theExcitationHandler->ModelDescription(outFile);
205 }
206 else
207 {
208 outFile << "void.\n";
209 }
210 outFile<< " \n";
211}
212void G4BinaryCascade::PropagateModelDescription(std::ostream& outFile) const
213{
214 outFile << "G4BinaryCascade propagtes secondaries produced by a high\n"
215 << "energy model through the wounded nucleus.\n"
216 << "Secondaries are followed after the formation time and if\n"
217 << "within the nucleus are propagated through the nuclear\n"
218 << "potential along curved trajectories until they interact\n"
219 << "with a nucleon, decay, or leave the nucleus.\n"
220 << "An interaction of a secondary with a nucleon produces two\n"
221 << "final-state particles, one or both of which may be resonances.\n"
222 << "Resonances decay hadronically and the decay products\n"
223 << "are in turn propagated through the nuclear potential along curved\n"
224 << "trajectories until they re-interact or leave the nucleus.\n"
225 << "This model is valid for pions up to 1.5 GeV and\n"
226 << "nucleons up to about 3.5 GeV.\n"
227 << "The remaining excited nucleus is handed on to ";
228 if (theDeExcitation) // pre-compound
229 {
230 outFile << theDeExcitation->GetModelName() << " : \n ";
232 }
233 else if (theExcitationHandler) // de-excitation
234 {
235 outFile << "G4ExcitationHandler"; //theExcitationHandler->GetModelName();
236 theExcitationHandler->ModelDescription(outFile);
237 }
238 else
239 {
240 outFile << "void.\n";
241 }
242outFile<< " \n";
243}
244
245//----------------------------------------------------------------------------
246
247//
248// I M P L E M E N T A T I O N
249//
250
251
252//----------------------------------------------------------------------------
254 G4Nucleus & aNucleus)
255//----------------------------------------------------------------------------
256{
257 if(fBCDEBUG) G4cerr << " ######### Binary Cascade Reaction starts ######### "<< G4endl;
258
259 G4LorentzVector initial4Momentum = aTrack.Get4Momentum();
260 const G4ParticleDefinition * definition = aTrack.GetDefinition();
261
262 if(initial4Momentum.e()-initial4Momentum.m()<theBCminP &&
263 ( definition==G4Neutron::NeutronDefinition() || definition==G4Proton::ProtonDefinition() ) )
264 {
265 return theDeExcitation->ApplyYourself(aTrack, aNucleus);
266 }
267
269 // initialize the G4V3DNucleus from G4Nucleus
271
272 // Build a KineticTrackVector with the G4Track
273 G4KineticTrackVector * secondaries;// = new G4KineticTrackVector;
274 G4ThreeVector initialPosition(0., 0., 0.); // will be set later
275
276 if(!fBCDEBUG)
277 {
278 if(definition!=G4Neutron::NeutronDefinition() &&
279 definition!=G4Proton::ProtonDefinition() &&
280 definition!=G4PionPlus::PionPlusDefinition() &&
282 {
283 G4cerr << "You are trying to use G4BinaryCascade with " <<definition->GetParticleName()<<" as projectile."<<G4endl;
284 G4cerr << "G4BinaryCascade should not be used for projectiles other than nucleons or pions."<<G4endl;
285 G4cerr << "If you want to continue, please switch on the developer environment: "<<G4endl;
286 G4cerr << "setenv I_Am_G4BinaryCascade_Developer 1 "<<G4endl<<G4endl;
287 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade - used for unvalid particle type - Fatal");
288 }
289 }
290
291 // keep primary
292 thePrimaryType = definition;
293 thePrimaryEscape = false;
294
295 G4double timePrimary=aTrack.GetGlobalTime();
296
297 // try until an interaction will happen
298 G4ReactionProductVector * products=0;
299 G4int interactionCounter = 0,collisionLoopMaxCount;
300 do
301 {
302 // reset status that could be changed in previous loop event
303 theCollisionMgr->ClearAndDestroy();
304
305 if(products != 0)
306 { // free memory from previous loop event
307 ClearAndDestroy(products);
308 delete products;
309 products=0;
310 }
311
312 G4int massNumber=aNucleus.GetA_asInt();
313 the3DNucleus->Init(massNumber, aNucleus.GetZ_asInt());
314 thePropagator->Init(the3DNucleus);
315 G4KineticTrack * kt;
316 collisionLoopMaxCount = 200;
317 do // sample impact parameter until collisions are found
318 {
319 theCurrentTime=0;
320 G4double radius = the3DNucleus->GetOuterRadius()+3*fermi;
321 initialPosition=GetSpherePoint(1.1*radius, initial4Momentum); // get random position
322 kt = new G4KineticTrack(definition, 0., initialPosition, initial4Momentum);
324 // secondaries has been cleared by Propagate() in the previous loop event
325 secondaries= new G4KineticTrackVector;
326 secondaries->push_back(kt);
327 if(massNumber > 1) // 1H1 is special case
328 {
329 products = Propagate(secondaries, the3DNucleus);
330 } else {
331 products = Propagate1H1(secondaries,the3DNucleus);
332 }
333 // until we FIND a collision ... or give up
334 } while(! products && --collisionLoopMaxCount>0); /* Loop checking, 31.08.2015, G.Folger */
335
336 if(++interactionCounter>99) break;
337 // ...until we find an ALLOWED collision ... or give up
338 } while(products && products->size() == 0); /* Loop checking, 31.08.2015, G.Folger */
339
340 if(products && products->size()>0)
341 {
342 // G4cout << "BIC Applyyourself: number of products " << products->size() << G4endl;
343
344 // Fill the G4ParticleChange * with products
346 G4ReactionProductVector::iterator iter;
347
348 for(iter = products->begin(); iter != products->end(); ++iter)
349 {
350 G4DynamicParticle * aNewDP =
351 new G4DynamicParticle((*iter)->GetDefinition(),
352 (*iter)->GetTotalEnergy(),
353 (*iter)->GetMomentum());
354 G4HadSecondary aNew = G4HadSecondary(aNewDP);
355 G4double time=(*iter)->GetFormationTime();
356 if(time < 0.0) { time = 0.0; }
357 aNew.SetTime(timePrimary + time);
358 aNew.SetCreatorModelID((*iter)->GetCreatorModelID());
359 aNew.SetParentResonanceDef((*iter)->GetParentResonanceDef());
360 aNew.SetParentResonanceID((*iter)->GetParentResonanceID());
362 }
363
364 //DebugFinalEpConservation(aTrack, products);
365
366
367 } else { // no interaction, return primary
368 if(fBCDEBUG) G4cerr << " ######### Binary Cascade Reaction void, return initial state ######### "<< G4endl;
372 }
373
374 if ( products )
375 {
376 ClearAndDestroy(products);
377 delete products;
378 }
379
380 delete the3DNucleus;
381 the3DNucleus = nullptr;
382
383 if(fBCDEBUG) G4cerr << " ######### Binary Cascade Reaction ends ######### "<< G4endl;
384
385 return &theParticleChange;
386}
387//----------------------------------------------------------------------------
389 G4KineticTrackVector * secondaries, G4V3DNucleus * aNucleus)
390//----------------------------------------------------------------------------
391{
392 G4ping debug("debug_G4BinaryCascade");
393#ifdef debug_BIC_Propagate
394 G4cout << "G4BinaryCascade Propagate starting -------------------------------------------------------" <<G4endl;
395#endif
396
397 the3DNucleus=aNucleus;
399 theOuterRadius = the3DNucleus->GetOuterRadius();
400 theCurrentTime=0;
401 theProjectile4Momentum=G4LorentzVector(0,0,0,0);
402 theMomentumTransfer=G4ThreeVector(0,0,0);
403 // build theSecondaryList, theProjectileList and theCapturedList
404 ClearAndDestroy(&theCapturedList);
405 ClearAndDestroy(&theSecondaryList);
406 theSecondaryList.clear();
407 ClearAndDestroy(&theFinalState);
408 std::vector<G4KineticTrack *>::iterator iter;
409 theCollisionMgr->ClearAndDestroy();
410
411 theCutOnP=90*MeV;
412 if(the3DNucleus->GetMass()>30) theCutOnP = 70*MeV;
413 if(the3DNucleus->GetMass()>60) theCutOnP = 50*MeV;
414 if(the3DNucleus->GetMass()>120) theCutOnP = 45*MeV;
415
416
417 BuildTargetList();
418
419#ifdef debug_BIC_GetExcitationEnergy
420 G4cout << "ExcitationEnergy0 " << GetExcitationEnergy() << G4endl;
421#endif
422
423 thePropagator->Init(the3DNucleus);
424
425 G4bool success = BuildLateParticleCollisions(secondaries);
426 if (! success ) // fails if no excitation energy left....
427 {
428 products=HighEnergyModelFSProducts(products, secondaries);
429 ClearAndDestroy(secondaries);
430 delete secondaries;
431
432#ifdef debug_G4BinaryCascade
433 G4cout << "G4BinaryCascade::Propagate: warning - high energy model failed energy conservation, returning unchanged high energy final state" << G4endl;
434#endif
435
436 return products;
437 }
438 // check baryon and charge ...
439
440 _CheckChargeAndBaryonNumber_("lateparticles");
441 _DebugEpConservation(" be4 findcollisions");
442
443 // if called stand alone find first collisions
444 FindCollisions(&theSecondaryList);
445
446
447 if(theCollisionMgr->Entries() == 0 ) //late particles ALWAYS create Entries
448 {
449 //G4cout << " no collsions -> return 0" << G4endl;
450 delete products;
451#ifdef debug_BIC_return
452 G4cout << "return @ begin2, no collisions "<< G4endl;
453#endif
454 return 0;
455 }
456
457 // end of initialization: do the job now
458 // loop until there are no more collisions
459
460
461 G4bool haveProducts = false;
462#ifdef debug_BIC_Propagate_Collisions
463 G4int collisionCount=0;
464#endif
465 G4int collisionLoopMaxCount=1000000;
466 while(theCollisionMgr->Entries() > 0 && currentZ && --collisionLoopMaxCount>0) /* Loop checking, 31.08.2015, G.Folger */
467 {
468 if(Absorb()) { // absorb secondaries, pions only
469 haveProducts = true;
470 }
471 if(Capture()) { // capture secondaries, nucleons only
472 haveProducts = true;
473 }
474
475 // propagate to the next collision if any (collisions could have been deleted
476 // by previous absorption or capture)
477 if(theCollisionMgr->Entries() > 0)
478 {
480 nextCollision = theCollisionMgr->GetNextCollision();
481#ifdef debug_BIC_Propagate_Collisions
482 G4cout << " NextCollision * , Time, curtime = " << nextCollision << " "
483 <<nextCollision->GetCollisionTime()<< " " <<
484 theCurrentTime<< G4endl;
485#endif
486 if (!DoTimeStep(nextCollision->GetCollisionTime()-theCurrentTime) )
487 {
488 // Check if nextCollision is still valid, ie. particle did not leave nucleus
489 if (theCollisionMgr->GetNextCollision() != nextCollision )
490 {
491 nextCollision = 0;
492 }
493 }
494 //_DebugEpConservation("Stepped");
495
496 if( nextCollision )
497 {
498 if (ApplyCollision(nextCollision))
499 {
500 //G4cerr << "ApplyCollision success " << G4endl;
501 haveProducts = true;
502#ifdef debug_BIC_Propagate_Collisions
503 collisionCount++;
504#endif
505
506 } else {
507 //G4cerr << "ApplyCollision failure " << G4endl;
508 theCollisionMgr->RemoveCollision(nextCollision);
509 }
510 }
511 }
512 }
513
514 //--------- end of on Collisions
515 //G4cout << "currentZ @ end loop " << currentZ << G4endl;
516 G4int nProtons(0);
517 for(iter = theTargetList.begin(); iter != theTargetList.end(); ++iter)
518 {
519 if ( (*iter)->GetDefinition() == G4Proton::Proton() ) ++nProtons;
520 }
521 if ( ! theTargetList.size() || ! nProtons ){
522 // nucleus completely destroyed, fill in ReactionProductVector
523 products = FillVoidNucleusProducts(products);
524#ifdef debug_BIC_return
525 G4cout << "return @ Z=0 after collision loop "<< G4endl;
526 PrintKTVector(&theSecondaryList,std::string(" theSecondaryList"));
527 G4cout << "theTargetList size: " << theTargetList.size() << G4endl;
528 PrintKTVector(&theTargetList,std::string(" theTargetList"));
529 PrintKTVector(&theCapturedList,std::string(" theCapturedList"));
530
531 G4cout << " ExcitE be4 Correct : " <<GetExcitationEnergy() << G4endl;
532 G4cout << " Mom Transfered to nucleus : " << theMomentumTransfer << " " << theMomentumTransfer.mag() << G4endl;
533 PrintKTVector(&theFinalState,std::string(" FinalState uncorrected"));
534 G4cout << "returned products: " << products->size() << G4endl;
535 _CheckChargeAndBaryonNumber_("destroyed Nucleus");
536 _DebugEpConservation("destroyed Nucleus");
537#endif
538
539 return products;
540 }
541
542 // No more collisions: absorb, capture and propagate the secondaries out of the nucleus
543 if(Absorb()) {
544 haveProducts = true;
545 // G4cout << "Absorb sucess " << G4endl;
546 }
547
548 if(Capture()) {
549 haveProducts = true;
550 // G4cout << "Capture sucess " << G4endl;
551 }
552
553 if(!haveProducts) // no collisions happened. Return an empty vector.
554 {
555#ifdef debug_BIC_return
556 G4cout << "return 3, no products "<< G4endl;
557#endif
558 return products;
559 }
560
561
562#ifdef debug_BIC_Propagate
563 G4cout << " Momentum transfer to Nucleus " << theMomentumTransfer << " " << theMomentumTransfer.mag() << G4endl;
564 G4cout << " Stepping particles out...... " << G4endl;
565#endif
566
567 StepParticlesOut();
568 _DebugEpConservation("stepped out");
569
570
571 if ( theSecondaryList.size() > 0 )
572 {
573#ifdef debug_G4BinaryCascade
574 G4cerr << "G4BinaryCascade: Warning, have active particles at end" << G4endl;
575 PrintKTVector(&theSecondaryList, "active particles @ end added to theFinalState");
576#endif
577 // add left secondaries to FinalSate
578 for ( iter =theSecondaryList.begin(); iter != theSecondaryList.end(); ++iter)
579 {
580 theFinalState.push_back(*iter);
581 }
582 theSecondaryList.clear();
583
584 }
585 while ( theCollisionMgr->Entries() > 0 ) /* Loop checking, 31.08.2015, G.Folger */
586 {
587#ifdef debug_G4BinaryCascade
588 G4cerr << " Warning: remove left over collision(s) " << G4endl;
589#endif
590 theCollisionMgr->RemoveCollision(theCollisionMgr->GetNextCollision());
591 }
592
593#ifdef debug_BIC_Propagate_Excitation
594
595 PrintKTVector(&theSecondaryList,std::string(" theSecondaryList"));
596 G4cout << "theTargetList size: " << theTargetList.size() << G4endl;
597 // PrintKTVector(&theTargetList,std::string(" theTargetList"));
598 PrintKTVector(&theCapturedList,std::string(" theCapturedList"));
599
600 G4cout << " ExcitE be4 Correct : " <<GetExcitationEnergy() << G4endl;
601 G4cout << " Mom Transfered to nucleus : " << theMomentumTransfer << " " << theMomentumTransfer.mag() << G4endl;
602 PrintKTVector(&theFinalState,std::string(" FinalState uncorrected"));
603#endif
604
605 //
606
607
608 G4double ExcitationEnergy=GetExcitationEnergy();
609
610#ifdef debug_BIC_Propagate_finals
611 PrintKTVector(&theFinalState,std::string(" FinalState be4 corr"));
612 G4cout << " Excitation Energy prefinal, #collisions:, out, captured "
613 << ExcitationEnergy << " "
614 << collisionCount << " "
615 << theFinalState.size() << " "
616 << theCapturedList.size()<<G4endl;
617#endif
618
619 if (ExcitationEnergy < 0 )
620 {
621 G4int maxtry=5, ntry=0;
622 do {
623 CorrectFinalPandE();
624 ExcitationEnergy=GetExcitationEnergy();
625 } while ( ++ntry < maxtry && ExcitationEnergy < 0 ); /* Loop checking, 31.08.2015, G.Folger */
626 }
627 _DebugEpConservation("corrected");
628
629#ifdef debug_BIC_Propagate_finals
630 PrintKTVector(&theFinalState,std::string(" FinalState corrected"));
631 G4cout << " Excitation Energy final, #collisions:, out, captured "
632 << ExcitationEnergy << " "
633 << collisionCount << " "
634 << theFinalState.size() << " "
635 << theCapturedList.size()<<G4endl;
636#endif
637
638
639 if ( ExcitationEnergy < 0. )
640 {
641 #ifdef debug_G4BinaryCascade
642 G4cerr << "G4BinaryCascade-Warning: negative excitation energy ";
643 G4cerr <<ExcitationEnergy<<G4endl;
644 PrintKTVector(&theFinalState,std::string("FinalState"));
645 PrintKTVector(&theCapturedList,std::string("captured"));
646 G4cout << "negative ExE:Final 4Momentum .mag: " << GetFinal4Momentum()
647 << " "<< GetFinal4Momentum().mag()<< G4endl
648 << "negative ExE:FinalNucleusMom .mag: " << GetFinalNucleusMomentum()
649 << " "<< GetFinalNucleusMomentum().mag()<< G4endl;
650 #endif
651 #ifdef debug_BIC_return
652 G4cout << " negative Excitation E return empty products " << products << G4endl;
653 G4cout << "return 4, excit < 0 "<< G4endl;
654 #endif
655
656 ClearAndDestroy(products);
657 return products; // return empty products- FixMe
658 }
659
660 G4ReactionProductVector * precompoundProducts=DeExcite();
661
662
663 G4DecayKineticTracks decay(&theFinalState);
664 _DebugEpConservation("decayed");
665
666 products= ProductsAddFinalState(products, theFinalState);
667
668 products= ProductsAddPrecompound(products, precompoundProducts);
669
670// products=ProductsAddFakeGamma(products);
671
672
673 thePrimaryEscape = true;
674
675 #ifdef debug_BIC_return
676 G4cout << "BIC: return @end, all ok "<< G4endl;
677 //G4cout << " return products " << products << G4endl;
678 #endif
679
680 return products;
681}
682
683//----------------------------------------------------------------------------
684G4double G4BinaryCascade::GetExcitationEnergy()
685//----------------------------------------------------------------------------
686{
687
688 // get A and Z for the residual nucleus
689#if defined(debug_G4BinaryCascade) || defined(debug_BIC_GetExcitationEnergy)
690 G4int finalA = theTargetList.size()+theCapturedList.size();
691 G4int finalZ = GetTotalCharge(theTargetList)+GetTotalCharge(theCapturedList);
692 if ( (currentA - finalA) != 0 || (currentZ - finalZ) != 0 )
693 {
694 G4cerr << "G4BIC:GetExcitationEnergy(): Nucleon counting error current/final{A,Z} "
695 << "("<< currentA << "," << finalA << ") ("<< currentZ << "," << finalZ << ")" << G4endl;
696 }
697
698#endif
699
700 G4double excitationE(0);
701 G4double nucleusMass(0);
702 if(currentZ>.5)
703 {
704 nucleusMass = GetIonMass(currentZ,currentA);
705 }
706 else if (currentZ==0 )
707 {
708 if(currentA == 1) {nucleusMass = G4Neutron::Neutron()->GetPDGMass();}
709 else {nucleusMass = GetFinalNucleusMomentum().mag() - 3.*MeV*currentA;}
710 }
711 else
712 {
713#ifdef debug_G4BinaryCascade
714 G4cout << "G4BinaryCascade::GetExcitationEnergy(): Warning - invalid nucleus (A,Z)=("
715 << currentA << "," << currentZ << ")" << G4endl;
716#endif
717 return 0;
718 }
719
720#ifdef debug_BIC_GetExcitationEnergy
721 G4ping debug("debug_ExcitationEnergy");
722 debug.push_back("====> current A, Z");
723 debug.push_back(currentZ);
724 debug.push_back(currentA);
725 debug.push_back("====> final A, Z");
726 debug.push_back(finalZ);
727 debug.push_back(finalA);
728 debug.push_back(nucleusMass);
729 debug.push_back(GetFinalNucleusMomentum().mag());
730 debug.dump();
731 // PrintKTVector(&theTargetList, std::string(" current target list info"));
732 //PrintKTVector(&theCapturedList, std::string(" current captured list info"));
733#endif
734
735 excitationE = GetFinalNucleusMomentum().mag() - nucleusMass;
736
737 //G4double exE2 = GetFinal4Momentum().mag() - nucleusMass;
738
739 //G4cout << "old/new excitE " << excitationE << " / "<< exE2 << G4endl;
740
741#ifdef debug_BIC_GetExcitationEnergy
742 // ------ debug
743 if ( excitationE < 0 )
744 {
745 G4cout << "negative ExE final Ion mass " <<nucleusMass<< G4endl;
746 G4LorentzVector Nucl_mom=GetFinalNucleusMomentum();
747 if(finalZ>.5) G4cout << " Final nuclmom/mass " << Nucl_mom << " " << Nucl_mom.mag()
748 << " (A,Z)=("<< finalA <<","<<finalZ <<")"
749 << " mass " << nucleusMass << " "
750 << " excitE " << excitationE << G4endl;
751
752
755 G4double initialExc(0);
756 if(Z>.5)
757 {
758 initialExc = theInitial4Mom.mag()- GetIonMass(Z, A);
759 G4cout << "GetExcitationEnergy: Initial nucleus A Z " << A << " " << Z << " " << initialExc << G4endl;
760 }
761 }
762
763#endif
764
765 return excitationE;
766}
767
768
769//----------------------------------------------------------------------------
770//
771// P R I V A T E M E M B E R F U N C T I O N S
772//
773//----------------------------------------------------------------------------
774
775//----------------------------------------------------------------------------
776void G4BinaryCascade::BuildTargetList()
777//----------------------------------------------------------------------------
778{
779
780 if(!the3DNucleus->StartLoop())
781 {
782 // G4cerr << "G4BinaryCascade::BuildTargetList(): StartLoop() error!"
783 // << G4endl;
784 return;
785 }
786
787 ClearAndDestroy(&theTargetList); // clear theTargetList before rebuilding
788
790 const G4ParticleDefinition * definition;
792 G4LorentzVector mom;
793 // if there are nucleon hit by higher energy models, then SUM(momenta) != 0
794 initialZ=the3DNucleus->GetCharge();
795 initialA=the3DNucleus->GetMassNumber();
796 initial_nuclear_mass=GetIonMass(initialZ,initialA);
797 theInitial4Mom = G4LorentzVector(0,0,0,initial_nuclear_mass);
798 currentA=0;
799 currentZ=0;
800 while((nucleon = the3DNucleus->GetNextNucleon()) != nullptr) /* Loop checking, 31.08.2015, G.Folger */
801 {
802 // check if nucleon is hit by higher energy model.
803 if ( ! nucleon->AreYouHit() )
804 {
805 definition = nucleon->GetDefinition();
806 pos = nucleon->GetPosition();
807 mom = nucleon->GetMomentum();
808 // G4cout << "Nucleus " << pos.mag()/fermi << " " << mom.e() << G4endl;
809 //theInitial4Mom += mom;
810 // the potential inside the nucleus is taken into account, and nucleons are on mass shell.
811 mom.setE( std::sqrt( mom.vect().mag2() + sqr(definition->GetPDGMass()) ) );
812 G4KineticTrack * kt = new G4KineticTrack(definition, 0., pos, mom);
814 kt->SetNucleon(nucleon);
815 theTargetList.push_back(kt);
816 ++currentA;
817 if (definition->GetPDGCharge() > .5 ) ++currentZ;
818 }
819
820#ifdef debug_BIC_BuildTargetList
821 else { G4cout << "nucleon is hit" << nucleon << G4endl;}
822#endif
823 }
824 massInNucleus = 0;
825 if(currentZ>.5)
826 {
827 massInNucleus = GetIonMass(currentZ,currentA);
828 } else if (currentZ==0 && currentA>=1 )
829 {
830 massInNucleus = currentA * G4Neutron::Neutron()->GetPDGMass();
831 } else
832 {
833 G4cerr << "G4BinaryCascade::BuildTargetList(): Fatal Error - invalid nucleus (A,Z)=("
834 << currentA << "," << currentZ << ")" << G4endl;
835 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCasacde::BuildTargetList()");
836 }
837 currentInitialEnergy= theInitial4Mom.e() + theProjectile4Momentum.e();
838
839#ifdef debug_BIC_BuildTargetList
840 G4cout << "G4BinaryCascade::BuildTargetList(): nucleus (A,Z)=("
841 << currentA << "," << currentZ << ") mass: " << massInNucleus <<
842 ", theInitial4Mom " << theInitial4Mom <<
843 ", currentInitialEnergy " << currentInitialEnergy << G4endl;
844#endif
845
846}
847
848//----------------------------------------------------------------------------
849G4bool G4BinaryCascade::BuildLateParticleCollisions(G4KineticTrackVector * secondaries)
850//----------------------------------------------------------------------------
851{
852 G4bool success(false);
853 std::vector<G4KineticTrack *>::iterator iter;
854
855 lateA=lateZ=0;
856 projectileA=projectileZ=0;
857
858 G4double StartingTime=DBL_MAX; // Search for minimal formation time
859 for(iter = secondaries->begin(); iter != secondaries->end(); ++iter)
860 {
861 if((*iter)->GetFormationTime() < StartingTime)
862 StartingTime = (*iter)->GetFormationTime();
863 }
864
865 //PrintKTVector(secondaries, "initial late particles ");
866 G4LorentzVector lateParticles4Momentum(0,0,0,0);
867 for(iter = secondaries->begin(); iter != secondaries->end(); ++iter)
868 {
869 // G4cout << " Formation time : " << (*iter)->GetDefinition()->GetParticleName() << " "
870 // << (*iter)->GetFormationTime() << G4endl;
871 G4double FormTime = (*iter)->GetFormationTime() - StartingTime;
872 (*iter)->SetFormationTime(FormTime);
873 if( (*iter)->GetState() == G4KineticTrack::undefined ) // particles from high energy generator
874 {
875 FindLateParticleCollision(*iter);
876 lateParticles4Momentum += (*iter)->GetTrackingMomentum();
877 lateA += (*iter)->GetDefinition()->GetBaryonNumber();
878 lateZ += G4lrint((*iter)->GetDefinition()->GetPDGCharge()/eplus);
879 //PrintKTVector(*iter, "late particle ");
880 } else
881 {
882 theSecondaryList.push_back(*iter);
883 //PrintKTVector(*iter, "incoming particle ");
884 theProjectile4Momentum += (*iter)->GetTrackingMomentum();
885 projectileA += (*iter)->GetDefinition()->GetBaryonNumber();
886 projectileZ += G4lrint((*iter)->GetDefinition()->GetPDGCharge()/eplus);
887#ifdef debug_BIC_Propagate
888 G4cout << " Adding initial secondary " << *iter
889 << " time" << (*iter)->GetFormationTime()
890 << ", state " << (*iter)->GetState() << G4endl;
891#endif
892 }
893 }
894 //theCollisionMgr->Print();
895 const G4HadProjectile * primary = GetPrimaryProjectile(); // check for primary from TheoHE model
896
897 if (primary){
898 G4LorentzVector mom=primary->Get4Momentum();
899 theProjectile4Momentum += mom;
900 projectileA = primary->GetDefinition()->GetBaryonNumber();
901 projectileZ = G4lrint(primary->GetDefinition()->GetPDGCharge()/eplus);
902 // now check if "excitation" energy left by TheoHE model
903 G4double excitation= theProjectile4Momentum.e() + initial_nuclear_mass - lateParticles4Momentum.e() - massInNucleus;
904#ifdef debug_BIC_GetExcitationEnergy
905 G4cout << "BIC: Proj.e, nucl initial, nucl final, lateParticles"
906 << theProjectile4Momentum << ", "
907 << initial_nuclear_mass<< ", " << massInNucleus << ", "
908 << lateParticles4Momentum << G4endl;
909 G4cout << "BIC: Proj.e / initial excitation: " << theProjectile4Momentum.e() << " / " << excitation << G4endl;
910#endif
911 success = excitation > 0;
912#ifdef debug_G4BinaryCascade
913 if ( ! success ) {
914 G4cout << "G4BinaryCascade::BuildLateParticleCollisions(): Proj.e / initial excitation: " << theProjectile4Momentum.e() << " / " << excitation << G4endl;
915 //PrintKTVector(secondaries);
916 }
917#endif
918 } else {
919 // no primary from HE model -> cascade
920 success=true;
921 }
922
923 if (success) {
924 secondaries->clear(); // Don't leave "G4KineticTrack *"s in two vectors
925 delete secondaries;
926 }
927 return success;
928}
929
930//----------------------------------------------------------------------------
931G4ReactionProductVector * G4BinaryCascade::DeExcite()
932//----------------------------------------------------------------------------
933{
934 // find a fragment and call the precompound model.
935 G4Fragment * fragment = 0;
936 G4ReactionProductVector * precompoundProducts = 0;
937
938 G4LorentzVector pFragment(0);
939 // G4cout << " final4mon " << GetFinal4Momentum() /MeV << G4endl;
940
941 fragment = FindFragments();
942
943 if(fragment)
944 {
945 if(fragment->GetA_asInt() >1)
946 {
947 pFragment=fragment->GetMomentum();
948 // G4cout << " going to preco with fragment 4 mom " << pFragment << G4endl;
949 if (theDeExcitation) // pre-compound
950 {
951 precompoundProducts= theDeExcitation->DeExcite(*fragment);
952 }
953 else if (theExcitationHandler) // de-excitation
954 {
955 precompoundProducts=theExcitationHandler->BreakItUp(*fragment);
956 }
957
958 } else
959 { // fragment->GetA_asInt() <= 1, so a single proton, as a fragment must have Z>0
960 if (theTargetList.size() + theCapturedList.size() > 1 ) {
961 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCasacde:: Invalid Fragment");
962 }
963
964 std::vector<G4KineticTrack *>::iterator i;
965 if ( theTargetList.size() == 1 ) {i=theTargetList.begin();}
966 if ( theCapturedList.size() == 1 ) {i=theCapturedList.begin();}
967 G4ReactionProduct * aNew = new G4ReactionProduct((*i)->GetDefinition());
968 aNew->SetTotalEnergy((*i)->GetDefinition()->GetPDGMass());
969 aNew->SetCreatorModelID(theBIC_ID);
970 aNew->SetParentResonanceDef((*i)->GetParentResonanceDef());
971 aNew->SetParentResonanceID((*i)->GetParentResonanceID());
972 aNew->SetMomentum(G4ThreeVector(0));// see boost for preCompoundProducts below..
973 precompoundProducts = new G4ReactionProductVector();
974 precompoundProducts->push_back(aNew);
975 } // End of fragment->GetA() < 1.5
976 delete fragment;
977 fragment=0;
978
979 } else // End of if(fragment)
980 { // No fragment, can be neutrons only
981
982 precompoundProducts = DecayVoidNucleus();
983 }
984 #ifdef debug_BIC_DeexcitationProducts
985
986 G4LorentzVector fragment_momentum=GetFinalNucleusMomentum();
987 G4LorentzVector Preco_momentum;
988 if ( precompoundProducts )
989 {
990 std::vector<G4ReactionProduct *>::iterator j;
991 for(j = precompoundProducts->begin(); j != precompoundProducts->end(); ++j)
992 {
993 G4LorentzVector pProduct((*j)->GetMomentum(),(*j)->GetTotalEnergy());
994 Preco_momentum += pProduct;
995 }
996 }
997 G4cout << "finalNuclMom / sum preco products" << fragment_momentum << " / " << Preco_momentum
998 << " delta E "<< fragment_momentum.e() - Preco_momentum.e() << G4endl;
999
1000 #endif
1001
1002 return precompoundProducts;
1003}
1004
1005//----------------------------------------------------------------------------
1006G4ReactionProductVector * G4BinaryCascade::DecayVoidNucleus()
1007//----------------------------------------------------------------------------
1008{
1009 G4ReactionProductVector * result=0;
1010 if ( (theTargetList.size()+theCapturedList.size()) > 0 )
1011 {
1012 result = new G4ReactionProductVector;
1013 std::vector<G4KineticTrack *>::iterator aNuc;
1014 G4LorentzVector aVec;
1015 std::vector<G4double> masses;
1016 G4double sumMass(0);
1017
1018 if ( theTargetList.size() != 0)
1019 {
1020 for ( aNuc=theTargetList.begin(); aNuc != theTargetList.end(); aNuc++)
1021 {
1022 G4double mass=(*aNuc)->GetDefinition()->GetPDGMass();
1023 masses.push_back(mass);
1024 sumMass += mass;
1025 }
1026 }
1027
1028 if ( theCapturedList.size() != 0)
1029 {
1030 for(aNuc = theCapturedList.begin(); aNuc != theCapturedList.end(); aNuc++)
1031 {
1032 G4double mass=(*aNuc)->GetDefinition()->GetPDGMass();
1033 masses.push_back(mass);
1034 sumMass += mass;
1035 }
1036 }
1037
1038 G4LorentzVector finalP=GetFinal4Momentum();
1040 // G4cout << " some neutrons? " << masses.size() <<" " ;
1041 // G4cout<< theTargetList.size()<<" "<<finalP <<" " << finalP.mag()<<G4endl;
1042
1043 G4double eCMS=finalP.mag();
1044 if ( eCMS < sumMass ) // @@GF --- Cheat!!
1045 {
1046 eCMS=sumMass + 2*MeV*masses.size();
1047 finalP.setE(std::sqrt(finalP.vect().mag2() + sqr(eCMS)));
1048 }
1049
1050 precompoundLorentzboost.set(finalP.boostVector());
1051 std::vector<G4LorentzVector*> * momenta=decay.Decay(eCMS,masses);
1052 std::vector<G4LorentzVector*>::iterator aMom=momenta->begin();
1053
1054
1055 if ( theTargetList.size() != 0)
1056 {
1057 for ( aNuc=theTargetList.begin();
1058 (aNuc != theTargetList.end()) && (aMom!=momenta->end());
1059 aNuc++, aMom++ )
1060 {
1061 G4ReactionProduct * aNew = new G4ReactionProduct((*aNuc)->GetDefinition());
1062 aNew->SetTotalEnergy((*aMom)->e());
1063 aNew->SetMomentum((*aMom)->vect());
1064 aNew->SetCreatorModelID(theBIC_ID);
1065 aNew->SetParentResonanceDef((*aNuc)->GetParentResonanceDef());
1066 aNew->SetParentResonanceID((*aNuc)->GetParentResonanceID());
1067 result->push_back(aNew);
1068 delete *aMom;
1069 }
1070 }
1071
1072 if ( theCapturedList.size() != 0)
1073 {
1074 for ( aNuc=theCapturedList.begin();
1075 (aNuc != theCapturedList.end()) && (aMom!=momenta->end());
1076 aNuc++, aMom++ )
1077 {
1078 G4ReactionProduct * aNew = new G4ReactionProduct((*aNuc)->GetDefinition());
1079 aNew->SetTotalEnergy((*aMom)->e());
1080 aNew->SetMomentum((*aMom)->vect());
1081 aNew->SetCreatorModelID(theBIC_ID);
1082 aNew->SetParentResonanceDef((*aNuc)->GetParentResonanceDef());
1083 aNew->SetParentResonanceID((*aNuc)->GetParentResonanceID());
1084 result->push_back(aNew);
1085 delete *aMom;
1086 }
1087 }
1088
1089 delete momenta;
1090 }
1091 return result;
1092} // End if(!fragment)
1093
1094//----------------------------------------------------------------------------
1095G4ReactionProductVector * G4BinaryCascade::ProductsAddFinalState(G4ReactionProductVector * products, G4KineticTrackVector & fs)
1096//----------------------------------------------------------------------------
1097{
1098// fill in products the outgoing particles
1099 size_t i(0);
1100#ifdef debug_BIC_Propagate_finals
1101 G4LorentzVector mom_fs;
1102#endif
1103 for(i = 0; i< fs.size(); i++)
1104 {
1105 G4KineticTrack * kt = fs[i];
1107 aNew->SetMomentum(kt->Get4Momentum().vect());
1108 aNew->SetTotalEnergy(kt->Get4Momentum().e());
1109 aNew->SetNewlyAdded(kt->IsParticipant());
1110 aNew->SetCreatorModelID(theBIC_ID);
1113 products->push_back(aNew);
1114
1115#ifdef debug_BIC_Propagate_finals
1116 mom_fs += kt->Get4Momentum();
1118 G4cout << " Particle Ekin " << aNew->GetKineticEnergy();
1119 G4cout << ", is " << (kt->GetDefinition()->GetPDGStable() ? "stable" :
1120 (kt->GetDefinition()->IsShortLived() ? "short lived " : "non stable")) ;
1121 G4cout << G4endl;
1122#endif
1123
1124 }
1125#ifdef debug_BIC_Propagate_finals
1126 G4cout << " Final state momentum " << mom_fs << G4endl;
1127#endif
1128
1129 return products;
1130}
1131//----------------------------------------------------------------------------
1132G4ReactionProductVector * G4BinaryCascade::ProductsAddPrecompound(G4ReactionProductVector * products, G4ReactionProductVector * precompoundProducts)
1133//----------------------------------------------------------------------------
1134{
1135 G4LorentzVector pSumPreco(0), pPreco(0);
1136
1137 if ( precompoundProducts )
1138 {
1139 std::vector<G4ReactionProduct *>::iterator j;
1140 for(j = precompoundProducts->begin(); j != precompoundProducts->end(); ++j)
1141 {
1142 // boost back to system of moving nucleus
1143 G4LorentzVector pProduct((*j)->GetMomentum(),(*j)->GetTotalEnergy());
1144 pPreco+= pProduct;
1145#ifdef debug_BIC_Propagate_finals
1146 G4cout << "BIC: pProduct be4 boost " <<pProduct << G4endl;
1147#endif
1148 pProduct *= precompoundLorentzboost;
1149#ifdef debug_BIC_Propagate_finals
1150 G4cout << "BIC: pProduct aft boost " <<pProduct << G4endl;
1151#endif
1152 pSumPreco += pProduct;
1153 (*j)->SetTotalEnergy(pProduct.e());
1154 (*j)->SetMomentum(pProduct.vect());
1155 (*j)->SetNewlyAdded(true);
1156 products->push_back(*j);
1157 }
1158 // G4cout << " unboosted preco result mom " << pPreco / MeV << " ..- fragmentMom " << (pPreco - pFragment)/MeV<< G4endl;
1159 // G4cout << " preco result mom " << pSumPreco / MeV << " ..-file4Mom " << (pSumPreco - GetFinal4Momentum())/MeV<< G4endl;
1160 precompoundProducts->clear();
1161 delete precompoundProducts;
1162 }
1163 return products;
1164}
1165//----------------------------------------------------------------------------
1166void G4BinaryCascade::FindCollisions(G4KineticTrackVector * secondaries)
1167//----------------------------------------------------------------------------
1168{
1169 for(std::vector<G4KineticTrack *>::iterator i = secondaries->begin();
1170 i != secondaries->end(); ++i)
1171 {
1172 for(std::vector<G4BCAction *>::iterator j = theImR.begin();
1173 j!=theImR.end(); j++)
1174 {
1175 // G4cout << "G4BinaryCascade::FindCollisions: at action " << *j << G4endl;
1176 const std::vector<G4CollisionInitialState *> & aCandList
1177 = (*j)->GetCollisions(*i, theTargetList, theCurrentTime);
1178 for(size_t count=0; count<aCandList.size(); count++)
1179 {
1180 theCollisionMgr->AddCollision(aCandList[count]);
1181 //4cout << "====================== New Collision ================="<<G4endl;
1182 //theCollisionMgr->Print();
1183 }
1184 }
1185 }
1186}
1187
1188
1189//----------------------------------------------------------------------------
1190void G4BinaryCascade::FindDecayCollision(G4KineticTrack * secondary)
1191//----------------------------------------------------------------------------
1192{
1193 const std::vector<G4CollisionInitialState *> & aCandList
1194 = theDecay->GetCollisions(secondary, theTargetList, theCurrentTime);
1195 for(size_t count=0; count<aCandList.size(); count++)
1196 {
1197 theCollisionMgr->AddCollision(aCandList[count]);
1198 }
1199}
1200
1201//----------------------------------------------------------------------------
1202void G4BinaryCascade::FindLateParticleCollision(G4KineticTrack * secondary)
1203//----------------------------------------------------------------------------
1204{
1205
1206 G4double tin=0., tout=0.;
1207 if (((G4RKPropagation*)thePropagator)->GetSphereIntersectionTimes(secondary,tin,tout))
1208 {
1209 if ( tin > 0 )
1210 {
1212 } else if ( tout > 0 )
1213 {
1214 secondary->SetState(G4KineticTrack::inside);
1215 } else {
1216 //G4cout << "G4BC set miss , tin, tout " << tin << " , " << tout <<G4endl;
1218 }
1219 } else {
1221 //G4cout << "G4BC set miss ,no intersect tin, tout " << tin << " , " << tout <<G4endl;
1222 }
1223
1224
1225#ifdef debug_BIC_FindCollision
1226 G4cout << "FindLateP Particle, 4-mom, times newState "
1227 << secondary->GetDefinition()->GetParticleName() << " "
1228 << secondary->Get4Momentum()
1229 << " times " << tin << " " << tout << " "
1230 << secondary->GetState() << G4endl;
1231#endif
1232
1233 const std::vector<G4CollisionInitialState *> & aCandList
1234 = theLateParticle->GetCollisions(secondary, theTargetList, theCurrentTime);
1235 for(size_t count=0; count<aCandList.size(); count++)
1236 {
1237#ifdef debug_BIC_FindCollision
1238 G4cout << " Adding a late Col : " << aCandList[count] << G4endl;
1239#endif
1240 theCollisionMgr->AddCollision(aCandList[count]);
1241 }
1242}
1243
1244
1245//----------------------------------------------------------------------------
1246G4bool G4BinaryCascade::ApplyCollision(G4CollisionInitialState * collision)
1247//----------------------------------------------------------------------------
1248{
1249 G4KineticTrack * primary = collision->GetPrimary();
1250
1251#ifdef debug_BIC_ApplyCollision
1252 G4cerr << "G4BinaryCascade::ApplyCollision start"<<G4endl;
1253 theCollisionMgr->Print();
1254 G4cout << "ApplyCollisions : projte 4mom " << primary->GetTrackingMomentum()<< G4endl;
1255#endif
1256
1257 G4KineticTrackVector target_collection=collision->GetTargetCollection();
1258 G4bool haveTarget=target_collection.size()>0;
1259 if( haveTarget && (primary->GetState() != G4KineticTrack::inside) )
1260 {
1261#ifdef debug_G4BinaryCascade
1262 G4cout << "G4BinaryCasacde::ApplyCollision(): StateError " << primary << G4endl;
1263 PrintKTVector(primary,std::string("primay- ..."));
1264 PrintKTVector(&target_collection,std::string("... targets"));
1265 collision->Print();
1266 G4cout << G4endl;
1267 theCollisionMgr->Print();
1268 //*GF* throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCasacde::ApplyCollision()");
1269#endif
1270 return false;
1271// } else {
1272// G4cout << "G4BinaryCasacde::ApplyCollision(): decay " << G4endl;
1273// PrintKTVector(primary,std::string("primay- ..."));
1274// G4double tin=0., tout=0.;
1275// if (((G4RKPropagation*)thePropagator)->GetSphereIntersectionTimes(primary,tin,tout))
1276// {
1277// G4cout << "tin tout: " << tin << " " << tout << G4endl;
1278// }
1279
1280 }
1281
1282 G4LorentzVector mom4Primary=primary->Get4Momentum();
1283
1284 G4int initialBaryon(0);
1285 G4int initialCharge(0);
1286 if (primary->GetState() == G4KineticTrack::inside)
1287 {
1288 initialBaryon = primary->GetDefinition()->GetBaryonNumber();
1289 initialCharge = G4lrint(primary->GetDefinition()->GetPDGCharge()/eplus);
1290 }
1291
1292 // for primary resonances, subtract neutron ( = proton) field ( ie. add std::abs(field))
1293 G4double initial_Efermi=CorrectShortlivedPrimaryForFermi(primary,target_collection);
1294 //****************************************
1295
1296
1297 G4KineticTrackVector * products = collision->GetFinalState();
1298
1299#ifdef debug_BIC_ApplyCollision
1300 DebugApplyCollisionFail(collision, products);
1301#endif
1302
1303 // reset primary to initial state, in case there is a veto...
1304 primary->Set4Momentum(mom4Primary);
1305
1306 G4bool lateParticleCollision= (!haveTarget) && products && products->size() == 1;
1307 G4bool decayCollision= (!haveTarget) && products && products->size() > 1;
1308 G4bool Success(true);
1309
1310
1311#ifdef debug_G4BinaryCascade
1312 G4int lateBaryon(0), lateCharge(0);
1313#endif
1314
1315 if ( lateParticleCollision )
1316 { // for late particles, reset charges
1317 //G4cout << "lateP, initial B C state " << initialBaryon << " "
1318 // << initialCharge<< " " << primary->GetState() << " "<< primary->GetDefinition()->GetParticleName()<< G4endl;
1319#ifdef debug_G4BinaryCascade
1320 lateBaryon = initialBaryon;
1321 lateCharge = initialCharge;
1322#endif
1323 initialBaryon=initialCharge=0;
1324 lateA -= primary->GetDefinition()->GetBaryonNumber();
1325 lateZ -= G4lrint(primary->GetDefinition()->GetPDGCharge()/eplus);
1326 }
1327
1328 initialBaryon += collision->GetTargetBaryonNumber();
1329 initialCharge += G4lrint(collision->GetTargetCharge());
1330 if (!lateParticleCollision)
1331 {
1332 if( !products || products->size()==0 || !CheckPauliPrinciple(products) )
1333 {
1334#ifdef debug_BIC_ApplyCollision
1335 if (products) G4cout << " ======Failed Pauli =====" << G4endl;
1336 G4cerr << "G4BinaryCascade::ApplyCollision blocked"<<G4endl;
1337#endif
1338 Success=false;
1339 }
1340
1341
1342
1343 if (Success && primary->GetState() == G4KineticTrack::inside ) { // if the primary was outside, nothing to correct
1344 if (! CorrectShortlivedFinalsForFermi(products, initial_Efermi)){
1345 Success=false;
1346 }
1347 }
1348 }
1349
1350#ifdef debug_BIC_ApplyCollision
1351 DebugApplyCollision(collision, products);
1352#endif
1353
1354 if ( ! Success ){
1355 if (products) ClearAndDestroy(products);
1356 if ( decayCollision ) FindDecayCollision(primary); // for decay, sample new decay
1357 delete products;
1358 products=0;
1359 return false;
1360 }
1361
1362 G4int finalBaryon(0);
1363 G4int finalCharge(0);
1364 G4KineticTrackVector toFinalState;
1365 for(std::vector<G4KineticTrack *>::iterator i =products->begin(); i != products->end(); i++)
1366 {
1367 if ( ! lateParticleCollision )
1368 {
1369 (*i)->SetState(primary->GetState()); // decay may be anywhere!
1370 if ( (*i)->GetState() == G4KineticTrack::inside ){
1371 finalBaryon+=(*i)->GetDefinition()->GetBaryonNumber();
1372 finalCharge+=G4lrint((*i)->GetDefinition()->GetPDGCharge()/eplus);
1373 } else {
1374 G4double tin=0., tout=0.;
1375 if (((G4RKPropagation*)thePropagator)->GetSphereIntersectionTimes((*i),tin,tout) &&
1376 tin < 0 && tout > 0 )
1377 {
1378 PrintKTVector((*i),"particle inside marked not-inside");
1379 G4cout << "tin tout: " << tin << " " << tout << G4endl;
1380 }
1381 }
1382 } else {
1383 G4double tin=0., tout=0.;
1384 if (((G4RKPropagation*)thePropagator)->GetSphereIntersectionTimes((*i),tin,tout))
1385 {
1386 //G4cout << "tin tout: " << tin << " " << tout << G4endl;
1387 if ( tin > 0 )
1388 {
1389 (*i)->SetState(G4KineticTrack::outside);
1390 }
1391 else if ( tout > 0 )
1392 {
1393 (*i)->SetState(G4KineticTrack::inside);
1394 finalBaryon+=(*i)->GetDefinition()->GetBaryonNumber();
1395 finalCharge+=G4lrint((*i)->GetDefinition()->GetPDGCharge()/eplus);
1396 }
1397 else
1398 {
1399 (*i)->SetState(G4KineticTrack::gone_out);
1400 toFinalState.push_back((*i));
1401 }
1402 } else
1403 {
1404 (*i)->SetState(G4KineticTrack::miss_nucleus);
1405 //G4cout << " G4BC - miss -late Part- no intersection found " << G4endl;
1406 toFinalState.push_back((*i));
1407 }
1408
1409 }
1410 }
1411 if(!toFinalState.empty())
1412 {
1413 theFinalState.insert(theFinalState.end(),
1414 toFinalState.begin(),toFinalState.end());
1415 std::vector<G4KineticTrack *>::iterator iter1, iter2;
1416 for(iter1 = toFinalState.begin(); iter1 != toFinalState.end();
1417 ++iter1)
1418 {
1419 iter2 = std::find(products->begin(), products->end(),
1420 *iter1);
1421 if ( iter2 != products->end() ) products->erase(iter2);
1422 }
1423 theCollisionMgr->RemoveTracksCollisions(&toFinalState);
1424 }
1425
1426 //G4cout << " currentA, Z be4: " << currentA << " " << currentZ << G4endl;
1427 currentA += finalBaryon-initialBaryon;
1428 currentZ += finalCharge-initialCharge;
1429 //G4cout << " ApplyCollision currentA, Z aft: " << currentA << " " << currentZ << G4endl;
1430
1431 G4KineticTrackVector oldSecondaries;
1432 oldSecondaries.push_back(primary);
1433 primary->Hit();
1434
1435#ifdef debug_G4BinaryCascade
1436 if ( (finalBaryon-initialBaryon-lateBaryon) != 0 || (finalCharge-initialCharge-lateCharge) != 0 )
1437 {
1438 G4cout << "G4BinaryCascade: Error in Balancing: " << G4endl;
1439 G4cout << "initial/final baryon number, initial/final Charge "
1440 << initialBaryon <<" "<< finalBaryon <<" "
1441 << initialCharge <<" "<< finalCharge <<" "
1442 << " in Collision type: "<< typeid(*collision->GetGenerator()).name()
1443 << ", with number of products: "<< products->size() <<G4endl;
1444 G4cout << G4endl<<"Initial condition are these:"<<G4endl;
1445 G4cout << "proj: "<<collision->GetPrimary()->GetDefinition()->GetParticleName()<<G4endl;
1446 for(size_t it=0; it<collision->GetTargetCollection().size(); it++)
1447 {
1448 G4cout << "targ: "
1449 <<collision->GetTargetCollection()[it]->GetDefinition()->GetParticleName()<<G4endl;
1450 }
1451 PrintKTVector(&collision->GetTargetCollection(),std::string(" Target particles"));
1452 G4cout << G4endl<<G4endl;
1453 }
1454#endif
1455
1456 G4KineticTrackVector oldTarget = collision->GetTargetCollection();
1457 for(size_t ii=0; ii< oldTarget.size(); ii++)
1458 {
1459 oldTarget[ii]->Hit();
1460 }
1461
1462 UpdateTracksAndCollisions(&oldSecondaries, &oldTarget, products);
1463 std::for_each(oldSecondaries.begin(), oldSecondaries.end(), Delete<G4KineticTrack>());
1464 std::for_each(oldTarget.begin(), oldTarget.end(), Delete<G4KineticTrack>());
1465
1466 delete products;
1467 return true;
1468}
1469
1470
1471//----------------------------------------------------------------------------
1472G4bool G4BinaryCascade::Absorb()
1473//----------------------------------------------------------------------------
1474{
1475 // Do it in two step: cannot change theSecondaryList inside the first loop.
1476 G4Absorber absorber(theCutOnPAbsorb);
1477
1478 // Build the vector of G4KineticTracks that must be absorbed
1479 G4KineticTrackVector absorbList;
1480 std::vector<G4KineticTrack *>::iterator iter;
1481 // PrintKTVector(&theSecondaryList, " testing for Absorb" );
1482 for(iter = theSecondaryList.begin();
1483 iter != theSecondaryList.end(); ++iter)
1484 {
1485 G4KineticTrack * kt = *iter;
1486 if(kt->GetState() == G4KineticTrack::inside)// absorption happens only inside the nucleus
1487 {
1488 if(absorber.WillBeAbsorbed(*kt))
1489 {
1490 absorbList.push_back(kt);
1491 }
1492 }
1493 }
1494
1495 if(absorbList.empty())
1496 return false;
1497
1498 G4KineticTrackVector toDelete;
1499 for(iter = absorbList.begin(); iter != absorbList.end(); ++iter)
1500 {
1501 G4KineticTrack * kt = *iter;
1502 if(!absorber.FindAbsorbers(*kt, theTargetList))
1503 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade::Absorb(): Cannot absorb a particle.");
1504
1505 if(!absorber.FindProducts(*kt))
1506 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade::Absorb(): Cannot absorb a particle.");
1507
1508 G4KineticTrackVector * products = absorber.GetProducts();
1509 G4int maxLoopCount = 1000;
1510 while(!CheckPauliPrinciple(products) && --maxLoopCount>0) /* Loop checking, 31.08.2015, G.Folger */
1511 {
1512 ClearAndDestroy(products);
1513 if(!absorber.FindProducts(*kt))
1514 throw G4HadronicException(__FILE__, __LINE__,
1515 "G4BinaryCascade::Absorb(): Cannot absorb a particle.");
1516 }
1517 if ( --maxLoopCount < 0 ) throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade::Absorb(): Cannot absorb a particle.");
1518 // ------ debug
1519 // G4cerr << "Absorb CheckPauliPrinciple count= " << maxLoopCount << G4endl;
1520 // ------ end debug
1521 G4KineticTrackVector toRemove; // build a vector for UpdateTrack...
1522 toRemove.push_back(kt);
1523 toDelete.push_back(kt); // delete the track later
1524 G4KineticTrackVector * absorbers = absorber.GetAbsorbers();
1525 UpdateTracksAndCollisions(&toRemove, absorbers, products);
1526 ClearAndDestroy(absorbers);
1527 }
1528 ClearAndDestroy(&toDelete);
1529 return true;
1530}
1531
1532
1533
1534// Capture all p and n with Energy < theCutOnP
1535//----------------------------------------------------------------------------
1536G4bool G4BinaryCascade::Capture(G4bool verbose)
1537//----------------------------------------------------------------------------
1538{
1539 G4KineticTrackVector captured;
1540 G4bool capture = false;
1541 std::vector<G4KineticTrack *>::iterator i;
1542
1543 G4RKPropagation * RKprop=(G4RKPropagation *)thePropagator;
1544
1545 G4double capturedEnergy = 0;
1546 G4int particlesAboveCut=0;
1547 G4int particlesBelowCut=0;
1548 if ( verbose ) G4cout << " Capture: secondaries " << theSecondaryList.size() << G4endl;
1549 for(i = theSecondaryList.begin(); i != theSecondaryList.end(); ++i)
1550 {
1551 G4KineticTrack * kt = *i;
1552 if (verbose) G4cout << "Capture position, radius, state " <<kt->GetPosition().mag()<<" "<<theOuterRadius<<" "<<kt->GetState()<<G4endl;
1553 if(kt->GetState() == G4KineticTrack::inside) // capture happens only inside the nucleus
1554 {
1555 if((kt->GetDefinition() == G4Proton::Proton()) ||
1556 (kt->GetDefinition() == G4Neutron::Neutron()))
1557 {
1558 //GF cut on kinetic energy if(kt->Get4Momentum().vect().mag() >= theCutOnP)
1559 G4double field=RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition())
1560 -RKprop->GetBarrier(kt->GetDefinition()->GetPDGEncoding());
1561 G4double energy= kt->Get4Momentum().e() - kt->GetActualMass() + field;
1562 if (verbose ) G4cout << "Capture: .e(), mass, field, energy" << kt->Get4Momentum().e() <<" "<<kt->GetActualMass()<<" "<<field<<" "<<energy<< G4endl;
1563 // if( energy < theCutOnP )
1564 // {
1565 capturedEnergy+=energy;
1566 ++particlesBelowCut;
1567 // } else
1568 // {
1569 // ++particlesAboveCut;
1570 // }
1571 }
1572 }
1573 }
1574 if (verbose) G4cout << "Capture particlesAboveCut,particlesBelowCut, capturedEnergy,capturedEnergy/particlesBelowCut <? 0.2*theCutOnP "
1575 << particlesAboveCut << " " << particlesBelowCut << " " << capturedEnergy
1576 << " " << G4endl;
1577// << " " << (particlesBelowCut>0) ? (capturedEnergy/particlesBelowCut) : (capturedEnergy) << " " << 0.2*theCutOnP << G4endl;
1578 // if(particlesAboveCut==0 && particlesBelowCut>0 && capturedEnergy/particlesBelowCut<0.2*theCutOnP)
1579 if(particlesBelowCut>0 && capturedEnergy/particlesBelowCut<0.2*theCutOnP)
1580 {
1581 capture=true;
1582 for(i = theSecondaryList.begin(); i != theSecondaryList.end(); ++i)
1583 {
1584 G4KineticTrack * kt = *i;
1585 if(kt->GetState() == G4KineticTrack::inside) // capture happens only inside the nucleus
1586 {
1587 if((kt->GetDefinition() == G4Proton::Proton()) ||
1588 (kt->GetDefinition() == G4Neutron::Neutron()))
1589 {
1590 captured.push_back(kt);
1591 kt->Hit(); //
1592 theCapturedList.push_back(kt);
1593 }
1594 }
1595 }
1596 UpdateTracksAndCollisions(&captured, nullptr, nullptr);
1597 }
1598
1599 return capture;
1600}
1601
1602
1603//----------------------------------------------------------------------------
1604G4bool G4BinaryCascade::CheckPauliPrinciple(G4KineticTrackVector * products)
1605//----------------------------------------------------------------------------
1606{
1609
1610 G4FermiMomentum fermiMom;
1611 fermiMom.Init(A, Z);
1612
1614
1615 G4KineticTrackVector::iterator i;
1616 const G4ParticleDefinition * definition;
1617
1618 // ------ debug
1619 G4bool myflag = true;
1620 // ------ end debug
1621 // G4ThreeVector xpos(0);
1622 for(i = products->begin(); i != products->end(); ++i)
1623 {
1624 definition = (*i)->GetDefinition();
1625 if((definition == G4Proton::Proton()) ||
1626 (definition == G4Neutron::Neutron()))
1627 {
1628 G4ThreeVector pos = (*i)->GetPosition();
1629 G4double d = density->GetDensity(pos);
1630 // energy correspondiing to fermi momentum
1631 G4double eFermi = std::sqrt( sqr(fermiMom.GetFermiMomentum(d)) + (*i)->Get4Momentum().mag2() );
1632 if( definition == G4Proton::Proton() )
1633 {
1634 eFermi -= the3DNucleus->CoulombBarrier();
1635 }
1636 G4LorentzVector mom = (*i)->Get4Momentum();
1637 // ------ debug
1638 /*
1639 * G4cout << "p:[" << (1/MeV)*mom.x() << " " << (1/MeV)*mom.y() << " "
1640 * << (1/MeV)*mom.z() << "] |p3|:"
1641 * << (1/MeV)*mom.vect().mag() << " E:" << (1/MeV)*mom.t() << " ] m: "
1642 * << (1/MeV)*mom.mag() << " pos["
1643 * << (1/fermi)*pos.x() << " "<< (1/fermi)*pos.y() << " "
1644 * << (1/fermi)*pos.z() << "] |Dpos|: "
1645 * << (1/fermi)*(pos-xpos).mag() << " Pfermi:"
1646 * << (1/MeV)*p << G4endl;
1647 * xpos=pos;
1648 */
1649 // ------ end debug
1650 if(mom.e() < eFermi )
1651 {
1652 // ------ debug
1653 myflag = false;
1654 // ------ end debug
1655 // return false;
1656 }
1657 }
1658 }
1659#ifdef debug_BIC_CheckPauli
1660 if ( myflag )
1661 {
1662 for(i = products->begin(); i != products->end(); ++i)
1663 {
1664 definition = (*i)->GetDefinition();
1665 if((definition == G4Proton::Proton()) ||
1666 (definition == G4Neutron::Neutron()))
1667 {
1668 G4ThreeVector pos = (*i)->GetPosition();
1669 G4double d = density->GetDensity(pos);
1670 G4double pFermi = fermiMom.GetFermiMomentum(d);
1671 G4LorentzVector mom = (*i)->Get4Momentum();
1672 G4double field =((G4RKPropagation*)thePropagator)->GetField(definition->GetPDGEncoding(),pos);
1673 if ( mom.e()-mom.mag()+field > 160*MeV )
1674 {
1675 G4cout << "momentum problem pFermi=" << pFermi
1676 << " mom, mom.m " << mom << " " << mom.mag()
1677 << " field " << field << G4endl;
1678 }
1679 }
1680 }
1681 }
1682#endif
1683
1684 return myflag;
1685}
1686
1687//----------------------------------------------------------------------------
1688void G4BinaryCascade::StepParticlesOut()
1689//----------------------------------------------------------------------------
1690{
1691 G4int counter=0;
1692 G4int countreset=0;
1693 //G4cout << " nucl. Radius " << radius << G4endl;
1694 // G4cerr <<"pre-while- theSecondaryList "<<G4endl;
1695 while( theSecondaryList.size() > 0 ) /* Loop checking, 31.08.2015, G.Folger */
1696 // if countreset reaches limit, there is a break from while, see below.
1697 {
1698 G4double minTimeStep = 1.e-12*ns; // about 30*fermi/(0.1*c_light);1.e-12*ns
1699 // i.e. a big step
1700 std::vector<G4KineticTrack *>::iterator i;
1701 for(i = theSecondaryList.begin(); i != theSecondaryList.end(); ++i)
1702 {
1703 G4KineticTrack * kt = *i;
1704 if( kt->GetState() == G4KineticTrack::inside )
1705 {
1706 G4double tStep(0), tdummy(0);
1707 G4bool intersect =
1708 ((G4RKPropagation*)thePropagator)->GetSphereIntersectionTimes(kt,tdummy,tStep);
1709#ifdef debug_BIC_StepParticlesOut
1710 G4cout << " minTimeStep, tStep Particle " <<minTimeStep << " " <<tStep
1711 << " " <<kt->GetDefinition()->GetParticleName()
1712 << " 4mom " << kt->GetTrackingMomentum()<<G4endl;
1713 if ( ! intersect );
1714 {
1715 PrintKTVector(&theSecondaryList, std::string(" state ERROR....."));
1716 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade::StepParticlesOut() particle not in nucleus");
1717 }
1718#endif
1719 if(intersect && tStep<minTimeStep && tStep> 0 )
1720 {
1721 minTimeStep = tStep;
1722 }
1723 } else if ( kt->GetState() != G4KineticTrack::outside ){
1724 PrintKTVector(&theSecondaryList, std::string(" state ERROR....."));
1725 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade::StepParticlesOut() particle not in nucleus");
1726 }
1727 }
1728 minTimeStep *= 1.2;
1729 G4double timeToCollision=DBL_MAX;
1730 G4CollisionInitialState * nextCollision=0;
1731 if(theCollisionMgr->Entries() > 0)
1732 {
1733 nextCollision = theCollisionMgr->GetNextCollision();
1734 timeToCollision = nextCollision->GetCollisionTime()-theCurrentTime;
1735 // G4cout << " NextCollision * , Time= " << nextCollision << " " <<timeToCollision<< G4endl;
1736 }
1737 if ( timeToCollision > minTimeStep )
1738 {
1739 DoTimeStep(minTimeStep);
1740 ++counter;
1741 } else
1742 {
1743 if (!DoTimeStep(timeToCollision) )
1744 {
1745 // Check if nextCollision is still valid, ie. partcile did not leave nucleus
1746 if (theCollisionMgr->GetNextCollision() != nextCollision )
1747 {
1748 nextCollision = 0;
1749 }
1750 }
1751 // G4cerr <<"post- DoTimeStep 3"<<G4endl;
1752
1753 if(nextCollision)
1754 {
1755 if ( ApplyCollision(nextCollision))
1756 {
1757 // G4cout << "ApplyCollision sucess " << G4endl;
1758 } else
1759 {
1760 theCollisionMgr->RemoveCollision(nextCollision);
1761 }
1762 }
1763 }
1764
1765 if(countreset>100)
1766 {
1767#ifdef debug_G4BinaryCascade
1768 G4cerr << "G4BinaryCascade.cc: Warning - aborting looping particle(s)" << G4endl;
1769 PrintKTVector(&theSecondaryList," looping particles added to theFinalState");
1770#endif
1771
1772 // add left secondaries to FinalSate
1773 std::vector<G4KineticTrack *>::iterator iter;
1774 for ( iter =theSecondaryList.begin(); iter != theSecondaryList.end(); ++iter)
1775 {
1776 theFinalState.push_back(*iter);
1777 }
1778 theSecondaryList.clear();
1779
1780 break;
1781 }
1782
1783 if(Absorb())
1784 {
1785 // haveProducts = true;
1786 // G4cout << "Absorb sucess " << G4endl;
1787 }
1788
1789 if(Capture(false))
1790 {
1791 // haveProducts = true;
1792#ifdef debug_BIC_StepParticlesOut
1793 G4cout << "Capture sucess " << G4endl;
1794#endif
1795 }
1796 if ( counter > 100 && theCollisionMgr->Entries() == 0) // no collision, and stepping for some time....
1797 {
1798#ifdef debug_BIC_StepParticlesOut
1799 PrintKTVector(&theSecondaryList,std::string("stepping 100 steps"));
1800#endif
1801 FindCollisions(&theSecondaryList);
1802 counter=0;
1803 ++countreset;
1804 }
1805 //G4cout << "currentZ @ end loop " << currentZ << G4endl;
1806 if ( ! currentZ ){
1807 // nucleus completely destroyed, fill in ReactionProductVector
1808 // products = FillVoidNucleusProducts(products);
1809 #ifdef debug_BIC_return
1810 G4cout << "return @ Z=0 after collision loop "<< G4endl;
1811 PrintKTVector(&theSecondaryList,std::string(" theSecondaryList"));
1812 G4cout << "theTargetList size: " << theTargetList.size() << G4endl;
1813 PrintKTVector(&theTargetList,std::string(" theTargetList"));
1814 PrintKTVector(&theCapturedList,std::string(" theCapturedList"));
1815
1816 G4cout << " ExcitE be4 Correct : " <<GetExcitationEnergy() << G4endl;
1817 G4cout << " Mom Transfered to nucleus : " << theMomentumTransfer << " " << theMomentumTransfer.mag() << G4endl;
1818 PrintKTVector(&theFinalState,std::string(" FinalState uncorrected"));
1819 // G4cout << "returned products: " << products->size() << G4endl;
1820 #endif
1821 }
1822
1823 }
1824 // G4cerr <<"Finished capture loop "<<G4endl;
1825
1826 //G4cerr <<"pre- DoTimeStep 4"<<G4endl;
1827 DoTimeStep(DBL_MAX);
1828 //G4cerr <<"post- DoTimeStep 4"<<G4endl;
1829
1830
1831}
1832
1833//----------------------------------------------------------------------------
1834G4double G4BinaryCascade::CorrectShortlivedPrimaryForFermi(
1835 G4KineticTrack* primary,G4KineticTrackVector target_collection)
1836//----------------------------------------------------------------------------
1837{
1838 G4double Efermi(0);
1839 if (primary->GetState() == G4KineticTrack::inside ) {
1840 G4int PDGcode=primary->GetDefinition()->GetPDGEncoding();
1841 Efermi=((G4RKPropagation *)thePropagator)->GetField(PDGcode,primary->GetPosition());
1842
1843 if ( std::abs(PDGcode) > 1000 && PDGcode != 2112 && PDGcode != 2212 )
1844 {
1845 Efermi = ((G4RKPropagation *)thePropagator)->GetField(G4Neutron::Neutron()->GetPDGEncoding(),primary->GetPosition());
1846 G4LorentzVector mom4Primary=primary->Get4Momentum();
1847 primary->Update4Momentum(mom4Primary.e() - Efermi);
1848 }
1849
1850 std::vector<G4KineticTrack *>::iterator titer;
1851 for ( titer=target_collection.begin() ; titer!=target_collection.end(); ++titer)
1852 {
1853 const G4ParticleDefinition * aDef=(*titer)->GetDefinition();
1854 G4int aCode=aDef->GetPDGEncoding();
1855 G4ThreeVector aPos=(*titer)->GetPosition();
1856 Efermi+= ((G4RKPropagation *)thePropagator)->GetField(aCode, aPos);
1857 }
1858 }
1859 return Efermi;
1860}
1861
1862//----------------------------------------------------------------------------
1863G4bool G4BinaryCascade::CorrectShortlivedFinalsForFermi(G4KineticTrackVector * products,
1864 G4double initial_Efermi)
1865//----------------------------------------------------------------------------
1866{
1867 G4double final_Efermi(0);
1868 G4KineticTrackVector resonances;
1869 for ( std::vector<G4KineticTrack *>::iterator i =products->begin(); i != products->end(); i++)
1870 {
1871 G4int PDGcode=(*i)->GetDefinition()->GetPDGEncoding();
1872 // G4cout << " PDGcode, state " << PDGcode << " " << (*i)->GetState()<<G4endl;
1873 final_Efermi+=((G4RKPropagation *)thePropagator)->GetField(PDGcode,(*i)->GetPosition());
1874 if ( std::abs(PDGcode) > 1000 && PDGcode != 2112 && PDGcode != 2212 )
1875 {
1876 resonances.push_back(*i);
1877 }
1878 }
1879 if ( resonances.size() > 0 )
1880 {
1881 G4double delta_Fermi= (initial_Efermi-final_Efermi)/resonances.size();
1882 for (std::vector<G4KineticTrack *>::iterator res=resonances.begin(); res != resonances.end(); res++)
1883 {
1884 G4LorentzVector mom=(*res)->Get4Momentum();
1885 G4double mass2=mom.mag2();
1886 G4double newEnergy=mom.e() + delta_Fermi;
1887 G4double newEnergy2= newEnergy*newEnergy;
1888 //G4cout << "mom = " << mom <<" newE " << newEnergy<< G4endl;
1889 if ( newEnergy2 < mass2 )
1890 {
1891 return false;
1892 }
1893 G4ThreeVector mom3=std::sqrt(newEnergy2 - mass2) * mom.vect().unit();
1894 (*res)->Set4Momentum(G4LorentzVector(mom3,newEnergy));
1895 //G4cout << " correct resonance from /to " << mom.e() << " / " << newEnergy<<
1896 // " 3mom from/to " << mom.vect() << " / " << mom3 << G4endl;
1897 }
1898 }
1899 return true;
1900}
1901
1902//----------------------------------------------------------------------------
1903void G4BinaryCascade::CorrectFinalPandE()
1904//----------------------------------------------------------------------------
1905//
1906// Modify momenta of outgoing particles.
1907// Assume two body decay, nucleus(@nominal mass) + sum of final state particles(SFSP).
1908// momentum of SFSP shall be less than momentum for two body decay.
1909//
1910{
1911#ifdef debug_BIC_CorrectFinalPandE
1912 G4cerr << "BIC: -CorrectFinalPandE called" << G4endl;
1913#endif
1914
1915 if ( theFinalState.size() == 0 ) return;
1916
1917 G4KineticTrackVector::iterator i;
1918 G4LorentzVector pNucleus=GetFinal4Momentum();
1919 if ( pNucleus.e() == 0 ) return; // check against explicit 0 from GetNucleus4Momentum()
1920#ifdef debug_BIC_CorrectFinalPandE
1921 G4cerr << " -CorrectFinalPandE 3" << G4endl;
1922#endif
1923 G4LorentzVector pFinals(0);
1924 for(i = theFinalState.begin(); i != theFinalState.end(); ++i)
1925 {
1926 pFinals += (*i)->Get4Momentum();
1927#ifdef debug_BIC_CorrectFinalPandE
1928 G4cout <<"CorrectFinalPandE a final " << (*i)->GetDefinition()->GetParticleName()
1929 << " 4mom " << (*i)->Get4Momentum()<< G4endl;
1930#endif
1931 }
1932#ifdef debug_BIC_CorrectFinalPandE
1933 G4cout << "CorrectFinalPandE pN pF: " <<pNucleus << " " <<pFinals << G4endl;
1934#endif
1935 G4LorentzVector pCM=pNucleus + pFinals;
1936
1937 G4LorentzRotation toCMS(-pCM.boostVector());
1938 pFinals *=toCMS;
1939#ifdef debug_BIC_CorrectFinalPandE
1940 G4cout << "CorrectFinalPandE pCM, CMS pCM " << pCM << " " <<toCMS*pCM<< G4endl;
1941 G4cout << "CorrectFinal CMS pN pF " <<toCMS*pNucleus << " "
1942 <<pFinals << G4endl
1943 << " nucleus initial mass : " <<GetFinal4Momentum().mag()
1944 <<" massInNucleus m(nucleus) m(finals) std::sqrt(s): " << massInNucleus << " " <<pNucleus.mag()<< " "
1945 << pFinals.mag() << " " << pCM.mag() << G4endl;
1946#endif
1947
1948 G4LorentzRotation toLab = toCMS.inverse();
1949
1950 G4double s0 = pCM.mag2();
1951 G4double m10 = GetIonMass(currentZ,currentA);
1952 G4double m20 = pFinals.mag();
1953 if( s0-(m10+m20)*(m10+m20) < 0 )
1954 {
1955#ifdef debug_BIC_CorrectFinalPandE
1956 G4cout << "G4BinaryCascade::CorrectFinalPandE() : error! " << G4endl;
1957
1958 G4cout << "not enough mass to correct: mass^2, A,Z, mass(nucl), mass(finals) "
1959 << (s0-(m10+m20)*(m10+m20)) << " "
1960 << currentA << " " << currentZ << " "
1961 << m10 << " " << m20
1962 << G4endl;
1963 G4cerr << " -CorrectFinalPandE 4" << G4endl;
1964
1965 PrintKTVector(&theFinalState," mass problem");
1966#endif
1967 return;
1968 }
1969
1970 // Three momentum in cm system
1971 G4double pInCM = std::sqrt((s0-(m10+m20)*(m10+m20))*(s0-(m10-m20)*(m10-m20))/(4.*s0));
1972#ifdef debug_BIC_CorrectFinalPandE
1973 G4cout <<" CorrectFinalPandE pInCM new, CURRENT, ratio : " << pInCM
1974 << " " << (pFinals).vect().mag()<< " " << pInCM/(pFinals).vect().mag() << G4endl;
1975#endif
1976 if ( pFinals.vect().mag() > pInCM )
1977 {
1978 G4ThreeVector p3finals=pInCM*pFinals.vect().unit();
1979
1980 G4double factor=std::max(0.98,pInCM/pFinals.vect().mag()); // small correction
1981 G4LorentzVector qFinals(0);
1982 for(i = theFinalState.begin(); i != theFinalState.end(); ++i)
1983 {
1984 // G4ThreeVector p3((toCMS*(*i)->Get4Momentum()).vect() + deltap);
1985 G4ThreeVector p3(factor*(toCMS*(*i)->Get4Momentum()).vect());
1986 G4LorentzVector p(p3,std::sqrt((*i)->Get4Momentum().mag2() + p3.mag2()));
1987 qFinals += p;
1988 p *= toLab;
1989#ifdef debug_BIC_CorrectFinalPandE
1990 G4cout << " final p corrected: " << p << G4endl;
1991#endif
1992 (*i)->Set4Momentum(p);
1993 }
1994#ifdef debug_BIC_CorrectFinalPandE
1995 G4cout << "CorrectFinalPandE nucleus corrected mass : " << GetFinal4Momentum() << " "
1996 <<GetFinal4Momentum().mag() << G4endl
1997 << " CMS pFinals , mag, 3.mag : " << qFinals << " " << qFinals.mag() << " " << qFinals.vect().mag()<< G4endl;
1998 G4cerr << " -CorrectFinalPandE 5 " << factor << G4endl;
1999#endif
2000 }
2001#ifdef debug_BIC_CorrectFinalPandE
2002 else { G4cerr << " -CorrectFinalPandE 6 - no correction done" << G4endl; }
2003#endif
2004
2005}
2006
2007//----------------------------------------------------------------------------
2008void G4BinaryCascade::UpdateTracksAndCollisions(
2009 //----------------------------------------------------------------------------
2010 G4KineticTrackVector * oldSecondaries,
2011 G4KineticTrackVector * oldTarget,
2012 G4KineticTrackVector * newSecondaries)
2013{
2014 std::vector<G4KineticTrack *>::iterator iter1, iter2;
2015
2016 // remove old secondaries from the secondary list
2017 if(oldSecondaries)
2018 {
2019 if(!oldSecondaries->empty())
2020 {
2021 for(iter1 = oldSecondaries->begin(); iter1 != oldSecondaries->end();
2022 ++iter1)
2023 {
2024 iter2 = std::find(theSecondaryList.begin(), theSecondaryList.end(),
2025 *iter1);
2026 if ( iter2 != theSecondaryList.end() ) theSecondaryList.erase(iter2);
2027 }
2028 theCollisionMgr->RemoveTracksCollisions(oldSecondaries);
2029 }
2030 }
2031
2032 // remove old target from the target list
2033 if(oldTarget)
2034 {
2035 // G4cout << "################## Debugging 0 "<<G4endl;
2036 if(oldTarget->size()!=0)
2037 {
2038
2039 // G4cout << "################## Debugging 1 "<<oldTarget->size()<<G4endl;
2040 for(iter1 = oldTarget->begin(); iter1 != oldTarget->end(); ++iter1)
2041 {
2042 iter2 = std::find(theTargetList.begin(), theTargetList.end(),
2043 *iter1);
2044 theTargetList.erase(iter2);
2045 }
2046 theCollisionMgr->RemoveTracksCollisions(oldTarget);
2047 }
2048 }
2049
2050 if(newSecondaries)
2051 {
2052 if(!newSecondaries->empty())
2053 {
2054 // insert new secondaries in the secondary list
2055 for(iter1 = newSecondaries->begin(); iter1 != newSecondaries->end();
2056 ++iter1)
2057 {
2058 theSecondaryList.push_back(*iter1);
2059 if ((*iter1)->GetState() == G4KineticTrack::undefined)
2060 {
2061 PrintKTVector(*iter1, "undefined in FindCollisions");
2062 }
2063
2064
2065 }
2066 // look for collisions of new secondaries
2067 FindCollisions(newSecondaries);
2068 }
2069 }
2070 // G4cout << "Exiting ... "<<oldTarget<<G4endl;
2071}
2072
2073
2075{
2076private:
2078 G4KineticTrack::CascadeState wanted_state;
2079public:
2081 :
2082 ktv(out), wanted_state(astate)
2083 {};
2084 void operator() (G4KineticTrack *& kt) const
2085 {
2086 if ( (kt)->GetState() == wanted_state ) ktv->push_back(kt);
2087 };
2088};
2089
2090
2091
2092//----------------------------------------------------------------------------
2093G4bool G4BinaryCascade::DoTimeStep(G4double theTimeStep)
2094//----------------------------------------------------------------------------
2095{
2096
2097#ifdef debug_BIC_DoTimeStep
2098 G4ping debug("debug_G4BinaryCascade");
2099 debug.push_back("======> DoTimeStep 1"); debug.dump();
2100 G4cerr <<"G4BinaryCascade::DoTimeStep: enter step="<< theTimeStep
2101 << " , time="<<theCurrentTime << G4endl;
2102 PrintKTVector(&theSecondaryList, std::string("DoTimeStep - theSecondaryList"));
2103 //PrintKTVector(&theTargetList, std::string("DoTimeStep - theTargetList"));
2104#endif
2105
2106 G4bool success=true;
2107 std::vector<G4KineticTrack *>::iterator iter;
2108
2109 G4KineticTrackVector * kt_outside = new G4KineticTrackVector;
2110 std::for_each( theSecondaryList.begin(),theSecondaryList.end(),
2112 //PrintKTVector(kt_outside, std::string("DoTimeStep - found outside"));
2113
2115 std::for_each( theSecondaryList.begin(),theSecondaryList.end(),
2117 // PrintKTVector(kt_inside, std::string("DoTimeStep - found inside"));
2118 //-----
2119 G4KineticTrackVector dummy; // needed for re-usability
2120#ifdef debug_BIC_DoTimeStep
2121 G4cout << "NOW WE ARE ENTERING THE TRANSPORT"<<G4endl;
2122#endif
2123
2124 // =================== Here we move the particles ===================
2125
2126 thePropagator->Transport(theSecondaryList, dummy, theTimeStep);
2127
2128 // =================== Here we move the particles ===================
2129
2130 //------
2131
2132 theMomentumTransfer += thePropagator->GetMomentumTransfer();
2133#ifdef debug_BIC_DoTimeStep
2134 G4cout << "DoTimeStep : theMomentumTransfer = " << theMomentumTransfer << G4endl;
2135 PrintKTVector(&theSecondaryList, std::string("DoTimeStep - secondaries aft trsprt"));
2136#endif
2137
2138 //_DebugEpConservation(" after stepping");
2139
2140 // Partclies which went INTO nucleus
2141
2142 G4KineticTrackVector * kt_gone_in = new G4KineticTrackVector;
2143 std::for_each( kt_outside->begin(),kt_outside->end(),
2145 // PrintKTVector(kt_gone_in, std::string("DoTimeStep - gone in"));
2146
2147
2148 // Partclies which went OUT OF nucleus
2149 G4KineticTrackVector * kt_gone_out = new G4KineticTrackVector;
2150 std::for_each( kt_inside->begin(),kt_inside->end(),
2152
2153 // PrintKTVector(kt_gone_out, std::string("DoTimeStep - gone out"));
2154
2155 G4KineticTrackVector *fail=CorrectBarionsOnBoundary(kt_gone_in,kt_gone_out);
2156
2157 if ( fail )
2158 {
2159 // some particle(s) supposed to enter/leave were miss_nucleus/captured by the correction
2160 kt_gone_in->clear();
2161 std::for_each( kt_outside->begin(),kt_outside->end(),
2163
2164 kt_gone_out->clear();
2165 std::for_each( kt_inside->begin(),kt_inside->end(),
2167
2168#ifdef debug_BIC_DoTimeStep
2169 PrintKTVector(fail,std::string(" Failed to go in/out -> miss_nucleus/captured"));
2170 PrintKTVector(kt_gone_in, std::string("recreated kt_gone_in"));
2171 PrintKTVector(kt_gone_out, std::string("recreated kt_gone_out"));
2172#endif
2173 delete fail;
2174 }
2175
2176 // Add tracks missing nucleus and tracks going straight though to addFinals
2177 std::for_each( kt_outside->begin(),kt_outside->end(),
2179 //PrintKTVector(kt_gone_out, std::string("miss to append to final state.."));
2180 std::for_each( kt_outside->begin(),kt_outside->end(),
2182
2183#ifdef debug_BIC_DoTimeStep
2184 PrintKTVector(kt_gone_out, std::string("append gone_outs to final state.. theFinalState"));
2185#endif
2186
2187 theFinalState.insert(theFinalState.end(),
2188 kt_gone_out->begin(),kt_gone_out->end());
2189
2190 // Partclies which could not leave nucleus, captured...
2191 G4KineticTrackVector * kt_captured = new G4KineticTrackVector;
2192 std::for_each( theSecondaryList.begin(),theSecondaryList.end(),
2194
2195 // Check no track is part in next collision, ie.
2196 // this step was to far, and collisions should not occur any more
2197
2198 if ( theCollisionMgr->Entries()> 0 )
2199 {
2200 if (kt_gone_out->size() )
2201 {
2202 G4KineticTrack * nextPrimary = theCollisionMgr->GetNextCollision()->GetPrimary();
2203 iter = std::find(kt_gone_out->begin(),kt_gone_out->end(),nextPrimary);
2204 if ( iter != kt_gone_out->end() )
2205 {
2206 success=false;
2207#ifdef debug_BIC_DoTimeStep
2208 G4cout << " DoTimeStep - WARNING: deleting current collision!" << G4endl;
2209#endif
2210 }
2211 }
2212 if ( kt_captured->size() )
2213 {
2214 G4KineticTrack * nextPrimary = theCollisionMgr->GetNextCollision()->GetPrimary();
2215 iter = std::find(kt_captured->begin(),kt_captured->end(),nextPrimary);
2216 if ( iter != kt_captured->end() )
2217 {
2218 success=false;
2219#ifdef debug_BIC_DoTimeStep
2220 G4cout << " DoTimeStep - WARNING: deleting current collision!" << G4endl;
2221#endif
2222 }
2223 }
2224
2225 }
2226 // PrintKTVector(kt_gone_out," kt_gone_out be4 updatetrack...");
2227 UpdateTracksAndCollisions(kt_gone_out,0 ,0);
2228
2229
2230 if ( kt_captured->size() )
2231 {
2232 theCapturedList.insert(theCapturedList.end(),
2233 kt_captured->begin(),kt_captured->end());
2234 //should be std::for_each(kt_captured->begin(),kt_captured->end(),
2235 // std::mem_fun(&G4KineticTrack::Hit));
2236 // but VC 6 requires:
2237 std::vector<G4KineticTrack *>::iterator i_captured;
2238 for(i_captured=kt_captured->begin();i_captured!=kt_captured->end();i_captured++)
2239 {
2240 (*i_captured)->Hit();
2241 }
2242 // PrintKTVector(kt_captured," kt_captured be4 updatetrack...");
2243 UpdateTracksAndCollisions(kt_captured, nullptr, nullptr);
2244 }
2245
2246#ifdef debug_G4BinaryCascade
2247 delete kt_inside;
2248 kt_inside = new G4KineticTrackVector;
2249 std::for_each( theSecondaryList.begin(),theSecondaryList.end(),
2251 if ( currentZ != (GetTotalCharge(theTargetList)
2252 + GetTotalCharge(theCapturedList)
2253 + GetTotalCharge(*kt_inside)) )
2254 {
2255 G4cout << " error-DoTimeStep aft, A, Z: " << currentA << " " << currentZ
2256 << " sum(tgt,capt,active) "
2257 << GetTotalCharge(theTargetList) + GetTotalCharge(theCapturedList) + GetTotalCharge(*kt_inside)
2258 << " targets: " << GetTotalCharge(theTargetList)
2259 << " captured: " << GetTotalCharge(theCapturedList)
2260 << " active: " << GetTotalCharge(*kt_inside)
2261 << G4endl;
2262 }
2263#endif
2264
2265 delete kt_inside;
2266 delete kt_outside;
2267 delete kt_captured;
2268 delete kt_gone_in;
2269 delete kt_gone_out;
2270
2271 // G4cerr <<"G4BinaryCascade::DoTimeStep: exit "<<G4endl;
2272 theCurrentTime += theTimeStep;
2273
2274 //debug.push_back("======> DoTimeStep 2"); debug.dump();
2275 return success;
2276
2277}
2278
2279//----------------------------------------------------------------------------
2280G4KineticTrackVector* G4BinaryCascade::CorrectBarionsOnBoundary(
2283//----------------------------------------------------------------------------
2284{
2285 G4KineticTrackVector * kt_fail(0);
2286 std::vector<G4KineticTrack *>::iterator iter;
2287 // G4cout << "CorrectBarionsOnBoundary,currentZ,currentA,"
2288 // << currentZ << " "<< currentA << G4endl;
2289 if (in->size())
2290 {
2291 G4int secondaries_in(0);
2292 G4int secondaryBarions_in(0);
2293 G4int secondaryCharge_in(0);
2294 G4double secondaryMass_in(0);
2295
2296 for ( iter =in->begin(); iter != in->end(); ++iter)
2297 {
2298 ++secondaries_in;
2299 secondaryCharge_in += G4lrint((*iter)->GetDefinition()->GetPDGCharge()/eplus);
2300 if ((*iter)->GetDefinition()->GetBaryonNumber()!=0 )
2301 {
2302 secondaryBarions_in += (*iter)->GetDefinition()->GetBaryonNumber();
2303 if((*iter)->GetDefinition() == G4Neutron::Neutron() ||
2304 (*iter)->GetDefinition() == G4Proton::Proton() )
2305 {
2306 secondaryMass_in += (*iter)->GetDefinition()->GetPDGMass();
2307 } else {
2308 secondaryMass_in += G4Proton::Proton()->GetPDGMass();
2309 }
2310 }
2311 }
2312 G4double mass_initial= GetIonMass(currentZ,currentA);
2313
2314 currentZ += secondaryCharge_in;
2315 currentA += secondaryBarions_in;
2316
2317 // G4cout << "CorrectBarionsOnBoundary,secondaryCharge_in, secondaryBarions_in "
2318 // << secondaryCharge_in << " "<< secondaryBarions_in << G4endl;
2319
2320 G4double mass_final= GetIonMass(currentZ,currentA);
2321
2322 G4double correction= secondaryMass_in + mass_initial - mass_final;
2323 if (secondaries_in>1)
2324 {correction /= secondaries_in;}
2325
2326#ifdef debug_BIC_CorrectBarionsOnBoundary
2327 G4cout << "CorrectBarionsOnBoundary,currentZ,currentA,"
2328 << "secondaryCharge_in,secondaryBarions_in,"
2329 << "energy correction,m_secondry,m_nucl_init,m_nucl_final "
2330 << currentZ << " "<< currentA <<" "
2331 << secondaryCharge_in<<" "<<secondaryBarions_in<<" "
2332 << correction << " "
2333 << secondaryMass_in << " "
2334 << mass_initial << " "
2335 << mass_final << " "
2336 << G4endl;
2337 PrintKTVector(in,std::string("in be4 correction"));
2338#endif
2339 for ( iter = in->begin(); iter != in->end(); ++iter)
2340 {
2341 if ((*iter)->GetTrackingMomentum().e()+correction > (*iter)->GetActualMass())
2342 {
2343 (*iter)->UpdateTrackingMomentum((*iter)->GetTrackingMomentum().e() + correction);
2344 } else {
2345 //particle cannot go in, put to miss_nucleus
2346 G4RKPropagation * RKprop=(G4RKPropagation *)thePropagator;
2347 (*iter)->SetState(G4KineticTrack::miss_nucleus);
2348 // Undo correction for Colomb Barrier
2349 G4double barrier=RKprop->GetBarrier((*iter)->GetDefinition()->GetPDGEncoding());
2350 (*iter)->UpdateTrackingMomentum((*iter)->GetTrackingMomentum().e() + barrier);
2351 if ( ! kt_fail ) kt_fail=new G4KineticTrackVector;
2352 kt_fail->push_back(*iter);
2353 currentZ -= G4lrint((*iter)->GetDefinition()->GetPDGCharge()/eplus);
2354 currentA -= (*iter)->GetDefinition()->GetBaryonNumber();
2355
2356 }
2357
2358 }
2359#ifdef debug_BIC_CorrectBarionsOnBoundary
2360 G4cout << " CorrectBarionsOnBoundary, aft, Z, A, sec-Z,A,m,m_in_nucleus "
2361 << currentZ << " " << currentA << " "
2362 << secondaryCharge_in << " " << secondaryBarions_in << " "
2363 << secondaryMass_in << " "
2364 << G4endl;
2365 PrintKTVector(in,std::string("in AFT correction"));
2366#endif
2367
2368 }
2369 //----------------------------------------------
2370 if (out->size())
2371 {
2372 G4int secondaries_out(0);
2373 G4int secondaryBarions_out(0);
2374 G4int secondaryCharge_out(0);
2375 G4double secondaryMass_out(0);
2376
2377 for ( iter =out->begin(); iter != out->end(); ++iter)
2378 {
2379 ++secondaries_out;
2380 secondaryCharge_out += G4lrint((*iter)->GetDefinition()->GetPDGCharge()/eplus);
2381 if ((*iter)->GetDefinition()->GetBaryonNumber() !=0 )
2382 {
2383 secondaryBarions_out += (*iter)->GetDefinition()->GetBaryonNumber();
2384 if((*iter)->GetDefinition() == G4Neutron::Neutron() ||
2385 (*iter)->GetDefinition() == G4Proton::Proton() )
2386 {
2387 secondaryMass_out += (*iter)->GetDefinition()->GetPDGMass();
2388 } else {
2389 secondaryMass_out += G4Neutron::Neutron()->GetPDGMass();
2390 }
2391 }
2392 }
2393
2394 G4double mass_initial= GetIonMass(currentZ,currentA);
2395 currentA -=secondaryBarions_out;
2396 currentZ -=secondaryCharge_out;
2397
2398 // G4cout << "CorrectBarionsOnBoundary,secondaryCharge_out, secondaryBarions_out "
2399 // << secondaryCharge_out << " "<< secondaryBarions_out << G4endl;
2400
2401 // a delta minus will do currentZ < 0 in light nuclei
2402 // if (currentA < 0 || currentZ < 0 )
2403 if (currentA < 0 )
2404 {
2405 G4cerr << "G4BinaryCascade - secondaryBarions_out,secondaryCharge_out " <<
2406 secondaryBarions_out << " " << secondaryCharge_out << G4endl;
2407 PrintKTVector(&theTargetList,"CorrectBarionsOnBoundary Target");
2408 PrintKTVector(&theCapturedList,"CorrectBarionsOnBoundary Captured");
2409 PrintKTVector(&theSecondaryList,"CorrectBarionsOnBoundary Secondaries");
2410 G4cerr << "G4BinaryCascade - currentA, currentZ " << currentA << " " << currentZ << G4endl;
2411 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade::CorrectBarionsOnBoundary() - fatal error");
2412 }
2413 G4double mass_final=GetIonMass(currentZ,currentA);
2414 G4double correction= mass_initial - mass_final - secondaryMass_out;
2415 // G4cout << "G4BinaryCascade::CorrectBarionsOnBoundary() total out correction: " << correction << G4endl;
2416
2417 if (secondaries_out>1) correction /= secondaries_out;
2418#ifdef debug_BIC_CorrectBarionsOnBoundary
2419 G4cout << "DoTimeStep,(current Z,A),"
2420 << "(secondaries out,Charge,Barions),"
2421 <<"* energy correction,(m_secondry,m_nucl_init,m_nucl_final) "
2422 << "("<< currentZ << ","<< currentA <<") ("
2423 << secondaries_out << ","
2424 << secondaryCharge_out<<","<<secondaryBarions_out<<") * "
2425 << correction << " ("
2426 << secondaryMass_out << ", "
2427 << mass_initial << ", "
2428 << mass_final << ")"
2429 << G4endl;
2430 PrintKTVector(out,std::string("out be4 correction"));
2431#endif
2432
2433 for ( iter = out->begin(); iter != out->end(); ++iter)
2434 {
2435 if ((*iter)->GetTrackingMomentum().e()+correction > (*iter)->GetActualMass())
2436 {
2437 (*iter)->UpdateTrackingMomentum((*iter)->GetTrackingMomentum().e() + correction);
2438 } else
2439 {
2440 // particle cannot go out due to change of nuclear potential!
2441 // capture protons and neutrons;
2442 if(((*iter)->GetDefinition() == G4Proton::Proton()) ||
2443 ((*iter)->GetDefinition() == G4Neutron::Neutron()))
2444 {
2445 (*iter)->SetState(G4KineticTrack::captured);
2446 // Undo correction for Colomb Barrier
2447 G4double barrier=((G4RKPropagation *)thePropagator)->GetBarrier((*iter)->GetDefinition()->GetPDGEncoding());
2448 (*iter)->UpdateTrackingMomentum((*iter)->GetTrackingMomentum().e() - barrier);
2449 if ( kt_fail == 0 ) kt_fail=new G4KineticTrackVector;
2450 kt_fail->push_back(*iter);
2451 currentZ += G4lrint((*iter)->GetDefinition()->GetPDGCharge()/eplus);
2452 currentA += (*iter)->GetDefinition()->GetBaryonNumber();
2453 }
2454#ifdef debug_BIC_CorrectBarionsOnBoundary
2455 else
2456 {
2457 G4cout << "Not correcting outgoing " << *iter << " "
2458 << (*iter)->GetDefinition()->GetPDGEncoding() << " "
2459 << (*iter)->GetDefinition()->GetParticleName() << G4endl;
2460 PrintKTVector(out,std::string("outgoing, one not corrected"));
2461 }
2462#endif
2463 }
2464 }
2465
2466#ifdef debug_BIC_CorrectBarionsOnBoundary
2467 PrintKTVector(out,std::string("out AFTER correction"));
2468 G4cout << " DoTimeStep, nucl-update, A, Z, sec-Z,A,m,m_in_nucleus, table-mass, delta "
2469 << currentA << " "<< currentZ << " "
2470 << secondaryCharge_out << " "<< secondaryBarions_out << " "<<
2471 secondaryMass_out << " "
2472 << massInNucleus << " "
2473 << GetIonMass(currentZ,currentA)
2474 << " " << massInNucleus - GetIonMass(currentZ,currentA)
2475 << G4endl;
2476#endif
2477 }
2478
2479 return kt_fail;
2480}
2481
2482
2483//----------------------------------------------------------------------------
2484
2485G4Fragment * G4BinaryCascade::FindFragments()
2486//----------------------------------------------------------------------------
2487{
2488
2489#ifdef debug_BIC_FindFragments
2490 G4cout << "target, captured, secondary: "
2491 << theTargetList.size() << " "
2492 << theCapturedList.size()<< " "
2493 << theSecondaryList.size()
2494 << G4endl;
2495#endif
2496
2497 G4int a = G4int(theTargetList.size()+theCapturedList.size());
2498 G4int zTarget = 0;
2499 G4KineticTrackVector::iterator i;
2500 for(i = theTargetList.begin(); i != theTargetList.end(); ++i)
2501 {
2502 if(G4lrint((*i)->GetDefinition()->GetPDGCharge()/eplus) == 1 )
2503 {
2504 zTarget++;
2505 }
2506 }
2507
2508 G4int zCaptured = 0;
2509 G4LorentzVector CapturedMomentum(0.,0.,0.,0.);
2510 for(i = theCapturedList.begin(); i != theCapturedList.end(); ++i)
2511 {
2512 CapturedMomentum += (*i)->Get4Momentum();
2513 if(G4lrint((*i)->GetDefinition()->GetPDGCharge()/eplus) == 1 )
2514 {
2515 zCaptured++;
2516 }
2517 }
2518
2519 G4int z = zTarget+zCaptured;
2520
2521#ifdef debug_G4BinaryCascade
2522 if ( z != (GetTotalCharge(theTargetList) + GetTotalCharge(theCapturedList)) )
2523 {
2524 G4cout << " FindFragment Counting error z a " << z << " " <<a << " "
2525 << GetTotalCharge(theTargetList) << " " << GetTotalCharge(theCapturedList)<<
2526 G4endl;
2527 PrintKTVector(&theTargetList, std::string("theTargetList"));
2528 PrintKTVector(&theCapturedList, std::string("theCapturedList"));
2529 }
2530#endif
2531 //debug
2532 /*
2533 * G4cout << " Fragment mass table / real "
2534 * << GetIonMass(z, a)
2535 * << " / " << GetFinal4Momentum().mag()
2536 * << " difference "
2537 * << GetFinal4Momentum().mag() - GetIonMass(z, a)
2538 * << G4endl;
2539 */
2540 //
2541 // if(fBCDEBUG) G4cerr << "Fragment A, Z "<< a <<" "<< z<<G4endl;
2542 if ( z < 1 ) return 0;
2543
2544 G4int holes = G4int(the3DNucleus->GetMassNumber() - theTargetList.size());
2545 G4int excitons = (G4int)theCapturedList.size();
2546#ifdef debug_BIC_FindFragments
2547 G4cout << "Fragment: a= " << a << " z= " << z << " particles= " << excitons
2548 << " Charged= " << zCaptured << " holes= " << holes
2549 << " excitE= " <<GetExcitationEnergy()
2550 << " Final4Momentum= " << GetFinalNucleusMomentum() << " capturMomentum= " << CapturedMomentum
2551 << G4endl;
2552#endif
2553
2554 G4Fragment * fragment = new G4Fragment(a,z,GetFinalNucleusMomentum());
2555 fragment->SetNumberOfHoles(holes);
2556
2557 //GF fragment->SetNumberOfParticles(excitons-holes);
2558 fragment->SetNumberOfParticles(excitons);
2559 fragment->SetNumberOfCharged(zCaptured);
2560 fragment->SetCreatorModelID(theBIC_ID);
2561
2562 return fragment;
2563}
2564
2565//----------------------------------------------------------------------------
2566
2567G4LorentzVector G4BinaryCascade::GetFinal4Momentum()
2568//----------------------------------------------------------------------------
2569// Return momentum of reminder nulceus;
2570// ie. difference of (initial state(primaries+nucleus) - final state) particles, ignoring remnant nucleus
2571{
2572 G4LorentzVector final4Momentum = theInitial4Mom + theProjectile4Momentum;
2573 G4LorentzVector finals(0,0,0,0);
2574 for(G4KineticTrackVector::iterator i = theFinalState.begin(); i != theFinalState.end(); ++i)
2575 {
2576 final4Momentum -= (*i)->Get4Momentum();
2577 finals += (*i)->Get4Momentum();
2578 }
2579
2580 if(final4Momentum.e()> 0 && (final4Momentum.vect()/final4Momentum.e()).mag()>1.0 && currentA > 0)
2581 {
2582#ifdef debug_BIC_Final4Momentum
2583 G4cerr << G4endl;
2584 G4cerr << "G4BinaryCascade::GetFinal4Momentum - Fatal"<<G4endl;
2585 G4KineticTrackVector::iterator i;
2586 G4cerr <<"Total initial 4-momentum " << theProjectile4Momentum << G4endl;
2587 G4cerr <<" GetFinal4Momentum: Initial nucleus "<<theInitial4Mom<<G4endl;
2588 for(i = theFinalState.begin(); i != theFinalState.end(); ++i)
2589 {
2590 G4cerr <<" Final state: "<<(*i)->Get4Momentum()<<(*i)->GetDefinition()->GetParticleName()<<G4endl;
2591 }
2592 G4cerr << "Sum( 4-mom ) finals " << finals << G4endl;
2593 G4cerr<< " Final4Momentum = "<<final4Momentum <<" "<<final4Momentum.m()<<G4endl;
2594 G4cerr <<" current A, Z = "<< currentA<<", "<<currentZ<<G4endl;
2595 G4cerr << G4endl;
2596#endif
2597
2598 final4Momentum=G4LorentzVector(0,0,0,0);
2599 }
2600 return final4Momentum;
2601}
2602
2603//----------------------------------------------------------------------------
2604G4LorentzVector G4BinaryCascade::GetFinalNucleusMomentum()
2605//----------------------------------------------------------------------------
2606{
2607 // return momentum of nucleus for use with precompound model; also keep transformation to
2608 // apply to precompoud products.
2609
2610 G4LorentzVector CapturedMomentum(0,0,0,0);
2611 G4KineticTrackVector::iterator i;
2612 // G4cout << "GetFinalNucleusMomentum Captured size: " <<theCapturedList.size() << G4endl;
2613 for(i = theCapturedList.begin(); i != theCapturedList.end(); ++i)
2614 {
2615 CapturedMomentum += (*i)->Get4Momentum();
2616 }
2617 //G4cout << "GetFinalNucleusMomentum CapturedMomentum= " <<CapturedMomentum << G4endl;
2618 // G4cerr << "it 9"<<G4endl;
2619
2620 G4LorentzVector NucleusMomentum = GetFinal4Momentum();
2621 if ( NucleusMomentum.e() > 0 )
2622 {
2623 // G4cout << "GetFinalNucleusMomentum GetFinal4Momentum= " <<NucleusMomentum <<" "<<NucleusMomentum.mag()<<G4endl;
2624 // boost nucleus to a frame such that the momentum of nucleus == momentum of Captured
2625 G4ThreeVector boost= (NucleusMomentum.vect() -CapturedMomentum.vect())/NucleusMomentum.e();
2626 if(boost.mag2()>1.0)
2627 {
2628# ifdef debug_BIC_FinalNucleusMomentum
2629 G4cerr << "G4BinaryCascade::GetFinalNucleusMomentum - Fatal"<<G4endl;
2630 G4cerr << "it 0"<<boost <<G4endl;
2631 G4cerr << "it 01"<<NucleusMomentum<<" "<<CapturedMomentum<<" "<<G4endl;
2632 G4cout <<" testing boost "<<boost<<" "<<boost.mag()<<G4endl;
2633# endif
2634 boost=G4ThreeVector(0,0,0);
2635 NucleusMomentum=G4LorentzVector(0,0,0,0);
2636 }
2637 G4LorentzRotation nucleusBoost( -boost );
2638 precompoundLorentzboost.set( boost );
2639#ifdef debug_debug_BIC_FinalNucleusMomentum
2640 G4cout << "GetFinalNucleusMomentum be4 boostNucleusMomentum, CapturedMomentum"<<NucleusMomentum<<" "<<CapturedMomentum<<" "<<G4endl;
2641#endif
2642 NucleusMomentum *= nucleusBoost;
2643#ifdef debug_BIC_FinalNucleusMomentum
2644 G4cout << "GetFinalNucleusMomentum aft boost GetFinal4Momentum= " <<NucleusMomentum <<G4endl;
2645#endif
2646 }
2647 return NucleusMomentum;
2648}
2649
2650//----------------------------------------------------------------------------
2651G4ReactionProductVector * G4BinaryCascade::Propagate1H1(
2652 //----------------------------------------------------------------------------
2653 G4KineticTrackVector * secondaries, G4V3DNucleus * nucleus)
2654{
2657 if (nucleus->GetCharge() == 0) aHTarg = G4Neutron::NeutronDefinition();
2658 G4double mass = aHTarg->GetPDGMass();
2659 G4KineticTrackVector * secs = 0;
2660 G4ThreeVector pos(0,0,0);
2661 G4LorentzVector mom(mass);
2662 G4KineticTrack aTarget(aHTarg, 0., pos, mom);
2663 G4bool done(false);
2664 std::vector<G4KineticTrack *>::iterator iter, jter;
2665 // data member static G4Scatterer theH1Scatterer;
2666 //G4cout << " start 1H1 for " << (*secondaries).front()->GetDefinition()->GetParticleName()
2667 // << " on " << aHTarg->GetParticleName() << G4endl;
2668 G4int tryCount(0);
2669 while(!done && tryCount++ <200) /* Loop checking, 31.08.2015, G.Folger */
2670 {
2671 if(secs)
2672 {
2673 std::for_each(secs->begin(), secs->end(), DeleteKineticTrack());
2674 delete secs;
2675 }
2676 secs = theH1Scatterer->Scatter(*(*secondaries).front(), aTarget);
2677#ifdef debug_H1_BinaryCascade
2678 PrintKTVector(secs," From Scatter");
2679#endif
2680 for(size_t ss=0; secs && ss<secs->size(); ss++)
2681 {
2682 // must have one resonance in final state, or it was elastic, not allowed here.
2683 if((*secs)[ss]->GetDefinition()->IsShortLived()) done = true;
2684 }
2685 }
2686
2687 ClearAndDestroy(&theFinalState);
2688 ClearAndDestroy(secondaries);
2689 delete secondaries;
2690
2691 for(size_t current=0; secs && current<secs->size(); current++)
2692 {
2693 if((*secs)[current]->GetDefinition()->IsShortLived())
2694 {
2695 done = true; // must have one resonance in final state, elastic not allowed here!
2696 G4KineticTrackVector * dec = (*secs)[current]->Decay();
2697 for(jter=dec->begin(); jter != dec->end(); jter++)
2698 {
2699 //G4cout << "Decay"<<G4endl;
2700 secs->push_back(*jter);
2701 //G4cout << "decay "<<(*jter)->GetDefinition()->GetParticleName()<<G4endl;
2702 }
2703 delete (*secs)[current];
2704 delete dec;
2705 }
2706 else
2707 {
2708 //G4cout << "FS "<<G4endl;
2709 //G4cout << "FS "<<(*secs)[current]->GetDefinition()->GetParticleName()<<G4endl;
2710 theFinalState.push_back((*secs)[current]);
2711 }
2712 }
2713
2714 delete secs;
2715#ifdef debug_H1_BinaryCascade
2716 PrintKTVector(&theFinalState," FinalState");
2717#endif
2718 for(iter = theFinalState.begin(); iter != theFinalState.end(); ++iter)
2719 {
2720 G4KineticTrack * kt = *iter;
2722 aNew->SetMomentum(kt->Get4Momentum().vect());
2723 aNew->SetTotalEnergy(kt->Get4Momentum().e());
2724 aNew->SetCreatorModelID(theBIC_ID);
2727 products->push_back(aNew);
2728#ifdef debug_H1_BinaryCascade
2729 if (! kt->GetDefinition()->GetPDGStable() )
2730 {
2731 if (kt->GetDefinition()->IsShortLived())
2732 {
2733 G4cout << "final shortlived : ";
2734 } else
2735 {
2736 G4cout << "final un stable : ";
2737 }
2739 }
2740#endif
2741 delete kt;
2742 }
2743 theFinalState.clear();
2744 return products;
2745
2746}
2747
2748//----------------------------------------------------------------------------
2749G4ThreeVector G4BinaryCascade::GetSpherePoint(
2750 G4double r, const G4LorentzVector & mom4)
2751//----------------------------------------------------------------------------
2752{
2753 // Get a point outside radius.
2754 // point is random in plane (circle of radius r) orthogonal to mom,
2755 // plus -1*r*mom->vect()->unit();
2756 G4ThreeVector o1, o2;
2757 G4ThreeVector mom = mom4.vect();
2758
2759 o1= mom.orthogonal(); // we simply need any vector non parallel
2760 o2= mom.cross(o1); // o2 is now orthogonal to mom and o1, ie. o1 and o2 define plane.
2761
2762 G4double x2, x1;
2763
2764 do
2765 {
2766 x1=(G4UniformRand()-.5)*2;
2767 x2=(G4UniformRand()-.5)*2;
2768 } while (sqr(x1) +sqr(x2) > 1.); /* Loop checking, 31.08.2015, G.Folger */ // or random is badly broken.....
2769
2770 return G4ThreeVector(r*(x1*o1.unit() + x2*o2.unit() - 1.5* mom.unit()));
2771
2772
2773
2774 /*
2775 * // Get a point uniformly distributed on the surface of a sphere,
2776 * // with z < 0.
2777 * G4double b = r*G4UniformRand(); // impact parameter
2778 * G4double phi = G4UniformRand()*2*pi;
2779 * G4double x = b*std::cos(phi);
2780 * G4double y = b*std::sin(phi);
2781 * G4double z = -std::sqrt(r*r-b*b);
2782 * z *= 1.001; // Get position a little bit out of the sphere...
2783 * point.setX(x);
2784 * point.setY(y);
2785 * point.setZ(z);
2786 */
2787}
2788
2789//----------------------------------------------------------------------------
2790
2791void G4BinaryCascade::ClearAndDestroy(G4KineticTrackVector * ktv)
2792//----------------------------------------------------------------------------
2793{
2794 std::vector<G4KineticTrack *>::iterator i;
2795 for(i = ktv->begin(); i != ktv->end(); ++i)
2796 delete (*i);
2797 ktv->clear();
2798}
2799
2800//----------------------------------------------------------------------------
2801void G4BinaryCascade::ClearAndDestroy(G4ReactionProductVector * rpv)
2802//----------------------------------------------------------------------------
2803{
2804 std::vector<G4ReactionProduct *>::iterator i;
2805 for(i = rpv->begin(); i != rpv->end(); ++i)
2806 delete (*i);
2807 rpv->clear();
2808}
2809
2810//----------------------------------------------------------------------------
2811void G4BinaryCascade::PrintKTVector(G4KineticTrackVector * ktv, std::string comment)
2812//----------------------------------------------------------------------------
2813{
2814 if (comment.size() > 0 ) G4cout << "G4BinaryCascade::PrintKTVector() " << comment << G4endl;
2815 if (ktv) {
2816 G4cout << " vector: " << ktv << ", number of tracks: " << ktv->size()
2817 << G4endl;
2818 std::vector<G4KineticTrack *>::iterator i;
2819 G4int count;
2820
2821 for(count = 0, i = ktv->begin(); i != ktv->end(); ++i, ++count)
2822 {
2823 G4KineticTrack * kt = *i;
2824 G4cout << " track n. " << count;
2825 PrintKTVector(kt);
2826 }
2827 } else {
2828 G4cout << "G4BinaryCascade::PrintKTVector():No KineticTrackVector given " << G4endl;
2829 }
2830}
2831//----------------------------------------------------------------------------
2832void G4BinaryCascade::PrintKTVector(G4KineticTrack * kt, std::string comment)
2833//----------------------------------------------------------------------------
2834{
2835 if (comment.size() > 0 ) G4cout << "G4BinaryCascade::PrintKTVector() "<< comment << G4endl;
2836 if ( kt ){
2837 G4cout << ", id: " << kt << G4endl;
2839 G4LorentzVector mom = kt->Get4Momentum();
2841 const G4ParticleDefinition * definition = kt->GetDefinition();
2842 G4cout << " definition: " << definition->GetPDGEncoding() << " pos: "
2843 << 1/fermi*pos << " R: " << 1/fermi*pos.mag() << " 4mom: "
2844 << 1/MeV*mom <<"Tr_mom" << 1/MeV*tmom << " P: " << 1/MeV*mom.vect().mag()
2845 << " M: " << 1/MeV*mom.mag() << G4endl;
2846 G4cout <<" trackstatus: "<<kt->GetState() << " isParticipant " << (kt->IsParticipant()?"T":"F") <<G4endl;
2847 } else {
2848 G4cout << "G4BinaryCascade::PrintKTVector(): No Kinetictrack given" << G4endl;
2849 }
2850}
2851
2852
2853//----------------------------------------------------------------------------
2854G4double G4BinaryCascade::GetIonMass(G4int Z, G4int A)
2855//----------------------------------------------------------------------------
2856{
2857 G4double mass(0);
2858 if ( Z > 0 && A >= Z )
2859 {
2861
2862 } else if ( A > 0 && Z>0 )
2863 {
2864 // charge Z > A; will happen for light nuclei with pions involved.
2866
2867 } else if ( A >= 0 && Z<=0 )
2868 {
2869 // all neutral, or empty nucleus
2870 mass = A * G4Neutron::Neutron()->GetPDGMass();
2871
2872 } else if ( A == 0 )
2873 {
2874 // empty nucleus, except maybe pions
2875 mass = 0;
2876
2877 } else
2878 {
2879 G4cerr << "G4BinaryCascade::GetIonMass() - invalid (A,Z) = ("
2880 << A << "," << Z << ")" <<G4endl;
2881 throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCascade::GetIonMass() - giving up");
2882
2883 }
2884 // G4cout << "G4BinaryCascade::GetIonMass() Z, A, mass " << Z << " " << A << " " << mass << G4endl;
2885 return mass;
2886}
2887G4ReactionProductVector * G4BinaryCascade::FillVoidNucleusProducts(G4ReactionProductVector * products)
2888{
2889 // return product when nucleus is destroyed, i.e. charge=0, or theTargetList.size()=0
2890 G4double Esecondaries(0.);
2891 G4LorentzVector psecondaries;
2892 std::vector<G4KineticTrack *>::const_iterator iter;
2893 std::vector<G4ReactionProduct *>::const_iterator rpiter;
2894 decayKTV.Decay(&theFinalState);
2895
2896 for(iter = theFinalState.cbegin(); iter != theFinalState.cend(); ++iter)
2897 {
2898 G4ReactionProduct * aNew = new G4ReactionProduct((*iter)->GetDefinition());
2899 aNew->SetMomentum((*iter)->Get4Momentum().vect());
2900 aNew->SetTotalEnergy((*iter)->Get4Momentum().e());
2901 aNew->SetCreatorModelID(theBIC_ID);
2902 aNew->SetParentResonanceDef((*iter)->GetParentResonanceDef());
2903 aNew->SetParentResonanceID((*iter)->GetParentResonanceID());
2904 Esecondaries +=(*iter)->Get4Momentum().e();
2905 psecondaries +=(*iter)->Get4Momentum();
2906 aNew->SetNewlyAdded(true);
2907 //G4cout << " Particle Ekin " << aNew->GetKineticEnergy() << G4endl;
2908 products->push_back(aNew);
2909 }
2910
2911 // pull out late particles from collisions
2912 //theCollisionMgr->Print();
2913 while(theCollisionMgr->Entries() > 0) /* Loop checking, 31.08.2015, G.Folger */
2914 {
2916 collision = theCollisionMgr->GetNextCollision();
2917
2918 if ( ! collision->GetTargetCollection().size() ){
2919 G4KineticTrackVector * lates = collision->GetFinalState();
2920 if ( lates->size() == 1 ) {
2921 G4KineticTrack * atrack=*(lates->begin());
2922 //PrintKTVector(atrack, " late particle @ void Nucl ");
2923
2924 G4ReactionProduct * aNew = new G4ReactionProduct(atrack->GetDefinition());
2925 aNew->SetMomentum(atrack->Get4Momentum().vect());
2926 aNew->SetTotalEnergy(atrack->Get4Momentum().e());
2927 aNew->SetCreatorModelID(atrack->GetCreatorModelID());
2930 Esecondaries +=atrack->Get4Momentum().e();
2931 psecondaries +=atrack->Get4Momentum();
2932 aNew->SetNewlyAdded(true);
2933 products->push_back(aNew);
2934
2935 }
2936 }
2937 theCollisionMgr->RemoveCollision(collision);
2938
2939 }
2940
2941 // decay must be after loop on Collisions, and Decay() will delete entries in theSecondaryList, refered
2942 // to by Collisions.
2943 decayKTV.Decay(&theSecondaryList);
2944
2945 // Correct for momentum transfered to Nucleus
2946 G4ThreeVector transferCorrection(0);
2947 if ( (theSecondaryList.size() + theCapturedList.size()) > 0)
2948 {
2949 transferCorrection= theMomentumTransfer /(theSecondaryList.size() + theCapturedList.size());
2950 }
2951
2952 for(iter = theSecondaryList.cbegin(); iter != theSecondaryList.cend(); ++iter)
2953 {
2954 G4ReactionProduct * aNew = new G4ReactionProduct((*iter)->GetDefinition());
2955 (*iter)->Update4Momentum((*iter)->Get4Momentum().vect()+transferCorrection);
2956 aNew->SetMomentum((*iter)->Get4Momentum().vect());
2957 aNew->SetTotalEnergy((*iter)->Get4Momentum().e());
2958 aNew->SetCreatorModelID(theBIC_ID);
2959 aNew->SetParentResonanceDef((*iter)->GetParentResonanceDef());
2960 aNew->SetParentResonanceID((*iter)->GetParentResonanceID());
2961 Esecondaries +=(*iter)->Get4Momentum().e();
2962 psecondaries +=(*iter)->Get4Momentum();
2963 if ( (*iter)->IsParticipant() ) aNew->SetNewlyAdded(true);
2964 products->push_back(aNew);
2965 }
2966
2967 for(iter = theCapturedList.cbegin(); iter != theCapturedList.cend(); ++iter)
2968 {
2969 G4ReactionProduct * aNew = new G4ReactionProduct((*iter)->GetDefinition());
2970 (*iter)->Update4Momentum((*iter)->Get4Momentum().vect()+transferCorrection);
2971 aNew->SetMomentum((*iter)->Get4Momentum().vect());
2972 aNew->SetTotalEnergy((*iter)->Get4Momentum().e());
2973 aNew->SetCreatorModelID(theBIC_ID);
2974 aNew->SetParentResonanceDef((*iter)->GetParentResonanceDef());
2975 aNew->SetParentResonanceID((*iter)->GetParentResonanceID());
2976 Esecondaries +=(*iter)->Get4Momentum().e();
2977 psecondaries +=(*iter)->Get4Momentum();
2978 aNew->SetNewlyAdded(true);
2979 products->push_back(aNew);
2980 }
2981
2982 G4double SumMassNucleons(0.);
2983 G4LorentzVector pNucleons(0.);
2984 for(iter = theTargetList.cbegin(); iter != theTargetList.cend(); ++iter)
2985 {
2986 SumMassNucleons += (*iter)->GetDefinition()->GetPDGMass();
2987 pNucleons += (*iter)->Get4Momentum();
2988 }
2989
2990 G4double Ekinetic=theProjectile4Momentum.e() + initial_nuclear_mass - Esecondaries - SumMassNucleons;
2991 #ifdef debug_BIC_FillVoidnucleus
2992 G4LorentzVector deltaP=theProjectile4Momentum + G4LorentzVector(initial_nuclear_mass) -
2993 psecondaries - pNucleons;
2994 //G4cout << "BIC::FillVoidNucleus() nucleons : "<<theTargetList.size() << " , T: " << Ekinetic <<
2995 // ", deltaP " << deltaP << " deltaPNoNucl " << deltaP + pNucleons << G4endl;
2996 #endif
2997 if (Ekinetic > 0. && theTargetList.size()){
2998 Ekinetic /= theTargetList.size();
2999 } else {
3000 G4double Ekineticrdm(0);
3001 if (theTargetList.size()) Ekineticrdm = ( 0.1 + G4UniformRand()*5.) * MeV; // leave some Energy for Nucleons
3002 G4double TotalEkin(Ekineticrdm);
3003 for (rpiter=products->cbegin(); rpiter!=products->cend(); ++rpiter){
3004 TotalEkin+=(*rpiter)->GetKineticEnergy();
3005 }
3006 G4double correction(1.);
3007 if ( std::abs(Ekinetic) < 20*perCent * TotalEkin ){
3008 correction=1. + (Ekinetic-Ekineticrdm)/TotalEkin; // Ekinetic < 0 == IS < FS, need to reduce energies
3009 }
3010 #ifdef debug_G4BinaryCascade
3011 else {
3012 G4cout << "BLIC::FillVoidNucleus() fail correction, Ekinetic, TotalEkin " << Ekinetic << ""<< TotalEkin << G4endl;
3013 }
3014 #endif
3015
3016 for (rpiter=products->cbegin(); rpiter!=products->cend(); ++rpiter){
3017 (*rpiter)->SetKineticEnergy((*rpiter)->GetKineticEnergy()*correction); // this sets kinetic & total energy
3018 (*rpiter)->SetMomentum((*rpiter)->GetTotalMomentum() * (*rpiter)->GetMomentum().unit());
3019
3020 }
3021
3022 Ekinetic=Ekineticrdm*correction;
3023 if (theTargetList.size())Ekinetic /= theTargetList.size();
3024
3025 }
3026
3027 for(iter = theTargetList.cbegin(); iter != theTargetList.cend(); ++iter) {
3028 // set Nucleon it to be hit - as it is in fact
3029 (*iter)->Hit();
3030 G4ReactionProduct * aNew = new G4ReactionProduct((*iter)->GetDefinition());
3031 aNew->SetKineticEnergy(Ekinetic);
3032 aNew->SetMomentum(aNew->GetTotalMomentum() * ((*iter)->Get4Momentum().vect().unit()));
3033 aNew->SetNewlyAdded(true);
3034 aNew->SetCreatorModelID(theBIC_ID);
3035 aNew->SetParentResonanceDef((*iter)->GetParentResonanceDef());
3036 aNew->SetParentResonanceID((*iter)->GetParentResonanceID());
3037 products->push_back(aNew);
3038 Esecondaries += aNew->GetTotalEnergy();
3039 psecondaries += G4LorentzVector(aNew->GetMomentum(),aNew->GetTotalEnergy() );
3040 }
3041 psecondaries=G4LorentzVector(0);
3042 for (rpiter=products->cbegin(); rpiter!=products->cend(); ++rpiter){
3043 psecondaries += G4LorentzVector((*rpiter)->GetMomentum(),(*rpiter)->GetTotalEnergy() );
3044 }
3045
3046 G4LorentzVector initial4Mom=theProjectile4Momentum + G4LorentzVector(initial_nuclear_mass);
3047
3048 //G4cout << "::FillVoidNucleus()final e/p conservation initial" <<initial4Mom
3049 // << " final " << psecondaries << " delta " << initial4Mom-psecondaries << G4endl;
3050
3051 G4ThreeVector SumMom=psecondaries.vect();
3052
3053 SumMom=initial4Mom.vect()-SumMom;
3054 G4int loopcount(0);
3055
3056 // reverse_iterator reverse - start to correct last added first
3057 while ( SumMom.mag() > 0.1*MeV && loopcount++ < 10) /* Loop checking, 31.08.2015, G.Folger */
3058 {
3059 G4int index=(G4int)products->size();
3060 for (auto reverse=products->crbegin(); reverse!=products->crend(); ++reverse, --index){
3061 SumMom=initial4Mom.vect();
3062 for (rpiter=products->cbegin(); rpiter!=products->cend(); ++rpiter){
3063 SumMom-=(*rpiter)->GetMomentum();
3064 }
3065 G4double p=((*reverse)->GetMomentum()).mag();
3066 (*reverse)->SetMomentum( p*(((*reverse)->GetMomentum()+SumMom).unit()));
3067 }
3068 }
3069 return products;
3070}
3071
3072G4ReactionProductVector * G4BinaryCascade::HighEnergyModelFSProducts(G4ReactionProductVector * products,
3073 G4KineticTrackVector * secondaries)
3074{
3075 std::vector<G4KineticTrack *>::iterator iter;
3076 for(iter = secondaries->begin(); iter != secondaries->end(); ++iter)
3077 {
3078 G4ReactionProduct * aNew = new G4ReactionProduct((*iter)->GetDefinition());
3079 aNew->SetMomentum((*iter)->Get4Momentum().vect());
3080 aNew->SetTotalEnergy((*iter)->Get4Momentum().e());
3081 aNew->SetNewlyAdded(true);
3082 aNew->SetCreatorModelID((*iter)->GetCreatorModelID());
3083 aNew->SetParentResonanceDef((*iter)->GetParentResonanceDef());
3084 aNew->SetParentResonanceID((*iter)->GetParentResonanceID());
3085 //G4cout << " Particle Ekin " << aNew->GetKineticEnergy() << G4endl;
3086 products->push_back(aNew);
3087 }
3088 const G4ParticleDefinition* fragment = 0;
3089 if (currentA == 1 && currentZ == 0) {
3090 fragment = G4Neutron::NeutronDefinition();
3091 } else if (currentA == 1 && currentZ == 1) {
3092 fragment = G4Proton::ProtonDefinition();
3093 } else if (currentA == 2 && currentZ == 1) {
3094 fragment = G4Deuteron::DeuteronDefinition();
3095 } else if (currentA == 3 && currentZ == 1) {
3096 fragment = G4Triton::TritonDefinition();
3097 } else if (currentA == 3 && currentZ == 2) {
3098 fragment = G4He3::He3Definition();
3099 } else if (currentA == 4 && currentZ == 2) {
3100 fragment = G4Alpha::AlphaDefinition();;
3101 } else {
3102 fragment =
3103 G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon(currentZ,currentA,0.0);
3104 }
3105 if (fragment != 0) {
3106 G4ReactionProduct * theNew = new G4ReactionProduct(fragment);
3107 theNew->SetMomentum(G4ThreeVector(0,0,0));
3108 theNew->SetTotalEnergy(massInNucleus);
3109 theNew->SetCreatorModelID(theBIC_ID);
3110 //theNew->SetFormationTime(??0.??);
3111 //G4cout << " Nucleus (" << currentZ << ","<< currentA << "), mass "<< massInNucleus << G4endl;
3112 products->push_back(theNew);
3113 }
3114 return products;
3115}
3116
3117void G4BinaryCascade::PrintWelcomeMessage()
3118{
3119 G4cout <<"Thank you for using G4BinaryCascade. "<<G4endl;
3120}
3121
3122//----------------------------------------------------------------------------
3123void G4BinaryCascade::DebugApplyCollisionFail(G4CollisionInitialState * collision,
3124 G4KineticTrackVector * products)
3125{
3126 G4bool havePion=false;
3127 if (products)
3128 {
3129 for ( std::vector<G4KineticTrack *>::iterator i =products->begin(); i != products->end(); i++)
3130 {
3131 G4int PDGcode=std::abs((*i)->GetDefinition()->GetPDGEncoding());
3132 if (std::abs(PDGcode)==211 || PDGcode==111 ) havePion=true;
3133 }
3134 }
3135 if ( !products || havePion)
3136 {
3137 const G4BCAction &action= *collision->GetGenerator();
3138 G4cout << " Collision " << collision << ", type: "<< typeid(action).name()
3139 << ", with NO products! " <<G4endl;
3140 G4cout << G4endl<<"Initial condition are these:"<<G4endl;
3141 G4cout << "proj: "<<collision->GetPrimary()->GetDefinition()->GetParticleName()<<G4endl;
3142 PrintKTVector(collision->GetPrimary());
3143 for(size_t it=0; it<collision->GetTargetCollection().size(); it++)
3144 {
3145 G4cout << "targ: "
3146 <<collision->GetTargetCollection()[it]->GetDefinition()->GetParticleName()<<G4endl;
3147 }
3148 PrintKTVector(&collision->GetTargetCollection(),std::string(" Target particles"));
3149 }
3150 // if ( lateParticleCollision ) G4cout << " Added late particle--------------------------"<<G4endl;
3151 // if ( lateParticleCollision && products ) PrintKTVector(products, " reaction products");
3152}
3153
3154//----------------------------------------------------------------------------
3155
3156G4bool G4BinaryCascade::CheckChargeAndBaryonNumber(G4String where)
3157{
3158 static G4int lastdA(0), lastdZ(0);
3159 G4int iStateA = the3DNucleus->GetMassNumber() + projectileA;
3160 G4int iStateZ = the3DNucleus->GetCharge() + projectileZ;
3161
3162 G4int fStateA(0);
3163 G4int fStateZ(0);
3164
3165 std::vector<G4KineticTrack *>::iterator i;
3166 G4int CapturedA(0), CapturedZ(0);
3167 G4int secsA(0), secsZ(0);
3168 for ( i=theCapturedList.begin(); i!=theCapturedList.end(); ++i) {
3169 CapturedA += (*i)->GetDefinition()->GetBaryonNumber();
3170 CapturedZ += G4lrint((*i)->GetDefinition()->GetPDGCharge()/eplus);
3171 }
3172
3173 for ( i=theSecondaryList.begin(); i!=theSecondaryList.end(); ++i) {
3174 if ( (*i)->GetState() != G4KineticTrack::inside ) {
3175 secsA += (*i)->GetDefinition()->GetBaryonNumber();
3176 secsZ += G4lrint((*i)->GetDefinition()->GetPDGCharge()/eplus);
3177 }
3178 }
3179
3180 for ( i=theFinalState.begin(); i!=theFinalState.end(); ++i) {
3181 fStateA += (*i)->GetDefinition()->GetBaryonNumber();
3182 fStateZ += G4lrint((*i)->GetDefinition()->GetPDGCharge()/eplus);
3183 }
3184
3185 G4int deltaA= iStateA - secsA - fStateA -currentA - lateA;
3186 G4int deltaZ= iStateZ - secsZ - fStateZ -currentZ - lateZ;
3187
3188#ifdef debugCheckChargeAndBaryonNumberverbose
3189 G4cout << where <<" A: iState= "<< iStateA<<", secs= "<< secsA<< ", fState= "<< fStateA<< ", current= "<<currentA<< ", late= " <<lateA << G4endl;
3190 G4cout << where <<" Z: iState= "<< iStateZ<<", secs= "<< secsZ<< ", fState= "<< fStateZ<< ", current= "<<currentZ<< ", late= " <<lateZ << G4endl;
3191#endif
3192
3193 if (deltaA != 0 || deltaZ!=0 ) {
3194 if (deltaA != lastdA || deltaZ != lastdZ ) {
3195 G4cout << "baryon/charge imbalance - " << where << G4endl
3196 << "deltaA " <<deltaA<<", iStateA "<<iStateA<< ", CapturedA "<<CapturedA <<", secsA "<<secsA
3197 << ", fStateA "<<fStateA << ", currentA "<<currentA << ", lateA "<<lateA << G4endl
3198 << "deltaZ "<<deltaZ<<", iStateZ "<<iStateZ<< ", CapturedZ "<<CapturedZ <<", secsZ "<<secsZ
3199 << ", fStateZ "<<fStateZ << ", currentZ "<<currentZ << ", lateZ "<<lateZ << G4endl<< G4endl;
3200 lastdA=deltaA;
3201 lastdZ=deltaZ;
3202 }
3203 } else { lastdA=lastdZ=0;}
3204
3205 return true;
3206}
3207//----------------------------------------------------------------------------
3208void G4BinaryCascade::DebugApplyCollision(G4CollisionInitialState * collision,
3209 G4KineticTrackVector * products)
3210{
3211
3212 PrintKTVector(collision->GetPrimary(),std::string(" Primary particle"));
3213 PrintKTVector(&collision->GetTargetCollection(),std::string(" Target particles"));
3214 PrintKTVector(products,std::string(" Scatterer products"));
3215
3216#ifdef dontUse
3217 G4double thisExcitation(0);
3218 // excitation energy from this collision
3219 // initial state:
3220 G4double initial(0);
3221 G4KineticTrack * kt=collision->GetPrimary();
3222 initial += kt->Get4Momentum().e();
3223
3224 G4RKPropagation * RKprop=(G4RKPropagation *)thePropagator;
3225
3226 initial += RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition());
3227 initial -= RKprop->GetBarrier(kt->GetDefinition()->GetPDGEncoding());
3228 G4cout << "prim. E/field/Barr/Sum " << kt->Get4Momentum().e()
3229 << " " << RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition())
3230 << " " << RKprop->GetBarrier(kt->GetDefinition()->GetPDGEncoding())
3231 << " " << initial << G4endl;;
3232
3234 for ( unsigned int it=0; it < ktv.size(); it++)
3235 {
3236 kt=ktv[it];
3237 initial += kt->Get4Momentum().e();
3238 thisExcitation += kt->GetDefinition()->GetPDGMass()
3239 - kt->Get4Momentum().e()
3240 - RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition());
3241 // initial += RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition());
3242 // initial -= RKprop->GetBarrier(kt->GetDefinition()->GetPDGEncoding());
3243 G4cout << "Targ. def/E/field/Barr/Sum " << kt->GetDefinition()->GetPDGEncoding()
3244 << " " << kt->Get4Momentum().e()
3245 << " " << RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition())
3246 << " " << RKprop->GetBarrier(kt->GetDefinition()->GetPDGEncoding())
3247 << " " << initial <<" Excit " << thisExcitation << G4endl;;
3248 }
3249
3250 G4double final(0);
3251 G4double mass_out(0);
3252 G4int product_barions(0);
3253 if ( products )
3254 {
3255 for ( unsigned int it=0; it < products->size(); it++)
3256 {
3257 kt=(*products)[it];
3258 final += kt->Get4Momentum().e();
3259 final += RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition());
3260 final += RKprop->GetBarrier(kt->GetDefinition()->GetPDGEncoding());
3261 if ( kt->GetDefinition()->GetBaryonNumber()==1 ) product_barions++;
3262 mass_out += kt->GetDefinition()->GetPDGMass();
3263 G4cout << "sec. def/E/field/Barr/Sum " << kt->GetDefinition()->GetPDGEncoding()
3264 << " " << kt->Get4Momentum().e()
3265 << " " << RKprop->GetField(kt->GetDefinition()->GetPDGEncoding(),kt->GetPosition())
3266 << " " << RKprop->GetBarrier(kt->GetDefinition()->GetPDGEncoding())
3267 << " " << final << G4endl;;
3268 }
3269 }
3270
3271
3272 G4int finalA = currentA;
3273 G4int finalZ = currentZ;
3274 if ( products )
3275 {
3276 finalA -= product_barions;
3277 finalZ -= GetTotalCharge(*products);
3278 }
3279 G4double delta = GetIonMass(currentZ,currentA) - (GetIonMass(finalZ,finalA) + mass_out);
3280 G4cout << " current/final a,z " << currentA << " " << currentZ << " "<< finalA<< " "<< finalZ
3281 << " delta-mass " << delta<<G4endl;
3282 final+=delta;
3283 mass_out = GetIonMass(finalZ,finalA);
3284 G4cout << " initE/ E_out/ Mfinal/ Excit " << currentInitialEnergy
3285 << " " << final << " "
3286 << mass_out<<" "
3287 << currentInitialEnergy - final - mass_out
3288 << G4endl;
3289 currentInitialEnergy-=final;
3290#endif
3291}
3292
3293//----------------------------------------------------------------------------
3294G4bool G4BinaryCascade::DebugFinalEpConservation(const G4HadProjectile & aTrack,
3295 G4ReactionProductVector* products)
3296//----------------------------------------------------------------------------
3297{
3298 G4ReactionProductVector::iterator iter;
3299 G4double Efinal(0);
3300 G4ThreeVector pFinal(0);
3301 if (std::abs(theParticleChange.GetWeightChange() -1 ) > 1e-5 )
3302 {
3303 G4cout <<" BIC-weight change " << theParticleChange.GetWeightChange()<< G4endl;
3304 }
3305
3306 for(iter = products->begin(); iter != products->end(); ++iter)
3307 {
3308
3309 G4cout << " Secondary E - Ekin / p " <<
3310 (*iter)->GetDefinition()->GetParticleName() << " " <<
3311 (*iter)->GetTotalEnergy() << " - " <<
3312 (*iter)->GetKineticEnergy()<< " / " <<
3313 (*iter)->GetMomentum().x() << " " <<
3314 (*iter)->GetMomentum().y() << " " <<
3315 (*iter)->GetMomentum().z() << G4endl;
3316 Efinal += (*iter)->GetTotalEnergy();
3317 pFinal += (*iter)->GetMomentum();
3318 }
3319
3320 G4cout << "e outgoing/ total : " << Efinal << " " << Efinal+GetFinal4Momentum().e()<< G4endl;
3321 G4cout << "BIC E/p delta " <<
3322 (aTrack.Get4Momentum().e()+theInitial4Mom.e() - Efinal)/MeV <<
3323 " MeV / mom " << (aTrack.Get4Momentum() - pFinal ) /MeV << G4endl;
3324
3325 return (aTrack.Get4Momentum().e() + theInitial4Mom.e() - Efinal)/aTrack.Get4Momentum().e() < perCent;
3326
3327}
3328//----------------------------------------------------------------------------
3329G4bool G4BinaryCascade::DebugEpConservation(const G4String where)
3330//----------------------------------------------------------------------------
3331{
3332 G4cout << where << G4endl;
3333 G4LorentzVector psecs, ptgts, pcpts, pfins;
3334 if (std::abs(theParticleChange.GetWeightChange() -1 ) > 1e-5 )
3335 {
3336 G4cout <<" BIC-weight change " << theParticleChange.GetWeightChange()<< G4endl;
3337 }
3338
3339 std::vector<G4KineticTrack *>::iterator ktiter;
3340 for(ktiter = theSecondaryList.begin(); ktiter != theSecondaryList.end(); ++ktiter)
3341 {
3342
3343 G4cout << " Secondary E - Ekin / p " <<
3344 (*ktiter)->GetDefinition()->GetParticleName() << " " <<
3345 (*ktiter)->Get4Momentum().e() << " - " <<
3346 (*ktiter)->Get4Momentum().e() - (*ktiter)->Get4Momentum().mag() << " / " <<
3347 (*ktiter)->Get4Momentum().vect() << G4endl;
3348 psecs += (*ktiter)->Get4Momentum();
3349 }
3350
3351 for(ktiter = theTargetList.begin(); ktiter != theTargetList.end(); ++ktiter)
3352 {
3353
3354 G4cout << " Target E - Ekin / p " <<
3355 (*ktiter)->GetDefinition()->GetParticleName() << " " <<
3356 (*ktiter)->Get4Momentum().e() << " - " <<
3357 (*ktiter)->Get4Momentum().e() - (*ktiter)->Get4Momentum().mag() << " / " <<
3358 (*ktiter)->Get4Momentum().vect() << G4endl;
3359 ptgts += (*ktiter)->Get4Momentum();
3360 }
3361
3362 for(ktiter = theCapturedList.begin(); ktiter != theCapturedList.end(); ++ktiter)
3363 {
3364
3365 G4cout << " Captured E - Ekin / p " <<
3366 (*ktiter)->GetDefinition()->GetParticleName() << " " <<
3367 (*ktiter)->Get4Momentum().e() << " - " <<
3368 (*ktiter)->Get4Momentum().e() - (*ktiter)->Get4Momentum().mag() << " / " <<
3369 (*ktiter)->Get4Momentum().vect() << G4endl;
3370 pcpts += (*ktiter)->Get4Momentum();
3371 }
3372
3373 for(ktiter = theFinalState.begin(); ktiter != theFinalState.end(); ++ktiter)
3374 {
3375
3376 G4cout << " Finals E - Ekin / p " <<
3377 (*ktiter)->GetDefinition()->GetParticleName() << " " <<
3378 (*ktiter)->Get4Momentum().e() << " - " <<
3379 (*ktiter)->Get4Momentum().e() - (*ktiter)->Get4Momentum().mag() << " / " <<
3380 (*ktiter)->Get4Momentum().vect() << G4endl;
3381 pfins += (*ktiter)->Get4Momentum();
3382 }
3383
3384 G4cout << " Secondaries " << psecs << ", Targets " << ptgts << G4endl
3385 <<" Captured " << pcpts << ", Finals " << pfins << G4endl
3386 <<" Sum " << psecs + ptgts + pcpts + pfins << " PTransfer " << theMomentumTransfer
3387 <<" Sum+PTransfer " << psecs + ptgts + pcpts + pfins + theMomentumTransfer
3388 << G4endl<< G4endl;
3389
3390
3391 return true;
3392
3393}
3394
3395//----------------------------------------------------------------------------
3396G4ReactionProductVector * G4BinaryCascade::ProductsAddFakeGamma(G4ReactionProductVector *products )
3397//----------------------------------------------------------------------------
3398{
3399 // else
3400// {
3401// G4ReactionProduct * aNew=0;
3402// // return nucleus e and p
3403// if (fragment != 0 ) {
3404// aNew = new G4ReactionProduct(G4Gamma::GammaDefinition()); // we only want to pass e/p
3405// aNew->SetMomentum(fragment->GetMomentum().vect());
3406// aNew->SetTotalEnergy(fragment->GetMomentum().e());
3407// delete fragment;
3408// fragment=0;
3409// } else if (products->size() == 0) {
3410// // FixMe GF: for testing without precompound, return 1 gamma of 0.01 MeV in +x
3411//#include "G4Gamma.hh"
3412// aNew = new G4ReactionProduct(G4Gamma::GammaDefinition());
3413// aNew->SetMomentum(G4ThreeVector(0.01*MeV,0,0));
3414// aNew->SetTotalEnergy(0.01*MeV);
3415// }
3416// if ( aNew != 0 ) products->push_back(aNew);
3417// }
3418 return products;
3419}
3420
3421//----------------------------------------------------------------------------
#define _CheckChargeAndBaryonNumber_(val)
#define _DebugEpConservation(val)
const G4DNABoundingBox initial
@ isAlive
@ stopAndKill
CLHEP::HepLorentzVector G4LorentzVector
std::vector< G4ReactionProduct * > G4ReactionProductVector
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
Hep3Vector unit() const
Hep3Vector orthogonal() const
double mag2() const
Hep3Vector cross(const Hep3Vector &) const
double mag() const
HepLorentzRotation inverse() const
HepLorentzRotation & set(double bx, double by, double bz)
Hep3Vector boostVector() const
Hep3Vector vect() const
static G4Alpha * AlphaDefinition()
Definition G4Alpha.cc:78
virtual const std::vector< G4CollisionInitialState * > & GetCollisions(G4KineticTrack *aProjectile, std::vector< G4KineticTrack * > &, G4double theCurrentTime)
Definition G4BCDecay.hh:41
virtual const std::vector< G4CollisionInitialState * > & GetCollisions(G4KineticTrack *aProjectile, std::vector< G4KineticTrack * > &, G4double theCurrentTime)
virtual void PropagateModelDescription(std::ostream &) const
G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &theNucleus)
virtual G4ReactionProductVector * Propagate(G4KineticTrackVector *, G4V3DNucleus *)
G4BinaryCascade(G4VPreCompoundModel *ptr=0)
virtual void ModelDescription(std::ostream &) const
virtual ~G4BinaryCascade()
G4KineticTrackVector & GetTargetCollection(void)
G4KineticTrackVector * GetFinalState()
G4KineticTrack * GetPrimary(void)
void AddCollision(G4double time, G4KineticTrack *proj, G4KineticTrack *target=nullptr)
void RemoveCollision(G4CollisionInitialState *collision)
void RemoveTracksCollisions(G4KineticTrackVector *ktv)
G4CollisionInitialState * GetNextCollision()
void Decay(G4KineticTrackVector *tracks) const
static G4Deuteron * DeuteronDefinition()
Definition G4Deuteron.cc:85
void ModelDescription(std::ostream &outFile) const
G4ReactionProductVector * BreakItUp(const G4Fragment &theInitialState)
G4double GetFermiMomentum(G4double density)
void Init(G4int anA, G4int aZ)
void SetNumberOfCharged(G4int value)
const G4LorentzVector & GetMomentum() const
void SetCreatorModelID(G4int value)
void SetNumberOfHoles(G4int valueTot, G4int valueP=0)
void SetNumberOfParticles(G4int value)
G4int GetA_asInt() const
void SetStatusChange(G4HadFinalStateStatus aS)
void AddSecondary(G4DynamicParticle *aP, G4int mod=-1)
void SetEnergyChange(G4double anEnergy)
void SetMomentumChange(const G4ThreeVector &aV)
G4double GetWeightChange() const
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
G4double GetGlobalTime() const
void SetParentResonanceDef(const G4ParticleDefinition *parentDef)
void SetTime(G4double aT)
void SetCreatorModelID(G4int id)
void SetParentResonanceID(const G4int parentID)
G4HadronicInteraction * FindModel(const G4String &name)
static G4HadronicInteractionRegistry * Instance()
virtual G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &targetNucleus)
void SetMinEnergy(G4double anEnergy)
const G4String & GetModelName() const
void SetEnergyMomentumCheckLevels(G4double relativeLevel, G4double absoluteLevel)
void SetMaxEnergy(const G4double anEnergy)
static G4HadronicParameters * Instance()
static G4He3 * He3Definition()
Definition G4He3.cc:85
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
G4double GetIonMass(G4int Z, G4int A, G4int nL=0, G4int lvl=0) const
CascadeState SetState(const CascadeState new_state)
G4int GetParentResonanceID() const
G4int GetCreatorModelID() const
CascadeState GetState() const
void SetNucleon(G4Nucleon *aN)
void Set4Momentum(const G4LorentzVector &a4Momentum)
const G4ThreeVector & GetPosition() const
const G4ParticleDefinition * GetDefinition() const
G4bool IsParticipant() const
const G4LorentzVector & GetTrackingMomentum() const
void Update4Momentum(G4double aEnergy)
const G4ParticleDefinition * GetParentResonanceDef() const
const G4LorentzVector & Get4Momentum() const
G4double GetActualMass() const
static G4Neutron * NeutronDefinition()
Definition G4Neutron.cc:96
static G4Neutron * Neutron()
Definition G4Neutron.cc:101
G4int GetA_asInt() const
Definition G4Nucleus.hh:99
G4int GetZ_asInt() const
Definition G4Nucleus.hh:105
G4bool GetPDGStable() const
const G4String & GetParticleName() const
G4IonTable * GetIonTable() const
static G4ParticleTable * GetParticleTable()
static G4int GetModelID(const G4int modelIndex)
static G4PionMinus * PionMinusDefinition()
static G4PionPlus * PionPlusDefinition()
Definition G4PionPlus.cc:88
static G4Proton * ProtonDefinition()
Definition G4Proton.cc:85
static G4Proton * Proton()
Definition G4Proton.cc:90
G4double GetField(G4int encoding, G4ThreeVector pos)
G4double GetBarrier(G4int encoding)
virtual void Transport(G4KineticTrackVector &theActive, const G4KineticTrackVector &theSpectators, G4double theTimeStep)
G4ThreeVector GetMomentumTransfer() const
void SetMomentum(const G4double x, const G4double y, const G4double z)
void SetTotalEnergy(const G4double en)
void SetParentResonanceDef(const G4ParticleDefinition *parentDef)
G4double GetTotalMomentum() const
G4double GetKineticEnergy() const
G4double GetTotalEnergy() const
void SetCreatorModelID(const G4int mod)
void SetNewlyAdded(const G4bool f)
G4ThreeVector GetMomentum() const
void SetKineticEnergy(const G4double en)
void SetParentResonanceID(const G4int parentID)
virtual G4KineticTrackVector * Scatter(const G4KineticTrack &trk1, const G4KineticTrack &trk2) const
static G4Triton * TritonDefinition()
Definition G4Triton.cc:85
virtual G4double CoulombBarrier()=0
virtual G4double GetOuterRadius()=0
virtual const G4VNuclearDensity * GetNuclearDensity() const =0
virtual G4Nucleon * GetNextNucleon()=0
virtual G4int GetCharge()=0
virtual G4bool StartLoop()=0
virtual G4double GetMass()=0
virtual void Init(G4int theA, G4int theZ, G4int numberOfLambdas=0)=0
virtual G4int GetMassNumber()=0
virtual void Init(G4V3DNucleus *theNucleus)=0
G4VPreCompoundModel * GetDeExcitation() const
const G4HadProjectile * GetPrimaryProjectile() const
void SetDeExcitation(G4VPreCompoundModel *ptr)
G4double GetDensity(const G4ThreeVector &aPosition) const
virtual void DeExciteModelDescription(std::ostream &outFile) const =0
virtual G4ReactionProductVector * DeExcite(G4Fragment &aFragment)=0
G4ExcitationHandler * GetExcitationHandler() const
SelectFromKTV(G4KineticTrackVector *out, G4KineticTrack::CascadeState astate)
void operator()(G4KineticTrack *&kt) const
ParticleList decay(Cluster *const c)
Carries out a cluster decay.
G4double energy(const ThreeVector &p, const G4double m)
const char * name(G4int ptype)
G4bool nucleon(G4int ityp)
int G4lrint(double ad)
Definition templates.hh:134
T sqr(const T &x)
Definition templates.hh:128
#define DBL_MAX
Definition templates.hh:62
#define ns(x)
Definition xmltok.c:1649