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