Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4BinaryCascade.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26
27#include "globals.hh"
29#include "G4SystemOfUnits.hh"
30#include "G4Proton.hh"
31#include "G4Neutron.hh"
32#include "G4LorentzRotation.hh"
33#include "G4BinaryCascade.hh"
37#include "G4Track.hh"
38#include "G4V3DNucleus.hh"
39#include "G4Fancy3DNucleus.hh"
40#include "G4Scatterer.hh"
41#include "G4MesonAbsorption.hh"
42#include "G4ping.hh"
43#include "G4Delete.hh"
44
45#include "G4CollisionManager.hh"
46#include "G4Absorber.hh"
47
49#include "G4ListOfCollisions.hh"
50#include "G4Fragment.hh"
51#include "G4RKPropagation.hh"
52
55#include "G4FermiMomentum.hh"
56
57#include "G4PreCompoundModel.hh"
60
62
63#include "G4PreCompoundModel.hh"
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