ATLAS Offline Software
Loading...
Searching...
No Matches
MultiLayer.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
8#include "GaudiKernel/SystemOfUnits.h"
9#include "GeoGenericFunctions/AbsFunction.h"
10#include "GeoGenericFunctions/Variable.h"
12#include "GeoModelKernel/GeoDefinitions.h"
13#include "GeoModelKernel/GeoFullPhysVol.h"
14#include "GeoModelKernel/GeoIdentifierTag.h"
15#include "GeoModelKernel/GeoLogVol.h"
16#include "GeoModelKernel/GeoNameTag.h"
17#include "GeoModelKernel/GeoPhysVol.h"
18#include "GeoModelKernel/GeoSerialDenominator.h"
19#include "GeoModelKernel/GeoSerialIdentifier.h"
20#include "GeoModelKernel/GeoSerialTransformer.h"
21#include "GeoModelKernel/GeoShape.h"
22#include "GeoModelKernel/GeoShapeShift.h"
23#include "GeoModelKernel/GeoShapeSubtraction.h"
24#include "GeoModelKernel/GeoShapeUnion.h"
25#include "GeoModelKernel/GeoTransform.h"
26#include "GeoModelKernel/GeoTrd.h"
27#include "GeoModelKernel/GeoTube.h"
28#include "GeoModelKernel/GeoXF.h"
31#include "MuonGeoModel/MYSQL.h"
32
33#include <GaudiKernel/IMessageSvc.h>
34#include <GaudiKernel/MsgStream.h>
35#include <array>
36#include <cassert>
37#include <cstdlib>
38#include <memory>
39#include <stdexcept>
40#include <utility>
41#include <vector>
42
43class GeoMaterial;
44class GeoVPhysVol;
45
46using namespace GeoXF;
47
48#define verbose_multilayer false
49
50namespace {
51 // the tube number of a tube in a tubeLayer in encoded in the GeoSerialIdentifier (modulo maxNTubesPerLayer)
52 constexpr unsigned int maxNTubesPerLayer = MdtIdHelper::maxNTubesPerLayer;
53} // namespace
54
55namespace MuonGM {
56
57 MultiLayer::MultiLayer(const MYSQL& mysql, const std::string& n)
58 : DetectorElement(n) {
59 MsgStream log(Athena::getMessageSvc(), "MultiLayer::MultiLayer");
60
61 const MDT *md = dynamic_cast<const MDT*>(mysql.GetTechnology(name));
62 if (md) {
65 tubePitch = md->pitch;
66 for (int i = 0; i < nrOfLayers; i++) {
67 yy[i] = md->y[i];
68 xx[i] = md->x[i];
69 }
70 nrOfSteps = 1;
71
72 } else {
73 log << MSG::ERROR << "Multilayer constructor - a problem here !!! MDT named " << name << " not found \n Cannot init correctly !" << endmsg;
74 assert(0);
75 }
76 }
77
78 GeoFullPhysVol *MultiLayer::build(StoredMaterialManager& matManager,
79 const MYSQL& mysql) {
80 MsgStream log(Athena::getMessageSvc(), "MultiLayer::build");
81
82 DriftTube tube(mysql, name + " DriftTube");
83 double eps = 0.001;
84 double tuberad = tube.outerRadius;
86 log << MSG::VERBOSE << " MultiLayer::build of " << name << " logVolName = " << logVolName << " tube radius, pitch = " << tuberad << " , " << tubePitch << endmsg;
87 }
88
89 const GeoShape *slay = nullptr;
90 const GeoShape *sfoamup = nullptr; // do them both together when there are cutouts
91 const GeoShape *sfoamlow = nullptr; // do them both together when there are cutouts
92 // so calculate other foam-related info first:
93 double foamthicknesslow = yy[0] - tuberad;
94 double foamthicknessup;
95 if (yy[3])
96 foamthicknessup = mdtthickness - (yy[3] + tuberad);
97 else
98 foamthicknessup = mdtthickness - (yy[2] + tuberad);
99
100 if (foamthicknessup > foamthicknesslow) {
101 foamthicknesslow = 0.;
102 if (std::abs(foamthicknessup - 15 * Gaudi::Units::mm) < 0.1) {
103 foamthicknessup = 15 * Gaudi::Units::mm;
104 } else if (std::abs(foamthicknessup - 30.75 * Gaudi::Units::mm) < 0.1) {
105 foamthicknessup = 30.75 * Gaudi::Units::mm;
106 } else if (std::abs(foamthicknessup - 30.00 * Gaudi::Units::mm) < 0.1) {
107 foamthicknessup = 30.00 * Gaudi::Units::mm;
108 } else if (std::abs(foamthicknessup - 10.00 * Gaudi::Units::mm) < 0.1 && logVolName.find("BMG") != std::string::npos) {
109 foamthicknessup = 10.00 * Gaudi::Units::mm;
110 } else if (logVolName.find("MDT09") != std::string::npos || logVolName.find("MDT14") != std::string::npos) {
111 // MDT09 is used for BME and BIS sMDTs, MDT14 is used for 2nd multilayer of BIS78
112 // All those sMDTs have no foam layer
113 foamthicknesslow = 0.;
114 foamthicknessup = 0.;
115 } else {
116 log << MSG::WARNING << " problem with thickness of " << std::abs(foamthicknessup) << " for foam in LogVolName " << logVolName << endmsg;
117 }
118
119 } else {
120 foamthicknessup = 0.;
121 if (std::abs(foamthicknesslow - 15 * Gaudi::Units::mm) < 0.1) {
122 foamthicknesslow = 15 * Gaudi::Units::mm;
123 } else if (std::abs(foamthicknesslow - 30.75 * Gaudi::Units::mm) < 0.1) {
124 foamthicknesslow = 30.75 * Gaudi::Units::mm;
125 } else if (std::abs(foamthicknesslow - 30.00 * Gaudi::Units::mm) < 0.1) {
126 foamthicknesslow = 30.00 * Gaudi::Units::mm;
127 } else if (std::abs(foamthicknesslow - 10.00 * Gaudi::Units::mm) < 0.1 && logVolName.find("BMG") != std::string::npos) {
128 foamthicknesslow = 10.00 * Gaudi::Units::mm;
129 } else if (logVolName.find("MDT09") != std::string::npos || logVolName.find("MDT14") != std::string::npos) {
130 // MDT09 is used for BME and BIS sMDTs, MDT14 is used for 2nd multilayer of BIS78
131 // All those sMDTs have no foam layer
132 foamthicknesslow = 0.;
133 foamthicknessup = 0.;
134 } else {
135 log << MSG::WARNING << " problem with thickness of " << std::abs(foamthicknesslow) << " for foam in LogVolName " << logVolName << endmsg;
136 }
137 }
138
139 // Build the layer envelope into which the MDTs are placed
140 double TrdDwoverL = (longWidth - width) / length;
142 // No cutouts - layer is a simple box or trapezoid
143 slay = new GeoTrd(mdtthickness / 2, mdtthickness / 2, width / 2, longWidth / 2, length / 2);
144 } else if (!m_nonCutoutXSteps.empty()) {
145 // there are cutouts sliced along amdb-x (slices in amdb-y)
146 double submlthick = mdtthickness / 2.; // corresponds to half amdb-z (chamber height=constant)
147
148 // loop on the cutout slices and create rectangular boxes which are NOT cutout and add them together to an envelope
149 for (unsigned int i = 0; i < m_nonCutoutXSteps.size(); ++i) {
150
151 double submlwidth = (m_nonCutoutXSteps.at(i).second - m_nonCutoutXSteps.at(i).first) / 2; // corresponds to half amdb-x
152 double submllength = (m_nonCutoutYSteps.at(i).second - m_nonCutoutYSteps.at(i).first) / 2; // corresponds to half amdb-y
153
154 // need a transform between center multilayer and center of trapezoid (y is amdb-x, z is amdb-y)
155 double yPos = (m_nonCutoutXSteps.at(i).first + m_nonCutoutXSteps.at(i).second) / 2;
156 double zPos = (m_nonCutoutYSteps.at(i).first + m_nonCutoutYSteps.at(i).second) / 2 - length / 2;
157 GeoTrf::Transform3D submlpos = GeoTrf::Translate3D(0., yPos, zPos);
158
159 const GeoTrd *tempSLay = nullptr;
160 const GeoShape *tempSLay1 = nullptr;
161
162 if (submlthick * submlwidth * submllength > 0) {
163 tempSLay = new GeoTrd(submlthick, submlthick, submlwidth, submlwidth, submllength);
164 tempSLay1 = &((*tempSLay) << submlpos);
165 } else {
166 log << MSG::WARNING << " problem with shape of temporary trapezoid in LogVolName " << logVolName << " thick,width,length=" << submlthick << "," << submlwidth
167 << "," << submllength << endmsg;
168 }
169
170 if (slay) {
171 slay = &(slay->add(*tempSLay1));
172 } else {
173 slay = tempSLay1;
174 }
175 } // Loop over cutout steps
176 } else {
177 // Layer to be built as a boolean of boxes and trapezoids to represent cutouts
178 if (verbose_multilayer) {
179 log << MSG::VERBOSE << name << " has " << cutoutNsteps << " cutout steps " << endmsg;
180 }
181 double submlthick = mdtthickness / 2.;
182 double submlwidths = width / 2.;
183 double submlwidthl = width / 2.;
184 double lengthPos = 0.;
185 double sum_len = 0;
186
187 for (int isub = 0; isub < cutoutNsteps; isub++) {
188 if (verbose_multilayer) {
189 log << MSG::VERBOSE << " cutout region " << isub << " has " << cutoutNtubes[isub] << " tubes " << endmsg;
190 }
191 if (cutoutNtubes[isub] <= 0) {
192 log << MSG::INFO << " Skipping cutout region " << isub << " with " << cutoutNtubes[isub] << " tubes in LogVolName " << logVolName << endmsg;
193 continue;
194 }
195
196 double submllength = (cutoutNtubes[isub] * tubePitch) / 2.;
197 if (cutoutFullLength[isub] && isub != cutoutNsteps - 1)
198 submllength += tubePitch / 4.;
199 submlwidthl += submllength * TrdDwoverL;
200 lengthPos = -length / 2. + sum_len + submllength;
201 sum_len += 2. * submllength;
202 double widthPos = cutoutXtubes[isub];
203 GeoTrf::Transform3D submlpos = GeoTrf::Translate3D(0., widthPos, lengthPos);
204
205 const GeoTrd *tempSLay = nullptr;
206 const GeoShape *tempSLay1 = nullptr;
207 const GeoTrd *tempSFoamup = nullptr;
208 const GeoShape *tempSFoamup1 = nullptr;
209 const GeoTrd *tempSFoamlow = nullptr;
210 const GeoShape *tempSFoamlow1 = nullptr;
211
212 if (submlthick * submlwidthl * submllength > 0) {
213 if (verbose_multilayer) {
214 log << MSG::VERBOSE << " LogVolName " << logVolName << " cut step " << isub << " thick = " << submlthick << " short width = " << submlwidths
215 << " long width = " << submlwidthl << " length = " << submllength << " translated to " << widthPos << " , " << lengthPos << endmsg;
216 }
217 if (cutoutFullLength[isub]) {
218 tempSLay = new GeoTrd(submlthick, submlthick, submlwidths, submlwidthl, submllength);
219 } else {
220 tempSLay = new GeoTrd(submlthick, submlthick, cutoutTubeLength[isub] / 2., cutoutTubeLength[isub] / 2., submllength);
221 }
222 tempSLay1 = &((*tempSLay) << submlpos);
223 } else {
224 log << MSG::INFO << " problem with shape of temporary trapezoid in LogVolName " << logVolName << " thick,width,length " << submlthick << " " << submlwidths
225 << " " << submllength << endmsg;
226 }
227
228 if (foamthicknessup != 0 || foamthicknesslow != 0) {
229 if (foamthicknessup > foamthicknesslow) {
230 if (foamthicknessup * submlwidths * submllength > 0) {
231 if (cutoutFullLength[isub]) {
232 tempSFoamup = new GeoTrd(foamthicknessup / 2., foamthicknessup / 2., submlwidths, submlwidthl, submllength);
233 } else {
234 tempSFoamup = new GeoTrd(foamthicknessup / 2., foamthicknessup / 2., cutoutTubeLength[isub] / 2., cutoutTubeLength[isub] / 2., submllength);
235 }
236
237 tempSFoamup1 = &((*tempSFoamup) << submlpos);
238 } else {
239 log << MSG::INFO << " problem with shape of upper foam trapezoid in LogVolName " << logVolName << " thick,width,length " << foamthicknessup << " "
240 << submlwidths << " " << submllength << endmsg;
241 }
242 } else {
243 if (foamthicknesslow * submlwidths * submllength > 0) {
244 if (cutoutFullLength[isub]) {
245 tempSFoamlow = new GeoTrd(foamthicknesslow / 2., foamthicknesslow / 2., submlwidths, submlwidthl, submllength);
246 } else {
247 tempSFoamlow = new GeoTrd(foamthicknesslow / 2., foamthicknesslow / 2., cutoutTubeLength[isub] / 2., cutoutTubeLength[isub] / 2., submllength);
248 }
249 tempSFoamlow1 = &((*tempSFoamlow) << submlpos);
250 } else {
251 log << MSG::INFO << " problem with shape of lower foam trapezoid in LogVolName " << logVolName << " thick,width,length " << foamthicknesslow << " "
252 << submlwidths << " " << submllength << endmsg;
253 }
254 }
255 }
256
257 submlwidths = submlwidthl;
258
259 if (slay) {
260 if (verbose_multilayer) {
261 log << MSG::VERBOSE << " Layer " << slay << " in " << logVolName << " exists - add step section to it " << endmsg;
262 }
263 slay = &(slay->add(*tempSLay1));
264 if (foamthicknessup > 0.)
265 sfoamup = &(sfoamup->add(*tempSFoamup1));
266 if (foamthicknesslow > 0.)
267 sfoamlow = &(sfoamlow->add(*tempSFoamlow1));
268
269 } else {
270 if (verbose_multilayer) {
271 log << MSG::VERBOSE << " Layer slay in " << logVolName << " does not yet exist - create it " << endmsg;
272 }
273 slay = tempSLay1;
274 if (foamthicknessup > 0.)
275 sfoamup = tempSFoamup1;
276 if (foamthicknesslow > 0.)
277 sfoamlow = tempSFoamlow1;
278 }
279 } // Loop over cutout steps
280 } // End of cutout block
281
282 // Add/subtract cylinders at ends of layers 2 and 4 to accommodate the last MDT
283
284 double tL = longWidth / 2.0 - (tubePitch / 2.) * TrdDwoverL;
285 GeoIntrusivePtr<const GeoShape> stube{new GeoTube(0.0, tubePitch / 2., tL)};
286 stube = &((*stube) << GeoTrf::RotateX3D(90. * Gaudi::Units::deg));
287 const GeoShape *stubewithcut = nullptr;
288 if (cutoutNsteps > 1 && m_nonCutoutXSteps.empty()) { // adaption of tube cuts only needed for cutouts along amdb-y
289 double toptubelength = cutoutTubeLength[cutoutNsteps - 1];
291 toptubelength = longWidth;
292 stubewithcut = new GeoTube(0.0, tubePitch / 2., toptubelength / 2.0);
293 stubewithcut = &((*stubewithcut) << GeoTrf::RotateX3D(90. * Gaudi::Units::deg));
294 }
295
296 GeoShape *sbox = new GeoTrd(mdtthickness, mdtthickness, longWidth, longWidth, tubePitch / 2.);
297 slay = &(slay->subtract((*sbox) << GeoTrf::Translate3D(0., 0., length / 2.)));
298
299 for (int i = 0; i < nrOfLayers; i++) {
300 // check in which tubeLayers the layer x position is outside of the envelope and add tube to envelope (not for BMG)
301 if (logVolName.find("BMG") == std::string::npos && 2 * xx[i] >= tubePitch) {
302 // subtract tube at the start
303 if (verbose_multilayer) {
304 log << MSG::VERBOSE << " Cutting tube at xx = " << yy[i] << " z = " << -length / 2. << endmsg;
305 }
306 slay = &(slay->subtract((*stube) << GeoTrf::Translate3D(-mdtthickness / 2. + yy[i], 0., -length / 2.)));
307 // add tube at the end
308 // distinguish stations with/without cutouts
309 if (cutoutNsteps == 1 || !m_nonCutoutXSteps.empty()) {
310 // no cutouts
311 if (verbose_multilayer) {
312 log << MSG::VERBOSE << " Adding tube at xx = " << yy[i] << " z = " << length / 2. << endmsg;
313 }
314 slay = &(slay->add((*stube) << GeoTrf::Translate3D(-mdtthickness / 2. + yy[i], 0., length / 2. - tubePitch / 2.)));
315 } else { // adaption of tube cuts only needed for cutouts along amdb-y
316 // there are cutouts
317 if (verbose_multilayer) {
318 log << MSG::VERBOSE << " Adding tube at xx = " << yy[i] << " y(cutout!) = " << cutoutXtubes[cutoutNsteps - 1] << " z = " << length / 2. << endmsg;
319 }
320 slay = &(slay->add((*stubewithcut) << GeoTrf::Translate3D(-mdtthickness / 2. + yy[i], cutoutXtubes[cutoutNsteps - 1], length / 2. - tubePitch / 2.)));
321 }
322 }
323 } // Loop over layers
324
325
326 const GeoMaterial *mlay = matManager.getMaterial("std::Air");
327 GeoLogVol *llay = new GeoLogVol(logVolName, slay, mlay);
328 GeoFullPhysVol *play = new GeoFullPhysVol(llay);
329
330 double foamposition = 0.;
331 const GeoShape *sfoam = nullptr;
332 const GeoMaterial *mfoam = nullptr;
333 GeoLogVol *lfoam = nullptr;
334 GeoPhysVol *pfoam = nullptr;
335
336 if (foamthicknesslow != 0) {
337 foamposition = -(mdtthickness - foamthicknesslow) / 2.;
338 if (sfoamlow) {
339 sfoam = sfoamlow;
340 } else {
341 sfoam = new GeoTrd(foamthicknesslow / 2. - eps, foamthicknesslow / 2. - eps, width / 2. - eps, longWidth / 2. - eps, length / 2.);
342 }
343 GeoShape *sboxf = new GeoTrd(mdtthickness, mdtthickness, longWidth, longWidth, tubePitch / 4. + 1 * Gaudi::Units::mm);
344 sfoam = &(sfoam->subtract((*sboxf) << GeoTrf::Translate3D(0., 0., length / 2. - tubePitch / 4.)));
345 mfoam = matManager.getMaterial("muo::Foam");
346 lfoam = new GeoLogVol("MultiLayerFoam", sfoam, mfoam);
347
348 } else if (foamthicknessup != 0) {
349 foamposition = (mdtthickness - foamthicknessup) / 2.;
350 if (sfoamup) {
351 sfoam = sfoamup;
352 } else {
353 sfoam = new GeoTrd(foamthicknessup / 2. - eps, foamthicknessup / 2. - eps, width / 2. - eps, longWidth / 2. - eps, length / 2.);
354 }
355 GeoShape *sboxf = new GeoTrd(mdtthickness, mdtthickness, longWidth, longWidth, tubePitch / 4. + 1 * Gaudi::Units::mm);
356 sfoam = &(sfoam->subtract((*sboxf) << GeoTrf::Translate3D(0., 0., length / 2. - tubePitch / 4.)));
357 mfoam = matManager.getMaterial("muo::Foam");
358 lfoam = new GeoLogVol("MultiLayerFoam", sfoam, mfoam);
359
360 } else if (logVolName.find("MDT09") != std::string::npos || logVolName.find("MDT14") != std::string::npos) {
361 // MDT09 is used for BME and BIS sMDTs, MDT14 is used for 2nd multilayer of BIS78
362 // All those sMDTs have no foam layer
363 lfoam = nullptr;
364 } else {
365 log << MSG::ERROR << " no foam thickeness, while it was expected " << endmsg;
366 throw std::runtime_error("ATTENTION: no foam");
367 }
368
369 if (lfoam) { //@@
370 pfoam = new GeoPhysVol(lfoam);
371 GeoTransform *xf = new GeoTransform(GeoTrf::TranslateX3D(foamposition));
372 GeoNameTag *nt = new GeoNameTag(name + " MultiLayerFoam");
373 play->add(new GeoIdentifierTag(0));
374 play->add(nt);
375 play->add(xf);
376 play->add(pfoam);
377 }
378
379 // Calculation of tube lengths and their positions in layers
380
381 double diff = (longWidth - width) * (length - tubePitch / 2.) / length;
382 int nrTubesPerStep = nrOfTubes / nrOfSteps;
383 std::vector<GeoVPhysVol *> tubeVector;
384 std::vector<bool> internalCutout;
385 std::vector<double> tubeDX;
386 std::vector<double> tubeL;
387 std::vector<int> Ntubes;
388
389 // No cutouts
390 if (cutoutNsteps <= 1 || !m_nonCutoutXSteps.empty()) { // adaption of tube cuts only needed for cutouts along amdb-y
391 for (int j = 0; j < nrOfSteps; j++) {
392 tube.length = width + j * diff / nrOfSteps;
393
394 if (verbose_multilayer) {
395 log << MSG::VERBOSE << " logVolName " << logVolName << " step = " << j << " tube length = " << tube.length << endmsg;
396 }
397 tubeVector.push_back(tube.build(matManager));
398 }
399
400 // Cutouts
401 } else {
402 if (verbose_multilayer) {
403 log << MSG::VERBOSE << " logVolName " << logVolName << " cutoutNsteps =" << cutoutNsteps << " nsteps " << nrOfSteps << endmsg;
404 }
405 int ntubes = 0;
406
407 // Loop over non-cutout steps
408
409 for (int j = 0; j < nrOfSteps; j++) {
410 if (verbose_multilayer) {
411 log << MSG::VERBOSE << " Building tube vectors for step " << j << endmsg;
412 }
413 double tlength = width + j * diff / nrOfSteps;
414 double tlen = 0.;
415 double previousTlen = -1.;
416 int nTubeToSwitch[5] = {0};
417 if (cutoutNsteps > 5)
418 std::abort();
419
420 for (int ii = 0; ii < cutoutNsteps; ii++) {
421 if (verbose_multilayer) {
422 log << MSG::VERBOSE << " Building tube vectors for cutout step " << ii << endmsg;
423 }
424 nTubeToSwitch[ii] = cutoutNtubes[ii] - 1;
425 if (ii > 0) {
426 for (int k = ii - 1; k >= 0; k--) {
427 nTubeToSwitch[ii] += cutoutNtubes[k];
428 }
429 }
430 if (verbose_multilayer) {
431 log << MSG::VERBOSE << " nTubeToSwitch[" << ii << "]=" << nTubeToSwitch[ii] << endmsg;
432 }
433 }
434
435 // Loop over tubes in non-cutout step
436 for (int it = 0; it < nrTubesPerStep; it++) {
437 tlen = tlength; // Calculated tube length within non-cutout step
438 double dx = 0.;
439
440 // For each tube within non-cutout step, find which cutout step it is in
441 int weAreInCutStep = 0;
442 if (cutoutNsteps > 5)
443 std::abort();
444 for (int ic = 0; ic < cutoutNsteps; ic++) {
445 if (verbose_multilayer) {
446 log << MSG::VERBOSE << " Loop over cuts ic " << ic << " FullLength " << cutoutFullLength[ic] << " ymax " << cutoutYmax[ic] << endmsg;
447 }
448 if (it + nrTubesPerStep * j > nTubeToSwitch[ic])
449 weAreInCutStep++;
450 }
451
452 if (verbose_multilayer) {
453 log << MSG::VERBOSE << " Tube " << it << " is in cut step " << weAreInCutStep << endmsg;
454 }
455
456 // Override original tube length with cutout tube length and position
457 if (nrOfSteps == 1 || !cutoutFullLength[weAreInCutStep]) {
458 tlen = cutoutTubeLength[weAreInCutStep];
459 dx = cutoutXtubes[weAreInCutStep];
460 if (longWidth > width)
461 tlen -= 3; // temporary fix - see above
462 // if (longWidth > width) {
463 // double smallshift = 2.;
464 // tlen -= smallshift; // temporary fix - see above
465 // if (cutoutXtubes[weAreInCutStep]+cutoutTubeLength[weAreInCutStep]/2. < tlength/2. - 20.) {
466 // dx += smallshift/2.;
467 // } else {
468 // dx -= smallshift/2.;
469 // }
470 // }
471 }
472
473 if (std::abs(tlen - previousTlen) > 0.001) {
474 tube.length = tlen;
475 tubeVector.push_back(tube.build(matManager));
476 if (weAreInCutStep < 1) {
477 internalCutout.push_back(false);
478 } else {
479 internalCutout.push_back(!cutoutFullLength[weAreInCutStep] && cutoutYmax[weAreInCutStep] < length - tubePitch / 2.);
480 }
481 tubeDX.push_back(dx);
482 tubeL.push_back(tlen);
483 previousTlen = tlen;
484 if (ntubes > 0)
485 Ntubes.push_back(ntubes);
486 ntubes = 1;
487
488 } else {
489 ntubes++;
490 }
491
492 if ((j * nrOfSteps + it) == nrOfTubes - 1)
493 Ntubes.push_back(ntubes);
494 if (verbose_multilayer) {
495 log << MSG::VERBOSE << " ntubes = " << ntubes << endmsg;
496 }
497 } // Loop over tubes in non-cutout steps
498 } // Loop over non-cutout steps
499 } // End cutout section
500
501 // Placement of MDTs in layers
502
503 double lstart;
504 double tstart;
505 GeoSerialDenominator *sd = new GeoSerialDenominator("DriftTube");
506 play->add(sd);
507
509
510 std::array<bool, 3> internalCutoutBMG{false, true, false};
511 std::array<std::array<int, 3>, 4> NtubesBMG{};
512
513 if (cutoutNsteps == -11112) { // BMG1A12 - ML1
514 NtubesBMG = {{{{23, 7, 24}}, {{24, 7, 23}}, {{24, 7, 23}}, {{25, 7, 22}}}};
515 } else if (cutoutNsteps == -11212) { // BMG1A12 - ML2
516 NtubesBMG = {{{{29, 7, 18}}, {{30, 7, 17}}, {{30, 7, 17}}, {{31, 7, 16}}}};
517 } else if (cutoutNsteps == -21112) { // BMG2A12 - ML1
518 NtubesBMG = {{{{13, 8, 33}}, {{14, 8, 32}}, {{14, 8, 32}}, {{15, 8, 31}}}};
519 } else if (cutoutNsteps == -21212) { // BMG2A12 - ML2
520 NtubesBMG = {{{{25, 8, 21}}, {{26, 8, 20}}, {{26, 8, 20}}, {{27, 8, 19}}}};
521 } else if (cutoutNsteps == -31112) { // BMG3A12 - ML1
522 NtubesBMG = {{{{14, 14, 26}}, {{16, 14, 24}}, {{16, 14, 24}}, {{18, 14, 22}}}};
523 } else if (cutoutNsteps == -31212) { // BMG3A12 - ML2
524 NtubesBMG = {{{{31, 14, 9}}, {{33, 14, 7}}, {{33, 14, 7}}, {{35, 14, 5}}}};
525 } else if (cutoutNsteps == -12112) { // BMG1C12 - ML1
526 NtubesBMG = {{{{24, 6, 24}}, {{23, 7, 24}}, {{24, 7, 23}}, {{24, 7, 23}}}};
527 } else if (cutoutNsteps == -12212) { // BMG1C12 - ML2
528 NtubesBMG = {{{{30, 7, 17}}, {{29, 8, 17}}, {{31, 7, 16}}, {{31, 6, 17}}}};
529 } else if (cutoutNsteps == -22112) { // BMG2C12 - ML1
530 NtubesBMG = {{{{13, 8, 33}}, {{13, 8, 33}}, {{14, 9, 31}}, {{15, 8, 31}}}};
531 } else if (cutoutNsteps == -22212) { // BMG2C12 - ML2
532 NtubesBMG = {{{{25, 8, 21}}, {{25, 8, 21}}, {{27, 8, 19}}, {{27, 8, 19}}}};
533 } else if (cutoutNsteps == -32112) { // BMG3C12 - ML1
534 NtubesBMG = {{{{15, 13, 26}}, {{15, 14, 25}}, {{17, 13, 24}}, {{17, 14, 23}}}};
535 } else if (cutoutNsteps == -32212) { // BMG3C12 - ML2
536 NtubesBMG = {{{{32, 14, 8}}, {{32, 14, 8}}, {{34, 14, 6}}, {{34, 14, 6}}}};
537 } else if (cutoutNsteps == -11114) { // BMG1A14 - ML1
538 NtubesBMG = {{{{24, 6, 24}}, {{23, 7, 24}}, {{24, 7, 23}}, {{24, 7, 23}}}};
539 } else if (cutoutNsteps == -11214) { // BMG1A14 - ML2
540 NtubesBMG = {{{{30, 7, 17}}, {{29, 8, 17}}, {{31, 7, 16}}, {{31, 6, 17}}}};
541 } else if (cutoutNsteps == -21114) { // BMG2A14 - ML1
542 NtubesBMG = {{{{13, 8, 33}}, {{13, 8, 33}}, {{14, 9, 31}}, {{15, 8, 31}}}};
543 } else if (cutoutNsteps == -21214) { // BMG2A14 - ML2
544 NtubesBMG = {{{{25, 8, 21}}, {{25, 8, 21}}, {{27, 8, 19}}, {{27, 8, 19}}}};
545 } else if (cutoutNsteps == -31114) { // BMG3A14 - ML1
546 NtubesBMG = {{{{19, 9, 26}}, {{19, 10, 25}}, {{21, 9, 24}}, {{21, 10, 23}}}};
547 } else if (cutoutNsteps == -31214) { // BMG3A14 - ML2
548 NtubesBMG = {{{{36, 10, 8}}, {{37, 9, 8}}, {{38, 10, 6}}, {{39, 9, 6}}}};
549 } else if (cutoutNsteps == -12114) { // BMG1C14 - ML1
550 NtubesBMG = {{{{23, 7, 24}}, {{24, 7, 23}}, {{24, 7, 23}}, {{25, 7, 22}}}};
551 } else if (cutoutNsteps == -12214) { // BMG1C14 - ML2
552 NtubesBMG = {{{{29, 7, 18}}, {{30, 7, 17}}, {{30, 7, 17}}, {{31, 7, 16}}}};
553 } else if (cutoutNsteps == -22114) { // BMG2C14 - ML1
554 NtubesBMG = {{{{13, 8, 33}}, {{14, 8, 32}}, {{14, 8, 32}}, {{15, 8, 31}}}};
555 } else if (cutoutNsteps == -22214) { // BMG2C14 - ML2
556 NtubesBMG = {{{{25, 8, 21}}, {{26, 8, 20}}, {{26, 8, 20}}, {{27, 8, 19}}}};
557 } else if (cutoutNsteps == -32114) { // BMG3C14 - ML1
558 NtubesBMG = {{{{18, 10, 26}}, {{20, 10, 24}}, {{20, 10, 24}}, {{22, 10, 22}}}};
559 } else if (cutoutNsteps == -32214) { // BMG3C14 - ML2
560 NtubesBMG = {{{{36, 9, 9}}, {{37, 10, 7}}, {{38, 9, 7}}, {{39, 10, 5}}}};
561 } else {
562 NtubesBMG = {{{{0, 0, 0}}, {{0, 0, 0}}, {{0, 0, 0}}, {{0, 0, 0}}}};
563 log << MSG::ERROR << "massive error placing tubes for BMG chambers" << endmsg;
564 std::abort();
565 }
566
567 for (int i = 0; i < nrOfLayers; i++) {
568 if (verbose_multilayer) {
569 log << MSG::VERBOSE << "Tube Layers n. " << i << endmsg;
570 }
571
572 tstart = -mdtthickness / 2. + yy[i];
573 double loffset = 0.;
574 int nttot = 0;
575 for (unsigned int j = 0; j < sizeof(NtubesBMG[i]) / sizeof(int); j++) {
576 // for BMGs tubeVector should be of size 1 with the one default tube
577 GeoVPhysVol *tV = tubeVector[0];
578 int nt = NtubesBMG[i][j];
579
580 if (verbose_multilayer) {
581 log << MSG::VERBOSE << "cutout region " << j << " n. of tubes affected should be " << NtubesBMG[i][j] << " internal cutout " << internalCutoutBMG[j]
582 << endmsg;
583 }
584
585 // ususal tube placement
586 if (nt > 0 && !internalCutoutBMG[j]) {
587 loffset = nttot * tubePitch;
588 lstart = loffset - length / 2. + xx[i];
589 GeoGenfun::Variable K;
590 GeoGenfun::GENFUNCTION f = tubePitch * K + lstart;
591 TRANSFUNCTION t = GeoTrf::TranslateY3D(0.) * GeoTrf::RotateX3D(90 * Gaudi::Units::deg) * GeoTrf::TranslateX3D(tstart) * Pow(GeoTrf::TranslateY3D(1.0), f);
592 GeoSerialTransformer *s = new GeoSerialTransformer(tV, &t, nt);
593 play->add(new GeoSerialIdentifier(maxNTubesPerLayer * (i + 1) + nttot + 1));
594 play->add(s);
595
596 nttot = nttot + nt;
597 if (verbose_multilayer) {
598 log << MSG::VERBOSE << " placing " << nt << " starting at t = " << tstart << " , y = " << lstart << " with " << nttot << " tubes so far " << endmsg;
599 }
600 } else {
601 nttot = nttot + nt;
602 if (verbose_multilayer) {
603 log << MSG::VERBOSE << " *NOT* placing " << nt << " starting at t = " << tstart << " , y = " << lstart << " with " << nttot << " tubes so far "
604 << endmsg;
605 }
606 }
607 }
608 } // Loop over layers
609
610 } else if (cutoutNsteps > 1 && m_nonCutoutXSteps.empty()) { // adaption of tube cuts only needed for cutouts along amdb-y
611 bool arrowpointoutwards = false;
612 bool cutAtAngle = cutoutAtAngle;
613 if (xx[1] - xx[0] > 0.) {
614 // arrow pointing outwards: like MDT 2
615 arrowpointoutwards = true;
616 }
617
618 for (int i = 0; i < nrOfLayers; i++) {
619 if (verbose_multilayer) {
620 log << MSG::VERBOSE << "Tube Layers n. " << i << endmsg;
621 }
622
623 tstart = -mdtthickness / 2. + yy[i];
624 double loffset = 0.;
625 int nttot = 0;
626 bool nextTimeSubtract = false;
627
628 for (unsigned int j = 0; j < tubeVector.size(); j++) {
629 GeoVPhysVol *tV = tubeVector[j];
630 double dy = tubeDX[j];
631 int nt = Ntubes[j];
632
633 if (arrowpointoutwards && cutAtAngle) {
634 if (j < tubeVector.size() - 1) {
635 if (internalCutout[j + 1]) {
636 // next region is the one with the cutout:
637 // for tubeLayer 3 (and 4) must increase the number of tubes in this region by one
638 if (i > 1)
639 nt += 1;
640 }
641 }
642
643 if (j > 0) {
644 if (internalCutout[j - 1]) {
645 // previous region is the one with the cutout:
646 // for tubeLayer 3 (and 4) must decrease the number of tubes in this region by one
647 if (i > 1)
648 nt -= 1;
649 }
650 }
651 }
652
653 if (verbose_multilayer) {
654 log << MSG::VERBOSE << "staircasing or cutout region " << j << " n. of tubes affected should be " << Ntubes[j] << " and are " << nt << " internal cutout "
655 << internalCutout[j] << " next time subtract " << nextTimeSubtract << endmsg;
656 }
657
658 if (nt > 0) {
659 loffset = nttot * tubePitch;
660 lstart = loffset - length / 2. + xx[i];
661 GeoGenfun::Variable K;
662 GeoGenfun::GENFUNCTION f = tubePitch * K + lstart;
663 TRANSFUNCTION t = GeoTrf::TranslateY3D(dy) * GeoTrf::RotateX3D(90 * Gaudi::Units::deg) * GeoTrf::TranslateX3D(tstart) * Pow(GeoTrf::TranslateY3D(1.0), f);
664 GeoSerialTransformer *s = new GeoSerialTransformer(tV, &t, nt);
665 play->add(new GeoSerialIdentifier(maxNTubesPerLayer * (i + 1) + nttot + 1));
666 play->add(s);
667
668 nttot = nttot + nt;
670 log << MSG::VERBOSE << " placing " << nt << " tubes of length " << tubeL[j] << " starting at t = " << tstart << " , y = " << lstart << " and x = " << dy
671 << " with " << nttot << " tubes so far " << endmsg;
672 }
673 }
674 } // Loop over layers
675
676 } else if (nrOfSteps == 1) {
677 // At this point no cutouts and only one non-cutout step
678 for (int i = 0; i < nrOfLayers; i++) {
679 tstart = -mdtthickness / 2. + yy[i];
680 lstart = -length / 2. + xx[i];
681 GeoGenfun::Variable K;
682 GeoGenfun::GENFUNCTION f = tubePitch * K + lstart;
683 TRANSFUNCTION t = GeoTrf::RotateX3D(90 * Gaudi::Units::deg) * GeoTrf::TranslateX3D(tstart) * Pow(GeoTrf::TranslateY3D(1.0), f);
684 GeoVPhysVol *tV = tubeVector[0];
685 GeoSerialTransformer *s = new GeoSerialTransformer(tV, &t, nrOfTubes);
686 play->add(new GeoSerialIdentifier(maxNTubesPerLayer * (i + 1) + 1));
687 play->add(s);
688 }
689 } else {
690 // Here, no cutouts but multiple non-cutout steps
691 lstart = 0.;
692 for (int i = 0; i < nrOfLayers; i++) {
693 tstart = -mdtthickness / 2. + yy[i];
694 double loffset = 0.;
695
696 for (int j = 0; j < nrOfSteps; j++) {
697 GeoVPhysVol *tV = tubeVector[j];
698 loffset = j * nrTubesPerStep * tubePitch;
699 lstart = loffset - length / 2. + xx[i];
700 GeoGenfun::Variable K;
701 GeoGenfun::GENFUNCTION f = tubePitch * K + lstart;
702 TRANSFUNCTION t = GeoTrf::RotateX3D(90 * Gaudi::Units::deg) * GeoTrf::TranslateX3D(tstart) * Pow(GeoTrf::TranslateY3D(1.0), f);
703 GeoSerialTransformer *s = new GeoSerialTransformer(tV, &t, nrTubesPerStep);
704 play->add(new GeoSerialIdentifier(maxNTubesPerLayer * (i + 1) + j * nrTubesPerStep + 1));
705 play->add(s);
706 }
707 }
708 }
709
710 return play;
711 }
712
713 void MultiLayer::print() const {
714 MsgStream log(Athena::getMessageSvc(), "MuonGM::MultiLayer");
715 log << MSG::INFO << "Multi Layer " << name.c_str() << " :" << endmsg;
716 }
717
718} // namespace MuonGM
#define endmsg
#define verbose_multilayer
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
static constexpr int maxNTubesPerLayer
The maxNTubesPerLayer represents the absolute maximum of tubes which are built into a single multilay...
Definition MdtIdHelper.h:68
DetectorElement(const std::string &n)
double totalThickness
std::array< double, 4 > y
std::array< double, 4 > x
Technology * GetTechnology(const std::string &name)
Definition MYSQL.cxx:105
std::array< double, 5 > cutoutTubeLength
Definition MultiLayer.h:42
std::array< double, 5 > cutoutYmax
Definition MultiLayer.h:41
std::vector< std::pair< double, double > > m_nonCutoutYSteps
Definition MultiLayer.h:49
std::array< double, 4 > xx
Definition MultiLayer.h:35
std::array< double, 4 > yy
Definition MultiLayer.h:34
std::array< int, 5 > cutoutNtubes
Definition MultiLayer.h:39
MultiLayer(const MYSQL &mysql, const std::string &n)
virtual void print() const override
std::array< bool, 5 > cutoutFullLength
Definition MultiLayer.h:43
std::array< double, 5 > cutoutXtubes
Definition MultiLayer.h:40
GeoFullPhysVol * build(StoredMaterialManager &matManager, const MYSQL &mysql)
std::vector< std::pair< double, double > > m_nonCutoutXSteps
Definition MultiLayer.h:48
This class holds one or more material managers and makes them storeable, under StoreGate.
virtual const GeoMaterial * getMaterial(const std::string &name)=0
singleton-like access to IMessageSvc via open function and helper
IMessageSvc * getMessageSvc(bool quiet=false)
Ensure that the Athena extensions are properly loaded.
Definition GeoMuonHits.h:27