CMS 3D CMS Logo

HadronicProcessHelper.cc

Go to the documentation of this file.
00001 #include "Randomize.hh"
00002 #include "G4ParticleTable.hh" 
00003 
00004 #include <iostream>
00005 #include <fstream>
00006 #include <string>
00007 
00008 #include "SimG4Core/CustomPhysics/interface/CustomPDGParser.h"
00009 #include "SimG4Core/CustomPhysics/interface/HadronicProcessHelper.hh"
00010 
00011 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00012 #include "FWCore/ParameterSet/interface/FileInPath.h"
00013 
00014 HadronicProcessHelper::HadronicProcessHelper(const std::string & fileName){
00015 
00016   m_particleTable = G4ParticleTable::GetParticleTable();
00017   m_proton = m_particleTable->FindParticle("proton");
00018   m_neutron = m_particleTable->FindParticle("neutron");
00019 
00020   G4String line;
00021 
00022   std::ifstream processListStream (fileName.c_str());
00023 
00024   while(getline(processListStream,line)){
00025     std::vector<G4String> tokens;
00026 
00027     //Getting a line
00028     m_readAndParse(line,tokens,"#");
00029     
00030     //Important info
00031     G4String incident = tokens[0];
00032     G4ParticleDefinition* incidentDef = m_particleTable->FindParticle(incident);
00033     G4int incidentPDG = incidentDef->GetPDGEncoding();
00034     m_knownParticles[incidentDef]=true;
00035     //    G4cout<<"Incident: "<<incident<<G4endl;
00036     G4String target = tokens[1];
00037     //    G4cout<<"Target: "<<target<<G4endl;
00038     
00039     // Making a ReactionProduct
00040     ReactionProduct prod;
00041     for (size_t i = 2; i != tokens.size();i++){
00042       G4String part = tokens[i];
00043       if (m_particleTable->contains(part))
00044         {
00045           prod.push_back(m_particleTable->FindParticle(part)->GetPDGEncoding());
00046         } else {
00047           G4cout<<"Particle: "<<part<<" is unknown."<<G4endl;
00048           G4Exception("HadronicProcessHelper", "UnkownParticle", FatalException,
00049                       "Initialization: The reaction product list contained an unknown particle");
00050         }
00051     }
00052     if (target == "proton")
00053       {
00054         m_protonReactionMap[incidentPDG].push_back(prod);
00055       } else if (target == "neutron") {
00056         m_neutronReactionMap[incidentPDG].push_back(prod);
00057       } else {
00058         G4Exception("HadronicProcessHelper", "IllegalTarget", FatalException,
00059                     "Initialization: The reaction product list contained an illegal target particle");
00060       }
00061    }
00062 
00063   processListStream.close();
00064 
00065 
00066   m_checkFraction = 0;
00067   m_n22 = 0;
00068   m_n23 = 0;
00069 
00070 
00071 }
00072 
00073 
00074 G4bool HadronicProcessHelper::applicabilityTester(const G4ParticleDefinition& aPart){
00075   const G4ParticleDefinition* aP = &aPart; 
00076   if (m_knownParticles[aP]) return true;
00077   return false;
00078 }
00079 
00080 G4double HadronicProcessHelper::inclusiveCrossSection(const G4DynamicParticle *particle,
00081                                                    const G4Element *element){
00082 
00083   //We really do need a dedicated class to handle the cross sections. They might not always be constant
00084 
00085   G4int pdgCode = particle->GetDefinition()->GetPDGEncoding();
00086 
00087   //24mb for gluino-balls
00088   if(CustomPDGParser::s_isRGlueball(pdgCode)) return 24 * millibarn * element->GetN();
00089   
00090   //get quark vector
00091   std::vector<G4int> quarks=CustomPDGParser::s_containedQuarks(pdgCode);
00092   
00093   G4double totalNucleonCrossSection = 0;
00094 
00095   for (std::vector<G4int>::iterator it = quarks.begin();
00096        it != quarks.end();
00097        it++)
00098     {
00099       // 12mb for each 'up' or 'down'
00100       if (*it == 1 || *it == 2) totalNucleonCrossSection += 12 * millibarn;
00101       //  6mb for each 'strange'
00102       if (*it == 3) totalNucleonCrossSection += 6 * millibarn;
00103     }
00104   
00105   //Convert to xsec per nucleus
00106   //  return totalNucleonCrossSection * element->GetN();
00107   return totalNucleonCrossSection * pow(element->GetN(),0.7)*1.25;// * 0.523598775598299;
00108 }
00109 
00110 HadronicProcessHelper::ReactionProduct HadronicProcessHelper::finalState(const G4DynamicParticle* incidentDynamicParticle,
00111    const G4Material *material, G4ParticleDefinition*& target){
00112 
00113 //  const G4DynamicParticle* incidentDynamicParticle = track.GetDynamicParticle();
00114 
00115   //-----------------------------------------------
00116   // Choose n / p as target
00117   // and get ReactionProductList pointer
00118   //-----------------------------------------------
00119   ReactionMap* m_reactionMap;
00120   //G4Material* material = track.GetMaterial();
00121   const G4ElementVector* elementVector = material->GetElementVector() ;
00122   const G4double* numberOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
00123 
00124   G4double numberOfProtons=0;
00125   G4double numberOfNucleons=0;
00126 
00127   //Loop on elements 
00128   for ( size_t elm=0 ; elm < material->GetNumberOfElements() ; elm++ )
00129     {
00130       //Summing number of protons per unit volume
00131       numberOfProtons += numberOfAtomsPerVolume[elm]*(*elementVector)[elm]->GetZ();
00132       //Summing nucleons (not neutrons)
00133       numberOfNucleons += numberOfAtomsPerVolume[elm]*(*elementVector)[elm]->GetN();
00134     }
00135   
00136   //random decision of the target
00137   if(G4UniformRand()<numberOfProtons/numberOfNucleons)
00138     { //target is a proton
00139       m_reactionMap = &m_protonReactionMap;
00140       target = m_proton;
00141     } else { //target is a neutron
00142       m_reactionMap = &m_neutronReactionMap;
00143       target = m_neutron;
00144     }
00145   
00146   const G4int incidentPDG = incidentDynamicParticle->GetDefinition()->GetPDGEncoding();
00147 
00148   //Making a pointer directly to the ReactionProductList we are looking at. Makes life easier :-)
00149   ReactionProductList*  reactionProductList = &((*m_reactionMap)[incidentPDG]);
00150 
00151   //-----------------------------------------------
00152   // Count processes
00153   // kinematic check
00154   // compute number of 2 -> 2 and 2 -> 3 processes
00155   //-----------------------------------------------
00156 
00157   G4int good22 = 0; //Number of 2 -> 2 processes that are possible
00158   G4int good23 = 0; //Number of 2 -> 3 processes that are possible
00159   
00160   //This is the list to be populated
00161   ReactionProductList goodReactionProductList;
00162 
00163   for (ReactionProductList::iterator prod_it = reactionProductList->begin();
00164        prod_it != reactionProductList->end();
00165        prod_it++){
00166     G4int secondaries = prod_it->size();
00167     // If the reaction is not possible we will not consider it
00168     if(m_reactionIsPossible(*prod_it,incidentDynamicParticle,target)){
00169       // The reaction is possible. Let's store and count it
00170       goodReactionProductList.push_back(*prod_it);
00171       if (secondaries == 2){
00172         good22++;
00173       } else if (secondaries ==3) {
00174         good23++;
00175       } else {
00176         G4cerr << "ReactionProduct has unsupported number of secondaries: "<<secondaries<<G4endl;
00177       }
00178     } /*else {
00179       G4cout<<"There was an impossible process"<<G4endl;
00180       }*/
00181   }
00182   //  G4cout<<"The size of the ReactionProductList is: "<<theReactionProductList.size()<<G4endl;
00183 
00184   if (goodReactionProductList.size()==0) G4Exception("HadronicProcessHelper", "NoProcessPossible", FatalException,
00185                                                     "GetFinalState: No process could be selected from the given list.");
00186   // Fill a probability map. Remember total probability
00187   // 2->2 is 0.15*1/n_22 2->3 uses phase space
00188   G4double prob22 = 0.15;
00189   G4double prob23 = 1-prob22; // :-)
00190 
00191   std::vector<G4double> probabilities;
00192   std::vector<G4bool> twoToThreeFlag;
00193   
00194   G4double cumulatedProbability = 0;
00195 
00196   // To each ReactionProduct we assign a cumulated probability and a flag
00197   // discerning between 2 -> 2 and 2 -> 3
00198   size_t numberOfReactions = goodReactionProductList.size();
00199   for (size_t i = 0; i != numberOfReactions; i++){
00200     if (goodReactionProductList[i].size() == 2) {
00201       cumulatedProbability += prob22/good22;
00202       twoToThreeFlag.push_back(false);
00203     } else {
00204       cumulatedProbability += prob23/good23;
00205       twoToThreeFlag.push_back(true);
00206     }
00207     probabilities.push_back(cumulatedProbability);
00208   }
00209 
00210   //Normalising probabilities to 1
00211   for (std::vector<G4double>::iterator it = probabilities.begin();
00212        it != probabilities.end();
00213        it++)
00214     {
00215       *it /= cumulatedProbability;
00216     }
00217 
00218   // Choosing ReactionProduct
00219   G4bool selected = false;
00220   G4int tries = 0;
00221   //  ReactionProductList::iterator prod_it;
00222 
00223   //Keep looping over the list until we have a choice, or until we have tried 100 times  
00224   size_t i;
00225   while(!selected && tries < 100){
00226     i=0;
00227     G4double dice = G4UniformRand();
00228     //select the process using the dice
00229     while(dice>probabilities[i] && i<numberOfReactions)  i++;
00230 
00231     if(twoToThreeFlag[i]) {
00232       // 2 -> 3 processes require a phase space lookup
00233       if (m_phaseSpace(goodReactionProductList[i],incidentDynamicParticle,target)>G4UniformRand()) selected = true;
00234     } else {
00235       // 2 -> 2 processes are chosen immediately
00236       selected = true;
00237     }
00238     tries++;
00239   }
00240   if(tries>=100) G4cerr<<"Could not select process!!!!"<<G4endl;
00241 
00242   
00243   //Debugging stuff
00244   //Updating checkfraction:
00245   if (goodReactionProductList[i].size()==2) {
00246     m_n22++;
00247   } else {
00248     m_n23++;
00249   }
00250   m_checkFraction = (1.0*m_n22)/(m_n22+m_n23);
00251   
00252   //return the selected productList
00253   return goodReactionProductList[i];
00254 }
00255 
00256 G4double HadronicProcessHelper::m_reactionProductMass(const ReactionProduct& reactionProd,
00257   const G4DynamicParticle* incidentDynamicParticle,G4ParticleDefinition* target){
00258   // Incident energy:
00259   G4double incidentEnergy = incidentDynamicParticle->GetTotalEnergy();
00260   G4double m_1 = incidentDynamicParticle->GetDefinition()->GetPDGMass();
00261   G4double m_2 = target->GetPDGMass();
00262   //square root of "s"
00263   G4double sqrtS = sqrt(m_1*m_1 + m_2*(m_2 + 2 * incidentEnergy));
00264   // Sum of rest masses after reaction:
00265   G4double productsMass = 0;
00266   //Loop on reaction producs
00267   for (ReactionProduct::const_iterator r_it = reactionProd.begin(); r_it !=reactionProd.end(); r_it++){
00268     //Sum the masses of the products
00269     productsMass += m_particleTable->FindParticle(*r_it)->GetPDGMass();
00270   }
00271   //the result is square root of "s" minus the masses of the products
00272   return sqrtS - productsMass;
00273 }
00274 
00275 G4bool HadronicProcessHelper::m_reactionIsPossible(const ReactionProduct& aReaction,
00276      const G4DynamicParticle* aDynamicParticle,G4ParticleDefinition* target){
00277   if (m_reactionProductMass(aReaction,aDynamicParticle,target)>0) return true;
00278   return false;
00279 }
00280 
00281 G4double HadronicProcessHelper::m_phaseSpace(const ReactionProduct& aReaction,
00282      const G4DynamicParticle* aDynamicParticle,G4ParticleDefinition* target){
00283   G4double qValue = m_reactionProductMass(aReaction,aDynamicParticle,target);
00284   G4double phi = sqrt(1+qValue/(2*0.139*GeV))*pow(qValue/(1.1*GeV),3./2.);
00285   return (phi/(1+phi));
00286 }
00287 
00288 void HadronicProcessHelper::m_readAndParse(const G4String& str,
00289                                    std::vector<G4String>& tokens,
00290                                    const G4String& delimiters)
00291 {
00292   // Skip delimiters at beginning.
00293   G4String::size_type lastPos = str.find_first_not_of(delimiters, 0);
00294   // Find first "non-delimiter".
00295   G4String::size_type pos     = str.find_first_of(delimiters, lastPos);
00296   
00297   while (G4String::npos != pos || G4String::npos != lastPos)
00298     {
00299       //Skipping leading / trailing whitespaces
00300       G4String temp = str.substr(lastPos, pos - lastPos);
00301       while(temp.c_str()[0] == ' ') temp.erase(0,1);
00302       while(temp[temp.size()-1] == ' ') temp.erase(temp.size()-1,1);
00303       // Found a token, add it to the vector.
00304       tokens.push_back(temp);
00305       // Skip delimiters.  Note the "not_of"
00306       lastPos = str.find_first_not_of(delimiters, pos);
00307       // Find next "non-delimiter"
00308       pos = str.find_first_of(delimiters, lastPos);
00309     }
00310 }

Generated on Tue Jun 9 17:47:02 2009 for CMSSW by  doxygen 1.5.4