MollerPrimaryGenAction_moller.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 Euler 0.5772157
00031 #define d2r pi/180.
00032 #define r2d 180/pi
00033 
00034 #define gevfm 0.1973
00035 #define pmu 2.79
00036 #define alpha 0.007299
00037 
00038 void MollerPrimaryGenAction::GeneratePrimaries_moller_dustin(G4Event* anEvent)
00039 {
00040   //----------------------
00041   // GenerateEvent
00042   //----------------------
00043   
00044   double initial_x = 0.0;//*cm;
00045   double initial_y = 0.0;//*cm;
00046   double initial_z = 0.0;//*cm;
00047 
00048   double initial_px = 0.0;//*GeV;
00049   double initial_py = 0.0;//*GeV;
00050   double initial_pz = 0.0;//*GeV;
00051 
00052   //Find the scattering point in the target
00053   double vertex; //scattering point in target (cm) measured from the upstream end of target
00054   double t = 150.0; // t = thickness of target in cm
00055   double rho = 0.0715; // rho = density of target in g/cm**3 (from KK)
00056   double radiationLength = 63.04; // g/cm**2 (from PDG)
00057   double t_rad = radiationLength/rho; // t_rad = radiation length in cm
00058   double z = G4UniformRand();
00059   vertex = z*t;//just do this for now
00060   
00061   double Evertex = ebeam;
00062   //Now we know how mush material the beam travels through before moller interaction
00063   //Use this to calculate energy loss
00064   double cut=0.000001; //lower limit of bremsstrahlung (1 keV)
00065   double  Ekin = ebeam - me;
00066   double fracrl = vertex/t_rad; //total radiation lenght fraction travelled through
00067   double bt = fracrl*4./3.;
00068 
00069   double prob, prob_sample, sample, eloss, env, value, ref;
00070   //Calculation of probability to have bremsstrahlung effect above 1 keV
00071   prob = 1.- pow(cut/Ekin,bt) - bt/(bt+1.)*(1.- pow(cut/Ekin,bt+1.))
00072     + 0.75*bt/(2.+bt)*(1.- pow(cut/Ekin,bt+2.));
00073   prob = prob/(1.- bt*Euler + bt*bt/2.*(Euler*Euler+pi*pi/6.)); /* Gamma function */
00074 
00075   prob_sample = G4UniformRand();  /* Random sampling */
00076 
00077   if (prob_sample <= prob) {//Bremsstrahlung has taken place!
00078     //Generate photon energy with sample and reject using 1/x as envelope 
00079     do {
00080       sample = G4UniformRand();
00081       eloss = cut*pow(Ekin/cut,sample);
00082       
00083       env = 1./eloss;
00084       value = 1./eloss*(1.-eloss/Ekin+0.75*pow(eloss/Ekin,2))*pow(eloss/Ekin,bt);
00085       
00086       sample = G4UniformRand();
00087       ref = value/env;
00088     } while (sample > ref);
00089     
00090     Evertex = ebeam - eloss;
00091   }
00092 
00093   if( Evertex < me ) return;
00094 
00095   double vertex_x = (-0.25 + (0.5*(G4UniformRand())));
00096   double vertex_y = (-0.25 + (0.5*(G4UniformRand())));
00097   initial_x = vertex_x;
00098   initial_y = vertex_y;
00099   initial_z = vertex - t/2.; //cm  
00100   
00101   //Make realistic beam angle (Not yet)
00102   //double theta_div = 0.000125*((double)random()/(double)RAND_MAX);
00103   //double phi_div = 2.0*M_PI*((double)random()/(double)RAND_MAX);
00104   ////double theta_div = 0.0;
00105   ////double phi_div = 0.0;
00106   ////cout << "theta = "<<theta_div*180/M_PI<<", phi = "<<phi_div*180/M_PI<<endl;
00107     
00108   initial_px = 0.0;
00109   initial_py = 0.0;
00110   initial_pz = Evertex; // GeV
00111   
00112   //cout <<"-------------Moller Event-------------------"<<endl;
00113   //cout <<" vertex = "<<vertex<<" , Evertex = "<<Evertex<<endl;
00114         
00115   //Center of Mass System
00116   double thetaMoller[2];
00117   thetaMoller[0] = 53.13010;//costheta_cm = +0.6
00118   thetaMoller[1] = 126.8699;//costheta_cm = -0.6
00119   double x1 = cos(thetaMoller[1]*d2r);
00120   double x2 = cos(thetaMoller[0]*d2r);
00121   double y2 = (1 - x1)/2.;
00122   double y1 = (1 - x2)/2.;
00123   double ds = me*me+me*me+2.*me*Evertex;
00124   double ecm = sqrt(ds);
00125   double decm[2];
00126   decm[0] = ds/2./ecm;
00127   double dps = pow(decm[0],2)-me*me;
00128   double dp = sqrt(dps);
00129   decm[1] = sqrt(dps+me*me);
00130 
00131   for(int i =0;i<nbin;i++) {
00132     double y = y1 + ((y2 - y1)/nbin*i)+(y2 - y1)/nbin/2.;
00133     double dt = -1.*y*ds;
00134     double ct = (dt-me*me-me*me+2.*pow(decm[0],2))/(2.*pow(dp,2));
00135     if( !( -1.0 < ct && ct < 1.0 )){ 
00136   // SPR 9/20/12
00137   // Something's wrong here for very low beam energies
00138   // Not sure how to handle it, but at least this point
00139   // is kinematically forbidden
00140   return;
00141     }
00142     double ct2 = pow(ct,2);
00143     double st2 = 1. - ct2;
00144     double st = sqrt(st2);
00145     double th = acos(ct);
00146       
00147     double ecmp = ecm/2.;
00148     double vcmp = sqrt(pow(ecmp,2)-me*me)/ecmp;
00149     double dsig = 0.;
00150       
00151     double eom = ecmp/me;
00152     double eom2 = pow(eom,2);
00153     double d1 = pow(r0,2)*pow((2.*eom2-1.),2)/4./pow(vcmp,4)/pow(eom2,3);
00154     double d2 = 4./pow(st2,2)-3./st2+pow((eom2-1.),2)/pow((2.*eom2-1),2)*(1+4./pow(st,2));
00155       
00156     dsig = d1*d2;
00157 
00158     assert( dsig > 0.0 );
00159 
00160     dsig = dsig*2.; //Convert from dsigma/dOmega to dsigma/dy/dphi
00161     dsig = dsig/100; //Convert from fm**2 to Barns
00162     XStable[i].y = y;
00163     XStable[i].theta = th;
00164     XStable[i].xs = dsig;
00165   }
00166 
00167   cms_cross_section_t *moller = XStable;
00168     
00169   //---- Convert cross section table to integral fractions ----
00170   // First, numerically integrate
00171   double Im=0.0;
00172   double save = moller[0].xs;
00173   moller[0].xs = Im;
00174 
00175   for(int j = 1;j<nbin;j++) {
00176       Im += (save + moller[j].xs)/2.0;
00177       save = moller[j].xs;
00178       moller[j].xs = Im;
00179   }
00180 
00181   double totXS = Im*(y2-y1)/(nbin-1.0)*2*pi;
00182   double factor = 6.0221415*0.1*1.0E-6/1.602176487E-19;
00183   double rate = totXS*t*rho/1.008*1.0*factor; //Event rate/sec/ uA
00184   gRootAnalysis->SetTotXS(totXS);
00185   gRootAnalysis->SetRate(rate);
00186 
00187   if( !(Im > 0.0) ){ 
00188       printf("Im = %f, Evertex = %f\n", Im, Evertex);
00189   }
00190   assert( Im > 0.0 ); // idiot check
00191 
00192   // Next, normalize tables
00193   moller = XStable;
00194   for(int k=0;k<nbin;k++){
00195     moller[k].xs /= Im;
00196   }
00197     
00198   // Determine moller cms scattering angle using ss
00199   double ss = (G4UniformRand());
00200     
00201   //cms_cross_section_t *c=XStable;
00202   int index;
00203   double slope, b;
00204   for(index=0;index<nbin-1;index++) if(ss <= moller[index+1].xs) break;
00205   assert( index < nbin-1 ); // idiot check
00206   slope = (moller[index+1].xs - moller[index].xs)/(moller[index+1].theta - moller[index].theta);
00207   b = moller[index].xs;
00208     
00209   double cms_theta = moller[index].theta + (ss - b)/slope;
00210 
00211   double cms_phi = (2.0*pi*(G4UniformRand())) - pi;
00212     
00213   //Now add unknown beam divergence
00214   //pi0_theta += theta_div;
00215   //pi0_phi += phi_div;
00216         
00217   // Define kinematic conditions in cms
00218   double gammap = Evertex/ecm;
00219   double betap = 1/gammap*sqrt(pow(gammap,2)-1);
00220     
00221   double e1cm = gammap*me;
00222   double e2cm = e1cm;
00223     
00224   //Primary (beam) electron
00225   double costheta1 = cos( cms_theta );
00226   double sintheta1 = sin( cms_theta );
00227     
00228   double cosphi1 = cos( cms_phi );
00229   double sinphi1 = sin( cms_phi );
00230     
00231   double p1cm[3];
00232 
00233 
00234   p1cm[0] = e1cm * sintheta1 * cosphi1;
00235   p1cm[1] = e1cm * sintheta1 * sinphi1;
00236   p1cm[2] = e1cm * costheta1;
00237     
00238   //Secondary (target) electron
00239   double costheta2 = cos( pi - cms_theta );
00240   double sintheta2 = sin( pi - cms_theta );
00241     
00242   double cosphi2 = cos( cms_phi - pi);
00243   double sinphi2 = sin( cms_phi - pi);
00244   if (cms_phi<0.0){
00245     cosphi2 = cos( cms_phi + pi);
00246     sinphi2 = sin( cms_phi + pi);
00247   } else {
00248       
00249   }
00250     
00251   double p2cm[3];  
00252   p2cm[0] = e2cm * sintheta2 * cosphi2;
00253   p2cm[1] = e2cm * sintheta2 * sinphi2;
00254   p2cm[2] = e2cm * costheta2;
00255     
00256     
00257   // Transform to the lab frame.
00258   double e1, p1[3], e2, p2[3];
00259   e1 = 0.0;
00260   e2 = 0.0;
00261   for(int i=0;i<3;i++) {
00262     p1[i] = 0.0;
00263     p2[i] = 0.0;
00264   }
00265     
00266   p1[2] = gammap * (p1cm[2] + betap*e1cm);
00267   p2[2] = gammap * (p2cm[2] + betap*e2cm);
00268   p1[0] = p1cm[0];
00269   p1[1] = p1cm[1];
00270   p2[0] = p2cm[0];
00271   p2[1] = p2cm[1];
00272     
00273   double pmag1 = sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
00274   double pmag2 = sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
00275   double pmag0 = sqrt(initial_px*initial_px+initial_py*initial_py+initial_pz*initial_pz);
00276     
00277   e1 = gammap * ( e1cm + betap*p1cm[2] );
00278   e2 = gammap * ( e2cm + betap*p2cm[2] );
00279     
00280   // Calculate the laboratory polar angles for moller electrons.  
00281   //double th1 = acos( p1[2] / e1 );
00282   //double ph1 = atan2( p1[1], p1[0] );
00283     
00284   //double th2 = acos( p2[2] / e2 );
00285   //double ph2 = atan2( p2[1], p2[0] );
00286     
00287     
00288   // ------------ Final state electrons ---------------
00289     
00290   //G4int n_particle = 1;
00291   //particleGun = new G4ParticleGun(n_particle);
00292     
00293   G4ParticleDefinition* particle = G4Electron::ElectronDefinition();
00294 
00295   assert( pmag1 > 0.0 && pmag2 > 0.0 && pmag0 > 0.0 );
00296 
00297   assert( e1 > 0.0 && e2 > 0.0 );
00298     
00299   if(e1>=e2) {
00300     particleGun->SetParticleDefinition(particle);
00301     particleGun->SetParticleMomentumDirection(G4ThreeVector(p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1));
00302     particleGun->SetParticleEnergy(e1*1000);
00303     particleGun->SetParticlePosition(G4ThreeVector(initial_x*10, initial_y*10, initial_z*10));
00304     particleGun->GeneratePrimaryVertex(anEvent);
00305       
00306     particleGun->SetParticleDefinition(particle);
00307     particleGun->SetParticleMomentumDirection(G4ThreeVector(p2[0]/pmag2,p2[1]/pmag2,p2[2]/pmag2));
00308     particleGun->SetParticleEnergy(e2*1000);
00309     particleGun->SetParticlePosition(G4ThreeVector(initial_x*10, initial_y*10, initial_z*10));
00310     particleGun->GeneratePrimaryVertex(anEvent);
00311       
00312     gRootAnalysis->SetMomentum0(Evertex*1000,initial_px/pmag0,initial_py/pmag0,initial_pz/pmag0);
00313     gRootAnalysis->SetMomentum1(e1*1000,p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1);
00314     gRootAnalysis->SetMomentum2(e2*1000,p2[0]/pmag2,p2[1]/pmag2,p2[2]/pmag2);
00315   } else {
00316     particleGun->SetParticleDefinition(particle);
00317     particleGun->SetParticleMomentumDirection(G4ThreeVector(p2[0]/pmag2,p2[1]/pmag2,p2[2]/pmag2));
00318     particleGun->SetParticleEnergy(e2*1000);
00319     particleGun->SetParticlePosition(G4ThreeVector(initial_x*10, initial_y*10, initial_z*10));
00320     particleGun->GeneratePrimaryVertex(anEvent);
00321       
00322     particleGun->SetParticleDefinition(particle);
00323     particleGun->SetParticleMomentumDirection(G4ThreeVector(p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1));
00324     particleGun->SetParticleEnergy(e1*1000);
00325     particleGun->SetParticlePosition(G4ThreeVector(initial_x*10, initial_y*10, initial_z*10));
00326     particleGun->GeneratePrimaryVertex(anEvent);    
00327       
00328     gRootAnalysis->SetMomentum0(Evertex*1000,initial_px/pmag0,initial_py/pmag0,initial_pz/pmag0);
00329     gRootAnalysis->SetMomentum2(e1*1000,p1[0]/pmag1,p1[1]/pmag1,p1[2]/pmag1);
00330     gRootAnalysis->SetMomentum1(e2*1000,p2[0]/pmag2,p2[1]/pmag2,p2[2]/pmag2);
00331   }
00332   //anEvent->SetEventID(0);
00333   anEvent->GetPrimaryVertex(0)->GetPrimary(0);//->SetTrackID(99999);
00334 
00335 }

Generated on 16 Jun 2013 for mollersim by  doxygen 1.6.1