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