MollerPrimaryGenAction_inelasticep.cc

Go to the documentation of this file.
00001 #include "G4ParticleGun.hh"
00002 #include "G4Electron.hh"
00003 #include "G4Event.hh"
00004 #include "globals.hh"
00005 
00006 #include "MollerPrimaryGenAction.hh"
00007 #include "RootAnalysis.hh"
00008 
00009 
00010 // typedef struct {
00011 //   double theta;
00012 //   double y;
00013 //   double xs;
00014 // }cms_cross_section_t;
00015 
00016 // typedef struct {
00017 //   double theta;
00018 //   double Eprime;
00019 //   double xs;
00020 // }double_differential_t;
00021 
00022 // #define nbinIneEP 100
00023 // double_differential_t DDtable[nbinIneEP][nbinIneEP];
00024 
00025 // #define nbin 1000
00026 // cms_cross_section_t XStable[nbin];
00027 
00028 #define r0 2.818  //electron radius in fm
00029 #define pi 3.14159
00030 #define me 0.511E-3 //electron restmass (GeV)
00031 #define Euler 0.5772157
00032 #define d2r pi/180.
00033 #define r2d 180/pi
00034 
00035 #define gevfm 0.1973
00036 #define pmu 2.79
00037 #define alpha 0.007299
00038 
00039 double SigT(double k);
00040 
00041 void MollerPrimaryGenAction::GeneratePrimaries_inelasticep_dustin(G4Event* anEvent)
00042 {
00043   //----------------------
00044   // GenerateEvent
00045   //----------------------
00046   
00047   double initial_x = 0.0;//*cm;
00048   double initial_y = 0.0;//*cm;
00049   double initial_z = 0.0;//*cm;
00050 
00051   double initial_px = 0.0;//*GeV;
00052   double initial_py = 0.0;//*GeV;
00053   double initial_pz = 0.0;//*GeV;
00054 
00055   //Find the scattering point in the target
00056   double vertex; //scattering point in target (cm) measured from the upstream end of target
00057   double t = 150.0; // t = thickness of target in cm
00058   double rho = 0.0715; // rho = density of target in g/cm**3 (from KK)
00059   double radiationLength = 63.04; // g/cm**2 (from PDG)
00060   double t_rad = radiationLength/rho; // t_rad = radiation length in cm
00061   double z = G4UniformRand();
00062   vertex = z*t;//just do this for now
00063   
00064   double Evertex = ebeam;
00065   //Now we know how mush material the beam travels through before moller interaction
00066   //Use this to calculate energy loss
00067   double cut=0.000001; //lower limit of bremsstrahlung (1 keV)
00068   double  Ekin = ebeam - me;
00069   double fracrl = vertex/t_rad; //total radiation lenght fraction travelled through
00070   double bt = fracrl*4./3.;
00071 
00072   double prob, prob_sample, sample, eloss, env, value, ref;
00073   //Calculation of probability to have bremsstrahlung effect above 1 keV
00074   prob = 1.- pow(cut/Ekin,bt) - bt/(bt+1.)*(1.- pow(cut/Ekin,bt+1.))
00075     + 0.75*bt/(2.+bt)*(1.- pow(cut/Ekin,bt+2.));
00076   prob = prob/(1.- bt*Euler + bt*bt/2.*(Euler*Euler+pi*pi/6.)); /* Gamma function */
00077 
00078   prob_sample = G4UniformRand();  /* Random sampling */
00079 
00080   if (prob_sample <= prob) {//Bremsstrahlung has taken place!
00081     //Generate photon energy with sample and reject using 1/x as envelope 
00082     do {
00083       sample = G4UniformRand();
00084       eloss = cut*pow(Ekin/cut,sample);
00085       
00086       env = 1./eloss;
00087       value = 1./eloss*(1.-eloss/Ekin+0.75*pow(eloss/Ekin,2))*pow(eloss/Ekin,bt);
00088       
00089       sample = G4UniformRand();
00090       ref = value/env;
00091     } while (sample > ref);
00092     
00093     Evertex = ebeam - eloss;
00094   }
00095 
00096   if( Evertex < me ) return;
00097 
00098   double vertex_x = (-0.25 + (0.5*(G4UniformRand())));
00099   double vertex_y = (-0.25 + (0.5*(G4UniformRand())));
00100   initial_x = vertex_x;
00101   initial_y = vertex_y;
00102   initial_z = vertex - t/2.; //cm  
00103   
00104   //Make realistic beam angle (Not yet)
00105   //double theta_div = 0.000125*((double)random()/(double)RAND_MAX);
00106   //double phi_div = 2.0*M_PI*((double)random()/(double)RAND_MAX);
00107   ////double theta_div = 0.0;
00108   ////double phi_div = 0.0;
00109   ////cout << "theta = "<<theta_div*180/M_PI<<", phi = "<<phi_div*180/M_PI<<endl;
00110     
00111   initial_px = 0.0;
00112   initial_py = 0.0;
00113   initial_pz = Evertex; // GeV
00114   //cout <<"------------inelastic ep Event-------------------"<<endl;
00115   //cout <<" vertex = "<<vertex<<" , Evertex = "<<Evertex<<endl;
00116     
00117   /*based in fit to sigma_T and assuming R=sig_L/sig_T=q2 (good to q2=0.2 or so) */
00118 
00119   //Lab System
00120   double thetaIneEP[2];
00121   thetaIneEP[0] = 0.1;//0.2578;//degree in lab
00122   thetaIneEP[1] = 2.0;//0.5157;//degree in lab
00123 
00124   double e = Evertex;
00125   double eprime_max = e - 0.150;
00126   double eprime_min = eprime_max/nbinIneEP;
00127   if(Evertex<eprime_min) G4cout <<"Evertex is less than eprime_min..."<<"\n";
00128   else if(Evertex<eprime_max) eprime_max = Evertex;
00129 
00130   if( eprime_min < me ){
00131       eprime_min = me;
00132   }
00133 
00134   for(int i=0;i<nbinIneEP;i++) {//loop over theta
00135     for (int j=0;j<nbinIneEP;j++) {//loop over eprime
00136       double theta = (thetaIneEP[1] - thetaIneEP[0])/(nbinIneEP-1)*i + thetaIneEP[0];
00137       double costh = cos(theta*d2r/2.);//Note theta/2 here
00138       double sinth = sin(theta*d2r/2.);//and here
00139       double sin2 = sinth*sinth;//(1. - costh)/2.;
00140       double cos2 = costh*costh;//1. - sin2;
00141       double eprime = (eprime_max - eprime_min)/(nbinIneEP-1)*j + eprime_min;
00142       double q2 = 4.*e*eprime*sin2;
00143       double x = q2/2./mp/(e-eprime);
00144       double nu = q2/2./mp/x;
00145       //double wsq = mp*mp + 2.*mp*(e-eprime) - q2;
00146       double k = nu - q2/2./mp;
00147       double sigt=SigT(k);/* get sigma_T */
00148       /* Get F_1 using virtual photon flux */
00149       double f1 = (nu - q2 / 2. / mp) * mp / 4. / (pi*pi) / alpha * sigt /0.389 ;
00150       //Note that 0.389 = (hbar*c)^2 in GeV^2 mbarn, a conversion constant
00151       /* calculate f_2 using R=q2 */
00152       double r = q2;
00153       double f2 = f1 / ( (1. + (2. * mp * x) * (2. * mp * x) /q2) / 2. / x / (1. + r )) ; 
00154       /* sig is in barns/GeV/sr */
00155       double sig=5.2E-9/e/e/sin2/sin2* (cos2 * f2 / nu + sin2 * 2. * f1 / mp); 
00156       sig *= sin(theta*d2r);//with phase space factor 
00157       DDtable[i][j].Eprime = eprime;
00158       DDtable[i][j].theta = theta;
00159       DDtable[i][j].xs = sig;
00160     }
00161   }
00162 
00163   double_differential_t XStable_theta[nbinIneEP];
00164   double_differential_t XStable_Eprime[nbinIneEP];
00165   //---- Convert cross section table to integral fractions ----
00166   // First, numerically integrate
00167   double Im=0.0;
00168   double save;
00169 
00170   for(int i = 0;i<nbinIneEP; i++) {
00171     XStable_theta[i].xs   = 0.0;
00172     XStable_theta[i].theta = (thetaIneEP[1] - thetaIneEP[0])/(nbinIneEP-1)*i + thetaIneEP[0];
00173     for(int j = 0;j<nbinIneEP-1;j++){
00174   XStable_theta[i].xs += (DDtable[i][j].xs + DDtable[i][j+1].xs)/2.0;
00175     }//Integrate over Eprime
00176     if( i == 0 ){ 
00177   save = XStable_theta[i].xs;
00178   XStable_theta[i].xs = 0.0;
00179     } else {
00180   Im += (save+XStable_theta[i].xs)/2.0;
00181   save = XStable_theta[i].xs;
00182   XStable_theta[i].xs = Im;
00183     }
00184   }
00185   double totXS = Im*(thetaIneEP[1]-thetaIneEP[0])*d2r*(eprime_max - eprime_min)/(nbinIneEP-1.0)/(nbinIneEP-1.0)*2*pi;
00186   double factor = 6.0221415*0.1*1.0E-6/1.602176487E-19;
00187   double rate = totXS*t*rho/1.008*1.0*factor; //Event rate/sec/ uA
00188   gRootAnalysis->SetTotXS(totXS);
00189   gRootAnalysis->SetRate(rate);
00190 
00191   if( !(Im > 0.0) ){
00192       // Cross section is zero
00193       // just abort
00194 
00195       return;
00196   }
00197 
00198   assert( Im > 0.0 );
00199 
00200   // Next, normalize tables
00201   for(int k=0;k<nbinIneEP;k++){
00202     XStable_theta[k].xs /= Im;
00203   }
00204 
00205   // Determine scattering angle using ss
00206   double ss = (G4UniformRand());
00207   int index;
00208   double slope, b;
00209   for(index=0;index<nbinIneEP-1;index++) if(ss <= XStable_theta[index+1].xs) break;
00210   assert( index < nbinIneEP-1 );
00211 
00212   slope = (XStable_theta[index+1].xs - XStable_theta[index].xs)/(XStable_theta[index+1].theta - XStable_theta[index].theta);
00213   b = XStable_theta[index].xs;
00214   double lab_theta = XStable_theta[index].theta + (ss - b)/slope;
00215   int theIndex  = index;
00216   // Dimensionless quantity on how far we are to the next bin
00217   // This is for our bilinear interpolation
00218   double intpar = (ss - b)/(XStable_theta[index+1].xs - XStable_theta[index].xs);
00219 
00220   assert( 0.0 <= intpar && intpar < 1.0 );
00221 
00222   //Now do the Eprime 
00223   //For this, simply use the array of the selected theta
00224   double Im2=0.0;
00225   // Binlinear interpolation
00226   save =  DDtable[theIndex][0].xs*(1.0-intpar) + DDtable[theIndex+1][0].xs*intpar;
00227   XStable_Eprime[0].xs = 0.0;
00228   XStable_Eprime[0].Eprime = eprime_min;
00229 
00230   for(int j = 1;j<nbinIneEP;j++) {
00231       // Binlinear interpolation
00232     Im2 += (save + DDtable[theIndex][j].xs*(1.0-intpar) + DDtable[theIndex+1][j].xs*intpar)/2.0;
00233     save = DDtable[theIndex][j].xs*(1.0-intpar) + DDtable[theIndex+1][j].xs*intpar;
00234     XStable_Eprime[j].xs = Im2;
00235     XStable_Eprime[j].Eprime = (eprime_max - eprime_min)/(nbinIneEP-1)*j + eprime_min;
00236   }
00237 
00238   assert( Im2 > 0.0 );
00239 
00240   //double_differential_t *ineEP_Eprime = XStable_Eprime;
00241   // Next, normalize tables
00242   for(int k=0;k<nbinIneEP;k++){
00243     XStable_Eprime[k].xs /= Im2;
00244   }
00245   // Determine Eprime using ss2
00246   double ss2 = (G4UniformRand());
00247   int index2;
00248   double slope2, b2;
00249   for(index2=0;index2<nbinIneEP-1;index2++) if(ss2 <= XStable_Eprime[index2+1].xs) break;
00250   assert( index2 < nbinIneEP-1 );
00251 
00252   slope2 = (XStable_Eprime[index2+1].xs - XStable_Eprime[index2].xs)/(XStable_Eprime[index2+1].Eprime - XStable_Eprime[index2].Eprime);
00253   b2 = XStable_Eprime[index2].xs;
00254   double lab_Eprime = XStable_Eprime[index2].Eprime + (ss2 - b2)/slope2;
00255 
00256   //Now do phi
00257   double lab_phi = (2.0*pi*(G4UniformRand())) - pi;
00258     
00259   //Now add unknown beam divergence
00260   //pi0_theta += theta_div;
00261   //pi0_phi += phi_div;
00262 
00263   // Define kinematic conditions in lab
00264   double costh = cos(lab_theta*d2r);
00265   double sinth = sin(lab_theta*d2r);
00266   e = lab_Eprime;
00267   assert( e > 0.0 );
00268   double p = sqrt(e*e - me*me);
00269   assert( p > 0.0 );
00270   //double ep = Evertex + mp - e;
00271   double cosphie = cos( lab_phi );
00272   double sinphie = sin( lab_phi );
00273   //double cosphip = cos( lab_phi - pi);
00274   //double sinphip = sin( lab_phi - pi);
00275 
00276   //G4cout <<"Evertex + mp = "<<(Evertex+mp)<<", theta = "<<lab_theta<<", p = "<<p<<", e = "<<e<<", pp = "<<pp<<", ep = "<<ep<<", e+ep = "<<(e+ep)<<"\n";
00277   //G4cout <<"Evertex = "<<(Evertex)<<", theta = "<<lab_theta<<", p = "<<p<<", e = "<<e<<"\n";
00278 
00279   double e1, p1[3];
00280   e1 = e;
00281   for(int i=0;i<3;i++) {
00282     p1[i] = 0.0;
00283   }
00284     
00285   p1[2] = p*costh;
00286   p1[0] = p*sinth*cosphie;
00287   p1[1] = p*sinth*sinphie;
00288     
00289   double pmag1 = p;//sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
00290   double pmag0 = sqrt(initial_px*initial_px+initial_py*initial_py+initial_pz*initial_pz);
00291     
00292   // ------------ Final state particles ---------------
00293     
00294   //G4int n_particle = 1;
00295   //particleGun = new G4ParticleGun(n_particle);
00296     
00297   G4ParticleDefinition* particle_e = G4Electron::ElectronDefinition();
00298   //We will only throw the electron for now    
00299   particleGun->SetParticleDefinition(particle_e);
00300   particleGun->SetParticleMomentumDirection(G4ThreeVector(p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1));
00301   particleGun->SetParticleEnergy(e1*1000);
00302   particleGun->SetParticlePosition(G4ThreeVector(initial_x*10, initial_y*10, initial_z*10));
00303   particleGun->GeneratePrimaryVertex(anEvent);
00304     
00305   gRootAnalysis->SetMomentum0(Evertex*1000,initial_px/pmag0,initial_py/pmag0,initial_pz/pmag0);
00306   gRootAnalysis->SetMomentum1(e1*1000,p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1);
00307 
00308   //anEvent->SetEventID(0);
00309   anEvent->GetPrimaryVertex(0)->GetPrimary(0);//->SetTrackID(99999);
00310     
00311 }
00312 
00313 
00314 double SigT(double k) {
00315   double sigt ; 
00316   sigt=0 ;
00317   /* histogram-type fit to world data from PDG over Delta, S11, tc.*/
00318   /* switch to linear interpolation
00319    * rather than block
00320   if(k > 0.175) sigt=0.08 ;
00321   if(k > 0.196) sigt=0.12 ;
00322   if(k > 0.214) sigt=0.17 ;
00323   if(k > 0.233) sigt=0.21 ;
00324   if(k > 0.251) sigt=0.32 ;
00325   if(k > 0.251) sigt=0.32 ;
00326   if(k > 0.251) sigt=0.32 ;
00327   if(k > 0.271) sigt=0.40 ;
00328   if(k > 0.290) sigt=0.50 ;
00329   if(k > 0.310) sigt=0.53 ;
00330   if(k > 0.330) sigt=0.50 ;
00331   if(k > 0.350) sigt=0.45 ;
00332   if(k > 0.370) sigt=0.41 ;
00333   if(k > 0.390) sigt=0.32 ;
00334   if(k > 0.410) sigt=0.24 ;
00335   if(k > 0.430) sigt=0.22 ;
00336   if(k > 0.450) sigt=0.18 ;
00337   if(k > 0.470) sigt=0.17 ;
00338   if(k > 0.520) sigt=0.18 ;
00339   if(k > 0.550) sigt=0.21 ;
00340   if(k > 0.600) sigt=0.22 ;
00341   if(k > 0.650) sigt=0.24 ;
00342   if(k > 0.700) sigt=0.27 ;
00343   if(k > 0.750) sigt=0.25 ;
00344   if(k > 0.800) sigt=0.25 ;
00345   if(k > 0.750) sigt=0.25 ;
00346   if(k > 0.800) sigt=0.22 ;
00347   if(k > 0.900) sigt=0.21 ;
00348   if(k > 0.950) sigt=0.215;
00349   if(k > 1.000) sigt=0.225;
00350   if(k > 1.050) sigt=0.215;
00351   if(k > 1.100) sigt=0.185;
00352   if(k > 1.150) sigt=0.165;
00353   if(k > 1.200) sigt=0.15 ;
00354   if(k > 1.300) sigt=0.16 ;
00355   if(k > 1.400) sigt=0.15 ;
00356   */
00357   /* use fit to sigt (in mb) from Caldwell */
00358 
00359   static const int nbin = 37;
00360 
00361 
00362   double kval[nbin] = { 0.175, 0.196, 0.214, 0.233, 0.251, 0.251, 0.251, 0.271, 0.290, 0.310, 0.330, 0.350, 0.370, 0.390, 0.410, 0.430, 0.450, 0.470, 0.520, 0.550, 0.600, 0.650, 0.700, 0.750, 0.800, 0.750, 0.800, 0.900, 0.950, 1.000, 1.050, 1.100, 1.150, 1.200, 1.300, 1.400, 1.5 };
00363 
00364   double tval[nbin] = { 0.08, 0.12, 0.17, 0.21, 0.32, 0.32, 0.32, 0.40, 0.50, 0.53, 0.50, 0.45, 0.41, 0.32, 0.24, 0.22, 0.18, 0.17, 0.18, 0.21, 0.22, 0.24, 0.27, 0.25, 0.25, 0.25, 0.22, 0.21, 0.215, 0.225, 0.215, 0.185, 0.165, 0.15, 0.16, 0.15, 0.15};
00365 
00366 
00367   int idx = 0;
00368 
00369   if(k > 1.5){
00370       sigt=0.0987 + 0.0649/sqrt(k) ;
00371   } else { 
00372 
00373       while( !( kval[idx] < k && k <= kval[idx+1] ) && idx < nbin-1 ){ idx++; }
00374 
00375       // Didn't find a good value
00376       if( idx == nbin-1 ) { 
00377     assert( k < 0.175 );
00378     sigt = 0.0; 
00379       }
00380       else {
00381     assert( 0 <= idx && idx < nbin-1 );
00382 
00383     double intval = (k - kval[idx])/(kval[idx+1]-kval[idx]);
00384 
00385     assert( 0.0 <= intval && intval < 1.0 );
00386 
00387     sigt = tval[idx]*(1.0-intval) + tval[idx+1]*intval;
00388       }
00389   }
00390 
00391   return sigt ;
00392 }      
00393 

Generated on 16 Jun 2013 for mollersim by  doxygen 1.6.1