MollerPrimaryGenAction_elasticep.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 // typedef struct {
00010 //   double theta;
00011 //   double y;
00012 //   double xs;
00013 // }cms_cross_section_t;
00014 
00015 // typedef struct {
00016 //   double theta;
00017 //   double Eprime;
00018 //   double xs;
00019 // }double_differential_t;
00020 
00021 // #define nbinIneEP 100
00022 // double_differential_t DDtable[nbinIneEP][nbinIneEP];
00023 
00024 // #define nbin 1000
00025 // cms_cross_section_t XStable[nbin];
00026 
00027 #define r0 2.818  //electron radius in fm
00028 #define pi 3.14159
00029 #define Euler 0.5772157
00030 #define d2r pi/180.
00031 #define r2d 180/pi
00032 
00033 //#define mp 0.9382796 //proton restmass (GeV)
00034 #define gevfm 0.1973
00035 #define pmu 2.79
00036 #define alpha 0.007299
00037 
00038 #define NINTERVAL 4
00039 
00040 
00041 void MollerPrimaryGenAction::GeneratePrimaries_elasticep_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 tt = 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*tt;//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  Ekin = ebeam - me;
00068   double fracrl = vertex/t_rad; //total radiation lenght fraction travelled through
00069   double bt = fracrl*4./3.;
00070 
00071   double prob, prob_sample, sample, eloss, value;
00072   //Calculation of probability to have bremsstrahlung effect above 1 keV
00073   prob = 1.- pow(bremcut/Ekin,bt) - bt/(bt+1.)*(1.- pow(bremcut/Ekin,bt+1.))
00074     + 0.75*bt/(2.+bt)*(1.- pow(bremcut/Ekin,bt+2.));
00075   prob = prob/(1.- bt*Euler + bt*bt/2.*(Euler*Euler+pi*pi/6.)); /* Gamma function */
00076   prob_sample = G4UniformRand();  /* Random sampling */
00077 
00078   value = 1.0;
00079 
00080   double colEcut = 0.080;  // Expected cutoff for collimator
00081 
00082   double Evlo[NINTERVAL] = {
00083       bremcut,
00084       (ebeam-bremcut-colEcut)*1.0/(11.0-colEcut-bremcut),
00085       (ebeam-bremcut-colEcut)*8.0/(11.0-colEcut-bremcut),
00086       (ebeam-bremcut-colEcut)*(ebeam-colEcut)/(11.0-colEcut-bremcut),
00087   };
00088 
00089   double Evhi[NINTERVAL] = {
00090       (ebeam-bremcut-colEcut)*1.0/(11.0-colEcut-bremcut),
00091       (ebeam-bremcut-colEcut)*8.0/(11.0-colEcut-bremcut),
00092       (ebeam-bremcut-colEcut)*(ebeam-colEcut)/(11.0-colEcut-bremcut),
00093       (ebeam-bremcut-colEcut)*ebeam/(11.0-colEcut-bremcut)
00094   };
00095 
00096   double Eprob[NINTERVAL]  = { 0.07, 0.05, 0.875, 0.005};
00097 
00098   double Enorm[NINTERVAL];
00099   // Interval normalization
00100   for( int idx = 0; idx < NINTERVAL; idx++ ){
00101       Enorm[idx]  = ((Evhi[idx]-Evlo[idx])/(Evhi[NINTERVAL-1]-Evlo[0]))
00102     /Eprob[idx];
00103   }
00104 
00105   int Evidx;
00106   double evsum = 0.0;
00107 
00108   // Averages over the intervals
00109   double vweight = 1.0;
00110   double vavg[4] = {
00111       log(Evhi[0]/Evlo[0])/(Evhi[0]-Evlo[0]),
00112       1.0,
00113       log((ebeam-Evlo[2])/(ebeam-Evhi[2]))/(Evhi[2]-Evlo[2]),
00114       1.0};
00115 
00116   if (prob_sample <= prob) {//Bremsstrahlung has taken place!
00117       //  We break this into 4 seperate energy loss intervals
00118       //  with total integrals roughly the size of
00119       //  what the ep product looks like with 11 GeV beam
00120       //   cut  -  1000 MeV, 1/x, 7%
00121       //   1000 -  8000 MeV, flat 5%
00122       //   8000 - 10920 MeV, 1/(E-x), 87.5%
00123       //  10920 - 11000 MeV, flat, 0.5%
00124 
00125       sample = G4UniformRand();
00126 
00127       // Identify our region
00128       //
00129       // based on the probability distribution
00130       Evidx = 0;
00131       evsum  = Eprob[Evidx];
00132       while( evsum < sample ){
00133     Evidx++;
00134     evsum += Eprob[Evidx];
00135       }
00136 
00137       sample = G4UniformRand();
00138 
00139       if( Evidx == 1 || Evidx == 3 ){
00140     // sample energy flat
00141     eloss = (Evhi[Evidx]-Evlo[Evidx])*sample + Evlo[Evidx];
00142     vweight = 1.0;
00143       }
00144 
00145       if( Evidx == 0 ){
00146     eloss = Evlo[Evidx]*pow(Evhi[Evidx]/Evlo[Evidx],sample);
00147     vweight = eloss;
00148       }
00149 
00150       if( Evidx == 2 ){
00151     eloss = ebeam - (ebeam-Evhi[Evidx])*
00152         pow((ebeam-Evlo[Evidx])/(ebeam-Evhi[Evidx]),sample);
00153     vweight = (ebeam-eloss);
00154       }
00155 
00156       vweight *= vavg[Evidx];
00157       //  mult by ebeam-bremcut for proper normalization
00158       value = RadProfile(eloss, bt)*
00159     ((Evhi[NINTERVAL-1]-Evlo[0])/EnergNumInt(bt, Evlo[0], Evhi[NINTERVAL-1])) // average of RadProfile
00160     *vweight // sampling weighting (flat or ) / average value for normalization
00161     *Enorm[Evidx]; //  Weight given the region
00162 
00163       Evertex = ebeam - eloss;
00164   }
00165 
00166   if( Evertex < me ) return;
00167 
00168   double vertex_x = (-0.25 + (0.5*(G4UniformRand())));
00169   double vertex_y = (-0.25 + (0.5*(G4UniformRand())));
00170   initial_x = vertex_x;
00171   initial_y = vertex_y;
00172   initial_z = vertex - tt/2.; //cm  
00173   
00174   //Make realistic beam angle (Not yet)
00175   //double theta_div = 0.000125*((double)random()/(double)RAND_MAX);
00176   //double phi_div = 2.0*M_PI*((double)random()/(double)RAND_MAX);
00177   ////double theta_div = 0.0;
00178   ////double phi_div = 0.0;
00179   ////cout << "theta = "<<theta_div*180/M_PI<<", phi = "<<phi_div*180/M_PI<<endl;
00180     
00181   initial_px = 0.0;
00182   initial_py = 0.0;
00183   initial_pz = Evertex; // GeV
00184   //cout <<"-------------elastic ep Event-------------------"<<endl;
00185   //cout <<" vertex = "<<vertex<<" , Evertex = "<<Evertex<<endl;
00186 
00187   //Lab System
00188   double thetaMott[2];
00189   thetaMott[0] = 0.1;//degree in lab
00190   thetaMott[1] = 2.0;//degree in lab
00191     
00192   double p0 = sqrt(Evertex*Evertex - me*me);
00193 
00194   for(int i =0;i<nbin;i++) {
00195     double theta = thetaMott[0] + i*(thetaMott[1]-thetaMott[0])/(nbin-1);
00196     double costh = cos(theta*d2r);
00197     double sinth = sin(theta*d2r);
00198     double sin2 = (1. - costh)/2.;
00199     double cos2 = 1. - sin2;
00200     double p = mp*Evertex/(Evertex*(1. - costh) + mp);
00201     double e = sqrt(p*p+me*me);
00202     double q2 = -2.*(me*me - Evertex*e + p0*p*costh);
00203     double t = q2/4./(mp*mp);
00204     double ge = 1./pow((1. + q2/0.71),2);
00205     double gm = ge*pmu;
00206     double cang = (ge*ge + t*gm*gm)/(1. + t) + t*t*gm*gm*sin2/cos2;
00207     double crmott = alpha*alpha*cos2/4./(p0*p0)/(sin2*sin2)/(1. + 2.*p0/mp*sin2)*gevfm*gevfm/100.;
00208     double cross = crmott*cang;
00209     double csmott = cross*sinth;
00210     XStable[i].y = theta;
00211     XStable[i].theta = theta;
00212     XStable[i].xs = csmott;
00213   }
00214 
00215   cms_cross_section_t *mott = XStable;
00216     
00217   //---- Convert cross section table to integral fractions ----
00218   // First, numerically integrate
00219   double Im=0.0;
00220   double save = mott[0].xs;
00221   mott[0].xs = 0.0;
00222 
00223   for(int j = 1;j<nbin-1;j++) {
00224     Im += (save+mott[j].xs)/2.0;
00225     save = mott[j].xs;
00226     mott[j].xs = Im;
00227   }
00228   // Next, normalize tables
00229   mott = XStable;
00230 
00231   assert( Im > 0.0 );
00232 
00233   for(int k=0;k<nbin;k++){
00234     mott[k].xs /= Im;
00235   }
00236   double totXS = Im*(thetaMott[1]-thetaMott[0])*d2r/(nbin-1.0)*2*pi;
00237   double factor = 6.0221415*0.1*1.0E-6/1.602176487E-19;
00238   double rate = totXS*tt*rho/1.008*1.0*factor; //Event rate/sec/ uA
00239   rate *= value; //mult by value to renorm rate to uneven energy distribution
00240   gRootAnalysis->SetTotXS(totXS);
00241   gRootAnalysis->SetRate(rate);
00242     
00243   // Determine mott cms scattering angle using ss
00244   double ss = (G4UniformRand());
00245     
00246   //cms_cross_section_t *c=XStable;
00247   int index;
00248   double slope, b;
00249   for(index=0;index<nbin-1;index++) if(ss <= mott[index+1].xs) break;
00250   assert( index < nbin-1 );
00251   slope = (mott[index+1].xs - mott[index].xs)/(mott[index+1].theta - mott[index].theta);
00252   b = mott[index].xs;
00253     
00254   double lab_theta = mott[index].theta + (ss - b)/slope;
00255   double lab_phi = (2.0*pi*(G4UniformRand())) - pi;
00256     
00257   //Now add unknown beam divergence
00258   //pi0_theta += theta_div;
00259   //pi0_phi += phi_div;
00260         
00261   // Define kinematic conditions in lab
00262   double costh = cos(lab_theta*d2r);
00263   double sinth = sin(lab_theta*d2r);
00264   double p = mp*Evertex/(Evertex*(1. - costh) + mp);    
00265   double e = sqrt(p*p + me*me);
00266   double ep = Evertex + mp - e;
00267   //double ep_alt = sqrt(mp*mp+p0*p0+p*p-2*p0*p*costh);
00268   double pp = sqrt(ep*ep - mp*mp);
00269   double sinp = p*sinth/pp;
00270   //double thetp = asin(sinp);
00271   double cosp = sqrt(1.- sinp*sinp);
00272   double cosphie = cos( lab_phi );
00273   double sinphie = sin( lab_phi );
00274   double cosphip = cos( lab_phi - pi);
00275   double sinphip = sin( lab_phi - pi);
00276 
00277   //G4cout <<"Evertex + mp = "<<(Evertex+mp)<<", theta = "<<lab_theta<<", p = "<<p<<", e = "<<e<<", pp = "<<pp<<", ep = "<<ep<<", e+ep = "<<(e+ep)<<"\n";
00278 
00279   double e1, p1[3], e2, p2[3];
00280   e1 = e;
00281   e2 = ep;
00282   for(int i=0;i<3;i++) {
00283     p1[i] = 0.0;
00284     p2[i] = 0.0;
00285   }
00286     
00287   p1[2] = p*costh;
00288   p2[2] = pp*cosp;
00289   p1[0] = p*sinth*cosphie;
00290   p1[1] = p*sinth*sinphie;
00291   p2[0] = pp*sinp*cosphip;
00292   p2[1] = pp*sinp*sinphip;
00293     
00294   double pmag1 = p;//sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
00295   //double pmag2 = pp;//sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
00296   double pmag0 = sqrt(initial_px*initial_px+initial_py*initial_py+initial_pz*initial_pz);
00297     
00298   // ------------ Final state particles ---------------
00299     
00300   //G4int n_particle = 1;
00301   //particleGun = new G4ParticleGun(n_particle);
00302     
00303   G4ParticleDefinition* particle = G4Electron::ElectronDefinition();
00304   //We will only throw the electron for now
00305 
00306   assert( pmag1 > 0.0 );
00307 
00308   particleGun->SetParticleDefinition(particle);
00309   particleGun->SetParticleMomentumDirection(G4ThreeVector(p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1));
00310   particleGun->SetParticleEnergy(e1*1000);
00311   particleGun->SetParticlePosition(G4ThreeVector(initial_x*10, initial_y*10, initial_z*10));
00312   particleGun->GeneratePrimaryVertex(anEvent);
00313 
00314   gRootAnalysis->SetMomentum0(Evertex*1000,initial_px/pmag0,initial_py/pmag0,initial_pz/pmag0);
00315   gRootAnalysis->SetMomentum1(e1*1000,p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1);
00316 
00317   //anEvent->SetEventID(0);
00318   anEvent->GetPrimaryVertex(0)->GetPrimary(0);//->SetTrackID(99999);
00319 
00320 }

Generated on 16 Jun 2013 for mollersim by  doxygen 1.6.1