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, mChipLength / 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, mChipLength / 2); // 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, mChipLength / 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, mChipLength / 2);
122 chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
123
124 sensVol = createSensor("cylinder");
125 metalVol = createMetalStack("cylinder");
126
127 TGeoCombiTrans* transSens = new TGeoCombiTrans();
128 transSens->SetTranslation(0, -(mChipThickness - mSensorThickness) / 2, 0); // TO BE CHECKED !!!
129 LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
130 chipVol->AddNode(sensVol, 1, transSens);
131
132 TGeoCombiTrans* transMetal = new TGeoCombiTrans();
133 transMetal->SetTranslation(0, mSensorThickness / 2, 0); // TO BE CHECKED !!!
134 LOGP(info, "Inserting {} in {} ", metalVol->GetName(), chipVol->GetName());
135 chipVol->AddNode(metalVol, 1, transMetal);
136
137 // deadVol = createDeadzone("cylinder");
138 } else if (type == "flat") {
139 chip = new TGeoBBox(mChipWidth / 2, mChipThickness / 2, mChipLength / 2); // TO BE CHECKED !!!
140 chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
141
142 sensVol = createSensor("flat");
143 deadVol = createDeadzone("flat");
144 metalVol = createMetalStack("flat");
145
146 TGeoCombiTrans* transSens = new TGeoCombiTrans();
147 transSens->SetTranslation(-mDeadzoneWidth / 2, -(mChipThickness - mSensorThickness) / 2, 0); // TO BE CHECKED !!!
148 LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
149 chipVol->AddNode(sensVol, 1, transSens);
150
151 TGeoCombiTrans* transDead = new TGeoCombiTrans();
152 transDead->SetTranslation((mChipWidth - mDeadzoneWidth) / 2, -(mChipThickness - mSensorThickness) / 2, 0); // TO BE CHECKED !!!
153 LOGP(info, "Inserting {} in {} ", deadVol->GetName(), chipVol->GetName());
154 chipVol->AddNode(deadVol, 1, transDead);
155
156 TGeoCombiTrans* transMetal = new TGeoCombiTrans();
157 transMetal->SetTranslation(0, mSensorThickness / 2, 0); // TO BE CHECKED !!!
158 LOGP(info, "Inserting {} in {} ", metalVol->GetName(), chipVol->GetName());
159 chipVol->AddNode(metalVol, 1, transMetal);
160 } else {
161 LOGP(fatal, "Sensor of type '{}' is not implemented", type);
162 }
163
164 chipVol->SetLineColor(kYellow);
165
166 return chipVol;
167}
168
169TGeoVolume* TRKLayer::createModule(std::string type)
170{
171 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
172 std::string moduleName = GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber);
173
174 TGeoShape* module;
175 TGeoVolume* moduleVol;
176
177 if (type == "cylinder") {
178 module = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mChipLength / 2);
179 moduleVol = new TGeoVolume(moduleName.c_str(), module, medAir);
180
181 TGeoVolume* chipVol = createChip("cylinder");
182 LOGP(info, "Inserting {} in {} ", chipVol->GetName(), moduleVol->GetName());
183 moduleVol->AddNode(chipVol, 1, nullptr);
184 } else if (type == "flat") {
185 double moduleWidth = constants::moduleMLOT::width;
186 double moduleLength = constants::moduleMLOT::length;
187
188 module = new TGeoBBox(moduleWidth / 2, mChipThickness / 2, moduleLength / 2); // TO BE CHECKED !!!
189 moduleVol = new TGeoVolume(moduleName.c_str(), module, medAir);
190
191 for (int iChip = 0; iChip < mHalfNumberOfChips; iChip++) {
192 TGeoVolume* chipVolLeft = createChip("flat");
193 TGeoVolume* chipVolRight = createChip("flat");
194
195 // Put the chips in the correct position
198
199 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
200 transLeft->SetTranslation(xLeft, 0, zLeft); // TO BE CHECKED !!!
201 TGeoRotation* rot = new TGeoRotation();
202 rot->RotateY(180);
203 transLeft->SetRotation(rot);
204 LOGP(info, "Inserting {} in {} ", chipVolLeft->GetName(), moduleVol->GetName());
205 moduleVol->AddNode(chipVolLeft, iChip * 2, transLeft);
206
209
210 TGeoCombiTrans* transRight = new TGeoCombiTrans();
211 transRight->SetTranslation(xRight, 0, zRight); // TO BE CHECKED !!!
212 LOGP(info, "Inserting {} in {} ", chipVolRight->GetName(), moduleVol->GetName());
213 moduleVol->AddNode(chipVolRight, iChip * 2 + 1, transRight);
214 }
215 } else {
216 LOGP(fatal, "Chip of type '{}' is not implemented", type);
217 }
218
219 moduleVol->SetLineColor(kYellow);
220
221 return moduleVol;
222}
223
224TGeoVolume* TRKLayer::createHalfStave(std::string type)
225{
226 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
227 std::string halfStaveName = GeometryTGeo::getTRKHalfStavePattern() + std::to_string(mLayerNumber);
228
229 TGeoShape* halfStave;
230 TGeoVolume* halfStaveVol;
231
232 if (type == "cylinder") {
233 halfStave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mChipLength / 2);
234 halfStaveVol = new TGeoVolume(halfStaveName.c_str(), halfStave, medAir);
235
236 TGeoVolume* moduleVol = createModule("cylinder");
237 LOGP(info, "Inserting {} in {} ", moduleVol->GetName(), halfStaveVol->GetName());
238 halfStaveVol->AddNode(moduleVol, 1, nullptr);
239 } else if (type == "flat") {
240 double moduleLength = constants::moduleMLOT::length;
241 double halfStaveWidth = constants::OT::halfstave::width;
242 double halfStaveLength = constants::moduleMLOT::length * mNumberOfModules;
243
244 halfStave = new TGeoBBox(halfStaveWidth / 2, mChipThickness / 2, halfStaveLength / 2);
245 halfStaveVol = new TGeoVolume(halfStaveName.c_str(), halfStave, medAir);
246
247 for (int iModule = 0; iModule < mNumberOfModules; iModule++) {
248 TGeoVolume* moduleVol = createModule("flat");
249
250 // Put the modules in the correct position
251 double zPos = -0.5 * mNumberOfModules * moduleLength + (iModule + 0.5) * moduleLength;
252
253 TGeoCombiTrans* trans = new TGeoCombiTrans();
254 trans->SetTranslation(0, 0, zPos); // TO BE CHECKED !!!
255
256 LOGP(info, "Inserting {} in {} ", moduleVol->GetName(), halfStaveVol->GetName());
257 halfStaveVol->AddNode(moduleVol, iModule, trans);
258 }
259 }
260 return halfStaveVol;
261}
262
263TGeoVolume* TRKLayer::createStave(std::string type)
264{
265 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
266 std::string staveName = GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber);
267
268 TGeoShape* stave;
269 TGeoVolume* staveVol;
270
271 if (type == "cylinder") {
272 stave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mChipLength / 2);
273 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
274
275 TGeoVolume* moduleVol = createModule("cylinder");
276 LOGP(info, "Inserting {} in {} ", moduleVol->GetName(), staveVol->GetName());
277 staveVol->AddNode(moduleVol, 1, nullptr);
278 } else if (type == "flat") {
279 double moduleLength = constants::moduleMLOT::length;
280 double staveWidth = constants::ML::width;
281 double staveLength = constants::moduleMLOT::length * mNumberOfModules;
282
283 stave = new TGeoBBox(staveWidth / 2, mChipThickness / 2, staveLength / 2);
284 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
285
286 for (int iModule = 0; iModule < mNumberOfModules; iModule++) {
287 TGeoVolume* moduleVol = createModule("flat");
288
289 // Put the modules in the correct position
290 double zPos = -0.5 * mNumberOfModules * moduleLength + (iModule + 0.5) * moduleLength;
291
292 TGeoCombiTrans* trans = new TGeoCombiTrans();
293 trans->SetTranslation(0, 0, zPos); // TO BE CHECKED !!!
294
295 LOGP(info, "Inserting {} in {} ", moduleVol->GetName(), staveVol->GetName());
296 staveVol->AddNode(moduleVol, iModule, trans);
297 }
298 } else if (type == "staggered") {
299 /*double moduleWidth = constants::moduleMLOT::width;
300 double moduleLength = constants::moduleMLOT::length;*/
301
302 double halfstaveWidth = constants::ML::width;
303 double staveWidth = constants::OT::width; // Each stave has two modules (based on the LOI design)
304 double staveLength = constants::moduleMLOT::length * mNumberOfModules;
305
306 stave = new TGeoBBox(staveWidth / 2, mLogicalVolumeThickness / 2, staveLength / 2);
307 staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
308
309 // Put the half staves in the correct position
310 TGeoVolume* halfStaveVolLeft = createHalfStave("flat");
311 TGeoVolume* halfStaveVolRight = createHalfStave("flat");
312
313 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
314 transLeft->SetTranslation(-halfstaveWidth / 2 + 0.05, 0, 0); // TO BE CHECKED !!! 1mm overlap between the modules
315 LOGP(info, "Inserting {} in {} ", halfStaveVolLeft->GetName(), staveVol->GetName());
316 staveVol->AddNode(halfStaveVolLeft, 0, transLeft);
317
318 TGeoCombiTrans* transRight = new TGeoCombiTrans();
319 transRight->SetTranslation(halfstaveWidth / 2 - 0.05, 0.2, 0); // TO BE CHECKED !!! 1mm overlap between the modules
320 LOGP(info, "Inserting {} in {} ", halfStaveVolRight->GetName(), staveVol->GetName());
321 staveVol->AddNode(halfStaveVolRight, 1, transRight);
322 } else {
323 LOGP(fatal, "Chip of type '{}' is not implemented", type);
324 }
325
326 staveVol->SetLineColor(kYellow);
327
328 return staveVol;
329}
330
331void TRKLayer::createLayer(TGeoVolume* motherVolume)
332{
333 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
334
335 double layerThickness = mChipThickness;
336 if (mLayout != eLayout::kCylinder) {
337 layerThickness = mLogicalVolumeThickness;
338 }
339
340 TGeoTube* layer;
341 TGeoVolume* layerVol;
342
343 if (mLayout == eLayout::kCylinder) {
344 layer = new TGeoTube(mInnerRadius - 0.333 * layerThickness, mInnerRadius + 0.667 * layerThickness, mChipLength / 2);
345 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
346
347 TGeoVolume* staveVol = createStave("cylinder");
348 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
349 layerVol->AddNode(staveVol, 1, nullptr);
350 } else if (mLayout == eLayout::kTurboStaves) {
351 double layerLength = constants::moduleMLOT::length * mNumberOfModules;
352 double staveWidth = constants::ML::width; // Each stave has two modules (based on the LOI design)
353
354 if (mInnerRadius > 25) {
355 staveWidth = constants::OT::width; // Outer layers have two modules per stave
356 }
357
358 layer = new TGeoTube(mInnerRadius - 0.333 * layerThickness, mInnerRadius + 0.667 * layerThickness, layerLength / 2);
359 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
360
361 // Compute the number of staves
362 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / staveWidth);
363 nStaves += nStaves % 2; // Require an even number of staves
364
365 // Compute the size of the overlap region
366 double theta = 2 * TMath::Pi() / nStaves;
367 double theta1 = std::atan(staveWidth / 2 / mInnerRadius);
368 double st = std::sin(theta);
369 double ct = std::cos(theta);
370 double theta2 = std::atan((mInnerRadius * st - staveWidth / 2 * ct) / (mInnerRadius * ct + staveWidth / 2 * st));
371 double overlap = (theta1 - theta2) * mInnerRadius;
372 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
373
374 for (int iStave = 0; iStave < nStaves; iStave++) {
375 TGeoVolume* staveVol = createStave("flat");
376
377 // Put the staves in the correct position and orientation
378 TGeoCombiTrans* trans = new TGeoCombiTrans();
379 double theta = 360. * iStave / nStaves;
380 TGeoRotation* rot = new TGeoRotation("rot", theta + 90 + 3, 0, 0);
381 trans->SetRotation(rot);
382 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
383
384 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
385 layerVol->AddNode(staveVol, iStave, trans);
386 }
387 } else if (mLayout == kStaggered) {
388 double layerLength = constants::moduleMLOT::length * mNumberOfModules;
389
390 layer = new TGeoTube(mInnerRadius - 0.333 * layerThickness, mInnerRadius + 0.667 * layerThickness, layerLength / 2);
391 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
392
393 // Compute the number of staves
394 double staveWidth = constants::OT::width; // Each stave has two modules (based on the LOI design)
395 int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / staveWidth);
396 nStaves += nStaves % 2; // Require an even number of staves
397
398 // Compute the size of the overlap region
399 double theta = 2 * TMath::Pi() / nStaves;
400 double theta1 = std::atan(staveWidth / 2 / mInnerRadius);
401 double st = std::sin(theta);
402 double ct = std::cos(theta);
403 double theta2 = std::atan((mInnerRadius * st - staveWidth / 2 * ct) / (mInnerRadius * ct + staveWidth / 2 * st));
404 double overlap = (theta1 - theta2) * mInnerRadius;
405 LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
406
407 for (int iStave = 0; iStave < nStaves; iStave++) {
408 TGeoVolume* staveVol = createStave("staggered");
409
410 // Put the staves in the correct position and orientation
411 TGeoCombiTrans* trans = new TGeoCombiTrans();
412 double theta = 360. * iStave / nStaves;
413 TGeoRotation* rot = new TGeoRotation("rot", theta + 90, 0, 0);
414 trans->SetRotation(rot);
415 trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
416
417 LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
418 layerVol->AddNode(staveVol, iStave, trans);
419 }
420 } else {
421 LOGP(fatal, "Layout not implemented");
422 }
423 layerVol->SetLineColor(kYellow);
424
425 LOGP(info, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
426 motherVolume->AddNode(layerVol, 1, nullptr);
427}
428// ClassImp(TRKLayer);
429
430} // namespace trk
431} // namespace o2
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:331
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:263
TGeoVolume * createHalfStave(std::string type)
Definition TRKLayer.cxx:224
TGeoVolume * createDeadzone(std::string type)
Definition TRKLayer.cxx:66
TRKLayer()=default
TGeoVolume * createModule(std::string type)
Definition TRKLayer.cxx:169
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