Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer << 3 // * DISCLAIMER * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th << 5 // * The following disclaimer summarizes all the specific disclaimers * 6 // * the Geant4 Collaboration. It is provided << 6 // * of contributors to this software. The specific disclaimers,which * 7 // * conditions of the Geant4 Software License << 7 // * govern, are listed with their locations in: * 8 // * LICENSE and available at http://cern.ch/ << 8 // * http://cern.ch/geant4/license * 9 // * include a list of copyright holders. << 10 // * 9 // * * 11 // * Neither the authors of this software syst 10 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 11 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 12 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 13 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file << 14 // * use. * 16 // * for the full disclaimer and the limitatio << 17 // * 15 // * * 18 // * This code implementation is the result << 16 // * This code implementation is the intellectual property of the * 19 // * technical work of the GEANT4 collaboratio << 17 // * GEANT4 collaboration. * 20 // * By using, copying, modifying or distri << 18 // * By copying, distributing or modifying the Program (or any work * 21 // * any work based on the software) you ag << 19 // * based on the Program) you indicate your acceptance of this * 22 // * use in resulting scientific publicati << 20 // * statement, and all its terms. * 23 // * acceptance of all terms of the Geant4 Sof << 24 // ******************************************* 21 // ******************************************************************** 25 // 22 // 26 // << 27 /// \file optical/LXe/src/LXeMainVolume.cc << 28 /// \brief Implementation of the LXeMainVolume << 29 // << 30 // << 31 #include "LXeMainVolume.hh" 23 #include "LXeMainVolume.hh" 32 << 33 #include "G4Box.hh" << 34 #include "G4Colour.hh" << 35 #include "G4LogicalBorderSurface.hh" << 36 #include "G4LogicalSkinSurface.hh" << 37 #include "G4LogicalVolume.hh" << 38 #include "G4Material.hh" << 39 #include "G4MaterialPropertiesTable.hh" << 40 #include "G4OpticalSurface.hh" << 41 #include "G4Sphere.hh" << 42 #include "G4SystemOfUnits.hh" << 43 #include "G4Tubs.hh" << 44 #include "G4VisAttributes.hh" << 45 #include "globals.hh" 24 #include "globals.hh" >> 25 #include "G4SDManager.hh" >> 26 #include "G4LogicalSkinSurface.hh" >> 27 #include "G4LogicalBorderSurface.hh" >> 28 #include "LXePMTSD.hh" >> 29 #include "LXeScintSD.hh" >> 30 >> 31 LXeScintSD* LXeMainVolume::scint_SD; >> 32 LXePMTSD* LXeMainVolume::pmt_SD; 46 33 47 //....oooOO0OOooo........oooOO0OOooo........oo << 34 G4LogicalVolume* LXeMainVolume::housing_log=NULL; 48 35 49 LXeMainVolume::LXeMainVolume(G4RotationMatrix* << 36 LXeMainVolume::LXeMainVolume(G4RotationMatrix *pRot, 50 G4LogicalVolume* << 37 const G4ThreeVector &tlate, 51 LXeDetectorConstr << 38 G4LogicalVolume *pMotherLogical, 52 // Pass info to the G4PVPlacement constructo << 39 G4bool pMany, 53 : G4PVPlacement( << 40 G4int pCopyNo, 54 pRot, tlate, << 41 LXeDetectorConstruction* c) 55 // Temp logical volume must be created h << 42 //Pass info to the G4PVPlacement constructor 56 new G4LogicalVolume(new G4Box("temp", 1, << 43 :G4PVPlacement(pRot,tlate, 57 "housing", pMotherLogical, pMany, pCopyN << 44 //Temp logical volume must be created here 58 fConstructor(c) << 45 new G4LogicalVolume(new G4Box("temp",1,1,1), >> 46 G4Material::GetMaterial("Vacuum"), >> 47 "temp",0,0,0), >> 48 "housing",pMotherLogical,pMany,pCopyNo),constructor(c) 59 { 49 { 60 CopyValues(); 50 CopyValues(); 61 51 62 G4double housing_x = fScint_x + 2. * fD_mtl; << 52 if(!housing_log || updated){ 63 G4double housing_y = fScint_y + 2. * fD_mtl; << 53 64 G4double housing_z = fScint_z + 2. * fD_mtl; << 54 G4double housing_x=scint_x+d_mtl; 65 << 55 G4double housing_y=scint_y+d_mtl; 66 //*************************** housing and sc << 56 G4double housing_z=scint_z+d_mtl; 67 fScint_box = new G4Box("scint_box", fScint_x << 57 68 fHousing_box = new G4Box("housing_box", hous << 58 //*************************** housing and scintillator 69 << 59 scint_box = new G4Box("scint_box",scint_x/2.,scint_y/2.,scint_z/2.); 70 fScint_log = new G4LogicalVolume(fScint_box, << 60 housing_box = new G4Box("housing_box",housing_x/2.,housing_y/2., 71 fHousing_log = new G4LogicalVolume(fHousing_ << 61 housing_z/2.); 72 << 62 73 new G4PVPlacement(nullptr, G4ThreeVector(), << 63 scint_log = new G4LogicalVolume(scint_box,G4Material::GetMaterial("LXe"), 74 << 64 "scint_log",0,0,0); 75 //*************** Miscellaneous sphere to de << 65 housing_log = new G4LogicalVolume(housing_box, 76 fSphere = new G4Sphere("sphere", 0., 2. * cm << 66 G4Material::GetMaterial("Al"), 77 fSphere_log = new G4LogicalVolume(fSphere, G << 67 "housing_log",0,0,0); 78 if (fSphereOn) << 68 79 new G4PVPlacement(nullptr, G4ThreeVector(5 << 69 80 fScint_log, false, 0); << 70 scint_phys = new G4PVPlacement(0,G4ThreeVector(),scint_log,"scintillator", 81 << 71 housing_log,false,0); 82 //****************** Build PMTs << 72 83 G4double innerRadius_pmt = 0.; << 73 //*************** Miscellaneous sphere to demonstrate skin surfaces 84 G4double height_pmt = fD_mtl / 2.; << 74 sphere = new G4Sphere("sphere",0.*mm,2.*cm,0.*deg,360.*deg,0.*deg, 85 G4double startAngle_pmt = 0.; << 75 360.*deg); 86 G4double spanningAngle_pmt = 360. * deg; << 76 sphere_log = new G4LogicalVolume(sphere,G4Material::GetMaterial("Al"), 87 << 77 "sphere_log"); 88 fPmt = new G4Tubs("pmt_tube", innerRadius_pm << 78 if(sphereOn) 89 spanningAngle_pmt); << 79 sphere_phys = new G4PVPlacement(0,G4ThreeVector(5.*cm,5.*cm,5.*cm), 90 << 80 sphere_log,"sphere",scint_log,false,0); 91 // the "photocathode" is a metal slab at the << 81 92 // is only a very rough approximation of the << 82 93 // absorbs or detects the photons based on t << 83 //****************** Build PMTs 94 fPhotocath = new G4Tubs("photocath_tube", in << 84 G4double innerRadius_pmt = 0.*cm; 95 startAngle_pmt, span << 85 G4double height_pmt = d_mtl/2.; 96 << 86 G4double startAngle_pmt = 0.*deg; 97 fPmt_log = new G4LogicalVolume(fPmt, G4Mater << 87 G4double spanningAngle_pmt = 360.*deg; 98 fPhotocath_log = new G4LogicalVolume(fPhotoc << 88 99 << 89 pmt = new G4Tubs("pmt_tube",innerRadius_pmt,outerRadius_pmt, 100 new G4PVPlacement(nullptr, G4ThreeVector(0., << 90 height_pmt,startAngle_pmt,spanningAngle_pmt); 101 fPmt_log, false, 0); << 91 102 << 92 //the "photocathode" is a metal slab at the back of the glass that 103 //***********Arrange pmts around the outside << 93 //is only a very rough approximation of the real thing since it only 104 << 94 //absorbs or detects the photons based on the efficiency set below 105 G4double dx = fScint_x / fNx; << 95 photocath = new G4Tubs("photocath_tube",innerRadius_pmt,outerRadius_pmt, 106 G4double dy = fScint_y / fNy; << 96 height_pmt/2,startAngle_pmt,spanningAngle_pmt); 107 G4double dz = fScint_z / fNz; << 97 108 << 98 pmt_log = new G4LogicalVolume(pmt,G4Material::GetMaterial("Glass"), 109 G4double x, y, z; << 99 "pmt_log"); 110 G4double xmin = -fScint_x / 2. - dx / 2.; << 100 photocath_log = new G4LogicalVolume(photocath, 111 G4double ymin = -fScint_y / 2. - dy / 2.; << 101 G4Material::GetMaterial("Al"), 112 G4double zmin = -fScint_z / 2. - dz / 2.; << 102 "photocath_log"); 113 G4int k = 0; << 103 114 << 104 photocath_phys = new G4PVPlacement(0,G4ThreeVector(0,0,-height_pmt/2), 115 z = -fScint_z / 2. - height_pmt; // front << 105 photocath_log,"photocath", 116 PlacePMTs(fPmt_log, nullptr, x, y, dx, dy, x << 106 pmt_log,false,0); 117 << 107 118 auto rm_z = new G4RotationMatrix(); << 108 119 rm_z->rotateY(180. * deg); << 109 120 z = fScint_z / 2. + height_pmt; // back << 110 //***********Arrange pmts around the outside of housing********** 121 PlacePMTs(fPmt_log, rm_z, x, y, dx, dy, xmin << 111 //---pmt sensitive detector 122 << 112 G4SDManager* SDman = G4SDManager::GetSDMpointer(); 123 auto rm_y1 = new G4RotationMatrix(); << 113 124 rm_y1->rotateY(-90. * deg); << 114 if(!pmt_SD){ 125 x = -fScint_x / 2. - height_pmt; // left << 115 pmt_SD = new LXePMTSD("/LXeDet/pmtSD"); 126 PlacePMTs(fPmt_log, rm_y1, y, z, dy, dz, ymi << 116 SDman->AddNewDetector(pmt_SD); 127 << 117 //Created here so it exists as pmts are being placed 128 auto rm_y2 = new G4RotationMatrix(); << 118 } 129 rm_y2->rotateY(90. * deg); << 119 pmt_SD->InitPMTs((nx*ny+nx*nz+ny*nz)*2); //let pmtSD know # of pmts 130 x = fScint_x / 2. + height_pmt; // right << 120 //------- 131 PlacePMTs(fPmt_log, rm_y2, y, z, dy, dz, ymi << 121 132 << 122 G4double dx = scint_x/nx; 133 auto rm_x1 = new G4RotationMatrix(); << 123 G4double dy = scint_y/ny; 134 rm_x1->rotateX(90. * deg); << 124 G4double dz = scint_z/nz; 135 y = -fScint_y / 2. - height_pmt; // bottom << 125 136 PlacePMTs(fPmt_log, rm_x1, x, z, dx, dz, xmi << 126 G4double x,y,z; 137 << 127 G4double xmin = -scint_x/2. - dx/2.; 138 auto rm_x2 = new G4RotationMatrix(); << 128 G4double ymin = -scint_y/2. - dy/2.; 139 rm_x2->rotateX(-90. * deg); << 129 G4double zmin = -scint_z/2. - dz/2.; 140 y = fScint_y / 2. + height_pmt; // top << 130 G4int k=0; 141 PlacePMTs(fPmt_log, rm_x2, x, z, dx, dz, xmi << 131 >> 132 z = -scint_z/2. - height_pmt; //front >> 133 PlacePMTs(pmt_log,0,x,y,dx,dy,xmin,ymin,nx,ny,x,y,z,k,pmt_SD); >> 134 G4RotationMatrix* rm_z = new G4RotationMatrix(); >> 135 rm_z->rotateY(180*deg); >> 136 z = scint_z/2. + height_pmt; //back >> 137 PlacePMTs(pmt_log,rm_z,x,y,dx,dy,xmin,ymin,nx,ny,x,y,z,k,pmt_SD); >> 138 >> 139 G4RotationMatrix* rm_y1 = new G4RotationMatrix(); >> 140 rm_y1->rotateY(-90*deg); >> 141 x = -scint_x/2. - height_pmt; //left >> 142 PlacePMTs(pmt_log,rm_y1,y,z,dy,dz,ymin,zmin,ny,nz,x,y,z,k,pmt_SD); >> 143 G4RotationMatrix* rm_y2 = new G4RotationMatrix(); >> 144 rm_y2->rotateY(90*deg); >> 145 x = scint_x/2. + height_pmt; //right >> 146 PlacePMTs(pmt_log,rm_y2,y,z,dy,dz,ymin,zmin,ny,nz,x,y,z,k,pmt_SD); >> 147 >> 148 G4RotationMatrix* rm_x1 = new G4RotationMatrix(); >> 149 rm_x1->rotateX(90*deg); >> 150 y = -scint_y/2. - height_pmt; //bottom >> 151 PlacePMTs(pmt_log,rm_x1,x,z,dx,dz,xmin,zmin,nx,nz,x,y,z,k,pmt_SD); >> 152 G4RotationMatrix* rm_x2 = new G4RotationMatrix(); >> 153 rm_x2->rotateX(-90*deg); >> 154 y = scint_y/2. + height_pmt; //top >> 155 PlacePMTs(pmt_log,rm_x2,x,z,dx,dz,xmin,zmin,nx,nz,x,y,z,k,pmt_SD); >> 156 >> 157 //**********Setup Sensitive Detectors*************** >> 158 if(!scint_SD){//determine if it has already been created >> 159 scint_SD = new LXeScintSD("/LXeDet/scintSD"); >> 160 SDman->AddNewDetector(scint_SD); >> 161 } >> 162 scint_log->SetSensitiveDetector(scint_SD); >> 163 >> 164 //sensitive detector is not actually on the photocathode. >> 165 //processHits gets done manually by the stepping action. >> 166 //It is used to detect when photons hit and get absorbed&detected at the >> 167 //boundary to the photocathode (which doesnt get done by attaching it to a >> 168 //logical volume. >> 169 //It does however need to be attached to something or else it doesnt get >> 170 //reset at the begining of events >> 171 photocath_log->SetSensitiveDetector(pmt_SD); 142 172 143 VisAttributes(); << 173 VisAttributes(); 144 SurfaceProperties(); << 174 SurfaceProperties(); >> 175 } 145 176 146 SetLogicalVolume(fHousing_log); << 177 SetLogicalVolume(housing_log); 147 } 178 } 148 179 149 //....oooOO0OOooo........oooOO0OOooo........oo << 180 void LXeMainVolume::CopyValues(){ >> 181 updated=constructor->GetUpdated(); 150 182 151 void LXeMainVolume::CopyValues() << 183 scint_x=constructor->GetScintX(); 152 { << 184 scint_y=constructor->GetScintY(); 153 fScint_x = fConstructor->GetScintX(); << 185 scint_z=constructor->GetScintZ(); 154 fScint_y = fConstructor->GetScintY(); << 186 d_mtl=constructor->GetHousingThickness(); 155 fScint_z = fConstructor->GetScintZ(); << 187 nx=constructor->GetNX(); 156 fD_mtl = fConstructor->GetHousingThickness() << 188 ny=constructor->GetNY(); 157 fNx = fConstructor->GetNX(); << 189 nz=constructor->GetNZ(); 158 fNy = fConstructor->GetNY(); << 190 outerRadius_pmt=constructor->GetPMTRadius(); 159 fNz = fConstructor->GetNZ(); << 191 sphereOn=constructor->GetSphereOn(); 160 fOuterRadius_pmt = fConstructor->GetPMTRadiu << 192 refl=constructor->GetHousingReflectivity(); 161 fSphereOn = fConstructor->GetSphereOn(); << 162 fRefl = fConstructor->GetHousingReflectivity << 163 } 193 } 164 194 165 //....oooOO0OOooo........oooOO0OOooo........oo << 195 //_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 166 << 196 void LXeMainVolume::PlacePMTs(G4LogicalVolume* pmt_log, 167 void LXeMainVolume::PlacePMTs(G4LogicalVolume* << 197 G4RotationMatrix *rot, 168 G4double& b, G4d << 198 G4double &a, G4double &b, G4double da, 169 G4int na, G4int << 199 G4double db, G4double amin, 170 { << 200 G4double bmin, G4int na, G4int nb, 171 /* PlacePMTs : a different way to parameter << 201 G4double &x, G4double &y, G4double &z, 172 * on calculating the position from the copy << 202 G4int &k,LXePMTSD* sd){ 173 * << 203 /*PlacePMTs : a different way to parameterize placement that does not depend on 174 * pmt_log = logical volume for pmts to be << 204 calculating the position from the copy number 175 * rot = rotation matrix to apply << 205 176 * a,b = coordinates to vary(ie. if varying << 206 pmt_log = logical volume for pmts to be placed 177 * da,db = value to increment a,b by << 207 rot = rotation matrix to apply 178 * amin,bmin = start values for a,b << 208 a,b = coordinates to vary(ie. if varying in the xy plane then pass x,y) 179 * na,nb = number of repitions in a and b << 209 da,db = value to increment a,b by 180 * x,y,z = just pass x,y, and z by referenc << 210 amin,bmin = start values for a,b 181 * k = copy number to start with << 211 na,nb = number of repitions in a and b 182 * sd = sensitive detector for pmts << 212 x,y,z = just pass x,y, and z by reference (the same ones passed for a,b) 183 */ << 213 k = copy number to start with 184 a = amin; << 214 sd = sensitive detector for pmts 185 for (G4int j = 1; j <= na; ++j) { << 215 */ 186 a += da; << 216 a=amin; 187 b = bmin; << 217 for(G4int j=1;j<=na;j++){ 188 for (G4int i = 1; i <= nb; ++i) { << 218 a+=da; 189 b += db; << 219 b=bmin; 190 new G4PVPlacement(rot, G4ThreeVector(x, << 220 for(G4int i=1;i<=nb;i++){ 191 fPmtPositions.push_back(G4ThreeVector(x, << 221 b+=db; 192 ++k; << 222 new G4PVPlacement(rot,G4ThreeVector(x,y,z),pmt_log,"pmt", >> 223 housing_log,false,k); >> 224 sd->SetPMTPos(k,x,y,z); >> 225 k++; 193 } 226 } 194 } 227 } 195 } 228 } 196 229 197 //....oooOO0OOooo........oooOO0OOooo........oo << 230 void LXeMainVolume::VisAttributes(){ 198 << 231 G4VisAttributes* housing_va = new G4VisAttributes(G4Colour(0.8,0.8,0.8)); 199 void LXeMainVolume::VisAttributes() << 232 housing_log->SetVisAttributes(housing_va); 200 { << 201 auto housing_va = new G4VisAttributes(G4Colo << 202 fHousing_log->SetVisAttributes(housing_va); << 203 233 204 auto sphere_va = new G4VisAttributes(); << 234 G4VisAttributes* sphere_va = new G4VisAttributes(); 205 sphere_va->SetForceSolid(true); 235 sphere_va->SetForceSolid(true); 206 fSphere_log->SetVisAttributes(sphere_va); << 236 sphere_log->SetVisAttributes(sphere_va); 207 } 237 } 208 238 209 //....oooOO0OOooo........oooOO0OOooo........oo << 239 void LXeMainVolume::SurfaceProperties(){ 210 << 240 const G4int num = 2; 211 void LXeMainVolume::SurfaceProperties() << 241 G4double Ephoton[num] = {7.0*eV, 7.14*eV}; 212 { << 242 213 std::vector<G4double> ephoton = {7.0 * eV, 7 << 243 //**Scintillator housing properties 214 << 244 G4double Reflectivity[num] = {refl, refl}; 215 //**Scintillator housing properties << 245 G4double Efficiency[num] = {0.0, 0.0}; 216 std::vector<G4double> reflectivity = {fRefl, << 246 G4MaterialPropertiesTable* scintHsngPT = new G4MaterialPropertiesTable(); 217 std::vector<G4double> efficiency = {0.0, 0.0 << 247 scintHsngPT->AddProperty("REFLECTIVITY", Ephoton, Reflectivity, num); 218 auto scintHsngPT = new G4MaterialPropertiesT << 248 scintHsngPT->AddProperty("EFFICIENCY", Ephoton, Efficiency, num); 219 scintHsngPT->AddProperty("REFLECTIVITY", eph << 249 G4OpticalSurface* OpScintHousingSurface = 220 scintHsngPT->AddProperty("EFFICIENCY", ephot << 250 new G4OpticalSurface("HousingSurface",unified,polished,dielectric_metal); 221 auto OpScintHousingSurface = << 222 new G4OpticalSurface("HousingSurface", uni << 223 OpScintHousingSurface->SetMaterialProperties 251 OpScintHousingSurface->SetMaterialPropertiesTable(scintHsngPT); 224 << 252 225 //**Sphere surface properties 253 //**Sphere surface properties 226 std::vector<G4double> sphereReflectivity = { << 254 G4double SphereReflectivity[num] = {1.0, 1.0}; 227 std::vector<G4double> sphereEfficiency = {0. << 255 G4double SphereEfficiency[num] = {0.0, 0.0}; 228 auto spherePT = new G4MaterialPropertiesTabl << 256 G4MaterialPropertiesTable* spherePT = new G4MaterialPropertiesTable(); 229 spherePT->AddProperty("REFLECTIVITY", ephoto << 257 spherePT->AddProperty("REFLECTIVITY", Ephoton, SphereReflectivity, num); 230 spherePT->AddProperty("EFFICIENCY", ephoton, << 258 spherePT->AddProperty("EFFICIENCY", Ephoton, SphereEfficiency, num); 231 auto OpSphereSurface = new G4OpticalSurface( << 259 G4OpticalSurface* OpSphereSurface = >> 260 new G4OpticalSurface("SphereSurface",unified,polished,dielectric_metal); 232 OpSphereSurface->SetMaterialPropertiesTable( 261 OpSphereSurface->SetMaterialPropertiesTable(spherePT); 233 << 262 234 //**Photocathode surface properties 263 //**Photocathode surface properties 235 std::vector<G4double> photocath_EFF = {1., 1 << 264 G4double photocath_EFF[num]={1.,1.}; //Enables 'detection' of photons 236 std::vector<G4double> photocath_ReR = {1.92, << 265 G4double photocath_REFL[num]={0.,0.}; 237 std::vector<G4double> photocath_ImR = {1.69, << 266 G4MaterialPropertiesTable* photocath_mt = new G4MaterialPropertiesTable(); 238 auto photocath_mt = new G4MaterialProperties << 267 photocath_mt->AddProperty("EFFICIENCY",Ephoton,photocath_EFF,num); 239 photocath_mt->AddProperty("EFFICIENCY", epho << 268 photocath_mt->AddProperty("REFLECTIVITY",Ephoton,photocath_REFL,num); 240 photocath_mt->AddProperty("REALRINDEX", epho << 269 G4OpticalSurface* photocath_opsurf= 241 photocath_mt->AddProperty("IMAGINARYRINDEX", << 270 new G4OpticalSurface("photocath_opsurf",glisur,polished, 242 auto photocath_opsurf = << 271 dielectric_metal); 243 new G4OpticalSurface("photocath_opsurf", g << 244 photocath_opsurf->SetMaterialPropertiesTable 272 photocath_opsurf->SetMaterialPropertiesTable(photocath_mt); 245 273 >> 274 246 //**Create logical skin surfaces 275 //**Create logical skin surfaces 247 new G4LogicalSkinSurface("photocath_surf", f << 276 new G4LogicalSkinSurface("photocath_surf",housing_log, 248 new G4LogicalSkinSurface("sphere_surface", f << 277 OpScintHousingSurface); 249 new G4LogicalSkinSurface("photocath_surf", f << 278 new G4LogicalSkinSurface("sphere_surface",sphere_log,OpSphereSurface); >> 279 new G4LogicalSkinSurface("photocath_surf",photocath_log,photocath_opsurf); 250 } 280 } >> 281 >> 282 >> 283 251 284