File indexing completed on 2025-01-18 09:11:45
0001
0002
0003
0004
0005
0006
0007
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
0043 G4NistManager* nist = G4NistManager::Instance();
0044
0045
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
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
0059
0060 G4bool checkOverlaps = true;
0061
0062
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
0068
0069
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
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,
0087 G4ThreeVector(),
0088 logicWorld,
0089 "World Phys",
0090 nullptr,
0091 false,
0092 0,
0093 checkOverlaps);
0094
0095
0096
0097 G4Box* solidEnv =
0098 new G4Box("Envelope Solid",
0099 0.5 * envSizeX, 0.5 * envSizeY, 0.5 * envSizeZ);
0100
0101 G4LogicalVolume* logicEnv1 =
0102 new G4LogicalVolume(solidEnv,
0103 galactic,
0104 "Envelope #1 Logic");
0105
0106 G4VPhysicalVolume* physEnv1 =
0107 new G4PVPlacement(rotation,
0108 G4ThreeVector(),
0109 logicEnv1,
0110 "Envelope #1 Phys",
0111 logicWorld,
0112 false,
0113 0,
0114 checkOverlaps);
0115
0116
0117
0118 G4LogicalVolume* logicEnv2 =
0119 new G4LogicalVolume(solidEnv,
0120 galactic,
0121 "Envelope #2 Logic");
0122
0123 G4VPhysicalVolume* physEnv2 = new G4PVPlacement(
0124 nullptr,
0125 G4ThreeVector(m_cfg.offsets[0] * mm, m_cfg.offsets[1] * mm,
0126 center),
0127 "Envelope #2 Phys",
0128 logicEnv2,
0129 physEnv1,
0130 false,
0131 0,
0132 checkOverlaps);
0133
0134
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,
0141 silicon,
0142 "Layer Logic");
0143
0144 for (std::size_t i = 0; i < m_cfg.positions.size(); ++i) {
0145 new G4PVPlacement(
0146 nullptr,
0147 G4ThreeVector(0, 0, m_cfg.positions[i] * mm - center),
0148 "Layer #" + std::to_string(i) + " Phys",
0149 logicLayer,
0150 physEnv2,
0151 false,
0152 0,
0153 checkOverlaps);
0154 }
0155
0156
0157 for (const auto& regionCreator : m_options.regionCreators) {
0158 regionCreator->buildRegion();
0159 }
0160
0161 return m_world;
0162 }
0163
0164 }