Project
Loading...
Searching...
No Matches
Flex.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
15
16#include "TGeoManager.h"
17#include "TGeoVolume.h"
18#include "TGeoTrd2.h"
19#include "TGeoMatrix.h"
20#include "TGeoBBox.h"
21#include "TGeoTube.h"
22#include "TGeoCompositeShape.h"
23#include "TGeoBoolNode.h"
24#include "TMath.h"
25
26#include <fairlogger/Logger.h>
27
28#include <map>
29#include <string>
30
33#include "MFTBase/Flex.h"
34#include "MFTBase/Ladder.h"
35#include "MFTBase/Geometry.h"
37
38using namespace o2::mft;
39using namespace o2::itsmft;
40
42
43//_____________________________________________________________________________
44Flex::Flex() : mFlexOrigin(), mLadderSeg(nullptr)
45{
46 // Constructor
47}
48
49//_____________________________________________________________________________
50Flex::~Flex() = default;
51
52//_____________________________________________________________________________
53Flex::Flex(LadderSegmentation* ladder) : mFlexOrigin(), mLadderSeg(ladder)
54{
55 // Constructor
56}
57
58//_____________________________________________________________________________
59std::string Flex::composeFlexName(Int_t nbsensors) { return "flex_" + std::to_string(nbsensors); }
60
61//_____________________________________________________________________________
62std::string Flex::composeFlexLayerName(const char* layer, Int_t nbsensors, Int_t iflag)
63{
64 std::string name = std::string(layer) + "_" + std::to_string(nbsensors);
65 if (iflag >= 0) {
66 name += "_" + std::to_string(iflag);
67 }
68 return name;
69}
70
71//_____________________________________________________________________________
72TGeoVolumeAssembly* Flex::getFlexVolume(Int_t nbsensors)
73{
74 if (!gGeoManager) {
75 return nullptr;
76 }
77 return dynamic_cast<TGeoVolumeAssembly*>(gGeoManager->GetVolume(composeFlexName(nbsensors).c_str()));
78}
79
80//_____________________________________________________________________________
81TGeoVolumeAssembly* Flex::makeFlex(Int_t nbsensors, Double_t length)
82{
83
84 // Informations from the technical report mft_flex_proto_5chip_v08_laz50p.docx on MFT twiki and private communications
85
86 // Ladders carrying the same number of sensors get the same flex: Ladder.cxx derives the
87 // flex length from that count alone, and nothing built below depends on which ladder asked
88 // for it. MFT has four such classes, so build one flex per class and place it on every
89 // ladder of that class instead of building 280 identical copies.
90 static TGeoManager* cacheOwner = nullptr;
91 static std::map<Int_t, TGeoVolumeAssembly*> flexPerClass;
92 static std::map<Int_t, Double_t> lengthPerClass;
93 if (cacheOwner != gGeoManager) {
94 // a new geometry leaves every cached pointer dangling
95 cacheOwner = gGeoManager;
96 flexPerClass.clear();
97 lengthPerClass.clear();
98 }
99 auto cached = flexPerClass.find(nbsensors);
100 if (cached != flexPerClass.end()) {
101 if (length != lengthPerClass[nbsensors]) {
102 LOG(fatal) << "Flex::makeFlex: the flex for " << nbsensors << " sensors was built with length "
103 << lengthPerClass[nbsensors] << " but this call asks for " << length
104 << " - the per-class flex cache assumes the length follows the sensor count";
105 }
106 return cached->second;
107 }
108
109 Geometry* mftGeom = Geometry::instance();
110 LOG(debug) << "Flex::makeFlex: building the flex for " << nbsensors << " sensors, first asked for by ladder "
111 << mftGeom->getHalfID(mLadderSeg->GetUniqueID()) << "/"
112 << mftGeom->getDiskID(mLadderSeg->GetUniqueID()) << "/"
113 << mftGeom->getLadderID(mLadderSeg->GetUniqueID());
114
115 auto* flex = new TGeoVolumeAssembly(composeFlexName(nbsensors).c_str());
116
117 // Defining one single layer for the strips and the AVDD and DVDD
118 TGeoVolume* lines = makeLines(nbsensors, length - Geometry::sClearance, Geometry::sFlexHeight - Geometry::sClearance,
120
121 // AGND and DGND layers
122 TGeoVolume* agnd_dgnd = makeAGNDandDGND(nbsensors, length - Geometry::sClearance,
124
125 // The others layers
126 TGeoVolume* kaptonlayer = makeKapton(nbsensors, length, Geometry::sFlexHeight, Geometry::sKaptonThickness);
127 TGeoVolume* varnishlayerIn = makeVarnish(nbsensors, length, Geometry::sFlexHeight, Geometry::sVarnishThickness, 0);
128 TGeoVolume* varnishlayerOut = makeVarnish(nbsensors, length, Geometry::sFlexHeight, Geometry::sVarnishThickness, 1);
129
130 // Final flex building
134 Double_t zkaptonlayer = -Geometry::sGlueThickness;
138
139 //-----------------------------------------------------------------------------------------
140 //-------------------------- Adding all layers of the FPC ----------------------------------
141 //-----------------------------------------------------------------------------------------
142
143 flex->AddNode(varnishlayerIn, 1, new TGeoTranslation(0., 0., zvarnishIn)); // inside, in front of the cold plate
144 flex->AddNode(agnd_dgnd, 1, new TGeoTranslation(0., 0., zgnd));
145 flex->AddNode(kaptonlayer, 1, new TGeoTranslation(0., 0., zkaptonlayer));
146 flex->AddNode(lines, 1, new TGeoTranslation(0., 0., zlines));
147 flex->AddNode(varnishlayerOut, 1, new TGeoTranslation(0., 0., zvarnishOut)); // outside
148
149 makeElectricComponents(flex, nbsensors, length, zvarnishOut);
150
151 flexPerClass[nbsensors] = flex;
152 lengthPerClass[nbsensors] = length;
153
154 return flex;
155}
156
157//_____________________________________________________________________________
158void Flex::makeElectricComponents(TGeoVolumeAssembly* flex, Int_t nbsensors, Double_t length, Double_t zvarnish)
159{
160
161 // Making and adding all the electric components
162 TGeoVolumeAssembly* electric[200];
163
164 // 2 components on the connector side
165 Int_t total;
166
167 auto* rotation = new TGeoRotation("rotation", 90., 0., 0.);
168 auto* rotationpi = new TGeoRotation("rotationpi", 180., 0., 0.);
169 auto* transformation0 =
170 new TGeoCombiTrans(length / 2 - 0.1, Geometry::sFlexHeight / 2 - 0.2,
171 zvarnish - Geometry::sVarnishThickness / 2 - Geometry::sCapacitorDz / 2, rotation);
172 auto* transformation1 =
173 new TGeoCombiTrans(length / 2 - 0.1, Geometry::sFlexHeight / 2 - 0.6,
174 zvarnish - Geometry::sVarnishThickness / 2 - Geometry::sCapacitorDz / 2, rotation);
175
176 for (Int_t id = 0; id < 2; id++) {
177 electric[id] = makeElectricComponent(Geometry::sCapacitorDy, Geometry::sCapacitorDx, Geometry::sCapacitorDz, id);
178 }
179 flex->AddNode(electric[0], 1, transformation0);
180 flex->AddNode(electric[1], 2, transformation1);
181 total = 2;
182
183 // 2 lines of electric components along the FPC in the middle (4 per sensor)
184 for (Int_t id = 0; id < 4 * nbsensors; id++) {
185 electric[id + total] =
186 makeElectricComponent(Geometry::sCapacitorDy, Geometry::sCapacitorDx, Geometry::sCapacitorDz, id + total);
187 }
188 for (Int_t id = 0; id < 2 * nbsensors; id++) {
189 flex->AddNode(electric[id + total], id + 1000,
190 new TGeoTranslation(-length / 2 + (id + 0.5) * SegmentationAlpide::SensorSizeCols / 2,
191 Geometry::sFlexHeight / 2 - 0.35,
193 flex->AddNode(electric[id + total + 2 * nbsensors], id + 2000,
194 new TGeoTranslation(-length / 2 + (id + 0.5) * SegmentationAlpide::SensorSizeCols / 2, 0.,
196 }
197 total = total + 4 * nbsensors;
198
199 // ------- 3 components on the FPC side --------
200 for (Int_t id = 0; id < 3; id++) {
201 electric[id + total] =
202 makeElectricComponent(Geometry::sCapacitorDy, Geometry::sCapacitorDx, Geometry::sCapacitorDz, id + total);
203 }
204 for (Int_t id = 0; id < 3; id++) {
205 flex->AddNode(electric[id + total], id + 3000,
206 new TGeoTranslation(-length / 2 + SegmentationAlpide::SensorSizeCols + (id + 1) * 0.3 - 0.6,
207 -Geometry::sFlexHeight / 2 + 0.2,
209 }
210 total = total + 3;
211
212 /*
213 // The connector of the FPC
214 for(Int_t id=0; id < 74; id++)electric[id+total] = makeElectricComponent(Geometry::sConnectorLength,
215 Geometry::sConnectorWidth,
216 Geometry::sConnectorThickness, id+total);
217 for(Int_t id=0; id < 37; id++){
218 flex->AddNode(electric[id+total], id+100, new TGeoTranslation(length/2+0.15-Geometry::sConnectorOffset,
219 id*0.04-Geometry::sFlexHeight/2 + 0.1,
220 zvarnish-Geometry::sVarnishThickness/2-Geometry::sCapacitorDz/2));
221 flex->AddNode(electric[id+total+37], id+200, new TGeoTranslation(length/2-0.15-Geometry::sConnectorOffset,
222 id*0.04-Geometry::sFlexHeight/2 + 0.1,
223 zvarnish - Geometry::sVarnishThickness/2 -
224 Geometry::sCapacitorDz/2));
225 }
226 total=total+74;
227 */
228
229 //-------------------------- New Connector ----------------------
230 Double_t interspace = 0.1; // interspace inside the 2 ranges of connector pads
231 Double_t step = 0.04; // interspace between each pad inside the connector
232 Double_t boxthickness = 0.05; // wall thickness of the PEEK box around the pads
233
234 // The connector pad and the PEEK box around it are the same solids on every flex - their
235 // dimensions come from Geometry constants only - so build them on the first call and place
236 // the same two volumes on every flex afterwards.
237 static TGeoManager* connectorCacheOwner = nullptr;
238 static TGeoVolume* connectord = nullptr;
239 static TGeoVolume* boxconnectord = nullptr;
240 if (connectorCacheOwner != gGeoManager) {
241 // a new geometry leaves every cached pointer dangling
242 connectorCacheOwner = gGeoManager;
243 connectord = nullptr;
244 boxconnectord = nullptr;
245 }
246
247 if (!connectord) {
248 TGeoMedium* kMedAlu = gGeoManager->GetMedium("MFT_Alu$");
249 TGeoMedium* kMedPeek = gGeoManager->GetMedium("MFT_PEEK$");
250
251 auto* connect = new TGeoBBox("connect", Geometry::sConnectorLength / 2, Geometry::sConnectorWidth / 2,
253 auto* remov =
256
257 auto* t1 = new TGeoTranslation("t1", Geometry::sConnectorThickness, 0., -0.01);
258 auto* connecto = new TGeoSubtraction(connect, remov, nullptr, t1);
259 auto* connector = new TGeoCompositeShape("connector", connecto);
260 connectord = new TGeoVolume("connectord", connector, kMedAlu);
261 connectord->SetVisibility(kTRUE);
262 connectord->SetLineColor(kRed);
263 connectord->SetLineWidth(1);
264 connectord->SetFillColor(connectord->GetLineColor());
265 connectord->SetFillStyle(4000); // 0% transparent
266
267 auto* boxconnect = new TGeoBBox("boxconnect", (2 * Geometry::sConnectorThickness + interspace + boxthickness) / 2,
269 auto* boxremov = new TGeoBBox("boxremov", (2 * Geometry::sConnectorThickness + interspace) / 2,
270 (Geometry::sFlexHeight - 0.1 - step) / 2, Geometry::sConnectorHeight / 2 + 0.001);
271 auto* boxconnecto = new TGeoSubtraction(boxconnect, boxremov, nullptr, nullptr);
272 auto* boxconnector = new TGeoCompositeShape("boxconnector", boxconnecto);
273 boxconnectord = new TGeoVolume("boxconnectord", boxconnector, kMedPeek);
274 }
275
276 for (Int_t id = 0; id < 37; id++) {
277 flex->AddNode(
278 connectord, id + total,
279 new TGeoTranslation(length / 2 + interspace / 2 + Geometry::sConnectorLength / 2 - Geometry::sConnectorOffset,
280 id * step - Geometry::sFlexHeight / 2 + 0.1,
282 auto* transformationpi =
283 new TGeoCombiTrans(length / 2 - interspace / 2 - Geometry::sConnectorLength / 2 - Geometry::sConnectorOffset,
284 id * step - Geometry::sFlexHeight / 2 + 0.1,
285 zvarnish - Geometry::sVarnishThickness / 2 - Geometry::sConnectorHeight / 2, rotationpi);
286 flex->AddNode(connectord, id + total + 37, transformationpi);
287 }
288
289 flex->AddNode(boxconnectord, 1,
290 new TGeoTranslation(length / 2 - Geometry::sConnectorOffset, -step / 2,
293}
294
295//_____________________________________________________________________________
296TGeoVolumeAssembly* Flex::makeElectricComponent(Double_t dx, Double_t dy, Double_t dz, Int_t id)
297{
298
299 //------------------------------------------------------
300 // X7R0402 (and its capacitor/welding0/welding1 children) is geometrically identical at
301 // every call site (dx,dy,dz are always Geometry::sCapacitorDy/Dx/Dz) — build the whole
302 // assembly once, place it many times.
303 static TGeoManager* cacheOwner = nullptr;
304 static TGeoVolumeAssembly* X7R0402 = nullptr;
305 static Double_t sCachedDx = 0., sCachedDy = 0., sCachedDz = 0.;
306 if (cacheOwner != gGeoManager) {
307 // a new geometry leaves the cached pointer dangling
308 cacheOwner = gGeoManager;
309 X7R0402 = nullptr;
310 }
311 if (X7R0402) {
312 if (dx != sCachedDx || dy != sCachedDy || dz != sCachedDz) {
313 LOG(fatal) << "Flex::makeElectricComponent: cached X7R0402 assembly was built with "
314 "different dx,dy,dz than this call - the single-assembly cache assumes "
315 "identical dimensions at every call site";
316 }
317 return X7R0402;
318 }
319 sCachedDx = dx;
320 sCachedDy = dy;
321 sCachedDz = dz;
322
323 TGeoMedium* kmedX7R = gGeoManager->GetMedium("MFT_X7Rcapacitors$");
324 TGeoMedium* kmedX7Rw = gGeoManager->GetMedium("MFT_X7Rweld$");
325
326 auto* capacit = new TGeoBBox("capacitor", dx / 2, dy / 2, dz / 2);
327 auto* weld = new TGeoBBox("weld", (dx / 4) / 2, dy / 2, (dz / 2) / 2);
328
329 auto* capacitor = new TGeoVolume("capacitor", capacit, kmedX7R);
330 auto* welding0 = new TGeoVolume("welding0", weld, kmedX7Rw);
331 auto* welding1 = new TGeoVolume("welding1", weld, kmedX7Rw);
332
333 capacitor->SetVisibility(kTRUE);
334 capacitor->SetLineColor(kRed);
335 capacitor->SetLineWidth(1);
336 capacitor->SetFillColor(capacitor->GetLineColor());
337 capacitor->SetFillStyle(4000); // 0% transparent
338
339 welding0->SetVisibility(kTRUE);
340 welding0->SetLineColor(kGray);
341 welding0->SetLineWidth(1);
342 welding0->SetFillColor(welding0->GetLineColor());
343 welding0->SetFillStyle(4000); // 0% transparent
344
345 welding1->SetVisibility(kTRUE);
346 welding1->SetLineColor(kGray);
347 welding1->SetLineWidth(1);
348 welding1->SetFillColor(welding1->GetLineColor());
349 welding1->SetFillStyle(4000); // 0% transparent
350
351 X7R0402 = new TGeoVolumeAssembly("X7R0402");
352 X7R0402->AddNode(capacitor, 1, new TGeoTranslation(0., 0., 0.));
353 X7R0402->AddNode(welding0, 1, new TGeoTranslation(dx / 2 + (dx / 4) / 2, 0., (dz / 2) / 2));
354 X7R0402->AddNode(welding1, 1, new TGeoTranslation(-dx / 2 - (dx / 4) / 2, 0., (dz / 2) / 2));
355 X7R0402->SetVisibility(kTRUE);
356
357 return X7R0402;
358
359 //------------------------------------------------------
360
361 /*
362 // the medium has to be changed, see ITS capacitors...
363 TGeoMedium *kMedCopper = gGeoManager->GetMedium("MFT_Cu$");
364
365 Geometry * mftGeom = Geometry::instance();
366 Int_t idHalfMFT = mftGeom->getHalfID(mLadderSeg->GetUniqueID());
367 Int_t idHalfDisk = mftGeom->getDiskID(mLadderSeg->GetUniqueID());
368 Int_t idLadder = mftGeom->getLadderID(mLadderSeg->GetUniqueID());
369
370 TGeoVolume* electriccomponent = new TGeoVolume(Form("electric_%d_%d_%d_%d",idHalfMFT,idHalfDisk,idLadder,id), new
371 TGeoBBox("BOX", dy/2, dx/2, dz/2), kMedCopper);
372 electriccomponent->SetVisibility(1);
373 electriccomponent->SetLineColor(kRed);
374 return electriccomponent;
375 */
376}
377
378//_____________________________________________________________________________
379TGeoVolume* Flex::makeLines(Int_t nbsensors, Double_t length, Double_t widthflex, Double_t thickness)
380{
381
382 // One line is built by removing 3 lines of aluminium in the TGeoBBox *layer_def layer. Then one line is made by the 2
383 // remaining aluminium strips.
384
385 // the initial layer of aluminium
386 auto* layer_def = new TGeoBBox("layer_def", length / 2, widthflex / 2, thickness / 2);
387
388 // Two holes for fixing and positionning of the FPC on the cold plate
389 auto* hole1 = new TGeoTube("hole1", 0., Geometry::sRadiusHole1, thickness / 2 + Geometry::sEpsilon);
390 auto* hole2 = new TGeoTube("hole2", 0., Geometry::sRadiusHole2, thickness / 2 + Geometry::sEpsilon);
391
392 auto* t1 = new TGeoTranslation("t1", length / 2 - Geometry::sHoleShift1, 0., 0.);
393 auto* layerholesub1 = new TGeoSubtraction(layer_def, hole1, nullptr, t1);
394 auto* layerhole1 = new TGeoCompositeShape("layerhole1", layerholesub1);
395
396 auto* t2 = new TGeoTranslation("t2", length / 2 - Geometry::sHoleShift2, 0., 0.);
397 auto* layerholesub2 = new TGeoSubtraction(layerhole1, hole2, nullptr, t2);
398 auto* layer = new TGeoCompositeShape("layerhole2", layerholesub2);
399
400 TGeoBBox* line[25];
401 TGeoTranslation *t[6], *ts[15], *tvdd, *tl[2];
402 TGeoSubtraction* layerl[25];
403 TGeoCompositeShape* layern[25];
404 Int_t istart, istop;
405 Int_t kTotalLinesNb = 0;
406 Int_t kTotalLinesNb1, kTotalLinesNb2;
407 Double_t length_line;
408
409 // ----------- two lines along the FPC digital side --------------
410 t[0] = new TGeoTranslation("t0", SegmentationAlpide::SensorSizeCols / 2 - Geometry::sConnectorOffset / 2,
411 -widthflex / 2 + 2 * Geometry::sLineWidth, 0.);
413 Geometry::sLineWidth / 2, thickness / 2 + Geometry::sEpsilon);
414 layerl[0] = new TGeoSubtraction(layer, line[0], nullptr, t[0]);
415 layern[0] = new TGeoCompositeShape(Form("layer%d", 0), layerl[0]);
416
417 istart = 1;
418 istop = 6;
419 for (int iline = istart; iline < istop; iline++) {
420 t[iline] =
421 new TGeoTranslation(Form("t%d", iline), SegmentationAlpide::SensorSizeCols / 2 - Geometry::sConnectorOffset / 2,
422 -widthflex / 2 + 2 * (iline + 1) * Geometry::sLineWidth, 0.);
423 line[iline] = new TGeoBBox(Form("line%d", iline),
425 Geometry::sLineWidth / 2, thickness / 2 + Geometry::sEpsilon);
426 layerl[iline] = new TGeoSubtraction(layern[iline - 1], line[iline], nullptr, t[iline]);
427 layern[iline] = new TGeoCompositeShape(Form("layer%d", iline), layerl[iline]);
428 kTotalLinesNb++;
429 }
430
431 // --------- lines for the sensors, one line/sensor -------------
432 istart = kTotalLinesNb + 1;
433 istop = 6 + 3 * nbsensors;
434 for (int iline = istart; iline < istop; iline++) {
435 length_line = length - Geometry::sConnectorOffset -
436 TMath::Nint((iline - 6) / 3) * SegmentationAlpide::SensorSizeCols -
438 ts[iline - 6] = new TGeoTranslation(Form("t%d", iline), length / 2 - length_line / 2 - Geometry::sConnectorOffset,
439 -2 * (iline - 6) * Geometry::sLineWidth + 0.5 - widthflex / 2, 0.);
440 line[iline] = new TGeoBBox(Form("line%d", iline), length_line / 2, Geometry::sLineWidth / 2,
441 thickness / 2 + Geometry::sEpsilon);
442 layerl[iline] = new TGeoSubtraction(layern[iline - 1], line[iline], nullptr, ts[iline - 6]);
443 layern[iline] = new TGeoCompositeShape(Form("layer%d", iline), layerl[iline]);
444 kTotalLinesNb++;
445 }
446
447 // --------- an interspace to separate AVDD and DVDD -------------
448 kTotalLinesNb++;
449 tvdd = new TGeoTranslation("tvdd", 0., widthflex / 2 - Geometry::sShiftDDGNDline, 0.);
450 line[kTotalLinesNb] = new TGeoBBox(Form("line%d", kTotalLinesNb), length / 2, 2 * Geometry::sLineWidth / 2,
451 thickness / 2 + Geometry::sEpsilon);
452 layerl[kTotalLinesNb] = new TGeoSubtraction(layern[kTotalLinesNb - 1], line[kTotalLinesNb], nullptr, tvdd);
453 layern[kTotalLinesNb] = new TGeoCompositeShape(Form("layer%d", kTotalLinesNb), layerl[kTotalLinesNb]);
454 kTotalLinesNb++;
455
456 // --------- one line along the FPC analog side -------------
457 istart = kTotalLinesNb;
458 istop = kTotalLinesNb + 2;
459 for (int iline = istart; iline < istop; iline++) {
460 length_line = length - Geometry::sConnectorOffset;
461 tl[iline - istart] =
462 new TGeoTranslation(Form("tl%d", iline), length / 2 - length_line / 2 - Geometry::sConnectorOffset,
463 widthflex / 2 - Geometry::sShiftline - 2. * (iline - istart) * Geometry::sLineWidth, 0.);
464 line[iline] = new TGeoBBox(Form("line%d", iline), length_line / 2, Geometry::sLineWidth / 2,
465 thickness / 2 + Geometry::sEpsilon);
466 layerl[iline] = new TGeoSubtraction(layern[iline - 1], line[iline], nullptr, tl[iline - istart]);
467 layern[iline] = new TGeoCompositeShape(Form("layer%d", iline), layerl[iline]);
468 kTotalLinesNb++;
469 }
470
471 TGeoMedium* kMedAlu = gGeoManager->GetMedium("MFT_Alu$");
472
473 auto* lineslayer = new TGeoVolume(composeFlexLayerName("lineslayer", nbsensors).c_str(),
474 layern[kTotalLinesNb - 1], kMedAlu);
475 lineslayer->SetVisibility(true);
476 lineslayer->SetLineColor(kBlue);
477
478 return lineslayer;
479}
480
481//_____________________________________________________________________________
482TGeoVolume* Flex::makeAGNDandDGND(Int_t nbsensors, Double_t length, Double_t widthflex, Double_t thickness)
483{
484
485 // AGND and DGND layers
486 auto* layer = new TGeoBBox("layer", length / 2, widthflex / 2, thickness / 2);
487 auto* hole1 = new TGeoTube("hole1", 0., Geometry::sRadiusHole1, thickness / 2 + Geometry::sEpsilon);
488 auto* hole2 = new TGeoTube("hole2", 0., Geometry::sRadiusHole2, thickness / 2 + Geometry::sEpsilon);
489
490 auto* t1 = new TGeoTranslation("t1", length / 2 - Geometry::sHoleShift1, 0., 0.);
491 auto* layerholesub1 = new TGeoSubtraction(layer, hole1, nullptr, t1);
492 auto* layerhole1 = new TGeoCompositeShape("layerhole1", layerholesub1);
493
494 auto* t2 = new TGeoTranslation("t2", length / 2 - Geometry::sHoleShift2, 0., 0.);
495 auto* layerholesub2 = new TGeoSubtraction(layerhole1, hole2, nullptr, t2);
496 auto* layerhole2 = new TGeoCompositeShape("layerhole2", layerholesub2);
497
498 //--------------
499 TGeoBBox* line[3];
500 TGeoTranslation* t[3];
501 TGeoCompositeShape* layern[3];
502 TGeoSubtraction* layerl[3];
503 Double_t length_line;
504 length_line = length - Geometry::sConnectorOffset;
505
506 // First, the two lines along the FPC side
507 t[0] = new TGeoTranslation("t0", length / 2 - length_line / 2 - Geometry::sConnectorOffset,
508 widthflex / 2 - Geometry::sShiftline, 0.);
509 line[0] = new TGeoBBox("line0", length / 2 - Geometry::sConnectorOffset / 2, Geometry::sLineWidth / 2,
510 thickness / 2 + Geometry::sEpsilon);
511 layerl[0] = new TGeoSubtraction(layerhole2, line[0], nullptr, t[0]);
512 layern[0] = new TGeoCompositeShape(Form("layer%d", 0), layerl[0]);
513
514 t[1] = new TGeoTranslation("t1", length / 2 - length_line / 2 - Geometry::sConnectorOffset,
515 widthflex / 2 - Geometry::sShiftline - 2 * Geometry::sLineWidth, 0.);
516 line[1] = new TGeoBBox("line1", length / 2 - Geometry::sConnectorOffset / 2, Geometry::sLineWidth / 2,
517 thickness / 2 + Geometry::sEpsilon);
518 layerl[1] = new TGeoSubtraction(layern[0], line[1], nullptr, t[1]);
519 layern[1] = new TGeoCompositeShape(Form("layer%d", 1), layerl[1]);
520
521 // Now the interspace to separate the AGND et DGND --> same interspace compare the AVDD et DVDD
522 t[2] = new TGeoTranslation("t2", length / 2 - length_line / 2, widthflex / 2 - Geometry::sShiftDDGNDline, 0.);
524 thickness / 2 + Geometry::sEpsilon);
525 layerl[2] = new TGeoSubtraction(layern[1], line[2], nullptr, t[2]);
526 layern[2] = new TGeoCompositeShape(Form("layer%d", 2), layerl[2]);
527
528 //--------------
529
530 TGeoMedium* kMedAlu = gGeoManager->GetMedium("MFT_Alu$");
531 auto* alulayer = new TGeoVolume(composeFlexLayerName("alulayer", nbsensors).c_str(), layern[2], kMedAlu);
532 alulayer->SetVisibility(true);
533 alulayer->SetLineColor(kBlue);
534
535 return alulayer;
536}
537
538//_____________________________________________________________________________
539TGeoVolume* Flex::makeKapton(Int_t nbsensors, Double_t length, Double_t widthflex, Double_t thickness)
540{
541
542 auto* layer = new TGeoBBox("layer", length / 2, widthflex / 2, thickness / 2);
543 // Two holes for fixing and positionning of the FPC on the cold plate
544 auto* hole1 = new TGeoTube("hole1", 0., Geometry::sRadiusHole1, thickness / 2 + Geometry::sEpsilon);
545 auto* hole2 = new TGeoTube("hole2", 0., Geometry::sRadiusHole2, thickness / 2 + Geometry::sEpsilon);
546
547 auto* t1 = new TGeoTranslation("t1", length / 2 - Geometry::sHoleShift1, 0., 0.);
548 auto* layerholesub1 = new TGeoSubtraction(layer, hole1, nullptr, t1);
549 auto* layerhole1 = new TGeoCompositeShape("layerhole1", layerholesub1);
550
551 auto* t2 = new TGeoTranslation("t2", length / 2 - Geometry::sHoleShift2, 0., 0.);
552 auto* layerholesub2 = new TGeoSubtraction(layerhole1, hole2, nullptr, t2);
553 auto* layerhole2 = new TGeoCompositeShape("layerhole2", layerholesub2);
554
555 TGeoMedium* kMedKapton = gGeoManager->GetMedium("MFT_Kapton$");
556 auto* kaptonlayer =
557 new TGeoVolume(composeFlexLayerName("kaptonlayer", nbsensors).c_str(), layerhole2, kMedKapton);
558 kaptonlayer->SetVisibility(true);
559 kaptonlayer->SetLineColor(kYellow);
560
561 return kaptonlayer;
562}
563
564//_____________________________________________________________________________
565TGeoVolume* Flex::makeVarnish(Int_t nbsensors, Double_t length, Double_t widthflex, Double_t thickness, Int_t iflag)
566{
567
568 auto* layer = new TGeoBBox("layer", length / 2, widthflex / 2, thickness / 2);
569 // Two holes for fixing and positionning of the FPC on the cold plate
570 auto* hole1 = new TGeoTube("hole1", 0., Geometry::sRadiusHole1, thickness / 2 + Geometry::sEpsilon);
571 auto* hole2 = new TGeoTube("hole2", 0., Geometry::sRadiusHole2, thickness / 2 + Geometry::sEpsilon);
572
573 auto* t1 = new TGeoTranslation("t1", length / 2 - Geometry::sHoleShift1, 0., 0.);
574 auto* layerholesub1 = new TGeoSubtraction(layer, hole1, nullptr, t1);
575 auto* layerhole1 = new TGeoCompositeShape("layerhole1", layerholesub1);
576
577 auto* t2 = new TGeoTranslation("t2", length / 2 - Geometry::sHoleShift2, 0., 0.);
578 auto* layerholesub2 = new TGeoSubtraction(layerhole1, hole2, nullptr, t2);
579 auto* layerhole2 = new TGeoCompositeShape("layerhole2", layerholesub2);
580
581 TGeoMedium* kMedVarnish = gGeoManager->GetMedium("MFT_Epoxy$"); // we assume that varnish = epoxy ...
582 TGeoMaterial* kMatVarnish = kMedVarnish->GetMaterial();
583 // kMatVarnish->Dump();
584 auto* varnishlayer =
585 new TGeoVolume(composeFlexLayerName("varnishlayer", nbsensors, iflag).c_str(), layerhole2, kMedVarnish);
586 varnishlayer->SetVisibility(true);
587 varnishlayer->SetLineColor(kGreen - 1);
588
589 return varnishlayer;
590}
Chip (sensor) segmentation description.
std::ostringstream debug
ClassImp(o2::mft::Flex)
Flex (Printed Cabled Board) class for ALICE MFT upgrade.
Class handling both virtual segmentation and real volumes.
Description of the virtual segmentation of a ladder.
Class building the Ladder geometry.
Definition of the SegmentationAlpide class.
static constexpr float SensorSizeCols
static std::string composeFlexName(Int_t nbsensors)
Definition Flex.cxx:59
void makeElectricComponents(TGeoVolumeAssembly *flex, Int_t nbsensors, Double_t length, Double_t zvarnish)
Definition Flex.cxx:158
static TGeoVolumeAssembly * getFlexVolume(Int_t nbsensors)
Definition Flex.cxx:72
static std::string composeFlexLayerName(const char *layer, Int_t nbsensors, Int_t iflag=-1)
Definition Flex.cxx:62
TGeoVolumeAssembly * makeFlex(Int_t nbsensors, Double_t length)
Definition Flex.cxx:81
static const Double_t sCapacitorDy
Definition Geometry.h:69
static const Double_t sHoleShift1
Definition Geometry.h:65
static const Double_t sEpsilon
Definition Geometry.h:75
static const Double_t sVarnishThickness
Definition Geometry.h:58
static const Double_t sShiftDDGNDline
Definition Geometry.h:78
Int_t getDiskID(UInt_t uniqueID) const
Returns Half-Disk ID based on Unique ID provided.
Definition Geometry.h:106
static const Double_t sLineWidth
Definition Geometry.h:57
static const Double_t sConnectorLength
Definition Geometry.h:71
Int_t getLadderID(UInt_t uniqueID) const
Returns Ladder ID based on Unique ID provided.
Definition Geometry.h:112
static const Double_t sConnectorOffset
Definition Geometry.h:67
Int_t getHalfID(UInt_t uniqueID) const
Returns Half-MFT ID based on Unique ID provided.
Definition Geometry.h:103
static const Double_t sGlueThickness
Definition Geometry.h:76
static const Double_t sKaptonThickness
Definition Geometry.h:60
static Geometry * instance()
Singleton access.
Definition Geometry.cxx:99
static const Double_t sCapacitorDz
Definition Geometry.h:68
static const Double_t sConnectorWidth
Definition Geometry.h:72
static const Double_t sClearance
Definition Geometry.h:62
static const Double_t sConnectorHeight
Definition Geometry.h:73
static const Double_t sFlexHeight
Flex Height.
Definition Geometry.h:56
static const Double_t sConnectorThickness
Definition Geometry.h:74
static const Double_t sRadiusHole1
Definition Geometry.h:63
static const Double_t sShiftline
Definition Geometry.h:79
static const Double_t sRadiusHole2
Definition Geometry.h:64
static const Double_t sHoleShift2
Definition Geometry.h:66
static const Double_t sCapacitorDx
Definition Geometry.h:70
static const Double_t sAluThickness
Definition Geometry.h:59
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
GLuint id
Definition glcorearb.h:650
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
int32_t const char int32_t line
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"