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