ATLAS Offline Software
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"
29 #include "MuonGeoModel/DriftTube.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 
43 class GeoMaterial;
44 class GeoVPhysVol;
45 
46 using namespace GeoXF;
47 
48 #define verbose_multilayer false
49 
50 namespace {
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 
55 namespace 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) {
63  nrOfLayers = md->numOfLayers;
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;
85  if (verbose_multilayer) {
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;
141  if (cutoutNsteps == 1 || cutoutAtAngle || (cutoutNsteps < -10000 && cutoutNsteps > -40000)) {
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 
508  if (cutoutNsteps < -10000 && cutoutNsteps > -40000) {
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;
669  if (verbose_multilayer)
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
python.TriggerHandler.tstart
string tstart
Definition: TriggerHandler.py:299
MuonGM::MYSQL::GetTechnology
Technology * GetTechnology(const std::string &name)
Definition: MYSQL.cxx:105
python.CaloRecoConfig.f
f
Definition: CaloRecoConfig.py:127
MuonGM::DetectorElement::name
std::string name
Definition: DetectorElement.h:17
verbose_multilayer
#define verbose_multilayer
Definition: MultiLayer.cxx:48
MuonGM
Ensure that the Athena extensions are properly loaded.
Definition: GeoMuonHits.h:27
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
MuonGM::MultiLayer::length
double length
Definition: MultiLayer.h:25
MuonGM::MultiLayer::cutoutFullLength
std::array< bool, 5 > cutoutFullLength
Definition: MultiLayer.h:43
skel.it
it
Definition: skel.GENtoEVGEN.py:423
MuonGM::MultiLayer::cutoutTubeLength
std::array< double, 5 > cutoutTubeLength
Definition: MultiLayer.h:42
deg
#define deg
Definition: SbPolyhedron.cxx:17
mc.diff
diff
Definition: mc.SFGenPy8_MuMu_DD.py:14
MuonGM::MultiLayer::tubePitch
double tubePitch
Definition: MultiLayer.h:23
MuonGM::MDT::numOfLayers
int numOfLayers
Definition: MDT_Technology.h:17
MuonGM::MYSQL
Definition: MYSQL.h:43
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
MuonGM::MultiLayer::xx
std::array< double, 4 > xx
Definition: MultiLayer.h:35
MuonGM::DetectorElement
Definition: DetectorElement.h:15
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
MuonGM::MultiLayer::yy
std::array< double, 4 > yy
Definition: MultiLayer.h:34
MuonGM::MultiLayer::nrOfSteps
int nrOfSteps
Definition: MultiLayer.h:29
MuonGM::MultiLayer::build
GeoFullPhysVol * build(StoredMaterialManager &matManager, const MYSQL &mysql)
Definition: MultiLayer.cxx:78
MuonGM::MDT
Definition: MDT_Technology.h:15
python.selector.AtlRunQuerySelectorLhcOlc.sd
sd
Definition: AtlRunQuerySelectorLhcOlc.py:612
MuonGM::MultiLayer::width
double width
Definition: MultiLayer.h:24
MuonGM::MultiLayer::cutoutNsteps
int cutoutNsteps
Definition: MultiLayer.h:38
lumiFormat.i
int i
Definition: lumiFormat.py:92
beamspotman.n
n
Definition: beamspotman.py:731
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
MuonGM::MDT::totalThickness
double totalThickness
Definition: MDT_Technology.h:20
MultiLayer.h
MuonGM::MDT::y
std::array< double, 4 > y
Definition: MDT_Technology.h:25
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MdtIdHelper.h
MuonGM::MultiLayer::cutoutNtubes
std::array< int, 5 > cutoutNtubes
Definition: MultiLayer.h:39
MuonGM::MultiLayer::m_nonCutoutYSteps
std::vector< std::pair< double, double > > m_nonCutoutYSteps
Definition: MultiLayer.h:49
grepfile.ic
int ic
Definition: grepfile.py:33
MYSQL.h
MuonGM::MultiLayer::cutoutAtAngle
bool cutoutAtAngle
Definition: MultiLayer.h:44
StoredMaterialManager.h
MuonGM::MDT::x
std::array< double, 4 > x
Definition: MDT_Technology.h:26
MDT_Technology.h
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
makeTRTBarrelCans.dy
tuple dy
Definition: makeTRTBarrelCans.py:21
MuonGM::MultiLayer::print
virtual void print() const override
Definition: MultiLayer.cxx:713
makeTRTBarrelCans.dx
tuple dx
Definition: makeTRTBarrelCans.py:20
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
StoredMaterialManager::getMaterial
virtual const GeoMaterial * getMaterial(const std::string &name)=0
StoredMaterialManager
This class holds one or more material managers and makes them storeable, under StoreGate.
Definition: StoredMaterialManager.h:28
MuonGM::MultiLayer::nrOfLayers
int nrOfLayers
Definition: MultiLayer.h:21
MuonGM::DetectorElement::logVolName
std::string logVolName
Definition: DetectorElement.h:18
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
MuonGM::MultiLayer::longWidth
double longWidth
Definition: MultiLayer.h:28
beamspotnt.nt
def nt
Definition: bin/beamspotnt.py:1063
MuonGM::MultiLayer::mdtthickness
double mdtthickness
Definition: MultiLayer.h:27
MuonGM::MDT::pitch
double pitch
Definition: MDT_Technology.h:18
MdtIdHelper::maxNTubesPerLayer
static constexpr int maxNTubesPerLayer
The maxNTubesPerLayer represents the absolute maximum of tubes which are built into a single multilay...
Definition: MdtIdHelper.h:68
MuonGM::DriftTube
Definition: DriftTube.h:17
MuonGM::MultiLayer::nrOfTubes
int nrOfTubes
Definition: MultiLayer.h:22
DriftTube.h
calibdata.tube
tube
Definition: calibdata.py:31
fitman.k
k
Definition: fitman.py:528
MuonGM::MultiLayer::cutoutYmax
std::array< double, 5 > cutoutYmax
Definition: MultiLayer.h:41
MuonGM::MultiLayer::cutoutXtubes
std::array< double, 5 > cutoutXtubes
Definition: MultiLayer.h:40
MuonGM::MultiLayer::m_nonCutoutXSteps
std::vector< std::pair< double, double > > m_nonCutoutXSteps
Definition: MultiLayer.h:48