Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:46

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2022-2024 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #include "ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp"
0010 
0011 #include "Acts/Utilities/BinningType.hpp"
0012 #include "Acts/Utilities/ThrowAssert.hpp"
0013 #include "ActsExamples/TelescopeDetector/BuildTelescopeDetector.hpp"
0014 
0015 #include <algorithm>
0016 #include <array>
0017 #include <cstddef>
0018 #include <memory>
0019 #include <string>
0020 #include <vector>
0021 
0022 #include "G4Box.hh"
0023 #include "G4LogicalVolume.hh"
0024 #include "G4NistManager.hh"
0025 #include "G4PVPlacement.hh"
0026 #include "G4RunManager.hh"
0027 #include "G4SystemOfUnits.hh"
0028 
0029 ActsExamples::Telescope::TelescopeG4DetectorConstruction::
0030     TelescopeG4DetectorConstruction(
0031         const TelescopeDetector::Config& cfg,
0032         std::vector<std::shared_ptr<RegionCreator>> regionCreators)
0033     : m_cfg(cfg), m_regionCreators(std::move(regionCreators)) {
0034   throw_assert(cfg.surfaceType ==
0035                    static_cast<int>(Telescope::TelescopeSurfaceType::Plane),
0036                "only plan is supported right now");
0037 }
0038 
0039 G4VPhysicalVolume*
0040 ActsExamples::Telescope::TelescopeG4DetectorConstruction::Construct() {
0041   if (m_world != nullptr) {
0042     return m_world;
0043   }
0044 
0045   G4double center =
0046       (m_cfg.positions.back() + m_cfg.positions.front()) * 0.5 * mm;
0047   G4double length = (m_cfg.positions.back() - m_cfg.positions.front()) * mm;
0048 
0049   // Get nist material manager
0050   G4NistManager* nist = G4NistManager::Instance();
0051 
0052   // World
0053   //
0054   G4double worldSize =
0055       std::max({std::abs(m_cfg.offsets[0]) + m_cfg.bounds[0] * 0.5,
0056                 std::abs(m_cfg.offsets[1]) + m_cfg.bounds[1] * 0.5,
0057                 m_cfg.positions.back() + m_cfg.thickness});
0058 
0059   // Envelope parameters
0060   //
0061   G4double envSizeX = m_cfg.bounds[0] * mm;
0062   G4double envSizeY = m_cfg.bounds[1] * mm;
0063   G4double envSizeZ = length + m_cfg.thickness * mm;
0064 
0065   // Option to switch on/off checking of volumes overlaps
0066   //
0067   G4bool checkOverlaps = true;
0068 
0069   // Materials
0070   G4Material* galactic = nist->FindOrBuildMaterial("G4_Galactic");
0071   G4Material* silicon =
0072       new G4Material("Silicon", 14, 28.0855 * g / mole, 2.329 * g / cm3);
0073 
0074   // Construct the rotation
0075   // This assumes the binValue is binX, binY or binZ. No reset is necessary in
0076   // case of binZ
0077   G4RotationMatrix* rotation = nullptr;
0078   if (static_cast<Acts::BinningValue>(m_cfg.binValue) ==
0079       Acts::BinningValue::binX) {
0080     rotation = new G4RotationMatrix({0, 0, 1}, {0, 1, 0}, {-1, 0, 0});
0081   } else if (static_cast<Acts::BinningValue>(m_cfg.binValue) ==
0082              Acts::BinningValue::binY) {
0083     rotation = new G4RotationMatrix({1, 0, 0}, {0, 0, 1}, {0, -1, 0});
0084   }
0085 
0086   // World
0087   //
0088   G4Box* solidWorld = new G4Box("World Solid", worldSize, worldSize, worldSize);
0089 
0090   G4LogicalVolume* logicWorld =
0091       new G4LogicalVolume(solidWorld, galactic, "World Logic");
0092 
0093   m_world = new G4PVPlacement(nullptr,          // no rotation
0094                               G4ThreeVector(),  // position
0095                               logicWorld,       // its logical volume
0096                               "World Phys",     // its name
0097                               nullptr,          // its mother volume
0098                               false,            // no boolean operation
0099                               0,                // copy number
0100                               checkOverlaps);   // overlaps checking
0101 
0102   // Envelope 1
0103   //
0104   G4Box* solidEnv =
0105       new G4Box("Envelope Solid",                                 // its name
0106                 0.5 * envSizeX, 0.5 * envSizeY, 0.5 * envSizeZ);  // its size
0107 
0108   G4LogicalVolume* logicEnv1 =
0109       new G4LogicalVolume(solidEnv,              // its solid
0110                           galactic,              // its material
0111                           "Envelope #1 Logic");  // its name
0112 
0113   G4VPhysicalVolume* physEnv1 =
0114       new G4PVPlacement(rotation,            // rotation
0115                         G4ThreeVector(),     // at detector center
0116                         logicEnv1,           // its logical volume
0117                         "Envelope #1 Phys",  // its name
0118                         logicWorld,          // its mother volume
0119                         false,               // no boolean operation
0120                         0,                   // copy number
0121                         checkOverlaps);      // overlaps checking
0122 
0123   // Envelope 2
0124   //
0125   G4LogicalVolume* logicEnv2 =
0126       new G4LogicalVolume(solidEnv,              // its solid
0127                           galactic,              // its material
0128                           "Envelope #2 Logic");  // its name
0129 
0130   G4VPhysicalVolume* physEnv2 = new G4PVPlacement(
0131       nullptr,  // no rotation
0132       G4ThreeVector(m_cfg.offsets[0] * mm, m_cfg.offsets[1] * mm,
0133                     center),  // at detector center
0134       "Envelope #2 Phys",     // its name
0135       logicEnv2,              // its logical volume
0136       physEnv1,               // its mother volume
0137       false,                  // no boolean operation
0138       0,                      // copy number
0139       checkOverlaps);         // overlaps checking
0140 
0141   // Layer
0142   //
0143 
0144   G4Box* solidLayer = new G4Box("Layer Solid", 0.5 * m_cfg.bounds[0],
0145                                 0.5 * m_cfg.bounds[1], 0.5 * m_cfg.thickness);
0146 
0147   G4LogicalVolume* logicLayer = new G4LogicalVolume(solidLayer,  // its solid
0148                                                     silicon,     // its material
0149                                                     "Layer Logic");  // its name
0150 
0151   for (std::size_t i = 0; i < m_cfg.positions.size(); ++i) {
0152     new G4PVPlacement(
0153         nullptr,                                                // no rotation
0154         G4ThreeVector(0, 0, m_cfg.positions[i] * mm - center),  // at position
0155         "Layer #" + std::to_string(i) + " Phys",                // its name
0156         logicLayer,      // its logical volume
0157         physEnv2,        // its mother volume
0158         false,           // no boolean operation
0159         0,               // copy number
0160         checkOverlaps);  // overlaps checking
0161   }
0162 
0163   // Create regions
0164   for (const auto& regionCreator : m_regionCreators) {
0165     regionCreator->Construct();
0166   }
0167 
0168   return m_world;
0169 }
0170 
0171 ActsExamples::Telescope::TelescopeG4DetectorConstructionFactory::
0172     TelescopeG4DetectorConstructionFactory(
0173         const TelescopeDetector::Config& cfg,
0174         std::vector<std::shared_ptr<RegionCreator>> regionCreators)
0175     : m_cfg(cfg), m_regionCreators(std::move(regionCreators)) {}
0176 
0177 std::unique_ptr<G4VUserDetectorConstruction>
0178 ActsExamples::Telescope::TelescopeG4DetectorConstructionFactory::factorize()
0179     const {
0180   return std::make_unique<TelescopeG4DetectorConstruction>(m_cfg,
0181                                                            m_regionCreators);
0182 }