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
13
14#include "Framework/Logger.h"
15
17#include "TRKBase/Specs.h"
19#include <TGeoBBox.h>
20#include <TGeoCompositeShape.h>
21#include <TGeoTube.h>
22#include <TGeoVolume.h>
23#include <TMath.h>
24
25#include <algorithm>
26#include <cassert>
27#include <cmath>
28#include <string>
29#include <utility>
30
31namespace o2
32{
33namespace trk
34{
35TRKCylindricalLayer::TRKCylindricalLayer(int layerNumber, std::string layerName, float rInn, float length, float thickOrX2X0, MatBudgetParamMode mode)
36 : mLayerNumber(layerNumber), mLayerName(layerName), mInnerRadius(rInn), mLength(length)
37{
39 mChipThickness = thickOrX2X0;
40 mX2X0 = thickOrX2X0 / Si_X0;
41 mOuterRadius = rInn + thickOrX2X0;
42 } else if (mode == MatBudgetParamMode::X2X0) {
43 mX2X0 = thickOrX2X0;
44 mChipThickness = thickOrX2X0 * Si_X0;
45 mOuterRadius = rInn + thickOrX2X0 * Si_X0;
46 }
47
48 LOGP(info, "Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}", mLayerNumber, mInnerRadius, mOuterRadius, mLength, mX2X0);
49}
50
52{
53 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
55 TGeoShape* sensor = new TGeoTube(mInnerRadius, mInnerRadius + sSensorThickness, mLength / 2);
56 TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
57 sensVol->SetLineColor(kYellow);
58
59 return sensVol;
60};
61
63{
64 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
66 TGeoShape* metalStack = new TGeoTube(mInnerRadius + sSensorThickness, mInnerRadius + mChipThickness, mLength / 2);
67 TGeoVolume* metalVol = new TGeoVolume(metalName.c_str(), metalStack, medSi);
68 metalVol->SetLineColor(kGray);
69
70 return metalVol;
71};
72
73void TRKCylindricalLayer::createLayer(TGeoVolume* motherVolume)
74{
75 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
76 TGeoTube* layer = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mLength / 2);
77 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
78 layerVol->SetLineColor(kYellow);
79
80 TGeoVolume* sensVol = createSensor();
81 LOGP(debug, "Inserting {} in {} ", sensVol->GetName(), layerVol->GetName());
82 layerVol->AddNode(sensVol, 1, nullptr);
83
84 TGeoVolume* metalVol = createMetalStack();
85 LOGP(debug, "Inserting {} in {} ", metalVol->GetName(), layerVol->GetName());
86 layerVol->AddNode(metalVol, 1, nullptr);
87
88 LOGP(debug, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
89 motherVolume->AddNode(layerVol, 1, nullptr);
90}
91
93
94TRKSegmentedLayer::TRKSegmentedLayer(int layerNumber, std::string layerName, float rInn, float tiltAngle, int numberOfStaves, int numberOfModules, float thickOrX2X0, MatBudgetParamMode mode)
95 : TRKCylindricalLayer(layerNumber, layerName, rInn, numberOfModules * sModuleLength, thickOrX2X0, mode), mTiltAngle(tiltAngle), mNumberOfStaves(numberOfStaves), mNumberOfModules(numberOfModules)
96{
97 assert(numberOfStaves % 2 == 0 && "Error: numberOfStaves must be even!");
98}
99
101{
102 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
104 TGeoShape* sensor = new TGeoBBox((sChipWidth - sDeadzoneWidth) / 2, sSensorThickness / 2, sChipLength / 2);
105 TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
106 sensVol->SetLineColor(kYellow);
107
108 return sensVol;
109}
110
112{
113 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
115 TGeoShape* deadzone = new TGeoBBox(sDeadzoneWidth / 2, sSensorThickness / 2, sChipLength / 2);
116 TGeoVolume* deadVol = new TGeoVolume(deadName.c_str(), deadzone, medSi);
117 deadVol->SetLineColor(kGray);
118
119 return deadVol;
120}
121
123{
124 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
126 TGeoShape* metalStack = new TGeoBBox(sChipWidth / 2, (mChipThickness - sSensorThickness) / 2, sChipLength / 2);
127 TGeoVolume* metalVol = new TGeoVolume(metalName.c_str(), metalStack, medSi);
128 metalVol->SetLineColor(kGray);
129
130 return metalVol;
131}
132
134{
135 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
137 TGeoShape* chip = new TGeoBBox(sChipWidth / 2, mChipThickness / 2, sChipLength / 2);
138 TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
139 chipVol->SetLineColor(kYellow);
140
141 TGeoVolume* sensVol = createSensor();
142 TGeoVolume* deadVol = createDeadzone();
143 TGeoVolume* metalVol = createMetalStack();
144 TGeoCombiTrans* transSens = new TGeoCombiTrans();
145 TGeoCombiTrans* transDead = new TGeoCombiTrans();
146 TGeoCombiTrans* transMetal = new TGeoCombiTrans();
147
148 const double sensY = mIsFlipped ? -(mChipThickness - sSensorThickness) / 2 : (mChipThickness - sSensorThickness) / 2;
149 const double metalY = mIsFlipped ? sSensorThickness / 2 : -sSensorThickness / 2;
150 transSens->SetTranslation(-sDeadzoneWidth / 2, sensY, 0);
151 transDead->SetTranslation((sChipWidth - sDeadzoneWidth) / 2, sensY, 0);
152 transMetal->SetTranslation(0, metalY, 0);
153
154 chipVol->AddNode(sensVol, 1, transSens);
155 chipVol->AddNode(deadVol, 1, transDead);
156 chipVol->AddNode(metalVol, 1, transMetal);
157
158 return chipVol;
159}
160
162{
163 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
165 TGeoShape* module = new TGeoBBox(sModuleWidth / 2, mChipThickness / 2, sModuleLength / 2);
166 TGeoVolume* moduleVol = new TGeoVolume(moduleName.c_str(), module, medSi);
167 moduleVol->SetLineColor(kYellow);
168
169 for (int iChip = 0; iChip < sHalfNumberOfChips; iChip++) {
170 TGeoVolume* chipVolLeft = createChip();
173 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
174 transLeft->SetTranslation(xLeft, 0, zLeft);
175 TGeoRotation* rot = new TGeoRotation();
176 rot->RotateY(180);
177 transLeft->SetRotation(rot);
178 LOGP(debug, "Inserting {} in {} ", chipVolLeft->GetName(), moduleVol->GetName());
179 moduleVol->AddNode(chipVolLeft, iChip * 2, transLeft);
180
181 TGeoVolume* chipVolRight = createChip();
184 TGeoCombiTrans* transRight = new TGeoCombiTrans();
185 transRight->SetTranslation(xRight, 0, zRight);
186 LOGP(debug, "Inserting {} in {} ", chipVolRight->GetName(), moduleVol->GetName());
187 moduleVol->AddNode(chipVolRight, iChip * 2 + 1, transRight);
188 }
189
190 return moduleVol;
191}
192
193std::pair<float, float> TRKSegmentedLayer::getBoundingRadii(double staveWidth) const
194{
195 const float avgRadius = 0.5 * (mInnerRadius + mOuterRadius);
196 const float staveSizeX = staveWidth;
197 const float staveSizeY = mOuterRadius - mInnerRadius;
198
199 /*const float deltaForTilt = 0.5 * (std::sin(TMath::DegToRad() * mTiltAngle) * staveSizeX + std::cos(TMath::DegToRad() * mTiltAngle) * staveSizeY);
200
201 float radiusMin = std::sqrt(avgRadius * avgRadius + 0.25 * staveSizeX * staveSizeX + 0.25 * staveSizeY * staveSizeY - avgRadius * 2. * deltaForTilt);
202 float radiusMax = std::sqrt(avgRadius * avgRadius + 0.25 * staveSizeX * staveSizeX + 0.25 * staveSizeY * staveSizeY + avgRadius * 2. * deltaForTilt);*/
203
204 const double alpha = TMath::DegToRad() * std::abs(mTiltAngle);
205
206 // The maximum distance from the center is always the outer top corner
207 double u_max = avgRadius * std::sin(alpha) + staveSizeX / 2.0;
208 double v_max = avgRadius * std::cos(alpha) + staveSizeY / 2.0;
209 double radiusMax = std::sqrt(u_max * u_max + v_max * v_max);
210
211 // The perpendicular distance from the center to the line where the inner face lies
212 double perpDistance = avgRadius * std::cos(alpha) - staveSizeY / 2.0;
213
214 // The projection of the center along the width of the stave
215 double projDistance = avgRadius * std::sin(alpha);
216
217 double radiusMin;
218 if (projDistance <= staveSizeX / 2.0) {
219 // The center projects directly inside the flat face.
220 // The closest point is on the face itself, not on the corner
221 radiusMin = perpDistance;
222 } else {
223 // The center projects outside the face. The closest point is the inner corner
224 double u_min = projDistance - staveSizeX / 2.0;
225 radiusMin = std::sqrt(u_min * u_min + perpDistance * perpDistance);
226 }
227
228 // Add a 0.5 mm safety margin to prevent false-positive overlaps in ROOT's geometry checker caused by floating-point inaccuracies
229 const float precisionMargin = 0.05f;
230
231 return {radiusMin - precisionMargin, radiusMax + precisionMargin};
232}
233
235
236TRKMLLayer::TRKMLLayer(int layerNumber, std::string layerName, float rInn, float staggerOffset, float tiltAngle, int numberOfStaves, int numberOfModules, float thickOrX2X0, MatBudgetParamMode mode)
237 : TRKSegmentedLayer(layerNumber, layerName, rInn, tiltAngle, numberOfStaves, numberOfModules, thickOrX2X0, mode), mStaggerOffset(staggerOffset)
238{
239 if (mLayerNumber == sFlippedLayerNumber) {
240 mOuterRadius = rInn;
242 mIsFlipped = true;
243 mStaggerOffset = -staggerOffset;
244 LOGP(info, "Layer {} is flipped: sensor and metal stack positions are switched", mLayerNumber);
245 }
246}
247
249{
250 // Assembly (not a solid box) so the end-of-stave card can extend past the module envelope.
252 TGeoVolume* staveVol = new TGeoVolumeAssembly(staveName.c_str());
253 staveVol->SetLineColor(kYellow);
254
255 for (int iModule = 0; iModule < mNumberOfModules; iModule++) {
256 TGeoVolume* moduleVol = createModule();
257 double zPos = -0.5 * mNumberOfModules * sModuleLength + (iModule + 0.5) * sModuleLength;
258 TGeoCombiTrans* trans = new TGeoCombiTrans();
259 trans->SetTranslation(0, 0, zPos);
260 LOGP(debug, "Inserting {} in {} ", moduleVol->GetName(), staveVol->GetName());
261 staveVol->AddNode(moduleVol, iModule, trans);
262 }
263
264 // End-of-stave card on the A-side (+z) only, just past the stave end and in front of the
265 // TRK_MIDBARCONN_DISK. Local frame: x = phi (width), y = radial (thickness), z = length.
266 TGeoCombiTrans* tCard = new TGeoCombiTrans();
267 tCard->SetTranslation(0, 0, mLength / 2 + constants::ML::eosCard::zGap + constants::ML::eosCard::length / 2);
268 staveVol->AddNode(createEndOfStaveCard(), 0, tCard);
269
270 return staveVol;
271}
272
273TGeoVolume* TRKMLLayer::createEndOfStaveCard()
274{
275 // FR4 board carrying evenly spaced copper planes; same construction as the OT card, with its
276 // own constants::ML::eosCard dimensions and a configurable copper thickness (TRKBase.mlEosCardCuThickness),
277 // which displaces FR4 inside the fixed envelope and sets the card x/X0.
278 TGeoMedium* medFR4 = gGeoManager->GetMedium("TRK_FR4$");
279 TGeoMedium* medCu = gGeoManager->GetMedium("TRK_COPPER$");
280 const std::string name = GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber) + "_EOSCard";
281
283 TGeoVolume* cardVol = new TGeoVolume(name.c_str(), board, medFR4);
284 cardVol->SetLineColor(kGreen + 3);
285
286 const double cuThickness = TRKBaseParam::Instance().mlEosCardCuThickness;
287 const int nPlanes = constants::ML::eosCard::nCopperLayers;
288 if (cuThickness * nPlanes >= constants::ML::eosCard::thickness) {
289 LOGP(fatal, "TRKBase.mlEosCardCuThickness = {} cm x {} planes does not fit in the {} cm ML end-of-stave card",
290 cuThickness, nPlanes, constants::ML::eosCard::thickness);
291 }
292 TGeoShape* plane = new TGeoBBox(constants::ML::eosCard::width / 2, cuThickness / 2, constants::ML::eosCard::length / 2);
293 TGeoVolume* planeVol = new TGeoVolume((name + "_Cu").c_str(), plane, medCu);
294 planeVol->SetLineColor(kOrange + 7);
295
296 // Evenly spaced, the outermost two flush with the board surfaces.
297 const double span = constants::ML::eosCard::thickness - cuThickness;
298 for (int iPlane = 0; iPlane < nPlanes; iPlane++) {
299 const double y = (nPlanes > 1) ? -span / 2 + iPlane * span / (nPlanes - 1) : 0.;
300 cardVol->AddNode(planeVol, iPlane, new TGeoTranslation(0, y, 0));
301 }
302
303 return cardVol;
304}
305
306void TRKMLLayer::createLayer(TGeoVolume* motherVolume)
307{
308 // Retrieve exact bounding boundaries and create the logical container volume
309 auto [rMin, rMax] = getBoundingRadii(sStaveWidth);
310
311 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
312 // TGeoTube* layer = new TGeoTube(mInnerRadius - 0.333 * sLogicalVolumeThickness, mInnerRadius + 0.667 * sLogicalVolumeThickness, mLength / 2);
313 // Extend the z half-length so the A-side end-of-stave card (past mLength/2) stays inside the layer.
315 TGeoTube* layer = new TGeoTube(rMin, rMax, halfLengthZ);
316 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
317 layerVol->SetLineColor(kYellow);
318
319 // Compute the number of staves
320 // int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / sStaveWidth);
321 // nStaves += nStaves % 2; // Require an even number of staves
322
323 // Nominal average radii used as placement barycenters for the staves
324 const double avgRadiusInner = 0.5 * (mInnerRadius + mOuterRadius);
325 const double avgRadiusOuter = avgRadiusInner + mStaggerOffset;
326
327 // Compute the size of the overlap region
328 double theta = 2. * TMath::Pi() / mNumberOfStaves;
329 double theta1 = std::atan(sStaveWidth / 2 / mInnerRadius);
330 double st = std::sin(theta);
331 double ct = std::cos(theta);
332 double theta2 = std::atan((mInnerRadius * st - sStaveWidth / 2 * ct) / (mInnerRadius * ct + sStaveWidth / 2 * st));
333 double overlap = (theta1 - theta2) * mInnerRadius;
334 LOGP(info, "Creating a layer with {} staves and {} mm overlap", mNumberOfStaves, overlap * 10);
335
336 for (int iStave = 0; iStave < mNumberOfStaves; iStave++) {
337 TGeoVolume* staveVol = createStave();
338 TGeoCombiTrans* trans = new TGeoCombiTrans();
339 // If the number of staves is a multiple of 4, rotate by half a stave to avoid having the first one exactly on the x
340 double phi = (mNumberOfStaves % 4 == 0) ? theta * (iStave + 0.5) : theta * iStave;
341 double phiDeg = phi * TMath::RadToDeg();
342 TGeoRotation* rot = new TGeoRotation("rot", phiDeg + 90 + mTiltAngle, 0, 0);
343 trans->SetRotation(rot);
344 // float trueRadius = (mLayerNumber == 3 || mLayerNumber == 4) ? (iStave % 2 == 0 ? mInnerRadius : mInnerRadius + mStaggerOffset) : mInnerRadius;
345 float trueRadius = (mLayerNumber == 3 || mLayerNumber == 4) ? (iStave % 2 == 0 ? avgRadiusInner : avgRadiusOuter) : avgRadiusInner;
346 trans->SetTranslation(trueRadius * std::cos(phi), trueRadius * std::sin(phi), 0);
347 LOGP(debug, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
348 layerVol->AddNode(staveVol, iStave, trans);
349 }
350
351 LOGP(debug, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
352 motherVolume->AddNode(layerVol, 1, nullptr);
353}
354
355std::pair<float, float> TRKMLLayer::getBoundingRadii(double staveWidth) const
356{
357 // Get the baseline RMin from the base class
358 auto [defaultRadiusMin, defaultRadiusMax] = TRKSegmentedLayer::getBoundingRadii(staveWidth);
359
360 // If we are not in the staggered layers, return the baseline values
361 if (mLayerNumber != 3 && mLayerNumber != 4) {
362 return {defaultRadiusMin, defaultRadiusMax};
363 }
364
365 /*// For staggered layers, we must recalculate RMax based on the outer shifted row
366 const float avgRadiusInner = 0.5 * (mInnerRadius + mOuterRadius);
367 const float avgRadiusOuter = avgRadiusInner + mStaggerOffset;
368
369 const float staveSizeX = staveWidth;
370 const float staveSizeY = mOuterRadius - mInnerRadius;
371
372 const float deltaForTiltOuter = 0.5 * (std::sin(TMath::DegToRad() * mTiltAngle) * staveSizeX + std::cos(TMath::DegToRad() * mTiltAngle) * staveSizeY);
373
374 const float radiusMax = std::sqrt(avgRadiusOuter * avgRadiusOuter + 0.25 * staveSizeX * staveSizeX + 0.25 * staveSizeY * staveSizeY + avgRadiusOuter * 2. * deltaForTiltOuter);*/
375
376 const float avgRadiusInner = 0.5 * (mInnerRadius + mOuterRadius);
377 const float avgRadiusStaggered = avgRadiusInner + mStaggerOffset;
378
379 const float staveSizeX = staveWidth;
380 const float staveSizeY = mOuterRadius - mInnerRadius;
381 const float alpha = TMath::DegToRad() * std::abs(mTiltAngle);
382
383 const float precisionMargin = 0.05f;
384
385 // If the layer is NOT flipped (e.g., Layer 4), the stagger goes outwards
386 // Therefore, we must recalculate only the maximum radius based on the outer shifted row
387 if (!mIsFlipped) {
388 float u_max = avgRadiusStaggered * std::sin(alpha) + staveSizeX / 2.0;
389 float v_max = avgRadiusStaggered * std::cos(alpha) + staveSizeY / 2.0;
390 float radiusMax = std::sqrt(u_max * u_max + v_max * v_max);
391
392 return {defaultRadiusMin, radiusMax + precisionMargin};
393 }
394 // If the layer IS flipped (e.g., Layer 3), the stagger goes inwards
395 // Therefore, we must recalculate only the minimum radius based on the inner shifted row
396 else {
397 double perpDistance = avgRadiusStaggered * std::cos(alpha) - staveSizeY / 2.0;
398 double projDistance = avgRadiusStaggered * std::sin(alpha);
399 double newRadiusMin;
400
401 if (projDistance <= staveSizeX / 2.0) {
402 newRadiusMin = perpDistance;
403 } else {
404 double u_min = projDistance - staveSizeX / 2.0;
405 newRadiusMin = std::sqrt(u_min * u_min + perpDistance * perpDistance);
406 }
407
408 return {newRadiusMin - precisionMargin, defaultRadiusMax};
409 }
410}
411
413
414TRKOTLayer::TRKOTLayer(int layerNumber, std::string layerName, float rInn, float tiltAngle, int numberOfStaves, int numberOfModules, float thickOrX2X0, MatBudgetParamMode mode)
415 : TRKSegmentedLayer(layerNumber, layerName, rInn, tiltAngle, numberOfStaves, numberOfModules, thickOrX2X0, mode)
416{
417}
418
420{
421 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
423 float lengthHalfBarrel = mLength / 2;
424 TGeoShape* halfStave = new TGeoBBox(sHalfStaveWidth / 2, mChipThickness / 2, lengthHalfBarrel / 2);
425 TGeoVolume* halfStaveVol = new TGeoVolume(halfStaveName.c_str(), halfStave, medSi);
426 halfStaveVol->SetLineColor(kYellow);
427
428 int nModulesPerHalfBarrel = mNumberOfModules / 2;
429 for (int iModule = 0; iModule < nModulesPerHalfBarrel; iModule++) {
430 double zPos = -0.5 * nModulesPerHalfBarrel * sModuleLength + (iModule + 0.5) * sModuleLength;
431 TGeoCombiTrans* trans = new TGeoCombiTrans();
432 trans->SetTranslation(0, 0, zPos);
433 halfStaveVol->AddNode(createModule(), iModule, trans);
434 }
435
436 return halfStaveVol;
437}
438
440{
442 TGeoVolume* staveVol = new TGeoVolumeAssembly(staveName.c_str());
443
444 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
445 transLeft->SetTranslation(-(sHalfStaveWidth - sInStaveOverlap) / 2, 0, 0);
446 staveVol->AddNode(createHalfStave(), 0, transLeft);
447
448 TGeoCombiTrans* transRight = new TGeoCombiTrans();
449 transRight->SetTranslation((sHalfStaveWidth - sInStaveOverlap) / 2, 0.2, 0);
450 staveVol->AddNode(createHalfStave(), 1, transRight);
451
452 return staveVol;
453}
454
455void TRKOTLayer::createLayer(TGeoVolume* motherVolume)
456{
457 auto [rMin, rMax] = getBoundingRadii(sStaveWidth);
458
459 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
460 TGeoTube* layer = new TGeoTube(rMin, rMax, (mLength + sGapBetweenOuterTrackerBarrelHalves) / 2);
461 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
462 layerVol->SetLineColor(kYellow);
463
464 int nStavesHalfBarrel = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / sStaveWidth);
465 nStavesHalfBarrel += nStavesHalfBarrel % 2;
466
467 const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius);
468 const double theta = 2. * TMath::Pi() / nStavesHalfBarrel;
469 const float lengthHalfBarrel = mLength / 2;
470 const int nStaves = nStavesHalfBarrel * 2;
471 LOGP(info, "Creating OT layer {} with two half-barrels of {} staves each", mLayerNumber, nStavesHalfBarrel);
472
473 for (int iStave = 0; iStave < nStaves; iStave++) {
474 int whichHalfBarrel = iStave / nStavesHalfBarrel;
475 double phi = theta * iStave;
476 TGeoRotation* rot = new TGeoRotation("rot");
477 if (whichHalfBarrel == 1) {
478 rot->RotateY(180.);
479 }
480 rot->RotateZ(phi * TMath::RadToDeg() + 90 + (whichHalfBarrel == 0 ? +1 : -1) * mTiltAngle);
481 double zPos = (whichHalfBarrel == 0 ? -1 : 1) * (0.5 * lengthHalfBarrel + sGapBetweenOuterTrackerBarrelHalves / 2);
482 TGeoCombiTrans* trans = new TGeoCombiTrans();
483 trans->SetRotation(rot);
484 trans->SetTranslation(avgRadius * std::cos(phi), avgRadius * std::sin(phi), zPos);
485 layerVol->AddNode(createStave(), iStave, trans);
486 }
487
488 motherVolume->AddNode(layerVol, 1, nullptr);
489}
490
491std::pair<float, float> TRKOTLayer::getBoundingRadii(double staveWidth) const
492{
493 auto [radiusMin, radiusMax] = TRKSegmentedLayer::getBoundingRadii(staveWidth);
494 return {radiusMin - 0.201f, radiusMax};
495}
496
498
499TRKOTLayerRealistic::TRKOTLayerRealistic(int layerNumber, std::string layerName, float rInn, float tiltAngle, int numberOfStaves, int numberOfModules, float thickOrX2X0, MatBudgetParamMode mode)
500 : TRKSegmentedLayer(layerNumber, layerName, rInn, tiltAngle, numberOfStaves, numberOfModules, thickOrX2X0, mode)
501{
502 // Outermost layer is flipped: cooling pipe and support rings on the inner side.
504 mIsFlipped = true;
505 }
506}
507
509{
510 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
512 TGeoShape* chip = new TGeoBBox(sChipWidth / 2, constants::OT::sensorThickness / 2, sChipLength / 2);
513 TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
514 chipVol->SetLineColor(kYellow);
515
516 // Active sensor and passive read-out edge tile the chip width.
517 chipVol->AddNode(createSensor(), 1, new TGeoTranslation(-sDeadzoneWidth / 2, 0, 0));
518 chipVol->AddNode(createDeadzone(), 1, new TGeoTranslation((sChipWidth - sDeadzoneWidth) / 2, 0, 0));
519 return chipVol;
520}
521
522TGeoVolume* TRKOTLayerRealistic::createFPC()
523{
524 TGeoMedium* med = gGeoManager->GetMedium("TRK_FPC$");
526 TGeoVolume* vol = new TGeoVolume((GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber) + "_FPC").c_str(), shape, med);
527 vol->SetLineColor(kOrange);
528 return vol;
529}
530
531TGeoVolume* TRKOTLayerRealistic::createColdPlate()
532{
533 TGeoMedium* med = gGeoManager->GetMedium("TRK_CARBONFIBER$");
535 TGeoVolume* vol = new TGeoVolume((GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber) + "_ColdPlate").c_str(), shape, med);
536 vol->SetLineColor(kGray + 2);
537 return vol;
538}
539
540double TRKOTLayerRealistic::getRowHalfLength() const
541{
542 const int nModulesPerRow = mNumberOfModules / 2;
543 return (nModulesPerRow * constants::OT::fpc::length + (nModulesPerRow - 1) * constants::OT::interModuleGap) / 2;
544}
545
546double TRKOTLayerRealistic::getPipeTrim() const
547{
548 // The mid-rapidity ring sits at the pipe radius, between the z = 0 wall and the pipe.
549 const double wallThickness = TRKBaseParam::Instance().otBarrelWallThickness;
551 return std::max(0., pipeStart - constants::OT::barrelHalvesZGap / 2);
552}
553
554TGeoVolume* TRKOTLayerRealistic::createSupportRing(double rMin, double rMax, double phi1, double phi2, int id)
555{
556 // Hollow rectangular-section half-ring, open at the two azimuthal ends.
557 TGeoMedium* med = gGeoManager->GetMedium("TRK_CARBONFIBER$");
559 const double dz = constants::OT::supportRing::zWidth / 2;
560 const std::string base = GeometryTGeo::getTRKLayerPattern() + std::to_string(mLayerNumber) + "_SupportRing" + std::to_string(id);
561 new TGeoTubeSeg((base + "_outsh").c_str(), rMin, rMax, dz, phi1, phi2);
562 new TGeoTubeSeg((base + "_insh").c_str(), rMin + t, rMax - t, dz - t, phi1, phi2);
563 TGeoShape* shape = new TGeoCompositeShape((base + "sh").c_str(), (base + "_outsh-" + base + "_insh").c_str());
564 TGeoVolume* vol = new TGeoVolume(base.c_str(), shape, med);
565 vol->SetLineColor(kGray + 2);
566 return vol;
567}
568
569TGeoVolume* TRKOTLayerRealistic::createCoolingPipe()
570{
571 TGeoMedium* med = gGeoManager->GetMedium("TRK_CARBONFIBER$");
573 getRowHalfLength() - getPipeTrim() / 2);
574 TGeoVolume* vol = new TGeoVolume((GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber) + "_CoolingPipe").c_str(), tube, med);
575 vol->SetLineColor(kBlue + 2);
576 return vol;
577}
578
579TGeoVolume* TRKOTLayerRealistic::createEndOfStaveCard()
580{
581 TGeoMedium* medFR4 = gGeoManager->GetMedium("TRK_FR4$");
582 TGeoMedium* medCu = gGeoManager->GetMedium("TRK_COPPER$");
583 const std::string name = GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber) + "_EOSCard";
584
586 TGeoVolume* cardVol = new TGeoVolume(name.c_str(), board, medFR4);
587 cardVol->SetLineColor(kGreen + 3);
588
589 // Copper thickness is configurable: it displaces FR4 inside the fixed board envelope and
590 // is what sets the card material budget, so it is the knob for x/X0 scans.
591 const double cuThickness = TRKBaseParam::Instance().otEosCardCuThickness;
592 const int nPlanes = constants::OT::eosCard::nCopperLayers;
593 if (cuThickness * nPlanes >= constants::OT::eosCard::thickness) {
594 LOGP(fatal, "TRKBase.otEosCardCuThickness = {} cm x {} planes does not fit in the {} cm end-of-stave card",
595 cuThickness, nPlanes, constants::OT::eosCard::thickness);
596 }
597 TGeoShape* plane = new TGeoBBox(constants::OT::eosCard::width / 2, cuThickness / 2, constants::OT::eosCard::length / 2);
598 TGeoVolume* planeVol = new TGeoVolume((name + "_Cu").c_str(), plane, medCu);
599 planeVol->SetLineColor(kOrange + 7);
600
601 // Evenly spaced, the outermost two flush with the board surfaces.
602 const double span = constants::OT::eosCard::thickness - cuThickness;
603 for (int iPlane = 0; iPlane < nPlanes; iPlane++) {
604 const double y = (nPlanes > 1) ? -span / 2 + iPlane * span / (nPlanes - 1) : 0.;
605 cardVol->AddNode(planeVol, iPlane, new TGeoTranslation(0, y, 0));
606 }
607
608 return cardVol;
609}
610
611void TRKOTLayerRealistic::addConnector(TGeoVolume* moduleVol, double rMid)
612{
613 TGeoMedium* med = gGeoManager->GetMedium("TRK_LCPCU$");
614 std::string name = GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber) + "_Connector";
616 TGeoVolume* vol = new TGeoVolume(name.c_str(), shape, med);
617 vol->SetLineColor(kBlue);
618
619 // Centred in phi, inset from the module short edge in z.
621 moduleVol->AddNode(vol, 0, new TGeoTranslation(0, rMid, z));
622}
623
624void TRKOTLayerRealistic::addCapacitors(TGeoVolume* moduleVol, double rMid)
625{
626 TGeoMedium* med = gGeoManager->GetMedium("TRK_BATIO3$");
629 TGeoVolume* vol = new TGeoVolume(name.c_str(), shape, med);
630 vol->SetLineColor(kCyan);
631
634 const double chipX[2] = {-0.5 * pitchX, +0.5 * pitchX};
635 const double chipZ[4] = {-1.5 * pitchZ, -0.5 * pitchZ, +0.5 * pitchZ, +1.5 * pitchZ};
636 const double dX[5] = {-0.80, +0.80, -0.80, +0.80, 0.0}; // per chip: 4 corners + centre [cm]
637 const double dZ[5] = {-0.95, -0.95, +0.95, +0.95, 0.0};
638
639 // Skip capacitors that fall under the connector footprint (+1 mm clearance).
641 const double skipX = constants::OT::connector::width / 2 + constants::OT::capacitor::width / 2 + 0.1;
642 const double skipZ = constants::OT::connector::length / 2 + constants::OT::capacitor::length / 2 + 0.1;
643
644 int capCopy = 0;
645 for (int iZ = 0; iZ < 4; iZ++) {
646 for (int iX = 0; iX < 2; iX++) {
647 for (int iCap = 0; iCap < constants::OT::capacitor::perChip; iCap++) {
648 const double x = chipX[iX] + dX[iCap];
649 const double z = chipZ[iZ] + dZ[iCap];
650 if (std::abs(x) < skipX && std::abs(z - connZ) < skipZ) {
651 continue;
652 }
653 moduleVol->AddNode(vol, capCopy++, new TGeoTranslation(x, rMid, z));
654 }
655 }
656 }
657}
658
659void TRKOTLayerRealistic::addBrackets(TGeoVolume* moduleVol, double rMid)
660{
661 TGeoMedium* med = gGeoManager->GetMedium("TRK_PEEK$");
664 TGeoVolume* vol = new TGeoVolume(name.c_str(), shape, med);
665 vol->SetLineColor(kGreen + 2);
666
668 moduleVol->AddNode(vol, 0, new TGeoTranslation(0, rMid, -z));
669 moduleVol->AddNode(vol, 1, new TGeoTranslation(0, rMid, +z));
670}
671
673{
675 TGeoVolume* moduleVol = new TGeoVolumeAssembly(modName.c_str());
676
677 // Flush component stack about the chip mid-plane (local r = 0).
678 const double chipHalf = constants::OT::sensorThickness / 2;
679 const double fpcMidY = -(chipHalf + constants::OT::fpc::thickness / 2);
680 const double coldPlateMidY = +(chipHalf + constants::OT::coldPlate::thickness / 2);
681 const double connMidY = -(chipHalf + constants::OT::fpc::thickness + constants::OT::connector::thickness / 2);
682 const double capMidY = -(chipHalf + constants::OT::fpc::thickness + constants::OT::capacitor::thickness / 2);
683 const double bracketMidY = +(chipHalf + constants::OT::coldPlate::thickness + constants::OT::bracket::thickness / 2);
684
685 // 8 chips: 2 phi columns x 4 z rows, on a uniform chip+gap pitch.
686 const double pitchX = sChipWidth + constants::OT::interChipGap;
687 const double pitchZ = sChipLength + constants::OT::interChipGap;
688 const double chipX[2] = {-0.5 * pitchX, +0.5 * pitchX};
689 const double chipZ[4] = {-1.5 * pitchZ, -0.5 * pitchZ, +0.5 * pitchZ, +1.5 * pitchZ};
690
691 moduleVol->AddNode(createColdPlate(), 0, new TGeoTranslation(0, coldPlateMidY, 0));
692
693 int chipCopy = 0;
694 for (int iZ = 0; iZ < 4; iZ++) {
695 for (int iX = 0; iX < 2; iX++) {
696 TGeoCombiTrans* trans = new TGeoCombiTrans();
697 trans->SetTranslation(chipX[iX], 0., chipZ[iZ]);
698 if (iX == 0) { // inner column rotated so its dead zone faces the outer module edge
699 TGeoRotation* rot = new TGeoRotation();
700 rot->RotateY(180.);
701 trans->SetRotation(rot);
702 }
703 moduleVol->AddNode(createChip(), chipCopy++, trans);
704 }
705 }
706
707 moduleVol->AddNode(createFPC(), 0, new TGeoTranslation(0, fpcMidY, 0));
708 addConnector(moduleVol, connMidY);
709 addCapacitors(moduleVol, capMidY);
710 addBrackets(moduleVol, bracketMidY);
711 return moduleVol;
712}
713
715{
717 TGeoVolume* rowVol = new TGeoVolumeAssembly(rowName.c_str());
718
719 const int nModulesPerRow = mNumberOfModules / 2;
720 const double moduleLength = constants::OT::fpc::length;
721 const double step = moduleLength + constants::OT::interModuleGap;
722 const double rowHalfLen = getRowHalfLength();
723
724 for (int iModule = 0; iModule < nModulesPerRow; iModule++) {
725 double zPos = -rowHalfLen + moduleLength / 2 + iModule * step;
726 TGeoCombiTrans* trans = new TGeoCombiTrans();
727 trans->SetTranslation(0, 0, zPos);
728 rowVol->AddNode(createModule(), iModule, trans);
729 }
730
731 return rowVol;
732}
733
735{
737 TGeoVolume* staveVol = new TGeoVolumeAssembly(staveName.c_str());
738
739 // Two rows overlapping in phi and staggered in r. They straddle the stave origin, so the
740 // stave is tangent to the barrel circle at its centre and every row-to-row radial step,
741 // within a stave and between neighbours, is rowRadialStagger.
742 const double edgeDead = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut;
743 const double inStaveOverlap = 2 * edgeDead + constants::OT::rowActiveOverlap;
744 const double rowOffset = constants::OT::fpc::width - inStaveOverlap;
745
746 TGeoCombiTrans* tRow0 = new TGeoCombiTrans();
747 tRow0->SetTranslation(-rowOffset / 2, 0, 0);
748 staveVol->AddNode(createHalfStave(), 0, tRow0);
749 TGeoCombiTrans* tRow1 = new TGeoCombiTrans();
750 tRow1->SetTranslation(rowOffset / 2, constants::OT::rowRadialStagger, 0);
751 staveVol->AddNode(createHalfStave(), 1, tRow1);
752
753 // Shortened at the mid-rapidity end for the support ring, hence off-centre.
754 TGeoCombiTrans* tPipe = new TGeoCombiTrans();
755 tPipe->SetTranslation(0, constants::OT::coolingPipe::rLocalOffset, getPipeTrim() / 2);
756 staveVol->AddNode(createCoolingPipe(), 0, tPipe);
757
758 // Past the last module at the outer z end (local +z in both eta half-barrels).
759 TGeoCombiTrans* tCard = new TGeoCombiTrans();
760 tCard->SetTranslation(0, constants::OT::rowRadialStagger / 2,
762 staveVol->AddNode(createEndOfStaveCard(), 0, tCard);
763 return staveVol;
764}
765
766void TRKOTLayerRealistic::createLayer(TGeoVolume* motherVolume)
767{
768 const double edgeDead = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut;
769 const double inStaveOverlap = 2 * edgeDead + constants::OT::rowActiveOverlap;
770 const double staveWidth = 2 * constants::OT::fpc::width - inStaveOverlap;
771
772 // One eta half-barrel = one row of modules, length set by the FPC.
773 const double lengthHalfBarrel = 2 * getRowHalfLength();
774
775 // The envelope reaches past the last module to hold the end-of-stave cards.
776 const double halfLength = lengthHalfBarrel + constants::OT::barrelHalvesZGap / 2 + constants::OT::eosCard::zGap + constants::OT::eosCard::length;
777
778 // Cut on the vertical plane (x = 0) and at mid-rapidity into four quarter barrels. The
779 // envelope is slotted along both cuts so the separation walls run continuously in r; the
780 // slots clear the walls only, the staves stand back by barrelWallClearance.
781 const double wallThickness = TRKBaseParam::Instance().otBarrelWallThickness;
782 const bool hasWalls = wallThickness > 0.;
783 const double slotHalfWidth = wallThickness / 2 + constants::OT::barrelWallSlotMargin;
784 // The two mid-rapidity walls sit back to back, so the z slot must clear both.
785 const double zSlotHalfWidth = wallThickness + constants::OT::barrelWallSlotMargin;
786 if (hasWalls && zSlotHalfWidth >= constants::OT::barrelHalvesZGap / 2) {
787 LOGP(fatal, "TRKBase.otBarrelWallThickness = {} cm leaves no room for the staves in the {} cm gap between the eta half-barrels",
788 wallThickness, constants::OT::barrelHalvesZGap);
789 }
790
791 auto [rMin, rMax] = getBoundingRadii(staveWidth);
792 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
793 TGeoShape* layer = nullptr;
794 if (hasWalls) {
795 const std::string tubeName = mLayerName + "_envelopesh";
796 const std::string slotName = mLayerName + "_wallslotsh";
797 const std::string zSlotName = mLayerName + "_midslotsh";
798 new TGeoTube(tubeName.c_str(), rMin, rMax, halfLength);
799 new TGeoBBox(slotName.c_str(), slotHalfWidth, rMax + 1., halfLength + 1.);
800 new TGeoBBox(zSlotName.c_str(), rMax + 1., rMax + 1., zSlotHalfWidth);
801 layer = new TGeoCompositeShape((mLayerName + "sh").c_str(), (tubeName + "-" + slotName + "-" + zSlotName).c_str());
802 } else {
803 layer = new TGeoTube(rMin, rMax, halfLength);
804 }
805 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
806 layerVol->SetLineColor(kYellow);
807
808 const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius);
809
810 // Arc lost at each of the two azimuthal cuts: the wall plus the passive stave edge,
811 // never less than the bare chip-to-chip gap.
812 const double accGap = std::max(constants::OT::halfBarrelChipGap + 2 * constants::moduleMLOT::chip::passiveEdgeReadOut,
813 2 * (wallThickness / 2 + constants::OT::barrelWallClearance + edgeDead));
814
815 // Smallest even count still leaving rowActiveOverlap between neighbours: the two boundary
816 // staves take activeStaveWidth + accGap each, so only nStaves - 2 junctions share the rest.
817 const double activeStaveWidth = staveWidth - 2 * edgeDead;
818 int nStavesHalfBarrel = (int)std::ceil(2. + (avgRadius * 2 * TMath::Pi() - 2 * (activeStaveWidth + accGap)) /
819 (activeStaveWidth - constants::OT::rowActiveOverlap));
820 nStavesHalfBarrel += nStavesHalfBarrel % 2;
821
822 const int nHalf = nStavesHalfBarrel / 2;
823 const double thetaGap = (activeStaveWidth + accGap) / avgRadius;
824 const double thetaInt = (2. * TMath::Pi() - 2. * thetaGap) / (nStavesHalfBarrel - 2);
825 const double overlap = activeStaveWidth - avgRadius * thetaInt;
826 LOGP(info, "Creating realistic OT layer {}: {} staves/half-barrel, internal overlap {} mm, boundary gap {} mm, flipped={}",
827 mLayerNumber, nStavesHalfBarrel, overlap * 10, accGap * 10, mIsFlipped);
828
829 const int nStaves = nStavesHalfBarrel * 2;
830
831 for (int iStave = 0; iStave < nStaves; iStave++) {
832 int whichHalfBarrel = iStave / nStavesHalfBarrel;
833 int sInHB = iStave % nStavesHalfBarrel;
834 int azHalf = sInHB / nHalf;
835 int sInAz = sInHB % nHalf;
836
837 // Stave centres placed so the boundary gaps land on the cut plane, keeping the
838 // region where the beam-pipe supports run clear of staves in both half-barrels.
839 const double phiCut = TMath::Pi() / 2;
840 double phi = phiCut + azHalf * TMath::Pi() + thetaGap / 2 + sInAz * thetaInt;
841
842 TGeoRotation* rot = new TGeoRotation("rot");
843 rot->RotateX(180.); // cooling pipe faces the larger-R side (inner for the flipped layer); keeps local phi
844 if (whichHalfBarrel == 1) {
845 rot->RotateY(180.);
846 }
847 if (mIsFlipped) {
848 rot->RotateZ(180.);
849 }
850 rot->RotateZ(phi * TMath::RadToDeg() + 90 + (whichHalfBarrel == 0 ? +1 : -1) * mTiltAngle);
851
852 double zPos = (whichHalfBarrel == 0 ? -1 : 1) * (0.5 * lengthHalfBarrel + constants::OT::barrelHalvesZGap / 2);
853 TGeoCombiTrans* trans = new TGeoCombiTrans();
854 trans->SetRotation(rot);
855 trans->SetTranslation(avgRadius * std::cos(phi), avgRadius * std::sin(phi), zPos);
856 layerVol->AddNode(createStave(), iStave, trans);
857 }
858
859 // Support half-rings carrying the stave space frames, centred on the cooling pipe radius.
860 // One per quarter barrel per z end (mid-rapidity and under the end-of-stave cards): 8 per layer.
861 const double ringRMid = avgRadius + (mIsFlipped ? -1. : 1.) * constants::OT::coolingPipe::rLocalOffset;
862 const double ringRMin = ringRMid - constants::OT::supportRing::radialHeight / 2;
863 const double ringRMax = ringRMid + constants::OT::supportRing::radialHeight / 2;
864 // Stand off the cut plane by the same clearance the boundary staves keep.
865 const double ringDPhi = TMath::RadToDeg() *
866 std::asin((wallThickness / 2 + constants::OT::barrelWallClearance) / ringRMin);
867 const double zRingMid = wallThickness + constants::OT::supportRing::zClearance +
869 const double zRingEos = lengthHalfBarrel + constants::OT::barrelHalvesZGap / 2 +
871
872 for (int azHalf = 0; azHalf < 2; ++azHalf) {
873 TGeoVolume* ringVol = createSupportRing(ringRMin, ringRMax,
874 90. + 180. * azHalf + ringDPhi,
875 270. + 180. * azHalf - ringDPhi, azHalf);
876 int iRing = 0;
877 for (int whichHalfBarrel = 0; whichHalfBarrel < 2; ++whichHalfBarrel) {
878 const double zSign = (whichHalfBarrel == 0) ? -1. : 1.;
879 for (double zAbs : {zRingMid, zRingEos}) {
880 layerVol->AddNode(ringVol, iRing++, new TGeoTranslation(0., 0., zSign * zAbs));
881 }
882 }
883 }
884
885 motherVolume->AddNode(layerVol, 1, nullptr);
886}
887
888std::pair<float, float> TRKOTLayerRealistic::getBoundingRadii(double staveWidth) const
889{
890 auto [radiusMin, radiusMax] = TRKSegmentedLayer::getBoundingRadii(staveWidth);
894 const float outerReach = std::max(pipeOuterReach, ringReach);
895 const float margin = 0.1f;
896 if (!mIsFlipped) {
897 return {radiusMin - connectorReach - margin, radiusMax + outerReach + margin};
898 }
899 return {radiusMin - outerReach - margin, radiusMax + connectorReach + margin};
900}
901// ClassImp(TRKLayer);
902
903} // namespace trk
904} // namespace o2
std::ostringstream debug
float phiCut
Definition Tracker.cxx:213
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 * getTRKLayerPattern()
static const char * getTRKHalfStavePattern()
static const char * getTRKMetalStackPattern()
static const char * getTRKModulePattern()
static constexpr float Si_X0
Definition TRKLayer.h:64
virtual void createLayer(TGeoVolume *motherVolume)
Definition TRKLayer.cxx:73
virtual TGeoVolume * createSensor()
Definition TRKLayer.cxx:51
virtual TGeoVolume * createMetalStack()
Definition TRKLayer.cxx:62
static constexpr double sSensorThickness
Definition TRKLayer.h:62
void createLayer(TGeoVolume *motherVolume) override
Definition TRKLayer.cxx:306
TGeoVolume * createStave() override
Definition TRKLayer.cxx:248
TGeoVolume * createModule() override
Definition TRKLayer.cxx:672
TGeoVolume * createChip() override
Definition TRKLayer.cxx:508
void createLayer(TGeoVolume *motherVolume) override
Definition TRKLayer.cxx:766
TGeoVolume * createHalfStave()
Definition TRKLayer.cxx:714
TGeoVolume * createStave() override
Definition TRKLayer.cxx:734
TGeoVolume * createHalfStave()
Definition TRKLayer.cxx:419
void createLayer(TGeoVolume *motherVolume) override
Definition TRKLayer.cxx:455
static constexpr float sGapBetweenOuterTrackerBarrelHalves
Definition TRKLayer.h:146
TGeoVolume * createStave() override
Definition TRKLayer.cxx:439
static constexpr double sChipWidth
Definition TRKLayer.h:91
TGeoVolume * createMetalStack() override
Definition TRKLayer.cxx:122
static constexpr int sHalfNumberOfChips
Definition TRKLayer.h:96
TGeoVolume * createSensor() override
Definition TRKLayer.cxx:100
virtual TGeoVolume * createModule()
Definition TRKLayer.cxx:161
static constexpr double sChipLength
Definition TRKLayer.h:92
virtual TGeoVolume * createChip()
Definition TRKLayer.cxx:133
static constexpr double sDeadzoneWidth
Definition TRKLayer.h:93
static constexpr double sModuleLength
Definition TRKLayer.h:94
static constexpr double sModuleWidth
Definition TRKLayer.h:95
TGeoVolume * createDeadzone()
Definition TRKLayer.cxx:111
virtual std::pair< float, float > getBoundingRadii(double staveWidth) const
Definition TRKLayer.cxx:193
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum mode
Definition glcorearb.h:266
GLuint const GLchar * name
Definition glcorearb.h:781
GLint y
Definition glcorearb.h:270
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
constexpr double length
Definition Specs.h:114
constexpr double zGap
Definition Specs.h:119
constexpr int nCopperLayers
Definition Specs.h:117
constexpr double thickness
Definition Specs.h:116
constexpr double width
Definition Specs.h:115
constexpr int nLayers
Definition Specs.h:105
constexpr double length
Definition Specs.h:169
constexpr double thickness
Definition Specs.h:171
constexpr double width
Definition Specs.h:170
constexpr double thickness
Definition Specs.h:164
constexpr double thickness
Definition Specs.h:152
constexpr double thickness
Definition Specs.h:158
constexpr double rLocalOffset
Definition Specs.h:177
constexpr double width
Definition Specs.h:182
constexpr double length
Definition Specs.h:181
constexpr double zGap
Definition Specs.h:186
constexpr int nCopperLayers
Definition Specs.h:184
constexpr double thickness
Definition Specs.h:183
constexpr double width
Definition Specs.h:145
constexpr double thickness
Definition Specs.h:146
constexpr double length
Definition Specs.h:144
constexpr double radialHeight
Definition Specs.h:191
constexpr double wallThickness
Definition Specs.h:193
constexpr double sensorThickness
Definition Specs.h:197
constexpr double halfBarrelChipGap
Definition Specs.h:201
constexpr double bracketZDepth
Definition Specs.h:205
constexpr double interModuleGap
Definition Specs.h:139
constexpr double rowActiveOverlap
Definition Specs.h:199
constexpr double connectorZDepth
Definition Specs.h:204
constexpr double interChipGap
Definition Specs.h:198
constexpr double rowRadialStagger
Definition Specs.h:200
constexpr double barrelWallClearance
Definition Specs.h:202
constexpr double barrelWallSlotMargin
Definition Specs.h:203
constexpr double barrelHalvesZGap
Definition Specs.h:206
constexpr double outerEdgeLongSide
Definition Specs.h:94
constexpr double outerEdgeShortSide
Definition Specs.h:95
MatBudgetParamMode
Definition TRKLayer.h:27
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