Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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