ATLAS Offline Software
HECModuleConstruction.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // HECModuleConstruction.cxx 1.0.0
6 // Derived from the HECConstruction - M. Fincke, Sept.2007
7 //
9 
10 #include "GeoModelKernel/GeoElement.h"
11 #include "GeoModelKernel/GeoMaterial.h"
12 #include "GeoModelKernel/GeoFullPhysVol.h"
13 #include "GeoModelKernel/GeoPhysVol.h"
14 #include "GeoModelKernel/GeoVPhysVol.h"
15 #include "GeoModelKernel/GeoLogVol.h"
16 #include "GeoModelKernel/GeoPcon.h"
17 #include "GeoModelKernel/GeoTubs.h"
18 #include "GeoModelKernel/GeoNameTag.h"
19 #include "GeoModelKernel/GeoTransform.h"
20 #include "GeoModelKernel/GeoAlignableTransform.h"
21 #include "GeoModelKernel/GeoIdentifierTag.h"
22 #include "GeoModelKernel/GeoSerialTransformer.h"
23 #include "GeoModelKernel/GeoSerialIdentifier.h"
24 #include "GeoModelKernel/GeoXF.h"
25 #include "GeoModelKernel/GeoDefinitions.h"
26 #include "GeoGenericFunctions/Variable.h"
27 #include "StoreGate/StoreGateSvc.h"
29 #include "GaudiKernel/MsgStream.h"
30 #include "GaudiKernel/Bootstrap.h"
31 #include "GaudiKernel/SystemOfUnits.h"
37 
38 #include <string>
39 #include <cmath>
40 #include <iostream>
41 #include <array>
42 
43 using Gaudi::Units::cm;
44 using Gaudi::Units::mm;
45 using Gaudi::Units::deg;
46 using GeoTrf::Translate3D;
47 using GeoTrf::TranslateY3D;
48 using GeoTrf::TranslateZ3D;
49 
50 
51 //Constructor
52 LArGeo::HECModuleConstruction::HECModuleConstruction(bool threeBoards, bool frontWheel, bool tb, int tbyear):
53  m_physiHECModule(nullptr)
54 {
55  m_threeBoards = threeBoards; // If true, build 3 boards in gap. Else just one thick board.
56  m_frontWheel = frontWheel; // If true, build a front Module. Else build a rear Module.
57  m_tb = tb; // If true, build a Module for testbeam.
58  m_tbyear = tbyear; // If testbeam, specify the testbeam year.
59 
60 }
61 
62 GeoIntrusivePtr<GeoFullPhysVol> LArGeo::HECModuleConstruction::GetEnvelope()
63 {
64  if(m_physiHECModule) return m_physiHECModule->clone();
65 
66  ISvcLocator *svcLocator = Gaudi::svcLocator();
67 
68  MsgStream log(Athena::getMessageSvc(),"HECModuleConstruction " );
69 
70  log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endmsg;
71  log << MSG::DEBUG << "+ +" << endmsg;
72  log << MSG::DEBUG << "+ Start of HECModule GeoModel definition +" << endmsg;
73  log << MSG::DEBUG << "+ +" << endmsg;
74  log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endmsg;
75 
76 
77  SmartIF<StoreGateSvc> detStore{svcLocator->service("DetectorStore")};
78  if(!detStore.isValid()) {
79  throw std::runtime_error("Error in HECModuleConstruction, cannot access DetectorStore");
80  }
81 
82 
83  StoredMaterialManager* materialManager = nullptr;
84  if (StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) {
85  throw std::runtime_error("Error in HECModuleConstruction, cannot access Material Manager");
86  }
87 
88  const GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon");
89  if (!LAr) throw std::runtime_error("Error in HECModuleConstruction, std::LiquidArgon is not found.");
90 
91  const GeoMaterial *Iron = materialManager->getMaterial("std::Iron");
92  if (!Iron) throw std::runtime_error("Error in HECModuleConstruction, std::Iron is not found.");
93 
94  const GeoMaterial *Copper = materialManager->getMaterial("std::Copper");
95  if (!Copper) throw std::runtime_error("Error in HECModuleConstruction, std::Copper is not found.");
96 
97  const GeoMaterial *Kapton = materialManager->getMaterial("std::Kapton");
98  if (!Kapton) throw std::runtime_error("Error in HECModuleConstruction, std::Kapton is not found.");
99 
100 
101  SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service("RDBAccessSvc")};
102  if(!pAccessSvc.isValid()) {
103  throw std::runtime_error ("Cannot locate RDBAccessSvc!!");
104  }
105 
106  SmartIF<IGeoModelSvc> geoModel{svcLocator->service ("GeoModelSvc")};
107  if(!geoModel.isValid()) {
108  throw std::runtime_error ("Cannot locate GeoModelSvc!!");
109  }
110 
111  std::string AtlasVersion = geoModel->atlasVersion();
112  std::string LArVersion = geoModel->LAr_VersionOverride();
113 
114  std::string detectorKey = LArVersion.empty() ? AtlasVersion : LArVersion;
115  std::string detectorNode = LArVersion.empty() ? "ATLAS" : "LAr";
116 
117  IRDBRecordset_ptr hadronicEndcap = pAccessSvc->getRecordsetPtr("HadronicEndcap",detectorKey, detectorNode);
118  if(hadronicEndcap->size()>0)
119  log << MSG::DEBUG << "Using numbers from HadronicEndcap tag: " << hadronicEndcap->tagName() << endmsg;
120  else
121  throw std::runtime_error("Error in HECConstruction: hadronicEendcap not found");
122 
123  IRDBRecordset_ptr hecLongitudinalBlock = pAccessSvc->getRecordsetPtr("HecLongitudinalBlock",detectorKey, detectorNode);
124  if(hecLongitudinalBlock->size()>0)
125  log << MSG::DEBUG << "Using numbers from HecLongitudinalBlock tag: " << hecLongitudinalBlock->tagName() << endmsg;
126  else
127  throw std::runtime_error("Error in HECConstruction: hecLongitudinalBlock not found");
128 
129  //----------------------------------------------------------------
130  // Collect all the numbers we need from the database:
131  //----------------------------------------------------------------
132 
133  double shrinkCold = 1.0; //thermal expansion factor: 1.0 = warm geometry
134  //kapton is treated the same at Cu and Fe at the moment
135 
136  int moduleNumber = (*hadronicEndcap)[0]->getInt("NSCT");
137  double moduleRinner1 = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMN")*cm;
138  double moduleRinner2 = shrinkCold * (*hecLongitudinalBlock)[1]->getDouble("BLRMN")*cm;
139  double moduleRouter = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMX")*cm;
140  if (m_tbyear==2004) moduleRouter = moduleRinner1 + 787*mm; // Mini Modules for 2004 testbeam CAUTION! Hard-coded number!!!
141  double copperPad = shrinkCold * (*hadronicEndcap)[0]->getDouble("COPPER")*cm;
142  double gapSize = shrinkCold * (*hadronicEndcap)[0]->getDouble("LARG")*cm;
143  double drModOverlap = shrinkCold * (*hadronicEndcap)[0]->getDouble("DRMODOVERLAP")*cm;
144  double kaptonWidth[2];
145  kaptonWidth[0] = shrinkCold * (*hadronicEndcap)[0]->getDouble("ESTPL")*cm;
146  kaptonWidth[1] = shrinkCold * (*hadronicEndcap)[0]->getDouble("PADPL")*cm;
147  int gapN[7];
148  for(int id=0;id<7;id++) gapN[id] = (int) (*hecLongitudinalBlock)[id]->getDouble("BLMOD");
149  double firstFrontAbsThickness= shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("PLATE0")*cm;
150  double firstRearAbsThickness = shrinkCold * (*hecLongitudinalBlock)[3]->getDouble("PLATE0")*cm;
151  double frontAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_0")*cm;
152  double rearAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_1")*cm;
153  double tieRodPositionX[4];
154  double tieRodPositionY[4];
155  tieRodPositionX[0] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_0")*cm;
156  tieRodPositionY[0] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_0")*cm;
157  tieRodPositionX[1] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_1")*cm;
158  tieRodPositionY[1] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_1")*cm;
159  tieRodPositionX[2] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_2")*cm;
160  tieRodPositionY[2] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_2")*cm;
161  tieRodPositionX[3] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_3")*cm;
162  tieRodPositionY[3] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_3")*cm;
163  double tieRodDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODDIM_0")*cm;
164  double spacerDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("SPCDIM_0")*cm;
165  double spacerDeadZone = shrinkCold * 3.0*mm;
166  if (!m_frontWheel)
167  {
168  tieRodDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODDIM_1")*cm;
169  spacerDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("SPCDIM_1")*cm;
170  }
171 
172 
173  //--- Get the right Absorber thickness and Depth number depending on Front or Rear Wheel (and TB)
174  // (2002 and 2004 testbeam have only 1/2 rear depth)
175  int depthNumber = 3;
176  int depthOffset = depthNumber; // need this to start rear wheel depth-number at 3
177  double absThickness = frontAbsThickness;
178  double firstAbsThickness = firstFrontAbsThickness;
179  if (!m_frontWheel) {
180  depthNumber = 4;
181  if (m_tb) depthNumber= 2;
182  absThickness = rearAbsThickness;
183  firstAbsThickness = firstRearAbsThickness;
184  }
185 
186 
187  //---- Calculate the sizes of the 7 longitudinal Depths -------------------------------------
188  double depthS[7];
189  depthS[0] = firstFrontAbsThickness + gapN[0]*(frontAbsThickness+gapSize);
190  depthS[1] = gapN[1]*(frontAbsThickness+gapSize);
191  depthS[2] = gapN[2]*(frontAbsThickness+gapSize);
192  depthS[3] = firstRearAbsThickness + gapN[3]*(rearAbsThickness+gapSize);
193  depthS[4] = gapN[4]*(rearAbsThickness+gapSize);
194  depthS[5] = gapN[5]*(rearAbsThickness+gapSize);
195  depthS[6] = gapN[6]*(rearAbsThickness+gapSize);
196 
197  //--- From the depth Size, calculate the boundary planes of the Module Mother volume ---------
198  // (Add 0.1 mm to avoid clashes)
199  double zCoordinate[4];
200  double depthSize[4];
201  int gapNumber[4];
202  int gaptally[4];
203  double g4allow = shrinkCold * 0.1*mm ;
204  double g4allowS = 0.001*mm ;
205  if (m_frontWheel){
206  zCoordinate[0] = shrinkCold * 0.0*cm;
207  zCoordinate[1] = depthS[0];
208  zCoordinate[2] = depthS[0] + g4allow;
209  zCoordinate[3] = depthS[0]+depthS[1]+depthS[2] + g4allow; // End of front Module
210  gaptally[0]=0;
211  for (int i=0; i<3; i++) {
212  if (i>0) gaptally[i] = gaptally[i-1] + gapN[i-1];
213  gapNumber[i] = gapN[i];
214  depthSize[i] = depthS[i];
215  }
216  }
217  else{
218  zCoordinate[0] = shrinkCold * 0.0*cm;
219  zCoordinate[1] = depthS[3]+depthS[4]+depthS[5]+depthS[6]+g4allow; // End of rear Atlas Module
220  if(m_tb) zCoordinate[1]= depthS[3]+depthS[4]+g4allow; // For TB only 1/2 rear depth
221  gaptally[0] = 0;
222  for (int i=0; i<4; i++) { // Re-number the rear wheel
223  if (i>0) gaptally[i] =gaptally[i-1] + gapN[i+3-1];
224  gapNumber[i] = gapN[i+3]; // gaps and depths to have
225  depthSize[i] = depthS[i+3]; // their index start at Zero.
226  }
227  }
228 
229  //--- Calculate where to put the tie-rod spacers into the available LAr gap.
230  // This depends on the configuration of the boards.
231 
232  // +/-ztie are the center z-coordinates of the LAr sub-gaps
233  // rodSize is the length of spacer to be fit into the LAr that is not occupied by boards
234  // Small tolerance to fit G4 volumes into one another
235  double ztie[2];
236  double rodSize;
237 
238  //-- For Three-board approach:
239  if (m_threeBoards) {
240  double halfGap = gapSize/2.;
241  double halfGapLAr = (gapSize - kaptonWidth[1])/2.;
242  double restLAr = (halfGapLAr-kaptonWidth[0])/2. ;
243  ztie[0] = restLAr/2 + kaptonWidth[1]/2.;
244  ztie[1] = halfGap - restLAr/2.;
245  rodSize = restLAr - g4allowS;
246  }
247  else{
248  //-- For One-board approach:
249  double halfGap = gapSize/2.;
250  double halfGapLAr = (gapSize - kaptonWidth[1])/2. - kaptonWidth[0];
251  ztie[0] = (halfGap-halfGapLAr/2.);
252  ztie[1] = 0.0; // fix complilation warning
253  rodSize = halfGapLAr-g4allowS;
254  }
255 
256 
257  //---- And here we have some more (yikes!) hard-coded values: ------------------------
258  int nZplane = 4;
259  if (!m_frontWheel) nZplane = 2;
260  int nRods = 4;
261  if (m_tbyear==2004) nRods = 2;
262  double modulePhistart = 264.375*deg; // (270.-11.25/2.)*deg
263  double moduleDeltaPhi = 2*M_PI/moduleNumber; //11.25*deg;
264  int sectMax = 2;
265  if(!m_frontWheel) sectMax = 1;
266  int rearOffset = 24; // The rear wheel slice numbering starts at 24
267  // This complies with the old HECConstruction.
268 
269  //--- A dead-zone in the LAr gap of depth deadZone all around the module
270  // requires a radial shift of size larshift
271  double deadZone = shrinkCold * 3.*mm;
272  double larShift = deadZone / sin(moduleDeltaPhi/2.);
273 
274  //--- To create a (dead) inter-module gap of 2mm (i.e. 1mm on either side of each module)
275  // between the absorbers, use a radial shift of -1.02*cm.
276  // This does that:
277  double deadGap = shrinkCold * 1.*mm;
278  double radialShift = deadGap / sin(moduleDeltaPhi/2.);
279 
280 
281 
282 
283 
284  //-------------------------------------------------------------------//
285  //-------------------------------------------------------------------//
286  // Now start building the Module geometry //
287  // First create all the little bits so that they are //
288  // ready to be inserted into the bigger pieces when they get //
289  // are created. //
290  //-------------------------------------------------------------------//
291  //-------------------------------------------------------------------//
292 
293  std::string moduleName = "LAr::HEC::Module";
294  std::string depthName = moduleName + "::Depth";
295  std::string sliceName = depthName + "::Slice";
296  std::string electrodeName = sliceName + "::Electrode";
297  std::string copperName = electrodeName + "::Copper";
298  std::string tieRodName = sliceName + "::TieRod";
299  std::string deadTieName = sliceName + "::TieRodDead";
300  std::string absorberName = depthName + "::Absorber";
301  std::string firstAbsorberName = depthName + "::FirstAbsorber";
302  std::string absTieRodName = absorberName + "::TieRod";
303  std::string firstabsTieRodName = firstAbsorberName + "::TieRod";
304 
305  //---- Tie rods to go into Absorbers --------------------------------------
306 
307  GeoIntrusivePtr<GeoTubs>solidAbsorberTieRod = new GeoTubs(0.*cm,tieRodDiameter/2.,absThickness/2.,0.*deg,360.*deg);
308  GeoIntrusivePtr<GeoLogVol> logiAbsorberTieRod = new GeoLogVol(absTieRodName,solidAbsorberTieRod,Iron); //,0,0,0);
309  GeoIntrusivePtr<GeoPhysVol> physiAbsorberTieRod = new GeoPhysVol(logiAbsorberTieRod);
310 
311  GeoIntrusivePtr<GeoTubs> solidFirstAbsorberTieRod = new GeoTubs(0.*cm,tieRodDiameter/2.,firstAbsThickness/2.,0.*deg,360.*deg);
312  GeoIntrusivePtr<GeoLogVol> logiFirstAbsorberTieRod = new GeoLogVol(firstabsTieRodName,solidFirstAbsorberTieRod,Iron); //,0,0,0);
313  GeoIntrusivePtr<GeoPhysVol> physiFirstAbsorberTieRod = new GeoPhysVol(logiFirstAbsorberTieRod);
314 
315 
316  //---- Tie rods to go into Slices (i.e. sensitive LAr gaps) -----------------
317 
318  GeoIntrusivePtr<GeoTubs> solidTieRod = new GeoTubs(0.*cm,spacerDiameter/2.,rodSize/2.,0.*deg,360.*deg);
319  GeoIntrusivePtr<GeoLogVol> logiTieRod = new GeoLogVol(tieRodName, solidTieRod, Iron);
320  GeoIntrusivePtr<GeoPhysVol> physiTieRod = new GeoPhysVol(logiTieRod);
321 
322 
323  GeoIntrusivePtr<GeoTubs> solidDeadTie = new GeoTubs(g4allowS+spacerDiameter/2.,
324  spacerDeadZone+spacerDiameter/2.,
325  rodSize/2.,
326  0.*deg,360.*deg);
327  GeoIntrusivePtr<GeoLogVol> logiDeadTie = new GeoLogVol(deadTieName, solidDeadTie, LAr);
328  GeoIntrusivePtr<GeoPhysVol> physiDeadTie = new GeoPhysVol(logiDeadTie);
329 
330 
331  //---- Create PAD board and EST boards, then also Slices (ie. LAr gaps) and put the boards into Slices ------------
332  // This requires a loop, because the frontWheel has two sections (iSect) of different radial size.
333  // The same goes for the Absorbers - create them in this loop, too.
334  // (NB: Each wheel has only one "firstAbsorber"; Create that ahead of everything else.)
335  // And finally equip the LAr Slices as well as the Absorbers with their respective tie-rods.
336 
337 
338  std::array<GeoIntrusivePtr<GeoTubs>, 2> solidPadBoard{};
339  std::array<GeoIntrusivePtr<GeoLogVol>, 2> logiPadBoard{};
340  std::array<GeoIntrusivePtr<GeoPhysVol>, 2> physiPadBoard{};
341 
342  std::array<GeoIntrusivePtr<GeoTubs>, 2> solidCopperPad{};
343  std::array<GeoIntrusivePtr<GeoLogVol>, 2> logiCopperPad{};
344  std::array<GeoIntrusivePtr<GeoPhysVol>, 2> physiCopperPad{};
345 
346  std::array<GeoIntrusivePtr<GeoTubs>, 2> solidEstBoard{};
347  std::array<GeoIntrusivePtr<GeoLogVol>, 2> logiEstBoard{};
348  std::array<GeoIntrusivePtr<GeoPhysVol>, 2> physiEstBoard{};
349 
350  std::array<GeoIntrusivePtr<GeoTubs>, 2> solidSlice{};
351  std::array<GeoIntrusivePtr<GeoLogVol>, 2> logiSlice{};
352  std::array<GeoIntrusivePtr<GeoPhysVol>,2> physiSlice{};
353 
354  std::array<GeoIntrusivePtr<GeoTubs>,2> solidAbsorber{};
355  std::array<GeoIntrusivePtr<GeoLogVol>,2> logiAbsorber{};
356  std::array<GeoIntrusivePtr<GeoPhysVol>,2> physiAbsorber{};
357 
358  // First Absorbers in front of first and third samplings (need only one type in each wheel)
359  double rOuterF = moduleRouter-radialShift;
360  double rInnerF = moduleRinner2-radialShift;
361  if (m_frontWheel) rInnerF= moduleRinner1-radialShift;
362  GeoIntrusivePtr<GeoTubs> solidFirstAbsorber = new GeoTubs(rInnerF,rOuterF,
363  firstAbsThickness/2.,
364  modulePhistart,moduleDeltaPhi);
365  GeoIntrusivePtr<GeoLogVol> logiFirstAbsorber = new GeoLogVol(firstAbsorberName, solidFirstAbsorber, Copper);
366  GeoIntrusivePtr<GeoPhysVol> physiFirstAbsorber = new GeoPhysVol(logiFirstAbsorber);
367 
368 
369  for(int iSect=0; iSect<sectMax; iSect++)
370  {
371  //-------- First make the slice: ------------------
372  // NB: larShift produces the inter-module gap,
373  // but the actual radial size of the board or slice also has to be
374  // made smaller by the value of deadZone.
375 
376  double rOuter = moduleRouter - larShift - deadZone;
377  double rInner = moduleRinner2 - larShift + deadZone;
378  if (iSect<1 && m_frontWheel) rInner = moduleRinner1 - larShift + deadZone;
379  solidSlice[iSect] = new GeoTubs(rInner, rOuter, gapSize/2., modulePhistart, moduleDeltaPhi);
380  logiSlice[iSect] = new GeoLogVol(sliceName, solidSlice[iSect], LAr);
381  physiSlice[iSect] = new GeoPhysVol(logiSlice[iSect]);
382 
383  //-------- Now make the boards: --------
384  rOuter = moduleRouter - larShift - deadZone -g4allowS;
385  rInner = moduleRinner2 - larShift + deadZone +g4allowS;
386  if (m_frontWheel && iSect==0) rInner = moduleRinner1 - larShift + deadZone +g4allowS ;
387 
388  // First, make a central PAD Board: Copper encased in Kapton
389  // In case of the one-board approach, that's the only board (just thicker)
390  if (m_threeBoards){
391  solidPadBoard[iSect] = new GeoTubs(rInner,rOuter,
392  kaptonWidth[1]/2.,
393  modulePhistart,moduleDeltaPhi);
394  }
395  else{
396  solidPadBoard[iSect] = new GeoTubs(rInner,rOuter,
397  (kaptonWidth[1]/2.+ kaptonWidth[0]),
398  modulePhistart,moduleDeltaPhi);
399  }
400  logiPadBoard[iSect] = new GeoLogVol(electrodeName, solidPadBoard[iSect], Kapton );
401  physiPadBoard[iSect] = new GeoPhysVol(logiPadBoard[iSect]);
402 
403  // The central board contains copper pads for readout
404  solidCopperPad[iSect] = new GeoTubs(rInner,rOuter,copperPad/2.,
405  modulePhistart,moduleDeltaPhi);
406  logiCopperPad[iSect] = new GeoLogVol(copperName, solidCopperPad[iSect], Copper);
407  physiCopperPad[iSect] = new GeoPhysVol(logiCopperPad[iSect]);
408  physiPadBoard[iSect]->add(physiCopperPad[iSect]);
409 
410  // For the three-board approach, make an individual EST board and place it twice in the LAr gap
411  if(m_threeBoards){
412  solidEstBoard[iSect] = new GeoTubs(rInner,rOuter,kaptonWidth[0]/2.,
413  modulePhistart,moduleDeltaPhi);
414  logiEstBoard[iSect] = new GeoLogVol(electrodeName, solidEstBoard[iSect], Kapton );
415  physiEstBoard[iSect] = new GeoPhysVol(logiEstBoard[iSect]);
416  }
417 
418  //--- Insert the Boards into the Slice ---------
419 
420  physiSlice[iSect]->add(new GeoIdentifierTag(1));
421  physiSlice[iSect]->add(physiPadBoard[iSect]);
422 
423 
424  // For the three-board approach, make an individual EST board and place it twice in the LAr gap
425  if(m_threeBoards){
426  double halfGapLAr = (gapSize - kaptonWidth[1])/2.;
427  double ESTPos = (kaptonWidth[1]+halfGapLAr)/2.;
428  physiSlice[iSect]->add(new GeoIdentifierTag(0));
429  physiSlice[iSect]->add(new GeoTransform(Translate3D(0,0,(-ESTPos))));
430  physiSlice[iSect]->add(physiEstBoard[iSect]);
431  physiSlice[iSect]->add(new GeoIdentifierTag(2));
432  physiSlice[iSect]->add(new GeoTransform(Translate3D(0,0,ESTPos)));
433  physiSlice[iSect]->add(physiEstBoard[iSect]);
434  }
435 
436 
437 
438 
439  //--- Create the absorbers -----
440 
441  rOuter = moduleRouter - radialShift;
442  rInner = moduleRinner2 - radialShift;
443  if (iSect<1 && m_frontWheel) rInner = moduleRinner1 - radialShift;
444  solidAbsorber[iSect] = new GeoTubs(rInner,rOuter,absThickness/2., modulePhistart,moduleDeltaPhi);
445  logiAbsorber[iSect] = new GeoLogVol(absorberName, solidAbsorber[iSect], Copper);
446  physiAbsorber[iSect] = new GeoPhysVol(logiAbsorber[iSect]);
447 
448 
449 
450  //--- Insert tie rods into the Absorbers and Slices -----
451  // There are three pairs (left/right symmetric-> handled by loop over isignX)
452  // and they need to be placed in z on either side of the board(s) (loop over isign)
453  // (Note; we did the radial shift for the absorber(and slice); have to compensate for that now in Y position)
454 
455 
456  for(int indexRod=1; indexRod<nRods; indexRod++) {
457  for(double isignX=-1;isignX<2;isignX=isignX+2.){
458 
459  physiAbsorber[iSect]->add(new GeoIdentifierTag(indexRod));
460  physiAbsorber[iSect]->add(new GeoTransform(Translate3D(isignX*tieRodPositionX[indexRod],
461  -tieRodPositionY[indexRod]+radialShift, 0)));
462  physiAbsorber[iSect]->add(physiAbsorberTieRod);
463  if (iSect==0){ // fill the FirstAbsorber with tie-rods at the same time)
464  physiFirstAbsorber->add(new GeoIdentifierTag(indexRod));
465  physiFirstAbsorber->add(new GeoTransform(Translate3D(isignX*tieRodPositionX[indexRod],
466  -tieRodPositionY[indexRod]+radialShift, 0)));
467  physiFirstAbsorber->add(physiFirstAbsorberTieRod);
468  }
469 
470  // For the LAr slices, we have to insert the spacers around the boards (in Z):
471 
472  for(int itie=0; itie<2; itie++ ){ // itie=0 inserts spacers, itie=1 inserts spacer dead-zone
473  for(double isignZ=-1;isignZ<2;isignZ=isignZ+2.){
474  physiSlice[iSect]->add(new GeoIdentifierTag(indexRod));
475  physiSlice[iSect]->add(new GeoTransform
476  (Translate3D(isignX*tieRodPositionX[indexRod],
477  -tieRodPositionY[indexRod]+larShift,
478  isignZ*ztie[0])));
479  if (itie==0) { physiSlice[iSect]->add(physiTieRod); }
480  else { physiSlice[iSect]->add(physiDeadTie);}
481 
482  if (m_threeBoards) {
483  physiSlice[iSect]->add(new GeoIdentifierTag(indexRod));
484  physiSlice[iSect]->add(new GeoTransform
485  (Translate3D(isignX*tieRodPositionX[indexRod],
486  -tieRodPositionY[indexRod]+larShift,
487  isignZ*ztie[1])));
488  if (itie==0) { physiSlice[iSect]->add(physiTieRod); }
489  else { physiSlice[iSect]->add(physiDeadTie);}
490  }
491  }
492  }
493 
494 
495 
496  }
497  }
498 
499  //--- This is for the lonely un-paired tie-rod at the narrow end of the module (Absorber):
500  physiAbsorber[iSect]->add(new GeoIdentifierTag(0));
501  physiAbsorber[iSect]->add(new GeoTransform(Translate3D(tieRodPositionX[0],
502  -tieRodPositionY[0]+radialShift,0)));
503  physiAbsorber[iSect]->add(physiAbsorberTieRod);
504  if (iSect==0){
505  physiFirstAbsorber->add(new GeoIdentifierTag(0));
506  physiFirstAbsorber->add(new GeoTransform(Translate3D(tieRodPositionX[0],
507  -tieRodPositionY[0]+radialShift,0)));
508  physiFirstAbsorber->add(physiFirstAbsorberTieRod);
509  }
510 
511  //--- And the lonely Slice tie-rods: -------------
512  for(int itie=0; itie<2; itie++ ){ // tie=0 inserts spacers, itie=1 inserts spacer dead-zone
513  for(double isignZ=-1;isignZ<2;isignZ=isignZ+2){
514  physiSlice[iSect]->add(new GeoIdentifierTag(0));
515  physiSlice[iSect]->add(new GeoTransform(Translate3D(tieRodPositionX[0],
516  -tieRodPositionY[0]+larShift,
517  isignZ*ztie[0])));
518  if (itie==0) { physiSlice[iSect]->add(physiTieRod); }
519  else { physiSlice[iSect]->add(physiDeadTie);}
520 
521  if (m_threeBoards) {
522  physiSlice[iSect]->add(new GeoIdentifierTag(0));
523  physiSlice[iSect]->add(new GeoTransform(Translate3D(tieRodPositionX[0],
524  -tieRodPositionY[0]+larShift,
525  isignZ*ztie[1])));
526  if (itie==0) { physiSlice[iSect]->add(physiTieRod); }
527  else { physiSlice[iSect]->add(physiDeadTie);}
528  }
529  }
530  }
531 
532  }//for iSect
533 
534 
535 
536  // Now that Slices and Absorbers are filled with their components,
537  // create the Depths and place the slices and absorbers into them
538 
539 
540  //----------------------------------------------------------------
541  // Depths
542  //----------------------------------------------------------------
543  // There are 3 depths in the front wheel, and 4 in the rear wheel.
544  // Create them and equip them with fully assembled slices and absorbers.
545 
546  std::array<GeoIntrusivePtr<GeoTubs>, 4> solidDepth{};
547  std::array<GeoIntrusivePtr<GeoLogVol>, 4> logiDepth{};
548  std::array<GeoIntrusivePtr<GeoPhysVol>, 4> physiDepth{};
549 
550  for(int iDepth=0; iDepth<depthNumber; iDepth++)
551  {
552  double rOuter = moduleRouter;
553  double rInner = moduleRinner2;
554  if (iDepth<1 && m_frontWheel) rInner= moduleRinner1;
555  solidDepth[iDepth] = new GeoTubs(rInner-drModOverlap,rOuter,
556  depthSize[iDepth]/2.,modulePhistart,moduleDeltaPhi);
557  logiDepth[iDepth] = new GeoLogVol(depthName, solidDepth[iDepth], LAr);
558  physiDepth[iDepth] = new GeoPhysVol(logiDepth[iDepth]);
559 
560 
561  // Position the sensitive LAr Slice-gaps and absorbers into the just created Depth:
562  // Absorber size and position
563  double firstAbs = 0.;
564  if (iDepth==0) firstAbs = firstAbsThickness;
565  double slicePositionZ = firstAbs + gapSize/2.0 -depthSize[iDepth]/2.0;
566  double absorberPositionZ = firstAbs + gapSize + absThickness/2.0 - depthSize[iDepth]/2.0;
567 
568  // sliceCopyNo is the copy number of the slice and runs consecutively from
569  // front to back throughout the module.
570  // The first gap in the rear Wheel has number 24 (=rearOffset).
571  // sliceNo refers to how many slice types there are (0,1 in Front ; 0 in Rear)
572  // gapNumber is the number of gaps in a given Depth
573  int sliceNo = 0;
574  int sliceCopyNo = 0;
575  if(!m_frontWheel) sliceCopyNo = rearOffset ;
576 
577  if (iDepth>0)
578  {
579  sliceCopyNo += gaptally[iDepth];
580  if(m_frontWheel) sliceNo=1;
581  }
582 
583  // Serially install all slices and _regular_ absorbers into the depths
584  GeoGenfun::Variable Index;
585  GeoXF::TRANSFUNCTION TS =
586  TranslateY3D(-larShift)*GeoXF::Pow(TranslateZ3D(1.0),slicePositionZ + (absThickness+gapSize)*Index);
587  GeoXF::TRANSFUNCTION TA =
588  TranslateY3D(-radialShift)*GeoXF::Pow(TranslateZ3D(1.0),absorberPositionZ + (absThickness+gapSize)*Index);
589 
590  GeoSerialIdentifier *sI = new GeoSerialIdentifier(sliceCopyNo);
591  GeoSerialTransformer *sTS = new GeoSerialTransformer(physiSlice[sliceNo], &TS, gapNumber[iDepth]);
592  GeoSerialTransformer *sTAF = new GeoSerialTransformer(physiAbsorber[sliceNo], &TA, gapNumber[iDepth]);
593  physiDepth[iDepth]->add(sI);
594  physiDepth[iDepth]->add(sTS);
595  physiDepth[iDepth]->add(sI);
596  physiDepth[iDepth]->add(sTAF);
597 
598  } //for iDepth
599 
600 
601  // The first absorber is special (1/2 thickness) install that now
602  double firstAbsorberPositionZ = firstAbsThickness/2.- depthSize[0]/2.0;
603  if(m_frontWheel) physiDepth[0]->add(new GeoIdentifierTag(0));
604  else physiDepth[0]->add(new GeoIdentifierTag(1));
605  physiDepth[0]->add(new GeoTransform(Translate3D(0,-radialShift,firstAbsorberPositionZ)));
606  physiDepth[0]->add(physiFirstAbsorber);
607 
608 
609  //----------------------------------------------------------------
610  // HEC Module
611  //----------------------------------------------------------------
612 
613 
614  GeoPcon* solidHECModule = new GeoPcon(modulePhistart, moduleDeltaPhi);
615  for (int i=0; i< nZplane; i++)
616  {
617  double innerRadius = moduleRinner2;
618  if (i<2 && m_frontWheel) innerRadius=moduleRinner1;
619  solidHECModule->addPlane(zCoordinate[i],innerRadius-drModOverlap,moduleRouter);
620  }
621  GeoIntrusivePtr<GeoLogVol> logicHECModule = new GeoLogVol(moduleName, solidHECModule , LAr);
622  GeoIntrusivePtr<GeoFullPhysVol> physiHECModule = new GeoFullPhysVol(logicHECModule);
623 
624 
625  //--- Place the fully instrumented depths into the Module: ----
626 
627  double depthPositionZ = 0.;
628 
629  for(int iDepth=0; iDepth<depthNumber; iDepth++)
630  {
631  depthPositionZ +=depthSize[iDepth]/2.;
632  if(!m_frontWheel) physiHECModule->add(new GeoIdentifierTag(iDepth+depthOffset));
633  else physiHECModule->add(new GeoIdentifierTag(iDepth));
634  physiHECModule->add(new GeoTransform(Translate3D(0,0,depthPositionZ)));
635  physiHECModule->add(physiDepth[iDepth]);
636  depthPositionZ +=depthSize[iDepth]/2.;
637  } //for iDepth
638 
639 
640 
641  // Return the physical volume that contains everything we've placed.
642  return physiHECModule;
643 }
JTC::TS
TS
Definition: IJetTileCorrectionTool.h:27
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
LAr
Definition: LArVolumeBuilder.h:36
M_PI
#define M_PI
Definition: ActiveFraction.h:11
deg
#define deg
Definition: SbPolyhedron.cxx:17
LArGeo::HECModuleConstruction::m_frontWheel
bool m_frontWheel
Definition: HECModuleConstruction.h:36
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
Execution.tb
tb
Definition: Execution.py:15
Index
IndexedConstituentUserInfo::Index Index
Definition: IndexedConstituentUserInfo.cxx:12
EventInfoWrite.AtlasVersion
AtlasVersion
Definition: EventInfoWrite.py:17
IRDBAccessSvc.h
Definition of the abstract IRDBAccessSvc interface.
lumiFormat.i
int i
Definition: lumiFormat.py:85
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
IRDBRecordset_ptr
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition: IRDBAccessSvc.h:25
LArGeo::HECModuleConstruction::HECModuleConstruction
HECModuleConstruction(bool threeBoards=false, bool frontWheel=true, bool tb=false, int tbyear=2002)
Definition: HECModuleConstruction.cxx:52
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
LArGeo::HECModuleConstruction::m_tb
bool m_tb
Definition: HECModuleConstruction.h:37
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:227
StoredMaterialManager.h
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
HECModuleConstruction.h
Declaration of HECModuleConstruction class.
IRDBRecord.h
Definition of the abstract IRDBRecord interface.
LArGeo::HECModuleConstruction::GetEnvelope
GeoIntrusivePtr< GeoFullPhysVol > GetEnvelope()
Definition: HECModuleConstruction.cxx:62
LArGeo::HECModuleConstruction::m_tbyear
int m_tbyear
Definition: HECModuleConstruction.h:38
DEBUG
#define DEBUG
Definition: page_access.h:11
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
LArGeo::HECModuleConstruction::m_threeBoards
bool m_threeBoards
Definition: HECModuleConstruction.h:35
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
IRDBRecordset.h
Definition of the abstract IRDBRecordset interface.
IGeoModelSvc.h
StoreGateSvc.h