File indexing completed on 2025-08-05 08:09:46
0001
0002
0003
0004
0005
0006
0007
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
0050 G4NistManager* nist = G4NistManager::Instance();
0051
0052
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
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
0066
0067 G4bool checkOverlaps = true;
0068
0069
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
0075
0076
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
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,
0094 G4ThreeVector(),
0095 logicWorld,
0096 "World Phys",
0097 nullptr,
0098 false,
0099 0,
0100 checkOverlaps);
0101
0102
0103
0104 G4Box* solidEnv =
0105 new G4Box("Envelope Solid",
0106 0.5 * envSizeX, 0.5 * envSizeY, 0.5 * envSizeZ);
0107
0108 G4LogicalVolume* logicEnv1 =
0109 new G4LogicalVolume(solidEnv,
0110 galactic,
0111 "Envelope #1 Logic");
0112
0113 G4VPhysicalVolume* physEnv1 =
0114 new G4PVPlacement(rotation,
0115 G4ThreeVector(),
0116 logicEnv1,
0117 "Envelope #1 Phys",
0118 logicWorld,
0119 false,
0120 0,
0121 checkOverlaps);
0122
0123
0124
0125 G4LogicalVolume* logicEnv2 =
0126 new G4LogicalVolume(solidEnv,
0127 galactic,
0128 "Envelope #2 Logic");
0129
0130 G4VPhysicalVolume* physEnv2 = new G4PVPlacement(
0131 nullptr,
0132 G4ThreeVector(m_cfg.offsets[0] * mm, m_cfg.offsets[1] * mm,
0133 center),
0134 "Envelope #2 Phys",
0135 logicEnv2,
0136 physEnv1,
0137 false,
0138 0,
0139 checkOverlaps);
0140
0141
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,
0148 silicon,
0149 "Layer Logic");
0150
0151 for (std::size_t i = 0; i < m_cfg.positions.size(); ++i) {
0152 new G4PVPlacement(
0153 nullptr,
0154 G4ThreeVector(0, 0, m_cfg.positions[i] * mm - center),
0155 "Layer #" + std::to_string(i) + " Phys",
0156 logicLayer,
0157 physEnv2,
0158 false,
0159 0,
0160 checkOverlaps);
0161 }
0162
0163
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 }