Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:28:32

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 //
0027 /// \file optical/LXe/src/LXeMainVolume.cc
0028 /// \brief Implementation of the LXeMainVolume class
0029 //
0030 //
0031 #include "LXeMainVolume.hh"
0032 
0033 #include "G4Box.hh"
0034 #include "G4Colour.hh"
0035 #include "G4LogicalBorderSurface.hh"
0036 #include "G4LogicalSkinSurface.hh"
0037 #include "G4LogicalVolume.hh"
0038 #include "G4Material.hh"
0039 #include "G4MaterialPropertiesTable.hh"
0040 #include "G4OpticalSurface.hh"
0041 #include "G4Sphere.hh"
0042 #include "G4SystemOfUnits.hh"
0043 #include "G4Tubs.hh"
0044 #include "G4VisAttributes.hh"
0045 #include "globals.hh"
0046 
0047 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0048 
0049 LXeMainVolume::LXeMainVolume(G4RotationMatrix* pRot, const G4ThreeVector& tlate,
0050                              G4LogicalVolume* pMotherLogical, G4bool pMany, G4int pCopyNo,
0051                              LXeDetectorConstruction* c)
0052   // Pass info to the G4PVPlacement constructor
0053   : G4PVPlacement(
0054       pRot, tlate,
0055       // Temp logical volume must be created here
0056       new G4LogicalVolume(new G4Box("temp", 1, 1, 1), G4Material::GetMaterial("Vacuum"), "temp"),
0057       "housing", pMotherLogical, pMany, pCopyNo),
0058     fConstructor(c)
0059 {
0060   CopyValues();
0061 
0062   G4double housing_x = fScint_x + 2. * fD_mtl;
0063   G4double housing_y = fScint_y + 2. * fD_mtl;
0064   G4double housing_z = fScint_z + 2. * fD_mtl;
0065 
0066   //*************************** housing and scintillator
0067   fScint_box = new G4Box("scint_box", fScint_x / 2., fScint_y / 2., fScint_z / 2.);
0068   fHousing_box = new G4Box("housing_box", housing_x / 2., housing_y / 2., housing_z / 2.);
0069 
0070   fScint_log = new G4LogicalVolume(fScint_box, G4Material::GetMaterial("LXe"), "scint_log");
0071   fHousing_log = new G4LogicalVolume(fHousing_box, G4Material::GetMaterial("Al"), "housing_log");
0072 
0073   new G4PVPlacement(nullptr, G4ThreeVector(), fScint_log, "scintillator", fHousing_log, false, 0);
0074 
0075   //*************** Miscellaneous sphere to demonstrate skin surfaces
0076   fSphere = new G4Sphere("sphere", 0., 2. * cm, 0. * deg, 360. * deg, 0. * deg, 360. * deg);
0077   fSphere_log = new G4LogicalVolume(fSphere, G4Material::GetMaterial("Al"), "sphere_log");
0078   if (fSphereOn)
0079     new G4PVPlacement(nullptr, G4ThreeVector(5. * cm, 5. * cm, 5. * cm), fSphere_log, "sphere",
0080                       fScint_log, false, 0);
0081 
0082   //****************** Build PMTs
0083   G4double innerRadius_pmt = 0.;
0084   G4double height_pmt = fD_mtl / 2.;
0085   G4double startAngle_pmt = 0.;
0086   G4double spanningAngle_pmt = 360. * deg;
0087 
0088   fPmt = new G4Tubs("pmt_tube", innerRadius_pmt, fOuterRadius_pmt, height_pmt, startAngle_pmt,
0089                     spanningAngle_pmt);
0090 
0091   // the "photocathode" is a metal slab at the back of the glass that
0092   // is only a very rough approximation of the real thing since it only
0093   // absorbs or detects the photons based on the efficiency set below
0094   fPhotocath = new G4Tubs("photocath_tube", innerRadius_pmt, fOuterRadius_pmt, height_pmt / 2.,
0095                           startAngle_pmt, spanningAngle_pmt);
0096 
0097   fPmt_log = new G4LogicalVolume(fPmt, G4Material::GetMaterial("Glass"), "pmt_log");
0098   fPhotocath_log = new G4LogicalVolume(fPhotocath, G4Material::GetMaterial("Al"), "photocath_log");
0099 
0100   new G4PVPlacement(nullptr, G4ThreeVector(0., 0., -height_pmt / 2.), fPhotocath_log, "photocath",
0101                     fPmt_log, false, 0);
0102 
0103   //***********Arrange pmts around the outside of housing**********
0104 
0105   G4double dx = fScint_x / fNx;
0106   G4double dy = fScint_y / fNy;
0107   G4double dz = fScint_z / fNz;
0108 
0109   G4double x, y, z;
0110   G4double xmin = -fScint_x / 2. - dx / 2.;
0111   G4double ymin = -fScint_y / 2. - dy / 2.;
0112   G4double zmin = -fScint_z / 2. - dz / 2.;
0113   G4int k = 0;
0114 
0115   z = -fScint_z / 2. - height_pmt;  // front
0116   PlacePMTs(fPmt_log, nullptr, x, y, dx, dy, xmin, ymin, fNx, fNy, x, y, z, k);
0117 
0118   auto rm_z = new G4RotationMatrix();
0119   rm_z->rotateY(180. * deg);
0120   z = fScint_z / 2. + height_pmt;  // back
0121   PlacePMTs(fPmt_log, rm_z, x, y, dx, dy, xmin, ymin, fNx, fNy, x, y, z, k);
0122 
0123   auto rm_y1 = new G4RotationMatrix();
0124   rm_y1->rotateY(-90. * deg);
0125   x = -fScint_x / 2. - height_pmt;  // left
0126   PlacePMTs(fPmt_log, rm_y1, y, z, dy, dz, ymin, zmin, fNy, fNz, x, y, z, k);
0127 
0128   auto rm_y2 = new G4RotationMatrix();
0129   rm_y2->rotateY(90. * deg);
0130   x = fScint_x / 2. + height_pmt;  // right
0131   PlacePMTs(fPmt_log, rm_y2, y, z, dy, dz, ymin, zmin, fNy, fNz, x, y, z, k);
0132 
0133   auto rm_x1 = new G4RotationMatrix();
0134   rm_x1->rotateX(90. * deg);
0135   y = -fScint_y / 2. - height_pmt;  // bottom
0136   PlacePMTs(fPmt_log, rm_x1, x, z, dx, dz, xmin, zmin, fNx, fNz, x, y, z, k);
0137 
0138   auto rm_x2 = new G4RotationMatrix();
0139   rm_x2->rotateX(-90. * deg);
0140   y = fScint_y / 2. + height_pmt;  // top
0141   PlacePMTs(fPmt_log, rm_x2, x, z, dx, dz, xmin, zmin, fNx, fNz, x, y, z, k);
0142 
0143   VisAttributes();
0144   SurfaceProperties();
0145 
0146   SetLogicalVolume(fHousing_log);
0147 }
0148 
0149 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0150 
0151 void LXeMainVolume::CopyValues()
0152 {
0153   fScint_x = fConstructor->GetScintX();
0154   fScint_y = fConstructor->GetScintY();
0155   fScint_z = fConstructor->GetScintZ();
0156   fD_mtl = fConstructor->GetHousingThickness();
0157   fNx = fConstructor->GetNX();
0158   fNy = fConstructor->GetNY();
0159   fNz = fConstructor->GetNZ();
0160   fOuterRadius_pmt = fConstructor->GetPMTRadius();
0161   fSphereOn = fConstructor->GetSphereOn();
0162   fRefl = fConstructor->GetHousingReflectivity();
0163 }
0164 
0165 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0166 
0167 void LXeMainVolume::PlacePMTs(G4LogicalVolume* pmt_log, G4RotationMatrix* rot, G4double& a,
0168                               G4double& b, G4double da, G4double db, G4double amin, G4double bmin,
0169                               G4int na, G4int nb, G4double& x, G4double& y, G4double& z, G4int& k)
0170 {
0171   /*  PlacePMTs : a different way to parameterize placement that does not depend
0172    * on calculating the position from the copy number
0173    *
0174    *  pmt_log = logical volume for pmts to be placed
0175    *  rot = rotation matrix to apply
0176    *  a,b = coordinates to vary(ie. if varying in the xy plane then pass x,y)
0177    *  da,db = value to increment a,b by
0178    *  amin,bmin = start values for a,b
0179    *  na,nb = number of repitions in a and b
0180    *  x,y,z = just pass x,y, and z by reference (the same ones passed for a,b)
0181    *  k = copy number to start with
0182    *  sd = sensitive detector for pmts
0183    */
0184   a = amin;
0185   for (G4int j = 1; j <= na; ++j) {
0186     a += da;
0187     b = bmin;
0188     for (G4int i = 1; i <= nb; ++i) {
0189       b += db;
0190       new G4PVPlacement(rot, G4ThreeVector(x, y, z), pmt_log, "pmt", fHousing_log, false, k);
0191       fPmtPositions.push_back(G4ThreeVector(x, y, z));
0192       ++k;
0193     }
0194   }
0195 }
0196 
0197 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0198 
0199 void LXeMainVolume::VisAttributes()
0200 {
0201   auto housing_va = new G4VisAttributes(G4Colour(0.8, 0.8, 0.8));
0202   fHousing_log->SetVisAttributes(housing_va);
0203 
0204   auto sphere_va = new G4VisAttributes();
0205   sphere_va->SetForceSolid(true);
0206   fSphere_log->SetVisAttributes(sphere_va);
0207 }
0208 
0209 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0210 
0211 void LXeMainVolume::SurfaceProperties()
0212 {
0213   std::vector<G4double> ephoton = {7.0 * eV, 7.14 * eV};
0214 
0215   //**Scintillator housing properties
0216   std::vector<G4double> reflectivity = {fRefl, fRefl};
0217   std::vector<G4double> efficiency = {0.0, 0.0};
0218   auto scintHsngPT = new G4MaterialPropertiesTable();
0219   scintHsngPT->AddProperty("REFLECTIVITY", ephoton, reflectivity);
0220   scintHsngPT->AddProperty("EFFICIENCY", ephoton, efficiency);
0221   auto OpScintHousingSurface =
0222     new G4OpticalSurface("HousingSurface", unified, polished, dielectric_metal);
0223   OpScintHousingSurface->SetMaterialPropertiesTable(scintHsngPT);
0224 
0225   //**Sphere surface properties
0226   std::vector<G4double> sphereReflectivity = {1.0, 1.0};
0227   std::vector<G4double> sphereEfficiency = {0.0, 0.0};
0228   auto spherePT = new G4MaterialPropertiesTable();
0229   spherePT->AddProperty("REFLECTIVITY", ephoton, sphereReflectivity);
0230   spherePT->AddProperty("EFFICIENCY", ephoton, sphereEfficiency);
0231   auto OpSphereSurface = new G4OpticalSurface("SphereSurface", unified, polished, dielectric_metal);
0232   OpSphereSurface->SetMaterialPropertiesTable(spherePT);
0233 
0234   //**Photocathode surface properties
0235   std::vector<G4double> photocath_EFF = {1., 1.};
0236   std::vector<G4double> photocath_ReR = {1.92, 1.92};
0237   std::vector<G4double> photocath_ImR = {1.69, 1.69};
0238   auto photocath_mt = new G4MaterialPropertiesTable();
0239   photocath_mt->AddProperty("EFFICIENCY", ephoton, photocath_EFF);
0240   photocath_mt->AddProperty("REALRINDEX", ephoton, photocath_ReR);
0241   photocath_mt->AddProperty("IMAGINARYRINDEX", ephoton, photocath_ImR);
0242   auto photocath_opsurf =
0243     new G4OpticalSurface("photocath_opsurf", glisur, polished, dielectric_metal);
0244   photocath_opsurf->SetMaterialPropertiesTable(photocath_mt);
0245 
0246   //**Create logical skin surfaces
0247   new G4LogicalSkinSurface("photocath_surf", fHousing_log, OpScintHousingSurface);
0248   new G4LogicalSkinSurface("sphere_surface", fSphere_log, OpSphereSurface);
0249   new G4LogicalSkinSurface("photocath_surf", fPhotocath_log, photocath_opsurf);
0250 }