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#include "TRKBase/Specs.h"
15
16#include "Framework/Logger.h"
17
18#include <TGeoTube.h>
19#include <TGeoBBox.h>
20#include <TGeoVolume.h>
21
22#include <TMath.h>
23
24namespace o2
25{
26namespace trk
27{
28TRKLayer::TRKLayer(int layerNumber, std::string layerName, float rInn, float rOut, int numberOfModules, float layerX2X0)
29 : mLayerNumber(layerNumber), mLayout(kCylinder), mLayerName(layerName), mInnerRadius(rInn), mOuterRadius(rOut), mNumberOfModules(numberOfModules), mX2X0(layerX2X0), mChipWidth(constants::moduleMLOT::chip::width), mChipLength(constants::moduleMLOT::chip::length), mDeadzoneWidth(constants::moduleMLOT::chip::passiveEdgeReadOut), mSensorThickness(constants::moduleMLOT::silicon::thickness), mHalfNumberOfChips(4)
30{
31 float Si_X0 = 9.5f;
32 mChipThickness = mX2X0 * Si_X0;
33 LOGP(info, "Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}", mLayerNumber, mInnerRadius, mOuterRadius, getZ(), mX2X0);
34}
35
36TRKLayer::TRKLayer(int layerNumber, std::string layerName, float rInn, int numberOfModules, float thick)
37 : mLayerNumber(layerNumber), mLayout(kCylinder), mLayerName(layerName), mInnerRadius(rInn), mNumberOfModules(numberOfModules), mChipThickness(thick), mChipWidth(constants::moduleMLOT::chip::width), mChipLength(constants::moduleMLOT::chip::length), mDeadzoneWidth(constants::moduleMLOT::chip::passiveEdgeReadOut), mSensorThickness(constants::moduleMLOT::silicon::thickness), mHalfNumberOfChips(4)
38{
39 float Si_X0 = 9.5f;
40 mOuterRadius = rInn + thick;
41 mX2X0 = mChipThickness / Si_X0;
42 LOGP(info, "Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}", mLayerNumber, mInnerRadius, mOuterRadius, getZ(), mX2X0);
43}
44
45TGeoVolume* TRKLayer::createSensor(std::string type)
46{
47 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
48 std::string sensName = GeometryTGeo::getTRKSensorPattern() + std::to_string(mLayerNumber);
49
50 TGeoShape* sensor;
51
52 if (type == "cylinder") {
53 sensor = new TGeoTube(mInnerRadius, mInnerRadius + mSensorThickness, (constants::moduleMLOT::length * mNumberOfModules) / 2); // TO BE CHECKED !!!
54 } else if (type == "flat") {
55 sensor = new TGeoBBox((mChipWidth - mDeadzoneWidth) / 2, mSensorThickness / 2, mChipLength / 2); // TO BE CHECKED !!!
56 } else {
57 LOGP(fatal, "Sensor of type '{}' is not implemented", type);
58 }
59
60 TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
61 sensVol->SetLineColor(kYellow);
62
63 return sensVol;
64};
65
66TGeoVolume* TRKLayer::createDeadzone(std::string type)
67{
68 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
69 std::string deadName = GeometryTGeo::getTRKDeadzonePattern() + std::to_string(mLayerNumber);
70
71 TGeoShape* deadzone;
72
73 if (type == "cylinder") {
74 deadzone = new TGeoTube(mInnerRadius, mInnerRadius + mSensorThickness, 0); // TO BE CHECKED !!!
75 } else if (type == "flat") {
76 deadzone = new TGeoBBox(mDeadzoneWidth / 2, mSensorThickness / 2, mChipLength / 2); // TO BE CHECKED !!!
77 } else {
78 LOGP(fatal, "Deadzone of type '{}' is not implemented", type);
79 }
80
81 TGeoVolume* deadVol = new TGeoVolume(deadName.c_str(), deadzone, medSi);
82 deadVol->SetLineColor(kGray);
83
84 return deadVol;
85};
86
87TGeoVolume* TRKLayer::createMetalStack(std::string type)
88{
89 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
90 std::string metalName = GeometryTGeo::getTRKMetalStackPattern() + std::to_string(mLayerNumber);
91
92 TGeoShape* metalStack;
93
94 if (type == "cylinder") {
95 metalStack = new TGeoTube(mInnerRadius + mSensorThickness, mInnerRadius + mChipThickness, (constants::moduleMLOT::length * mNumberOfModules) / 2); // TO BE CHECKED !!!
96 } else if (type == "flat") {
97 metalStack = new TGeoBBox(mChipWidth / 2, (mChipThickness - mSensorThickness) / 2, mChipLength / 2); // TO BE CHECKED !!!
98 } else {
99 LOGP(fatal, "Metal stack of type '{}' is not implemented", type);
100 }
101
102 TGeoVolume* metalVol = new TGeoVolume(metalName.c_str(), metalStack, medSi);
103 metalVol->SetLineColor(kGray);
104
105 return metalVol;
106};
107
108TGeoVolume* TRKLayer::createChip(std::string type)
109{
110 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
111 std::string chipName = GeometryTGeo::getTRKChipPattern() + std::to_string(mLayerNumber);
112
113 TGeoShape* chip;
114 TGeoVolume* chipVol;
115
116 TGeoVolume* sensVol;
117 TGeoVolume* deadVol;
118 TGeoVolume* metalVol;
119
120 if (type == "cylinder") {
121 chip = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, (constants::moduleMLOT::length * mNumberOfModules) / 2);
122 chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
123
124 sensVol = createSensor("cylinder");
125 LOGP(debug, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
126 chipVol->AddNode(sensVol, 1, nullptr);
127
128 metalVol = createMetalStack("cylinder");
129 LOGP(debug, "Inserting {} in {} ", metalVol->GetName(), chipVol->GetName());
130 chipVol->AddNode(metalVol, 1, nullptr);
131
132 // deadVol = createDeadzone("cylinder");
133 } else if (type == "flat") {
134 chip = new TGeoBBox(mChipWidth / 2, mChipThickness / 2, mChipLength / 2); // TO BE CHECKED !!!
135 chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
136
137 sensVol = createSensor("flat");
138 deadVol = createDeadzone("flat");
139 metalVol = createMetalStack("flat");
140
141 TGeoCombiTrans* transSens = new TGeoCombiTrans();
142 transSens->SetTranslation(-mDeadzoneWidth / 2, -(mChipThickness - mSensorThickness) / 2, 0); // TO BE CHECKED !!!
143 LOGP(debug, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
144 chipVol->AddNode(sensVol, 1, transSens);
145
146 TGeoCombiTrans* transDead = new TGeoCombiTrans();
147 transDead->SetTranslation((mChipWidth - mDeadzoneWidth) / 2, -(mChipThickness - mSensorThickness) / 2, 0); // TO BE CHECKED !!!
148 LOGP(debug, "Inserting {} in {} ", deadVol->GetName(), chipVol->GetName());
149 chipVol->AddNode(deadVol, 1, transDead);
150
151 TGeoCombiTrans* transMetal = new TGeoCombiTrans();
152 transMetal->SetTranslation(0, mSensorThickness / 2, 0); // TO BE CHECKED !!!
153 LOGP(debug, "Inserting {} in {} ", metalVol->GetName(), chipVol->GetName());
154 chipVol->AddNode(metalVol, 1, transMetal);
155 } else {
156 LOGP(fatal, "Sensor of type '{}' is not implemented", type);
157 }
158
159 chipVol->SetLineColor(kYellow);
160
161 return chipVol;
162}
163
164TGeoVolume* TRKLayer::createModule(std::string type)
165{
166 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
167 std::string moduleName = GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber);
168
169 TGeoShape* module;
170 TGeoVolume* moduleVol;
171
172 if (type == "cylinder") {
173 double moduleLength = constants::moduleMLOT::length * mNumberOfModules;
174
175 module = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, moduleLength / 2);
176 moduleVol = new TGeoVolume(moduleName.c_str(), module, medSi);
177
178 TGeoVolume* chipVol = createChip("cylinder");
179 LOGP(debug, "Inserting {} in {} ", chipVol->GetName(), moduleVol->GetName());
180 moduleVol->AddNode(chipVol, 1, nullptr);
181 } else if (type == "flat") {
182 double moduleWidth = constants::moduleMLOT::width;
183 double moduleLength = constants::moduleMLOT::length;
184
185 module = new TGeoBBox(moduleWidth / 2, mChipThickness / 2, moduleLength / 2); // TO BE CHECKED !!!
186 moduleVol = new TGeoVolume(moduleName.c_str(), module, medSi);
187
188 for (int iChip = 0; iChip < mHalfNumberOfChips; iChip++) {
189 TGeoVolume* chipVolLeft = createChip("flat");
190 TGeoVolume* chipVolRight = createChip("flat");
191
192 // Put the chips in the correct position
195
196 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
197 transLeft->SetTranslation(xLeft, 0, zLeft); // TO BE CHECKED !!!
198 TGeoRotation* rot = new TGeoRotation();
199 rot->RotateY(180);
200 transLeft->SetRotation(rot);
201 LOGP(debug, "Inserting {} in {} ", chipVolLeft->GetName(), moduleVol->GetName());
202 moduleVol->AddNode(chipVolLeft, iChip * 2, transLeft);
203
206
207 TGeoCombiTrans* transRight = new TGeoCombiTrans();
208 transRight->SetTranslation(xRight, 0, zRight); // TO BE CHECKED !!!
209 LOGP(debug, "Inserting {} in {} ", chipVolRight->GetName(), moduleVol->GetName());
210 moduleVol->AddNode(chipVolRight, iChip * 2 + 1, transRight);
211 }
212 } else {
213 LOGP(fatal, "Chip of type '{}' is not implemented", type);
214 }
215
216 moduleVol->SetLineColor(kYellow);
217
218 return moduleVol;
219}
220
221TGeoVolume* TRKLayer::createHalfStave(std::string type)
222{
223 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
224 std::string halfStaveName = GeometryTGeo::getTRKHalfStavePattern() + std::to_string(mLayerNumber);
225
226 TGeoShape* halfStave;
227 TGeoVolume* halfStaveVol;
228
229 double halfStaveLength = constants::moduleMLOT::length * mNumberOfModules;
230
231 if (type == "cylinder") {
232 halfStave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, halfStaveLength / 2);
233 halfStaveVol = new TGeoVolume(halfStaveName.c_str(), halfStave, medSi);
234
235 TGeoVolume* moduleVol = createModule("cylinder");
236 LOGP(debug, "Inserting {} in {} ", moduleVol->GetName(), halfStaveVol->GetName());
237 halfStaveVol->AddNode(moduleVol, 1, nullptr);
238 } else if (type == "flat") {
239 double moduleLength = constants::moduleMLOT::length;
240 double halfStaveWidth = constants::OT::halfstave::width;
241
242 halfStave = new TGeoBBox(halfStaveWidth / 2, mChipThickness / 2, halfStaveLength / 2);
243 halfStaveVol = new TGeoVolume(halfStaveName.c_str(), halfStave, medSi);
244
245 for (int iModule = 0; iModule < mNumberOfModules; iModule++) {
246 TGeoVolume* moduleVol = createModule("flat");
247
248 // Put the modules in the correct position
249 double zPos = -0.5 * mNumberOfModules * moduleLength + (iModule + 0.5) * moduleLength;
250
251 TGeoCombiTrans* trans = new TGeoCombiTrans();
252 trans->SetTranslation(0, 0, zPos); // TO BE CHECKED !!!
253
254 LOGP(debug, "Inserting {} in {} ", moduleVol->GetName(), halfStaveVol->GetName());
255 halfStaveVol->AddNode(moduleVol, iModule, trans);
256 }
257 }
258
259 halfStaveVol->SetLineColor(kYellow);
260
261 return halfStaveVol;
262}
263
264TGeoVolume* TRKLayer::createStave(std::string type)
265{
266 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
267 std::string staveName = GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber);
268
269 TGeoShape* stave;
270 TGeoVolume* staveVol;
271
272 double staveLength = constants::moduleMLOT::length * mNumberOfModules;
273
274 if (type == "cylinder") {
275 stave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, staveLength / 2);
276 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
277
278 TGeoVolume* moduleVol = createModule("cylinder");
279 LOGP(debug, "Inserting {} in {} ", moduleVol->GetName(), staveVol->GetName());
280 staveVol->AddNode(moduleVol, 1, nullptr);
281 } else if (type == "flat") {
282 double moduleLength = constants::moduleMLOT::length;
283 double staveWidth = constants::ML::width;
284
285 stave = new TGeoBBox(staveWidth / 2, mChipThickness / 2, staveLength / 2);
286 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
287
288 for (int iModule = 0; iModule < mNumberOfModules; iModule++) {
289 TGeoVolume* moduleVol = createModule("flat");
290
291 // Put the modules in the correct position
292 double zPos = -0.5 * mNumberOfModules * moduleLength + (iModule + 0.5) * moduleLength;
293
294 TGeoCombiTrans* trans = new TGeoCombiTrans();
295 trans->SetTranslation(0, 0, zPos); // TO BE CHECKED !!!
296
297 LOGP(debug, "Inserting {} in {} ", moduleVol->GetName(), staveVol->GetName());
298 staveVol->AddNode(moduleVol, iModule, trans);
299 }
300 } else if (type == "staggered") {
301 double overlap = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut + 0.1; // 1.5mm outer-edge + 1mm deadzone + 1mm (true)overlap
302 double shift = overlap / 2;
303
304 double halfstaveWidth = constants::OT::halfstave::width;
305 double staveWidth = constants::OT::width - overlap;
306
307 stave = new TGeoBBox(staveWidth / 2, mLogicalVolumeThickness / 2, staveLength / 2);
308 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
309
310 // Put the half staves in the correct position
311 TGeoVolume* halfStaveVolLeft = createHalfStave("flat");
312 TGeoVolume* halfStaveVolRight = createHalfStave("flat");
313
314 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
315 transLeft->SetTranslation(-halfstaveWidth / 2 + shift, 0, 0); // TO BE CHECKED !!! 1mm overlap between the modules
316 LOGP(debug, "Inserting {} in {} ", halfStaveVolLeft->GetName(), staveVol->GetName());
317 staveVol->AddNode(halfStaveVolLeft, 0, transLeft);
318
319 TGeoCombiTrans* transRight = new TGeoCombiTrans();
320 transRight->SetTranslation(halfstaveWidth / 2 - shift, 0.2, 0); // TO BE CHECKED !!! 1mm overlap between the modules
321 LOGP(debug, "Inserting {} in {} ", halfStaveVolRight->GetName(), staveVol->GetName());
322 staveVol->AddNode(halfStaveVolRight, 1, transRight);
323 } else {
324 LOGP(fatal, "Chip of type '{}' is not implemented", type);
325 }
326
327 staveVol->SetLineColor(kYellow);
328
329 return staveVol;
330}
331
332void TRKLayer::createLayer(TGeoVolume* motherVolume)
333{
334 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
335
336 double layerThickness = mChipThickness;
337 if (mLayout != eLayout::kCylinder) {
338 layerThickness = mLogicalVolumeThickness;
339 }
340
341 TGeoTube* layer;
342 TGeoVolume* layerVol;
343
344 double layerLength = constants::moduleMLOT::length * mNumberOfModules;
345
346 if (mLayout == eLayout::kCylinder) {
347 layer = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, layerLength / 2);
348 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
349
350 TGeoVolume* staveVol = createStave("cylinder");
351 LOGP(debug, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
352 layerVol->AddNode(staveVol, 1, nullptr);
353 } else if (mLayout == eLayout::kTurboStaves) {
354 double staveWidth = constants::ML::width; // Each stave has two modules (based on the LOI design)
355
356 if (mInnerRadius > 25) {
357 staveWidth = constants::OT::width; // Outer layers have two modules per stave
358 }
359
360 layer = new TGeoTube(mInnerRadius - 0.333 * layerThickness, mInnerRadius + 0.667 * layerThickness, layerLength / 2);
361 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
362
363 // Compute the number of staves
364 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / staveWidth);
365 nStaves += nStaves % 2; // Require an even number of staves
366
367 // Compute the size of the overlap region
368 double theta = 2 * TMath::Pi() / nStaves;
369 double theta1 = std::atan(staveWidth / 2 / mInnerRadius);
370 double st = std::sin(theta);
371 double ct = std::cos(theta);
372 double theta2 = std::atan((mInnerRadius * st - staveWidth / 2 * ct) / (mInnerRadius * ct + staveWidth / 2 * st));
373 double overlap = (theta1 - theta2) * mInnerRadius;
374 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
375
376 for (int iStave = 0; iStave < nStaves; iStave++) {
377 TGeoVolume* staveVol = createStave("flat");
378
379 // Put the staves in the correct position and orientation
380 TGeoCombiTrans* trans = new TGeoCombiTrans();
381 double theta = 360. * iStave / nStaves;
382 TGeoRotation* rot = new TGeoRotation("rot", theta - 90 + 3, 0, 0);
383 trans->SetRotation(rot);
384 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
385
386 LOGP(debug, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
387 layerVol->AddNode(staveVol, iStave, trans);
388 }
389 } else if (mLayout == kStaggered) {
390 double overlapInStave = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut + 0.1; // 1.5mm outer-edge + 1mm deadzone + 1mm (true)overlap
391
392 double staveWidth = constants::OT::width - overlapInStave;
393
394 layer = new TGeoTube(mInnerRadius - 0.333 * layerThickness, mInnerRadius + 0.667 * layerThickness, layerLength / 2);
395 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
396
397 // Compute the number of staves
398 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / staveWidth);
399 nStaves += nStaves % 2; // Require an even number of staves
400
401 // Compute the size of the overlap region
402 double theta = 2 * TMath::Pi() / nStaves;
403 double theta1 = std::atan(staveWidth / 2 / mInnerRadius);
404 double st = std::sin(theta);
405 double ct = std::cos(theta);
406 double theta2 = std::atan((mInnerRadius * st - staveWidth / 2 * ct) / (mInnerRadius * ct + staveWidth / 2 * st));
407 double overlap = (theta1 - theta2) * mInnerRadius;
408 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
409
410 for (int iStave = 0; iStave < nStaves; iStave++) {
411 TGeoVolume* staveVol = createStave("staggered");
412
413 // Put the staves in the correct position and orientation
414 TGeoCombiTrans* trans = new TGeoCombiTrans();
415 double theta = 360. * iStave / nStaves;
416 TGeoRotation* rot = new TGeoRotation("rot", theta - 90 + 3, 0, 0);
417 trans->SetRotation(rot);
418 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
419
420 LOGP(debug, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
421 layerVol->AddNode(staveVol, iStave, trans);
422 }
423 } else {
424 LOGP(fatal, "Layout not implemented");
425 }
426 layerVol->SetLineColor(kYellow);
427
428 LOGP(debug, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
429 motherVolume->AddNode(layerVol, 1, nullptr);
430}
431// ClassImp(TRKLayer);
432
433} // namespace trk
434} // namespace o2
std::ostringstream debug
specs of the ALICE3 TRK
benchmark::State & st
static const char * getTRKStavePattern()
static const char * getTRKChipPattern()
static const char * getTRKSensorPattern()
static const char * getTRKDeadzonePattern()
static const char * getTRKHalfStavePattern()
static const char * getTRKMetalStackPattern()
static const char * getTRKModulePattern()
void createLayer(TGeoVolume *motherVolume)
Definition TRKLayer.cxx:332
auto getZ() const
Definition TRKLayer.h:37
TGeoVolume * createMetalStack(std::string type)
Definition TRKLayer.cxx:87
TGeoVolume * createSensor(std::string type)
Definition TRKLayer.cxx:45
TGeoVolume * createChip(std::string type)
Definition TRKLayer.cxx:108
TGeoVolume * createStave(std::string type)
Definition TRKLayer.cxx:264
TGeoVolume * createHalfStave(std::string type)
Definition TRKLayer.cxx:221
TGeoVolume * createDeadzone(std::string type)
Definition TRKLayer.cxx:66
TRKLayer()=default
TGeoVolume * createModule(std::string type)
Definition TRKLayer.cxx:164
GLint GLsizei width
Definition glcorearb.h:270
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
constexpr double width
Definition Specs.h:103
constexpr double width
Definition Specs.h:120
constexpr double outerEdgeLongSide
Definition Specs.h:92
constexpr double outerEdgeShortSide
Definition Specs.h:93
constexpr double length
Definition Specs.h:96
constexpr double width
Definition Specs.h:95
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