Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4BinaryCascade.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 
27 #include "globals.hh"
28 #include "G4PhysicalConstants.hh"
29 #include "G4SystemOfUnits.hh"
30 #include "G4Proton.hh"
31 #include "G4Neutron.hh"
32 #include "G4LorentzRotation.hh"
33 #include "G4BinaryCascade.hh"
34 #include "G4KineticTrackVector.hh"
35 #include "G4DecayKineticTracks.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 
54 #include "G4NuclearFermiDensity.hh"
55 #include "G4FermiMomentum.hh"
56 
57 #include "G4PreCompoundModel.hh"
58 #include "G4ExcitationHandler.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 
103 G4VIntraNuclearTransportModel("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 
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 /*
153 G4BinaryCascade::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 
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 }
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() &&
247  definition!=G4PionMinus::PionMinusDefinition() )
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;
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  }
418  _CheckChargeAndBaryonNumber_("absorbed");
419  if(Capture()) { // capture secondaries, nucleons only
420  haveProducts = true;
421  }
422  _CheckChargeAndBaryonNumber_("captured");
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 //----------------------------------------------------------------------------
623 G4double 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 //----------------------------------------------------------------------------
717 void 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 //----------------------------------------------------------------------------
790 G4bool 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 //----------------------------------------------------------------------------
872 G4ReactionProductVector * 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 //----------------------------------------------------------------------------
927 G4ReactionProductVector * 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 //----------------------------------------------------------------------------
1013 G4ReactionProductVector * 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 //----------------------------------------------------------------------------
1038 G4ReactionProductVector * 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 //----------------------------------------------------------------------------
1072 void 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 //----------------------------------------------------------------------------
1097 void 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 //----------------------------------------------------------------------------
1109 void 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  {
1118  secondary->SetState(G4KineticTrack::outside);
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 //----------------------------------------------------------------------------
1153 G4bool 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 //----------------------------------------------------------------------------
1379 G4bool 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 //----------------------------------------------------------------------------
1447 G4bool 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 //----------------------------------------------------------------------------
1515 G4bool G4BinaryCascade::CheckPauliPrinciple(G4KineticTrackVector * products)
1516 //----------------------------------------------------------------------------
1517 {
1519  G4int Z = the3DNucleus->GetCharge();
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 //----------------------------------------------------------------------------
1599 void 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 //----------------------------------------------------------------------------
1730 G4double 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 //----------------------------------------------------------------------------
1759 G4bool 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 //----------------------------------------------------------------------------
1798 void 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 //----------------------------------------------------------------------------
1906 void 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 {
1974 private:
1975  G4KineticTrackVector * ktv;
1976  G4KineticTrack::CascadeState wanted_state;
1977 public:
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 //----------------------------------------------------------------------------
1991 G4bool 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 
2012  G4KineticTrackVector * kt_inside = new G4KineticTrackVector;
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(),
2047  SelectFromKTV(kt_gone_out, G4KineticTrack::gone_out));
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(),
2062  SelectFromKTV(kt_gone_out, G4KineticTrack::gone_out));
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(),
2089  SelectFromKTV(kt_captured, G4KineticTrack::captured));
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 //----------------------------------------------------------------------------
2176 G4KineticTrackVector* G4BinaryCascade::CorrectBarionsOnBoundary(
2178  G4KineticTrackVector *out)
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 
2382 G4Fragment * 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 
2466 G4LorentzVector 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 //----------------------------------------------------------------------------
2503 G4LorentzVector 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 //----------------------------------------------------------------------------
2550 G4ReactionProductVector * 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 //----------------------------------------------------------------------------
2644 G4ThreeVector 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 
2686 void 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 //----------------------------------------------------------------------------
2696 void 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 //----------------------------------------------------------------------------
2706 void 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 //----------------------------------------------------------------------------
2727 void 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();
2735  G4LorentzVector tmom = kt->GetTrackingMomentum();
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 //----------------------------------------------------------------------------
2749 G4double 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 }
2781 G4ReactionProductVector * 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 }
2880 G4ReactionProductVector * 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 
2921 void G4BinaryCascade::PrintWelcomeMessage()
2922 {
2923  G4cout <<"Thank you for using G4BinaryCascade. "<<G4endl;
2924 }
2925 
2926 //----------------------------------------------------------------------------
2927 void 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 
2959 G4bool 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 //----------------------------------------------------------------------------
3006 void 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 
3031  G4KineticTrackVector ktv=collision->GetTargetCollection();
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 //----------------------------------------------------------------------------
3094 G4bool 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 //----------------------------------------------------------------------------
3130 G4ReactionProductVector * 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 //----------------------------------------------------------------------------