Project
Loading...
Searching...
No Matches
FT3Layer.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
16
21
22#include <TGeoManager.h> // for TGeoManager, gGeoManager
23#include <TGeoMatrix.h> // for TGeoCombiTrans, TGeoRotation, etc
24#include <TGeoTube.h> // for TGeoTube, TGeoTubeSeg
25#include <TGeoArb8.h> // for TGeoTrap
26#include <TGeoVolume.h> // for TGeoVolume, TGeoVolumeAssembly
27#include <TGeoCompositeShape.h> // for TGeoCompositeShape
28#include "TMathBase.h" // for Abs
29#include <TMath.h> // for Sin, RadToDeg, DegToRad, Cos, Tan, etc
30
31class TGeoMedium;
32
33using namespace TMath;
34using namespace o2::ft3;
35using namespace o2::itsmft;
36
38
39FT3Layer::~FT3Layer() = default;
40
41TGeoMaterial* FT3Layer::carbonFiberMat = nullptr;
42TGeoMedium* FT3Layer::medCarbonFiber = nullptr;
43
44TGeoMaterial* FT3Layer::kaptonMat = nullptr;
45TGeoMedium* FT3Layer::kaptonMed = nullptr;
46
47TGeoMaterial* FT3Layer::waterMat = nullptr;
48TGeoMedium* FT3Layer::waterMed = nullptr;
49
50TGeoMaterial* FT3Layer::foamMat = nullptr;
51TGeoMedium* FT3Layer::medFoam = nullptr;
52
53FT3Layer::FT3Layer(Int_t layerDirection, Int_t layerNumber, std::string layerName, Float_t z, Float_t rIn, Float_t rOut, Float_t Layerx2X0, bool partOfMiddleLayers)
54{
55 // Creates a simple parametrized EndCap layer covering the given
56 // pseudorapidity range at the z layer position
57 mDirection = layerDirection;
58 mLayerNumber = layerNumber;
59 mIsMiddleLayer = partOfMiddleLayers;
60 mLayerName = layerName;
61 mZ = layerDirection ? std::abs(z) : -std::abs(z);
62 mx2X0 = Layerx2X0;
63 mInnerRadius = rIn;
64 mOuterRadius = rOut;
65 const double Si_X0 = 9.5;
66 mChipThickness = Layerx2X0 * Si_X0;
67 mSensorThickness = 0.005; // assume 50 microns of active thickness (for sensor volumes for trapezoidal disks)
68
69 // Sanity checks
70 if (std::isnan(mZ)) {
71 LOG(fatal) << "FT3 Layer " << mLayerNumber << " has z = NaN, which is not a valid number.";
72 }
73 if (mZ < 0.001 && mZ > -0.001) {
74 LOG(fatal) << "FT3 Layer " << mLayerNumber << " has z = " << mZ << " cm, which is very close to 0.";
75 }
76
77 LOG(info) << "Creating FT3 Layer " << mLayerNumber << " ; direction " << mDirection;
78 LOG(info) << " Using silicon X0 = " << Si_X0 << " to emulate layer radiation length.";
79 LOG(info) << " Layer z = " << mZ << " ; R_in = " << mInnerRadius << " ; R_out = " << mOuterRadius << " ; x2X0 = " << mx2X0 << " ; ChipThickness = " << mChipThickness;
80}
81
83{
84
85 if (carbonFiberMat) {
86 return;
87 }
88
89 carbonFiberMat = new TGeoMaterial("CarbonFiber", 12.0, 6.0, 1.6);
90 medCarbonFiber = new TGeoMedium("CarbonFiber", 1, carbonFiberMat);
91
92 auto* itsC = new TGeoElement("FT3_C", "Carbon", 6, 12.0107);
93
94 auto* itsFoam = new TGeoMixture("FT3_Foam", 1);
95 itsFoam->AddElement(itsC, 1);
96 itsFoam->SetDensity(0.17);
97
98 medFoam = new TGeoMedium("FT3_Foam", 1, itsFoam);
99 foamMat = medFoam->GetMaterial();
100
101 kaptonMat = new TGeoMaterial("Kapton (cooling pipe)", 13.84, 6.88, 1.346);
102 kaptonMed = new TGeoMedium("Kapton (cooling pipe)", 1, kaptonMat);
103
104 waterMat = new TGeoMaterial("Water", 18.01528, 8.0, 1.064);
105 waterMed = new TGeoMedium("Water", 2, waterMat);
106}
107
108static double y_circle(double x, double radius)
109{
110 return (x * x < radius * radius) ? std::sqrt(radius * radius - x * x) : 0;
111}
112
113void FT3Layer::createSeparationLayer_waterCooling(TGeoVolume* motherVolume, const std::string& separationLayerName)
114{
115
117
118 const double carbonFiberThickness = 0.01; // cm
119 const double foamSpacingThickness = 0.5; // cm
120
121 TGeoTube* carbonFiberLayer = new TGeoTube(mInnerRadius, mOuterRadius, carbonFiberThickness / 2);
122
123 // volumes
124 TGeoVolume* carbonFiberLayerVol1 = new TGeoVolume((separationLayerName + "_CarbonFiber1").c_str(), carbonFiberLayer, medCarbonFiber);
125 TGeoVolume* carbonFiberLayerVol2 = new TGeoVolume((separationLayerName + "_CarbonFiber2").c_str(), carbonFiberLayer, medCarbonFiber);
126
127 carbonFiberLayerVol1->SetLineColor(kGray + 2);
128 carbonFiberLayerVol2->SetLineColor(kGray + 2);
129
130 const double zSeparation = foamSpacingThickness / 2.0 + carbonFiberThickness / 2.0;
131
132 motherVolume->AddNode(carbonFiberLayerVol1, 1, new TGeoTranslation(0, 0, mZ - zSeparation));
133 motherVolume->AddNode(carbonFiberLayerVol2, 1, new TGeoTranslation(0, 0, mZ + zSeparation));
134
135 const double pipeOuterRadius = 0.20;
136 const double kaptonThickness = 0.0025;
137 const double pipeInnerRadius = pipeOuterRadius - kaptonThickness;
138 const double pipeMaxLength = mOuterRadius * 2.0;
139
140 int name_it = 0;
141
142 // positions of the pipes depending on the overlap of the sensors inactive regions: (ALICE 3 dimensions)
143 // partial:
144 // std::vector<double> X_pos = {-63.2, -58.4, -53.6, -48.8, -44.0, -39.199999999999996, -34.4, -29.599999999999994, -24.799999999999997, -19.999999999999993, -15.199999999999998, -10.399999999999993, -5.599999999999998, -0.7999999999999936, 4.000000000000002, 8.800000000000006, 13.600000000000001, 18.400000000000006, 23.200000000000003, 28.000000000000007, 32.800000000000004, 37.60000000000001, 42.400000000000006, 47.20000000000001, 52.00000000000001, 56.80000000000001, 61.60000000000001, 66.4};
145 // complete:
146 // std::vector<double> X_pos = {-63.4, -58.8, -54.199999999999996, -49.599999999999994, -44.99999999999999, -40.39999999999999, -35.79999999999999, -31.199999999999992, -26.59999999999999, -21.999999999999993, -17.39999999999999, -12.799999999999994, -8.199999999999992, -3.5999999999999934, 1.000000000000008, 5.600000000000007, 10.200000000000008, 14.800000000000008, 19.40000000000001, 24.000000000000007, 28.60000000000001, 33.20000000000001, 37.80000000000001, 42.40000000000001, 47.000000000000014, 51.600000000000016, 56.20000000000002, 60.80000000000002, 65.40000000000002};
147 std::vector<double> X_pos = {-62.3168, -57.9836, -53.650400000000005, -49.317200000000014, -44.984000000000016, -40.65080000000002, -36.31760000000002, -31.984400000000026, -27.65120000000003, -23.318000000000037, -18.98480000000004, -14.651600000000043, -10.318400000000047, -5.98520000000005, -1.6520000000000519, 2.6811999999999445, 7.014399999999941, 11.347599999999936, 15.680799999999934, 20.01399999999993, 24.347199999999926, 28.68039999999992, 33.013599999999926, 37.34679999999992, 41.980000000000004, 46.613200000000006, 51.246399999999994, 55.87960000000001, 60.5128};
148
149 for (double xPos : X_pos) {
150
151 double pipeLength = pipeMaxLength;
152 double yMax = 0.0;
153
154 TGeoRotation* rotation = new TGeoRotation();
155 rotation->RotateX(90);
156
157 if (std::abs(xPos) < mInnerRadius) {
158 double yInner = std::abs(y_circle(xPos, mInnerRadius));
159 double yOuter = std::abs(y_circle(xPos, mOuterRadius));
160
161 yMax = 2 * yOuter;
162 pipeLength = yMax;
163
164 double positiveYLength = yOuter - yInner;
165
166 TGeoVolume* kaptonPipePos = new TGeoVolume((separationLayerName + "_KaptonPipePos_" + std::to_string(name_it)).c_str(), new TGeoTube(pipeInnerRadius, pipeOuterRadius, positiveYLength / 2), kaptonMed);
167 kaptonPipePos->SetLineColor(kGray);
168 TGeoVolume* waterVolumePos = new TGeoVolume((separationLayerName + "_WaterVolumePos_" + std::to_string(name_it)).c_str(), new TGeoTube(0.0, pipeInnerRadius, positiveYLength / 2), waterMed);
169 waterVolumePos->SetLineColor(kBlue);
170
171 motherVolume->AddNode(waterVolumePos, 1, new TGeoCombiTrans(xPos, (yInner + yOuter) / 2.0, mZ, rotation));
172
173 TGeoVolume* kaptonPipeNeg = new TGeoVolume((separationLayerName + "_KaptonPipeNeg_" + std::to_string(name_it)).c_str(), new TGeoTube(pipeInnerRadius, pipeOuterRadius, positiveYLength / 2), kaptonMed);
174 kaptonPipeNeg->SetLineColor(kGray);
175 TGeoVolume* waterVolumeNeg = new TGeoVolume((separationLayerName + "_WaterVolumeNeg_" + std::to_string(name_it)).c_str(), new TGeoTube(0.0, pipeInnerRadius, positiveYLength / 2), waterMed);
176 waterVolumeNeg->SetLineColor(kBlue);
177
178 motherVolume->AddNode(waterVolumeNeg, 1, new TGeoCombiTrans(xPos, -(yInner + yOuter) / 2.0, mZ, rotation));
179
180 motherVolume->AddNode(kaptonPipePos, 1, new TGeoCombiTrans(xPos, (yInner + yOuter) / 2.0, mZ, rotation));
181 motherVolume->AddNode(kaptonPipeNeg, 1, new TGeoCombiTrans(xPos, -(yInner + yOuter) / 2.0, mZ, rotation));
182
183 } else {
184
185 double yOuter = std::abs(y_circle(xPos, mOuterRadius));
186 yMax = 2 * yOuter;
187 pipeLength = yMax;
188
189 TGeoVolume* kaptonPipe = new TGeoVolume((separationLayerName + "_KaptonPipe_" + std::to_string(name_it)).c_str(), new TGeoTube(pipeInnerRadius, pipeOuterRadius, pipeLength / 2), kaptonMed);
190 kaptonPipe->SetLineColor(kGray);
191 TGeoVolume* waterVolume = new TGeoVolume((separationLayerName + "_WaterVolume_" + std::to_string(name_it)).c_str(), new TGeoTube(0.0, pipeInnerRadius, pipeLength / 2), waterMed);
192 waterVolume->SetLineColor(kBlue);
193
194 motherVolume->AddNode(waterVolume, 1, new TGeoCombiTrans(xPos, 0, mZ, rotation));
195 motherVolume->AddNode(kaptonPipe, 1, new TGeoCombiTrans(xPos, 0, mZ, rotation));
196 }
197
198 name_it++;
199 }
200}
201
202void FT3Layer::createSeparationLayer(TGeoVolume* motherVolume, const std::string& separationLayerName)
203{
204
206
207 constexpr double carbonFiberThickness = 0.01; // cm
208 constexpr double foamSpacingThickness = 1.0; // cm
209
210 TGeoTube* carbonFiberLayer = new TGeoTube(mInnerRadius, mOuterRadius, carbonFiberThickness / 2);
211 TGeoTube* foamLayer = new TGeoTube(mInnerRadius, mOuterRadius, foamSpacingThickness / 2);
212
213 // volumes
214 TGeoVolume* carbonFiberLayerVol1 = new TGeoVolume((separationLayerName + "_CarbonFiber1").c_str(), carbonFiberLayer, medCarbonFiber);
215 TGeoVolume* foamLayerVol = new TGeoVolume((separationLayerName + "_Foam").c_str(), foamLayer, medFoam);
216 TGeoVolume* carbonFiberLayerVol2 = new TGeoVolume((separationLayerName + "_CarbonFiber2").c_str(), carbonFiberLayer, medCarbonFiber);
217
218 carbonFiberLayerVol1->SetLineColor(kGray + 2);
219 foamLayerVol->SetLineColor(kBlack);
220 foamLayerVol->SetFillColorAlpha(kBlack, 1.0);
221 carbonFiberLayerVol2->SetLineColor(kGray + 2);
222
223 const double zSeparation = foamSpacingThickness / 2.0 + carbonFiberThickness / 2.0;
224
225 motherVolume->AddNode(carbonFiberLayerVol1, 1, new TGeoTranslation(0, 0, 0 - zSeparation));
226 motherVolume->AddNode(foamLayerVol, 1, new TGeoTranslation(0, 0, 0));
227 motherVolume->AddNode(carbonFiberLayerVol2, 1, new TGeoTranslation(0, 0, 0 + zSeparation));
228}
229
230void FT3Layer::createReferenceCircles(TGeoVolume* motherVolume, const std::string& name)
231{
232
233 // create reference circles at the inner and outer radius of the layer, for visualization purposes
234 TGeoTube* innerCircle = new TGeoTube(mInnerRadius - 0.1, mInnerRadius + 0.1, 0.01);
235 TGeoTube* outerCircle = new TGeoTube(mOuterRadius - 0.1, mOuterRadius + 0.1, 0.01);
236
237 TGeoVolume* innerCircleVol = new TGeoVolume((mLayerName + "_InnerCircle").c_str(), innerCircle, gGeoManager->GetMedium("FT3_AIR$"));
238 TGeoVolume* outerCircleVol = new TGeoVolume((mLayerName + "_OuterCircle").c_str(), outerCircle, gGeoManager->GetMedium("FT3_AIR$"));
239
240 innerCircleVol->SetLineColor(kRed);
241 outerCircleVol->SetLineColor(kBlue);
242
243 double z_position = mDirection ? 0.5 : -0.5;
244
245 motherVolume->AddNode(innerCircleVol, 1, new TGeoTranslation(0, 0, z_position));
246 motherVolume->AddNode(outerCircleVol, 1, new TGeoTranslation(0, 0, z_position));
247}
248
249void FT3Layer::createLayer(TGeoVolume* motherVolume)
250{
251 auto& ft3Params = FT3BaseParam::Instance();
252
253 if (mLayerNumber < 0) {
254 LOG(fatal) << "Invalid layer number " << mLayerNumber << " for FT3 layer.";
255 }
256
257 LOG(info) << "FT3: ft3Params.layoutFT3 = " << ft3Params.layoutFT3
258 << " Creating Layer " << mLayerNumber << " at z=" << mZ
259 << " with direction " << mDirection;
260
261 // ### options for ML and OT disk layout
262 if (ft3Params.layoutFT3 == kTrapezoidal /*|| (mIsMiddleLayer && ft3Params.layoutFT3 == kSegmented)*/) {
263 // trapezoidal ML+OT disks
264 // (disks with TGeoTubes doesn'n work properly in ACTS, due to polar coordinates on TGeoTube sides)
265
266 // (!) Currently (March 12, 2026), only OT disks are segmented --> use Trapezoidal option for ML disks as a simplified segmentation
267 // To be changed to "true" paving with modules, as for the OT disks
268
269 std::string chipName = o2::ft3::GeometryTGeo::getFT3ChipPattern() + std::to_string(mLayerNumber);
270 std::string sensName = Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), mDirection, mLayerNumber);
271 std::string passiveName = o2::ft3::GeometryTGeo::getFT3PassivePattern() + std::to_string(mLayerNumber);
272
273 TGeoMedium* medSi = gGeoManager->GetMedium("FT3_SILICON$");
274 TGeoMedium* medAir = gGeoManager->GetMedium("FT3_AIR$");
275
276 TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2);
277 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
278 layerVol->SetLineColor(kGray);
279
280 const int NtrapezoidalSegments = ft3Params.nTrapezoidalSegments;
281
282 const double dz = mChipThickness / 2;
283 const double dzSensor = mSensorThickness / 2;
284
285 const double dphi = 2.0 * TMath::Pi() / NtrapezoidalSegments;
286 double innerRadiusTrapezoidCorner = mInnerRadius / sin((TMath::Pi() - dphi) / 2); // to ensure that the trapezoid segments do not extend beyond the volume
287
288 const double rc = 0.5 * (innerRadiusTrapezoidCorner + mOuterRadius) * TMath::Cos(0.5 * dphi); // radius of tile center
289 const double h = 0.5 * (mOuterRadius - innerRadiusTrapezoidCorner) * TMath::Cos(0.5 * dphi); // half radial length
290
291 // chord lengths at inner/outer radii
292 const double bl = innerRadiusTrapezoidCorner * TMath::Sin(0.5 * dphi); // half lower base
293 const double tl = mOuterRadius * TMath::Sin(0.5 * dphi); // half upper base
294
295 // create trapezoids
296 for (int iTr = 0; iTr < NtrapezoidalSegments; ++iTr) {
297 // chip volume
298 auto trdShapeChip = new TGeoTrap(dz,
299 0.0, 0.0, // theta, phi
300 h, // h1
301 bl, // bl1
302 tl, // tl1
303 0.0, // alpha1
304 h, // h2
305 bl, // bl2
306 tl, // tl2
307 0.0); // alpha2
308 TGeoVolume* trapezoidChipVolume = new TGeoVolume(chipName.c_str(), trdShapeChip, medSi);
309 trapezoidChipVolume->SetLineColor(kCyan);
310 trapezoidChipVolume->SetTransparency(50);
311
312 // sensor volume
313 auto trdShapeSensor = new TGeoTrap(dzSensor,
314 0.0, 0.0, // theta, phi
315 h, // h1
316 bl, // bl1
317 tl, // tl1
318 0.0, // alpha1
319 h, // h2
320 bl, // bl2
321 tl, // tl2
322 0.0); // alpha2
323 TGeoVolume* trapezoidSensorVolume = new TGeoVolume(sensName.c_str(), trdShapeSensor, medSi);
324 trapezoidSensorVolume->SetLineColor(kYellow);
325
326 // placing sensor in chip:
327 const double zSensorInChip = (dz - dzSensor) * (mZ < 0 ? 1 : -1); // place sensor at the outer face of the chip, towards the incoming particles
328 TGeoCombiTrans* transSens = new TGeoCombiTrans();
329 transSens->SetTranslation(0, 0, zSensorInChip);
330 trapezoidChipVolume->AddNode(trapezoidSensorVolume, iTr, transSens);
331
332 // passive volume
333 auto trdShapePassive = new TGeoTrap(dz - dzSensor,
334 0.0, 0.0, // theta, phi
335 h, // h1
336 bl, // bl1
337 tl, // tl1
338 0.0, // alpha1
339 h, // h2
340 bl, // bl2
341 tl, // tl2
342 0.0); // alpha2
343 TGeoVolume* trapezoidPassiveVolume = new TGeoVolume(passiveName.c_str(), trdShapePassive, medSi);
344 trapezoidPassiveVolume->SetLineColor(kGray);
345
346 // placing passive volume in chip:
347 const double zPassiveInChip = (-dzSensor) * (mZ < 0 ? 1 : -1); // place passive volume at the outer face of the chip, towards the incoming particles
348 TGeoCombiTrans* transPassive = new TGeoCombiTrans();
349 transPassive->SetTranslation(0, 0, zPassiveInChip);
350 trapezoidChipVolume->AddNode(trapezoidPassiveVolume, iTr, transPassive);
351
352 // prepare placing of chip in layer:
353 const double phi_c = (iTr + 0.5) * dphi; // sector center
354 const double phi_deg = phi_c * 180.0 / TMath::Pi();
355
356 // center of tile
357 const double x = rc * TMath::Cos(phi_c);
358 const double y = rc * TMath::Sin(phi_c);
359 const double z = 0.0;
360
361 // local +Y should point radially outward
362 auto rot = new TGeoRotation();
363 rot->RotateZ(phi_deg - 90.0);
364 auto transf = new TGeoCombiTrans(x, y, z, rot);
365
366 layerVol->AddNode(trapezoidChipVolume, iTr, transf);
367 }
368
369 LOG(info) << "Inserting " << NtrapezoidalSegments << " trapezoidal segments (Rmin="
370 << mInnerRadius << ", Rmax=" << mOuterRadius << ", z = " << mZ << "cm) inside " << layerVol->GetName();
371
372 auto* diskRotation = new TGeoRotation("TrapezoidalDiskRotation", 0, 0, 0);
373 auto* diskCombiTrans = new TGeoCombiTrans(0, 0, mZ, diskRotation);
374 motherVolume->AddNode(layerVol, 1, diskCombiTrans);
375 } else if (ft3Params.layoutFT3 == kCylindrical) {
376 // cylindrical ML+OT disks
377
378 std::string chipName = o2::ft3::GeometryTGeo::getFT3ChipPattern() + std::to_string(mLayerNumber),
379 sensName = Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), mDirection, mLayerNumber);
380 TGeoTube* sensor = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2);
381 TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2);
382 TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2);
383
384 TGeoMedium* medSi = gGeoManager->GetMedium("FT3_SILICON$");
385 TGeoMedium* medAir = gGeoManager->GetMedium("FT3_AIR$");
386
387 TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
388 sensVol->SetLineColor(kYellow);
389 TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
390 chipVol->SetLineColor(kYellow);
391 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
392 layerVol->SetLineColor(kYellow);
393
394 LOG(info) << "Inserting " << sensVol->GetName() << " inside " << chipVol->GetName();
395 chipVol->AddNode(sensVol, 1, nullptr);
396
397 LOG(info) << "Inserting " << chipVol->GetName() << " inside " << layerVol->GetName();
398 layerVol->AddNode(chipVol, 1, nullptr);
399
400 // Finally put everything in the mother volume
401 auto* FwdDiskRotation = new TGeoRotation("FwdDiskRotation", 0, 0, 180);
402 auto* FwdDiskCombiTrans = new TGeoCombiTrans(0, 0, mZ, FwdDiskRotation);
403
404 LOG(info) << "Inserting " << layerVol->GetName() << " inside " << motherVolume->GetName();
405 motherVolume->AddNode(layerVol, 1, FwdDiskCombiTrans);
406 } else if (ft3Params.layoutFT3 == kSegmented ||
407 (ft3Params.layoutFT3 == kSegmentedStaveOTOnly && mIsMiddleLayer)) {
408 FT3Module module;
409
410 // layer structure
411 std::string frontLayerName = o2::ft3::GeometryTGeo::getFT3LayerPattern() + std::to_string(mDirection) + std::to_string(mLayerNumber) + "_Front";
412 std::string backLayerName = o2::ft3::GeometryTGeo::getFT3LayerPattern() + std::to_string(mDirection) + std::to_string(mLayerNumber) + "_Back";
413 std::string separationLayerName = "FT3SeparationLayer" + std::to_string(mDirection) + std::to_string(mLayerNumber);
414
415 TGeoMedium* medAir = gGeoManager->GetMedium("FT3_AIR$");
416 TGeoVolume* layerVol = nullptr;
417 // Add a little additional room in radius
418 TGeoTube* layer = new TGeoTube(mInnerRadius - 0.1, mOuterRadius + 0.1, 1.5);
419 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
420 layerVol->SetLineColor(kYellow + 2);
421 // createSeparationLayer_waterCooling(motherVolume, separationLayerName);
422 createSeparationLayer(layerVol, separationLayerName);
423 module.createModule(0, mLayerNumber, mDirection, mInnerRadius, mOuterRadius, 0., "front", "rectangular", layerVol);
424 module.createModule(0, mLayerNumber, mDirection, mInnerRadius, mOuterRadius, 0., "back", "rectangular", layerVol);
425
426 // Finally put everything in the mother volume
427 auto* FwdDiskRotation = new TGeoRotation("FwdDiskRotation", 0, 0, 180);
428 // need to shift outwards always, so + forwards and - backwards
429 auto* FwdDiskCombiTrans = new TGeoCombiTrans(0, 0, mZ + 0, FwdDiskRotation);
430
431 LOG(info) << "Inserting " << layerVol->GetName() << " (Rmin=" << mInnerRadius << ", Rmax=" << mOuterRadius << ", z=" << mZ << "cm) inside " << motherVolume->GetName();
432 motherVolume->AddNode(layerVol, 1, FwdDiskCombiTrans);
433 } else if (ft3Params.layoutFT3 == kSegmentedStave ||
434 ft3Params.layoutFT3 == kSegmentedStaveOTOnly) {
435 FT3Module module;
436
437 // layer structure
438 std::string frontLayerName = o2::ft3::GeometryTGeo::getFT3LayerPattern() + std::to_string(mDirection) + std::to_string(mLayerNumber) + "_Front";
439 std::string backLayerName = o2::ft3::GeometryTGeo::getFT3LayerPattern() + std::to_string(mDirection) + std::to_string(mLayerNumber) + "_Back";
440 std::string separationLayerName = "FT3SeparationLayer" + std::to_string(mDirection) + std::to_string(mLayerNumber);
441
442 TGeoMedium* medAir = gGeoManager->GetMedium("FT3_AIR$");
443 TGeoVolume* layerVol = nullptr;
444
445 // set up stave config, differs between ML and OT disks
446 const Constants::StaveConfig& staveConfig = Constants::getStaveConfig(mIsMiddleLayer);
447
448 // need a thicker air layer to encompass the staves (4.5cm high, 1.2cm offsets)
449 // stave face is at z=0 (or +-z_offset_stave), meaning that volumes are at
450 // ~-+1cm < z < ~+-6cm, the +- referring forward/backward discs
451 double z_layer_thickness = // need to shift internally with this
458 0.5; // add some extra room to ensure all volumes are encapsulated
459
460 // shift stave volumes into layer volume, since nominal z_{stave face} = 0
461 double z_local_offset = z_layer_thickness / 2.0;
462 TGeoTube* layer = new TGeoTube(mInnerRadius - 0.2, mOuterRadius + 2.5, z_layer_thickness / 2); // margins to ensure staves are fully encapsulated in the layer volume
463 layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
464
465 if (ft3Params.drawReferenceCircles) {
466 std::string referenceCirclesName = "ReferenceCircles_Dir" + std::to_string(mDirection) + "_Layer" + std::to_string(mLayerNumber);
467 createReferenceCircles(layerVol, referenceCirclesName); // for visualization purposes
468 }
469
470 // need the -0.5 added to local offset to ensure all sensor modules are inside the layer
471 module.createModule_staveGeo(0., mLayerNumber, mDirection, mInnerRadius,
472 mOuterRadius, z_local_offset, staveConfig, layerVol);
473 // Finally put everything in the mother volume
474 auto* FwdDiskRotation = new TGeoRotation("FwdDiskRotation", 0, 0, 180);
475 // need to shift outwards always, so + forwards and - backwards
476 double z_offset_directional = mDirection ? z_local_offset : -z_local_offset;
477 auto* FwdDiskCombiTrans = new TGeoCombiTrans(0, 0, mZ + z_offset_directional, FwdDiskRotation);
478
479 LOG(info) << "Inserting " << layerVol->GetName() << " (Rmin=" << mInnerRadius << ", Rmax=" << mOuterRadius << ", z=" << mZ << "cm, segmented disk with staves) inside " << motherVolume->GetName();
480
481 motherVolume->AddNode(layerVol, 1, FwdDiskCombiTrans);
482 } else {
483 LOG(fatal) << "Unknown FT3 layout option: " << static_cast<int>(ft3Params.layoutFT3);
484 }
485}
ClassImp(FT3Layer)
Definition of the FT3Layer class.
Definition of various constants for tiling the modules of sensors.
float & yMax
Definition of the GeometryTGeo class.
Class for time synchronization of RawReader instances.
static TGeoMaterial * waterMat
Definition FT3Layer.h:75
virtual void createLayer(TGeoVolume *motherVolume)
Definition FT3Layer.cxx:249
static TGeoMedium * medFoam
Definition FT3Layer.h:79
static TGeoMedium * medCarbonFiber
Definition FT3Layer.h:70
void createSeparationLayer_waterCooling(TGeoVolume *motherVolume, const std::string &separationLayerName)
Definition FT3Layer.cxx:113
void createReferenceCircles(TGeoVolume *motherVolume, const std::string &name)
Definition FT3Layer.cxx:230
static void initialize_mat()
Definition FT3Layer.cxx:82
static TGeoMedium * waterMed
Definition FT3Layer.h:76
~FT3Layer() override
Default destructor.
FT3Layer()=default
static TGeoMaterial * carbonFiberMat
Definition FT3Layer.h:69
static TGeoMedium * kaptonMed
Definition FT3Layer.h:73
static TGeoMaterial * kaptonMat
Definition FT3Layer.h:72
void createSeparationLayer(TGeoVolume *motherVolume, const std::string &separationLayerName)
Definition FT3Layer.cxx:202
static TGeoMaterial * foamMat
Definition FT3Layer.h:78
static const char * getFT3PassivePattern()
static const char * getFT3SensorPattern()
static const char * getFT3ChipPattern()
static const char * getFT3LayerPattern()
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint const GLchar * name
Definition glcorearb.h:781
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
const double z_offsetStave(double x_midpoint_spacing)
StaveConfig getStaveConfig(bool isInnerDisk)
@ kSegmentedStaveOTOnly
@ kSegmentedStave
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"