ATLAS Offline Software
EMECConstruction.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 // EMECConstruction
6 
7 // Revision history:
8 
9 // LArEMECConstruction:
10 // 09-May-2001 WGS: Copied from Andrei Soukharev's EMECDetectorConstruction.
11 // 09-May-2001 WGS: Put in the LAr parent volumes for the endcaps.
12 // 09-Jan-2002 WGS: The LAr parent volume now comes from the calling routine.
13 // Any shifts in z are handled in the parent volume.
14 // 02-Dec-2002 J.Toth: wheels' shape and position are corrected;
15 // : support rings in front of sens.volume are introduced,
16 // like in endegeo.age of dice
17 // 13-Dec-2002 J.Toth: electrode shape is corrected
18 // 08-Jan-2003 J.Toth: the 11mm section between GTenbars and FrontFace
19 // of WheelSolid is added
20 // new 'average' materials G10FeInner, G10FeOuter are added
21 // for barrettes connecting long.bars and absorbers
22 // 24-Jan-2003 J.Toth: Code for Emec nonsensitive pieces is revised.
23 // details of emec support structure are added
24 // parameters for radial position of the rings
25 // are still in warm, while those for z positions are
26 // in cold.
27 // missing pieces:guides,feets
28 // Alu cone at Inner surface of Inner wheel is present
29 // new material PermaliE730 for FrontMiddleRing is added
30 // (composition to be checked)
31 // density of glue changed for that of prepreg glue of
32 // absorbers
33 
34 // 21-Sep-2003 Revised to create EMEC mother volume, and to
35 // place all EMEC components (wheels,mech structure) within this volume.
36 //
37 // WGS: new class EMECConstruction for GeoModel application created
38 // EMECConstruction:
39 // 06-Oct-2003 J.T. code revised to work in the GeoModel framework
40 // 06-Oct-2003 J.T. EMEC Mother volume z limits corrected for cold values.
41 // 06-Oct-2003 J.T. crossing of volume of top indexing ring and stretchers
42 // corrected.
43 // 21-Jul-2005 C.S. Revised to take into account changes in G4 simulation
44 // 18-Sep-2006 V.N. Put back options for TB module
45 // 18-Sep-2006 V.N Get materials from LarMaterialManager
46 // May-June 2009 AMS Get most part of geometry constants from LArWheelCalculator
47 // General code cleanup
48 // Feb 2022 JFB Since the appearance of the GeoUnidentifiedShape, the LArCustomShape
49 // class is deprecated. We therefore decouple this package from
50 // GeoSpecialShapes, computing a few constants here which were previously
51 // taken from the calculator.
52 #include <string>
53 #include <cmath>
54 #include <iostream>
55 
56 #include "GeoModelKernel/GeoElement.h"
57 #include "GeoModelKernel/GeoMaterial.h"
58 #include "GeoModelKernel/GeoFullPhysVol.h"
59 #include "GeoModelKernel/GeoPhysVol.h"
60 #include "GeoModelKernel/GeoVPhysVol.h"
61 #include "GeoModelKernel/GeoLogVol.h"
62 #include "GeoModelKernel/GeoPcon.h"
63 #include "GeoModelKernel/GeoNameTag.h"
64 #include "GeoModelKernel/GeoTransform.h"
65 #include "GeoModelKernel/GeoIdentifierTag.h"
66 #include "GeoModelKernel/GeoDefinitions.h"
71 #include "StoreGate/StoreGateSvc.h"
72 #include "GaudiKernel/IService.h"
73 #include "GaudiKernel/ISvcLocator.h"
74 #include "GaudiKernel/PhysicalConstants.h"
75 
79 
82 #include "GeoModelKernel/GeoUnidentifiedShape.h"
83 
84 
85 LArGeo::EMECConstruction::EMECConstruction(bool is_tb, bool has_inner, bool has_outer)
86  : AthMessaging("EMECConstruction"),
87  m_fullGeo(true), m_isTB(is_tb), m_hasInnerWheel(has_inner), m_hasOuterWheel(has_outer),
88  m_innerWheelVariant("Wheel"), m_outerWheelVariant("Wheel") // "Wheel" (Meaning polycone) or "Cone" or "Slices"
89 {
90 /*
91  ISvcLocator* svcLocator = Gaudi::svcLocator();
92  IMessageSvc* msgSvc;
93  StatusCode status = svcLocator->service("MessageSvc", msgSvc);
94  if(!status.isFailure()){
95  m_msg = new MsgStream(msgSvc, "EMECConstruction");
96  } else {
97  throw std::runtime_error("EMECConstruction: cannot initialze message service");
98  }
99  (*m_msg) << MSG::DEBUG << "Parameters:"
100  << "m_fullGeo: " << m_fullGeo << std::endl
101  << "m_isTB: " << m_isTB << std::endl
102  << "m_hasInnerWheel: " << m_hasInnerWheel << std::endl
103  << "m_hasOuterWheel: " << m_hasOuterWheel
104  << endmsg;
105 */
106 }
107 
109 = default;
110 
111 GeoIntrusivePtr<GeoFullPhysVol> LArGeo::EMECConstruction::GetEnvelope(bool bPos)
112 {
113  ISvcLocator *svcLocator = Gaudi::svcLocator();
115  if(svcLocator->service("DetectorStore", detStore, false)==StatusCode::FAILURE) {
116  throw std::runtime_error("Error in EndcapCryostatConstruction, cannot access DetectorStore");
117  }
118 
119  // Get GeoModelSvc and RDBAccessSvc
120 
121  IRDBAccessSvc* pAccessSvc(nullptr);
122  IGeoModelSvc* geoModelSvc(nullptr);
123  StatusCode sc = svcLocator->service("RDBAccessSvc",pAccessSvc);
124  if(sc != StatusCode::SUCCESS){
125  throw std::runtime_error("EMECConstruction: cannot locate RDBAccessSvc!");
126  }
127 
128  sc = svcLocator->service ("GeoModelSvc",geoModelSvc);
129  if(sc != StatusCode::SUCCESS){
130  throw std::runtime_error("EMECConstruction: cannot locate GeoModelSvc!");
131  }
132 
133  DecodeVersionKey larVersionKey(geoModelSvc, "LAr");
134 
135  // Flag for building detailed absorber. Default=false
136  int multilayered_absorbers = 0;
137  IRDBRecordset_ptr larSwitches = pAccessSvc->getRecordsetPtr("LArSwitches", larVersionKey.tag(), larVersionKey.node());
138  if(larSwitches->size()!=0){
139  if(!(*larSwitches)[0]->isFieldNull("DETAILED_ABSORBER_EC")){
140  multilayered_absorbers = (*larSwitches)[0]->getInt("DETAILED_ABSORBER_EC");
141  } else if(!(*larSwitches)[0]->isFieldNull("DETAILED_ABSORBER")){
142  multilayered_absorbers = (*larSwitches)[0]->getInt("DETAILED_ABSORBER");
143  }
144  }
145 
146  if(multilayered_absorbers > 0){
147  ATH_MSG_INFO( "multi-layered version of absorbers activated, "
148  << "parameter value is " << multilayered_absorbers );
149  }
150 
151  StoredMaterialManager* materialManager = nullptr;
152  if(StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) return nullptr;
153 
155  // Get materials from the manager
157 
158  const GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon");
159  if(!LAr) throw std::runtime_error("Error in EMECConstruction, std::LiquidArgon is not found.");
160 
161  const GeoMaterial* innerAbsorberMaterial = nullptr;
162  std::string innerAbsorberMaterial_name = "LAr::EMEC_Thickabs";
163  if(multilayered_absorbers > 0){
164  if(multilayered_absorbers != 2){
165 // to be replaced with steel - finished by Adam Agocs
166  innerAbsorberMaterial_name = "std::Iron";
167  } else {
168  innerAbsorberMaterial_name = "LAr::EMEC_shell";
169  }
170  }
171  innerAbsorberMaterial = materialManager->getMaterial(innerAbsorberMaterial_name);
172  if(!innerAbsorberMaterial){
173  throw std::runtime_error(
174  (innerAbsorberMaterial_name +
175  " is not found for inner absorber in EMECConstruction.").c_str()
176  );
177  }
178 
179  const GeoMaterial* outerAbsorberMaterial = nullptr;
180  std::string outerAbsorberMaterial_name = "LAr::EMEC_Thinabs";
181  if(multilayered_absorbers > 0){
182  if(multilayered_absorbers != 2){
183 // to be replaced with steel - finished by Adam Agocs
184  outerAbsorberMaterial_name = "std::Iron";
185  } else {
186  outerAbsorberMaterial_name = "LAr::EMEC_shell";
187  }
188  }
189  outerAbsorberMaterial = materialManager->getMaterial(outerAbsorberMaterial_name);
190  if(!outerAbsorberMaterial){
191  throw std::runtime_error(
192  (outerAbsorberMaterial_name +
193  " is not found for outer absorber in EMECConstruction.").c_str()
194  );
195  }
196 
197  const GeoMaterial *Glue = nullptr;
198  const GeoMaterial *Lead = nullptr;
199  if(multilayered_absorbers > 0){
200 // to be replaced with glue and lead - finished by Adam Agocs
201  Glue = materialManager->getMaterial("LAr::Glue");
202  if(!Glue) throw std::runtime_error("Error in EMECConstruction, LAr::Glue is not found.");
203  Lead = materialManager->getMaterial("std::Lead");
204  if(!Lead) throw std::runtime_error("Error in EMECConstruction, LAr::Lead is not found.");
205  }
206 
207  const GeoMaterial* electrodeMaterial = materialManager->getMaterial("LAr::KaptonC");
208  if(!electrodeMaterial) throw std::runtime_error("Error in EMECConstruction, LAr::KaptonC is not found.");
209 
211  // Define geometry
213 
214  // Set up strings for volume names.
215  std::string baseName = "LAr::EMEC";
216 
217  double phiPosition, phiSize;
218 
219  if(m_isTB) {
221  phiSize = M_PI*Gaudi::Units::rad / 8. + 0.065*Gaudi::Units::rad; // half-angle of inner part of module
222  }
223  else {
224  phiPosition = M_PI*Gaudi::Units::rad;
225  phiSize = M_PI*Gaudi::Units::rad; // half-angle of a full wheel
226  }
227 
228  // Define the mother volume for the emec. Everything
229  // else in the emec (wheels,structure, etc.) should be
230  // placed inside here.
231 
232  //double emecMotherZplan[] = {3641.*Gaudi::Units::mm,4273.*Gaudi::Units::mm}; //warm
233 
234  // 21-Jul-2005, C.S. : above line valid in warm, below is in cold.
235  // The latter one should apply, othervise SupportMotherVolumes cross
236  // the EMEC Mother and/or their position rel to the sensitive LAr
237  // become wrong
238 
239 
240  IRDBRecordset_ptr cryoPcons =
241  pAccessSvc->getRecordsetPtr("CryoPcons", larVersionKey.tag(), larVersionKey.node());
242  if(cryoPcons->size() == 0){
243  cryoPcons = pAccessSvc->getRecordsetPtr("CryoPcons", "CryoPcons-EMEC-00");
244  }
245 
246  //double emecMotherZplan[] = {3639.5*Gaudi::Units::mm,3639.5*Gaudi::Units::mm+630.*Gaudi::Units::mm}; //cold (J.T)
247  // // Zplane[0]=endg_z0*Gaudi::Units::cm-50*Gaudi::Units::mm
248  // // Zplane[1]=Zplane[0]+endg_dzende*Gaudi::Units::cm-2.Gaudi::Units::mm
249  //double emecMotherRin[] = { 279.*Gaudi::Units::mm, 324*Gaudi::Units::mm}; //{ 302.*Gaudi::Units::mm, 302.*Gaudi::Units::mm };
250  //double emecMotherRout[] = {(2077.-7)*Gaudi::Units::mm,(2077.-7)*Gaudi::Units::mm}; // -7 for cold
251  //int lastPlaneEmec = (sizeof(emecMotherZplan) / sizeof(double));
252 
253  std::string emecMotherName = baseName + "::Mother"; //+ extension;
254 
255  GeoTransform *refSystemTransform = nullptr;
256  double zTrans = 0.*Gaudi::Units::mm;
257  double zMSTrans = 0.*Gaudi::Units::mm;
258 
259  GeoPcon* emecMotherShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize); //start phi,total phi
260  for(const IRDBRecord_ptr& currentRecord : *cryoPcons) {
261  if(currentRecord->getString("PCON") == "EMEC::Mother"){
262  if(!refSystemTransform){
263  if(m_isTB){
264  zTrans = -3700.5*Gaudi::Units::mm;
265  zMSTrans = zTrans;
266  } else {
267  zTrans = currentRecord->getDouble("ZPLANE") - 3639.5*Gaudi::Units::mm;
268  zMSTrans = 0.*Gaudi::Units::mm;
269  }
270  refSystemTransform = new GeoTransform(GeoTrf::TranslateZ3D(zTrans));
271  }
272  emecMotherShape->addPlane(currentRecord->getDouble("ZPLANE") + zMSTrans,
273  currentRecord->getDouble("RMIN"),
274  currentRecord->getDouble("RMAX"));
275  }
276  }
277 
278  IRDBRecordset_ptr DB_EmecGeometry =
279  pAccessSvc->getRecordsetPtr("EmecGeometry", larVersionKey.tag(), larVersionKey.node());
280  if(DB_EmecGeometry->size() == 0){
281  DB_EmecGeometry = pAccessSvc->getRecordsetPtr("EmecGeometry", "EmecGeometry-00");
282  }
283  double zWheelRefPoint = (*DB_EmecGeometry)[0]->getDouble("Z0")*Gaudi::Units::cm;
284  double dMechFocaltoWRP=(*DB_EmecGeometry)[0]->getDouble("Z1")*Gaudi::Units::cm;
285  double LArTotalThickness = (*DB_EmecGeometry)[0]->getDouble("ETOT") *Gaudi::Units::cm;
286  double halfGapBetweenWheels = (*DB_EmecGeometry)[0]->getDouble("DCRACK")*Gaudi::Units::cm;
287  double rOuterCutoff = (*DB_EmecGeometry)[0]->getDouble("RLIMIT")*Gaudi::Units::cm;
288 
289  IRDBRecordset_ptr DB_EMECmn =
290  pAccessSvc->getRecordsetPtr("EmecMagicNumbers", larVersionKey.tag(), larVersionKey.node());
291  if(DB_EMECmn->size() == 0)
292  DB_EMECmn = pAccessSvc->getRecordsetPtr("EmecMagicNumbers","EMECMagicNumbers-00");
293  double reftoactive = (*DB_EMECmn)[0]->getDouble("REFTOACTIVE") *Gaudi::Units::mm;
294  double activelength = (*DB_EMECmn)[0]->getDouble("ACTIVELENGTH") *Gaudi::Units::mm;
295  double straightstartsection = (*DB_EMECmn)[0]->getDouble("STRAIGHTSTARTSECTION")*Gaudi::Units::mm;
296  double wheelThickness=activelength+2*straightstartsection;
297  double dWRPtoFrontFace = reftoactive;
298  double zWheelFrontFace = dMechFocaltoWRP + dWRPtoFrontFace;
299  double zWheelBackFace = zWheelFrontFace+wheelThickness;
300  IRDBRecordset_ptr DB_EMECwp=
301  pAccessSvc->getRecordsetPtr("EmecWheelParameters", larVersionKey.tag(),larVersionKey.node());
302  if (DB_EMECwp->size()==0)
303  DB_EMECwp=pAccessSvc->getRecordsetPtr("EmecWheelParameters", "EmecWheelParameters","EmecWheelParameters-00");
304  int numberOfHalfWavesInner=2*(*DB_EMECwp)[0]->getInt("NACC")+2;
305  int numberOfHalfWavesOuter=2*(*DB_EMECwp)[1]->getInt("NACC")+3;// one extra for outer wheel
306  double eta_hi = (*DB_EMECwp)[0]->getDouble("ETAINT");
307  double eta_mid = (*DB_EMECwp)[0]->getDouble("ETAEXT");
308  double eta_low = (*DB_EMECwp)[1]->getDouble("ETAEXT");
309 
310  // NEW BLURB
311  double zMid[2];
312  double rMin[2][3];
313  double rMax[2][3];
314  {
315  double tanThetaMid = 2. * std::exp(-eta_mid) / (1. - std::exp(-2.*eta_mid));
316  double tanThetaOuter = 2. * std::exp(-eta_low) / (1. - std::exp(-2.*eta_low));
317  double tanThetaInner = 2. * std::exp(-eta_hi ) / (1. - std::exp(-2.*eta_hi ));
318  double inv_tanThetaOuter = (1. - std::exp(-2.*eta_low)) / (2. * std::exp(-eta_low));
319 
320  // Inner Wheel Outer Radius
321  rMax[0][0] = zWheelFrontFace * tanThetaMid - halfGapBetweenWheels;
322  rMax[0][1] = zWheelBackFace * tanThetaMid - halfGapBetweenWheels;
323  // Outer Wheel Outer Radius
324  rMax[1][0] = zWheelFrontFace * tanThetaOuter;
325  rMax[1][1] = rOuterCutoff;
326  rMax[1][2] = rOuterCutoff;
327 
328  // Note that there is a 3mm gap between the outer surface of the
329  // inner wheel and the inner surface of the outer wheel.
330 
331  // Inner Wheel Inner Radius
332  rMin[0][0] = zWheelFrontFace * tanThetaInner;
333  rMin[0][1] = zWheelBackFace * tanThetaInner;
334  zMid[0] = 0;
335 
336  // Outer Wheel Inner Radius
337  rMin[1][0] = zWheelFrontFace * tanThetaMid + halfGapBetweenWheels;
338  rMin[1][1] = rOuterCutoff * inv_tanThetaOuter * tanThetaMid + halfGapBetweenWheels;
339  rMin[1][2] = zWheelBackFace * tanThetaMid + halfGapBetweenWheels;
340  zMid[1] = rOuterCutoff * inv_tanThetaOuter - zWheelFrontFace;
341  }
342 
343  const GeoLogVol* emecMotherLogical =
344  new GeoLogVol(emecMotherName, emecMotherShape, LAr);
345  GeoIntrusivePtr<GeoFullPhysVol> emecMotherPhysical = new GeoFullPhysVol(emecMotherLogical);
346 
347  if(!m_isTB) baseName += bPos? "::Pos": "::Neg";
348 
349  if(m_hasInnerWheel){
350  std::string innerName = baseName + "::Inner";
351  std::string LArName = innerName + (m_isTB? "Module": "Wheel");
352 
353  std::vector<std::string> absorbers;
354  std::vector<std::string> electrodes;
355 
356  if(m_innerWheelVariant == "Cone"){
357  innerName += "Cone";
358  absorbers.push_back(innerName + "::Absorber");
359  electrodes.push_back(innerName + "::Electrode");
360  } else if(m_innerWheelVariant == "Slices"){
361  innerName += "Slice";
362  uint8_t slice = 0; // To silence Wformat-truncation use datatype with 3-digit range
363  do {
364  char buf[4];
365  snprintf(buf, 4, "%02d", slice);
366 
367  std::string a = innerName + buf + "::Absorber";
368  std::string e = innerName + buf + "::Electrode";
369  absorbers.push_back(a);
370  electrodes.push_back(e);
371  slice ++;
372  } while(
373  numberOfHalfWavesInner > slice
374  && slice < 100 // slice number limited by two digits
375  );
376  if(slice >= 100){
377  ATH_MSG_ERROR( "too many LArWheel slices, something"
378  << " goes wrong in EMECConstruction" );
379  }
380  innerName += "s";
381  } else { // it is a Polycone
382  innerName += (m_isTB? "Module": "Wheel");
383  absorbers.push_back(innerName + "::Absorber");
384  electrodes.push_back(innerName + "::Electrode");
385  }
386  ATH_MSG_INFO( "activating " << innerName );
387  ATH_MSG_DEBUG( absorbers.size() << " absorber, "
388  << electrodes.size() << " electrode shapes created" );
389 
390 
391  double zBack = wheelThickness;
392  GeoPcon* innerShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize);
393  innerShape->addPlane(0.*Gaudi::Units::mm, rMin[0][0], rMax[0][0]);
394  innerShape->addPlane(zBack , rMin[0][1], rMax[0][1]);
395 
396  GeoLogVol* innerLogical = new GeoLogVol (LArName,innerShape, LAr);
397  GeoIntrusivePtr<GeoFullPhysVol> fullPV = new GeoFullPhysVol(innerLogical);
398 
399  emecMotherPhysical->add(new GeoIdentifierTag(1));
400  emecMotherPhysical->add(refSystemTransform);
401  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
402  emecMotherPhysical->add(fullPV);
403 
404  StoredPhysVol *sPhysVol = new StoredPhysVol(fullPV);
405  StatusCode status=detStore->record(sPhysVol, bPos? "EMEC_INNER_WHEEL_POS": "EMEC_INNER_WHEEL_NEG");
406  if(!status.isSuccess()){
407  throw std::runtime_error(bPos? "Cannot store EMEC_INNER_WHEEL_POS": "Cannot store EMEC_INNER_WHEEL_NEG");
408  }
409 
410  place_custom_solids(
411  fullPV, absorbers, electrodes, multilayered_absorbers,
412  innerAbsorberMaterial, electrodeMaterial, Glue, Lead
413  );
414  } // if(m_hasInnerWheel)
415 
416  if(m_hasOuterWheel){
417  std::string outerName = baseName + "::Outer";
418  const std::string LArName = outerName + (m_isTB? "Module": "Wheel");
419 
420  std::vector<std::string> absorbers;
421  std::vector<std::string> electrodes;
422 
423  if(m_outerWheelVariant == "Cone"){
424  absorbers.push_back(outerName + "FrontCone::Absorber");
425  absorbers.push_back(outerName + "BackCone::Absorber");
426  electrodes.push_back(outerName + "FrontCone::Electrode");
427  electrodes.push_back(outerName + "BackCone::Electrode");
428  outerName += "Cones";
429  } else if(m_outerWheelVariant == "Slices"){
430  outerName += "Slice";
431  uint8_t slice = 0; // To silence Wformat-truncation use datatype with 3-digit range
432  do {
433  char buf[4];
434  snprintf(buf, 4, "%02d", slice);
435  std::string a = outerName + buf + "::Absorber";
436  std::string e = outerName + buf + "::Electrode";
437  absorbers.push_back(a);
438  electrodes.push_back(e);
439  slice ++;
440  } while( // outer wheel has an extra slice
441  numberOfHalfWavesOuter > slice
442  && slice < 100 // slice number limited by two digits
443  );
444  if(slice >= 100){
445  ATH_MSG_ERROR( "too many LArWheel slices, something"
446  << " goes wrong in EMECConstruction" );
447  }
448  outerName += "s";
449  } else { // it is Polycone
450  outerName += (m_isTB? "Module": "Wheel");
451  absorbers.push_back(outerName + "::Absorber");
452  electrodes.push_back(outerName + "::Electrode");
453  }
454  ATH_MSG_INFO( "activating " << outerName );
455  ATH_MSG_DEBUG( absorbers.size() << " absorber, "
456  << electrodes.size() << " electrode shapes created" );
457 
458  double zBack = wheelThickness;
459  GeoPcon *outerShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize);
460  outerShape->addPlane(0.*Gaudi::Units::mm, rMin[1][0], rMax[1][0]);
461  outerShape->addPlane(zMid[1] , rMin[1][1], rMax[1][1]);
462  outerShape->addPlane(zBack , rMin[1][2], rMax[1][2]);
463 
464  GeoLogVol *outerLogical = new GeoLogVol(LArName, outerShape, LAr);
465  GeoIntrusivePtr<GeoFullPhysVol>fullPV = new GeoFullPhysVol(outerLogical);
466 
467  emecMotherPhysical->add(new GeoIdentifierTag(1));
468  emecMotherPhysical->add(refSystemTransform);
469  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
470  emecMotherPhysical->add(fullPV);
471 
472  StoredPhysVol *sPhysVol = new StoredPhysVol(fullPV);
473  StatusCode status = detStore->record(sPhysVol, bPos? "EMEC_OUTER_WHEEL_POS": "EMEC_OUTER_WHEEL_NEG");
474  if(!status.isSuccess()){
475  throw std::runtime_error(bPos? "Cannot store EMEC_OUTER_WHEEL_POS": "Cannot store EMEC_OUTER_WHEEL_NEG");
476  }
477 
478  place_custom_solids(
479  fullPV, absorbers, electrodes, multilayered_absorbers,
480  outerAbsorberMaterial, electrodeMaterial, Glue, Lead
481  );
482 
483  } // if(m_hasOuterWheel)
484 
485 // ***********************************
486 //Description of nonsensitive pieces:*
487 // ***********************************
488 
489  if(m_fullGeo) {
490  double z0;
491 
492  // Volumes for FRONT and BACK support structures
494  FrontSupp = EMECSupportConstruction::Front,
496  if(m_hasInnerWheel && !m_hasOuterWheel){
499  } else if(m_hasOuterWheel && !m_hasInnerWheel){
502  }
503 
504  IRDBRecordset_ptr DMpcons =
505  pAccessSvc->getRecordsetPtr("EmecDMPCons", larVersionKey.tag(), larVersionKey.node());
506  if(DMpcons->size() == 0){
507  DMpcons = pAccessSvc->getRecordsetPtr("EmecDMPCons", "EmecDMPCons-00");
508  }
509 
510  double front_shift = 0.*Gaudi::Units::mm;
511  double back_shift = 0.*Gaudi::Units::mm;
512  try {
513  for(const IRDBRecord_ptr& dmPcon : *DMpcons) {
514  const std::string& object = dmPcon->getString("PCONNAME");
515  if(object == "FrontSupportMother"){
516  int zplane = dmPcon->getInt("NZPLANE");
517  if(zplane == 0) front_shift += dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
518  else if(zplane == 1) front_shift -= dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
519  else continue;
520  } else if(object == "BackSupportMother"){
521  int zplane = dmPcon->getInt("NZPLANE");
522  if(zplane == 0) back_shift -= 0.;//dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
523  else if(zplane == 1) back_shift += dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
524  else continue;
525  }
526  }
527  front_shift += reftoactive;
528  back_shift += LArTotalThickness - reftoactive;
529  }
530  catch (...){
531  front_shift = -50.*Gaudi::Units::mm; // start of EMEC envelop in the cryo.(length of env=630.)
532  back_shift = 580.*Gaudi::Units::mm;
533  std::cout << "EMECConstruction: WARNING: cannot get front|back_shift from DB"
534  << std::endl;
535  }
536 //std::cout << "EMECConstruction : " << front_shift << " " << back_shift << std::endl;
537  z0 = zWheelRefPoint + front_shift;
538  EMECSupportConstruction *fsc = nullptr;
539  if(m_isTB) fsc = new EMECSupportConstruction(FrontSupp, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
540  else fsc = new EMECSupportConstruction(FrontSupp, bPos);
541  GeoIntrusivePtr<GeoPhysVol> physicalFSM = fsc->GetEnvelope();
542  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
543  emecMotherPhysical->add(refSystemTransform);
544  emecMotherPhysical->add(physicalFSM);
545  delete fsc;
546 
547  z0 = zWheelRefPoint + back_shift; // end of EMEC envelop in the cryo.
548  EMECSupportConstruction *bsc = nullptr;
549  if(m_isTB) bsc = new EMECSupportConstruction(BackSupp, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
550  else bsc = new EMECSupportConstruction(BackSupp, bPos);
551  GeoIntrusivePtr<GeoPhysVol>physicalBSM = bsc->GetEnvelope();
552  GeoTrf::Transform3D rotBSM(GeoTrf::RotateX3D(-M_PI));
553  if(m_isTB) rotBSM = GeoTrf::RotateZ3D(M_PI)*rotBSM;
554  emecMotherPhysical->add(refSystemTransform);
555  emecMotherPhysical->add(new GeoTransform(GeoTrf::Transform3D(GeoTrf::Translate3D(0., 0., z0)*rotBSM)));
556  emecMotherPhysical->add(physicalBSM);
557  delete bsc;
558 
559  z0 = zWheelRefPoint + LArTotalThickness * 0.5; //dist. to middle of sens vol. along z from WRP
560  EMECSupportConstruction *osc = nullptr;
563  GeoIntrusivePtr<GeoPhysVol>physicalOSM = osc->GetEnvelope();
564  emecMotherPhysical->add(refSystemTransform);
565  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
566  emecMotherPhysical->add(physicalOSM);
567  delete osc;
568 
569  z0 = zWheelRefPoint + LArTotalThickness * 0.5;
570  EMECSupportConstruction *isc = nullptr;
571  if(m_isTB) isc = new EMECSupportConstruction(EMECSupportConstruction::Inner, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
573  GeoIntrusivePtr<GeoPhysVol>physicalISM = isc->GetEnvelope();
574  emecMotherPhysical->add(refSystemTransform);
575  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
576  emecMotherPhysical->add(physicalISM);
577  delete isc;
578 
579  z0 = zWheelRefPoint + LArTotalThickness * 0.5;
580  EMECSupportConstruction *msc = nullptr;
581  if(m_isTB) msc = new EMECSupportConstruction(EMECSupportConstruction::Middle, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
583  GeoIntrusivePtr<GeoPhysVol>physicalMSM = msc->GetEnvelope();
584  emecMotherPhysical->add(refSystemTransform);
585  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
586  emecMotherPhysical->add(physicalMSM);
587  delete msc;
588  }
589 
590  return emecMotherPhysical;
591 }
592 
594 {
595  m_fullGeo = flag;
596 }
597 
598 // Place the custom accordion volumes into the liquid argon
600  GeoIntrusivePtr<GeoFullPhysVol>fullPV,
601  std::vector<std::string> &absorbers,
602  std::vector<std::string> &electrodes,
603  int multilayered_absorbers,
604  const GeoMaterial *Absorber, const GeoMaterial *Electrode,
605  const GeoMaterial *Glue, const GeoMaterial *Lead
606 )
607 {
608 
609  for(const auto& name: absorbers){
610  GeoLogVol* log_volume = new GeoLogVol(name, new GeoUnidentifiedShape("LArCustomShape", name) , Absorber);
611  GeoIntrusivePtr<GeoPhysVol> phys_volume = new GeoPhysVol(log_volume);
612  fullPV->add(new GeoIdentifierTag(1));
613  fullPV->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
614  fullPV->add(phys_volume);
615  if(multilayered_absorbers > 0){
616  GeoIntrusivePtr<GeoPhysVol> glue_phys = phys_volume;
617  std::string lead_name = name;
618  size_t repl = lead_name.find("Absorber");
619  if(std::string::npos != repl) lead_name.replace(repl, 8, "Lead");
620  else throw std::runtime_error(lead_name + ": cannot find 'Absorber'");
621  if(multilayered_absorbers != 2){
622  std::string glue_name = name;
623  glue_name.replace(repl, 8, "Glue");
624  GeoLogVol* glue_log = new GeoLogVol(glue_name, new GeoUnidentifiedShape("LArCustomShape",glue_name), Glue);
625  glue_phys = new GeoPhysVol(glue_log);
626  phys_volume->add(new GeoIdentifierTag(1));
627  phys_volume->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
628  phys_volume->add(glue_phys);
629  }
630  GeoLogVol *lead_log = new GeoLogVol(lead_name, new GeoUnidentifiedShape("LArCustomShape",lead_name), Lead);
631  GeoIntrusivePtr<GeoPhysVol>lead_phys = new GeoPhysVol(lead_log);
632  glue_phys->add(new GeoIdentifierTag(1));
633  glue_phys->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
634  glue_phys->add(lead_phys);
635  }
636  }
637 
638  for(const auto& name: electrodes){
639  GeoLogVol* log_volume = new GeoLogVol(name, new GeoUnidentifiedShape("LArCustomShape",name), Electrode);
640  GeoIntrusivePtr<GeoPhysVol> phys_volume = new GeoPhysVol(log_volume);
641  fullPV->add(new GeoIdentifierTag(1));
642  fullPV->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
643  fullPV->add(phys_volume);
644  }
645 }
EMECSupportConstruction.h
Declaration of EMECSupportConstruction class.
LArGeo::EMECSupportConstruction::FrontOuter
@ FrontOuter
Definition: EMECSupportConstruction.h:52
LArGeo::EMECSupportConstruction::GetEnvelope
virtual GeoIntrusivePtr< GeoPhysVol > GetEnvelope(void) const
Definition: EMECSupportConstruction.cxx:292
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
IRDBAccessSvc::getRecordsetPtr
virtual IRDBRecordset_ptr getRecordsetPtr(const std::string &node, const std::string &tag, const std::string &tag2node="", const std::string &connName="ATLASDD")=0
Provides access to the Recordset object containing HVS-tagged data.
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:575
IGeoModelSvc
Definition: IGeoModelSvc.h:17
LAr
Definition: LArVolumeBuilder.h:36
LArGeo::EMECSupportConstruction::type_t
type_t
Definition: EMECSupportConstruction.h:49
LArGeo::EMECConstruction::~EMECConstruction
virtual ~EMECConstruction()
M_PI
#define M_PI
Definition: ActiveFraction.h:11
DecodeVersionKey::node
const std::string & node() const
Return the version node.
Definition: DecodeVersionKey.cxx:99
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
LArGeo::EMECSupportConstruction::Middle
@ Middle
Definition: EMECSupportConstruction.h:50
LArGeo::EMECSupportConstruction::Outer
@ Outer
Definition: EMECSupportConstruction.h:50
StoredPhysVol
Definition: StoredPhysVol.h:27
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
LArGeo::EMECSupportConstruction::Front
@ Front
Definition: EMECSupportConstruction.h:50
StoreGateSvc
The Athena Transient Store API.
Definition: StoreGateSvc.h:128
IRDBAccessSvc.h
Definition of the abstract IRDBAccessSvc interface.
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
LArGeo::EMECSupportConstruction
GeoModel description of the EMEC Support Structures.
Definition: EMECSupportConstruction.h:47
perfmonmt-refit.slice
slice
Definition: perfmonmt-refit.py:52
IRDBAccessSvc
IRDBAccessSvc is an abstract interface to the athena service that provides the following functionalit...
Definition: IRDBAccessSvc.h:45
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
LArGeo::EMECSupportConstruction::BackInner
@ BackInner
Definition: EMECSupportConstruction.h:51
DecodeVersionKey
This is a helper class to query the version tags from GeoModelSvc and determine the appropriate tag a...
Definition: DecodeVersionKey.h:18
LArGeo::EMECConstruction::GetEnvelope
virtual GeoIntrusivePtr< GeoFullPhysVol > GetEnvelope(bool bPos=true)
Definition: EMECConstruction.cxx:111
master.flag
bool flag
Definition: master.py:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
LArGeo::EMECConstruction::setFullGeo
void setFullGeo(bool flag)
Definition: EMECConstruction.cxx:593
DecodeVersionKey::tag
const std::string & tag() const
Return version tag.
Definition: DecodeVersionKey.cxx:93
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
TRT::Track::z0
@ z0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:63
IRDBRecordset_ptr
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition: IRDBAccessSvc.h:25
LArGeo::EMECSupportConstruction::Back
@ Back
Definition: EMECSupportConstruction.h:50
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
LArGeo::EMECSupportConstruction::Inner
@ Inner
Definition: EMECSupportConstruction.h:50
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
StoredMaterialManager.h
DecodeVersionKey.h
LArGeo::EMECConstruction::EMECConstruction
EMECConstruction(bool is_tb=false, bool has_inner=true, bool has_outer=true)
Definition: EMECConstruction.cxx:85
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
ReadFromCoolCompare.osc
osc
Definition: ReadFromCoolCompare.py:281
a
TList * a
Definition: liststreamerinfos.cxx:10
IRDBRecord.h
Definition of the abstract IRDBRecord interface.
LArGeo::EMECSupportConstruction::BackOuter
@ BackOuter
Definition: EMECSupportConstruction.h:52
IRDBRecord_ptr
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
Definition: IRDBRecordset.h:23
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
merge.status
status
Definition: merge.py:17
LArGeo::EMECConstruction::place_custom_solids
static void place_custom_solids(GeoIntrusivePtr< GeoFullPhysVol >fullPV, std::vector< std::string > &absorbers, std::vector< std::string > &electrodes, int multilayered_absorbers, const GeoMaterial *Absorber, const GeoMaterial *Electrode, const GeoMaterial *Glue, const GeoMaterial *Lead)
Definition: EMECConstruction.cxx:599
IRDBRecordset.h
Definition of the abstract IRDBRecordset interface.
python.PhysicalConstants.halfpi
float halfpi
Definition: PhysicalConstants.py:51
LArGeo::EMECSupportConstruction::FrontInner
@ FrontInner
Definition: EMECSupportConstruction.h:51
IGeoModelSvc.h
StoreGateSvc.h
EMECConstruction.h
Declaration of EMECConstruction class.
python.SystemOfUnits.rad
int rad
Definition: SystemOfUnits.py:111
StoredPhysVol.h