Project
Loading...
Searching...
No Matches
TRKLayer.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#include "Framework/Logger.h"
16
17#include <TGeoTube.h>
18#include <TGeoBBox.h>
19#include <TGeoVolume.h>
20
21#include <TMath.h>
22
23namespace o2
24{
25namespace trk
26{
27TRKLayer::TRKLayer(int layerNumber, std::string layerName, float rInn, float rOut, float zLength, float layerX2X0)
28 : mLayerNumber(layerNumber), mLayerName(layerName), mInnerRadius(rInn), mOuterRadius(rOut), mZ(zLength), mX2X0(layerX2X0), mModuleWidth(4.54), mLayout(kCylinder)
29{
30 float Si_X0 = 9.5f;
31 mChipThickness = mX2X0 * Si_X0;
32 LOGP(info, "Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}", mLayerNumber, mInnerRadius, mOuterRadius, mZ, mX2X0);
33}
34
35TRKLayer::TRKLayer(int layerNumber, std::string layerName, float rInn, float zLength, float thick)
36 : mLayerNumber(layerNumber), mLayerName(layerName), mInnerRadius(rInn), mZ(zLength), mChipThickness(thick), mModuleWidth(4.54), mLayout(kCylinder)
37{
38 float Si_X0 = 9.5f;
39 mOuterRadius = rInn + thick;
40 mX2X0 = mChipThickness / Si_X0;
41 LOGP(info, "Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}", mLayerNumber, mInnerRadius, mOuterRadius, mZ, mX2X0);
42}
43
44TGeoVolume* TRKLayer::createSensor(std::string type, double width)
45{
46 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
47 std::string sensName = Form("%s%d", GeometryTGeo::getTRKSensorPattern(), this->mLayerNumber);
48
49 TGeoShape* sensor;
50
51 if (type == "cylinder") {
52 sensor = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
53 } else if (type == "flat") {
54 if (width < 0) {
55 LOGP(fatal, "Attempting to create sensor with invalid width");
56 }
57 sensor = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
58 } else {
59 LOGP(fatal, "Sensor of type '{}' is not implemented", type);
60 }
61
62 TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
63 sensVol->SetLineColor(kYellow);
64
65 return sensVol;
66};
67
68TGeoVolume* TRKLayer::createChip(std::string type, double width)
69{
70 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
71 std::string chipName = o2::trk::GeometryTGeo::getTRKChipPattern() + std::to_string(mLayerNumber);
72
73 TGeoShape* chip;
74 TGeoVolume* sensVol;
75
76 if (type == "cylinder") {
77 chip = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
78 sensVol = createSensor("cylinder");
79 } else if (type == "flat") {
80 if (width < 0) {
81 LOGP(fatal, "Attempting to create chip with invalid width");
82 }
83 chip = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
84 sensVol = createSensor("flat", width);
85 } else {
86 LOGP(fatal, "Sensor of type '{}' is not implemented", type);
87 }
88
89 TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
90 LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
91 chipVol->AddNode(sensVol, 1, nullptr);
92 chipVol->SetLineColor(kYellow);
93
94 return chipVol;
95}
96
97TGeoVolume* TRKLayer::createStave(std::string type, double width)
98{
99 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
100 std::string staveName = o2::trk::GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber);
101
102 TGeoShape* stave;
103 TGeoVolume* staveVol;
104 TGeoVolume* chipVol;
105
106 if (type == "cylinder") {
107 stave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
108 chipVol = createChip("cylinder");
109 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
110 LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName());
111 staveVol->AddNode(chipVol, 1, nullptr);
112 } else if (type == "flat") {
113 if (width < 0) {
114 LOGP(fatal, "Attempting to create stave with invalid width");
115 }
116 stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
117 chipVol = createChip("flat", width);
118 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
119 LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName());
120 staveVol->AddNode(chipVol, 1, nullptr);
121 } else if (type == "staggered") {
122 double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design)
123 stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
124 TGeoVolume* chipVolLeft = createChip("flat", mModuleWidth);
125 TGeoVolume* chipVolRight = createChip("flat", mModuleWidth);
126 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
127
128 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
129 transLeft->SetTranslation(-mModuleWidth / 2 + 0.05, 0, 0); // 1mm overlap between the modules
130 LOGP(info, "Inserting {} in {} ", chipVolLeft->GetName(), staveVol->GetName());
131 staveVol->AddNode(chipVolLeft, 0, transLeft);
132
133 TGeoCombiTrans* transRight = new TGeoCombiTrans();
134 transRight->SetTranslation(mModuleWidth / 2 - 0.05, 0.2, 0);
135 LOGP(info, "Inserting {} in {} ", chipVolRight->GetName(), staveVol->GetName());
136 staveVol->AddNode(chipVolRight, 1, transRight);
137 } else {
138 LOGP(fatal, "Chip of type '{}' is not implemented", type);
139 }
140
141 staveVol->SetLineColor(kYellow);
142
143 return staveVol;
144}
145
146void TRKLayer::createLayer(TGeoVolume* motherVolume)
147{
148 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
149 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
150
151 std::string staveName = o2::trk::GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber),
152 chipName = o2::trk::GeometryTGeo::getTRKChipPattern() + std::to_string(mLayerNumber),
153 sensName = Form("%s%d", GeometryTGeo::getTRKSensorPattern(), mLayerNumber);
154
155 TGeoTube* layer = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
156
157 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
158 layerVol->SetLineColor(kYellow);
159
160 if (mLayout == eLayout::kCylinder) {
161 auto staveVol = createStave("cylinder");
162 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
163 layerVol->AddNode(staveVol, 1, nullptr);
164 } else if (mLayout == eLayout::kTurboStaves) {
165 // Compute the number of staves
166 double width = mModuleWidth; // Each stave has two modules (based on the LOI design)
167 if (mInnerRadius > 25) {
168 width *= 2; // Outer layers have two modules per stave
169 }
170
171 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width);
172 nStaves += nStaves % 2; // Require an even number of staves
173
174 // Compute the size of the overlap region
175 double theta = 2 * TMath::Pi() / nStaves;
176 double theta1 = std::atan(width / 2 / mInnerRadius);
177 double st = std::sin(theta);
178 double ct = std::cos(theta);
179 double theta2 = std::atan((mInnerRadius * st - width / 2 * ct) / (mInnerRadius * ct + width / 2 * st));
180 double overlap = (theta1 - theta2) * mInnerRadius;
181 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
182
183 for (int iStave = 0; iStave < nStaves; iStave++) {
184 TGeoVolume* staveVol = createStave("flat", width);
185
186 // Put the staves in the correct position and orientation
187 TGeoCombiTrans* trans = new TGeoCombiTrans();
188 double theta = 360. * iStave / nStaves;
189 TGeoRotation* rot = new TGeoRotation("rot", theta + 90 + 3, 0, 0);
190 trans->SetRotation(rot);
191 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
192
193 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
194 layerVol->AddNode(staveVol, iStave, trans);
195 }
196 } else if (mLayout == kStaggered) {
197 // Compute the number of staves
198 double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design)
199 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width);
200 nStaves += nStaves % 2; // Require an even number of staves
201
202 // Compute the size of the overlap region
203 double theta = 2 * TMath::Pi() / nStaves;
204 double theta1 = std::atan(width / 2 / mInnerRadius);
205 double st = std::sin(theta);
206 double ct = std::cos(theta);
207 double theta2 = std::atan((mInnerRadius * st - width / 2 * ct) / (mInnerRadius * ct + width / 2 * st));
208 double overlap = (theta1 - theta2) * mInnerRadius;
209 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
210
211 for (int iStave = 0; iStave < nStaves; iStave++) {
212 TGeoVolume* staveVol = createStave("staggered");
213
214 // Put the staves in the correct position and orientation
215 TGeoCombiTrans* trans = new TGeoCombiTrans();
216 double theta = 360. * iStave / nStaves;
217 TGeoRotation* rot = new TGeoRotation("rot", theta + 90, 0, 0);
218 trans->SetRotation(rot);
219 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
220
221 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
222 layerVol->AddNode(staveVol, iStave, trans);
223 }
224 } else {
225 LOGP(fatal, "Layout not implemented");
226 }
227 LOGP(info, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
228 motherVolume->AddNode(layerVol, 1, nullptr);
229}
230// ClassImp(TRKLayer);
231
232} // namespace trk
233} // namespace o2
benchmark::State & st
static const char * getTRKStavePattern()
static const char * getTRKChipPattern()
static const char * getTRKSensorPattern()
void createLayer(TGeoVolume *motherVolume)
Definition TRKLayer.cxx:146
TGeoVolume * createStave(std::string type, double width=-1)
Definition TRKLayer.cxx:97
TGeoVolume * createChip(std::string type, double width=-1)
Definition TRKLayer.cxx:68
TGeoVolume * createSensor(std::string type, double width=-1)
Definition TRKLayer.cxx:44
TRKLayer()=default
GLint GLsizei width
Definition glcorearb.h:270
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52