MWPC.cc

Go to the documentation of this file.
00001 //! \file
00002 //!
00003 //! Source file for MWPC class.
00004 //!
00005 //! The MWPC class is used to build the GEM tracking detector
00006 //! for the OLYMPUS detector simulation.
00007 //!
00008 //! \author D.K. Hasell
00009 //! \version 1.0
00010 //! \date 2010-10-31
00011 //!
00012 //! \ingroup detector
00013 
00014 // *+****1****+****2****+****3****+****4****+****5****+****6****+****7****+****
00015 
00016 // Include the MW header file and the user header files referenced here.
00017 
00018 #include "MWPC.h"
00019 #include "MW_SD.h"
00020 
00021 // Include the GEANT4 header files referenced in this file.
00022 
00023 #include "G4VPhysicalVolume.hh"
00024 #include "G4LogicalVolume.hh"
00025 #include "G4PVPlacement.hh"
00026 #include "G4Box.hh"
00027 #include "G4SubtractionSolid.hh"
00028 #include "G4UnionSolid.hh"
00029 #include "G4Material.hh"
00030 #include "G4ThreeVector.hh"
00031 #include "G4RotationMatrix.hh"
00032 #include "G4VisAttributes.hh"
00033 #include "G4Colour.hh"
00034 
00035 #include "G4SDManager.hh"
00036 
00037 // Use the standard namespace.
00038 
00039 using namespace std;
00040 
00041 // *+****1****+****2****+****3****+****4****+****5****+****6****+****7****+****
00042 
00043 // Routines in the OLYMPUS MWPC class.
00044 
00045 // Constructor.
00046 
00047 MWPC::MWPC() {}
00048 
00049 // Destructor.
00050 
00051 MWPC::~MWPC() {}
00052 
00053 // Member function to build the MWPC.
00054 
00055 void MWPC::Build( G4VPhysicalVolume * World_phys ) {
00056 
00057    // Building the MW detector.
00058    
00059    G4cout << "Building the MWPC detectors:\n" << flush;
00060    
00061    // Define the MW position and dimensions.
00062    
00063    G4double R[N_MW]      = { 200.0, 234.0, 268.0, 200.0, 234.0, 268.0 };
00064    
00065    G4double Theta[N_MW]  = {  12.0,  12.0,  12.0,  12.0,  12.0,  12.0 };
00066 
00067    G4double Phi[N_MW]    = {   0.0,   0.0,   0.0, 180.0, 180.0, 180.0 };
00068 
00069    G4double Alpha[N_MW]  = { -12.0, -12.0, -12.0,  12.0,  12.0,  12.0 };
00070 
00071    // Set the units properly.
00072    
00073    for( int i = 0; i < N_MW; ++i ) {
00074       R[i]      *= cm;
00075       Theta[i]  *= degree;
00076       Phi[i]    *= degree;
00077       Alpha[i]  *= degree;
00078    }
00079 
00080    G4double Width  = 18.0 * cm;
00081    G4double Height = 18.0 * cm;
00082    G4double Thick  =  5.0 * cm;
00083 
00084    // Create an instance of the MW sensitive detector.
00085 
00086    MW_SD * SD = new MW_SD( "OLYMPUS/MW" );
00087 
00088    G4SDManager::GetSDMpointer()->AddNewDetector( SD );
00089 
00090    // Loop over the detectors.
00091 
00092    for( int i = 0; i < N_MW; ++i ) {
00093 
00094      // Create the MW and place it.
00095    
00096      G4Box * MW_Active = new
00097        G4Box( "MW_Active", Width / 2.0, Height / 2.0, Thick / 2.0 );
00098    
00099      // Add the electronics boxes.
00100 
00101      G4Box * MW_Elect = new
00102         G4Box( "MW_Elect", 33.5 * cm / 2.0, 5.4 * cm / 2.0,
00103                18.0 * cm / 2.0 );
00104 
00105      G4RotationMatrix * RotE1 = new G4RotationMatrix;
00106      RotE1->rotateZ( -22.05 * degree );
00107 
00108      G4UnionSolid * MW_S1 = new
00109         G4UnionSolid( "MW_S1", MW_Active, MW_Elect,
00110                       RotE1, G4ThreeVector( 0.5 * cm,  8.7 * cm, 11.5 * cm ) );
00111 
00112      G4RotationMatrix * RotE2 = new G4RotationMatrix;
00113      RotE2->rotateZ(  22.05 * degree );
00114 
00115      G4UnionSolid * MW_solid = new
00116         G4UnionSolid( "MW_solid", MW_S1, MW_Elect,
00117                       RotE2, G4ThreeVector( 0.5 * cm, -8.7 * cm, 11.5 * cm ) );
00118 
00119      G4LogicalVolume * MW_log = new
00120        G4LogicalVolume( MW_solid, G4Material::GetMaterial( "WC_gas" ),
00121          "MW_log", 0, 0, 0, true );
00122       
00123      MW_log->SetVisAttributes( G4VisAttributes( false, G4Color() ) );
00124       
00125      G4double costheta = cos( Theta[i] );
00126      G4double sintheta = sin( Theta[i] );
00127      G4double cosphi   = cos( Phi[i] );
00128      G4double sinphi   = sin( Phi[i] );
00129 
00130      // Note these rotations produce the correct local coordinates in the left
00131      // and right sectors assuming the detectors are identical.
00132 
00133      G4RotationMatrix * Rotation = new G4RotationMatrix;
00134      Rotation->rotateY( Alpha[i] );
00135      if( i > 2 ) Rotation->rotateZ( 180.0 * degree );
00136 
00137      new G4PVPlacement( Rotation, G4ThreeVector( R[i] * sintheta * cosphi,
00138                                                  R[i] * sintheta * sinphi,
00139                                                  R[i] * costheta ),
00140                         "MW_phys", MW_log, World_phys, false, i, false );
00141 
00142      // Create and place the Gas volume.
00143    
00144      G4Box * MW_Gas_solid = new
00145        G4Box( "MW_Gas_solid", ( Width - 2.5 * cm ) / 2.0,
00146              ( Height - 2.5 * cm ) / 2.0, ( Thick + 0.01 * cm ) / 2.0 );
00147    
00148      G4LogicalVolume * MW_Gas_log = new
00149        G4LogicalVolume( MW_Gas_solid, G4Material::GetMaterial( "WC_gas" ),
00150          "MW_Gas_log", 0, 0, 0, true );
00151    
00152      MW_Gas_log->SetVisAttributes( G4VisAttributes( false, G4Color() ) );
00153       
00154      new G4PVPlacement( 0, G4ThreeVector(), 
00155          MW_Gas_log, "MW_Gas_phys", MW_log, false, i, false );
00156       
00157      // Create the Frame volume.
00158       
00159      G4SubtractionSolid * MW_Frame_solid = new
00160        G4SubtractionSolid( "MW_Frame_solid", MW_solid, MW_Gas_solid );
00161       
00162      G4LogicalVolume * MW_Frame_log = new
00163        G4LogicalVolume( MW_Frame_solid, G4Material::GetMaterial( "NemaG10" ),
00164          "MW_Frame_log", 0, 0, 0, true );
00165       
00166      MW_Frame_log->SetVisAttributes( G4VisAttributes( true,
00167                         G4Colour( 1.0, 0.0, 0 ) ) );
00168       
00169      new G4PVPlacement( 0, G4ThreeVector(),
00170          MW_Frame_log, "MW_Frame_phys", MW_log, false, i, false );
00171       
00172      // Create the Drift volume.
00173    
00174      G4Box * MW_Drift_solid = new
00175        G4Box( "MW_Drift_solid", ( Width - 2.5 * cm ) / 2.0,
00176          ( Height - 2.5 * cm ) / 2.0, ( 1.0 * cm ) / 2.0 );
00177    
00178      G4LogicalVolume * MW_Drift_log = new
00179        G4LogicalVolume( MW_Drift_solid, G4Material::GetMaterial( "WC_gas" ),
00180                        "MW_Drift_log", 0, 0, 0, true );
00181    
00182      MW_Drift_log->SetVisAttributes( G4VisAttributes( false, G4Color() ) );
00183       
00184      new G4PVPlacement( 0, G4ThreeVector( 0.0, 0.0, 0.0 ),
00185          MW_Drift_log, "MW_Drift_phys", MW_log, false, i, false );
00186       
00187      // Make the Drift volume sensitive.
00188       
00189      MW_Drift_log->SetSensitiveDetector( SD );
00190 
00191      // Place the electronics.
00192 
00193      G4LogicalVolume * MW_Elect_log = new
00194        G4LogicalVolume( MW_Elect, G4Material::GetMaterial( "G4_C" ),
00195                        "MW_Elect_log", 0, 0, 0, true );
00196    
00197      MW_Elect_log->SetVisAttributes(
00198         G4VisAttributes( true, G4Color( 1.0, 1.0, 0.0 ) ) );
00199       
00200      new G4PVPlacement( RotE1, G4ThreeVector( 0.5 * cm,  8.7 * cm, 11.5 * cm ),
00201          MW_Elect_log, "MW_Elect_phys", MW_log, false, i, false );
00202       
00203      new G4PVPlacement( RotE2, G4ThreeVector( 0.5 * cm, -8.7 * cm, 11.5 * cm ),
00204          MW_Elect_log, "MW_Elect_phys", MW_log, false, i, false );
00205       
00206    }
00207 
00208    // Add the support beams.
00209 
00210    G4Box * MW_Beam_solid = new
00211       G4Box( "MW_Beam_solid", 3.0 * cm / 2.0, 3.0 * cm / 2.0, 120 * cm / 2.0 );
00212    
00213    G4LogicalVolume * MW_Beam_log = new
00214       G4LogicalVolume( MW_Beam_solid, G4Material::GetMaterial( "G4_Al" ),
00215                        "MW_Beam_log", 0, 0, 0, true );
00216    
00217    MW_Beam_log->SetVisAttributes(
00218       G4VisAttributes( true, G4Color( 0.663, 0.675, 0.714 ) ) );
00219    
00220    G4double R_B = 240.0 * cm;
00221    G4double angle = 12.0 * degree;
00222    G4double cosang = cos( angle );
00223    G4double sinang = sin( angle );
00224 
00225    G4RotationMatrix * Rot1 = new G4RotationMatrix;
00226    Rot1->rotateY( -angle );
00227 
00228    new G4PVPlacement( Rot1,
00229                       G4ThreeVector( R_B * sinang + 12.0 * cm * cosang,
00230                                      5.0 * cm,
00231                                      R_B * cosang - 12.0 * cm * sinang ),
00232                       "MW_Beam_phys",
00233                       MW_Beam_log, World_phys, false, 0, false );
00234 
00235    new G4PVPlacement( Rot1,
00236                       G4ThreeVector( R_B * sinang + 12.0 * cm * cosang,
00237                                      -5.0 * cm,
00238                                      R_B * cosang - 12.0 * cm * sinang ),
00239                       "MW_Beam_phys",
00240                       MW_Beam_log, World_phys, false, 1, false );
00241 
00242    G4RotationMatrix * Rot2 = new G4RotationMatrix;
00243    Rot2->rotateY( angle );
00244 
00245    new G4PVPlacement( Rot2,
00246                       G4ThreeVector( -R_B * sinang - 12.0 * cm * cosang,
00247                                      5.0 * cm,
00248                                      R_B * cosang - 12.0 * cm * sinang ),
00249                       "MW_Beam_phys",
00250                       MW_Beam_log, World_phys, false, 2, false );
00251 
00252    new G4PVPlacement( Rot2,
00253                       G4ThreeVector( -R_B * sinang - 12.0 * cm * cosang,
00254                                      -5.0 * cm,
00255                                      R_B * cosang - 12.0 * cm * sinang ),
00256                       "MW_Beam_phys",
00257                       MW_Beam_log, World_phys, false, 3, false );
00258 
00259    G4cout << "     done.\n" << G4endl << flush;
00260 
00261    // That's All Folks !
00262 
00263    return;
00264 
00265 }