Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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