2 #include "G4ProcessManager.hh"
3 #include "G4ParticleTable.hh"
5 #include "Randomize.hh"
7 #include "SimG4Core/CustomPhysics/interface/ToyModelHadronicProcess.hh"
10 #include "SimG4Core/CustomPhysics/interface/HadronicProcessHelper.hh"
13 using namespace CLHEP;
15 ToyModelHadronicProcess::ToyModelHadronicProcess(HadronicProcessHelper * aHelper,
const G4String& processName) :
16 G4VDiscreteProcess(processName), m_verboseLevel(0), m_helper(aHelper), m_detachCloud(
true)
26 G4bool ToyModelHadronicProcess::IsApplicable(
const G4ParticleDefinition& aP)
28 return m_helper->applicabilityTester(aP);
31 G4double ToyModelHadronicProcess::GetMicroscopicCrossSection(
const G4DynamicParticle *particle,
32 const G4Element *element,
36 G4double inclusiveCrossSection = m_helper->inclusiveCrossSection(particle,element);
39 G4double highestEnergyLimit = 10 * TeV ;
40 G4double lowestEnergyLimit = 1 * eV;
41 G4double particleEnergy = particle->GetKineticEnergy();
43 if (particleEnergy > highestEnergyLimit || particleEnergy < lowestEnergyLimit){
44 if(m_verboseLevel >= 1)
std::cout <<
"ToyModelHadronicProcess: Energy out of bounds [" <<
45 lowestEnergyLimit / MeV <<
"MeV , " <<
46 highestEnergyLimit / MeV <<
"MeV ] while it is " << particleEnergy/MeV <<
50 if(m_verboseLevel >= 3)
std::cout <<
"ToyModelHadronicProcess: Return cross section " << inclusiveCrossSection << std::endl;
51 return inclusiveCrossSection;
57 G4double ToyModelHadronicProcess::GetMeanFreePath(
const G4Track& aTrack, G4double, G4ForceCondition*)
59 G4Material *aMaterial = aTrack.GetMaterial();
60 const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
63 G4int nElements = aMaterial->GetNumberOfElements();
65 const G4double *theAtomicNumDensityVector =
66 aMaterial->GetAtomicNumDensityVector();
67 G4double aTemp = aMaterial->GetTemperature();
69 for( G4int
i=0;
i<nElements; ++
i )
72 GetMicroscopicCrossSection( aParticle, (*aMaterial->GetElementVector())[
i], aTemp);
73 sigma += theAtomicNumDensityVector[
i] * xSection;
81 G4VParticleChange* ToyModelHadronicProcess::PostStepDoIt(
const G4Track& track,
85 const G4TouchableHandle thisTouchable(track.GetTouchableHandle());
88 G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
89 m_particleChange.Initialize(track);
91 const G4DynamicParticle* incidentRHadron = track.GetDynamicParticle();
94 const G4ThreeVector aPosition = track.GetPosition();
99 G4DynamicParticle* cloudParticle =
new G4DynamicParticle();
104 if(CustomIncident==0)
106 std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Definition of particle cloud not available!!" << std::endl;
108 cloudParticle->SetDefinition(CustomIncident->
GetCloud());
112 double scale=cloudParticle->GetDefinition()->GetPDGMass()/incidentRHadron->GetDefinition()->GetPDGMass();
113 G4LorentzVector cloudMomentum;
114 cloudMomentum.setVectM(incidentRHadron->GetMomentum()*
scale,cloudParticle->GetDefinition()->GetPDGMass());
115 G4LorentzVector gluinoMomentum;
116 gluinoMomentum.setVectM(incidentRHadron->GetMomentum()*(1.-
scale),CustomIncident->
GetSpectator()->GetPDGMass());
118 cloudParticle->Set4Momentum(cloudMomentum);
120 const G4DynamicParticle *incidentParticle;
121 if(! m_detachCloud) incidentParticle = incidentRHadron;
122 else incidentParticle= cloudParticle;
124 if(m_verboseLevel >= 3)
126 std::cout <<
"ToyModelHadronicProcess::PostStepDoIt After scaling " << std::endl;
127 std::cout <<
" RHadron "<<incidentRHadron->GetDefinition()->GetParticleName()<<
" pdgmass= " << incidentRHadron->GetDefinition()->GetPDGMass() / GeV
128 <<
" P= " << incidentRHadron->Get4Momentum() / GeV<<
" mass= "<< incidentRHadron->Get4Momentum().m() / GeV <<std::endl;
129 std::cout <<
" Cloud "<<cloudParticle->GetDefinition()->GetParticleName()<<
" pdgmass= " << cloudParticle->GetDefinition()->GetPDGMass() / GeV
130 <<
" P= " << cloudParticle->Get4Momentum() / GeV<<
" mass= "<< cloudParticle->Get4Momentum().m() / GeV <<std::endl;
131 std::cout <<
" Incident pdgmass= " << incidentParticle->GetDefinition()->GetPDGMass() / GeV
132 <<
" P= " << incidentParticle->Get4Momentum() / GeV<<
" mass= "<< incidentParticle->Get4Momentum().m() / GeV <<std::endl;
135 const G4ThreeVector
position = track.GetPosition();
136 const G4int incidentParticlePDG = incidentRHadron->GetDefinition()->GetPDGEncoding();
137 std::vector<G4ParticleDefinition*> newParticles;
138 std::vector<G4ParticleDefinition*> newParticlesRHadron;
140 G4bool incidentSurvives =
false;
143 G4ParticleDefinition* targetParticle;
144 HadronicProcessHelper::ReactionProduct reactionProduct = m_helper->finalState(incidentRHadron,track.GetMaterial(),targetParticle);
149 for(HadronicProcessHelper::ReactionProduct::iterator it = reactionProduct.begin();
150 it != reactionProduct.end() ;
153 G4ParticleDefinition * productDefinition =theParticleTable->FindParticle(*it);
155 if (productDefinition->GetPDGEncoding()==incidentParticlePDG)
156 incidentSurvives =
true;
158 newParticlesRHadron.push_back(productDefinition);
163 if( cProd!=0 && m_detachCloud)
164 productDefinition=cProd->
GetCloud();
166 newParticles.push_back(productDefinition);
169 int numberOfSecondaries = reactionProduct.size();
171 if(m_verboseLevel >= 2)
std::cout <<
"ToyModelHadronicProcess::PostStepDoIt N secondaries: "
172 << numberOfSecondaries << std::endl;
180 const G4LorentzVector incident4Momentum = incidentParticle->Get4Momentum();
181 const G4LorentzVector target4Momentum(0,0,0,targetParticle->GetPDGMass());
182 const G4LorentzVector sum4Momentum = incident4Momentum + target4Momentum;
183 const G4ThreeVector cmBoost = sum4Momentum.boostVector();
184 const G4LorentzVector cm4Momentum = sum4Momentum.rest4Vector();
186 if(m_verboseLevel >= 2)
std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Kinematics in GeV: " << std::endl
187 <<
" Boost = " << cmBoost / GeV<< std::endl
188 <<
" 4P CM = " << cm4Momentum / GeV << std::endl
189 <<
" 4P Inc = " << incident4Momentum / GeV << std::endl
190 <<
" 4P Targ = " << target4Momentum / GeV<< std::endl;
193 const G4double phi_p = 2*
pi*G4UniformRand()-
pi ;
194 const G4double theta_p = pi*G4UniformRand() ;
195 const G4ThreeVector randomDirection(
sin(theta_p)*
cos(phi_p),
200 std::vector<G4double>
m;
201 std::vector<G4LorentzVector> fourMomenta;
204 for(
int ip=0;ip<numberOfSecondaries;ip++)
206 m.push_back(newParticles[ip]->GetPDGMass());
210 if (numberOfSecondaries==2){
214 G4double
energy = cm4Momentum.e();
221 G4double cmMomentum = 1/(2*
energy)*
sqrt(energy*energy*energy*energy + m[0]*m[0]*m[0]*m[0] + m[1]*m[1]*m[1]*m[1]
222 - 2*(m[0]*m[0] + m[1]*m[1])*energy*energy -2*m[0]*m[0]*m[1]*m[1]);
223 p[0] = cmMomentum * randomDirection;
226 if(m_verboseLevel >= 2)
std::cout <<
"ToyModelHadronicProcess::PostStepDoIt 2->2: " << std::endl
227 <<
" Pcm(GeV) = " << cmMomentum / GeV << std::endl;
229 for(
int ip=0;ip<2;ip++)
232 G4double
e =
sqrt(p[ip].
mag2() + m[ip]*m[ip]);
234 fourMomenta.push_back(G4LorentzVector(p[ip],e));
236 fourMomenta[ip].boost(cmBoost);
238 if(m_verboseLevel >= 2)
std::cout <<
" particle " << ip <<
" Plab(GeV) = " << fourMomenta[ip] /GeV << std::endl;
241 }
else if (numberOfSecondaries==3) {
245 for (std::vector<G4double>::iterator it=m.begin();it!=m.end();it++)
246 fourMomenta.push_back(G4LorentzVector(0,0,0,*it));
249 KinCalc.
doDecay(cm4Momentum, fourMomenta[0], fourMomenta[1], fourMomenta[2] );
252 CLHEP::HepRotation
rotation(randomDirection,G4UniformRand()*2*pi);
253 for (std::vector<G4LorentzVector>::iterator it = fourMomenta.begin();
254 it!=fourMomenta.end();
258 (*it).boost(cmBoost);
260 if(m_verboseLevel >= 3) G4cout<<
"Momentum-check: "<<incident4Momentum /GeV<<
" GeV vs "
261 << (fourMomenta[0]+fourMomenta[1]+fourMomenta[2])/GeV<<G4endl;
267 if(incidentSurvives){
269 m_particleChange.SetNumberOfSecondaries(numberOfSecondaries-1);
270 if(m_verboseLevel >= 3)
std::cout <<
"Incident survives: set num secondaries to " << numberOfSecondaries-1 << std::endl;
274 m_particleChange.SetNumberOfSecondaries(numberOfSecondaries);
275 m_particleChange.ProposeTrackStatus(fStopAndKill);
276 if(m_verboseLevel >= 3)
std::cout <<
"Incident does not survive: stopAndKill + set num secondaries to " << numberOfSecondaries << std::endl;
280 for (
int ip=0; ip <numberOfSecondaries;ip++)
282 if (newParticlesRHadron[ip]==incidentRHadron->GetDefinition())
287 if(m_verboseLevel >= 3)
288 std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Add gluino momentum " <<
289 fourMomenta[ip]/GeV <<
"(m="<< fourMomenta[ip].m()/ GeV<<
") + " <<gluinoMomentum/GeV<<std::endl; ;
290 G4LorentzVector p4_new = gluinoMomentum+fourMomenta[ip];
291 G4ThreeVector momentum = p4_new.vect();
292 double rhMass=newParticlesRHadron[ip]->GetPDGMass() ;
295 fourMomenta[ip].setVectM(momentum,rhMass);
299 if(m_verboseLevel >= 3)
300 std::cout <<
" = " << fourMomenta[ip]/GeV <<
"(m="<< fourMomenta[ip].m() / GeV<<
") vs. "<<rhMass/GeV
303 m_particleChange.ProposeMomentumDirection(fourMomenta[ip].vect()/fourMomenta[ip].vect().
mag());
304 m_particleChange.ProposeEnergy(fourMomenta[ip].
e()-fourMomenta[ip].
mag());
305 if(m_verboseLevel >= 3)
std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Propose momentum " << fourMomenta[ip]/GeV << std::endl;
308 G4DynamicParticle* productDynParticle =
new G4DynamicParticle();
310 productDynParticle->SetDefinition(newParticlesRHadron[ip]);
312 if(newParticlesRHadron[ip]!=newParticles[ip] && m_detachCloud )
314 G4LorentzVector p4_new;
315 p4_new.setVectM(gluinoMomentum.vect()+fourMomenta[ip].vect(),productDynParticle->GetDefinition()->GetPDGMass());
317 productDynParticle->Set4Momentum(p4_new);
321 if(m_verboseLevel >= 3)
322 std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Add gluino momentum " <<
324 <<
"(m="<< fourMomenta[ip].m()/ GeV<<
") + "
326 <<
" = " << productDynParticle->Get4Momentum()/GeV
327 <<
" => "<<productDynParticle->Get4Momentum().m()/GeV
328 <<
" vs. "<<productDynParticle->GetDefinition()->GetPDGMass()/GeV
333 productDynParticle->Set4Momentum(fourMomenta[ip]);
336 G4Track* productTrack =
new G4Track(productDynParticle,
337 track.GetGlobalTime(),
339 productTrack->SetTouchableHandle(thisTouchable);
341 if(m_verboseLevel >= 3)
std::cout <<
"ToyModelHadronicProcess::PostStepDoIt Add secondary with 4-Momentum " << productDynParticle->Get4Momentum()/GeV << std::endl;
342 m_particleChange.AddSecondary(productTrack);
347 ClearNumberOfInteractionLengthLeft();
349 return &m_particleChange;
353 const G4DynamicParticle* ToyModelHadronicProcess::FindRhadron(G4ParticleChange* aParticleChange)
355 G4int nsec = aParticleChange->GetNumberOfSecondaries();
356 if (nsec==0)
return 0;
358 G4bool
found =
false;
359 while (i!=nsec && !found){
360 if (dynamic_cast<CustomParticle*>(aParticleChange->GetSecondary(i)->GetDynamicParticle()->GetDefinition())!=0) found =
true;
364 if(found)
return aParticleChange->GetSecondary(i)->GetDynamicParticle();
void doDecay(const G4LorentzVector &mother, G4LorentzVector &daughter1, G4LorentzVector &daughter2, G4LorentzVector &daughter3)
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
Sin< T >::type sin(const T &t)
G4ParticleDefinition * GetCloud()
static int position[TOTALCHAMBERS][3]
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
Cos< T >::type cos(const T &t)
G4ParticleDefinition * GetSpectator()