1 #include "G4HadReentrentException.hh"
2 #include "G4ProcessManager.hh"
3 #include "G4ParticleTable.hh"
5 #include "SimG4Core/CustomPhysics/interface/FullModelHadronicProcess.hh"
6 #include "SimG4Core/CustomPhysics/interface/G4ProcessHelper.hh"
8 #include "SimG4Core/CustomPhysics/interface/FullModelReactionDynamics.hh"
12 FullModelHadronicProcess::FullModelHadronicProcess(G4ProcessHelper * aHelper,
const G4String& processName) :
13 G4VDiscreteProcess(processName), theHelper(aHelper)
17 FullModelHadronicProcess::~FullModelHadronicProcess(){}
19 G4bool FullModelHadronicProcess::IsApplicable(
const G4ParticleDefinition& aP)
21 return theHelper->ApplicabilityTester(aP);
24 G4double FullModelHadronicProcess::GetMicroscopicCrossSection(
const G4DynamicParticle *aParticle,
25 const G4Element *anElement,
29 G4double InclXsec = theHelper->GetInclusiveCrossSection(aParticle,anElement);
33 G4double HighestEnergyLimit = 10 * TeV ;
34 G4double LowestEnergyLimit = 1 * eV;
36 G4double ParticleEnergy = aParticle->GetKineticEnergy();
39 if (ParticleEnergy > HighestEnergyLimit || ParticleEnergy < LowestEnergyLimit){
48 G4double FullModelHadronicProcess::GetMeanFreePath(
const G4Track& aTrack, G4double, G4ForceCondition*)
50 G4Material *aMaterial = aTrack.GetMaterial();
51 const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
54 G4int nElements = aMaterial->GetNumberOfElements();
56 const G4double *theAtomicNumDensityVector =
57 aMaterial->GetAtomicNumDensityVector();
58 G4double aTemp = aMaterial->GetTemperature();
60 for( G4int
i=0;
i<nElements; ++
i )
63 GetMicroscopicCrossSection( aParticle, (*aMaterial->GetElementVector())[
i], aTemp);
64 sigma += theAtomicNumDensityVector[
i] * xSection;
71 G4VParticleChange* FullModelHadronicProcess::PostStepDoIt(
const G4Track& aTrack,
76 const G4TouchableHandle thisTouchable(aTrack.GetTouchableHandle());
79 aParticleChange.Initialize(aTrack);
81 G4DynamicParticle* IncidentRhadron =
const_cast<G4DynamicParticle*
>(aTrack.GetDynamicParticle());
83 const G4ThreeVector aPosition = aTrack.GetPosition();
85 const G4int theIncidentPDG = IncidentRhadron->GetDefinition()->GetPDGEncoding();
86 G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
87 std::vector<G4ParticleDefinition*> theParticleDefinitions;
89 G4bool IncidentSurvives =
false;
90 G4bool TargetSurvives =
false;
91 G4Nucleus targetNucleus(aTrack.GetMaterial());
92 G4ParticleDefinition* outgoingRhadron=0;
93 G4ParticleDefinition* outgoingCloud=0;
94 G4ParticleDefinition* outgoingTarget=0;
98 G4ThreeVector p_0 = IncidentRhadron->GetMomentum();
102 G4double e_kin_0 = IncidentRhadron->GetKineticEnergy();
105 G4DynamicParticle* cloudParticle =
new G4DynamicParticle();
118 cloudParticle->SetDefinition(CustomIncident->
GetCloud());
120 if(cloudParticle->GetDefinition() == 0)
122 std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Definition of particle cloud not available!!" << std::endl;
128 double scale=cloudParticle->GetDefinition()->GetPDGMass()/IncidentRhadron->GetDefinition()->GetPDGMass();
130 G4LorentzVector cloudMomentum;
131 cloudMomentum.setVectM(IncidentRhadron->GetMomentum()*scale,cloudParticle->GetDefinition()->GetPDGMass());
132 G4LorentzVector gluinoMomentum;
134 gluinoMomentum.setVectM(IncidentRhadron->GetMomentum()*(1.-scale),CustomIncident->
GetSpectator()->GetPDGMass());
141 G4LorentzVector FullRhadron4Momentum = IncidentRhadron->Get4Momentum();
142 G4LorentzVector Cloud4Momentum = cloudMomentum;
144 cloudParticle->Set4Momentum(cloudMomentum);
146 G4DynamicParticle* OrgPart = cloudParticle;
156 double E_0 = IncidentRhadron->GetKineticEnergy();
159 G4double ek = OrgPart->GetKineticEnergy();
160 G4double amas = OrgPart->GetDefinition()->GetPDGMass();
162 G4double tkin = targetNucleus.Cinema( ek );
164 OrgPart->SetKineticEnergy( ek );
165 G4double et = ek + amas;
167 G4double
pp = OrgPart->GetMomentum().mag();
170 G4ThreeVector momentum = OrgPart->GetMomentum();
171 OrgPart->SetMomentum( momentum * (p/pp) );
176 tkin = targetNucleus.EvaporationEffects( ek );
178 if(ek+gluinoMomentum.e()-gluinoMomentum.m()<=0.1*MeV||ek<=0.) {
180 G4cout<<
"Kinetic energy is sick"<<G4endl;
181 G4cout<<
"Full R-hadron: "<<(ek+gluinoMomentum.e()-gluinoMomentum.m())/MeV<<
" MeV" <<G4endl;
182 G4cout<<
"Quark system: "<<ek/MeV<<
" MeV"<<G4endl;
183 aParticleChange.ProposeTrackStatus( fStopAndKill );
184 return &aParticleChange;
186 OrgPart->SetKineticEnergy( ek );
189 pp = OrgPart->GetMomentum().mag();
193 G4ThreeVector momentum = OrgPart->GetMomentum();
194 OrgPart->SetMomentum( momentum * (p/pp) );
201 G4ParticleDefinition* aTarget;
202 ReactionProduct rp = theHelper->GetFinalState(aTrack,aTarget);
203 G4bool force2to2 =
false;
205 while(rp.size()!=2 && force2to2){
206 rp = theHelper->GetFinalState(aTrack,aTarget);
208 G4int NumberOfSecondaries = rp.size();
212 G4LorentzVector Target4Momentum;
213 Target4Momentum.setVectM(0.,aTarget->GetPDGMass());
215 G4LorentzVector psum_full,psum_cloud;
216 psum_full = FullRhadron4Momentum + Target4Momentum;
217 psum_cloud = Cloud4Momentum + Target4Momentum;
218 G4ThreeVector trafo_full_cms = (-1)*psum_full.boostVector();
219 G4ThreeVector trafo_cloud_cms = (-1)*psum_cloud.boostVector();
229 for(ReactionProduct::iterator it = rp.begin();
233 G4ParticleDefinition* tempDef = theParticleTable->FindParticle(*it);
235 if (tempDef==aTarget) TargetSurvives =
true;
240 outgoingRhadron = tempDef;
249 if(outgoingCloud == 0)
251 std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Definition of outgoing particle cloud not available!!" << std::endl;
259 if (tempDef==G4Proton::Proton()||tempDef==G4Neutron::Neutron()) outgoingTarget = tempDef;
261 if (tempCust==0&&rp.size()==2) outgoingTarget = tempDef;
262 if (tempDef->GetPDGEncoding()==theIncidentPDG) {
263 IncidentSurvives =
true;
265 theParticleDefinitions.push_back(tempDef);
277 if (outgoingTarget==0) outgoingTarget = theParticleTable->FindParticle(rp[1]);
291 if(IncidentSurvives) NumberOfSecondaries--;
292 aParticleChange.SetNumberOfSecondaries(NumberOfSecondaries);
300 const G4HadProjectile* originalIncident =
new G4HadProjectile(*OrgPart);
304 G4HadProjectile* org2 =
new G4HadProjectile(*OrgPart);
305 G4LorentzRotation trans = org2->GetTrafoToLab();
329 G4DynamicParticle *originalTarget =
new G4DynamicParticle;
330 originalTarget->SetDefinition(aTarget);
332 G4ReactionProduct targetParticle(aTarget);
335 G4ReactionProduct currentParticle(const_cast<G4ParticleDefinition *>(originalIncident->GetDefinition() ) );
336 currentParticle.SetMomentum( originalIncident->Get4Momentum().vect() );
337 currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
347 G4ReactionProduct modifiedOriginal = currentParticle;
349 currentParticle.SetSide( 1 );
350 targetParticle.SetSide( -1 );
351 G4bool incidentHasChanged =
false;
352 if (!IncidentSurvives) incidentHasChanged =
true;
353 G4bool targetHasChanged =
false;
354 if (!TargetSurvives) targetHasChanged =
true;
355 G4bool quasiElastic =
false;
356 if (rp.size()==2) quasiElastic =
true;
357 G4FastVector<G4ReactionProduct,GHADLISTSIZE> vec;
366 for (G4int
i = 0;
i!=NumberOfSecondaries;
i++){
367 if(theParticleDefinitions[
i]!=aTarget
368 && theParticleDefinitions[
i]!=originalIncident->GetDefinition()
369 && theParticleDefinitions[
i]!=outgoingRhadron
370 && theParticleDefinitions[
i]!=outgoingTarget)
372 G4ReactionProduct* pa =
new G4ReactionProduct;
373 pa->SetDefinition( theParticleDefinitions[
i] );
374 (G4UniformRand() < 0.5) ? pa->SetSide( -1 ) : pa->SetSide( 1 );
375 vec.SetElement( vecLen++, pa );
381 if (incidentHasChanged) currentParticle.SetDefinitionAndUpdateE( outgoingCloud );
382 if (incidentHasChanged) modifiedOriginal.SetDefinition( outgoingCloud );
383 if (targetHasChanged) targetParticle.SetDefinitionAndUpdateE( outgoingTarget );
393 CalculateMomenta( vec, vecLen,
394 originalIncident, originalTarget, modifiedOriginal,
395 targetNucleus, currentParticle, targetParticle,
396 incidentHasChanged, targetHasChanged, quasiElastic );
400 G4String cPname = currentParticle.GetDefinition()->GetParticleName();
432 aParticleChange.SetNumberOfSecondaries(vecLen+NumberOfSecondaries);
434 G4LorentzVector cloud_p4_new;
446 cloud_p4_new.setVectM(currentParticle.GetMomentum(),currentParticle.GetMass());
447 cloud_p4_new *= trans;
449 G4LorentzVector cloud_p4_old_full = Cloud4Momentum;
450 cloud_p4_old_full.boost(trafo_full_cms);
451 G4LorentzVector cloud_p4_old_cloud = Cloud4Momentum;
452 cloud_p4_old_cloud.boost(trafo_cloud_cms);
453 G4LorentzVector cloud_p4_full = cloud_p4_new;
454 cloud_p4_full.boost(trafo_full_cms);
455 G4LorentzVector cloud_p4_cloud = cloud_p4_new;
456 cloud_p4_cloud.boost(trafo_cloud_cms);
458 G4LorentzVector p_g_cms = gluinoMomentum;
459 p_g_cms.boost(trafo_full_cms);
461 G4LorentzVector p4_new;
465 p4_new.setVectM( cloud_p4_new.v() + gluinoMomentum.v(), outgoingRhadron->GetPDGMass() );
469 p_new = p4_new.vect();
471 aParticleChange.ProposeLocalEnergyDeposit((p4_new-cloud_p4_new-gluinoMomentum).
m());
473 if( incidentHasChanged )
475 G4DynamicParticle* p0 =
new G4DynamicParticle;
476 p0->SetDefinition( outgoingRhadron );
477 p0->SetMomentum( p_new );
480 G4Track* Track0 =
new G4Track(p0,
481 aTrack.GetGlobalTime(),
483 Track0->SetTouchableHandle(thisTouchable);
484 aParticleChange.AddSecondary(Track0);
490 if(p0->GetKineticEnergy()>e_kin_0) {
491 G4cout<<
"ALAAAAARM!!! (incident changed from "
492 <<IncidentRhadron->GetDefinition()->GetParticleName()
493 <<
" to "<<p0->GetDefinition()->GetParticleName()<<
")"<<G4endl;
494 G4cout<<
"Energy loss: "<<(e_kin_0-p0->GetKineticEnergy())/GeV<<
" GeV (should be positive)"<<G4endl;
496 if(rp.size()!=3) G4cout<<
"DOUBLE ALAAAAARM!!!"<<G4endl;
500 if(
std::abs(p0->GetKineticEnergy()-e_kin_0)>100*GeV) {
501 G4cout<<
"Diff. too big"<<G4endl;
504 aParticleChange.ProposeTrackStatus( fStopAndKill );
509 G4double p = p_new.mag();
511 aParticleChange.ProposeMomentumDirection( p_new.x()/
p, p_new.y()/
p, p_new.z()/
p );
513 aParticleChange.ProposeMomentumDirection( 1.0, 0.0, 0.0 );
515 G4double aE =
sqrt(p*p+(outgoingRhadron->GetPDGMass()*outgoingRhadron->GetPDGMass()) );
516 e_kin = aE - outgoingRhadron->GetPDGMass();
522 G4cout<<
"ALAAAAARM!!!"<<G4endl;
523 G4cout<<
"Energy loss: "<<(e_kin_0-e_kin)/GeV<<
" GeV (should be positive)"<<G4endl;
524 if(rp.size()!=3) G4cout<<
"DOUBLE ALAAAAARM!!!"<<G4endl;
526 if(
std::abs(e_kin-e_kin_0)>100*GeV) {
527 G4cout<<
"Diff. too big"<<G4endl;
530 if (std::fabs(aE)<.1*eV) aE=.1*eV;
531 aParticleChange.ProposeEnergy( aE- outgoingRhadron->GetPDGMass() );
532 if(
std::abs(e_kin-e_kin_0)>100*GeV) {
533 G4cout<<
"Diff. too big"<<G4endl;
539 if( targetParticle.GetMass() > 0.0 )
541 G4DynamicParticle *
p1 =
new G4DynamicParticle;
542 p1->SetDefinition( targetParticle.GetDefinition() );
544 G4ThreeVector momentum = targetParticle.GetMomentum();
545 momentum = momentum.rotate(cache,what);
546 p1->SetMomentum( momentum );
547 p1->SetMomentum( (trans*p1->Get4Momentum()).vect());
548 G4Track* Track1 =
new G4Track(p1,
549 aTrack.GetGlobalTime(),
551 Track1->SetTouchableHandle(thisTouchable);
552 aParticleChange.AddSecondary(Track1);
554 G4DynamicParticle *pa;
562 for(
int i=0; i<vecLen; ++
i )
564 pa =
new G4DynamicParticle();
565 pa->SetDefinition( vec[i]->GetDefinition() );
566 pa->SetMomentum( vec[i]->GetMomentum() );
567 pa->Set4Momentum(trans*(pa->Get4Momentum()));
568 G4ThreeVector pvec = pa->GetMomentum();
569 G4Track* Trackn =
new G4Track(pa,
570 aTrack.GetGlobalTime(),
572 Trackn->SetTouchableHandle(thisTouchable);
573 aParticleChange.AddSecondary(Trackn);
588 const G4DynamicParticle* theRhadron = FindRhadron(&aParticleChange);
591 if (theRhadron!=
NULL||IncidentSurvives)
600 E_new = theRhadron->GetKineticEnergy();
617 G4LorentzVector p4_old_full = FullRhadron4Momentum;
618 p4_old_full.boost(trafo_full_cms);
619 G4LorentzVector p4_old_cloud = FullRhadron4Momentum;
620 p4_old_cloud.boost(trafo_cloud_cms);
621 G4LorentzVector p4_full = p4_new;
623 p4_full=p4_full.boost(trafo_full_cms);
625 G4LorentzVector p4_cloud = p4_new;
626 p4_cloud.boost(trafo_cloud_cms);
677 G4double AbsDeltaE = E_0-E_new;
679 if (AbsDeltaE > 10*GeV) {
680 G4cout<<
"Energy loss larger than 10 GeV..."<<G4endl;
681 G4cout<<
"E_0: "<<E_0/GeV<<
" GeV"<<G4endl;
682 G4cout<<
"E_new: "<<E_new/GeV<<
" GeV"<<G4endl;
683 G4cout<<
"Gamma: "<<IncidentRhadron->GetTotalEnergy()/IncidentRhadron->GetDefinition()->GetPDGMass()<<G4endl;
684 G4cout<<
"x: "<<aPosition.x()/cm<<
" cm"<<G4endl;
687 delete originalIncident;
688 delete originalTarget;
693 ClearNumberOfInteractionLengthLeft();
696 return &aParticleChange;
701 void FullModelHadronicProcess::CalculateMomenta(
702 G4FastVector<G4ReactionProduct,GHADLISTSIZE> &vec,
704 const G4HadProjectile *originalIncident,
705 const G4DynamicParticle *originalTarget,
706 G4ReactionProduct &modifiedOriginal,
707 G4Nucleus &targetNucleus,
708 G4ReactionProduct ¤tParticle,
709 G4ReactionProduct &targetParticle,
710 G4bool &incidentHasChanged,
711 G4bool &targetHasChanged,
712 G4bool quasiElastic )
714 FullModelReactionDynamics theReactionDynamics;
717 what = originalIncident->Get4Momentum().vect();
730 theReactionDynamics.TwoBody( vec, vecLen,
731 modifiedOriginal, originalTarget,
732 currentParticle, targetParticle,
733 targetNucleus, targetHasChanged );
739 G4ReactionProduct leadingStrangeParticle;
740 G4bool leadFlag = MarkLeadingStrangeParticle( currentParticle,
742 leadingStrangeParticle );
749 G4bool finishedGenXPt =
false;
750 G4bool annihilation =
false;
751 if( originalIncident->GetDefinition()->GetPDGEncoding() < 0 &&
752 currentParticle.GetMass() == 0.0 && targetParticle.GetMass() == 0.0 )
756 G4double ekcor = 1.0;
757 G4double ek = originalIncident->GetKineticEnergy();
760 const G4double tarmas = originalTarget->GetDefinition()->GetPDGMass();
761 if( ek > 1.0*GeV )ekcor = 1./(ek/GeV);
762 const G4double atomicWeight = targetNucleus.GetN();
763 ek = 2*tarmas + ek*(1.+ekcor/atomicWeight);
765 G4double tkin = targetNucleus.Cinema( ek );
768 modifiedOriginal.SetKineticEnergy( ekOrg );
771 const G4double twsup[] = { 1.0, 0.7, 0.5, 0.3, 0.2, 0.1 };
772 G4double rand1 = G4UniformRand();
773 G4double rand2 = G4UniformRand();
774 if( (annihilation || (vecLen >= 6) || (modifiedOriginal.GetKineticEnergy()/GeV >= 1.0)) &&
775 (((originalIncident->GetDefinition() == G4KaonPlus::KaonPlus()) ||
776 (originalIncident->GetDefinition() == G4KaonMinus::KaonMinus()) ||
777 (originalIncident->GetDefinition() == G4KaonZeroLong::KaonZeroLong()) ||
778 (originalIncident->GetDefinition() == G4KaonZeroShort::KaonZeroShort())) &&
779 ((rand1 < 0.5) || (rand2 > twsup[vecLen]))))
781 theReactionDynamics.GenerateXandPt( vec, vecLen,
782 modifiedOriginal, originalIncident,
783 currentParticle, targetParticle,
784 targetNucleus, incidentHasChanged,
785 targetHasChanged, leadFlag,
786 leadingStrangeParticle );
793 G4bool finishedTwoClu =
false;
794 if( modifiedOriginal.GetTotalMomentum()/MeV < 1.0 )
797 for(G4int i=0; i<vecLen; i++)
delete vec[i];
803 theReactionDynamics.SuppressChargedPions( vec, vecLen,
804 modifiedOriginal, currentParticle,
805 targetParticle, targetNucleus,
806 incidentHasChanged, targetHasChanged );
810 finishedTwoClu = theReactionDynamics.TwoCluster( vec, vecLen,
811 modifiedOriginal, originalIncident,
812 currentParticle, targetParticle,
813 targetNucleus, incidentHasChanged,
814 targetHasChanged, leadFlag,
815 leadingStrangeParticle );
817 catch(G4HadReentrentException aC)
820 throw G4HadReentrentException(__FILE__, __LINE__,
"Failing to calculate momenta");
849 theReactionDynamics.TwoBody( vec, vecLen,
850 modifiedOriginal, originalTarget,
851 currentParticle, targetParticle,
852 targetNucleus, targetHasChanged );
856 G4bool FullModelHadronicProcess::MarkLeadingStrangeParticle(
857 const G4ReactionProduct ¤tParticle,
858 const G4ReactionProduct &targetParticle,
859 G4ReactionProduct &leadParticle )
867 if( (currentParticle.GetMass() >= G4KaonPlus::KaonPlus()->GetPDGMass()) &&
868 (currentParticle.GetDefinition() != G4Proton::Proton()) &&
869 (currentParticle.GetDefinition() != G4Neutron::Neutron()) )
872 leadParticle = currentParticle;
874 else if( (targetParticle.GetMass() >= G4KaonPlus::KaonPlus()->GetPDGMass()) &&
875 (targetParticle.GetDefinition() != G4Proton::Proton()) &&
876 (targetParticle.GetDefinition() != G4Neutron::Neutron()) )
879 leadParticle = targetParticle;
884 void FullModelHadronicProcess::Rotate(G4FastVector<G4ReactionProduct,GHADLISTSIZE> &vec, G4int &vecLen)
886 G4double rotation = 2.*
pi*G4UniformRand();
889 for( i=0; i<vecLen; ++
i )
891 G4ThreeVector momentum = vec[
i]->GetMomentum();
892 momentum = momentum.rotate(rotation, what);
893 vec[
i]->SetMomentum(momentum);
897 const G4DynamicParticle* FullModelHadronicProcess::FindRhadron(G4ParticleChange* aParticleChange)
899 G4int nsec = aParticleChange->GetNumberOfSecondaries();
900 if (nsec==0)
return 0;
902 G4bool
found =
false;
903 while (i!=nsec && !found){
906 if (dynamic_cast<CustomParticle*>(aParticleChange->GetSecondary(i)->GetDynamicParticle()->GetDefinition())!=0) found =
true;
910 if(found)
return aParticleChange->GetSecondary(i)->GetDynamicParticle();
G4ParticleDefinition * GetCloud()
static bool s_isRMeson(int pdg)
static bool s_isMesonino(int pdg)
G4ParticleDefinition * GetSpectator()