Generator.cc

Go to the documentation of this file.
00001 //! \file
00002 //!
00003 //! Source file for Generator class used for defining the OLYMPUS
00004 //! event generator.
00005 //!
00006 //! This defines the Generator class and the member routines which
00007 //! generate the primary events for the OLYMPUS Monte Carlo
00008 //!
00009 //! \author D.K. Hasell
00010 //! \version 1.0
00011 //! \date 2010-10-14
00012 //!
00013 //! \ingroup event
00014 
00015 // *+****1****+****2****+****3****+****4****+****5****+****6****+****7****+****
00016 
00017 // Include the Generator header file.
00018 
00019 #include "Generator.h"
00020 #include "GN_Messenger.h"
00021 
00022 // Include the required GEANT event generation header files.
00023 
00024 #include "G4ParticleGun.hh"
00025 #include "G4Event.hh"
00026 #include "G4ThreeVector.hh"
00027 #include "G4ParticleTable.hh"
00028 #include "Randomize.hh"
00029 
00030 // Include required C and C++ header files.
00031 
00032 #include <cmath>
00033 
00034 // *+****1****+****2****+****3****+****4****+****5****+****6****+****7****+****
00035 
00036 // Use the standard namespace.
00037 
00038 using namespace std;
00039 
00040 // Define the Generator class.
00041 
00042 // Constructor.
00043 
00044 Generator::Generator() {
00045 
00046    // Set defaults.
00047 
00048    Ebeam = 2.0 * GeV;
00049 
00050    BeamCharge = -1;
00051 
00052    ep_Elastic = true;
00053 
00054    // Create pointer to Generator Messenger.
00055 
00056    GN_Messenger::Instance()->setGNptr( this );
00057 
00058    // Initialise ep elastic scattering kinematics.
00059 
00060    epKin = new ep_Kinematics( Ebeam );
00061 
00062    epTheta_Min =  15.0 * degree;
00063    epTheta_Max =  90.0 * degree;
00064 
00065    cos_epThMin = cos( epTheta_Min );
00066    cos_epThMax = cos( epTheta_Max );
00067 
00068    epPhi_Min = -20.0 * degree;
00069    epPhi_Max =  20.0 * degree;
00070 
00071    particleGun = new G4ParticleGun( 1 );
00072 
00073 }
00074 
00075 // Destructor.
00076 
00077 Generator::~Generator() {
00078    delete epKin;
00079    delete particleGun;
00080 }
00081 
00082 // Member functions.
00083 
00084 void Generator::GeneratePrimaries( G4Event * event ) {
00085 
00086    // Generate ep elastic scattering events with an isotropic distribution.
00087 
00088    G4double theta3 = acos( CLHEP::RandFlat::shoot() * 
00089                            ( cos_epThMax - cos_epThMin ) + cos_epThMin );
00090 
00091    G4double phi = CLHEP::RandFlat::shoot() *
00092       ( epPhi_Max - epPhi_Min ) + epPhi_Min;
00093 
00094    if( CLHEP::RandFlat::shoot() > 0.5 ) phi += CLHEP::pi;
00095 
00096    G4double cosTH3 = cos( theta3 );
00097    G4double sinTH3 = sin( theta3 );
00098    G4double cosPH = cos( phi );
00099    G4double sinPH = sin( phi );
00100 
00101    G4double E3, E4, Q2, theta4;
00102 
00103    epKin->for_e_angle( theta3, E3, E4, Q2, theta4 );
00104 
00105    G4double cosTH4 = cos( theta4 );
00106    G4double sinTH4 = sin( theta4 );
00107 
00108    G4ThreeVector vertex = Target_Distribution();
00109 
00110    // Define a pointer to the particle table.
00111 
00112    static G4ParticleTable * particletable = G4ParticleTable::GetParticleTable();
00113 
00114    // Generate electron or positron.
00115 
00116    if( BeamCharge == -1 ) {
00117       particleGun->SetParticleDefinition( particletable->FindParticle("e-") );
00118    }
00119    else {
00120       particleGun->SetParticleDefinition( particletable->FindParticle("e+") );
00121    }
00122    particleGun->SetParticleEnergy( E3 - CLHEP::electron_mass_c2 );
00123    particleGun->SetParticlePosition( vertex );
00124    particleGun->SetParticleMomentumDirection(
00125       G4ThreeVector( sinTH3 * cosPH, sinTH3 * sinPH, cosTH3 ) );
00126 
00127    particleGun->GeneratePrimaryVertex( event );
00128 
00129    // Generate proton.
00130 
00131    particleGun->SetParticleDefinition( particletable->FindParticle("proton") );
00132    particleGun->SetParticleEnergy( E4 - CLHEP::proton_mass_c2 );
00133    particleGun->SetParticlePosition( vertex );
00134    particleGun->SetParticleMomentumDirection( 
00135       G4ThreeVector( -sinTH4 * cosPH, -sinTH4 * sinPH, cosTH4 ) );
00136 
00137    particleGun->GeneratePrimaryVertex( event );
00138 
00139 }
00140 
00141 G4ThreeVector Generator::Target_Distribution() {
00142 
00143    static G4double Half_Target_Length = 60.0 * cm / 2.0;
00144 
00145    G4double x, y, z, rand;
00146   
00147    x = CLHEP::RandGauss::shoot( 0.0, 0.1 * cm );
00148  
00149    y = CLHEP::RandGauss::shoot( 0.0, 0.1 * cm );
00150  
00151    rand = CLHEP::RandFlat::shoot();
00152 
00153    if( rand < 0.5 ) z = Half_Target_Length * ( sqrt( 2.0 * rand ) - 1.0 );
00154    else z = Half_Target_Length * ( 1.0 - sqrt( 2.0 * ( 1.0 - rand ) ) );
00155 
00156    return G4ThreeVector( x, y, z );
00157 }
00158 
00159 // Set/Get beam kinetic energy.
00160 
00161 G4double Generator::setEbeam( G4double energy ) {
00162    Ebeam = energy;
00163    delete epKin;
00164    epKin = new ep_Kinematics( Ebeam );
00165    return Ebeam;
00166 }
00167 G4double Generator::getEbeam() { return Ebeam; }
00168 
00169 //! Set/Get beam charge.
00170 
00171 G4int Generator::setBeamCharge( G4int q ) {
00172    if( q == 1 || q == -1 ) BeamCharge = q;
00173    return BeamCharge;
00174 }
00175 G4int Generator::getBeamCharge() { return BeamCharge; }
00176 
00177 //! Set/Get ep Theta min.
00178 
00179 G4double Generator::setepThetaMin( G4double min ) {
00180    epTheta_Min = min;
00181    cos_epThMin = cos( epTheta_Min );
00182    return epTheta_Min;
00183 }
00184 G4double Generator::getepThetaMin() { return epTheta_Min; }
00185 
00186 //! Set/Get ep Theta max.
00187 
00188 G4double Generator::setepThetaMax( G4double max ) {
00189    epTheta_Max = max;
00190    cos_epThMax = cos( epTheta_Max );
00191    return epTheta_Max;
00192 }
00193 G4double Generator::getepThetaMax() { return epTheta_Max; }
00194 
00195 //! Set/Get ep Phi min.
00196 
00197 G4double Generator::setepPhiMin( G4double min ) { return epPhi_Min = min; }
00198 G4double Generator::getepPhiMin() { return epPhi_Min; }
00199 
00200 //! Set/Get ep Phi max.
00201 
00202 G4double Generator::setepPhiMax( G4double max ) { return epPhi_Max = max; }
00203 G4double Generator::getepPhiMax() { return epPhi_Max; }
00204 
00205 // Print
00206 
00207 void Generator::Print() {
00208    G4cout << "Generator\n"
00209           << "   Ebeam       = " << Ebeam / MeV << " [MeV]\n"
00210           << "   Charge      = " << BeamCharge << "\n"
00211           << "   epElastic   = " << ep_Elastic << "\n"
00212           << "   epTheta_Min = " << epTheta_Min / degree << " [degree]\n"
00213           << "   epTheta_Max = " << epTheta_Max / degree << " [degree]\n"
00214           << G4endl;
00215 }
00216 
00217 // Routines for calculating ep elastic scattering kinematics.
00218 
00219 ep_Kinematics::ep_Kinematics( G4double Ebeam ) {
00220 
00221    G4double Me = CLHEP::electron_mass_c2;
00222    G4double Mp = CLHEP::proton_mass_c2;
00223 
00224    // Note we assume Ebeam is the electron kinetic energy.
00225    // N.B. these equations are exact and do not neglect the electron mass.
00226 
00227    E1 = Ebeam + Me;
00228    p1 = sqrt( Ebeam * Ebeam + 2.0 * Me * Ebeam );
00229 
00230    beta  = p1 / ( E1 + Mp );
00231 
00232    E3cmbyG = ( Me * Me + Mp * E1 ) / ( E1 + Mp );
00233 
00234 }
00235 
00236 // Destructor.
00237 
00238 ep_Kinematics::~ep_Kinematics() {}
00239 
00240 // Return kinematic variables as a function of electron scattering angle.
00241 
00242 void ep_Kinematics::for_e_angle( G4double theta3, G4double & E3, G4double & E4,
00243                                 G4double & Q2, G4double & theta4 ) {
00244 
00245    G4double Me = CLHEP::electron_mass_c2;
00246    G4double Mp = CLHEP::proton_mass_c2;
00247 
00248    G4double cos3 = cos( theta3 );
00249    G4double bbcos = 1.0 - beta * beta * cos3 * cos3;
00250 
00251    E3 = ( E3cmbyG + beta * cos3 *
00252           sqrt( E3cmbyG * E3cmbyG - bbcos * Me * Me ) ) / bbcos;
00253 
00254    G4double p3 = sqrt( E3 * E3 - Me * Me );
00255 
00256    Q2 = 2.0 * ( E1 * E3 - p1 * p3 * cos3  - Me * Me );
00257 
00258    E4 = E1 + Mp - E3;
00259 
00260    G4double p4 = sqrt( E4 * E4 - Mp * Mp );
00261 
00262    theta4 = acos( ( p1 - p3 * cos3 ) / p4 );
00263 
00264    return;
00265 }
00266 
00267 // Print
00268 
00269 void ep_Kinematics::Print() {
00270 
00271    G4cout << "ep_Kinenmatics\n"
00272           << "   E1   = " << E1 / MeV << " [MeV]\n"
00273           << "   p1   = " << p1 / MeV << " [MeV]\n"
00274           << "   beta = " << beta << "\n"
00275           << "   E3cm = " << E3cmbyG / MeV << " [MeV]\n"
00276           << G4endl;
00277 }
00278 
00279 // Calculate the ep elastic cross section.
00280 
00281 G4double epCrossSection( const G4double & E, const G4double & theta3,
00282                          const G4double & Ep, const G4double & Q2 ) {
00283 
00284    static G4double Mp    = CLHEP::proton_mass_c2;
00285    static G4double Alpha = 1.0 / 137.035999679;
00286    static G4double Mu_p2 = pow( 2.792847356, 2 );
00287    static G4double hbarc = CLHEP::hbarc;
00288 
00289    G4double th     = theta3 / 2.0;
00290    G4double costh  = cos( th );
00291    G4double costh2 = pow( cos( th ), 2 );
00292    G4double sinth2 = pow( sin( th ), 2 );
00293 
00294    G4double Mott   = pow( ( Alpha * costh * hbarc ) /
00295                           ( 2.0 * E * sinth2 ), 2 );
00296 
00297    G4double GE2    = pow( 1.0 - Q2 / ( 0.71 * GeV * GeV ), -4 );
00298    G4double GM2    = Mu_p2 * GE2;
00299 
00300    G4double tau    = Q2 / ( 4.0 * Mp * Mp );
00301 
00302    return Mott * Ep / E * ( ( GE2 + tau * GM2 ) / ( 1.0 + tau ) +
00303                             2.0 * tau * GM2 * sinth2 / costh2 );
00304 
00305 }