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

Last change on this file since 960 was 819, checked in by garnier, 17 years ago

import all except CVS

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