Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4BinaryLightIonReaction.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 #include <algorithm>
27 #include <vector>
28 #include <cmath>
29 #include <numeric>
30 
32 #include "G4PhysicalConstants.hh"
33 #include "G4SystemOfUnits.hh"
34 #include "G4LorentzVector.hh"
35 #include "G4LorentzRotation.hh"
37 #include "G4ping.hh"
38 #include "G4Delete.hh"
39 #include "G4Neutron.hh"
40 #include "G4VNuclearDensity.hh"
41 #include "G4FermiMomentum.hh"
42 #include "G4HadTmpUtil.hh"
43 #include "G4PreCompoundModel.hh"
45 
46 //#define debug_G4BinaryLightIonReaction
47 //#define debug_BLIR_finalstate
48 
50 : G4HadronicInteraction("Binary Light Ion Cascade"),
51  theProjectileFragmentation(ptr),
52  pA(0),pZ(0), tA(0),tZ(0),spectatorA(0),spectatorZ(0),
53  projectile3dNucleus(0),target3dNucleus(0)
54 {
55  if(!ptr) {
58  G4VPreCompoundModel* pre = static_cast<G4VPreCompoundModel*>(p);
59  if(!pre) { pre = new G4PreCompoundModel(); }
60  theProjectileFragmentation = pre;
61  }
62  theModel = new G4BinaryCascade(theProjectileFragmentation);
63  theHandler = theProjectileFragmentation->GetExcitationHandler();
64 
65  debug_G4BinaryLightIonReactionResults=getenv("debug_G4BinaryLightIonReactionResults")!=0;
66 }
67 
69 {}
70 
72 {
73  outFile << "G4Binary Light Ion Cascade is an intra-nuclear cascade model\n"
74  << "using G4BinaryCasacde to model the interaction of a light\n"
75  << "nucleus with a nucleus.\n"
76  << "The lighter of the two nuclei is treated like a set of projectiles\n"
77  << "which are transported simultanously through the heavier nucleus.\n";
78 }
79 
80 //--------------------------------------------------------------------------------
82 {
84 };
85 
87 ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus & targetNucleus )
88 {
89  static G4int eventcounter=0;
90  eventcounter++;
91  if(getenv("BLICDEBUG") ) G4cerr << " ######### Binary Light Ion Reaction number starts ######### "<<eventcounter<<G4endl;
92  G4ping debug("debug_G4BinaryLightIonReaction");
93  pA=aTrack.GetDefinition()->GetBaryonNumber();
94  pZ=G4lrint(aTrack.GetDefinition()->GetPDGCharge()/eplus);
95  tA=targetNucleus.GetA_asInt();
96  tZ=targetNucleus.GetZ_asInt();
97 
98  G4LorentzVector mom(aTrack.Get4Momentum());
99  //G4cout << "proj mom : " << mom << G4endl;
100  G4LorentzRotation toBreit(mom.boostVector());
101 
102  G4bool swapped=SetLighterAsProjectile(mom, toBreit);
103  //G4cout << "after swap, swapped? / mom " << swapped << " / " << mom <<G4endl;
104  G4ReactionProductVector * result = 0;
105  G4ReactionProductVector * cascaders=0; //new G4ReactionProductVector;
106 // G4double m_nucl(0); // to check energy balance
107 
108 
109  // G4double m1=G4ParticleTable::GetParticleTable()->GetIonTable()->GetIonMass(pZ,pA);
110  // G4cout << "Entering the decision point "
111  // << (mom.t()-mom.mag())/pA << " "
112  // << pA<<" "<< pZ<<" "
113  // << tA<<" "<< tZ<<G4endl
114  // << " "<<mom.t()-mom.mag()<<" "
115  // << mom.t()- m1<<G4endl;
116  if( (mom.t()-mom.mag())/pA < 50*MeV )
117  {
118  // G4cout << "Using pre-compound only, E= "<<mom.t()-mom.mag()<<G4endl;
119  // m_nucl = mom.mag();
120  cascaders=FuseNucleiAndPrompound(mom);
121  }
122  else
123  {
124  result=Interact(mom,toBreit);
125 
126  if(! result )
127  {
128  {
129  // abort!!
130 
131  G4cerr << "G4BinaryLightIonReaction no final state for: " << G4endl;
132  G4cerr << " Primary " << aTrack.GetDefinition()
133  << ", (A,Z)=(" << aTrack.GetDefinition()->GetBaryonNumber()
134  << "," << aTrack.GetDefinition()->GetPDGCharge()/eplus << ") "
135  << ", kinetic energy " << aTrack.GetKineticEnergy()
136  << G4endl;
137  G4cerr << " Target nucleus (A,Z)=("
138  << (swapped?pA:tA) << ","
139  << (swapped?pZ:tZ) << ")" << G4endl;
140  G4cerr << " if frequent, please submit above information as bug report"
141  << G4endl << G4endl;
142 
143  theResult.Clear();
144  theResult.SetStatusChange(isAlive);
145  theResult.SetEnergyChange(aTrack.GetKineticEnergy());
146  theResult.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
147  return &theResult;
148 
149  }
150  }
151 
152  // Calculate excitation energy,
153  G4double theStatisticalExEnergy = GetProjectileExcitation();
154 
155 
156  pInitialState = mom;
157  //G4cout << "pInitialState from aTrack : " << pInitialState;
158  pInitialState.setT(pInitialState.getT() +
160  //G4cout << "target nucleus added : " << pInitialState << G4endl;
161 
162  delete target3dNucleus;target3dNucleus=0;
163  delete projectile3dNucleus;projectile3dNucleus=0;
164 
166 
167  cascaders = new G4ReactionProductVector;
168 
169  G4LorentzVector pspectators=SortResult(result,spectators,cascaders);
170 
171  // pFinalState=std::accumulate(cascaders->begin(),cascaders->end(),pFinalState,ReactionProduct4Mom);
172  std::vector<G4ReactionProduct *>::iterator iter;
173 
174  //G4cout << "pInitialState, pFinalState / pspectators"<< pInitialState << " / " << pFinalState << " / " << pspectators << G4endl;
175  // if ( spectA-spectatorA !=0 || spectZ-spectatorZ !=0)
176  // {
177  // G4cout << "spect Nucl != spectators: nucl a,z; spect a,z" <<
178  // spectatorA <<" "<< spectatorZ <<" ; " << spectA <<" "<< spectZ << G4endl;
179  // }
180  delete result;
181  result=0;
182  G4LorentzVector momentum(pInitialState-pFinalState);
183  G4int loopcount(0);
184  //G4cout << "momentum, pspectators : " << momentum << " / " << pspectators << G4endl;
185  while (std::abs(momentum.e()-pspectators.e()) > 10*MeV)
186  {
187  G4LorentzVector pCorrect(pInitialState-pspectators);
188  //G4cout << "BIC nonconservation? (pInitialState-pFinalState) / spectators :" << momentum << " / " << pspectators << "pCorrect "<< pCorrect<< G4endl;
189  // Correct outgoing casacde particles.... to have momentum of (initial state - spectators)
190  G4bool EnergyIsCorrect=EnergyAndMomentumCorrector(cascaders, pCorrect);
191  if ( ! EnergyIsCorrect && debug_G4BinaryLightIonReactionResults)
192  {
193  G4cout << "Warning - G4BinaryLightIonReaction E/P correction for cascaders failed" << G4endl;
194  }
195  pFinalState=G4LorentzVector(0,0,0,0);
196  unsigned int i;
197  for(i=0; i<cascaders->size(); i++)
198  {
199  pFinalState += G4LorentzVector( (*cascaders)[i]->GetMomentum(), (*cascaders)[i]->GetTotalEnergy() );
200  }
201  momentum=pInitialState-pFinalState;
202  if (++loopcount > 10 )
203  {
204  if ( momentum.vect().mag() - momentum.e()> 10*keV )
205  {
206  G4cerr << "G4BinaryLightIonReaction.cc: Cannot correct 4-momentum of cascade particles" << G4endl;
207  throw G4HadronicException(__FILE__, __LINE__, "G4BinaryCasacde::ApplyCollision()");
208  } else {
209  break;
210  }
211 
212  }
213  }
214 
215  if (spectatorA > 0 )
216  {
217  // check spectator momentum
218  if ( momentum.vect().mag() - momentum.e()> 10*keV )
219  {
220 
221  G4ReactionProductVector::iterator ispectator;
222  for (ispectator=spectators->begin();ispectator!=spectators->end();ispectator++)
223  {
224  delete *ispectator;
225  }
226  delete spectators;
227 
228  G4cout << "G4BinaryLightIonReaction.cc: mom check: " << momentum
229  << " 3.mag "<< momentum.vect().mag() << G4endl
230  << " .. pInitialState/pFinalState/spectators " << pInitialState <<" "
231  << pFinalState << " " << pspectators << G4endl
232  << " .. A,Z " << spectatorA <<" "<< spectatorZ << G4endl;
233  G4cout << "G4BinaryLightIonReaction invalid final state for: " << G4endl;
234  G4cout << " Primary " << aTrack.GetDefinition()
235  << ", (A,Z)=(" << aTrack.GetDefinition()->GetBaryonNumber()
236  << "," << aTrack.GetDefinition()->GetPDGCharge()/eplus << ") "
237  << ", kinetic energy " << aTrack.GetKineticEnergy()
238  << G4endl;
239  G4cout << " Target nucleus (A,Z)=(" << targetNucleus.GetA_asInt()
240  << "," << targetNucleus.GetZ_asInt() << ")" << G4endl;
241  G4cout << " if frequent, please submit above information as bug report"
242  << G4endl << G4endl;
243 
244  theResult.Clear();
245  theResult.SetStatusChange(isAlive);
246  theResult.SetEnergyChange(aTrack.GetKineticEnergy());
247  theResult.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
248  return &theResult;
249  }
250 
251 
252  DeExciteSpectatorNucleus(spectators, cascaders, theStatisticalExEnergy, momentum);
253  }
254  }
255  // Rotate to lab
256  G4LorentzRotation toZ;
257  toZ.rotateZ(-1*mom.phi());
258  toZ.rotateY(-1*mom.theta());
259  G4LorentzRotation toLab(toZ.inverse());
260 
261  // Fill the particle change, while rotating. Boost from projectile breit-frame in case we swapped.
262  // theResult.Clear();
263  theResult.Clear();
264  theResult.SetStatusChange(stopAndKill);
265  G4double Etot(0);
266  size_t i=0;
267  for(i=0; i<cascaders->size(); i++)
268  {
269  if((*cascaders)[i]->GetNewlyAdded())
270  {
271  G4DynamicParticle * aNew =
272  new G4DynamicParticle((*cascaders)[i]->GetDefinition(),
273  (*cascaders)[i]->GetTotalEnergy(),
274  (*cascaders)[i]->GetMomentum() );
275  G4LorentzVector tmp = aNew->Get4Momentum();
276  if(swapped)
277  {
278  tmp*=toBreit.inverse();
279  tmp.setVect(-tmp.vect());
280  }
281  tmp *= toLab;
282  aNew->Set4Momentum(tmp);
283  //G4cout << "result[" << i << "], 4vect: " << tmp << G4endl;
284  theResult.AddSecondary(aNew);
285  Etot += tmp.e();
286  // G4cout << "LIBIC: Secondary " << aNew->GetDefinition()->GetParticleName()
287  // <<" "<< aNew->GetMomentum()
288  // <<" "<< aNew->GetTotalEnergy()
289  // << G4endl;
290  }
291  delete (*cascaders)[i];
292  }
293  delete cascaders;
294 
295 #ifdef debug_BLIR_result
296  G4cout << "Result analysis, secondaries" << theResult.GetNumberOfSecondaries() << G4endl;
297  G4cout << " Energy conservation initial/primary/nucleus/final/delta(init-final) "
298  << aTrack.GetTotalEnergy() + m_nucl << aTrack.GetTotalEnergy() << m_nucl <<Etot
299  << aTrack.GetTotalEnergy() + m_nucl - Etot;
300 #endif
301 
302  if(getenv("BLICDEBUG") ) G4cerr << " ######### Binary Light Ion Reaction number ends ######### "<<eventcounter<<G4endl;
303 
304  return &theResult;
305 }
306 
307 //--------------------------------------------------------------------------------
308 
309 //****************************************************************************
310 G4bool G4BinaryLightIonReaction::EnergyAndMomentumCorrector(
311  G4ReactionProductVector* Output, G4LorentzVector& TotalCollisionMom)
312 //****************************************************************************
313 {
314  const int nAttemptScale = 2500;
315  const double ErrLimit = 1.E-6;
316  if (Output->empty())
317  return TRUE;
318  G4LorentzVector SumMom(0,0,0,0);
319  G4double SumMass = 0;
320  G4double TotalCollisionMass = TotalCollisionMom.m();
321  size_t i = 0;
322  // Calculate sum hadron 4-momenta and summing hadron mass
323  for(i = 0; i < Output->size(); i++)
324  {
325  SumMom += G4LorentzVector((*Output)[i]->GetMomentum(),(*Output)[i]->GetTotalEnergy());
326  SumMass += (*Output)[i]->GetDefinition()->GetPDGMass();
327  }
328  // G4cout << " E/P corrector, SumMass, SumMom.m2, TotalMass "
329  // << SumMass <<" "<< SumMom.m2() <<" "<<TotalCollisionMass<< G4endl;
330  if (SumMass > TotalCollisionMass) return FALSE;
331  SumMass = SumMom.m2();
332  if (SumMass < 0) return FALSE;
333  SumMass = std::sqrt(SumMass);
334 
335  // Compute c.m.s. hadron velocity and boost KTV to hadron c.m.s.
336  G4ThreeVector Beta = -SumMom.boostVector();
337  //G4cout << " == pre boost 2 "<< SumMom.e()<< " "<< SumMom.mag()<<" "<< Beta <<G4endl;
338  //--old Output->Boost(Beta);
339  for(i = 0; i < Output->size(); i++)
340  {
341  G4LorentzVector mom = G4LorentzVector((*Output)[i]->GetMomentum(),(*Output)[i]->GetTotalEnergy());
342  mom *= Beta;
343  (*Output)[i]->SetMomentum(mom.vect());
344  (*Output)[i]->SetTotalEnergy(mom.e());
345  }
346 
347  // Scale total c.m.s. hadron energy (hadron system mass).
348  // It should be equal interaction mass
349  G4double Scale = 0,OldScale=0;
350  G4double factor = 1.;
351  G4int cAttempt = 0;
352  G4double Sum = 0;
353  G4bool success = false;
354  for(cAttempt = 0; cAttempt < nAttemptScale; cAttempt++)
355  {
356  Sum = 0;
357  for(i = 0; i < Output->size(); i++)
358  {
359  G4LorentzVector HadronMom = G4LorentzVector((*Output)[i]->GetMomentum(),(*Output)[i]->GetTotalEnergy());
360  HadronMom.setVect(HadronMom.vect()+ factor*Scale*HadronMom.vect());
361  G4double E = std::sqrt(HadronMom.vect().mag2() + sqr((*Output)[i]->GetDefinition()->GetPDGMass()));
362  HadronMom.setE(E);
363  (*Output)[i]->SetMomentum(HadronMom.vect());
364  (*Output)[i]->SetTotalEnergy(HadronMom.e());
365  Sum += E;
366  }
367  OldScale=Scale;
368  Scale = TotalCollisionMass/Sum - 1;
369  // G4cout << "E/P corr - " << cAttempt << " " << Scale << G4endl;
370  if (std::abs(Scale) <= ErrLimit
371  || OldScale == Scale) // protect 'frozen' situation and divide by 0 in calculating new factor below
372  {
373  if (debug_G4BinaryLightIonReactionResults) G4cout << "E/p corrector: " << cAttempt << G4endl;
374  success = true;
375  break;
376  }
377  if ( cAttempt > 10 )
378  {
379  // G4cout << " speed it up? " << std::abs(OldScale/(OldScale-Scale)) << G4endl;
380  factor=std::max(1.,std::log(std::abs(OldScale/(OldScale-Scale))));
381  // G4cout << " ? factor ? " << factor << G4endl;
382  }
383  }
384 
385  if( (!success) && debug_G4BinaryLightIonReactionResults)
386  {
387  G4cout << "G4G4BinaryLightIonReaction::EnergyAndMomentumCorrector - Warning"<<G4endl;
388  G4cout << " Scale not unity at end of iteration loop: "<<TotalCollisionMass<<" "<<Sum<<" "<<Scale<<G4endl;
389  G4cout << " Increase number of attempts or increase ERRLIMIT"<<G4endl;
390  }
391 
392  // Compute c.m.s. interaction velocity and KTV back boost
393  Beta = TotalCollisionMom.boostVector();
394  //--old Output->Boost(Beta);
395  for(i = 0; i < Output->size(); i++)
396  {
397  G4LorentzVector mom = G4LorentzVector((*Output)[i]->GetMomentum(),(*Output)[i]->GetTotalEnergy());
398  mom *= Beta;
399  (*Output)[i]->SetMomentum(mom.vect());
400  (*Output)[i]->SetTotalEnergy(mom.e());
401  }
402  return TRUE;
403 }
404 G4bool G4BinaryLightIonReaction::SetLighterAsProjectile(G4LorentzVector & mom,const G4LorentzRotation & toBreit)
405 {
406  G4bool swapped = false;
407  if(tA<pA)
408  {
409  swapped = true;
410  G4int tmp(0);
411  tmp = tA; tA=pA; pA=tmp;
412  tmp = tZ; tZ=pZ; pZ=tmp;
414  G4LorentzVector it(m1, G4ThreeVector(0,0,0));
415  mom = toBreit*it;
416  }
417  return swapped;
418 }
419 G4ReactionProductVector * G4BinaryLightIonReaction::FuseNucleiAndPrompound(const G4LorentzVector & mom)
420 {
421  G4Fragment aPreFrag;
422  aPreFrag.SetA(pA+tA);
423  aPreFrag.SetZ(pZ+tZ);
424  aPreFrag.SetNumberOfParticles(pA);
425  aPreFrag.SetNumberOfCharged(pZ);
426  aPreFrag.SetNumberOfHoles(0);
427  G4ThreeVector plop(0.,0., mom.vect().mag());
429  G4LorentzVector aL(mom.t()+m_nucl, plop);
430  aPreFrag.SetMomentum(aL);
431  G4ParticleDefinition * preFragDef;
432  preFragDef = G4ParticleTable::GetParticleTable()
433  ->FindIon(pZ+tZ,pA+tA,0,pZ+tZ);
434  aPreFrag.SetParticleDefinition(preFragDef);
435 
436  // G4cout << "Fragment INFO "<< pA+tA <<" "<<pZ+tZ<<" "
437  // << aL <<" "<<preFragDef->GetParticleName()<<G4endl;
438  G4ReactionProductVector * cascaders = theProjectileFragmentation->DeExcite(aPreFrag);
439  //G4double tSum = 0;
440  for(size_t count = 0; count<cascaders->size(); count++)
441  {
442  cascaders->operator[](count)->SetNewlyAdded(true);
443  //tSum += cascaders->operator[](count)->GetKineticEnergy();
444  }
445  // G4cout << "Exiting pre-compound only, E= "<<tSum<<G4endl;
446  return cascaders;
447 }
448 G4ReactionProductVector * G4BinaryLightIonReaction::Interact(G4LorentzVector & mom, const G4LorentzRotation & toBreit)
449 {
450  G4ReactionProductVector * result = 0;
451  G4double projectileMass(0);
452  G4LorentzVector it;
453 
454  G4int tryCount(0);
455  do
456  {
457  ++tryCount;
458  projectile3dNucleus = new G4Fancy3DNucleus;
459  projectile3dNucleus->Init(pA, pZ);
460  projectile3dNucleus->CenterNucleons();
462  projectile3dNucleus->GetCharge(),projectile3dNucleus->GetMassNumber());
463  it=toBreit * G4LorentzVector(projectileMass,G4ThreeVector(0,0,0));
464 
465  target3dNucleus = new G4Fancy3DNucleus;
466  target3dNucleus->Init(tA, tZ);
467  G4double impactMax = target3dNucleus->GetOuterRadius()+projectile3dNucleus->GetOuterRadius();
468  // G4cout << "out radius - nucleus - projectile " << target3dNucleus->GetOuterRadius()/fermi << " - " << projectile3dNucleus->GetOuterRadius()/fermi << G4endl;
469  G4double aX=(2.*G4UniformRand()-1.)*impactMax;
470  G4double aY=(2.*G4UniformRand()-1.)*impactMax;
471  G4ThreeVector pos(aX, aY, -2.*impactMax-5.*fermi);
472 
473  G4KineticTrackVector * initalState = new G4KineticTrackVector;
474  projectile3dNucleus->StartLoop();
475  G4Nucleon * aNuc;
476  G4LorentzVector tmpV(0,0,0,0);
477  G4LorentzVector nucleonMom(1./pA*mom);
478  nucleonMom.setZ(nucleonMom.vect().mag());
479  nucleonMom.setX(0);
480  nucleonMom.setY(0);
481  theFermi.Init(pA,pZ);
482  while( (aNuc=projectile3dNucleus->GetNextNucleon()) )
483  {
484  G4LorentzVector p4 = aNuc->GetMomentum();
485  tmpV+=p4;
486  G4ThreeVector nucleonPosition(aNuc->GetPosition());
487  G4double density=(projectile3dNucleus->GetNuclearDensity())->GetDensity(nucleonPosition);
488  nucleonPosition += pos;
489  G4KineticTrack * it1 = new G4KineticTrack(aNuc, nucleonPosition, nucleonMom );
491  G4double pfermi= theFermi.GetFermiMomentum(density);
492  G4double mass = aNuc->GetDefinition()->GetPDGMass();
493  G4double Efermi= std::sqrt( sqr(mass) + sqr(pfermi)) - mass;
494  it1->SetProjectilePotential(-Efermi);
495  initalState->push_back(it1);
496  }
497 
498  result=theModel->Propagate(initalState, target3dNucleus);
499  if( result && result->size()==0)
500  {
501  delete result;
502  result=0;
503  }
504  if ( ! result )
505  {
506  delete target3dNucleus;
507  delete projectile3dNucleus;
508  }
509 
510  // std::for_each(initalState->begin(), initalState->end(), Delete<G4KineticTrack>());
511  // delete initalState;
512 
513  } while (! result && tryCount< 150);
514  return result;
515 }
516 G4double G4BinaryLightIonReaction::GetProjectileExcitation()
517 {
518  spectatorA=spectatorZ=0;
519 
520  G4Nucleon * aNuc;
521  // targetNucleus->StartLoop();
522  // while( (aNuc=targetNucleus->GetNextNucleon()) )
523  // {
524  // G4cout << " tgt Nucleon : " << aNuc->GetDefinition()->GetParticleName() <<" "<< aNuc->AreYouHit() <<" "<<aNuc->GetMomentum()<<G4endl;
525  // }
526  // the projectileNucleus excitation energy estimate...
527  G4double theStatisticalExEnergy = 0;
528  projectile3dNucleus->StartLoop();
529  while( (aNuc=projectile3dNucleus->GetNextNucleon()) )
530  {
531  // G4cout << " Nucleon : " << aNuc->GetDefinition()->GetParticleName() <<" "<< aNuc->AreYouHit() <<" "<<aNuc->GetMomentum()<<G4endl;
532  if(!aNuc->AreYouHit())
533  {
534  spectatorA++;
535  spectatorZ+=G4lrint(aNuc->GetDefinition()->GetPDGCharge()/eplus);
536  }
537  else
538  {
539  G4ThreeVector aPosition(aNuc->GetPosition());
540  G4double localDensity = projectile3dNucleus->GetNuclearDensity()->GetDensity(aPosition);
541  G4double localPfermi = theFermi.GetFermiMomentum(localDensity);
542  G4double nucMass = aNuc->GetDefinition()->GetPDGMass();
543  G4double localFermiEnergy = std::sqrt(nucMass*nucMass + localPfermi*localPfermi) - nucMass;
544  G4double deltaE = localFermiEnergy - (aNuc->GetMomentum().t()-aNuc->GetMomentum().mag());
545  theStatisticalExEnergy += deltaE;
546  }
547  }
548  return theStatisticalExEnergy;
549 }
550 
551 G4LorentzVector G4BinaryLightIonReaction::SortResult(G4ReactionProductVector * result, G4ReactionProductVector * spectators,G4ReactionProductVector * cascaders)
552 {
553  unsigned int i(0);
554  // G4int spectA(0),spectZ(0);
555  G4LorentzVector pspectators(0,0,0,0);
556  pFinalState=G4LorentzVector(0,0,0,0);
557  for(i=0; i<result->size(); i++)
558  {
559  if( (*result)[i]->GetNewlyAdded() )
560  {
561  pFinalState += G4LorentzVector( (*result)[i]->GetMomentum(), (*result)[i]->GetTotalEnergy() );
562  cascaders->push_back((*result)[i]);
563  }
564  else {
565  // G4cout <<" spectator ... ";
566  pspectators += G4LorentzVector( (*result)[i]->GetMomentum(), (*result)[i]->GetTotalEnergy() );
567  spectators->push_back((*result)[i]);
568  // spectA++;
569  // spectZ+= G4lrint((*result)[i]->GetDefinition()->GetPDGCharge()/eplus);
570  }
571 
572  // G4cout << (*result)[i]<< " "
573  // << (*result)[i]->GetDefinition()->GetParticleName() << " "
574  // << (*result)[i]->GetMomentum()<< " "
575  // << (*result)[i]->GetTotalEnergy() << G4endl;
576  }
577  //G4cout << "pFinalState / pspectators" << pFinalState << " / " << pspectators << G4endl;
578  return pspectators;
579 }
580 
581 void G4BinaryLightIonReaction::DeExciteSpectatorNucleus(G4ReactionProductVector * spectators, G4ReactionProductVector * cascaders,
582  G4double theStatisticalExEnergy, G4LorentzVector & pSpectators)
583 {
584  // call precompound model
585  G4ReactionProductVector * proFrag = 0;
586  G4LorentzVector pFragment(0.,0.,0.,0.);
587  // G4cout << " == pre boost 1 "<< momentum.e()<< " "<< momentum.mag()<<G4endl;
588  G4LorentzRotation boost_fragments;
589  // G4cout << " == post boost 1 "<< momentum.e()<< " "<< momentum.mag()<<G4endl;
590  // G4LorentzRotation boost_spectator_mom(-momentum.boostVector());
591  // G4cout << "- momentum " << boost_spectator_mom * momentum << G4endl;
592  G4LorentzVector pFragments(0,0,0,0);
593 
594  if(spectatorZ>0 && spectatorA>1)
595  {
596  // Make the fragment
597  G4Fragment aProRes;
598  aProRes.SetA(spectatorA);
599  aProRes.SetZ(spectatorZ);
600  aProRes.SetNumberOfParticles(0);
601  aProRes.SetNumberOfCharged(0);
602  aProRes.SetNumberOfHoles(pA-spectatorA);
603  G4double mFragment=G4ParticleTable::GetParticleTable()->GetIonTable()->GetIonMass(spectatorZ,spectatorA);
604  pFragment=G4LorentzVector(0,0,0,mFragment+std::max(0.,theStatisticalExEnergy) );
605  aProRes.SetMomentum(pFragment);
606  G4ParticleDefinition * resDef;
607  resDef = G4ParticleTable::GetParticleTable()->FindIon(spectatorZ,spectatorA,0,spectatorZ);
608  aProRes.SetParticleDefinition(resDef);
609 
610  proFrag = theHandler->BreakItUp(aProRes);
611 
612  boost_fragments = G4LorentzRotation(pSpectators.boostVector());
613 
614  // G4cout << " Fragment a,z, Mass Fragment, mass spect-mom, exitationE "
615  // << spectatorA <<" "<< spectatorZ <<" "<< mFragment <<" "
616  // << momentum.mag() <<" "<< momentum.mag() - mFragment
617  // << " "<<theStatisticalExEnergy
618  // << " "<< boost_fragments*pFragment<< G4endl;
619  G4ReactionProductVector::iterator ispectator;
620  for (ispectator=spectators->begin();ispectator!=spectators->end();ispectator++)
621  {
622  delete *ispectator;
623  }
624  }
625  else if(spectatorA!=0)
626  {
627  G4ReactionProductVector::iterator ispectator;
628  for (ispectator=spectators->begin();ispectator!=spectators->end();ispectator++)
629  {
630  (*ispectator)->SetNewlyAdded(true);
631  cascaders->push_back(*ispectator);
632  pFragments+=G4LorentzVector((*ispectator)->GetMomentum(),(*ispectator)->GetTotalEnergy());
633  // G4cout << "from spectator "
634  // << (*ispectator)->GetDefinition()->GetParticleName() << " "
635  // << (*ispectator)->GetMomentum()<< " "
636  // << (*ispectator)->GetTotalEnergy() << G4endl;
637  }
638  }
639  // / if (spectators)
640  delete spectators;
641 
642  // collect the evaporation part and boost to spectator frame
643  G4ReactionProductVector::iterator ii;
644  if(proFrag)
645  {
646  for(ii=proFrag->begin(); ii!=proFrag->end(); ii++)
647  {
648  (*ii)->SetNewlyAdded(true);
649  G4LorentzVector tmp((*ii)->GetMomentum(),(*ii)->GetTotalEnergy());
650  tmp *= boost_fragments;
651  (*ii)->SetMomentum(tmp.vect());
652  (*ii)->SetTotalEnergy(tmp.e());
653  // result->push_back(*ii);
654  pFragments += tmp;
655  }
656  }
657 
658  // G4cout << "Fragmented p, momentum, delta " << pFragments <<" "<<momentum
659  // <<" "<< pFragments-momentum << G4endl;
660 
661  // correct p/E of Cascade secondaries
662  G4LorentzVector pCas=pInitialState - pFragments;
663 
664  //G4cout <<" Going to correct from " << pFinalState << " to " << pCas << G4endl;
665  G4bool EnergyIsCorrect=EnergyAndMomentumCorrector(cascaders, pCas);
666  if ( ! EnergyIsCorrect && debug_G4BinaryLightIonReactionResults)
667  {
668  G4cout << "G4BinaryLightIonReaction E/P correction for nucleus failed, will try to correct overall" << G4endl;
669  }
670 
671  // Add deexcitation secondaries
672  if(proFrag)
673  {
674  for(ii=proFrag->begin(); ii!=proFrag->end(); ii++)
675  {
676  cascaders->push_back(*ii);
677  }
678  delete proFrag;
679  }
680  //G4cout << "EnergyIsCorrect? " << EnergyIsCorrect << G4endl;
681  if ( ! EnergyIsCorrect )
682  {
683  //G4cout <<" ! EnergyIsCorrect " << pFinalState << " to " << pInitialState << G4endl;
684  if (! EnergyAndMomentumCorrector(cascaders,pInitialState))
685  {
686  if(debug_G4BinaryLightIonReactionResults)
687  G4cout << "G4BinaryLightIonReaction E/P corrections failed" << G4endl;
688  }
689  }
690 
691 }
692