Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 #include "Par03DetectorConstruction.hh" 27 28 #include "Par03DetectorMessenger.hh" 29 #include "Par03EMShowerModel.hh" 30 #include "Par03SensitiveDetector.hh" 31 32 #include "G4Box.hh" 33 #include "G4LogicalVolume.hh" 34 #include "G4Material.hh" 35 #include "G4NistManager.hh" 36 #include "G4PVPlacement.hh" 37 #include "G4PVReplica.hh" 38 #include "G4Region.hh" 39 #include "G4RegionStore.hh" 40 #include "G4RunManager.hh" 41 #include "G4SDManager.hh" 42 #include "G4Tubs.hh" 43 #include "G4UnitsTable.hh" 44 #include "G4VisAttributes.hh" 45 46 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 47 48 Par03DetectorConstruction::Par03DetectorConstruction() : G4VUserDetectorConstruction() 49 { 50 fDetectorMessenger = new Par03DetectorMessenger(this); 51 52 G4NistManager* nistManager = G4NistManager::Instance(); 53 fDetectorMaterial = nistManager->FindOrBuildMaterial("G4_Fe"); 54 } 55 56 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 57 58 Par03DetectorConstruction::~Par03DetectorConstruction() = default; 59 60 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 61 62 G4VPhysicalVolume* Par03DetectorConstruction::Construct() 63 { 64 //--------- Material definition --------- 65 G4NistManager* nistManager = G4NistManager::Instance(); 66 G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR"); 67 68 //--------- Derived dimensions --------- 69 G4double full2Pi = 2. * CLHEP::pi * rad; 70 G4double layerThickness = fDetectorLength / fNbOfLayers; 71 G4double cellPhi = full2Pi / fNbOfPhiCells; 72 G4double cellDR = fDetectorRadius / fNbOfRhoCells; 73 74 //--------- World --------- 75 auto fSolidWorld = new G4Box("World", // name 76 fWorldSize / 2., // half-width in X 77 fWorldSize / 2., // half-width in Y 78 fWorldSize / 2.); // half-width in Z 79 auto fLogicWorld = new G4LogicalVolume(fSolidWorld, // solid 80 air, // material 81 "World"); // name 82 auto fPhysicWorld = new G4PVPlacement(0, // no rotation 83 G4ThreeVector(), // at (0,0,0) 84 fLogicWorld, // logical volume 85 "World", // name 86 0, // mother volume 87 false, // not used 88 999, // copy number 89 true); // copy number 90 91 //--------- Detector envelope --------- 92 auto fSolidDetector = new G4Tubs("Detector", // name 93 0, // inner radius 94 fDetectorRadius, // outer radius 95 fDetectorLength / 2., // half-width in Z 96 0, // start angle 97 full2Pi); // delta angle 98 auto fLogicDetector = new G4LogicalVolume(fSolidDetector, // solid 99 fDetectorMaterial, // material 100 "Detector"); // name 101 new G4PVPlacement(0, // no rotation 102 G4ThreeVector(0, 0, 103 fDetectorLength / 2), // detector face starts at (0,0,0) 104 fLogicDetector, // logical volume 105 "Detector", // name 106 fLogicWorld, // mother volume 107 false, // not used 108 99, // copy number 109 true); // check overlaps 110 111 // Region for fast simulation 112 auto detectorRegion = new G4Region("DetectorRegion"); 113 detectorRegion->AddRootLogicalVolume(fLogicDetector); 114 115 //--------- Readout geometry --------- 116 // Layers (along z) 117 auto fSolidLayer = new G4Tubs("Layer", // name 118 0, // inner radius 119 fDetectorRadius, // outer radius 120 layerThickness / 2., // half-width in Z 121 0, // start angle 122 full2Pi); // delta angle 123 auto fLogicLayer = new G4LogicalVolume(fSolidLayer, // solid 124 air, // material 125 "Layer"); // name 126 if (fNbOfLayers > 1) 127 new G4PVReplica("Layer", // name 128 fLogicLayer, // logical volume 129 fLogicDetector, // mother volume 130 kZAxis, // axis of replication 131 fNbOfLayers, // number of replicas 132 layerThickness); // width of single replica 133 else 134 new G4PVPlacement(0, // no rotation 135 G4ThreeVector(), // place at centre of mother volume 136 fLogicLayer, // logical volume 137 "Layer", // name 138 fLogicDetector, // mother volume 139 false, // not used 140 0, // copy number 141 true); // check overlaps 142 143 // Layer segment (division in phi) 144 auto fSolidRow = new G4Tubs("Row", // name 145 0, // inner radius 146 fDetectorRadius, // outer radius 147 layerThickness / 2., // half-width in Z 148 0, // start angle 149 cellPhi); // delta angle 150 151 auto fLogicRow = new G4LogicalVolume(fSolidRow, // solid 152 air, // material 153 "Segment"); // name 154 if (fNbOfPhiCells > 1) 155 new G4PVReplica("Segment", // name 156 fLogicRow, // logical volume 157 fLogicLayer, // mother volume 158 kPhi, // axis of replication 159 fNbOfPhiCells, // number of replicas 160 cellPhi); // width of single replica 161 else 162 new G4PVPlacement(0, // no rotation 163 G4ThreeVector(), // place at centre of mother volume 164 fLogicRow, // logical volume 165 "Row", // name 166 fLogicLayer, // mother volume 167 false, // not used 168 0, // copy number 169 true); // check overlaps 170 171 // Final cells (segment slices in radius) 172 // No volume can be placed inside a radial replication 173 auto fSolidCell = new G4Tubs("Cell", // name 174 0, // inner radius 175 cellDR, // outer radius 176 layerThickness / 2., // half-width in Z 177 0, // start angle 178 cellPhi); // delta angle 179 180 fLogicCell = new G4LogicalVolume(fSolidCell, // solid 181 fDetectorMaterial, // material 182 "Cell"); // name 183 if (fNbOfRhoCells > 1) 184 new G4PVReplica("Cell", // name 185 fLogicCell, // logical volume 186 fLogicRow, // mother volume 187 kRho, // axis of replication 188 fNbOfRhoCells, // number of replicas 189 cellDR); // width of single replica 190 else 191 new G4PVPlacement(0, // no rotation 192 G4ThreeVector(), // place at centre of mother volume 193 fLogicCell, // logical volume 194 "Cell", // name 195 fLogicRow, // mother volume 196 false, // not used 197 0, // copy number 198 true); // check overlaps 199 200 //--------- Visualisation settings --------- 201 fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible()); 202 fLogicLayer->SetVisAttributes(G4VisAttributes::GetInvisible()); 203 fLogicRow->SetVisAttributes(G4VisAttributes::GetInvisible()); 204 G4VisAttributes attribs; 205 attribs.SetColour(G4Colour(0, 0, 1, 0.3)); 206 attribs.SetForceSolid(true); 207 fLogicCell->SetVisAttributes(attribs); 208 209 Print(); 210 return fPhysicWorld; 211 } 212 213 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 214 215 void Par03DetectorConstruction::ConstructSDandField() 216 { 217 Par03SensitiveDetector* caloSD = 218 new Par03SensitiveDetector("sensitiveDetector", fNbOfLayers, fNbOfPhiCells, fNbOfRhoCells); 219 G4SDManager::GetSDMpointer()->AddNewDetector(caloSD); 220 SetSensitiveDetector(fLogicCell, caloSD); 221 222 auto detectorRegion = G4RegionStore::GetInstance()->GetRegion("DetectorRegion"); 223 new Par03EMShowerModel("model", detectorRegion); 224 } 225 226 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 227 228 void Par03DetectorConstruction::Print() const 229 { 230 G4cout << "\n------------------------------------------------------" 231 << "\n--- Detector material:\t" << fDetectorMaterial->GetName() 232 << "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length") 233 << "\n--- Detector radius:\t" << G4BestUnit(fDetectorRadius, "Length") 234 << "\n--- Number of layers:\t" << fNbOfLayers << "\n--- Number of R-cells:\t" 235 << fNbOfRhoCells << "\n--- Number of phi-cells:\t" << fNbOfPhiCells << G4endl; 236 G4cout << "-----------------------------------------------------" << G4endl; 237 } 238 239 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 240 241 void Par03DetectorConstruction::SetMaterial(const G4String& aName) 242 { 243 // search material by its name 244 G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName); 245 if (material) 246 fDetectorMaterial = material; 247 else 248 G4Exception("Par03DetectorConstruction::SetMaterial()", "InvalidSetup", FatalException, 249 ("Unknown material name: " + aName).c_str()); 250 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 251 } 252 253 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 254 255 void Par03DetectorConstruction::SetRadius(G4double aRadius) 256 { 257 // check if fits within world volume 258 if (aRadius >= fWorldSize / 2.) 259 G4Exception("Par03DetectorConstruction::SetRadius()", "InvalidSetup", FatalException, 260 ("Detector radius cannot be larger than the world size (" 261 + G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")") 262 .c_str()); 263 fDetectorRadius = aRadius; 264 } 265 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 266 267 void Par03DetectorConstruction::SetLength(G4double aLength) 268 { 269 // check if fits within world volume 270 if (aLength >= fWorldSize / 2.) 271 G4Exception("Par03DetectorConstruction::SetLength()", "InvalidSetup", FatalException, 272 ("Detector length cannot be larger than the world size (" 273 + G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")") 274 .c_str()); 275 fDetectorLength = aLength; 276 }