Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:45

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp"
0010 
0011 #include "Acts/Utilities/ThrowAssert.hpp"
0012 #include "ActsExamples/Geant4/RegionCreator.hpp"
0013 #include "ActsExamples/TelescopeDetector/BuildTelescopeDetector.hpp"
0014 #include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp"
0015 
0016 #include "G4Box.hh"
0017 #include "G4LogicalVolume.hh"
0018 #include "G4NistManager.hh"
0019 #include "G4PVPlacement.hh"
0020 #include "G4RunManager.hh"
0021 #include "G4SystemOfUnits.hh"
0022 
0023 namespace ActsExamples {
0024 
0025 TelescopeG4DetectorConstruction::TelescopeG4DetectorConstruction(
0026     const TelescopeDetector::Config& cfg,
0027     const Geant4ConstructionOptions& options)
0028     : m_cfg(cfg), m_options(options) {
0029   throw_assert(cfg.surfaceType == static_cast<int>(TelescopeSurfaceType::Plane),
0030                "only plan is supported right now");
0031 }
0032 
0033 G4VPhysicalVolume* TelescopeG4DetectorConstruction::Construct() {
0034   if (m_world != nullptr) {
0035     return m_world;
0036   }
0037 
0038   G4double center =
0039       (m_cfg.positions.back() + m_cfg.positions.front()) * 0.5 * mm;
0040   G4double length = (m_cfg.positions.back() - m_cfg.positions.front()) * mm;
0041 
0042   // Get nist material manager
0043   G4NistManager* nist = G4NistManager::Instance();
0044 
0045   // World
0046   //
0047   G4double worldSize =
0048       std::max({std::abs(m_cfg.offsets[0]) + m_cfg.bounds[0] * 0.5,
0049                 std::abs(m_cfg.offsets[1]) + m_cfg.bounds[1] * 0.5,
0050                 m_cfg.positions.back() + m_cfg.thickness});
0051 
0052   // Envelope parameters
0053   //
0054   G4double envSizeX = m_cfg.bounds[0] * mm;
0055   G4double envSizeY = m_cfg.bounds[1] * mm;
0056   G4double envSizeZ = length + m_cfg.thickness * mm;
0057 
0058   // Option to switch on/off checking of volumes overlaps
0059   //
0060   G4bool checkOverlaps = true;
0061 
0062   // Materials
0063   G4Material* galactic = nist->FindOrBuildMaterial("G4_Galactic");
0064   G4Material* silicon =
0065       new G4Material("Silicon", 14, 28.0855 * g / mole, 2.329 * g / cm3);
0066 
0067   // Construct the rotation
0068   // This assumes the binValue is AxisDirection::AxisX, AxisDirection::AxisY or
0069   // AxisDirection::AxisZ. No reset is necessary in case of AxisDirection::AxisZ
0070   G4RotationMatrix* rotation = nullptr;
0071   if (static_cast<Acts::AxisDirection>(m_cfg.binValue) ==
0072       Acts::AxisDirection::AxisX) {
0073     rotation = new G4RotationMatrix({0, 0, 1}, {0, 1, 0}, {-1, 0, 0});
0074   } else if (static_cast<Acts::AxisDirection>(m_cfg.binValue) ==
0075              Acts::AxisDirection::AxisY) {
0076     rotation = new G4RotationMatrix({1, 0, 0}, {0, 0, 1}, {0, -1, 0});
0077   }
0078 
0079   // World
0080   //
0081   G4Box* solidWorld = new G4Box("World Solid", worldSize, worldSize, worldSize);
0082 
0083   G4LogicalVolume* logicWorld =
0084       new G4LogicalVolume(solidWorld, galactic, "World Logic");
0085 
0086   m_world = new G4PVPlacement(nullptr,          // no rotation
0087                               G4ThreeVector(),  // position
0088                               logicWorld,       // its logical volume
0089                               "World Phys",     // its name
0090                               nullptr,          // its mother volume
0091                               false,            // no boolean operation
0092                               0,                // copy number
0093                               checkOverlaps);   // overlaps checking
0094 
0095   // Envelope 1
0096   //
0097   G4Box* solidEnv =
0098       new G4Box("Envelope Solid",                                 // its name
0099                 0.5 * envSizeX, 0.5 * envSizeY, 0.5 * envSizeZ);  // its size
0100 
0101   G4LogicalVolume* logicEnv1 =
0102       new G4LogicalVolume(solidEnv,              // its solid
0103                           galactic,              // its material
0104                           "Envelope #1 Logic");  // its name
0105 
0106   G4VPhysicalVolume* physEnv1 =
0107       new G4PVPlacement(rotation,            // rotation
0108                         G4ThreeVector(),     // at detector center
0109                         logicEnv1,           // its logical volume
0110                         "Envelope #1 Phys",  // its name
0111                         logicWorld,          // its mother volume
0112                         false,               // no boolean operation
0113                         0,                   // copy number
0114                         checkOverlaps);      // overlaps checking
0115 
0116   // Envelope 2
0117   //
0118   G4LogicalVolume* logicEnv2 =
0119       new G4LogicalVolume(solidEnv,              // its solid
0120                           galactic,              // its material
0121                           "Envelope #2 Logic");  // its name
0122 
0123   G4VPhysicalVolume* physEnv2 = new G4PVPlacement(
0124       nullptr,  // no rotation
0125       G4ThreeVector(m_cfg.offsets[0] * mm, m_cfg.offsets[1] * mm,
0126                     center),  // at detector center
0127       "Envelope #2 Phys",     // its name
0128       logicEnv2,              // its logical volume
0129       physEnv1,               // its mother volume
0130       false,                  // no boolean operation
0131       0,                      // copy number
0132       checkOverlaps);         // overlaps checking
0133 
0134   // Layer
0135   //
0136 
0137   G4Box* solidLayer = new G4Box("Layer Solid", 0.5 * m_cfg.bounds[0],
0138                                 0.5 * m_cfg.bounds[1], 0.5 * m_cfg.thickness);
0139 
0140   G4LogicalVolume* logicLayer = new G4LogicalVolume(solidLayer,  // its solid
0141                                                     silicon,     // its material
0142                                                     "Layer Logic");  // its name
0143 
0144   for (std::size_t i = 0; i < m_cfg.positions.size(); ++i) {
0145     new G4PVPlacement(
0146         nullptr,                                                // no rotation
0147         G4ThreeVector(0, 0, m_cfg.positions[i] * mm - center),  // at position
0148         "Layer #" + std::to_string(i) + " Phys",                // its name
0149         logicLayer,      // its logical volume
0150         physEnv2,        // its mother volume
0151         false,           // no boolean operation
0152         0,               // copy number
0153         checkOverlaps);  // overlaps checking
0154   }
0155 
0156   // Create regions
0157   for (const auto& regionCreator : m_options.regionCreators) {
0158     regionCreator->buildRegion();
0159   }
0160 
0161   return m_world;
0162 }
0163 
0164 }  // namespace ActsExamples