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 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
252 TGeoShape* stave = new TGeoBBox(sStaveWidth / 2, mChipThickness / 2, mLength / 2);
253 TGeoVolume* staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
254 staveVol->SetLineColor(kYellow);
255
256 for (int iModule = 0; iModule < mNumberOfModules; iModule++) {
257 TGeoVolume* moduleVol = createModule();
258 double zPos = -0.5 * mNumberOfModules * sModuleLength + (iModule + 0.5) * sModuleLength;
259 TGeoCombiTrans* trans = new TGeoCombiTrans();
260 trans->SetTranslation(0, 0, zPos);
261 LOGP(debug, "Inserting {} in {} ", moduleVol->GetName(), staveVol->GetName());
262 staveVol->AddNode(moduleVol, iModule, trans);
263 }
264
265 return staveVol;
266}
267
268void TRKMLLayer::createLayer(TGeoVolume* motherVolume)
269{
270 // Retrieve exact bounding boundaries and create the logical container volume
271 auto [rMin, rMax] = getBoundingRadii(sStaveWidth);
272
273 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
274 // TGeoTube* layer = new TGeoTube(mInnerRadius - 0.333 * sLogicalVolumeThickness, mInnerRadius + 0.667 * sLogicalVolumeThickness, mLength / 2);
275 TGeoTube* layer = new TGeoTube(rMin, rMax, mLength / 2);
276 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
277 layerVol->SetLineColor(kYellow);
278
279 // Compute the number of staves
280 // int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / sStaveWidth);
281 // nStaves += nStaves % 2; // Require an even number of staves
282
283 // Nominal average radii used as placement barycenters for the staves
284 const double avgRadiusInner = 0.5 * (mInnerRadius + mOuterRadius);
285 const double avgRadiusOuter = avgRadiusInner + mStaggerOffset;
286
287 // Compute the size of the overlap region
288 double theta = 2. * TMath::Pi() / mNumberOfStaves;
289 double theta1 = std::atan(sStaveWidth / 2 / mInnerRadius);
290 double st = std::sin(theta);
291 double ct = std::cos(theta);
292 double theta2 = std::atan((mInnerRadius * st - sStaveWidth / 2 * ct) / (mInnerRadius * ct + sStaveWidth / 2 * st));
293 double overlap = (theta1 - theta2) * mInnerRadius;
294 LOGP(info, "Creating a layer with {} staves and {} mm overlap", mNumberOfStaves, overlap * 10);
295
296 for (int iStave = 0; iStave < mNumberOfStaves; iStave++) {
297 TGeoVolume* staveVol = createStave();
298 TGeoCombiTrans* trans = new TGeoCombiTrans();
299 // 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
300 double phi = (mNumberOfStaves % 4 == 0) ? theta * (iStave + 0.5) : theta * iStave;
301 double phiDeg = phi * TMath::RadToDeg();
302 TGeoRotation* rot = new TGeoRotation("rot", phiDeg + 90 + mTiltAngle, 0, 0);
303 trans->SetRotation(rot);
304 // float trueRadius = (mLayerNumber == 3 || mLayerNumber == 4) ? (iStave % 2 == 0 ? mInnerRadius : mInnerRadius + mStaggerOffset) : mInnerRadius;
305 float trueRadius = (mLayerNumber == 3 || mLayerNumber == 4) ? (iStave % 2 == 0 ? avgRadiusInner : avgRadiusOuter) : avgRadiusInner;
306 trans->SetTranslation(trueRadius * std::cos(phi), trueRadius * std::sin(phi), 0);
307 LOGP(debug, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
308 layerVol->AddNode(staveVol, iStave, trans);
309 }
310
311 LOGP(debug, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
312 motherVolume->AddNode(layerVol, 1, nullptr);
313}
314
315std::pair<float, float> TRKMLLayer::getBoundingRadii(double staveWidth) const
316{
317 // Get the baseline RMin from the base class
318 auto [defaultRadiusMin, defaultRadiusMax] = TRKSegmentedLayer::getBoundingRadii(staveWidth);
319
320 // If we are not in the staggered layers, return the baseline values
321 if (mLayerNumber != 3 && mLayerNumber != 4) {
322 return {defaultRadiusMin, defaultRadiusMax};
323 }
324
325 /*// For staggered layers, we must recalculate RMax based on the outer shifted row
326 const float avgRadiusInner = 0.5 * (mInnerRadius + mOuterRadius);
327 const float avgRadiusOuter = avgRadiusInner + mStaggerOffset;
328
329 const float staveSizeX = staveWidth;
330 const float staveSizeY = mOuterRadius - mInnerRadius;
331
332 const float deltaForTiltOuter = 0.5 * (std::sin(TMath::DegToRad() * mTiltAngle) * staveSizeX + std::cos(TMath::DegToRad() * mTiltAngle) * staveSizeY);
333
334 const float radiusMax = std::sqrt(avgRadiusOuter * avgRadiusOuter + 0.25 * staveSizeX * staveSizeX + 0.25 * staveSizeY * staveSizeY + avgRadiusOuter * 2. * deltaForTiltOuter);*/
335
336 const float avgRadiusInner = 0.5 * (mInnerRadius + mOuterRadius);
337 const float avgRadiusStaggered = avgRadiusInner + mStaggerOffset;
338
339 const float staveSizeX = staveWidth;
340 const float staveSizeY = mOuterRadius - mInnerRadius;
341 const float alpha = TMath::DegToRad() * std::abs(mTiltAngle);
342
343 const float precisionMargin = 0.05f;
344
345 // If the layer is NOT flipped (e.g., Layer 4), the stagger goes outwards
346 // Therefore, we must recalculate only the maximum radius based on the outer shifted row
347 if (!mIsFlipped) {
348 float u_max = avgRadiusStaggered * std::sin(alpha) + staveSizeX / 2.0;
349 float v_max = avgRadiusStaggered * std::cos(alpha) + staveSizeY / 2.0;
350 float radiusMax = std::sqrt(u_max * u_max + v_max * v_max);
351
352 return {defaultRadiusMin, radiusMax + precisionMargin};
353 }
354 // If the layer IS flipped (e.g., Layer 3), the stagger goes inwards
355 // Therefore, we must recalculate only the minimum radius based on the inner shifted row
356 else {
357 double perpDistance = avgRadiusStaggered * std::cos(alpha) - staveSizeY / 2.0;
358 double projDistance = avgRadiusStaggered * std::sin(alpha);
359 double newRadiusMin;
360
361 if (projDistance <= staveSizeX / 2.0) {
362 newRadiusMin = perpDistance;
363 } else {
364 double u_min = projDistance - staveSizeX / 2.0;
365 newRadiusMin = std::sqrt(u_min * u_min + perpDistance * perpDistance);
366 }
367
368 return {newRadiusMin - precisionMargin, defaultRadiusMax};
369 }
370}
371
373
374TRKOTLayer::TRKOTLayer(int layerNumber, std::string layerName, float rInn, float tiltAngle, int numberOfStaves, int numberOfModules, float thickOrX2X0, MatBudgetParamMode mode)
375 : TRKSegmentedLayer(layerNumber, layerName, rInn, tiltAngle, numberOfStaves, numberOfModules, thickOrX2X0, mode)
376{
377}
378
380{
381 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
383 float lengthHalfBarrel = mLength / 2;
384 TGeoShape* halfStave = new TGeoBBox(sHalfStaveWidth / 2, mChipThickness / 2, lengthHalfBarrel / 2);
385 TGeoVolume* halfStaveVol = new TGeoVolume(halfStaveName.c_str(), halfStave, medSi);
386 halfStaveVol->SetLineColor(kYellow);
387
388 int nModulesPerHalfBarrel = mNumberOfModules / 2;
389 for (int iModule = 0; iModule < nModulesPerHalfBarrel; iModule++) {
390 double zPos = -0.5 * nModulesPerHalfBarrel * sModuleLength + (iModule + 0.5) * sModuleLength;
391 TGeoCombiTrans* trans = new TGeoCombiTrans();
392 trans->SetTranslation(0, 0, zPos);
393 halfStaveVol->AddNode(createModule(), iModule, trans);
394 }
395
396 return halfStaveVol;
397}
398
400{
402 TGeoVolume* staveVol = new TGeoVolumeAssembly(staveName.c_str());
403
404 TGeoCombiTrans* transLeft = new TGeoCombiTrans();
405 transLeft->SetTranslation(-(sHalfStaveWidth - sInStaveOverlap) / 2, 0, 0);
406 staveVol->AddNode(createHalfStave(), 0, transLeft);
407
408 TGeoCombiTrans* transRight = new TGeoCombiTrans();
409 transRight->SetTranslation((sHalfStaveWidth - sInStaveOverlap) / 2, 0.2, 0);
410 staveVol->AddNode(createHalfStave(), 1, transRight);
411
412 return staveVol;
413}
414
415void TRKOTLayer::createLayer(TGeoVolume* motherVolume)
416{
417 auto [rMin, rMax] = getBoundingRadii(sStaveWidth);
418
419 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
420 TGeoTube* layer = new TGeoTube(rMin, rMax, (mLength + sGapBetweenOuterTrackerBarrelHalves) / 2);
421 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
422 layerVol->SetLineColor(kYellow);
423
424 int nStavesHalfBarrel = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / sStaveWidth);
425 nStavesHalfBarrel += nStavesHalfBarrel % 2;
426
427 const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius);
428 const double theta = 2. * TMath::Pi() / nStavesHalfBarrel;
429 const float lengthHalfBarrel = mLength / 2;
430 const int nStaves = nStavesHalfBarrel * 2;
431 LOGP(info, "Creating OT layer {} with two half-barrels of {} staves each", mLayerNumber, nStavesHalfBarrel);
432
433 for (int iStave = 0; iStave < nStaves; iStave++) {
434 int whichHalfBarrel = iStave / nStavesHalfBarrel;
435 double phi = theta * iStave;
436 TGeoRotation* rot = new TGeoRotation("rot");
437 if (whichHalfBarrel == 1) {
438 rot->RotateY(180.);
439 }
440 rot->RotateZ(phi * TMath::RadToDeg() + 90 + (whichHalfBarrel == 0 ? +1 : -1) * mTiltAngle);
441 double zPos = (whichHalfBarrel == 0 ? -1 : 1) * (0.5 * lengthHalfBarrel + sGapBetweenOuterTrackerBarrelHalves / 2);
442 TGeoCombiTrans* trans = new TGeoCombiTrans();
443 trans->SetRotation(rot);
444 trans->SetTranslation(avgRadius * std::cos(phi), avgRadius * std::sin(phi), zPos);
445 layerVol->AddNode(createStave(), iStave, trans);
446 }
447
448 motherVolume->AddNode(layerVol, 1, nullptr);
449}
450
451std::pair<float, float> TRKOTLayer::getBoundingRadii(double staveWidth) const
452{
453 auto [radiusMin, radiusMax] = TRKSegmentedLayer::getBoundingRadii(staveWidth);
454 return {radiusMin - 0.201f, radiusMax};
455}
456
458
459TRKOTLayerRealistic::TRKOTLayerRealistic(int layerNumber, std::string layerName, float rInn, float tiltAngle, int numberOfStaves, int numberOfModules, float thickOrX2X0, MatBudgetParamMode mode)
460 : TRKSegmentedLayer(layerNumber, layerName, rInn, tiltAngle, numberOfStaves, numberOfModules, thickOrX2X0, mode)
461{
462 // Outermost layer is flipped: cooling pipe and support rings on the inner side.
464 mIsFlipped = true;
465 }
466}
467
469{
470 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
472 TGeoShape* chip = new TGeoBBox(sChipWidth / 2, constants::OT::sensorThickness / 2, sChipLength / 2);
473 TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
474 chipVol->SetLineColor(kYellow);
475
476 // Active sensor and passive read-out edge tile the chip width.
477 chipVol->AddNode(createSensor(), 1, new TGeoTranslation(-sDeadzoneWidth / 2, 0, 0));
478 chipVol->AddNode(createDeadzone(), 1, new TGeoTranslation((sChipWidth - sDeadzoneWidth) / 2, 0, 0));
479 return chipVol;
480}
481
482TGeoVolume* TRKOTLayerRealistic::createFPC()
483{
484 TGeoMedium* med = gGeoManager->GetMedium("TRK_FPC$");
486 TGeoVolume* vol = new TGeoVolume((GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber) + "_FPC").c_str(), shape, med);
487 vol->SetLineColor(kOrange);
488 return vol;
489}
490
491TGeoVolume* TRKOTLayerRealistic::createColdPlate()
492{
493 TGeoMedium* med = gGeoManager->GetMedium("TRK_CARBONFIBER$");
495 TGeoVolume* vol = new TGeoVolume((GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber) + "_ColdPlate").c_str(), shape, med);
496 vol->SetLineColor(kGray + 2);
497 return vol;
498}
499
500double TRKOTLayerRealistic::getRowHalfLength() const
501{
502 const int nModulesPerRow = mNumberOfModules / 2;
503 return (nModulesPerRow * constants::OT::fpc::length + (nModulesPerRow - 1) * constants::OT::interModuleGap) / 2;
504}
505
506double TRKOTLayerRealistic::getPipeTrim() const
507{
508 // The mid-rapidity ring sits at the pipe radius, between the z = 0 wall and the pipe.
509 const double wallThickness = TRKBaseParam::Instance().otBarrelWallThickness;
511 return std::max(0., pipeStart - constants::OT::barrelHalvesZGap / 2);
512}
513
514TGeoVolume* TRKOTLayerRealistic::createSupportRing(double rMin, double rMax, double phi1, double phi2, int id)
515{
516 // Hollow rectangular-section half-ring, open at the two azimuthal ends.
517 TGeoMedium* med = gGeoManager->GetMedium("TRK_CARBONFIBER$");
519 const double dz = constants::OT::supportRing::zWidth / 2;
520 const std::string base = GeometryTGeo::getTRKLayerPattern() + std::to_string(mLayerNumber) + "_SupportRing" + std::to_string(id);
521 new TGeoTubeSeg((base + "_outsh").c_str(), rMin, rMax, dz, phi1, phi2);
522 new TGeoTubeSeg((base + "_insh").c_str(), rMin + t, rMax - t, dz - t, phi1, phi2);
523 TGeoShape* shape = new TGeoCompositeShape((base + "sh").c_str(), (base + "_outsh-" + base + "_insh").c_str());
524 TGeoVolume* vol = new TGeoVolume(base.c_str(), shape, med);
525 vol->SetLineColor(kGray + 2);
526 return vol;
527}
528
529TGeoVolume* TRKOTLayerRealistic::createCoolingPipe()
530{
531 TGeoMedium* med = gGeoManager->GetMedium("TRK_CARBONFIBER$");
533 getRowHalfLength() - getPipeTrim() / 2);
534 TGeoVolume* vol = new TGeoVolume((GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber) + "_CoolingPipe").c_str(), tube, med);
535 vol->SetLineColor(kBlue + 2);
536 return vol;
537}
538
539TGeoVolume* TRKOTLayerRealistic::createEndOfStaveCard()
540{
541 TGeoMedium* medFR4 = gGeoManager->GetMedium("TRK_FR4$");
542 TGeoMedium* medCu = gGeoManager->GetMedium("TRK_COPPER$");
543 const std::string name = GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber) + "_EOSCard";
544
546 TGeoVolume* cardVol = new TGeoVolume(name.c_str(), board, medFR4);
547 cardVol->SetLineColor(kGreen + 3);
548
549 // Copper thickness is configurable: it displaces FR4 inside the fixed board envelope and
550 // is what sets the card material budget, so it is the knob for x/X0 scans.
551 const double cuThickness = TRKBaseParam::Instance().otEosCardCuThickness;
552 const int nPlanes = constants::OT::eosCard::nCopperLayers;
553 if (cuThickness * nPlanes >= constants::OT::eosCard::thickness) {
554 LOGP(fatal, "TRKBase.otEosCardCuThickness = {} cm x {} planes does not fit in the {} cm end-of-stave card",
555 cuThickness, nPlanes, constants::OT::eosCard::thickness);
556 }
557 TGeoShape* plane = new TGeoBBox(constants::OT::eosCard::width / 2, cuThickness / 2, constants::OT::eosCard::length / 2);
558 TGeoVolume* planeVol = new TGeoVolume((name + "_Cu").c_str(), plane, medCu);
559 planeVol->SetLineColor(kOrange + 7);
560
561 // Evenly spaced, the outermost two flush with the board surfaces.
562 const double span = constants::OT::eosCard::thickness - cuThickness;
563 for (int iPlane = 0; iPlane < nPlanes; iPlane++) {
564 const double y = (nPlanes > 1) ? -span / 2 + iPlane * span / (nPlanes - 1) : 0.;
565 cardVol->AddNode(planeVol, iPlane, new TGeoTranslation(0, y, 0));
566 }
567
568 return cardVol;
569}
570
571void TRKOTLayerRealistic::addConnector(TGeoVolume* moduleVol, double rMid)
572{
573 TGeoMedium* med = gGeoManager->GetMedium("TRK_LCPCU$");
574 std::string name = GeometryTGeo::getTRKModulePattern() + std::to_string(mLayerNumber) + "_Connector";
576 TGeoVolume* vol = new TGeoVolume(name.c_str(), shape, med);
577 vol->SetLineColor(kBlue);
578
579 // Centred in phi, inset from the module short edge in z.
581 moduleVol->AddNode(vol, 0, new TGeoTranslation(0, rMid, z));
582}
583
584void TRKOTLayerRealistic::addCapacitors(TGeoVolume* moduleVol, double rMid)
585{
586 TGeoMedium* med = gGeoManager->GetMedium("TRK_BATIO3$");
589 TGeoVolume* vol = new TGeoVolume(name.c_str(), shape, med);
590 vol->SetLineColor(kCyan);
591
594 const double chipX[2] = {-0.5 * pitchX, +0.5 * pitchX};
595 const double chipZ[4] = {-1.5 * pitchZ, -0.5 * pitchZ, +0.5 * pitchZ, +1.5 * pitchZ};
596 const double dX[5] = {-0.80, +0.80, -0.80, +0.80, 0.0}; // per chip: 4 corners + centre [cm]
597 const double dZ[5] = {-0.95, -0.95, +0.95, +0.95, 0.0};
598
599 // Skip capacitors that fall under the connector footprint (+1 mm clearance).
601 const double skipX = constants::OT::connector::width / 2 + constants::OT::capacitor::width / 2 + 0.1;
602 const double skipZ = constants::OT::connector::length / 2 + constants::OT::capacitor::length / 2 + 0.1;
603
604 int capCopy = 0;
605 for (int iZ = 0; iZ < 4; iZ++) {
606 for (int iX = 0; iX < 2; iX++) {
607 for (int iCap = 0; iCap < constants::OT::capacitor::perChip; iCap++) {
608 const double x = chipX[iX] + dX[iCap];
609 const double z = chipZ[iZ] + dZ[iCap];
610 if (std::abs(x) < skipX && std::abs(z - connZ) < skipZ) {
611 continue;
612 }
613 moduleVol->AddNode(vol, capCopy++, new TGeoTranslation(x, rMid, z));
614 }
615 }
616 }
617}
618
619void TRKOTLayerRealistic::addBrackets(TGeoVolume* moduleVol, double rMid)
620{
621 TGeoMedium* med = gGeoManager->GetMedium("TRK_PEEK$");
624 TGeoVolume* vol = new TGeoVolume(name.c_str(), shape, med);
625 vol->SetLineColor(kGreen + 2);
626
628 moduleVol->AddNode(vol, 0, new TGeoTranslation(0, rMid, -z));
629 moduleVol->AddNode(vol, 1, new TGeoTranslation(0, rMid, +z));
630}
631
633{
635 TGeoVolume* moduleVol = new TGeoVolumeAssembly(modName.c_str());
636
637 // Flush component stack about the chip mid-plane (local r = 0).
638 const double chipHalf = constants::OT::sensorThickness / 2;
639 const double fpcMidY = -(chipHalf + constants::OT::fpc::thickness / 2);
640 const double coldPlateMidY = +(chipHalf + constants::OT::coldPlate::thickness / 2);
641 const double connMidY = -(chipHalf + constants::OT::fpc::thickness + constants::OT::connector::thickness / 2);
642 const double capMidY = -(chipHalf + constants::OT::fpc::thickness + constants::OT::capacitor::thickness / 2);
643 const double bracketMidY = +(chipHalf + constants::OT::coldPlate::thickness + constants::OT::bracket::thickness / 2);
644
645 // 8 chips: 2 phi columns x 4 z rows, on a uniform chip+gap pitch.
646 const double pitchX = sChipWidth + constants::OT::interChipGap;
647 const double pitchZ = sChipLength + constants::OT::interChipGap;
648 const double chipX[2] = {-0.5 * pitchX, +0.5 * pitchX};
649 const double chipZ[4] = {-1.5 * pitchZ, -0.5 * pitchZ, +0.5 * pitchZ, +1.5 * pitchZ};
650
651 moduleVol->AddNode(createColdPlate(), 0, new TGeoTranslation(0, coldPlateMidY, 0));
652
653 int chipCopy = 0;
654 for (int iZ = 0; iZ < 4; iZ++) {
655 for (int iX = 0; iX < 2; iX++) {
656 TGeoCombiTrans* trans = new TGeoCombiTrans();
657 trans->SetTranslation(chipX[iX], 0., chipZ[iZ]);
658 if (iX == 0) { // inner column rotated so its dead zone faces the outer module edge
659 TGeoRotation* rot = new TGeoRotation();
660 rot->RotateY(180.);
661 trans->SetRotation(rot);
662 }
663 moduleVol->AddNode(createChip(), chipCopy++, trans);
664 }
665 }
666
667 moduleVol->AddNode(createFPC(), 0, new TGeoTranslation(0, fpcMidY, 0));
668 addConnector(moduleVol, connMidY);
669 addCapacitors(moduleVol, capMidY);
670 addBrackets(moduleVol, bracketMidY);
671 return moduleVol;
672}
673
675{
677 TGeoVolume* rowVol = new TGeoVolumeAssembly(rowName.c_str());
678
679 const int nModulesPerRow = mNumberOfModules / 2;
680 const double moduleLength = constants::OT::fpc::length;
681 const double step = moduleLength + constants::OT::interModuleGap;
682 const double rowHalfLen = getRowHalfLength();
683
684 for (int iModule = 0; iModule < nModulesPerRow; iModule++) {
685 double zPos = -rowHalfLen + moduleLength / 2 + iModule * step;
686 TGeoCombiTrans* trans = new TGeoCombiTrans();
687 trans->SetTranslation(0, 0, zPos);
688 rowVol->AddNode(createModule(), iModule, trans);
689 }
690
691 return rowVol;
692}
693
695{
697 TGeoVolume* staveVol = new TGeoVolumeAssembly(staveName.c_str());
698
699 // Two rows overlapping in phi and staggered in r. They straddle the stave origin, so the
700 // stave is tangent to the barrel circle at its centre and every row-to-row radial step,
701 // within a stave and between neighbours, is rowRadialStagger.
702 const double edgeDead = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut;
703 const double inStaveOverlap = 2 * edgeDead + constants::OT::rowActiveOverlap;
704 const double rowOffset = constants::OT::fpc::width - inStaveOverlap;
705
706 TGeoCombiTrans* tRow0 = new TGeoCombiTrans();
707 tRow0->SetTranslation(-rowOffset / 2, 0, 0);
708 staveVol->AddNode(createHalfStave(), 0, tRow0);
709 TGeoCombiTrans* tRow1 = new TGeoCombiTrans();
710 tRow1->SetTranslation(rowOffset / 2, constants::OT::rowRadialStagger, 0);
711 staveVol->AddNode(createHalfStave(), 1, tRow1);
712
713 // Shortened at the mid-rapidity end for the support ring, hence off-centre.
714 TGeoCombiTrans* tPipe = new TGeoCombiTrans();
715 tPipe->SetTranslation(0, constants::OT::coolingPipe::rLocalOffset, getPipeTrim() / 2);
716 staveVol->AddNode(createCoolingPipe(), 0, tPipe);
717
718 // Past the last module at the outer z end (local +z in both eta half-barrels).
719 TGeoCombiTrans* tCard = new TGeoCombiTrans();
720 tCard->SetTranslation(0, constants::OT::rowRadialStagger / 2,
722 staveVol->AddNode(createEndOfStaveCard(), 0, tCard);
723 return staveVol;
724}
725
726void TRKOTLayerRealistic::createLayer(TGeoVolume* motherVolume)
727{
728 const double edgeDead = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut;
729 const double inStaveOverlap = 2 * edgeDead + constants::OT::rowActiveOverlap;
730 const double staveWidth = 2 * constants::OT::fpc::width - inStaveOverlap;
731
732 // One eta half-barrel = one row of modules, length set by the FPC.
733 const double lengthHalfBarrel = 2 * getRowHalfLength();
734
735 // The envelope reaches past the last module to hold the end-of-stave cards.
736 const double halfLength = lengthHalfBarrel + constants::OT::barrelHalvesZGap / 2 + constants::OT::eosCard::zGap + constants::OT::eosCard::length;
737
738 // Cut on the vertical plane (x = 0) and at mid-rapidity into four quarter barrels. The
739 // envelope is slotted along both cuts so the separation walls run continuously in r; the
740 // slots clear the walls only, the staves stand back by barrelWallClearance.
741 const double wallThickness = TRKBaseParam::Instance().otBarrelWallThickness;
742 const bool hasWalls = wallThickness > 0.;
743 const double slotHalfWidth = wallThickness / 2 + constants::OT::barrelWallSlotMargin;
744 // The two mid-rapidity walls sit back to back, so the z slot must clear both.
745 const double zSlotHalfWidth = wallThickness + constants::OT::barrelWallSlotMargin;
746 if (hasWalls && zSlotHalfWidth >= constants::OT::barrelHalvesZGap / 2) {
747 LOGP(fatal, "TRKBase.otBarrelWallThickness = {} cm leaves no room for the staves in the {} cm gap between the eta half-barrels",
748 wallThickness, constants::OT::barrelHalvesZGap);
749 }
750
751 auto [rMin, rMax] = getBoundingRadii(staveWidth);
752 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
753 TGeoShape* layer = nullptr;
754 if (hasWalls) {
755 const std::string tubeName = mLayerName + "_envelopesh";
756 const std::string slotName = mLayerName + "_wallslotsh";
757 const std::string zSlotName = mLayerName + "_midslotsh";
758 new TGeoTube(tubeName.c_str(), rMin, rMax, halfLength);
759 new TGeoBBox(slotName.c_str(), slotHalfWidth, rMax + 1., halfLength + 1.);
760 new TGeoBBox(zSlotName.c_str(), rMax + 1., rMax + 1., zSlotHalfWidth);
761 layer = new TGeoCompositeShape((mLayerName + "sh").c_str(), (tubeName + "-" + slotName + "-" + zSlotName).c_str());
762 } else {
763 layer = new TGeoTube(rMin, rMax, halfLength);
764 }
765 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
766 layerVol->SetLineColor(kYellow);
767
768 const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius);
769
770 // Arc lost at each of the two azimuthal cuts: the wall plus the passive stave edge,
771 // never less than the bare chip-to-chip gap.
772 const double accGap = std::max(constants::OT::halfBarrelChipGap + 2 * constants::moduleMLOT::chip::passiveEdgeReadOut,
773 2 * (wallThickness / 2 + constants::OT::barrelWallClearance + edgeDead));
774
775 // Smallest even count still leaving rowActiveOverlap between neighbours: the two boundary
776 // staves take activeStaveWidth + accGap each, so only nStaves - 2 junctions share the rest.
777 const double activeStaveWidth = staveWidth - 2 * edgeDead;
778 int nStavesHalfBarrel = (int)std::ceil(2. + (avgRadius * 2 * TMath::Pi() - 2 * (activeStaveWidth + accGap)) /
779 (activeStaveWidth - constants::OT::rowActiveOverlap));
780 nStavesHalfBarrel += nStavesHalfBarrel % 2;
781
782 const int nHalf = nStavesHalfBarrel / 2;
783 const double thetaGap = (activeStaveWidth + accGap) / avgRadius;
784 const double thetaInt = (2. * TMath::Pi() - 2. * thetaGap) / (nStavesHalfBarrel - 2);
785 const double overlap = activeStaveWidth - avgRadius * thetaInt;
786 LOGP(info, "Creating realistic OT layer {}: {} staves/half-barrel, internal overlap {} mm, boundary gap {} mm, flipped={}",
787 mLayerNumber, nStavesHalfBarrel, overlap * 10, accGap * 10, mIsFlipped);
788
789 const int nStaves = nStavesHalfBarrel * 2;
790
791 for (int iStave = 0; iStave < nStaves; iStave++) {
792 int whichHalfBarrel = iStave / nStavesHalfBarrel;
793 int sInHB = iStave % nStavesHalfBarrel;
794 int azHalf = sInHB / nHalf;
795 int sInAz = sInHB % nHalf;
796
797 // Stave centres placed so the boundary gaps land on the cut plane, keeping the
798 // region where the beam-pipe supports run clear of staves in both half-barrels.
799 const double phiCut = TMath::Pi() / 2;
800 double phi = phiCut + azHalf * TMath::Pi() + thetaGap / 2 + sInAz * thetaInt;
801
802 TGeoRotation* rot = new TGeoRotation("rot");
803 rot->RotateX(180.); // cooling pipe faces the larger-R side (inner for the flipped layer); keeps local phi
804 if (whichHalfBarrel == 1) {
805 rot->RotateY(180.);
806 }
807 if (mIsFlipped) {
808 rot->RotateZ(180.);
809 }
810 rot->RotateZ(phi * TMath::RadToDeg() + 90 + (whichHalfBarrel == 0 ? +1 : -1) * mTiltAngle);
811
812 double zPos = (whichHalfBarrel == 0 ? -1 : 1) * (0.5 * lengthHalfBarrel + constants::OT::barrelHalvesZGap / 2);
813 TGeoCombiTrans* trans = new TGeoCombiTrans();
814 trans->SetRotation(rot);
815 trans->SetTranslation(avgRadius * std::cos(phi), avgRadius * std::sin(phi), zPos);
816 layerVol->AddNode(createStave(), iStave, trans);
817 }
818
819 // Support half-rings carrying the stave space frames, centred on the cooling pipe radius.
820 // One per quarter barrel per z end (mid-rapidity and under the end-of-stave cards): 8 per layer.
821 const double ringRMid = avgRadius + (mIsFlipped ? -1. : 1.) * constants::OT::coolingPipe::rLocalOffset;
822 const double ringRMin = ringRMid - constants::OT::supportRing::radialHeight / 2;
823 const double ringRMax = ringRMid + constants::OT::supportRing::radialHeight / 2;
824 // Stand off the cut plane by the same clearance the boundary staves keep.
825 const double ringDPhi = TMath::RadToDeg() *
826 std::asin((wallThickness / 2 + constants::OT::barrelWallClearance) / ringRMin);
827 const double zRingMid = wallThickness + constants::OT::supportRing::zClearance +
829 const double zRingEos = lengthHalfBarrel + constants::OT::barrelHalvesZGap / 2 +
831
832 for (int azHalf = 0; azHalf < 2; ++azHalf) {
833 TGeoVolume* ringVol = createSupportRing(ringRMin, ringRMax,
834 90. + 180. * azHalf + ringDPhi,
835 270. + 180. * azHalf - ringDPhi, azHalf);
836 int iRing = 0;
837 for (int whichHalfBarrel = 0; whichHalfBarrel < 2; ++whichHalfBarrel) {
838 const double zSign = (whichHalfBarrel == 0) ? -1. : 1.;
839 for (double zAbs : {zRingMid, zRingEos}) {
840 layerVol->AddNode(ringVol, iRing++, new TGeoTranslation(0., 0., zSign * zAbs));
841 }
842 }
843 }
844
845 motherVolume->AddNode(layerVol, 1, nullptr);
846}
847
848std::pair<float, float> TRKOTLayerRealistic::getBoundingRadii(double staveWidth) const
849{
850 auto [radiusMin, radiusMax] = TRKSegmentedLayer::getBoundingRadii(staveWidth);
854 const float outerReach = std::max(pipeOuterReach, ringReach);
855 const float margin = 0.1f;
856 if (!mIsFlipped) {
857 return {radiusMin - connectorReach - margin, radiusMax + outerReach + margin};
858 }
859 return {radiusMin - outerReach - margin, radiusMax + connectorReach + margin};
860}
861// ClassImp(TRKLayer);
862
863} // namespace trk
864} // 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 * 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:268
TGeoVolume * createStave() override
Definition TRKLayer.cxx:248
TGeoVolume * createModule() override
Definition TRKLayer.cxx:632
TGeoVolume * createChip() override
Definition TRKLayer.cxx:468
void createLayer(TGeoVolume *motherVolume) override
Definition TRKLayer.cxx:726
TGeoVolume * createHalfStave()
Definition TRKLayer.cxx:674
TGeoVolume * createStave() override
Definition TRKLayer.cxx:694
TGeoVolume * createHalfStave()
Definition TRKLayer.cxx:379
void createLayer(TGeoVolume *motherVolume) override
Definition TRKLayer.cxx:415
static constexpr float sGapBetweenOuterTrackerBarrelHalves
Definition TRKLayer.h:144
TGeoVolume * createStave() override
Definition TRKLayer.cxx:399
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
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 int nLayers
Definition Specs.h:105
constexpr double length
Definition Specs.h:159
constexpr double thickness
Definition Specs.h:161
constexpr double width
Definition Specs.h:160
constexpr double thickness
Definition Specs.h:154
constexpr double thickness
Definition Specs.h:142
constexpr double thickness
Definition Specs.h:148
constexpr double rLocalOffset
Definition Specs.h:167
constexpr double width
Definition Specs.h:172
constexpr double length
Definition Specs.h:171
constexpr double zGap
Definition Specs.h:176
constexpr int nCopperLayers
Definition Specs.h:174
constexpr double thickness
Definition Specs.h:173
constexpr double width
Definition Specs.h:135
constexpr double thickness
Definition Specs.h:136
constexpr double length
Definition Specs.h:134
constexpr double radialHeight
Definition Specs.h:181
constexpr double wallThickness
Definition Specs.h:183
constexpr double sensorThickness
Definition Specs.h:187
constexpr double halfBarrelChipGap
Definition Specs.h:191
constexpr double bracketZDepth
Definition Specs.h:195
constexpr double interModuleGap
Definition Specs.h:129
constexpr double rowActiveOverlap
Definition Specs.h:189
constexpr double connectorZDepth
Definition Specs.h:194
constexpr double interChipGap
Definition Specs.h:188
constexpr double rowRadialStagger
Definition Specs.h:190
constexpr double barrelWallClearance
Definition Specs.h:192
constexpr double barrelWallSlotMargin
Definition Specs.h:193
constexpr double barrelHalvesZGap
Definition Specs.h:196
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