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, mLogicalVolumeThickness / 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 double layerThickness = mChipThickness;
156 if (mLayout != eLayout::kCylinder) {
157 layerThickness = mLogicalVolumeThickness;
158 }
159 TGeoTube* layer = new TGeoTube(mInnerRadius - 0.333 * layerThickness, mInnerRadius + 0.667 * layerThickness, mZ / 2);
160
161 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
162 layerVol->SetLineColor(kYellow);
163
164 if (mLayout == eLayout::kCylinder) {
165 auto staveVol = createStave("cylinder");
166 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
167 layerVol->AddNode(staveVol, 1, nullptr);
168 } else if (mLayout == eLayout::kTurboStaves) {
169 // Compute the number of staves
170 double width = mModuleWidth; // Each stave has two modules (based on the LOI design)
171 if (mInnerRadius > 25) {
172 width *= 2; // Outer layers have two modules per stave
173 }
174
175 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width);
176 nStaves += nStaves % 2; // Require an even number of staves
177
178 // Compute the size of the overlap region
179 double theta = 2 * TMath::Pi() / nStaves;
180 double theta1 = std::atan(width / 2 / mInnerRadius);
181 double st = std::sin(theta);
182 double ct = std::cos(theta);
183 double theta2 = std::atan((mInnerRadius * st - width / 2 * ct) / (mInnerRadius * ct + width / 2 * st));
184 double overlap = (theta1 - theta2) * mInnerRadius;
185 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
186
187 for (int iStave = 0; iStave < nStaves; iStave++) {
188 TGeoVolume* staveVol = createStave("flat", width);
189
190 // Put the staves in the correct position and orientation
191 TGeoCombiTrans* trans = new TGeoCombiTrans();
192 double theta = 360. * iStave / nStaves;
193 TGeoRotation* rot = new TGeoRotation("rot", theta + 90 + 3, 0, 0);
194 trans->SetRotation(rot);
195 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
196
197 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
198 layerVol->AddNode(staveVol, iStave, trans);
199 }
200 } else if (mLayout == kStaggered) {
201 // Compute the number of staves
202 double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design)
203 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width);
204 nStaves += nStaves % 2; // Require an even number of staves
205
206 // Compute the size of the overlap region
207 double theta = 2 * TMath::Pi() / nStaves;
208 double theta1 = std::atan(width / 2 / mInnerRadius);
209 double st = std::sin(theta);
210 double ct = std::cos(theta);
211 double theta2 = std::atan((mInnerRadius * st - width / 2 * ct) / (mInnerRadius * ct + width / 2 * st));
212 double overlap = (theta1 - theta2) * mInnerRadius;
213 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
214
215 for (int iStave = 0; iStave < nStaves; iStave++) {
216 TGeoVolume* staveVol = createStave("staggered");
217
218 // Put the staves in the correct position and orientation
219 TGeoCombiTrans* trans = new TGeoCombiTrans();
220 double theta = 360. * iStave / nStaves;
221 TGeoRotation* rot = new TGeoRotation("rot", theta + 90, 0, 0);
222 trans->SetRotation(rot);
223 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
224
225 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
226 layerVol->AddNode(staveVol, iStave, trans);
227 }
228 } else {
229 LOGP(fatal, "Layout not implemented");
230 }
231 LOGP(info, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
232 motherVolume->AddNode(layerVol, 1, nullptr);
233}
234// ClassImp(TRKLayer);
235
236} // namespace trk
237} // 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