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