5 #include "G4ProcessHelper.hh"
7 #include "G4Element.hh"
8 #include "G4DynamicParticle.hh"
9 #include "G4ParticleDefinition.hh"
10 #include "G4Exception.hh"
15 #include "G4ParticleTable.hh"
16 #include "G4DecayTable.hh"
17 #include "CLHEP/Random/RandFlat.h"
18 #include "CLHEP/Units/PhysicalConstants.h"
25 G4ProcessHelper::G4ProcessHelper()
27 G4cout <<
"G4ProcessHelper constructor: start" << G4endl;
29 particleTable = G4ParticleTable::GetParticleTable();
30 theProton = particleTable->FindParticle(
"proton");
31 theNeutron = particleTable->FindParticle(
"neutron");
36 std::ifstream process_stream (
"ProcessList.txt");
38 while(getline(process_stream,
line)){
39 std::vector<G4String>
tokens;
45 G4String incident =
tokens[0];
47 G4ParticleDefinition* incidentDef = particleTable->FindParticle(incident);
48 G4int incidentPDG = incidentDef->GetPDGEncoding();
49 m_knownParticles[incidentDef]=
true;
56 for (
unsigned int i = 2;
i !=
tokens.size();
i++){
58 if (particleTable->contains(
part))
60 prod.push_back(particleTable->FindParticle(
part)->GetPDGEncoding());
62 G4cout<<
"Particle: "<<
part<<
" is unknown."<<G4endl;
63 G4Exception(
"G4ProcessHelper",
"UnkownParticle", FatalException,
64 "Initialization: The reaction product list contained an unknown particle");
68 pReactionMap[incidentPDG].push_back(std::move(prod));
69 }
else if (
target ==
"neutron") {
70 nReactionMap[incidentPDG].push_back(std::move(prod));
72 G4Exception(
"G4ProcessHelper",
"IllegalTarget", FatalException,
73 "Initialization: The reaction product list contained an illegal target particle");
77 process_stream.close();
78 G4cout <<
"Found " << pReactionMap.size() <<
" proton interactions and " << nReactionMap.size() <<
" neutron interactions in ProcessList.txt." << G4endl;
80 G4ParticleTable::G4PTblDicIterator* theParticleIterator;
81 theParticleIterator = particleTable->GetIterator();
83 theParticleIterator->reset();
84 while( (*theParticleIterator)() ){
85 G4DecayTable*
table = theParticleIterator->value()->GetDecayTable();
86 SetCustomParticleLifeTime(theParticleIterator->value(),
table);
88 theParticleIterator->reset();
89 G4cout <<
"G4ProcessHelper constructor: end" << G4endl;
94 void G4ProcessHelper::SetCustomParticleLifeTime(G4ParticleDefinition* aPart,
bool decaysIdentified)
const
97 std::string
name = aPart->GetParticleName();
99 if (m_parameters->DoDecays() == 1){
102 particle->SetPDGLifeTime(m_parameters->Lifetime());
103 G4cout<<
"Forcing a decay for "<<
name<<G4endl;
105 G4cout<<
"Stable: "<<
particle->GetPDGStable()<<G4endl;
107 else if (decaysIdentified &&
name.find(
"cloud")>
name.size()) {
108 particle->SetPDGLifeTime(m_parameters->Lifetime());
111 G4cout<<
"Stable: "<<
particle->GetPDGStable()<<G4endl;
114 G4cout <<
"Done with particle " <<
name << G4endl;
118 const G4ProcessHelper* G4ProcessHelper::Instance()
120 static const G4ProcessHelper
instance;
125 G4bool G4ProcessHelper::ApplicabilityTester(
const G4ParticleDefinition& aPart)
const {
127 return m_knownParticles.at(&aPart);
129 catch (
const std::out_of_range&
e) {
134 G4double G4ProcessHelper::GetInclusiveCrossSection(
const G4DynamicParticle *aParticle,
135 const G4Element *anElement)
const {
139 const G4int thePDGCode = aParticle->GetDefinition()->GetPDGEncoding();
140 const double boost = (aParticle->GetKineticEnergy()+aParticle->GetMass())/aParticle->GetMass();
141 G4double theXsec = 0;
142 G4String
name = aParticle->GetDefinition()->GetParticleName();
144 if(!m_parameters->ReggeModel()){
150 for (
const G4int & quark : nq) {
152 if (quark == MC::DQUARK || quark == MC::UQUARK) theXsec += 12 *
CLHEP::millibarn;
164 if (containsSquark) {
182 if(m_parameters->Resonant())
186 double e_0 = m_parameters->ResonanceEnergy() + aParticle->GetDefinition()->GetPDGMass();
188 e_0 = sqrt(aParticle->GetDefinition()->GetPDGMass()*aParticle->GetDefinition()->GetPDGMass()
189 + theProton->GetPDGMass()*theProton->GetPDGMass()
190 + 2.*e_0*theProton->GetPDGMass());
191 const double sqrts=sqrt(aParticle->GetDefinition()->GetPDGMass()*aParticle->GetDefinition()->GetPDGMass()
192 + theProton->GetPDGMass()*theProton->GetPDGMass() + 2*aParticle->GetTotalEnergy()*theProton->GetPDGMass());
193 const double gamma = m_parameters->Gamma();
194 const double res_result = m_parameters->Amplitude()*(
gamma*
gamma/4.)/((sqrts-e_0)*(sqrts-e_0)+(
gamma*
gamma/4.));
196 theXsec += res_result;
200 return theXsec *
pow(anElement->GetN(),0.7)*1.25 * m_parameters->XsecMultiplier();
204 ReactionProduct G4ProcessHelper::GetFinalState(
const G4Track& aTrack, G4ParticleDefinition*& aTarget)
const {
205 return GetFinalStateInternal(aTrack,aTarget,
false);
209 ReactionProduct G4ProcessHelper::GetFinalStateInternal(
const G4Track& aTrack,G4ParticleDefinition*& aTarget,
const bool baryonize_failed)
const {
211 const G4DynamicParticle* aDynamicParticle = aTrack.GetDynamicParticle();
218 G4Material* aMaterial = aTrack.GetMaterial();
219 const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
220 const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
222 G4double NumberOfProtons=0;
223 G4double NumberOfNucleons=0;
225 for (
size_t elm=0 ; elm < aMaterial->GetNumberOfElements() ; elm++ )
228 NumberOfProtons += NbOfAtomsPerVolume[elm]*(*theElementVector)[elm]->GetZ();
230 NumberOfNucleons += NbOfAtomsPerVolume[elm]*(*theElementVector)[elm]->GetN();
233 const ReactionMap* reactionMap{};
234 if (NumberOfNucleons>0 && CLHEP::RandFlat::shoot()<NumberOfProtons/NumberOfNucleons) {
235 reactionMap = &pReactionMap;
238 reactionMap = &nReactionMap;
239 aTarget = theNeutron;
242 G4int theIncidentPDG = aDynamicParticle->GetDefinition()->GetPDGEncoding();
244 if (m_parameters->ReggeModel()
246 && CLHEP::RandFlat::shoot()*m_parameters->Mixing()>0.5
247 && aDynamicParticle->GetDefinition()->GetPDGCharge()==0.
251 theIncidentPDG *= -1;
255 bool baryonise=
false;
257 if (!baryonize_failed
258 && m_parameters->ReggeModel()
259 && CLHEP::RandFlat::shoot()>0.9
261 ( (theIncidentPDG > 0) || !containsSquark )
268 const ReactionProductList& aReactionProductList = reactionMap->at(theIncidentPDG);
280 ReactionProductList theReactionProductList;
281 std::vector<bool> theChargeChangeList;
283 for (
const ReactionProduct& prod : aReactionProductList) {
284 const G4int secondaries = prod.size();
290 if (ReactionIsPossible(prod,*aTarget,aDynamicParticle) &&
292 (baryonise && ReactionGivesBaryon(prod)) ||
293 (!baryonise && !ReactionGivesBaryon(prod)) ||
295 !m_parameters->ReggeModel()
300 theReactionProductList.push_back(prod);
301 if (secondaries == 2) {
303 }
else if (secondaries ==3) {
306 G4cerr <<
"ReactionProduct has unsupported number of secondaries: "<<secondaries<<G4endl;
311 if (theReactionProductList.size()==0 && baryonize_failed) {
312 G4Exception(
"G4ProcessHelper",
"NoProcessPossible", FatalException,
313 "GetFinalState: No process could be selected from the given list.");
314 }
else if (theReactionProductList.size()==0 && !baryonize_failed) {
316 G4cout <<
"G4ProcessHelper::GetFinalStateInternal WARNING Could not select an appropriate process in first pass" << G4endl;
317 return GetFinalStateInternal(aTrack,aTarget,
true);
321 if (m_parameters->ReggeModel()) {
322 const int n_rps = theReactionProductList.size();
323 const int select =
static_cast<int>(CLHEP::RandFlat::shoot()*n_rps);
325 return theReactionProductList[
select];
331 G4double p23 = 1-p22;
333 std::vector<G4double> Probabilities;
334 std::vector<G4bool> TwotoThreeFlag;
336 G4double CumulatedProbability = 0;
340 for (
unsigned int i = 0;
i != theReactionProductList.size();
i++){
341 if (theReactionProductList[
i].
size() == 2) {
342 if(0==N22) {
throw std::runtime_error(
"G4ProcessHelper::GetFinalState: N22 is zero!"); }
343 CumulatedProbability += p22/N22;
344 TwotoThreeFlag.push_back(
false);
346 if(0==N23) {
throw std::runtime_error(
"G4ProcessHelper::GetFinalState: N23 is zero!"); }
347 CumulatedProbability += p23/N23;
348 TwotoThreeFlag.push_back(
true);
350 Probabilities.push_back(CumulatedProbability);
355 it != Probabilities.end();
358 *
it /= CumulatedProbability;
363 G4bool selected =
false;
369 while(!selected && tries < 100){
371 G4double dice = CLHEP::RandFlat::shoot();
372 while(
i<theReactionProductList.size() && dice>Probabilities[
i] ){
376 if(!TwotoThreeFlag[
i]) {
381 if (PhaseSpace(theReactionProductList[
i],*aTarget,aDynamicParticle)>CLHEP::RandFlat::shoot()) selected =
true;
385 if(selected &&
table->FindParticle(theReactionProductList[
i][0])->GetPDGCharge()!=aDynamicParticle->GetDefinition()->GetPDGCharge())
393 if(CLHEP::RandFlat::shoot()<m_parameters->SuppressionFactor()) selected =
false;
398 if(tries>=100) G4cerr<<
"Could not select process!!!!"<<G4endl;
401 return theReactionProductList[
i];
404 G4double G4ProcessHelper::ReactionProductMass(
const ReactionProduct& aReaction,
const G4ParticleDefinition& aTarget,
const G4DynamicParticle* aDynamicParticle)
const{
406 const G4double E_incident = aDynamicParticle->GetTotalEnergy();
409 const G4double m_1 = aDynamicParticle->GetDefinition()->GetPDGMass();
410 const G4double m_2 = aTarget.GetPDGMass();
412 const G4double sqrts = sqrt(m_1*m_1 + m_2*(m_2 + 2 * E_incident));
415 G4double M_after = 0;
416 for (
const auto& product_pdg_id : aReaction) {
419 M_after +=
table->FindParticle(product_pdg_id)->GetPDGMass();
422 return sqrts - M_after;
425 G4bool G4ProcessHelper::ReactionIsPossible(
const ReactionProduct& aReaction,
const G4ParticleDefinition& aTarget,
const G4DynamicParticle* aDynamicParticle)
const{
426 if (ReactionProductMass(aReaction,aTarget,aDynamicParticle)>0)
return true;
430 G4bool G4ProcessHelper::ReactionGivesBaryon(
const ReactionProduct& aReaction)
const{
431 for (
const auto& product_pdg_id : aReaction) {
437 G4double G4ProcessHelper::PhaseSpace(
const ReactionProduct& aReaction,
const G4ParticleDefinition& aTarget,
const G4DynamicParticle* aDynamicParticle)
const {
438 const G4double qValue = ReactionProductMass(aReaction,aTarget,aDynamicParticle);
444 void G4ProcessHelper::ReadAndParse(
const G4String&
str,
445 std::vector<G4String>&
tokens,
446 const G4String& delimiters)
const
449 G4String::size_type lastPos =
str.find_first_not_of(delimiters, 0);
450 if (lastPos==G4String::npos)
return;
453 G4String::size_type
pos =
str.find_first_of(delimiters, lastPos);
455 while (G4String::npos !=
pos || G4String::npos != lastPos)
458 G4String temp =
str.substr(lastPos,
pos - lastPos);
459 while(temp.c_str()[0] ==
' ') temp.erase(0,1);
460 while(temp[temp.size()-1] ==
' ') temp.erase(temp.size()-1,1);
463 tokens.push_back(std::move(temp));
466 lastPos =
str.find_first_not_of(delimiters,
pos);
467 if (lastPos==G4String::npos)
continue;
470 pos =
str.find_first_of(delimiters, lastPos);
474 double G4ProcessHelper::Regge(
const double boost)
const
478 const double a=2.165635078566177;
479 const double b=0.1467453738547229;
480 const double c=-0.9607903711871166;
485 double G4ProcessHelper::Pom(
const double boost)
const
489 const double a=4.138224000651535;
490 const double b=1.50377557581421;
491 const double c=-0.05449742257808247;
492 const double d=0.0008221235048211401;