Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TelescopeG4DetectorConstruction.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TelescopeG4DetectorConstruction.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
14 
15 #include <algorithm>
16 #include <array>
17 #include <cstddef>
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include "G4Box.hh"
23 #include "G4Cons.hh"
24 #include "G4LogicalVolume.hh"
25 #include "G4NistManager.hh"
26 #include "G4Orb.hh"
27 #include "G4PVPlacement.hh"
28 #include "G4RunManager.hh"
29 #include "G4Sphere.hh"
30 #include "G4SystemOfUnits.hh"
31 #include "G4Trd.hh"
32 
35  : m_cfg(cfg) {
37  static_cast<int>(Telescope::TelescopeSurfaceType::Plane),
38  "only plan is supported right now");
39 }
40 
43  if (m_world != nullptr) {
44  return m_world;
45  }
46 
47  G4double center =
48  (m_cfg.positions.back() + m_cfg.positions.front()) * 0.5 * mm;
49  G4double length = (m_cfg.positions.back() - m_cfg.positions.front()) * mm;
50 
51  // Get nist material manager
52  G4NistManager* nist = G4NistManager::Instance();
53 
54  // World
55  //
56  G4double worldSize =
57  std::max({std::abs(m_cfg.offsets[0]) + m_cfg.bounds[0] * 0.5,
58  std::abs(m_cfg.offsets[1]) + m_cfg.bounds[1] * 0.5,
59  m_cfg.positions.back() + m_cfg.thickness});
60 
61  // Envelope parameters
62  //
63  G4double envSizeX = m_cfg.bounds[0] * mm;
64  G4double envSizeY = m_cfg.bounds[1] * mm;
65  G4double envSizeZ = length + m_cfg.thickness * mm;
66 
67  // Option to switch on/off checking of volumes overlaps
68  //
69  G4bool checkOverlaps = true;
70 
71  // Materials
72  G4Material* galactic = nist->FindOrBuildMaterial("G4_Galactic");
73  G4Material* silicon =
74  new G4Material("Silicon", 14, 28.0855 * g / mole, 2.329 * g / cm3);
75 
76  // Construct the rotation
77  // This assumes the binValue is binX, binY or binZ. No reset is necessary in
78  // case of binZ
79  G4RotationMatrix* rotation = nullptr;
80  if (static_cast<Acts::BinningValue>(m_cfg.binValue) ==
82  rotation = new G4RotationMatrix({0, 0, 1}, {0, 1, 0}, {-1, 0, 0});
83  } else if (static_cast<Acts::BinningValue>(m_cfg.binValue) ==
85  rotation = new G4RotationMatrix({1, 0, 0}, {0, 0, 1}, {0, -1, 0});
86  }
87 
88  // World
89  //
90  G4Box* solidWorld = new G4Box("World Solid", worldSize, worldSize, worldSize);
91 
92  G4LogicalVolume* logicWorld =
93  new G4LogicalVolume(solidWorld, galactic, "World Logic");
94 
95  m_world = new G4PVPlacement(nullptr, // no rotation
96  G4ThreeVector(), // position
97  logicWorld, // its logical volume
98  "World Phys", // its name
99  nullptr, // its mother volume
100  false, // no boolean operation
101  0, // copy number
102  checkOverlaps); // overlaps checking
103 
104  // Envelope 1
105  //
106  G4Box* solidEnv =
107  new G4Box("Envelope Solid", // its name
108  0.5 * envSizeX, 0.5 * envSizeY, 0.5 * envSizeZ); // its size
109 
110  G4LogicalVolume* logicEnv1 =
111  new G4LogicalVolume(solidEnv, // its solid
112  galactic, // its material
113  "Envelope #1 Logic"); // its name
114 
115  G4VPhysicalVolume* physEnv1 =
116  new G4PVPlacement(rotation, // rotation
117  G4ThreeVector(), // at detector center
118  logicEnv1, // its logical volume
119  "Envelope #1 Phys", // its name
120  logicWorld, // its mother volume
121  false, // no boolean operation
122  0, // copy number
123  checkOverlaps); // overlaps checking
124 
125  // Envelope 2
126  //
127  G4LogicalVolume* logicEnv2 =
128  new G4LogicalVolume(solidEnv, // its solid
129  galactic, // its material
130  "Envelope #2 Logic"); // its name
131 
132  G4VPhysicalVolume* physEnv2 = new G4PVPlacement(
133  nullptr, // no rotation
134  G4ThreeVector(m_cfg.offsets[0] * mm, m_cfg.offsets[1] * mm,
135  center), // at detector center
136  "Envelope #2 Phys", // its name
137  logicEnv2, // its logical volume
138  physEnv1, // its mother volume
139  false, // no boolean operation
140  0, // copy number
141  checkOverlaps); // overlaps checking
142 
143  // Layer
144  //
145 
146  G4Box* solidLayer = new G4Box("Layer Solid", 0.5 * m_cfg.bounds[0],
147  0.5 * m_cfg.bounds[1], 0.5 * m_cfg.thickness);
148 
149  G4LogicalVolume* logicLayer = new G4LogicalVolume(solidLayer, // its solid
150  silicon, // its material
151  "Layer Logic"); // its name
152 
153  for (std::size_t i = 0; i < m_cfg.positions.size(); ++i) {
154  new G4PVPlacement(
155  nullptr, // no rotation
156  G4ThreeVector(0, 0, m_cfg.positions[i] * mm - center), // at position
157  "Layer #" + std::to_string(i) + " Phys", // its name
158  logicLayer, // its logical volume
159  physEnv2, // its mother volume
160  false, // no boolean operation
161  0, // copy number
162  checkOverlaps); // overlaps checking
163  }
164 
165  return m_world;
166 }
167 
170  : m_cfg(cfg) {}
171 
172 std::unique_ptr<G4VUserDetectorConstruction>
174  const {
175  return std::make_unique<TelescopeG4DetectorConstruction>(m_cfg);
176 }