source: trunk/source/processes/hadronic/models/binary_cascade/src/G4BinaryCascade.cc @ 962

Last change on this file since 962 was 962, checked in by garnier, 15 years ago

update processes

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