5 #include "FullModelHadronicProcess.hh"
6 #include "G4Version.hh"
7 #include "G4ProcessManager.hh"
8 #include "G4ProcessHelper.hh"
9 #include "G4ParticleTable.hh"
10 #include "FullModelReactionDynamics.hh"
12 #if G4VERSION_NUMBER < 1100
13 #include "G4HadReentrentException.hh"
15 #include "G4HadronicException.hh"
21 FullModelHadronicProcess::FullModelHadronicProcess(
const G4String& processName) :
22 G4VDiscreteProcess(processName,fUserDefined),m_theParticle(0),m_newParticle(0),m_cache(0)
25 m_theHelper = G4ProcessHelper::Instance();
30 G4bool FullModelHadronicProcess::IsApplicable(
const G4ParticleDefinition& aP)
33 return m_theHelper->ApplicabilityTester(aP);
37 G4double FullModelHadronicProcess::GetMicroscopicCrossSection(
const G4DynamicParticle *aParticle,
38 const G4Element *anElement,
42 G4double InclXsec = m_theHelper->GetInclusiveCrossSection(aParticle,anElement);
46 G4double HighestEnergyLimit = 10 *
CLHEP::TeV ;
47 G4double LowestEnergyLimit = 1 *
CLHEP::eV;
49 G4double ParticleEnergy = aParticle->GetKineticEnergy();
52 if (ParticleEnergy > HighestEnergyLimit || ParticleEnergy < LowestEnergyLimit){
61 G4double FullModelHadronicProcess::GetMeanFreePath(
const G4Track& aTrack, G4double, G4ForceCondition*)
63 G4Material *aMaterial = aTrack.GetMaterial();
64 const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
67 G4int nElements = aMaterial->GetNumberOfElements();
69 const G4double *theAtomicNumDensityVector =
70 aMaterial->GetAtomicNumDensityVector();
71 G4double aTemp = aMaterial->GetTemperature();
73 for( G4int
i=0;
i<nElements; ++
i )
76 GetMicroscopicCrossSection( aParticle, (*aMaterial->GetElementVector())[
i], aTemp);
77 sigma += theAtomicNumDensityVector[
i] * xSection;
85 G4VParticleChange* FullModelHadronicProcess::PostStepDoIt(
const G4Track& aTrack,
89 aParticleChange.Initialize(aTrack);
91 const G4DynamicParticle* IncidentRhadron = aTrack.GetDynamicParticle();
93 const G4ThreeVector& aPosition = aTrack.GetPosition();
94 const G4int theIncidentPDG = IncidentRhadron->GetDefinition()->GetPDGEncoding();
95 G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
96 std::vector<G4ParticleDefinition*> theParticleDefinitions;
97 G4bool IncidentSurvives =
false;
98 G4bool TargetSurvives =
false;
99 G4Nucleus targetNucleus(aTrack.GetMaterial());
100 G4ParticleDefinition* outgoingRhadron=0;
101 G4ParticleDefinition* outgoingCloud=0;
102 G4ParticleDefinition* outgoingTarget=0;
105 G4ThreeVector p_0 = IncidentRhadron->GetMomentum();
109 G4double e_kin_0 = IncidentRhadron->GetKineticEnergy();
111 G4DynamicParticle* cloudParticle =
new G4DynamicParticle();
113 cloudParticle->SetDefinition(CustomIncident->
GetCloud());
115 if(cloudParticle->GetDefinition() == 0)
117 G4cout <<
"FullModelHadronicProcess::PostStepDoIt Definition of particle cloud not available!!" << G4endl;
119 double scale=cloudParticle->GetDefinition()->GetPDGMass()/IncidentRhadron->GetDefinition()->GetPDGMass();
121 G4LorentzVector cloudMomentum;
122 cloudMomentum.setVectM(IncidentRhadron->GetMomentum()*
scale,cloudParticle->GetDefinition()->GetPDGMass());
123 G4LorentzVector gluinoMomentum;
125 gluinoMomentum.setVectM(IncidentRhadron->GetMomentum()*(1.-
scale),CustomIncident->
GetSpectator()->GetPDGMass());
127 G4LorentzVector FullRhadron4Momentum = IncidentRhadron->Get4Momentum();
128 G4LorentzVector Cloud4Momentum = cloudMomentum;
130 cloudParticle->Set4Momentum(cloudMomentum);
132 G4DynamicParticle* OrgPart = cloudParticle;
134 G4double ek = OrgPart->GetKineticEnergy();
135 G4double amas = OrgPart->GetDefinition()->GetPDGMass();
136 G4double tkin = targetNucleus.Cinema( ek );
138 OrgPart->SetKineticEnergy( ek );
139 G4double
et = ek + amas;
140 G4double
p = std::sqrt( std::abs((
et-amas)*(
et+amas)) );
141 G4double pp = OrgPart->GetMomentum().mag();
144 G4ThreeVector
momentum = OrgPart->GetMomentum();
145 OrgPart->SetMomentum(
momentum * (
p/pp) );
149 if(ek>0.) {tkin = targetNucleus.EvaporationEffects( ek ); ek -= tkin;}
150 if(ek+gluinoMomentum.e()-gluinoMomentum.m()<=0.1*
CLHEP::MeV||ek<=0.) {
151 G4cout<<
"Stopping particle...:"<<G4endl;
152 G4cout<<
"ek: "<<ek/
CLHEP::MeV<<
" MeV"<<G4endl;
153 aParticleChange.ProposeTrackStatus( fStopButAlive );
155 return &aParticleChange;
157 OrgPart->SetKineticEnergy( ek );
159 p = std::sqrt( std::abs((
et-amas)*(
et+amas)) );
160 pp = OrgPart->GetMomentum().mag();
164 G4ThreeVector
momentum = OrgPart->GetMomentum();
165 OrgPart->SetMomentum(
momentum * (
p/pp) );
172 G4ParticleDefinition* aTarget;
173 ReactionProduct
rp = m_theHelper->GetFinalState(aTrack,aTarget);
184 G4int NumberOfSecondaries =
rp.size();
188 G4LorentzVector Target4Momentum;
189 Target4Momentum.setVectM(CLHEP::Hep3Vector(0.,0.,0.),aTarget->GetPDGMass());
191 G4LorentzVector psum_full,psum_cloud;
192 psum_full = FullRhadron4Momentum + Target4Momentum;
193 psum_cloud = Cloud4Momentum + Target4Momentum;
194 G4ThreeVector trafo_full_cms = (-1)*psum_full.boostVector();
195 G4ThreeVector trafo_cloud_cms = (-1)*psum_cloud.boostVector();
204 G4ParticleDefinition* tempDef = theParticleTable->FindParticle(*
it);
206 if (tempDef==aTarget) TargetSurvives =
true;
210 outgoingRhadron = tempDef;
212 if(outgoingCloud == 0)
214 G4cout <<
"FullModelHadronicProcess::PostStepDoIt() Definition of outgoing particle cloud for " << tempDef->GetParticleName() <<
" not available!!" << G4endl;
219 if (tempCust==0&&
rp.size()==2) outgoingTarget = tempDef;
220 if (tempDef->GetPDGEncoding()==theIncidentPDG) {
221 IncidentSurvives =
true;
223 theParticleDefinitions.push_back(tempDef);
227 if (NULL==outgoingRhadron) {
232 description <<
"PostStepDoIt: outgoingRHadron is null";
233 G4Exception(
"FullModelHadronicProcess",
"NoOutGoingRHadron", FatalException,
description);
236 if (outgoingTarget==0) outgoingTarget = theParticleTable->FindParticle(
rp[1]);
240 if(IncidentSurvives) NumberOfSecondaries--;
241 aParticleChange.SetNumberOfSecondaries(NumberOfSecondaries);
248 const G4HadProjectile* originalIncident =
new G4HadProjectile(*OrgPart);
252 G4HadProjectile* org2 =
new G4HadProjectile(*OrgPart);
253 G4LorentzRotation trans = org2->GetTrafoToLab();
256 G4DynamicParticle *originalTarget =
new G4DynamicParticle;
257 originalTarget->SetDefinition(aTarget);
259 G4ReactionProduct targetParticle(aTarget);
262 G4ReactionProduct currentParticle(
const_cast<G4ParticleDefinition *
>(originalIncident->GetDefinition() ) );
263 currentParticle.SetMomentum( originalIncident->Get4Momentum().vect() );
264 currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
267 G4ReactionProduct modifiedOriginal = currentParticle;
269 currentParticle.SetSide( 1 );
270 targetParticle.SetSide( -1 );
271 G4bool incidentHasChanged =
false;
272 if (!IncidentSurvives) incidentHasChanged =
true;
273 G4bool targetHasChanged =
false;
274 if (!TargetSurvives) targetHasChanged =
true;
275 G4bool quasiElastic =
false;
276 if (
rp.size()==2) quasiElastic =
true;
277 G4FastVector<G4ReactionProduct,GHADLISTSIZE>
vec;
286 for (G4int
i = 0;
i!=NumberOfSecondaries;
i++){
287 if(theParticleDefinitions[
i]!=aTarget
288 && theParticleDefinitions[
i]!=originalIncident->GetDefinition()
289 && theParticleDefinitions[
i]!=outgoingRhadron
290 && theParticleDefinitions[
i]!=outgoingTarget)
292 G4ReactionProduct* pa =
new G4ReactionProduct;
293 pa->SetDefinition( theParticleDefinitions[
i] );
294 (G4UniformRand() < 0.5) ? pa->SetSide( -1 ) : pa->SetSide( 1 );
295 vec.SetElement( vecLen++, pa );
301 if (incidentHasChanged) currentParticle.SetDefinitionAndUpdateE( outgoingCloud );
302 if (incidentHasChanged) modifiedOriginal.SetDefinition( outgoingCloud );
303 if (targetHasChanged) targetParticle.SetDefinitionAndUpdateE( outgoingTarget );
306 CalculateMomenta(
vec, vecLen,
307 originalIncident, originalTarget, modifiedOriginal,
308 targetNucleus, currentParticle, targetParticle,
309 incidentHasChanged, targetHasChanged, quasiElastic );
312 G4String cPname = currentParticle.GetDefinition()->GetParticleName();
315 aParticleChange.SetNumberOfSecondaries(vecLen+NumberOfSecondaries);
317 G4LorentzVector cloud_p4_new;
319 cloud_p4_new.setVectM(currentParticle.GetMomentum(),currentParticle.GetMass());
320 cloud_p4_new *= trans;
322 G4LorentzVector cloud_p4_old_full = Cloud4Momentum;
323 cloud_p4_old_full.boost(trafo_full_cms);
324 G4LorentzVector cloud_p4_old_cloud = Cloud4Momentum;
325 cloud_p4_old_cloud.boost(trafo_cloud_cms);
326 G4LorentzVector cloud_p4_full = cloud_p4_new;
327 cloud_p4_full.boost(trafo_full_cms);
328 G4LorentzVector cloud_p4_cloud = cloud_p4_new;
329 cloud_p4_cloud.boost(trafo_cloud_cms);
331 G4LorentzVector p_g_cms = gluinoMomentum;
332 p_g_cms.boost(trafo_full_cms);
334 G4LorentzVector p4_new;
335 p4_new.setVectM( cloud_p4_new.v() + gluinoMomentum.v(), outgoingRhadron->GetPDGMass() );
338 p_new = p4_new.vect();
340 aParticleChange.ProposeLocalEnergyDeposit((p4_new-cloud_p4_new-gluinoMomentum).
m());
342 if( incidentHasChanged )
344 G4DynamicParticle*
p0 =
new G4DynamicParticle;
345 p0->SetDefinition( outgoingRhadron );
346 p0->SetMomentum( p_new );
349 G4Track* Track0 =
new G4Track(
p0,
350 aTrack.GetGlobalTime(),
352 aParticleChange.AddSecondary(Track0);
357 if(
p0->GetKineticEnergy()>e_kin_0+1.e-9) {
358 G4cout<<
"ALAAAAARM!!! (incident changed from "
359 <<IncidentRhadron->GetDefinition()->GetParticleName()
360 <<
" to "<<
p0->GetDefinition()->GetParticleName()<<
")"<<G4endl;
361 G4cout<<
"Energy loss: "<<(e_kin_0-
p0->GetKineticEnergy())/
CLHEP::GeV<<
" GeV (should be positive)"<<G4endl;
363 if(
rp.size()!=3) G4cout<<
"DOUBLE ALAAAAARM!!!"<<G4endl;
367 if(std::abs(
p0->GetKineticEnergy()-e_kin_0)>100*
CLHEP::GeV) {
368 G4cout<<
"Diff. too big"<<G4endl;
371 aParticleChange.ProposeTrackStatus( fStopAndKill );
376 G4double
p = p_new.mag();
378 aParticleChange.ProposeMomentumDirection( p_new.x()/
p, p_new.y()/
p, p_new.z()/
p );
380 aParticleChange.ProposeMomentumDirection( 1.0, 0.0, 0.0 );
382 G4double aE = sqrt(
p*
p+(outgoingRhadron->GetPDGMass()*outgoingRhadron->GetPDGMass()) );
383 e_kin = aE - outgoingRhadron->GetPDGMass();
386 G4cout<<
"ALAAAAARM!!!"<<G4endl;
387 G4cout<<
"Energy loss: "<<(e_kin_0-e_kin)/
CLHEP::GeV<<
" GeV (should be positive)"<<G4endl;
388 if(
rp.size()!=3) G4cout<<
"DOUBLE ALAAAAARM!!!"<<G4endl;
391 G4cout<<
"Diff. too big"<<G4endl;
395 aParticleChange.ProposeEnergy( aE- outgoingRhadron->GetPDGMass() );
397 G4cout<<
"Diff. too big"<<G4endl;
402 if( targetParticle.GetMass() > 0.0 )
404 G4DynamicParticle *
p1 =
new G4DynamicParticle;
405 p1->SetDefinition( targetParticle.GetDefinition() );
407 G4ThreeVector
momentum = targetParticle.GetMomentum();
410 p1->SetMomentum( (trans*
p1->Get4Momentum()).vect());
411 G4Track* Track1 =
new G4Track(
p1,
412 aTrack.GetGlobalTime(),
414 aParticleChange.AddSecondary(Track1);
416 G4DynamicParticle *pa;
419 for(
int i=0;
i<vecLen; ++
i )
421 pa =
new G4DynamicParticle();
422 pa->SetDefinition(
vec[
i]->GetDefinition() );
423 pa->SetMomentum(
vec[
i]->GetMomentum() );
424 pa->Set4Momentum(trans*(pa->Get4Momentum()));
425 G4ThreeVector
pvec = pa->GetMomentum();
426 G4Track* Trackn =
new G4Track(pa,
427 aTrack.GetGlobalTime(),
429 aParticleChange.AddSecondary(Trackn);
433 delete originalIncident;
434 delete originalTarget;
437 ClearNumberOfInteractionLengthLeft();
440 return &aParticleChange;
445 void FullModelHadronicProcess::CalculateMomenta(
446 G4FastVector<G4ReactionProduct,GHADLISTSIZE> &
vec,
448 const G4HadProjectile *originalIncident,
449 const G4DynamicParticle *originalTarget,
450 G4ReactionProduct &modifiedOriginal,
451 G4Nucleus &targetNucleus,
452 G4ReactionProduct ¤tParticle,
453 G4ReactionProduct &targetParticle,
454 G4bool &incidentHasChanged,
455 G4bool &targetHasChanged,
456 G4bool quasiElastic )
458 FullModelReactionDynamics theReactionDynamics;
461 m_what = originalIncident->Get4Momentum().vect();
474 theReactionDynamics.TwoBody(
vec, vecLen,
475 modifiedOriginal, originalTarget,
476 currentParticle, targetParticle,
477 targetNucleus, targetHasChanged );
483 G4ReactionProduct leadingStrangeParticle;
484 G4bool leadFlag = MarkLeadingStrangeParticle( currentParticle,
486 leadingStrangeParticle );
493 G4bool finishedGenXPt =
false;
494 G4bool annihilation =
false;
495 if( originalIncident->GetDefinition()->GetPDGEncoding() < 0 &&
496 currentParticle.GetMass() == 0.0 && targetParticle.GetMass() == 0.0 )
500 G4double ekcor = 1.0;
501 G4double ek = originalIncident->GetKineticEnergy();
504 const G4double tarmas = originalTarget->GetDefinition()->GetPDGMass();
506 const G4double atomicWeight = targetNucleus.AtomicMass(targetNucleus.GetA_asInt(),targetNucleus.GetZ_asInt());
507 ek = 2*tarmas + ek*(1.+ekcor/atomicWeight);
509 G4double tkin = targetNucleus.Cinema( ek );
512 modifiedOriginal.SetKineticEnergy( ekOrg );
515 const G4double twsup[] = { 1.0, 0.7, 0.5, 0.3, 0.2, 0.1 };
516 G4double rand1 = G4UniformRand();
517 G4double rand2 = G4UniformRand();
518 if (annihilation || vecLen >= 6 ||
519 (modifiedOriginal.GetKineticEnergy()/
CLHEP::GeV >= 1.0 &&
521 (originalIncident->GetDefinition() == G4KaonPlus::KaonPlus() ||
522 originalIncident->GetDefinition() == G4KaonMinus::KaonMinus() ||
523 originalIncident->GetDefinition() == G4KaonZeroLong::KaonZeroLong() ||
524 originalIncident->GetDefinition() == G4KaonZeroShort::KaonZeroShort()))
525 || rand2 > twsup[vecLen])))
527 theReactionDynamics.GenerateXandPt(
vec, vecLen,
528 modifiedOriginal, originalIncident,
529 currentParticle, targetParticle,
530 targetNucleus, incidentHasChanged,
531 targetHasChanged, leadFlag,
532 leadingStrangeParticle);
539 G4bool finishedTwoClu =
false;
540 if( modifiedOriginal.GetTotalMomentum()/
CLHEP::MeV < 1.0 )
543 for(G4int
i=0;
i<vecLen;
i++)
delete vec[
i];
549 theReactionDynamics.SuppressChargedPions(
vec, vecLen,
550 modifiedOriginal, currentParticle,
552 incidentHasChanged );
556 finishedTwoClu = theReactionDynamics.TwoCluster(
vec, vecLen,
557 modifiedOriginal, originalIncident,
558 currentParticle, targetParticle,
559 targetNucleus, incidentHasChanged,
560 targetHasChanged, leadFlag,
561 leadingStrangeParticle );
563 #if G4VERSION_NUMBER < 1100
564 catch(G4HadReentrentException& aC)
567 throw G4HadReentrentException(__FILE__, __LINE__,
"Failing to calculate momenta");
570 catch(G4HadronicException& aC)
573 throw G4HadronicException(__FILE__, __LINE__,
"Failing to calculate momenta");
603 theReactionDynamics.TwoBody(
vec, vecLen,
604 modifiedOriginal, originalTarget,
605 currentParticle, targetParticle,
606 targetNucleus, targetHasChanged );
610 G4bool FullModelHadronicProcess::MarkLeadingStrangeParticle(
611 const G4ReactionProduct ¤tParticle,
612 const G4ReactionProduct &targetParticle,
613 G4ReactionProduct &leadParticle )
621 if( (currentParticle.GetMass() >= G4KaonPlus::KaonPlus()->GetPDGMass()) &&
626 leadParticle = currentParticle;
628 else if( (targetParticle.GetMass() >= G4KaonPlus::KaonPlus()->GetPDGMass()) &&
633 leadParticle = targetParticle;
638 void FullModelHadronicProcess::Rotate(G4FastVector<G4ReactionProduct,GHADLISTSIZE> &
vec, G4int &vecLen)
643 for(
i=0;
i<vecLen; ++
i )
651 const G4DynamicParticle* FullModelHadronicProcess::FindRhadron(G4ParticleChange* aParticleChange)
653 G4int nsec = aParticleChange->GetNumberOfSecondaries();
654 if (nsec==0)
return 0;
656 G4bool
found =
false;
657 while (
i!=nsec && !
found){
660 if (
dynamic_cast<CustomParticle*
>(aParticleChange->GetSecondary(
i)->GetDynamicParticle()->GetDefinition())!=0)
found =
true;
664 if(
found)
return aParticleChange->GetSecondary(
i)->GetDynamicParticle();